安全现状
传统的防火墙(WAF)部署在Web应用前线,通过HTTP/HTTPS策略对Web应用保护,容易被绕过,并且难以对其进行优化,不能成为应用安全计划的唯一支柱。
近些年常见的漏洞多为远程代码执行(RCE),扫描探测,各类命令注入。随着 Web 应用攻击手段变得复杂,
基于请求特征的防护手段,已经不能满足企业安全防护需求。
2014 引入了RASP,一种新型应用安全保护技术,它将防护功能"注入"到应用程序中,与应用程序融为一体,通过Hook少量关键函数,来实时观测程序运行期间的内部情况。
RASP能做什么
抵御未知攻击,不过度依赖检测规则。
RASP 的防护层深入代码上下文,基于行为来精准识别攻击,提供相关代码调用堆栈。
利用 RASP 也能够对应用打虚拟补丁,修复官方未修复的漏洞。(热修复机制)
RASP赋能扫描器实现灰盒检测(IAST)。
第三方组件安全风险梳理。RASP获取JVM的jar版本、路径等信息,结合第三方CVE漏洞信息库,评估当前系统的风险等级。
与WAF 的关系
WAF 主要通过分析流量中的特征过滤攻击请求,并拦截携带有攻击特征的请求。但是不知道应用运行时的上下文,会造成一定程度的误报。并且 WAF 严重依赖于特征库,特征编写难。
RASP 的不同就在于运行在应用之中,与应用融为一体,可以获取上下文,攻击精准识别或拦截。
可获取到解码过的真实 payload ,减少由于 WAF 规则的不完善导致的漏报。
WAF和RASP是互补的,rasp更准确的拦截漏洞,WAF更像是口罩防护服,很多场景立竿见影,在应用外面包一层盔甲来防御。
开发测试环境安装
环境条件
linux操作系统
jrasp-agent 项目源码
IDEA 2021.2+
maven3.25+
jdk1.8
linux操作系统
如果使用的是windows操作系统,可以使用虚拟机安装linux操作系统,用centos镜像进行安装。可以使用VMware player,区别于pro,它是官方免费的产品,而且功能与pro大部分相同,只是少一个多虚拟机同时工作的功能,这次的测试完全够用。
jrasp-agent 项目源码
IDEA 2021.2+
IDEA官网地址 选择下载最新版也可以,只要是2021.2版本以上就行
maven3.25+
jdk1.8
阅读源代码及原理探究(初级)
jrasp是基于java agent实现的,只要搞懂agent的原理,就可以实现一个简单的jrasp-launcher。Java Agent 代码无法独立启动,必须依赖于JVM才能运行。
一、jvm 参数形式: 调用 premain 方法
javaagent是 jvm的一个参数,这个参数可以指定一个jar包,在真正的程序没有运行之前先运行指定的jar包。并且对jar包有两个要求:
- jar包的MANIFEST.MF文件必须指定Premain-Class
- Premain-Class指定的类必须实现premain()方法。
premain方法会在java命令行指定的main函数之前运行。
javaagent可以指定很多个,jvm会依次执行不同的jar。
premain方法的定义方式
/** * 启动加载 * * @param featureString 启动参数 * [namespace,prop] * @param inst inst */ public static void premain(String featureString, Instrumentation inst) { System.out.println(“在main方法之前和inst类加载之前执行”); //上面代码之后,可以使用inst进行类的查看和修改 }
在premain方法执行时,获取的Instrumentation对象还会加载大部分类,包括后面main方法执行时需要加载的各种类,但是抓不到系统类。也就是说,在这个位置在main方法执行前,就可以拦截或者重写类,结合其它方式就可以实现对类的改写或者插桩。
a:pom.xml 指定配置方式
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <!-- <manifestFile>--> <!-- src/main/resources/META-INF/MANIFEST.MF--> <!-- </manifestFile>--> <manifestEntries> <Premain-Class>agentclass.SimpleAgent</Premain-Class> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build>
<Can-Redefine-Classes>和<Can-Retransform-Classes>官方默认为false,所以要写。
官方文档摘要
Can-Redefine-Classes
Boolean (true or false, case irrelevant). Is the ability to redefine classes needed by this agent. Values other than true are considered false. This attribute is optional, the default is false.
Can-Retransform-Classes
Boolean (true or false, case irrelevant). Is the ability to retransform classes needed by this agent. Values other than true are considered false. This attribute is optional, the default is false.
通过mvn assembly:assembly
命令打包
b:MANIFEST.MF 配置文件方式
-在资源目录(Resources)下,新建目录META-INF
-在META-INF目录下,新建文件MANIFEST.MF
Manifest-Version: 1.0 Premain-Class: agentclass.SimpleAgent Can-Redefine-Classes: true Can-Retransform-Classes: true
请注意,最后一行要有一个空行,不能少,在 idea 中,删除最后一行时,会有错误提醒:
然后我们的pom.xml配置,需要作出对应的修改:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifestFile> src/main/resources/META-INF/MANIFEST.MF </manifestFile> <!-- <manifestEntries>--> <!-- <Premain-Class>agentclass.SimpleAgent</Premain-Class>--> <!-- <Agent-Class>agentclass.SimpleAgent</Agent-Class>--> <!-- <Can-Redefine-Classes>true</Can-Redefine-Classes>--> <!-- <Can-Retransform-Classes>true</Can-Retransform-Classes>--> <!-- </manifestEntries>--> </archive> </configuration> </plugin> </plugins> </build>
通过mvn assembly:assembly
命令打包
接下来测试一下agent 的使用.
首先新建一个 demo 项目,写一个简单的测试类:
测试类中,有一个死循环,各 1s 调用一下 print 方法.
在配置类中添加 jvm 参数:
-javaagent:D:\agent_project\agentTest2\target\agentTest2-1.0-SNAPSHOT-jar-with-dependencies.jar
是刚才打下jar包的绝对路径。
上面的文字, 就是我们上面的premain方法输出,在主程序main函数运行前,先运行了agent的premain函数的内容。
二、attach 方式: 调用 agentmain 方法
还是之前的位置,在agentTest2的SimpleAgent实现agentmain方法。
public static void agentmain(String agentArgs, Instrumentation inst){ System.out.println("在main方法后,运行时调用agentmain方法"); }
然后在pom.xml或者
MANIFEST.MF文件下添加如下
或
之后使用mvn assembly:assembly
命令打包
在使用 attach 方式时,可以简单的理解为将 agent 注入到目标的应用程序中,所以我们需要自己起一个程序来完成这件事情,新建一个AttachMain类:
package agentclass; import com.sun.tools.attach.*; import java.io.IOException; public class AttachMain { public static void main(String[] args) throws AgentLoadException, IOException, AgentInitializationException, AttachNotSupportedException { VirtualMachine vm = VirtualMachine.attach("111"); vm.loadAgent("D:\\agent_project\\agentTest2\\target\\agentTest2-1.0-SNAPSHOT-jar-with-dependencies.jar"); } }
然后启动目标应用程序demo项目的BaseMain的main函数。然后通过jps 获取目标应用的进程号:
将目标进程号和jar包绝对路径加入到AttachMain里,
运行,
可以看到,图中的文字,就是之前agenttest2项目SimpleAgent类下agentmain函数的代码运行了。
标签:Jrasp,--,jar,agent,项目分析,开源,RASP,main,true From: https://www.cnblogs.com/Post-90sDachenchen/p/17686734.html