渗透利器-kali工具 (第四章-8) 模块学习与渗透测试
本文内容:
- sqlmapapi学习
- 开启api两种模式
- 使用脚本实现
- 脚本解析和使用
1,sqlmapapi学习:
为什么要使用sqlmapapi:
由于sqlmap每检测一个站点需要开启一个新的命令窗口或者结束上一个检测任务。才能进行另一个任务。
虽然-m参数可以批量扫描url,但是此模式也是一个结束扫描,才开始另一个扫描任务。
通过api接口下 扫描任务就简单了,只需开启一个新的命令窗口。
在sqlmap安装目中有sqlmapapi.py文件,这个文件,就是sqlmapapi
api有两种模式:
1.基于HTTP协议的接口模式。
2.基于命令行的接口模式。
api命令:
sqlmapapi.py -h
Usage:sqlmapapi.py [options]
Options: -h ,--help 显示帮助信息并退出
-s, --server 作为api服务端运行
-c, --client 作为api客户端运行
-H HOST, --host=HOST 指定服务端IP地址[默认ip是"127.0.0.1"]
-p PORT, --port=PORT 指定服务端口端口[默认端口8775]
--adapter=ADAPTER 服务端口标准接口[默认是"wsgiref"]
--username=USERNAME 可空,设置用户名
--password=PASSWORD 可空,设置密码
2,开启api两种模式:
1.开启api服务端:
无论是基于HTTP协议的接口模式,还是基于命令行的接口模式,首先都是需要开启api服务端。
通过此命令可以看起api服务端:python sqlmapapi .py -s 名称执行成功会在命令行返回一些信息
IPC数据库的位置在/tmp/sqlmapipc-zOIGm
api服务端已经和IPC数据库连接上了,正在使用bottle框架wsgired标准接口。
python sqlmapapi.py -s -H "127.0.0.1" -p 8775
命令成功后,远程客户端就可以通过指定远程主机IP和端口来连接到API服务端。
2.开启api命令行接口模式:
输入一下命令,可连接api服务端,进行后期的指令发送操作:
python sqlmapapi.py -c
如果是客户端和服务端不是同一台计算机的话,输入一下命令:
python sqlmapapi.py -c -H "127.0.0.1" -p 8775
其他命令:
help 显示帮助信息
new ARGS 开启一个新的扫描任务:new -u 127.0.0.1[url]
use TASKID 切换taskid
data 获取当前任务返回的数据
log 获取当前任务的扫描日志
status 获取当前任务的扫描状态
option OPTION 获取当前任务的选项
options 获取当前任务的所有配置信息
stop 停止当前任务
kill 杀死当前任务
list 显示所有任务列表
flush 清空所有任务
exit 退出客户端
举例:
通过一个sql注入,举例:
1.检测注入类型:new -u "url" [127.0.0.1]
Status:来获取该任务的扫描状态
Data:返回的内容data字段不为空就说明存在注入
2.检测POST、Cookie、UA等注入:new -r data.txt
3.开启HTTP的接口模式:
基于HTTP的接口模式用起来可能比较繁琐,但是对于程序调用接口还是很友善的。
1.流程:
1.通过GET请求:[127.0.0.1:8775] http://ip:port/task/new 这个地址,创建一个新的扫描任务;
2.通过POST请求 [127.0.0.1:8775]http://ip:port/scan//start 地址,并通过json格式提交参数,开启一个扫描;通过GET请求 http://ip:port/scan//status 地址,即可获取指定的taskid的扫描状态。这个返回值分为两种,一种是run状态(扫描未完成),一种是terminated状态(扫描完成);
3.3.扫描完成后获取扫描的结果。
3,脚本代码及实现思路:
1.实现思路
1.开启sqlmap api的服务端。服务端启动后,在服务端命令行中会返回一个随机的admin token值,这个token值用于管理taskid(获取、清空操作),在这个流程中不需要admin token这个值,可以忽略。之后,服务端会处于一个等待客户端的状态。
2.通过GET请求 http://ip:port/task/new 这个地址,即可创建一个新的扫描任务,在响应中会返回一个随机的taskid。这个taskid在这个流程中尤为重要,因此需要通过变量存储下来,方便后面程序的调用。
3.通过POST请求 http://ip:port/scan//start 地址,并通过json格式提交参数(待扫描的HTTP数据包、若存在注入是否获取当前数据库用户名),即可开启一个扫描任务,该请求会返回一个enginedid。
4.通过GET请求 http://ip:port/scan//status 地址,即可获取指定的taskid的扫描状态。这个返回值分为两种,一种是run状态(扫描未完成),一种是terminated状态(扫描完成)。
5.判断扫描状态,如果扫描未完成,再次请求 http://ip:port/scan//status 地址 ,直到扫描完成。
6.扫描完成后获取扫描的结果,是否是SQL注入,若不存在SQL注入,data字段为空,若存在SQL注入,则会返回数据库类型、payload等等。
2.脚本代码:
import os import sys import json import time import requests def usage(): print('+' + '-' * 50 + '+') print('\t Python sqlmapapi') print('\t Code BY:zhoumo') print('+' + '-' * 50 + '+') ##sys.argv不等于2的sys.exit if len(sys.argv) != 2: print("example: 1.py url.txt") sys.exit() ##获取task_id和success def task_new(server): url = server + '/task/new' req = requests.get(url) taskid = req.json()['taskid'] success = req.json()['success'] return (success, taskid) ##给server + '/scan/' + taskid + '/start'传一个json类型的data数据,return 'success' def task_start(server, taskid, data, headers): url = server + '/scan/' + taskid + '/start' ##字典反序列化 req = requests.post(url, json.dumps(data), headers=headers) success = req.json()['success'] return success ##获取server + '/scan/' + taskid + '/status'状态 return 'status' def task_status(server, taskid): url = server + '/scan/' + taskid + '/status' req = requests.get(url) status_check = req.json()['status'] return status_check ##获取该taskid的日志 def task_log(server, taskid): url = server + '/scan/' + taskid + '/log' req = requests.get(url).text scan_json = json.loads(req)['log'] ##初始化 'retry'不在 'message'里面 flag1 = 0 if scan_json: ##取log'的最后一个的'message' print(scan_json[-1]['message']) ## 判断'retry'是否在'message'里 if 'retry' in scan_json[-1]['message']: flag1 = 1 else: flag1 = 0 return flag1 ##判断该taskid有没有'data' def task_data(server, taskid): url = server + '/scan/' + taskid + '/data' req = requests.get(url) vuln_data = req.json()['data'] if len(vuln_data): ##有 vuln = 1 else: vuln = 0 return vuln ##return '/stop'中的 'success' def task_stop(server, taskid): url = server + '/scan/' + taskid + '/stop' req = requests.get(url) success = req.json()['success'] return success ##'/kill' def task_kill(server, taskid): url = server + '/scan/' + taskid + '/kill' req = requests.get(url) success = req.json()['success'] return success ##请求/delete def task_delete(server, taskid): url = server + '/scan/' + taskid + '/delete' requests.get(url) ##判断url是否有get请求,添加newurl中 def get_url(urls): newurl = [] for url in urls: if '?' in url and url not in newurl: newurl.append(url) return newurl if __name__ == "__main__": ##sys.argv长度都等于2 usage() ##循环sys.argv[1]并对每一个.rstrip()处理 targets = [x.rstrip() for x in open(sys.argv[1])] ##获取targets中有请求的url,并添加到newurl中 targets = get_url(targets) server = 'http://127.0.0.1:8775' headers = {'Content-Type': 'application/json'} i = 0 ##data数据列表 vuln = [] ##遍历所有带get请求的url for target in targets: try: data = {"url": target, 'batch': True, 'randomAgent': True, 'tamper': 'space2comment', 'tech': 'BT', 'timeout': 15, 'level': 1} ##记数 i = i + 1 flag = 0 (new, taskid) = task_new(server) ##'success' 'taskid' ##如果响应'success'存在 if new: print("scan created") if not new: print("create failed") ##给server + '/scan/' + taskid + '/start'传一个json类型的data数据,return 'success',将响应状态赋值给start start = task_start(server, taskid, data, headers) ##响应成功 if start: print("--------------->>> start scan target %s" % i) if not start: print("scan can not be started") while start: ##记录start时间 start_time = time.time() ##获取server + '/scan/' + taskid + '/status'状态 return 'status' status = task_status(server, taskid) ##status == running if status == 'running': print("scan running:") ## status == ' terminated' elif status == 'terminated': print("scan terminated\n") ##判断该taskid响应有没有'data'数据 data = task_data(server, taskid) ##有data if data: print("--------------->>> congratulation! %s is vuln\n" % target) ##有响应数据data的url f = open('injection.txt', 'a') f.write(target + '\n') f.close() vuln.append(target) if not data: print("--------------->>> the target is not vuln\n") ##请求/delete task_delete(server, taskid) break else: print("scan get some error") break time.sleep(10) ##获取该taskid的日志,'retry'在'message'里话返回的flag1=1,反之=0 flag1 = task_log(server, taskid) ##flag初始化的值为0 ##计算flag值 flag = (flag + 1) * flag1 if (time.time() - start_time > 30) or (flag == 2): # 此处设置检测超时时间,以及链接超时次数 print("there maybe a strong waf or time is over,i will abandon this target.") ##超时的化请求'/stop/,并返回响应数据'success',赋值给stop stop = task_stop(server, taskid) ##有响应值 if stop: print("scan stoped") ## if not stop: print("the scan can not be stopped") ##请求'/kill',并将响应数据'success'赋值给kill kill = task_kill(server, taskid) ##请求删除进程 task_delete(server, taskid) if kill: print("scan killed") if not kill: print("the scan can not be killed") break except: pass for each in vuln: print(each + '\n')
4,脚本使用:
1.打开服务:sqlmapapi -s
2.使用命令:脚本名称 1.txt 如:text.py 1.txt [存放url的文档]