JAVA安全入门之反射

反射

对于反射这个概念来说,直白的讲就是:

对象可以通过反射获取他的类,类可以通过反射拿到所有⽅法(包括私有),拿到的⽅法可以调⽤

而众所周知 JAVA 是一门静态语言,我们通过反射就可以达到动态的语言的特性。
我们可以类比一下我们的老朋友 PHP ,对于 PHP 来说,一个简单的 webshell 可以完成各种操作,而对于 JAVA 来说,我们就可以用 反射 达到一些动态的特性。
比如以下代码:

public void execute(String className, String methodName) throws Exception {Class clazz = Class.forName(className);clazz.getMethod(methodName).invoke(clazz.newInstance());
}

以上代码,有几个反射中重要的方法:

  • 获取类的⽅法: forName
  • 实例化类对象的方法:newInstance
  • 获取函数的方法:getMethod
  • 执行函数的方法:invoke

但是 forName 并不是获取类的唯一方法,对于反射来说,还有两种方法来获取类:
1、如果已经有了一个类的实例,我们只需要用 obj.getClass() 来获取他的类。
2、如果你知道某个类的名字,想获取到这个类,就可以使⽤ forName 来获取。
当然除了以上反射的方法,还有一种方法:
如果你已经加载了某个类,只是想获取到它的 java.lang.Class 对象,那么就直接拿它的 class 属性即可。

如果我们看一下 forName 会发现他有两个重载方法:

public static Class<?> forName(String className)  throws ClassNotFoundException {  Class<?> caller = Reflection.getCallerClass();  return forName0(className, true, ClassLoader.getClassLoader(caller), caller);  
}
public static Class<?> forName(String name, boolean initialize,  ClassLoader loader)  throws ClassNotFoundException  
{  Class<?> caller = null;  SecurityManager sm = System.getSecurityManager();  if (sm != null) {  // Reflective call to get caller class is only needed if a security manager  // is present.  Avoid the overhead of making this call otherwise.        caller = Reflection.getCallerClass();  if (sun.misc.VM.isSystemDomainLoader(loader)) {  ClassLoader ccl = ClassLoader.getClassLoader(caller);  if (!sun.misc.VM.isSystemDomainLoader(ccl)) {  sm.checkPermission(  SecurityConstants.GET_CLASSLOADER_PERMISSION);  }  }  }  return forName0(name, initialize, loader, caller);  
}

对比着来看,会发现第一个比第二个少了个点东西:

public static Class<?> forName(String className)public static Class<?> forName(String name, boolean initialize,  ClassLoader loader)

对于第二种:

  • name : 类名
  • initialize : 是否初始化
  • ClassLoader : 类的加载器

ClassLoader 看到这个名字就能看出来,他就是一个类的 加载器
Java 默认的 ClassLoader 是根据类的名字(类的全称,例如 : java.lang.runtime)加载类。

反射的主要目的就是不通过 import 来导入类,这一点是攻击者想要的,而 forName 就可以做到这一点。

Java 中可以在类中编写内部类,在编译的时候会产生两个类文件如下:

public class main {  public static void main(String[] args) throws Exception {  System.out.println("Hello World!");  }  class test1{  public String test =  "hello";  }  
}

会生成如下文件:

├── main$test1.class
└── main.class

而你想要通过反射拿到 test1 类的时候可以通过 Class.forName("main$test1") 的方式来加载内部类,从而一系列操作。

说了这么多,我们举个小例子:

public static void main(String[] args) throws Exception {  Class c = Class.forName("java.lang.Runtime");  c.getMethod("exec", String.class).invoke(c.newInstance(), "open -a Calculator ");  
}

发现会报错对吧!

Exception in thread "main" java.lang.IllegalAccessException: Class main can not access a member of class java.lang.Runtime with modifiers "private"

这里很好理解,c.newInstance() 的作用就是调用这个类的无参构造函数所以存在以下情况就会失败:

  • 加载的类没有无参构造函数
  • 加载的类的构造函数是私有的
    我们可以看一下 newInstance() 的代码:
if (cachedConstructor == null) {  if (this == Class.class) {  throw new IllegalAccessException(  "Can not call newInstance() on the Class for java.lang.Class"  );  }

这里就很明确了 if (cachedConstructor == null) 如果没有构造函数就抛出一个异常。

// Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers();  
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {  Class<?> caller = Reflection.getCallerClass();  if (newInstanceCallerCache != caller) {  Reflection.ensureMemberAccess(caller, this, null, modifiers);  newInstanceCallerCache = caller;  }  
}

跟进 ensureMemberAccess 方法:

public static void ensureMemberAccess(Class<?> var0, Class<?> var1, Object var2, int var3) throws IllegalAccessException {  if (var0 != null && var1 != null) {  if (!verifyMemberAccess(var0, var1, var2, var3)) {  throw new IllegalAccessException("Class " + var0.getName() + " can not access a member of class " + var1.getName() + " with modifiers \"" + Modifier.toString(var3) + "\"");  }  } else {  throw new InternalError();  }  
}

可以看到在这里抛出了异常,在此先不细说中间是怎么校验的。

所以我们可以这样来改造:

public static void main(String[] args) throws Exception {  Class c = Class.forName("java.lang.Runtime");  c.getMethod("exec", String.class).invoke(c.getMethod("getRuntime").invoke(c), "open -a Calculator");  
}

这里有两个方法需要说一下 getMethodinvokegetMethod 的作用是通过反射获取一个类的某个特定的公有方法,然后利用这个方式来获取 Runtime.exec 方法。

invoke 大家应该很熟悉,我们可以看看他的源码:

public Object invoke(Object obj, Object... args)  throws IllegalAccessException, IllegalArgumentException,  InvocationTargetException  
{  if (!override) {  if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {  Class<?> caller = Reflection.getCallerClass();  checkAccess(caller, clazz, obj, modifiers);  }  }  MethodAccessor ma = methodAccessor;             // read volatile  if (ma == null) {  ma = acquireMethodAccessor();  }  return ma.invoke(obj, args);  
}

这里做了一些操作,可以自己跟一下,这里就不过多叙述了。

invoke 的作用是执行方法,它的第一个参数是:

  • 如果这个方法是一个普通方法,那么第一个参数是类对象
  • 如果这个方法是一个静态方法,那么第一个参数是类
    正常执行方法是 [1].method([2], [3], [4]...),在反射里就是这样的 method.invoke([1], [2], [3], [4]...)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/125084.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

322. 零钱兑换 279.完全平方数

322. 零钱兑换 题目&#xff1a; 给一个不同数额硬币的数组和一个目标金额&#xff0c;硬币可取无限次&#xff0c;求用硬币达到总金额的最小硬币数量。&#xff08;求不同组合数/排列数&#xff0c;但是硬币数量最小&#xff09; 思路&#xff1a; 求硬币数量最小&#x…

数据中台租户概念

数据中台是一种将数据作为核心资源进行管理和共享的架构模式。它通过集中管理组织内部各个业务系统产生的数据&#xff0c;并提供一套通用的数据服务和工具&#xff0c;以满足不同业务需求的数据访问、整合和分析等需求。 在数据中台中引入了租户的概念&#xff0c;租户是指数…

Unity 粒子特效-第三集-星星闪烁特效

一、特效预览 二、制作原理 星星素材资源 链接&#xff1a;https://pan.baidu.com/s/17D-9sC-ErtqmUxl81Ln1Mw?pwdndm9 提取码&#xff1a;ndm9 1.素材介绍 仔细看&#xff0c;我们的粒子贴图是&#xff08;如下&#xff09;&#xff0c;一颗星星 2.步骤介绍 1.星星动画的…

【如何写论文】硕博学位论文的结构框架、过程与大纲分析

硕士论文可以说是毕业前最重要的一部分&#xff0c;也可以说是展示和检验你3年研究生学习的成果的一个考试。硕士论文答辩和检验合格&#xff0c;才能够顺利拿到毕业生和学位证&#xff0c;可见其重要性。 目录 一、基础框架1.1、摘要&#xff08;Abstract&#xff09;1.2、绪论…

MySQL WITH AS及递归查询

MySQL WITH AS及递归查询 WITH AS 官网&#xff1a;WITH 是 SQL 中的一个关键字&#xff0c;用于创建临时表达式&#xff08;也称为 Common Table Expression&#xff0c;CTE&#xff09;&#xff0c;它允许你在一个查询中临时定义一个表达式&#xff0c;然后在后续的查询中引…

【多线程面试题十五】、synchronized可以修饰静态方法和静态代码块吗?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;synchronized可以修饰静…

灯串上亚马逊加拿大合规标准CSA认证如何办理?

灯串 灯串和配件都是插头连接的便携式、临时性商品&#xff0c;最大额定输入电压为 120 伏。 本政策适用于季节性照明、装饰性灯具以及灯串。 亚马逊灯串政策 根据亚马逊的要求&#xff0c;所有季节性和装饰性灯串均应经过检测&#xff0c;并且遵守下列法规、标准和要求&…

AUTOSAR CAN协议栈架构总览介绍

Classic AUTOSAR层级架构简介 如下图是Classic AUTOSAR层级架构图,每个层主要功能如下 微控制器抽象层:使上层软件和微处理器型号无关,包含MCU中内部外设的驱动以及MCU内存映射的外部设备的驱动ECU抽象层:使上层软件和ECU硬件设计无关,包含ECU板上外部设备的驱动以及内部…

Hi3516DV500部署paddle版型分析模型记录

原版模型测试并导出onnx paddle 版面分析-> https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7/ppstructure/layout/README_ch.md 测试 python3 deploy/python/infer.py \ --model_dirmodel/picodet_lcnet_x1_0_fgd_layout_cdla_infer/ \ --image_fil…

Apache Dolphinscheduler如何不重启解决Master服务死循环

个人建议 Apache Dolphinscheduler作为一个开源的调度平台&#xff0c;目前已经更新到了3.X版本&#xff0c;4.0版本也已经呼之欲出。3.0版本作为尝鲜版本&#xff0c;新添加了许多的功能&#xff0c;同时也存在非常多的隐患&#xff0c;本人使用3.0版本作为生产调度也踩了很多…

Android开发知识学习——TCP / IP 协议族

文章目录 学习资源来自&#xff1a;扔物线TCP / IP 协议族TCP连接TCP 连接的建立与关闭TCP 连接的建立为什么要三次握手&#xff1f; TCP 连接的关闭为什么要四次挥手&#xff1f; 为什么要⻓连接&#xff1f; 常见面试题课后题 学习资源来自&#xff1a;扔物线 TCP / IP 协议…

OpenCV学习(一)——图像读取

1. 图像入门 读取图像显示图像写入图像 import cv2# 读取图像 img cv2.imread(lena.jpg) print(img.shape)# 显示图像 cv2.imshow(image, img) cv2.waitKey(0) cv2.destroyAllWindows()# 写入图像 cv2.imwrite(image.jpg, img)1.1 读取图像 读取图像cv.imread(filename, fl…

人工智能-softmax回归

回归可以用于预测多少的问题。 比如预测房屋被售出价格&#xff0c;或者棒球队可能获得的胜场数&#xff0c;又或者患者住院的天数。 事实上&#xff0c;我们也对分类问题感兴趣&#xff1a;不是问“多少”&#xff0c;而是问“哪一个”&#xff1a; 某个电子邮件是否属于垃圾…

最新版本QGIS 开始支持cesium 3D TILE 数据源了

最新版本QGIS 也开始支持3D TILE 数据源了!加载和运行速度也是慢&#xff0c;不过都这样&#xff0c;也不是qgis的问题!这东西对网络和性能要求比较高!据说这是cesium社区提供基金让qgis团队开发的&#xff0c;cesium社区真是很有钱啊&#x1f601;&#xff0c;不过也不奇怪&am…

分享8个分布式Kafka的使用场景

Kafka 最初是为海量日志处理而构建的。它保留消息直到过期&#xff0c;并让消费者按照自己的节奏提取消息。与它的前辈不同&#xff0c;Kafka 不仅仅是一个消息队列&#xff0c;它还是一个适用于各种情况的开源事件流平台。 1. 日志处理与分析 下图显示了典型的 ELK&#xff0…

数学知识:容斥原理

能被整除的数&#xff1a; #include<iostream> using namespace std; typedef long long LL;const int N 20; int p[N], n, m;//p[]存的i这个集合的质数的个数int main() {scanf("%d%d",&n,&m);for(int i 0; i < m; i) scanf("%d",&a…

Matlab中的app设计

1.窗口焦点问题&#xff1a; 窗口焦点问题&#xff1a;确保你的应用程序窗口正常处于焦点状态。有时&#xff0c;其他窗口的弹出或焦点切换可能导致应用程序最小化。点击应用程序窗口以确保它处于焦点状态。 窗口管理&#xff1a;确保你的 MATLAB 或操作系统没有未处理的错误或…

​测绘人注意,你可能会改变历史!

你也许想不到&#xff0c;曾经有一个测绘人员在进行实地测量作业时&#xff0c;在地图上就这么随手一标注&#xff0c;却让这个地方成为了如今的网红打卡地。 这个地方就是外地游客慕名而来的“宽窄巷子”&#xff0c;如果连这个地方都不知道的成都人&#xff0c;就应该不能算…

audio 标签动态src 且src是http无法播放问题

<audioref"audio" :src"src"alt"加载失败"controls/>src是动态传参的 无法播放因为动态src需要在赋值后对audio进行重载 this.$refs.audio.load()注意如果&#xff0c;src跟本项目地址IP端口协议不同&#xff0c;会出现跨域问题。audio标…