Findbugs代码审计

Findbugs代码审计
 
Findbugs
    1. 简介
      1. 该插件可以与各种开发工具集成。它可以在Eclipse、 IntelliJ和 Netbeans 中使用它们各自的 FindBugs 插件。
      2. 它还可以用于Jenkins 和Sonar等持续集成。
      3. Spring-MVC、Struts、Tapestry 
      4. 138种漏洞类型
      5. 开源的
    2. 目录
    3. 漏洞:
        1. 密码 csrftoken 推荐 java.security.SecureRandom.
        1. 使用 java.security.SecureRandom.
        1. Servlet 可以从各种方法读取 GET 和 POST 参数。获得的值应该被认为是不安全的。您可能需要先验证或清理这些值,然后再将它们传递给敏感的 API,例如:
        2. SQL 查询(可能导致 SQL 注入)
        3. 文件打开(可能导致路径遍历)
        4. 命令执行(Potential Command injection)
        5. HTML 构造(潜在 XSS)
        6. 等等...
        1. HTTP 头 Content-Type 可以由客户端控制。因此,不应在任何安全关键决策中使用其值。
        1. 主机名标头可由客户端控制。因此,不应在任何安全关键决策中使用其值。二者ServletRequest.getServerName()并HttpServletRequest.getHeader("Host")具有相同的行为,这是提取Host标题。
        1. 该方法HttpServletRequest.getRequestedSessionId() 通常返回 cookie 的值JSESSIONID。这个值通常只能由会话管理逻辑访问,而不是普通的开发人员代码。
        2. 因此,JSESSIONID 应仅用于查看其值是否与现有会话 ID 匹配。如果不是,则用户应被视为未经身份验证的用户。此外,不应记录会话 ID 值。如果是,则日志文件可能包含有效的活动会话 ID,从而允许内部人员劫持其 ID 已被记录且仍处于活动状态的任何会话。
        1. 查询字符串是 GET 参数名称和值的串联。可以传入非预期参数。
        2. 对于 URL 请求/app/servlet.htm?a=1&b=2,查询字符串提取将是a=1&b=2
        3. 就像通过诸如 之类HttpServletRequest.getParameter()、HttpServletRequest.getQueryString()的方法检索的单个参数值一样,从中获得的值应该被认为是不安全的。在将查询字符串传递给敏感 API 之前,您可能需要验证或清理从查询字符串中提取的任何内容。
        1. 请求头可以很容易地被请求的用户改变。一般而言,不应假设请求来自常规浏览器而未经攻击者修改。因此,建议您不要在针对请求做出的任何安全决策中信任此值。
        1. 行为:
          1. 如果请求来自恶意用户,则可以为该标头分配任何值。
          2. 如果请求是从另一个安全源 (HTTPS) 发起的,则“Referer”将不存在。
        2. 建议:
          1. 不应基于此标头的值进行访问控制。
          2. 没有 CSRF 保护应仅基于此值(因为它是可选的)。
        1. 标头“User-Agent”很容易被客户端欺骗。不建议根据 User-Agent(对于爬虫 UA)采用不同的行为。
        1. Cookie中不应存在敏感信息
        1. 打开文件以读取其内容。文件名来自输入参数。如果将未经过滤的参数传递给此文件 API,则可以读取来自任意文件系统位置的文件。
        2. 此规则识别潜在的路径遍历漏洞。在很多情况下,构建的文件路径是用户无法控制的。如果是这种情况,则报告的实例是误报
        3. 错误代码,image 参数未仅过滤
          1. @GET@Path("/images/{image}")@Produces("images/*")public Response getImage(@javax.ws.rs.PathParam("image") String image) {
          2. File file = new File("resources/images/", image); //Weak point
          3.  
          4. if (!file.exists()) {
          5. return Response.status(Status.NOT_FOUND).build();
          6. }
          7.  
          8. return Response.ok().entity(new FileInputStream(file)).build();}
          9.  
        4. 修复方式,使用
          1. 修复方式,使用org.apache.commons.io.FilenameUtils处理文件名
            1. import org.apache.commons.io.FilenameUtils;
               
              @GET@Path("/images/{image}")@Produces("images/*")public Response getImage(@javax.ws.rs.PathParam("image") String image) {
              File file = new File("resources/images/", FilenameUtils.getName(image)); //Fix
               
              if (!file.exists()) {
              return Response.status(Status.NOT_FOUND).build();
              }
               
              return Response.ok().entity(new FileInputStream(file)).build();
        1. 打开文件以写入其内容。文件名来自输入参数。如果将未过滤的参数传递给此文件 API,则可以修改任意文件系统位置的文件。
        2. 此规则识别潜在的路径遍历漏洞。在很多情况下,构建的文件路径是用户无法控制的。如果是这种情况,则报告的实例是误报
        3. 路径遍历攻击(也称为目录遍历)旨在访问存储在 Web 根文件夹之外的文件和目录。通过操作引用带有“点-点-斜线 (../)”序列及其变体的文件的变量或使用绝对文件路径,可以访问存储在文件系统上的任意文件和目录,包括应用程序源代码或配置和关键系统文件
        1. 打开文件以读取其内容。文件名来自输入参数。如果将未经过滤的参数传递给此文件 API,则可以读取来自任意文件系统位置的文件。
        2. 此规则识别潜在的路径遍历漏洞。在很多情况下,构建的文件路径是用户无法控制的。如果是这种情况,则报告的实例是误报。
        3. 问题代码
          1. def getWordList(value:String) = Action {
            if (!Files.exists(Paths.get("public/lists/" + value))) {
            NotFound("File not found")
            } else {
            val result = Source.fromFile("public/lists/" + value).getLines().mkString // Weak point
            Ok(result)
            }
          2.  
        4. 同上也是通过import org.apache.commons.io.FilenameUtils;处理未经处理的参数
        1. exec的 API 用于执行系统命令。如果将未经过滤的输入传递给此 API,则可能导致任意命令执行。
        2. 问题代码
          1. import java.lang.Runtime;
          2.  
          3. Runtime r = Runtime.getRuntime();
          4. r.exec("/bin/sh -c some_tool" + input);
        1. value 为传入的参数,执行系统命令前未过滤参数
        2. 问题代码
          1. def executeCommand(value:String) = Action {
          2. val result = value.!
          3. Ok("Result: "+result)}
        1. 某些FilenameUtils'方法不过滤 NULL 字节 ( 0x00)。,文件名被00字符阶段,将造成文件名绕过校验
        2. 修复
          1. 升级到 Java 7 update 40 或更高版本,或 Java 8+,因为 文件名中的 NULL 字节注入在这些版本中是固定的
          2. 强烈验证不受信任的用户提供的任何文件名,以确保它们有效(即,不包含空值、不包含路径字符等)。
        1. 空的 TrustManager 实现通常用于轻松连接到未由根证书颁发机构签名的主机 。因此,这很容易受到 中间人攻击, 因为客户端将信任任何证书。
        2. 应该构建允许特定证书(例如基于 TrustStore)的 TrustManager。
        3. 问题代码
          1. class TrustAllManager implements X509TrustManager {
          2.  
          3. @Override
          4. public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
          5. //Trust any client connecting (no certificate validation)
          6. }
          7.  
          8. @Override
          9. public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
          10. //Trust any remote server (no certificate validation)
          11. }
          12.  
          13. @Override
          14. public X509Certificate[] getAcceptedIssuers() {
          15. return null;
          16. }}
        4. 解决方案, (基于密钥库的 TrustManger)
          1. KeyStore ks = //Load keystore containing the certificates trusted
          2.  
          3. SSLContext sc = SSLContext.getInstance("TLS");
          4.  
          5. TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
          6. tmf.init(ks);
          7.  
          8. sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);
        1. HostnameVerifier由于证书在许多主机上重用,因此经常使用接受任何主机的A。因此,这很容易受到 中间人攻击, 因为客户端将信任任何证书。
        2. 应该构建允许特定证书(例如基于信任库)的 TrustManager。应创建通配符证书以在多个子域上重复使用。有关正确实施的详细信息,请访问: [1] [2]
        3. 易受攻击的代码:
          1. public class AllHosts implements HostnameVerifier {
          2. public boolean verify(final String hostname, final SSLSession session) {
          3. return true;
          4. }}
        4. 解决方案(基于密钥库的TrustManger)
          1. KeyStore ks = //Load keystore containing the certificates trusted
          2.  
          3. SSLContext sc = SSLContext.getInstance("TLS");
          4.  
          5. TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
          6. tmf.init(ks);
          7.  
          8. sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);
          9.  
        1. soap web 服务
          1. 应分析此 Web 服务的安全性。例如:
          2. 如果强制执行身份验证,则应进行测试。
          3. 如果实施了访问控制,则应进行测试。
          4. 应跟踪输入的潜在漏洞。
          5. 理想情况下,通信应该通过 SSL。
        1. 前后端分离的web
          1. 应分析此 Web 服务的安全性。例如:
          2. 如果强制执行身份验证,则应进行测试。
          3. 如果实施了访问控制,则应进行测试。
          4. 应跟踪输入的潜在漏洞。
          5. 理想情况下,通信应该通过 SSL。
          6. 如果服务支持写入(例如,通过 POST),则应调查其对 CSRF 的脆弱性。
        1. 在应用程序启动时发现了 Tapestry 端点。Tapestry 应用程序由一个支持 Java 类和.tml每个页面对应的 Tapestry 标记语言页面(一个文件)构成。收到请求后,GET/POST 参数将映射到支持 Java 类中的特定输入。映射要么使用字段名称完成:
        2. 示例
          1.  
          2.  
          3. [...]
          4. protected String input;
          5. [...]
        3. 显示注释
          1.  
          2.  
          3. [...]
          4. @org.apache.tapestry5.annotations.Parameter
          5. protected String parameter1;
          6.  
          7. @org.apache.tapestry5.annotations.Component(id = "password")
          8. private PasswordField passwordField;
          9. [...]
        4. 页面被映射到视图/resources/package/PageName.tml。
        5. 应研究此应用程序中的每个 Tapestry 页面,以确保以这种方式自动映射的所有输入在使用之前都经过正确验证。
        1. 此类表示 Wicket WebPage。输入是从传递给构造函数的 PageParameters 实例中自动读取的。当前页面被映射到视图/package/WebPageName.html。
        2. 应研究此应用程序中的每个 Wicket 页面,以确保以这种方式自动映射的所有输入在使用之前都经过正确验证。
        1. 算法 MD2、MD4 和 MD5 不是推荐的 MessageDigest。例如,应该使用PBKDF2来散列密码。
        2. “MD5 哈希函数的安全性受到严重损害。存在碰撞攻击,它可以在具有 2.6 GHz Pentium 4 处理器(复杂度为 2 24.1)的计算机上在几秒钟内发现碰撞。[1] 此外,还有一个选择-前缀冲突攻击,可以使用现成的计算硬件(复杂度 2 39)在数小时内为具有指定前缀的两个输入产生冲突。[2]” 
        3. “ SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224 和 SHA-512/256:
        4. 所有散列函数应用程序都可以接受使用这些散列函数。” 
        5. “PBKDF 的主要思想是通过增加测试每个密码所需的时间来减慢对密码的字典或蛮力攻击。拥有可能密码列表的攻击者可以使用已知的迭代计数器和盐来评估 PBKDF。由于攻击者每次尝试都必须花费大量计算时间,因此应用字典或蛮力攻击变得更加困难。” 
        6. 推荐
          1. public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
          2. KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 4096, 256 * 8);
          3. SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
          4. return f.generateSecret(spec).getEncoded();}
        1. 算法 SHA-1 不是用于哈希密码、签名验证和其他用途的推荐算法。例如,应该使用PBKDF2来散列密码。
        2. “ SHA-1用于数字签名生成:
          1. SHA-1可仅被用于数字签名生成,其中特别是通过特定于协议的NIST指导允许对于所有其他应用程序,。SHA-1不得用于数字签名生成。
        3. SHA-1对于数字签名验证:
          1. 对于数字签名验证,允许使用 SHA-1。
          2. [...] 
          3. SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224 和 SHA- 512/256:
        4. 所有散列函数应用程序都可以使用这些散列函数。” 
        1. 易受攻击的代码
          1. HttpClient client = new DefaultHttpClient();
        2. 解决办法
          1. 升级您的实现以使用推荐的构造之一并配置https.protocolsJVM 选项以包含 TLSv1.2:
            1. 使用SystemDefaultHttpClient代替HttpClient client = new SystemDefaultHttpClient();
            2. 创建一个基于 SSLSocketFactory 的 HttpClient - 获取一个 SSLScoketFactory 实例getSystemSocketFactory()并使用这个实例来创建 HttpClient
            3. 创建一个基于 SSLConnectionSocketFactory 的 HttpClient - 获取一个实例getSystemSocketFactory()并使用这个实例来创建 HttpClient
            4. 使用 HttpClientBuilder - 调用useSystemProperties()前调用build()  如:HttpClient client = HttpClientBuilder.create().useSystemProperties().build();
            5. HttpClients - 调用createSystem()以创建实例
              1. 示例代码:HttpClient client = HttpClients.createSystem();
        1. 易受攻击的代码
          1. SSLContext.getInstance("SSL");
        2. 解决方案:
          1. 将您的实现升级到以下内容,并配置https.protocolsJVM 选项以包含 TLSv1.2:
            1. SSLContext.getInstance("TLS");
        1. 实现自定义 MessageDigest 容易出错。
        2. NIST建议使用 SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224 或 SHA-512/256。
        3. 易受攻击的代码
          1. MyProprietaryMessageDigest extends MessageDigest {
          2. @Override
          3. protected byte[] engineDigest() {
          4. [...]
          5. //Creativity is a bad idea
          6. return [...];
          7. }}
        4. 解决方案,使用已批准的算法,如
          1. MessageDigest sha256Digest = MessageDigest.getInstance("SHA256");
          2. sha256Digest.update(password.getBytes());
        1. FileUpload API 提供的文件名可以被客户端篡改以引用未经授权的文件。
        2. "../../../config/overide_file"
        3. "shell.jspu0000expected.gif"
        4. 因此,不应将此类值直接传递给文件系统 API。如果可以接受,应用程序应生成自己的文件名并使用这些文件名。否则,应正确验证提供的文件名,以确保其结构正确,不包含未经授权的路径字符(例如 /),并指代授权文件。
        1. 正则表达式 (Regex) 经常受到拒绝服务 (DOS) 攻击(称为 ReDOS)。这是因为正则表达式引擎在分析某些字符串时可能会花费大量时间,具体取决于正则表达式的定义方式。
        2. 例如,对于 regex: ^(a+)+$,输入“ aaaaaaaaaaaaaaaaX”将导致 regex 引擎分析 65536 条不同的路径, 因此,单个请求可能会导致服务器端的大量计算
        1. 当 XML 解析器在处理从不受信任的来源接收的 XML 时支持 XML 实体时,可能会发生 XML 外部实体 (XXE) 攻击。
        2. 风险1:公开本地文件内容
          1. <?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [
          2. <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]><foo>&xxe;</foo>
        3. 风险2:拒绝服务
          1. <?xml version="1.0"?><!DOCTYPE lolz [
          2. <!ENTITY lol "lol">
          3. <!ELEMENT lolz (#PCDATA)>
          4. <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
          5. <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
          6. <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">[...]
          7. <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]><lolz>&lol9;</lolz>
        4. 解决方案
          1. 为了避免暴露 XML 解析器的危险特性,您可以对代码进行以下更改。
          2. 易受攻击的代码
            1. public void parseXML(InputStream input) throws XMLStreamException {
            2.  
            3. XMLInputFactory factory = XMLInputFactory.newFactory();
            4. XMLStreamReader reader = factory.createXMLStreamReader(input);
            5. [...]}
          3. 禁用外部实体的解决方案:
            1. public void parseXML(InputStream input) throws XMLStreamException {
            2.  
            3. XMLInputFactory factory = XMLInputFactory.newFactory();
            4. factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
            5. XMLStreamReader reader = factory.createXMLStreamReader(input);
            6. [...]}
          4. 禁用 DTD 的解决方案:
            1. public void parseXML(InputStream input) throws XMLStreamException {
            2.  
            3. XMLInputFactory factory = XMLInputFactory.newFactory();
            4. factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
            5. XMLStreamReader reader = factory.createXMLStreamReader(input);
            6. [...]}
        1. 当 XML 解析器在处理从不受信任的来源接收的 XML 时支持 XML 实体时,可能会发生 XML 外部实体 (XXE) 攻击。
        2. 风险1:公开本地文件内容
        3. 风险2:拒绝服务
        4. 解决方案
          1. 易受攻击的代码:
            1. DocumentBuilder builder = df.newDocumentBuilder();
            2.  
            3. XPathFactory xPathFactory = XPathFactory.newInstance();
            4. XPath xpath = xPathFactory.newXPath();
            5. XPathExpression xPathExpr = xpath.compile("/somepath/text()");
            6.  
            7. xPathExpr.evaluate(new InputSource(inputStream));
          2. 使用“安全处理”模式的解决方案
            1. 此设置将保护您免受拒绝服务攻击和远程文件访问
            2. DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
            3. df.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
            4. DocumentBuilder builder = df.newDocumentBuilder();
            5.  
            6. [...]
            7.  
            8. xPathExpr.evaluate( builder.parse(inputStream) );
          3. 禁用DTD的解决方案
            1. 通过禁用 DTD,几乎所有的 XXE 攻击都将被阻止。
            2. DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
            3. DocumentBuilder builder = df.newDocumentBuilder();
            4.  
            5. [...]
            6.  
            7. xPathExpr.evaluate( builder.parse(inputStream) );
        1. 当 XML 解析器在处理从不受信任的来源接收的 XML 时支持 XML 实体时,可能会发生 XML 外部实体 (XXE) 攻击
        2. 风险1:公开本地文件内容
        3. 风险2:拒绝服务
        4. 解决方案
          1. 易受攻击的代码
            1. SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            2.  
            3. parser.parse(inputStream, customHandler);
          2. 使用“安全处理”模式的解决方案
            1. 此设置将保护您免受拒绝服务攻击和远程文件访问
            2. SAXParserFactory spf = SAXParserFactory.newInstance();
            3. spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);SAXParser parser = spf.newSAXParser();
            4.  
            5. parser.parse(inputStream, customHandler);
          3. 禁用DTD的方案
            1. 通过禁用DTD,几乎所有的XXE攻击都将被阻止
            2. SAXParserFactory spf = SAXParserFactory.newInstance();
            3. spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);SAXParser parser = spf.newSAXParser();
            4.  
            5. parser.parse(inputStream, customHandler);
        1. 当 XML 解析器在处理从不受信任的来源接收的 XML 时支持 XML 实体时,可能会发生 XML 外部实体 (XXE) 攻击。
        2. 风险1:公开本地文件内容
        3. 风险2:拒绝服务
        4. 易受攻击的代码
          1. XMLReader reader = XMLReaderFactory.createXMLReader();
          2. reader.setContentHandler(customHandler);
          3. reader.parse(new InputSource(inputStream));
        5. 使用安全模式的解决方案
          1. 此设置将保护您免受拒绝服务攻击和远程文件访问。
          2. XMLReader reader = XMLReaderFactory.createXMLReader();
          3. reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
          4. reader.setContentHandler(customHandler);
          5.  
          6. reader.parse(new InputSource(inputStream));
        6. 禁用 DTD 的解决方案:
          1. 通过禁用 DTD,几乎所有的 XXE 攻击都将被阻止。
          2. XMLReader reader = XMLReaderFactory.createXMLReader();
          3. reader.setContentHandler(customHandler);
          4.  
          5. reader.parse(new InputSource(inputStream));
        1. 当 XML 解析器在处理从不受信任的来源接收的 XML 时支持 XML 实体时,可能会发生 XML 外部实体 (XXE) 攻击。
        2. 风险1:公开本地文件内容
        3. 风险2:拒绝服务
        4. 易受攻击的代码:
          1. DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
          2.  
          3. Document doc = db.parse(input);
        5. 使用“安全处理”模式的解决方案:
          1. 此设置将保护您免受拒绝服务攻击和远程文件访问。
          2. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
          3. dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);DocumentBuilder db = dbf.newDocumentBuilder();
          4.  
          5. Document doc = db.parse(input);
        6. 禁用 DTD 的解决方案:
          1. 通过禁用 DTD,几乎所有的 XXE 攻击都将被阻止。
          2. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
          3. dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);DocumentBuilder db = dbf.newDocumentBuilder();
          4.  
          5. Document doc = db.parse(input);
        1. 当 XML 解析器在处理从不受信任的来源接收的 XML 时支持 XML 实体时,可能会发生 XML 外部实体 (XXE) 攻击。
        2. 风险1:公开本地文件内容
        3. 风险2:拒绝服务
        4. 易受攻击的代码
          1. Transformer transformer = TransformerFactory.newInstance().newTransformer();
          2. transformer.transform(input, result);
        5. 使用安全处理模式的解决方案
          1. 此设置将保护您免受远程文件访问,但不会拒绝服务。
          2. TransformerFactory factory = TransformerFactory.newInstance();
          3. factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "all");
          4. factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "all");
          5.  
          6. Transformer transformer = factory.newTransformer();
          7. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
          8.  
          9. transformer.transform(input, result);
        6. 禁用DTD的解决方案
          1. 此设置将保护您免受远程文件访问,但不会拒绝服务。
          2. TransformerFactory factory = TransformerFactory.newInstance();
          3. factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
          4.  
          5. Transformer transformer = factory.newTransformer();
          6. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
          7.  
          8. transformer.transform(input, result);
        1. XSLT 外部实体 (XXE) 攻击可能发生在 XSLT 解析器在处理从不受信任的来源接收的 XSLT 时支持外部实体。
        2. 风险:公开本地文件内容
          1. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          2. <xsl:template match="/">
          3. <xsl:value-of select="document('/etc/passwd')">
          4. </xsl:value-of></xsl:template></xsl:stylesheet>
        3. 易受攻击的代码:
          1. Transformer transformer = TransformerFactory.newInstance().newTransformer();
          2. transformer.transform(input, result);
        4. 使用“安全处理”模式的解决方案:
          1. 此设置将保护您免受远程文件访问,但不会拒绝服务。
          2. TransformerFactory factory = TransformerFactory.newInstance();
          3. factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "all");
          4. factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "all");
          5.  
          6. Transformer transformer = factory.newTransformer();
          7. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
          8.  
          9. transformer.transform(input, result);
        5. 禁用 DTD 的解决方案:
          1. 此设置将保护您免受远程文件访问,但不会拒绝服务。
            1. TransformerFactory factory = TransformerFactory.newInstance();
            2. factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
            3.  
            4. Transformer transformer = factory.newTransformer();
            5. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            6.  
            7. transformer.transform(input, result);
        1. XPath 注入风险类似于 SQL 注入。如果 XPath 查询包含不受信任的用户输入,则可能会暴露完整的数据源。这可能允许攻击者访问未经授权的数据或恶意修改目标 XML。
        1. 这个类是一个 Struts 1 Action。
        2. 一旦请求被路由到这个控制器,一个包含 HTTP 参数的 Form 对象将被自动实例化。应审查这些参数的使用,以确保它们被安全使用。
        1. 在 Struts 2 中,端点是普通旧 Java 对象 (POJO),这意味着不需要实现/扩展接口/类。
        2. 当一个请求被路由到它的控制器(比如被选择的类)时,提供的 HTTP 参数会自动映射到该类的 setter。因此,即使表单不包含这些值,此类的所有 setter 也应被视为不受信任的输入。攻击者可以简单地在请求中提供额外的值,并且无论如何都会在对象中设置这些值,只要该对象具有这样的设置器。应审查这些参数的使用,以确保它们被安全使用。
        1. 这个类是一个 Spring 控制器。带注释的所有方法RequestMapping(以及它的快捷方式的注释GetMapping,PostMapping,PutMapping,DeleteMapping,和PatchMapping)可达远程。应分析此类以确保远程公开的方法可以安全地暴露给潜在的攻击者。
        1. 禁用 Spring Security 的 CSRF 保护对于标准 Web 应用程序是不安全的。
        2. 禁用此保护的有效用例是暴露状态更改操作的服务,该操作保证仅由非浏览器客户端使用。
        3. 不安全的配置:
          1. @EnableWebSecuritypublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {
          2.  
          3. @Override
          4. protected void configure(HttpSecurity http) throws Exception {
          5. http.csrf().disable();
          6. }}
        1. 注释的方法RequestMapping默认映射到所有 HTTP 请求方法。
        2. 然而,Spring Security的CSRF保护默认情况下,不为HTTP请求方法激活GET,HEAD,TRACE,和OPTIONS (因为这可能导致令牌被泄露)。因此,状态改变方法被注解RequestMapping而不是缩小映射到 HTTP ,请求方法POST、PUT、DELETE、 或PATCH 容易受到 CSRF 攻击。
        3. 易受攻击的代码:
          1. @Controllerpublic class UnsafeController {
          2.  
          3. @RequestMapping("/path")
          4. public void writeData() {
          5. // State-changing operations performed within this method.
          6. }}
        4. 解决方案(Spring Framework 4.3 及更高版本):
          1. @Controllerpublic class SafeController {
          2.  
          3. /**
          4. * For methods without side-effects use @GetMapping.
          5. */
          6. @GetMapping("/path")
          7. public String readData() {
          8. // No state-changing operations performed within this method.
          9. return "";
          10. }
          11.  
          12. /**
          13. * For state-changing methods use either @PostMapping, @PutMapping, @DeleteMapping, or @PatchMapping.
          14. */
          15. @PostMapping("/path")
          16. public void writeData() {
          17. // State-changing operations performed within this method.
          18. }}
        5. 解决方案(Spring Framework 4.3 之前):
          1. @Controllerpublic class SafeController {
          2.  
          3. /**
          4. * For methods without side-effects use either
          5. * RequestMethod.GET, RequestMethod.HEAD, RequestMethod.TRACE, or RequestMethod.OPTIONS.
          6. */
          7. @RequestMapping(value = "/path", method = RequestMethod.GET)
          8. public String readData() {
          9. // No state-changing operations performed within this method.
          10. return "";
          11. }
          12.  
          13. /**
          14. * For state-changing methods use either
          15. * RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, or RequestMethod.PATCH.
          16. */
          17. @RequestMapping(value = "/path", method = RequestMethod.POST)
          18. public void writeData() {
          19. // State-changing operations performed within this method.
          20. }}
          21.  
        1. 确定的方法易于注入。输入应经过验证并正确转义
        2. 易受攻击的代码示例
          1. SqlUtil.execQuery("select * from UserEntity t where id = " + parameterInput);
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。作为准备语句的替代方法,每个参数都可以手动转义。
        2. 易受攻击的代码
          1. createQuery("select * from User where id = '"+inputId+"'");
        3. 解决方案
          1. import org.owasp.esapi.Encoder;
          2.  
          3. createQuery("select * from User where id = '"+Encoder.encodeForSQL(inputId)+"'");
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。Turbine API 提供了一个 DSL 来使用 Java 代码构建查询。
        2. 易受攻击的代码
          1. List<Record> BasePeer.executeQuery( "select * from Customer where id=" + inputId );
        3. 解决方案
          1. 使用Criteria DSL
            1. Criteria c = new Criteria();
            2. c.add( CustomerPeer.ID, inputId );
            3.  
            4. List<Customer> customers = CustomerPeer.doSelect( c );
          2. 使用专门方法
            1. Customer customer = CustomerPeer.retrieveByPK( new NumberKey( inputId ) );
          3. OWASP编码器
            1. import org.owasp.esapi.Encoder;
            2.  
            3. BasePeer.executeQuery("select * from Customer where id = '"+Encoder.encodeForSQL(inputId)+"'");
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。作为准备语句的替代方法,可以使用 Hibernate Criteria。
        2. 易受攻击的代码
          1. Session session = sessionFactory.openSession();Query q = session.createQuery("select t from UserEntity t where id = " + input);
          2. q.execute();
        3. 解决方案
          1. Session session = sessionFactory.openSession();Query q = session.createQuery("select t from UserEntity t where id = :userId");
          2. q.setString("userId",input);
          3. q.execute();
        4. 动态查询解决方案 使用 Hibernate Criteria)
          1. Session session = sessionFactory.openSession();Query q = session.createCriteria(UserEntity.class)
          2. .add( Restrictions.like("id", input) )
          3. .list();
          4. q.execute();
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。
        2. 易受攻击的代码
          1. PersistenceManager pm = getPM();
          2.  
          3. Query q = pm.newQuery("select * from Users where name = " + input);
          4. q.execute();
        3. 解决方案
          1. PersistenceManager pm = getPM();
          2.  
          3. Query q = pm.newQuery("select * from Users where name = nameParam");
          4. q.declareParameters("String nameParam");
          5. q.execute(input);
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。
        2. 易受攻击的代码
          1. EntityManager pm = getEM();
          2.  
          3. TypedQuery<UserEntity> q = em.createQuery(
          4. String.format("select * from Users where name = %s", username),
          5. UserEntity.class);
          6.  
          7. UserEntity res = q.getSingleResult();
        3. 解决方案
          1. TypedQuery<UserEntity> q = em.createQuery(
          2. "select * from Users where name = usernameParam",UserEntity.class)
          3. .setParameter("usernameParam", username);
          4.  
          5. UserEntity res = q.getSingleResult();
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。
        2. 易受攻击的代码
          1. JdbcTemplate jdbc = new JdbcTemplate();
          2. int count = jdbc.queryForObject("select count(*) from Users where name = '"+paramName+"'", Integer.class);
          3. @Value("properties")private String sql;
          4.  
          5. public function count() {
          6. JdcbOperation jdbc = new JdcbOperation();
          7. int count = jdbc.query(sql);}
        3. 解决方案
          1. JdbcTemplate jdbc = new JdbcTemplate();
          2. int count = jdbc.queryForObject("select count(*) from Users where name = ?", Integer.class, paramName);
          3. private final static String sql = "select count(*) from Users";
          4.  
          5. public function count() {
          6. JdcbOperation jdbc = new JdcbOperation();
          7. int count = jdbc.query(sql);}
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。
        2. 易受攻击的代码
          1. Connection conn = [...];
          2. Statement stmt = con.createStatement();
          3. ResultSet rs = stmt.executeQuery("update COFFEES set SALES = "+nbSales+" where COF_NAME = '"+coffeeName+"'");
        3. 解决方案
          1. Connection conn = [...];
          2. conn.prepareStatement("update COFFEES set SALES = ? where COF_NAME = ?");
          3. updateSales.setInt(1, nbSales);
          4. updateSales.setString(2, coffeeName);
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。
        2. 易受攻击的代码:
        3. db.run {
          sql"select * from people where name = '#$value'".as[Person]}
        4. 解决方案:
        5. db.run {
          sql"select * from people where name = $value".as[Person]}
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。
        2. 易受攻击的代码:
        3. val peopleParser = Macro.parser[Person]("id", "name", "age")
           
          DB.withConnection { implicit c =>
          val people: List[Person] = SQL("select * from people where name = '" + value + "'").as(peopleParser.*)}
        4. 解决方案:
        5. val peopleParser = Macro.parser[Person]("id", "name", "age")
           
          DB.withConnection { implicit c =>
          val people: List[Person] = SQL"select * from people where name = $value".as(peopleParser.*)}
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。Vert.x Sql Client API 提供了一个 DSL 来使用 Java 代码构建查询。
        2. 易受攻击的代码:
        3. SqlClient.query( "select * from Customer where id=" + inputId ).execute(ar -> ...);
        4. 解决方案(使用准备好的语句):
        5. client
          .preparedQuery( "SELECT * FROM users WHERE id=$1" )
          .execute(Tuple.of("julien"))
          .onSuccess(rows -> ...)
          .onFailure(err -> ...);
        1. SQL 查询中包含的输入值需要安全地传入。准备语句中的绑定变量可用于轻松降低 SQL 注入的风险。
        2. 易受攻击的代码:
        3. String query = "SELECT * FROM messages WHERE uid= '"+userInput+"'" ;Cursor cursor = this.getReadableDatabase().rawQuery(query,null);
        4. 解决方案:
        5. String query = "SELECT * FROM messages WHERE uid= ?" ;Cursor cursor = this.getReadableDatabase().rawQuery(query,new String[] {userInput});
        1. 就像 SQL 一样,传递给 LDAP 查询的所有输入都需要安全地传入。不幸的是,LDAP 没有像 SQL 那样准备好的语句接口。因此,针对 LDAP 注入的主要防御措施是在将任何不受信任的数据包含在 LDAP 查询中之前对其进行强输入验证。
        2. 有风险的代码:
        3. NamingEnumeration<SearchResult> answers = context.search("dc=People,dc=example,dc=com",
          "(uid=" + username + ")", ctrls);
        4.  
        5. 解决方案:
        6. 使用“StringUtils”库安全评估 Java 代码。
        7. if(StringUtils.isAlphanumeric(username)) {
          NamingEnumeration<SearchResult> answers = context.search("dc=People,dc=example,dc=com",
          "(uid=" + username + ")", ctrls);}
        1. 正在评估动态代码。应仔细分析代码结构。恶意代码执行可能导致数据泄露或操作系统受损。
        2. 如果打算对用户代码进行评估,则应应用适当的沙箱(请参阅参考资料)。
        3. 有风险的代码:
        4. public void runCustomTrigger(String script) {
          ScriptEngineManager factory = new ScriptEngineManager();
          ScriptEngine engine = factory.getEngineByName("JavaScript");
           
          engine.eval(script); //Bad things can happen here.}
        5. 解决方案:
        6. 使用“Cloudbees Rhino Sandbox”库安全评估 JavaScript 代码。
        7. public void runCustomTrigger(String script) {
          SandboxContextFactory contextFactory = new SandboxContextFactory();
          Context context = contextFactory.makeContext();
          contextFactory.enterContext(context);
          try {
          ScriptableObject prototype = context.initStandardObjects();
          prototype.setParentScope(null);
          Scriptable scope = context.newObject(prototype);
          scope.setPrototype(prototype);
           
          context.evaluateString(scope,script, null, -1, null);
          } finally {
          context.exit();
          }}
        1. Spring 表达式是使用动态值构建的。应验证值的来源,以避免未过滤的值落入这种有风险的代码评估中。
        2. 有风险的代码:
        3. public void parseExpressionInterface(Person personObj,String property) {
           
          ExpressionParser parser = new SpelExpressionParser();
           
          //Unsafe if the input is control by the user..
          Expression exp = parser.parseExpression(property+" == 'Albert'");
           
          StandardEvaluationContext testContext = new StandardEvaluationContext(personObj);
          boolean result = exp.getValue(testContext, Boolean.class);[...]
        1. 表达式是用动态值构建的。应验证值的来源,以避免未过滤的值落入这种有风险的代码评估中。
        2. 有风险的代码:
        3. public void evaluateExpression(String expression) {
          FacesContext context = FacesContext.getCurrentInstance();
          ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory();
          ELContext elContext = context.getELContext();
          ValueExpression vex = expressionFactory.createValueExpression(elContext, expression, String.class);
          return (String) vex.getValue(elContext);}

Seam 日志记录调用中的潜在代码注入 

        1. 错误模式:SEAM_LOG_INJECTION
        2. Seam Logging API 支持一种表达语言来将 bean 属性引入日志消息。表达式语言也可能是不需要的代码执行的来源。
        3. 在这种情况下,表达式是用动态值构建的。应验证值的来源,以避免未过滤的值落入这种有风险的代码评估中。
        4. 有风险的代码:
        5. public void logUser(User user) {
          log.info("Current logged in user : " + user.getUsername());
          //...}
        6. 解决方案:
        7. public void logUser(User user) {
          log.info("Current logged in user : #0", user.getUsername());
          //...}
        1. 表达式是用动态值构建的。应验证值的来源,以避免未过滤的值落入这种有风险的代码评估中。
        2. 有风险的代码:
        3. public void getUserProperty(String property) {
          [...]
          //The first argument is the dynamic expression.
          return ognlUtil.getValue("user."+property, ctx, root, String.class);}
        4. 解决方案:
        5. 通常,评估 OGNL 表达式的方法不应接收用户输入。它旨在用于静态配置。
        1. 表达式是用动态值构建的。应验证值的来源,以避免未过滤的值落入这种有风险的代码评估中。
        2. 有风险的代码:
        3. public void evaluateScript(String script) {
          GroovyShell shell = new GroovyShell();
          shell.evaluate(script);}
        4. 解决方案:
        5. 通常,评估 Groovy 表达式的方法不应接收来自低权限用户的用户输入。
        1. 当 HTTP 请求包含意外CR和LF字符时,服务器可能会使用一个输出流进行响应,该输出流被解释为两个不同的 HTTP 响应(而不是一个)。攻击者可以控制第二响应并发起跨站点脚本攻击和缓存中毒攻击等攻击。根据 OWASP 的说法,这个问题几乎在所有现代 Java EE 应用服务器中都得到了解决,但最好还是验证输入。如果您担心这种风险,您应该在所关注的平台上进行测试,看看底层平台是否允许将CR或LF字符注入到标头中。这个弱点被报告为低优先级,因为它要求 web 容器是易受攻击的。
        2.  
        3. 有风险的代码:
        4. String author = request.getParameter(AUTHOR_PARAMETER);// ...Cookie cookie = new Cookie("author", author);
          response.addCookie(cookie);
        1. 当来自不受信任来源的数据被放入记录器且未正确中和时,攻击者可能会伪造日志条目或包含恶意内容。插入的虚假条目可用于歪曲统计数据、分散管理员的注意力,甚至暗示另一方参与恶意行为。如果日志文件是自动处理的,攻击者可以通过破坏文件格式或注入意外字符来使文件无法使用。攻击者还可能将代码或其他命令注入日志文件,并利用日志处理实用程序中的漏洞(例如命令注入或 XSS)。
        2.  
        3. 有风险的代码:
        4. String val = request.getParameter("user");String metadata = request.getParameter("metadata");[...]if(authenticated) {
          log.info("User " + val + " (" + metadata + ") was authenticated successfully");}else {
          log.info("User " + val + " (" + metadata + ") was not authenticated");}
        5. 恶意用户可以发送值为: 的元数据参数"Firefox) was authenticated successfully [INFO] User bbb (Internet Explorer"。
        6. 解决方案:
        7. 您可以手动清理每个参数。
        8. log.info("User " + val.replaceAll("[ ]","") + " (" + userAgent.replaceAll("[ ]","") + ") was not authenticated");
        9. 您还可以配置您的记录器服务以替换所有消息事件的新行。这是使用replace函数的LogBack 的示例配置。
        10. <pattern>%-5level - %replace(%msg){'[ ]', ''}%n</pattern>
        11. 最后,您可以使用用空格替换新行的记录器实现。OWASP Security Logging项目有一个 Logback 和 Log4j 的实现。
        1. 允许对系统设置进行外部控制可能会中断服务或导致应用程序以意外和潜在的恶意方式运行。攻击者可能会通过提供不存在的目录名称或连接到数据库的未授权部分来导致错误。
        2.  
        3. 有风险的代码:
        4. conn.setCatalog(request.getParameter("catalog"));
        1. 将包含哈希签名的字节数组转换为人类可读的字符串时,如果逐字节读取数组,则可能会出现转换错误。以下示例说明了该方法的使用,该方法Integer.toHexString()将从计算的散列值的每个字节中修剪任何前导零。
        2. MessageDigest md = MessageDigest.getInstance("SHA-256");byte[] resultBytes = md.digest(password.getBytes("UTF-8"));
           
          StringBuilder stringBuilder = new StringBuilder();for(byte b :resultBytes) {
          stringBuilder.append( Integer.toHexString( b & 0xFF ) );}
           
          return stringBuilder.toString();
        3. 这个错误会削弱计算的哈希值,因为它引入了更多的冲突。例如,对于上述函数,哈希值“0x0679”和“0x6709”都将输出为“679”。
        4. 在这种情况下,该方法Integer.toHexString()应替换String.format()为如下:
        5. stringBuilder.append( String.format( "%02X", b ) );
        1. Hazelcast 的网络通信配置为使用对称密码(可能是 DES 或 Blowfish)。
        2. 这些密码本身并不能提供完整性或安全认证。首选使用非对称加密。
        1. NullCipher 在生产应用程序中很少有意使用。它通过返回与提供的明文相同的密文来实现 Cipher 接口。在某些情况下,例如测试,NullCipher 可能是合适的。
        2. 易受攻击的代码:
        3. Cipher doNothingCihper = new NullCipher();[...]//The ciphertext produced will be identical to the plaintext.byte[] cipherText = c.doFinal(plainText);
        1. 解决方案:
        2. 避免使用 NullCipher。它的意外使用会带来重大的保密风险。
        1. 使用的通信通道未加密。拦截网络流量的攻击者可以读取流量。
        1. 漏洞代码:
        2. 普通套接字(明文通信):
        3. Socket soc = new Socket("www.google.com",80);
        1. 解决方案:
        2. SSL Socket(安全通信):
        3. Socket soc = SSLSocketFactory.getDefault().createSocket("www.google.com", 443);
        4. 除了使用 SSL 套接字之外,您还需要确保使用 SSLSocketFactory 进行所有适当的证书验证检查,以确保您不会受到中间人攻击。有关如何正确执行此操作的详细信息,请阅读 OWASP 传输层保护备忘单。
        1. 使用的通信通道未加密。拦截网络流量的攻击者可以读取流量。
        1. 漏洞代码:
        2. 普通服务器套接字(明文通信):
        3. ServerSocket soc = new ServerSocket(1234);
        1. 解决方案:
        2. SSL Server Socket(安全通信):
        3. ServerSocket soc = SSLServerSocketFactory.getDefault().createServerSocket(1234);
        4. 除了使用 SSL 服务器套接字之外,您还需要确保使用 SSLServerSocketFactory 进行所有适当的证书验证检查,以确保您不会受到中间人攻击。有关如何正确执行此操作的详细信息,请阅读 OWASP 传输层保护备忘单。
        1. DES 被认为是现代应用程序的强密码。目前,NIST 建议使用 AES 分组密码而不是 DES。
        2. 示例弱代码:
        3. Cipher c = Cipher.getInstance("DES/ECB/PKCS5Padding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        4. 示例解决方案:
        5. Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        1. 三重 DES(也称为 3DES 或 DESede)被认为是现代应用程序的强密码。目前,NIST 建议使用 AES 分组密码而不是 3DES。
        2. 示例弱代码:
        3. Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        4. 示例解决方案:
        5. Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);

没有填充的 RSA 是不安全的 

        1. 错误模式:RSA_NO_PADDING
        2. 该软件使用 RSA 算法,但不包含可能削弱加密的最佳非对称加密填充 (OAEP)。
        3. 易受攻击的代码:
        4. Cipher.getInstance("RSA/NONE/NoPadding")
        1. 解决方案:
        2. 代码应替换为:
        3. Cipher.getInstance("RSA/ECB/OAEPWithMD5AndMGF1Padding")
        1. 密码不应保留在源代码中。源代码可以在企业环境中广泛共享,当然在开源中共享。为了安全管理,密码和密钥应该存储在单独的配置文件或密钥库中。(硬编码密钥由硬编码密钥模式单独报告)
        2. 易受攻击的代码:
        3. private String SECRET_PASSWORD = "letMeIn!";
           
          Properties props = new Properties();
          props.put(Context.SECURITY_CREDENTIALS, "p@ssw0rd");
        1. 加密密钥不应保留在源代码中。源代码可以在企业环境中广泛共享,当然在开源中共享。为了安全管理,密码和密钥应该存储在单独的配置文件或密钥库中。(硬编码密码由硬编码密码模式单独报告)
        2. 易受攻击的代码:
        3. byte[] key = {1, 2, 3, 4, 5, 6, 7, 8};SecretKeySpec spec = new SecretKeySpec(key, "AES");Cipher aes = Cipher.getInstance("AES");
          aes.init(Cipher.ENCRYPT_MODE, spec);return aesCipher.doFinal(secretData);
        1. 由于比较时间的暴露,攻击者可能能够检测到秘密哈希的值。当函数Arrays.equals()orString.equals()被调用时,如果匹配的字节数较少,它们将提前退出。
        2. 易受攻击的代码:
        3. String actualHash = ...
           
          if(userInput.equals(actualHash)) {
          ...}
        4. 解决方案:
        5. String actualHash = ...
           
          if(MessageDigest.isEqual(userInput.getBytes(),actualHash.getBytes())) {
          ...}
        1. 表单输入应该有最少的输入验证。预防性验证有助于提供针对各种风险的深度防御。
        2. 验证可以通过实现一个validate方法来引入。
        3. public class RegistrationForm extends ValidatorForm {
           
          private String name;
          private String email;
           
          [...]
           
          public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
          //Validation code for name and email parameters passed in via the HttpRequest goes here
          }}
        1. 通过各种博客站点发布了 一个HttpServletRequestWrapper调用的实现XSSRequestWrapper。[1] [2]
        2. 由于以下几个原因,过滤很弱:
        3. 它仅涵盖参数,不包括标题和侧通道输入
        4. 可以轻松绕过替换功能链(请参见下面的示例)
        5. 这是一个非常具体的坏模式的黑名单(而不是一个好的/有效输入的白名单)
        6. 旁路示例:
        7. <scrivbscript:pt>alert(1)</scrivbscript:pt>
        8. 之前的输入将被转换为"<script>alert(1)</script>". 删除"vbscript:"是在替换之后"<script>.*</script>"。
        9. 为了获得更强大的保护,请选择一个在视图(模板或 JSP)中自动编码字符的解决方案,遵循 OWASP XSS 预防备忘单中定义的 XSS 保护规则。
        1. Blowfish 密码支持从 32 位到 448 位的密钥大小。较小的密钥大小使密文容易受到蛮力攻击。如果需要使用 Blowfish,则在生成密钥时应至少使用 128 位的熵。
        2. 如果可以更改算法,则应改用 AES 分组密码。
        3. 易受攻击的代码:
        4. KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
          keyGen.init(64);
        5. 解决方案:
        6. KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
          keyGen.init(128);
        1. NIST 建议对 RSA 算法使用2048 位和更高的密钥。
“数字签名验证 | RSA:1024 ≤ len(n) < 2048| 传统使用” 
“数字签名验证 | RSA:len(n) ≥ 2048|可接受” 
        1. 易受攻击的代码:
        2. KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
          keyGen.initialize(512);
        1. 解决方案:
        2. KeyPairGenerator 创建应如下所示,密钥大小至少为 2048 位。
        3. KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
          keyGen.initialize(2048);
        1. 应用程序将用户重定向到由用户提供的未验证参数指定的目标 URL 时,会发生未验证重定向。此类漏洞可用于促进网络钓鱼攻击。
        1. 场景
        2. 2. 用户被重定向到看起来像他们信任的站点的虚假登录页面。( http://evil.vvebsite.com/fake/login
        3. 3. 用户输入其凭据。
        4. 4. 恶意站点盗取用户凭据,将其重定向到原网站。
        5.  
        6. 这种攻击是合理的,因为大多数用户在重定向后不会再次检查 URL。此外,重定向到身份验证页面也很常见。
        7. 易受攻击的代码:
        8. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          [...]
          resp.sendRedirect(req.getParameter("redirectUrl"));
          [...]}
        9. 解决方案/对策:
        10. 不接受来自用户的重定向目的地
        11. 接受目标密钥,并使用它来查找目标(合法)目标
        12. 只接受相对路径
        13. 白名单 URL(如果可能)
        14. 验证 URL 的开头是白名单的一部分
        1. 当应用程序将用户重定向到由用户提供的未验证参数指定的目标 URL 时,会发生未验证重定向。此类漏洞可用于促进网络钓鱼攻击。
        1. 场景
        2. 2. 用户被重定向到看起来像他们信任的站点的虚假登录页面。( http://evil.vvebsite.com/fake/login
        3. 3. 用户输入其凭据。
        4. 4. 恶意站点盗取用户凭据,将其重定向到原网站。
        5.  
        6. 这种攻击是合理的,因为大多数用户在重定向后不会再次检查 URL。此外,重定向到身份验证页面也很常见。
        7. 易受攻击的代码:
        8. def login(redirectUrl:String) = Action {
          [...]
          Redirect(url)}
        9. 解决方案/对策:
        10. 不接受来自用户的重定向目的地
        11. 接受目标密钥,并使用它来查找目标(合法)目标
        12. 只接受相对路径
        13. 白名单 URL(如果可能)
        14. 验证 URL 的开头是白名单的一部分
        1. 当应用程序将用户重定向到由用户提供的未验证参数指定的目标 URL 时,会发生未验证重定向。此类漏洞可用于促进网络钓鱼攻击。
        1. 场景
        2. 2. 用户被重定向到看起来像他们信任的站点的虚假登录页面。( http://evil.vvebsite.com/fake/login
        3. 3. 用户输入其凭据。
        4. 4. 恶意站点盗取用户凭据,将其重定向到原网站。
        5.  
        6. 这种攻击是合理的,因为大多数用户在重定向后不会再次检查 URL。此外,重定向到身份验证页面也很常见。
        7. 易受攻击的代码:
        8. @RequestMapping("/redirect")public String redirect(@RequestParam("url") String url) {
          [...]
          return "redirect:" + url;}
        9. 解决方案/对策:
        10. 不接受来自用户的重定向目的地
        11. 接受目标密钥,并使用它来查找目标(合法)目标
        12. 只接受相对路径
        13. 白名单 URL(如果可能)
        14. 验证 URL 的开头是白名单的一部分
        1. API 永远不应该返回持久对象。它们可能会导致通过 UI 泄漏业务逻辑,未经授权篡改数据库中的持久对象。
        2. 易受攻击的代码:
        3. @javax.persistence.Entityclass UserEntity {
           
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
           
          private String username;
           
          private String password;}
           
          [...]@Controllerclass UserController {
           
          @GetMapping("/user/{id}")
          public UserEntity getUser(@PathVariable("id") String id) {
           
          return userService.findById(id).get(); //Return the user entity with ALL fields.
          }
           
          }
        4. 解决方案/对策:
        5. 应使用数据传输对象,而不是仅包括作为对 API 的输入/响应所需的参数。
        6. 在转移到 UI 之前,应正确删除敏感参数。
        7. 只有经过适当的消毒检查后,数据才应保留在数据库中。
        1. Spring MVC 解决方案:特别是
        2. 在 Spring 中,您可以应用以下解决方案来允许或禁止特定字段。
        3. @Controllerclass UserController {
           
          @InitBinder
          public void initBinder(WebDataBinder binder, WebRequest request)
          {
          binder.setAllowedFields(["username","firstname","lastname"]);
          }
           
          }
        1. API 永远不应该返回持久对象。它们可能会导致通过 UI 泄漏业务逻辑,未经授权篡改数据库中的持久对象。
        2. 易受攻击的代码:
        3. @javax.persistence.Entityclass UserEntity {
           
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
           
          private String username;
           
          private String password;
           
          private Long role;}
           
          [...]@Controllerclass UserController {
           
          @PutMapping("/user/")
          @ResponseStatus(value = HttpStatus.OK)
          public void update(UserEntity user) {
           
          userService.save(user); //ALL fields from the user can be altered
          }
           
          }
        4. 一般准则:
        5. 应使用数据传输对象,而不是仅包括作为对 API 的输入/响应所需的参数。
        6. 在转移到 UI 之前,应正确删除敏感参数。
        7. 只有经过适当的消毒检查后,数据才应保留在数据库中。
        1. Spring MVC 解决方案:特别是
        2. 在 Spring 中,您可以应用以下解决方案来允许或禁止特定字段。
        3.  
        4. 有白名单:
        5. @Controllerclass UserController {
           
          @InitBinder
          public void initBinder(WebDataBinder binder, WebRequest request)
          {
          binder.setAllowedFields(["username","password"]);
          }
           
          }
        6.  
        7. 有黑名单:
        8. @Controllerclass UserController {
           
          @InitBinder
          public void initBinder(WebDataBinder binder, WebRequest request)
          {
          binder.setDisallowedFields(["role"]);
          }
           
          }
        1. JSP 文件的包含允许动态值的输入。它可能允许攻击者控制包含的 JSP 页面。如果是这种情况,攻击者将尝试在他控制的磁盘上包含一个文件。通过包含任意文件,攻击者可以获得执行任何代码的能力。
        2. 易受攻击的代码:
        3. <jsp:include page="${param.secret_param}" />
        4. 解决方案:
        5. <c:if test="${param.secret_param == 'page1'}">
          <jsp:include page="page1.jsp" /></c:if>
        1. pring 表达式是使用动态值构建的。应验证值的来源,以避免未过滤的值落入这种有风险的代码评估中。
        2. 易受攻击的代码:
        3. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
           
          <spring:eval expression="${param.lang}" var="lang" />
        4.  
        5. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
           
          <spring:eval expression="'${param.lang}'=='fr'" var="languageIsFrench" />
        6. 解决方案:  用set 而不是eval
        7. <c:set var="lang" value="${param.lang}"/>
        8.  
        9. <c:set var="languageIsFrench" value="${param.lang == 'fr'}"/>
        1. 发现了潜在的 XSS。它可用于在客户端浏览器中执行不需要的 JavaScript。(见参考资料)
        2. 易受攻击的代码:
        3. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
           
          <c:out value="${param.test_param}" escapeXml="false"/>
        4. 解决方案:
        5. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
           
          <c:out value="${param.test_param}"/>
        1. 发现了潜在的 XSS。它可用于在客户端浏览器中执行不需要的 JavaScript。(见参考资料)
        2. 易受攻击的代码:
        3. <%String taintedInput = (String) request.getAttribute("input");%>[...]<%= taintedInput %>
        4. 解决方案:
        5. <%String taintedInput = (String) request.getAttribute("input");%>[...]<%= Encode.forHtml(taintedInput) %>
        6. 对 XSS 的最佳防御是上下文敏感的输出编码,如上面的示例。通常需要考虑 4 种上下文:HTML、JavaScript、CSS(样式)和 URL。请遵循 OWASP XSS 预防备忘单中定义的 XSS 保护规则,其中详细解释了这些防御措施。
        1. 发现了潜在的 XSS。它可用于在客户端浏览器中执行不需要的 JavaScript。(见参考资料)
        2. 易受攻击的代码:
        3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          String input1 = req.getParameter("input1");
          [...]
          resp.getWriter().write(input1);}
        4. 解决方案:
        5. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          String input1 = req.getParameter("input1");
          [...]
          resp.getWriter().write(Encode.forHtml(input1));}
        6. 对 XSS 的最佳防御是上下文敏感的输出编码,如上面的示例。通常需要考虑 4 种上下文:HTML、JavaScript、CSS(样式)和 URL。请遵循 OWASP XSS 预防备忘单中定义的 XSS 保护规则,其中详细解释了这些防御措施。
        7. 请注意,此 Servlet 中的 XSS 规则查找类似问题,但查找方式与 FindBugs 中现有的“XSS:Servlet 反映的跨站点脚本漏洞”和“XSS:错误页面中的 Servlet 反映的跨站点脚本漏洞”规则不同.
        1. XMLDecoder 不应用于解析不受信任的数据。反序列化用户输入可能导致任意代码执行。这是可能的,因为 XMLDecoder 支持任意方法调用。此功能旨在调用 setter 方法,但实际上,可以调用任何方法。
        2. 恶意 XML 示例:
        3. <?xml version="1.0" encoding="UTF-8" ?><java version="1.4.0" class="java.beans.XMLDecoder">
          <object class="java.io.PrintWriter">
          <string>/tmp/Hacked.txt</string>
          <void method="println">
          <string>Hello World!</string>
          </void>
          <void method="close"/>
          </object></java>
        4. 上面的 XML 代码将创建一个内容为“Hello World!”的文件。
        5. 易受攻击的代码:
        6. XMLDecoder d = new XMLDecoder(in);try {
          Object result = d.readObject();}[...]
        1. 解决方案:
        2. 解决方案是避免使用 XMLDecoder 解析来自不受信任来源的内容。
        1. 必须为每个要加密的消息重新生成初始化向量。
        2. 易受攻击的代码:
        3. private static byte[] IV = new byte[16] {(byte)0,(byte)1,(byte)2,[...]};
           
          public void encrypt(String message) throws Exception {
           
          IvParameterSpec ivSpec = new IvParameterSpec(IV);[...]
        4. 解决方案:
        5. public void encrypt(String message) throws Exception {
           
          byte[] iv = new byte[16];
          new SecureRandom().nextBytes(iv);
           
          IvParameterSpec ivSpec = new IvParameterSpec(iv);[...]
        1. 应使用可为加密数据提供更好机密性的身份验证密码模式代替电子密码本 (ECB) 模式,后者不能提供良好的机密性。具体来说,ECB 模式每次为相同的输入产生相同的输出。因此,例如,如果用户发送密码,则加密值每次都相同。这允许攻击者拦截和重放数据。
        2. 为了解决这个问题,应该使用像 Galois/Counter Mode (GCM) 这样的东西。
        3. 有风险的代码:
        4. Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        5. 解决方案: 或BCB
        6. Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        1. 这种带有 PKCS5Padding 的 CBC 特定模式容易受到填充预言机攻击。如果系统暴露了具有无效填充或有效填充的明文之间的差异,则对手可能会解密该消息。有效和无效填充之间的区别通常通过为每个条件返回的不同错误消息来揭示。
        2. 有风险的代码:
        3. Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        4. 解决方案:
        5. Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        1. 生成的密文很容易被对手更改。这意味着密码无法检测数据是否已被篡改。如果密文可以被攻击者控制,它就可以在不被发现的情况下被更改。
        2. 解决方案是使用包含基于哈希的消息身份验证代码 (HMAC) 的密码对数据进行签名。将 HMAC 函数与现有密码相结合很容易出错[1]。具体来说,始终建议您先验证 HMAC,并且只有在数据未修改的情况下,才能对数据执行任何加密功能。
        1. 以下模式易受攻击,因为它们不提供 HMAC:
        2. - CBC 
        3. - OFB 
        4. - CTR 
        5. - ECB
        6.  
        7. 以下代码片段是易受攻击代码的一些示例。
        8.  
        9. 有风险的代码:
        10. CBC 模式下的 AES
        11. Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        12.  
        13. 带 ECB 模式的三重 DES
        14. Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        15. 解决方案:
        16. Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
          c.init(Cipher.ENCRYPT_MODE, k, iv);byte[] cipherText = c.doFinal(plainText);
        17. 在上面的示例解决方案中,GCM 模式将 HMAC 引入到生成的加密数据中,从而提供了结果的完整性。
        1. ESAPI 在加密组件中的漏洞历史很少。这是一个快速验证列表,以确保经过身份验证的加密按预期工作。
        2. 1. 库版本
        3. 此问题已在 ESAPI 版本 2.1.0 中得到纠正。版本 <= 2.0.1 容易受到 MAC 绕过 (CVE-2013-5679)。
        4. 对于 Maven 用户,可以使用以下命令调用插件版本。ESAPI 的有效版本将在输出中提供。
        5. $ mvn versions:display-dependency-updates
        6.  
        7. 输出:
        8. [...][INFO] The following dependencies in Dependencies have newer versions:[INFO] org.slf4j:slf4j-api ................................... 1.6.4 -> 1.7.7[INFO] org.owasp.esapi:esapi ................................. 2.0.1 -> 2.1.0[...]
        9. 或者直接查看配置。
        10. <dependency>
          <groupId>org.owasp.esapi</groupId>
          <artifactId>esapi</artifactId>
          <version>2.1.0</version></dependency>
        11. 对于 Ant 用户,使用的 jar 应该是esapi-2.1.0.jar
        12. 2.配置:
        1. 库版本 2.1.0 仍然容易受到密文定义中密钥大小更改的影响 (CVE-2013-5960)。需要采取一些预防措施。
        2.  
        3. 如果存在以下任何元素,ESAPI 的加密配置也可能容易受到攻击:
          不安全的配置:
          Encryptor.CipherText.useMAC=false
           
          Encryptor.EncryptionAlgorithm=AES
          Encryptor.CipherTransformation=AES/CBC/PKCS5Padding
           
          Encryptor.cipher_modes.additional_allowed=CBC
        4. 安全配置:
          #NeededEncryptor.CipherText.useMAC=true
           
          #Needed to have a solid auth. encryption
          Encryptor.EncryptionAlgorithm=AES
          Encryptor.CipherTransformation=AES/GCM/NoPadding
           
          #CBC mode should be removed to avoid padding oracle
          Encryptor.cipher_modes.additional_allowed=
        1. 应用程序将数据写入外部存储(可能是 SD 卡)。此操作有多种安全含义。首先,具有READ_EXTERNAL_STORAGE权限的应用程序可以访问存储在 SD 卡上的文件 。此外,如果持久保存的数据包含有关用户的机密信息,则需要加密。
        2. 有风险的代码:
        3. file file = new File(getExternalFilesDir(TARGET_TYPE), filename);
          fos = new FileOutputStream(file);
          fos.write(confidentialData.getBytes());
          fos.flush();
        4. 更好的选择:
        5. fos = openFileOutput(filename, Context.MODE_PRIVATE);
          fos.write(string.getBytes());
        1. 任何具有适当权限的应用程序都可以收听广播意图。建议尽可能避免传输敏感信息。
        2. 有风险的代码:
        3. Intent i = new Intent();
          i.setAction("com.insecure.action.UserConnected");
          i.putExtra("username", user);
          i.putExtra("email", email);
          i.putExtra("session", newSessionId);
           
          this.sendBroadcast(v1);
        4.  
        5. 解决方案(如果可能):
        6. Intent i = new Intent();
          i.setAction("com.secure.action.UserConnected");
           
          sendBroadcast(v1);
        7.  
        8. 配置(接收器)[1] 来源:StackOverflow:
        9. <manifest ...>
           
          <!-- Permission declaration -->
          <permission android:name="my.app.PERMISSION" />
           
          <receiver
          android:name="my.app.BroadcastReceiver"
          android:permission="my.app.PERMISSION"> <!-- Permission enforcement -->
          <intent-filter>
          <action android:name="com.secure.action.UserConnected" />
          </intent-filter>
          </receiver>
           
          ...</manifest>
        10. 配置(发送方)[1] 来源:StackOverflow:
        11. <manifest>
          <!-- We declare we own the permission to send broadcast to the above receiver -->
          <uses-permission android:name="my.app.PERMISSION"/>
           
          <!-- With the following configuration, both the sender and the receiver apps need to be signed by the same developer certificate. -->
          <permission android:name="my.app.PERMISSION" android:protectionLevel="signature"/><
        12. 不要使用隐式意图广播敏感信息
        13. 设置广播发送器和接收器的权限
        1. 在此上下文中编写的文件使用的是创建模式MODE_WORLD_READABLE。公开正在编写的内容可能不是预期的行为。
        2. 有风险的代码:
        3. fos = openFileOutput(filename, MODE_WORLD_READABLE);
          fos.write(userInfo.getBytes());
        4.  
        5. 解决方案(使用 MODE_PRIVATE):
        6. fos = openFileOutput(filename, MODE_PRIVATE);
        1. 解决方案(使用本地 SQLite 数据库):
        2. 使用本地 SQLite 数据库可能是存储结构化数据的最佳解决方案。确保数据库文件不是在外部存储上创建的。有关实施指南,请参阅下面的参考资料。
        1. 建议要求用户确认获取其地理位置。
        2. 有风险的代码:
        3. webView.setWebChromeClient(new WebChromeClient() {
          @Override
          public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
          callback.invoke(origin, true, false);
          }});
        1. 建议代码:
        2. 限制地理位置的采样,并要求用户确认。
        3. webView.setWebChromeClient(new WebChromeClient() {
          @Override
          public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
          callback.invoke(origin, true, false);
           
          //Ask the user for confirmation
          }});
        1. 为 WebView 启用 JavaScript 意味着它现在容易受到 XSS 的影响。应该检查页面渲染是否有潜在的反射 XSS、存储型 XSS 和 DOM XSS。
        2. WebView myWebView = (WebView) findViewById(R.id.webView);WebSettings webSettings = myWebView.getSettings();
          webSettings.setJavaScriptEnabled(true);
        1. 有风险的代码:
        2. 启用 JavaScript 并不是一个坏习惯。这只是意味着需要针对潜在的 XSS 审核后端代码。XSS 也可以通过 DOM XSS 引入客户端。
        3. function updateDescription(newDescription) {
          $("#userDescription").html("<p>"+newDescription+"</p>");}
        1. 使用 JavaScript 接口可能会将 WebView 暴露给有风险的 API。如果在 WebView 中触发了 XSS,恶意 JavaScript 代码可能会调用该类。
        2. 有风险的代码:
        3. WebView myWebView = (WebView) findViewById(R.id.webView);
           
          myWebView.addJavascriptInterface(new FileWriteUtil(this), "fileWriteUtil");
           
          WebSettings webSettings = myWebView.getSettings();
          webSettings.setJavaScriptEnabled(true);
           
          [...]class FileWriteUtil {
          Context mContext;
           
          FileOpenUtil(Context c) {
          mContext = c;
          }
           
          public void writeToFile(String data, String filename, String tag) {
          [...]
          }}
        1. 创建一个没有设置Secure标志的新 cookie 。该Secure标志是对浏览器的指令,以确保不会为不安全的通信发送 cookie ( http://)。
        2. 有风险的代码:
        3. Cookie cookie = new Cookie("userName",userName);
          response.addCookie(cookie);
        4. 解决方案(具体配置):
        5. Cookie cookie = new Cookie("userName",userName);
          cookie.setSecure(true); // Secure flag
          cookie.setHttpOnly(true);
        6. 解决方案(Servlet 3.0 配置):
        7. <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0">[...]<session-config>
          <cookie-config>
          <http-only>true</http-only>
          <secure>true</secure>
          </cookie-config></session-config></web-app>
        1. 建一个没有设置HttpOnly标志的新 cookie 。该HttpOnly标志是对浏览器的指令,以确保 cookie 不会被恶意脚本红色。例如,当用户成为“跨站点脚本”的目标时,攻击者将从获取会话 ID 中受益匪浅。
        2. 有风险的代码:
        3. Cookie cookie = new Cookie("email",userName);
          response.addCookie(cookie);
        4. 解决方案(具体配置):
        5. Cookie cookie = new Cookie("email",userName);
          cookie.setSecure(true);
          cookie.setHttpOnly(true); //HttpOnly flag
        6. 解决方案(Servlet 3.0 配置):
        7. <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0">[...]<session-config>
          <cookie-config>
          <http-only>true</http-only>
          <secure>true</secure>
          </cookie-config></session-config></web-app>
        1. 如果类路径中存在允许触发恶意操作的类,则不受信任数据的对象反序列化可能导致远程代码执行。
        2. 库开发人员倾向于修复提供潜在恶意触发器的类。仍然有已知的类会触发拒绝服务[1]。
        3. 反序列化是一种明智的操作,它有着悠久的漏洞历史。一旦在 Java 虚拟机[2] [3] 中发现新漏洞,Web 应用程序可能会变得易受攻击。
        4. 有风险的代码:
        5. public UserData deserializeObject(InputStream receivedFile) throws IOException, ClassNotFoundException {
           
          try (ObjectInputStream in = new ObjectInputStream(receivedFile)) {
          return (UserData) in.readObject();
          }}
        6. 解决方案:
        7. 避免反序列化远程用户提供的对象。
        1. 当 Jackson 数据绑定库使用不当时,如果 classpath 中存在允许触发恶意操作的类,则不可信数据的反序列化可能会导致远程代码执行。
        2. 解决方案:
        3. 通过 JsonTypeInfo.Id.NAME 明确定义在使用多态时您希望可用的类型和子类型。此外,永远不要调用ObjectMapper.enableDefaultTyping(然后调用readValue包含 Object 或 Serializable 或 Comparable 或已知反序列化类型的类型)。
        4. 有风险的代码:
        5. public class Example {
          static class ABean {
          public int id;
          public Object obj;
          }
           
          static class AnotherBean {
          @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) // or JsonTypeInfo.Id.MINIMAL_CLASS
          public Object obj;
          }
           
          public void example(String json) throws JsonMappingException {
          ObjectMapper mapper = new ObjectMapper();
          mapper.enableDefaultTyping();
          mapper.readValue(json, ABean.class);
          }
           
          public void exampleTwo(String json) throws JsonMappingException {
          ObjectMapper mapper = new ObjectMapper();
          mapper.readValue(json, AnotherBean.class);
          }
           
          }
        1. 反序列化小工具是攻击者可以用来利用本地序列化利用远程 API 的类。此类要么使用readObject方法 (Serializable)向反序列化添加自定义行为,要么可以从序列化对象 (InvocationHandler) 中调用。
        2. 该探测器主要供研究人员使用。真正的问题是使用反序列化进行远程操作。删除小工具是一种强化做法,可降低被利用的风险。
        1. “信任边界可以被认为是通过程序绘制的线。在这条线的一侧,数据是不可信的。在这条线的另一侧,假设数据是可信的。验证逻辑的目的是允许数据安全地跨越信任边界——从不受信任转移到受信任。当程序模糊了可信和不可信之间的界限时,就会发生信任边界违规。通过在同一数据结构中组合可信和不可信数据,它变得更容易程序员错误地相信未经验证的数据。” [1]
        2. 有风险的代码:
        3. public void doSomething(HttpServletRequest req, String activateProperty) {
          //..
           
          req.getSession().setAttribute(activateProperty,"true");
           
          }
        4.  
        5. public void loginEvent(HttpServletRequest req, String userSubmitted) {
          //..
           
          req.getSession().setAttribute("user",userSubmitted);}
        6. 解决方案:
        7. 解决方案是在设置新会话属性之前添加验证。在可能的情况下,更喜欢来自安全位置的数据,而不是使用直接的用户输入。
        1. “XSLT(可扩展样式表语言转换)是一种将 XML 文档转换为其他 XML 文档的语言”。[1]
        2. 有可能将恶意行为附加到这些样式表中。因此,如果攻击者可以控制样式表的内容或来源,他就有可能触发远程代码执行。[2]
        3. 有风险的代码:
        4. <x:transform xml="${xmlData}" xslt="${xsltControlledByUser}" />
        5. 解决方案:
        6. 解决方案是确保从安全来源加载样式表,并确保不会出现诸如路径遍历[3][4] 之类的漏洞。
        1. “XSLT(可扩展样式表语言转换)是一种将 XML 文档转换为其他 XML 文档的语言”。[1]
        2. 有可能将恶意行为附加到这些样式表中。因此,如果攻击者可以控制样式表的内容或来源,他就有可能触发远程代码执行。[2]
        3. 有风险的代码:
        4. Source xslt = new StreamSource(new FileInputStream(inputUserFile)); //Dangerous source
           
          Transformer transformer = TransformerFactory.newInstance().newTransformer(xslt);
           
          Source text = new StreamSource(new FileInputStream("/data_2_process.xml"));
          transformer.transform(text, new StreamResult(...));
        5. 解决方案:
        6. 解决方案是启用安全处理模式,该模式将阻止对 Java 类的潜在引用,例如java.lang.Runtime.
        7. TransformerFactory factory = TransformerFactory.newInstance();
          factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);Source xslt = new StreamSource(new FileInputStream(inputUserFile));
           
          Transformer transformer = factory.newTransformer(xslt);
        8. 或者,请确保从安全来源加载样式表,并确保不会出现诸如路径遍历[3][4] 之类的漏洞。
        1. 应用程序可能会通过各种应用程序问题无意中泄露有关其配置、内部工作或侵犯隐私的信息。[1]根据数据有效性提供不同响应的页面可能导致信息泄漏;特别是当被视为机密的数据由于 Web 应用程序的设计而被泄露时。[2]
        2. 敏感数据的示例包括(但不限于):API 密钥、密码、产品版本或环境配置。
        3. 有风险的代码:
        4. def doGet(value:String) = Action {
          val configElement = configuration.underlying.getString(value)
           
          Ok("Hello "+ configElement +" !")}
        5. 不应在响应内容中发送应用程序配置元素,并且不应允许用户控制代码将使用哪些配置元素。
        1. 当 Web 服务器对用户提供的未验证目标参数执行请求时,就会发生服务器端请求伪造。此类漏洞可能允许攻击者访问内部服务或从您的 Web 服务器发起攻击。
        2. 易受攻击的代码:
        3. def doGet(value:String) = Action {
          WS.url(value).get().map { response =>
          Ok(response.body)
          }}
        4. 解决方案/对策:
        5. 不接受来自用户的请求目的地
        6. 接受目标密钥,并使用它来查找目标(合法)目标
        7. 白名单 URL(如果可能)
        8. 验证 URL 的开头是白名单的一部分
        1. 当 Web 服务器对用户提供的未验证目标参数执行请求时,就会发生服务器端请求伪造。此类漏洞可能允许攻击者访问内部服务或从您的 Web 服务器发起攻击。
        2. URLConnection 可以与 file:// 协议或其他协议一起使用来访问本地文件系统和潜在的其他服务。
        3. 易受攻击的代码:
        4. new URL(String url).openConnection()
        5. new URL(String url).openStream()
        6. new URL(String url).getContent()
        7. 解决方案/对策:
        8. 不接受来自用户的 URL 目标
        9. 接受目标密钥,并使用它来查找与密钥关联的目标目标
        10. 白名单 URL(如果可能)
        11. 验证 URL 的开头是白名单的一部分
        1. 发现了潜在的 XSS。它可用于在客户端浏览器中执行不需要的 JavaScript。(见参考资料)
        2. 易受攻击的代码:
        3. @(value: Html)
           
          @value
        4. 解决方案:
        5. @(value: String)
           
          @value
        6. 对 XSS 的最佳防御是上下文敏感的输出编码,如上面的示例。通常需要考虑 4 种上下文:HTML、JavaScript、CSS(样式)和 URL。请遵循 OWASP XSS 预防备忘单中定义的 XSS 保护规则,其中详细解释了这些防御措施。
        1. 发现了潜在的 XSS。它可用于在客户端浏览器中执行不需要的 JavaScript。(见参考资料)
        2. 易受攻击的代码:
        3. def doGet(value:String) = Action {
          Ok("Hello " + value + " !").as("text/html")
          }
        4. 解决方案:
        5. def doGet(value:String) = Action {
          Ok("Hello " + Encode.forHtml(value) + " !")
          }
        6. 对 XSS 的最佳防御是上下文敏感的输出编码,如上面的示例。通常需要考虑 4 种上下文:HTML、JavaScript、CSS(样式)和 URL。请遵循 OWASP XSS 预防备忘单中定义的 XSS 保护规则,其中详细解释了这些防御措施。
        1. Velocity 模板引擎功能强大。可以添加包括条件语句、循环和外部调用在内的逻辑。它不是设计为模板操作的沙箱。控制模板的恶意用户可以在服务器端运行恶意代码。Velocity 模板应该被视为脚本。
        2. 易受攻击的代码:
        3. [...]
           
          Velocity.evaluate(context, swOut, "test", userInput);
        1. 解决方案: 
        2. 避免让最终用户使用 Velocity 操作模板。如果您需要向用户公开模板编辑,请首选无逻辑模板引擎,例如 Handlebars 或 Mustache(请参阅参考资料)。

使用 Freemarker 进行潜在模板注入 

        1. 错误模式:TEMPLATE_INJECTION_FREEMARKER
        2. Freemarker 模板引擎功能强大。可以添加包括条件语句、循环和外部调用在内的逻辑。它不是设计为模板操作的沙箱。控制模板的恶意用户可以在服务器端运行恶意代码。Freemarker 模板应该被视为脚本。
        3. 易受攻击的代码:
        4. Template template = cfg.getTemplate(inputTemplate);[...]
          template.process(data, swOut);
        1. 解决方案: 
        2. 避免让最终用户使用 Freemarker 操作模板。如果您需要向用户公开模板编辑,请首选无逻辑模板引擎,例如 Handlebars 或 Mustache(请参阅参考资料)。
        3.  
        1. 参考

        1. Pebble 模板引擎功能强大。可以添加包括条件语句、循环和外部调用在内的逻辑。它不是设计为模板操作的沙箱。控制模板的恶意用户可以在服务器端运行恶意代码。Pebble 模板应该被视为脚本。
        2. 易受攻击的代码:
        3. PebbleTemplate compiledTemplate = engine.getLiteralTemplate(inputFile);[...]
          compiledTemplate.evaluate(writer, context);
        1. 解决方案: 
        2. 避免让最终用户使用 Pebble 操作模板。如果您需要向用户公开模板编辑,请首选无逻辑模板引擎,例如 Handlebars 或 Mustache(请参阅参考资料)。
        3.  
        1. 参考资料
        2. 服务器端模板注入——以 Michał Bentkowski 
        1. 在 HTML5 之前,Web 浏览器执行同源策略,以确保 JavaScript 访问网页的内容时,JavaScript 和网页必须来自同一域。如果没有同源策略,恶意网站可以提供 JavaScript,使用客户端的凭据从其他网站加载敏感信息,剔除它,并将其返回给攻击者。如果定义了名为 Access-Control-Allow-Origin 的新 HTTP 标头,则 HTML5 使 JavaScript 可以跨域访问数据。使用此标头,Web 服务器定义允许哪些其他域使用跨域请求访问其域。然而,
        2. 易受攻击的代码:
        3. response.addHeader("Access-Control-Allow-Origin", "*");
        1. 解决方案: 
        2. 避免使用 * 作为 Access-Control-Allow-Origin 标头的值,这表明应用程序的数据可被在任何域上运行的 JavaScript 访问。
        1. 如果没有适当的访问控制,执行包含用户控制值的 LDAP 语句可能允许攻击者滥用配置不当的 LDAP 上下文。针对上下文执行的所有 LDAP 查询都将在没有身份验证和访问控制的情况下执行。攻击者可能能够以一种意想不到的方式操纵这些查询之一,以获得对记录的访问权限,否则这些记录将受到目录的访问控制机制的保护。
        2. 易受攻击的代码:
        3. ...
          env.put(Context.SECURITY_AUTHENTICATION, "none");DirContext ctx = new InitialDirContext(env);...
        1. 解决方案: 
        2. 考虑对 LDAP 进行其他身份验证模式并确保正确的访问控制机制。
        3.  
        1. 参考
        1. JNDI API 支持在 LDAP 目录中绑定序列化对象。如果提供了某些属性,则将在查询目录的应用程序中进行对象的反序列化(详见 Black Hat USA 2016 白皮书)。对象反序列化应该被视为可能导致远程代码执行的危险操作。
        2. 如果攻击者在 LDAP 基本查询中拥有入口点,通过向现有 LDAP 条目添加属性或将应用程序配置为使用恶意 LDAP 服务器,则有可能利用该漏洞。
        3. 易受攻击的代码:
        4. DirContext ctx = new InitialDirContext();//[...]
           
          ctx.search(query, filter,
          new SearchControls(scope, countLimit, timeLimit, attributes,
          true, //Enable object deserialization if bound in directory
          deref));
        5. 解决方案:
        6. DirContext ctx = new InitialDirContext();//[...]
           
          ctx.search(query, filter,
          new SearchControls(scope, countLimit, timeLimit, attributes,
          false, //Disable
          deref));
        7.  
        1. 参考
        1. 将敏感数据长时间存储在持久性 cookie 中可能会导致机密性泄露或帐户泄露。
        1. 解释:
        2. 如果私人信息存储在持久性 cookie 中,攻击者有更大的时间窗口来窃取这些数据——特别是因为持久性 cookie 通常会在遥远的将来过期。持久性 cookie 通常存储在客户端的文本文件中,可以访问受害者机器的攻击者可以窃取此信息。
        3. 持久性 cookie 通常用于在用户与站点交互时对其进行概要分析。根据对这些跟踪数据的处理方式,有可能使用持久性 cookie 来侵犯用户的隐私。
        4. 易受攻击的代码:以下代码将 cookie 设置为在 1 年内过期。
        5. [...]Cookie cookie = new Cookie("email", email);
          cookie.setMaxAge(60*60*24*365);[...]
        6. 解决方案:
        7. 仅在必要时使用持久性 cookie 并限制其最长期限。
        8. 不要对敏感数据使用持久性 cookie。
        9.  
        1. 参考

URL重写方法 

        1. 错误模式:URL_REWRITING
        1. 该方法的实现包括判断会话ID是否需要在URL中编码的逻辑。
        2. URL 重写具有重大的安全风险。由于会话 ID 出现在 URL 中,因此很容易被第三方看到。URL中的Session ID可以通过多种方式公开,例如:
        3. 日志文件,
        4. 浏览器历史记录,
        5. 通过将其复制并粘贴到电子邮件或发布中,
        6. HTTP 引荐来源网址。
        7. 易受攻击的代码:
        8. out.println("Click <a target="_blank" href=" +
          res.encodeURL(HttpUtils.getRequestURL(req).toString()) +
          ">here</a>");
        1. 解决方案:
        2. 避免使用这些方法。如果您希望对 URL 字符串或表单参数进行编码,请不要将 URL 重写方法与 URLEncoder 类混淆。
        1. 建立 SSL 连接时禁用服务器身份验证。默认情况下,某些启用 SSL 连接的电子邮件库不验证服务器证书。这相当于信任所有证书。当尝试连接到服务器时,此应用程序将很容易接受颁发给“victim.com”的证书。该应用程序现在可能会在与受害者服务器的 SSL 连接断开时泄漏敏感用户信息。
        2. 易受攻击的代码:
        3. ...Email email = new SimpleEmail();
          email.setHostName("smtp.servermail.com");
          email.setSmtpPort(465);
          email.setAuthenticator(new DefaultAuthenticator(username, password));
          email.setSSLOnConnect(true);
          email.setFrom("user@gmail.com");
          email.setSubject("TestMail");
          email.setMsg("This is a test mail ... :-)");
          email.addTo("foo@bar.com");
          email.send();...
        1. 解决方案:
        2. 请添加以下检查以验证服务器证书:
        3. email.setSSLCheckServerIdentity(true);
        1. 构建包含用户输入的 SimpleDB 查询可能允许攻击者查看未经授权的记录。
        2. 以下示例动态构造并执行 SimpleDB SELECT 查询,允许用户指定 productCategory。攻击者可以修改查询,绕过 customerID 所需的身份验证并查看与任何客户匹配的记录。
        3. 易受攻击的代码:
        4. ...String customerID = getAuthenticatedCustomerID(customerName, customerCredentials);String productCategory = request.getParameter("productCategory");...AmazonSimpleDBClient sdbc = new AmazonSimpleDBClient(appAWSCredentials);String query = "select * from invoices where productCategory = '"
          + productCategory + "' and customerID = '"
          + customerID + "' order by '"
          + sortColumn + "' asc";SelectResult sdbResult = sdbc.select(new SelectRequest(query));
        1. 解决方案:
        2. 这个问题类似于 SQL 注入。在 SimpleDB 查询中使用之前清理用户输入。
        1. 攻击者可以设置可能危及系统完整性的任意 bean 属性。Bean 填充函数允许设置 bean 属性或嵌套属性。攻击者可以利用此功能访问特殊的 bean 属性class.classLoader,这样他就可以覆盖系统属性并可能执行任意代码。
        2. 易受攻击的代码:
        3. MyBean bean = ...;HashMap map = new HashMap();Enumeration names = request.getParameterNames();while (names.hasMoreElements()) {
          String name = (String) names.nextElement();
          map.put(name, request.getParameterValues(name));}BeanUtils.populate(bean, map);
        1. 解决方案:
        2. 避免使用用户控制的值来填充 Bean 属性名称。
        1. 使用用户输入构建服务器端重定向路径可能允许攻击者下载应用程序二进制文件(包括应用程序类或 jar 文件)或查看受保护目录中的任意文件。
        2. 攻击者可能能够伪造请求参数以匹配敏感文件位置。例如,请求"http://example.com/?returnURL=WEB-INF/applicationContext.xml"将显示应用程序的applicationContext.xml文件。攻击者可以定位并下载applicationContext.xml其他配置文件中引用的文件,甚至是class文件或jar文件,获取敏感信息,发起其他类型的攻击。
        3. 易受攻击的代码:
        4. ...String returnURL = request.getParameter("returnURL");Return new ActionForward(returnURL);...
        1. 解决方案:
        2. 避免使用用户控制的输入构建服务器端重定向。
        1. 使用用户输入构建服务器端重定向路径可能允许攻击者下载应用程序二进制文件(包括应用程序类或 jar 文件)或查看受保护目录中的任意文件。
        2. 攻击者可能能够伪造请求参数以匹配敏感文件位置。例如,请求"http://example.com/?returnURL=WEB-INF/applicationContext.xml"将显示应用程序的applicationContext.xml文件。攻击者可以定位并下载applicationContext.xml其他配置文件中引用的文件,甚至是class文件或jar文件,获取敏感信息,发起其他类型的攻击。
        3. 易受攻击的代码:
        4. ...String returnURL = request.getParameter("returnURL");return new ModelAndView(returnURL);...
        1. 解决方案:
        2. 避免使用用户控制的输入构建服务器端重定向。
        1. 使用用户输入构建服务器端重定向路径可能允许攻击者下载应用程序二进制文件(包括应用程序类或 jar 文件)或查看受保护目录中的任意文件。
        2. 攻击者可能能够伪造请求参数以匹配敏感文件位置。例如,请求"http://example.com/?jspFile=../applicationContext.xml%3F"将显示应用程序的applicationContext.xml文件。攻击者可以定位并下载applicationContext.xml其他配置文件中引用的文件,甚至是class文件或jar文件,获取敏感信息,发起其他类型的攻击。
        3. 易受攻击的代码:
        4. ...String jspFile = request.getParameter("jspFile");
          request.getRequestDispatcher("/WEB-INF/jsps/" + jspFile + ".jsp").include(request, response);...
        1. 解决方案:
        2. 避免使用用户控制的输入构建服务器端重定向。
        1. 许用户输入控制格式参数可能使攻击者能够引发异常或泄漏信息。
        2. 攻击者可能能够修改格式字符串参数,从而引发异常。如果此异常未被捕获,则可能会导致应用程序崩溃。或者,如果在未使用的参数中使用了敏感信息,攻击者可能会更改格式字符串以显示此信息。
        3. 下面的示例代码让用户指定显示余额的小数点。用户实际上可以指定任何导致抛出可能导致应用程序失败的异常的内容。在这个例子中更重要的是,如果攻击者可以指定用户输入"2f %3$s %4$.2",格式字符串将是"The customer: %s %s has the balance %4$.2f %3$s %4$.2". 这将导致敏感accountNo 要包含在结果字符串中。
        4. 易受攻击的代码:
        5. Formatter formatter = new Formatter(Locale.US);String format = "The customer: %s %s has the balance %4$." + userInput + "f";
          formatter.format(format, firstName, lastName, accountNo, balance);
        1. 解决方案:
        2. 避免在格式字符串参数中使用用户控制的值。
        1. 未经验证的用户输入连接到 URL 中可能允许攻击者覆盖请求参数的值。攻击者可能能够覆盖现有参数值、注入新参数或利用无法直接访问的变量。HTTP 参数污染 (HPP) 攻击包括将编码的查询字符串分隔符注入其他现有参数。如果 Web 应用程序没有正确清理用户输入,恶意用户可能会破坏应用程序的逻辑以执行客户端或服务器端攻击。
        2. 在下面的例子中,程序员没有考虑攻击者可以提供lang诸如的参数的可能性en&user_id=1,这将使他能够随意更改user_id。
        3. 易受攻击的代码:
        4. String input = request.getParameter("lang");GetMethod get = new GetMethod("http://www.host.com/viewDetails");
          get.setQueryString("lang=" + input + "&user_id=" + userId);
          get.execute();
      1. 解决方案:
      2. 你可以将其放置在HTTP参数或使用之前任一编码的用户输入 UriBuilder类 从Apache的HttpClient的
      3. URIBuilder uriBuilder = new URIBuilder("http://www.host.com/viewDetails");
        uriBuilder.addParameter("lang", input);
        uriBuilder.addParameter("user_id", userId);
         
        HttpGet httpget = new HttpGet(uriBuilder.build().toString()); //OK
      1. 敏感信息本身可能是有价值的信息(例如密码),也可能对发起其他更致命的攻击很有用。如果攻击失败,攻击者可能会利用服务器提供的错误信息发起另一次更有针对性的攻击。例如,尝试利用路径遍历弱点 (CWE-22) 可能会产生已安装应用程序的完整路径名。反过来,这可用于选择适当数量的“..”序列以导航到目标文件。使用 SQL 注入 (CWE-89) 的攻击最初可能不会成功,但错误消息可能会揭示格式错误的查询,这会暴露查询逻辑,甚至可能暴露查询中使用的密码或其他敏感信息。
      2. 易受攻击的代码:
      3. try {
        out = httpResponse.getOutputStream()} catch (Exception e) {
        e.printStackTrace(out);}
      1. 简单邮件传输协议 (SMTP) 是一种用于电子邮件传送的基于文本的协议。与 HTTP 一样,标头由换行符分隔。如果用户输入位于标题行中,则应用程序应删除或替换新行字符 ( CR/ LF)。您应该使用安全包装器,例如Apache Common Email 和Simple Java Mail,它们可以过滤可能导致头部注入的特殊字符。
      2. 易受攻击的代码:
      3. Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress("noreply@your-organisation.com"));
        message.setRecipients(Message.RecipientType.TO, new InternetAddress[] {new InternetAddress("target@gmail.com")});
        message.setSubject(usernameDisplay + " has sent you notification"); //Injectable API
        message.setText("Visit your ACME Corp profile for more info.");Transport.send(message);
      4. 解决方案
      1. 在 Apache XML RPC 服务器或客户端中启用扩展可能会导致反序列化漏洞,这将允许攻击者执行任意代码。 
      2. 建议不要使用or 的setEnabledForExtensions方法。默认情况下,客户端和服务器上的扩展都被禁用。org.apache.xmlrpc.client.XmlRpcClientConfigImplorg.apache.xmlrpc.XmlRpcConfigImpl
      3. 参考
      1. 禁用 HTML 转义会使应用程序面临跨站点脚本 (XSS) 的风险。
      2. 易受攻击的代码:
      3. add(new Label("someLabel").setEscapeModelStrings(false));
      1. 安全断言标记语言 (SAML) 是一种使用 XML 的单点登录协议。SAMLResponse 消息包括描述经过身份验证的用户的语句。如果用户设法放置 XML 注释 ( <!-- -->),则可能会导致解析器提取文字值的方式出现问题。
      2. 例如,让我们采用以下 XML 部分:
      3. <saml:Subject><saml:NameID>admin@domain.com<!---->.evil.com</saml:NameID></saml:Subject>
      4. 用户身份是"admin@domain.com<!---->.evil.com"但它实际上是一个文本节点"admin@domain.com"、一个评论""和一个文本节点".evil.com"。提取 NameID 时,服务提供者实现可能会采用第一个文本节点或最后一个文本节点。
      5. 易受攻击的代码:
      6. @BeanParserPool parserPool1() {
        BasicParserPool pool = new BasicParserPool();
        pool.setIgnoreComments(false);
        return pool;}
      7. 解决方案:
      8. @BeanParserPool parserPool1() {
        BasicParserPool pool = new BasicParserPool();
        pool.setIgnoreComments(true);
        return pool;}
      1. 为所有用户设置过于宽松的文件权限(例如 read+write+exec)通常是一种不好的做法。如果受影响的文件是配置、二进制文件、脚本或敏感数据,则可能导致权限提升或信息泄漏。
      2. 与您的应用程序在同一主机上运行的另一项服务可能会受到威胁。服务通常在不同的用户下运行。受感染的服务帐户可用于读取您的配置、向脚本添加执行指令或更改数据文件。为了限制来自其他服务或本地用户的损害,您应该限制您的应用程序文件的权限。
      3. 易受攻击的代码 1(符号表示法):
      4. Files.setPosixFilePermissions(configPath, PosixFilePermissions.fromString("rw-rw-rw-"));
      5. 解决方案1(符号表示法):
      6. Files.setPosixFilePermissions(configPath, PosixFilePermissions.fromString("rw-rw----"));
      7. 漏洞代码2(面向对象的实现):
      8. Set<PosixFilePermission> perms = new HashSet<>();
        perms.add(PosixFilePermission.OWNER_READ);
        perms.add(PosixFilePermission.OWNER_WRITE);
        perms.add(PosixFilePermission.OWNER_EXECUTE);
         
        perms.add(PosixFilePermission.GROUP_READ);
        perms.add(PosixFilePermission.GROUP_WRITE);
        perms.add(PosixFilePermission.GROUP_EXECUTE);
         
        perms.add(PosixFilePermission.OTHERS_READ);
        perms.add(PosixFilePermission.OTHERS_WRITE);
        perms.add(PosixFilePermission.OTHERS_EXECUTE);
      9. 方案二(面向对象的实现):
      10. Set<PosixFilePermission> perms = new HashSet<>();
        perms.add(PosixFilePermission.OWNER_READ);
        perms.add(PosixFilePermission.OWNER_WRITE);
        perms.add(PosixFilePermission.OWNER_EXECUTE);
         
        perms.add(PosixFilePermission.GROUP_READ);
        perms.add(PosixFilePermission.GROUP_WRITE);
        perms.add(PosixFilePermission.GROUP_EXECUTE);
      1. Unicode 转换中的意外行为有时会导致错误,其中一些会影响软件安全。将大写转换应用于两个字符串的代码可能会错误地将两个字符串解释为相等。
      2. 在下面的代码中,字符串"ADMu0131N"会导致条件为真。应用大写转换后,字符u0131将变为u0049(I)。如果开发人员只有一个用户,这可能是一个问题"ADMIN"。
      3. if(username.toUpperCase().equals("ADMIN")) {
        //...}
      4. 使用归一化函数可以发生类似的字符转换。在下面的代码中,字符串"BACu212AUP"会导致条件为真。应用归一化变换后,字符u212A将变为u0048(K)。
      5. if(Normalizer.normalize(input, Normalizer.Form.NFC).equals("BACKUP")) {
        //...}
 
原文地址:https://www.cnblogs.com/nancyfeng/p/15404497.html