


Analyse du principe de vulnérabilité d'exécution de code à distance causée par la désérialisation Java
est principalement composé de 3 parties :
1. Le mécanisme d'introspection de Java
2.
3. Exécution de code à distance en JavaRéflexion et exécution de code en Java
Regardons d'abord un exemple simple, utilisant Java pour appeler le programme de la calculatrice :import java.io.IOException; import java.lang.Runtime; public class Test { public static void main(String[] args) { Runtime env = Runtime.getRuntime(); String cmd = "calc.exe"; try { env.exec(cmd); } catch (IOException e) { e.printStackTrace(); } } }
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { try { Class<?> cls = Class.forName("java.lang.Runtime"); String cmd = "calc.exe"; try { Method getRuntime = cls.getMethod("getRuntime", new Class[] {}); Object runtime = getRuntime.invoke(null); Method exec = cls.getMethod("exec", String.class); exec.invoke(runtime, cmd); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (ClassNotFoundException e1) { e1.printStackTrace(); } } }
Method getRuntime = cls.getMethod("getRuntime", new Class[] {});
Traitement de sérialisation Java
Pour le traitement de sérialisation en Java, la classe correspondante doit implémenter l'interface Serialisable, par exemple :import java.io.Serializable; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class Reader implements Serializable { private static final long serialVersionUID = 10L; private void readObject(ObjectInputStream stream) { System.out.println("foo...bar..."); } public static byte[] serialize(Object obj) { //序列化对象 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream output = null; try { output = new ObjectOutputStream(out); output.writeObject(obj); output.flush(); output.close(); } catch (IOException e) { e.printStackTrace(); } return out.toByteArray(); } public static Object deserialize(byte[] bytes) { //反序列化处理 ByteArrayInputStream in = new ByteArrayInputStream(bytes); ObjectInputStream input; Object obj = null; try { input = new ObjectInputStream(in); obj = input.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return obj; } public static void main(String[] args) { byte[] data = serialize(new Reader()); //对类自身进行序列化 Object response = deserialize(data); System.out.println(response); } }
Communication et transport à distance Java
Afin de réaliser la transmission à distance et l'exécution de code à distance du code Java, nous pouvons utiliser RMI, RPC et d'autres méthodes. Ici, nous utilisons Socket pour le traitement côté serveur et côté client. Le premier est le côté serveur, qui écoute le port local 8888. Son code est :import java.net.Socket; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; public class Server { public static void main(String[] args) throws ClassNotFoundException { int port = 8888; try { ServerSocket server = new ServerSocket(port); System.out.println("Server is waiting for connect"); Socket socket = server.accept(); InputStream input = socket.getInputStream(); byte[] bytes = new byte[1024]; int length = 0; while((length=input.read(bytes))!=-1) { String out = new String(bytes, 0, length, "UTF-8"); System.out.println(out); } input.close(); socket.close(); server.close(); } catch (IOException e) { e.printStackTrace(); } } }
import java.io.IOException; import java.net.Socket; import java.io.OutputStream; public class Client { public static void main(String[] args) { String host = "192.168.1.108"; int port = 8888; try { Socket socket = new Socket(host, port); OutputStream output = socket.getOutputStream(); String message = "Hello,Java Socket Server"; output.write(message.getBytes("UTF-8")); output.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
Server is waiting for connect Hello,Java Socket Server
Java反序列化与远程代码执行
下面我们通过Java反序列化的问题来实现远程代码执行,为了实现远程代码执行,我们首先在Reader类中添加1个malicious方法,其代码为:
public Object malicious() throws IOException { Runtime.getRuntime().exec("calc.exe"); System.out.println("Hacked the Server..."); return this; }
在该方法中我们使用之前的介绍调用宿主机器上的计算器程序,然后输出1个相关信息,最后返回当前类。
之后是对服务器端的代码进行如下的修改:
while((length=input.read(bytes))!=-1) { Reader obj = (Reader) Reader.deserialize(bytes); obj.malicious(); }
我们在接收到客户端对应的字符串后对其进行反序列处理,之后调用某个指定的函数,从而实现远程代码的执行。而在客户端,我们需要对其进行序列化处理:
Reader reader = new Reader(); byte[] bytes = Reader.serialize(reader); String message = new String(bytes); output.write(message.getBytes());
下面我们在宿主机器上运行服务器端程序,之后在本地机器上运行客户端程序,当客户端程序执行时,可以看到类似如下的结果:
可以看到,我们成功的在宿主机器上执行了对应的命令执行。
总结
为了实现通过Java的反序列问题来实现远程代码执行的漏洞,我们需要编写1个有恶意代码注入的序列化类。之后在客户端将恶意代码序列化后发送给服务器端,而服务器端需要调用我们期望的方法,从而触发远程代码执行。
为了避免服务器端进行一些安全处理,我们可以采用反射的方式来逃逸其处理。
这里只是1个简化的过程,更加实用的过程可以参考Apache Common Collections的问题导致的Weblogic漏洞CVE-2015-4852及Jboss的漏洞CVE-2015-7501。
推荐相关文章教程:web安全教程
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide de la racine carrée en Java. Nous discutons ici du fonctionnement de Square Root en Java avec un exemple et son implémentation de code respectivement.

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Guide du générateur de nombres aléatoires en Java. Nous discutons ici des fonctions en Java avec des exemples et de deux générateurs différents avec d'autres exemples.

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.
