ctf变量覆盖漏洞
1.變量覆蓋:
①:針對(duì)extract函數(shù)的變量覆蓋漏洞:
1 <?php 2 @error_reporting(E_ALL^E_NOTICE); 3 require('config.php'); 4 5 if($_GET['show_source'] === '1') { 6 highlight_file(__FILE__); 7 exit; 8 } 9 10 $user = null; 11 12 // connect to database 13 14 if(!empty($_POST['data'])) { 15 try { 16 $data = json_decode($_POST['data'], true); 17 } catch (Exception $e) { 18 $data = []; 19 } 20 extract($data); 21 if($users[$username] && strcmp($users[$username], $password) == 0) { 22 $user = $username; 23 } 24 } 1 <?php if($user == 'admin') printf("<code>%s</code>", htmlentities($flag)); ?>當(dāng)$user=“admin”時(shí),輸出flag
向上看,$user =$username
則需要使$username="admin"
if成立的條件是$users[$username]不為空并且需要滿足$users[$username]=$password
我們?cè)诓恢?password的情況下需要使$users[$username]=$password成立。
再向上看extract()函數(shù),此函數(shù)為變量注冊(cè)函數(shù),將數(shù)組中的數(shù)據(jù)以鍵名為變量名,鍵值為變量值的形式注冊(cè)變量。
那在這就存在變量覆蓋問題,我們可以傳入任意構(gòu)造$password的值覆蓋原有的$password的值。
即構(gòu)造data={"username":"admin","password":"123","users":{"admin":"123"}}即可得到flag
?②:基于parse_str()函數(shù)的變量覆蓋漏洞
1 <meta charset="utf-8"> 2 error_reporting(0); 3 if (empty($_GET['b'])) { 4 show_source(__FILE__); 5 die(); 6 }else{ 7 include('flag.php'); 8 $a = "www.XMAN.com"; 9 $b = $_GET['b']; 10 @parse_str($b); 11 if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) { 12 echo $flag; 13 }else{ 14 exit('你的答案不對(duì)0.0'); 15 } 16 }輸出flag的條件為$a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')
parse_str — 將字符串解析成多個(gè)變量,如果參數(shù)str是URL傳遞入的查詢字符串(query string),則將它解析為變量并設(shè)置到當(dāng)前作用域。
由于此函數(shù)的作用可以將$a[0]的值覆蓋,則在需要找一對(duì)md5碰撞即可。
即傳b=a[0]=s155964671a即可得到flag。
③:基于register_globals的變量覆蓋漏洞:
1 <?php 2 echo "Register_globals: ".(int)ini_get("register_globals")."<br/>"; 3 4 if ($auth){ 5 echo "private!"; 6 } 7 ?>當(dāng)register_globals=OFF時(shí),這段代碼不會(huì)出問題。
但是當(dāng)register_globals=ON時(shí),提交請(qǐng)求URL:http://www.a.com/test.php?auth=1,變量$auth將自動(dòng)得到賦值。得到的結(jié)果為
Register_globals:1
小記:如果上面的代碼中,已經(jīng)對(duì)變量$auth賦了初始值,比如$auth=0,那么即使在URL中有/test.PHP?auth=1,也不會(huì)將變量覆蓋,也就是說不會(huì)打印出private!
?
通過$GLOBALS獲取的變量,也可能導(dǎo)致變量覆蓋。
1 <?php 2 echo "Register_globals:".(int)ini_get("register_globals")."<br/>"; 3 if (ini_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k}); 4 print $a; 5 print $_GET[b]; 6 ?>變量$a未初始化,在register_globals=ON時(shí),再嘗試控制“$a”的值(http://www.a.com/test1.php?a=1&b=2),會(huì)因?yàn)檫@段代碼而出錯(cuò)(因?yàn)?a沒有值)。
而當(dāng)嘗試注入“GLOBALS[a]”以覆蓋全局變量時(shí)(http://www.a.com/test1.php?GLOBALS[a]=1&b=2),則可以成功控制變量“$a”的值。這是因?yàn)閡nset()默認(rèn)只會(huì)銷毀局部變量,要銷毀全局變量必須使用$GLOBALS。
而在register_globals=OFF時(shí),則無法覆蓋到全局變量。
小記:register_globals的意思是注冊(cè)為全局變量,所以當(dāng)On的時(shí)候,傳遞過來的值會(huì)被直接注冊(cè)為全局變量而直接使用,當(dāng)為OFF的時(shí)候,就需要到特定的數(shù)組中去得到它。unset用于釋放給定的變量
④:遍歷初始化變量
1 <? 2 $chs = ''; 3 if($_POST && $charset != 'utf-8'){ 4 $chs = new Chinese('UTF-8', $charset); 5 foreach($_POST as $key => $value){ 6 $$key = $chs->Convert($value); 7 } 8 unset($chs); 9 } 10 ?>由于php中可以使用$$聲明變量,因此當(dāng)在遍歷數(shù)組時(shí)可能會(huì)覆蓋原來的值。
若提交參數(shù)chs,則可覆蓋變量"$chs"的值。
小記:在代碼審計(jì)時(shí)需要注意類似“$$k”的變量賦值方式有可能覆蓋已有的變量,從而導(dǎo)致一些不可控制的結(jié)果
⑤:import_request_variables變量覆蓋
1 <?php 2 $auth = '0'; 3 import_request_variables('G'); 4 5 if($auth == 1){ 6 echo "private!"; 7 }else{ 8 echo "public!"; 9 } 10 ?>當(dāng)用戶輸入http://www.a.com/test1.php?auth=1時(shí),網(wǎng)頁上會(huì)輸出private!
import_request_variables('G')指定導(dǎo)入GET請(qǐng)求中的變量,從而導(dǎo)致變量覆蓋。
小記:import_request_variables — 將 GET/POST/Cookie 變量導(dǎo)入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局變量,那么此函數(shù)就很有用。
轉(zhuǎn)載于:https://www.cnblogs.com/wfzWebSecuity/p/7295705.html
總結(jié)
- 上一篇: aspectj xml
- 下一篇: 洛谷 P1019 单词接龙