Códigos de baixa qualidade levam a comportamentos imprevisíveis. Da perspectiva do usuário, isso normalmente se manifesta como usabilidade ruim. Para um invasor, trata-se de uma oportunidade para atacar o sistema de formas imprevistas.
<script>
.
...
public String tagProcessor(String tag){
if (tag.toUpperCase().equals("SCRIPT")){
return null;
}
//does not contain SCRIPT tag, keep processing input
...
}
...
Example 1
é que java.lang.String.toUpperCase()
, quando usado sem uma localidade, aplica as regras da localidade padrão. O uso da localidade turca "title".toUpperCase()
retorna "T\u0130TLE", onde "\u0130" é o caractere "LATIN CAPITAL LETTER I WITH DOT ABOVE". Isso pode provocar resultados inesperados, como no Example 1
, em que isso impedirá que a palavra "script" seja capturada por essa validação, podendo causar uma vulnerabilidade de Cross-Site Scripting.
...
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
, o desenvolvedor esperaria que box.area
fosse um número inteiro aleatório que, por acaso, é um múltiplo de 10, já que width
é igual a 10. Porém, na realidade, isso sempre terá um valor inserido em código fixo de 0. Campos estáticos finais declarados com uma constante em tempo de compilação são inicializados primeiros e depois cada um é executado em ordem. Isso significa que, como height
não é uma constante em tempo de compilação, ela é declarada após a declaração de box
e, portanto, o construtor é chamado antes da inicialização do 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 que seja verificado se ele é realmente null
. Erros de desreferência após a verificação ocorrem quando um programa faz uma verificação explícita em busca de valores null
, mas prossegue para desreferenciar o ponteiro quando se sabe que ele é null
. Erros desse tipo são frequentemente o resultado de um erro de digitação ou de uma desatenção do programador. Um erro de desreferência após o armazenamento ocorre quando um programa define explicitamente um ponteiro como null
e o desreferencia mais tarde. Esse erro é frequentemente o resultado de um programador inicializar uma variável como null
quando ela é declarada.foo
é null
e depois o desreferencia erroneamente. Se foo
for null
quando for verificado na instrução if
, ocorrerá um cancelamento de referência null
, o que causa uma exceção de ponteiro nulo.Exemplo 2: No código a seguir, o programador supõe que a variável
if (foo is null) {
foo.SetBar(val);
...
}
foo
não seja null
e confirma essa suposição desfazendo a referência ao objeto. No entanto, o programador mais tarde contradiz a suposição, verificando foo
com base em null
. Se a variável foo
puder ser null
quando for verificada na instrução if
, ela também poderá ser null
quando sua referência for desfeita, podendo causar uma exceção de ponteiro nulo. Ou o cancelamento de referência não é seguro, ou a verificação subsequente é desnecessária.Exemplo 3: No código a seguir, o programador define explicitamente a variável
foo.SetBar(val);
...
if (foo is not null) {
...
}
foo
como null
. Mais tarde, o programador desreferencia foo
antes de verificar o objeto em busca de um valor null
.
Foo foo = null;
...
foo.SetBar(val);
...
}
null
antes que seja verificado se ele é realmente null
. Erros de desreferência após a verificação ocorrem quando um programa faz uma verificação explícita em busca de valores null
, mas prossegue para desreferenciar o ponteiro quando se sabe que ele é null
. Erros desse tipo são frequentemente o resultado de um erro de digitação ou de uma desatenção do programador. Um erro de desreferência após o armazenamento ocorre quando um programa define explicitamente um ponteiro como null
e o desreferencia mais tarde. Esse erro é frequentemente o resultado de um programador inicializar uma variável como null
quando ela é declarada.ptr
não seja NULL
. Essa suposição se torna explícita quando o programador desreferencia o ponteiro. Mais tarde, essa suposição é contrariada quando o programador verifica ptr
contra NULL
. Se a variável ptr
puder ser NULL
quando for verificada na instrução if
, ela também poderá ser NULL
quando desreferenciada, podendo causar uma falha de segmentação.Exemplo 2: No código a seguir, o programador confirma que a variável
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
é NULL
e depois a desreferencia erroneamente. Se a variável ptr
for NULL
quando for verificada na instrução if
, ocorrerá uma desreferência null
, causando assim uma falha de segmentação.Exemplo 3: No código a seguir, o programador se esquece de que a cadeia de caracteres
if (ptr == null) {
ptr->field = val;
...
}
'\0'
é, na verdade, 0 ou NULL
, desreferenciando assim um ponteiro nulo e provocando uma falha de segmentação.Exemplo 4: No código a seguir, o programador define explicitamente a variável
if (ptr == '\0') {
*ptr = val;
...
}
ptr
como NULL
. Mais tarde, o programador desreferencia ptr
antes de verificar o objeto em busca de um valor null
.
*ptr = NULL;
...
ptr->field = val;
...
}
null
, mas prossegue para cancelar a referência ao objeto quando se sabe que ele é null
. Erros desse tipo são frequentemente o resultado de um erro de digitação ou de uma desatenção do programador.foo
é null
e depois a desreferencia erroneamente. Se a variável foo
for null
quando for verificada na instrução if
, ocorrerá um cancelamento de referência null
, provocando assim uma exceção de ponteiro 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 verificar se o saldo da instância de contrato Lock
é um 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()
e send()
, que usam uma quantidade fixa de gás 2300.
interface ICallable {
function callMe() external;
}
contract HardcodedNotGood {
function callWithArgs() public {
callable.callMe{gas: 10000}();
}
}