Siphashdos Appsec12 Slides
Siphashdos Appsec12 Slides
Martin
Independent SW engineer and security expert
Ruby core dev team member
http://www.martinbosslet.de @_emboss_
Hash-flooding DoS reloaded:
attacks and defenses
Denial-of-Service (DoS) attacks
d[12345]=0xc, hash(12345)=1
If the table is about as large as the
number of elements to be stored (=n),
insertion or lookup of n elements takes
O(n) operations on average
0 1 2
‘astring’: ‘foo’ 12345: 0xc
d[‘astring’]=‘foo’ , hash(‘astring’)=0
If the table is about as large as the
number of elements to be stored (=n),
insertion or lookup of n elements takes
O(n) operations on average
0 1 2
‘astring’: ‘foo’ 12345: 0xc (‘a’,’tuple’): 0
d[(‘a’,’tuple’)=0; hash((‘a’,’tuple’))=2
If the table is about as large as the
number of elements to be stored (=n),
insertion or lookup of n elements takes
O(n2) operations in the worst case
0 1 2
12345: 0xc
d[12345]=0xc, hash(12345)=1
If the table is about as large as the
number of elements to be stored (=n),
insertion or lookup of n elements takes
O(n2) operations in the worst case
0 1 2
12345: 0xc
‘astring’: ‘foo’
d[‘astring’]=‘foo’ , hash(‘astring’)=0
If the table is about as large as the
number of elements to be stored (=n),
insertion or lookup of n elements takes
O(n2) operations in the worst case
0 1 2
12345: 0xc
‘astring’: ‘foo’
d[(‘a’,’tuple’)=0; hash((‘a’,’tuple’))=2
Hash flooding:
Send to a server many inputs with a
same hash (a multicollision) so as to
enforce worst-case insert time
send 2MB of POST data consisting of
200.000 colliding 10B strings
CRuby, JRuby
MurmurHash3
“successor to MurmurHash2”
for (i=0;i<nblocks;i++) {
uint32_t k1 = getblock(blocks, i);
k1 *= 0xcc9e2d51 ;
k1 = ROTL32(k1 ,15);
k1 *= 0x1b873593;
h1 ^= k1;
h1 = ROTL32 ( h1 ,13);
h1 = h1 *5+0 xe6546b64;}
Differential cryptanalysis strategy
1/ introduce a difference in the state h1 via the input k1
2/ cancel this difference with a second well chosen difference
for (i=0;i<nblocks;i++) {
uint32_t k1 = getblock(blocks, i);
k1 *= 0xcc9e2d51 ;
k1 = ROTL32(k1 ,15);
k1 *= 0x1b873593;
h1 ^= k1;
h1 = ROTL32 ( h1 ,13);
h1 = h1 *5+0 xe6546b64;}
Differential cryptanalysis strategy
1/ introduce a difference in the state h1 via the input k1
2/ cancel this difference with a second well chosen difference
h1 ^= k1;
h1 = ROTL32 ( h1 ,13);
h1 = h1 *5+0 xe6546b64;}
Differential cryptanalysis strategy
1/ introduce a difference in the state h1 via the input k1
2/ cancel this difference with a second well chosen difference
h1 ^= k1;
h1 = ROTL32 ( h1 ,13);
h1 = h1 *5+0 xe6546b64;}
Differential cryptanalysis strategy
1/ introduce a difference in the state h1 via the input k1
2/ cancel this difference with a second well chosen difference
h1 ^= k1;
h1 = ROTL32 ( h1 ,13);
h1 = h1 *5+0 xe6546b64;}
Differential cryptanalysis strategy
1/ introduce a difference in the state h1 via the input k1
2/ cancel this difference with a second well chosen difference
32-bit
32-bit h1=f(X)=H
h1=X
M1^D1 M2^D2
32-bit
32-bit
h1=f(X^D3^D3)=H
h1=X^D3
Utils.parse_nested_query(qs)
end
def parse_nested_query(qs, d = nil)
params = KeySpaceConstrainedParams.new
end
return params.to_params_hash
end
def unescape(s, encoding = Encoding::UTF_8)
URI.decode_www_form_component(s, encoding)
end
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
end
/\A[^%]*(?:%\h\h[^%]*)*\z/
???
Catches invalid % encodings
(e.g. %ZV, %%1 instead of %2F)
def parse_nested_query(qs, d = nil)
params = KeySpaceConstrainedParams.new
end
return params.to_params_hash
end
def normalize_params(params, name, v = nil)
name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
k = $1 || ''
…
end
%r(\A[\[\]]*([^\[\]]+)\]*)
???
helps transform [[]] to []
idea:
pre-generate matching values
create random values
passing the regular expressions
that should do it, right?
Demo
def parse_nested_query(qs, d = nil)
params = KeySpaceConstrainedParams.new
end
return params.to_params_hash
end
class KeySpaceConstrainedParams
@params[key] = value
end
end
What now? Rails is safe?
Remember:
}
Tough nut to crack
What now? Java is safe?
String(char[] value)
public String(char value[]) {
}
No decoding!
Substitute byte[] operations
with equivalent operations
on char[]
Demo
Disclosure
Oracle (Java): Sep 11
CRuby, JRuby, Rubinius: Aug 30
Hash-flooding DoS reloaded:
attacks and defenses
SipHash: a fast short-input PRF
v0 = k0 ⊕ 736f6d6570736575
v1 = k1 ⊕ 646f72616e646f6d
v2 = k0 ⊕ 6c7967656e657261
v3 = k1 ⊕ 7465646279746573
SipHash initialization
256-bit state v0 v1 v2 v3
128-bit key k0 k1
v0 = k0 ⊕ “somepseu”
v1 = k1 ⊕ “dorandom”
v2 = k0 ⊕ “lygenera”
v3 = k1 ⊕ “tedbytes”
SipHash compression
Message parsed as 64-bit words m0, m1, …
v3 ⊕= m0
c iterations of SipRound
v0 ⊕= m0
SipHash compression
Message parsed as 64-bit words m0, m1, …
v3 ⊕= m1
c iterations of SipRound
v0 ⊕= m1
SipHash compression
Message parsed as 64-bit words m0, m1, …
v3 ⊕= m2
c iterations of SipRound
v0 ⊕= m2
SipHash compression
Message parsed as 64-bit words m0, m1, …
Etc.
SipRound
SipHash finalization
v2 ⊕= 255
d iterations of SipRound
Return v0 ⊕ v1 ⊕ v2 ⊕ v3
SipHash-2-4 hashing 15 bytes
Family SipHash-c-d
Fast proposal: SipHash-2-4
Conservative proposal: SipHash-4-8
http://www.opendns.com/ http://www.rust-lang.org/
Soon?
Take home message
THANK YOU!