Archive for the ‘Security’ Category

How to Fix: PHPMyAdmin 403 Forbidden Error

By Automater on April 20th, 2010

If you have installed phpMyAdmin in your linux server (centos/RHEL/debian), and tried to access phpMyAdmin in most cases you will get this 403 forbidden error. I have seen this issue very often if you are installing phpmyadmin using yum or by apt-get. By default phpmyadmin installed path is /usr/share/phpmyadmin and the apache configuration file is located in /etc/httpd/conf.d/phpmyadmin.conf.

Forbidden

You don’t have permission to access /phpmyadmin/ on this server.

To fix:

nano /etc/httpd/conf.d/phpmyadmin.conf

Remove or comment the first two lines in bold.

#Order Allow,Deny

#Deny from all

Allow from 127.0.0.1

Restart the apache server.

service httpd restart

Once this is done, you should be able to see phpmyadmin working by pointing your browser to http://ipaddress/phpmyadmin

This method worked for me and leave a comment here if there is an issue.

PHP security checklist

By Automater on April 11th, 2010

An interesting read I found while browsing reddit. This is not my content however this is very useful for others.

  • Basic:
    • Make sure your passwords aren’t obvious or easy to guess.
    • Be sure that your “password recovery questions” are not too obvious.
    • If you write down your password, ensure you have thought about physical security.
    • Make sure that register_globals is disabled, because that allows arbitrary variables to be injected into your script’s environment (!).
  • Incoming data:
    • Be aware that a request can be generated from something as simple as telnet, so that means that all incoming data is suspect.
    • $_GET, $_POST, $_COOKIE, and $_REQUEST can all contain any value, so remember to filter and validate data.
    • Some variables in $_SERVER and $_ENV come from the web server, while others come from the client.
      • $_SERVER['PHP_SELF'] is not entirely safe, as URLs can be, depending on your configuration, cleverly constructed to contain arbitrary data and yet still work.
    • Incoming data can contain control characters such as null. Null happens to be the string terminator character in C/C++, so you can imagine what could happen when passing a PHP string to another program.
    • Check the length of inputted data to make sure it is not too long.
    • Before outputting data to the browser, make sure to properly escape it to prevent cross-site scripting.
      • If you are allowing the user to use a subset of HTML, it is important that you use a very complete HTML sanitizer (HTML Purifier is recommended).
        • There are many many ways to achieve the same result in HTML, so don’t try to do HTML sanitizing yourself (seriously, just forget it).
      • If CSS is allowed, then be aware that it could be used maliciously if you allow properties such as “position” to be changed (elements overlaying login forms, etcetera).
        • CSS can also contain escape sequences both inside and outside strings (\34).
      • Be aware that many browsers pre-fill password input boxes on page load if the user has saved the password in the browser’s password manager.
      • Check to make sure that any user-supplied URLs are valid and safe.
        • This applies to URLs in embedded resources (such as images) as well.
      • Included Java applets, Flash movies, or other plugin content may be able to access the page by means of JavaScript code execution or otherwise, depending on the way that the content was embedded into the page. This can include navigating to a javascript: URL.
      • If you allow users to embed arbitrary plugin files (i.e. Flash movies), make sure you embed it in a way where a different plugin cannot be loaded (based on file type).
    • Use a “safe” encoding for your page (such as ISO-8859-1) or otherwise verify that the content of inputted data to see if it valid (including if you use UTF-8). This is because certain invalid character sequences can cause the next character(like < (!)) to be ignored in some encodings.
      • Specify the encoding in an HTTP header and not in the HTML.
    • Be aware that some character sets (namely Unicode) have “invisible” characters, characters that look alike, or different ways of combining characters (for diacritics, namely).
      • Some character sets also contain layout control characters (namely Unicode), which could be used to modify the layout of the page slightly.
    • Be aware that CSS files can contain JavaScript.
    • Make sure to validate email addresses (you should validate everything anyway), because it is possible to inject email headers by crafting a specially constructed email address.
      • Email address validation is fairly complicated. “John Doe”@example.com is actually a valid email address (quotation marks and space included). Many programs are not aware of this and the syntax is too cumbersome, so you do not actually see radical email addresses in the real world. Often you can use a fairly simple email address regular expression to match the real use cases of email addresses, but many regular expressions you find on the Internet are not very inclusive (often blocking legitimate Gmail addresses that contain a plus sign in the address). regular-expressions.info has a good email validation regex. For comparison, check out the regex that fully supports RFC822.
  • Including and serving files:
    • Never use user input directly in a pathname. It is best to employ a whitelist, as opposed to a blacklist.
      • Check for directory traversal (both downwards and upwards, including “..”).
      • Check for null poison bytes.
      • Be aware of the “:” character, which is used on NTFS and Windows to access Alternate Data Streams.
      • Be aware of PHP streams, which allows you (and attackers) to access non-file-based resources with URIs like http://example.com/badcode.txt.
        • Check to make sure that attackers can’t include a remote file containing PHP code.
    • You should not be merely hiding files in a web-accessible directory because people may guess URLs.
      • This applies to hiding things based on the content of a GET or POST variable. Actually verifying the identity of the user and his or her authorization level is a much better approach.
    • When you need to get a remote file, do not use include(), as that will also execute any PHP code on the page. Use something such as file_get_contents().
  • Database:
    • When inserting inputted data into an SQL query, escape the data or use prepared statements. The issue at hand is an SQL injection.
      • Do not use addslashes() to escape data; use the function for your particular DBMS to escape data, because different databases escape differently.
    • Lock down access permissions so that your PHP scripts do not have access to more of the database than it needs.
    • Be aware that your DBMS may allow remote connections (by default), so disable that feature as necessary.
  • Uploaded files:
    • Be aware that the filename provided by the user in the $_FILES array can be anything.
      • The provided mime type can be spoofed or be otherwise wrong as well.
    • Make sure that uploaded files are what you want in terms of file type by analyzing the contents of the file.
      • A simple file type check script can be easily fooled by putting the minimum necessary parts of the file format to pass that check. For example, you could take the first 20 bytes of a PNG file and then append the contents of badvirus.vbs to the end, giving you a file that would easily pass through many filters.
      • Be aware that some formats can contain arbitrary data and still be valid (think “comment fields” in some file types).
    • Uploaded files may be or contain viruses. You can scan for viruses if you wish, although it does use up (possibly expensive) resources to do so.
    • Don’t move uploaded files to web-accessible directories, as your web server may parse some files as executable code (i.e. an uploaded .php file). It also hampers your ability to restrict access to the files (as noted before about hiding files).
    • Do extensive path checks to make sure you do not serve a non-uploaded file.
    • Serve all uploaded files as an attachment and never inline (it’s a HTTP header called “Content-Disposition”). This is because Internet Explorer will override the content type you tell it and guess on its own. PNG image? No! Internet Explorer says it’s a HTML file with JavaScript code.
      • Send the “X-Content-Type-Options: nosniff” header. This only alleviates the problem for IE8 and above, but IE7 and below would still have the issue (so you still need to send files as attachments).
    • Don’t execute/serve uploaded files with include(). This executes PHP code, as previously mentioned.
    • Be aware that uploaded HTML files can contain malicious JavaScript.
    • Try to not serve files with content types of “application/octet-stream,” “application/unknown,” or “plain/text”. This may invoke content type guessing, although if you send files as attachments, it should not be an issue. To be fair, I am updating this post right now and I don’t entirely remember why I put this point, but I assume that it’s for what I just said.
  • Authentication and authorization:
    • Install a bad password throttling system to prevent brute force attacks.
      • You should consider throwing up a CAPTCHA test before outright denying any further login attempts. Do that not for security reasons, but rather to make it less annoying for your more forgetful users.
    • Be aware that a malicious user can sniff for packets to get a user’s password. The only solution to this problem is to use SSL for the most part. It is possible to setup your own challenge and response system, but it won’t protect users if they are also susceptible to a man-in-the-middle attack (an attacker’s computer secretly sits between your website and the user, able to modify the data as it passes through).
    • Don’t store a user’s password in a cookie when logging in, for obvious reasons.
  • Sessions and cookies:
    • Use only cookies for sessions, to prevent session fixation and session hijacking attacks. If you are using the PHP sessions, there is a PHP setting named session.use_only_cookies that determines this behavior.
      • If you are writing your own session handling system, never accept a session identifier that you didn’t generate, and make it difficult to inject a custom session identifier (i.e. taking session IDs from a GET parameter).
    • After a session is complete (”logout”), destroy its data and don’t just clear the cookie (a malicious user could otherwise just re-instate the cookie and use the session again).
    • When changing a user’s authorization level (i.e. from guest to a logged in user), destroy the old session and create a new session to make session fixation harder. This is because if the attacker has access to the session (for some reason), the old session will now become useless rather than get extra privileges.
    • Even if you are not in a shared hosting environment, if you use the same directory to store session files for two or more of your sites, then a session created on one website will be a valid session on another.
  • Remote websites / content not under your control:
    • Be aware that other sites can conduct cross-site request forgeries, and pass off as a logged in user (both GET and POST requests can be forged).
      • Don’t rely on referrers to protect against CSRFs, because many Internet security programs block the referrer field or give it some dubious value (like “—”).
      • Use tokens/keys with your forms to prevent CSRFs.
      • Note that content that you host (like a link in a user’s profile) can also be used against you. Example: An avatar URL that loads your logout page. Use tokens for important pages.
      • Using POST for pages that perform actions helps mitigate the issue, although it is still possible to submit a POST request from a form automatically.
    • Be aware that, while other websites cannot just read content off your pages, some files can be read remotely (such as .js files) by their nature (including them via SCRIPT tags, etcetera).
      • Files that look like JavaScript files could possibly be read remotely.
    • Older versions (and possibly current) of ActionScript could play media files remotely and bypass referrer checks, because Flash Player did not send a referrer.
    • Be aware that information could be probed using inclusion of a file on your server on a remote site.
      • Be aware that the existence of a file could be detected using the “onerror” event of an image element.
      • Pages that conditionally take a longer time to load could be detected on a remote website.
        • Cached files will take a shorter time to load.
      • The dimensions of images on you server can be detected on a remote website.
      • CSS files can be included remotely, and although not read, if the CSS files are conditional, information could be garnered from how the attack site is changed with the inclusion of the CSS file. Rather than including a CSS file, an attacker could attempt to include an HTML file directly as well, because the CSS parsers in web browsers are fairly lax and will try their best.
      • Some browsers allow a remote site to detect the frames within another site.
      • Some browsers may throw a different error if you attempt to delete a non-existent variable in a frame contain a remote website than if you were to delete an existing variable.
      • It is possible to detect whether a user has visited a URL by checking how the browser has styled the link (visited vs. unvisited styles).
    • Be aware that Internet Explorer allows a remote website to include another website in an inline frame but disable JavaScript and cookies to function inside the inline frame. This breaks frame break-out attempts.
  • Client-side issues:
    • Be aware that IE6 allows header spoofing with XMLHttpRequest, including the spoofing of Host and Referer. IE6 does not allow cross-domain requests though.
    • Install frame busting code and send the X-Frame-Options header to protect against UI redressing/clickjacking. Frame bursting code won’t work in IE if the attacker’s website disabled JavaScript in an inline frame (see above), but that’s what the header is for. Older versions of IE are still left vulnerable.
  • Miscellaneous:
    • Hash stored passwords to make it harder for an attacker who has gained access to get the raw password of users.
      • Use salts to make rainbow tables ineffective. It is highly recommended that you use a different salt per user to make intrusion more difficult (you will have to store the individual salts). Salts should be sufficiently long and complex to be strong.
    • Pages that conduct long or resource intensive operations should be throttled, so that performing a denial-of-service attack against you isn’t as simple as leaving 10 browser windows on auto-refresh.
    • Check to make sure that pages that access remote resources cannot be used to launch harder-to-trace denial of service attacks against these remote resources by using your site as a proxy.
    • Be aware that something could go wrong, and your PHP files may suddenly be exposed (it has happened to big name sites, such as Facebook and others). Take precautions to prevent this.
    • Don’t put configuration files in a web accessible directory, especially if their content can be read via the browser.
    • If you need to protect files (for example, against a login), put the files into a non-web-accessible directory and route all files through a PHP script. (This has been touched on previously.)
    • Internet Explorer has an XSS filter that could possibly be exploited to prevent a piece of code in a page to be executed by passing that piece of code as a query parameter in the URL.
    • If you are using random numbers for security, be aware that you need to be using a cryptographically secure random number generator otherwise it is possible to guess the pattern of random numbers (remember that computers use psuedo random number generators).
  • Shared host security:
    • Be aware that on many shared hosts, users can access the files of other users. It may not be doable via PHP, but it may be doable via PHP via CGI (or Perl, etc. via CGI).
      • In shared hosts where security is slightly better, you should chmod your files so that users of other groups cannot access your files.
      • Someone noted that I glossed over this issue. Okay, read that again: users can access the files of other users. That should be a major worry, and the best part is that most PHP shared web hosts don’t secure their servers against this. You should verify that the web host that you are working with has properly secured their environment, and if it hasn’t, you should move.
    • Be aware that other users on the same server may have the same IP address as your website or can access your website from 127.0.0.1.
    • Be aware that other users on the same server may be able to run a server on the same IP as your website but on a different port.
    • Be aware that other users are “not” remote as far as your database may be concerned.
    • Be aware that another user on the same server may be able to create a false session for use on your own site (because in many configurations, all session temporary files are stored in the same directory for all users).
      • Consequently, that means that other users may also be able to read your session data.
      • A session created on one site can be used on another as well.
    • File uploads on one site might be accessible on another site because sites often share a single world-readable /tmp directory.
Posted in