變量覆蓋漏洞
變量覆蓋(Dynamic Variable Evaluation)是指變量未被初始化,我
們自定義的參數值可以替換程序原有的變量值
通常結合程序的其它漏洞實現完整的攻擊,比如文件上傳頁面,覆蓋
掉原來白名單的列表,導致任意文件上傳;用戶註冊頁面控制沒覆蓋的未
初始化變量導致SQL
思路
$$extract()函數parse_str()函數執行import_request_variables()函數如下代碼:
<?php$a = 1;foreach (array('_COOKIE','_POST','_GET') as $_request){ foreach ($$_request as $_key => $_value){ $$_key = addslashes($_value); }}echo $a;?>a 賦值後為1
重新賦值變量a
extract()函數
int extract ( $array , extract_rules,prefix ) $array 關聯的數組,受第二個和第三個參數的影響。 extract_rules 對待非法/數字和衝突的鍵名的方法將根據取出標記prefix 僅在第二個參數特殊時需要,添加前綴
EXTR_OVERWRITE - 默認。如果有衝突,則覆蓋已有的變量。EXTR_SKIP - 如果有衝突,不覆蓋已有的變量。(忽略數組中同名的元素)EXTR_PREFIX_SAME - 如果有衝突,在變量名前加上前綴 prefix。自 PHP 4.0.5 起,這也包括了對數字索引的處理EXTR_PREFIX_ALL - 給所有變量名加上前綴 prefix(第三個參數)EXTR_PREFIX_INVALID - 僅在非法或數字變量名前加上前綴 prefix。本標記是 PHP 4.0.5 新加的。EXTR_IF_EXISTS - 僅在當前符號表中已有同名變量時,覆蓋它們的值。其它的都不處理。可以用在已經定義了一組合法的變量,然後要從一個數組例如 $_REQUEST 中提取值覆蓋這些變量的場合。本標記是 PHP 4.2.0 新加的。EXTR_PREFIX_IF_EXISTS - 僅在當前符號表中已有同名變量時,建立附加了前綴的變量名,其它的都不處理。本標記是 PHP 4.2.0 新加的。EXTR_REFS - 將變量作為引用提取。這有力地表明了導入的變量仍然引用了 var_array 參數的值。可以單獨使用這個標誌或者在 extract_type 中用 OR 與其它任何標誌結合使用。本標記是 PHP 4.3.0 新加的。<?php
$password = 'pwd';$arr =array( 'username' => 'username', 'password' => 'password');extract($arr,EXTR_PREFIX_SAME,"pwd");echo "$password" . "<br>";echo $pwd_password;?>
<?php
$password = 'pwd';$arr =array( 'username' => 'username', 'password' => 'password');extract($arr,EXTR_OVERWRITE);echo "$password";?>
<?php
$password = 'pwd';$arr =array( 'username' => 'username', 'password' => 'password');extract($arr,EXTR_IF_EXISTS);echo "$password";?>
parse_str()函數
void parse_str ( string $encoded_string [, array &$result ] )$encoded_string 輸入的字符串$result 變量將會以數組元素的形式存入到這個數組,作為替代<?php$a = 'a';parse_str($a = 'b');echo $a;?>
import_request_variables()函數
(PHP 4 >= 4.1.0, PHP 5 < 5.4.0)import_request_variables — 將 GET/POST/Cookie 變量導入到全局作用域中
bool import_request_variables ( string $types [, string $prefix ] )$type 指定需要導入的變量。可以用字母『G』、『P』和『C』分別表示 GET、POST 和 Cookie$prefix 變量名前綴<?php$a = 0;import_request_variables('G');if ($a == 1){ echo 'sucess';} else{ echo 'fail';}?>
序列化漏洞
序列化:把對象轉換為字節序列的過程稱為對象的序列化反序列化:把字節序列恢復為對象的過程稱為對象的反序列化反序列化對象中存在魔術方法,而且魔術方法中的代碼可以被控制,漏洞根據不同的代碼可以導致各種攻擊,如代碼注入、SQL注入、目錄遍歷等等
<?php$name = 'ajie';echo serialize($name);
?><?php
class A { private $test1 = "ajie"; public $test = "ajie"; protected $test2 = "ajie";}$test = new A();echo serialize($test);?>
O:1:"A":3:{s:8:" A test1";s:4:"ajie";s:4:"test";s:4:"ajie";s:8:" * test2";s:4:"ajie";}魔術方法
__construct(), __destruct()__call(), __callStatic()__get(), __set()__isset(), __unset()__sleep(), __wakeup()__toString()__invoke()__set_state()__clone()__debugInfo()參考文檔:https://www.cnblogs.com/20175211lyz/p/11403397.html
弱類型
標準類型:布爾boolen、整型integer、浮點float、字符string複雜類型:數組array、對象object特殊類型:資源resource操作之間比較
(1) 字符串和數字比較(2) 數字和數組比較(3) 字符串和數組比較(4) "合法數字+e+合法數字"類型的字符串(5) == 和 ===<?phpvar_dump(0=="admin"); var_dump(1=="1admin"); var_dump(1=="admin1"); var_dump(0=="admin1");
$arr = array();var_dump(0==$arr);
$arr = array();var_dump("0"==$arr);
var_dump("0e123"=="0e456"); var_dump("1e1"=="10"); ?>empty 和 isset
變量為:0,"0",null,'',false,array()時,使用empty函數,返回的都為true變量未定義或者為null時,isset函數返回的為false,其他都為true$a = null;$b = 0;$c = '';
var_dump(isset($a)); var_dump(isset($b)); var_dump(isset($c));函數md5
string md5 ( string $str [, bool $raw_output = false ] )參數 描述string 必需。規定要計算的字符串。raw可選。規定十六進位或二進位輸出格式:TRUE - 原始 16 字符二進位格式FALSE - 默認。32 字符十六進位數$a = array("1","2","3");$b = array("1","2","4");var_dump(md5($a) == md5($b));strcmp函數
int strcmp ( string $str1 , string $str2 )
string1 必需。規定要比較的第一個字符串。string2 必需。規定要比較的第二個字符串。
返回值:本函數返回:0 - 如果兩個字符串相等<0 - 如果 string1 小於 string2<?php
$password = "123456";if (isset($_GET['pwd'])){ if(strcmp($_GET['pwd'],$password) == 0){ echo "success"; } else { echo "fail"; }}?>
in_array() 和 array_search()
bool in_array ( mixed $search , array $array [, bool $type = FALSE ] )search必需。規定要在數組搜索的值。array 必需。規定要搜索的數組。type
可選。如果設置該參數為 true,則檢查搜索的數據與數組的值的類型是否相同。
mixed array_search ( mixed $value , array $array [, bool $type = false ] )value 必需。規定需要搜素的鍵值。array 必需。規定被搜索的數組。strict可選。如果該參數被設置為 TRUE,則函數在數組中搜索數據類型和值都一致的元素。可能的值:true false - 默認swith語句
如果switch是數字類型的case的判斷時,switch會將參數轉換為int類型
$a = "1asd";switch ($a){ case 1: echo "success"; break; case 2: echo "fail"; break;}
偽協議
file:// 協議
條件
allow_url_fopen:off/onallow_url_include :off/on作用
用於訪問本地文件系統如導入為非.php文件,則仍按照php語法進行解析,這是include()函數所決定的。用法
php:// 協議
條件
allow_url_fopen:off/onallow_url_include :off/on僅php://input php://stdin php://memory php://temp 需要on作用
php:// 訪問各個輸入/輸出流(I/O streams),php://filter用於讀取源碼,php://input用於執行php代碼。php://input可以訪問請求的原始數據的只讀流,在POST請求中訪問POST的data部分,在enctype="multipart/form-data" 的時候php://input 是無效的。php://output只寫的數據流,允許以 print 和 echo 一樣的方式寫入到輸出緩衝區。php://fd(>=5.3.6)允許直接訪問指定的文件描述符。例如 php://fd/3 引用了文件描述符 3。php://memory php://temp(>=5.1.0)一個類似文件包裝器的數據流,允許讀寫臨時數據。兩者的唯一區別是 php://memory 總是把數據儲存在內存中,而 php://temp 會在內存量達到預定義的限制後(默認是 2MB)存入臨時文件中。臨時文件位置的決定和 sys_get_temp_dir() 的方式一致。php://filter(>=5.0.0)一種元封裝器,設計用於數據流打開時的篩選過濾應用。對於一體式(all-in-one)的文件函數非常有用,類似 readfile()、file() 和 file_get_contents(),在數據流內容讀取之前沒有機會應用其他過濾器。php://filter 參數描述
resource=<要過濾的數據流>必須項。它指定了你要篩選過濾的數據流。
read=<讀鏈的過濾器>可選項。可以設定一個或多個過濾器名稱,以管道符(*\*)分隔。write=<寫鏈的過濾器>可選項。可以設定一個或多個過濾器名稱,以管道符(\)分隔。<; 兩個鏈的過濾器>任何沒有以 read= 或 write= 作前綴的篩選器列表會視情況應用於讀或寫鏈。用法:
php://filter/read=convert.base64-encode/resource=[文件名]讀取文件源碼(針對php文件需要base64編碼)
http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.phpphp://input + [POST DATA]執行php代碼
http:[POST DATA部分]<?php phpinfo(); ?>data:// 協議
allow_url_fopen:onallow_url_include :on作用
data://text/plain
data://text/plain;base64,
http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2bhttp:// & https:// 協議
allow_url_fopen:onallow_url_include :on作用
常規 URL 形式,允許通過 HTTP 1.0 的 GET方法,以只讀訪問文件或資源http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txthttps://test.com/1.txt會話劫持
遇到的比較多的就是出現在cookie驗證上面,通常是沒有使用session來認證,直接將用戶信息保存在cookie中
Session劫持攻擊是指黑客劫持目標用戶的session id來獲取網站伺服器上未經許可的存取信息,特別是竊取目標用戶等的cookie數據,來取得網站的認可
session.php
<?phpheader("Content-type:text/html;charset=utf-8");session_start();if (isset($_POST['login'])){ $username = $_POST['username']; $password = $_POST['password']; $conn = mysql_connect("127.0.0.1","root","123456"); mysql_select_db("admin",$conn); $sql = "SELECT * FROM user WHERE name ='".$username ."'"; $result = mysql_query($sql) or die("執行語句失敗". mysql_error()); if($row = mysql_num_rows($result)){ $_SESSION['username'] = $username; $_SESSION['password'] = $password; header("Location:http://127.0.0.1/member.php?user=".$username); }}?>
<html><body><form method="post" name="form"> 帳號:<input type="text" name="username" /> 密碼:<input type="password" name="password" /> <input type="submit" name="login" /></form></body></htmlmember.php
<?phperror_reporting(E_ALL & ~E_NOTICE);session_start();echo "The session id is " . session_id() ."<br>";echo "The user is " . $_GET['user'] ."<br />";echo "The book num is 1";?>attack.php
<?phpheader("Content-type:text/html;charset=utf-8");session_start();echo "The session id is " . session_id() ."<br>";echo "The user is " . $_SESSION['username'] ."<br />";echo "The book num is 2000";?>
基礎講完了,下一篇 正式進行實戰!