Shop Hosting
Neuigkeiten
  • Die modified eCommerce Shopsoftware ist kostenlos, aber nicht umsonst.
    Spenden
  • Damit wir die modified eCommerce Shopsoftware auch zukünftig kostenlos anbieten können:
    Spenden
  • Thema: Inputfilter filtert alles:

    Thomas K.

    • Mitglied
    • Beiträge: 214
    Inputfilter filtert alles:
    am: 17. Juli 2012, 16:44:52
    Hallo,

    ich will gerade öffentliche Benutzerprofile erstellen. Ein Teil davon ist frei definierbarer Text, in dem sie einige HTML-Tags benutzen dürfen.

    Leider wird in der "includes/application_top.php" jeglicher tag entfernt, egal wie harmlos (<b><u><i><del>) sie sind.
    Gibt es dafür einen Ansatz eienr Whitelist, oder muss ich an der Stelle die application_top umgehen und einen eigenen html Filter hinterhersetzen?

    Grüße

    Thomas

    Linkback: https://www.modified-shop.org/forum/index.php?topic=21179.0

    Thomas K.

    • Mitglied
    • Beiträge: 214
    Re: Inputfilter filtert alles:
    Antwort #1 am: 20. Juli 2012, 01:16:53
    Ich glaube ich habe mich missverständlich ausgedrückt.

    Die superglobale $_POST wird i.d. application_top.php durch die inputfilter Klasse gefiltert.
    Leider werden dabei auch alle farmlosen html-tags entfernt.

    Im Content-Manager im Admin-Bereich werden html-tags aber z.B. nicht entfernt.

    Ich wäre über feedback dankbar, wie man das am besten löst.

    Danke
    Thomas

    h-h-h

    • modified Team
    • Beiträge: 4.562
    Re: Inputfilter filtert alles:
    Antwort #2 am: 20. Juli 2012, 02:11:38
    Hallo Thomas

    class.inputfilter.php
    Suche:
    Code: PHP  [Auswählen]
    return strip_tags($source);
    Ersetze mit:
    Code: PHP  [Auswählen]
    return strip_tags($source, '<b><u><i><del>');

    Besten Gruß

    h-h-h

    Thomas K.

    • Mitglied
    • Beiträge: 214
    Re: Inputfilter filtert alles:
    Antwort #3 am: 20. Juli 2012, 11:58:31
    Hallo h-h-h,
    danke für die schnelle Antwort, aber meine Klasse hat kein strip_tags(). (includes/classes/class.inputfilter.php)

    Code: PHP  [Auswählen]
    <?php
    /**
     *  @class: InputFilter (PHP4 & PHP5, with comments)
     * @project: PHP Input Filter
     * @date: 10-05-2005
     * @version: 1.2.2_php4/php5
     * @author: Daniel Morris
     * @contributors: Gianpaolo Racca, Ghislain Picard, Marco Wandschneider, Chris
     * Tobin and Andrew Eddie.
     *
     * Modification by Louis Landry
     *
     * @copyright: Daniel Morris
     * @email: dan@rootcube.com
     * @license: GNU General Public License (GPL)
     */

    class InputFilter {
            var $tagsArray; // default = empty array
            var $attrArray; // default = empty array

            var $tagsMethod; // default = 0
            var $attrMethod; // default = 0

            var $xssAuto; // default = 1
            var $tagBlacklist = array ('applet', 'body', 'bgsound', 'base', 'basefont', 'embed', 'frame', 'frameset', 'head', 'html', 'id', 'iframe', 'ilayer', 'layer', 'link', 'meta', 'name', 'object', 'script', 'style', 'title', 'xml');
            var $attrBlacklist = array ('action', 'background', 'codebase', 'dynsrc', 'lowsrc'); // also will strip ALL event handlers

            /**
              * Constructor for inputFilter class. Only first parameter is required.
              * @access constructor
              * @param Array $tagsArray - list of user-defined tags
              * @param Array $attrArray - list of user-defined attributes
              * @param int $tagsMethod - 0= allow just user-defined, 1= allow all but user-defined
              * @param int $attrMethod - 0= allow just user-defined, 1= allow all but user-defined
              * @param int $xssAuto - 0= only auto clean essentials, 1= allow clean blacklisted tags/attr
              */

            function inputFilter($tagsArray = array (), $attrArray = array (), $tagsMethod = 0, $attrMethod = 0, $xssAuto = 1) {
                            // make sure user defined arrays are in lowercase
            for ($i = 0; $i < count($tagsArray); $i ++)
                            $tagsArray[$i] = strtolower($tagsArray[$i]);
                    for ($i = 0; $i < count($attrArray); $i ++)
                            $attrArray[$i] = strtolower($attrArray[$i]);
                    // assign to member vars
                    $this->tagsArray = (array) $tagsArray;
                    $this->attrArray = (array) $attrArray;
                    $this->tagsMethod = $tagsMethod;
                    $this->attrMethod = $attrMethod;
                    $this->xssAuto = $xssAuto;
            }

            /**
              * Method to be called by another php script. Processes for XSS and specified bad code.
              * @access public
              * @param Mixed $source - input string/array-of-string to be 'cleaned'
              * @return String $source - 'cleaned' version of input parameter
              */

            function process($source)
            {
                    // Hetfield - 2010-03-01 - removed wrong placed code
                    // clean all elements in this array
                    if (is_array($source)) {
                            // BOF Hetfield - 2010-03-15 - Bugfix missing brace at foreach
                            foreach ($source as $key => $value) {
                                    // filter element for XSS and other 'bad' code etc.
                                    $tmp_key = $key;
                                    unset ($source[$key]);
                                    $key = $this->remove($this->decode($key));
                                    if ($key != $tmp_key) {
                                            return $source;
                                    } else {
                                            if (is_string($value)) {
                                                    $source[$key] = $this->remove($this->decode($value));
                                            } elseif (is_array($value)) {
                                                    $source[$key] = $this->process($value);
                                            }
                                    }
                            }
                            // EOF Hetfield - 2010-03-15 - Bugfix missing brace at foreach
                            return $source;
                            // clean this string
                    // BOF Hetfield - 2010-03-01 - Bugfix wrong closed if-else
                    } else {
                            if (is_string($source)) {
                                    // filter source for XSS and other 'bad' code etc.
                                    return $this->remove($this->decode($source));
                                    // return parameter as given
                            } else {
                                    return $source;
                            }
                    }
                    // EOF Hetfield - 2010-03-01 - Bugfix wrong closed if-else
            }

            /**
              * Internal method to iteratively remove all unwanted tags and attributes
              * @access protected
              * @param String $source - input string to be 'cleaned'
              * @return String $source - 'cleaned' version of input parameter
              */

            function remove($source) {
                    $loopCounter = 0;
                    // provides nested-tag protection
                    while ($source != $this->filterTags($source)) {
                            $source = $this->filterTags($source);
                            $loopCounter ++;
                    }
                    return $source;
            }

            /**
              * Internal method to strip a string of certain tags
              * @access protected
              * @param String $source - input string to be 'cleaned'
              * @return String $source - 'cleaned' version of input parameter
              */

            function filterTags($source) {
                    // filter pass setup
                    $preTag = NULL;
                    $source = str_replace('<>','',$source);
                    $postTag = $source;
                    // find initial tag's position
                    $tagOpen_start = strpos($source, '<');
                    // interate through string until no tags left
                    while ($tagOpen_start !== FALSE) {
                            // process tag interatively
                            $preTag .= substr($postTag, 0, $tagOpen_start);
                            $postTag = substr($postTag, $tagOpen_start);
                            $fromTagOpen = substr($postTag, 1);
                            // end of tag
                            $tagOpen_end = strpos($fromTagOpen, '>');
                            if ($tagOpen_end === false)
                                    break;
                            // next start of tag (for nested tag assessment)
                            $tagOpen_nested = strpos($fromTagOpen, '<');
                            if (($tagOpen_nested !== false) && ($tagOpen_nested < $tagOpen_end)) {
                                    $preTag .= substr($postTag, 0, ($tagOpen_nested +1));
                                    $postTag = substr($postTag, ($tagOpen_nested +1));
                                    $tagOpen_start = strpos($postTag, '<');
                                    continue;
                            }
                            $tagOpen_nested = (strpos($fromTagOpen, '<') + $tagOpen_start +1);
                            $currentTag = substr($fromTagOpen, 0, $tagOpen_end);
                            $tagLength = strlen($currentTag);
                            if (!$tagOpen_end) {
                                    $preTag .= $postTag;
                                    $tagOpen_start = strpos($postTag, '<');
                            }
                            // iterate through tag finding attribute pairs - setup
                            $tagLeft = $currentTag;
                            $attrSet = array ();
                            $currentSpace = strpos($tagLeft, ' ');
                            // is end tag
                            if (substr($currentTag, 0, 1) == "/") {
                                    $isCloseTag = TRUE;
                                    list ($tagName) = explode(' ', $currentTag);
                                    $tagName = substr($tagName, 1);
                                    // is start tag
                            } else {
                                    $isCloseTag = FALSE;
                                    list ($tagName) = explode(' ', $currentTag);
                            }
                            // excludes all "non-regular" tagnames OR no tagname OR remove if xssauto is on and tag is blacklisted
                            if ((!preg_match("/^[a-z][a-z0-9]*$/i", $tagName)) || (!$tagName) || ((in_array(strtolower($tagName), $this->tagBlacklist)) && ($this->xssAuto))) {
                                    $postTag = substr($postTag, ($tagLength +2));
                                    $tagOpen_start = strpos($postTag, '<');
                                    // don't append this tag
                                    continue;
                            }
                            // this while is needed to support attribute values with spaces in!
                            while ($currentSpace !== FALSE) {
                                    $fromSpace = substr($tagLeft, ($currentSpace +1));
                                    $nextSpace = strpos($fromSpace, ' ');
                                    $openQuotes = strpos($fromSpace, '"');
                                    $closeQuotes = strpos(substr($fromSpace, ($openQuotes +1)), '"') + $openQuotes +1;
                                    // another equals exists
                                    if (strpos($fromSpace, '=') !== FALSE) {
                                            // opening and closing quotes exists
                                            if (($openQuotes !== FALSE) && (strpos(substr($fromSpace, ($openQuotes +1)), '"') !== FALSE))
                                                    $attr = substr($fromSpace, 0, ($closeQuotes +1));
                                            // one or neither exist
                                            else
                                                    $attr = substr($fromSpace, 0, $nextSpace);
                                            // no more equals exist
                                    } else
                                            $attr = substr($fromSpace, 0, $nextSpace);
                                    // last attr pair
                                    if (!$attr)
                                            $attr = $fromSpace;
                                    // add to attribute pairs array
                                    $attrSet[] = $attr;
                                    // next inc
                                    $tagLeft = substr($fromSpace, strlen($attr));
                                    $currentSpace = strpos($tagLeft, ' ');
                            }
                            // appears in array specified by user
                            $tagFound = in_array(strtolower($tagName), $this->tagsArray);
                            // remove this tag on condition
                            if ((!$tagFound && $this->tagsMethod) || ($tagFound && !$this->tagsMethod)) {
                                    // reconstruct tag with allowed attributes
                                    if (!$isCloseTag) {
                                            $attrSet = $this->filterAttr($attrSet);
                                            $preTag .= '<'.$tagName;
                                            for ($i = 0; $i < count($attrSet); $i ++)
                                                    $preTag .= ' '.$attrSet[$i];
                                            // reformat single tags to XHTML
                                            if (strpos($fromTagOpen, "</".$tagName))
                                                    $preTag .= '>';
                                            else
                                                    $preTag .= ' />';
                                            // just the tagname
                                    } else
                                            $preTag .= '</'.$tagName.'>';
                            }
                            // find next tag's start
                            $postTag = substr($postTag, ($tagLength +2));
                            $tagOpen_start = strpos($postTag, '<');
                    }
                    // append any code after end of tags
                    $preTag .= $postTag;
                    return $preTag;
            }

            /**
              * Internal method to strip a tag of certain attributes
              * @access protected
              * @param Array $attrSet
              * @return Array $newSet
              */

            function filterAttr($attrSet) {
                    $newSet = array ();
                    // process attributes
                    for ($i = 0; $i < count($attrSet); $i ++) {
                            // skip blank spaces in tag
                            if (!$attrSet[$i])
                                    continue;
                            // split into attr name and value
                            $attrSubSet = explode('=', trim($attrSet[$i]));
                            list ($attrSubSet[0]) = explode(' ', $attrSubSet[0]);
                            // removes all "non-regular" attr names AND also attr blacklisted
                            if ((!preg_match("/^[a-z]*$/i", $attrSubSet[0])) || (($this->xssAuto) && ((in_array(strtolower($attrSubSet[0]), $this->attrBlacklist)) || (substr($attrSubSet[0], 0, 2) == 'on')))) // Hetfield - 2009-08-19 - replaced deprecated function eregi with preg_match to be ready for PHP >= 5.3
                                    continue;
                            // xss attr value filtering
                            if ($attrSubSet[1]) {
                                    // strips unicode, hex, etc
                                    $attrSubSet[1] = str_replace('&#', '', $attrSubSet[1]);
                                    // strip normal newline within attr value
                                    $attrSubSet[1] = preg_replace('/\s+/', '', $attrSubSet[1]);
                                    // strip double quotes
                                    $attrSubSet[1] = str_replace('"', '', $attrSubSet[1]);
                                    // [requested feature] convert single quotes from either side to doubles (Single quotes shouldn't be used to pad attr value)
                                    if ((substr($attrSubSet[1], 0, 1) == "'") && (substr($attrSubSet[1], (strlen($attrSubSet[1]) - 1), 1) == "'"))
                                            $attrSubSet[1] = substr($attrSubSet[1], 1, (strlen($attrSubSet[1]) - 2));
                                    // strip slashes
                                    $attrSubSet[1] = stripslashes($attrSubSet[1]);
                            }
                            // auto strip attr's with "javascript:
                            if (((strpos(strtolower($attrSubSet[1]), 'expression') !== false) && (strtolower($attrSubSet[0]) == 'style')) || (strpos(strtolower($attrSubSet[1]), 'javascript:') !== false) || (strpos(strtolower($attrSubSet[1]), 'behaviour:') !== false) || (strpos(strtolower($attrSubSet[1]), 'vbscript:') !== false) || (strpos(strtolower($attrSubSet[1]), 'mocha:') !== false) || (strpos(strtolower($attrSubSet[1]), 'livescript:') !== false))
                                    continue;

                            // if matches user defined array
                            $attrFound = in_array(strtolower($attrSubSet[0]), $this->attrArray);
                            // keep this attr on condition
                            if ((!$attrFound && $this->attrMethod) || ($attrFound && !$this->attrMethod)) {
                                    // attr has value
                                    if ($attrSubSet[1])
                                            $newSet[] = $attrSubSet[0].'="'.$attrSubSet[1].'"';
                                    // attr has decimal zero as value
                                    else
                                            if ($attrSubSet[1] == "0")
                                                    $newSet[] = $attrSubSet[0].'="0"';
                                    // reformat single attributes to XHTML
                                    else
                                            $newSet[] = $attrSubSet[0].'="'.$attrSubSet[0].'"';
                            }
                    }
                    return $newSet;
            }

            /**
              * Try to convert to plaintext
              * @access protected
              * @param String $source
              * @return String $source
              */

            function decode($source = '') {
                    if ($source!='') {
                    // url decode
                    if (function_exists('html_entity_decode')) {
                    $source = html_entity_decode($source, ENT_QUOTES, "ISO-8859-1");
                    }
                    // convert decimal
                    $source = preg_replace('/&#(\d+);/me', "chr(\\1)", $source); // decimal notation
                    // convert hex
                    $source = preg_replace('/&#x([a-f0-9]+);/mei', "chr(0x\\1)", $source); // hex notation
                    }
                    return $source;
            }

            /**
              * Method to be called by another php script. Processes for SQL injection
              * @access public
              * @param Mixed $source - input string/array-of-string to be 'cleaned'
              * @param Buffer $connection - An open MySQL connection
              * @return String $source - 'cleaned' version of input parameter
              */

            function safeSQL($source, $connection = 'db_link') {
                            // clean all elements in this array
            if (is_array($source)) {
                            foreach ($source as $key => $value)
                                    // filter element for SQL injection
                                    if (is_string($value))
                                            $source[$key] = $this->quoteSmart($this->decode($value), $connection);
                            return $source;
                            // clean this string
                    } else
                            if (is_string($source)) {
                                    // filter source for SQL injection
                                    if (is_string($source))
                                            return $this->quoteSmart($this->decode($source), $connection);
                                    // return parameter as given
                            } else
                                    return $source;
            }

            /**
              * @author Chris Tobin
              * @author Daniel Morris
              * @access protected
              * @param String $source
              * @param Resource $connection - An open MySQL connection
              * @return String $source
              */

            function quoteSmart($source, & $connection) {
                    // strip slashes
                    if (get_magic_quotes_gpc())
                            $source = stripslashes($source);
                    // quote both numeric and text
                    $source = $this->escapeString($source, $connection);
                    return $source;
            }

            /**
              * @author Chris Tobin
              * @author Daniel Morris
              * @access protected
              * @param String $source
              * @param Resource $connection - An open MySQL connection
              * @return String $source
              */

            function escapeString($string, & $connection) {
                    // depreciated function
                    // BOF - Hetfield - 2009-08-18 - deprecated function mysql_escape_string added mysql_real_escape_string to be ready for PHP >= 5.3
                    if (function_exists('mysql_real_escape_string')) {
                            mysql_real_escape_string($string);
                    } elseif (function_exists('mysql_escape_string')) {
                            mysql_escape_string($string);
                    }
                    // EOF - Hetfield - 2009-08-18 - deprecated function mysql_escape_string added mysql_real_escape_string to be ready for PHP >= 5.3
                    return $string;
            }
    }
    ?>

    web28

    • modified Team
    • Beiträge: 9.404
    Re: Inputfilter filtert alles:
    Antwort #4 am: 20. Juli 2012, 15:37:20
    Dann hast Du nicht die aktuelle Shopversion 1.05 Sp1d

    Thomas K.

    • Mitglied
    • Beiträge: 214
    Re: Inputfilter filtert alles:
    Antwort #5 am: 02. August 2012, 17:03:48
    Hey,

    ich habe die neue Datei wegen des Sicherheitsupdates gezogen.
    Jetzt ist deine Lösung anwendbar und ich habe glaube ich einen Bug entdeckt,

    i.d. Funktion

    Code: PHP  [Auswählen]
    function filterTags($source) {
        //fix null byte injection
        if (strpos($source,"\0")!== false) {return '';}
        if (strpos($source,"\x00")!== false) {return '';}
        if (strpos($source,"\u0000")!== false) {return '';}
        if (strpos($source,"\000")!== false) {return '';}
        //clean input string
        return strip_tags($source, "<a><p><i><b><u><del><span><div>");

    Warum kommt heir schon ein return? Danach stehen bei mir in der Funktion über hundert Zeilen weiterer Code.

    Außerdem ist für mich unverständlich, warum man sich den Aufwand macht eine Tag- und Attribut-Blacklist zu erstellen, um die dann zu ignorieren und JEDEN Tag zu entfernen.

    web28

    • modified Team
    • Beiträge: 9.404
    Re: Inputfilter filtert alles:
    Antwort #6 am: 02. August 2012, 18:16:29
    Zitat
    Warum kommt heir schon ein return? Danach stehen bei mir in der Funktion über hundert Zeilen weiterer Code.

    Trotz der über hundert Zeilen Code hat das für gemeldete Sicherheitsprobleme gar nicht funktioniert. Mit strip_tags waren die Probleme sofort erledigt.

    Im Frontend sind für Benutzereingaben auch keine Tags notwendig. Wer das möchte muss eben auf eigene Gefahr Anpassungen vornehmen.

    Der ganze Inputfilter steht aber auf unserer ToDo Liste.

    Gruss Web28

    Thomas K.

    • Mitglied
    • Beiträge: 214
    Re: Inputfilter filtert alles:
    Antwort #7 am: 03. August 2012, 13:48:43
    Dann würde ich euch den html purifier empfehlen.
    Einbau sehr intuitiv, sicher und ebenfalls OS.

    http://htmlpurifier.org/
    2 Antworten
    3937 Aufrufe
    08. Januar 2009, 19:21:41 von Anonym
    4 Antworten
    2797 Aufrufe
    15. März 2010, 12:26:51 von DokuMan
    112 Antworten
    38502 Aufrufe
    22. Oktober 2013, 11:03:23 von MarcoJ1980
               
    anything