科普:安全漏洞的概念及分類
本文是一個安全漏洞相關的科普,介紹安全漏洞的概念認識,漏洞在幾個維度上的分類及實例展示。
安全漏洞及相關的概念
本節介紹什么是安全漏洞及相關的概況。
安全漏洞的定義
我們經常聽到漏洞這個概念,可什么是安全漏洞?想給它一個清晰完整的定義其實是非常困難的。如果你去搜索一下對于漏洞的定義,基本上會發現高大上的學術界和講求實用的工業界各有各的說法,漏洞相關的各種角色,比如研究者、廠商、用戶,對漏洞的認識也是非常不一致的。
從業多年,我至今都找不到一個滿意的定義,于是我自己定義一個:
安全漏洞是信息系統在生命周期的各個階段(設計、實現、運維等過程)中產生的某類問題,這些問題會對系統的安全(機密性、完整性、可用性)產生影響。
這是一個從研究者角度的偏狹義的定義,影響的主體范圍限定在了信息系統中,以盡量不把我們所不熟悉的對象扯進來。
漏洞之所以被描述為某種”問題”,是因為我發現無法簡單地用脆弱性、缺陷和Bug等概念來涵蓋它,而更象是這些概念的一個超集。
漏洞會在系統生命周期內的各個階段被引入進來,比如設計階段引入的一個設計得非常容易被破解的加密算法,實現階段引入的一個代碼緩沖區溢出問題,運維階段的一個錯誤的安全配置,這些都有可能最終成為漏洞。
定義對安全的影響也只涉及狹義信息安全的三方面:機密性、完整性和可用性。漏洞造成的敏感信息泄露導致機密性的破壞;造成數據庫中的信息被非法篡改導致完整性的破壞;造成服務器進程的崩潰導致可用性的喪失。漏洞也可能同時導致多個安全屬性的破壞。#p#
安全漏洞與Bug的關系
漏洞與Bug并不等同,他們之間的關系基本可以描述為:大部分的Bug影響功能性,并不涉及安全性,也就不構成漏洞;大部分的漏洞來源于Bug,但并不是全部,它們之間只是有一個很大的交集??梢杂萌缦逻@個圖來展示它們的關系
已知漏洞的數量
各個漏洞數據庫和索引收錄了大量已知的安全漏洞,下表是一個主流漏洞庫的數量的大致估計,漏洞一般最早從20世紀90年代開始:
事實上,即便把未知的漏洞排除在外,只要訂了若干漏洞相關的郵件列表就會知道:并不是所有漏洞數據庫都會收錄,就算把上面的所列的數據庫中的所有條目加起來去重以后也只是收錄了一部分的已知漏洞而已,實際的已知漏洞數比總收錄的要高得多。#p#
安全漏洞的分類
和其他事物一樣,安全漏洞具有多方面的屬性,也就可以從多個維度對其進行分類,重點關注基于技術的維度。注意,下面提到的所有分類并不是在數學意義上嚴格的,也就是說并不保證同一抽象層次、窮舉和互斥,而是極其簡化的出于實用為目的分類。
基于利用位置的分類
本地漏洞
需要操作系統級的有效帳號登錄到本地才能利用的漏洞,主要構成為權限提升類漏洞,即把自身的執行權限從普通用戶級別提升到管理員級別。
實例:
Linux Kernel 2.6 udev Netlink消息驗證本地權限提升漏洞( CVE-2009-1185 )
攻擊者需要以普通用戶登錄到系統上,通過利用漏洞把自己的權限提升到root用戶,獲取對系統的完全控制。
遠程漏洞
無需系統級的帳號驗證即可通過網絡訪問目標進行利用,這里強調的是系統級帳號,如果漏洞利用需要諸如FTP用戶這樣應用級的帳號要求也算是遠程漏洞。
實例:
- Microsoft Windows DCOM RPC接口長主機名遠程緩沖區溢出漏洞(MS03-026)(CVE-2003-0352)
攻擊者可以遠程通過訪問目標服務器的RPC服務端口無需用戶驗證就能利用漏洞,以系統權限執行任意指令,實現對系統的完全控制。
基于威脅類型的分類
獲取控制
可以導致劫持程序執行流程,轉向執行攻擊者指定的任意指令或命令,控制應用系統或操作系統。威脅最大,同時影響系統的機密性、完整性,甚至在需要的時候可以影響可用性。
主要來源:內存破壞類、CGI類漏洞
獲取信息
可以導致劫持程序訪問預期外的資源并泄露給攻擊者,影響系統的機密性。
主要來源:輸入驗證類、配置錯誤類漏洞
拒絕服務
可以導致目標應用或系統暫時或永遠性地失去響應正常服務的能力,影響系統的可用性。
主要來源:內存破壞類、意外處理錯誤處理類漏洞。
基于技術類型的分類
基于漏洞成因技術的分類相比上述的兩種維度要復雜得多,對于目前我所見過的漏洞大致歸納為以下幾類:
- 內存破壞類
- 邏輯錯誤類
- 輸入驗證類
- 設計錯誤類
- 配置錯誤類
以下是對這幾類漏洞的描述和實例分析。
內存破壞類
此類漏洞的共同特征是由于某種形式的非預期的內存越界訪問(讀、寫或兼而有之),可控程度較好的情況下可執行攻擊者指定的任意指令,其他的大多數情況下會導致拒絕服務或信息泄露。
對內存破壞類漏洞再細分下來源,可以分出如下這些子類型:
- 棧緩沖區溢出
- 堆緩沖區溢出
- 靜態數據區溢出
- 格式串問題
- 越界內存訪問
- 釋放后重用
- 二次釋放#p#
棧緩沖區溢出
最古老的內存破壞類型。發生在堆棧中的緩沖區溢出,由于利用起來非常穩定,大多可以導致執行任意指令,威脅很大。此類漏洞歷史非常悠久, 1988年著名的Morris蠕蟲傳播手段之一就是利用了finger服務的一個棧緩沖區溢出漏洞。在2008年之前的幾乎所有影響面巨大的網絡蠕蟲也基本利用此類漏洞,匯總情況可以見下表:
上面表格里列出的蠕蟲即使經過多年,在當前的互聯網上還經常被捕捉到。 棧溢出漏洞是相對比較容易發現的漏洞,靜態動態分析的方法對于此漏洞的挖掘已經相當成熟,因此這類漏洞,特別是服務端程序中,目前基本處于日漸消亡的狀態。 實例:
- 暴風影音stormtray進程遠程棧緩沖區溢出漏洞
長度檢查不充分的串連接操作。
- Sun Solaris snoop(1M)工具遠程指令執行漏洞( CVE-2008-0964 )
無長度檢查的*printf調用。
- Novell eDirectory HTTPSTK Web服務器棧溢出漏洞
無長度檢查的memcpy調用。
- FlashGet FTP PWD命令超長響應棧溢出漏洞
- Imatix Xitami If-Modified-Since頭遠程棧溢出漏洞。
極其危險的sscanf類調用。
- Borland StarTeam Multicast服務用戶請求解析遠程棧溢出漏洞( CVE-2008-0311 )
- Microsoft DirectShow MPEG2TuneRequest 溢出漏洞( CVE-2008-0015 )
手抖,緩沖區的指針被當做緩沖區本身被數據覆蓋溢出。
#p#
堆緩沖區溢出
導致堆緩沖區溢出的來源與棧溢出的一致,基本都是因為一些長度檢查不充分的數據操作,唯一不同的地方只是發生問題的對象不是在編譯階段就已經確定分配的棧緩沖區,而是隨著程序執行動態分配的堆塊。
實例:
- HP OpenView NNM Accept-Language HTTP頭堆溢出漏洞( CVE-2009-0921)
典型的先分配后使用的堆溢出問題。
- PHP (phar extension)堆溢出漏洞
堆溢出特有的溢出樣式:由于整數溢出引發Malloc小緩沖區從而最終導致堆溢出。
靜態數據區溢出
發生在靜態數據區BSS段中的溢出,非常少見的溢出類型。
實例:
- Symantec pcAnyWhere awhost32遠程代碼執行漏洞(CVE-2011-3478)
#p#
格式串問題
在*printf類調用中由于沒有正確使用格式串參數,使攻擊者可以控制格式串的內容操縱*printf調用越界訪問內存。此類漏洞通過靜態或動態的分析方法可以相對容易地被挖掘出來,因此目前已經很少能夠在使用廣泛的軟件中看到了。
實例:
- Qualcomm Qpopper 2.53格式串處理遠程溢出漏洞(CVE-2000-0442)
想了解更多格式串漏洞的原理和利用,可以參考warning3在很早之前寫的文檔:
*printf()格式化串安全漏洞分析http://www.nsfocus.net/index.php?act=magazine&do=view&mid=533http://www.nsfocus.net/index.php?act=magazine&do=view&mid=534
越界內存訪問
程序盲目信任來自通信對方傳遞的數據,并以此作為內存訪問的索引,畸形的數值導致越界的內存訪問,造成內存破壞或信息泄露。
實例:
- OpenSSL TLS心跳擴展協議包遠程信息泄露漏洞 (CVE-2014-0160)
漏洞是由于進程不加檢查地使用通信對端提供的數據區長度值,按指定的長度讀取內存返回,導致越界訪問到大塊的預期以外的內存數據并返回,泄露包括用戶名、口令、SessionID甚至是私鑰等在內的敏感信息。
#p#
釋放后重用
這是目前最主流最具威脅的客戶端(特別是瀏覽器)漏洞類型,大多數被發現的利用0day漏洞進行的水坑攻擊也幾乎都是這種類型,每個月各大瀏覽器廠商都在修復大量的此類漏洞。技術上說,此類漏洞大多來源于對象的引用計數操作不平衡,導致對象被非預期地釋放后重用,進程在后續操作那些已經被污染的對象時執行攻擊者的指令。與上述幾類內存破壞類漏洞的不同之處在于,此類漏洞的觸發基于對象的操作異常,而非基于數據的畸形異常(通常是不是符合協議要求的超長或畸形字段值),一般基于協議合規性的異常檢測不再能起作用,檢測上構成極大的挑戰。
實例:
- Microsoft IE非法事件操作內存破壞漏洞(CVE-2010-0249)
著名的Aurora攻擊,涉嫌入侵包括Google在內的許多大互聯網公司的行動,就使用了這個CVE-2010-0249這個典型的釋放后重用漏洞。
二次釋放
一般來源于代碼中涉及內存使用和釋放的操作邏輯,導致同一個堆緩沖區可以被反復地釋放,最終導致的后果與操作系統堆管理的實現方式相關,很可能實現執行任意指令。
實例:
- CVS遠程非法目錄請求導致堆破壞漏洞( CVE-2003-0015)
#p#
邏輯錯誤類
涉及安全檢查的實現邏輯上存在的問題,導致設計的安全機制被繞過。
實例:
- Real VNC 4.1.1驗證繞過漏洞( CVE-2006-2369 )
漏洞允許客戶端指定服務端并不聲明支持的驗證類型,服務端的驗證交互代碼存在邏輯問題。
- Android應用內購買驗證繞過漏洞
Google Play的應用內購買機制的實現上存在的漏洞,在用戶在Android應用內購買某些數字資產時會從Play 市場獲取是否已經付費的驗證數據,對這塊數據的解析驗證的代碼存在邏輯問題,導致攻擊者可以繞過驗證不用真的付費就能買到東西。驗證相關的代碼如下:
代碼會先檢查回來的數據簽名是否為空,不空的話檢查簽名是否正確,如果不對返回失敗。問題在于如果簽名是空的話并沒有對應的else邏輯分支來處理,會直接執行最下面的return true操作,導致的結果是只要返回的消息中簽名為空就會返回驗證通過。#p#
輸入驗證類
漏洞來源都是由于對來自用戶輸入沒有做充分的檢查過濾就用于后續操作,絕大部分的CGI漏洞屬于此類。所能導致的后果,經常看到且威脅較大的有以下幾類:
- SQL注入
- 跨站腳本執行
- 遠程或本地文件包含
- 命令注入
- 目錄遍歷
SQL注入
Web應用對來自用戶的輸入數據未做充分檢查過濾,就用于構造訪問后臺數據庫的SQL命令,導致執行非預期的SQL操作,最終導致數據泄露或數據庫破壞。
實例:
- 一個網站Web應用的數值參數的SQL注入漏洞。
跨站腳本執行(XSS)
Web應用對來自用戶的輸入數據未做充分檢查過濾,用于構造返回給用戶瀏覽器的回應數據,導致在用戶瀏覽器中執行任意腳本代碼。
實例: YouTube上的一個存儲式XSS漏洞。
遠程或本地文件包含
如果Web應用支持在URL參數中指定服務器上的一個文件執行一些處理,對來自客戶端URL數據及本地資源的訪問許可如果未做充分的檢查,攻擊者可能通過簡單的目錄遍歷串使應用把Web主目錄以外的系統目錄下的文件包含進來,很可能導致信息泄露。
實例:
- 一個網站存在的本地文件包含的漏洞
#p#
命令注入
涉及系統命令調用和執行的函數在接收用戶的參數輸入時未做檢查過濾,或者攻擊者可以通過編碼及其他替換手段繞過安全限制注入命令串,導致執行攻擊指定的命令。 實例:
- AWStats 6.1及以下版本configdir變量遠程執行命令漏洞( CVE-2005-0116 )
典型的由于Perl語言對文件名特性的支持加入未充分檢查用戶輸入的問題,導致的命令注入漏洞,awstats.pl的1082行:if (open(CONFIG,”$searchdir$PROG.$SiteConfig.conf”)) 。
目錄遍歷
涉及系統用于生成訪問文件路徑用戶輸入數據時未做檢查過濾,并且對最終的文件絕對路徑的合法性檢查存在問題,導致訪問允許位置以外的文件。多見于CGI類應用,其他服務類型也可能存在此類漏洞。
實例:
- Novell Sentinel Log Manager “filename”參數目錄遍歷漏洞( CVE-2011-5028 )
http://www.example.com/novelllogmanager/FileDownload?filename=/opt/novell/sentinel_log_mgr/3rdparty/tomcat/temp/../../../../../../etc/passwd
- HP Data Protector Media Operations DBServer.exe目錄遍歷漏洞
在HP Data protecetor Media Operations的客戶端連接服務端時,通過私訪有的通信協議,客戶端會首先檢查[系統分區]:/Documents and Settings/[用戶名]/Application Data下面是否有相應的資源(如插件等),如果沒有,則會向服務器請求需要的文件,服務器沒有驗證請求的文件名的合法性,而且這個過程不需要任何驗證,攻擊者精心構造文件名,可以讀取服務端安裝目錄所在分區的任意文件。
- RHINOSOFT SERV-U FTP SERVER遠程目錄遍歷漏洞
Caucho Resin遠程目錄遍歷漏洞

#p#
設計錯誤類
系統設計上對安全機制的考慮不足導致的在設計階段就已經引入的安全漏洞。
實例:
- LM HASH算法脆弱性
這個算法至少存在以下3方面的弱點:
1、口令轉換為大寫極大地縮小了密鑰空間。
2、切分出的兩組數據分別是獨立加密的,暴力破解時可以完全獨立并行。
3、不足7字節的口令加密后得到的結果后半部分都是一樣的固定串,由此很容易判定口令長度。
這些算法上的弱點導致攻擊者得到口令HASH后可以非常容易地暴力猜測出等價的明文口令。
- Microsoft Windows圖形渲染引擎WMF格式代碼執行漏洞(MS06-001) (CVE-2005-4560)
如果一個WMF文件的StandardMetaRecord中,Function 被設置為 META_ESCAPE而Parameters[0] 等于SETABORTPROC,PlayMetaFileRecord()就會調用Escape()函數,Escape()調用SetAbortProc()將自己的第四形參設置為一個回調函數,把圖像文件中包含的一個數據塊象Shellcode那樣執行。此漏洞從Windows 3.1一直影響到2003,攻擊者只要讓用戶處理惡意的WMF文件(通過掛馬或郵件)在用戶系統上執行任意指令,漏洞實在是太好用影響面太大了,以至有人認為這是一個故意留的后門,其實影響設計的功能是處理打印任務的取消,功能已經被廢棄,但廢棄的代碼并沒有移除而導致問題。
– 搜狐郵箱密碼找回功能
密碼找回功能在要求用戶提供找回密碼需要的問題答案時,在返回給用戶的頁面中就已經包含了答案,只要通過查看頁面源碼就能看到,使這個找回密碼功能的安全驗證完全形同虛設,攻擊者由此可以控制任意郵箱。之所以這么設計,可能就是為了盡可能地少對數據庫的查詢,而把用戶帳號安全根本不放在心上。
– 紫光輸入法用戶驗證繞過漏洞
這是類似于2000年微軟輸入法漏洞的例子,通過訪問輸入法設置的某些功能繞過操作系統的用戶驗證執行某些操作。
#p#
配置錯誤類
系統運維過程中默認不安全的配置狀態,大多涉及訪問驗證的方面。
實例:
– JBoss企業應用平臺非授權訪問漏洞( CVE-2010-0738 )
對控制臺訪問接口的訪問控制默認配置只禁止了HTTP的兩個主要請求方法GET和POST,事實上HTTP還支持其他的訪問方法,比如HEAD,雖然無法得到的請求返回的結果,但是提交的命令還是可以正常執行的。
– Apache Tomcat遠程目錄信息泄露漏洞
Tomcat的默認配置允許列某些目錄的文件列表。
總結
各種眼花繚亂的安全漏洞其實體現的是人類在做事的各種環節上犯過的錯誤,通過改進工具流程制度可以得到某些種程度的解決,但有些涉及人性非常不容易解決,而且隨著信息系統的日趨復雜,我們可以看到更多的新類型漏洞,這個領域永遠都有的玩。