代碼審計入門實戰

2020-12-16 湖南蟻景

前段時間在整理一個PHP函數代碼審計的項目,所以文章也是圍繞PHP的代碼審計來寫,如果有寫的不對的地方,還請大佬們指正。文章開始前,我們先來了解一下PHP是什麼。

0x01 PHP是什麼

根據百度百科的描述,PHP是一種在伺服器端執行的通用開源腳本語言,主要適用於Web開發。

既然是網站程式語言,自然需要一款工具輔助程式設計師高效編程。PhpStorm就是一款PHP集成開發工具,可以隨時幫助程式設計師對代碼進行調整、運行單元測試、且提供可視化debug功能。

當然也可以使用其他工具對PHP程序進行調試,比如Xdebug,一款開放源碼的PHP debug工具,用來跟蹤、調試和分析PHP程序的運行狀況。

大家可以通過學習這個實驗,掌握PhpStorm環境搭建和Xdebug工具的安裝和配置:

留言或私信獲取實驗地址哦~

網傳這麼一個段子:如何讓一個論壇的人吵起來?答:PHP是世界上最好的語言。這個梗出自PHP的官方文檔,最早出現在2001年7月的PHP文檔中。雖然有PHP是世界上最好的語言這種說法,但是也有一些因為弱類型語言的安全性問題出現,這就需要安全人員通過代碼審計來檢查PHP程序的安全性。

0x02 代碼審計又是什麼

代碼審計,顧名思義就是檢查原始碼中的安全缺陷。通過自動化工具或人工審查的方式,對程序原始碼逐條進行檢查和分析,發現源碼缺陷引發的安全漏洞,有時還需要提供代碼修訂措施和修復建議。

軟體的原始碼、程序缺陷可能導致嚴重的安全漏洞,要消除代碼中的漏洞、減少不必要的補丁升級,就需要進行原始碼的安全審計。原始碼審計是對代碼庫和軟體架構的安全性、可靠性進行全面的安全檢查。人工審查已經成為軟體源碼設計、開發和應用的最佳保障,因此做好代碼審計就是從安全的角度對整個代碼質量進行評估。安全人員需要在黑客發現系統漏洞之前,找出應用的安全隱患,並提供相應的安全報告和修複方法,從而提高應用系統的安全性。

除了人工審查的方式,還可以通過一些自動化工具進行代碼審計,下面簡單介紹兩種代碼審計利器:

1、 Seay原始碼審計系統

這是一款針對PHP代碼安全審計的系統,基於C#語言開發,主要運行於Windows系統上。這款軟體能夠發現SQL注入、代碼/命令執行、文件包含、文件上傳、拒絕服務、XSS、信息洩露、任意URL跳轉等漏洞。關於Seay原始碼審計系統工具的使用,可以通過下面的實驗進行學習:

實驗地址留言或私信獲取哦

2、 RIPS

RIPS通過標記和解析所有原始碼文件,自動檢測PHP應用程式中的漏洞。RIPS能夠將PHP原始碼轉換為程序模型,檢測程序流期間用戶輸入可能汙染的敏感接收器,即潛在易受攻擊的函數。RIPS工具的使用參考下面的實驗:

實驗地址留言或私信獲取哦

學習了代碼審計的常用工具,相信大家會對代碼審計的方法和步驟有一定的了解,那麼接下來簡單總結一下代碼審計的流程:

① 通讀全文代碼:更好地了解程序的架構及業務邏輯,挖掘更多高質量的漏洞;

② 通讀敏感功能點:快速挖掘某種漏洞;

③ 正向追蹤可控變量;

④ 敏感關鍵字回溯參數傳遞過程。

下面進入文章的重點部分——PHP函數的代碼審計,通過具體實例分析PHP部分函數,包括in_array函數、filter_var函數、escapeshellarg與escapeshellcmd函數、parse_str函數及addslashes函數,學習上述函數缺陷引發的漏洞及利用方式,結合CTF練習掌握PHP函數漏洞審計流程。

0x03 PHP函數的代碼審計

這裡我們根據《PHP函數漏洞審計》課程順序進行學習。

一、PHP代碼審計之in_array函數

既然是對in_array函數進行具體分析,我們先來了解一下in_array函數的相關定義:

註:後面說到的函數定義均來自PHP手冊,手冊地址:

$needle變量表示待搜索的值,$haystack表示待搜索的數組。in_array函數用法為:在$haystack數組中搜索$needle變量的值,檢查值是否存在。如果第三個變量$strict的值為true,則in_array函數會進行強檢查,檢查$needle的類型是否和$haystack數組中的相同。

in_array函數為什麼會存在漏洞呢,原因是程式設計師在使用in_array函數進行數據處理時,未使用第三個參數進行嚴格匹配,比如Piwigo軟體2.7.1版本就是因為in_array函數的不安全使用,導致SQL注入漏洞發生。

查看源碼/picture.php文件可以發現,當$_GET[『action』]為rate時,會調用文件/include/function_rate.inc.php文件中的rate_picture方法,漏洞就存在於這個方法中:

而在rate_picture方法中,使用了in_array函數對$rate變量進行檢測,判斷$rate是否在$conf['rate_items']中:

由於functions_rate.inc.php文件中沒有將in_array函數的第三個參數設置為true,所以會進行弱比較,可以將$rate的值設置成1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));#進行繞過。

那麼SQL語句就變成:

INSERT INTO piwigo_rate(user_id,anonymous_id,element_id,rate,date) VALUES (2,'192.168.2',1,1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));#,NOW())

這樣就可以進行盲注了。直接利用sqlmap進行漏洞利用:

python sqlmap.py -u "http://10.1.1.79/piwigo/picture.php?/1/category/1&action=rate" --data "rate=1" --dbs

還可以用sqlmap獲取目標資料庫的表及敏感數據。總結一下in_array函數的審計流程:

大家可以訪問合天網安實驗室,學習in_array函數缺陷引發的相關漏洞及其利用方式

二、PHP代碼審計之filter_var函數

filter_var函數定義:

$variable變量表示待過濾的變量(變量的值在過濾前,會被轉換成字符串),$filter變量表示要應用的過濾器的ID,$options變量代表一個選項的關聯數組或按位區分的標識。filter_var函數返回過濾後的數據,過濾失敗則返回false。

這裡以一個CTF練習介紹filter_var函數缺陷引發的漏洞可以怎麼利用,題目考察filter_var函數的繞過與遠程命令執行。題目源碼為:

程序使用exec函數來執行curl命令,很容易讓人聯繫到命令執行。可以看到用於拼接命令的$site_info變量是從用戶傳來的url參數,經過filter_var和parse_url兩個函數過濾而來。之後又規定當url參數的值以hetianlab.com結尾時,才會執行exec函數。

這就需要繞過filter_var和parse_url函數,並且需要滿足$site_info['host']的值以hetianlab.com結尾,然後通過執行系統命令獲取flag。

Payload為/ctf/index.php?url=demo://%22;ls;%23;hetianlab.com:80/

直接用cat f1agi3hEre.php命令過不了filter_var函數檢測,因為包含空格,使用如下payload獲取flag:/ctf/index.php?url=demo://%22;cat<f1agi3hEre.php;%23;hetianlab.com:80/

總結一下filter_var函數的審計流程:

快去合天網安實驗室搜索實驗--PHP代碼審計之filter_var函數

三、PHP代碼審計之escapeshellarg與escapeshellcmd函數

先看一下兩個函數的相關定義,escapeshellarg函數:

$arg變量表示需要被轉碼的參數,函數返回值為轉碼之後的字符串。escapeshellcmd函數:

$command變量代表要轉義的命令,函數返回值為轉義後的字符串。以一個由PHP內置函數mail,結合escapeshellarg與escapeshellcmd函數所引發的命令執行漏洞為例,代碼如下:

第4行代碼的作用是確保只使用有效的電子郵件地址$email,filter_var函數用於使用特定是過濾器過濾一個變量。PHP的mail函數在底層實現中,調用了escapeshellcmd函數,對用戶輸入的郵箱地址進行檢測。即使存在特殊符號,也會被escapeshellcmd函數處理轉義,無法達到命令執行的目的。第6行代碼的作用是處理$email傳入的數據,而escapeshellarg和escapeshellcmd兩個函數一起使用,會造成特殊字符逃逸,導致遠程代碼執行。

PHPMailer命令執行漏洞(CVE-2016-10033)也是利用escapeshellarg和escapeshellcmd兩個函數結合使用,導致了單引號逃逸。具體的漏洞分析和利用過程可以去合天網安實驗室搜索下面這個實驗進行學習:

總結一下escapeshellarg與escapeshellcmd函數的審計流程:

四、PHP代碼審計之parse_str函數

同樣先了解parse_str函數的相關定義:

$encoded_string變量代表輸入的字符串,如果設置了第二個變量result,變量將會以數組元素的形式存入數組,作為替代。下面簡述parse_str函數缺陷引發的變量覆蓋漏洞,代碼如下:

由於第22行parse_str()調用,其行為非常類似於註冊全局變量,通過提交類似config[dbhost]=127.0.0.1這樣的數據,因此可以控制getUser()中第6到第9行的全局變量$config。如果目標存在登錄驗證的過程,就可以通過變量覆蓋的方法,遠程連接我們自己的MySQL伺服器,從而繞過登錄驗證進行下一步攻擊。一個簡單的例子:

直接覆蓋了原有的變量$b。

parse_str函數還有一個有意思的CTF練習,首先利用PHP哈希比較缺陷,構造請求參數,使其經過哈希之後,值是以』OE』開頭。缺陷就是如果兩個不同的密碼經過哈希之後,其哈希值都是以'OE'開頭,PHP將會認為它們結果都為0。請求後頁面會出現『flag is here』,點擊跳轉至flag.php。題目真正的考察點在於flag.php存在一個refer判斷,判斷refer是否存在,如果存在則展示上傳頁面,否則返回『you can not see this page』。接下來的部分存在時間競爭問題,需要在寫入too slow之前訪問之前寫入的文件,才能獲取flag。

此題的解法是開burp的200線程不斷發包,在start attack之前寫一個腳本不斷請求寫入文件的路徑,是變量覆蓋與競爭條件漏洞的結合利用。

CTF練習地址:合天網安實驗室搜索相關實驗

總結一下parse_str函數的審計流程:

五、PHP代碼審計之addslashes函數

addslashes函數相關定義:

$str表示要轉義的字符,當我們要往資料庫中輸入數據時,例如將名字O’reilly插入到資料庫中,就需要對其進行轉義。以一個用戶登錄程序為例,考察通過SQL注入繞過登錄驗證,代碼如下:

第29行通過POST方式傳入user和passwd兩個參數,通過isValid函數判斷是否合法。isValid函數主要功能代碼在第10~20行,調用sanitizeInput方法對user和passwd進行相關處理。sanitizeInput方法主要功能代碼在第22~25行,針對輸入的數據調用addslashes函數進行處理,然後對處理後的內容進行長度判斷,長度大於20則只截取前20個字符。

這道題已經過濾了單引號,正常情況是沒有注入了,為什麼還能導致注入呢?原因實際上出在第24行substr函數這裡,下面簡單看一下substr函數的定義:

substr函數的參數說明:string表示輸入的字符串(至少有一個字符),如果start為非負數,返回的字符串從string的start位置開始,從0開始計算;如果start為負數,返回的字符串從string結尾處向前數,從第start個字符開始。

註:如果string的長度小於start,將返回false。

length:如果length為正數,返回的字符串將從start處開始,最多包括length個字符(取決於string的長度);如果length為負數,string末尾處的length個字符將會被省略(若start是負數則從字符串尾部算起);如果length為0、false或null,則返回一個空字符串;如果沒有提供length,返回的字符串將從start位置開始,直到字符串結尾。關於substr函數一個簡單的例子:

substr中的參數0代表從位置為0的字符開始計算,2代表返回的字符串將從0(start)處開始最多包括2(length)個字符。

再回到題目中,我們知道反斜槓可以取消特殊字符的用法,而注入想要通過單引號閉合,必然會引入反斜槓。將官方提供的payload帶入題目中,拼接第15~17行代碼中的SQL語句:select count(p) from user u where user = 』1234567890123456789\』 AND password = 『$pass』

這裡的SQL語句由於反斜槓的原因,user=』1234567890123456789\』最後這個單引號會失去它的作用,我們讓password=or 1=1#,那麼最後的SQL語句為:select count(p) from user u where user = 』1234567890123456789\』 AND password = 『or 1=1#』

此時user值為1234567890123456789\』 AND password =,可以保證帶入資料庫執行的結果為true,就能順利地通過驗證。因此使用形如user=1234567890123456789』&passwd= or 1=1#的payload即可逃逸出\(反斜槓)注入。

蘋果CMS視頻分享程序8.0版本也曾爆出過SQL注入漏洞,程序調用addslashes函數對反斜槓進行轉義處理,但是對用戶請求的參數又會進行url解碼,因此可以使用雙url編碼繞過addslashes函數,觸發漏洞。

具體的漏洞分析過程可以通過下面的實驗進行學習:

總結一下addslashes函數的審計流程:

0x04 總結

除了上面提到的,PHP還有很多常見危險函數,合天網安實驗室也有相關的實驗方便大家了解PHP常見的危險函數,以及使用這些函數可能導致的漏洞。

代碼審計重在分析、重在堅持。文章看到最後,相信大家對代碼審計這個名詞不再陌生,學習完上述所有的實驗,再上GitHub找幾個代碼審計的案例源碼練練手,差不多就算入門了。安全學習貴在實踐、貴在總結,還記得文章一共提到了哪些實驗嗎,還等什麼,搜索前往合天網安實驗室進行學習啊!

相關焦點

  • Python代碼審計實戰案例總結之CRLF和任意文件讀取
    介紹Python代碼審計方法多種多樣,但是總而言之是根據前人思路的遷移融合擴展而形成。
  • 五天入門深度學習,這裡有一份PyTorch實戰課程
    機器之心整理參與:李亞洲、路這是一門五天入門深度學習的實戰課程想入門深度學習的小夥伴有福了!dataflowr 最近推出了一門五天初步掌握深度學習的實戰教程(實戰使用 PyTorch 框架),有知識點有實例有代碼,值得一看。
  • 搜索 PHP代碼審計之旅
    但如果這些代碼是分布在一套源碼中(如CMS),需要我們去發現,去找到並會利用,就需要有一定的查找以及利用思路,這次測試的是BlueCMS1.6,重要不在於去復現這個CMS的漏洞,而在先了解一下整個審計思路還有過程是怎麼樣的,去鍛鍊自己的審計能力。由於我比較菜,所以有錯誤的地方也請師傅們指正。何為白盒、黑盒、灰盒測試審計代碼會經常遇到這三個名詞,這又代表是什麼意思那?
  • 代碼審計中滲透測試的智能化分析
    在其中智能化代碼審計便是安全防護智能化繞不過去的坎。這次我們就一塊聊聊智能化代碼審計的發展歷程,也順帶講一講怎樣開展1個智能化靜態數據代碼審計的核心。智能化代碼審計在聊智能化代碼審計軟體以前,最先我們必需要明白2個定義,少報率和漏報率。
  • 推薦:《機器學習實戰:基於Scikit-Learn和TensorFlow》中文翻譯和代碼下載
    本文提供機器學習入門的好書《機器學習實戰:基於Scikit-Learn和TensorFlow》的中文翻譯文件和原始碼下載。一、前言推薦一本機器學習入門的好書:《機器學習實戰:基於Scikit-Learn和TensorFlow》。
  • XDCMS V1 代碼審計之旅
    前奏俗話說的好:「工欲善其事,必先利其器」,下面我理了一下這次審計的思路3:訪問特定功能點,進行特定代碼審計,也就是說一個功能點看一段代碼(這裡如果出現了過濾函數,基本上可以在2中找到)審計之旅先打開首頁看看,看到有登陸框和註冊框,那就先從註冊框開始審計
  • 薦書 | Kotlin開發快速入門與實戰
    資深軟體開發工程師根據Kotlin最新版本撰寫,內容全面,系統講解Kotlin開發技巧和項目實戰,將為您打造一個全棧工程師。1.零基礎在學習本書之前不需要具備任何的計算機專業背景,任何有志於APP開發的讀者都能利用本書從頭學起。
  • Python Web 開發入門實戰【教學大綱+教學進度表】
    《Python Web開發從入門到實戰》
  • 【新教學上架】您的ZBrush由您定義 | ZBrush腳本入門和實戰案例教程
    ZBrush腳本入門和實戰案例教程本教學由花月風清老師錄製,從零開始、由淺入深地帶大家學習zscript基礎以及實例代碼的編寫
  • 美國安全審計公司CERTIK完成去中心化借貸協議TLC智能合約代碼審計
    至此,Super Trister已通過包括成都BEOSIN鏈安科技在內的TLC智能合約代碼「雙審計」。合約審計的目的主要是檢查代碼規範性、常規漏洞、安全漏洞、業務邏輯漏洞等,最關鍵是減少因代碼導致的業務無法按預期正常運轉,其次是保障資金的安全;第三方面也是體現智能合約部署後的「公平、公開、公正、透明」等。
  • 美國安全審計公司CERTIK完成去中心化借貸協議TLC智能合約代碼審計...
    至此,Super Trister已通過包括成都BEOSIN鏈安科技在內的TLC智能合約代碼「雙審計」。圖2:Super Trister去中心化借貸協議TLC智能合約代碼安全審計結果預覽  合約審計的目的主要是檢查代碼規範性、常規漏洞、安全漏洞、業務邏輯漏洞等,最關鍵是減少因代碼導致的業務無法按預期正常運轉,其次是保障資金的安全;第三方面也是體現智能合約部署後的「公平、公開、公正、透明」等。
  • C/C++學習指南系列 QT界面開發入門與實戰視頻教程
    課程名稱: C/C++學習指南系列 QT界面開發入門與實戰視頻教程課程簡介:C/C++學習指南系列 QT
  • 【Vue.js入門到實戰教程】11-Vue Loader(下)| 編寫一個單文件 Vue 組件
    編寫 ModalExample 組件我們將 vue_learning/component/slot.html 中的 modal-example 組件拆分出來,在 vue_learning/demo-project/src/components 目錄下新建一個單文件組件 ModalExample.vue,將 modal-example 組件代碼按照 Vue Loader 指定的格式填充到對應位置
  • 三款商業化原始碼審計工具對比
    原始碼檢測屬於程序分析領域,需要具有相關領域的技術儲備,很多傳統的安全廠商都沒有相關的商業化技術產品。網上有很多開源的審計工具,但檢測能力、檢測精度較差,本文結合多年對原始碼檢測產品的了解,介紹三款較為成熟的商業化原始碼檢測產品。
  • Python實戰進階,一套就夠了~
    一切的基礎知識,都是為了後期的實戰應用做鋪墊。那麼學完基礎,如何實戰和進階呢?明日科技針對進階階段的同學,亦或是對實戰訓練有需求的同學,提供了一套非常實用的套裝:Python實戰入門三劍客:《零基礎學Python》+《Python實效編程百例·綜合卷》+《Python項目開發實戰入門》。
  • 《PyTorch 機器學習從入門到實戰》國內最懂「小扎」的技術團隊...
    近日,由校寶在線CTO孫琳,攜校寶研究院技術專家項斌、蔣陽波、汪建成共同撰寫的國內首款介紹PyTorch 深度學習框架在教育信息化領域實戰操作書籍《PyTorch 機器學習從入門到實戰》 正式出版了。作為最早介入PyTorch 深度學習框架研究的國內技術團隊之一,該書向想要學習PyTorch 深度學習框架學習者,提供從基礎入門到商業實操的全部經驗。
  • 【視頻】物聯網開發入門+項目實戰
    第1階段 學前準備01 C語言及程序設計快速入門  -- 01 課程開場白---學什麼,怎麼學,C語言的重要性  -- 02 計算機基礎---程序執行原理和編譯原理(1)-串口初始化及發送代碼講解  -- 03 串口實驗之代碼實現分析演示(2)-串口接收代碼講解及在板演示05 Cortex-M系列CPU初級實驗(3)CPU世界的守護者和計時器---看門狗和定時器編程及應用  -- 01 看門狗及定時器實驗之理論基礎
  • 前端框架bootstrap4.4入門教程,使用方法實例響應式布局實戰
    bootstrap是我最喜歡的前端框架,沒有之一,當前的最新版本是bootstrap4.4.1,和之前的3.X版本相比較有較大的變化,不過都是屬於各種標籤的分離,方法還是一樣的,在網上各種教程雖多,但是對於入門還不是不夠,很多入門教程講得雲裡霧裡,看不懂到底在說些什麼。我覺得使用具體的實例來結合相關的標籤使用才能真正的加深理解。
  • 這套1600贊的NLP課程已開放,面向實戰,視頻代碼都有丨資源
    一套面向實戰、號稱「代碼優先」的NLP課程來了,名字為A Code-First Introduction to Natural Language Processing,fast.ai出品,全程免費學習。不到半天點讚超過1600,轉發近500。
  • CTF入門指南 | 內附教程分享
    如何入門?如何組隊?