Skip to content

Instantly share code, notes, and snippets.

@q3k
Last active May 16, 2024 16:49
Show Gist options
  • Save q3k/af3d93b6a1f399de28fe194add452d01 to your computer and use it in GitHub Desktop.
Save q3k/af3d93b6a1f399de28fe194add452d01 to your computer and use it in GitHub Desktop.
liblzma backdoor strings extracted from 5.6.1 (from a built-in trie)
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'
@workingjubilee
Copy link

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.

@tux3
Copy link

tux3 commented Mar 31, 2024

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}

@wanlill
Copy link

wanlill commented Mar 31, 2024

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.

@karcherm
Copy link

karcherm commented Apr 1, 2024

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.

@Xinayder
Copy link

Xinayder commented Apr 2, 2024

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?

@stan423321
Copy link

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.

@karcherm
Copy link

karcherm commented Apr 3, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment