這兩題跟之前 Lab - phpisbest 差不多,只要在後面加上 /?A[]=[0]&B[]=[3]
就能達成各種 null==null
就能過關了
這題我有觀察到可以 path traversal,但是我亂戳戳不到東西,過了大概十分鐘,又沒忍住點了一下 hint ,才發現要戳的東西就是寫在原始碼裡面的 config.php
,就能前往下一關了
這題她沒有一個地方讀取 👀
,但有個 extract($_POST)
可以利用 POST
的方式輸入 👀
,之後就跟 lfi2rce
一樣,利用 php filter chain 構造出 webshell ,就能得到 Flag 了
Note: 這邊要注意的是這個 webshell 指令最後需要的參數 1
,他是透過 $_GET[1]
來取得的,所以要寫在網址後面解析,不是寫在 POST 裡面
他很好心的給我們看了他生成的原始碼
#!/usr/local/bin/python3
import sys
if __name__ == '__main__':
if len(sys.argv) < 2:
print("no argument")
sys.exit()
magic_num = int(sys.argv[1]) if sys.argv[1].isdigit() else sys.argv[1]
if magic_num == 0:
print("0 is not allowed")
sys.exit()
while magic_num != 1:
with open(f"fakelog/{magic_num % 6 if isinstance(magic_num, int) else magic_num}", "r", encoding="utf-8") as fd:
print(fd.read())
magic_num = 3 * magic_num + 1 if magic_num % 2 else magic_num // 2
重點有兩個
magic_num = int(sys.argv[1]) if sys.argv[1].isdigit() else sys.argv[1]
with open(f"fakelog/{magic_num % 6 if isinstance(magic_num, int) else magic_num}", "r", encoding="utf-8") as fd:
他不會檢查 magic number 是文字,而且在他是文字的時候他還會直接讓我們讀取檔案,所以我們可以利用這個漏洞來做 path traversal
又可以從 Hint 的 dockerfile 中知道有個叫 main.py
是主程式,拿出來看看
FROM python:3.10
RUN curl -sSL https://install.python-poetry.org | POETRY_HOME=/etc/poetry python3 -
WORKDIR /app
COPY pyproject.toml poetry.lock .
RUN /etc/poetry/bin/poetry config virtualenvs.create false && \
/etc/poetry/bin/poetry install
COPY . .
ARG FLAG
RUN echo $FLAG > /app/flag_`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1`
USER daemon
ENTRYPOINT ["python", "/app/main.py"]
result:
from flask import Flask, render_template, request, send_file
import subprocess
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/howtogen')
def howtogen():
return send_file('gen.py', mimetype='text/plain', as_attachment=False)
@app.route('/hint')
def hint():
return send_file('Dockerfile', mimetype='text/plain', as_attachment=False)
@app.route('/gen', methods=['GET', 'POST'])
def get_input():
message = None
if request.method == 'POST':
user_input = request.form['user_input']
if " " in user_input:
result = "evil input"
else:
result = subprocess.run(
f"python gen.py {user_input}", shell=True, capture_output=True, text=True).stdout.replace('\', '')
message = f"result: {result}"
return render_template('generate.html', message=message)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5050)
可以知道不能輸入空白,另外還有他執行程式的方法是
subprocess.run(
f"python gen.py {user_input}", shell=True, capture_output=True, text=True).stdout.replace('\', '')
可以讓我們利用類似 ;id
這樣的方式來達到 RCE,空白就用 ${IFS}
來代替,隨便戳戳看之後就能拿到 Flag 了