Tomaría el ejemplo similar de enlace que ha citado . En el ejemplo, obtendré el ID de usuario (Integer) como argumento e intentaré validarlo contra la base de datos.
class ListUtility {
private static void addToList(List list, Object obj) {
list.add(obj); // Unchecked warning
}
private static boolean validateUser(List list){
boolean isValidUser=false;
Statement stmt = conn.createStatement(); //conn is a jdbc Connection
String Query="SELECT userid FROM Customers WHERE userid='"+list.get(0)+"'"; //developer expects list.get(0) is a integer
ResultSet rs = stmt.executeQuery(Query);
if (rs.next()) {
System.out.println("Valid User");
isValidUser=true;
}
return isValidUser; //returns true for args[0]=something' or '1'='1
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer> ();
addToList(list, args[0]); //arg[0] is expected to be a valid userid of type Integer(say)
validateuser(list);
}
}
Ahora, si invoco el programa con el argumento something' or '1'='1
, se imprimirá "Valid User"
. Esta es una inyección típica de Sql. Pero esto tuvo éxito debido a la Contaminación del Heap donde agregamos args[0]
a list
a pesar de que el tipo no coincide.
La contaminación del montón es posible en este caso porque la información de tipo parametrizada se descarta antes de la ejecución.
La llamada a addToList(list,args[0])
logra agregar una cadena a la lista, aunque la lista es de tipo List<Integer>
. Además, la llamada a validateUser(List list)
toma la lista del tipo List<Object>
en lugar del estricto List<Integer>
.
Este tiempo de ejecución de Java no lanza una excepción ClassCastException ya que la lista de valores no se leyó con un tipo no válido en este ejemplo.
Porque la lista nunca se lee estrictamente como List<Integer>
.