More Related Content Similar to Опасная сериализация / Иван Юшкевич (Digital Security) (20) Опасная сериализация / Иван Юшкевич (Digital Security)3. © Digital Security 3
Опасная сериализация
Agenda
• Что такое сериализация
Зачем, для чего, почему
• Уязвимости (calc.exe time)
• Как искать
• Как защититься
• …
• Profit(?)
4. © Digital Security 4
Опасная сериализация
Сериализация
Сериализация - это процесс сохранения состояния объекта в последовательность байт.
Десериализация - это процесс восстановления объекта, из этих байт. Обратный процесс
сериализация(!)
Формат представления:
Бинарный: Java Serialization, Ruby Marshal, Protobuf, Thrift, Avro, MS-NRBF, Android
Binder/Parcel, IIOP
Смешанный: PHP Serialization, Python pickle, Binary XML/JSON
«Читаемый»: XML, JSON, YAML
5. © Digital Security 5
Опасная сериализация
Сериализация
• Протоколы передачи данных:
RMI (Remote Method Invocation)
JMX (Java Management Extension)
JMS (Java Messaging System)
• Обмен «объектами» между двумя приложениями
• Кэширование
• Cookie, API-токены
• Сохранение и восстановление объекта
8. © Digital Security 8
Опасная сериализация
Сериализация
• readObject()
• readResolve()
• validateObject()
• readObjectNoData()
• readExternal()
• finalize()
9. © Digital Security 9
Опасная сериализация
Сериализация
public class Gadget0
{
public String command;
protected void readObject(java.io.ObjectInputStream
stream) throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
Runtime.getRuntime().exec(command);
}
}
10. © Digital Security 10
Опасная сериализация
Сериализация
public class Gadget0
{
public String command;
protected void readObject(java.io.ObjectInputStream
stream) throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
Runtime.getRuntime().exec(command);
}
}
12. © Digital Security 12
Опасная сериализация
Как это сделано?
public static void main(String[] args) {
User user = new User();
user.name = "steph"; user.isAdmin=false;
FileOutputStream fos = new
FileOutputStream("object.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(user); os.close();
FileInputStream fis = new FileInputStream("object.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
User objectFromDisk = (User)ois.readObject();
System.out.println(objectFromDisk.name); ois.close();
}
public class User implements Serializable{
public String name;
public boolean isAdmin;
public String picture;
public User() {
}
}
13. © Digital Security 13
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
14. © Digital Security 14
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
00 05: STREAM_VERSION. – версия
15. © Digital Security 15
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
00 05: STREAM_VERSION. – версия
0x73: TC_OBJECT. – новый объект
16. © Digital Security 16
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
00 05: STREAM_VERSION. – версия
0x73: TC_OBJECT. – новый объект
0x72: TC_CLASSDESC. Обозначение нового класса.
17. © Digital Security 17
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
00 05: STREAM_VERSION. – версия
0x73: TC_OBJECT. – новый объект
0x72: TC_CLASSDESC. Обозначение нового класса.
00 08 – длина имени класса
18. © Digital Security 18
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
00 05: STREAM_VERSION. – версия
0x73: TC_OBJECT. – новый объект
0x72: TC_CLASSDESC. Обозначение нового класса.
00 08 – длина имени класса
Имя класса
UID класса
19. © Digital Security 19
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
00 05: STREAM_VERSION. – версия
0x73: TC_OBJECT. – новый объект
0x72: TC_CLASSDESC. Обозначение нового класса.
00 08 – длина имени класса
Имя класса
UID класса
02 – поддерживает сериализацию
00 03 – количество полей
20. © Digital Security 20
Опасная сериализация
Как это сделано?
AC ED: STREAM_MAGIC – указание , что это сериализованные данные
00 05: STREAM_VERSION. – версия
0x73: TC_OBJECT. – новый объект
0x72: TC_CLASSDESC. Обозначение нового класса.
00 08 – длина имени класса
Имя класса
UID класса
02 – поддерживает сериализацию
00 03 – количество полей
5A – тип поля
00 07 - Длина имени поля
22. © Digital Security 22
Опасная сериализация
Уязвимости
1) Нарушение логики работы программы
2) Ошибки связанные с валидацией пользовательских данных
3) RCE
• Даже когда её не ждешь…
А все почему?
Данные приходят из НЕ ДОВЕРЕННОГО источника.
23. © Digital Security 23
Опасная сериализация
Уязвимости
Date Type Product Researcher(s)
Apr 2005 DOS JRE Marc Schönefeld
Aug 2008 Applet->RCE JRE Sami Koivu
Apr 2010 Applet->RCE JRE Sami Koivu
Mar 2010 DOS Sun Java Web Console Luca Carettoni
Sept 2011 RCE Spring Framework Wouter Coekaerts
Oct 2012 RCE IBM Cognos BI Pierre Ernst
Feb 2013 File Write->RCE Apache OpenJPA Pierre Ernst
Mar 2013 File Write->RCE Apache Tomcat Pierre Ernst
July 2015 RCE Apache Groovy "cpnrodzc7"
Aug 2015 Buffer Overflow->RCE Android Or Peles & Roee Hay
Nov 2015 RCE Apache Commons Collections Chris Frohoff & Gabriel Lawrence
Nov 2015 DOS JRE Wouter Coekaerts
24. © Digital Security 24
Опасная сериализация
Уязвимости
Date Type Product Researcher(s)
Apr 2005 DOS JRE Marc Schönefeld
Aug 2008 Applet->RCE JRE Sami Koivu
Apr 2010 Applet->RCE JRE Sami Koivu
Mar 2010 DOS Sun Java Web Console Luca Carettoni
Sept 2011 RCE Spring Framework Wouter Coekaerts
Oct 2012 RCE IBM Cognos BI Pierre Ernst
Feb 2013 File Write->RCE Apache OpenJPA Pierre Ernst
Mar 2013 File Write->RCE Apache Tomcat Pierre Ernst
July 2015 RCE Apache Groovy "cpnrodzc7"
Aug 2015 Buffer Overflow->RCE Android Or Peles & Roee Hay
Nov 2015 RCE Apache Commons Collections Chris Frohoff & Gabriel Lawrence
Nov 2015 DOS JRE Wouter Coekaerts
25. © Digital Security 25
Опасная сериализация
Почему так?
Может ввести в заблуждение из-за
необычного формата:
• Хранение и передача данных - безопасны
• Бинарный формат непонятен, сложно
подделать
• Сериализация безопасна
Это всего лишь формат представления
данных
26. © Digital Security 26
Опасная сериализация
Пример
Cookie: user=base64(serialized(User.class))
27. © Digital Security 27
Опасная сериализация
Пример
Cookie: user=base64(serialized(User.class))
31. © Digital Security 31
Опасная сериализация
IRL
1) Cookie подписывается с помощью md5, по следующей схеме md5(cookie.key)
2) Шифруется с помощью AES
3) Если AES не доступен, шифруется с помощью XOR(!)
https://www.dionach.com/blog/codeigniter-session-decoding-
vulnerability
33. © Digital Security 33
Опасная сериализация
Untrusted input
USER
Permissions
UserInfo
Statistics
Name
Surname
Email
Type
Picture
String path=“/var/www/”
byte[] getPicture()
{
File file = new File(path, picture);
} return Files.readAllBytes(file.getPath());
Query =“select * from usersPermissions
where type=“+userType;
34. © Digital Security 34
Опасная сериализация
Untrusted input
USER
Permissions
UserInfo
Statistics
Name
Surname
Email
Type
Picture
String path=“/var/www/”
byte[] getPicture()
{
File file = new File(path, picture);
} return Files.readAllBytes(file.getPath());
Query =“select * from usersPermissions
where type=“+userType;
35. © Digital Security 35
Опасная сериализация
Untrusted input
USER
Permissions
UserInfo
Statistics
Name
Surname
Email
Type
Picture
String path=“/var/www/”
byte[] getPicture()
{
File file = new File(path, picture);
} return Files.readAllBytes(file.getPath());
Query =“select * from usersPermissions
where type=“+userType;
36. © Digital Security 36
Опасная сериализация
Untrusted input
USER
Permissions
UserInfo
Statistics
Name
Surname
Email
Type
Picture
String path=“/var/www/”
byte[] getPicture()
{
File file = new File(path, picture);
} return Files.readAllBytes(file.getPath());
Query =“select * from usersPermissions
where type=“+userType;
37. © Digital Security 37
Опасная сериализация
Untrusted input
USER
Permissions
UserInfo
Statistics
Name
Surname
Email
Type
Picture
String path=“/var/www/”
byte[] getPicture()
{
File file = new File(path, picture);
} return Files.readAllBytes(file.getPath());
Query =“select * from usersPermissions
where type=“+userType;
38. © Digital Security 38
Опасная сериализация
Untrusted input
USER
Permissions
UserInfo
Statistics
Name
Surname
Email
Type
Picture
String path=“/var/www/”
byte[] getPicture()
{
File file = new File(path, picture);
} return Files.readAllBytes(file.getPath());
Query =“select * from usersPermissions
where type=“+userType;
39. © Digital Security 39
Опасная сериализация
Untrusted input
Необходимо контролировать и обрабатывать те
данные которые пришли от пользователя!
Они получены из не доверенного источника.
Cериализация не поможет вам справиться с SQL/XSS
И т.д.
42. © Digital Security 42
Опасная сериализация
Gadget
ObjectInputStream
readObject()
defaultReadObject()
43. © Digital Security 43
Опасная сериализация
Gadget
ObjectInputStream
readObject()
defaultReadObject()
CacheManager
readObject()
44. © Digital Security 44
Опасная сериализация
Gadget
ObjectInputStream
readObject()
defaultReadObject()
CacheManager
readObject()
45. © Digital Security 45
Опасная сериализация
Gadget
ObjectInputStream
readObject()
defaultReadObject()
CacheManager
readObject()
46. © Digital Security 46
Опасная сериализация
Gadget
ObjectInputStream
readObject()
defaultReadObject()
CacheManager
readObject() CommandTask
run()
47. © Digital Security 47
Опасная сериализация
Gadget
ObjectInputStream
readObject()
defaultReadObject()
CacheManager
readObject() CommandTask
run()
Runtime
exec()
“calc.exe”
48. © Digital Security 48
Опасная сериализация
Gadget
ObjectInputStream
readObject()
defaultReadObject()
CacheManager
readObject() CommandTask
run()
Runtime
exec()
“calc.exe”
51. © Digital Security 51
Опасная сериализация
YaS
public class Gadget1 {
public Map map;
public String key;
protected void
readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
String foo = (String) map.get(key);
}
}
52. © Digital Security 52
Опасная сериализация
YaS
public class Handler0 implements InvocationHandler, Serializable
{
Object invoke(Object proxy, Method method, Object[] args)
{
Runtime.getRuntime().exec(args[0]);
}
}
54. © Digital Security 54
Опасная сериализация
YaS
Java-машина во время исполнения может сгенерировать прокси-класс для данного класса
A, т.е. такой класс, который реализует все интерфейсы класса A, но заменяет вызов всех
методов этих интерфейсов на вызов метода InvocationHandler#invoke, где
InvocationHandler - интерфейс JVM, для которого можно определять свои реализации.
Handler0 h = new Handler0();
Map proxy = (Map) Proxy.newProxyInstance(classLoader, new Class<?>[] { Map.class }, h);
Gadget1 g = new Gadget1();
g.map = proxy;
g.key = “<MALICIOUS COMMAND>”;
byte[] bytes = serialize(g);
55. © Digital Security 55
Опасная сериализация
YaS
readObject()
Handler0 h = new Handler0();
Map proxy = (Map) Proxy.newProxyInstance(classLoader, new Class<?>[] { Map.class }, h);
Gadget1 g = new Gadget1();
g.map = proxy;
g.key = “<MALICIOUS COMMAND>”;
byte[] bytes = serialize(g);
56. © Digital Security 56
Опасная сериализация
YaS
readObject()
Handler0 h = new Handler0();
Map proxy = (Map) Proxy.newProxyInstance(classLoader, new Class<?>[] { Map.class }, h);
Gadget1 g = new Gadget1();
g.map = proxy;
g.key = “<MALICIOUS COMMAND>”;
byte[] bytes = serialize(g);
map.get() Proxy
57. © Digital Security 57
Опасная сериализация
YaS
readObject()
Handler0 h = new Handler0();
Map proxy = (Map) Proxy.newProxyInstance(classLoader, new Class<?>[] { Map.class }, h);
Gadget1 g = new Gadget1();
g.map = proxy;
g.key = “<MALICIOUS COMMAND>”;
byte[] bytes = serialize(g);
map.get() Proxy
Gadget0
58. © Digital Security 58
Опасная сериализация
YaS
readObject()
Handler0 h = new Handler0();
Map proxy = (Map) Proxy.newProxyInstance(classLoader, new Class<?>[] { Map.class }, h);
Gadget1 g = new Gadget1();
g.map = proxy;
g.key = “<MALICIOUS COMMAND>”;
byte[] bytes = serialize(g);
map.get() Proxy
Gadget0 invoke exec
63. © Digital Security 63
Опасная сериализация
Библиотеки
• Большое количество
библиотек
• Сложно обновлять
65. © Digital Security 65
Опасная сериализация
PHP
Basic types:
• <type specifier>:<data>;
Arrays:
• a:<count>:{<key>:<value>,…}
Two ways for Objects:
• “O” just like array
• Custom defined by developer
66. © Digital Security 66
Опасная сериализация
PHP
0000000: 4f3a 343a 2255 7365 7222 3a33 3a7b 733a O:4:"User":3:{s:
0000010: 373a 2269 7361 646d 696e 223b 623a 303b 7:"isadmin";b:0;
0000020: 733a 343a 2270 6c61 6e22 3b73 3a31 393a s:4:"plan";s:19:
0000030: 222f 7661 722f 7777 772f 6e6f 706c 616e "/var/www/noplan
0000040: 2e74 7874 223b 733a 383a 2275 7365 726e .txt";s:8:"usern
0000050: 616d 6522 3b73 3a34 3a22 6761 6265 223b ame";s:4:"gabe";
0000060: 7d0a }.
67. © Digital Security 67
Опасная сериализация
PHP
0000000: 4f3a 343a 2255 7365 7222 3a33 3a7b 733a O:4:"User":3:{s:
0000010: 373a 2269 7361 646d 696e 223b 623a 303b 7:"isadmin";b:0;
0000020: 733a 343a 2270 6c61 6e22 3b73 3a31 393a s:4:"plan";s:19:
0000030: 222f 7661 722f 7777 772f 6e6f 706c 616e "/var/www/noplan
0000040: 2e74 7874 223b 733a 383a 2275 7365 726e .txt";s:8:"usern
0000050: 616d 6522 3b73 3a34 3a22 6761 6265 223b ame";s:4:"gabe";
0000060: 7d0a }.
68. © Digital Security 68
Опасная сериализация
PHP
0000000: 4f3a 343a 2255 7365 7222 3a33 3a7b 733a O:4:"User":3:{s:
0000010: 373a 2269 7361 646d 696e 223b 623a 303b 7:"isadmin";b:0;
0000020: 733a 343a 2270 6c61 6e22 3b73 3a31 393a s:4:"plan";s:19:
0000030: 222f 7661 722f 7777 772f 6e6f 706c 616e "/var/www/noplan
0000040: 2e74 7874 223b 733a 383a 2275 7365 726e .txt";s:8:"usern
0000050: 616d 6522 3b73 3a34 3a22 6761 6265 223b ame";s:4:"gabe";
0000060: 7d0a }.
69. © Digital Security 69
Опасная сериализация
PHP
0000000: 4f3a 343a 2255 7365 7222 3a33 3a7b 733a O:4:"User":3:{s:
0000010: 373a 2269 7361 646d 696e 223b 623a 303b 7:"isadmin";b:0;
0000020: 733a 343a 2270 6c61 6e22 3b73 3a31 393a s:4:"plan";s:19:
0000030: 222f 7661 722f 7777 772f 6e6f 706c 616e "/var/www/noplan
0000040: 2e74 7874 223b 733a 383a 2275 7365 726e .txt";s:8:"usern
0000050: 616d 6522 3b73 3a34 3a22 6761 6265 223b ame";s:4:"gabe";
0000060: 7d0a }.
70. © Digital Security 70
Опасная сериализация
PHP
0000000: 4f3a 343a 2255 7365 7222 3a33 3a7b 733a O:4:"User":3:{s:
0000010: 373a 2269 7361 646d 696e 223b 623a 303b 7:"isadmin";b:0;
0000020: 733a 343a 2270 6c61 6e22 3b73 3a31 393a s:4:"plan";s:19:
0000030: 222f 7661 722f 7777 772f 6e6f 706c 616e "/var/www/noplan
0000040: 2e74 7874 223b 733a 383a 2275 7365 726e .txt";s:8:"usern
0000050: 616d 6522 3b73 3a34 3a22 6761 6265 223b ame";s:4:"gabe";
0000060: 7d0a }.
76. © Digital Security 76
Опасная сериализация
Как искать?
В коде
• ObjectInputStream.readObject
• ObjectInputStream.readUnshared
Find Security Bugs
Serianalyzer
Паттерны:
• Magic bytes 'ac ed 00 05' bytes
• 'rO0' for Base64
• 'application/x-java-serialized-object' for Content-Type header
79. © Digital Security 79
Опасная сериализация
Sandbox
Sandbox – все можно контролировать
• File R/W access
• Process creation
• Network access
• …
Недостатки
«Сложна, сложна, непонятно» - что
есть легитимное действие
• Были найдены уязвимости и
возможности обхода
80. © Digital Security 80
Опасная сериализация
Проверка имен классов
Проверка имен классов перед десерилизацией
• SerialKiller
• contrast-rO0
Можно использовать готовый парсер или написать свой(!)
81. © Digital Security 81
Опасная сериализация
Проверка имен классов
public class LookAheadObjectInputStream extends
ObjectInputStream {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) {
if ( ! desc.getName().equals(“Application.User”) ) {
throw new InvalidClassException(
"Unauthorized deserialization attempt",
desc.getName());
}
return super.resolveClass(desc);
}
}
Получить имя класса
Сравнить с каким-то значением
Profit?
82. © Digital Security 82
Опасная сериализация
План
Black List
• method1
• method2
Magic methods?
Class x.y.z
accept
reject
blacklisted methods?
yes yes
no no
Called methods
• methodA
• methodB
Analyze
Magic method
83. © Digital Security 83
Опасная сериализация
Whitelist vs Blacklist
Не использовать десеарилизацию данных из не доверенных
источников(!!!!)
Whitelist
Определить все классы, которые могут быть десериализованными
BlackList
Определить список классов, которые нельзя десериализовать
• Возможно обойти
Editor's Notes Теория. Прочитать.
Сериализация - это процесс сохранения состояния объекта в последовательность байт.
Десериализация - это процесс восстановления объекта, из этих байт. Обратный процесс сериализация(!)
Сериализация объекта это способность объекта сохранять полную копию его и любых других объектов на которые он ссылается, используя поток вывода(например, во внешний файл). Таким образом, объект может быть воссоздан из сериализованной(сохраненной) копии немного позже, когда это потребуется.
В сегодняшнем мире типичное промышленное приложение будет иметь множество компонентов и будет распространено через различные системы и сети. Если двум компонентам Java необходимо общаться друг с другом, то им необходим механизм для обмена данными. Есть несколько способов реализовать этот механизм. Первый способ это разработать собственный протокол и передать объект. В Java всё представлено в виде объектов; Это означает, что получатель должен знать протокол, используемый отправителем для воссоздания объекта, что усложняет разработку сторонних компонентов. Следовательно, должен быть универсальный и эффективный протокол передачи объектов между компонентами. Сериализация создана для этого, и компоненты Java используют этот протокол для передачи объектов.
Процесс десиреализации начинается с момента когда объект считывается с ObjectInputStream, в который поступает данные, которые пришли от атакующего. Процесс начинает считывать сериализоанные данные и начинает цикличный процесс, в котором имя класса, который будет десиарилизован передается в метод ObjectInputStream.resolveClass(). Это необходимо для того, чтобы получить информацию и метаданные о классе. Это важный этап, поскольку на нем проверяется, что существует данный класс в classpath или нет. Стоит отметить, что уже на этом этапе, можно проверять класс, который будет сериализован с точки зрения безопасносити и можно еще все остановить.
После того, как класс загружен ObjectInputStream, проверяет, содержит-ли он такие функции как readObject() и/или readResolve – если да, то вызывает их. readObject служит для того , чтобы устновить значения полей класса. В некоторых случаях могут вызываться и другие функции, такие как validateObject и другие.
Этот процесс будет повторяться до самого конца, когда сам объект и все вложенные в него объекты не будут полностью десеарилизованны.
Важно отметить, что перед тем , как быть скастованным до определенного объекта, некоторые методы будут вызваны, такие как readObject, readObjectNoData, readResolve и validateObject у десиарилизрованного класса. То есть если атакующий, сможешь каким-либо образом проэксплуатировать эти функции, то он сможет получить возможность выполнения произврольного кода.
Иными словами, те действия, которые будут произходить в этим функциях с данными атакующего и крайне важны
Пытаясь найти необходимые функции и классы, атакующий может быть не только ограничен данным методами. Он может использовать перехват вызовов, и с одной стороны метод readobject может передать управление на c.
JDK и другие библиотеки, позволяет разработчикам писать проки классы , которые реализуют или расширяют определенный набор классов или интерфейсов. Любой метод который вызывается в этих проксях перехватывается и передается в invocation handler для выполнения дополнительного кода.
И класс invocation handler. Как видно, если бы мы попытались его сериализовать стырм путем, то него нет методов и необходимы параметоров, которые можно было бы перезаписать
Сначала атакующий создает экземпляр класса Handler0
Создает прокси на объект map, где в качестве F pfntv