360奇安信和SonarQube漏洞及bug修改

  • Post author:
  • Post category:其他




360奇安信扫描


代码注入:SQL注入:MyBatis

`#`变量名称创建参数化查询SQL语句,不会导致SQL注入。而`$`变量名称直接使用SQL指令,会导致SQL注入攻击

`#`变量名称,创建参数化查询SQL语句

此项目中出现的mybatis注入为框架自封装的数据权限方法,使用$处为将封装好的sql语句填入,并不会存才从外部注入sql的情况

跨站脚本:存储型XSS(66)

存储型XSS是指应用程序通过Web请求获取不可信赖的数据,并且在未检验数据是否存在XSS代码的情况下,将其存入数据库。当程序下一次从数据库中获取该数据时,致使页面再次执行XSS代码。存储型XSS可以持续攻击用户,在用户提交了包含XSS代码的数据存储到数据库后,每当用户在浏览网页查询对应数据库中的数据时,那些包含XSS代码的数据就会在服务器解析并加载,当浏览器读到XSS代码后,会当做正常的HTML和JS解析并执行,于是发生存储型XSS攻击

对从数据库或其它后端数据存储获取不可信赖的数据进行合理验证(如年龄只能是数字),对特殊字符(如`<、>、’、”以及\<script\>、javascript`等进行过滤。

根据数据将要置于HTML上下文中的不同位置(HTML标签、HTML属性、JavaScript脚本、CSS、URL),对所有不可信数据进行恰当的输出编码。

360奇安信扫描的错误都是后端返回时报XSS漏洞,属硬扫描漏洞,前后端有XSS过滤工具类

跨站脚本:反射型XSS(33)

反射型XSS是指应用程序通过Web请求获取不可信赖的数据,并在未检验数据是否存在恶意代码的情况下,将其发送给用户。反射型XSS一般可以由攻击者构造带有恶意代码参数的URL来实现,在构造的URL地址被打开后,其中包含的恶意代码参数被浏览器解析和执行。这种攻击的特点是非持久化,必须用户点击包含恶意代码参数的链接时才会触发

对用户的输入进行合理验证(如年龄只能是数字),对特殊字符(如`<、>、’、”以及\<script\>、javascript`等进行过滤。

根据数据将要置于HTML上下文中的不同位置(HTML标签、HTML属性、JavaScript脚本、CSS、URL),对所有不可信数据进行恰当的输出编码。

360奇安信扫描的错误都是后端返回时报XSS漏洞,属硬扫描漏洞,前后端有XSS过滤工具类

输入验证:重定向

应用程序允许未验证的用户输入控制重定向中的URL,攻击通过构建URL,使用户重定向到任意URL,利用这个漏洞可以诱使用户访问某个页面,挂马、密码记录、下载任意文件等,常被用来钓鱼。

防止重定向漏洞的方法是创建一份合法URL列表,用户只能从中进行选择,进行重定向操作。

后端url在配置文件中配置的,是固定的

输入验证:路径遍历

应用程序对用户可控制的输入未经合理校验,就传送给一个文件API。攻击者可能会使用一些特殊的字符(如`..`和`/`)摆脱受保护的限制,访问一些受保护的文件或目录

程序对非受信的用户输入做过滤和验证,对网站用户提交的文件路径进行硬编码或统一编码,过滤非法字符。

对文件后缀进行白名单控制,拒绝包含了恶意的符号或空字节。

合理配置Web服务器的目录访问权限。

增加路径名称过滤验证

输入验证:直接绑定敏感字段

目前大部分WEB框架支持将HTTP请求参数与类的属性相匹配的而生成一个对象。因此,攻击者能够将值放入HTTP请求参数中从而绑定系统对象

当程序将非将HTTP请求参数直接绑定给对象时,应该要控制绑定到对象的属性,防止暴露敏感属性。

增加敏感字段验证

输入验证:文件上传(4)

文件可能会被攻击者注入危险内容或恶意代码,当程序允许用户上传时,攻击者可以通过文件将恶意代码在服务器上运行或者将危险内容注入程序。

检查代码逻辑,判断程序是否需要文件上传。

扫描出的文件上传共有4个,都需要上传接口

代码注入:HTTP响应截断(4)

程序从一个不可信赖的数据源获取数据,未进行验证就置于HTTP头文件中发给用户,可能会导致HTTP响应截断攻击。

防止HTTP响应截断攻击的最安全的方法是创建一份安全字符白名单,只接受完全由这些受认可的字符组成的输入出现在HTTP响应头文件中。

输入验证:拒绝服务:正则表达式

正则表达式引擎分成两类:一类称为DFA(确定性有限状态自动机),另一类称为NFA(非确定性有限状态自动机)。Java使用的是NFA正则引擎,使用正则式和文本比较,每碰到一个字符,就把它跟正则式比较,匹配就记下来,然后接着往下比较。一旦不匹配,就会后退直到回到上一次匹配的地方。而不可信赖数据被传递至应用程序并作为正则表达式使用,可能导致线程过度使用 CPU 资源,从而导致拒绝服务攻击。

不要将不可信赖数据作为正则表达式使用。

代码中是“名字脱敏”字符串替换,没有用到正则表达式

输入验证:日志伪造

允许日志记录未经验证的用户输入,会导致日志伪造攻击。

防止日志伪造攻击可以采用白名单、黑名单或验证用户输入数据的方式对不可信赖的数据进行校验。

不输出具体日志

代码注入:资源注入(6)

使用用户输入控制资源标识符,借此攻击者可以访问或修改其他受保护的系统资源。当满足以下两个条件时,就会发生资源注入

为了避免资源注入漏洞攻击,可以采用黑名单或白名单策略。黑名单会有选择地拒绝或避免潜在的危险字符。但是,任何这样一份黑名单都不可能是完整的,而且将随着时间的推移而过时。比较好的方法是创建白名单,允许其中的字符出现在资源名称中,且只接受完全由这些被认可的字符所组成的输入。

输入验证:服务器端请求伪造(2)

很多Web应用提供了从其他的服务器上获取数据的功能,例如用户指定URL让Web应用加载图片,下载文件等。如果恶意利用这个功能,可以让存在缺陷的Web应用作为代理攻击远程和本地的服务器。这种形式的攻击称为服务端请求伪造攻击`(Server-side Request Forgery, SSRF)`。攻击者利用SSRF可以实现的攻击主要有5种:

1. 可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务器的banner信息;

2. 攻击运行在内网或本地的应用程序(比如溢出);

3. 对内网web应用进行指纹识别,通过访问默认文件实现;

4. 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);

5. 利用file协议读取本地文件等。

1. 过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。

2. 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。

3. 限制请求的端口为http常用的端口,比如80,443,8080,8090。

4. 禁用不需要的协议。仅仅允许http和https请求。可以防止类似于`file:///, gopher:// , ftp://` 等引起的问题。

5. 过滤内网ip,限制访问内网

输入验证:访问权限修饰符控制

AccessibleObject类是Field、Method和Constructor对象的基类,能够允许反射对象修改访问权限修饰符,绕过由Java访问修饰符提供的访问控制检查。它让程序员能够更改私有字段或调用私有方法,这在通常情况下是不允许的。

通过有权限的类更改访问权限修饰符,并确保修改的访问权限修饰符参数不能被攻击者控制。

项目中调用Excelutils等工具类时,需要把工具类中的字段变成public

代码质量:有风险的SSL:过于广泛的信任证书

由于盗用证书颁发机构的数量正在不断增加,因此即使是由CA签名的证书也不应该信任,因为拥有这些盗用证书的攻击者可能会拦截这些CA的SSL/TLS信息流

不要直接信任用户证书,应该对证书进行判断和处理

进行证书返回不为空

API误用:使用DNS名称作为安全性的依据(4)

程序中采用DNS名称进行安全认证,但DNS名称是容易被攻击者进行欺骗的

不要依赖DNS名称来做安全认证

API误用:不安全的框架绑定

目前大部分WEB框架支持将HTTP请求参数与类的属性相匹配的而生成一个对象。因此,攻击者能够将值放入HTTP请求参数中从而绑定系统对象

当程序将非将HTTP请求参数直接绑定给对象时,应该要控制绑定到对象的属性,防止暴露所有属性。

在Spring MVC中,可以配置绑定器使用`setAllowedFields`和`setDisallowedFields`方法控制属性绑定过程以控制应绑定的属性。

进行框架验证

密码管理:不安全的随机数

Java API中提供了`java.util.Random`类实现`PRNG()`,该PRNG是可移植和可重复的,如果两个`java.util.Random`类的实例使用相同的种子,会在所有Java实现中生成相同的数值序列。

在安全性要求较高的应用中,应使用更安全的随机数生成器,如`java.security.SecureRandom`类。

使用更安全的随机数

密码管理:配置文件中的明文密码(11)空密码(4)及硬编码加密密钥(4)

配置文件中采用明文存储密码,将会降低系统安全性。

配置文件中的密码应进行加密存储

资源管理:格式化缺陷

格式化对象是非线程安全的,java.text.Format中的`parse()`和`format()`方法包含一个可导致用户看到其他用户数据的race condition。

1. 将格式化对象定义成局部变量,但是每调用一次方法意味创建一个格式化对象,浪费内存。

2. 方法加同步锁synchronized,在同一时刻,只有一个线程可以执行类中的某个方法。这样性能较差,每次都要等待锁释放后其他线程才能进入。

3. 使用第三方库joda-time,由第三方考虑线程不安全的问题。

4. 使用ThreadLocal:每个线程拥有自己的格式化对象。

进行统一格式化处理

资源管理:单例成员变量

`javax.servlet.http.HttpServlet`和`org.apache.struts.action.Action`的对象不是线程安全的。对于同一个Servlet对象(或struts1的Action对象)的多个请求,Servlet对象(或struts1的Action对象)将在一个多线程的环境中并发执行。Web容器默认采用单实例多线程的方式来处理Http请求,这将导致Servlet对象(或struts1的Action对象)成员变量访问的线程安全问题。

使用Java EE的Servlet或struts1的Action时,必须保证其是线程安全的。修复方式举例如下:

使用局部变量

输入验证:JavaScript劫持(1)

使用JavaScript传送敏感数据的应用程序可能会存在JavaScript劫持的漏洞,该漏洞允许未经授权的攻击者从一个易受攻击的应用程序中读取机密数据。

JavaScript劫持可以简单的理解为模拟授权的用户,窃取用户在服务器上的信息。Web浏览器使用同源策略(Same Origin Policy),以保护用户免受恶意网站的攻击。同源策略规定:如果要使用JavaScript来访问某个网页的内容的话,则JavaScript和网页必须都来源于相同的域。若不采取同源策略,恶意网站便可以使用受害者的客户端凭证来运行 JavaScript,从其他网站加载的敏感信息,并对这些信息进行处理,然后将其返回给攻击者。 使用JSON传输数据的JavaScript应用更容易受到JavaScript劫持攻击。

尽量避免跨域的数据传输,对于同域的数据传输使用xmlhttp的方式作为数据获取的方式。如果是跨域的数据传输,必须要对敏感的数据获取做权限认证,具体的方式可以包括:

1. referer的来源限制,利用前端referer的不可伪造性来保障请求数据的应用来源于可信的地方,此种方式力度较稀,完全依赖于referer,某些情况下(如存在XSS)可能导致被绕过。

2. 加入Token。利用Token对调用者的身份进行认证,这种方式对于调用者的身份会要求力度较细,但是一旦出现XSS也可能导致前端Token的泄露,从而导致保护失效。

3. 避免直接执行JavaScript响应:在响应中加入一些额外的字符。这些响应只有经过了修改,才能成功地转到JavaScript解释器进行处理。这样可以防止攻击者使用<script>标签来进行劫持。比如,可以给响应加上注释符号,使其无法直接执行;或者是在真实的响应前面,添加死循环语句,使其无法正常的直接运行

资源管理:数据库访问控制(234)

程序未进行恰当的访问控制,执行了一个包含用户控制主键的SQL语句,可能会导致攻击者访问未经授权的记录。

任何情况下都不允许用户在没有取得相应权限的情况下获取或修改数据库中的记录。可以通过把当前被授权的用户名作为查询语句的一部分来实现

代码质量:系统信息泄露:外部

系统数据或调试信息通过网络流向远程机器时,发生外部信息泄露。

程序不应通过系统输出流或程序日志将系统数据或调试信息输出程序。

输出的系统信息,是程序员自定义的,需要返回到外部

代码质量:比较Locale相关的数据未指定适当的Locale

在比较数据时,如果可能与Locale设置相关,则应指定相应的Locale。

在比较数据时,如果可能与Locale设置相关,则应指定相应的Locale。

指定Locale

代码质量:使用getHost判断域名

使用getHost获取到的域名信息存在安全漏洞,例如:`http://127.0.0.1\.360.cn/1.htm`这个URL使用getHost得到的域名是`127.0.0.1\.360.cn`。

建议通过正则表达式校验获取到的域名,或者直接通过正则表达式获取域名

通过正则获得

代码质量:null引用

程序间接引用了可能为null的变量,从而引发空指针异常。

程序在间接引用可能为null的对象之前应对其进行判断

判空

资源管理:资源未释放:流

程序创建或分配流资源后,不进行合理释放,将会降低系统性能。攻击者可能会通过耗尽资源池的方式发起拒绝服务攻击

程序不应依赖于Java虚拟机的`finalize()`方法来自动回收流资源,而需要手动在finally代码块中进行流资源的释放。

手动关闭流


SonarQube


Cast one of the operands of this multiplication operation to a “long”.

当对整数执行算术时,结果总是整数。您可以通过自动类型转换将该结果赋给long、double或float,但如果以int或long开头,结果可能与您预期的不同。

指定类型

增加L

Use the original value instead.

调用hashCode可以返回整数。最小值。取这样一个哈希代码的绝对值,仍然会有一个负数。由于您的代码可能会假设它是正值,因此您的结果将不可靠。

abs方法不明智

转换写法

Either re-interrupt this method or rethrow the “InterruptedException”

在代码中不应忽略InterruptedException,在这种情况下,简单地记录异常将被视为“忽略”。抛出InterruptedException会清除线程的中断状态,因此如果异常处理不当,则线程被中断的事实将丢失。相反,InterruptedException应该被重新调用-立即或在清理方法的状态之后-或者通过调用线程来重新中断线程。中断(),即使这应该是一个单线程应用程序。任何其他操作过程都有延迟线程关闭的风险,并会丢失线程被中断的信息-可能没有完成其任务。

catch中增加 Thread.currentThread().interrupt();

catch中增加 Thread.currentThread().interrupt();

Cast one of the operands of this addition operation to a “double”.

当对整数执行算术时,结果总是整数。您可以通过自动类型转换将该结果赋给long、double或float,但如果以int或long开头,结果可能与您预期的不同。

指定类型

增加.0结尾,转换成double

NullPointerException” will be thrown when invoking method “internalIp()”.

对null的引用不应被解引用/访问。这样做将导致抛出NullPointerException。充其量,这种异常将导致程序突然终止。最坏的情况下,它可能会暴露对攻击者有用的调试信息,或者允许攻击者绕过安全措施。

判空

判空

Prevent “int” promotion by adding “& 0xff” to this expression.

当读取字节以构建其他基本值(如int或long)时,字节值会自动提升,但这种提升可能会产生意外的结果。

限制最大

& 0xff

Change this condition so that it does not always evaluate to “false”

始终为true或false的条件表达式可能会导致死代码。这样的代码总是有缺陷的,不应该在生产中使用。

删除一直为false代码

删除一直为false代码

Check the return value of the “read” call to see how many bytes were read.

您不能假设任何给定的流读取调用都会填充传递给该方法的字节[]。相反,您必须检查read方法返回的值,以查看读取了多少字节。否则,您将引入有害且难以复制的错误。


判断是不是读到了数据流的末尾 ,防止出现死循环。


判断是不是读到了数据流的末尾 ,防止出现死循环。

Use a logger to log this exception.

可丢弃。printStackTrace(…)打印一个可丢弃文件及其堆栈跟踪到某个流。默认情况下,该流系统。Err,这可能会无意中暴露敏感信息。

取而代之的是,应使用记录器打印一次性物品,因为它们有许多优点:

用户能够轻松检索日志。

日志消息的格式是统一的,允许用户轻松浏览日志。

当在没有参数的情况下使用printStackTrace时,即当堆栈跟踪打印到默认流时,该规则会引发一个问题。

LOGGER.log(“context”, e);

用logger日志输出

Make this member “protected”.

没有充分的理由将可变对象作为接口的公共(默认)静态成员。此类变量应移入类中,并降低其可见性。

类似地,直接访问而不是通过getter和setter访问的类和枚举的可变静态成员应该得到尽可能多的保护。这可以通过降低能见度或在适当的情况下使现场最终确定来实现。

设置成private,用getset访问

Make excludes a static final constant or non-public and provide accessors if needed.

公共类变量字段不遵守封装原则,有三个主要缺点:

无法添加其他行为,例如验证。

内部表示是公开的,以后不能更改。

成员值可能会在代码中的任何位置发生更改,并且可能不符合程序员的假设。

通过使用私有属性和访问器方法(set和get),可以防止未经授权的修改。

设置成private,用getset访问

设置成private,用getset访问

Make log a static final constant or non-public and provide accessors if needed.

公共类变量字段不遵守封装原则,有三个主要缺点:

无法添加其他行为,例如验证。

内部表示是公开的,以后不能更改。

成员值可能会在代码中的任何位置发生更改,并且可能不符合程序员的假设。

通过使用私有属性和访问器方法(set和get),可以防止未经授权的修改。

改为final

改为final

Make this “public static YYYY” field final

公共类变量字段不遵守封装原则,有三个主要缺点:

无法添加其他行为,例如验证。

内部表示是公开的,以后不能更改。

成员值可能会在代码中的任何位置发生更改,并且可能不符合程序员的假设。

通过使用私有属性和访问器方法(set和get),可以防止未经授权的修改。

固定字段用final

固定字段用final

Do something with the “boolean” value returned by “createNewFile”.

当函数调用的返回值包含操作状态代码时,应测试该值以确保操作成功完成。

使用“createNewFile”返回的“boolean”值执行操作。

操作boolean

Use Galois/Counter Mode (GCM/NoPadding) instead.

高级加密标准(AES)加密算法可用于各种模式。某些组合不安全:

电子码本(ECB)模式:在给定密钥下,任何给定的明文块始终加密到同一密文块。因此,它不能很好地隐藏数据模式。在某些意义上,它不提供严格的消息机密性,并且根本不建议在加密协议中使用。

具有PKCS#5填充(或PKCS#7)的密码块链接(CBC)容易受到填充oracle攻击。

在这两种情况下,应首选无填充的伽罗瓦/计数器模式(GCM)。

当使用ECB或CBC/PKCS5P添加模式创建密码实例时,此规则会引发问题。

解决方案

Cipher c = Cipher.getInstance(“AES/GCM/NoPadding”);

不确定加密算法

Change this code to use a stronger protocol.

当使用不安全的协议(即:不同于“TLSv1.2”或“DTLSv1.2”的协议)创建SSLContext时,该规则会引发问题。

解决方案context = SSLContext.getInstance(“TLSv1.2”);

不确定协议

Change this method so it throws exceptions.

X509TrustManager接口的空实现通常创建为允许连接到未经根证书颁发机构签名的主机。这种实现将接受任何证书,这使得应用程序容易受到中间人攻击。正确的解决方案是提供适当的信任存储。

当X509TrustManager的实现从不引发异常时,该规则会引发一个问题。

暂无解决方案



版权声明:本文为qq_60547244原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。