Slashdot Mirror


PHP and SQL Security

An anonymous reader writes "PHP and SQL Security are being proven more weak every day. Uberhacker.Com is running a PHP and SQL security research project to raise awareness of secure scripting. The site hosts guides to secure PHP programming, forums, and scripting challenges to see who can create the most secure scripts."

7 of 305 comments (clear)

  1. Guides to Secure Programming? by JumboMessiah · · Score: 5, Informative

    Other than the scripting challenge, what's on this site? I've read the guides to hacking, but it's all a bunch of kindergarden material. Seems if you follow the guides you'll certainly have insecure PHP scripts with all kinds of SQL injection. How about posting some real articles on secure PHP scripting...

    1. Re:Guides to Secure Programming? by shiflett · · Score: 4, Informative

      I have a few articles on my Web site that might be informative: http://shiflett.org/articles

      I'm also writing a monthly PHP security column in php|architect, and these articles will be available for free six months after publication.

      Lastly, I am writing PHP Security for O'Reilly, which is due out in the fall.

  2. SQL Injection in PHP by uss_valiant · · Score: 5, Informative

    AFAIK SQL injection can be prevented by binding the parameters to the SQL statement and not putting them within SQL.
    An example:
    It's easy to inject some malicious SQL when using the following PHP code:
    mysql_query("INSERT INTO FOO('Bar') VALUES('$some_post_param');");
    But if you prepare the SQL statement with parameters and bind the variable $some_post_param to the statement, it will be secure.
    see mysql manual for mysqli_stmt_bind_param() aka bind_param
    $stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); $stmt->bind_param('sssd', $code, $language, $official, $percent);

    I know this concept from Perl DBI, but in PHP I haven't seen anyone (phpBB, ...) using bind_param. Why is this? Performance? Keeping the code short and simple?

    As for general webserver security: use PHP and perl as cgi, use suEXEC, run the webserver as nobody/www, put the users into chroot jails, but by all means, don't use PHP safe_mode On.

  3. Secure Programming HOWTO by dwheeler · · Score: 4, Informative
    For guidelines on how to develop secure programs, see my Secure Programming for Linux and Unix HOWTO. This Free book provides a set of design and implementation guidelines for writing secure programs for Linux and Unix systems. That includes application programs used as viewers of remote data, web applications (including CGI scripts), network servers, and setuid/setgid programs. The book includes specific guidance for a number of languages, including C, C++, Java, Perl, Python, PHP, and Ada95.

    --
    - David A. Wheeler (see my Secure Programming HOWTO)
  4. Re:No. by Anonymous Coward · · Score: 4, Informative
    I regard myself as a fairly competent PHP programmer, and while I wouldn't be surprised if there are security holes in some of the stuff I've written, I've made every effort to stop them from happening.

    I've got a couple of rules I try to abide by - can anyone confirm if they're good programming practice? If they are, then they might prove useful to other people. :-)
    • Always check user input as much as is possible. Probably at least two-thirds of my programming is input data verification.
    • Always escape text which is going into an SQL query, or do an (integer )$number if it's supposed to be an integer. Do this in a very obvious place (eg when setting the $query string itself) so you don't forget. SQL injections are horrid. Test any functions which generate SQL until you're absolutely sure they aren't doing the wrong thing.
    • Use htmlspecialchars() on any text that's being output, to stop users putting rogue HTML, Javascript or anything into the output - even if it'll only end up in an error message or similar.
    • Put database usernames, passwords, pathnames and other similarly important but site-specific data in a define(), where once set it cannot be redefined.
    • Never include() or require() something that isn't a hard-coded string. Use readfile() or fpassthru() or similar if you need to output an HTML template or whatever.
    • Be hugely careful with any file operations. Don't use any user-supplied filenames, etc, unless they're thoroughly checked.
    • Initialise variables, and forcibly set the type of incoming data with an (integer ), (string ) or whatever.
    • Always use $_GET, $_POST etc to get submitted variables and not register_globals, and put anything that's not dealing with getting such data into a function - page_blah( (integer )$_GET['id'], text_unescape( $_GET['moo'] ) ); and so on, in a place neatly out of the scope of any register_globals crap.
    • Never rely on automatic escaping of input variables - I've got a bunch of functions for automatically unescaping arrays and strings which have been mangled by the magic_quotes_gpc rubbish. I'd switch the feature off, but hosts often have it switched on - and my functions check if it is and respond accordingly.
    • Be paranoid. Always assume the user is out to get you. If there's a function which does something restricted but is called by an apparently safe function, double-check the user's credentials.
  5. Re:No. by Lumpy · · Score: 4, Informative

    not only purification but treat all incoming data as hostile.

    every thing that comes from the user needs to be scrubbed, bleached, hammered and then finally used when you know it is 100% safe. and it must be used in a safe manner.

    what blows my mind is those that use the DB column name in a webform to be passed.. Oh nice. select from that drop down item_number and simply change it to start playing corrupt the database games.

    Nothing that is ever given to the user, or recieved from the user should be trusted... EVER. that is the first rule and needs to be pounded into everyone in every book about any programming language for the first 5 chapters.

    start there and you will heve very little security issues.

    --
    Do not look at laser with remaining good eye.
  6. Re:No. by mfh · · Score: 5, Informative
    > Always check user input as much as is possible. Probably at least two-thirds of my programming is input data verification.

    Good. You are off to the right start, but with better function programming, you will find yourself writing more feature code than purification code.

    Things to look for:
    • Push 99% of all expected/selectable data into tables with a record_id, so you can easily purify the incoming data:

      function npurify(&$text){
      if(!is_numeric($text)) $text = 1;
      }

      Protects against SELECT SQL injection attacks.

    • Snuff out > and < chars so that they can't contain the Script HTML tag when purifying data. Replacing these characters with their html entities usually works; ie:
      > becomes &gt;
      < becomes &lt;
    • Convert data in your database to base_64 and gzdeflate it:
      $data = base64_encode(gzdeflate($data));
      This will prevent the problems with escaping quotes and apostrophes for SQL, and it will kill any SQL injections in your data.
    • Use better logic for testing incoming data;
      if($this) {perform action}... will limit your chances of having to cope with scipt injections because you are only testing for the existence of a condition, and not the value of the data.
    • Run bitchecking against acceptable alphabets for purification of character values. Gauge to have good CPU usage of this sort of thing.

      // blanks out unaccepted characters
      $alphabet = '`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz01234567890~!@#$%^&*()_+=-,.<>?/|;:\'"'.chr(92 ).chr(10);
      $sizestr = strlen($text);
      $sizestr--;
      for($i = 0; $i <= $sizestr; $i++) {
      if(strstr($alphabet, $text[$i])) {
      continue;
      }else{
      $text[$i] = ' ';
      }
      }

    • Code a good link converter, so you don't have to accept HTML in posts, and you don't need to accept any HTML.
    • There are likely more, but these are the big ones.

    > Always escape text which is going into an SQL query

    I prefer to write my own SQL text, based on input values. That way you are never using data submitted for the SQL query. The only time they would really submit values would be when they are sending in a username and password, but in that case, you should be extremely stringent in purification by only accepting alphanumeric usernames and passwords (ie: run the alphabet function above, but erase all non-alphanumeric chars from the $ALPHABET var).

    > Use htmlspecialchars() on any text that's being output, to stop users putting rogue HTML

    htmlspecialchars() doesn't always work. I prefer using the example above, by limiting the characters allowed and disallowing HTML in the form of post body/subject data. Converting everything to base64 will make it nearly impossible to script attack the database, too.

    > Put database usernames, passwords, pathnames and other similarly important but site-specific data in a define()

    I disagree, because I use the $_SESSION array instead, which can not be changed by a user if the session cookie is server-side. Sessions can be scooped by sniffers, but that can be managed by your host's security, to prevent it. Certainly change the locale for session data from /tmp/, because that narrows down hack attempts, making it all the more harder to compromise the system.

    > Never include() or require() something that isn't a hard-coded string

    To me, this isn't totally required if you have suitable purification, but that extra bit of paranoia is welcomed, because it shows true fear and that is acceptable in any kind of programming. That sort of humility is welcomed because it demonstrates a compassion for the task at hand.

    > Be hugely care

    --
    The dangers of knowledge trigger emotional distress in human beings.