How to Break Software
Capítulo 3
Testing from the user Interface
Taíse Dias
Roteiro
Testando “dentro da caixa”
Explorando armazenamento de dados
Attcak 11
Attack 12
Attack 13
Attack 14
Attack 15
Attack 16
Attack 17
Testando “dentro da caixa”
Dados e computação (caixa branca)
Escopo do livro: caixa cinza
Abstrações do código
Baseado em interface com usuário,
porém envolve dados e computação
interna
Explorando armazenamento de dados
Dado é o “sangue” do software
Se corrompido, provoca danos
trágicos
Dados são manipulados através de
leitura e escrita pela aplicação
Tentar enxergar através da interface
Tentar encontrar que dados estão
sendo carregados
Ex.: Se um dado entrou em uma tela, e
o mesmo dado apareceu em outra tela,
esse dado foi carregado
Attack 11
“Apply inputs using a variaty
of inicial conditions”
Quando aplicar esse ataque?
Configurar pré-condições que causem
bugs
Entradas são aplicadas em diversas
circunstâncias
Ex.: um arquivo pode ser salvo
contendo ou não alterações
Que falhas do software tornam
esse ataque bem sucedido?
A computação funciona apenas sob
determinadas condições
Entradas devem ser validadas
Estruturas de dados devem ser
validadas
Combinação entre entradas e
estruturas de dados
Como determinar se esse
ataque revela falhas?
Melhor caso: combinações de
entradas e estruturas de dados
incompatíveis, o software trava
Pior caso: Poucas variações de saídas
ou disposição/ordem da tela
Como conduzir esse ataque?
Isolar features ou funções
Considerar as possibilidades de
dados usadas nessas features
Tentar particionar configurações dos
dados que teriam o mesmo
comportamento
Executar uma combinação pra cada
partição
Attack 12
“Force a data structure to store too
many or too few values”
Quando aplicar esse ataque?
Estruturas de dados conhecidas
ou identificando estruturas de dados:
Utilizando a aplicação
Imaginando como os desenvolvedores
implementaram
Estruturas de tamanho fixo (limites)
Que falhas do software tornam
esse ataque bem sucedido?
Desenvolvedores implementam
estruturas de dados com cuidado mas
esquecem dos limites
“AddElement” e “RemoveElement” sem
checar
Provoca underflow e overflow
Como determinar se esse
ataque revela falhas?
Leitura e escrita em fronteiras de
arrays geralmente fecha o SO,
prejudicando a aplicação
Dados corrompidos
Saídas incorretas
Como conduzir esse ataque?
Detectar os limites das estruturas de
dados
Inserir números grandes como
entradas (256, 1.024, 32.767)
Underflow – deletar mais elementos
do que os que foram inserido
Attack 13
“Investigative alternative to modify
internal data constraints”
Quando aplicar esse ataque?
Sempre que identificar qualquer
restrição de carregamento de dado
Investigando todos os pontos de
acesso para quaisquer restrições na
estrutura de dados
Tamanho, dimensão, tipo, forma,
localização na tela...
Qualquer propriedade da estrutura,
que o usuário possa configurar
Que falhas do software tornam
esse ataque bem sucedido?
Implementa casos para restrição na
criação de dados
Não implementa casos para restrição
na modificação dos dados
Dados manipulados por diferentes
funções
Código para checar restrições deve
ser incluído em toda as funções
Como determinar se esse
ataque revela falhas?
Dados inválidos provocam travamento
do sistema
Como conduzir esse ataque?
Identifica dados
Lista propriedades de mudança
Intervalos, tipos, condições de execução
Inicializa os dados e realiza
modificações
Attack 14
“Experiment with invalid operand and
operator combinations”
Quando aplicar esse ataque?
Computação envolvendo entradas e
dados específicos
Computação
Entradas e dados
Combinar operandos/operadores para
produzir falhas
operadores
operandos
Que falhas do software tornam
esse ataque bem sucedido?
Quase todo operador possui
operandos inválidos (ex.: divisão)
Alguns desenvolvedores se descuidam
ao escrever casos de erros
Como determinar se esse
ataque revela falhas?
Executar operações inválidas
geralmente trava softwares
Se o exception handler mantém a
aplicação funcionando, o dado está
incorreto ou a mensagem de erro
está ilegível
Como conduzir esse ataque?
Identificar onde a computação ocorre
Entender que dados são usados
Usar valores inválidos nas operações
Attack 15
“Force a function to call itself
recursively”
Quando aplicar esse ataque?
Aplicações com funções recursivas
Número de chamadas ilimitadas
Loops infinitos
Que falhas do software tornam
esse ataque bem sucedido?
Desenvolvedores geralmente falham
ao tratar casos de recursão
Não garantem que loops e recursões
terminarão
Verificação condicional no começo ou
no fim do loop
Como determinar se esse
ataque revela falhas?
Overflow no heap na memória do
computador
Trava a aplicação
Como conduzir esse ataque?
Lista features que podem usar
recursão
Força a utilização da recursão
long int factorial (int n) {
if( n <=1) return (1);
else {
return (n * factorial (n-1) );
}
Attack 16
“Force computation results to be too
large or too small”
Quando aplicar esse ataque?
Objetivo é analisar os resultados da
computação
Aplicações que produzem e carregam
resultados internamente
Que falhas do software tornam
esse ataque bem sucedido?
Entradas e dados corretos, mas
resultados incorretos
Como? Depende da combinação
Desenvolvedores esquecem de checar
limites dos resultados
Como determinar se esse
ataque revela falhas?
Overflow e underflow
Desenvolvedores raramente escrevem
exception handlers
Às vezes não compreendem como
pode surgir falha uma vez que
entradas e dados estão corretos
Como conduzir esse ataque?
Forçar ocorrência da computação
várias vezes
Usar valores muito pequenos ou
muito grandes
const count = 2
main() {
int sum, value[count];
sum = 0;
for (int i = 0; i < count; ++i) {
sum = sum + value[i];
}
}
Attack 17
“Find features that share data or
interact poorly”
Quando aplicar esse ataque?
Features compartilham dados
Sempre que uma aplicação executa
mais de uma instrução ao mesmo
tempo
Sempre que mais de uma feature é
ativada ao mesmo tempo
Que falhas do software tornam
esse ataque bem sucedido?
Uma feature produz um dado e outra
feature o modifica
Restrições diferentes para o mesmo
dado
Como determinar se esse
ataque revela falhas?
Falhas sutis durante uso de entradas
subseqüentes
Testador deve estar atento
Como conduzir esse ataque?
Verificar uso de entradas iguais para
features diferentes
Verificar se saídas similares são
produzidas pelas features
Verificar se uma feature interfere na
computação de outra
Conclusão
Ataques relativos a dados e
computação exigem que os
testadores enxerguem através da
interface com o usuário e imagine o
que acontece
Em compensação, os que conseguem
encontrão sérios bugs nos softwares
analisados