Shell simples

7 02 2007

Nesse post, vou demonstrar como criar uma pequena shell, bastante simples, para conexões remotas. Na verdade, essa é uma pseudo-shell, pois a unica coisa que esse código faz, é liberar uma conexão com o servidor, e executar comandos, através do comando shell_exec( ), ou seja, se o servidor PHP onde este código estiver rodando estiver com o safe_mode ativado, este código já não irá funcionar. Por se tratar de uma pseudo-shell, programas como ‘vi’ podem não funcionar também.

Este é um bom exemplo para entender como funciona um socket em PHP, e pode ser utilizado de base para alguma outra implementação de alguma idéia.

Para usar a shell, coloque-a no diretório de seu webserver, e acesse a url, passando como parametro o IP da interface que deve aguardar por conexão.Por exemplo:

http://localhost/shell.php?ip=127.0.0.1

Significa queuma conexão será aberta na interface com o ip ‘127.0.0.1’. Normalmente ai, é colocado o IP de internet da máquina, caso esteja sendo estabelecida uma conexão através da internet. Feito isso, o navegador deve manter o status de ‘Carregando’ o tempo todo, mantendo uma tela em branco. Agora basta conectar-se usando um cliente de telnet, ao ip especificado em $ip e na porta que foi definida no código. No caso apresentado aqui, seria:

telnet 127.0.0.1 10001

Não se esqueça, essa ‘shell’ estará sendo executada com os privilégios que o webserver possui.

Divirta-se : )

<?php
// Tirar o timeout, pois o script ficará rodando em loop infinitoset_time_limit(0);

// Ativar o flush, para que o buffer possa ser descarregado conforme os
// comandos sao enviados
ob_implicit_flush();

// Porta em que o servidor ficará rodando
define ("PORTA","10001");

// O ip no qual o servidor estará rodando.
// Deve ser passado como argumento o ip válido
// Não se pega automaticamente, para evitar problemas de pegar ip da
// interface errada.
$ip = $_REQUEST["ip"];

// Cria o socket que será usado na conexão
// O primeiro argumento, é definido como AF_INET, pois estamos abrindo um
// socket com a internet, que irá utilizar o protocolo TCP e IPv4
// Caso fosse ser estabelecida uma conexao usando IPv6, poderia ser utilizado
// AF_INET6
if( ! $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP) )
    die("Erro ao criar o socket");

// Aqui é relaizada a ligação entre o socket, e uma porta de comunicação
// em $ip. Essa é a porta que ficará aberta, para que mais tarde possa ser
// realizada a conexão através de telnet.
if ( !$binda = socket_bind($socket,$ip,PORTA) )
    die("Erro no bind. Provavelmente a porta especificada ja está em uso");

// Diz que o socket deve esperar no máximo por 5 conexões simultaneas
if ( !$listen = socket_listen($socket,5) ) 
    die("Erro no listen");

// Loop principal, onde será lido tudo que é retornado pelo socket, e por onde
// serão enviados todos os comandos desejados
do
{
	// Aguarda uma conexão
	$accept = socket_accept($socket) or die("cant accept");

        // Aqui uma conexao foi aceita e estabelecida, então enviamos uma
        // mensagem de boas vindas para o cliente.
	socket_write($accept,"Bem vindon",2048);

	// Pega o caminho atual onde o script está sendo executado
	$path = getcwd();

	// Aqui, criamos uma linha de prompt simulando uma linha de prompt
	// do bash
	$resultado = "bash@".$ip.":".$path."$ ";

	// É enviada a linha de prompt para que o cliente possa ve-la
	socket_write($accept,$resultado,strlen($resultado));

	// Loop que lê os comandos enviados pelo cliente que se conectou
	do
	{
		
		// Lê até 2048 bytes enviados pelo cliente
		$comando = socket_read($accept,2048,PHP_NORMAL_READ);
		
		// Remove espaços em branco no começo/final da string
		$comando = trim($comando);

		// Se nenhum comando é digitado, reexibe o prompt
		// Caso contrario, se o comando for a string 'sair', termina a conexão
		if ($comando=="") {
			$path = getcwd();
			$resultado = "bash@".$ip.":".$path."$ ";
			socket_write($accept,$resultado,strlen($resultado));
		}
		else if ($comando=="sair") {
			socket_close($accept);
			break 2;
		}

		// Verifica se o comando é o de mudança de diretorio
		// Por algum motivo, utilizar o comando cd do bash e tentar executa-lo
		// com shell_exec nao funciona
		$pos = strpos($comando,"cd ");

		// Se não for o comando cd, executa o comando que foi dado
		// Caso contrario, muda de diretório
		if($pos === false) {
			$result = shell_exec($comando);
		}
		else {
			$comand = str_replace("cd ","",$comando);
			chdir($comand);
		}
		
		// Envia o comando para o servidor, que tentará executa-lo
		// quando esse loop recomeçar logo na sequência
		socket_write($accept,$result,strlen($result));
				
	} while(true);

	// Fecha a conexao
	socket_close($accept);

} while(true);

// Fecha o socket
socket_close($socket);
?>
Anúncios

Ações

Information

3 responses

18 04 2008
Lucas Vianna

Muito boa a matéria, bem explicada só tenho elogios a fazer e uma sugestão, porque não colocar o código inteiro já que não possui textos entre os blocos de código? abraços e parabéns.

18 04 2008
Henrique

Costumava ser um bloco inteiro. Esse wordpress é meio estúpido e quebra as tags no meio do caminho e bla bla bla, acabou acarretando nisso ai… To meio sem tempo pra ver isso agora pra corrigir, mas logo logo vou tentar resolver. Valeu por chamar a atenção pra isso.

17 02 2014
Rafael

Eu tenho um socket so o que acontece. Deixo ele ativo por uns 3 dias. Do nada ele da erro na solicitação do cliente e fica e um loop infinito. Ai mando socket_close so para o cliente e não mando para o socket inteiro so que ele fica em um loop infinito. Alguém ja passou por isso ? Mande email para rafaunit@yahoo.com.br

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s




%d blogueiros gostam disto: