AOP为Aspect Oriented Programming的缩写 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
日志记录,性能统计,安全控制,事务处理

Javassist是编辑字节码的Java类库.
通过使用Javassist可以使Java程序在运行时定义一个新的类,并且在JVM加载类文件时修改它.
提供两个级别的API:源码级别和字节码级别。

ClassLoader是java的核心组件,所有的class都是由ClassLoader进行加载的。ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部,转换为一个与目标类对应的java.lang.Class对象实例,然后交给虚拟机进行链接、初始化等操作。
java程序开始执行,遇到的第一个classloader是bootstrap classloader,这个classloader是用c++语言编写,通过他来完成加载java中的核心类。第二个classloader是extension classloader,加载的是jre/lib目录中的ext目录中的jar包。然后第三个是system classloader,也被称为应用加载器,主要负责完成加载-classpath 或者系统中的全局变量ClassPath中的类。

在java.net包中,JDK提供了一个更加易用的类加载器URLClassLoader,它扩展了ClassLoader,能够从本地或者网络上指定的位置加载类。我们可以使用该类作为自定义的类加载器使用。
构造方法:
public URLClassLoader(URL[] urls):指定要加载的类所在的URL地址,父类加载器默认为系统类加载器。
public URLClassLoader(URL[] urls, ClassLoader parent):指定要加载的类所在的URL地址,并指定父类加载器。

那么使用Javassist生成一个新类也包含类似的步骤:

获取ClassPool对象(ClassPool代表CtClass的容器)
通过ClassPool对象构建一个CtClass对象(一个CtClass代表一个Class的容器)(确定类名)
通过CtField对象向类中添加类字段(添加字段)
通过CtConstructor对象向类中添加构造函数(添加构造函数)
通过CtMethod对象向类中添加方法(添加成员函数)

添加maven依赖

<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.28.0-GA</version>
</dependency>

相关代码知识
ClassPool:存放CtClass的容器
ClassPool是存放CtClass的容器,CtClass只能通过ClassPool提供的方法获取,其中包括get()&makeClass()方法;ClassPool通过HashTable来缓存已经创建好的CtClass对象,其中键为className,值为CtClass对象。
ClassPool中如果缓存大量的CtClass对象,可能会消耗大量缓存;为了避免这种情况的发生,我们可以调用CtClass.detach()方法,该方法将会删除ClassPool中相应的CtClass对象,释放空间;如果我们调用get()方法获取被删除的CtClass对象,那么ClassPool会重新生成相应的CtClass对象
toClass():将CtClass对象转换为Class对象
importPackage():将Java包导入到ClassPool中,方便其通过package查找到对应的类
appendClassPath, insertClassPath : 将一个ClassPath加到类搜索路径的末尾位置 或 插入到起始位置。通常通过该方法写入额外的类搜索路径,以解决多个类加载器环境中找不到类的尴尬;


CtClass:代表一个class or interface or annotation

CtField:代表class中的某个字段
CtConstructor:代表class的构造函数

CtMethod:代表class的包含的方法
insertBefore : 在方法的起始位置插入代码;
insterAfter : 在方法的所有 return 语句前插入代码以确保语句能够被执行,除非遇到exception;
insertAt : 在指定的位置插入代码;
setBody : 将方法的内容设置为要写入的代码,当方法被 abstract修饰时,该修饰符被移除;
make : 创建一个新的方法。

instrumentation,其中addtransformer添加的transformer在每一次类被加载进jvm时都将被调用,并且转换是可以有多个的(自己添加多个classfiletransformer),当一个类转换报错时,jvm将按顺序调用其它的transformer进行类文件的转换

实例代码
插桩操作

import javassist.*;if("java/sql/Statement".equals(className)){//通过类名称获取类CtClass ctClass = ClassPool.getDefault().getCtClass(className.replace('/', '.'));//获取已申明方法CtMethod ctMethod = ctClass.getDeclaredMethod("executeQuery");//方法前插入语句ctMethod.insertBefore();//新增方法ctClass.addMethod(CtMethod.make(" 方法体 "), ctClass));//转换为字节码byte[] byteCode = ctClass.toBytecode();ctClass.detach();return byteCode;// 添加getter和setter方法CtMethod setUsername = new CtMethod(CtClass.voidType, "setUsername", new CtClass[] {pool.get("java.lang.String")},ctClass);setUsername.setModifiers(Modifier.PUBLIC);setUsername.setBody("{$0.username = $1;}");ctClass.addMethod(setUsername);CtMethod getUsername = new CtMethod(pool.get("java.lang.String"), "getUsername", new CtClass[] {}, ctClass);getUsername.setModifiers(Modifier.PUBLIC);getUsername.setBody("{return $0.username;}");ctClass.addMethod(getUsername);Class<?> user = ctClass.toClass();Object instance = user.getDeclaredConstructors()[0].newInstance();System.out.println(instance);// 获取String的ctClass类CtClass[] method_arguments = new CtClass[1];method_arguments[0] = classPool.get("java.lang.String");CtMethod ctMethod_query = clazz.getDeclaredMethod("DruidPooledPreparedStatement", method_arguments);Instrumentation类: “java.lang.instrument”包的具体实现,依赖于 JVMTI。JVMTI(Java Virtual Machine Tool Interface)是一套于JVM 相关的本地编程工具接口集合。- addTransformer:添加字节码转换器- removeTransformer:移除字节码转换器- getAllLoadedClasses:返回当前由JVM加载的所有类的数组- appendToBootstrapClassLoaderSearch:添加jar包到启动类加载器- appendToSystemClassLoaderSearch:添加jar包到系统类加载器获取当前类名: Thread.currentThread().getStackTrace()[1].getClassName()获取当前方法名: Thread.currentThread().getStackTrace()[1].getMethodName()启动方式:-javaagent:jar包路径=参数-javaagent:user\project\test\testagent-1.0-SNAPSHOT.jar=test注:等号后的参数会传入到premain方法的agentArgs参数中。一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。
}获取request请求参数信息
public static void getInfo(HttpServletRequest request){Enumeration<String> names = request.getParameterNames();while(names.hasMoreElements()) {//获取参数名String name = names.nextElement();//获取参数值String value = request.getParameter(name);System.out.println(name + "=" + value);}}$_    代表函数的返回值

捕获异常操作:

catch (Throwable e) {System.err.println("出错了:" + e.getMessage());e.printStackTrace();
}

您还可以直接加载CtClass:

获取字节码: byte[] b = cc.toBytecode();
直接加载CtClass: Class clazz = cc.toClass();

获取运行程序的进程号 // cmd 下 jps获取

List<VirtualMachineDescriptor> list = VirtualMachine.list();
for (VirtualMachineDescriptor vmd : list)
{  System.out.println("pid:" + vmd.id() + ":" + vmd.displayName());
}
Annotation[][] annotations = method.getParameterAnnotations();

annotations[0]代表第一个参数,annotations[1]代表第二个参数。
像第一个参数的话,它有2个注解,annotations[0][0]表示第一个注解,annotations[0][1]表示第二个注解。

经验:

1. 被监控的主程序需要javassit依赖
2. .MF文件内容 需要写全
3. 解决spring boot项目找不到javassist类: 添加参数+javassist.jar包路径
-Xbootclasspath/a:<path>  Appends the specified resources to the end of the bootstrap class path.

遍历插桩

for(Class hook: hooks){try {Object object = hook.newInstance();if (object instanceof AbstractClassHook) {AbstractClassHook item =(AbstractClassHook) object;}}
}

获取java包中mainfest的信息

Class clazz = Agent.class;
String className = clazz.getSimpleName() + ".class";
// 获取类路径
String classPath = clazz.getResource(className).toString();
// 通过类路径获取mainfest文件路径
String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1)  + "/META-INF/MANIFEST.MF";
//打开mainfest文件
Manifest manifest = new Manifest(new URL(manifestPath).openStream());
//分别获取各属性字段值
Attributes attr = manifest.getMainAttributes();
String projectVersion = attr.getValue("Project-Version");
String buildTime = attr.getValue("Build-Time");

class.forName()说明

Class.forName(xxx.xx.xx)返回的是一个类。
Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段。

关于jdbc中Statement:
statement 用于执行不带参数的SQL语句
​preperStatement 用于执行带参数的SQL语句可以防SQL注入
​callableStatement 用于执行存储过程的调用

Statement 接口提供了三种执行 SQL 语句的方法:executeQuery、executeUpdate 和 execute。使用哪一个方法由 SQL 语句所产生的内容决定。
1.方法executeQuery : 用于产生单个结果集的语句,例如 SELECT 语句。
2.方法executeUpdate:用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。
3.方法execute:用于执行返回多个结果集、多个更新计数或二者组合的语句。

要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3种类型:
1、执行静态SQL语句。通常通过Statement实例实现。  SQL语句在程序运行前被编译
2、执行动态SQL语句。通常通过PreparedStatement实例实现。 SQL语句在程序运行时被编译
3、执行数据库存储过程。通常通过CallableStatement实例实现。

redefineClasses 是自己提供字节码文件替换掉已存在的 class 文件
retransformClasses 是在已存在的字节码文件上修改后再进行替换

Web安全漏洞学习平台:WebGoat (java 15)
WebGoat是一个用来演示Web浏览器中典型安全漏洞的应用程序,其目的是在应用程序安全审查的上下文中系统、完整地介绍如何测试和利用这些安全漏洞。

SQL注入类型:
SQL注入方式主要有以下几种:

①同义反复:将恶意代码插入到多个条件语句中,使SQL语句的条件子句部分总是为真,致使原条件失效,主要用于绕过身份验证。
②逻辑错误查询:向被测系统提交错误的SQL语句,通过分析系统返回的错误信息来判断系统内部信息。
③联合查询:通过在SQL语句中加入“UNION”求并集子句来获得额外信息。
④复合查询:使用“;”将SQL查询、插入、删除等操作连接并执行。
⑤存储过程:存储过程包含参数,在参数传递中存在SQL注入。
⑥推理:构造条件互相对立的SQL语句,可分为条件盲注和时间盲注。
⑦编码替换:利用ASCII编码、十六进制编码等方式转换语句进行注入。
⑧按具体的攻击手段,常用的SQL注入方法大致有Union注入、Boolean注入、报错注入、时间注入、堆叠查询注入、二次注入、宽字节注入、Cookie注入、Base64注入、XFF注入等。

时间盲注是指基于时间的盲注,也叫延时注入,根据页面的响应时间来判断是否存在注入。

#{}与${}的区别

#{}是占位符   预编译 -> 执行
${}是拼接符   编译 -> 执行

@interface不是接口是注解类,在jdk1.5之后加入的功能,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节
@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

public @interface Component {String value() default "";
}

使用 该注解的地方,需要给属性赋值,如果属性定义时,带有default,则可以不用赋值

@Retention 用来确定这个注解的生命周期;
@Target 指定注解使用的目标范围(类、方法、字段等)

//保留的环境
@Retention(RUNTIME)

public enum RetentionPolicy {SOURCE,            /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了  */CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}

//注释起作用的位置,此处表示它只能给类、接口、枚举注解
@Target(TYPE)

public enum ElementType {TYPE,               /* 类、接口(包括注释类型)或枚举声明  */FIELD,              /* 字段声明(包括枚举常量)  */METHOD,             /* 方法声明  */PARAMETER,          /* 参数声明  */CONSTRUCTOR,        /* 构造方法声明  */LOCAL_VARIABLE,     /* 局部变量声明  */ANNOTATION_TYPE,    /* 注释类型声明  */PACKAGE             /* 包声明  */
}

@Documented:说明该注解将会被包含在JavaDoc文档中 导出(export–java doc)
这个注解对程序没什么影响,只是在对于生成帮助文档时有帮助。

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF是要目标网站的内部系统。(因为他是从内部系统访问的,所有可以通过它攻击外网无法访问的内部系统,也就是把目标网站当中间人)

一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。


hashcode
hashcode代表对象的地址说的是对象在hash表中的位置,物理地址说的对象存放在内存中的地址
HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的
1、如果两个对象equals相等,那么这两个对象的HashCode一定也相同
2、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置

javassist技术研究Sql注入检测相关推荐

  1. SQL注入检测模块开源项目DRUID-SQL-WALL学习小结

    作为sql注入原理.sql注入检测.防御系列学习的第三篇.本文主要关注了抽象语法树ast在sql注入检测上的应用开发.以及开源项目druid-sql-wall的学习,希望能给研究这一领域的朋友带来一点 ...

  2. C#SQL注入检测——特别是对于旧版.NET代码

    目录 使用Decorator模式提供添加SQL注入检测的位置 SQL注入检测代码 究竟如何检测到SQL注入? SQLExtensions类中包含的格式化方法 自定义.NET异常类 用于检测SQL注入的 ...

  3. 基于AST抽象语法树的SQL注入检测 (2) -- 每周小结(01-02~01-08) - .Little Hann

    本周继续学习AST的SQL语法检测原理的学习,文章的接下来部分准备分为2部分进行学习: 1. SQL注入语法防御规则 2. druid中SQL注入防御模块sql-wall 1. 相关学习资料 http ...

  4. 使用Python打造基本WEB漏洞扫描器(一) 网站爬虫+SQL注入检测

    一.实验介绍 扫描器需要实现功能的思维导图: 1.1 实验内容 编写一个简单的多线程爬虫,用于对网站地址进行爬取,编写一个简单的sql注入工具,用于对网站地址进行sql注入的检测. 1.2 实验知识点 ...

  5. sqlmap地表最强sql注入检测工具学习使用

    官网戳:https://sqlmap.org/ 带着问题去学习:假如有一个POST接口,传递的body是一个json, 我需要去检查这个json里面的一个字段有没有sql注入的可能,我使用sqlmap ...

  6. 利用预编译技术防御SQL注入

    一.关于SQL注入 众所周知,SQL注入漏洞是一种常见的Web安全漏洞,其形成原因是服务器没有对用户输入的内容进行严格过滤,导致该内容拼接到服务器原本的SQL语句中,被当作SQL语句的一部分执行. 以 ...

  7. Data-Hack SQL注入检测

    大学生 · 2015/03/12 10:02 0x00 前言 这个系列教程我本来打算的是翻译,后来过了一下文章发现教学过程不是很友好,所以大体是按他的思路,不过其中做了很多改动,还有个事情就是我假定读 ...

  8. python sql注入检测_在源代码中检测SQL注入

    不确定这将如何与其他包进行比较,但在某种程度上,您需要解析传递给cursor.execute的参数.这段pyparsing代码寻找:使用字符串插值的参数 使用字符串与变量名串联的参数 只是变量名的参数 ...

  9. 利用sqlmap对网站进行sql注入检测

    1.下载sqlmap github地址:https://github.com/sqlmapproject/sqlmap/zipball/master 2.sqlmap的运行环境需要python,这个网 ...

最新文章

  1. Oracle归档日志删除
  2. RabbitMQ安装遇到的问题及解决记录
  3. linux内核网络协议栈--数据包的接收过程(二十二)
  4. mysql8報錯解決方案彙總(持續更新中)
  5. *nix下部署第三方动态库文件
  6. quatus ii------调试利器 SignalTap II简介(基于TIGER BOARD 板子)
  7. 学习dubbo(四): 启动时检查
  8. NSA漏洞披露政策:攻击和防御间的权衡
  9. UC大裁员:全体带薪休假至3月31日,补偿措施羡煞网友!
  10. 超级有用的git reset --hard和git revert命令
  11. ad18 bell封装_Altium 中异形焊盘异形封装的创建图文教程
  12. 22.11.16 IO day 8
  13. 计算机无法识别建行网银盾,为你修复建行网银盾无法识别 【应对方案】 的详细方案_...
  14. uniapp中uni.navigateTo传递变量
  15. 语音转换成文本 技术实现_职业转换者指南,帮助您实现梦想的技术工作
  16. 《滕王阁序》古文鉴赏
  17. 基于深度搜索的树路径求解_基于深度学习的自动验证码求解器
  18. OpenCV C++入门,读取和显示一张图片
  19. 【工程师经验分享】 2 嵌入式大牛开发经验心得及其学习方向
  20. 开膛手约翰(john)的初学者指南(第2部分)

热门文章

  1. 使用antigen轻松打造赏心悦目的shell环境
  2. PTA-整除光棍(C语言)
  3. 揭阳计算机短期培训机构,揭阳市PLC自动化速成班
  4. AI行为树的基础运作原理
  5. python模块相互引用_python导入模块交叉引用的方法
  6. html隐藏标签属性
  7. Linux内核版本和发行版本的区别
  8. 华为ENSP网络设备配置实战2(较为复杂的ospf)
  9. AutoHotKey的那些事儿:(一)、AutoHotkey常用命令
  10. 【Matlab学习】