[脆弱性]練習-Day8 CmsEasy 5.5でコードが実行される脆弱性

彼は、PHP-監査-Labsのコード監査Day8の練習の[赤]チームに始まった
リンク:https://github.com/hongriSec/PHP-Audit-Labs
練習に行くことができます興味のある学生
予備知識:
コンテンツのタイトルが来るPHPセキュリティ2017 CALENDAR
。8日目-次のようにキャンドルのコードは次のとおりです。

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

function complexStrtolower($regex, $value) {
  return preg_replace(
    '/(' . $regex . ')/ei',
    'strtolower("\\1")',
    $value
  );
}

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

脆弱性分析:
この質問は検査されpreg_replaceた機能の使用の/eコード実行の問題につながる、パターンを。我々は、上記のコードことが判明第11行GET要求内のパラメータ実施態様来complexStrtolower機能、および変数$regex$value、コードの実行モードの存在下で使用されるpreg_replace機能。そこで、我々は、制御することができますpreg_replace機能を第1个第3个参数するためにコードを実行します。

preg_replace()関数:

(PHP 4、PHP 5、PHP 7)

特長:

preg_replace関数は、正規表現検索および置換を実行します。

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

検索subjectマッチングpatternする部分をreplacement交換すること。

説明:
パラメータ 説明
パターン パターンを検索するには、それは文字列または文字列の配列にすることができます
置換 文字列または文字列の選択肢の配列
主題 置き換え文字列のターゲット文字列や配列を検索します。
限定 代替的に、各被験者の代替文字列の各パターンのため倍の最大数。デフォルトは-1(無制限)
カウント あるいは、置換の数は、実行されます。
  • $patternプレゼンス/eコードの実行を許可するモード修飾子、
  • /eパターン修飾子を、ある**preg_replace() **$replacementようphpに実行するためのコード
戻り値:

場合はsubject、配列は、preg_replace()リストを返し、それ以外の文字列を返します。

一致が確認された場合は、交換をした後、subject返され、それ以外の場合にはそのまま返されますsubjectエラーが発生した場合、リターンNULL

例:

ここに画像を挿入説明
ここに画像を挿入説明
ここに画像を挿入説明
ここに画像を挿入説明

しかし、コードとして実行することができる第2个参数が、固定されました'strtolower("\\1")'ここではそれがどこ\ 1つまり、参照をバック正規表現の知識に来る時には、我々は、参照することができW3Cschoolの説明を:

後方参照:

パターンの正規表現パターンまたは一部に两边添加圆括号関連する原因となり匹配存储到一个临时缓冲区、各サブマッチングが捕捉右正規表現パターンで表示され、左から順に格納されます。以下からのバッファ番号1の開始は、あなたがするまで保存することができ99、サブ表現をキャプチャします。各バッファを使用することができる'\n'アクセスにn一つまたは2桁の10進数の特定のバッファを識別することです。

公式のタイトルがするpayload :/?.*={${phpinfo()}}GETリクエストパラメータ名不正な文字場合、PHPは、アンダースコアに置き換えられますので、実際に、使用されていない、それは.*なります_*ここでは、使用可能な提供payload :\S*=${phpinfo()}、詳細な分析を、記事を参照してください。綿密な調査とコードにpreg_replaceの実装

ここに画像を挿入説明

ケーススタディ:

ケーススタディでは、我々は選択しCmsEasy 5.5たバージョンを。

セキュリティツールを提供するために、脆弱性のPOCサイト、手続き(メソッド)のみご自身の責任で安全研究と教育の目的のために、攻撃運ぶことができます!

脆弱性分析:

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

    function getform($name,$form,$field,$data) {
        if (get('table') &&isset(setting::$var[get('table')][$name]))
            $form[$name]=setting::$var[get('table')][$name];
        if (get('form') &&isset(setting::$var[get('form')][$name]))
            $form[$name]=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']))
            $data[$name]=@$form[$name]['default'];
        if (preg_match('/templat/',$name) &&empty($data[$name]))
            $data[$name]=@$form[$name]['default'];

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

 <div class="hid_box">
        <strong>{lang(addcategory)}</strong>
        <div class="hbox" style="background:none;">
            {form::getform('catid',$form,$field,$data)}
        </div>
    </div>

那么问题来了, catid 是在何处定义的,或者说与什么有关?通过搜索,我们发现 lib/table/archive.php文件中的 get_form() 函数对其进行了定义。
ここに画像を挿入説明

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

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

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

ここに画像を挿入説明

这就意味着前面说的 $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模板直接渲染到前台显示:

ここに画像を挿入説明
这就形成了这套程序整体的一个执行流程,如下图所示:
ここに画像を挿入説明

漏洞利用:

1、首先打开首页,点击游客投稿
ここに画像を挿入説明
2、进入到相应的页面,传给catid值,让他匹配到 /\{\?([^}]+)\}/e这一内容,正则匹配的内容也就是{?(任意内容)},所以我们可以构造payload: catid={?(phpinfo())}
ここに画像を挿入説明
ここに画像を挿入説明

修复建议:

漏洞是 preg_replace()存在/e模式修正符,如果正则匹配成功,会造成代码执行漏洞,因此为了避免这样的问题,我们避免使用 /e 模式修正符,如下图第7行:
ここに画像を挿入説明

结语

再次感谢【红日团队】

相关文章

preg_replace的/e修饰符妙用与慎用
老洞新姿势,记一次漏洞挖掘和利用(PHPMailer RCE)

公開された35元の記事 ウォン称賛19 ビュー5194

おすすめ

転載: blog.csdn.net/zhangpen130/article/details/103971158