The front-end time is fortunate to participate in RASP technology-related projects, just to come to an end, so today to popular science under this form of technology and concrete applications. (i) Java instrumentation introduction
The Java instrumentation is a new feature offered from Javase 5 to build an agent that is independent of Java applications, primarily to monitor applications on the JVM, such as performance tuning monitoring, and so on.
Through this feature, we can do this by manipulating bytecode without modifying the source of the JVM, which can also implement a virtual machine-level AOP mechanism, which is different from the AOP mechanism implemented by dynamic proxies in spring, which is lighter and less coupled to the project.
In Javase 6, instrumentation is more powerful, and can even modify native code (Native).
(ii) Java Agent sample code
On the basis of instrumentation, we can implement a Java Agent program to implement the hook mechanism.
To begin with, let's look at the following sample code:
What we're going to do is hook up the Say method here.
(1) First, create a new MAVEN project and add Resources/meta-inf/manifest. MF File: Right key item-> properties-> Java build path-> Add Folder
(2) Write Agent class, realize Premain method:
The Premain method only does one thing, is to set up a classfiletransform to get and manipulate bytecode.
(3) The implementation of Testtransform is as follows:
First, the ASM dependency is introduced into the pom.xml, which is used to insert the byte code:
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactid>asm-all</artifactid >
<version>5.1</version>
</dependency>
Java code:
Package Agenttest. Agenttest;
Import Java.lang.instrument.ClassFileTransformer;
Import java.lang.instrument.IllegalClassFormatException;
Import Java.security.ProtectionDomain;
Import Org.objectweb.asm.ClassReader;
Import Org.objectweb.asm.ClassWriter;
public class Testtransform implements classfiletransformer{public
byte[] Transform (ClassLoader loader, String ClassName, class<?> classbeingredefined,
protectiondomain protectiondomain, byte[] classfilebuffer) throws illegalclassformatexception {
Classreader classreader = new Classreader (classfilebuffer);
Classwriter classwriter = new Classwriter (classwriter.compute_frames);
Classreader.accept (New Myclassvisitor (Classwriter), 0);
byte[] bytes = Classwriter.tobytearray ();
return bytes
}
}
We are in myclassvisitor to implement the operation to modify bytecode.
(4) Implement Myclassvisitor and Inherit Classvisitor class.
package agenttest.
Agenttest;
Import Org.objectweb.asm.ClassVisitor;
Import Org.objectweb.asm.MethodVisitor;
Import Org.objectweb.asm.Opcodes;
public class Myclassvisitor extends classvisitor{public myclassvisitor (classvisitor CV) {super (OPCODES.ASM5, CV); @Override public methodvisitor visitmethod (int access, string name, String desc, string signature, string[] exception s) {if ("Say". Equals (name)) {Methodvisitor Methodvisitor = Cv.visitmethod (access, name, desc, signature, exceptions
) ;
Methodvisitor.visitcode ();
METHODVISITOR.VISITFIELDINSN (opcodes.getstatic, "Java/lang/system", "Out", "ljava/io/printstream;");
METHODVISITOR.VISITLDCINSN ("call" + name); METHODVISITOR.VISITMETHODINSN (opcodes.invokevirtual, "Java/io/printstream", "println", "(ljava/lang/string;) V",
FALSE);
Methodvisitor.visitend ();
return methodvisitor;
Return Super.visitmethod (access, name, desc, signature, exceptions); }
}
In the above code, rewrite the Visitmethod method and then judge the case with the method name say. Here's a specific operation to read the ASM5 documentation.
(5) Writing resources/meta-inf/manifest. MF file, specifying the Premain class:
manifest-version:1.0
premain-class:agenttest. Agenttest.agentmain
built-by:chongrui
build-jdk:1.8.0_111
created-by:maven integration for Eclipse
(6) Add packing required items in POM
<build> <plugins> <plugin> <GROUPID>ORG.APACHE.MAVEN.PLUGINS&L T;/groupid> <artifactId>maven-compiler-plugin</artifactId> <configuratio
N> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupid>org.apa
Che.maven.plugins</groupid> <artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version> <executions> <execution>
<id>attach-sources</id> <phase>verify</phase> <goals> <goal>jar-no-fork</goal> </goals
> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactid>maven-assembly-plugin</a
Rtifactid> <version>2.6</version> <configuration>
<descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <MANIFESTFILE>RESOURC Es/meta-inf/manifest. mf</manifestfile> </archive> </configuration> <ex
Ecutions> <execution> <id>assemble-all</id> <phase>package</phase> <goals> <GOAL&G T;single</goal> </goals> </execution> </exec
utions> </plugin> </plugins> <resources> <resource> <directory>${basedir}/resources</directory> </resource> <RESOURC e> <directory>${basedir}/src/main/java</directory> </resource> &L
T;/resources> </build>
(7) Build under Eclipse as Jar pack
(8) Experiment
Executes Test.java alone. Output say Hello.
After the Agent.jar is set, the command that executes the Java application specifies the agent with the-javaagent:path option.
You can see that the call say is output, and the output occurs before the Say method is invoked:
(iii) Java RASP technology
The Java rasp technology principle is roughly as follows:
PS. This picture comes from other citations.
We can see that the RASP process is embedded directly into the app execution process, which is fundamentally different from the WAF. It is for this reason that rasp avoids the pain point where the WAF rule is bypassed by a variety of singular encodings, because the parameters that the agent process ultimately acquires are the parameters that are actually executed after the encoding conversion has been completed at each level. And rasp does not need to intercept each request to check whether it hits the rules of the attack, as WAF does, but it triggers the detection logic when the dangerous function of the hook is invoked.
Roughly speaking of the implementation of the RASP agent, first of all, we can register a lot of Codefilevisitor in the transform class, such as each vulnerability type to write a visitor, in fact, here ASM provides this visitor is an event-based model of the processing class , you write code that is similar to the parsing of XML events. In these visitor we can only monitor some of the dangerous functions we care about, such as the Execsql function of JDBC, use ASM programming to get the specific parameters to call this function, and then write our rules to determine whether there is a vulnerability, if there is a vulnerability, according to the configuration of the escalation, Block the action on the line.
At deployment time, the agent can be integrated into the Java middleware startup script by embedding it. For example, in the Tomcat startup script catalina.sh, we can modify the java_opts variable to set the Javaagent mode to start.
(iv) Summary
The essence of rasp technology is how to implement such a hook action agent. The implementation of each language is different, such as the PHP and Java mechanism is different, PHP is written in the form of PHP expansion of the hook and vulnerability to judge, report. However, the rule of vulnerability determination is universal, so this part can be made into General Service operation.
Although Rasp technology is easy to use, but it is a criticism of the source program itself performance impact, when the concurrency increases, the vulnerability to determine the logic will slow down the speed of the program itself. Therefore, unless there is a very strong courage and the support of the top, otherwise the general business line of large companies will not be easy to accept the security needs of this performance impact, after all, performance, stability considerations are counted in the KPI. The best scenarios are deployed in small and medium sized enterprises, and the effect should be obvious.
Reference Documents
https://liuzhengyang.github.io/2017/03/15/javaagent/
http://paper.seebug.org/330/