php slim 教程,php框架slim架构上存在XXE漏洞(XXE的典型存在形式)

现代cms框架(laraval/symfony/slim)的出现,导致现今的php漏洞出现点、原理、利用方法,发生了一些变化,这个系列希望可以总结一下自己挖掘的此类cms漏洞。

slim是一个设计思路超前的知名的php轻框架,完美结合了psr7来设计,至今用户已超过100w:

bab4db435be38de8299106d264ff7642.png

在阅读其源码的过程中,我发现其存在一个只有在框架式CMS中才会出现的漏洞。

漏洞详情

这个漏洞存在于最新版(3.0)中。

首先用conposer安装之

composer require slim/slim “^3.0@RC”

00b28169a469d478f3e4a7fe1ea35efe.png

很典型的问题,在这篇帖子里也提到过: http://zone.wooyun.org/content/19908

有时候框架会帮开发者一些他可能并不需要的『忙』,比如slimphp这里,常规的POST的content-type为application/x- www-form-urlencoded,但只要我将其修改为application/json,我就可以传入json格式的POST数据,修改为 application/xml,我就可以传入XML格式的数据。

这个特性将会导致两个问题:

WAF绕过

可能存在的XXE漏洞

WAF绕过这个肯定不用说了,常规的WAF一般只检测application/x-www-form-urlencoded的数据,一旦修改数据类型则将通杀各大WAF。

XXE是本漏洞的重点。

我们看到解析body的代码:

Default

public function __construct($method, UriInterface $uri, HeadersInterface $headers, array $cookies, array $serverParams, StreamInterface $body, array $uploadedFiles = [])

{

$this->originalMethod = $this->filterMethod($method);

$this->uri = $uri;

$this->headers = $headers;

$this->cookies = $cookies;

$this->serverParams = $serverParams;

$this->attributes = new Collection();

$this->body = $body;

$this->uploadedFiles = $uploadedFiles;

if (!$this->headers->has('Host') || $this->uri->getHost() !== '') {

$this->headers->set('Host', $this->uri->getHost());

}

$this->registerMediaTypeParser('application/json', function ($input) {

return json_decode($input, true);

});

$this->registerMediaTypeParser('application/xml', function ($input) {

return simplexml_load_string($input);

});

$this->registerMediaTypeParser('text/xml', function ($input) {

return simplexml_load_string($input);

});

$this->registerMediaTypeParser('application/x-www-form-urlencoded', function ($input) {

parse_str($input, $data);

return $data;

});

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

publicfunction__construct($method,UriInterface$uri,HeadersInterface$headers,array$cookies,array$serverParams,StreamInterface$body,array$uploadedFiles=[])

{

$this->originalMethod=$this->filterMethod($method);

$this->uri=$uri;

$this->headers=$headers;

$this->cookies=$cookies;

$this->serverParams=$serverParams;

$this->attributes=newCollection();

$this->body=$body;

$this->uploadedFiles=$uploadedFiles;

if(!$this->headers->has('Host')||$this->uri->getHost()!==''){

$this->headers->set('Host',$this->uri->getHost());

}

$this->registerMediaTypeParser('application/json',function($input){

returnjson_decode($input,true);

});

$this->registerMediaTypeParser('application/xml',function($input){

returnsimplexml_load_string($input);

});

$this->registerMediaTypeParser('text/xml',function($input){

returnsimplexml_load_string($input);

});

$this->registerMediaTypeParser('application/x-www-form-urlencoded',function($input){

parse_str($input,$data);

return$data;

});

}

实际上解析代码是作为回调函数写在Request类的构造方法里了。

可见这里直接调用了simplexml_load_string解析$input,造成XML实体注入漏洞。

所以,用slim framework 3.0开发的CMS,只要获取了POST数据,都将受到此XXE漏洞的影响。

漏洞证明

编写一个最简单的demo页面,只有一个获取POST信息并输出的功能:

Default

require 'vendor/autoload.php';

$app = new \Slim\App();

$app->post("/post", function($request, $response) {

$parsedBody = $request->getParsedBody();

print_r($parsedBody);

});

$app->run();

1

2

3

4

5

6

7

require'vendor/autoload.php';

$app=new\Slim\App();

$app->post("/post",function($request,$response){

$parsedBody=$request->getParsedBody();

print_r($parsedBody);

});

$app->run();

55a187184f5bcba7e9f7d482149d708d.png

触发XXE漏洞并读取/etc/passwd:

a098f833f227b31bfe10580c4e8e102e.png

漏洞修复

在slimphp2中,官方是对这块进行一定处理了:

Default

/**

* Parse XML

*

* This method creates a SimpleXMLElement

* based upon the XML input. If the SimpleXML

* extension is not available, the raw input

* will be returned unchanged.

*

* @param string $input

* @return \SimpleXMLElement|string

*/

protected function parseXml($input)

{

if (class_exists('SimpleXMLElement')) {

try {

$backup = libxml_disable_entity_loader(true);

$result = new \SimpleXMLElement($input);

libxml_disable_entity_loader($backup);

return $result;

} catch (\Exception $e) {

// Do nothing

}

}

return $input;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

/**

* Parse XML

*

* This method creates a SimpleXMLElement

* based upon the XML input. If the SimpleXML

* extension is not available, the raw input

* will be returned unchanged.

*

* @param  string                  $input

* @return \SimpleXMLElement|string

*/

protectedfunctionparseXml($input)

{

if(class_exists('SimpleXMLElement')){

try{

$backup=libxml_disable_entity_loader(true);

$result=new\SimpleXMLElement($input);

libxml_disable_entity_loader($backup);

return$result;

}catch(\Exception$e){

// Do nothing

}

}

return$input;

}

不知为何在3.0版本中官方就无视这个问题了。

我猜可能有两个原因:

官方注意到了这个问题,但认为3.0版本需求的php版本在5.5以上,而错以为5.5以上的php就已经不存在XXE的隐患了。但实际上XML外部实体的解析,和php版本并无关系,而是和编译时的libxml库版本有关。

官方尚未注意到这个问题。

感觉前者的可能性较大。

所以解决方案也还是按照2中的方案进行。

【via@phith0n】注:文章来自P牛,他博客不错,对审计有兴趣的同学推荐关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值