本项目包含两部分: java安全编码规范和JAVA安全SDK,SDK介绍详见下述。
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── immomo
│ │ └── rhizobia
│ │ └── rhizobia_J
│ │ ├── base
│ │ │ ├── SqliSanitiser.java
│ │ │ └── WhiteChecker.java
│ │ ├── crypto
│ │ │ ├── AESUtils.java
│ │ │ └── RSAUtils.java
│ │ ├── csrf
│ │ │ └── CSRFTokenUtils.java
│ │ ├── deserialization
│ │ │ └── SecureObjectInputStream.java
│ │ ├── extra
│ │ │ ├── LICENSE
│ │ │ ├── LICENSE-CONTENT
│ │ │ ├── LICENSE-README
│ │ │ ├── codecs
│ │ │ │ ├── AbstractCharacterCodec.java
│ │ │ │ ├── AbstractCodec.java
│ │ │ │ ├── AbstractIntegerCodec.java
│ │ │ │ ├── AbstractPushbackSequence.java
│ │ │ │ ├── Codec.java
│ │ │ │ ├── DB2Codec.java
│ │ │ │ ├── HTMLEntityCodec.java
│ │ │ │ ├── HashTrie.java
│ │ │ │ ├── JavaScriptCodec.java
│ │ │ │ ├── MySQLCodec.java
│ │ │ │ ├── OracleCodec.java
│ │ │ │ ├── PushBackSequenceImpl.java
│ │ │ │ ├── PushbackSequence.java
│ │ │ │ ├── PushbackString.java
│ │ │ │ └── Trie.java
│ │ │ └── commons
│ │ │ ├── CollectionsUtil.java
│ │ │ ├── EncoderConstants.java
│ │ │ ├── NullSafe.java
│ │ │ ├── RandomCreater.java
│ │ │ └── StringUtilities.java
│ │ ├── sqli
│ │ │ ├── DB2Sanitiser.java
│ │ │ ├── MysqlSanitiser.java
│ │ │ └── OracleSanitiser.java
│ │ ├── ssrf
│ │ │ └── SSRFWhiteChecker.java
│ │ ├── urlredirection
│ │ │ └── UrlRedirectionWhiteChecher.java
│ │ ├── xss
│ │ │ └── XssSanitiser.java
│ │ └── xxe
│ │ └── XmlUtils.java
│ └── resources
│ └── log4j.properties
└── test
└── java
└── com
└── immomo
└── rhizobia
└── rhizobia_J
├── AESUtilsTest.java
├── CSRFTokenUtilsTest.java
├── DB2SanitiserTest.java
├── MysqlSanitiserTest.java
├── OracleSanitiserTest.java
├── SSRFWhiteCheckerTest.java
├── SafeClass.java
├── SecureObjectInputStreamTest.java
├── TestBean.java
├── UnsafeClass.java
├── UrlRedirectionWhiteChecherTest.java
├── XmlUtilsTest.java
└── XssEncoderTest.java
- 1、引用java security library
- 2、SQL注入防护
- 3、xss防护
- 4、url重定向防护
- 5、SSRF防护
- 6、CSRF防护
- 7、readObject反序列化漏洞防护
- 8、xxe防护
- 9、AES加解密
- 10、RSA加解密
- Java 8
- Maven 3
mvn -Dmaven.test.skip=true clean install
在target目录中找到target/rhizobia_J-1.0.jar,导入工程中
需要在自己的maven工程pom.xml中加入如下依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
import com.immomo.rhizobia.rhizobia_J.sqli.MysqlSanitiser;
//import com.immomo.rhizobia.rhizobia_J.sqli.OracleSanitiser;
//import com.immomo.rhizobia.rhizobia_J.sqli.DB2Sanitiser;
MysqlSanitiser sqlTool = MysqlSanitiser.getInstance();
String id = "1' or '1'='1' #";
String idEncode = sqlTool.mysqlSanitise(id);
String query = "SELECT NAME FROM users WHERE id = '" + idEncode + "'";
使用order by、group by等需要转换列名时,需使用带boolean参数
//保证列名中的下划线不被转义
String columnName = "user_name";
String columnNameEncode = sqlTool.mysqlSanitise(columnName, true);
query = "SELECT NAME FROM users order by " + columnNameEncode ;
转义前:SELECT NAME FROM users WHERE id = '1' or '1'='1' #'
转义后:SELECT NAME FROM users WHERE id = '1\' or \'1\'\=\'1\' \#'
转义前:SELECT NAME FROM users order by user_name
转义后:SELECT NAME FROM users order by user_name
转义前:SELECT NAME FROM users order by user-name
转义后:SELECT NAME FROM users order by user\-name
import com.immomo.rhizobia.rhizobia_J.xss.XssSanitiser;
XssSanitiser xssFilter = XssSanitiser.getInstance();
String ret = xssFilter.encodeForHTML(oriString);
过滤前后对比:
过滤前:<script> alert('xss') </script>
过滤后:<script>alert('xss')</script>
String ret = xssFilter.encodeForHTMLAttribute(oriString);
过滤前后对比:
过滤前:<script> alert('xss') </script>
过滤后:<script> alert('xss') </script>
String ret = xssFilter.encodeForJavaScript(oriString);
过滤前后对比:
过滤前:alert('xss');
过滤后:alert\x28\x27xss\x27\x29\x3B
import com.immomo.rhizobia.rhizobia_J.urlredirection.UrlRedirectionWhiteChecher;
UrlRedirectionWhiteChecher urlChecker = UrlRedirectionWhiteChecher.getInstance();
List<String> whitelist = new ArrayList<String>();
String white1=".trust1.com";
String white2=".trust2.com";
//setWhiteList会先清空原有白名单列表
//在原有基础上新增白名单,使用addWhiteList(whitelist)
urlChecker.setWhiteList(whitelist);
try{
boolean isWhite = urlChecker.verifyURL(url.trim());
} catch (Exception e) {
...
}
import com.immomo.rhizobia.rhizobia_J.ssrf.SSRFWhiteChecker;
SSRFWhiteChecker ssrfChecker = SSRFWhiteChecker.getInstance();
List<String> whitelist = new ArrayList<String>();
String white1=".trust1.com";
String white2=".trust2.com";
//setWhiteList会先清空原有白名单列表
//在原有基础上新增白名单,使用addWhiteList(whitelist)
ssrfChecker.setWhiteList(whitelist);
try{
boolean isWhite = ssrfChecker.verifyURL(url.trim());
} catch (Exception e) {
...
}
import com.immomo.rhizobia.rhizobia_J.csrf.CSRFTokenUtils;
CSRFTokenUtils csrfInstance = CSRFTokenUtils.getInstance();
String token = csrfInstance.resetCsrfToken(32);
c、前端页面加上hidden字段
form中加入csrf token的hidden字段:
<input name="${(_csrf.parameterName)!}" value="${(_csrf.token)!}" type="hidden">
ajax中加入csrf头
xhr.setRequestHeader("${_csrf.headerName}", "${_csrf.token}");
使用SecureObjectInputStream中适当的构造函数,增加自定义的白名单
import com.immomo.rhizobia.rhizobia_J.deserialization.SecureObjectInputStream;
SecureObjectInputStream(InputStream in, String[] classlist)
SecureObjectInputStream(InputStream in, List<String> classlist)
List<String> classlist = new ArrayList<String>();
classlist.add(SafeClass.class.toString());
try{
//考虑如果白名单为空时会影响正常判断逻辑,所以此处会抛出异常
SecureObjectInputStream ois = new SecureObjectInputStream(fis, classlist);
//使用安全的SecureObjectInputStream恢复对象时会抛出exception
UnsafeClass objectFromDisk = (UnsafeClass)ois.readObject();
} catch (Exception e) {
...
}
import com.immomo.rhizobia.rhizobia_J.xxe.XmlUtils;
//如果xml格式包含外部实体,会抛异常
try{
Document doc = XmlUtils.getInstance().newDocument(xmlFile, "utf-8");
} catch (Exception e) {
...
}
Node notifyNode = doc.getFirstChild();
NodeList list = notifyNode.getChildNodes();
for (int i = 0, length = list.getLength(); i < length; i++) {
Node n = list.item(i);
String nodeName = n.getNodeName();
String nodeContent = n.getTextContent();
System.out.println(nodeName.toString() + " " + nodeContent.toString());
}
import com.immomo.rhizobia.rhizobia_J.xxe.XmlUtils;
//如果xml格式包含外部实体,会抛异常
XmlUtils xmlParser = XmlUtils.getInstance();
try {
TestBean testbean = (TestBean)xmlParser.converyToJavaBean(xmlFile, TestBean.class);
} catch (Exception e) {
...
}
testbean.getTo()
testbean.getFrom()
testbean.getHeading()
testbean.getBody()
import com.immomo.rhizobia.rhizobia_J.crypto.AESUtils;
AESUtils aesInstance = AESUtils.getInstance(String aesKey, String secretKey, String aesMode);
/**
参数说明:
aesKey: 用于生成密钥的原始字符串,推荐使用session/id,具有唯一性
secretKey: 加解密双方约定的secret
aesMode: 值为null时,默认采用"AES/CBC/PKCS5Padding"
*/
AESUtils aesInstance = AESUtils.getInstance("843739488","TcmEqGzSpH5S2VgoUix7HJ9cwqCofoUD",null);
String orginText = "10000";
byte[] ciphertext = aesInstance.Encrypt(orginText);
//由于返回是byte流,所以如果需要base64编码或转换成Hex,需另做处理
String encryptRet = new BASE64Encoder().encode(ciphertext);
//同样,如果加密内容用base64编码或转换成Hex,解密时需另做处理
byte[] encrypted = new BASE64Decoder().decodeBuffer(encryptRet);
String DeString = aesInstance.Decrypt(encrypted);
import com.immomo.rhizobia.rhizobia_J.crypto.RSAUtils;
RSAUtils rsaInstance = RSAUtils.getInstance(priKeyPath, pubKeyPath);
/**
参数说明:目前证书支持 PEM 格式
priKeyPath: openssl生成的私钥地址
pubKeyPath: openssl生成的公钥地址
*/
String priKeyPath = "/tmp/pri.key";
String pubKeyPath = "/tmp/pub.key";
RSAUtils rsaInstance = RSAUtils.getInstance(priKeyPath, pubKeyPath);
String plaintext = "123";
byte[] ciphertext = rsaInstance.encrypt(plaintext);
//与aes一样返回是byte流,所以如果需要base64编码或转换成Hex,需另做处理
String encryptRet = new BASE64Encoder().encode(ciphertext);
//同样,如果加密内容用base64编码或转换成Hex,解密时需另做处理
byte[] encrypted = new BASE64Decoder().decodeBuffer(encryptRet);
String plaintext = rsaInstance.decrypt(ciphertext);