In this blog, we talk about some of the vulnerabilities found in PHP applications that are generally ignored by the developers. The severity of such vulnerabilities is quite high and may compromise the entire server. Let’s address some of such vulnerabilities.
An SQL Injection (SQLi) attack exploits the injection of SQL commands into SQL queries of a web application. A successful SQLi attack lets malicious user access and manipulate a web application’s back-end database.
In the above image, the malicious user can access the back-end database of the web application with SQL injection. This would allow him to do privilege escalations at the application level. When a SQL server is running under the context of system admin (DBO,SA), a malicious user would be able to own the entire server.
Refer to the below PHP code snippet:
#Insert statement
<html>
<form id="login" method="post" >
<table id="login">
<tr> <td><input type="text" id="company" /></td> </tr>
<tr><td><input type="text" id="address" /></td></tr>
<tr><td><input type="button" id="submit" value="submit" /></td></tr>
</table>
</form>
</html>
<?php
if (isset($_POST['submit']))
{
$company = $_POST['company'];
$address = $_POST[address];
$insert = "Insert into emp(company, address)values(‘$company’,’$address’)";
mysql_query($insert);
}
?>
The above code is vulnerable for persistent cross-site scripting. The script will be executed when details of the company and address are viewed by the user or admin. This would lead to privilege escalation at the application level, gaining admin level permissions.
#Select statement
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
if (isset($_POST["username"]))
{
$user_name = $_POST["username"];
}
if (isset($_POST["password"]))
{
$pass = $_POST["password"];
}
$sql = "SELECT username FROM admin WHERE username = '$user_name' AND password = '$pass'";
$count=$conn->prepare($sql);
$count->execute();
$no=$count->rowCount();
if ($no > 0) {
$yourURL="http://localhost/admin/welcome.php";
echo ("<script>location.href='$yourURL'</script>");
}
else
{
print("<h1>Access Denied...!!!</h1>");
}
}
?>
<html>
<div align="center">
<h1>Login</h1>
<body>
<form action='logincheck.php' method='post'>
<table>
<tr><td>Username:<input type="text" name="username" /></td></tr><br />
<tr><td>Password:<input type="password" name="password" /></td></tr><br />
<tr><td><input type='submit' value='Login' /></td></tr><br />
</table>
</form>
</div>
</body>
</html>
Cross script scripting (XSS): Sole purpose of a malicious user is to inject HTML (HTML injection) or run JavaScript in the website. JavaScript code is injected into the web page source code to execute JavaScript within the website context of the browser.
<?php
echo ‘<h2>Welcome ‘ . $_Get[‘username’] . ‘</h2>’ ;
?>
The code above is intended to print a welcome message for the logged-in user. Username is retrieved using GET variable. GET method stores values of query string parameters in the form of
Now, the server will return the following code to the browser:
<h2>Welcome user1</h2>
But malicious user can add additional details in the above code to exploit XSS vulnerability. Such vulnerability occurred because the user input is passed to a local variable since it is not sanitized. These types of attacks are possible when user input is used in the web application output that allows an attacker to take control of the content which is rendered to the users, eventually attacking the users.
Cross-site scripting can be used to achieve the following:
Three types of XSS are identified so far – Reflected, Persistent, and DOM-based XSS.
<?php
$name = $_GET[‘username’];
?>
Welcome <?=$name?>;
In this case, the malicious payload is added somehow in the HTTP request and, later on, it gets inserted into the webpage and executed by the browsers. Malicious user tricks the actual user of the web application to click the specially crafted link. By doing so, malicious payload runs into the browser within the context of the user.
<h2 id=”welcome”></h2>
<script>
var msg = “Welcome”;
</script>
document.getElementByID(‘welcome’).innerHTML = w
The above code snippet is clearly vulnerable to DOM side cross site scripting. In this case, client-side code is able to access browser DOM elements. It majorly impacts history, cookies, and local storage.
Impact of XSS vulnerabilities:
Enabling certain protection headers can prevent XSS to a certain level
X-XSS-Protection Header:
This header is designed to enable cross-site-scripting filter built into modern browsers. When a cross-site scripting attack is detected, the browser sanitizes the page itself to stop the attack.
When it is set to x-xss-protection:1 – enables the XSS filter
When mode=block is set along with it, then the browser will stop rendering the page when XSS attack is detected.
Using developer tools in Chrome in headers tab, notice the x-xss-protection value (as shown in below screenshot). This protection header is not enabled by blogger.com web server. Its value is set to 0. But this does not mean it is vulnerable to XSS. There are multiple ways to handle XSS.
How to enable this protection header in web servers?
<httpProtocol>
<customHeaders>
<add name="X-XSS-Protection" value="1; mode=block" />
</customHeaders>
</httpProtocol>
Some more headers can also be added in the web server configuration file.
X-Frame-Options Header:
This will prevent clickjacking vulnerability and instruct the web page to not embed web page in frame/iframe. Some of the configuration values for this header are:
Content Security Policy Header:
By default, all scripts on the web page are allowed to send and fetch data from any other site. But this behavior is dangerous and is prone to security risks.
Content Security Policy header allows the developer to define from where the content can be loaded and from which domain data can be posted to your web application. Let’s say, CSP header is set as default-src:self, then the content can be loaded only from http://myweb.com/*.
Encoding User Output:
Let us assume that the user is searching for a specific product on an eCommerce website. Web application should never trust user input and must encode the user input before it is displayed as an output on the web page. Before adding any data in HTML element or an attribute, developer must ensure that it is HTML encoded. This will encode special characters like “<” to <
Add encoding, user input escaping, and filtering techniques before assigning user input directly to an HTML element.
Overall, usage of iframe must be avoided on your web application which can be used by a malicious user to embed hidden content from other websites. This affects every visitor of your web application by malware or other vulnerabilities like CSRF (Client-side request forgery). It tricks a user to execute unwanted actions on web application in which they are authenticated. Purpose of such attacks is to change the data in database.
Basically, a PHP file can be included in another PHP file using include () function. Contents of the files are included into the calling PHP file along with any functions or variables declared in that PHP file. For example, a file named config.php contains MySQL connection details and a conn variable used to connect and fetch the data from MySQL server when firing SQL statements. The developer will include this file in index.php to fetch the data from MySQL server.
First scenario:
Let us assume there is a GET variable “productname” passed to local variable:
<?php
$productpage = $_REQUEST['productpage'];
If(isset($productpage))
{
include(“$productpage”.php);
}
URL becomes - http://www.vuln.web.com/page=<productpage> ?>
Now because $productpage variable is not sanitized, the malicious user can now read any file contents from the web server. This code is also vulnerable for a remote file inclusion as well.
Second scenario:
@include('include/$productpage.php');
The above code is vulnerable but also leads to remote code execution.
If the malicious user is able to access /proc/self/environ variable through LFI, then remote code execution is possible by poisoning using user-agent value. Environ file has variables for web server and one of the variables is the user-agent.
It can execute anything between in PHP file.
Third scenario:
file_get_contents(include/language/$language.lang.php)
The code mentioned above is still vulnerable to file inclusion, but it will read the content of the file. It does not allow remote code execution.
By now, it is identified that including any un-sanitized GET/POST parameter value directly in the include function is dangerous and can lead to high-risk vulnerabilities.
SQL Injection, XSS, and LFI are input validation vulnerabilities and can be prevented by enforcing input volition on any user-controlled parameter. The idea is to never trust user input and take necessary measures in the code to ensure that only intended data is passed to local variables.
Implementation of Mod_Security (Modsec): It is an open-source Windows Application Firewall (WAF) developed by Trustwave Spiderlabs. It adds an extra layer of security to protect web applications and is available for Linux, Windows, Solaris, FreeBSD, Mac OS X. It integrates well with Apache HTTP server, IIS server, and Nginx server.
Mod_Security is configured as a proxy server between user, web server, and based on certain user-defined rules set. It monitors and filters any incoming and outgoing data from the web server which does not satisfy the defined rules in it. It blocks any special characters passed to GET or POST variables to rule out cross-site scripting SQL injection and other web common attacks. It analyses headers, cookies, server variables, POST payload, etc.
$query = ("SELECT * FROM admin WHERE user='%s' AND password='%s'",mysql
_real_escape_string($user),mysql_real_escape_string($password));
function parseSpecialCharacters($chars)
{
return str_replace(array("'",""","'",'"'),array("'","""'",""",htmlspecialcharacters($chars));
}
$query = ("SELECT * FROM admin WHERE user='%s' AND password='%s'",
parseSpecialCharacters($user), parseSpecialCharacters($password));
Htmlspecialcharacters function converts special characters to HTML entities :
If(!preg_match(!’^[a-z\s-]$i’, $name)) {
die(‘Please enter a valid name’)
}
Above is a whitelist-based validation in PHP. Only letters, spaces, and dashes are allowed.
Thus, any parameter that is passed to the application must be sanitized before its value is passed to a local variable. User input should be considered unsafe and it must be checked against the whitelist (allowed character set) instead of blacklist. Ensure that Web Application Firewall is configured correctly, which monitors user input and filters out malicious payload using a behavioral and security heuristics.
This blog is a part of the series that highlights high-risk vulnerabilities in ASP.Net and cross-site request forgery (CSRF) in web applications.