SitePoint Sponsor

User Tag List

Results 1 to 22 of 22
  1. #1
    SitePoint Zealot
    Join Date
    Mar 2005
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How do you handle security?

    Just wondering what sort of "best practices" everyone is using for security in PHP?

    I have been using the PHP Filters provided by the OWASP Foundation. These filters provide some pretty comprehensive validation methods, but I am sure I can do more.

  2. #2
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have just downloaded a PDF available from Microsoft the other day there, which you can find here

    http://msdn.microsoft.com/library/de...eatCounter.asp

    Looking at it briefly earlier today it covers everything you would need to know, provided you take into account what references about DotNet there are, also apply to PHP, but the implementation and script are different

  3. #3
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would say that "PHP Filters" will fit most situations: though may not be tough enough on XSS for some applications.

    Thanks for the article Dr Livingston: looks like an alright read.

  4. #4
    SitePoint Enthusiast
    Join Date
    Apr 2005
    Posts
    58
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Chris Shiflett is the security guru of PHP. There are a lot of great security resources on his blog , such as his security workbook.

  5. #5
    SitePoint Zealot
    Join Date
    Feb 2003
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by tobyhede
    I have been using the PHP Filters
    Code:
    // sanitize a string for SQL input (simple slash out quotes and slashes)
    function sanitize_sql_string($string, $min='', $max='')
    {
      $string = nice_addslashes($string); //gz
      $pattern = "/;/"; // jp
      $replacement = "";
      $len = strlen($string);
      if((($min != '') && ($len < $min)) || (($max != '') && ($len > $max)))
        return FALSE;
      return preg_replace($pattern, $replacement, $string);
    }
    They just drop all semi-colons from every sql-string? Interesting, to say the least...

  6. #6
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    sanitize_html in not that bad too

    PHP Code:
    function sanitize_html_string($string)
    {
      
    $pattern[0] = '/\&/';
      
    $pattern[1] = '/</';
      
    $pattern[2] = "/>/";
      
    $pattern[3] = '/\n/';
      
    $pattern[4] = '/"/';
      
    $pattern[5] = "/'/";
      
    $pattern[6] = "/%/";
      
    $pattern[7] = '/\(/';
      
    $pattern[8] = '/\)/';
      
    $pattern[9] = '/\+/';
      
    $pattern[10] = '/-/';
      
    $replacement[0] = '&amp;';
      
    $replacement[1] = '&lt;';
      
    $replacement[2] = '&gt;';
      
    $replacement[3] = '<br>';
      
    $replacement[4] = '&quot;';
      
    $replacement[5] = ''';
      
    $replacement[6] = '%';
      
    $replacement[7] = '(';
      
    $replacement[8] = ')';
      
    $replacement[9] = '+';
      
    $replacement[10] = '-';
      return 
    preg_replace($pattern$replacement$string);

    tobyhede

    First advice to you: stop using "the PHP Filters provided by the OWASP Foundation"

  7. #7
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's far from extensive protection but it really depends on the application at hand. If the application is not going to be displaying much user-defined data then the sanitize_html_string may be effecient.

    However, I do agree that parsing all ';' out of SQL queries is wrong. They should at least use some regex to see if the ; appeared in a quoted string. Valid ; (can't remember the name) would be stripped out.

  8. #8
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I dont like the look of those OWASP functions, imo either something is valid, or it isnt, you dont attempt fix it by replacing/removing bits.

    The ctype_*() functions are my usual first step. (well 2nd after checking min/max lengths)

    If there isn't one that matches the characters i want, something like

    strlen($value) == strspn($value, '01')

    will be true if $value is only made up of 0s or 1s. (a binary number).

    If its something bit more complex, then preg_match

  9. #9
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    I dont like the look of those OWASP functions, imo either something is valid, or it isnt, you dont attempt fix it by replacing/removing bits.

    The ctype_*() functions are my usual first step. (well 2nd after checking min/max lengths)

    If there isn't one that matches the characters i want, something like

    strlen($value) == strspn($value, '01')

    will be true if $value is only made up of 0s or 1s. (a binary number).

    If its something bit more complex, then preg_match
    Yes, often true when dealing with SQL Injection and such, strict is often the better option. However, XSS is a completely different ball game: you don't expect you're members to type &lt;, &gt;, etc, etc do you?

  10. #10
    SitePoint Zealot
    Join Date
    Mar 2005
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That PHP Security Workbook is a great resource, thanks. Lots of excellent ideas about securing files and sessions -> that's the kind of stuff I am looking for. Validating and verifying data is obvious and realtively simple, but I want to ensure I am not missing other obvious issues.

    The PHP Filters I use are slightly modified for my own use-cases. It's not a case of slapping these on and thinking that security is done, data has to be validated for each process according to the tightest possible requirements.

    Good catch on the sanitize_sql function. There are obviously cases where semi-colons are required inside text. This is a dangerous issue though, because semi-colons are statement terminators in many SQL variants (if not all) and some databases allow multiple statements to be executed (not such an issue for MySQL as only the most recent versions allow this functionality). Probably need the ability to switch this on or off - only allow semi-colons if the data warrants it and in other cases strip it completely.

    I think data needs to be handled on a case by case basis -> data such as email addresses and postcodes can be rejected if they are not in the correct format, but allowing HTML in the case of forums or RSS feeds is often necessary. Allowing the smallest possible set of HTML is the wisest cause of action in these cases.

  11. #11
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    To defeat semi-colons issues could you not just:

    If input is a string (ie. enclosed within quote tags), make sure slashes are applied (or equivalent procedure)
    If input is a number make sure it is a integer (or intval it, so if not valid will be 0).

    Just my take on it

  12. #12
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ryan Wray
    Yes, often true when dealing with SQL Injection and such, strict is often the better option. However, XSS is a completely different ball game: you don't expect you're members to type &lt;, &gt;, etc, etc do you?
    Has nothing todo with SQL Injection.. it has todo with being valid.

    SQL Injection & XSS are the same problem, both solved by escaping for the intended destination.

  13. #13
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well as for me I use the following class for all my security needs. Sometimes when some crucial Delete operations are done I may add some additional stuff too depending on the context.

    PHP Code:
    <?php
    /**
     * Author: Tim Koschützki
     * Based on ideas from Matt Mecham
     * Date Started: January 7th, 2003
    */
    class Request {

        
    /*-------------------------------------------------------------------------*/
        // Makes incoming info "safe"              
        /*-------------------------------------------------------------------------*/
        
        
    public function parse() {        
            
    $this->get_magic_quotes get_magic_quotes_gpc();
            
            
    $return = array();
            
            if( 
    is_array($_GET) ) {
                while( list(
    $k$v) = each($_GET) )    {
                    if ( 
    is_array($_GET[$k]) ) {
                        while( list(
    $k2$v2) = each($_GET[$k]) ) {
                            
    $return$this->clean_key($k) ][ $this->clean_key($k2) ] = $this->clean_value($v2);
                        }
                    } else {
                        
    $return$this->clean_key($k) ] = $this->clean_value($v);
                    }
                }
            }
            
            
    //-----------------------------------------
            // Overwrite GET data with post data
            //-----------------------------------------
            
            
    if( is_array($_POST) ) {
                while( list(
    $k$v) = each($_POST) ) {
                    if ( 
    is_array($_POST[$k]) )    {
                        while( list(
    $k2$v2) = each($_POST[$k]) )    {
                            
    $return$this->clean_key($k) ][ $this->clean_key($k2) ] = $this->clean_value($v2);
                        }
                    } else {
                        
    $return$this->clean_key($k) ] = $this->clean_value($v);
                    }
                }
            }
            
            
    $return['request_method'] = strtolower($_SERVER['REQUEST_METHOD']);
            
            return 
    $return;
        }
        

        private function 
    clean_key($key) {
            if (
    $key == "") {
                return 
    "";
            }
            
            
    $key htmlspecialchars(urldecode($key));
            
    $key preg_replace"/\.\./"           ""  $key );
            
    $key preg_replace"/\_\_(.+?)\_\_/"  ""  $key );
            
    $key preg_replace"/^([\w\.\-\_]+)$/""$1"$key );
            
            return 
    $key;
        }
        
        private function 
    clean_evil_tags$t ) {
            
    $t preg_replace"/javascript/i" "javascript"$t );
            
    $t preg_replace"/alert/i"      "alert"          $t );
            
    $t preg_replace"/about:/i"     "about:"         $t );
            
    $t preg_replace"/onmouseover/i""onmouseover"    $t );
            
    $t preg_replace"/onclick/i"    "onclick"        $t );
            
    $t preg_replace"/onload/i"     "onload"         $t );
            
    $t preg_replace"/onsubmit/i"   "onsubmit"       $t );
            
    $t preg_replace"/<body/i"      "&lt;body"            $t );
            
    $t preg_replace"/<html/i"      "&lt;html"            $t );
            
    $t preg_replace"/document\./i" "document."      $t );
            
            return 
    $t;
        }
        
        private function 
    clean_value($val) {       
            if (
    $val == "")    {
                return 
    "";
            }
        
            
    $val str_replace" "" "$val );
            
    $val str_replacechr(0xCA), ""$val );  //Remove sneaky spaces
            
            
    $val str_replace"&"            "&amp;"         $val );
            
    $val str_replace"<!--"         "<!--"  $val );
            
    $val str_replace"-->"          "-->"       $val );
            
    $val preg_replace"/<script/i"  "<script"   $val );
            
    $val str_replace">"            "&gt;"          $val );
            
    $val str_replace"<"            "&lt;"          $val );
            
    $val str_replace"\""           "&quot;"        $val );
            
    $val preg_replace"/\n/"        "<br />"        $val ); // Convert literal newlines
            
    $val preg_replace"/\\\$/"      "$"        $val );
            
    $val preg_replace"/\r/"        ""              $val ); // Remove literal carriage returns
            
    $val str_replace"!"            "!"         $val );
            
    $val str_replace"'"            "'"         $val ); // IMPORTANT: It helps to increase sql query safety.
            
            // Ensure unicode chars are OK
            
            
    if ( $this->allow_unicode ) {
                
    $val preg_replace("/&amp;#([0-9]+);/s""&#\\1;"$val );
            }
            
            
    // Strip slashes if not already done so.
            
            
    if ( $this->get_magic_quotes ) {
                
    $val stripslashes($val);
            }
            
            
    // Swop user inputted backslashes
            
            
    $val preg_replace"/\\\(?!&amp;#|\?#)/""\"$val ); 
            
            return 
    $val;
        }
    }

  14. #14
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    Has nothing todo with SQL Injection.. it has todo with being valid.

    SQL Injection & XSS are the same problem, both solved by escaping for the intended destination.
    You mis-understood me. You said that you never change anything, you only see if it is clean or not. This, however, will not be always effecient.

    When in an input field on a HTTP browser, I may use < and >in my post (ie. &lt; &gt with valid reasons. However, if you only do a check to see if it is clean or not, then you will either:

    Disallow the post, as you deem < and > tags as security risk and hence the post is invalid

    Allow it, but you don't convert the characters into their HTML entities.

    In this case, my post, although valid, would need to be modified before you can accept it as secure to display.

    Hence, for XSS this:
    Quote Originally Posted by Ren
    imo either something is valid, or it isnt, you dont attempt fix it by replacing/removing bits.
    Is often not enough.

    Quote Originally Posted by Ren
    SQL Injection & XSS are the same problem, both solved by escaping for the intended destination.
    SQL Injection and XSS are far from the same thing. But I think I get what you mean: they are both solved by appropiate validation. However, validation is not always as simple as 1 boolean check. It all depends on the application at hand.

    Good Luck

  15. #15
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ryan Wray
    You mis-understood me. You said that you never change anything, you only see if it is clean or not. This, however, will not be always effecient.

    When in an input field on a HTTP browser, I may use < and >in my post (ie. &lt; &gt with valid reasons. However, if you only do a check to see if it is clean or not, then you will either:

    Disallow the post, as you deem < and > tags as security risk and hence the post is invalid

    Allow it, but you don't convert the characters into their HTML entities.

    In this case, my post, although valid, would need to be modified before you can accept it as secure to display.

    Hence, for XSS this:

    Is often not enough.

    SQL Injection and XSS are far from the same thing. But I think I get what you mean: they are both solved by appropiate validation. However, validation is not always as simple as 1 boolean check. It all depends on the application at hand.

    Good Luck
    Sorry, as soon as any mentions "effecient" when it comes to security issues, I get very dubious.

    SQL Injection and XSS aren't solved by validation, but escaping. Period.

  16. #16
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What do you mean by escaping, Ren. To me, it seems like you contradict yourself.

    Quote Originally Posted by Ren
    mo either something is valid, or it isnt, you dont attempt fix it by replacing/removing bits.
    Keyword being valid. So, you use validation, yes?

    Quote Originally Posted by Ren
    SQL Injection and XSS aren't solved by validation, but escaping. Period.
    Okay, but is escaping not modifying the input in question.

    Maybe I am simply reading you wrong. I don't see how efficient is an incorrect term (though I spelled it wrong). Efficient also implies sufficient, with minimal waste. There is no reason to waste, say, memory when you can accomplish the same thing more efficiently.

    Oh well, I think I get what you are trying to say, in a round-about way.

  17. #17
    SitePoint Addict
    Join Date
    Oct 2004
    Location
    Brooklyn, NY
    Posts
    359
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by tobyhede
    I have been using the PHP Filters provided by the OWASP Foundation.
    I love OWASP, applaud their efforts, and am fairly active on the mailing list. However, I am not fond of these filters.

    The primary reason that I dislike them is that they reflect a very imprecise approach to this particular topic, and I think precision is important for a number of reasons. For example, sanitize_html_string() escapes data, which is a very different thing from filtering. How does a security-conscious developer intuit the behavior of this function or know when it should be used?

    Another complaint is that almost every function violates the security principle that says we should never modify invalid data in order to make it valid (although some security professionals agree that this approach can be acceptable when used as a Defense in Depth approach).

    Quote Originally Posted by stereofrog
    First advice to you: stop using "the PHP Filters provided by the OWASP Foundation"
    Agreed. :-)

    Quote Originally Posted by Ren
    I dont like the look of those OWASP functions, imo either something is valid, or it isnt, you dont attempt fix it by replacing/removing bits.
    I am sincerely happy to see that so many people immediately see the problem with such an approach. :-)

    Quote Originally Posted by Ryan Wray
    You mis-understood me. You said that you never change anything, you only see if it is clean or not. This, however, will not be always effecient.

    When in an input field on a HTTP browser, I may use < and >in my post (ie. &lt; &gt with valid reasons. However, if you only do a check to see if it is clean or not, then you will either:

    Disallow the post, as you deem < and > tags as security risk and hence the post is invalid

    Allow it, but you don't convert the characters into their HTML entities.

    In this case, my post, although valid, would need to be modified before you can accept it as secure to display.
    There is a distinct and important difference between filtering (inspecting data to prove its validity) and escaping (escaping or encoding special characters in order to preserve them).

    What Ren is describing is filtering. If I am filtering a last name, O'Reilly is going to pass my whitelist approach, because it consists entirely of characters that I consider to be valid in a last name. In order to use the name O'Reilly in an SQL query that I intend to send to MySQL, however, I still need to escape it with mysql_real_escape_string().

    Quote Originally Posted by Ryan Wray
    SQL Injection and XSS are far from the same thing. But I think I get what you mean: they are both solved by appropiate validation. However, validation is not always as simple as 1 boolean check. It all depends on the application at hand.
    I think this is part of the same misunderstanding. I agree with Ren that SQL Injection and XSS are very similar. In fact, they represent the same vulnerability in different contexts - you're sending tainted, unescaped data to some external system. For SQL Injection, the external system is a database server. For XSS, the external system is an HTTP client.

    Quote Originally Posted by Ren
    SQL Injection and XSS aren't solved by validation, but escaping. Period.
    Although I mostly agree with you, be careful with such statements. While escaping is more important than filtering in these contexts, it is not a substitute. There do exist exploits that leverage valid data to perform unintended actions.

    Quote Originally Posted by Ryan Wray
    Okay, but is escaping not modifying the input in question.
    Not exactly. The point of escaping is always to preserve data. For example, given the following string:

    I am writing a book for O'Reilly.

    When I escape this with mysql_real_escape_string(), it becomes the following:

    I am writing a book for O\'Reilly.

    Now, technically, this string has been modified, but that's not the purpose. It is in an escaped state so that the string is preserved when I send it to a MySQL database.

    Functions like htmlentities() and urlencode() also preserve data.

    Anyway, I hope that helps clarify some things. :-)
    Chris Shiflett
    http://shiflett.org/

  18. #18
    SitePoint Enthusiast
    Join Date
    Mar 2005
    Posts
    94
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    not so shy with ads chris

    -> http://phpsec.org/

    [edit]
    A security-careless-packet has dangers, because you cannot protect a
    system if you don't know how to compromise it. So its up to the programmer
    to learn about security and then use/build the right tools.

    my 2 eurocent

  19. #19
    SitePoint Evangelist
    Join Date
    Jun 2003
    Location
    Melbourne, Australia
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by shiflett
    There do exist exploits that leverage valid data to perform unintended actions.
    What, precisely, does leverage mean?
    Zealotry is contingent upon 100 posts and addiction 200?

  20. #20
    SitePoint Zealot
    Join Date
    Mar 2005
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Chris, thanks for the response. Excellent summary of the issues.

    By popular demand, I've stopped using those OWASP filters

  21. #21
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by shiftlet
    I agree with Ren that SQL Injection and XSS are very similar. In fact, they represent the same vulnerability in different contexts - you're sending tainted, unescaped data to some external system. For SQL Injection, the external system is a database server. For XSS, the external system is an HTTP client.
    I agree with you Chris, however that is not really what Ren said. Ren said they are the same 'problem', not that they are similar. Pespi and Coke are similar, they are not the same.

    As for the rest, looking back I mis-read Ren.

  22. #22
    SitePoint Zealot
    Join Date
    Mar 2005
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just wondering what Validation scripts people used? The one I have strung together is getting complex very quickly, and there may be an OS valdiation system that people recommend that will be much more robust and tested than anything I can produce.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •