ChristmasCTF had some interesting problems. We started late but still did pretty well. I focused mainly on web and tried to do some of the easier pwn problems. The CTF wasn’t on CTFTime but was located at

Web #

Please note for all the web problems, I worked with teammates on RedPwn to solve these problems so I do not have the final solve scripts. However, I will share the general idea for the web problems I did solve. All of these problems were solved by Ginkoid and DWang I’m just writing them down for future reference.

Watermelon #


If you visit it is clear there is a .git repository public and available to be extracted. When looking at the repository, there was flag.php which made it clear that the flag would be given if one song had more than 1225 votes. This was gathered from this code:

$flag = "XMAS{******}";  
if ($login) {  
$music = getMusicChartByUser_no((int)$user['user_no'], 0, 100);  
	for ($i = 0; $i < count($music); $i++) {  
		if ($music[$i]['vote'] > 1225) {  

There was a restriction that one account could only vote for a song a single time. However, looking at the jwt.php class, we can easily see how to generate valid jwts.

protected $alg;  
function __construct()  
	$this->alg = 'sha256';  
function hashing(array $data)  
	$header = json_encode(array(  
		'alg'=> $this->alg,  
		'typ'=> 'JWT'  
	$payload = json_encode($data);  
	$signature = hash($this->alg, $header.$payload);  
	return base64_encode($header.'.'.$payload.'.'.$signature);  
function dehashing($token)  
	$parted = explode('.', base64_decode($token));  
	$signature = $parted[2];  
	if(hash($this->alg, $parted[0].$parted[1]) != $signature)  
		die("<script>alert('INVALID JWT!!');</script>");  
	$payload = json_decode($parted[1],true);  
	return $payload;  

The last step was to upload a song, write a script which generate valid jwts with different ids, and voted by sending a post request to vote.php with your music id, and collecting the flag.


Plz crack jwt  
* CSRF 문제와 같은 파일입니다

The hint makes it obvious that the goal is to crack the jwt secret. Furthermore, when looking at the source, and more specifically at the config.php file, we see a comment next to the redacted key.

Windows Terminal

jwt: {  
	bruth: {  
		key: '********', // 0~9, 8 length  
		options: {  
			issuer: 'c2w2m2',  
			expiresIn: '1d',  
			algorithm: 'HS256',  

This comment suggests that it is an 8 character secret, with each character being a number between 0 and 9. All we had to do was brute force for the secret and generate our own valid token with the flag isAdmin set to true. Then after visited the /flag route, we would be given our flag.


CSRF? XSS? 뭐징..?? 어드민이 글을 본다고는 하는데...  
* JWT 문제와 같은 파일입니다

This has the same source as the JWT problem. Looking at the source, we can look at csrf.js for the possible routes. We see that there are now that the server displays the static pages admin.html, board.html, index.html, join.html, login.html, and post.html. When visiting the websites, the general idea seemed to be to post something to post.html and that could be viewed by others.

This seemed like the perfect opportunity for an XSS attack. However, when looking at the source, it seems that if we tried to put “hacky” things in the post, the server would give us a 400 and the user would be safe. To get around this, Ginkoid found that if we just put our XSS attack in the title of the post and we were able to bypass this “hack detection” system which was just a keyword filter.

The final exploit was to just requestbin the admin’s cookies with any XSS vector in the title of a post

Concluding thoughts on web #

Overall the problems seemed to be pretty standard. Working with teammates defenitely made the process faster. We were able to solve these three web problems in a couple hours and it likely would’ve taken me much longer alone. There was a new category called “webnable” which involved a server and had integrated web components. Although we did not have the time to look and solve this problem, it does seems really interesting.