关于sqlmapapi自己练习的还是很少 今天看见freebuf上师傅的分享的内容 自己练习了一下

来自: https://www.freebuf.com/articles/web/204875.html 这位师傅总结非常好

为什么要使用SQLMAP API?

由于SQLMAP每检测一个站点都需要开启一个新的命令行窗口或者结束掉上一个检测任务。虽然 -m 参数可以批量扫描URL,但是模式也是一个结束扫描后才开始另一个扫描任务。通过api接口,下发扫描任务就简单了,无需开启一个新的命令行窗口。

sqlmap api

在sqlmap安装目录中找到一个 sqlmapapi.py 的文件,这个 sqlmapapi.py 文件就是sqlmmap api。sqlmap api分为服务端和客户端,sqlmap api有两种模式,一种是基于HTTP协议的接口模式,一种是基于命令行的接口模式。

python 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 可空,设置密码

开启api服务端

无论是基于HTTP协议的接口模式还是基于命令行的接口模式,首先都是需要开启api服务端的。通过输入以下命令即可开启api服务端:

python sqlmapapi.py -s

命令成功后,在命令行中会返回一些信息。以下命令大概的意思是api服务端在本地8775端口上运行,admin token为e98dfc2b53cca0edbccbdafd78a3d2a4,IPC数据库的位置在/tmp/sqlmapipc-zOIGm_,api服务端已经和IPC数据库连接上了,正在使用bottle 框架wsgiref标准接口。

但是通过上面的这种方式开启api服务端有一个缺点,当服务端和客户端不是一台主机会连接不上,因此如果要解决这个问题,可以通过输入以下命令来开启api服务端:

python sqlmapapi.py -s -H "0.0.0.0" -p 8775

命令成功后,远程客户端就可以通过指定远程主机IP和端口来连接到API服务端。

固定admin token

如果您有特殊的需求需要固定admin token的话,可以修改文件api.py,该文件在sqlmap目录下的/lib/utils/中,修改该文件的第661行代码,以下是源代码:

DataStore.admin_token = hexencode(os.urandom(16))

sqlmap api的两种模式

命令行接口模式

输入以下命令,可连接api服务端,进行后期的指令发送操作:

python sqlmapapi.py -c

如果是客户端和服务端不是同一台计算机的话,输入以下命令:

python sqlmapapi.py -c -H "192.168.1.101" -p 8775

输入以上命令后,会进入交互模式,如下图所示:

命令行接口模式的相关命令

通过在交互模式下输入help命令,获取所有命令,以下是该接口模式的所有命令:

api> help
help 显示帮助信息
new ARGS 开启一个新的扫描任务
use TASKID 切换taskid
data 获取当前任务返回的数据
log 获取当前任务的扫描日志
status 获取当前任务的扫描状态
option OPTION 获取当前任务的选项
options 获取当前任务的所有配置信息
stop 停止当前任务
kill 杀死当前任务
list 显示所有任务列表
flush 清空所有任务
exit 退出客户端

既然了解了命令行接口模式中所有命令,那么下面就通过一个sql注入来演示该模式接口下检测sql注入的流程。

这里我在另外一台2003上的sqli-lab测试

检测GET型注入

通过输入以下命令可以检测GET注入

new -u "url"

虽然我们仅仅只指定了-u参数,但是从返回的信息中可以看出,输入new命令后,首先先请求了/task/new,来创建一个新的taskid,后又发起了一个请求去开始任务,因此可以发现该模式实质也是基于HTTP协议的。

通过输入 status 命令,来获取该任务的扫描状态,若返回内容中的status字段为terminated,说明扫描完成,若返回内容中的status字段为run,说明扫描还在进行中。下图是扫描完成的截图:

通过输入 data 命令,来获取扫描完成后注入出来的信息,若返回的内容中data字段不为空就说明存在注入。下图是存在SQL注入返回的内容,可以看到返回的内容有数据库类型、payload、注入的参数等等。

检测POST型、cookie、UA等注入

通过输入以下命令,在data.txt中加入星号,指定注入的位置,来达到检测POST、cookie、UA等注入的目的:

new -r data.txt

基于HTTP协议的接口模式

下列都是基于HTTP协议API交互的所有方法:提示:“@get”就说明需要通过GET请求的,“@post”就说明需要通过POST请求的;POST请求需要修改HTTP头中的Content-Type字段为application/json

#辅助
@get('/error/401')
@get("/task/new")
@get("/task/<taskid>/delete") #Admin 命令
@get("/admin/list")
@get("/admin/<token>/list")
@get("/admin/flush")
@get("/admin/<token>/flush") #sqlmap 核心交互命令
@get("/option/<taskid>/list")
@post("/option/<taskid>/get")
@post("/option/<taskid>/set")
@post("/scan/<taskid>/start")
@get("/scan/<taskid>/stop")
@get("/scan/<taskid>/kill")
@get("/scan/<taskid>/status")
@get("/scan/<taskid>/data")
@get("/scan/<taskid>/log/<start>/<end>")
@get("/scan/<taskid>/log")
@get("/download/<taskid>/<target>/<filename:path>")

@get(‘/error/401′)

该接口首先需要登录(Admin token),不然会返回状态码401。具体代码如下:

response.status = 401
return response

@get(“/task/new”)

该接口用于创建一个新的任务,使用后会返回一个随机的taskid。

下图是调用该接口的截图:

@get(“/task//delete”)

该接口用于删除taskid。

@get(“/admin/list”)

该接口用于返回所有taskid。在调用时指定taskid

@get(“/admin/flush”)

该接口用于删除所有任务。在调用时指定admin token,

@post(“/option//get”)

该接口可获取特定任务ID的选项值,调用时请指定taskid

@post(“/option//set”)

该接口为特定任务ID设置选项值,调用时请指定taskid

@post(“/scan//start”)

该接口定义开始扫描特定任务,调用时请指定taskid

@get(“/scan//stop”)

该接口定义停止扫描特定任务,调用时请指定taskid

总结

基于HTTP的接口模式用起来可能比较繁琐,但是对于程序调用接口还是很友善的。总之该模式的流程是:

1、通过GET请求 http://ip:port/task/new 这个地址,创建一个新的扫描任务;

2、通过POST请求 http://ip:port/scan//start 地址,并通过json格式提交参数,开启一个扫描;通过GET请求 http://ip:port/scan//status 地址,即可获取指定的taskid的扫描状态。这个返回值分为两种,一种是run状态(扫描未完成),一种是terminated状态(扫描完成);3、扫描完成后获取扫描的结果。

使用Python3编写sqlmapapi调用程序

下面就来编写一个sqlmapapi调用程序,首先我们得再次明确一下流程:

1、通过 sqlmapapi.py -s -H “0.0.0.0″ 开启sqlmap api的服务端。服务端启动后,在服务端命令行中会返回一个随机的admin token值,这个token值用于管理taskid(获取、清空操作),在这个流程中不需要amin 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等等。

#!/usr/bin/python
# -*- coding:utf-8 -*-
# wirter:En_dust
import requests
import json
import time class Client():
def __init__(self,server_ip,server_port,admin_token="",taskid="",filepath=None):
self.server = "http://" + server_ip + ":" + server_port
self.admin_token = admin_token
self.taskid = taskid
self.filepath = ""
self.status = ""
self.scan_start_time = ""
self.scan_end_time = ""
self.engineid=""
self.headers = {'Content-Type': 'application/json'} def create_new_task(self):
'''创建一个新的任务,创建成功返回taskid'''
r = requests.get("%s/task/new"%(self.server))
self.taskid = r.json()['taskid']
if self.taskid != "":
return self.taskid
else:
print("创建任务失败!")
return None def set_task_options(self,url):
'''设置任务扫描的url等'''
self.filepath = url def start_target_scan(self,url):
'''开始扫描的方法,成功开启扫描返回True,开始扫描失败返回False'''
r = requests.post(self.server + '/scan/' + self.taskid + '/start',
data=json.dumps({'url':url,'getCurrentUser':True,'getBanner':True,'getCurrentDb':True}),
headers=self.headers)
if r.json()['success']:
self.scan_start_time = time.time()
#print(r.json())
#print(r.json()['engineid'])
return r.json()['engineid']
else:
#print(r.json())
return None def get_scan_status(self):
'''获取扫描状态的方法,扫描完成返回True,正在扫描返回False'''
self.status = json.loads(requests.get(self.server + '/scan/' + self.taskid + '/status').text)['status']
if self.status == 'terminated':
self.scan_end_time = time.time()
#print("扫描完成!")
return True
elif self.status == 'running':
#print("Running")
return False
else:
#print("未知错误!")
self.status = False def get_result(self):
'''获取扫描结果的方法,存在SQL注入返回payload和注入类型等,不存在SQL注入返回空'''
if(self.status):
r = requests.get(self.server + '/scan/' + self.taskid + '/data')
if (r.json()['data']):
return r.json()['data']
else:
return None def get_all_task_list(self):
'''获取所有任务列表'''
r = requests.get(self.server + '/admin/' + self.admin_token + "/list")
if r.json()['success']:
#print(r.json()['tasks'])
return r.json()['tasks']
else:
return None def del_a_task(self,taskid):
'''删除一个任务'''
r = requests.get(self.server + '/task/' + taskid + '/delete')
if r.json()['success']:
return True
else:
return False def stop_a_scan(self,taskid):
'''停止一个扫描任务'''
r = requests.get(self.server + '/scan/' + taskid + '/stop')
if r.json()['success']:
return True
else:
return False def flush_all_tasks(self):
'''清空所有任务'''
r =requests.get(self.server + '/admin/' + self.admin_token + "/flush")
if r.json()['success']:
return True
else:
return False def get_scan_log(self):
'''获取log'''
r = requests.get(self.server + '/scan/' + self.taskid + '/log')
return r.json()

Githun地址:https://github.com/FiveAourThe/sqlmap_api_demo

mian.py

#!/usr/bin/python
# -*- coding:utf-8 -*-
# wirter:En_dust
from Service import Client
import time
from threading import Thread def main():
'''实例化Client对象时需要传递sqlmap api 服务端的ip、port、admin_token和HTTP包的绝对路径'''
print("————————————————Start Working!—————————————————")
target = input("url:")
task1 = Thread(target=set_start_get_result,args=(target,))
task1.start() def time_deal(mytime):
first_deal_time = time.localtime(mytime)
second_deal_time = time.strftime("%Y-%m-%d %H:%M:%S", first_deal_time)
return second_deal_time def set_start_get_result(url):
#/home/cheng/Desktop/sqldump/1.txt
current_taskid = my_scan.create_new_task()
print("taskid: " + str(current_taskid))
my_scan.set_task_options(url=url)
print("扫描id:" + str(my_scan.start_target_scan(url=url)))
print("扫描开始时间:" + str(time_deal(my_scan.scan_start_time)))
while True:
if my_scan.get_scan_status() == True:
print(my_scan.get_result())
print("当前数据库:" + str(my_scan.get_result()[-1]['value']))
print("当前数据库用户名:" + str(my_scan.get_result()[-2]['value']))
print("数据库版本:" + str(my_scan.get_result()[-3]['value']))
print("扫描结束时间:" + str(time_deal(my_scan.scan_end_time)))
print("扫描日志:\n" + str(my_scan.get_scan_log()))
break if __name__ == '__main__':
my_scan = Client("127.0.0.1", "", "c88927c30abb1ef6ea78cb81ac7ac6b0")
main()

关于sqlmapapi一点记录的更多相关文章

  1. 关于Java8:StreamAPI的一点记录

    关于 Stream ,Functional Interface 的一点记录 stream对于集合操作的便捷度提升: import java.util.ArrayList; import java.ut ...

  2. 对Integer类中的私有IntegerCache缓存类的一点记录

    对Integer类中的私有IntegerCache缓存类的一点记录 // Integer类有内部缓存,存贮着-128 到 127. // 所以,每个使用这些数字的变量都指向同一个缓存数据 // 因此可 ...

  3. 从symbol link和hard link 到 unlink函数的一点记录

    之前一直对Linux的文件类型中的 “l” 类型的了解不是很深入,最近经过“圣经”指点,略知一二,在此先记录一下,以便以后查阅,之后会对文件和目录.文件I/O这部分再扩充. 首先需明确,Unix在查阅 ...

  4. 关于删除MySQL Logs的一点记录

    五一前,一个DBA同事反馈,在日常环境中删除一个大的slow log文件(假设文件大小10G以上吧),然后在MySQL中执行flush slow logs,会发现mysqld hang住. 今天尝试着 ...

  5. 关于类属性值校验的一点记录 【知识点Attribute】

    好久没有进来了,之前励志坚持写博客,记录自己在做代码搬运工这段历程中点滴,可是仅仅只坚持了几天,就放弃了!果然是,世上无难事,只要肯放弃!哈哈……闲话不多说,开始进入正题,给自己留点笔记,避免将来老了 ...

  6. 【.Net】关于内存缓存的一点记录

    引言 最近看了内存缓存的一些介绍和用法,在此做个简单记录. MemoryCache 类 MemoryCache 类是.Net 4.0推出的类库,主要是为了方便在Winform和Wpf中构建缓存框架的. ...

  7. 关于db2的一点记录

    近期听搞db2的兄弟说:db2数据库软件的license 不区分平台(os). 先记下来.像db2这么高大上的软件,接触的机会是比較少的. 另外:db2 的license是须要打的,不打的话,超过一段 ...

  8. Nodejs Promise的一点记录

    项目需要,看了点nodejs,其中比较难理解的就是Promise了,记录一下学习bluebird提供的Promise实现. Promise.promisifyAll(obj)方法 作用:把对象的方法属 ...

  9. 关于strlen误用的一点记录

    今天帮一个朋友查一个错误,是运行时报vector iterator incompatible,一般这种问题是向量和迭代器的类型不兼容,或者是进行迭代器判等时前后向量的结构发生变化,如erase操作之后 ...

随机推荐

  1. NOIP2006 1.明明的随机数

    题目:明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不 ...

  2. 实现一个extend函数

    NOW,今天让我们来实现一个extend函数. 具体思路: 使用Object.defineProperty()对属性的特性进行设置,然后通过Object.getOwnPropertyDescripto ...

  3. 分别设计点类Point和圆类Circle,点类有两个私有数据纵坐标和横坐标;圆类有也两个私有数据圆心和半径,其中圆心是一个点类对象;要求如下所述: (1) 通过构造方法初始化数据成员,数据成员的初始化通过构造方法的参数传递;(2) 分别编写点和圆的输出函数,其中圆的输出包括圆心和半径的输出;点的输出x,y;

    题目相对简单: package naizi; public class Circle { //私有成员及构造方法 private Point center; private int r; Circle ...

  4. Fortify漏洞修复总结

    1.代码注入 1.1 命令注入 命令注入是指应用程序执行命令的字符串或字符串的一部分来源于不可信赖的数据源,程序没有对这些不可信赖的数据进行验证.过滤,导致程序执行恶意命令的一种攻击方式. 问题代码: ...

  5. IPMI在linux下常用命令

    ipmitool lan print 1 ipmitool lan set 1 ipaddr 192.168.0.12 ipmitool lan set 1 netmask 255.255.255.0 ...

  6. elasticsearch Discovery 发现模块学习

    发现模块和集群的形成 目标 发现节点 Master选举 组成集群,在Master信息发生变化时及时更新. 故障检测 细分为几个子模块 Discovery发现模块 Discover是在集群Master节 ...

  7. linux安装couchbase

    一.卸载 查看已安装的版本 rpm -qa|grep couchbase 卸载已安装的版本 rpm -e xxxx 二.安装 安装couchbase rpm -i xxxx.rpm 浏览器中访问809 ...

  8. java.lang.IllegalArgumentException: System memory 259522560 must be at least 471859200.

    报错信息 java.lang.IllegalArgumentException: System memory 259522560 must be at least 471859200. Please ...

  9. BOM之window核心模块

    Window对象包含以下五大核心:document,screen,navigator,history,location. 一     document 文档 document包含了浏览器对标准DOM实 ...

  10. Java行业未来发展

    互联网时代的飞速发展,为机械,自动化,等传统行业敲响了警钟,曾经火爆一时的行业逐渐没落,曾经网上有个段子,一个人在20多年前,看BP机卖的如火如荼,自己一想,那么多人都在用,总会有坏的时候吧,然后去技 ...