개발 블로그

[DreamHack] filestorage 본문

Study/Web Hacking

[DreamHack] filestorage

얀 짱 2026. 9. 29. 11:33

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