Java
  • About This Book
  • 🍖Prerequisites
    • 反射
      • 反射基本使用
      • 高版本JDK反射绕过
      • 反射调用命令执行
      • 反射构造HashMap
      • 方法句柄
    • 类加载
      • 动态加载字节码
      • 双亲委派模型
      • BCEL
      • SPI
    • RMI & JNDI
      • RPC Intro
      • RMI
      • JEP 290
      • JNDI
    • Misc
      • Unsafe
      • 代理模式
      • JMX
      • JDWP
      • JPDA
      • JVMTI
      • JNA
      • Java Security Manager
  • 👻Serial Journey
    • URLDNS
    • SerialVersionUID
    • Commons Collection 🥏
      • CC1-TransformedMap
      • CC1-LazyMap
      • CC6
      • CC3
      • CC2
    • FastJson 🪁
      • FastJson-Basic Usage
      • FastJson-TemplatesImpl
      • FastJson-JdbcRowSetImpl
      • FastJson-BasicDataSource
      • FastJson-ByPass
      • FastJson与原生反序列化(一)
      • FastJson与原生反序列化(二)
      • Jackson的原生反序列化利用
    • Other Components
      • SnakeYaml
      • C3P0
      • AspectJWeaver
      • Rome
      • Spring
      • Hessian
      • Hessian_Only_JDK
      • Kryo
      • Dubbo
  • 🌵RASP
    • JavaAgent
    • JVM
    • ByteCode
    • JNI
    • ASM 🪡
      • ASM Intro
      • Class Generation
      • Class Transformation
    • Rasp防御命令执行
    • OpenRASP
  • 🐎Memory Shell
    • Tomcat-Architecture
    • Servlet API
      • Listener
      • Filter
      • Servlet
    • Tomcat-Middlewares
      • Tomcat-Valve
      • Tomcat-Executor
      • Tomcat-Upgrade
    • Agent MemShell
    • WebSocket
    • 内存马查杀
    • IDEA本地调试Tomcat
  • ✂️JDBC Attack
    • MySQL JDBC Attack
    • H2 JDBC Attack
  • 🎨Templates
    • FreeMarker
    • Thymeleaf
    • Enjoy
  • 🎏MessageQueue
    • ActiveMQ CNVD-2023-69477
    • AMQP CVE-2023-34050
    • Spring-Kafka CVE-2023-34040
    • RocketMQ CVE-2023-33246
  • 🛡️Shiro
    • Shiro Intro
    • Request URI ByPass
    • Context Path ByPass
    • Remember Me反序列化 CC-Shiro
    • CB1与无CC依赖的反序列化链
  • 🍺Others
    • Deserialization Twice
    • A New Blazer 4 getter RCE
    • Apache Commons Jxpath
    • El Attack
    • Spel Attack
    • C3P0原生反序列化的JNDI打法
    • Log4j
    • Echo Tech
      • SpringBoot Under Tomcat
    • CTF 🚩
      • 长城杯-b4bycoffee (ROME反序列化)
      • MTCTF2022(CB+Shiro绕过)
      • CISCN 2023 西南赛区半决赛 (Hessian原生JDK+Kryo反序列化)
      • CISCN 2023 初赛 (高版本Commons Collections下其他依赖的利用)
      • CISCN 2021 总决赛 ezj4va (AspectJWeaver写字节码文件到classpath)
      • D^3CTF2023 (新的getter+高版本JNDI不出网+Hessian异常toString)
      • WMCTF2023(CC链花式玩法+盲读文件)
      • 第六届安洵杯网络安全挑战赛(CB PriorityQueue替代+Postgresql JDBC Attack+FreeMarker)
  • 🔍Code Inspector
    • CodeQL 🧶
      • Tutorial
        • Intro
        • Module
        • Predicate
        • Query
        • Type
      • CodeQL 4 Java
        • Basics
        • DFA
        • Example
    • SootUp ✨
      • Intro
      • Jimple
      • DFA
      • CG
    • Tabby 🔦
      • install
    • Theory
      • Static Analysis
        • Intro
        • IR & CFG
        • DFA
        • DFA-Foundation
        • Interprocedural Analysis
        • Pointer Analysis
        • Pointer Analysis Foundation
        • PTA-Context Sensitivity
        • Taint Anlysis
        • Datalog
Powered by GitBook
On this page
  • 0x01 Getting Started
  • 0x02 Apprentice Lab
  • Finding XML deserialization
  • Find the implementations of the toObject method from ContentTypeHandler
  • Unsafe XML deserialization
  • 0x03 CodeQL Recipe for Java
  • RefType
  • Method

Was this helpful?

  1. 🔍Code Inspector
  2. CodeQL 🧶
  3. CodeQL 4 Java

Example

0x01 Getting Started

Create Database for java:

codeql database create test4fun --language="java" --command="mvn clean install --file pom.xml" --source-root=D:\Code\Java\CodeQL\Demo\test1

Get Familiar With This Weird And Wicked Declarative Program🤧

Here is an example:Finding if statements which have an empty then block

import java

from IfStmt ifStmt, BlockStmt block
where
  block = ifStmt.getThen() and
  block.getNumStmt() = 0
select ifStmt, "This isf-statement has an empty then-block"
  • Predicate Wrap

import java

predicate isEmpty(BlockStmt block) {
  block.getNumStmt() = 0
}

from IfStmt ifStmt
where
  isEmpty(ifStmt.getThen())
select ifStmt
  • Class Wrap

import java

class EmptyBlock extends BlockStmt{
  EmptyBlock(){
    this.getNumStmt() = 0
  }
}
from IfStmt ifStmt
where
  ifStmt.getThen() instanceof EmptyBlock
select ifStmt

Or Use It In This Way

import java

class EmptyBlock extends BlockStmt{
  EmptyBlock(){
    this.getNumStmt() = 0
  }
}
from IfStmt ifStmt, EmptyBlock block
where
  ifStmt.getThen() = block
select ifStmt

0x02 Apprentice Lab

Unsafe deserialization in Apache Struts —— CVE-2017-9805

Finding XML deserialization

XStream is a Java framework for serializing Java objects to XML used by Apache Struts. It provides a method XStream.fromXML for deserializing XML to a Java object. By default, the input is not validated in any way, and is vulnerable to remote code execution exploits. In this section, we will identify calls to fromXML in the codebase.

  1. 查找程序中的所有方法调用

import java

from MethodAccess call
select call
  1. 找到所有方法调用及其对应的方法声明

import java

from MethodAccess call, Method method
where call.getMethod() = method
select call, method
  1. 找到程序中所有调用fromXML的地方

import java

from MethodAccess call, Method method
where 
  call.getMethod() = method and
  method.getName() = "fromXML"
select call, method

可以简化为

import java

from MethodAccess fromXML
where 
  fromXML.getMethod().getName() = "fromXML"
select fromXML
  1. 找出调用fromXML方法的第一个参数

import java

from MethodAccess fromXML, Expr arg
where 
  fromXML.getMethod().getName() = "fromXML" and
  arg = fromXML.getArgument(0)
select fromXML, arg
  1. 使用谓词包装

import java

predicate isXMLDeserialized(Expr arg) {
  exists(MethodAccess fromXML | 
    fromXML.getMethod().getName() = "fromXML" and
    arg = fromXML.getArgument(0)  
  )
}

from Expr arg
where isXMLDeserialized(arg)
select arg

Find the implementations of the toObject method from ContentTypeHandler

  1. 创建一个ContentTypeHandler类,找到org.apache.struts2.rest.handler.ContentTypeHandler接口

import java

class ContentTypeHandler extends RefType {
  ContentTypeHandler() {
      this.hasQualifiedName("org.apache.struts2.rest.handler", "ContentTypeHandler")
  }
}
  1. 创建一个ContentTypeHandlerToObject类,识别org.apache.struts2.rest.handler.ContentTypeHandler子类/实现类的toObject的方法

class ContentTypeHandlerToObject extends Method {
  ContentTypeHandlerToObject() {
    this.getName() = "toObject" and
    this.getDeclaringType().getASupertype() instanceof ContentTypeHandler
  }
}
  1. toObject方法应将第一个参数视为不受信任的用户输入。查询toObject方法的第一个参数

from ContentTypeHandlerToObject toObject
select toObject.getParameter(0)

Unsafe XML deserialization

(英文写的很通俗易懂,就直接搬运了)

We have now identified (a) places in the program which receive untrusted data and (b) places in the program which potentially perform unsafe XML deserialization. We now want to tie these two together to ask: does the untrusted data ever flow to the potentially unsafe XML deserialization call?

In program analysis we call this a data flow problem. Data flow helps us answer questions like: does this expression ever hold a value that originates from a particular other place in the program?

We can visualize the data flow problem as one of finding paths through a directed graph, where the nodes of the graph are elements in program, and the edges represent the flow of data between those elements. If a path exists, then the data flows between those two nodes.

Consider this example Java method:

int func(int tainted) {
   int x = tainted;
   if (someCondition) {
     int y = x;
     callFoo(y);
   } else {
     return x;
   }
   return -1;
}

The data flow graph for this method will look something like this:

This graph represents the flow of data from the tainted parameter. The nodes of graph represent program elements that have a value, such as function parameters and expressions. The edges of this graph represent flow through these nodes.

CodeQL for Java provides data flow analysis as part of the standard library. You can import it using semmle.code.java.dataflow.DataFlow. The library models nodes using the DataFlow::Node CodeQL class. These nodes are separate and distinct from the AST (Abstract Syntax Tree, which represents the basic structure of the program) nodes, to allow for flexibility in how data flow is modeled.

/**
* @kind path-problem
*/
import java
import semmle.code.java.dataflow.DataFlow
import DataFlow::PathGraph

class ContentTypeHandler extends RefType {
  ContentTypeHandler() {
    this.hasQualifiedName("org.apache.struts2.rest.handler", "ContentTypeHandler")
  }
}

class ContentTypeHandlerToObject extends Method {
  ContentTypeHandlerToObject() {
    this.getName() = "toObject" and
    this.getDeclaringType().getASupertype() instanceof ContentTypeHandler
  }
}


predicate isXMLDeserialized(Expr arg) {
  exists(MethodAccess fromXML | 
    fromXML.getMethod().getName() = "fromXML" and
    arg = fromXML.getArgument(0)  
  )
}


class StrutsUnsafeDeserializationConfig extends DataFlow::Configuration {
  StrutsUnsafeDeserializationConfig() { this = "StrutsUnsafeDeserializationConfig" }
  override predicate isSource(DataFlow::Node source) {
    exists(ContentTypeHandlerToObject toObject |
      source.asParameter() = toObject.getParameter(0)
    )
  }
  override predicate isSink(DataFlow::Node sink) {
    exists(Expr arg |
      isXMLDeserialized(arg) and
      sink.asExpr() = arg
    )
  }
}

from StrutsUnsafeDeserializationConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink, source, sink, "Unsafe XML deserialization"

0x03 CodeQL Recipe for Java

RefType

getACallable() 获取所有可以调用方法(包括构造方法)

getAMember() 获取所有成员,其中包括调用方法,字段和内部类

getAField() 获取所有字段

getAMethod() 获取所有方法

getASupertype() 获取父类

getAnAncestor() 获取所有的父类相当于递归的getASupertype*()

hasQualifiedName(packageName, className) 标识具有给定包名和类名的类

Method

getName() 获取类名

getDeclaringType() 获取方法的声明类型

getParameter(int index) 获取索引为index的参数(索引从0开始)

PreviousDFANextSootUp ✨

Last updated 11 months ago

Was this helpful?

Download and unzip👉

image-20230404110635854
apache_struts_cve_2017_9805.zip database