java安全编码规范(0)

news2024/10/6 9:21:47

JAVA安全编码标准  有这么一指导书,新手可以去看看,这里主要从实践总结,随时会更新。

 主要从十个方面去了解下,实际上远远不只这些哦。

​​​​​​​

1、引用java security library

环境需求

  • Java 8
  • Maven 3

a、编译jar包:

    mvn -Dmaven.test.skip=true clean install

b、引入java security library:

在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>

2、SQL注入防护

a、确认是连接的是哪种数据库,选择对应的数据库编码,目前支持数据库包括:MySQL Oracle DB2:

    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();

b、对sql语句中拼接的参数进行转义:

    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 ;

c、转义前后对比:

    转义前:SELECT NAME FROM users WHERE id = '1' or '1'='1' #'
    转义后:SELECT NAME FROM users WHERE id = '1\' or \'1\'\=\'1\' \#'

d、表名列名转义前后对比:

    转义前: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

3、xss防护

a、调用XssSanitiser单例:

    import com.immomo.rhizobia.rhizobia_J.xss.XssSanitiser;
    
    XssSanitiser xssFilter = XssSanitiser.getInstance();

b、如果输出到html body:

    String ret = xssFilter.encodeForHTML(oriString);

过滤前后对比:

    过滤前:<script> alert('xss') </script>
    过滤后:&lt;script&gt;alert&#x28;&#x27;xss&#x27;&#x29;&lt;&#x2f;script&gt;

c、如果输出到html标签的属性(多了对空字符的过滤):

    String ret = xssFilter.encodeForHTMLAttribute(oriString);

过滤前后对比:

    过滤前:<script> alert('xss') </script>
    过滤后:&lt;script&gt;&#x20;alert&#x28;&#x27;xss&#x27;&#x29;&#x20;&lt;&#x2f;script&gt;

d、如果输出到JavaScript代码块中:

    String ret = xssFilter.encodeForJavaScript(oriString);

过滤前后对比:

    过滤前:alert('xss');
    过滤后:alert\x28\x27xss\x27\x29\x3B

4、url重定向防护

a、调用UrlRedirectionWhiteChecher单例:

    import com.immomo.rhizobia.rhizobia_J.urlredirection.UrlRedirectionWhiteChecher;
    
    UrlRedirectionWhiteChecher urlChecker = UrlRedirectionWhiteChecher.getInstance();

b、自定义白名单:

    List<String> whitelist = new ArrayList<String>();
    String white1=".trust1.com";
    String white2=".trust2.com";
    
    //setWhiteList会先清空原有白名单列表
    //在原有基础上新增白名单,使用addWhiteList(whitelist)
    urlChecker.setWhiteList(whitelist);

c、校验url:

    try{
        boolean isWhite = urlChecker.verifyURL(url.trim());
    } catch (Exception e) {
        ...
    }

5、SSRF防护

a、调用SSRFWhiteChecker单例,与前面url重定向类似:

    import com.immomo.rhizobia.rhizobia_J.ssrf.SSRFWhiteChecker;
    
    SSRFWhiteChecker ssrfChecker = SSRFWhiteChecker.getInstance();

b、自定义白名单:

    List<String> whitelist = new ArrayList<String>();
    String white1=".trust1.com";
    String white2=".trust2.com";
    
    //setWhiteList会先清空原有白名单列表
    //在原有基础上新增白名单,使用addWhiteList(whitelist)
    ssrfChecker.setWhiteList(whitelist);

c、校验url:

    try{
        boolean isWhite = ssrfChecker.verifyURL(url.trim());
    } catch (Exception e) {
        ...
    }

6、CSRF防护

a、随机算出csrf token,并且每次生成随机值都不一样(实测结果连续生成1000亿次无重复):

    import com.immomo.rhizobia.rhizobia_J.csrf.CSRFTokenUtils;

    CSRFTokenUtils csrfInstance = CSRFTokenUtils.getInstance();
    String token = csrfInstance.resetCsrfToken(32);

b、后端保存生成的token,以待校验(可以采用数据库、分布存储等任意存储手段)

c、前端页面加上hidden字段

form中加入csrf token的hidden字段:

    <input name="${(_csrf.parameterName)!}" value="${(_csrf.token)!}" type="hidden">

ajax中加入csrf头

    xhr.setRequestHeader("${_csrf.headerName}", "${_csrf.token}");

d、当前端向后端发送请求时,请求header中携带token,后端收到后与之前存储的token进行校验

7、readObject反序列化漏洞防护

a、选择适当的构造函数初始化,自定义白名单:

使用SecureObjectInputStream中适当的构造函数,增加自定义的白名单

    import com.immomo.rhizobia.rhizobia_J.deserialization.SecureObjectInputStream;

    SecureObjectInputStream(InputStream in, String[] classlist)
    SecureObjectInputStream(InputStream in, List<String> classlist)

b、使用安全的类SecureObjectInputStream,恢复非白名单中类的对象时会抛出异常:

    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) {
        ...
    }

8、xxe防护

8.1、解析xml内容为Document

a、初始化时注意xml编码格式:

    import com.immomo.rhizobia.rhizobia_J.xxe.XmlUtils;
    //如果xml格式包含外部实体,会抛异常
    try{
        Document doc =  XmlUtils.getInstance().newDocument(xmlFile, "utf-8");
    } catch (Exception e) {
        ...
    }

b、使用生成的Document对象:

    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());
    }

8.2、解析xml内容为Bean

a、自定义TestBean,然后调用converyToJavaBean解析:

    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) {
        ...
    }

b、使用生成的bean对象:

    testbean.getTo()
    testbean.getFrom()
    testbean.getHeading()
    testbean.getBody()

9、AES加解密

知识点1:oracle官方已经在如下版本去除了aes-256的限制,6u181,7u171,8u161,9 b148,openjdk7u
                 https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8170157
 
知识点2:之所以AES、RSA没有封装base64或16进制编码处理,是因为在使用base64编码后的内容中,可能存在'+'字符,
              '+'字符返回给前端后再返回给后端时,如果不经过处理,会变为' '空格字符,
               所以请用户自行选择base64编码或16进制编码
               并在对加密内容进行base64编码时,请注意'+'字符

a、调用AESUtils:

    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);

b、加密

    String orginText = "10000";
    
    byte[] ciphertext = aesInstance.Encrypt(orginText);
    //由于返回是byte流,所以如果需要base64编码或转换成Hex,需另做处理
    String encryptRet = new BASE64Encoder().encode(ciphertext);

c、解密

    //同样,如果加密内容用base64编码或转换成Hex,解密时需另做处理
    byte[] encrypted = new BASE64Decoder().decodeBuffer(encryptRet);
    String DeString = aesInstance.Decrypt(encrypted);

10、RSA加解密 加签验签

知识点1:RSA加解密时,明文是有长度限制的,明文字符串限制长度 = 密钥长度(byte) - padding占用大小(byte)
         padding大小如下:
              RSA/ECB/PKCS1Padding or RSA             :   11
              RSA/ECB/OAEPWithSHA-1AndMGF1Padding     :   42
              RSA/ECB/OAEPWithSHA-256AndMGF1Padding   :   66
    
         例如:RSA密钥长度为1024(bit)/8 = 128(byte),keyPairGenerator.initialize(1024),
              在RSA/ECB/OAEPWithSHA-1AndMGF1Padding模式下,
              被加密的明文字符串长度不能超过 128-42 = 86
              
知识点2:同前一节aes的知识点2

知识点3:源码所用的signature类中,已经封装了摘要算法,所以可以不必再生成摘要,当然自已多生成摘要也没有问题

感谢LeadroyaL的issue

10.1、加解密

a、创建RSAUtils单例

  1. 如密钥在文件中:
    import com.immomo.rhizobia.rhizobia_J.crypto.RSAUtils;
    
    /**
    参数说明:目前证书支持 PEM 格式
        priKeyPath:  openssl生成的私钥地址
        pubKeyPath:  openssl生成的公钥地址
    */
    String priKeyPath = "/tmp/pri.key";
    String pubKeyPath = "/tmp/pub.key";
    RSAUtils rsaInstance = RSAUtils.getInstance(priKeyPath, pubKeyPath);
  1. 由于文件头尾格式有多种,根据需要调用set方法修改头尾后生成公私钥
   RSAUtils rsaInstance = RSAUtils.getInstance();
   rsaInstance.setPemPriHead("-----BEGIN PRIVATE KEY-----\n");
   rsaInstance.setPemPriEnd("-----END PRIVATE KEY-----");
   rsaInstance.setPemPubHead("-----BEGIN PUBLIC KEY-----\n");
   rsaInstance.setPemPubEnd("-----END PUBLIC KEY-----");
   rsaInstance.setPrivateKey(rsaInstance.getPrivateKey(priKeyPath));
   rsaInstance.setPublicKey(rsaInstance.getPublicKey(pubKeyPath));
  1. 如果已有公私钥,也可直接用已有密钥生成单例
    //如下为生成公私钥的例子,用户可任意选用其他方法生成公私钥
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    PublicKey rsaPublicKey = (PublicKey) keyPair.getPublic();
    PrivateKey rsaPrivateKey = (PrivateKey) keyPair.getPrivate();
    
    //生成单例
    RSAUtils rsaInstance = RSAUtils.getInstance(rsaPrivateKey, rsaPublicKey);

b、加密

    String plaintext = "123";

    //如知识点1,如果明文长度超过最大长度,可以用rsaInstance.encryptWithouLimit
    //或者自行将明文字符串拆分成对应的限制长度的块
    byte[] ciphertext = rsaInstance.encrypt(plaintext);
    
    //与aes一样返回是byte流,所以如果需要base64编码或转换成Hex,需另做处理
    String encryptRet = new BASE64Encoder().encode(ciphertext);

c、解密

    //同样,如果加密内容用base64编码或转换成Hex,解密时需另做处理
    byte[] encrypted = new BASE64Decoder().decodeBuffer(encryptRet);

    //如知识点1,如果使用了encryptWithouLimit加密,对应使用rsaInstance.decryptWithoutLimit进行解密
    String plaintext = rsaInstance.decrypt(ciphertext);

10.2、加签验签(更推荐使用ECDSA来实现加签验签,参考)

a、加签

    //原文
    String plaintext = "123";

    byte[] sigintext = rsaInstance.sign(plaintext);
    //与aes一样返回是byte流,所以如果需要base64编码或转换成Hex,需另做处理
    String signtRet = new BASE64Encoder().encode(sigintext);

b、验签

    //同样,如果加密内容用base64编码或转换成Hex,解密时需另做处理
    byte[] verified = new BASE64Decoder().decodeBuffer(signtRet);
    boolean ifPass = rsaInstance.verify(verified, plaintext);

11、ECDSA 加签验签

a、创建ECDSAUtils单例

与前面一节RSA类似,也有三种获取单例的方法

    import com.immomo.rhizobia.rhizobia_J.crypto.ECDSAUtils;

    String priKeyPath = "/tmp/ECDSAPrivateKey.key";
    String pubKeyPath = "/tmp/ECDSAPublicKey.key";
    ECDSAUtils ecInstance = ECDSAUtils.getInstance(priKeyPath, pubKeyPath);

    //ECDSAUtils.getInstance()或ECDSAUtils.getInstance(ecPrivateKey, ecPublicKey)参照前面RSA章节

b、加签

    String plaintext = "123";

    byte[] sigintext = ecInstance.sign(plaintext);
    //与aes一样返回是byte流,所以如果需要base64编码或转换成Hex,需另做处理
    String signtRet = new BASE64Encoder().encode(sigintext);

c、验签

    //同样,如果加密内容用base64编码或转换成Hex,解密时需另做处理
    byte[] verified = new BASE64Decoder().decodeBuffer(signtRet);
    boolean ifPass = ecInstance.verify(verified, plaintext);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「锂」清思绪,触达未来 | 锂电池企业如何实现数字化破局?

锂电池制造的困局与破局 锂电池行业产业链的上游主要为正负极材料、电解液、电极基材、隔膜等领域的供应商&#xff1b;中游为电芯制造及封装行业&#xff1b;下游则主要是动力电池、消费电子等锂电池的应用领域。 图1&#xff1a;锂电池行业产业链 近年来&#xff0c;随着相…

虹科方案 | 适用于高压环境或潜在爆炸性环境的加速度计系统

PART 1 加速度系统 加速度计系统通常用于测量振动或运动。测量系统能够记录一个、两个或三个空间方向的运动。所实际使用的传感器是光纤传感器&#xff0c;可提供不受电磁干扰影响的可靠测量值。当然&#xff0c;这样的系统具有高可靠性&#xff0c;即使在不断变化的天气条件下…

转置卷积(Transposed Convolution)可视化过程

目录 1. 介绍2. 标准卷积3. 转置卷积4. 总结 1. 介绍 转置卷积&#xff08;Transposed Convolution&#xff09;经常也被称作反卷积&#xff0c;所谓反卷积即为通过标准卷积层生成的输出被反卷积&#xff0c;将得到原始输入。而转置卷积不按值反转标准卷积&#xff0c;而仅按维…

STM32F4_待机唤醒详解

目录 1. 低功耗模式 1.1 降低系统时钟速度 1.2 外设时钟门控 2. 睡眠模式 2.1 进入睡眠模式 2.2 退出休眠模式 3. 停止模式 3.1 进入停止模式 3.2 退出停止模式 4. 待机模式 4.1 进入待机模式 4.2 退出待机模式 4.3 电源控制寄存器&#xff1a;PWR_CR 4.4 电源控…

‘OpenpyxlWriter‘ object has no attribute ‘save‘

使用read_sql(sql,conn)来获取数据库查询的结果&#xff0c; 在将处理完成的表格保存下来时&#xff0c;可能会显示如下错误&#xff1a; 将writer.save()改成writer._save()就可以解决这个问题了。

必须了解的mysql三大日志-binlog、redo log和undo log

目录 一&#xff0c;前言二&#xff0c;binlog-备份日志1&#xff0c;作用2&#xff0c;使用场景3&#xff0c;日志形式4&#xff0c;binlog刷盘时机 三&#xff0c;redo log-重做日志1&#xff0c;概念2&#xff0c;为什么需要redo log3&#xff0c;日志形式4&#xff0c;redo…

数据结构之树(一)

一.概念 边:一棵n个结点树有n-1条边 结点深度&#xff1a;从根到当前结点的路径的深度。 结点高度&#xff1a;从当前结点到叶子结点最长路径的长度。 树的性质 树中的结点总数等于所有结点的度1&#xff1b;m叉树中第i(i>1)层上至多可以有m^(i-1)个节点&#xff1b; 高…

互联网大厂手把手教你搭建数据服务中台(附下载链接)

摘要: 随着公司业务的发展&#xff0c;对于数据的需求会越来越多。怎么在业务系统中高效的使用数据&#xff0c;让业务系统处理大数据时化繁为简&#xff0c;数据服务化基本是必经之路。那么什么是数据服务化&#xff0c;简单理解就是数据SaaS&#xff0c;通过一些数据库语言把…

true or false?

有同学在星球问了这样一个问题。 代码是这样的&#xff1a; public class Main {private static final Main instance new Main();private boolean b a;private static boolean a initA();private static boolean c a;private static boolean initA() {return true;}priva…

洛谷B2099 矩阵交换行

矩阵交换行 题目描述 给定一个 5 5 5 \times 5 55 的矩阵(数学上&#xff0c;一个 r c r \times c rc 的矩阵是一个由 r r r 行 c c c 列元素排列成的矩形阵列)&#xff0c;将第 n n n 行和第 m m m 行交换&#xff0c;输出交换后的结果。 输入格式 输入共 6 6 6 …

DataEase 本地源码启动详细教程

本教程将引导你通过本地源码部署的方式启动 DataEase&#xff0c;同时我还录制了相应的视频教程&#xff0c;你可以跟随视频进行操作&#xff1a; DataEase 本地源码启动_哔哩哔哩_bilibili 1、下载并安装IDEA开发工具 2、下载安装Mysql 5.7 以及 JDK 1.8 如果你使用的是wi…

使用pdf.js展示pdf文件(亲测可用)

简单的实现方式 如果只是电脑端&#xff0c;可通过 iframe 标签嵌套预览 ios手机端可通过 a 标签包裹点击跳转预览&#xff08;安卓端不行&#xff09; 安卓电脑ios的通用方法 资料 老版本github地址 全版本地址 获取当前客户端类型 judgeClient() {let client if (/(iPh…

鲁大师智能化评测新项目——鲁大师真续航测试1.0正式发布

随着社会的高速发展&#xff0c;人们出行的交通工具正变得多种多样&#xff0c;有电单车、摩托车、自行车、两轮平衡车、甚至滑板等。不过如我们所见&#xff0c;电动两轮车已经成为了大多数近途出行用户的选择&#xff0c;因电单车具有方便、快捷、灵活、小巧、易停放等优点而…

MySQL基础篇4

MySQL基础 1. 数据类型1.1 整数类型1.2 浮点类型1.3 定点数类型1.4 位类型1.5 日期时间类型1.6 文本字符串类型1.6.1 CHAR类型和VARCHAR类型1.6.2 TEXT类型 1.7 ENUM枚举类型1.8 SET类型1.9 二进制字符串类型1.10 JSON数据类型 2. 约束2.1 前置知识2.1.1 为什么需要约束2.1.2 约…

亚马逊云科技围绕需求发力,赋能医疗与生命科学行业数字化创新

2023年4月27日&#xff0c;亚马逊云科技医疗与生命科学行业峰会召开&#xff0c;会议汇聚了业界专家和思想领袖&#xff0c;共同探讨行业数字化转型和创新之道。作为全球医疗及生命科学行业云计算引领者&#xff0c;亚马逊云科技将围绕数据、算力和行业用户体验三大需求发力&am…

移远“5G+Wi-Fi 6”方案双重加速,为用户带来更具性价比的连网体验

近年来&#xff0c;人们对于高速宽带连接的需求猛增&#xff0c;这对网络传输速率、稳定性与时延都提出了更高的要求。在离开网络寸步难行的今天&#xff0c;插电即用、免拉宽带的5G CPE受到了广泛关注。 在地广人稀的部分海外市场&#xff0c;受制于光纤铺设成本、周期、路由规…

Day966.从组件团队到Spotify模型 -遗留系统现代化实战

从组件团队到Spotify模型 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于从组件团队到Spotify模型的内容。 团队结构现代化。这个方向跟管理有关&#xff0c;但无论掌控全局的 CTO、架构师&#xff0c;还是身处遗留系统一线战队的队员&#xff0c;都有必要了解现代…

JavaScript - 基础+WebAPI(笔记)

前言&#xff1a; 求关注&#x1f62d; 本篇文章主要记录以下几部分&#xff1a; 基础&#xff1a; 输入输出语法&#xff1b;数据类型&#xff1b;运算符&#xff1b;流程控制 - 分支语句&#xff1b;流程控制 - 循环语句&#xff1b;数组 - 基础&#xff1b;函数 - 基础&…

idm下载器2024官方最新中文版免费下载

哈喽大家好呀&#xff0c;coco玛奇朵发现我已经有一阵子没有给大家分享windows软件了&#xff0c;今天给大家分享一款暗藏惊喜的windows软件&#xff0c;用过之后真的很难拒绝&#xff01; 这是一个可以帮你提升下载速度的工具&#xff0c;有了它几秒就能帮你下载好各种资源。…

UNIAPP实战项目笔记64 当前用户修改收货地址的前端和后端

UNIAPP实战项目笔记64 当前用户修改收货地址的前端和后端 思路 默认地址的修改&#xff0c;先清空当前id下的所有默认地址&#xff0c;再将新地址设为默认 前端 将新值传给后端 后端接受值后更新处理 实例截图 代码 后端 index.js var express require(express); var route…