wtf.sh-150( 需要Shell指令碼知識 )
註冊---->登入---->是一個論壇----->我們也發文章(如上圖)
發現http://61.147.171.105:56056/post.wtf?post=HYBRM#,post引數好像可以修改,嘗試路徑穿越
學習連結:https://zhuanlan.zhihu.com/p/593376086
拿到網頁原始碼
網頁搜尋flag
看到cookie和username都是admin就可以拿到flag
並且我們注意到裡面的一行程式碼
if contains 'user' ${!URL_PARAMS[@]} && file_exists "users/${URL_PARAMS['user']}"
contains 'user' ${!URL_PARAMS[@]}:這個部分是一個條件判斷語句。它看起來是在檢查陣列URL_PARAMS中是否存在名為user的索引。
${!URL_PARAMS[@]}:這部分是一個Shell陣列的用法,它會展開為陣列URL_PARAMS中的所有索引值。這個符號!用於間接引用,意味著${!URL_PARAMS[@]}會展開為user,如果URL_PARAMS陣列中有user索引的話。
contains 'user' ${!URL_PARAMS[@]}:這個部分是一個條件判斷語句。它看起來是在檢查陣列URL_PARAMS中是否存在名為user的索引。
&&:這個符號是邏輯AND運算子,表示如果前面的條件滿足,則執行後面的操作。
file_exists "users/${URL_PARAMS['user']}":這個部分是在檢查名為users目錄下是否存在名為${URL_PARAMS['user']}的檔案。${URL_PARAMS['user']}是user索引對應的值。
整個程式碼的含義是:如果URL_PARAMS陣列中存在名為user的索引,並且名為users目錄下存在名為${URL_PARAMS['user']}的檔案,則執行相應的操作
那我們去看看
推測一下,第二個就是cookie,第三個就是admin這個使用者的token了(因為抓個包就能看出來)
uYpiNNf/X0/0xNfqmsuoKFEtRlQDwNbS2T6LdHDRWH5p3x4bL4sxN0RMg17KJhAmTMyr8Sem++fldP0scW7g3w==
先主頁抓包,用Burp修改變成admin使用者,之後如圖1中所示,點選進行抓包修改然後拿到(get_flag1)
還得找後半段flag
繼續回去審計網頁原始碼(注意題目wtf.sh)
那什麼是.sh?
通常情況下,.sh檔案是指Shell指令碼檔案,其中包含了一系列Shell命令,通常用於執行特定的任務或操作。Shell指令碼是一種文字檔案,其中包含了一系列Shell命令,可以被直譯器(如Bash、sh等)讀取並執行。
在網頁上,如果遇到.sh檔案,它可能是提供給使用者下載的指令碼檔案,使用者可以在本地環境中執行這些指令碼來執行特定的任務。這些任務可能包括配置環境、部署應用程式、執行自動化任務等。
可能網頁上就存在
搜尋.sh,發現了一個比較有意思的東西
post_id=$(create_post "${COOKIES['USERNAME']}" "${POST_PARAMS['title']}" "${POST_PARAMS['text']}");
大概意思
create_post "${COOKIES['USERNAME']}" "${POST_PARAMS['title']}" "${POST_PARAMS['text']}":這部分是一個函式呼叫,其中包含三個引數,分別是使用者名稱、標題和文字內容。這個函式的作用是建立一個帖子,並返回新帖子的ID
$(...):這是一個命令替換的語法,表示執行括號中的命令,並將其輸出作為整體表示式的值。在這裡,create_post函式的呼叫被執行,其返回值(即新帖子的ID)會被賦給post_id變數
整個語句的含義是:使用${COOKIES['USERNAME']}作為作者名,${POST_PARAMS['title']}作為標題,${POST_PARAMS['text']}作為文字內容,建立一個帖子,並將新帖子的ID儲存在post_id變數中
我看著好像也沒對使用者名稱進行檢測,好像可以做手腳
繼續審計
from bs4 import BeautifulSoup
import html
html_content = """
在這放入html
"""
使用Beautiful Soup解析HTML
soup = BeautifulSoup(html_content, 'html.parser')
提取所有的文字內容
plain_text = soup.get_text()
解碼特殊字元轉義
decoded_text = html.unescape(plain_text)
print(decoded_text)
對比圖如下
function reply {
local post_id=$1;
local username=$2;
local text=$3;
local hashed=$(hash_username "${username}");
curr_id=$(for d in posts/${post_id}/*; do basename $d; done | sort -n | tail -n 1);
next_reply_id=$(awk '{print $1+1}' <<< "${curr_id}");
next_file=(posts/${post_id}/${next_reply_id});
echo "${username}" > "${next_file}";
echo "RE: $(nth_line 2 < "posts/${post_id}/1")" >> "${next_file}";
echo "${text}" >> "${next_file}";
# add post this is in reply to to posts cache
echo "${post_id}/${next_reply_id}" >> "users_lookup/${hashed}/posts";
}
來自AI
這段程式碼是一個Shell指令碼中的函式,名為 reply。下面是對其功能的總結:
1.reply 函式接受三個引數:post_id、username 和 text,分別表示帖子的ID、回覆者的使用者名稱和回覆的文字內容。
2.它首先計算回覆的ID。它透過查詢特定帖子目錄下已有的回覆檔案,找到最後一個檔案的ID,並在此基礎上加1,得到新的回覆ID。
3.然後,它建立一個新的回覆檔案,檔案路徑儲存在 next_file 變數中。
4.接著,它向新的回覆檔案中寫入回覆者的使用者名稱、回覆標題(透過呼叫 nth_line 函式從原帖子的第一行獲取)、以及回覆的文字內容。
5.最後,它將帖子ID和新回覆的ID新增到回覆者的帖子快取中,以便後續檢索。
也就是說:
這行程式碼把使用者名稱寫在了評論檔案的內容中:echo "${username}" > "${next_file}";
如果使用者名稱是一段可執行程式碼,而且可以讓我們寫入,那麼這個檔案就能夠執行我們想要的程式碼。
想一想要讀取檔案中的的內容要幹嘛?
1使用 cat 命令:cat 命令可以將檔案內容輸出到標準輸出流,可以透過管道將其輸出傳遞給其他命令進行處理。
cat filename
2使用 while 迴圈逐行讀取:可以使用 while 迴圈結合 read 命令逐行讀取檔案內容,並進行處理。
while IFS= read -r line; do
# 處理每一行的內容,例如輸出到螢幕
echo "$line"
done < filename
3使用 mapfile 命令:mapfile 命令可以將檔案內容讀入到陣列中,每一行對應陣列的一個元素。
mapfile -t array < filename
4使用 read 命令讀取檔案內容到變數:可以使用 read 命令將檔案的一行或多行內容讀入到變數中。
讀取一行內容到變數
read -r line < filename
搜尋一下 “read -r line”
看到一些有意思的函式
function log {
echo "[date
] $@" 1>&9
}
urldecode() {
# urldecode
local url_encoded="${1//+/ }"
printf '%b' "${url_encoded//%/\x}"
}
max_page_include_depth=64
page_include_depth=0
function include_page {
# include_page
local pathname=$1
local cmd=""
[[ "${pathname:(-4)}" = '.wtf' ]];
local can_execute=$?;
page_include_depth=$(($page_include_depth+1))
if [[ $page_include_depth -lt $max_page_include_depth ]]
then
local line;
while read -r line; do
# check if we're in a script line or not ($ at the beginning implies script line)
# also, our extension needs to be .wtf
[[ "$" = "${line:0:1}" && ${can_execute} = 0 ]];
is_script=$?;
# execute the line.
if [[ $is_script = 0 ]]
then
cmd+=$'
'"${line#"$"}";
else
if [[ -n $cmd ]]
then
eval "$cmd" || log "Error during execution of ${cmd}";
cmd=""
fi
echo $line
fi
done < ${pathname}
else
echo "
Max include depth exceeded!
"
fi
}
1.function include_page { ... }:定義了名為 include_page 的Shell函式,用於包含 .wtf 檔案並執行其中的內容
2.[[ ${pathname(-4)} = '.wtf' ]];:檢查副檔名是否為 .wtf
3.local can_execute=$;:初始化一個變數 can_execute,用於標記是否可以執行檔案
4.[[ $ = ${line01} && ${can_execute} = 0 ]]:檢查當前行是否為指令碼行(以 $ 開頭),並且 can_execute 變數為0,以確定是否可以執行該行
我們去看看正常評論能不能抓到什麼有用的的東西
好像沒有什麼用啊
參考大佬的wp
新建一個後門
%09是水平製表符,必須新增,不然後臺會把我們的後門當做目錄去解析
上文也提到了:[[ $ = ${line01} && ${can_execute} = 0 ]]:檢查當前行是否為指令碼行(以 $ 開頭),並且 can_execute 變數為0,以確定是否可以執行該行
所以我們新建一個使用者
${find / -iname get_flag2}//註冊不了
${find,/,-iname,get_flag2}//這樣就可以
登入---> 留言 ----> 評論 ----> 上傳檔案
拿到路徑
接著註冊
$/usr/bin/get_flag2
同樣的流程再來一次
拿到後半段flag