“安全是一個整體,保證安全不在于強大的地方有多強大 而在于真正薄弱的地方在哪里”--劍心
從很多的滲透大型企業內網的案例來看,入侵者大多數是從Web上找到漏洞,從而利用漏洞進一步進行提權,滲透入侵。
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三個等級
#!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#
這樣導致了數據庫中其他數據被黑客查詢。 ?
#!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 ?
字符型注入漏洞修補方法:
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);
但是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);
修補后效果
黑客往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>
?
#!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>' );
}
?>
使用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代碼已經不執行
任意命令執行可謂是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
假如黑客在利用時輸入的是
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 瀏覽器使用其代理服務器,見下圖 ?
然后打開你要暴力破解的后臺,隨便輸入一個賬號密碼…把抓到的包send to intruder ? ?
Start attack~~~
然后就對面返回包的大小,知道密碼
加個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看漏洞