...
In order to comply with guideline MSC05-J. Store passwords using a hash function, the passwords would have to be encryptedhashed. Unfortunately, on many small systems, they are not, and so the password text added in the query string would match precisely what the user enters. An attacker could supply a string for <PASSWORD>
such as:
...
Code Block | ||
---|---|---|
| ||
class Login { public Connection getConnection() throws SQLException { DriverManager.registerDriver(new com.microsoft.jdbc.sqlserver.SQLServerDriver()); String dbConnection = PropertyManager.getProperrty("db.connection"); // can hold some value like "jdbc:microsoft:sqlserver://<HOST>:1433,<UID>,<PWD>" return DriverManager.getConnection( dbConnection); } String hashPassword(char[] password) { // create hash of password } public void doPrivilegedAction(String username, char[] password) throws SQLException { Connection connection = getConnection(); if (connection == null) { // handle error } String pwd = hashPassword( password); String sqlString = "SELECT * FROM db_user WHERE username = '" + username + "' AND password = '" + pwd + "'"; Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery( sqlString); if (!rs.next()) { throw new SecurityException("User name or Password incorrect"); } // Authenticated; proceed } } |
...
Code Block | ||
---|---|---|
| ||
class Login { public void doPrivilegedAction(String username, char[] password) throws SQLException { Connection connection = getConnection(); if (connection == null) { // handle error } String pwd = hashPassword( password); // Ensure that the length of username and password is legitimate if ((username.length() >= 8) { // Handle error } String sqlString = "select * from db_user where username=? and password=?"; PreparedStatement stmt = connection.prepareStatement(sqlString); stmt.setString(1, username); stmt.setString(2, pwd); ResultSet rs = stmt.executeQuery(); if (!rs.next()) { throw new SecurityException("User name or Password incorrect"); } // Authenticated; proceed } } |
...
In this noncompliant code example, a client method uses simple string concatenation to build an XML query to send to a server. Since XML injection is possible because the method performs no validation of the input, XML injection becomes possibleinput validation.
Code Block | ||
---|---|---|
| ||
private void createXMLStream(BufferedOutputStream outStream, String quantity) throws IOException { String xmlString; xmlString = "<item>\n<description>Widget</description>\n<price>500.0</price>\n" + "<quantity>" + quantity + "</quantity></item>"; outStream.write(xmlString.getBytes()); outStream.flush(); } |
...
Unfortunately, this program is subject to a remote XXE attack. Suppose that , if the evil.xml
file contains the following:
...
Code Block | ||
---|---|---|
| ||
class CustomResolver implements EntityResolver { public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { // check for known good entities String entityPath = "/home/username/java/xxe/file"; if (systemId.equals(entityPath)) { System.out.println("Resolving entity: " + publicId + " " + systemId); return new InputSource(entityPath); } else { return new InputSource(); // Disallow unknown entities, by returning blank path } } } class XXE { private static void receiveXMLStream(InputStream inStream, DefaultHandler defaultHandler) throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); // To set the Entity Resolver, an XML reader needs to be created XMLReader reader = saxParser.getXMLReader(); reader.setEntityResolver(new CustomResolver()); reader.setErrorHandler( defaultHandler); InputSource is = new InputSource(inStream); reader.parse(is); } public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { receiveXMLStream( new FileInputStream( "evil.xml"), new DefaultHandler()); } } |
...