31 const ENTITY_DETECT =
'Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks';
41 foreach (self::getEntityComparison($xml) as $compare) {
42 if (strpos($xml, $compare) !==
false) {
57 if (substr_count($errstr,
'DOMDocument::loadXML()') > 0) {
71 public static function scan($xml, DOMDocument $dom =
null)
76 if (self::isPhpFpm()) {
82 $dom =
new DOMDocument();
85 if (!self::isPhpFpm()) {
86 $loadEntities = libxml_disable_entity_loader(
true);
87 $useInternalXmlErrors = libxml_use_internal_errors(
true);
92 set_error_handler(array(
'Zend_Xml_Security',
'loadXmlErrorHandler'), E_WARNING);
94 $result = $dom->loadXml($xml, LIBXML_NONET);
95 restore_error_handler();
99 if (!self::isPhpFpm()) {
100 libxml_disable_entity_loader($loadEntities);
101 libxml_use_internal_errors($useInternalXmlErrors);
107 if (!self::isPhpFpm()) {
108 foreach ($dom->childNodes as $child) {
109 if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
110 if ($child->entities->length > 0) {
111 #require_once 'Exception.php'; 119 if (!self::isPhpFpm()) {
120 libxml_disable_entity_loader($loadEntities);
121 libxml_use_internal_errors($useInternalXmlErrors);
124 if (isset($simpleXml)) {
125 $result = simplexml_import_dom($dom);
126 if (!
$result instanceof SimpleXMLElement) {
142 public static function scanFile($file, DOMDocument $dom =
null)
144 if (!file_exists($file)) {
145 #require_once 'Exception.php'; 147 "The file $file specified doesn't exist" 169 $isVulnerableVersion = (
170 version_compare(PHP_VERSION,
'5.5.22',
'lt')
172 version_compare(PHP_VERSION,
'5.6',
'gte')
173 && version_compare(PHP_VERSION,
'5.6.6',
'lt')
177 if (
substr(php_sapi_name(), 0, 3) ===
'fpm' && $isVulnerableVersion) {
193 array(__CLASS__,
'generateEntityComparison'),
194 self::detectXmlEncoding($xml, self::detectStringEncoding($xml))
225 foreach (self::getBomMap() as $criteria) {
226 if (0 === strncmp($string, $criteria[
'bom'], $criteria[
'length'])) {
227 return $criteria[
'encoding'];
241 foreach (self::getAsciiEncodingMap() as $encoding =>
$generator) {
274 $closePos = strpos($xml, $close);
275 if (
false === $closePos) {
276 return array($fileEncoding);
279 $encPos = strpos($xml, $encAttr);
280 if (
false === $encPos
281 || $encPos > $closePos
283 return array($fileEncoding);
286 $encPos += strlen($encAttr);
287 $quotePos = strpos($xml,
$quote, $encPos);
288 if (
false === $quotePos) {
289 return array($fileEncoding);
295 str_replace(
'\0',
'', $encoding),
313 'encoding' =>
'UTF-32BE',
314 'bom' => pack(
'CCCC', 0x00, 0x00, 0xfe, 0xff),
318 'encoding' =>
'UTF-32LE',
319 'bom' => pack(
'CCCC', 0xff, 0xfe, 0x00, 0x00),
323 'encoding' =>
'GB-18030',
324 'bom' => pack(
'CCCC', 0x84, 0x31, 0x95, 0x33),
328 'encoding' =>
'UTF-16BE',
329 'bom' => pack(
'CC', 0xfe, 0xff),
333 'encoding' =>
'UTF-16LE',
334 'bom' => pack(
'CC', 0xff, 0xfe),
338 'encoding' =>
'UTF-8',
339 'bom' => pack(
'CCC', 0xef, 0xbb, 0xbf),
357 'UTF-32BE' => array(__CLASS__,
'encodeToUTF32BE'),
358 'UTF-32LE' => array(__CLASS__,
'encodeToUTF32LE'),
359 'UTF-32odd1' => array(__CLASS__,
'encodeToUTF32odd1'),
360 'UTF-32odd2' => array(__CLASS__,
'encodeToUTF32odd2'),
361 'UTF-16BE' => array(__CLASS__,
'encodeToUTF16BE'),
362 'UTF-16LE' => array(__CLASS__,
'encodeToUTF16LE'),
363 'UTF-8' => array(__CLASS__,
'encodeToUTF8'),
364 'GB-18030' => array(__CLASS__,
'encodeToUTF8'),
383 $substr .= $string[
$i];
401 $generator = isset($encodingMap[$encoding]) ? $encodingMap[$encoding] : $encodingMap[
'UTF-8'];
414 return preg_replace(
'/(.)/',
"\0\0\0\\1", $ascii);
426 return preg_replace(
'/(.)/',
"\\1\0\0\0", $ascii);
438 return preg_replace(
'/(.)/',
"\0\\1\0\0", $ascii);
450 return preg_replace(
'/(.)/',
"\0\0\\1\0", $ascii);
462 return preg_replace(
'/(.)/',
"\0\\1", $ascii);
474 return preg_replace(
'/(.)/',
"\\1\0", $ascii);
static detectXmlEncoding($xml, $fileEncoding)
static getEntityComparison($xml)
static encodeToUTF32LE($ascii)
static scanFile($file, DOMDocument $dom=null)
static scan($xml, DOMDocument $dom=null)
static substr($string, $start, $end)
static encodeToUTF32BE($ascii)
call_user_func($callable, $param)
static generateEntityComparison($encoding)
static getAsciiEncodingMap()
static encodeToUTF16BE($ascii)
static detectXmlStringEncoding($xml)
static encodeToUTF32odd1($ascii)
static encodeToUTF8($ascii)
static heuristicScan($xml)
static encodeToUTF16LE($ascii)
static encodeToUTF32odd2($ascii)
static detectBom($string)
static detectStringEncoding($xml)
static loadXmlErrorHandler($errno, $errstr, $errfile, $errline)