Um exemplo simples de uso de PHP e AJAX. Criando um formulário de contato usando Bootstrap, PHP e extensão de entidade geral AJAX

04.09.2024

Na lista dos dez tipos de ataques mais comuns segundo a OWASP, os dois primeiros lugares são ocupados por ataques de injeção de código e XSS (cross-site scripting). Eles andam de mãos dadas porque o XSS, como vários outros tipos de ataques, depende do sucesso dos ataques de injeção. Este nome esconde toda uma classe de ataques em que dados são injetados em uma aplicação web para forçá-la a executar ou interpretar código malicioso da maneira que o invasor deseja. Esses ataques incluem, por exemplo, XSS, injeção de SQL, injeção de cabeçalho, injeção de código e divulgação de caminho completo. E esta é apenas uma pequena parte.


Os ataques de injeção são uma história de terror para todos os programadores. Eles são mais comuns e bem-sucedidos devido à variedade, escala e (às vezes) dificuldade de proteção contra eles. Todos os aplicativos precisam obter dados de algum lugar. XSS e UI Redress são especialmente comuns, então dediquei capítulos separados a eles e os separei da classe geral.


OWASP oferece a seguinte definição de ataques de injeção:


Oportunidades de injeção – como SQL, SO e LDAP – surgem quando o interpretador recebe dados não confiáveis ​​como parte de uma solicitação de comando. Dados maliciosos podem induzir o intérprete a executar determinados comandos ou acessar dados não autorizados.

Injeção SQL

A injeção de SQL é a forma mais comum e extremamente perigosa de ataque de injeção. É difícil superestimar a gravidade desta ameaça, por isso é extremamente importante compreender o que influencia o sucesso dos ataques e como se proteger contra eles.


Assim, os dados são injetados na aplicação web e depois utilizados em consultas SQL. Eles normalmente vêm de fontes de entrada não confiáveis, como formulários da web. No entanto, a injeção também pode ser feita em outros locais, como no próprio banco de dados. Os programadores muitas vezes acreditam na segurança total de seu banco de dados, sem perceber que, se ele era seguro em um caso, isso não significa de forma alguma que será seguro no futuro. Os dados da base de dados devem ser considerados não confiáveis ​​até prova em contrário, ou seja, até que sejam verificados.


Se o ataque for bem-sucedido, o invasor poderá manipular a consulta SQL para que ela execute operações no banco de dados que não são pretendidas pelos desenvolvedores.


Veja esta consulta:


$db = new mysqli("localhost", "nome de usuário", "senha", "storedb"); $resultado = $db->query("SELECT * FROM transações WHERE user_id = " . $_POST["user_id"]);

Existem vários batentes aqui. Primeiramente, não verificamos o conteúdo dos dados POST para garantir que o user_id esteja correto. Em segundo lugar, permitimos que uma fonte não confiável nos diga qual user_id usar: um invasor pode inserir qualquer user_id válido. Ele pode estar contido em um campo oculto em um formulário que consideramos seguro porque não poderia ser editado (esquecendo que os invasores poderiam inserir quaisquer dados). Terceiro, não escapamos do user_id nem o passamos para a consulta como um parâmetro vinculado, o que também permite que um invasor injete strings arbitrárias que manipularão a consulta SQL, visto que não conseguimos verificá-la em primeiro lugar.


Essas três omissões são muito comuns em aplicações web.


Com relação à confiança do banco de dados, imagine que procuramos transações usando o campo user_name. Os nomes são de escopo amplo e podem conter aspas. Digamos que o invasor armazenou um valor de string injetado em um dos nomes de usuário. Quando usarmos esse valor novamente em uma das consultas a seguir, ele manipulará a string de consulta, pois consideramos o banco de dados uma fonte confiável e não isolamos ou limitamos a consulta comprometida.


Preste atenção também em outro fator da implementação do SQL: o armazenamento persistente nem sempre precisa ser mantido no servidor. HTML 5 suporta o uso de um banco de dados do lado do cliente, onde você pode enviar consultas usando SQL e JavaScript. Existem duas APIs para isso: WebSQL e IndexedDB. Em 2010, o W3C não recomendou a escolha do WebSQL; é suportado por navegadores WebKit usando SQLite como backend. Muito provavelmente, o suporte permanecerá para fins de compatibilidade com versões anteriores, mesmo apesar da recomendação do W3C. Como o próprio nome sugere, esta API aceita consultas SQL, o que significa que pode ser alvo de ataques de injeção. IndexedDB é uma alternativa mais recente, um banco de dados NoSQL (não requer o uso de consultas SQL).

Exemplos de injeção SQL

A manipulação de consultas SQL pode ter os seguintes objetivos:

  • Vazamentos de dados.
  • Divulgação de informações armazenadas.
  • Manipulação de informações armazenadas.
  • Ignorar autorização.
  • Injeção SQL do lado do cliente.
  • Proteção de injeção SQL

    A proteção contra injeção de SQL é baseada no princípio de escalonamento. Antes de utilizar dados em uma consulta, você deve verificar se seu formato está correto. Também é necessário isolar os dados antes de incluí-los na solicitação ou incluí-los como parâmetro de transição.

    Exame

    Eu continuo repetindo: todos os dados que não foram criados explicitamente no código-fonte PHP da solicitação atual não são confiáveis. Verifique-os rigorosamente e rejeite qualquer coisa que não passe nas verificações. Não tente “corrigir” os dados; apenas pequenas alterações cosméticas no formato podem ser feitas.


    Erros comuns incluem a validação de dados para uso contínuo (como exibição ou cálculos) e a não validação de campos no banco de dados nos quais as informações serão armazenadas como resultado.

    Blindagem

    Usando a extensão mysqli, você pode isolar todos os dados incluídos em uma consulta SQL. A função mysqli_real_escape_string() faz isso. A extensão pgsql para PostgresSQL oferece as funções pg_escape_bytea() , pg_escape_identifier() , pg_escape_literal() e pg_escape_string() . A extensão mssql (Microsoft SQL Server) não possui funções de isolamento e a abordagem addlashes() é ineficaz - você precisará de uma função personalizada.


    Para dificultar ainda mais a sua vida, direi que você não tem o direito de cometer erros ao isolar os dados inseridos em uma solicitação. Uma falha e você estará vulnerável a ataques.


    Vamos resumir. A blindagem não é a melhor opção de proteção. Deve ser usado como último recurso. Pode ser necessário se a biblioteca de banco de dados usada para abstração permitir configurar consultas SQL simples ou partes de uma consulta sem forçar a vinculação de parâmetros. Em outros casos, é melhor evitar totalmente o isolamento. Essa abordagem é complexa, propensa a erros e varia dependendo da extensão do banco de dados.

    Consultas parametrizadas (expressões preparadas)

    A parametrização, ou associação de parâmetros, é a forma recomendada de criar consultas SQL. Todas as boas bibliotecas de banco de dados o utilizam por padrão. Aqui está um exemplo de uso da extensão PDO para PHP:


    if(ctype_digit($_POST["id"]) && is_int($_POST["id"])) ( $validatedId = $_POST["id"]; $pdo = new PDO("mysql:store.db") ; $stmt = $pdo->prepare("SELECT * FROM transações WHERE user_id = :id"); $stmt->bindParam(":id", $validatedId, $stmt->execute() ); // rejeita o valor do id e reporta um erro ao usuário)

    O método bindParam(), disponível para expressões PDO, permite que parâmetros sejam vinculados a “placeholders” fornecidos em uma expressão previamente preparada. Este método aceita parâmetros de tipos de dados básicos, como PDO::PARAM_INT , PDO::PARAM_BOOL , PDO::PARAM_LOB e PDO::PARAM_STR . Este é o padrão para PDO::PARAM_STR, a menos que especificado de outra forma, então lembre-se de outros valores também!


    Ao contrário do isolamento manual, a ligação de parâmetros (ou qualquer método usado pela sua biblioteca de banco de dados) isolará corretamente os dados vinculados automaticamente para que você não precise se lembrar de qual função usar. Além disso, a vinculação consistente de parâmetros é muito mais confiável do que tentar lembrar que você precisa isolar tudo manualmente.

    Implementação do princípio do menor privilégio

    Encerrar uma injeção de SQL bem-sucedida é tão importante quanto evitá-la totalmente. Quando um invasor consegue executar consultas SQL, ele o fará como um usuário específico do banco de dados. O princípio do menor privilégio pode garantir que todos os usuários tenham apenas os privilégios absolutamente necessários para executar suas tarefas.


    Se um usuário tiver privilégios elevados, um invasor poderá eliminar tabelas e alterar os privilégios de outros usuários executando novas injeções de SQL em seu nome. Para evitar que isso aconteça, nunca acesse o banco de dados de um aplicativo Web como root, administrador ou outro usuário com privilégios elevados.


    Outra aplicação do princípio é a separação das funções de leitura e gravação de dados no banco de dados. Selecione um usuário com permissões somente gravação e outro com permissões somente leitura. Se o ataque for direcionado ao usuário “leitor”, o invasor não poderá manipular os dados da tabela ou gravá-los. Você pode limitar o acesso de forma ainda mais restrita, reduzindo assim o impacto de ataques de injeção de SQL bem-sucedidos.


    Muitas aplicações web, especialmente as de código aberto, são projetadas para usar apenas um usuário de banco de dados, cujo nível de privilégio quase certamente nunca é verificado. Portanto, não se esqueça deste ponto e não tente executar aplicativos com uma conta de administrador.

    Injeção de código (conhecida como inclusão remota de arquivo)

    Injeção de código é qualquer técnica que permite a um invasor adicionar código-fonte a um aplicativo da web com a capacidade de interpretá-lo e executá-lo. Nesse caso, não estamos falando em introduzir código na parte do cliente, por exemplo, em JavaScript, ataques XSS já são usados ​​aqui.


    Você pode injetar código-fonte diretamente de uma fonte de entrada não confiável ou forçar o aplicativo Web a carregá-lo do sistema de arquivos local ou de um recurso externo, como uma URL. Quando o código é injetado como resultado da inclusão de fonte externa, isso é comumente chamado de inclusão remota de arquivo (RFI), embora a própria RFI sempre tenha como objetivo injetar código.


    As principais razões para a introdução do código:

    • ignorando a verificação de dados de entrada,
    • injeção de entrada não confiável em qualquer contexto onde será tratada como código PHP,
    • hackear a segurança dos repositórios de código-fonte,
    • desativar avisos sobre o carregamento de bibliotecas de terceiros,
    • reconfigurar o servidor para que ele passe arquivos não-PHP para o interpretador PHP.

    Preste atenção especial ao último ponto: neste caso, usuários não confiáveis ​​podem fazer upload de qualquer arquivo para o servidor.

    Exemplos de injeção de código

    PHP tem muitos alvos de injeção de código, então esse tipo de ataque está no topo da lista de observação de qualquer programador.

    Incluindo um arquivo

    Os alvos mais óbvios para injeção de código são as funções include() , include_once() , require() e require_once() . Se dados de entrada não confiáveis ​​permitirem determinar o parâmetro de caminho passado para essas funções, você poderá controlar remotamente qual arquivo incluir. Deve-se notar que o arquivo incluído não precisa ser um arquivo PHP real; qualquer formato de arquivo capaz de armazenar dados de texto pode ser usado (ou seja, quase sem restrições).


    O parâmetro path também pode ser vulnerável a ataques de Directory Traversal ou de inclusão remota de arquivos. Usar as combinações de caracteres ../ ou... no caminho permite que um invasor navegue para praticamente qualquer arquivo ao qual o processo PHP tenha acesso. Ao mesmo tempo, na configuração padrão do PHP, as funções acima aceitam uma URL, a menos que allow_url_include esteja desabilitado.

    Exame

    A função PHP eval() aceita uma linha de código PHP para execução.

    Implementando Expressões Regulares

    A função PCRE (Expressão regular compatível com Perl) preg_replace() em PHP permite o uso do modificador e (PREG_REPLACE_EVAL). Isso significa uma string de substituição, que após a substituição será considerada código PHP. E se houver uma entrada não confiável nessa linha, eles poderão injetar código PHP executável.

    Lógica de inclusão de arquivo com defeito

    Os aplicativos da Web, por definição, incluem os arquivos necessários para atender a quaisquer solicitações. Se você aproveitar defeitos na lógica de roteamento, gerenciamento de dependências, carregamento automático e outros processos, a manipulação do caminho da solicitação ou de seus parâmetros forçará o servidor a incluir arquivos locais específicos. Como a aplicação web não foi projetada para lidar com tais manipulações, as consequências podem ser imprevisíveis. Por exemplo, o aplicativo exporá involuntariamente rotas destinadas apenas ao uso na linha de comando. Ou revelará outras classes cujos construtores executam tarefas (é melhor não projetar classes dessa forma, mas isso ainda acontece). Qualquer um desses cenários pode interferir nas operações de back-end do aplicativo, permitindo manipulação de dados ou ataques DOS em operações com uso intensivo de recursos que não envolvem acesso direto.

    Desafios de injeção de código

    A gama de tarefas é extremamente ampla, pois esse tipo de ataque permite executar qualquer código PHP da escolha do invasor.

    Defesas contra injeção de códigoInjeção de comandoExemplos de injeção de comandoDefesas contra injeção de comandoInjeção de log (conhecida como injeção de arquivo de log)

    Muitos aplicativos coletam logs e usuários autorizados geralmente os visualizam por meio de uma interface HTML. Portanto, os logs são um dos principais alvos de invasores que querem disfarçar outros ataques, enganar quem visualiza os logs e depois até atacar os usuários do aplicativo de monitoramento com o qual os logs são lidos e analisados.


    A vulnerabilidade dos logs depende de mecanismos de controle sobre a gravação de logs, bem como do tratamento dos dados de log como uma fonte não confiável ao visualizar e analisar logs.


    Um sistema de registro simples pode gravar strings de texto em um arquivo usando file_put_contents() . Por exemplo, um programador registra tentativas de autorização malsucedidas como strings no seguinte formato:


    sprintf("Falha na tentativa de login de %s", $nomedeusuario);

    E se o invasor usar o nome “AdminnSuccessful login by Adminn” no formulário?


    Se esta linha for inserida no log a partir de dados de entrada não confiáveis, o invasor disfarçará com sucesso a tentativa de autorização fracassada usando uma falha inocente ao inserir a senha do administrador. A suspeita dos dados será reduzida ainda mais se você adicionar uma tentativa de autorização bem-sucedida.


    A questão aqui é que o invasor é capaz de adicionar todos os tipos de entradas ao log. Você também pode injetar vetores XSS e até caracteres que dificultam a leitura das entradas de log no console.

    Tarefas de injeção de log

    Um dos objetivos da implementação são os intérpretes de formato de log. Se uma ferramenta de análise usar expressões regulares para analisar entradas de log e separá-las em campos diferentes, será possível criar e injetar uma string que faça com que a expressão regular selecione os campos injetados em vez dos corretos. Por exemplo, esta entrada pode causar vários problemas:


    $username = "iamnothacker! na segunda-feira, 01 de janeiro 00:00:00 +1000 2009"; sprintf("Falha na tentativa de login de %s em %s", $nomedeusuário,)

    Ataques de injeção de log mais sofisticados dependem de ataques de passagem de diretório para exibir o log no navegador. Sob as condições corretas, injetar código PHP em uma mensagem de log e abrir o arquivo de log em um navegador resultará em uma injeção de código bem-sucedida, que será formatado de maneira organizada e executado a pedido do invasor. E se se trata de executar PHP malicioso no servidor, só podemos esperar a eficácia das camadas de defesa, que podem reduzir os danos.

    Proteção de injeção de log

    A maneira mais fácil de filtrar todas as mensagens de log externas é usar uma lista de permissões. Digamos que limitamos o conjunto de caracteres apenas a números, letras e espaços. Mensagens contendo caracteres não autorizados são consideradas corrompidas. Em seguida, aparece uma entrada no log sobre uma possível tentativa de injetar um arquivo de log. Este é um método de segurança simples para logs de texto simples onde as mensagens não podem ser evitadas de incluir dados de entrada não confiáveis.


    O segundo método de proteção é converter pedaços de dados de entrada não confiáveis ​​usando um sistema como o base64, que suporta um conjunto limitado de caracteres e ainda permite que uma variedade de informações sejam armazenadas em formato de texto.

    Path Traversal (conhecido como Directory Traversal)

    Ataques de passagem de caminho são tentativas de afetar operações de leitura ou gravação de arquivos no back-end de um aplicativo da web. Isso é feito introduzindo parâmetros que permitem manipular os caminhos dos arquivos envolvidos nas operações de back-end. Portanto, esse tipo de ataque facilita a divulgação de informações e a injeção local/remota de arquivos.


    Consideraremos esses ataques separadamente, mas a base de seu sucesso é precisamente a travessia do caminho. Como as funções descritas abaixo são específicas para a manipulação de caminhos de arquivos, faz sentido mencionar que muitas funções PHP não aceitam caminhos de arquivos no sentido usual da palavra. Em vez disso, funções como include() ou file() aceitam um URI.


    Parece completamente antinatural. Mas isso significa que as duas chamadas de função a seguir são equivalentes, que usam caminhos absolutos (por exemplo, sem depender de caminhos relativos de carregamento automático).


    include('/var/www/vendor/library/Class.php'); include('arquivo:///var/www/vendor/library/Class.php');

    O problema é que o caminho relativo é processado paralelamente (a configuração include_path no php.ini e os autoloaders disponíveis). Nesses casos, as funções PHP são especialmente vulneráveis ​​a muitas formas de manipulação de parâmetros, incluindo substituição de esquema de URI de arquivo, onde um invasor pode injetar um URI HTTP ou FTP se dados não confiáveis ​​forem incorporados no início do caminho do arquivo. Falaremos sobre isso com mais detalhes na seção sobre ataques de inclusão remota de arquivos, mas por enquanto nos concentraremos em contornar os caminhos do sistema de arquivos.


    Esta vulnerabilidade envolve alterar o caminho para acessar outro arquivo. Isso normalmente é conseguido injetando uma série de sequências ../ em um argumento, que é então anexado a funções ou inserido inteiramente em funções como include() , require() , file_get_contents() e funções ainda menos suspeitas (para algumas) como DOMDocument: :load() .


    Usando a sequência ../, o invasor força o sistema a retornar ao diretório pai. Portanto, o caminho /var/www/public/../vendor na verdade vai para /var/www/vendor . A sequência ../ após /public nos leva de volta ao diretório pai, ou seja, /var/www. Isso permite que o invasor obtenha acesso a arquivos localizados fora do diretório /public acessível no servidor web.


    É claro que percorrer um caminho não se limita apenas a retornar. Você pode implementar novos elementos de caminho para acessar diretórios filhos que não são acessíveis no navegador devido às configurações de restrições do .htaccess. As operações do sistema de arquivos PHP não se preocupam com a configuração do controle de acesso de arquivos e diretórios não públicos no servidor web.

    Exemplos de defesas de Path Traversal contra injeção de Path TraversalXML

    Apesar da introdução do JSON como um meio leve de transferência de dados entre servidor e cliente, o XML continua sendo uma alternativa popular, e as APIs de serviços da Web geralmente o suportam em paralelo com o JSON. XML também é usado para trocar dados usando esquemas XML: RSS, Atom, SOAP e RDF, etc.


    XML é onipresente: pode ser encontrado em servidores de aplicativos da web, navegadores (como formato preferido para solicitações e respostas XMLHttpRequest) e extensões de navegador. Dada a sua prevalência e processamento padrão por analisadores populares como o libxml2, usado pelo PHP no DOM e nas extensões SimpleXML e XMLReader, o XML tornou-se alvo de ataques de injeção. Quando o navegador participa ativamente da troca de XML, deve-se levar em consideração que, por meio do XSS, usuários autorizados podem transmitir solicitações XML que foram realmente criadas por invasores.

    Incorporação de entidade externa XML (XXE)

    Esses ataques existem porque as bibliotecas de análise XML geralmente suportam o uso de referências de entidades personalizadas. Você aprenderá sobre o preenchimento de entidade XML padrão, que é usado para representar caracteres de marcação especiais como > , < ; e '. XML permite expandir o conjunto de entidades padrão definindo entidades personalizadas por meio do próprio documento XML. Eles podem ser definidos incluindo-os diretamente no DOCTYPE opcional. O valor estendido que representam pode referir-se a um recurso externo que deve ser incluído. Os ataques XXE tornaram-se populares precisamente devido à capacidade do XML comum de armazenar links personalizados que podem ser expandidos devido ao conteúdo de recursos externos. Em circunstâncias normais, entradas não confiáveis ​​nunca devem interagir com o nosso sistema de maneiras inesperadas. E a maioria dos programadores XXE quase certamente não prevê ataques XXE, o que é particularmente preocupante.


    Vamos, por exemplo, definir uma nova entidade personalizada como inofensiva:



    Um documento XML com esta definição agora pode fazer referência a uma entidade onde quer que entidades sejam geralmente permitidas:


    Este resultado é

    Quando um analisador XML como o PHP DOM interpreta esse XML, ele processará essa entidade personalizada assim que o documento for carregado. Portanto, ao solicitar o texto correspondente, retornará o seguinte:


    Este resultado é completamente inofensivo


    Obviamente, as entidades personalizadas têm a vantagem de representar texto e XML repetidos com nomes de entidade mais curtos. Muitas vezes, o XML deve seguir uma determinada gramática e as entidades personalizadas facilitam a edição. No entanto, dada a nossa desconfiança em relação a entradas externas, precisamos ter muito cuidado com qualquer XML que nossa aplicação consuma. Por exemplo, esta não é uma variedade segura:


    &harmless;

    Dependendo do conteúdo do arquivo local solicitado, os dados poderão ser utilizados na expansão da entidade. E então o conteúdo expandido pode ser extraído do analisador XML e incluído nos dados de saída do aplicativo web para análise pelo invasor. Por exemplo, para divulgar informações. O arquivo extraído será interpretado como XML, embora não existam caracteres especiais para acionar esta interpretação. Isto limita a extensão em que o conteúdo do arquivo local pode ser exposto. Se o arquivo for interpretado como XML, mas não contiver XML válido, provavelmente receberemos um erro, o que impedirá que o conteúdo seja revelado. No entanto, um truque interessante está disponível no PHP para contornar o limite de escopo, de modo que as solicitações HTTP remotas afetem o aplicativo da web, mesmo que a resposta retornada não possa ser repassada ao invasor.


    Existem três métodos comumente usados ​​para analisar e usar XML em PHP: PHP DOM, SimpleXML e XMLReader. Todos eles usam a extensão libxml2 e o suporte para entidades externas está habilitado por padrão. Como consequência, o PHP é vulnerável a ataques XXE por padrão, o que é muito fácil de ignorar quando se considera a segurança de uma aplicação web ou biblioteca que usa XML.


    Não esqueça também que XHTML e HTML 5 podem ser serializados como XML válido. Isso significa que algumas páginas XHTML ou HTML 5 serializado em XML podem ser analisadas como XML, usando DOMDocument::loadXML() em vez de DOMDocument::loadHTML() . Este uso de um analisador XML também é vulnerável à injeção de entidades XML externas. Lembre-se que a libxml2 ainda nem reconhece HTML 5 DOCTYPE, portanto não pode validá-lo como XHTML DOCTYPES.

    Exemplos de implementação de entidades XML externas Conteúdo e divulgação do arquivo

    Vimos um exemplo de divulgação de informações acima, observando que uma entidade XML personalizada pode fazer referência a um arquivo externo.


    &harmless;

    Neste caso, a entidade personalizada será expandida com o conteúdo dos arquivos. Como todas essas solicitações são executadas localmente, isso permite que o conteúdo de todos os arquivos que o aplicativo pode ler seja exposto. Ou seja, quando a entidade estendida for incluída nos dados de saída da aplicação, o invasor poderá examinar arquivos que não estão acessíveis. Porém, neste caso há uma limitação séria: os arquivos devem estar no formato XML ou em um formato que não leve a erros do analisador XML. Mas a questão é que essa limitação pode ser completamente ignorada no PHP:


    &harmless;

    PHP fornece acesso ao wrapper como um URI, um dos protocolos aceitos pelas funções padrão do sistema de arquivos: file_get_contents(), require(), require_once(), file(), copy() e muitos outros. O wrapper PHP suporta vários filtros que podem ser aplicados a um recurso específico para que os resultados sejam retornados chamando uma função. No exemplo acima, aplicamos o filtro convert.base-64-encode ao arquivo de destino que queremos ler.


    Isso significa que um invasor pode ler qualquer arquivo disponível para PHP, independentemente do formato do texto. Basta simplesmente decodificar os dados provenientes do aplicativo e depois dissecá-los impunemente. Embora isso não prejudique diretamente os usuários finais ou o back-end do aplicativo, permite que os invasores estudem minuciosamente a estrutura do aplicativo na tentativa de encontrar outras vulnerabilidades. Além disso, o risco de os invasores serem detectados é mínimo.

    Ignorar controle de acesso

    O acesso é controlado de diferentes maneiras. Como os ataques XXE são realizados no backend da aplicação web, não será possível utilizar a sessão do usuário atual. Mas um invasor ainda pode ignorar o controle de acesso ao backend usando solicitações do servidor local. Considere este controle de acesso primitivo:


    if (isset($_SERVER["HTTP_CLIENT_IP"]) || isset($_SERVER["HTTP_X_FORWARDED_FOR"]) || !in_array(@$_SERVER["REMOTE_ADDR"], array("127.0.0.1", "::1 ",))) ( header("HTTP/1.0 403 Proibido"); exit("Você não tem permissão para acessar este arquivo."); )

    Este pedaço de PHP, como inúmeros outros semelhantes, restringe o acesso a determinados arquivos PHP no servidor local, ou seja, localhost. No entanto, um ataque XXE no front-end do aplicativo fornece ao invasor as credenciais exatas necessárias para contornar esses controles de acesso, porque todas as solicitações HTTP ao analisador XML serão feitas a partir do host local.


    &harmless;

    Mesmo que a visualização dos logs fosse limitada a solicitações locais, um invasor ainda seria capaz de obter os logs. O mesmo se aplica às interfaces de manutenção ou administração, cujo acesso é limitado desta forma.

    Ataques DOS

    Quase tudo que determina o consumo de recursos do servidor pode ser usado para ataques DOS. Ao injetar uma entidade XML externa, um invasor pode fazer solicitações HTTP arbitrárias que, nas condições certas, esgotam os recursos do servidor.


    Falaremos mais tarde sobre outros usos potenciais de ataques XXE do DOS em termos de expansão de entidade XML.

    Proteção contra injeção de entidades XML externas

    Esses ataques são muito populares, então você ficará surpreso com a facilidade de se defender deles. Como DOM, SimpleXML e XMLReader dependem de libxml2, você pode simplesmente usar a função libxml_disable_entity_loader() para desabilitar o uso de entidades externas. No entanto, isso não desabilitará entidades personalizadas predefinidas em DOCTYPE, porque elas não usam recursos externos que exigem uma solicitação HTTP ou operação do sistema de arquivos.


    $oldValue = libxml_disable_entity_loader(true); $dom = new DOMDocument(); $dom->carregarXML($xml); libxml_disable_entity_loader($oldValue);

    Isso deve ser feito para todas as operações que envolvem o carregamento de XML de strings, arquivos ou URIs remotos.


    Onde um aplicativo nunca requer entidades externas, e para a maioria de suas solicitações, o carregamento de recursos externos pode ser totalmente desabilitado em um nível mais global. Na maioria dos casos, isto é muito preferível para definir todos os pontos de carregamento XML, dado que muitas bibliotecas têm vulnerabilidades inerentes a ataques XXE:


    libxml_disable_entity_loader(verdadeiro);

    Apenas lembre-se de retornar TRUE após cada habilitação temporária de carregamento de recursos externos. Você pode precisar dele para algo tão inócuo como converter Docbook XML em HTML, onde a aplicação de estilos XSL depende de entidades externas.


    No entanto, a função de desabilitar libxml2 não é uma panacéia. Analise outras extensões e bibliotecas PHP que analisam ou processam XML para encontrar suas “opções” para usar entidades externas.


    Se isso não for possível, verifique adicionalmente se o documento XML declara DOCTYPE. Nesse caso, e se as entidades externas estiverem desativadas, basta descartar o documento XML, negando acesso XML não confiável ao analisador potencialmente vulnerável e registrando-o como um ataque provável. Este é um passo necessário porque não haverá outros sinais – nem erros, nem exceções. Incorpore esta verificação em sua validação de entrada regular. Mas este método está longe de ser ideal, por isso é altamente recomendado para resolver fundamentalmente o problema de entidades externas.


    /** * Tentativa de detecção rápida */ $collapsedXML = preg_replace("/[:space:]/", "", $xml); if(preg_match("/