Null Ahmedabad abril de 2023 CTF Write-up

May 01 2023
A comunidade conhecida como Null Ahmedabad foi fundada por um grupo de quatro indivíduos. No dia 18 de fevereiro de 2018, eles realizaram sua reunião inaugural, que foi possível com a ajuda da Ganpat University.

A comunidade conhecida como Null Ahmedabad foi fundada por um grupo de quatro indivíduos. No dia 18 de fevereiro de 2018, eles realizaram sua reunião inaugural, que foi possível com a ajuda da Ganpat University. Seu evento principal é uma reunião mensal onde os participantes se reúnem para participar de discussões sobre segurança e CTFs (desafios práticos). Com o passar do tempo, a Null Ahmedabad continua a expandir seu alcance, oferecendo formatos de reunião e workshops adicionais. Para qualquer pessoa interessada em segurança da informação, seja estudante, entusiasta ou profissional, Null Ahmedabad é uma comunidade ideal para se conectar com outros hackers e profissionais na área de Ahmedabad.

Em abril de 2023, Null Ahmedabad organizou uma competição CTF, na qual consegui garantir o terceiro lugar. Como resultado dessa conquista, decidi escrever um artigo.

Para explorar a comunidade nula, clique em:https://null.community/chapters/17-ahmedabad

Foto de Alex Chumak no Unsplash

1. Acesso negado?

O prompt do desafio diz:

Null Ahmedabad está lançando sua loja de roupas online pela primeira vez! No entanto, tememos que possa haver algumas vulnerabilidades em nosso código. Como membro da comunidade de segurança aberta, você tem a tarefa de localizar e enviar quaisquer vulnerabilidades (sinalizadores) que possa encontrar.

Nossa loja fica em:http://nullahm.kuldeep.io:5000/

Feliz compras! :)

Comecei a explorar o site; ele tem um recurso de login e registro.

Registrei minha conta e fiz login. Comecei a pesquisar o código JavaScript e encontrei um endpoint graphql.

Se você está familiarizado com o graphql, provavelmente sabe que ele suporta consultas de introspecção, que geralmente são proibidas por motivos de segurança.

Então, tentei disparar a consulta de introspecção e funcionou.

Eu inspecionei o resultado e encontrei um campo chamado `allUsers`.

Tentei acessar o nó `allUsers` e agora consigo acessar os dados de todos os usuários.

E encontrei a bandeira.

2. Strings anexadas

O prompt do desafio diz:

Tenho certeza de que não deixei nenhum segredo neste binário, mas meu gerente ainda está duvidando de mim. Você pode, por favor, verificar o binário e provar que ele está errado?

Tem um binário executável para download.

Eu baixei o binário e suas estatísticas de metadados são:

ELF 64-bit LSB pie executável, x86–64, versão 1 (SYSV), vinculado dinamicamente, interpretador /lib64/ld-linux-x86–64.so.2, BuildID[sha1]=9b34236e59bfcdbdb606def64c05cdfdbce9753b, para GNU/Linux 4.4. 0, não descascado

Parece um desafio da velha escola; Eu sei que o formato da bandeira é “nullahm”. Então eu tentei usar strings contra o binário.

strings -n 7 -tx chal | grep nullahm

Segredo encontrado no binário.

3. Historicamente inseguro

Dica de desafio diz:

Decodifique isso e obtenha o sinalizador: ubsshot{d4f_700_345f}

Parece um sinalizador, mas é criptografado como diz o prompt. Se eu comparar o sinalizador criptografado com o formato do sinalizador, ou seja, “nullahm”, parece que é Vigenère Cipher.

Vigenère Cipher é vulnerável a ataques de texto sem formatação conhecidos. Eu tenho uma parte do texto simples conhecido, ou seja, ubsshot = nullahm.

Então eu escrevi um pequeno script para extrair a chave:

def solve_historically_insecure(ciphertext, plaintext):

    ciphertext = ciphertext.upper()
    plaintext = plaintext.upper()
    key = ""
    for i in range(len(plaintext)):
        key += chr(((ord(ciphertext[i]) - ord(plaintext[i])) % 26) + ord('A'))
    return key
ciphertext = "ubsshot"
plaintext = "nullahm"
key = solve_historically_insecure(ciphertext, plaintext)
print("Key : ",key)

Agora posso usar a chave contra o texto cifrado,

def vigenere_decode(ciphertext, key):
    plaintext = ''
    key_len = len(key)
    for i in range(len(ciphertext)):
        shift = ord(key[i % key_len]) - 65
        if ciphertext[i].isupper():
            plaintext += chr((ord(ciphertext[i]) - shift - 65) % 26 + 65)
        elif ciphertext[i].islower():
            plaintext += chr((ord(ciphertext[i]) - shift - 97) % 26 + 97)
        else:
            plaintext += ciphertext[i]
    return plaintext

ciphertext = "ubsshot{d4f_700_345f}"
key = solve_historically_insecure(ciphertext, plaintext)
plaintext = vigenere_decode(ciphertext, key)
print("Plain Text : ",plaintext)

      
                

Obrigado por reservar um tempo para ler este artigo.