Jujutsu

References:

[1] Control Jujutsu: On the Weaknesses of Fine-Grained Control Flow Integrity. CCS, 2015.


A new attack on fine-grained CF that exploit the incompleteness of pointer analysis, when combined with common software engineering practices, to enable an attacker to execute arbitrary malicious code.


Concepts:

  • ICS: Indirect Call Site
  • ACICS: Argument Corruptible Indirect Call Site
  • RCE: Remote Code Execution
  • DSA: Data Structure Analysis
  • DEP: Data Execution Prevention
  • ASLR: Address Space Layout Randomization
  • SSP: Stack Smashing Protection
  • ROP: Return-oriented Programming
  • JOP: Jump-Oriented Programming

Threat Model

The threat model in this paper is a remote attacker trying to hijack control of a machine by exploiting memory vulnerabilities.

Secure Part:

  • Fine-grained CFI, with unlimited tags for the forward edge and a shadow stack
  • DEP deployed.
  • ASLR deployed.

Insecure Part:

  • Memory corruption vulnerability exits, which allows an attacker to corrupt certain values on stack or heap.

Exploit Design

Searching ACICS Candidate

Searching among all ICS:

  • The forward edge pointer and its arguments that reside on the heap or a global variable.
  • The argument at ICS can be altered without crashing the program, before reaching a target function.
  • The ICS should be reachable from external input, e.g., a network request.

ap_run_dirwalk_stat() contains pHook[n].pFunc, which invokes a function pointer.

Select Target

Apache HTTPD and Nginx

piped_log_spawn

Exploit

figure1 httpd code apr-macro

figure2 httpd code

figure3 httpd code

figure4 httpd code

  1. use heap memory corruption vulnerability to corrupt an entry in the _hooks structure’s link_dirwalk_stat field to point to piped_log_spawn.

  2. use same vulnerability to corrupt the struct in the request_rec->finfo field such that, when viewed as a piped_log struct, the fields read_fd and write_fd are null, and the field program points to a string with the name and arguments of the program we intend to invoke, such as /bin/sh -c ....

Why success with fine-grained CFI?

Short answer: No fine-grained CFI with CFG generated by static analysis.

Long story:

Building control flow graph with static analysis

A precise CFG requires a pointer analysis to determine the set of functions to which the pointer at each indirect call site can point.

Challenges

  • Global Struct. _hooks is a global struct variable in Apache HTTPD. Each filed of it contains an array of function pointers. For example, field link_dirwalk_stat contains an array of function pointers to implementation functions of the functionality dirwalk_stat.
  • Customized Container API to manipulate function pointers. The analysis has to capture inter-procedural data flows via customized container APIs. For example, function pointers are stored and manipulated using customized array APIs apr_array_push(), apr_array_make().
  • Macro Generated Code. Those code are structurally similar. This imposes a significant additional precision requirement on the static analysis, as it needs to consider a (potentially) large number of similar functions that can manipulate the data structures inside _hooks.

Static Analysis Trade-offs

Precise(sound and complete) pointer analysis is undecidable[41], for languages with if statements, loops, dynamic storage, and recursive data structures.

Questions:

Could we restrict the language features in different ways so that the pointer analysis could either be sound, or complete, or decidable?

Created Jun 26, 2019 // Last Updated Jul 8, 2022

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?