SQL注入的问题
PHP自带的几个防止SQL注入的函数
1.php.ini 中的magic_quotes_gpc配置
为了防止SQL注入,PHP自带一个功能可以对输入的字符串处理,可以在较低层对输入进行安全上的初步处理,也就是Magic Quotes。(php.magic_quotes_gpc)。默认情况下开启,如果magic_quotes_gpc选项启用,那么输入的字符串中的单引号,双引号和其它一些字符前将会自动加上反斜杠。 但Magic Quotes并不是一个很通用的解决方案,没能屏蔽所有有潜在危险的字符,并且在许多服务器上Magic Quotes并没有被启用。所以,我们还需要使用其它多种方法来防止SQL注入。
许多数据库本身就提供这种输入数据处理功能。例如PHP操作函数中就有addslashes(),mysql_real_excape_string(),mysql_escape_string()函数等
2.addslashes()
addslashes()函数返回在预定义字符之前添加反斜杠的字符串
预定义的字符
单引号双引号反斜杠(\)NULL
注释:默认地,PHP默认情况下会开启magic_quotes_gpc,对所有的GET,POST和COOKIE数据自动运行addslashes(),所以不应该对已转移过的字符串使用addslashes(),因为这样会导致双层转义。遇到这种情况可以使用函数get_magic_quotes_gpc()函数进行检查是否开启了magic_quotes_gpc的配置
3.mysql_escape_string() && mysql_real_escape_string()
mysql_escape_string-- 转义一个字符串用于 mysql_query
mysql_escape_string() 并不转义 % 和 _。
mysql_escape_string()和 mysql_real_escape_string() 完全一样,除了 mysql_real_escape_string() 接受的是一个连接句柄并根据当前字符集转移字符串之外。mysql_escape_string() 并不接受连接参数,也不管当前字符集设定。
4.以上的过滤还不够彻底,需要使用正则表达式过滤掉SQL注入的关键字
/**
* @param $gpc 传入参数
* @return $gpc 转义后的数据
*/
function saddslashes($gpc){
$magic_quote = get_magic_quotes_gpc();
if(empty($magic_quote)){
if(is_array($gpc)){
foreach($gpc as $key => $val){
$gpc[$key] = saddslashes(trim($val));
}
}else{
$gpc =urldecode($gpc);
$gpc = strip_tags($gpc); //strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。
$gpc = trim($gpc); //trim() 函数移除字符串两侧的空白字符或其他预定义字符 trim()
//自动过滤Sql的注入语句。
$check=preg_match('/select|insert|update|delete|\.\.\/|\.\/|union|into|table|database|load_file|outfile/i',$gpc);
if ($check) {
DLOG('filter_string='.$gpc,'run','mobile');
return '';
}
}
}
return $gpc;
}
5.最有效的防止SQL注入的方法
使用预处理语句和参数化查询。预处理语句和参数化查询分别发送到数据库服务器进行解析,参数会被当作普通字符处理。这种方式使得攻击者无法注入恶意的SQL
a.使用PDO
$stmt = $pdo->prepare("SELECT * FROM t_user WHERE user_nick=:user_nick");
$stmt->excute(array(':user_nick'=>$user_nick));
foreach ($stmt as $row) {
//do something with $row
}
?>
b.使用mysqli
$stmt = $dbConnection->prepare("SELECT * FROM t_user WHERE user_nick=?");
$stmt->bind_param(array('s', $user_nick));
$stmt->excute();
$result = $stmt->get_result();
foreach ($row = $result->fetch_assoc()) {
//do something with $row
}
?>
注释:使用预处理语句和参数化查询的好处
当你将SQL语句发送给数据库服务器进行预处理和解析时发生了什么?通过指定占位符(一个?或者一个上面例子中命名的 :name),告诉数据库引擎你想在哪里进行过滤。当你调用execute的时候,预处理语句将会与你指定的参数值结合。 关键点就在这里:参数的值是和经过解析的SQL语句结合到一起,而不是SQL字符串。SQL注入是通过触发脚本在构造SQL语句时包含恶意的字符串。所 以,通过将SQL语句和参数分开,你防止了SQL注入的风险。任何你发送的参数的值都将被当作普通字符串,而不会被数据库服务器解析。回到上面的例子,如 果$name变量的值为 ’Sarah’; DELETE FROM employees ,那么实际的查询将是在 employees 中查找 name 字段值为 ’Sarah’; DELETE FROM employees 的记录。 另一个使用预处理语句的好处是:如果你在同一次数据库连接会话中执行同样的语句许多次,它将只被解析一次,这可以提升一点执行速度
XSS攻击 跨站脚本攻击(Cross Site Scripting)
XSS攻击与SQL注入类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在XSS攻击中,通过插入恶意脚本,实现对用户浏览器的控制
以下为XSS攻击的最简单的例子
a.角色分配
有XSS漏洞的网站受害访问者黑客的数据接收网站
b.有XSS漏洞的网站
./xss_demo.php
session_start();
?>
该网页吧用户通过GET发送过来的表单数据,未经处理直接写入返回的html流中,这就是XSS漏洞所在
c.黑客接受的网站
./xss_hacker.php
$victim='XXS得到的cookie:'.$_SERVER['REMOTE_ADDR'].':'.$_GET['cookie'];
file_put_contents('xss_victim.txt',$victim);
?>
把受害用户的IP地址和访问漏洞网站时使用的cookie,一起写入xss_vitim.txt文件中保存
注:
现在网站一般都采用session+cookie来保存用户登录信息,网站通过验证cookie来确实是否是合法已登录用户,所以cookie是用户的敏感数据。客户端通过cookie将session id传递到服务器,服务器根据session id找到对应的文件,读取的时候对文件内容进行反序列化就得到session的值,保存的时候先序列化再写入。
d.攻击过程
(1)黑客准备攻击字符串,构造攻击URL
黑客可以通过各种扫描工具或者人工输入来找到有XSS漏洞的网站URL,然后精心构造攻击字符串。对于本例来说构造出来的字符串就是
将重要的cookie标记为http only, 这样的话Javascript 中的document.cookie语句就不能获取到cookie了.只允许用户输入我们期望的数据。 例如: 年龄的textbox中,只允许用户输入数字。 而数字之外的字符都过滤掉。对数据进行Html Encode 处理过滤或移除特殊的Html标签, 例如: