SQL注入
漏洞类型
普通注入
普通注入值得是最容易利用的注入方式,比如union注入,盲注(基于时间盲注和基于Boolean的忙住),基于报错的注入等。
//union注入
<?php
$uid = $_GET['id'];
$sql = "SELECT * FROM userinfo where id = $id";
$conn = mysql_connect('localhost','root','root');
mysql_select_db("test",$conn);
$result = mysql_query($sql,$conn);
echo mysql_fetch_row($result);
?>
普通注入还分为字符型注入和数字型注入,上述例子是数字型注入,下面代码是字符型注入:
//union字符型注入
<?php
$uid = $_GET['id'];
$sql = "SELECT * FROM userinfo where id = '$id'";
$conn = mysql_connect('localhost','root','root');
mysql_select_db("test",$conn);
$result = mysql_query($sql,$conn);
echo mysql_fetch_row($result);
?>
字符型注入在利用时首先需要对单引号进行闭合,通常针对上述代码只需要将id设置为**1’ or 1=1 – '**就可以了,构造出来的查询语句如下
SELECT * FROM userinfo where id = '1' or 1=1 -- '';
但通常服务器端会开启GPC等功能将单引号给转义掉,这时候如果仍然使用上述payload构造出来的查询语句如下所示:
SELECT * FROM userinfo where id = '1\' or 1=1 --\ '';
很明显上述语句不会成功的,为了仍然能够利用漏洞就需要想办法从单引号中逃逸出来。
编码注入
编码转换就为上述提到的从单引号中逃逸出来提供了途径。只要存在编码转换就有可能存在注入问题。
宽字节注入
1.原理:
- 首先服务器对数据库进行了如下设置
set character_set_client = gbk
或
SET NAMES 'gbk'
/*
上条语句等价于:
SET
character_set_connection = 'gbk'
character_set_results = 'gbk'
character_set_client = 'gbk'
*/
或
mysql_set_charaset('gbk');
/*
上述函数其实仅是调用了SET NAMES
*/
- 接着攻击者将payload设置为id%df’ or 1=1 #, 经过转义后payload为id%df\’ or 1=1 #,其中’\'就是**%5c**,至此就结合为了id%df%5c’ or 1=1 #。由于设置了编码为gbk或者使用了addslashes()、mysql_escape_string()、mysql_real_escape_string(),payload就变成了
- 例子
以下面代码为例:
<?php
$link = mysqli_connect("localhost", "root", "147258zhao") or die("Cannot contact server");
mysqli_select_db($link, "test") or die("Cannot use database");
$id = addslashes($_GET['id']);//当前没有开启GPC所以使用了addslashes,如果开启GPC去掉addslashes
$sql = "SELECT * FROM User where id = '$id'";
echo $sql."<br>";
$request = mysqli_query($link,"SET character_set_client='gbk'");
$request = mysqli_query($link,$sql);
while($field = mysqli_fetch_assoc($request)){
echo var_dump($field);
}
mysqli_close($link);
?>
当设置payload为id=1’ or 1=1 – '时页面输出如下:
接着将payload设置为id=1%df’ or 1=1 – %df’,页面输出为:
数据库执行语句如下:
3. 防范
- 设置SET NAMES 'gbk’后接着设置SET character_set_client=binary
- 使用mysql_set_charset(‘gbk’)后,使用mysql_real_escape_string() 对参数进行过滤。
- 使用pdo方式,在PHP5.3.6及以下版本中需要设置setAttribute(PDO::ATTR_MULTATE_PREPARES,false);
- 挖掘关键字
SET NAMES
character_set_client='gbk'
mysql_set_character('gbk')
二次urldecode注入
- 原理
提交到服务器的数据会自动进行一次url解码,如果服务器段再调用urldecode()或者rawurldecode()函数来对参数进行解码则会造成二次解码。这样 %2527在第一次解码后变为 %27从而绕过过滤再次经过urldecode()、rawurldecode()解码后变为 ’ 。 - 例子
以下面代码为例:
<?php
$link = mysqli_connect("localhost", "root", "147258zhao") or die("Cannot contact server");
mysqli_select_db($link, "test") or die("Cannot use database");
$id = urldecode(addslashes($_GET['id']));
$sql = "SELECT * FROM User where id = '$id'";
echo $sql."<br>";
$request = mysqli_query($link,$sql);
while($field = mysqli_fetch_assoc($request)){
echo var_dump($field);
}
mysqli_close($link);
?>
3. 挖掘关键字
扫描二维码关注公众号,回复:
5837410 查看本文章
urldecode()
rawurldecode()
漏洞防范
- GPC魔术引号
- 过滤函数和类
addslashes()
mysql_real_escape_string()
mysql_escape_string()
intval()
自定义类及函数
- PDO预编译
XSS
原理
后台对于用户输入的数据未经过滤便直接输出到页面中,倘若用户输入的数据中存在恶意指令浏览器则会将其执行。XSS造成的影响可以用一句话来概括:
前段页面能做的他都能做
例子
<?php
echo $_GET['id'];
?>
访问效果如下:
挖掘关键字
print()
print_r()
echo()
printf()
sprintf()
die()
var_dump()
var_export()
防范
- 特殊HTML实体转码
- 标签时间属性黑白名单
CSRF
原理
类似于XSS,但是它的目的不向XSS那样盗取COOKIE等,而是伪造请求做一些触发这个漏洞角色所能做的事情。
例子
挖掘关键
观察后台是否验证token或者referer
防范
防范的关键就是验证请求是否真正来自用户,这就要一些攻击者不能确定的元素,比如在页面
- 增加token/referer验证
<?php
session_start();
function set_token(){
$_SESSION['token'] = md5(time()+rand(1,1000));
}
function check_token(){
if(isset($_POST['token'])&&$_POST['token']===$_SESSION['token']){
return true;
}else{
return false;
}
}
if(isset($_SESSION['token'])&&check_token()){
echo "success";
}else{
echo "failed";
}
set_token();
?>
<form method="POST">
<input type="hidden" name="token" value="<?= $_SESSION['token']?>">
<input type="submit">
</form>
- 增加验证码