GHSA-p462-prxw-mjx4: NASA AMMOS Instrument Toolkit: Path traversal resulting in arbitrary file append (can be triggered over the network by unauthenticated attacker)
1. SummaryThe Binary Stream Capture (BSC) component exposes an unauthenticated HTTP API for dynamically creating packet capture “handlers.” Because the code blindly trusts path‑related form fields, a remote client can:**Bypass the configured log root** and direct BSC to log to **arbitrary filesystem paths** (path traversal / directory escape), and**Append attacker‑controlled data** to those files, using the privileges of the`ait-bsc` process.There are two ways for a remote attacker to trigger this:If the attacker has access to the network where `ait-bsc` is deployed (a reason for that could be that the ports are publicly accessible), the payloads can be directly sent to the server to trigger the arbitrary file append. This type of attack is demonstrated in `python_poc.py`.Even if the attacker does not have direct access to the network because the software is running in a local network, it is possible to exploit this if a bad actor in that network opens an attacker-controlled website (which might be a website created by an attacker, or a third-party website compromised by the attacker). The browser javascript can automatically send the requests necessary to exploit this into the local network. This is even possible if the server is only accessible on `localhost`. This type of attack is demonstrated by `attacker_tcp.py` and `test1.html` (first launch the attacker TCP server, then start a webserver to host `test1.html`, for example using `python3 -m http.server 7000`,
and open `test1.html`).ImpactThis issue affects BSC (Binary Stream Capture) and usage of the ait-bsc server. This impacts AIT-Core versions before 3.1.1, from 2.x before 2.6.1. Users are recommended to upgrade to version 3.1.1 or 2.6.1.DetailsA remote attacker can use this vulnerability to append data to arbitrary files on the system (if the `ait-bsc` has privileges to write to them). It is easy to use this to corrupt data on the system (which can include the AIT-Core python code to crash the server after it is restarted and python attempts to execute the corrupted code). It should be mentioned here that there seems to be a bug in the TCP handler that results in a lot of data being written in an infinite loop after the connection has been closed, this could result in excessive disk space use. That the attacker can modify executable files like python or bash scripts means that this vulnerability could also lead to Remote Code Execution as soon as the user runs the modified code. However, depending on the system, it is not so easy to execute this attack in practice (it might not be possible), because `ait-bsc` adds a header in front of attacker-controlled data.Fix InformationThe vulnerability is mitigated by constraining BSC ability to write paths only in the project root log directory which is configured through the bsc.yaml. Additionally, any attempts to traverse outside of the configured location are rejected.Patches3.1.12.6.12. Affected Code Paths2.1 REST entry point: `/NAME/start``StreamCaptureManagerServer` exposes an unauthenticated POST endpoint:Handler:All form fields except `loc`, `port`, `conn_type` are passed directly as `**data` into add_logger.
This includes attacker‑controlled `path`, `file_name_pattern`, and potentially `log_dir_path`.
There is no authentication on this route.2.2 Manager: unvalidated `path` and `log_dir_path``StreamCaptureManager.add_logger`:Key points:If the REST client supplies `log_dir_path` explicitly (as a named parameter), it overrides the manager’s `root_log_directory`.All other attacker‑supplied fields in `kwargs` become part of the handler configuration dict (`capture_handler_conf`), including `path` and `file_name_pattern`.There is **no** check that `log_dir_path` or `path` are relative or confined.2.3 Path traversal via `_get_log_file``SocketStreamCapturer._get_log_file` builds the actual log path:On POSIX systems:If `handler["path"]` is **absolute** (e.g. `/home/user/...`), `os.path.join(base, abs_component, ...)` discards the `base` component:If `handler["path"]` contains `..`, the result can point **outside** the nominal root even if `path` is relative.There is:No `os.path.realpath` canonicalization *after* join, andNo enforcement that the final `log_file` begins with the configured root prefix.Combined with `StreamCaptureManager.add_logger`, this means:Attacker controls both:`handler["log_dir"]` (via `log_dir_path`), and`handler["path"]` and `handler["file_name_pattern"]`.They can therefore direct BSC’s log output to **any path that the OS permissions allow**, not just under `root_log_directory`.2.4 File opened for append without safety checks`pcap.open`:Consequences:If the target directory does not exist, `os.makedirs(os.path.dirname(log_file))` will **create it**, even if it is outside the intended root.The file is opened in append‑binary mode (`"ab"`):The OS will create it if missing.Existing content is preserved; new data is appended.There is no:realpath‑based confinement,symlink protection,or additional access control beyond standard filesystem permissions.2.5 A part of the data written is attacker‑controlled network payloadCaptured data path:`SocketStreamCapturer.__init__`:UDP:TCP:Thus:For UDP, any host that can send datagrams to the configured (IP,port) directly controls `data`.For TCP, the remote server at `(loc, port)` directly controls `data`.`PCapStream.write` wraps this `data` in a PCAP packet header and writes it to the file, but does not sanitize or transform the payload bytes beyond optional in‑process transforms.3. RecommendationsThe core objective is to ensure that untrusted REST input cannot steer log file paths outside a trusted directory tree.3.1 Constrain log paths to a trusted rootIn `StreamCaptureManager.add_logger` and/or `SocketStreamCapturer._get_log_file`:Compute a canonical root:When applying `path` and `file_name_pattern`, always join relative to this root; do **not** accept absolute `path` from REST:Enforce the prefix:Reject any REST‑supplied `log_dir_path` that is absolute or attempts to escape the configured root, or disallow `log_dir_path` entirely in REST calls.3.2 Treat REST input as untrustedOnly allow `path` / `file_name_pattern` override from the configuration file (`bsc.yaml`), not from REST.For REST‑created handlers, either:Use a fixed subdirectory under the configured root, orValidate `path` strictly as a simple relative name with no `/` or `..`.3.3 Note on `/tmp` usageWhile not the root cause of this vulnerability, using a world‑writable directory such as `/tmp` as a log root in a multi‑user system is generally unsafe (standard symlink and race issues).It is recommended to:Use a dedicated, non‑world‑writable directory for BSC logs (e.g. `/var/opt/ait-bsc/logs`).Update the documentation examples to reflect this and add a warning against `/tmp` for production use.3.4 Harden open callsIf symlink attacks are a concern in specific deployments, consider to not follow them when writing to log files.3.5 REST API exposureBecause `/NAME/start` directly controls file paths and network connections:It should **not** be exposed to untrusted networks.Consider adding optional HTTP authentication or limiting binding to a protected interface or Unix domain socket.4 Proof of concept files4.1 `python_poc.py`4.2 `attacker_tcp.py`4.3 `test1.html`
CVSS v3.1: 9.1