代碼審計入門


又補了一大章節的課程,對我來說感覺很多都要學習,不太會,那就先熟悉流程

1 代碼審計入門

1、常見的代碼審計工具

1、Fortify SCA

2、Checkmarx CxSuite

3、360代碼衛士

4、PHP代碼審計工具——Rips

參考:https://www.jianshu.com/p/cd1cb66e4d7d

5、seay代碼審計(常用)

參考:https://www.oschina.net/p/seay

6、SonarQube

參考:https://www.cnblogs.com/qiumingcheng/p/7253917.html

7、Cobra

參考:https://zhuanlan.zhihu.com/p/32363880

8、kiwi

參考:https://github.com/alpha1e0/kiwi

 

2、代碼審計中常見的危險函數和字符串

參考:

https://wps2015.org/drops/drops/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E5%85%A5%E9%97%A8%E6%80%BB%E7%BB%93.html

0x01 整體

0x02 各種洞洞

a.文件操作漏洞

1.文件包含漏洞:

(1) 本地文件包含:
(2) 遠程文件包含:
(3) 文件包含截斷:

2.文件讀取(下載)漏洞:

3.文件上傳漏洞:

(1) 未過濾或本地過濾:服務器端未過濾,直接上傳PHP格式的文件即可利用。

    (2) 黑名單擴展名過濾:

    (3) 文件頭 content-type驗證繞過:

(4) 防范:

4.文件刪除漏洞:

b.代碼執行漏洞

1.代碼執行函數:

(1) preg_replace()函數:

(2)mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed $…):
(3)eval()和assert():

2.動態函數執行:

3.命令執行函數:

(1) popenproc_open()

(2) 反引號命令執行:

c.變量覆蓋漏洞

1.函數使用不當:

2.$$變量覆蓋:

d.邏輯漏洞

1.等於與存在判斷繞過:

(1) in_array(): 比較之前會自動轉換類型
(2)is_numeric():當傳入參數為hex時 直接通過並返回true 並且MYSQL可以直接使用hex編碼代替字符串明文 可以二次注入 並且可能造成XSS漏洞

(3)雙等於==和三等於===

2.賬戶體系中的越權問題:

(1) 未exit/return/die:
(2) 支付漏洞

e.會話認證漏洞

  1. 找到傳入sql語句的參數的傳遞過程 回溯變量到最原始的函數 看它保存在cookie的算法 是否可逆
  2. 和MD5比起 sha1更安全 解密sha1的網站更少
  3. 限制一個用戶只能同時在一個IP上登錄

f.二次漏洞

1.類型:

2.技巧:

(1) 鑽GPC等轉義的空子:
  GBK的寬字節注入
(2)字符串問題:

2 常見的危險函數和審計點

1、RIPS審計工具的下載,安裝,使用

2、PHP常見的部分危險函數解析

2.1 PHP代碼執行函數

a.eval()

b.assert()

c.create_function()

2.2 PHP包含函數

常見的包含函數:require,include,require_once,include_once

include $file 中,如果變量 $file 可控,則就可以包含任意文件。

此外,根據不同的配置環境,可以包含不同的文件:遠程文件和本地文件。

包含函數還可以通過支持的協議和封裝協議以及 過濾器讀取任意文件內容。

例子,如

利用php流filter讀取任意文件

include($_GET('file');

// ?file=php://filter/convert.base64-encode/resource=index.php

上面的代碼中,就通過filter讀取index.php的內容,並將內容編碼成base64再輸出。

 

2.3命令執行函數

常見的命令執行函數有:

* exec() -- 執行一個外部程序

* passthru() -- 執行外部程序並顯示原始輸出

* proc_exec() -- 通過shell環境執行命令,並且將完整的輸出以字符串的方法返回

* system() -- 執行外部程序,並且顯示輸出

* popen() -- 通過popen()的參數傳遞一條命令,並對popen()所打開的文件進行執行。

2.4 文件操作函數常見的任意文件讀取,寫入,刪除往往是下面幾個函數受到了控制.

copy() -- 拷貝文件

file_get_contents() -- 將整個文件讀入一個字符串

file_put_contents() -- 將一個字符串寫入文件

file() -- 將整個文件讀入一個數組中

fopen() -- 打開文件或者URL

move_uploaded_file() -- 將上傳的文件移動到新位置

readfile() -- 讀取文件

rename() --重命名文件或者目錄

rmdir() -- 刪除目錄

unlink() & delete() -- 刪除文件

 

詳細參考鏈接:https://www.zybuluo.com/Dukebf/note/715934

https://www.bbsmax.com/A/pRdB8DR6Jn/

3 代碼審計實戰之SQL注入漏洞

1.基本技巧

sql注入漏洞通常有兩種利用方式。一種是權限較大,直接寫入webshell,另外一種是權限較小,但是可以讀取用戶賬號密碼,比如讀取管理員賬號密碼,登錄后台管理。

sql注入經常出現在登錄頁面http請求中的user-agent,client-ip,x-forward-for等可能會被程序存儲到數據庫中的地方。另外,在訂單處理的地方,由於業務邏輯復雜,經常會有二次注入漏洞。

至於在白盒審計中,若想定向挖掘sql注入漏洞,只需要注意這幾個數據庫操作關鍵字:select from , mysql_connect , mysql_query , mysql_fetch_now , update , insert , delete ; 查到這些關鍵字后,定向追蹤他們,就可以審計sql注入漏洞

 

 

2.編碼注入

程序在進行一些操作之前,經常會進行一些編碼處理,通過輸入一些編碼函數不兼容的特殊字符,可以導致輸出的字符變成有害數據。其中最常見的編碼注入就是mysql的寬字節注入以及urldecode/rawurldecode這兩個函數。

寬字節注入

怎么說呢,這個漏洞以前研究過,但是總是沒研究透。個人感覺,只要是set character_set_client='gbk'或者set NAMES 'gbk',那么就可能存在漏洞。至於原理雖然無法搞的十分清楚,但是可以直接手工測試。看能否吃的掉轉義字符。

解決這個漏洞的方法:

第一種方法,set NAMES 'gbk' 之后,在 set character_set_client=binary就可以了。

第二種方法,使用pdo方式,在php5.3.6及以下版本設置 setAttribute(PDO::ATTR_EMULATE_PREPARES,false);來禁用prepared statements的仿真效果。

綜上所述,要想看代碼中是否有寬字節注入,那么搜索幾個關鍵字:

SET NAMES

character_set_client

mysql_set_charset('gbk')

 

二次urldecode注入

如果目標網站開啟了GPC,並且用了urldecode或者rawurldecode函數,那么通過二次解碼,第二次就會解析出單引號,導致注入。

 

因此,在代碼審計中,可以通過搜索urldecode和rawurldecode來挖掘二次注入漏洞。

 

常見的注入點:

  • 輸入
  • HTTP頭
  • user-agent
  • client-ip
  • x-forward-for
  • 數據庫操作關鍵字
  • select/update/insert/delete
  • mysql_connect
  • mysql_query
  • mysql_fetch_row

 

編碼注入

sql注入預防方法

通常,程序要么被動獲取參數,比如get,post;要么主動讀取文件或者遠程頁面;因此,過濾好這兩條路,就可以防止sql注入。

在PHP的核心配置中,magic_quotes_gpc負責對get,post,cookie的值進行過濾,magic_quotes_runtime對從數據庫中或者文件中獲取的數據進行過濾。

但是,上面兩種方法只能過濾部分sql注入,因為他們只是轉義了單引號,雙引號,反斜杠\,空字符null,對int注入沒什么用。因為int類型可以直接接sql語句,不需要閉合。

 

addslashes函數

這個函數對參數中的單引號,雙引號,反斜線,空字符進行過濾。但是有的程序員在開發的時候,沒有考慮到get請求中可能存在數組(這個函數是對字符串進行過濾),導致了繞過。

說實話,get請求中帶數組是怎么帶的?這個我還真比較懵。估計得完整開發一個網站之后,才能知道get請求中帶數組是怎么回事?

mysql_rel_escape_string($str,$con)

這個函數也是過濾,第一個參數是字符串,第二個參數可選,是數據庫連接,若沒有設置第二個參數,那就默認為上一次連接的數據庫。

這個函數主要過濾的是:\x00,\n,\r,\,',",\x1a

但是,這里的\x00和\x1a我不太懂是什么意思。

intval()函數

前面的函數針對的是字符型注入,對Int型注入效果不是太好。因此,這個intval()函數就是以白名單的思想,對數據進行過濾。

 

4 代碼審計實戰之任意文件上傳

1、代碼審計之文件上傳漏洞危險函數的繞過姿勢

A.move_uploaded_file() 接着看調用這個函數的代碼是否存在為限制上傳格式或者可以繞過。

B.getimagesize函數驗證:只要在文件頭添加GIF89a即可;

C文件頭content-type驗證繞過:驗證$_FILES[“file”][“type”]的值,這個是可控的。

D.函數誤用導致上傳繞過

以iconv()函數為例,在iconv轉碼的過程中,utf->gb2312(其他部分編碼之間轉換同樣存在這個問題)會導致字符串被截斷,如:$filename=”shell.php(hex).jpg”;(hex為0x80-0x99),經過iconv轉碼后會變成$filename=”shell.php “。

E.競爭上傳,主要涉及到的為copy函數。

 

2、文件上傳漏洞審計流程

  1. 審計函數
  2. move_uploaded_file()
  3. 定義和用法:
  4. move_uploaded_file() 函數將上傳的文件移動到新位置。
  5. 若成功,則返回 true,否則返回 false。
  6. 語法:
  7. move_uploaded_file(file,newloc)
  8. 超全局變量 $_FILES
  9. 后綴名是圖片格式
  10. 前綴名不能是外部提交的
  11. 上傳的目錄不可以是獲取外部提交的路徑

 

3、代碼舉例分析

文件上傳首先需要一個表單,如下,我們把它叫做a.html

<form action="t.php" method="post" enctype="multipart/form-data"><input name="aaa" type="file" /><input type="submit" /></form>

這里有幾個要素:

  • action屬性是提交的目標。
  • method屬性是提交所用的HTTP方法,常用的就是 POST 和 GET,文件上傳一般用 POST。
  • enctype屬性必須要寫成這樣,因為文件上傳和普通的提交具有不同的編碼方式。如果不寫的話,可能會被當做urlencoded,就是k1=v1&k2=v2的鍵值對形式,導致解析不出東西。
  • 最后是文件輸入框,它的name屬性非常重要,它是PHP腳本中尋找文件的關鍵字。

接下來是PHP腳本中的東西,PHP中通過$_FILES對象來讀取文件,通過下列幾個屬性:

  • $_FILES[file]['name'] - 被上傳文件的名稱。
  • $_FILES[file]['type'] - 被上傳文件的類型。
  • $_FILES[file]['size'] - 被上傳文件的大小(字節)。
  • $_FILES[file]['tmp_name'] - 被上傳文件在服務器保存的路徑,通常位於臨時目錄中。
  • $_FILES[file]['error'] - 錯誤代碼,0為無錯誤,其它都是有錯誤。

t.php中的代碼寫成這樣:

<?phpif(!isset($_FILES['aaa'])) {
    echo 'file not found';
    exit();
}

var_dump($_FILES['aaa'])

可以看到那個aaa就是文件輸入框中的name屬性。

我們把這兩個文件放到服務器的目錄中,或者直接在目錄下啟動PHP自帶的服務器。之后打開a.html隨便傳上去一個文件,會得到這樣的結果,這里我直接上傳了a.html

array(5) { 
    ["name"]=> string(6) "a.html" 
    ["type"]=> string(9) "text/html" 
    ["tmp_name"]=> string(44) "C:\Users\asus\AppData\Local\Temp\php43A1.tmp" 
    ["error"]=> int(0) 
    ["size"]=> int(133) 
}

需要說的是,在處理文件上傳的時候,不應信任文件類型type,因為類型在瀏覽器生成之后,是可以改的。甚至可以手動構造出於類型與實際內容不匹配的數據包。

同時也不應該信任文件名稱name。而是應該分離文件名與擴展名,對擴展名進行白名單過濾。文件名按需舍棄重新生成,或者過濾后再使用。

5 PHP反序列化漏洞代碼審計

1、什么是序列化

A、PHP網站的定義:

B、PHP反序列化

2、理解PHP反序列化漏洞

3、PHP反序列化漏洞利用的前提

a.unserialize()函數的參數可控;

b.php文件中存在可利用的類,類中有魔術方法

4、PHP反序列化漏洞—發現技巧

5、PHP反序列化漏洞—構造exploit思路

6、案例分析

https://www.cnblogs.com/xiaozi/p/7839256.html

https://www.grt1st.cn/posts/php-unserialize-analysis/

注:以上大多轉自破殼筆記學習資料,歡迎大家前來報名學習

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM