1, Background
The core code module of the project team is deployed on the user server. Another company obtained the root password of the server. The conventional way of encrypting the database by configuring environment variables and directly throwing jar packages to the server is very likely to lead to data disclosure and code disclosure.
2, Code obfuscation
1. Common confusion tools
Software name | Reasons for recommendation |
---|---|
Allatori Java Obfuscator | Lightweight can be integrated into IDE tools and introduced through configuration files |
DashO for Android and Java | Charge, integrate with eclipse, prevent Java programs from being reverse engineered and tampered with, and compress the amount of code |
Zelix KlassMaster | It can read and modify Java class files, and can run on any platform that supports Java virtual machine version 1.1.6. |
Cinnabar Canner | Protect your code from reverse engineering decompilation by creating a native Windows executable file (EXE file). This executable file contains all encrypted versions of your application classes and resources. It is only in an unencrypted state when it is called into memory by the JVM |
Jmangle Java class crusher | To prevent decompiling Java programs and reduce pirated software, developers can use it to smash symbols in class files. |
RetroGuard | The general bytecode obfuscator is used to seamlessly integrate into your daily construction and testing process, making it safer for you to work hard to write valuable Java code |
JODE | Java package with Java decoder and optimizer |
ProGuard | Free Java class file compression, optimization, mixer. It removes useless classes, fields, methods, and properties. Maximize bytecode optimization by renaming classes, fields, and methods with short, meaningless names. eclipse has integrated Proguard. |
Java bytecode manipulation framework ASM | ASM is a Java bytecode manipulation framework. It can dynamically generate stub classes or other proxy classes directly in binary form, or dynamically modify classes when loading. ASM provides functions similar to toolkits such as BCEL and SERP, but it is designed to be smaller and faster, which makes it suitable for real-time code instrumentation |
After comparison, proguard was finally selected. The main reasons for choosing this tool are as follows:
- Support direct integration within pom
- Configuration files can be integrated into pom or configured separately
- There are many related blog introductions
- Other project teams of the company have experience in using this
2. Actual configuration of Proguard
Taking springboot single application as an example, based on the original project configuration file, the relevant configuration of plugins needs to be modified
-
[optional] modify the Maven plugin configuration of springboot
<!--Springboot repackage pack--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <!-- springboot Packaging needs repackage Otherwise, it is not executable jar --> <goals> <goal>repackage</goal> </goals> <configuration> <mainClass>com.xxx.xxx.MainApplication</mainClass> </configuration> </execution> </executions> </plugin>
-
[required] configure proguard
<!-- proguard Obfuscate plug-ins--> <plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <version>2.2.0</version> <executions> <execution> <!-- It began to mix up when packing--> <phase>package</phase> <goals> <goal>proguard</goal> </goals> </execution> </executions> <configuration> <injar>${project.build.finalName}.jar</injar> <!--Exported jar--> <outjar>${project.build.finalName}.jar</outjar> <!-- Is it confused--> <obfuscate>true</obfuscate> <options> <!--appoint java Version number--> <option>-target 1.8</option> <!--It is on by default, without shrinkage (delete comments and unreferenced codes)--> <option>-dontshrink</option> <!--It is on by default, and bytecode level optimization is turned off here--> <option>-dontoptimize</option> <!--After confusing the class name, use Class.forName('className')And so on--> <option>-adaptclassstrings</option> <!-- ignore warn news,If prompted org.apache.http.* If there is a problem with the class in this package, add the following code:-keep class org.apache.http.** { *; } -dontwarn org.apache.http.**--> <option>-ignorewarnings</option> <option>-keep class org.apache.logging.log4j.util.* { *; }</option> <option>-dontwarn org.apache.logging.log4j.util.**</option> <!--For exceptions and annotation information runtime Keep it, otherwise it will affect springboot start-up--> <option>-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod</option> <!--Don't confuse all interface Interface, optional--> <!--<option>-keepnames interface **</option>--> <!--Keep enumeration members and methods--> <option>-keepclassmembers enum * { *; }</option> <!--Package name--> <option>-keeppackagenames com.xxx.controller.**</option> <option>-keeppackagenames com.xxx.entity.**</option> <!--Reserved method parameter name--> <option>-keepparameternames</option> <option>-keepclasseswithmembers public class * { public static void main(java.lang.String[]);} </option> <!--retain main Class of method and its method name--> <option>-keepclassmembers public class * {void set*(***);*** get*();}</option> <!--ignore note Message, if prompted javax.annotation If there is a problem, add the following code--> <option>-dontnote javax.annotation.**</option> <option>-dontnote sun.applet.**</option> <option>-dontnote sun.tools.jar.**</option> <option>-dontnote org.apache.commons.logging.**</option> <option>-dontnote javax.inject.**</option> <option>-dontnote org.aopalliance.intercept.**</option> <option>-dontnote org.aopalliance.aop.**</option> <option>-dontnote org.apache.logging.log4j.**</option> <!--The entry program class cannot be confused, which will lead to springboot Can't start--> <option>-keep class com.xxx.MainApplication</option> <option>-keep class org.apache.logging.log4j.util.* {*;}</option> <option>-keep class com.xxx.entity.* {*;}</option> <option>-keep class com.xxx.config.* {*;}</option> <option>-keep class com.xxx.controller.*.* {*;}</option> <option>-keep class com.xxx.service.kafka.* {*;}</option> <option>-keep class com.xxx.service.xxljob.* {*;}</option> <option>-keep interface * extends * { *; }</option> <option>-keep interface com.xxx.entity.*.*.* {*;}</option> <!--Do not confuse all classes,Save the original defined comments--> <option>-keepclassmembers class * { @org.springframework.beans.factory.annotation.Autowired *; @org.springframework.beans.factory.annotation.Value *; @com.xxl.job.core.handler.annotation.XxlJob *; @org.springframework.kafka.annotation.KafkaListener *; } </option> </options> <libs> <!-- Add dependency java8--> <lib>${java.home}/lib/rt.jar</lib> <lib>${java.home}/lib/jce.jar</lib> </libs> </configuration> <dependencies> <!-- https://mvnrepository.com/artifact/net.sf.proguard/proguard-base --> <dependency> <groupId>net.sf.proguard</groupId> <artifactId>proguard-base</artifactId> <version>6.1.1</version> </dependency> </dependencies> </plugin>
3, Profile encryption
Jasypt is used to encrypt the configuration file
Reference configuration:
[java information security (19) encryption tool Jasypt](https://www.cnblogs.com/bjlhx/p/12229296.html)
4, jar package encryption
Jar package encryption is carried out by Xjar. The way of custom compilation is widely used for configuration on the Internet. If you want to simplify it, you can encrypt it directly through the generated jar. The following methods are not applicable to the programs developed by springBoot+jpa(hibernate) technology.
1. Custom compilation
2. Encrypt directly through existing jar s
-
GitHub download xjar demo, download address: https://github.com/yumingzhu/xjarDemo/tree/master/target
-
Under the pom peer directory of your own code, create a new folder (such as xjarEncode), and add xjardemo-1.0-snapshot Jar copy put in
-
Compile confused code, pom Command window execution under XML: mvn clean package -DskipTests
-
Create a bat script file (such as encode.bat) in the folder created in step 2 to facilitate subsequent rapid execution
[123456] user defined password. Fill in according to your own needs
[targets-0.0.1-SNAPSHOT.jar] name of the jar package generated by maven packaging
[targets.jar] name of target jar package
java -cp .\xjarDemo-1.0-SNAPSHOT.jar XjarDemo 123456 ..\target\targets-0.0.1-SNAPSHOT.jar .\targets.jar
-
implement
-
windows execution method
java -jar xxx.jar
Enter the password you set in step 4 in the pop-up window
-
linux execution method, create a new encode Key file
password: 123456 hold: true
Profile description:
Parameter name Parameter meaning default explain password password nothing Password string algorithm Key algorithm AES Support all built-in algorithms of JDK, such as AES/DES keysize Key length 128 Choose different secret key lengths according to different algorithms ivsize Vector length 128 Choose different vector lengths according to different algorithms hold Whether to keep false Whether to keep the key file after reading, true/1/yes/y, which means that it will not be deleted after reading -
Modify the startup script and add --xjar keyfile=encode. Key parameter. If linux is used, the following startup script is recommended to realize start / stop / restart operations
#!/bin/bash ################################################################# # Author: Shi San # Time: July 14, 2022 # Purpose: start management ################################################################# if [ -f /etc/init.d/functions ]; then . /etc/init.d/functions fi ################################################################# # Define variables ################################################################# # application name SERVICE_NAME='custom' SERVICE_PACKAGE="${SERVICE_NAME}.jar" # application path SERVICE_PATH='custom' ################################################################# # Define commands ################################################################# function START_COMMAND() { echo "${SERVICE_PATH}/${SERVICE_PACKAGE}" java -Duser.timezone=Asia/Shanghai -Xms4g -Xmx4g -jar ${SERVICE_PATH}/${SERVICE_PACKAGE} --xjar.keyfile=encode.key 2>/dev/null 1>&2 & if [[ $? -eq 0 ]]; then action "${SERVICE_NAME} start successed" /bin/true else action "${SERVICE_NAME} start failed" /bin/false fi } function STOP_COMMAND() { SERVICE_PID=`ps -ef | grep "${SERVICE_PACKAGE}" | grep -v 'grep' | awk '{print $2}'` if [[ ${SERVICE_PID} == '' ]]; then action "${SERVICE_NAME} is not running" /bin/false else kill -9 ${SERVICE_PID} >/dev/null 2>&1 if [[ $? -eq 0 ]]; then action "${SERVICE_NAME} stop successed" /bin/true else action "${SERVICE_NAME} stop failed" /bin/false fi fi } function STATUS_COMMAND() { SERVICE_PID=`ps -ef | grep "${SERVICE_PACKAGE}" | grep -v 'grep' | awk '{print $2}'` if [[ ${SERVICE_PID} == '' ]]; then action "${SERVICE_NAME} is not running" /bin/false else action "${SERVICE_NAME} is running" /bin/true fi } ################################################################# # Define commands ################################################################# case "$1" in start) START_COMMAND ;; stop) STOP_COMMAND ;; restart|reload) STOP_COMMAND START_COMMAND ;; status) STATUS_COMMAND ;; *) echo "Usage: $0 {start|stop|restart|status|reload}" ;; esac
-
Add jar, encode Key, copy the script file to the corresponding directory of the server
-
Execute sh xxx sh restart
-
5, Contrast effect before and after
1. Before confusion
2. After confusion
At this time, the configuration file and ORM mybatis xml file have not been encrypted