Java规范之Sonar规则的汉化【漏洞类】

规则S1148 : 不可以调用"Throwable.printStackTrace(...)",使用日志

错误的代码示例

try {
  /* ... */
} catch(Exception e) {
  e.printStackTrace();        // 错误示范
}

正确的代码示例

try {
  /* ... */
} catch(Exception e) {
  LOGGER.log("context", e);
}

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
MITRE, CWE-489 - Leftover Debug Code

规则S1444 : "public static"需要为固定值

错误的代码示例

public class Greeter {
  public static Foo foo = new Foo();
  ...
}

正确的代码示例

public class Greeter {
  public static final Foo FOO = new Foo();
  ...
}

See

MITRE, CWE-500 - Public Static Field Not Marked Final
CERT OBJ10-J - Do not use public static nonfinal fields

规则S1989 : servlet的所有方法不可以抛出"Exception"

错误的代码示例

public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {
  String ip = request.getRemoteAddr();
  InetAddress addr = InetAddress.getByName(ip); // 错误示范; getByName(String) throws UnknownHostException
  //...
}

正确的代码示例

public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {
  try {
    String ip = request.getRemoteAddr();
    InetAddress addr = InetAddress.getByName(ip);
    //...
  }
  catch (UnknownHostException uhex) {
    //...
  }
}

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
MITRE, CWE-600 - Uncaught Exception in Servlet
CERT, ERR01-J. - Do not allow exceptions to expose sensitive information

规则S2039 : 类的所有属性可见性需要声明

错误的代码示例

class Ball {
    String color="red";  // 错误示范
}
enum A {
  B;
  int a;
}

正确的代码示例

class Ball {
    private String color="red";  // 正确的代码示范
}
enum A {
  B;
  private int a;
}

特殊情况

添加了Guava @VisibleForTesting 注解的资源可以不适用本规范

class Cone {
  @VisibleForTesting
  Logger logger; // 正确的代码示范
}

规则S2070 : SHA-1和MD5算法不可用于安全操作

SHA1和MD5已经被标识为非安全的算法。

错误的代码示例

MessageDigest md = MessageDigest.getInstance("SHA1");  // 错误示范

正确的代码示例

MessageDigest md = MessageDigest.getInstance("SHA-256");

See

OWASP Top 10 2017 Category A6 - Security
Misconfiguration
MITRE, CWE-328 - Reversible One-Way Hash
MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
SANS Top 25 - Porous Defenses
SHAttere - The first concrete collision attack against SHA-1.

规则S2089 : 不可以信赖"HTTP"请求头中的"referer"值

该值可能是攻击篡改的内容。

错误的代码示例

public class MyServlet extends HttpServlet {
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    String referer = request.getHeader("referer");  // 错误示范
    if(isTrustedReferer(referer)){
      //..
    }
    //...
  }
}

See
OWASP Top 10 2017 Category A2 - Broken Authentication
MITRE, CWE-807 - Reliance on Untrusted Inputs in a Security Decision
MITRE, CWE-293 - Using Referer Field for Authentication
SANS Top 25 - Porous Defenses

规则S2115 : 所有的数据库访问必须使用密码

不可以使用免密的数据库连接。

错误的代码示例

Connection conn = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true", "AppLogin", "");
Connection conn2 = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true?user=user&password=");

正确的代码示例

DriverManager.getConnection("jdbc:derby:memory:myDB;create=true?user=user&password=password");

DriverManager.getConnection("jdbc:mysql://address=(host=myhost1)(port=1111)(key1=value1)(user=sandy)(password=secret),address=(host=myhost2)(port=2222)(key2=value2)(user=sandy)(password=secret)/db");

DriverManager.getConnection("jdbc:mysql://sandy:secret@[myhost1:1111,myhost2:2222]/db");

String url = "jdbc:postgresql://localhost/test";
Properties props = new Properties();
props.setProperty("user", "fred");
props.setProperty("password", "secret");
DriverManager.getConnection(url, props);

See
OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
MITRE, CWE-521 - Weak Password Requirements

规则S2254 : 不可使用"HttpServletRequest.getRequestedSessionId()"

错误的代码示例

if(isActiveSession(request.getRequestedSessionId()) ){
  ...
}

See
OWASP Top 10 2017 Category A2 - Broken Authentication MITRE, CWE-807 - Reliance on Untrusted Inputs in a Security Decision
SANS Top 25 - Porous Defenses

规则S2384 : 可变化的属性,不能直接返回或赋值

错误的代码示例

class A {
  private String [] strings;

  public A () {
    strings = new String[]{"first", "second"};
  }

  public String [] getStrings() {
    return strings; // 错误示范
  }

  public void setStrings(String [] strings) {
    this.strings = strings;  // 错误示范
  }
}

public class B {

  private A a = new A();  // At this point a.strings = {"first", "second"};

  public void wreakHavoc() {
    a.getStrings()[0] = "yellow";  // a.strings = {"yellow", "second"};
  }
}

正确的代码示例

class A {
  private String [] strings;

  public A () {
    strings = new String[]{"first", "second"};
  }

  public String [] getStrings() {
    return strings.clone();
  }

  public void setStrings(String [] strings) {
    this.strings = strings.clone();
  }
}

public class B {

  private A a = new A();  // At this point a.strings = {"first", "second"};

  public void wreakHavoc() {
    a.getStrings()[0] = "yellow";  // a.strings = {"first", "second"};
  }
}

See

ITRE, CWE-374 - Passing Mutable Objects to an Untrusted Method
MITRE, CWE-375 - Returning a Mutable Object to an Untrusted Caller
CERT, OBJ05-J. - Do not return references to private mutable class members
CERT, OBJ06-J. - Defensively copy mutable inputs and mutable internal
components
CERT, OBJ13-J. - Ensure that references to mutable objects are not exposed

规则S2386 : 需要保证"public static"属性不可修改

错误的代码示例

public interface MyInterface {
  public static String [] strings; // 错误示范
}

public class A {
  public static String [] strings1 = {"first","second"};  // 错误示范
  public static String [] strings2 = {"first","second"};  // 错误示范
  public static List strings3 = new ArrayList<>();  // 错误示范
  // ...
}

See

MITRE, CWE-582 - Array Declared Public, Final, and Static
MITRE, CWE-607 - Public Static Final Field References Mutable Object
CERT, OBJ01-J. - Limit accessibility of fields
CERT, OBJ13-J. - Ensure that references to mutable objects are not exposed

规则S2612 : 正确设置文件的访问权限

  • 错误的代码示范
    public void setPermissions(String filePath) {
        Set perms = new HashSet();
        // user permission
        perms.add(PosixFilePermission.OWNER_READ);
        perms.add(PosixFilePermission.OWNER_WRITE);
        perms.add(PosixFilePermission.OWNER_EXECUTE);
        // group permissions
        perms.add(PosixFilePermission.GROUP_READ);
        perms.add(PosixFilePermission.GROUP_EXECUTE);
        // others permissions
        perms.add(PosixFilePermission.OTHERS_READ); // Sensitive
        perms.add(PosixFilePermission.OTHERS_WRITE); // Sensitive
        perms.add(PosixFilePermission.OTHERS_EXECUTE); // Sensitive

        Files.setPosixFilePermissions(Paths.get(filePath), perms);
    }
    public void setPermissionsUsingRuntimeExec(String filePath) {
        Runtime.getRuntime().exec("chmod 777 file.json"); // Sensitive
    }
    public void setOthersPermissionsHardCoded(String filePath ) {
        Files.setPosixFilePermissions(Paths.get(filePath), PosixFilePermissions.fromString("rwxrwxrwx")); // Sensitive
    }

正确的代码示例

    public void setPermissionsSafe(String filePath) throws IOException {
        Set perms = new HashSet();
        // user permission
        perms.add(PosixFilePermission.OWNER_READ);
        perms.add(PosixFilePermission.OWNER_WRITE);
        perms.add(PosixFilePermission.OWNER_EXECUTE);
        // group permissions
        perms.add(PosixFilePermission.GROUP_READ);
        perms.add(PosixFilePermission.GROUP_EXECUTE);
        // others permissions removed
        perms.remove(PosixFilePermission.OTHERS_READ); // 正确的代码示范
        perms.remove(PosixFilePermission.OTHERS_WRITE); // 正确的代码示范
        perms.remove(PosixFilePermission.OTHERS_EXECUTE); // 正确的代码示范

        Files.setPosixFilePermissions(Paths.get(filePath), perms);
    }

See

OWASP Top 10 2017 Category A5 - Broken Access Control
OWASP File Permission
MITRE, CWE-732 - Incorrect Permission Assignment for Critical Resource
CERT, FIO01-J. -
Create files with appropriate access permissions
CERT, FIO06-C. - Create
files with appropriate access permissions
SANS Top 25 - Porous Defenses

规则S2647 : 禁止使用"Basic"认证方式

错误的代码示例

// Using HttpPost from Apache HttpClient
String encoding = Base64Encoder.encode ("login:passwd");
org.apache.http.client.methods.HttpPost httppost = new HttpPost(url);
httppost.setHeader("Authorization", "Basic " + encoding);  // 错误示范

or

// Using HttpURLConnection
String encoding = Base64.getEncoder().encodeToString(("login:passwd").getBytes("UTF-8"));
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Authorization", "Basic " + encoding); // 错误示范

See
OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
OWASP Basic Authentication
MITRE, CWE-522 - Insufficiently Protected Credentials
SANS Top 25 - Porous Defenses

规则S2653 : Servlet容器部署"Web"应用不得包含main方法

错误的代码示例

public class MyServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    if (userIsAuthorized(req)) {
      updatePrices(req);
    }
  }

  public static void main(String[] args) { // 错误示范
    updatePrices(req);
  }
}

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
MITRE, CWE-489 - Leftover Debug Code
CERT, ENV06-J. - Production code must not contain debugging entry points

规则S2658 : 不可以动态加载类

错误的代码示例

String className = System.getProperty("messageClassName");
Class clazz = Class.forName(className);  // 错误示范

See

OWASP Top 10 2017 Category A1 - Injection
MITRE, CWE-470 - Use of Externally-Controlled Input to Select Classes or Code
('Unsafe Reflection')

规则S2755 : "XML"解析必须防护XXE攻击


  
  ]>

  &xxe;
  Jani
  Reminder
  Don't forget me this weekend!



]>

  
  
 
  &content;
 



  ]>

  
  
    
      
        
        
        
        
      
    
  

错误的代码示例

DocumentBuilderFactory library:

String xml = "xxe.xml";
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();  // 错误示范
DocumentBuilder builder = df.newDocumentBuilder();
Document document = builder.parse(new InputSource(xml));
DOMSource domSource = new DOMSource(document);

SAXParserFactory library:

String xml = "xxe.xml";
SaxHandler handler = new SaxHandler();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();  // 错误示范
parser.parse(xml, handler);

XMLInputFactory library:

XMLInputFactory factory = XMLInputFactory.newInstance();  // 错误示范
XMLEventReader eventReader = factory.createXMLEventReader(new FileReader("xxe.xml"));

TransformerFactory library:

String xslt = "xxe.xsl";
String xml = "xxe.xml";
TransformerFactory transformerFactory = javax.xml.transform.TransformerFactory.newInstance();  // 错误示范
Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt));

StringWriter writer = new StringWriter();
transformer.transform(new StreamSource(xml), new StreamResult(writer));
String result = writer.toString();

SchemaFactory library:

String xsd = "xxe.xsd";
StreamSource xsdStreamSource = new StreamSource(xsd);

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);  // 错误示范
Schema schema = schemaFactory.newSchema(xsdStreamSource);

Validator library:

String xsd = "xxe.xsd";
String xml = "xxe.xml";
StreamSource xsdStreamSource = new StreamSource(xsd);
StreamSource xmlStreamSource = new StreamSource(xml);

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(xsdStreamSource);
Validator validator = schema.newValidator();   // 错误示范

StringWriter writer = new StringWriter();
validator.validate(xmlStreamSource, new StreamResult(writer));

Dom4j library:

SAXReader xmlReader = new SAXReader(); // 错误示范 by default
Document xmlResponse = xmlReader.read(xml);

Jdom2 library:

SAXBuilder builder = new SAXBuilder(); // 错误示范 by default
Document document = builder.build(new File(xml));

正确的代码示例

DocumentBuilderFactory library:

String xml = "xxe.xml";
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // 正确的代码示范
df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // 正确的代码示范
DocumentBuilder builder = df.newDocumentBuilder();
Document document = builder.parse(new InputSource(xml));
DOMSource domSource = new DOMSource(document);

SAXParserFactory library:

String xml = "xxe.xml";
SaxHandler handler = new SaxHandler();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // 正确的代码示范
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // 正确的代码示范
parser.parse(xml, handler);

XMLInputFactory library:

XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // 正确的代码示范
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");  // 正确的代码示范

XMLEventReader eventReader = factory.createXMLEventReader(new FileReader("xxe.xml"));

TransformerFactory library:

String xslt = "xxe.xsl";
String xml = "xxe.xml";
TransformerFactory transformerFactory = javax.xml.transform.TransformerFactory.newInstance();
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // 正确的代码示范
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); // 正确的代码示范
// ACCESS_EXTERNAL_SCHEMA not supported in several TransformerFactory implementations
Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt));

StringWriter writer = new StringWriter();
transformer.transform(new StreamSource(xml), new StreamResult(writer));
String result = writer.toString();

SchemaFactory library:

String xsd = "xxe.xsd";
StreamSource xsdStreamSource = new StreamSource(xsd);

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // 正确的代码示范
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // 正确的代码示范
Schema schema = schemaFactory.newSchema(xsdStreamSource);

Validator library:

String xsd = "xxe.xsd";
String xml = "xxe.xml";
StreamSource xsdStreamSource = new StreamSource(xsd);
StreamSource xmlStreamSource = new StreamSource(xml);

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(xsdStreamSource);
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
// validators will also inherit of these properties
Validator validator = schema.newValidator();

validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");   // 正确的代码示范
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");   // 正确的代码示范

StringWriter writer = new StringWriter();
validator.validate(xmlStreamSource, new StreamResult(writer));

dom4j library, ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA are not supported, thus a very strict fix
is to disable doctype declarations:

SAXReader xmlReader = new SAXReader();
xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 正确的代码示范
Document xmlResponse = xmlReader.read(xml);

Jdom2 library:

SAXBuilder builder = new SAXBuilder(); // 正确的代码示范
builder.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // 正确的代码示范
builder.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // 正确的代码示范
Document document = builder.build(new File(xml));

See

OWASP Top 10 2017 Category A4 - XML External Entities
(XXE)
OWASP XXE Prevention Cheat Sheet
MITRE, CWE-611 - Information Exposure Through XML External Entity Reference
MITRE, CWE-827 - Improper Control of Document Type Definition

规则S2976 : 不可以使用"File.createTempFile" 创建目录

错误的代码示例

File tempDir;
tempDir = File.createTempFile("", ".");
tempDir.delete();
tempDir.mkdir();  // 错误示范

正确的代码示例

Path tempPath = Files.createTempDirectory("");
File tempDir = tempPath.toFile();

See

OWASP Top 10 2017 Category A9 - Using Components with Known Vulnerabilities

规则S3066 : "enum"的属性不可以修改

错误的代码示例

public enum Continent {

  NORTH_AMERICA (23, 24709000),
  // ...
  EUROPE (50, 39310000);

  public int countryCount;  // 错误示范
  private int landMass;

  Continent(int countryCount, int landMass) {
    // ...
  }

  public void setLandMass(int landMass) {  // 错误示范
    this.landMass = landMass;
  }

正确的代码示例

public enum Continent {

  NORTH_AMERICA (23, 24709000),
  // ...
  EUROPE (50, 39310000);

  private int countryCount;
  private int landMass;

  Continent(int countryCount, int landMass) {
    // ...
  }

规则S3329 : Cypher Block Chaining IV's 初始化必须随机且唯一

错误的代码示例

public class MyCbcClass {

  public String applyCBC(String strKey, String plainText) {
    byte[] bytesIV = "7cVgr5cbdCZVw5WY".getBytes("UTF-8");

    /* KEY + IV setting */
    IvParameterSpec iv = new IvParameterSpec(bytesIV);
    SecretKeySpec skeySpec = new SecretKeySpec(strKey.getBytes("UTF-8"), "AES");

    /* Ciphering */
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);  // 错误示范 because IV hard coded and cannot vary with each ciphering round
    byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
    return DatatypeConverter.printBase64Binary(bytesIV) // IV is typically published
            + ";" + DatatypeConverter.printBase64Binary(encryptedBytes);
  }
}

正确的代码示例

public class MyCbcClass {

  SecureRandom random = new SecureRandom();

  public String applyCBC(String strKey, String plainText) {
    byte[] bytesIV = new byte[16];
    random.nextBytes(bytesIV);

    /* KEY + IV setting */
    IvParameterSpec iv = new IvParameterSpec(bytesIV);
    SecretKeySpec skeySpec = new SecretKeySpec(strKey.getBytes("UTF-8"), "AES");

    /* Ciphering */
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
    byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
    return DatatypeConverter.printBase64Binary(bytesIV)
            + ";" + DatatypeConverter.printBase64Binary(encryptedBytes);
  }
}

See

MITRE, CWE-330 - Use of Insufficiently Random Values

OWASP Top 10 2017 Category A6 - Security Misconfiguration
Derived from FindSecBugs rule
STATIC_IV

规则S3355 : web.xml中定义的过滤器必须使用

错误的代码示例

  
     DefinedNotUsed
     com.myco.servlet.ValidationFilter
  

正确的代码示例

  
     ValidationFilter
     com.myco.servlet.ValidationFilter
  

  
     ValidationFilter
     /*
  

See

OWASP Top 10 2017 Category A6 - Security Misconfiguration

规则S3749 : Spring组件的成员变量需要注入

错误的代码示例

@Controller
public class HelloWorld {

  private String name = null;

  @RequestMapping("/greet", method = GET)
  public String greet(String greetee) {

    if (greetee != null) {
      this.name = greetee;
    }

    return "Hello " + this.name;  // if greetee is null, you see the previous user's data
  }
}

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure

规则S3751 : "@RequestMapping"必须为"public"

错误的代码示例

@RequestMapping("/greet", method = GET)
private String greet(String greetee) {  // 错误示范

正确的代码示例

@RequestMapping("/greet", method = GET)
public String greet(String greetee) {

See

OWASP Top 10 2017 Category A6 - Security Misconfiguration

规则S3752 : "@RequestMapping"必须指定 HTTP方法

错误的代码示例

@RequestMapping("/greet")  // 错误示范
public String greet(String greetee) {
}

@RequestMapping(path = "/delete", method = {RequestMethod.GET, RequestMethod.POST}) // 错误示范
String delete(@RequestParam("id") String id) {
  return "Hello from delete";
}

正确的代码示例

  @RequestMapping("/greet", method = GET)
  public String greet(String greetee) {
  }

  @RequestMapping(path = "/delete", method = RequestMethod.GET)
  String delete(@RequestParam("id") String id) {
   return "Hello from delete";
  }

See
OWASP Top 10 2017 Category A6 - Security Misconfiguration
MITRE, CWE-352 - Cross-Site Request Forgery (CSRF)
OWASP: Cross-Site Request Forgery
SANS Top 25 - Insecure Interaction Between Components
Spring Security Official Documentation: Use proper HTTP verbs (CSRF protection)

规则S4347 : "SecureRandom"的种子必须具有不可预测性

错误的代码示例

SecureRandom sr = new SecureRandom();
sr.setSeed(123456L); // 错误示范
int v = sr.next(32);

sr = new SecureRandom("abcdefghijklmnop".getBytes("us-ascii")); // 错误示范
v = sr.next(32);

正确的代码示例

SecureRandom sr = new SecureRandom();
int v = sr.next(32);

See

OWASP Top 10 2017 Category A6 - Security Misconfiguration
MITRE, CWE-330 - Use of Insufficiently Random Values
MITRE, CWE-332 - Insufficient Entropy in PRNG
MITRE, CWE-336 - Same Seed in Pseudo-Random Number Generator (PRNG)
MITRE, CWE-337 - Predictable Seed in Pseudo-Random Number Generator (PRNG)
CERT, MSC63J. - Ensure that SecureRandom is properly seeded

规则S4423 : 不可以使用弱"SSL/TLS"协议

错误的代码示例

context = SSLContext.getInstance("SSLv3"); // 错误示范

正确的代码示例

context = SSLContext.getInstance("TLSv1.2");

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
OWASP Top 10 2017 Category A6 - Security Misconfiguration
MITRE, CWE-327 - Inadequate Encryption Strength
MITRE, CWE-326 - Use of a Broken or Risky Cryptographic Algorithm
SANS Top 25 - Porous Defenses
Diagnosing TLS, SSL, and HTTPS
SSL and TLS Deployment Best Practices - Use secure protocols

规则S4426 : 非对称加密/验密算法的Key必须足够强壮

错误的代码示例

KeyPairGenerator keyPairGen1 = KeyPairGenerator.getInstance("RSA");
keyPairGen1.initialize(1024); // 错误示范

KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec ecSpec1 = new ECGenParameterSpec("secp112r1"); // 错误示范
keyPairGen5.initialize(ecSpec1);

KeyGenerator keyGen1 = KeyGenerator.getInstance("AES");
keyGen1.init(64); // 错误示范

正确的代码示例

KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("RSA");
keyPairGen6.initialize(2048); // 正确的代码示范

KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec ecSpec10 = new ECGenParameterSpec("secp224k1"); // 正确的代码示范
keyPairGen5.initialize(ecSpec10);

KeyGenerator keyGen2 = KeyGenerator.getInstance("AES");
keyGen2.init(128); // 正确的代码示范

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
OWASP Top 10 2017 Category A9 - Security Misconfiguration
NIST 800-131A - Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths
MITRE, CWE-326 - Inadequate Encryption Strength

规则S4433 : 所有的"LDAP"连接需要进行身份认证

错误的代码示例

// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Use anonymous authentication
env.put(Context.SECURITY_AUTHENTICATION, "none"); // 错误示范

// Create the initial context
DirContext ctx = new InitialDirContext(env);

正确的代码示例

// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Use simple authentication
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, getLDAPPassword());

// Create the initial context
DirContext ctx = new InitialDirContext(env);

See

OWASP Top 10 2017 Category A2 - Broken Authentication CWE-521 - Weak Password Requirements
Modes of Authenticating to LDAP
Derived from FindSecBugs rule - LDAP_ANONYMOUS

规则S4434 : 禁止使用"LDAP"反序列化

错误的代码示例

DirContext ctx = new InitialDirContext();
// ...
ctx.search(query, filter,
        new SearchControls(scope, countLimit, timeLimit, attributes,
            true, // 错误示范; allows deserialization
            deref));

正确的代码示例

DirContext ctx = new InitialDirContext();
// ...
ctx.search(query, filter,
        new SearchControls(scope, countLimit, timeLimit, attributes,
            false,
            deref));

See

MITRE, CWE-502 - Deserialization of Untrusted Data
OWASP Top 10 2017 Category A8 - Insecure Deserialization
BlackHat presentation
Derived from FindSecBugs rule - LDAP_ENTRY_POISONING

规则S4435 : 需要安全的"XML"转换器

错误的代码示例

Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(input, result);

正确的代码示例

Recommended:

TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

Transformer transformer = factory.newTransformer();

transformer.transform(input, result);

Implementation dependent:

TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

Transformer transformer = factory.newTransformer();

transformer.transform(input, result);

See

OWASP Top 10 2017 Category A4 XML External Entities
OWASP XXE Cheat Sheet
MITRE, CWE-611 - Improper Restriction of XML External Entity Reference ('XXE')
Derived from FindSecBugs ruleXXE_DTD_TRANSFORM_FACTORY
Derived from FindSecBugs rule XXE_XSLT_TRANSFORM_FACTORY

Deprecated

This rule is deprecated; use {rule:java:S2755} instead.

规则S4499 : "SMTP SSL"连接需要检查服务器身份

错误的代码示例

Email email = new SimpleEmail();
email.setSmtpPort(465);
email.setAuthenticator(new DefaultAuthenticator(username, password));
email.setSSLOnConnect(true); // 错误示范; setSSLCheckServerIdentity(true) should also be called before sending the email
email.send();
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // 错误示范; Session is created without having "mail.smtp.ssl.checkserveridentity" set to true
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("[email protected]", "password");
  }
});

正确的代码示例

Email email = new SimpleEmail();
email.setSmtpPort(465);
email.setAuthenticator(new DefaultAuthenticator(username, password));
email.setSSLOnConnect(true);
email.setSSLCheckServerIdentity(true); // 正确的代码示范
email.send();
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.ssl.checkserveridentity", true); // 正确的代码示范
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("[email protected]", "password");
  }
});

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
CWE-297 - Improper Validation of Certificate with Host Mismatch

Deprecated

This rule is deprecated; use {rule:java:S5527} instead.

规则S4601 : "HttpSecurity" URL匹配需要正确排序

错误的代码示例

  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      .antMatchers("/resources/**", "/signup", "/about").permitAll() // 正确的代码示范
      .antMatchers("/admin/**").hasRole("ADMIN")
      .antMatchers("/admin/login").permitAll() // 错误示范; the pattern "/admin/login" should occurs before "/admin/**"
      .antMatchers("/**", "/home").permitAll()
      .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // 错误示范; the pattern "/db/**" should occurs before "/**"
      .and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();
  }

正确的代码示例

  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      .antMatchers("/resources/**", "/signup", "/about").permitAll() // 正确的代码示范
      .antMatchers("/admin/login").permitAll()
      .antMatchers("/admin/**").hasRole("ADMIN") // 正确的代码示范
      .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
      .antMatchers("/**", "/home").permitAll() // 正确的代码示范; "/**" is the last one
      .and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();
  }

See

OWASP Top 10 2017 Category A6 - Security
Misconfiguration

规则S4684 : 持久化Entity不可用于"@RequestMapping"方法参数

错误的代码示例

import javax.persistence.Entity;

@Entity
public class Wish {
  Long productId;
  Long quantity;
  Client client;
}

@Entity
public class Client {
  String clientId;
  String name;
  String password;
}

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WishListController {

  @PostMapping(path = "/saveForLater")
  public String saveForLater(Wish wish) {
    session.save(wish);
  }

  @RequestMapping(path = "/saveForLater", method = RequestMethod.POST)
  public String saveForLater(Wish wish) {
    session.save(wish);
  }
}

正确的代码示例

public class WishDTO {
  Long productId;
  Long quantity;
  Long clientId;
}

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PurchaseOrderController {

  @PostMapping(path = "/saveForLater")
  public String saveForLater(WishDTO wish) {
    Wish persistentWish = new Wish();
    // do the mapping between "wish" and "persistentWish"
    [...]
    session.save(persistentWish);
  }

  @RequestMapping(path = "/saveForLater", method = RequestMethod.POST)
  public String saveForLater(WishDTO wish) {
    Wish persistentWish = new Wish();
    // do the mapping between "wish" and "persistentWish"
    [...]
    session.save(persistentWish);
  }
}

特殊情况

如果是用 @PathVariable注解,此规范可以忽略

See
OWASP Top 10 2017 Category A5 - Broken Access Control

MITRE, CWE-915 - Improperly Controlled Modification of Dynamically-Determined
Object Attributes
Two Security Vulnerabilities in the Spring
Framework’s MVC by Ryan Berg and Dinis Cruz

规则S4830 : 进行SSL/TLS连接时,需要进行服务器证书校验

错误的代码示例

class TrustAllManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {  // 错误示范, nothing means trust any client
    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { // 错误示范, this method never throws exception, it means trust any client
        LOG.log(Level.SEVERE, ERROR_MESSAGE);
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

See
OWASP Top 10 2017 Category A6 - Security
Misconfiguration
MITRE, CWE-295 - Improper Certificate Validation
CERT, MSC61-J. - Do not use insecure or weak cryptographic algorithms

规则S5301 : "ActiveMQConnectionFactory" 需要对任意数据包进行反序列化

错误的代码示例

ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
factory.setTrustAllPackages(true); // 错误示范

ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
// no call to factory.setTrustedPackages(...);

正确的代码示例

ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
factory.setTrustedPackages(Arrays.asList("org.mypackage1", "org.mypackage2"));

See

OWASP Top 10 2017 Category A8 - Insecure Deserialization
MITRE, CWE-502 - Deserialization of Untrusted Data
ActiveMQ ObjectMessage Security Advisory
CVE-2015-5254

规则S5344 : 需要使用安全的"PasswordEncoder"进行身份认证

错误的代码示例

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("SELECT * FROM users WHERE username = ?")
                .passwordEncoder(new StandardPasswordEncoder()); // 错误示范
        // OR
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("SELECT * FROM users WHERE username = ?"); // 错误示范; default uses plain-text
        // OR
        auth.userDetailsService(...); // 错误示范; default uses plain-text
        // OR
        auth.userDetailsService(...).passwordEncoder(new StandardPasswordEncoder()); // 错误示范
    }

正确的代码示例

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("Select * from users where username=?")
                .passwordEncoder(new BCryptPasswordEncoder());
        // or
        auth.userDetailsService(null).passwordEncoder(new BCryptPasswordEncoder());
    }

See
OWASP Top 10 2017 Category A2 - Broken Authentication
OWASP Top 10 2017 Category A6 - Securityc Misconfiguration
MITRE, CWE-328 - Reversible One-Way Hash
MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
SANS Top 25 - Porous Defenses

规则S5527 : SSL/TLS连接需要校验主机名

错误的代码示例

SSLContext sslcontext = SSLContext.getInstance( "TLS" );
sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
  public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
  public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
  public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }

}}, new java.security.SecureRandom());

Client client = ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(new HostnameVerifier() {
  @Override
  public boolean verify(String requestedHost, SSLSession remoteServerSession) {
    return true;  // 错误示范
  }
}).build();

SimpleEmail example:

Email email = new SimpleEmail();
email.setSmtpPort(465);
email.setAuthenticator(new DefaultAuthenticator(username, password));
email.setSSLOnConnect(true); // 错误示范; setSSLCheckServerIdentity(true) should also be called before sending the email
email.send();

JavaMail's example:

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // 错误示范; Session is created without having "mail.smtp.ssl.checkserveridentity" set to true
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("[email protected]", "password");
  }
});

正确的代码示例

SSLContext sslcontext = SSLContext.getInstance( "TLSv1.2" );
sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
  @Override
  public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
  @Override
  public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
  @Override
  public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }

}}, new java.security.SecureRandom());

Client client = ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(new HostnameVerifier() {
  @Override
  public boolean verify(String requestedHost, SSLSession remoteServerSession) {
    return requestedHost.equalsIgnoreCase(remoteServerSession.getPeerHost()); // 正确的代码示范
  }
}).build();

SimpleEmail example:

Email email = new SimpleEmail();
email.setSmtpPort(465);
email.setAuthenticator(new DefaultAuthenticator(username, password));
email.setSSLOnConnect(true);
email.setSSLCheckServerIdentity(true); // 正确的代码示范
email.send();

JavaMail's example:

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.ssl.checkserveridentity", true); // 正确的代码示范
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("[email protected]", "password");
  }
});

See
OWASP Top 10 2017 Category A6 - Security Misconfiguration
MITRE, CWE-295 - Improper Certificate Validation
Derived from FindSecBugs rule - WEAK_HOSTNAME_VERIFIER

规则S5542 : 加密算法需要使用安全模式及填充

错误的代码示例

Cipher c0 = Cipher.getInstance("AES"); // 错误示范: by default ECB mode is chosen
Cipher c1 = Cipher.getInstance("AES/ECB/NoPadding"); // 错误示范: ECB doesn't provide serious message confidentiality
Cipher c3 = Cipher.getInstance("Blowfish/ECB/PKCS5Padding"); // 错误示范: ECB doesn't provide serious message confidentiality
Cipher c4 = Cipher.getInstance("DES/ECB/PKCS5Padding"); // 错误示范: ECB doesn't provide serious message confidentiality

Cipher c6 = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 错误示范: CBC with PKCS5 is vulnerable to oracle padding attacks
Cipher c7 = Cipher.getInstance("Blowfish/CBC/PKCS5Padding"); // 错误示范: CBC with PKCS5 is vulnerable to oracle padding attacks
Cipher c8 = Cipher.getInstance("DES/CBC/PKCS5Padding"); // 错误示范: CBC with PKCS5 is vulnerable to oracle padding attacks
Cipher c9 = Cipher.getInstance("AES/CBC/PKCS7Padding"); // 错误示范: CBC with PKCS7 is vulnerable to oracle padding attacks
Cipher c10 = Cipher.getInstance("Blowfish/CBC/PKCS7Padding"); // 错误示范: CBC with PKCS7 is vulnerable to oracle padding attacks
Cipher c11 = Cipher.getInstance("DES/CBC/PKCS7Padding"); // 错误示范: CBC with PKCS7 is vulnerable to oracle padding attacks

Cipher c14 = Cipher.getInstance("RSA/NONE/NoPadding"); // 错误示范: RSA without OAEP padding scheme is not recommanded

正确的代码示例

// Recommended for block ciphers
Cipher c5 = Cipher.getInstance("AES/GCM/NoPadding"); // 正确的代码示范

// Recommended for RSA
Cipher c15 = Cipher.getInstance("RSA/None/OAEPWithSHA-1AndMGF1Padding"); // 正确的代码示范
Cipher c16 = Cipher.getInstance("RSA/None/OAEPWITHSHA-256ANDMGF1PADDING"); // 正确的代码示范

See
OWASP Top 10 2017 Category A6 - Security
Misconfiguration
MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
CERT, MSC61-J. - Do not use insecure or weak cryptographic algorithms
SANS Top 25 - Porous Defenses

规则S5547 : 需要使用强壮的密钥算法

错误的代码示例

import javax.crypto.Cipher;
import java.security.NoSuchAlgorithmException;
import javax.crypto.NoSuchPaddingException;

public class test {

    public static void main(String[] args) {
      try
      {
        Cipher c1 = Cipher.getInstance("DES"); // 错误示范: DES works with 56-bit keys allow attacks via exhaustive search
        Cipher c7 = Cipher.getInstance("DESede"); // 错误示范: Triple DES is vulnerable to meet-in-the-middle attack
        Cipher c13 = Cipher.getInstance("RC2"); // 错误示范: RC2 is vulnerable to a related-key attack
        Cipher c19 = Cipher.getInstance("RC4"); // 错误示范: vulnerable to several attacks (see https://en.wikipedia.org/wiki/RC4#Security)
        Cipher c25 = Cipher.getInstance("Blowfish"); // 错误示范: Blowfish use a 64-bit block size makes it vulnerable to birthday attacks

        NullCipher nc = new NullCipher(); // 错误示范: the NullCipher class provides an "identity cipher" one that does not transform or encrypt the plaintext in any way.
      }
      catch(NoSuchAlgorithmException|NoSuchPaddingException e)
      {
      }
    }
}

正确的代码示例

import javax.crypto.Cipher;
import java.security.NoSuchAlgorithmException;
import javax.crypto.NoSuchPaddingException;

public class test {

    public static void main(String[] args) {
      try
      {
        Cipher c31 = Cipher.getInstance("AES/GCM/NoPadding"); // 正确的代码示范
      }
      catch(NoSuchAlgorithmException|NoSuchPaddingException e)
      {
      }
    }
}

See

OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
CERT, MSC61-J. - Do not use insecure or weak cryptographic algorithms
SANS Top 25 - Porous Defenses

规则S899 : 如果方法返回中包含状态信息,必须进行状态检查

例如:如下操作必须进行检查:

  • java.io.File 所有返回状态码的操作 ( mkdirs除外)
  • Iterator.hasNext()
  • Enumeration.hasMoreElements()
  • Lock.tryLock()
  • Condition.await*
  • CountDownLatch.await(long, TimeUnit)
  • Semaphore.tryAcquire
  • BlockingQueue: offer, remove

错误的代码示例

public void doSomething(File file, Lock lock) {
  file.delete();  // 错误示范
  // ...
  lock.tryLock(); // 错误示范
}

正确的代码示例

public void doSomething(File file, Lock lock) {
  if (!lock.tryLock()) {
    // lock failed; take appropriate action
  }
  if (!file.delete()) {
    // file delete failed; take appropriate action
  }
}

See

CERT, ERR33-C. - Detect and handle standard library errors
CERT, POS54-C. - Detect and handle POSIX library errors
CERT, EXP00-J. - Do not ignore values returned by methods
CERT, EXP12-C. - Do not ignore values returned by functions
CERT, FIO02-J. - Detect and handle file-related errors
MITRE, CWE-754 - Improper Check for Unusual Exceptional Conditions

你可能感兴趣的:(Java规范之Sonar规则的汉化【漏洞类】)