“Vulnado, Ownado? WTF!? - Parte 2”
XSS
Agora que foi possível realizar o login alterando a senha de qualquer usuário via SQLi ou utilizando as senhas expostas no código, vemos uma página de comentários a ideia dessa parte do post é explicar o porque foi possível realizar um XSS.
Front-end
Você já parou para analisar as entranhas do javascript
quando clica em um botão Submit
? Bom, de vez enquando faz bem.. hehe 🤓
Em casos de DOM XSS por exemplo analisar como é processada sua request, pode levar a descoberta dessa vulnerabilidade e de outras qua acontecem no client-side.
Nesse caso aqui a vulnerabilidade está no Server-side, porém irei mostrar como podemos debugar e como isso pode ser útil em alguns casos.
Olhando o código javascript pelo “Developer Tools”, foi possível identificar as funções que realizam as principais funções da página de comentários e na linha 41 eu setei um breakpoint.
Conseguimos descobrir outros endpoints, como são feitas as requests, se existe alguma obfuscação, encontrar keys, tokens, etc.. E você passa a entender melhor como funciona a aplicação em si. “Nunca subestime o client-side”. 😉 Temos um “Debugger” no navegador, porque não usa-lo?
Back-end
Vamos analisar todas as proteções que não foram implementadas no back-end. :D
CommentsController.java
@CrossOrigin(origins = "*")
@RequestMapping(value = "/comments", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
Comment createComment(@RequestHeader(value="x-auth-token") String token, @RequestBody CommentRequest input) {
return Comment.create(input.username, input.body);
}
Aqui é possível perceber que a aplicação envia o CORS como “*“, no /comments
o que seria um problema se não fosse pelo header “x-auth-token”. Uma vez que o CSRF não é possível quando tem que enviar um header como parte de sua autenticação.
Comment.java
public static Comment create(String username, String body){
long time = new Date().getTime();
Timestamp timestamp = new Timestamp(time);
Comment comment = new Comment(UUID.randomUUID().toString(), username, body, timestamp);
try {
if (comment.commit()) {
return comment;
} else {
throw new BadRequest("Unable to save comment");
}
} catch (Exception e) {
throw new ServerError(e.getMessage());
}
}
Olhando as definições da classe “Comments”, vemos que ela recebe o usuário e a mensagem, cria um timestamp e concatena com um “UUID” rândomico.
Logo em seguida o comentário é postado, sem nenhuma validação no comentário, por isso foi possível trigar um XSS com um simples payload:
<img src=1 onerror="alert(1337)">
.