space-r7 (89)
Last Login: December 22, 2020
space-r7's Contributions (28)
Technical Analysis
Rating this as very high as this is a widespread Wordpress plugin, and the vulnerability is easily exploitable. The vulnerability is due to an example file, lib/php/connector.minimal.php
, being left over in installations of the plugin. The file enables unauthenticated execution of select commands including an upload
command that allows for file upload which can lead to code execution on the server.
Note that disabling the plugin in Wordpress does not fix the vulnerability. The plugin should either be removed or updated to the patched version, which is v6.9
.
Technical Analysis
This vulnerability is essentially a duplicate of CVE-2017-5645, which was discovered in various versions of Log4j 2. I am unsure why the Log4j 1.x versions were addressed later, especially since Log4j 1.x was considered EoL in 2015.
Including any of the vulnerable versions of the Log4j library and enabling it in the application of choice opens up a pretty nasty vulnerability in said application. The CVE listing mentions that the vulnerability exists within the SocketServer
class. Within its main()
method, a SocketNode
object is created once a client connection is accepted.
public static void main(String argv[]) { ... while(true) { cat.info("Waiting to accept a new client."); Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); cat.info("Connected to client at " + inetAddress); LoggerRepository h = (LoggerRepository) server.hierarchyMap.get(inetAddress); if(h == null) { h = server.configureHierarchy(inetAddress); } cat.info("Starting new socket node."); new Thread(new SocketNode(socket, h)).start(); ... }
The SocketNode
constructor creates a new ObjectInputStream
object named ois
from data on the socket:
public SocketNode(Socket socket, LoggerRepository hierarchy) { this.socket = socket; this.hierarchy = hierarchy; try { ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream())); ... }
And in the SocketNode
’s run()
method, readObject()
is called on the data previously read from the socket:
public void run() { LoggingEvent event; Logger remoteLogger; try { if (ois != null) { while(true) { // read an event from the wire event = (LoggingEvent) ois.readObject(); // get a logger from the hierarchy. The name of the logger is taken to be the name contained in the event. remoteLogger = hierarchy.getLogger(event.getLoggerName()); ... }
This vulnerability could give an attacker unauthenticated RCE easily if and only if the Log4j library is enabled and listening for remote connections. I’m rating this vulnerability a little lower in utility / attacker value because of that. This is quite an old vulnerability despite the CVE date, but as always, make sure you’re patched.
Technical Analysis
The readFrom
method within the Command
class in the Jenkins CLI remoting component deserializes objects received from clients without first checking / sanitizing the data. Because of this, a malicious serialized object contained within a serialized SignedObject
can be sent to the Jenkins endpoint to achieve code execution on the target.
This is a fairly old vulnerability, so it’s unlikely that there are many, if any vulnerable installations on the web today, but I rated this vulnerability based on what it could give an attacker if they were to find a vulnerable installation online today. This vulnerability is yet another Java deserialization vulnerability that I would define as critical given a number of reasons:
- Unauthenticated code execution
- There is no special / proprietary protocol that will hinder exploitation ( you just send the object in the body of a POST request )
- A proof of concept exists and has for some time
Again, this is an unlikely target given the date of the vulnerability, but I think an attacker would definitely aim to exploit this if it was spotted online.
Technical Analysis
Versions of Wildfly below 20.0.0.Final
can load arbitrary classes through either JNDI or EJB invocation, which could potentially result in RCE. Despite that, authentication is required, making exploitation all the more difficult.
Technical Analysis
Not many details have been released regarding this vulnerability, Despite that, exploitation sounds trivial, and the result is code execution as root
. This should definitely be patched.
Technical Analysis
This is now being reported as a bypass for the patch for CVE-2020-2555. The gadget chain is slightly modified, but it seems that exploitation results in unauthenticated RCE just as with CVE-2020-2555. This should certainly be patched.
Technical Analysis
The vulnerability exists in the LimitFilter
class’s toString()
method within the Coherence library, a library that exists within WebLogic installations by default.
public String toString() { StringBuilder sb = new StringBuilder("LimitFilter: ("); sb.append(this.m_filter) .append(" [pageSize=") .append(this.m_cPageSize) .append(", pageNum=") .append(this.m_nPage); if (this.m_comparator instanceof ValueExtractor) { ValueExtractor extractor = (ValueExtractor)this.m_comparator; sb.append(", top=") .append(extractor.extract(this.m_oAnchorTop)) .append(", bottom=") .append(extractor.extract(this.m_oAnchorBottom)); } else if (this.m_comparator != null) { sb.append(", comparator=") .append(this.m_comparator); } sb.append("])"); return sb.toString(); }
As originally noted in the ZDI blog post, all of the calls to extract()
were removed from the aforementioned toString()
method in the fix. The removal was due to having the ability to leverage the ReflectionExtractor
class’s extract()
method to execute arbitrary code via method.invoke()
.
public E extract(T oTarget) { if (oTarget == null) return null; Class<?> clz = oTarget.getClass(); try { Method method = this.m_methodPrev; if (method == null || method.getDeclaringClass() != clz) this.m_methodPrev = method = ClassHelper.findMethod(clz, getMethodName(), ClassHelper.getClassArray(this.m_aoParam), false); return (E)method.invoke(oTarget, this.m_aoParam); } catch (NullPointerException e) { throw new RuntimeException(suggestExtractFailureCause(clz)); } catch (Exception e) { throw ensureRuntimeException(e, clz .getName() + this + '(' + oTarget + ')'); } }
The prerequisite for being able to leverage extract()
to execute code is to first trigger the toString()
method from the LimitFilter
class. The BadAttributeValueExpException
class within the JRE meets the prereq, as can be seen in its readObject()
method:
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ObjectInputStream.GetField gf = ois.readFields(); Object valObj = gf.get("val", null); if (valObj == null) { val = null; } else if (valObj instanceof String) { val= valObj; } else if (System.getSecurityManager() == null || valObj instanceof Long || valObj instanceof Integer || valObj instanceof Float || valObj instanceof Double || valObj instanceof Byte || valObj instanceof Short || valObj instanceof Boolean) { val = valObj.toString(); ... }
Provided that the server does not have a Security Manager, sending a serialized BadAttributeValueExpException
object to a WebLogic server will result in the toString()
method being triggered. As of now, Weblogic installations do not come with a Security Manager by default.
I would rate this vulnerability as quite high, since successful exploitation does not require authentication, and the application accepts the crafted object without any sort of filtering. This is an important one to patch.
Technical Analysis
Judging by the Kaspersky writeup, it looks like the vulnerability exists for a relatively large number of Chrome versions. Fix was released for 78.0.3904.87, and the exploit checks the range from 65-77. Despite the seemingly difficult development and execution of this exploit, this is an important one to patch.
Technical Analysis
Simply sending a malformed packet can result in RCE on a device running VxWorks, and there are reportedly no features such as ASLR, DEP, etc. enabled to mitigate the issue. Given the simplicity of successful exploitation, I’d say that this is a vulnerability to take seriously and patch.
Technical Analysis
Details
The soffice
binary allows passing arguments in order to listen on a host ip and port. Axel Boesenach found that the Apache UNO API that acts as a communication bridge to the soffice
process
can execute shell commands through the XSystemShellExecute
execute module. This exploit is useful in that exploitation comes easy through the usage of a Python library. Discovering targets running
this process are likely rare, given that the functionality exploited here is rarely used, and there is no default port that this service listens on. The effort to exploit this vulnerability was
given a higher rating due to these caveats.
Technical Analysis
Details
There exists a PHP deserialization vulnerability in Pimcore versions prior to 5.7.1 that allows the ability to gain remote code execution post authentication.
The Metasploit module documentation for exploit/multi/http/pimcore_unserialize_rce
mentions that the PHP deserialization vulnerability exists in the ClassController.php
file in the function that takes care of the bulk-commit
method. The bulkCommitAction()
function has a comment mentioning that it handles the bulk-commit
route, so it’s safe to say that analysis should start there.
In bulkCommitAction()
, the serialized PHP object gets assigned to the data
variable, and its layout type is checked in an if
statement.
The block of code is quite large, but the important detail happens in the first few lines of the elseif
block:
elseif ($type == 'customlayout') { $layoutData = unserialize($data['name']); $className = $layoutData['className']; $layoutName = $layoutData['name']; ... }
The serialized payload is passed to the unserialize()
function unsanitized, which will call the object’s magic method, __destruct()
in this case. The object used in Metasploit’s module is an object of the ApcuAdapter
class, which inherits its magic method from AbstractAdapter
.
__destruct()
method:
public function __destruct() { if ($this->deferred) { $this->commit(); } }
The deferred
variable contains the PHP code, so the commit()
function is called.
In commit()
, there are two lines of interest:
$byLifetime = $this->mergeByLifetime; $byLifetime = $byLifetime($this->deferred, $this->namespace, $expiredIds);
The object’s mergeByLifetime
variable, which is set to proc_open
in the serialized object, gets assigned to $byLifetime
. In the next line, $byLifetime
is executed with the object’s instance variables passed as the arguments. As noted previously, the deferred
variable contains the PHP code to execute. Viewing the serialized object in the pimcore_unserialize_rce
Metasploit module shows us that the namespace
variable is an empty array, and $expiredIds
is a variable that will hold an array of file pointers. So summing this up, proc_open()
will execute code embedded in a PHP serialized object, potentially giving unauthorized individuals shell access.
Technical Analysis
High attacker utility if only the vulnerability is considered.
Quoting Cisco:
In order for a device to be considered vulnerable, all of the following conditions must be met:
- A REST API OVA package with a version below 16.9.3 must be present on the device local storage
- The REST API virtual service is installed
- The REST API virtual service is configured
- The REST API virtual service is enabled
Given that the vulnerable service is not enabled by default and requires some extra steps to even set up, I am unsure of the actual likelihood of successful exploitation. Echoing what Brendan said, mitigations are already in place on the device if the vulnerable service is installed and enabled. Because of that, I wouldn’t say that this is the most urgent of patches to install, although it’s always better to have a patched system.
Technical Analysis
This vulnerability allows for taking over SYSTEM-owned files. Getting an elevated shell takes more effort, either by exposing the DiagHub service, which will willingly load a file from System32 with SYSTEM privileges or by combing the target for a service that loads a dll as SYSTEM. Exploitability is variable due to those reasons, but ultimately this is a useful vulnerability. Effort to execute this exploit is rated higher due to shell access being a prerequisite.
There is even a bypass for this vulnerability’s patch: CVE-2019-1064.
Technical Analysis
If this vulnerability is found in the wild, then it’s likely that the target is vulnerable to CVE-2018-15710 as well. An attacker can get unauthenticated root access to a target given that it is vulnerable to both vulnerabilities, which means it is incredibly important to get this patched. A module now exists for this vulnerability, which further eases the process of exploitation.
Technical Analysis
Given that the enableCmdLineArguments
setting is configured, it looks fairly easy to get code execution. This should definitely be patched.
Technical Analysis
Useful exploit with a caveat. This exploit takes more effort to execute given that authentication is required first.
According to the CVE listing on NVD, shell commands can be passed through the _POST['community']
parameter to html/pages/addhost.inc.php
, which deals with the creation of new devices. After successfully creating a device, a request can be sent to ajax_output.php
, which triggers the actual execution of code through html/includes/output/capture.inc.php
.
If the community
parameter is set when a request is made to addhost.inc.php
, then community
is passed to the clean()
function with the second argument set to false
.
if ($_POST['community']) { $config['snmp']['community'] = array(clean($_POST['community'], false)); }
The clean()
function is located in includes/common.php
. Here’s what it looks like in version 1.46
:
function clean($value, $strip_tags = true) { if ($strip_tags === true) { return strip_tags(mres($value)); } else { return mres($value); } }
In this particular call to clean()
, the $strip_tags
value is set to false
, meaning that the community
parameter is acted upon by the mres()
function, then returned. The mres()
function:
function mres($string) { return $string; global $database_link; return mysqli_real_escape_string($database_link, $string); }
The community
parameter is simply returned without any modifications.
From here, we can see that the community
parameter is set through a POST request to addhost.inc.php
, and it is unsanitized. Assuming that unwanted input is passed into the community
parameter, now the goal is to see how a request to ajax_output.php
will trigger code execution.
In ajax_output.php
, the id
is checked and is used to require another file. In this case, that would be capture.inc.php
.
if (isset($id)) { require $config['install_dir'] . "/html/includes/output/$id.inc.php"; }
The functionality in capture.inc.php
runs a command that is determined by the type
parameter and either prints the output of the command or saves the output to a file. Initially, the type
parameter is checked against three different values. If the type
parameter is snmp
walk, the command becomes the output of the gen_snmp_walk()
function.
$type = $_REQUEST['type']; switch ($type) { case 'poller': ... case 'snmpwalk': $device = device_by_name(mres($hostname)); $cmd = gen_snmpwalk_cmd($device, '.', ' -OUneb'); ... case 'discovery': ... default: ... }
The gen_snmp_walk()
function is located in the snmp.inc.php
file. gen_snmp_walk()
first checks the version that was passed in the addhost
POST request earlier and then returns the result of calling gen_snmp_cmd()
. The gen_snmp_cmd()
also resides in the snmp.inc.php
file, and this function is where the bulk of the command used in capture.inc.php
is created.
The first addition to $cmd
is set to the result of calling the snmp_gen_auth()
function.
function gen_snmp_cmd($cmd, $device, $oids, $options = null, $mib = null, $mibdir = null) { ... $cmd .= snmp_gen_auth($device); ... }
snmp_gen_auth()
further builds the $cmd
variable by checking snmpver
. If that value is either v2c
or v1
, then the unsanitized community
parameter is added to the command and then returned.
} elseif ($device['snmpver'] === 'v2c' or $device['snmpver'] === 'v1') { $cmd = " -".$device['snmpver']; $cmd .= " -c '".$device['community']."'"; ... return $cmd;
Now that there is a command that contains unsanitized input, code execution is the last step.
As was stated previously, the functionality in capture.inc.php
generates a command to run and either prints the output of that command or saves the output to a file. The functionality that runs the command checks the format
parameter passed in the request made to ajax_output.php
described earlier. If the format
parameter is set to text
, then this code block will be executed:
if ($_GET['format'] == 'text') { header("Content-type: text/plain"); header('X-Accel-Buffering: no'); if (($fp = popen($cmd, "r"))) { while (!feof($fp)) { $line = stream_get_line($fp, 1024, PHP_EOL); echo preg_replace('/\033\[[\d;]+m/', '', $line) . PHP_EOL; ob_flush(); flush(); // you have to flush buffer } fclose($fp); }
The $cmd
variable that now contains the unsanitized community
parameter gets passed to the popen()
function and executed.
Technical Analysis
This vulnerability is important to patch given the ease by which an attacker can exploit a Confluence server.
Technical Analysis
This vuln is important to focus attention to. Pre-auth RCE on a likely large target base is very dangerous.
Technical Analysis
Details
With over 1 million installations of this plugin in Wordpress, this vulnerability is valuable to exploit.
Technical Analysis
Details
On vulnerable versions of Cisco’s Webex client software, any local or domain user can execute commands
with SYSTEM-level privileges. The software installs a service called WebExService
, that once started,
will run commands at the SYSTEM level.
This exploit prompts for an Administrator verification on Windows 10 and requires credentials to exploit, but it
is still a useful exploit for targets prior to Windows 10.
Technical Analysis
Details
LibreOffice offers the ability to create program events that when triggered, will execute a macro. LibreOffice gives the option to develop custom macros or select a macro from a list of scripts included with the installation. The included macros are written in a variety of languages, including Python.
Creating a mouse over event that will execute a macro upon hovering over a hyperlink will result in XML that looks similar to this:
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|TableSample.py$createTable?language=Python&location=share" xlink:type="simple"/>
Alex Inführ discovered that a directory traversal vulnerability exists in the xlink:href
attribute, allowing the ability to call functions (with its arguments) of other Python scripts included with the LibreOffice installation. The tempfilepager()
function in program/python-core-3.5.5/lib/pydoc.py
was found to both accept function arguments and pass those arguments to os.system()
, allowing for arbitrary code execution.
def tempfilepager(text, cmd): """Page through text by invoking a program on a temporary file.""" import tempfile filename = tempfile.mktemp() with open(filename, 'w', errors='backslashreplace') as file: file.write(text) try: os.system(cmd + ' "' + filename + '"') finally: os.unlink(filename)
The directory traversal vulnerability stems from how the URI in the xlink:href
attribute is converted to the actual URI of the Python script on disk. The function that does this conversion is located in program/pythonscript.py
called scriptURI2StorageUri()
.
def scriptURI2StorageUri( self, scriptURI ): try: myUri = self.m_uriRefFac.parse(scriptURI) ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" ) log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret ) return ret except UnoException as e: log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message) raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None ) except Exception as e: log.error( "error during converting scriptURI="+scriptURI + ": " + str(e)) raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None )
The scriptURI
variable passed to the function is the attacker-controlled path. In the line ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" )
, the local scripts path gets built. m_baseUri
, the base installation path, gets concatenated with a /
and the controllable path (with vnd.sun.star.script:
removed) after any |
characters are replaced with /
.
The final storage URI ret
would look like this on a Linux LibreOffice installation:
file:///opt/libreoffice6.1/share/Scripts/python/../../../../program/python-core-3.5.5/lib/pydoc.py$tempfilepager(ARG1, ARG2)
Technical Analysis
Details
The PHP component in the elFinder software allows unauthenticated users to upload and manipulate images.
While performing image manipulation on a JPEG, elFinder passes the file’s name unsanitized to a command line utility called exiftran
.
By inserting arbitrary code into the JPEG’s file name, the code will get passed to the exiftran utility and be executed.
This exploit requires that exiftran
be installed to work. If exiftran
is not installed, then the software opts to use jpegtran
,
which removes exploitability. Despite the caveat listed previously, this is still a valuable exploit.
Technical Analysis
Details
This exploit requires authentication and either the php-imagick
or php-gd
extension to be installed. Exploiting this vulnerability with only
the php-gd
extension installed will require more work when crafting the JPEG because the php-gd
extension compresses the image and strips it of
its exif metadata. This is still a valuable exploit due to the large user base of the application.
Technical Analysis
Details
Large number of devices affected. This exploit is useful for determining valid user names.