Skip to main content

PHP Security Tips

Today PHP emerged as one of the leading programming languages used in web development. It had increased the responsibility of PHP programmers to save web pages from security threats. Some holes in programming can damage the whole website. Sometimes programmers, in most cases beginners, are not aware of these security holes. In this tutorial we are going to discuss where could be the problem and we would be able to fix them.

1) Global Variables (regiser_globals):

You should do your best to write your scripts so that they do not require register_globals to be on.  Using variables as globals can easily lead
to possible security problems.  For example

<?php
// define $authorized = true only if user is authenticated
if (authenticated_user()) {
    
$authorized true;
}

// Because we didn't first initialize $authorized as false, this might be
// defined through register_globals, like from GET auth.php?authorized=1
// So, anyone can be seen as authenticated!

if ($authorized) {
    include 
"/highly/sensitive/data.php";
}
?>

When register_globals = on, our logic above may be compromised. When off, $authorized can't be set via request so it'll be fine, although it really is generally a good programming practice to initialize variables first. For example, in our example above we might have first done $authorized = false. Doing this first means our above code would work with register_globals on or off as users by default would be unauthorized.

With register_globals turned off, this type of forced entry isn’t possible. The good news is that PHP 4.2.0 has register_globals turned off as its default setting, and PHP 6.0.0 has actually removed the feature. In terms of PHP security it’s a crucial step in the right direction. register_global can turned on or off from php.ini file.

So instead of relying on register_globals, you should instead go through PHP Predefined Variables, such as $_REQUEST. To further tighten security, you should also specify by using: $_ENV, $_GET, $_POST, $_COOKIE, or $_SERVER instead using the more general $_REQUEST.

2) Error Reporting :

Error reporting is a great tool for diagnosing bugs and allowing you to fix them quicker and easier, but it also poses a potential security threat. The problem occurs when the error is visible to others on-screen, because it reveals possible security holes in your source code that a hacker can easily take advantage of. If display_errors is not turned off, or have a value of “0”, the output will appear on the end user’s browser – Not good for security! You do, however, want to set log_errors to on, and then indicate the exact location of the log with error_log.

            So what should you do when you have launched your new killer app? Bugs might still appear and you need the before-mentioned information in order to fix them. What you can do, and should do, is write the errors into a log file. Actually, PHP does insert all errors into a log file on the server by default. However, if you are on shared hosting then you will most likely not have access to that file and it will therefore be necessary to write it into your own file. There are a couple of php.ini directives that are relevant to our problem:
  • display_errors this directive controls whether PHP errors should be sent to the screen. In a production environment this should always be turned off.
  • error_reporting this directive controls which errors that should be reported. You should set this to E_ALL and you should fix all issues that appear by doing this.
  • log_errors this controls whether errors should be logged to a file. I would recommend that you always turn this on.
  • error_log this is the path of the file errors should be written to. This is only applies if log_errors is turned on obviously.
 
3) SQL Injections :

These days sql injections are one of the common threats to security. In this case of vulnerability user(hacker) provide input in such a ways that it is embedded to the query and produce undesired results. In serious cases it may empty your database tables or even drop them.
With the sql injections, all you really have to do is to filter all user input through a function specially designed for this purpose. There is a special feature in php called ”magic quotes”. Magic Quotes automatically perfom an addslashes opration to the GET, POST and COOKIE values. But this is not the full proof solution to the SQL Injection. Moreover, it is deprecated from PHP 5.3.0. and will be removed from PHP 6.0. Let’s have an example:

PHP Code:
<?php
           include(”dbconnect.php”);
          
$id $_GET['id'];
          
$result mysql_query(”SELECT FROM `newsWHERE `id`='{$id}');  
           while(
$row mysql_fetch_assoc($result)) {
                 
print_r($row);
           }
?>
 
This code is vulnerable as it doesn't filter user input and simply inserts whatever the id variable contains into the query. You have two options when you're about to safen up this code. Either use addslashes() or use mysql_real_escape_string(). I would suggest the latter unless you don't use mysql as database server. Both because it filters more characters and because it's binary-safe. The code looks like this when we've added a filter:
PHP Code:
<?php
include(”dbconnect.php”);
$id mysql_real_escape_string($_GET['id']);
$result mysql_query(”SELECT FROM `newsWHERE `id`='{$id}');
while(
$row mysql_fetch_assoc($result)) {
    
print_r($row);
}
?>

4) Cross Site Scripting (XSS attacks)

Hackers can gather an important information from your site by using malicious html or javascript. They can redirect your web page to another one. Think about your site is having a login page and it’s been redirected to another login page looks similar to yours’ one. In this way hackers can get the login details of your website users. Now you can imagine how harmful it could be for you and your website users.

The best way to defend against XSS is to disable JavaScript and images while surfing the web, but we all know that’s nearly impossible with so many websites using JavaScript’s rich application environment these days.  Other method is to put filters on user input. You can use htmlentities() and htmlspecialchars() functions for that. While htmlentities() will simply convert characters which have a meaning in HTML to their corresponding entities, htmlspecialchars() will convert all special characters to HTML entities.

Let’s have an example:

PHP Code:
<?php
include(”dbconnect.php”);
$str = "<a href='test'>Test</a>”;
$text = htmlspecialchars($str, ENT_QUOTES);
echo $text;
?>

Output:
&lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;


5) Remote File Inclusion

Remote file inclusion attacks (sometimes abbreviated RFI) is a vulnerability many people probably do not know of, but it is a very serious issue that also must be addressed. As the name implies, it is when remote files are included, but what exactly does that? Let us look at an example:

<?php

$page = isset($_GET['page']) ? $_GET['page'] : 'home';
require $page . '.php';

?>

This is a very basic front controller that will forward the request to whatever file that should be responsible for that particular request.

Imagine that at http://example.com/malice.php a file exists and our script is located at http://site.com/index.php. The attacker will do this request: http://site.com/index.php?page=http://example.com/malice. This file will get executed when it is included and it will a write a new file to the disk. This file could be a shell which would allow people to execute commands to the terminal from it as well as other things they should not be able to. Another thing the attacker can do is set page to http://example.com/malice.php? (note the ending question mark). That will make whatever follows it part of the query string and therefore ignored by the server the file is getting included from. Why this is a security issue should be pretty obvious. People should definitely not be able to execute whatever commands they want on our server, so how can we prevent them?

There are a couple of php.ini directives you can use to prevent this:
  • allow_url_fopen this directive is set to on by default and it controls whether remote files should be includable.
  • allow_url_include this directive is set to off by default and was introduced in PHP 5.2. It controls whether the include(), require(), include_once() and require_once() should be able to include remote files. In versions below PHP 5.2 this was also controlled by allow_url_fopen. Furthermore, if allow_url_fopen is set to off then this directive will be ignored and set to off as well.
Basically those two directives will enable you to set the required security settings you will need. Again, no data that is not from the inside of your system should be trusted. You must validate user input and ensure that people will not enter malformed or unexpected data.

Thanks!!!!!!!!!!! Enjoy Programming :)
 

Comments

Popular posts from this blog

Odoo/OpenERP: one2one relational field example

one2one relational field is deprecated in OpenERP version>5 but you can achieve the same using many2one relational field. You can achieve it in following two ways : 1) using many2one field in both the objects ( http://tutorialopenerp.wordpress.com/2014/04/23/one2one/ ) 2)  using inheritance by deligation You can easily find the first solution with little search over internet so let's start with 2nd solution. Scenario :  I want to create a one2one relation between two objects of openerp hr.employee and hr.employee.medical.details What I should do  i. Add _inherits section in hr_employee class ii. Add field medical_detail_id in hr_employee class class hr_employee(osv.osv):     _name = 'hr.employee'     _inherits = {' hr.employee.medical.details ': "medical_detail_id"}     _inherit = 'hr.employee'         _columns = {             ...

How to draw Dynamic Line or Timeseries Chart in Java using jfreechart library?

Today we are going to write a code to draw a dynamic timeseries-cum-line chart in java.   The only difference between simple and dynamic chart is that a dynamic event is used to create a new series and update the graph. In out example we are using timer which automatically calls a funtion after every 1/4 th second and graph is updated with random data. Let's try with the code : Note : I had tried my best to provide complete documentation along with code. If at any time anyone have any doubt or question please post in comments section. DynamicLineAndTimeSeriesChart.java import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Timer; import javax.swing.JPanel; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.XYPlot; import...

pyodbc.OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 17 for SQL Server]

Recently, I faced this error in our Docker-Container environment. All the necessary packages were already installed but still, I was facing this clueless error. I search a bit and after an hour and so I found the exact reason and solution for this error. To know more about this error in detail. Please follow this Github thread. https://github.com/mkleehammer/pyodbc/issues/610 https://github.com/mkleehammer/pyodbc/issues/610#issuecomment-587523802 Solution: It's because the   server's certificate has too weak a key. In case you are using Linux env directly/not the Docker one.  Just edited /etc/ssl/openssl.cnf and change these 2 lines. MinProtocol = TLSv1.0 CipherString = DEFAULT@SECLEVEL=1 In case you are also using a container, please add these three lines to your Docker file. RUN chmod +rwx /etc/ssl/openssl.cnf RUN sed -i ' s/TLSv1.2/TLSv1/g ' /etc/ssl/openssl.cnf RUN sed -i ' s/SECLEVEL=2/SECLEVEL=1/g ' /etc/ssl/openssl.cnf Thanks!! Enjoy Programming! Refer...