Frage

Ich arbeite eine gute Art und Weise auf der Suche nach Benutzern übermittelten Daten, in diesem Fall zu machen erlauben HTML und habe es so sicher und schnell wie ich kann.

Ich weiß, jede einzelne Person auf dieser Seite http://htmlpurifier.org scheint zu denken, ist die Antwort hier. Ich stimme teilweise. HTMLPurifier hat den besten Open-Source-Code gibt zum Filtern Benutzer HTML abgegeben, aber es Lösung ist sehr sperrig und ist für die Leistung nicht gut auf einem hohen Verkehr Ort. Ich könnte sogar dort Lösung einen Tag verwenden, aber jetzt mein Ziel ist es, eine leichtere Methode zu finden.

Ich habe mit den zwei folgenden Funktionen für etwa 2 ½ Jahre ohne Probleme noch nicht, aber ich denke, es ist Zeit, eine Eingabe von den Profis hier zu nehmen, wenn sie mir helfen.

Die erste Funktion aufgerufen wird FilterHTML ($ string) ist ran, bevor Benutzerdaten zu einer MySQL-Datenbank gespeichert wird. Die zweite Funktion wird aufgerufen, format_db_value ($ text, $ nl2br = false) und ich benutze es auf einer Seite, wo ich die Benutzer vorgelegten Daten zu zeigen, planen.

Unter den 2-Funktionen ist ein Bündel des XSS-Codes ich auf http: // ha.ckers.org/xss.html und ich lief sich auf diesen zwei Funktionen dann zu sehen, wie mein Code affektiven, ich etwas mit den Ergebnissen zufrieden bin, haben sie jeden Codeblock heraus, dass ich versuchte, aber ich weiß, dass es offensichtlich immer noch nicht zu 100% sicher ist.

Can ihr bitte Blick über sie und geben Sie mir einen Rat für meinen Code selbst oder auch im großen und ganzen html Filterung Konzept.

Ich möchte einen Whitelist-Ansatz eines Tages tun, aber HTMLPurifier ist die einzige Lösung, die ich wert gefunden haben, unter Verwendung von für das und wie ich bereits erwähnt es nicht leicht ist, wie ich möchte.

function FilterHTML($string) {
    if (get_magic_quotes_gpc()) {
        $string = stripslashes($string);
    }
    $string = html_entity_decode($string, ENT_QUOTES, "ISO-8859-1");
    // convert decimal
    $string = preg_replace('/&#(\d+)/me', "chr(\\1)", $string); // decimal notation
    // convert hex
    $string = preg_replace('/&#x([a-f0-9]+)/mei', "chr(0x\\1)", $string); // hex notation
    //$string = html_entity_decode($string, ENT_COMPAT, "UTF-8");
    $string = preg_replace('#(&\#*\w+)[\x00-\x20]+;#U', "$1;", $string);
    $string = preg_replace('#(<[^>]+[\s\r\n\"\'])(on|xmlns)[^>]*>#iU', "$1>", $string);
    //$string = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $string); //bad line
    $string = preg_replace('#/*\*()[^>]*\*/#i', "", $string); // REMOVE /**/
    $string = preg_replace('#([a-z]*)[\x00-\x20]*([\`\'\"]*)[\\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iU', '...', $string); //JAVASCRIPT
    $string = preg_replace('#([a-z]*)([\'\"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iU', '...', $string); //VBSCRIPT
    $string = preg_replace('#([a-z]*)[\x00-\x20]*([\\\]*)[\\x00-\x20]*@([\\\]*)[\x00-\x20]*i([\\\]*)[\x00-\x20]*m([\\\]*)[\x00-\x20]*p([\\\]*)[\x00-\x20]*o([\\\]*)[\x00-\x20]*r([\\\]*)[\x00-\x20]*t#iU', '...', $string); //@IMPORT
    $string = preg_replace('#([a-z]*)[\x00-\x20]*e[\x00-\x20]*x[\x00-\x20]*p[\x00-\x20]*r[\x00-\x20]*e[\x00-\x20]*s[\x00-\x20]*s[\x00-\x20]*i[\x00-\x20]*o[\x00-\x20]*n#iU', '...', $string); //EXPRESSION
    $string = preg_replace('#</*\w+:\w[^>]*>#i', "", $string);
    $string = preg_replace('#</?t(able|r|d)(\s[^>]*)?>#i', '', $string); // strip out tables
    $string = preg_replace('/(potspace|pot space|rateuser|marquee)/i', '...', $string); // filter some words
    //$string = str_replace('left:0px; top: 0px;','',$string);
    do {
        $oldstring = $string;
        //bgsound|
        $string = preg_replace('#</*(applet|meta|xml|blink|link|script|iframe|frame|frameset|ilayer|layer|title|base|body|xml|AllowScriptAccess|big)[^>]*>#i', "...", $string);
    } while ($oldstring != $string);
    return addslashes($string);
}

Unter-Funktion wird verwendet, wenn Benutzercode auf einer Webseite eingereicht zeigt

function format_db_value($text, $nl2br = false) {
    if (is_array($text)) {
        $tmp_array = array();
        foreach ($text as $key => $value) {
            $tmp_array[$key] = format_db_value($value);
        }
        return $tmp_array;
    } else {
        $text = htmlspecialchars(stripslashes($text));
        if ($nl2br) {
            return nl2br($text);
        } else {
            return $text;
        }
    }
}

Die folgenden Codes sind von ha.ckers.org und sie alle scheinen auf meinen Funktionen über

zum scheitern verurteilt

Ich habe nicht versucht, alle auf dieser Website, obwohl es viel mehr ist, ist dies nur einige von ihnen.
Der ursprüngliche Code ist auf der obere Zeile jeden Satz und den Code nach meinen Funktionen ausgeführt durch auf der Linie darunter.

<IMG SRC="javascript:alert(\'XSS\');"><b>hello</b> hiii
<IMG SRC=...alert('XSS');"><b>hello</b> hiii

<IMG SRC=JaVaScRiPt:alert('XSS')>
<IMG SRC=...alert('XSS')>

<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
<IMG SRC=...alert(String.fromCharCode(88,83,83))>

<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>
<IMG SRC=...alert('XSS')>

<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>
<IMG SRC=F  MLEJNALN !>

<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
<IMG SRC=...alert('XSS')>


<IMG SRC="jav&#x0A;ascript:alert('XSS');">
<IMG SRC=...alert('XSS');">

perl -e 'print "<IMG SRC=javascript:alert("XSS")>";' > out
perl -e 'print "<IMG SRC=java\0script:alert(\"XSS\")>";' > out

<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>
...

<iframe src=http://ha.ckers.org/scriptlet.html <
...

<LAYER SRC="http://ha.ckers.org/scriptlet.html"></LAYER>
......

<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">
...; REL=stylesheet">

<IMG STYLE="xss:...(alert('XSS'))">
<IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))">

<XSS STYLE="xss:...(alert('XSS'))">
<XSS STYLE="xss:expression(alert('XSS'))">

<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>

<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>


<IMG
SRC
=
"
j
a
v
a
s
c
r
i
p
t
:
a
l
e
r
t
(
'
X
S
S
'
)
"
>

<IMG
SRC
=...
a
l
e
r
t
(
'
X
S
S
'
)
"
>
War es hilfreich?

Andere Tipps

Der einzige Weg um sicher zu sein ist es, die weiße Liste der Tags und Attribute, die sie streng regexps verwenden und schreiben können zulässigen Werte von Attributen zu validieren. Wenn Sie Attribute erlauben, wie „Stil“ wollen, dann müssen Sie zusätzliche Komplexität.

Schwarze Liste könnte nur Angriff für einige Menschen härter machen, aber es wird nicht schwieriger macht jede für die Person, dass Anwendungen Technik, die Sie jetzt noch nicht gehört haben.

Ich würde versuchen, regexp mit Schließen-Tags hinzufügen fehlt, was die Nutzer eingegeben und ersetzen <br> mit <br /> und so weiter, dann analysieren sie SimpleXML verwenden, dann Iterierte über sie und entfernen Sie das Etikett, das nicht in die weiße Liste ist, jedes Attribut, dass ist nicht für gegebenen Tag in der weißen Liste, und jedes Attribut, das einen Wert hat, um präzisen regexp für dieses Attribut nicht entspricht. Schließlich würde ich asXML () verwenden, um den Text wieder zu bekommen. Ich würde mit einem minimalen Satz von Tags und Attributen beginnen und neue hinzufügen als besonders vorsichtig etwas brauchte, die URL enthält.

IMHO htmlawed ist die beste - schlanke, schnelle, vollständige HTML-Abdeckung, flexibelste ... schwarze oder weiße Liste für Tags und Attribute. Sicher? Niederlagen alle die ha.ckers Codes XSS

Wie wäre es mit PHP nativen HTML-Parser?

Ich war neugierig, also habe ich einige Code geschrieben für die Prüfung (benötigt PHP 5.3.6 +):

$badHtml = file_get_contents('badHtml.txt');
$html = sprintf('<div id="input">%s</div>', $badHtml);

// tidy is no required, but may fix invalid markup
$tidy = new \tidy();
$tidy->parseString($html, array(), 'utf8');
$tidy->cleanRepair();

$dom = new \DomDocument('1.0', 'UTF-8');
libxml_use_internal_errors(true);
$dom->loadHtml($tidy);
$input = $dom->getElementById('input');

// tag as key, attributes as values
$allowed = array(
  'table'  => array('border'),  
  'tbody'  => array(),
  'tr'     => array(),
  'td'     => array(),
  'th'     => array(),
  'img'    => array('src', 'alt'),
  'p'      => array(),
  'ul'     => array(),
  'ol'     => array(),
  'li'     => array(),
  'a'      => array('href', 'title'),
  'strong' => array(),
  'em'     => array(),
  'sub'    => array(),
  'sup'    => array(),
);

$walk = function(\DomNode $node) use($allowed, &$walk){

  // only check tags
  if($node->nodeType !== XML_ELEMENT_NODE)
    return;

  if(!isset($allowed[$node->nodeName]))
    return $node->parentNode->removeChild($node);

  foreach($node->attributes as $key => $attr){
    if(!in_array($key, $allowed[$node->nodeName], true))
     $node->removeAttribute($key);

    // expect URLs here
    if(!in_array($key, array('href', 'src'), true))
      continue;

    if(!filter_var($attr->value, FILTER_VALIDATE_URL))
      return $node->parentNode->removeChild($node); 

  }

  array_map($walk, iterator_to_array($node->childNodes));  
};

// convert DOMNodeList to array because this way the bad stuff
// can be removed within the loop
array_map($walk, iterator_to_array($input->childNodes));

// export HTML
$sanitized = $dom->saveHtml($input);

Der Ausgang, ohne Tidy ausgeführt wird:

eingeben Bild Beschreibung hier

Scheint ok. Oder hat es entfernen zu viel? :) Sollte Weg schneller als HTMLPurifier theoretisch mehr sichern, da es weniger freizügig, und wahrscheinlich schneller als die regulären Ausdrücke zu.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top