# Balsn CTF 2022 ## Web ### 2linenodejs ```shell= steve@Desktop:~/CTF/Balsn2022$ ls 2linenodejs/ docker-compose.yml Dockerfile flag readflag.c src steve@Desktop:~/CTF/Balsn2022$ ls 2linenodejs/src/ index.js server.js usage.js steve@Desktop:~/CTF/Balsn2022$ cat 2linenodejs/src/server.js #!/usr/local/bin/node process.stdin.setEncoding('utf-8'); process.stdin.on('readable', () => { try{ console.log('HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Close\n'); const json = process.stdin.read().match(/\?(.*?)\ /)?.[1], obj = JSON.parse(json); console.log(`JSON: ${json}, Object:`, require('./index')(obj, {})); }catch{ require('./usage') }finally{ process.exit(); } }); steve@Desktop:~/CTF/Balsn2022$ cat 2linenodejs/src/index.js module.exports=(O,o) => (Object.entries(O).forEach(([K,V])=>Object.entries(V).forEach(([k,v])=>(o[K]=o[K]||{},o[K][k]=v))), o); steve@Desktop:~/CTF/Balsn2022$ cat 2linenodejs/src/usage.js console.log('Validate your JSON with <a href="/?{}">query</a>'); steve@Desktop:~/CTF/Balsn2022$ cat 2linenodejs/readflag.c #include <stdio.h> #include <unistd.h> int main(void) { seteuid(0); setegid(0); setuid(0); setgid(0); char flag[256] = {0}; FILE* fp = fopen("/flag", "r"); if (!fp) { perror("fopen"); return 1; } if (fread(flag, 1, 256, fp) < 0) { perror("fread"); return 1; } puts(flag); fclose(fp); return 0; } ``` With valid API query: ![](https://i.imgur.com/nK5htSh.png) With invalid API query: ![](https://i.imgur.com/vg5WFLy.png) ### myFirstapp 載回來的 web source code 路徑如下 ls /deploy . ├── Dockerfile ├── README.md ├── docker-compose.yml ├── next.config.js ├── package-lock.json ├── package.json ├── pages │   ├── _app.js │   ├── api │   │   └── hello.js │   └── index.js ├── public │   ├── favicon.ico │   └── vercel.svg ├── styles │   ├── Home.module.css │   └── globals.css └── utils └── globalVars.js 5 directories, 14 files flag 生成的變數存在 utils/globalVars.js const globalVars = { TITLE: "My First App!", SECRET: "here is my secret: https://www.youtube.com/watch?v=jIQ6UV2onyI", FLAG: "FLAGFLAGFLAG", }; export default globalVars; 但是 source code 裡的 flag 是不對的,要跟 http://my-first-web.balsnctf.com:3000/ 要 頁面生成的 api 在 pages ├── pages │   ├── _app.js │   ├── api │   │   └── hello.js │   └── index.js 在 api hello.js 裏 ``` // Next.js API route support: https://nextjs.org/docs/api-routes/introduction import globalVars from '../../utils/globalVars' export default function handler(req, res) { // res.status(200).json({ name: globalVars.FLAG }) res.status(200).json({ name: globalVars.SECRET }) } ``` 產 flag 的 res 被註解掉了 所以網頁只會回 {"name":"here is my secret: https://www.youtube.com/watch?v=jIQ6UV2onyI"} 這個迷因 目前卡在不知道怎麼要這個 json 資料 ![](https://i.imgur.com/uD29mnd.png) > 我在想看能不能 fileuplaod 新的 hello.js(可以讀globalVars.FLAG的版本),所以嘗試找admin page,但好像沒有 > [name=song856854132] ```shell= $ gobuster -w /usr/share/wordlist/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://my-first-web.balsnctf.com:3000 -t 40 ===================================================== Gobuster v2.0.1 OJ Reeves (@TheColonial) ===================================================== [+] Mode : dir [+] Url/Domain : http://my-first-web.balsnctf.com:3000/ [+] Threads : 40 [+] Wordlist : /usr/share/wordlist/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt [+] Status codes : 200,204,301,302,307,403 [+] Timeout : 10s ===================================================== 2022/09/03 21:16:46 Starting gobuster ===================================================== ===================================================== 2022/09/03 21:36:11 Finished ===================================================== $ gobuster -w /usr/share/wordlist/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://my-first-web.balsnctf.com:3000/pages -t 40 -x html ===================================================== Gobuster v2.0.1 OJ Reeves (@TheColonial) ===================================================== [+] Mode : dir [+] Url/Domain : http://my-first-web.balsnctf.com:3000/pages/ [+] Threads : 40 [+] Wordlist : /usr/share/wordlist/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt [+] Status codes : 200,204,301,302,307,403 [+] Extensions : html [+] Timeout : 10s ===================================================== 2022/09/03 21:42:24 Starting gobuster ===================================================== ===================================================== 2022/09/03 22:18:34 Finished ===================================================== $ gobuster -w /usr/share/wordlist/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://my-first-web.balsnctf.com:3000/api -t 40 ===================================================== Gobuster v2.0.1 OJ Reeves (@TheColonial) ===================================================== [+] Mode : dir [+] Url/Domain : http://my-first-web.balsnctf.com:3000/api/ [+] Threads : 40 [+] Wordlist : /usr/share/wordlist/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt [+] Status codes : 200,204,301,302,307,403 [+] Timeout : 10s ===================================================== 2022/09/03 22:50:03 Starting gobuster ===================================================== /hello (Status: 200) ===================================================== 2022/09/03 23:06:19 Finished ===================================================== ``` --- This web uses NextJS, a framework that base on nodejs and support ReactJS by SSR (Server Side Rendering). And according to packages.json, it's using a 12.2.5 version. > What is SSR? > SSR convert HTML and other component on the server into a fully rendered HTML page and then transfer to the client. > So in pages/index.js, the template page shows "Welcome to <a href="#">{globalVars.TITLE}</a>" > However, what we recieve was "Welcome to <a href="#">My First App!</a>" > That's becase it render TITLE with "My First App!" that declare in globalVars.js. I found some useful info(maybe) for nextjs: ~~[Path traversal](https://security.snyk.io/vuln/SNYK-JS-NEXT-561584)~~ > this vuln was flound in Next version before 9.3.2, so not consider it --- ### Health Check 1 :::success #### 題目 Want to know whether the challenge is down or it's just your network down? Want to know who to send a message when you want to contact an admin of some challenges? Take a look at our "fastest" Health Check API in the world! http://fastest-healthcheck.balsnctf.com Warning: Do not violate our CTF rules. ::: > Fast API: v0.1.0 > [name=song856854132] ```shell= $ sudo nmap -Pn -A -sV 3.239.8.140 [sudo] password for steve: Starting Nmap 7.80 ( https://nmap.org ) at 2022-09-04 13:51 CST Nmap scan report for ec2-3-239-8-140.compute-1.amazonaws.com (3.239.8.140) Host is up (0.23s latency). Not shown: 999 filtered ports PORT STATE SERVICE VERSION 80/tcp open http uvicorn | fingerprint-strings: | DNSStatusRequestTCP: | HTTP/1.1 400 Bad Request | date: Sun, 04 Sep 2022 05:52:34 GMT | server: uvicorn | content-type: text/plain; charset=utf-8 | content-length: 30 | connection: close | Invalid HTTP request received. | DNSVersionBindReqTCP, RPCCheck: | HTTP/1.1 400 Bad Request | date: Sun, 04 Sep 2022 05:52:33 GMT | server: uvicorn | content-type: text/plain; charset=utf-8 | content-length: 30 | connection: close | Invalid HTTP request received. | FourOhFourRequest: | HTTP/1.1 404 Not Found | date: Sun, 04 Sep 2022 05:52:27 GMT | server: uvicorn | content-length: 22 | content-type: application/json | {"detail":"Not Found"} | GetRequest: | HTTP/1.1 200 OK | date: Sun, 04 Sep 2022 05:52:18 GMT | server: uvicorn | content-length: 25 | content-type: application/json | {"message":"Hello World"} | HTTPOptions, RTSPRequest: | HTTP/1.1 405 Method Not Allowed | date: Sun, 04 Sep 2022 05:52:25 GMT | server: uvicorn | allow: GET | content-length: 31 | content-type: application/json | {"detail":"Method Not Allowed"} | X11Probe: | HTTP/1.1 400 Bad Request | date: Sun, 04 Sep 2022 05:52:26 GMT | server: uvicorn | content-type: text/plain; charset=utf-8 | content-length: 30 | connection: close |_ Invalid HTTP request received. |_http-server-header: uvicorn |_http-title: Site doesn't have a title (application/json). $ gobuster dir -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://fastest-healthcheck.balsnctf.com/ -b 404,403 -t 40 --exclude-length=55 1 ⨯ =============================================================== Gobuster v3.1.0 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://fastest-healthcheck.balsnctf.com/ [+] Method: GET [+] Threads: 40 [+] Wordlist: /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt [+] Negative Status codes: 403,404 [+] Exclude Length: 55 [+] User Agent: gobuster/3.1.0 [+] Timeout: 10s =============================================================== 2022/09/04 18:12:25 Starting gobuster in directory enumeration mode =============================================================== /docs (Status: 200) [Size: 931] /redoc (Status: 200) [Size: 891] =============================================================== 2022/09/04 18:20:45 Finished =============================================================== ``` ![](https://i.imgur.com/1bx06Rw.png) ![](https://i.imgur.com/on6gVyw.png) >Following the instruction, I upload both shell script and python script(myzip.zip and myzip2.zip). The response contain body with "dirname-num", which may be dir_name that stored status.json file. ![](https://i.imgur.com/6JTWueI.png) >However, I cannot find that dir which store the status.json. >I've tried various possiblility in json format, like /{dir_naem:myzip2-3c493b90e7af78f3}, /{dir_naem:3c493b90e7af78f3}, /{dir_naem:myzip2}, {myzip2-3c493b90e7af78f3}, {myzip2}, {3c493b90e7af78f3} .etc. but all return 404. ![](https://i.imgur.com/6A5RTPe.png) ## misc ### welcome 簽到拼接遊戲 建議先解