SitePoint Sponsor

User Tag List

Page 1 of 4 1234 LastLast
Results 1 to 25 of 93
  1. #1
    ********* Articles ArticleBot's Avatar
    Join Date
    Apr 2001
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Article Discussion

    This is an article discussion thread for discussing the SitePoint article, "Top 7 PHP Security Blunders"

  2. #2
    SitePoint Wizard
    Join Date
    Jan 2001
    Location
    Grand Rapids, MI
    Posts
    1,284
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No mention of the PHP Security Consortium, in which Chris wrote the book on this stuff, literally: phpsec.org

  3. #3
    SitePoint Member
    Join Date
    Dec 2005
    Location
    California
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Pretty good until the part about sql insertion vulnerabilities. magic_quotes_gpc is a really terrible configuration option: it escapes all your data (even data you might not want escaped) and it escapes it in a way that assumes you will be using mysql as the database (not every database handles escaping in the same way).

    I think the worst thing about it is it promotes a careless attitude towards data tainting (one magic config and now I don't have to think about it any more.) A much better idea for avoiding sql injection attacks is to use bound parameters via a db abstraction library like pear DB. See my blog @ http://metapundit.net/sections/blog/45 for example...

  4. #4
    SitePoint Evangelist
    Join Date
    Jan 2005
    Location
    bahrain
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    great article really helpful. should be read by all php programmers.

  5. #5
    SitePoint Evangelist dscriptor's Avatar
    Join Date
    Oct 2005
    Location
    in front of my computer
    Posts
    571
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Thumbs up

    yes, it's a good article! great idea too!
    still many things i need to know when it comes to PHP security.. :'(
    happy is the man that finds wisdom....wisdom in {PHP}.


  6. #6
    SitePoint Evangelist spinmaster's Avatar
    Join Date
    Mar 2005
    Posts
    456
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    nice article! enjoyed reading it...

  7. #7
    SitePoint Enthusiast
    Join Date
    Nov 2005
    Posts
    85
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sweeeet. Top security articles ever read.

  8. #8
    SitePoint Enthusiast
    Join Date
    Mar 2005
    Posts
    78
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Let's solve the security problem in two pages! YAY!

  9. #9
    SitePoint Addict
    Join Date
    Oct 2004
    Location
    Brooklyn, NY
    Posts
    359
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here are some additional notes and corrections. I hope they help.

    > User-provided data simply cannot be trusted.

    Users aren't the only source of input. No input can be trusted.

    > An extremely malicious user could append ";rm -rf" to the
    > year value and delete your entire Website!

    Maybe the attacker will also forget to specify any files to remove. :-)

    > You should check the user's credentials upon every load
    > of a restricted page of your PHP application.

    Be careful. Most people equate "user's credentials" with a username and password. Surely you don't mean to suggest that developers expose such sensitive data more than necessary (once).

    > It's also advisable to layer your security, for example,
    > by restricting user access on the basis of the user's IP
    > address as well as their user name, if possible."

    Enforcing IP consistency is only applicable in environments where you have control over the network layer. For a public web application, this is a terrible idea.

    > Use the PHP include function to include these files from
    > a directory that's not Web-accessible, possibly including
    > an .htaccess file containing "deny from any".

    I think you mean deny from all:

    http://httpd.apache.org/docs/1.3/mod/mod_access.html

    This offers no protection if these files are not stored within document root. Redundant safeguards are great, but this isn't a safeguard.

    > Always name these include files with a .php extension, so
    > that even if all your protection is bypassed, the Web
    > server will parse the PHP code, and will not display it
    > to the user.

    Executing code out of context is an additional and unnecessary risk. I would argue that it's safer to instruct Apache to deny access to .inc resources (in httpd.conf) and store includes outside of document root. That's Defense in Depth. Naming includes .php eliminates the potential to add this extra safeguard, plus it just exchanges one risk for another.

    > Never, ever, make a backup of a php file in your
    > Web-exposed directory by adding .bak or another extension
    > to the filename. If you do this, the PHP code in the file
    > will not be parsed by the Web server, and may be output
    > as source to a user who stumbles upon a URL to the backup
    > file.

    Surprisingly enough, this isn't true:

    http://www.christopher-kunz.de/serendipity/archives/75-Apache-and-.php.bak-files.html

    > If you must store a password in a session variable, do
    > not store the password in clear text; use the sha1()
    > (PHP 4.3+) or md5() function to store the hash of the
    > password instead.

    Don't store a user's password in the session. Sessions aren't as exposed as data you output to or receive from a user, but unnecessary exposure of a user's password is never a good idea.

    > To prevent this type of attack, you must perform user
    > input validation by disallowing any <script> tags from
    > being submitted to your forms. Always convert the < and >
    > characters in user input that may be viewed by other
    > users to &lt; and &gt;.

    You're describing two separate things. Validation (also known as filtering) ensures data integrity. Escaping (converting special characters to their HTML entity equivalents) ensures data preservation. Filter input. Escape output.

    Also, Cross-site scripting (XSS) is an output escaping problem, not an input filtering one:

    http://www.oreillynet.com/pub/wlg/8235

    Again, redundant safeguards are great, but always make sure the primary safeguard addresses the root cause of the problem.

    > SQL insertion vulnerabilities are yet another class of
    > input validation flaws.

    I think you mean SQL injection vulnerabilities. I've never heard this one misnamed, but inconsistent naming is a problem with other vulnerabilities such as cross-site request forgeries. The Web Application Security Consortium is trying to help:

    http://webappsec.org/projects/threat/

    > To alleviate this problem, ensure that your
    > magic_quotes_gpc PHP ini variable is turned on, which is
    > the default in most recently released versions of PHP.

    Oh. My. God.

    Never enable magic quotes. :-)

    > If you're developing software that may be installed on
    > shared servers where the end user might not be able to
    > change the php.ini file, use code to check that status of
    > magic_quotes_gpc and, if it is turned off, pass any user
    > input that will be used in a database query through the
    > addslashes() function, as shown below.

    Use a database-specific escaping function when possible. Also, do this on output, not input.

    > Credit card numbers and customer information are the most
    > common types of secured data, but if you transmit
    > usernames and passwords over a regular HTTP connection,
    > and those usernames and passwords allow access to
    > sensitive material, you might as well transmit the
    > sensitive material itself over an unencrypted connection.

    This is a good point, but didn't you recommend using HTTP authentication earlier?

    > If you're on a shared host, use the ini_set() function in
    > all your pages and disable this setting.

    You can't disable register_globals in a PHP script unless you're using a very old version of PHP. See here for a list of configuration directives and where you can set them:

    http://php.net/manual/ini.php#ini.list

    This dispelGlobals() function might be helpful:

    http://www.phpguru.org/article.php?ne_id=60

    > phpAdvisory is another great site focused on PHP
    > security. It lists PHP-related advisories and provides
    > articles dealing with various aspects of PHP security.

    The information on this site appears to be at least 3 years old, so it's not a good place to look for advisories. The PHP Security Consortium is a more updated resource:

    http://phpsec.org/

    It has a library with links to other helpful resources, PHP-specific summaries of the SecurityFocus newsletters, the PHP Security Guide, and a couple of articles.

    I hope this was helpful.

  10. #10
    Team SitePoint AlexW's Avatar
    Join Date
    Apr 2000
    Location
    Melbourne
    Posts
    832
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Wow. Now that's what I call a comprehensive critique. Impressive, Shiflett.
    Alex Walker
    SitePoint Developer
    SitePoint - Learnable

  11. #11
    SitePoint Enthusiast
    Join Date
    May 2005
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It needs saying again: God no! NEVER ENABLE MAGIC QUOTES.

    A couple of other points that were missed from the article and Shiflett's post.

    If you're passing untrusted data to exec(), you can use regex to validate yes, but you should also use escapeshellarg() and / or escapeshellcmd().

    addslashes() is ok for sql input I suppose, but you'll probably find a command more suited to your database engine. For example, MySQL has mysql_real_escape_string()

    (taken from php.net)
    // Quote variable to make safe
    function quote_smart($value)
    {
    // Stripslashes
    if (get_magic_quotes_gpc()) {
    $value = stripslashes($value);
    }
    // Quote if not integer
    if (!is_numeric($value)) {
    $value = "'" . mysql_real_escape_string($value) . "'";
    }
    return $value;
    }

    I use the above, but with !is_int && !is_float rather than is_numeric. Else you end up with phone numbers like "+44123456879" or "07931712345" losing the + / 0 respectively when being passed to the DB.

  12. #12
    SitePoint Zealot
    Join Date
    Jul 2005
    Location
    Venlo, the Netherlands
    Posts
    141
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    "you can develop your own error handling functions that are automatically invoked when PHP encounters an error, and can email you"
    Not recomendable, unless you really want your inbox to be flooded within minutes

    And like shiflett already mentioned,
    never ever store passwords in sessions. You simply don't need them anymore, after a user is logged in. All you need is the user_id and a flag which indicates true(logged in) or false (not logged in


  13. #13
    SitePoint Enthusiast petersj's Avatar
    Join Date
    Aug 2002
    Posts
    59
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    An easy way to secure files from being directly accessed is to include the following code at the top of each file. This method has the advantage that does not rely upon the hosting environment to secure the files.
    PHP Code:
    if ($_SERVER['REQUEST_URI'] == $_SERVER['PHP_SELF']) exit(); 

  14. #14
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In addition to what's already said, "$_GET[month]" is an invalid syntax.

  15. #15
    SitePoint Enthusiast
    Join Date
    May 2005
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    petersj: That method isn't secure at all. If I access one of your files with ?=blah at the end it'll let me in. PHP_SELF doesn't store querystring data whereas REQUEST_URI does.

    Thanks everyone for the points about passwords and sessions. It's a mistake I've been making and only just realised how stupid it is. Back soon, off to rewrite some session classes :)

  16. #16
    SitePoint Zealot
    Join Date
    May 2003
    Location
    Midwest
    Posts
    100
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No mention by the article or anyone else about the location of there config file..

    If at all possible ALWAYS put your config files outside of your web path. This reduces the risk of exposure due to things like a bad php upgrade.
    Cyberlot Technologies Group
    FlashUnity - PHP Based Flash communications server


  17. #17
    SitePoint Member
    Join Date
    Dec 2002
    Posts
    15
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It look as though a lot of these tips can transfer to other programming languages as well. Helpful.

  18. #18
    SitePoint Guru LinhGB's Avatar
    Join Date
    Apr 2004
    Location
    Melbourne, Australia
    Posts
    902
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here we go again... addslashes()

    SELECT * FROM users WHERE name='$username' AND pass='$password';

    However, if the user who's logging in is devious, he may enter the following as his password:

    ' OR '1'='1

    This results in the query being sent to the database as:

    SELECT * FROM users WHERE name='known_user' AND pass='' OR '1'='1';

    <snip>

    if (magic_quotes_gpc()){
    $username = $_GET["username"];
    } else {
    $username = addslashes($_GET["username"]);
    }
    Not everyone quotes integer. So here's a version that'll break your addslashes:

    Code:
    SELECT * FROM users WHERE name='$username' AND pass='$password';
    
    $password = blah' OR 1=1 OR 'blah' = 'blah
    It still amazes me how many people get SQL injection wrong.

    Solution to this: firstly always have a list of accepted formats for your inputs, and reject whatever doesn't match one of those. Secondly, use a query builder or prepared query, like what PEAR-DB or ADODB support. 1=1 will not work if you use prepared queries.

    Some more:

    Configuring PHP For Security ->

    open_basedir - should set this in your vhost:

    Code:
    <Directory /path/to/website>
         php_admin_value open_basedir "/path/to/website:/tmp"
    </Directory>
    Having modsecurity installed will also catch most of the stuff you mentioned in the article.
    "I disapprove of what I say,
    but I will defend to the death my right to say it."

  19. #19
    Zach
    SitePoint Community Guest
    I think that email header injection attacks are fairly common.

    $header = "From: $email";
    mail( $to, $subject, $body, $header );

    You had better make sure $email is a valid address.

  20. #20
    SitePoint Enthusiast webinista's Avatar
    Join Date
    Oct 2002
    Location
    Stankonia
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    according to the security section of the PHP, you should code without magic quotes, and instead properly escape your data.

    re. XSS: be aware that some browsers will execute javascript with an incomplete end tag (&lt;/script), or without a type attribute. try using preg_replace to address such problems.


  21. #21
    SitePoint Enthusiast
    Join Date
    Dec 2002
    Location
    Dewsbury, UK
    Posts
    79
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very interesting read, thanks for all the tips.

    Oh yeah, this article is dugg at the mo ;-)

  22. #22
    SitePoint Zealot
    Join Date
    Aug 2005
    Posts
    123
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Magic quotes will almost assuredly be removed from PHP6.

    Here's the developers notes from a meeting about PHP6.

    http://www.php.net/~derick/meeting-n...l#magic-quotes

    Not every server will have magic quotes enabled anyways, so no matter what you have to check all the incoming data.

  23. #23
    SitePoint Enthusiast webinista's Avatar
    Join Date
    Oct 2002
    Location
    Stankonia
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    and of course i hath stated the obvious after everyone has already pointed out the wrong bits :-).


  24. #24
    SitePoint Enthusiast
    Join Date
    Jun 2004
    Location
    Williamsport, PA
    Posts
    87
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Speaking of phpinfo(), I got curious about a week ago and did a Google search for "phpinfo.php"... go ahead, try it, and witness the hundreds of thousands of developers leaving their configuration information wide-open to the world.

    I'm not giving the exact website, but a University had a phpinfo file and I used that to find out the register_globals was turned on. That university also had a test login page for their MySQL server set up (and available on google). I plugged in ?user=root&password= (default username/password for MySQL) on the end of the URL and, just like that, I had root access to their database. Silly rabbits...

  25. #25
    SitePoint Guru OfficeOfTheLaw's Avatar
    Join Date
    Apr 2004
    Location
    Quincy
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One issue I have seen is also of note is formmail scripts (not matt's, but any type of email that uses user provided input) that don't properly validate fields being used. For example, here's a common flaw I have seen:

    PHP Code:
    $messgae $_POST['message'];
    $headers $_POST['from'];
    mail('foobar@example.com''Contact Form Submission'$message$headers); 
    A malicous user or bot could insert \n\r (or is it \r\n?) to add an additional To header to send out spam, which will overide the first parameter sent to mail.

    The solution is to stripout newlines, don't use their email address in such a way, or use a library (e.g. PEAR::Mail_Mime, PEAR::Mail) to do it for you.


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
  •