DVWA中學習PHP常見漏洞及修復方法

wyzsk發表於2020-08-19
作者: erevus · 2013/08/14 11:46

“安全是一個整體,保證安全不在於強大的地方有多強大 而在於真正薄弱的地方在哪裡”--劍心

從很多的滲透大型企業內網的案例來看,入侵者大多數是從Web上找到漏洞,從而利用漏洞進一步進行提權,滲透入侵。

WooYun: 時代互聯上傳漏洞多臺資料庫可控

WooYun: 網易某系統未授權訪問可導致內網被滲透

WooYun: 網易某系統未授權訪問續—內網滲透

WooYun: 搜弧某分站XFF注射&配置不當導致原始碼洩漏等重大漏洞

梧桐雨的大型網際網路系列

指令碼安全就像你家的防盜門,你家門都沒關,你家能安全嗎?

烏雲上最常見的指令碼漏洞莫過於SQL隱碼攻擊和XSS。

指令碼安全的本質就是指令碼接受了不安全的變數輸入,又沒得到有效的過濾,最後進入一些對敏感的函式就會對安全造成威脅。

比如出現在mysql_query()函式可能就會造成SQL隱碼攻擊漏洞,出現在eval()以及preg_replace()中可能導致程式碼的執行。

這裡我用DVWA演示SQL,XSS ,任意程式碼執行漏洞的原理

然後用各種修復方法進行修復,附帶講解一些修復方法的弊端。

DVWA下載地址: https://github.com/RandomStorm/DVWA/archive/v1.0.8.zip

DVWA sql呼叫的檔案/vulnerabilities/sqli/目錄下,分為low,medium,high三個等級

SQL隱碼攻擊原理

#!php
//Low.php

if(isset($_GET['Submit'])){

    // Retrieve data

    $id = $_GET['id'];

    $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";//這裡$id變數沒有經過任何的過濾,直接傳入了sql語句,造成字元型注入
    $result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );//執行SQL

原SQL中

SELECT first_name, last_name FROM users WHERE user_id = '$id'

中的$id可被使用者控制,當駭客把$id變成

' union select user,password from users#

那麼這條語句就會變成

SELECT first_name, last_name FROM users WHERE user_id = '' union select user,password from users#

這樣導致了資料庫中其他資料被駭客查詢。 

enter image description here

#!php
//medium.php中
if (isset($_GET['Submit'])) {

    // Retrieve data

    $id = $_GET['id'];
    $id = mysql_real_escape_string($id);

    $getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";

    $result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

    $num = mysql_numrows($result);

雖然$id經過了mysql_real_escape_string轉義了’,可是因為後面的SQL語句$id沒有單引號保護,會被系統認為是數值型,導致數值型注入

構造SQL隱碼攻擊語句

1 union select user,password from users

SQL語句就變成了

SELECT first_name, last_name FROM users WHERE user_id = 1 union select user,password from users 

enter image description here

SQL隱碼攻擊修補方法

字元型注入漏洞修補方法:

PHP5.3之前版本在php.ini中設定

magic_quotes_gpc=On; 

magic_quotes_quotes_gpc會對傳入的$_POST,$_GET,$_SERVER裡的 ‘,”,\進行轉義。

但是PHP5.4之後,magic_quotes_quotes_gpc就被廢除了。

還要使用mysql_real_escape_string()或addslashes()對傳入引數進行過濾,或者使用str_replace()對一些關鍵詞進行替換。

例:

#!php
if(isset($_GET['Submit'])){

// Retrieve data

$id = addslashes($_GET['id']);

$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

$num = mysql_numrows($result);

修補後進行SQL隱碼攻擊

enter image description here

但是addslashes()和mysql_real_escape_string()在資料庫字符集設為GBK時是可能被繞過的。

PHP字元編碼繞過漏洞參考文http://huaidan.org/archives/2268.html

如果資料庫字符集是GBK的情況下,可以把

$mysqli->query('SET NAMES gbk'); 

修改為:

$mysqli->set_charset('gbk');

數值型注入:

數值型注入比較好修補,只需要判斷傳入的變數是否為數值型就可以了(或者強行改成字元型)

例:

#!php
$id = $_GET['id'];
$id = intval ($id);

$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";

$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

$num = mysql_numrows($result);

修補後效果

enter image description here

XSS漏洞原理

駭客往Web頁面裡插入惡意html程式碼,當使用者瀏覽該頁之時,嵌入其中Web裡面的html程式碼會被執行,從而達到駭客的特殊目的,比如竊取使用者cookies.或者進行其他操作。 在

#!php
//low.php
<?php
if(isset($_POST['btnSign']))
{

   $message = trim($_POST['mtxMessage']);
   $name    = trim($_POST['txtName']);

   // Sanitize message input
   $message = stripslashes($message);//stripslashes() 函式刪除由 addslashes() 函式新增的反斜槓。
   $message = mysql_real_escape_string($message);//mysql_real_escape_string() 函式轉義 SQL 語句中使用的字串中的特殊字元。

   // Sanitize name input
   $name = mysql_real_escape_string($name);

   $query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";

   $result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' ); } 
?> 

從上面程式可以看出,$message,$name兩個變數從$_POST傳入,只是經過一些特殊字元的轉換。並沒有對尖括號進行轉義,所以還是造成了XSS的產生。

直接插入XSS語句

<script>alert(1)<script>

就執行了

而medium.php中,雖然對$message進行了尖括號轉義,而且對<script>進行了替換,但是$name沒有進行轉義,而且跨站指令碼可以用多種標籤,如<img />,等…。Name的<input />限制了maxlength=‘10’的長度,但是我們的防禦物件是精通技術的駭客。這種html下的長度限制是可以直接透過瀏覽器修改..然後透過大小寫成功繞過str_replace(),插入XSS.

<SCript>alert(1)</SCript>

enter image description here

#!php
<?php

if(isset($_POST['btnSign']))
{

   $message = trim($_POST['mtxMessage']);
   $name    = trim($_POST['txtName']);

   // Sanitize message input
   $message = trim(strip_tags(addslashes($message)));
   $message = mysql_real_escape_string($message);
   $message = htmlspecialchars($message);

   // Sanitize name input
   $name = str_replace('<script>', '', $name);  //一個大小寫就可以繞過,或者<img />
   $name = mysql_real_escape_string($name);

   $query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";

   $result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );

}

?>

XSS漏洞修補方法

使用htmlspecialchars()在輸出時對輸出內容就行轉義。

瞌睡龍說:在輸出時進行轉義比輸入時進行轉義效果更好,因為可以確保資料在入庫時是完整的….不然丟失資料。

例:

#!php
<?php

if(isset($_POST['btnSign']))
{

   $message = trim($_POST['mtxMessage']);
   $name    = trim($_POST['txtName']);

   // Sanitize message input
   $message = stripslashes($message);
   $message = mysql_real_escape_string($message);
   $message = htmlspecialchars($message);

   // Sanitize name input
   $name = stripslashes($name);
   $name = mysql_real_escape_string($name); 
   $name = htmlspecialchars($name);

   $query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";

   $result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );

}

?>

修補後效果,可以看到尖括號已經被轉義了,html程式碼已經不執行

enter image description here

任意命令執行漏洞原理

任意命令執行可謂是web裡最高危的漏洞了,有可能可以直接寫下shell或者直接新增使用者。

任意命令執行漏洞的產生大多是因為變數可以被使用者輸入控制,而沒有經過任何的判斷和過濾處理就進入了高危的函式。

#!php
<?php

if( isset( $_POST[ 'submit' ] ) ) {

    $target = $_REQUEST[ 'ip' ];

    // Determine OS and execute the ping command.
    if (stristr(php_uname('s'), 'Windows NT')) { 

        $cmd = shell_exec( 'ping  ' . $target );
        $html .= '<pre>'.$cmd.'</pre>';

    } else { 

        $cmd = shell_exec( 'ping  -c 3 ' . $target );
        $html .= '

  <pre>'.$cmd.'</pre>';

    }

}
?>

由於$target沒有經過處理就進入shell_exec函式,導致駭客可以構造特殊的變數執行批處理命令。

我輸入可 0 | dir

那麼執行的命令的命令就是 ping -c 0 | dir

enter image description here

假如駭客在利用時輸入的是

0|net user hacker/add

那麼造成的後果將不堪設想

以下是可能會造成任意命令執行的函式

system|passthru|exec|popen|proc_open|move_uploaded_file|eval|copy|shell_exec|assert

任意命令執行漏洞修補辦法

在寫程式時儘量地使變數不能被使用者所控制!且注意變數初始化的問題。

使用str_replace對“%”,”|”,“>”進行替換

進入函式前判斷變數是否合法。

暴力破解漏洞

這個是漏洞?算是吧…

祭上神器Burp Suite,Burp suite執行後,Burp suite,Proxy 開起預設的8080 埠作為本地代理介面。

使用Burp suite透過置一個web 瀏覽器使用其代理伺服器,見下圖  enter image description here

然後開啟你要暴力破解的後臺,隨便輸入一個賬號密碼…把抓到的包send to intruder  enter image description here

enter image description here

enter image description here

Start attack~~~

然後就對面返回包的大小,知道密碼

enter image description here

暴力破解漏洞修補方法

加個google驗證碼,保證沒有程式能識別出來…

檔案包含漏洞

檔案包含漏洞分為兩種,一種是遠端包含,一種是本地包含。

伺服器透過php的特性(函式)去包含任意檔案時,由於要包含的這個檔案來源過濾不嚴,從而可去呼叫並執行一個文(木)件(馬),而我們可以構造這個文(木)件(馬)來達到邪惡的目的。

涉及到的危險函式,include(),require()和include_once(),require_once()

現在遠端包含的漏洞已經不多了,但是遠端包含的危害是最大,相當於一個命令執行。

而本地包含,有時配合一下解析漏洞往往可以getshell.

例:

#!php
<?php 

    $file = $_GET['page']; //The page we wish to display  

?>

Include.php內容:

#!php
<?php 
echo "hello world\n";
?>

總結

在編寫程式時,應有良好的程式碼習慣,如使用變數前初始化。

做安全的過濾在全域性裡做,或者寫在類裡。

不要相信資料,所有輸入在得到證明之前都是不可信的,所有從使用者上輸入的資料都應該加以判斷。

不返回過多錯誤的原因,如一個駭客進行sql注入。

多上wooyun看漏洞

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章