Format string vulnerabilities

Similar documents
Software Vulnerabilities. Jeff Foster University of Maryland, College Park

Assembly Language: Function Calls

Assembly Language: Function Calls" Goals of this Lecture"

Procedure Calls. Young W. Lim Mon. Young W. Lim Procedure Calls Mon 1 / 29

Buffer Overflows. Buffer Overflow. Many of the following slides are based on those from

Assembly Language: Function Calls. Goals of this Lecture. Function Call Problems

Assembly Language: Function Calls" Goals of this Lecture"

Question 4.2 2: (Solution, p 5) Suppose that the HYMN CPU begins with the following in memory. addr data (translation) LOAD 11110

Intel assembly language using gcc

Procedure Calls. Young W. Lim Sat. Young W. Lim Procedure Calls Sat 1 / 27

CMSC 313 Lecture 12. Project 3 Questions. How C functions pass parameters. UMBC, CMSC313, Richard Chang

CSC 2400: Computing Systems. X86 Assembly: Function Calls"

CPEG421/621 Tutorial

Function Calls COS 217. Reading: Chapter 4 of Programming From the Ground Up (available online from the course Web site)

Architecture-level Security Vulnerabilities

X86 Review Process Layout, ISA, etc. CS642: Computer Security. Drew Davidson

CS 161 Computer Security. Week of January 22, 2018: GDB and x86 assembly

administrivia today start assembly probably won t finish all these slides Assignment 4 due tomorrow any questions?

Introduction to Computer Systems , fall th Lecture, Sep. 28 th

Secure Programming Lecture 3: Memory Corruption I (Stack Overflows)

Betriebssysteme und Sicherheit Sicherheit. Buffer Overflows

Midterm 1 Review. Memory Safety & Web Attacks

Format String Dangers. Shachar Shemesh Security Consultant

Final exam. Scores. Fall term 2012 KAIST EE209 Programming Structures for EE. Thursday Dec 20, Student's name: Student ID:

CMPSC 497 Buffer Overflow Vulnerabilities

Lecture 9: Buffer Overflow* CS 392/6813: Computer Security Fall Nitesh Saxena

Linux Memory Layout. Lecture 6B Machine-Level Programming V: Miscellaneous Topics. Linux Memory Allocation. Text & Stack Example. Topics.

4) C = 96 * B 5) 1 and 3 only 6) 2 and 4 only

CMSC 313 Lecture 12 [draft] How C functions pass parameters

Process Layout and Function Calls

Roadmap: Security in the software lifecycle. Memory corruption vulnerabilities

Computer Systems CEN591(502) Fall 2011

CS241 Computer Organization Spring 2015 IA

CYSE 411/AIT681 Secure Software Engineering Topic #12. Secure Coding: Formatted Output

2/9/18. CYSE 411/AIT681 Secure Software Engineering. Readings. Secure Coding. This lecture: String management Pointer Subterfuge

Sungkyunkwan University

BUFFER OVERFLOW DEFENSES & COUNTERMEASURES

CSE2421 FINAL EXAM SPRING Name KEY. Instructions: Signature

Lecture 09 Code reuse attacks. Stephen Checkoway University of Illinois at Chicago CS 487 Fall 2017

Assembly Programmer s View Lecture 4A Machine-Level Programming I: Introduction

Buffer Overflow. Jo, Heeseung

BUFFER OVERFLOW. Jo, Heeseung

x86 assembly CS449 Fall 2017

Machine-level Programming (3)

CMSC 313 COMPUTER ORGANIZATION & ASSEMBLY LANGUAGE PROGRAMMING PREVIEW SLIDES 16, SPRING 2013

CS642: Computer Security

CSE 127 Computer Security

Architecture-level Security Vulnerabilities. Julian Stecklina

CPSC W Term 2 Problem Set #3 - Solution

AS08-C++ and Assembly Calling and Returning. CS220 Logic Design AS08-C++ and Assembly. AS08-C++ and Assembly Calling Conventions

CPS104 Recitation: Assembly Programming

Lecture 04 Control Flow II. Stephen Checkoway University of Illinois at Chicago CS 487 Fall 2017 Based on Michael Bailey s ECE 422

Machine Programming 1: Introduction

Lab 10: Introduction to x86 Assembly

CSC 2400: Computing Systems. X86 Assembly: Function Calls

CS 31: Intro to Systems Functions and the Stack. Martin Gagne Swarthmore College February 23, 2016

Project 1 Buffer Overflow

Assembly level Programming. 198:211 Computer Architecture. (recall) Von Neumann Architecture. Simplified hardware view. Lecture 10 Fall 2012

Lecture 6: Buffer Overflow. CS 436/636/736 Spring Nitesh Saxena

CS 645: Lecture 3 Software Vulnerabilities. Rachel Greenstadt July 3, 2013

CS61, Fall 2012 Midterm Review Section

symbolic name data type (perhaps with qualifier) allocated in data area, stack, or heap duration (lifetime or extent)

238P: Operating Systems. Lecture 7: Basic Architecture of a Program. Anton Burtsev January, 2018

Control Hijacking Attacks

CNIT 127: Exploit Development. Ch 2: Stack Overflows in Linux

Assembly Language Programming - III

CS 33: Week 3 Discussion. x86 Assembly (v1.0) Section 1G

CSCI 192 Engineering Programming 2. Assembly Language

What the CPU Sees Basic Flow Control Conditional Flow Control Structured Flow Control Functions and Scope. C Flow Control.

Process Layout, Function Calls, and the Heap

The first Secure Programming Laboratory will be today! 3pm-6pm in Forrest Hill labs 1.B31, 1.B32.

Access. Young W. Lim Sat. Young W. Lim Access Sat 1 / 19

CS 161 Computer Security

Buffer Overflow. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

CMSC 313 Fall2009 Midterm Exam 2 Section 01 Nov 11, 2009

Turning C into Object Code Code in files p1.c p2.c Compile with command: gcc -O p1.c p2.c -o p Use optimizations (-O) Put resulting binary in file p

Secure Programming Lecture 6: Memory Corruption IV (Countermeasures)

CAS CS Computer Systems Spring 2015 Solutions to Problem Set #2 (Intel Instructions) Due: Friday, March 20, 1:00 pm

Machine/Assembler Language Putting It All Together

CIT Week13 Lecture

COMP 210 Example Question Exam 2 (Solutions at the bottom)

Security Workshop HTS. LSE Team. February 3rd, 2016 EPITA / 40

CSE 509: Computer Security

Access. Young W. Lim Fri. Young W. Lim Access Fri 1 / 18

Section 4: Threads and Context Switching

Data in Memory. variables have multiple attributes. variable

CS , Fall 2004 Exam 1

Section 4: Threads CS162. September 15, Warmup Hello World Vocabulary 2

Buffer-Overflow Attacks on the Stack

CSCE 548 Building Secure Software Integers & Integer-related Attacks & Format String Attacks. Professor Lisa Luo Spring 2018

Computer Systems Lecture 9

Homework. In-line Assembly Code Machine Language Program Efficiency Tricks Reading PAL, pp 3-6, Practice Exam 1

CSE 127 Computer Security

18-600: Recitation #4 Exploits

CSE 127 Computer Security

CSE 361S Intro to Systems Software Lab Assignment #4

1 /* file cpuid2.s */ 4.asciz "The processor Vendor ID is %s \n" 5.section.bss. 6.lcomm buffer, section.text. 8.globl _start.

EECE.3170: Microprocessor Systems Design I Summer 2017 Homework 4 Solution

Buffer-Overflow Attacks on the Stack

CS61 Section Solutions 3

Transcription:

Format string vulnerabilities

Goal Take control of the program (as usual) How? Write4 (write 4 bytes to an arbitrary location) Inject shellcode (or other exploits) into the process

What should we overwrite? Saved instruction pointer () Other pointers to code (we ll come back to this)

printf family printf fprintf sprintf snprintf asprintf dprintf vprintf vfprintf vsprintf vsnprintf vasprintf vdprintf

Conversion specifiers %c Character %s String %d, %i Integer %p Pointer %u Unsigned integer %% Literal % %x, %X Hex %n Stores number of characters written %e, %f, %g Double

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 H ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 He ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 Hel_ ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 o Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 o Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 o 5_ Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 o 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 w o 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 wo o 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 wor_ o 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 worl o 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 d worl o 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 ds worl o 5 Hell ending 5 s

The way snprintf() normally works void foo(int w) { char []; const char *ending = w==1? : s ; snprintf(,, Hello %d world%s, w, ending); foo(5); w: 5 ds _ worl o 5 Hell ending 5 s

Now with %n void foo(int w) { char []; int x; snprintf(,, Hello %d world%n, w, &x); foo(5); w: 5 x: _ 5

Now with %n void foo(int w) { char []; int x; snprintf(,, Hello %d world%n, w, &x); foo(5); w: 5 o Hell x: _ 5

Now with %n void foo(int w) { char []; int x; snprintf(,, Hello %d world%n, w, &x); foo(5); w: 5 o 5_ Hell x: _ 5

Now with %n void foo(int w) { char []; int x; snprintf(,, Hello %d world%n, w, &x); foo(5); w: 5 d worl o 5 Hell x: _ 5

Now with %n void foo(int w) { char []; int x; snprintf(,, Hello %d world%n, w, &x); foo(5); w: 5 d worl o 5 Hell x: 13 5

Now with %n void foo(int w) { char []; int x; snprintf(,, Hello %d world%n, w, &x); foo(5); w: 5 d worl o 5 Hell x: 13 5

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); 2b ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); f 2b72 ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); fa 2b72 ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); fa75 2b72 ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); 5a5a 5a5a fa75 2b72 ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); Z = 0x5a 5a5a 5a5a fa75 2b72 ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Attacker controlled void foo(const char *) { char []; snprintf(,, ); foo( ZZZZ%x%x%x%x%x ); 5a5a 5a5a fa75 2b72 ZZZZ garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Overwriting void foo(const char *) { char []; snprintf(,, ); foo( \xe6\xff\xff\xbf%x%x%x%x%n ); 0xbfffffe6 garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Overwriting void foo(const char *) { char []; snprintf(,, ); foo( \xe6\xff\xff\xbf%x%x%x%x%n ); 0xbfffffe6 garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Overwriting void foo(const char *) { char []; snprintf(,, ); foo( \xe6\xff\xff\xbf%x%x%x%x%n ); 0xbfffffe6 fa75 2b72 garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Overwriting void foo(const char *) { char []; snprintf(,, ); foo( \xe6\xff\xff\xbf%x%x%x%x%n ); 0xbfffffe6 12 fa75 2b72 garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Overwriting void foo(const char *) { char []; snprintf(,, ); foo( \xe6\xff\xff\xbf%x%x%x%x%n ); 0xbfffffe6 12 fa75 2b72 garbage: 117 garbage: 10 garbage: 1839 garbage: 43 format string

Picking the bytes to write Use % len x to control the length of the output Use %hhn to write just the least-significant byte of the length

Almost putting it all together = address ZZZZ address+1 ZZZZ address+2 ZZZZ address+3 %8x%8x%8x % len x%hhn % len x%hhn % len x%hhn % len x%hhn ;

Misaligned If is not 4-byte aligned, prepend 1, 2, or 3 characters to

Advantages of format string exploits No need to smash the stack (targeted write) Avoids defenses such as stack canaries! Stack canary is a random word pushed onto the stack that is checked before the function returns

Stack Canaries int bar(char *); char foo(void) { char [100]; bar(); return [0]; foo: push {r4, lr sub sp, sp, #104 movw r4, #:lower16: stack_chk_guard movt r4, #:upper16: stack_chk_guard ldr r3, [r4] str r3, [sp, #100] mov r0, sp bl bar ldrb r0, [sp] @ zero_extendqisi2 ldr r2, [sp, #100] ldr r3, [r4] cmp r2, r3 beq.l2 bl stack_chk_fail.l2: add sp, sp, #104 pop {r4, pc saved lr saved r4 canary

Disadvantages of exploits Easy to catch so rarer: $ gcc -Wformat=2 f.c f.c: In function main : f.c:5: warning: format not a string literal and no format arguments Tricky to exploit compared to fer overflows

What else can we overwrite? Function pointers C++ vtables Global offset table (GOT)

Function pointers #include <stdlib.h> #include <stdio.h> int compare(const void *a, const void *b) { const int *x = a; const int *y = b; return *x - *y; int main() { int i; int arr[6] = {2, 1, 5, 13, 8, 4; qsort(arr, 6, 4, compare); for (i = 0; i < 6; ++i) printf("%d ", arr[i]); putchar('\n'); return 0; main: pushl movl leal movl movl movl movl call %ebp %esp, %ebp qsort: call *0x14(%ebp) 24(%esp), %esi // arr $compare, 12(%esp) $4, 8(%esp) $6, 4(%esp) %esi, (%esp) qsort

C++ Virtual function tables (vtable) struct Foo { Foo() { virtual ~Foo() { virtual void fun1() { virtual void fun2() { ; void bar(foo &f) { f.fun1(); f.fun2(); int main() { Foo f; foo(f); _Z3barR3Foo: // bar(foo&) pushl %ebp movl %esp, %ebp pushl %ebx subl $20, %esp movl 8(%ebp), %ebx // ebx <- f movl (%ebx), %eax // eax <- vtable movl %ebx, (%esp) // (esp) <- this call *8(%eax) // call virtual function movl (%ebx), %eax // eax <- vtable movl %ebx, (%esp) // (esp) <- this call *12(%eax) // call virtual function addl $20, %esp popl %ebx popl %ebp ret

vtable for Foo // Real code _ZN3FooC1Ev: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax movl $_ZTV3Foo+8, (%eax) popl %ebp ret _ZTV3Foo:.long 0.long _ZTI3Foo.long _ZN3FooD1Ev.long _ZN3FooD0Ev.long _ZN3Foo4fun1Ev.long _ZN3Foo4fun2Ev address of vtable+8 stored in first word of object // Demangled Foo::Foo(): pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax movl vtable for Foo+8, (%eax) popl %ebp ret vtable for Foo:.long 0.long typeinfo for Foo.long Foo::~Foo().long Foo::~Foo().long Foo::fun1().long Foo::fun2()

Global Offset Table (GOT) Contains pointers to code and data in shared libraries Library functions aren t called directly; stub in the Procedure Linkage Table (PLT) called E.g., call exit -> call exit@plt exit@plt looks up the address of exit in the GOT and jumps to it (not the whole story) Overwrite function pointer in GOT