Home🏡

3vil $p1r1t

“o que das?“

Recentemente encontrei um servidor de Mu, mas ele não tinha aquela interface padrão de servidor de Mu, quem já jogou sabe do que eu to falando. Comecei dando uma olhada nas chamadas que o site fazia e vi que ele enviava as requests pra uma API. Comecei a testar a API e forçando alguns erros vi que o servidor era em php usando o framework Slim.

alt

Bom, se alguns erros não são tratados, em algum outro lugar deve ter alguma falha pra explorar.

Comecei a testar as rotas que encontrei e encontrei algo que poderia ser uma ponte para conseguir informações sensíveis do servidor.

$(function() {
    var params = $.getQueryParameters();
    if (!params.ranking) {
        return;
    }

    var ranking = $("#ranking");
    ranking.removeClass("ui");
    ranking.removeClass("message");

    ranking.attr("data-template", "rankings/" + params.ranking + ".html");
});

Na página onde mostra os rankings, basicamente você seleciona uma opção num menu e esse menu tem o nome do arquivo que vai ser carregado.

Quando essa função é chamada, ela pega o nome do arquivo e tenta carregar o arquivo que está na pasta rankings e adiciona a extensão html. Fiz alguns testes, é possível fazer uma enumeração dos arquivos que existem no servidor.

Uma vez que alguma configuração do servidor bloqueia o acesso aos arquivos, sabemos que quando recebemos um 403, o arquivo existe mas não temos permissão pra acessar. Quando recebemos um 404, o arquivo não existe.

alt

Nesse exemplo eu forcei a página carregar o index.html da raiz do servidor. Tentei fazer bypass com os arquivos que retornam 403 mas não foi possível.


Analisando os subdominios do servidor, encontrei um subdominio de outro servidor de Mu. Dei uma olhada no site e nos arquivos do projeto e era basicamente o mesmo projeto, só mudava a cor.

Criei uma conta nos 2 servidores, e no subdominio "hard" até criei um char pelo client do jogo. Quando loguei nas duas contas, vi que o token JWT era o mesmo para ambas as contas, ou seja, era usado o mesmo secret para gerar o token em cada servidor.


Dando uma olhada na estrutura do payload do JWT, vi que ele tinha duas informações que poderiam ser usadas para buscar os dados do usuário no banco de dados.

{
    "user": "20matar70correr",
    "email": "email@test.com"
}

Iniciei uma busca na lista de ranking, mas como ela exibe apenas os nomes dos personagens, precisei encontrar uma maneira de verificar se esses nomes também correspondiam a contas registradas no servidor.

alt

Foi quando encontrei esse personagem: tonybalada. Para validar eu tentei criar uma conta com esse nome.

alt

Depois dessa mensagem, eu já não estava considerando o e-mail como uma chave de busca no banco


Após realizar o login no servidor "easy" copiei o token do localStorage e usei esse mesmo token no servidor hard. Assim a api de autenticação validou o token por ambos os servidores utilizarem a mesma secret e conseguiu fazer a busca do usuário pois utilizei no easy o mesmo nome de uma conta que existe no hard.

Essa era a tela de personagens no subdominio "easy"

alt

E essa era a lista de personagens no subdominio "hard"

alt