Mitigating Memory Safety Vulnerabilities
CS161 Summer 22: Lecture 4
Computer Science 161
Announcements
Computer Science 161
Last Time: Memory Safety Vulnerabilities
3
Computer Science 161
Today: Memory Safety Mitigations
4
Computer Science 161
Today: Defending Against Memory Safety Vulnerabilities
5
Computer Science 161
Today: Defending Against Memory Safety Vulnerabilities
6
Computer Science 161
Using Memory-Safe Languages
7
Textbook Chapter 4.1
Computer Science 161
Today: Defending Against Memory Safety Vulnerabilities
8
Computer Science 161
Memory-Safe Languages
9
Computer Science 161
Why Use Non-Memory-Safe Languages?
10
Computer Science 161
The Cited Reason: The Myth of Performance
11
Computer Science 161
The Cited Reason: The Myth of Performance
12
Computer Science 161
The Real Reason: Legacy
13
Computer Science 161
Example of Legacy Code: iPhones
14
Computer Science 161
Writing Memory-Safe Code
15
Textbook Chapter 4.2
Computer Science 161
Today: Defending Against Memory Safety Vulnerabilities
16
Computer Science 161
Writing Memory-Safe Code
17
Computer Science 161
Writing Memory-Safe Code
18
Computer Science 161
Building Secure Software
19
Textbook Chapter 4.3
Computer Science 161
Today: Defending Against Memory Safety Vulnerabilities
20
Computer Science 161
Approaches for Building Secure Software/Systems
21
Computer Science 161
Approaches for Building Secure Software/Systems
22
Computer Science 161
Testing for Software Security Issues
23
Computer Science 161
Working Towards Secure Systems
24
Computer Science 161
Exploit Mitigations
25
Textbook Chapter 4.4
Computer Science 161
Today: Defending Against Memory Safety Vulnerabilities
26
Computer Science 161
Exploit Mitigations
27
Computer Science 161
Recall: Putting Together an Attack
28
Computer Science 161
Recall: Putting Together an Attack
We can defend against memory safety vulnerabilities by making each of these steps more difficult (or impossible)!
29
Computer Science 161
Mitigation: Non-Executable Pages
30
Textbook Chapter 4.5 & 4.6 & 4.7
Computer Science 161
Recall: Putting Together an Attack
We can defend against memory safety vulnerabilities by making each of these steps more difficult (or impossible)!
31
Computer Science 161
Non-Executable Pages
32
Computer Science 161
Subverting Non-Executable Pages
33
Computer Science 161
Subverting Non-Executable Pages: Return-to-libc
34
char cmd[] = "rm -rf /";
system(cmd);
Computer Science 161
Subverting Non-Executable Pages: Return-to-libc
35
EBP
ESP
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
RIP of main | |||
SFP of main | |||
RIP of vulnerable | |||
SFP of vulnerable | |||
name | |||
name | |||
name | |||
name | |||
name | |||
&name (arg to gets) |
Exploit:
'A' * 24� + [address of system]
+ 'B' * 4
+ [address of "rm -rf /"]
+ "rm -rf /"
system:
...
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
int system(char *command);
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
Computer Science 161
Subverting Non-Executable Pages: Return-to-libc
36
ESP
... | ... | ... | ... |
... | ... | ... | ... |
'\0' | ... | ... | ... |
'r' | 'f' | ' ' | '/' |
'r' | 'm' | ' ' | '-' |
[address of "rm -rf /"] | |||
'B' | 'B' | 'B' | 'B' |
[address of system] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
Exploit:
'A' * 24� + [address of system]
+ 'B' * 4
+ [address of "rm -rf /"]
+ "rm -rf /"
system:
...
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
EBP
int system(char *command);
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
Computer Science 161
Subverting Non-Executable Pages: Return-to-libc
37
ESP
... | ... | ... | ... |
... | ... | ... | ... |
'\0' | ... | ... | ... |
'r' | 'f' | ' ' | '/' |
'r' | 'm' | ' ' | '-' |
[address of "rm -rf /"] | |||
'B' | 'B' | 'B' | 'B' |
[address of system] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
system:
...
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
EBP
int system(char *command);
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
Computer Science 161
Subverting Non-Executable Pages: Return-to-libc
38
system:
...
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
ESP
... | ... | ... | ... |
... | ... | ... | ... |
'\0' | ... | ... | ... |
'r' | 'f' | ' ' | '/' |
'r' | 'm' | ' ' | '-' |
[address of "rm -rf /"] | |||
'B' | 'B' | 'B' | 'B' |
[address of system] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
EIP
EBP
int system(char *command);
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
Computer Science 161
Subverting Non-Executable Pages: Return-to-libc
39
system:
...
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
ESP
... | ... | ... | ... |
... | ... | ... | ... |
'\0' | ... | ... | ... |
'r' | 'f' | ' ' | '/' |
'r' | 'm' | ' ' | '-' |
[address of "rm -rf /"] | |||
'B' | 'B' | 'B' | 'B' |
[address of system] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
EIP
EBP
int system(char *command);
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
Computer Science 161
Subverting Non-Executable Pages: Return-to-libc
40
system:
...
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
ESP
... | ... | ... | ... |
... | ... | ... | ... |
'\0' | ... | ... | ... |
'r' | 'f' | ' ' | '/' |
'r' | 'm' | ' ' | '-' |
[address of "rm -rf /"] | |||
'B' | 'B' | 'B' | 'B' |
[address of system] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
EIP
EBP
We jumped into the system function, and it expects the first argument to be 4 bytes above the ESP: "rm -rf /"!
int system(char *command);
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
Computer Science 161
Subverting Non-Executable Pages: ROP
41
Computer Science 161
Subverting Non-Executable Pages: ROP
Example: Let’s say our shellcode involves the following sequence:
movl $1, %eax�xorl %eax, %ebx
The following is present in memory:
foo:� ...�<foo+7> addl $4, %esp�<foo+10> xorl %eax, %ebx�<foo+12> ret��bar:� ...�<bar+22> andl $1, %edx�<bar+25> movl $1, %eax�<bar+30> ret
How can we chain returns to run the code sequence we want?
42
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
RIP of main | |||
SFP of main | |||
RIP of vulnerable | |||
SFP of vulnerable | |||
name | |||
name | |||
name | |||
name | |||
name | |||
&name (arg to gets) |
Computer Science 161
Subverting Non-Executable Pages: ROP
Example: Let’s say our shellcode involves the following sequence:
movl $1, %eax�xorl %eax, %ebx
The following is present in memory:
foo:� ...�<foo+7> addl $4, %esp�<foo+10> xorl %eax, %ebx�<foo+12> ret��bar:� ...�<bar+22> andl $1, %edx�<bar+25> movl $1, %eax�<bar+30> ret
How can we chain returns to run the code sequence we want?
43
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
RIP of main | |||
SFP of main | |||
RIP of vulnerable | |||
SFP of vulnerable | |||
name | |||
name | |||
name | |||
name | |||
name | |||
&name (arg to gets) |
If we jump 25 bytes after the start of bar then 10 bytes after the start of foo, we get the result we want!
Computer Science 161
Subverting Non-Executable Pages: ROP
44
EBP
ESP
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
RIP of main | |||
SFP of main | |||
RIP of vulnerable | |||
SFP of vulnerable | |||
name | |||
name | |||
name | |||
name | |||
name | |||
&name (arg to gets) |
Exploit:
'A' * 24� + [address of <bar+25>]
+ [address of <foo+10>]
+ ... (more chains)
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
Computer Science 161
Subverting Non-Executable Pages: ROP
45
ESP
Exploit:
'A' * 24� + [address of <bar+25>]
+ [address of <foo+10>]
+ ... (more chains)
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
EBP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
Computer Science 161
Subverting Non-Executable Pages: ROP
46
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
ESP
EBP
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
Computer Science 161
Subverting Non-Executable Pages: ROP
47
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
ESP
EBP
Computer Science 161
Subverting Non-Executable Pages: ROP
48
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
EBP
ESP
Computer Science 161
Subverting Non-Executable Pages: ROP
49
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
EBP
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
ESP
Computer Science 161
Subverting Non-Executable Pages: ROP
50
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
EBP
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
ESP
Computer Science 161
Subverting Non-Executable Pages: ROP
51
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
ESP
EBP
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
Computer Science 161
Subverting Non-Executable Pages: ROP
52
foo:
addl $4, %esp
xorl %eax, %ebx
ret
bar:
...
andl $1, %edx
movl $1, %eax
ret
vulnerable:
...
call gets� addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
main:
...
call vulnerable
...
EIP
void vulnerable(void) {
char name[20];
gets(name);
}
int main(void) {
vulnerable();
return 0;
}
ESP
EBP
The ret instruction always pops off the bottom of the stack, so execution continues based on the chain of addresses!
... | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[ROP chain address] | |||
[address of <foo+10>] | |||
[address of <bar+25>] | |||
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
'A' | 'A' | 'A' | 'A' |
&name (arg to gets) |
Computer Science 161
Subverting Non-Executable Pages: ROP
53
Computer Science 161
Mitigation: Stack Canaries
54
Textbook Chapter 4.8 & 4.9
Computer Science 161
Recall: Putting Together an Attack
We can defend against memory safety vulnerabilities by making each of these steps more difficult (or impossible)!
55
Computer Science 161
Analogy: Canary in a Coal Mine
56
Computer Science 161
Stack Canaries
57
Computer Science 161
Stack Canaries: Properties
58
Computer Science 161
Stack Canaries
59
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
RIP of vulnerable | |||
SFP of vulnerable | |||
🐦🐦🐦 canary 🐦🐦🐦 | |||
name | |||
name | |||
name | |||
name | |||
name |
vulnerable:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl ($CANARY_ADDR), %eax # Load canary
movl %eax, -4(%ebp) # Save on stack
...
movl -4(%ebp), %eax # Load stack value
cmpl %eax, ($CANARY_ADDR) # Compare to canary and...
jne canary_failed # ... crash if not equal
movl %ebp, %esp
popl %ebp
ret
void vulnerable(void) {
char name[20];
gets(name);
}
Because the write starts at name, the attacker has to overwrite the canary before the RIP or SFP!
Note: 20 bytes for name + 4 bytes for canary (32-bit architecture)
Computer Science 161
Stack Canaries: Efficiency
60
Computer Science 161
Subverting Stack Canaries
61
Computer Science 161
Subverting Stack Canaries: Leaking the Canary
62
Computer Science 161
Subverting Stack Canaries: Bypassing the Canary
63
Computer Science 161
Subverting Stack Canaries: Guessing the Canary
64
Computer Science 161
Subverting Stack Canaries: Guessing the Canary
65
Computer Science 161
Mitigation: Pointer Authentication
66
Textbook Chapter 4.10
Computer Science 161
Recall: Putting Together an Attack
We can defend against memory safety vulnerabilities by making each of these steps more difficult (or impossible)!
67
Computer Science 161
Reminder: 32-Bit and 64-Bit Processors
68
Computer Science 161
Pointer Authentication
69
Computer Science 161
Pointer Authentication: Properties of the PAC
70
Computer Science 161
Subverting Pointer Authentication
71
Computer Science 161
Defenses Against Pointer Reuse
72
Computer Science 161
Pointer Authentication on ARM
73
Computer Science 161
Mitigation: Address Space Layout Randomization (ASLR)
74
Textbook Chapter 4.11 & 4.12
Computer Science 161
Recall: Putting Together an Attack
We can defend against memory safety vulnerabilities by making each of these steps more difficult (or impossible)!
75
Computer Science 161
Recall: x86 Memory Layout
76
Higher addresses
Lower addresses
Stack |
|
Heap |
Data |
Code |
Grows upwards
In theory, x86 memory layout looks like this...
Grows downwards
Computer Science 161
Recall: x86 Memory Layout
77
Higher addresses
Lower addresses
Stack |
|
Heap |
Data |
Code |
Grows downwards
Grows upwards
In theory, x86 memory layout looks like this...
Higher addresses
Lower addresses
Unused |
Stack |
Unused |
Heap |
Unused |
Data |
Unused |
Code |
Unused |
...but in practice, it usually looks like this (mostly empty)!
Computer Science 161
Recall: x86 Memory Layout
78
Higher addresses
Lower addresses
|
Stack |
|
Heap |
|
Data |
|
Code |
|
Idea: Put each segment of memory in a different location each time the program is run
|
Heap |
|
Data |
|
Code |
|
Stack |
|
Computer Science 161
Address Space Layout Randomization
79
Computer Science 161
ASLR: Efficiency
80
Computer Science 161
Subverting ASLR
81
Computer Science 161
Relative Addresses
82
void vulnerable(char *dest) {
// Format string vulnerability
printf(dest);
}
int main(void) {
int secret = 42;� char buf[20];
fgets(buf, 20, stdin);
vulnerable(buf);
}
... | ... | ... | ... |
... | ... | ... | ... |
... | ... | ... | ... |
RIP of main | |||
SFP of main | |||
secret = 42 | |||
buf | |||
buf | |||
buf | |||
buf | |||
buf | |||
dest (arg to vulnerable) | |||
RIP of vulnerable | |||
SFP of vulnerable | |||
format (arg to printf) |
We know that the SFP is a pointer to the stack. How would you print the value of the SFP?
secret is 4 bytes below where the SFP points, so its address is 0xbfff0404!
Input:
'%x'
If the output is bfff0408 what is the address of secret?
Computer Science 161
Combining Mitigations
83
Textbook Chapter 4.13
Computer Science 161
Combining Mitigations
84
Computer Science 161
Combining Mitigations
85
Computer Science 161
Enabling Mitigations
86
Computer Science 161
Enabling Mitigations: CISCO
87
Computer Science 161
Enabling Mitigations: Internet of Things
Takeaway: Many (most?) IoT devices don’t enable basic mitigations
88
Qualys Security Blog | |
CVE-2021-3156: Heap-Based Buffer Overflow in Sudo (Baron Samedit) | |
Animesh Jain | January 26, 2021 |
The Qualys Research Team has discovered a heap overflow vulnerability in sudo, a near-ubiquitous utility available on major Unix-like operating systems. Any unprivileged user can gain root privileges on a vulnerable host using a default sudo configuration by exploiting this vulnerability. |
Computer Science 161
Summary: Memory Safety Mitigations
89
Computer Science 161
Summary: Memory Safety Mitigations
90
Computer Science 161
Summary: Memory Safety Mitigations
91
Computer Science 161