Security

By ukmodak | March 31st 2024 10:36:23 AM | viewed 228 times
  1. Cross site scripting (XSS)
  2. Injections
    1. SQL injection
    2. Directory traversal (path injection)
    3. Command injection
    4. Code injection
  3. Cross site request forgery (XSRF/CSRF)
  4. Public files
  5. Passwords
  6. Uploading files
  7. Session hijacking
  8. Remote file inclusion
  9. PHP configuration
    1. Error reporting
    2. Exposing PHP Version
    3. Remote files
    4. open_basedir
    5. Session settings
  10. Use HTTPS
  11. Things not listed

Cross site scripting (XSS)

XSS attacks happen when client-side code (usually JavaScript) gets injected into the output of your PHP script. This can be through the URL, but can also occur via a stored technique such as the database.

// GET data is sent through URL: http://example.com/search.php?search=<script>alert('test')</script>
$search = $_GET['search'] ?? null;
echo 'Search results for '.$search;

// This can be solved with htmlspecialchars
$search = htmlspecialchars($search, ENT_QUOTES, 'UTF-8');
echo 'Search results for '.$search;

ENT_QUOTES is used to escape single and double quotes beside HTML entities

Injections

SQL injection

When accessing databases from your application, SQL injection attack can happen by injecting malicious SQL parts into your existing SQL statement.

SQL injection is a code injection technique that might destroy your database.

SQL injection is one of the most common web hacking techniques.

SQL injection is the placement of malicious code in SQL statements, via web page input.

SQL in Web Pages

SQL injection usually occurs when you ask a user for input, like their username/userid, and instead of a name/id, the user gives you an SQL statement that you will unknowingly run on your database.

Look at the following example which creates a SELECT statement by adding a variable (txtUserId) to a select string. The variable is fetched from user input (getRequestString):


    // Based on 1=1 
txtUserId = getRequestString("UserId"); 
txtUserId = 105
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
SELECT * FROM Users WHERE UserId = 105;

// hack as:

txtUserId = 105 OR 1=1
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
SELECT * FROM Users WHERE UserId = 105 OR 1=1;



    // Based on ""=""
uName = getRequestString("username");  // John Doe
uPass = getRequestString("userpassword");  // myPass

sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass + '"'
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass" 

// hack as:

uName = getRequestString("username");  // " or ""="
uPass = getRequestString("userpassword");  // " or ""="

sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass + '"'
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""="" 



    // Based on Batched SQL Statements 
	
txtUserId = getRequestString("UserId");  // 105
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
SELECT * FROM Users WHERE UserId = 105

// hack as:

txtUserId = getRequestString("UserId");  // 105; DROP TABLE Suppliers
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers


Use SQL Parameters for Protection

To protect a web site from SQL injection, you can use SQL parameters.

SQL parameters are values that are added to an SQL query at execution time, in a controlled manner.

$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City) VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();

Directory traversal (path injection)

Directory traversal attacks, also known as ../ (dot, dot, slash) attacks, happen when users supply filenames as input that can traverse to parent directories. Data can be set as index.php?page=../secret, or /var/www/secret, or something more catastrophic:

$page = $_GET['page'] ?? 'home';

require $page;
// or something like this
echo file_get_contents('../pages/'.$page.'.php');

In such cases you must check if there are attempts to access the parent or some remote folder:

// Checking if the string contains parent directory
if (strstr($_GET['page'], '../') !== false) {
throw new \Exception("Directory traversal attempt!");
}

// Checking remote file inclusions
if (strstr($_GET['page'], 'file://') !== false) {
throw new \Exception("Remote file inclusion attempt!");
}

// Using whitelists of pages that are allowed to be included in the first place
$allowed = ['home', 'blog', 'gallery', 'catalog'];
$page = (in_array($page, $allowed)) ? $page : 'home';
echo file_get_contents('../pages/'.$page.'.php');


Command injection

Be careful when dealing with commands executing functions and data you don’t trust.

exec('rm -rf '.$GET['path']);

Code injection

Code injection happens when malicious code can be injected via the eval() function, so remember to always sanitize your data when using it:

eval('include '.$_GET['path']);

Cross site request forgery (XSRF/CSRF)

Cross site request forgery, one click attacks, or session riding is an exploit whereby users execute unwanted actions on web applications.

CSRF attacks can be performed over GET or POST requests.

Including a random token with each request. This is a unique string that is generated for each session. We generate the token and then include it in every form as a hidden input. The system then checks if the form is valid by comparing the token with the one stored in the user's session variable. An attacker will be unable to generate a request without knowing the token value.

Using a random name for each form field. The value of the random name for each field is stored in a session variable. After the form has been submitted, the system generates a new random value. To be successful, an attacker would have to guess these random form names.

use token to prevent csrf 

Public files

Configure your web server to serve files from the public folder instead of from your application root folder. The public folder contains the front controller (index.php). In case of a web server misconfiguration resulting in PHP files failing to be served properly, the source code of index.php will be visible to the public.

Passwords

When working with users’ passwords, hash them properly with the password_hash() function.

Uploading files

Many security breaches occur when users can upload files onto a server. Make sure you go through all the vulnerabilities associated with uploading files and take appropriate precautions against these vulnerabilities, such as by renaming uploaded files, moving them to publicly inaccessible folders, checking the types of files uploaded and so on. Since there are many issues to check here, more information is also located in the separate FAQ:

Session hijacking

Session hijacking is an attack where an attacker steals the session ID of a user. The session ID is sent to the server where the associated $_SESSION array is populated. Session hijacking is possible through an XSS attack or when someone gains access to the folder on a server where the session data is stored.

To defend against Session Hijacking attacks you need to check the current user’s browser and location information against information stored about the session. Below is an example implementation that can help mitigate the effects of a session hijacking attack. It checks the IP Address, User Agent, and if the Session Expired removing a session before it’s resumed.

session_start();

// Does IP Address match?
if ($_SERVER['REMOTE_ADDR'] != $_SESSION['ipaddress'])
{
session_unset();
session_destroy();
}

// Does user agent match?
if ($_SERVER['HTTP_USER_AGENT'] != $_SESSION['useragent'])
{
  session_unset();
  session_destroy();
}

// Is the last access over an hour ago?
if (time() > ($_SESSION['lastaccess'] + 3600))
{
  session_unset();
  session_destroy();
}
else
{
  $_SESSION['lastaccess'] = time();
}

Remote file inclusion

An RFI (remote file inclusion) attack is when an attacker can include custom scripts:

$page = $_GET['page'] ?? 'home'
require $page . '.php';

In the above code, $_GET can be set to a remote file http://yourdomain.tld/index.php?page=http://example.com/evilscript. Make sure you disable this in your php.ini unless you know what you’re doing:

; Disable including remote files
allow_url_fopen = off
; Disable opening remote files for include(), require() and include_once() functions.
; If above allow_url_fopen is disabled, allow_url_include is also disabled.
allow_url_include = off

PHP configuration

Always keep the installed PHP version updated. You can use versionscan to check for possible vulnerabilities of your PHP version. Update open source libraries and applications, and keep your web server well maintained.

Here are some of the important settings from php.ini that you should check out. You can also use iniscan to scan your php.ini files for best security practices.

Error reporting

In your production environment, you must always turn off displaying errors to the screen. If errors occur in your application and they are visible to the outside world, an attacker could get valuable data for attacking your application. display_errors and log_errors directives in the php.ini file:

; Disable displaying errors to screen
display_errors = off
; Enable writing errors to server logs
log_errors = on
Exposing PHP version

PHP version is visible in HTML headers. You might want to consider hiding your PHP version by turning off the expose_php directive, preventing the web server from sending back the X-Powered-By header:

expose_php = off
Remote files

In most cases, it’s important to disable access to remote files:

; disabled opening remote files for fopen, fsockopen, file_get_contents and similar functions
allow_url_fopen =  0
; disabled including remote files for require, include ans similar functions
allow_url_include = 0
open_basedir

This settings defines one or more directories (subdirectories included) where PHP has access to read and write files. This includes file handling (fopen, file_get_contents) and also including files (include, require):

open_basedir = "/var/www/test/uploads"
Session settings

PHP is by default configured to store session data on the server and a tracking cookie on client-side (usually called PHPSESSID) with unique ID for the session.

; in most cases you'll want to enable cookies for storing session
session.use_cookies = 1
; disabled changing session id through PHPSESSID parameter (e.g foo.php?PHPSESSID=)
session.use_only_cookies = 1
session.use_trans_sid = 0
; rejects any session ID from user that doesn't match current one and creates new one
session.use_strict_mode = 1

If the attacker somehow manages to inject JavaScript code for stealing a user’s current cookies (the document.cookie string), the HttpOnly cookie you’ve set won’t show up in the list.

session.cookie_httponly = 1

This sets the domain for which cookies apply. For wildcard domains you can use .example.com, or set this to the domain where it should be applied. By default, it isn’t enabled, so it’s highly recommended for you to enable it:

session.cookie_domain = example.com

For HTTPS sites, this accepts only cookies sent over HTTPS. If you’re still not using HTTPS, you should consider it.

session.cookie_secure = 1

Use HTTPS

HTTPS is a protocol for securely communication over networks. It’s highly recommended that you enable it on all sites. Read more about HTTPS in the dedicated FAQ: How to install an SSL certificate and enable HTTPS.

We need to enable SSL for this domain and let XAMPP know where we store the SSL Cert. So we need to edit C:\xampp\apache\conf\extra\httpd-xampp.conf

    ## site.test
     
         DocumentRoot "C:/xampp/htdocs"
         ServerName site.test
         ServerAlias *.site.test
     
     
         DocumentRoot "C:/xampp/htdocs"
         ServerName site.test
         ServerAlias *.site.test
         SSLEngine on
         SSLCertificateFile "crt/site.test/server.crt"
         SSLCertificateKeyFile "crt/site.test/server.key"
     

Add following code in .htaccess file

#Force www:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^qriusbd.com [NC]
RewriteRule ^(.*)$ https://www.qriusbd.com/$1 [L,R=301,NC]

After that, you will need to restart Apache in XAMPP. It’s very simple, simply open XAMPP Control Panel and Stop and re-Start Apache Module.

bONEandALL
Visitor

Total : 20974

Today :28

Today Visit Country :

  • Germany
  • United States
  • Singapore
  • China
  • United Kingdom
  • South Korea
  • Czechia