Home CVE-2023-36932 - Progress MoveIt authenticated SQLi
Post
Cancel

CVE-2023-36932 - Progress MoveIt authenticated SQLi

TL;DR

A SQL injection can be triggered through header crafting, for MySQL backend, in moveitisapi.dll. This SQLi can only be triggered authenticated, and I do not know if there is a configuration under which it could have beeen exploited. So clearly this vulnerability would fall under the Low or even None severity.

To note: I’m almost certain that CVE-2023-36932 describes multiple SQL injection vulnerabilities, and I only reported one.

Description:

Quite late to the vuln research party following the 0day exploitation surge in June 2023, I decided to spend a few hours looking for SQLi on an area that should be less scrutinized than the core logic of MoveIt Transfer application, which is the ISAPI dll-moveitisapi.dll. Indeed, it’s binary code that is intrinsicaly harder to research than .Net code that can be decompiled.

moveitisapi.dll handles several HTTP requests by itself. One of them allows a user to download a “large” file. Inside the function responsible to handle this download, multiple values are extracted from the headers of the HTTP requestfor further processing, such as the username, the password, or the FileID:

moveit1

In case the request is determined to not use machine2 URL, moveitisapi.dll will handle the rest of the request itself. To do so, it will execute several SQL queries, especially the following one: SELECT * FROM files WHERE ID='XXX' where the FileID is extracted from the X-siLock-FileID header:

moveit2

As seen in the code snippet, this header is neuteurized before the SQL query, through a function I personally call escape_sql.

Within this function, as the third argument passed to it is null, ticks will be doubled, but escape_sequence \ are left as is. This means it’s possible to escape the neuteurization and to obtain a valid payload for MySQL backend (MSSQL won’t work), through the following payload \' that gets transformed into \''.

One example to trigger a potential SQL injection payload would be to use the following HTTP header: X-siLock-FileID: 123\'; drop table users;#, that once escaped and inserted into the query creates the following SQL query: SELECT * FROM files WHERE ID='123\''; drop table users;#';

POC

  1. obtain a valid session to make sure machine2 is not used.

  2. send the following request but with the session obtained at previous step:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    GET /moveitisapi/moveitisapi.dll?action=download HTTP/1.1
     
    Host: localhost
    X-siLock-FileID: 123\'; drop table users;#
    X-siLock-Username: b5ddiwqgrfr3k315
    X-siLock-IPAddress: 127.0.0.1
    X-siLock-AgentBrand: titi
    X-siLock-AgentVersion: 1
    Cache-Control: max-age=0
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.134 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
    Cookie: ASP.NET_SessionId=fe3cryhlppu1tml4zvij1cj2
    Connection: close
    

Impact/Exploitation

I encountered several problematics while trying to exploit the vulnerability:

  • the FileID header can be filled with 32 characters max. Hence it’s not possible to trigger a SQL query that would allow for privilege escalation. There is no leak of information so it can’t be used for that either. Only remaining possibilities are to alter availability by destroying database (using DROP TABLE or shutdown), or to try to use SQL injection to download files we should not.

  • Using the SQL injection to try to download files we are not supposed to does not appear possible: there is a folderperms SQL request that is done afterwards to check whether the user can download the file. For this SQL query, the escape_sql function third argument is set to 1 while using MySQL, making the injection not possible.

  • finally, if we try to alter availability through DROP TABLE or shutdown, by default we should obtain the following log that indicates an error:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
       ```
      <timestamp>  328:Error running SQL: SELECT * FROM files WHERE ID='123\''; drop table users;#';
      <timestamp>  328:** The error was [MySQL][ODBC 8.0(w) Driver][mysqld-8.0.32-commercial]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'drop table users;#'' at line 1
      <timestamp>  328:Reconnecting to DB because query failed
      <timestamp>  328:Reconnected to DB OK
      <timestamp>  328:Error running SQL: SELECT * FROM files WHERE ID='123\''; drop table users;#';
      <timestamp>  328:** The error was Cannot change the ActiveConnection property of a Recordset object which has a Command object as its source.
      <timestamp>  328:Using machine2 because query failed a second time
      ```
    

    This error appears to be there because the MYSQL_OPTION_MULTI_STATEMENTS_ON option is not set while connecting to the database through the ODBC driver. To be honest, I don’t know if there are cases where this option can be set by installation, or if a given user who modified the connection string in the DMZConfig2.exe application could have this option set.

To conclude, I was not able to fully exploit the vulnerability. Still, Progress thankfully accepted the report for defense in depth purpose.

Contents