Clarifications on XXE vulnerabilities throughout PHP versions

后端 未结 1 1842
借酒劲吻你
借酒劲吻你 2020-12-30 01:06

I post a question here as a last resort, I have browsed the web and went through many attempts but did not succeed.

Replicating a XXE attack is what I am trying to d

1条回答
  •  礼貌的吻别
    2020-12-30 01:38

    Keeping it simple .. As it should be simple :-)

    Your first code snippet

    libxml_disable_entity_loader does or does not do anything here based on whether your system resolves entities by default or not (mine does not). This is controlled by LIBXML_NOENT option of libxml.

    Without it the document processor may not even try translating external entities and therefore libxml_disable_entity_loader has nothing to really influence (if libxml does not load entities by default which seems to be the case in your test-case).

    Add LIBXML_NOENT to loadXML() like this:

    $dom->loadXML($xml, LIBXML_NOENT);
    

    and you'll quickly get:

    PHP Warning:  DOMDocument::loadXML(): I/O warning : failed to load external entity "/etc/passwd" in ...
    PHP Warning:  DOMDocument::loadXML(): Failure to process entity c in Entity, line: 7 in ...
    PHP Warning:  DOMDocument::loadXML(): Entity 'c' not defined in Entity, line: 7 in ...
    

    Your second code snippet

    In this scenario you've enabled entity resolving by using the LIBXML_NOENT option, that's why it goes after /etc/passwd.

    The example works just fine on my machine even for external URL - I changed the ENTITY to an external one like this:

    
    

    It can, however, be even influenced by eg. allow_url_fopen PHP INI setting - put it to false and PHP won't ever load a remote file.

    Your third code snippet

    XML Entity that you've provided is not an external one but rather an internal one (see eg. here).

    Your entity:

    
    

    How internal entity is defined:

    
    

    Therefore there is no reason for PHP or libxml to prevent resolving such entity.

    Conclusion

    I've quickly put up a PHP XXE tester script which tries out different settings and shows whether XXE is successful and in which case.

    The only line that should actually show a warning is the "LIBXML_NOENT" one.

    If any other line loads the WARNING, external entity loaded! your setup does allow loading external entities by default.

    You can't go wrong by using SHOULD USE libxml_disable_entity_loader() regardless of your/your provider's machine default settings. If your app ever gets migrated it might become vulnerable instantly.

    correct usage

    As the MediaWiki states in link you've posted.

    Unfortunately, the way that libxml2 implements the disabling, the library is crippled when external entities are disabled, and functions that would otherwise be safe cause an exception in the entire parsing.

    $oldValue = libxml_disable_entity_loader(true);
    // do whatever XML-processing related
    libxml_disable_entity_loader($oldValue);
    

    Note: libxml_disable_entity_loader() also prohibits loading external xml files directly (not through entities):

    load($remote_xml) !== FALSE)
        echo "loaded remote xml!\n";
    else
        echo "failed to load remote xml!\n";
    
    libxml_disable_entity_loader(true);
    if ($dom->load($remote_xml) !== FALSE)
        echo "loaded remote xml after libxml_disable_entity_loader(true)!\n";
    else 
        echo "failed to remote xml after libxml_disable_entity_loader(true)!\n";
    

    On my machine:

    loaded remote xml!
    PHP Warning:  DOMDocument::load(): I/O warning : failed to load external entity "https://stackoverflow.com/opensearch.xml" in ...
    failed to remote xml after libxml_disable_entity_loader(true)!
    

    It might perhaps be related to this PHP bug but PHP is being really stupid about it as:

    libxml_disable_entity_loader(true);
    $dom->loadXML(file_get_contents($remote_xml));
    

    works just fine.

    0 讨论(0)
提交回复
热议问题