-
-
Save q3k/af3d93b6a1f399de28fe194add452d01 to your computer and use it in GitHub Desktop.
0810 b' from ' | |
0678 b' ssh2' | |
00d8 b'%.48s:%.48s():%d (pid=%ld)\x00' | |
0708 b'%s' | |
0108 b'/usr/sbin/sshd\x00' | |
0870 b'Accepted password for ' | |
01a0 b'Accepted publickey for ' | |
0c40 b'BN_bin2bn\x00' | |
06d0 b'BN_bn2bin\x00' | |
0958 b'BN_dup\x00' | |
0418 b'BN_free\x00' | |
04e0 b'BN_num_bits\x00' | |
0790 b'Connection closed by ' | |
0018 b'Could not chdir to home directory %s: %s\n\x00' | |
00b0 b'Could not get agent socket\x00' | |
0960 b'DISPLAY=' | |
09d0 b'DSA_get0_pqg\x00' | |
0468 b'DSA_get0_pub_key\x00' | |
07e8 b'EC_KEY_get0_group\x00' | |
0268 b'EC_KEY_get0_public_key\x00' | |
06e0 b'EC_POINT_point2oct\x00' | |
0b28 b'EVP_CIPHER_CTX_free\x00' | |
0838 b'EVP_CIPHER_CTX_new\x00' | |
02a8 b'EVP_DecryptFinal_ex\x00' | |
0c08 b'EVP_DecryptInit_ex\x00' | |
03f0 b'EVP_DecryptUpdate\x00' | |
00f8 b'EVP_Digest\x00' | |
0408 b'EVP_DigestVerify\x00' | |
0118 b'EVP_DigestVerifyInit\x00' | |
0d10 b'EVP_MD_CTX_free\x00' | |
0af8 b'EVP_MD_CTX_new\x00' | |
06f8 b'EVP_PKEY_free\x00' | |
0758 b'EVP_PKEY_new_raw_public_key\x00' | |
0510 b'EVP_PKEY_set1_RSA\x00' | |
0c28 b'EVP_chacha20\x00' | |
0c60 b'EVP_sha256\x00' | |
0188 b'EVP_sm' | |
08c0 b'GLIBC_2.2.5\x00' | |
06a8 b'GLRO(dl_naudit) <= naudit\x00' | |
01e0 b'KRB5CCNAME\x00' | |
0cf0 b'LD_AUDIT=' | |
0bc0 b'LD_BIND_NOT=' | |
0a90 b'LD_DEBUG=' | |
0b98 b'LD_PROFILE=' | |
03e0 b'LD_USE_LOAD_BIAS=' | |
0a88 b'LINES=' | |
0ac0 b'RSA_free\x00' | |
0798 b'RSA_get0_key\x00' | |
0918 b'RSA_new\x00' | |
01d0 b'RSA_public_decrypt\x00' | |
0540 b'RSA_set0_key\x00' | |
08f8 b'RSA_sign\x00' | |
0990 b'SSH-2.0' | |
04a8 b'TERM=' | |
00e0 b'Unrecognized internal syslog level code %d\n\x00' | |
0158 b'WAYLAND_DISPLAY=' | |
0878 b'__errno_location\x00' | |
02b0 b'__libc_stack_end\x00' | |
0228 b'__libc_start_main\x00' | |
0a60 b'_dl_audit_preinit\x00' | |
09c8 b'_dl_audit_symbind_alt\x00' | |
08a8 b'_exit\x00' | |
05b0 b'_r_debug\x00' | |
05b8 b'_rtld_global\x00' | |
0a98 b'_rtld_global_ro\x00' | |
00b8 b'auth_root_allowed\x00' | |
01d8 b'authenticating' | |
0028 b'demote_sensitive_data\x00' | |
0348 b'getuid\x00' | |
0a48 b'ld-linux-x86-64.so' | |
07d0 b'libc.so' | |
07c0 b'libcrypto.so' | |
0590 b'liblzma.so' | |
0938 b'libsystemd.so' | |
0020 b'list_hostkey_types\x00' | |
0440 b'malloc_usable_size\x00' | |
00c0 b'mm_answer_authpassword\x00' | |
00c8 b'mm_answer_keyallowed\x00' | |
00d0 b'mm_answer_keyverify\x00' | |
0948 b'mm_answer_pam_start\x00' | |
0078 b'mm_choose_dh\x00' | |
0040 b'mm_do_pam_account\x00' | |
0050 b'mm_getpwnamallow\x00' | |
00a8 b'mm_log_handler\x00' | |
0038 b'mm_pty_allocate\x00' | |
00a0 b'mm_request_send\x00' | |
0048 b'mm_session_pty_cleanup2\x00' | |
0070 b'mm_sshpam_free_ctx\x00' | |
0058 b'mm_sshpam_init_ctx\x00' | |
0060 b'mm_sshpam_query\x00' | |
0068 b'mm_sshpam_respond\x00' | |
0030 b'mm_terminate\x00' | |
0c58 b'parse PAM\x00' | |
0400 b'password\x00' | |
04f0 b'preauth' | |
0690 b'pselect\x00' | |
07b8 b'publickey\x00' | |
0308 b'read\x00' | |
0710 b'rsa-sha2-256\x00' | |
0428 b'setlogmask\x00' | |
05f0 b'setresgid\x00' | |
0ab8 b'setresuid\x00' | |
0760 b'shutdown\x00' | |
0d08 b'ssh-2.0' | |
02c8 b'ssh-rsa-cert-v01@openssh.com\x00' | |
0088 b'sshpam_auth_passwd\x00' | |
0090 b'sshpam_query\x00' | |
0080 b'sshpam_respond\x00' | |
0098 b'start_pam\x00' | |
09f8 b'system\x00' | |
0198 b'unknown\x00' | |
0b10 b'user' | |
0380 b'write\x00' | |
0010 b'xcalloc: zero size\x00' | |
0b00 b'yolAbejyiejuvnup=Evjtgvsh5okmkAvj\x00' | |
0300 b'\x7fELF' |
Could you share your python code used for extracting?
Can anyone explain the seemingly suspicious string at L115?
Here's the tooling I used to extract this: https://gist.github.com/q3k/3fadc5ce7b8001d550cf553cfdc09752 . This has tables extracted from the 5.6.1 Fedora build (https://koji.fedoraproject.org/koji/buildinfo?buildID=2417414).
@stan423321 yeah it's a kill switch
@stan423321 Thanks for the info, greatly appreciated!
Is there any information about setlogmask
section? That means the exploited SSH connections wouldnt be logged?
Yes, setlogmask is a symbol where calls to it override previous calls, and it could be used to silence logging that went through syslog.
However, it's also possible that some of these symbols appear for a "non-malicious" reason: the code in question must still behave like the OpenSSH code it replaces, in order to evade immediate detection, so it may just be duplicating some of that code.
Same list as a rough C enum, in case it saves anyone 2 min :)
enum {usr_sbin_sshd = 0x108,Accepted_password_for = 0x870,Accepted_publickey_for = 0x1A0,BN_bin2bn = 0xC40,BN_bn2bin = 0x6D0,BN_dup = 0x958,BN_free = 0x418,BN_num_bits = 0x4E0,Connection_closed_by = 0x790,Could_not_chdir_to_home = 0x18,Could_not_get_agent_socket = 0xB0,DISPLAY_equal = 0x960,DSA_get0_pqg = 0x9D0,DSA_get0_pub_key = 0x468,EC_KEY_get0_group = 0x7E8,EC_KEY_get0_public_key = 0x268,EC_POINT_point2oct = 0x6E0,EVP_CIPHER_CTX_free = 0xB28,EVP_CIPHER_CTX_new = 0x838,EVP_DecryptFinal_ex = 0x2A8,EVP_DecryptInit_ex = 0xC08,EVP_DecryptUpdate = 0x3F0,EVP_Digest = 0xF8,EVP_DigestVerify = 0x408,EVP_DigestVerifyInit = 0x118,EVP_MD_CTX_free = 0xD10,EVP_MD_CTX_new = 0xAF8,EVP_PKEY_free = 0x6F8,EVP_PKEY_new_raw_public_key = 0x758,EVP_PKEY_set1_RSA = 0x510,EVP_chacha20 = 0xC28,EVP_sha256 = 0xC60,EVP_sm = 0x188,GLIBC_2_2_5 = 0x8C0,GLRO_dl_naudit_lte_naudit = 0x6A8,KRB5CCNAME = 0x1E0,LD_AUDIT_eq = 0xCF0,LD_BIND_NOT_eq = 0xBC0,LD_DEBUG_eq = 0xA90,LD_PROFILE_eq = 0xB98,LD_USE_LOAD_BIAS_eq = 0x3E0,LINES_eq = 0xA88,RSA_free = 0xAC0,RSA_get0_key = 0x798,RSA_new = 0x918,RSA_public_decrypt = 0x1D0,RSA_set0_key = 0x540,RSA_sign = 0x8F8,SSH_2_0 = 0x990,TERM_eq = 0x4A8,Unrecognized_internal_syslog_level_code_fmt = 0xE0,WAYLAND_DISPLAY_eq = 0x158,__errno_location = 0x878,__libc_stack_end = 0x2B0,__libc_start_main = 0x228,_dl_audit_preinit = 0xA60,_dl_audit_symbind_alt = 0x9C8,_exit = 0x8A8,_r_debug = 0x5B0,_rtld_global = 0x5B8,_rtld_global_ro = 0xA98,auth_root_allowed = 0xB8,authenticating = 0x1D8,demote_sensitive_data = 0x28,getuid = 0x348,ld_linux_x86_64_so = 0xA48,libc_so = 0x7D0,libcrypto_so = 0x7C0,liblzma_so = 0x590,libsystemd_so = 0x938,list_hostkey_types = 0x20,malloc_usable_size = 0x440,mm_answer_authpassword = 0xC0,mm_answer_keyallowed = 0xC8,mm_answer_keyverify = 0xD0,mm_answer_pam_start = 0x948,mm_choose_dh = 0x78,mm_do_pam_account = 0x40,mm_getpwnamallow = 0x50,mm_log_handler = 0xA8,mm_pty_allocate = 0x38,mm_request_send = 0xA0,mm_session_pty_cleanup2 = 0x48,mm_sshpam_free_ctx = 0x70,mm_sshpam_init_ctx = 0x58,mm_sshpam_query = 0x60,mm_sshpam_respond = 0x68,mm_terminate = 0x30,parse_PAM = 0xC58,password = 0x400,preauth = 0x4F0,pselect = 0x690,publickey = 0x7B8,read = 0x308,rsa_sha2_256 = 0x710,setlogmask = 0x428,setresgid = 0x5F0,setresuid = 0xAB8,shutdown = 0x760,ssh_2_0 = 0xD08,ssh_rsa_cert_v01_at_openssh_com = 0x2C8,sshpam_auth_passwd = 0x88,sshpam_query = 0x90,sshpam_respond = 0x80,start_pam = 0x98,system = 0x9F8,unknown = 0x198,user = 0xB10,write = 0x380,xcalloc_zero_size = 0x10,yolAbejyiejuvnup_eq_Evjtgvsh5okmkAvj = 0xB00,ELF_MAGIC = 0x300,from = 0x810,ssh2 = 0x678,pid_line_fmt = 0xD8,percent_s_fmt = 0x708}
Can anyone explain the seemingly suspicious string at L115?
There's a theory this was one way to disable the malware (source).
I found this post because I dumped same list of strings and then googled yolAbejyiejuvnup=Evjtgvsh5okmkAvj
.... I'm not sure whether this strange string is intended to be a kill switch but setting any string in the list as envar (e.g. LINES=
, TERM=
) will make the exploit stop early. It's checked in _Llzma_filter_decoder_is_supported_part_0 -> sub_3A10 -> _Lsimple_coder_update_0
. This is why the original post mentioned that TERM, LD_DEBUG, LD_PROFILE need to be unset for exploit to work.
They just run all environment variables through the trie. If it hits a leaf, the malware is killed. So TERM=
(not NUL-terminated) is a hit if TERM has whatever value, same for DISPLAY=
and WAYLAND_DISPLAY=
. That's surely intended behaviour. I'm unsure whether the suspicious string is yet another killswitch, or it was intended for some other purpose - I didn't find a reference to the string ID 0xB00 yet, though.
As as side effect, all non-NUL-terminated strings in the list also work as variable name prefixes for a killswitch. So if you set EVP_sm=1234
or EVP_smd_components_soldering=difficult
the backdoor is deactivated as well.
So TERM= (not NUL-terminated) is a hit if TERM has whatever value, same for DISPLAY= and WAYLAND_DISPLAY=.
Could it be that the actor was explicitly targeting servers and not desktops?
Could it be that the actor was explicitly targeting servers and not desktops?
This question is hard to directly answer as it depends on how you classify them. You could say no, because plugging in a screen wouldn't help. You could say yes, because desktops tend to not run Linux and sshd in the first place.
In context of environmental variables, however, this seems much more focused on skipping analysis of sshd, as that's when it will be invoked from some sort of regular work environment and not the daemon/service management one.
So TERM= (not NUL-terminated) is a hit if TERM has whatever value, same for DISPLAY= and WAYLAND_DISPLAY=.
Could it be that the actor was explicitly targeting servers and not desktops?
The code is intended to affect sshd only, not any user-interactive process. So I don't think this is about servers versus desktops, but it is an attempt to only activate the injected code when sshd is invoked in the background from any kind of init system (like systemd), but not if sshd is started at an interactive command line (like sshd -h). It has been reported that "sshd -h" to display the help is slowed down considerably (but only if run in a "clean" environment). The "no TERM or DISPLAY" check seems to try to avoid exposure of the backdoor in the normal interactive use-case.
Very nice!