java安全(一)

命令执行

在这里插入图片描述从上往下依次是:
单独的进程中执行指定的字符串命令
单独的进程中执行指定的命令并传入变量
在指定环境的独立进程执行命令和传入变量
在指定环境和工作目录的独立进程执行中执行命令
在指定环境和工作目录的独立进程执行中执行命令和传入变量

有回显的命令

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Exec {
    public static void main(String[] args) throws IOException {
        BufferedReader br = null;
        try{
            Process p = Runtime.getRuntime().exec("ping 127.0.0.1");
            br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while((line= br.readLine())!=null){
                sb.append(line+"\n");
            }
            System.out.println(sb.toString());
        
    }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(br != null){
                try{
                    br.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        }
}

进一步地,命令执行在不同系统下做一个判断
windows

 String [] cmd = {"cmd","/c","calc.exe"};
Process ps = Runtime.getRuntime().exec(cmd);

linux

String [] cmd = {"/bin/sh","-c","ls"};
Process ps = Runtime.getRuntime().exec(cmd);

判断方法可以使用getProperty获取系统变量
在这里插入图片描述查看getproperties描述可以看到可以获取很多系统变量的键值对
判断系统

if(property.contains(‘linux’))
if (properties.contains(“windows”)||properties.contains(“Windows”))

具有回显的命令,使用IO流读出来输出

Process p = Runtime.getRuntime().exec("");
InputStream io = p.getInputStream();//获得命令结果
InputStreamReader reader = new InputStreamReader(io);//读取结果
BufferedReader BuffRead = new BufferReader(reader);//创建缓冲器
StringBuilder sb = new StringBuilder();
String line = null;
while((line = BuffRead.readline())!=null){
	sb.append(line);
	System.out.println(line);
	}
	关闭流....

反射

反射里面的几个重要方法

forName 获取类的方法
newInstance 获取实例化类对象的方法
getMethod 获取函数的方法
invoke 执行函数的方法
Java.lang.reflect.Constructor;
Java.lang.reflect.Field;
Java.lang.reflect.Method;
Java.lang.reflect.Modifier;

在获取类还有几种方式:

  1. 如果上下文存在某个类的实例a,可以通过**a.getClass()**获取
  2. 加载了某个类,获取它的java.lang.Class对象,访问它的属性class即可(不属于反射)
  3. 知道某个类的名字,获取这个类就可以使用forName来获取

forName有两个函数重载
Class<?> forName(String name)
Class<?> forName(String name, boolean initialize, ClassLoader loader)
第⼀个就是我们最常⻅的获取class的⽅式,其实可以理解为第⼆种⽅式的⼀个封装:
Class.forName(className) 等价于
Class.forName(className, true, currentLoader)
即 initialize=true

  • 类加载器
    java虚拟机加载类的时候,ClassLoader根据类名加载类,类名是类的完整路径,比如java.lang.Runtime
    什么是ClassLoader呢,就是告诉jvm如何加载这个类
public class ClzLoad {

    {
        System.out.println("匿名代码块");// 第二个输出
    }

    static {
        System.out.println("静态代码块");// 与类一同加载,所以最先输出,创建多个对象时,只在第一个对象里输出
    }

    public ClzLoad() {
        System.out.println("构造方法");// 构造方法反而不是最先的
    }
    }

⾸先调⽤的是 static {} ,其次是 {} ,最后是构造函数。
其中, static {} 就是在“类初始化”的时候调⽤的,⽽ {} 中的代码会放在构造函数的 super() 后⾯,
但在当前构造函数内容的前⾯。
所以说, forName 中的 initialize=true 其实就是告诉Java虚拟机是否执⾏”类初始化“。

  • 构造器
    写payload的时候,newInstance()不成功原因有其一:1. 该类没有无参构造函数 2. 该类的构造函数时私有的

**getDeclaredConstructor()**获得构造方法,Runtime的构造方法是private,利用反射修改其访问权限
**getConstructor()**无论是否设置setAccessible(),都不可获取到类的私有构造器.

Constructor ct = a.getDeclaredConstructor();
ct.setAccessible(true);//修改访问权限 setAccessible

Object类是所有类的父类

  • 实例化对象
    在刚刚获得的构造器进行实例化一个对象
Object instance = ct.newInstance();
//等价于
Runtime rt = new Runtime();
  • 获取方法
Method runMethod = a.getMethod("exec",String Class);

//获取当前类的所有成员方法
Method[] methods = class.getDeclaredMethod() ;
//获取指定类成员方法
Method method = class.getDeclaredMethod("func");
Method method = class.getDeclaredMethod("func",int,double,...)//详见重载
  • 执行方法
Process ps = (Process) runMethod.invoke(instance,"clac")

method.invoke(instance,var1,var2…)

  • 获取成员变量
Field var1 = class.getDeclaredField();
Field var2 = class.getDeclaredField("apple");//指定变量

Object obj = field.get(instance);//获取变量值
field.set(instance,setValue);//修改变量值
  • 序列化
  1. 类要实现java.io.Serlalizable接口
  2. 所类的属性必须是可序列化,static,transient 修饰的变量不可被序列化

ObjectOutputStream类->writeObject():对参数指定的Obj文件序列化后写入一个ser文件

  • 反序列化
    ObjectInputStream类->readObject():从文件输入流读入,序列化成对象返回

当readObject()可控时,恶意构造后可以命令执行

一道简单的反序列化题
Recaf工具导入war包(java字节码,直接解压看不到源码)

在这里插入图片描述在这里插入图片描述
上传的地方和读取的地方一致,考察文件上传木马了

在这里插入图片描述
Recaf将tools包导入进idea后,创建一个用来伪造cinfo的Test.java

在这里插入图片描述
成功进入,上传一句话木马

在这里插入图片描述但是展示图片是:showpic.form?file=showpic.jsp
直接改为showpic.form?file=1.jsp出现404,看本地文件夹是传进了resource文件夹了,没有权限去调用resource,于是需要目录穿越
在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值