| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 클래스
- node.js
- 지도학습
- 레이블인코딩
- git push -u
- 루키즈
- 패키지
- 방콕
- 보안공부
- 성능평가지표
- 생성형AI
- dropna
- 블록(Block)
- 태국
- 꽉뚝짝 시장
- sqld
- 수업복습
- Package
- Linked List
- gdgm
- OT후기
- 데이터분포
- 루키즈33기
- List
- tunder client
- SK쉴더스
- 함수
- echo 명령어
- pandas
- 예외처리
- Today
- Total
개발 블로그
[DreamHack] filestorage 본문
https://dreamhack.io/wargame/challenges/643
로그인 | Dreamhack
dreamhack.io
소스코드로 주어진 파일은 js 파일임.
나같은 경우에는 소스코드 중에 app.js를 먼저 봤는데 전에 봤던 코드들이랑 다른 부분을 위주로 봤던 것 같음.
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={};
function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
// 중첩된 객체에 안전하게 값을 설정하려는 프로토타입 기반 객체 조작? 함수
// 예: key가 'user.name'이면 obj['user']['name'] = value 형태로 저장함
function setValue(obj, key, value) {
const keylist = key.split('.');
const e = keylist.shift();
if (keylist.length > 0) {
// 여기서 __proto__ 검증이 없어서 모든 객체의 최상위 프로토타입을 변조할 수 있음
if (!isObject(obj[e])) obj[e] = {};
setValue(obj[e], keylist.join('.'), value);
} else {
obj[key] = value;
return obj;
}
}
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.post('/mkfile',function(req,resp){
let {filename,content}=req.body;
filename=hash(filename).toString();
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>");
}
})
})
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');
}
})
}
})
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");
}
})
app.listen(8000);
app.get 뭐 이런 부분은 전에도 많이 봤었으니까 위쪽에 먼저 정의되어 있는 함수에 집중을 했음.
해당 일반 함수는 매개변수를 3개 가진 프로토타입 객체 조작 함수라고 할 수 있을 것 같고 자바스크립트에서 해당 함수 관련 취약점이 있나 구글링함.
https://ajy1120.tistory.com/46
프로토타입 오염 (Prototype Pollution)
프로토타입자바스크립트에서 모든 객체들이 메소드와 속성을 상속 받기 위한 객체 객체를 생성할 때 기본적으로 상속되며 여러 메소드를 포함합니다. 새로운 인스턴스가 생성될 때, 생성된 인
ajy1120.tistory.com
프로토타입 기반 객체에 대해서 이런 취약점이 있다고 함.
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Prototype%20Pollution
PayloadsAllTheThings/Prototype Pollution at master · swisskyrepo/PayloadsAllTheThings
A list of useful payloads and bypass for Web Application Security and Pentest/CTF - swisskyrepo/PayloadsAllTheThings
github.com
이 레포에도 설명을 해뒀더라고.
프로토타입 오염은 Object.prototype의 속성을 수정할 때 발생하는 자바스크립트 취약점의 일종이라고 함.
내가 가진 소스코드에서는

이 부분임.



sha256으로 암호화해서 이름을 주는 것 같음.
/readfile 에는 filename이라는 쿼리가 있으니까 아까 받았던 해시를 넣어보았음.

이런 식으로 동작함.
다음은 /test
/test는 쿼리가 무려 3개임. func (rename, reset)/filename/rename
내가 방금 작성한 파일을 가지고 프로토타입 오염 취약점으로 rename해서 플래그를 얻는 식인 것 같음.

func=rename에 filename은 아까 작성한 파일이름을 넣음.
rename은 dockerfile에서 확인하다시피 /flag로 하면 될 것 같고

filename은 __proto__ 이거 써서 하면 될 것 같음.
-> __proto__.filename 이렇게



이때 중간에 reset을 한 번 해주는 이유는 위의 테스트를 먼저 하고 나서 바로 /readfile로 이동하면

이 코드 때문에 filename이 다시 fake로 덮어써지는 것 같음.
reset을 하면

여기처럼 이렇게 {} 비워지기 때문에 부모 프로토타입으로 올라갈 수 있게됨.

근데 계속 아무것도 안 뜸...
파일 관리에서 간과하고 있는 것이 있었음.. 바로 path traversal!!




플래그를 얻음.
'Study > Web Hacking' 카테고리의 다른 글
| [DreamHack] Audio Steganography (0) | 2026.09.29 |
|---|---|
| [DreamHack] rev-basic-0 (0) | 2026.09.28 |
| [DreamHack] Easy-forensic (0) | 2026.09.28 |
| [DreamHack] BMP Recovery (0) | 2026.09.28 |
| [DreamHack] structure-based carving (0) | 2026.09.27 |