[Vulnerability] practice -Day8 CmsEasy 5.5 Code Execution Vulnerability

He began to practice [red] team of PHP-Audit-Labs code audit Day8
link: https://github.com/hongriSec/PHP-Audit-Labs
interested students can go to Exercise
Prior knowledge:
content title comes from PHP SECURITY 2017 CALENDAR
Day. 8 - Candle code is as follows:

header("Content-Type: text/plain");

function complexStrtolower($regex, $value) {
  return preg_replace(
    '/(' . $regex . ')/ei',

foreach ($_GET as $regex => $value) {
  echo complexStrtolower($regex, $value) . "\n";

Vulnerability Analysis:
This question is examined preg_replacefunction uses /epattern, leading to code execution problem. We found that the above codes 第11行at the GETrequest came embodiment the parameters in complexStrtolowerthe function, and the variable $regexand $valuealso used in the presence of the code execution mode preg_replacefunction. So, we can control the preg_replacefunction 第1个, 第3个参数to execute code.

preg_replace () function:

(PHP 4, PHP 5, PHP 7)


preg_replace function performs a regular expression search and replace.

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

Search subjectmatching patternportion to replacementbe replaced.

parameter description
pattern To search pattern, it can be a string or an array of strings
replacement A string or array of strings alternative
subject To search the target string or array of strings replaced.
limit Alternatively, the maximum number of times for each pattern for each subject alternative string. The default is -1 (unlimited)
count Alternatively, the number of the replacement executed.
  • $patternPresence /emode modifier, allowing code execution
  • /ePattern Modifiers, is **preg_replace() **to $replacementas a phpcode to execute
return value:

If subjectan array, preg_replace()returns a list, it returns a string otherwise.

If a match is found checked, after the replacement subjectis returned, returned unchanged in other cases subject. If an error occurs, the return NULL.


Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description

However, as the code can be executed 第2个参数, but fixed 'strtolower("\\1")'. On time, here it comes to knowledge of regular expressions back references, that is where the \ 1, we can refer W3Cschool explanation of:

Backward reference:

For a regular expression pattern or part of the pattern 两边添加圆括号will cause the associated 匹配存储到一个临时缓冲区, each sub-matching captured are stored in the order from left to right appear in regular expression pattern. Buffer number from the 1start, you can store up to 99capture the sub-expression. Each buffer can be used '\n'to access, which nis to identify a specific buffer of one or two decimal digits.

The title of the official to payload :/?.*={${phpinfo()}}not actually be used, because if the GET request parameter name illegal character, PHP will be replaced with an underscore, that .*will become _*. Here we provide a usable payload :\S*=${phpinfo()}, detailed analysis, please refer to the article: in-depth study and implementation of the code preg_replace

Here Insert Picture Description

Case Analysis:

The case study, we selected a CmsEasy 5.5version.

Vulnerability POC site to provide security tools, procedures (methods) may carry offensive, only for safety research and teaching purposes at your own risk!

Vulnerability Analysis:

漏洞入口文件为/lib/tool/form.php (84-94行),我们可以看到下面第7行处引用了preg_replace

    function getform($name,$form,$field,$data) {
        if (get('table') &&isset(setting::$var[get('table')][$name]))
        if (get('form') &&isset(setting::$var[get('form')][$name]))
        if (isset($form[$name]['default']))
            $form[$name]['default']=preg_replace('/\{\?([^}]+)\}/e',"eval('return $1;')",$form[$name]['default']);
        if (!isset($data[$name]) &&isset($form[$name]['default']))
        if (preg_match('/templat/',$name) &&empty($data[$name]))

且使用了/e 模式。如果 $form[$name]['default']的内容被正则匹配到,就会执行 eval函数,导致代码执行。
我们再来看看这个getform()函数在何处被引用。通过搜索,我们可以发现在 Cache/template/default/manage/add.html程序中,调用了此函数。这里我们需要关注catid(下面 第4行代码),因为 catid作为 $namepreg_preolace()函数中使用到,这是我们成功利用漏洞的关键。 add.html中的关键代码如下:

 <div class="hid_box">
        <div class="hbox" style="background:none;">

那么问题来了, catid 是在何处定义的,或者说与什么有关?通过搜索,我们发现 lib/table/archive.php文件中的 get_form() 函数对其进行了定义。
Here Insert Picture Description

如图所示,我们可以看到该函数 return了一个数组,数组里包含了catidtypeid等参数对应的内容。仔细查看,发现其中又嵌套着一个数组。在 第6行处 发现了 default字段,这个就是我们上面提到的$form[$name]['default']

而上图 第6行get()方法在lib/tool/front_class.php中,它是程序内部封装的一个方法。可以看到根据用户的请求方式, get()方法会调用 front 类相应的 get方法或 post方法,具体代码如下:
Here Insert Picture Description
front 类的 get方法和 post方法如下,看到其分别对应静态数组:
Here Insert Picture Description

继续跟进静态方法 getpost ,可以看到在 front 类中定义的静态属性:

Here Insert Picture Description

这就意味着前面说的 $form[$name]['default']namedefault的内容,都是我们可以控制的。

我们屡一下思路,get_form 函数定义了catid的值, catid对应的 default字段又存在代码执行漏洞。而catid的值由 get('catid')决定,这个 get('catid')又是用户可以控制的。所以我们现在只要找到调用 get_form 函数的地方,即可触发该漏洞。通过搜索,我们发现在 /lib/default/manage_act.php文件的第10行调用了 get_form()函数,通过 View模板直接渲染到前台显示:

Here Insert Picture Description
Here Insert Picture Description


Here Insert Picture Description
2、进入到相应的页面,传给catid值,让他匹配到 /\{\?([^}]+)\}/e这一内容,正则匹配的内容也就是{?(任意内容)},所以我们可以构造payload: catid={?(phpinfo())}
Here Insert Picture Description
Here Insert Picture Description


漏洞是 preg_replace()存在/e模式修正符,如果正则匹配成功,会造成代码执行漏洞,因此为了避免这样的问题,我们避免使用 /e 模式修正符,如下图第7行:
Here Insert Picture Description




老洞新姿势,记一次漏洞挖掘和利用(PHPMailer RCE)

Published 35 original articles · won praise 19 · views 5194

Guess you like

Origin blog.csdn.net/zhangpen130/article/details/103971158