這是tr0ll2靶機涉及到的東西,先看一下在這個靶機上的過程。
咱們獲取了noob用戶的ssh密鑰,以後登陸卻失敗了:
以後咱們輸入以下命令:html
ssh noob@192.168.16.141 -i noob -t '() { :;}; /bin/bash'
再次登陸,竟然成功了:
以上就是shellshock攻擊,其利用的是bash在導入環境變量函數時候的漏洞,啓動bash的時候,它不只會導入這個函數,也會把函數定義後面的命令執行,在有些CGI腳本的設計中,數據是經過環境變量來傳遞的,這樣就給了數據提供者利用Shellshock漏洞的機會。shell
這個漏洞剛開始接觸還會以爲有些奇怪,由於命令自己就是bash執行的,不以爲有什麼危害。實際環境中在遠程訪問時,有些CGI會把post包中的變量導入成用戶變量,並起一個子bash來運行。bash
成因分析以下,參考了一位博主的文章,結尾貼連接:
在 bash 中能夠自定義 Shell 變量 , 以下所示網絡
但此時該變量僅是當前 Shell 的一個局部變量 , 只有在當前 Shell 進程中能夠調用 . 即便是當前 Shell Fork 出的子進程 , 也是不能訪問該變量的 .ssh
爲此 , 咱們能夠經過 export 命令 , 將該變量轉變爲一個環境變量 , 這樣當前 Shell 的子進程就能夠訪問它了
不只如此 , 在 Bash 中還能夠定義 Shell 函數並將其導出爲環境函數 , 只須要指明 -f
參數便可
上圖這種函數的定義方法是很是廣泛的 , 很容易理解 . 但在 Bash 中還有一種獨有的方法來定義函數 , 即 : 經過環境變量來定義函數函數
當某個環境變量的值以字符串 " () {
" 的格式做爲開頭( 注意大括號與小括號間的空格不能少 ) , 那麼該變量就會被當前 Bash 看成一個導出函數( export function
) , 該函數僅會在當前 Bash 的子進程中生效 . 在不少文章中會把它稱爲 Bash 的 "`自動導入機制( 自動導入函數到當前 Bash
由於這種獨特的函數定義方式僅會在當前 bash 的子進程中生效 , 因此網絡上不少帖子給出的 POC 都是下面這樣 .post
POC : env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
經過 bash -c
開啓當前 Bash 的子進程 , 在子進程載入時會初始化用戶環境變量 , 在初始化時發現了包含 "() {
" 格式的字符串 , 因此將該字符串做爲一個自動導入函數 . 但因爲沒有判斷函數定義的結束 , 因此錯誤的將該函數定義後的語句也初始化並看成命令執行了 . 因此子 Bash 會執行該語句並輸出 vulnerable
, 而後再輸出 this is a test
.測試
簡單的說 , 就是將惡意命令添加到合法的Bash函數定義後 , 在啓動子進程時 , Bash 會先執行惡意命令 , 而後再執行正常的指令 .ui
在 Shellshock漏洞回顧與分析測試 中有一副圖作的很是棒 , 十分容易理解 , 這裏貼出來 .this
以後看一下源代碼:
由於 ShellShock 觸發於 Bash 子進程初始化環境變量的時候 . 因此咱們進入 variables.c
文件 , 找到 initialize_shell_variables()
函數 .
這裏先定義了一些參數 , 而後循環遍歷全部環境變量 , 經過 " = " 來分割變量名與變量值。以後判斷剛纔獲取到的環境變量中是否有不合法的( 好比 "=xxx
" 或者沒有等號的 ) . 若是發現不合法的變量 , 就跳過它們,並賦值。再以後先判斷是否存在自動導出函數( 經過 "() {
" 來判斷 ) , 若存在就將其定義爲一個函數 . 同時判斷當前是否處於 privileged mode
,若不處於該模式就將以前導出的函數導入到新的環境變量中 .
注意這裏 , string( 獲取到的環境變量值 ) 沒有進行任何過濾 , 就被放入到 parse_and_execute
函數中 . 這是典型的注入漏洞。