CVE-2022–36635 — A SQL Injection in ZKSecurityBio to RCE

Silton Santos
stolabs
Published in
4 min readOct 6, 2022

Researched and written by: Caio Burgardt and Silton Santos

This is a write-up of CVE-2022–36635: SQLInjection found in a platform of physical security (access control, elevator control, guest management, patrol and parking management) called ZKSecurity Bio v4.1.3 and how it was used to obtain a RCE.

How it all began…

It was a Thursday, on a beautiful sunny morning, when another subdomain showed up during the recon phase of a Red Team Exercise. After we scanned it and discovered an odd web application server, the fun had started.

After some password attacks and the discovery of a privilege escalation vulnerability (CVE-2022–36634). We gave a quick tour through the application. We figured we already could open doors, after all it is an physical access control application, but we wanted something with more substance for our objective. After throwing around some single quotes in requests parameters of different functionalities, we found a possible SQL Injection.

For you who are beginning in cyber security, I think it is important to know the basics SQL Injection vulnerability type and because we said: “After some single quotes in requests parameters”. Thus we explain about this:

SQL Injection, what is it?

In a nutshell, SQL Injection (SQLi) is a vulnerability that allows an attacker to manipulate the application’s SQL query arbitrarily through input data. The attacker may then retrieve information, control the database, and other shenanigans using many different techniques of exploitation.

For instance, consider a simple user and password query:

SELECT id,name,key FROM users WHERE username = ‘{USER_INPUT}’ AND password = {HASH_OF_PASSWORD}

Provided there are no checks on the USER_INPUT, one could send the value of the username admin’ — . This would bypass password check, because you will close the username value and comment the rest of query. So, usually to test SQLi, pentesters throw quotes around to try and trigger errors in the original query.

Going back to what I was saying…

In the Operation Log functionality, inside the System menu, when inserted the single quote in the Time field, the application returns data indicating that something went wrong with our request. When inserted two single quotes, the application returns other JSON data, indicating that the request was accepted. Common SQL injection behaviour. We can see the requests and responses in the next pictures:

Common SQL injection behaviour
Common SQL injection behaviour

However, we realized there was a filter preventing simple exploitation, because any attempt on exploiting it would shows us the error:

Error

Well, this sucks, but we ask ourselves “is there a way to bypass this?”. The Mentor said: Yes, I am a criminal. My crime is that of curiosity. Trying bypasses on the target’s live machine is not smart, so we searched, downloaded and installed the trial version of the ZK BioSecurity program to try and find some clues in a controlled environment.

After installation, we found plenty of .jar files containing the application logic. But it didn’t seem too time-friendy in our red team exercise to reverse engineer and decompile them, so we went for a quicker path. To put it simply, we used the logs of the application to help us writing the exploit.

With the log, it became possible to craft a good payload for the query, by finishing the first query manually and to using the stacked query technique to inject arbitrary content together. The next image shows a sample of the log:

holy log

As mentioned earlier the log helped us view the full query, but we still needed to bypass the sanitization filter. To that end, we simply used an old trick of replacing spaces with comments (/**/) in the SQL payload, this was enough to bypass the filter. The image below shows the injection of a sleep call of 5 seconds:

injection of a sleep call of 5 seconds

During the analysis of the application in our environment, we noticed that the application installs its own postgres instance, that is, in this version of ZKSecurity, everyone uses the same database version, using the same user, in this case: root.

We confirmed that the PostgreSQL version was vulnerable to the good old ‘COPY FROM PROGRAM’ RCE trick, shown in the following SQL commands.

DROP TABLE IF EXISTS AAAAAA;

CREATE TABLE AAAAAA(filenam e text);

COPY AAAAAA FROM PROGRAM ‘command’;

SELECT * FROM AAAAAA ORDER BY filename ASC;

Finally, to test the RCE, we use the trick above to execute a ping command to trigger a DNS lookup. The result is shows the command was executed remotely, as shown in the next figures :

call of ping
request DNS, result of ping

Time line

  • Responsible disclosure to vendor — 16/07/2022
  • Reserved the CVE — 18/07/2022
  • Vendor’s response, saying he would check — 18/07/2022
  • Vendor’s response, informing public fixing —24/08/2022

--

--