Great Lakes Security Conference CTF — Hackeando Apps NodeJS — Parte 2
Desafio: Express Puzzle
Esta é a parte 2 da Série Great Lakes Security Conference CTF — Hackeando Apps NodeJS.
Este desafio já começa mostrando o código-fonte da página principal (Framework Express.js):
Resumo do Código
- Ele responde na URL /flag,
- Pega o valor da querystring value.
- Verifica se é diferente de ‘itchy,knee’ (strict inequality ‘!==’)
- Verifica se é igual a ‘itchy,knee’ (loose equality ‘==’)
- Se passar nas duas condições acima, entrega a flag
Receber a flag depende exclusivamente de passar nas condições acima, pois a resposta está dentro do secret.js, que está bem protegido. O desafio aqui é passar uma string que seja “igual e ao mesmo tempo diferente” de ‘itchy,knee’. Confuso? :)
Strict vs. Loose Equality
O segredo aqui está na diferença do modo strict para o modo loose, nas comparações de igualdade do Javascript.
- No modo strict da igualdade (==) ele valida o tipo de dados também.
Neste caso, ele vai considerar diferentes dados “iguais”, se tiverem tipos diferentes. Exemplo: (“1” == 1) será considerado false.
- No modo loose da igualdade (==), ele não valida o tipo de dados.
Neste caso, ele vai considerar dados iguais, se eles tiverem o mesmo valor após conversão, mesmo sendo de tipos diferentes. Exemplo: (“1” == 1) será considerado verdadeiro.
Vulnerabilidade
No código acima, a igualdade no modo loose pode ser explorada a partir do uso de um tipo de dados diferente no input. O tipo que funciona neste caso é o array, conforme exemplo abaixo:
Welcome to Node.js v14.12.0.
Type ".help" for more information.
> ['itchy', 'knee'] == 'itchy,knee'
true
A mesma comparação não funciona com o strict. Como ele está testando desigualdade, também retorna verdadeiro:
> ['itchy', 'knee'] !== 'itchy,knee'
true
Agora, testando a comparação completa (com uma variável arr ao invés de req.query.value):
> arr = ['itchy', 'knee']
[ 'itchy', 'knee' ]
> arr !== 'itchy,knee' && arr == 'itchy,knee'
true
Ou seja, encontramos o valor da querystring value que gera a condição verdadeira. Mas como passar uma matriz na querystring? A resposta é simplesmente repetir o mesmo nome da querystring várias vezes que o Express.js vai interpretar o valor como um array.
Exploit final:
$ curl -g $URL'/flag?value=itchy&value=knee' --compressed
GLSC{7wo_p@r@m5_@re_6e77er_7h@n_one}
Parte 3
O próximo desafio da série é o Javascript Puzzle, que explora uma outra aplicação NodeJS que também utiliza o framework Express.js.
Referências
- Parte 1 da série: https://neptunian.medium.com/great-lakes-security-conference-ctf-hackeando-apps-nodejs-parte-1-6e0f90a6b9a3
- Perfil do CTF — no CTF Time: https://ctftime.org/event/1051
- Meu perfil no CTF Time: https://ctftime.org/team/122851
- Link Direto do Evento: https://glsc.tech/
- Strict vs. Loose Equality: https://medium.com/jspoint/loose-vs-strict-equality-in-javascript-3e5136720b00
- Twitter: @NeptunianHacks