Full Disclosure mailing list archives
Irony in the Otherworld
From: "Phantasmal Phantasmagoria" <phantasmal () hush ai>
Date: Tue, 1 Mar 2005 19:41:45 -0800
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 [------------------------------------ Irony in the Otherworld by Phantasmal Phantasmagoria phantasmal () hush ai [------------------------------------ The Linux Security Module [1] provides a framework for access control models to be hooked in to the Linux kernel. The standard Discretionary Access Control found in a traditional Unix system has long been considered insufficient and various alternatives [2][3] have been developed. It is for these alternative projects that LSM was designed for. This text examines the potential misuse of an LSM system, specifically the insertion of rootkit and backdoor code in to the kernel through the abuse of LSM hooks. The techniques developed below manifest themselves when an LSM system does not explicitly disallow the writing of kernel memory by kernel modules and the kmem/mem devices. It should be stressed that the methods presented here do not constitute a vulnerability or flaw in LSM itself. This should hopefully be evident after having read the entire document. The official stance from the LSM developers is that any policy that does not disallow the writing of kernel memory is equivalent to a misconfiguration. I don't completely agree with this sentiment, but the important thing to note is that LSM does provide all the necessary hooks to prevent the techniques discussed. It should also be noted that a system is not significantly less secure for having an LSM setup which is affected by the presented methods, simply because there are alternative ways to achieve the same results without using LSM hooks. We need to start by looking at how LSM works in a general sense. In its technical essence LSM inserts a number of kernel level hooks in order to provide the ability to check system call permissions. These hooks are referenced off a globally defined pointer: "struct security_operations *security_ops;". The security_operations structure is defined in include/linux/security.h and is essentially a series of predefined function pointers. In order for an access control model to hook into the system a security_operations structure must be registered with the LSM function register_security(). The requesting module sets the function pointer entries of the structure to the location of the desired hook function, or NULL if the default hook is to be used. The register_security() function simply points the security_ops global to the security_operations structure passed as an argument. The default security_operations structure points to a series of dummy hook functions (which are the same dummy hook functions used if register_security() finds a NULL function pointer): c0327320 B security_ops c0327340 B dummy_security_ops (gdb) x/wx 0xc0327320 0xc0327320: 0xc0327340 The security_ops pointer and the hook functions it contains are the focus of the redirection technqiues presented below. Given an appropriately misconfigured system, the only barrier for a rootkit is a check in register_security() that prevents more than one security_operations structure from being registered. However, this check was not designed to be a security measure and is thus trivial to bypass. The actual reason for this check, LSM module "stacking", is a significant point of contention in the design of LSM. Stacking essentially means the functionality of having multiple LSM modules is offloaded to the LSM modules themselves, and is an important concept for a successful LSM rootkit. Assuming that a system is appropriately misconfigured we are left with three scenarios to consider in regards to the insertion of a malicious LSM hook. Firstly, an LSM enabled kernel with module support and no alternative access models registered. Secondly, an LSM enabled kernel with module support and a previously registered access model. Lastly, an LSM enabled kernel with a previously registered access model and no module support (and thus no exported symbols). The first scenario will not be covered here due to its triviality: simply insert a module that registers a malicious hooking function in the standard LSM manner. So let us assume we have a kernel with both LSM and an LSM enabled module. The only prerequisite for this technique is the ability to use the init_module syscall. As mentioned previously, the only problem we are faced with is the register_security() checks. To circumvent these checks we simply need to modify the security_operations structure of the currently registered module directly. This is made relatively easy by the fact that the security_ops pointer is an exported symbol (see security/security.c). The implementation of a local backdoor LKM using security_ops to locate the currently registered structure is attached at the end of this document (lsm_local.c). In practice the implementation resembles the hook stacking discussed above. There is, however, a significant chance that modules will be disabled, either by configuration at compile time or by the use of linux capabilities, specifically CAP_SYS_MODULE. In this circumstance a different approach can be taken to achieve the same result as using the exported security_ops pointer. In order to modify kernel memory we have to use the /dev/kmem device. Lets assume the worst, and state that the System.map file is unavailable, meaning we have no knowledge of the location of the system_ops pointer. In this circumstance we can use the sidt technique [4] to find the location of one of the system calls that contains an LSM hook, and then use opcode pattern matching to find the reference to system_ops. This is made possible as the hooking procedure is compiled inline to each of the hooked system calls. It looks like this: mov sys_op,%eax call ref(%eax) Where "sys_op" represents the location of the system_ops pointer and "ref" is a reference to the appropriate function pointer within the registered security_operations structure. A proof of concept for this technique (lsmkmem_local.c) is attached at the end of this document, providing backdoor functionality similar to the LKM described above. So it has been clearly established that under certain circumstances we can use LSM hooks for some less than legitimate purpose. The last thing that needs to be considered is the total effect that may leveraged. The examples provided at the end of this document both demonstrate covert local privilege escalation, but there is potential to do much more. Firstly, if compiled with CONFIG_SECURITY_NETWORK=y the attacker is given access to a series of socket related hooks. It is possible to use one of these hooks, socket_sock_rcv_skb, to remotely trigger an arbitrary execution flow. The idea of pure kernel-space remote backdoors under Linux has not received much attention in public research, but a number of potential implementations have been discussed [5]. The final hook I'd like to mention, file_permission, can be used to hide processes and files. This hook is called from readdir()'s VFS layer handler. There are two techniques that may be applied to this hook, the first of which is only relevant when hiding a procfs pid directory. These pid directories are handled specially by the proc filesystem function proc_pid_readdir() which fills the userspace callback buffer with every pid in the task_struct list. Since the file_permission hook is called before the VFS layer passes control to this function we can not directly affect the contents of the callback buffer. Fortunately, we can prevent a target pid from being included in this buffer by abusing get_tid_list()'s error checking: if (pid_alive(task)) do { int tid = task->pid; ... tids[nr_tids] = tid; nr_tids++; ... } while ((task = next_thread(task)) != leader_task); The get_tid_list() function is used by proc_pid_readdir() to extract the list of pid's from the current task_struct. By temporarily marking our target process as "stale" the pid_alive() check will fail and our pid will be exempt from the callback buffer. This technique is ideal for hiding a process, but hiding regular files with the file_permission hook is unfortunately more difficult. The solution for hiding regular files I present here is only conceptual, it has not been tested. The general idea is to intercept the "VFS to filesystem specific" translation by examing vfs_readir()'s stack. This puts the file_permission hook in charge of the translation, and allows the hook to modify the userland callback buffer after it has been filled. It should be possible to work backwards from the stack pointer in the file_permission hook to the arguments passed to vfs_readdir(), specifically the filldir_t function pointer and the userland callback buffer. Our hook would then need to reference the relevant readdir() operation from the file structure passed to it, supplying the arguments lifted from vfs_readdir(). From there we can remove the target file from the callback buffer. However, there are a couple of problems to be overcome if this idea were to be implemented. Firstly, the differentiation of a file_permission hook from vfs_readdir() and a file_permission hook in vfs_read/write(). In general this can be done by checking that the type of the file structure passed to the hook is a directory, but this is not always going to work (for instance, it is perfectly legitimate to read from a directory). Secondly, we have to modify the return location of our hook to prevent vfs_readdir() from continuing with the filesystem specific reference that we have already handled. There are two ways of doing this. The first is to return directly to the original system call by lifting the saved return address from vfs_readdir()'s stack. The second is to take advantage of the code succeeding the file_permission hook: if (res) goto out; ... out: return res; Unfortunately, it is not an option to return a non-zero res as that would indicate a failure to the original system call. Instead, we can advance our hook's saved return address past the comparison operation to the near jump of the goto. This has the same effect as returning directly to the original syscall, but is perhaps the safer method of the two. If necessary we may have to adjust the relevant status flags in the EFLAGS register. It was always inevitable that the Linux Security Module would be utilized in a less than honest way, so I don't think much of a conclusion is in order. For a full list of LSM hooks consult include/linux/security.h as there are many other potential targets that have not been mentioned here. Finally, I'm going to save my usual rhetoric on the hacking community for another day, but I promise a return to my overly socratic style within the next half year. Phantasmal Phantasmagoria [------------------------------------ [1] http://lsm.immunix.org/ [2] http://www.nsa.gov/selinux/ [3] http://www.rsbac.org/ [4] http://www.phrack.org/show.php?p=58&a=7 [5] http://www.phrack.org/show.php?p=61&a=13 [6] http://www.grsecurity.net/lsm.php [7] http://www.rsbac.org/documentation/lsm.php [------------------------------------ begin 644 irony.tar.gz M'XL("$S'`$(``VER;VYY+G1A<@#M6&UOVT8,SE?[5W`>6DB>DTBRXSA+TPU8 MO6*HDQ1)BV)(`D&13O8MLJ1)I]3NUO\^\DZ2)>>E:;L4&R`BCG4\'H^DC@]Y M]MU0!%ONQF.281K&<##8,!2M?QN[EKEA&I9AF`-KB,^&:1IF?P.,1[4JIRP5 M3@*PD421N$_N4_/_4]KN@J^.`+2A"RWY3R1\.F5)"@X$D>L$$"?\F@=LRH"E M.'8$CT+`/P?2C`OG,E@"#WWF"N;!W'%G/&1;J$DJ>SUS0N&D<U13/DZCA#MR M-BYG?YYEZ6S+X<C>;K>_YZ$;9!Z#9UG(4^%MS9Y7>.DRW1;+F*4WV?@Z19VK M_*L+"H]'=19+DE"RVCP4Z`0/-7IPDJG;`W>&9Z2+S]=G%SK\U6[1E._MM_') M!XV$X!E8>KO58@LN-$/?;[?:+=^#`XAB%FIRJ7G1@V/[Y,7QT>1WG=8&*6-7 MFN_UP-P;#7MP.AZ_LD_';VBUM%K._6J_'+\Y?G<DE[`%<X.5NO+AZ.UD@@(? MVY_Y_H-T;LMW_(@8\(G\-X>#89G_NWV+\G\X'#3Y_RT(\[]R!"@E95JJM+]T MW"LOBA*8O#J$+.7A%":GAS"+HBO`L+E7Q!&S),JF,TB9FR5<+.TH3K=4;F/, M?,`_-PI=%HL>>.PZXAZQG'`);L(02:YQS;\&%@$/L\7V//*R@-7S6\U<L21D MP6TS:DWL),[\MNG"N]OF?`E#[</C%V\G8WORVR_CH].QUGGY>M*AG"5$XBX0 M9&A=]&5J4P!M'P'5EEFN:ZE(,A<1!5G0[4$6IGP:(I;BFLHHB,(I*21-:RKJ M&NA_70NX<T02A*>:,H(/"6<*QN3BIT^EDLWGOAU'*1P<2&PB-JJ@X9Y<T<)P M)"P4F\\S3BA7#ID:&PAAK82)+`EA<_QZ?'*(C(^T4\Z\+1":,ES:2J81GDEO M><B%K=Z01B=(FI"[7#EW+)&5*045YFB_\.R[ZN'4*Y:94D1)H]55L?V<OV8C M(;H4QPB5S$*VQD3)M;7[%?\-Z9Q,!S=@3IC%-QQ4DE\`ZI]!F/Q7<_:X->`3 M^+]CF67_U[?ZU/]9R&OP_UN0PO_J$2B@>*T$%#"_C1B^3?(]2+F'#5+HR:(0 MQ6Z$D!@[0B#&8@,EJ`V<JDKP?A9A_6`I8(=FA]QEA/_OG>5/JY[S:Y'_EI;N MJ[M$$EQ2PRLGVK(+C,FQLPM,;NB<+_KF^<(USA>#$7[W.^T6\D:7YXN=P?G" MPH\Q4..!I<;]'93#9V,7/T;^*>91Q^Z.TD'SHSZ.W5P/SAE[.*;G_FI?%Y\O M1TJ/3Q^?/DJ'A3+,4/O3O$LZ\7N7Y,W*_FL?):=TR/WND24;W9':%_TG@).` M?367W7$.T8AE9=U)9U$BL`/P"7K7N"D+JDP9[S`*6<\/G&EZ4QZU6`B/8-MX MZA)^F0EFVZ!I,1Y:YNDZX`&UL2JA)?6Z-V7"ICG'\Y(5WM8WQOGD;'A1W56N M13XUXK@G]DTV7$=T'<+"J75D/CPQ.C]"YV#>`8TTZ-3+$_\`NII6U]35X:G< MQ;K0JZ5![E`4!^R1/$HWK5;.T?.486\@1;JQ2-;*?<H_,'51P>JGKAGT2GKE MPO*J025]TU0U':]YH?"U#NT'<A7@M2A*SD-J9/*[C:G+2JY4DW6Y9FF$VO<N ME21]M\;"X_=8@=E_UV5IWL-]EN+W.KVZ<-X\B:L3M\;+<0EW_S-C[`-V347O MT@,L:'C`<4D.6-Z9:8WPCMB-Y855'L9:!JC35YCM1QEBNL1V`<;BR0+M[M%8 M+_LIZ7YQM^V4):&C[K?O3O2[XT%+[@MQ>=[)@!]`&W4-1".])U.%DED%//*U M?"PS+`\'FE2PMP@<X-DS,(<Z_`T5KDE1J#N+RP560*FBZG2NMLC.W+(R]AA: MO+I;(YJ/:6_U.X$.*$6"Q7R/2@5!I$GE8`<5]^M&=V\B@Q:C]_W;W@S54%IG MTP\O[.'V4C0'7=L^.I$EF$):'IX!+;EG@:R.PP&M4:=K?4G!K89D9;B:!1_[ M"![^P5SY^Q%/*X8K0V0@:\ZJ3KHPJ.JKTIGO\Y#@[QFXRI*!SU/ESLAO*N]N M1+YR/8`XPBF6U..?"ZR_@#(UZ]'+P_+#W0?`NLV,/"958_!H)\L[P[-"U/*% MRS:F3"4Y4HFD!,BFP7YU96%X_<RL3"L;1?6"F=>K6XB7&^YSYN59C^`41*G" ET2_YW:JAAAIJJ*&&&FJHH88::JBAAAIJJ*&'T3^29G2F`"@````` ` end [------------------------------------ -----BEGIN PGP SIGNATURE----- Note: This signature can be verified at https://www.hushtools.com/verify Version: Hush 2.4 wkYEARECAAYFAkIlNgMACgkQImcz/hfgxg2dkQCfSE9n7cV5VoaUWWlgpgZ+eApsDk8A n1md8ECuTcDX1W2vKaC2/NQKwp/g =WISz -----END PGP SIGNATURE----- Concerned about your privacy? Follow this link to get secure FREE email: http://www.hushmail.com/?l=2 Free, ultra-private instant messaging with Hush Messenger http://www.hushmail.com/services-messenger?l=434 Promote security and make money with the Hushmail Affiliate Program: http://www.hushmail.com/about-affiliate?l=427 _______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.netsys.com/full-disclosure-charter.html
Current thread:
- Irony in the Otherworld Phantasmal Phantasmagoria (Mar 01)