Una mala calidad del código lleva a un comportamiento no predecible. Desde la perspectiva de un usuario, muchas veces también supone una usabilidad limitada. Pero para un atacante es una oportunidad para atacar al sistema de formas insospechadas.
<script>
.
...
public String tagProcessor(String tag){
if (tag.toUpperCase().equals("SCRIPT")){
return null;
}
//does not contain SCRIPT tag, keep processing input
...
}
...
Example 1
es que java.lang.String.toUpperCase()
, cuando se usa sin configuración regional, emplea las reglas de la configuración regional predeterminada. El hecho de utilizar la configuración regional turca "title".toUpperCase()
devuelve "T\u0130TLE", donde "\u0130" es el carácter "I LATINA MAYÚSCULA CON PUNTO". Esto puede dar lugar a resultados inesperados, como en el Example 1
, en el que se impide que la validación capture la palabra "script", lo que puede dar lugar a una potencial vulnerabilidad de scripts entre sitios.
...
import java.sql.PreparedStatement;
import com.sap.sql.NativeSQLAccess;
String mssOnlyStmt = "...";
// variant 1
PreparedStatement ps =
NativeSQLAccess.prepareNativeStatement(
conn, mssOnlyStmt);
. . .
// variant 2
Statement stmt =
NativeSQLAccess.createNativeStatement(conn);
int result = stmt.execute(mssOnlyStmt);
. . .
// variant 3
CallableStatement cs =
NativeSQLAccess.prepareNativeCall(
conn, mssOnlyStmt);
. . .
...
public class Box{
public int area;
public static final int width = 10;
public static final Box box = new Box();
public static final int height = (int) (Math.random() * 100);
public Box(){
area = width * height;
}
...
}
...
Example 1
, el desarrollador espera que box.area
sea un entero aleatorio que resulta ser múltiplo de 10, ya que width
es igual a 10. Sin embargo, en realidad, siempre tuvo un valor codificado de 0. Se inicializan primero los campos estáticos finales declarados con una constante de tiempo de compilación y, a continuación, se ejecutan en orden. Esto significa que, puesto que height
no es una constante de tiempo de compilación, se declara después de la declaración debox
y, por consiguiente, se llama al constructor antes de que se inicialice el campo height
.
...
class Foo{
public static final int f = Bar.b - 1;
...
}
...
class Bar{
public static final int b = Foo.f + 1;
...
}
This example is perhaps easier to identify, but would be dependent on which class is loaded first by the JVM. In this exampleFoo.f
could be either -1 or 0, andBar.b
could be either 0 or 1.
null
antes de comprobar si es null
o no. Los errores de desreferencia tras la comprobación se producen cuando un programa realiza una comprobación explícita de null
y procede a desreferenciar el puntero cuando se sabe que es null
. Los errores de este tipo son normalmente el resultado de errores de escritura o descuidos del programador. Los errores de desreferencia tras el almacenamiento se producen cuando un programa establece de forma explícita un puntero en null
y luego lo desreferencia. Con frecuencia, el error es el resultado de que un programador inicialice una variable en null
cuando se declara.foo
es null
y por eso lo desreferencia erróneamente. Si foo
es null
cuando se comprueba en la instrucción if
, se produce una desreferencia null
, lo que provoca una excepción de puntero nulo.Ejemplo 2: En el código siguiente, el programador presupone que la variable
if (foo is null) {
foo.SetBar(val);
...
}
foo
no es null
y confirma esta suposición eliminando la referencia del objeto. Sin embargo, este contradice posteriormente esta suposición al comprobar si foo
es null
. Si foo
puede ser null
al comprobarlo en relación con la instrucción if
, también puede ser null
cuando se elimina su referencia, lo que puede provocar una excepción de puntero nulo. O bien la desreferencia no es segura o la comprobación posterior es innecesaria.Ejemplo 3: En el código siguiente, el programador establece explícitamente la variable
foo.SetBar(val);
...
if (foo is not null) {
...
}
foo
en null
. A continuación, el programador desreferencia foo
antes de comprobar si en el objeto hay un valor null
.
Foo foo = null;
...
foo.SetBar(val);
...
}
null
antes de comprobar si es null
o no. Los errores de desreferencia tras la comprobación se producen cuando un programa realiza una comprobación explícita de null
y procede a desreferenciar el puntero cuando se sabe que es null
. Los errores de este tipo son normalmente el resultado de errores de escritura o descuidos del programador. Los errores de desreferencia tras el almacenamiento se producen cuando un programa establece de forma explícita un puntero en null
y luego lo desreferencia. Con frecuencia, el error es el resultado de que un programador inicialice una variable en null
cuando se declara.ptr
no es NULL
. Esta suposición se hace explícita cuando el programador desreferencia el puntero. Esta suposición luego queda contradicha cuando el programador contrasta ptr
y NULL
. Si ptr
puede ser NULL
al comprobarla en la instrucción if
, entonces también puede ser NULL
cuando se desreferencia y podría ocasionar un error de segmentación.Ejemplo 2: En el código siguiente, el programador confirma que la variable
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
es NULL
y por eso lo desreferencia erróneamente. Si ptr
es NULL
cuando se comprueba en la instrucción if
, entonces se produce una desreferencia de null
que provocará un error de segmentación.Ejemplo 3: En el código siguiente, el programador olvida que la cadena
if (ptr == null) {
ptr->field = val;
...
}
'\0'
es en realidad 0 o NULL
; por lo tanto, puede desreferenciar un puntero nulo y provocar un fallo de segmentación.Ejemplo 4: En el código siguiente, el programador establece explícitamente la variable
if (ptr == '\0') {
*ptr = val;
...
}
ptr
en NULL
. A continuación, el programador desreferencia ptr
antes de comprobar si en el objeto hay un valor null
.
*ptr = NULL;
...
ptr->field = val;
...
}
null
, pero continúa eliminando la referencia del objeto cuando se detecta que es null
. Los errores de este tipo son normalmente el resultado de errores de escritura o descuidos del programador.foo
es null
y por eso lo desreferencia erróneamente. Si foo
es null
cuando se compruebe en la instrucción if
, se producirá una desreferencia null
, provocando una excepción de puntero nulo.
if (foo == null) {
foo.setBar(val);
...
}
require
.
function withdrawWinnings() {
require(uint32(msg.sender) == 0);
_sendWinnings();
}
function _sendWinnings() {
msg.sender.transfer(this.balance);
}
assert
para comprobar que el saldo de la instancia Lock
del contrato es un valor específico (msg.value
).
contract Lock {
constructor (address owner, uint256 unlockTime) public payable {
...
}
}
contract Lockdrop {
...
function lock(...) {
uint256 eth = msg.value;
address owner = msg.sender;
uint256 unlockTime = unlockTimeForTerm(term);
Lock lockAddr = (new Lock).value(eth)(owner, unlockTime);
assert(address(lockAddr).balance == msg.value);
}
}
transfer()
y send()
, que utilizan una cantidad fija de 2300 unidades de gas.
interface ICallable {
function callMe() external;
}
contract HardcodedNotGood {
function callWithArgs() public {
callable.callMe{gas: 10000}();
}
}