Logo
    Discovering _ CVE-2022–22980 real exploitable path
    🛣️

    Discovering _ CVE-2022–22980 real exploitable path

    ⚠️ [ ORIGIN SOURCE ]
    https://infosecwriteups.com/analyzing-cve-2022-22980-to-discover-a-real-exploitable-path-in-the-source-code-review-process-with-145d97717656
    📅 [ Archival Date ]
    Oct 19, 2022 11:20 PM
    🏷️ [ Tags ]
    CVE-2022–22980CodeQL
    ✍️ [ Author ]

    Frentzen Amaral

    💣 [ PoC / Exploit ]
    https://crash.link/CVE-2022-22980
    image

    Introduction

    In this post, I will walk you through a journey that starts analyzing CVE-2022–22980 and extracting a pattern of this vulnerability to query a codebase to discover the true exploitation path.

    While many vulnerability scanning tools are powerful in detecting vulnerable components in an application, some of them fail to prove whether the vulnerability is exploitable by a threat.

    As a powerful ally for this task, there is CodeQL. It is a semantic code analysis engine open source from GitHub that lets query your codebase as it were data. Thus, it is a crucial tool that allows us to search for a pattern of vulnerability in the entire source code.

    In the creation process, it is possible to refine the query until just exploitable paths are discovered, which will be demonstrated in this article.

    Analysis of CVE-2022–22980

    While reading some security vulnerabilities bulletins, CVE-2022–22980 caught my attention. It treats about a fix in an Expression Language injection in Spring Data MongoDB that could lead to remote code execution.

    So, reviewing the announcement provided by VMWare some points were identified that could lead to a vulnerable scenario.

    A repository query method is annotated with @Query or @Aggregation

    The annotated query or aggregation value/pipeline contains SpEL parts using the parameter placeholder syntax within the expression

    The user supplied input is not sanitized by the application

    Accomplishing these conditions and using the Spring Data MongoDB in both 3.4.0, 3.3.0 to 3.3.4 and older unsupported versions, the application is prone to vulnerability. Thus, the next step will turn these conditions into a pattern and build a CodeQL query to search the entire codebase.

    Building a CodeQL query

    The first step in building this query is to determine which user inputs are used by the application. So RemoteFlowSources is a good point for this task. It is a Class defined by CodeQL that maps a data flow source of remote user input.

    So in the first part of this query, we needed to do the imports and define that sources are equal to remote flow sources.

    /**
     *@kind path-problem
     */
    import java
    import semmle.code.java.dataflow.FlowSources
    import semmle.code.java.dataflow.DataFlow
    import DataFlow::PathGraphclass MyConf extends DataFlow::Configuration {
      MyConf() { this = "MyConf" }
    
      override predicate isSource(DataFlow::Node source) {
        exists(RemoteFlowSource remote | source.asParameter() = remote.asParameter())
      }

    Once defined which are the sources is time to build a sink part of the query. In this part, the conditions of exploitability must be met. Thus, three variables were defined to conduct this phase. One for methods that have annotations assigned, the other for the names of the annotations, and the last one for finding access to methods with assigned annotations.

    After defining the variables, it is necessary to perform conditional operations that find the correct sink. First, it was compared if the method annotation was equal to the annotation defined by us, then it was compared if the annotation was equal to both Query or Aggregation, then a search via regex in annotation for values that contain ?[0-9], finally it is defined that the access to the method must be equal to the method defined by us and the argument of this access must be equal to our sink.

    override predicate isSink(DataFlow::Node sink) {
        exists(Method c, Annotation ann, MethodAccess ma | ann = c.getAnAnnotation() and (ann.toString() = "Query" or ann.toString() = "Aggregation") and ann.getAValue().toString().regexpMatch(".*\\?[0-9].*")
    and ma.getMethod() = c and ma.getAnArgument()
     = sink.asExpr())
      }

    At the end of the query, the portion that connects all the points of our constructed query was defined. The final query looks like this:

    Executing the query in CodeQL

    For this phase, we used the vulnerable public application designed for this security issue, which will serve as our codebase. Thus, the CodeQL database was created from the codebase that was defined.

    codeql database create cveanalysis --language=java

    Once the database is created, it’s time to import it into VSCode’s CodeQL extension to run our query.

    image

    VSCode after database import and query filled

    After selecting the recently uploaded database, it is time to go to the VSCode workspace for CodeQL in the Java tab and edit the default template with our query. Finally can run our query in the codebase.

    image

    Results of query execution

    It is the possible view that there is a real path exploitable for the vulnerability in this codebase. It is the possible view that there is a real exploitable path to the vulnerability in this codebase. The results give us the source, drain, and intermediate steps if any. In this case, there is a simple path between the source and sink.

    image

    source and sink

    Validating the Exploitable Path

    As identified in prior steps this vulnerability receives a parameter in its /test endpoint and passes it to the vulnerable function. As identified in the previous steps, this vulnerability receives a POST parameter on its /testendpoint and passes it to the vulnerable function. So by running the following command, the vulnerability is achieved:

    image

    cURL command with malicious payload

    With this, we can constant that the file was created in the temporary directory and the remote code execution was achieved.

    image

    After and before code execution

    Conclusion

    It is also important to determine if a vulnerability is exploitable in your environment once this influence a Risk Management process.

    More about CVE-2022–22980 on this previous post 👇

    CVE-2022-22980 _ Spring Data MongoDB SpEL ExpInjection

    MongoDB is a document-oriented NoSQL database with the scalable and flexible that used for high volume data storage. Instead of using tables and rows as in the traditional relational databases, MongoDB makes use of collections and documents. Documents consist of key-value pairs which are the basic unit of data in MongoDB.

    cra.sh

    CVE-2022-22980 _ Spring Data MongoDB SpEL ExpInjection
    /**
     *@kind path-problem
     */
    import java
    import semmle.code.java.dataflow.FlowSources
    import semmle.code.java.dataflow.DataFlow
    import DataFlow::PathGraphclass MyConf extends DataFlow::Configuration {
      MyConf() { this = "MyConf" }
    
      override predicate isSource(DataFlow::Node source) {
        exists(RemoteFlowSource remote | source.asParameter() = remote.asParameter())
      }override predicate isSink(DataFlow::Node sink) {
        exists(Method c, Annotation ann, MethodAccess ma | ann = c.getAnAnnotation() and (ann.toString() = "Query" or ann.toString() = "Aggregation") and ann.getAValue().toString().regexpMatch(".*\\?[0-9].*")
    and ma.getMethod() = c and ma.getAnArgument()
     = sink.asExpr())
      }
    }from MyConf conf, DataFlow::PathNode source, DataFlow::PathNode sink
    where conf.hasFlowPath(source, sink)
    select sink, source, sink, "SpEL Injection found! - CVE-2022-22980"