利用sqlmapapi打造自动化SQL注入工具
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用sqlmapapi打造自动化SQL注入工具相关的知识,希望对你有一定的参考价值。
友链:http://www.freebuf.com/sectool/74445.html
0×01 前言
各位看官看到标题吐槽帝就开始了:已经有了各种各样的注入工具,为什么还要手工打造一个?
事实上,做为一名苦逼乙方测试工程师以及漏洞盒子屌丝白帽子 ,在疲于应对各种死缠滥打的甲方以及成堆的web测试需求时,我经常遇到以下场景:
(1)有大批量的网站需要检测的场景
乙方工程师工作辛苦劳累从来都不抱怨,有项目一定都是最能抗的,向无数奋斗在一线的乙方工程师致敬!
(2)系统内部业务复杂可能会存在众多测注入点
很多系内部业务复杂,查询功能较多,此时可能会较多的注入点,手工测试时间紧,容易纰漏,此时需要一个提取burpsuit的history记录的工具,来自动帮你分析问题所在。
(3)漏洞盒子测试时间需要争分夺秒
在漏洞盒子进行项目安全测试时,时间就是金钱——谁能以更快的速度挖到漏洞谁就能拿到更多的奖励.
系统框架组成:
[核心检测引擎]
Sqlmap
[核心信息收集引擎]
Python代理
[数据库]
mysql
[Web展示]
Bootstrap主题+JQuery(Ajax)
0×02 系统设计过程
先介绍一下Sqlmapi及其用法:
Sqlmapapi在sqlmap中是自带的功能,可能许多人都忽略了.当我们下载到sqlmap源码的适合会发现在根目录下还有一个sqlmapapi.py的文件,此时,使用命令python sqlmapapi.py -s -H 127.0.0.1 -p 8889就可以启动了
启动后会生成一个Admin ID,这个AdminID就是我们用于管理Sqlmapapi使用管理id
但是注意,在新建sqlmap任务的时候,这个AdminID没有什么作用,只是在查看任务和删除任务的时候才有用.这个AdminID也是后面php程序对sqlmapapi进行管理的时候使用的AdminID,但是为了方便,我将这一部分代码进行了重写,使得生成的AdminID是唯一的/或者写入一个特定的文件让PHP去读取。
使用的时候需要使用HTTP协议与该API进行交互。新建一个空任务,然后再向该任务POST sql注入的相关参数来启动该任务,/task/new为新建任务,/scan/taskid/start为启动任务接口。
需要使用POST方法向该接口提交json格式的数据,详情可参考后文的req2sqlmap.py
有了sqlmapapi的背景知识后,我们的打造自己的自动sql注入工具之路就开始了:
这款工具后台由Python代理实现且支持Https,启动sqlmapapi进程后,Python代理会截取http请求并将该请求发送给Sqlmapapi,Sqlmap就开始进行注入尝试,Web界面部分负责生成最后的结果便于测试人员直接分析,Web部分由PHP负责监控sqlmapapi并获取注入结果保存入mysql数据库,此处我写了一个单独的类库sqlmapapi.class.php处理,只要实例化一个对象并传入固定的adminid(sqlmap的管理id)就可以对sqlmapapi进程进行管理。
sqlmapapi.class.php代码如下:
<?php
class sqlmapapi {
private $adminid=‘‘;
private $sqlmapapi=SQLMAPAPI;
private $tasknumber=0;
function __construct($adminid=null) {
if($adminid!=null){
$this->adminid=$adminid;
}
$this->AutoTask();
return 0;
}
//自动处理所有任务
function AutoTask(){
$tasklistarr= $this->getTasklist();
foreach ($tasklistarr as $taskid) {
//查询结果并入库
$this->Task2db($taskid);
}
return TRUE;
}
function getTasklist($adminid=null){
if($adminid==null){
$adminid=$this->adminid;
}
$jsonres=$this->doGet("/admin/".$this->adminid."/list");
$jsonobj= json_decode($jsonres);
$tasklist=$jsonobj->tasks;
$tasknumber=$jsonobj->tasks_num;
$this->tasknumber=$tasknumber;
print_r($tasklist);
return $tasklist;
}
function flushTask($adminid=null){
if($adminid==null){
$adminid=$this->adminid;
}
$jsonres=$this->doGet("/admin/".$this->adminid."/list");
$res= json_decode($jsonres);
if($res[‘success‘]==true){
return TRUE;
}else{
return FALSE;
}
}
function Task2db($taskid){
$jsonres= $this->doGet