SQL注入攻击.docx
《SQL注入攻击.docx》由会员分享,可在线阅读,更多相关《SQL注入攻击.docx(8页珍藏版)》请在冰豆网上搜索。
![SQL注入攻击.docx](https://file1.bdocx.com/fileroot1/2022-11/25/6166825a-dd75-4043-8571-56d1789feb6c/6166825a-dd75-4043-8571-56d1789feb6c1.gif)
SQL注入攻击
一.SQL注入攻击
1.什么是SQL注入攻击
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。
2.为何会有SQL注入攻击
很多电子商务应用程序都使用数据库来存储信息。
不论是产品信息,账目信息还是其它类型的数据,数据库都是Web应用环境中非常重要的环节。
SQL命令就是前端Web和后端数据库之间的接口,使得数据可以传递到Web应用程序,也可以从其中发送出来。
需要对这些数据进行控制,保证用户只能得到授权给他的信息。
可是,很多Web站点都会利用用户输入的参数动态的生成SQL查询要求,攻击者通过在URL、表格域,或者其他的输入域中输入自己的SQL命令,以此改变查询属性,骗过应用程序,从而可以对数据库进行不受限的访问。
因为SQL查询经常用来进行验证、授权、订购、打印清单等,所以,允许攻击者任意提交SQL查询请求是非常危险的。
通常,攻击者可以不经过授权,使用SQL输入从数据库中获取信息。
3.何时使用SQL注入攻击
当Web应用向后端的数据库提交输入时,就可能遭到SQL注入攻击。
可以将SQL命令人为的输入到URL、表格域,或者其他一些动态生成的SQL查询语句的输入参数中,完成上述攻击。
因为大多数的Web应用程序都依赖于数据库的海量存储和相互间的逻辑关系(用户权限许可,设置等),所以,每次的查询中都会存在大量的参数。
二.MySQL简介
SQL是结构化查询语言的简称,它是全球通用的标准数据库查询语言,主要用于关系型数据的操作和管理,如增加记录,删除记录,更改记录,查询记录等,常用命令知识如表15-1-1所示。
表15-1-1SQL常用命令
命令短语
功能
例句
select
用于查询记录和赋值
selecti,j,kfromA(i,j,k是表A中仅有的列名)
selecti='1'(将i赋值为字符1)
select*fromA(含义同第一个例句)
update
用于修改记录
updateAseti=2wherei=1(修改A表中i=1的i值为2)
insert
用于添加记录
insertintoAvalues(1,'2',3)(向A表中插入一条记录(i,j,k)对应为(1,'2',3))
delete
用于删除记录
deleteAwherei=2(删除A标中i=2的所有表项)
from
用于指定操作的对象名(表,视图,数据库等的名称)
见select
where
用于指定查询条件
select*fromA,BwhereA.name=B.nameandA.id=B.id
and
逻辑与
1=1and2<=2
or
逻辑或
1=1or1>2
not
逻辑非
not1>1
=
相等关系或赋值
见and、or、not
>,>=,<,<=
关系运算符
与相等关系('=')的用法一致。
单引号(“'”)
用于指示字符串型数据
见select
逗号
分割相同的项
见select
*
通配符所有
见select
--
行注释
--这里的语句将不被执行!
/**/
块注释
/*这里的语句将不被执行!
*/
MySQL是一个快速而又健壮的关系数据库管理系统(RDBMS)。
一个数据库将允许使用者高效地存储、搜索、排序和检索数据。
MySQL服务器将控制对数据的访问,从而确保多个用户可以并发地使用它,同时提供了快速访问并且确保只有通过验证的用户才能获得数据访问。
因此,MySQL是一个多用户、多线程的服务器。
它使用了结构化查询语言(SQL)。
MySQL是世界上最受欢迎的开放源代码数据库。
MySQL的主要竞争产品包括PostgreSQL、MicrosoftSQLServer和Oracle。
MySQL具有许多优点,如高性能、低成本、易于配置和学习、可移植性、源代码可供使用等。
三.实施SQL注入攻击
1.攻击一
任何输入,不论是Web页面中的表格域还是一条SQL查询语句中API的参数,都有可能遭受SQL注入的攻击。
如果没有采取适当的防范措施,那么攻击只有可能在对数据库的设计和查询操作的结构了解不够充分时才有可能失败。
从SQL命令(更多的SQL命令见原理三)SELECT切入比较好。
SELECT的使用格式如下:
SQL在Web应用程序中的常见用途就是查询产品信息。
应用程序通过CGI参数建立链接,在随后的查询中被引用。
这些链接看起来通常像如下的样子:
应用程序需要知道用户希望得到哪种产品的信息,所以浏览器会发送一个标识符,通常称为id。
随后,应用程序动态的将其包含到SQL查询请求中,以便于从数据库中找到正确的行。
查询语句通常的形式如下:
但是,用户可以在浏览器中轻易的修改信息。
设想一下,作为某个Web站点的合法用户,在登入这个站点的时候输入了账号ID和密码。
下面的SQL查询语句将返回合法用户的信息:
上面的SQL查询语句中唯一受用户控制的部分就是在单引号中的字符串。
这些字符串就是用户在Web表格中输入的。
Web应用程序自动生成了查询语句中的剩余部分。
常理来讲,其他用户在查看此账号信息时,他需要同时知道此账号ID和密码,但通过SQL输入的攻击者可以绕过全部的检查。
比如,当攻击者知道系统中存在一个叫做Tom的用户时,他会在SQL请求中使用注释符(双虚线--),然后将下面的内容输入到用户账号的表格域中。
这将会动态地生成如下的SQL查询语句:
由于“--”符号表示注释,随后的内容都被忽略,那么实际的语句就是:
没有输入Tom的密码,却从数据库中查到了Tom用户的全部信息!
注意这里所使用的语法,作为用户,可以在用户名之后使用单引号。
这个单引号也是SQL查询请求的一部分,这就意味着,可以改变提交到数据库的查询语句结构。
在上面的案例中,查询操作本来应该在确保用户名和密码都正确的情况下才能进行的,而输入的注释符将一个查询条件移除了,这严重的危及到了查询操作的安全性。
允许用户通过这种方式修改Web应用中的代码,是非常危险的。
2.攻击二
一般的应用程序对数据库进行的操作都是通过SQL语句进行,如查询一个表(A)中的一个num=8的用户的所有信息,我们通过下面的语句来进行:
对应页面地址可能有http:
//127.0.0.1/list.jsp?
num=8。
一个复合条件的查询
对应页面地址可能有http:
//127.0.0.1/aaa.jsp?
id=8&name=k。
通常数据库应用程序中where子句后面的条件部分都是在程序中按需要动态创建的,如下面使用的方法:
当N,K从前台获得的数据中存在像“'”,“and1=1”,“or1=1”,“--”就会出现具有特殊意义的SQL语句,当上面http:
//127.0.0.1/aaa.jsp?
id=8&name=k中的“id=8--”时,在页面地址中可能会有如下的表示:
http:
//127.0.0.1/list.jsp?
n=8--
上面的str变成了:
熟悉SQLServer的人一定明白上面语句的意义,很明显,--后面的条件andname='k'不会被执行,因为它被“--”注释掉了。
当上面的K="XXX\'or1=1"时(“\'”是“'”在字符串中的转义字符),在页面地址中会有如下的表示:
http:
//127.0.0.1/list.jsp?
name=XXX’or1=1
同样上面的语句变成了:
这条语句会导致查询到所有用户的信息而不需要使用正确的id和name属性,虽然结果不会在页面上直接得到,但可以通过数据库的一些辅助函数间接猜解得到,下面猜解的例子能够说明SQL注入漏洞的危害性:
在SQLServer2000中有user变量,用于存储当前登录的用户名,因此可以利用猜解它来获得当前数据库用户名,从而确定当前数据库的操作权限是否为最高用户权限,在一个可以注入的页面请求地址后面加上下面的语句,通过修改数值范围,截取字符的位置,并重复尝试,就可以猜解出当前数据库连接的用户名:
如果正常返回,则说明当前数据库操作用户帐户名的前一个字符在A~Z的范围内,逐步缩小猜解范围,就可以确定猜解内容。
SubString()是SQLServer2000数据库中提供的系统函数,用于获取字符字符串的子串。
65,和90分别是字母A和Z的ascii码。
再有,在数据库中查找用户表(需要一定的数据库操作权限),可以使用下面的复合语句:
n取1,2,……,通过上面形式的语句可以判断数据库中有多少用户表。
可以通过and(substring((selecttop1namefromsysobjectswherextype='u'),1,1)=字符)的形式逐步猜解出表名。
利用构建的SQL注入短语,可以查询出数据库中的大部分信息,只要构建的短语能够欺骗被注入程序按你的意图执行,并能够正确分析程序返回的现象,注入攻击者就可以控制整个系统。
基于网页地址的SQL注入只是利用了页面地址携带参数这一性质,来构建特殊sql语句以实现对Web应用程序的恶意操作(查询,修改,添加等)。
事实上SQL注入不一定要只针对浏览器地址栏中的url。
任何一个数据库应用程序对前台传入数据的处理不当都会产生SQL注入漏洞,如一个网页表单的输入项,应用程序中文本框输的入信息等。
四.PHP简介
1.PHP是什么
PHP,即“HypertextPreprocessor”是一种服务器端脚本语言,它是专门为Web而设计的,其主要目标是让Web开发人员快速的书写动态生成的网页。
在一个HTML页面中,可以嵌入PHP代码,这些代码在每次页面被访问时执行。
PHP代码将在Web服务器中被解释并且生成HTML或访问者看到的其他输出。
PHP的主要竞争对手是Perl、MicrosoftASP.NET、JavaServerPage(JSP)和ColdFusion。
与这些产品比较,PHP具有高性能、与许多不同数据库系统的接口、内置许多常见Web任务所需的函数库、低成本、容易学习和使用、对面向对象的高度支持、可移植性、源代码可供使用等。
下面是一个介绍性的PHP脚本范例。
这里使用PHP编写了一个HTML脚本,其中嵌入PHP代码实现文本输出。
PHP代码被特殊的起始符(“
php”)和结束符(“?
>”)包含。
与客户端的JavaScript不同的是,PHP代码是运行在服务端的。
在服务器上建立了如上例类似的代码,则在运行该脚本后,客户端就能接收到其处理结果,但他们无法得知其背后的代码是如何动作的。
2.PHP能做什么
PHP主要是用于服务端的脚本程序,因此可以用PHP来完成任何其它的CGI程序能够完成的工作,例如收集表单数据,生成动态网页,或者发送/接收Cookies。
但PHP的功能远不局限于此。
PHP脚本主要用于以下三个领域。
(1)服务端脚本
这是PHP最传统,也是最主要的目标领域。
开展这项工作需要具备以下三点:
PHP解析器(CGI或者服务器模块)、Web服务器和Web浏览器。
(2)命令行脚本
可以编写一段PHP脚本,并且不需要任何服务器或者浏览器来运行它。
通过这种方式,仅仅只需要PHP解析器来执行。
(3)编写客户端的GUI应用程序
对于图形界面的应用程序来说,PHP或许不是一种最好的语言,但是如果非常精通PHP,并且希望在客户端应用程序中使用PHP的一些高级特性,则可以利用PHP-GTK来编写这些程序。
PHP能够用在所有的主流操作系统上,包括Linux、Unix、MicrosoftWindows、MacOSX等。
并且PHP已经支持了大多数的Web服务器,包括Apache、IIS、PWS、Netscape等。
五.使用PHP从Web访问MySQL数据库
1.Web数据库架构的工作原理
以下给出的是Web数据库架构的基本步骤:
(1)客户Web浏览器发出一个HTTP请求,请求特定的Web页面。
例如,客户使用一个HTML表单请求搜索Book数据库中所有于2008年出版的书籍。
该搜索结果页面为results.php。
(2)Web服务器接收到对results.php页面的请求后,检索该文件,并将其传递给PHP引擎处理。
(3)PHP引擎开始解析脚本。
脚本主要包括了连接到数据库和执行查询的命令(执行对书籍的搜索)。
PHP启动了对MySQL服务器的连接并向该服务器发送适当的查询。
(4)MySQL服务器接收到数据库查询的请求,开始处理这个查询,并将查询结果——书籍列表——返回给PHP引擎。
(5)PHP引擎完成了脚本的运行后(其中包括以HTML格式表示经过处理后的查询结果),然后将该HTML返回给Web服务器。
(6)Web服务器再将HTML返回给客户端浏览器,用户就可以看到所要求查询的书籍。
2.从Web查询数据库的基本步骤
在任何用于从Web访问数据库的脚本中,都应该遵循以下这些基本步骤:
(1)检查并过滤来自用户的数据。
(2)建立一个到数据库的连接。
(3)查询数据库。
(4)获取查询结果。
(5)将结果显示给用户。
3.PHP访问Mysql数据库
(1)连接到MySQL服务器
在从目标数据库中获取Web页面所包含的内容之前,首先必须知道如何建立与MySQL的连接。
通常情况下,使用MySQL客户端程序来实现连接数据库,但PHP不需要这样的程序,对连接MySQL的支持是语言内置的。
下面的函数用来建立与MySQL数据库的连接。
●address是MySQL服务器(MySQL服务软件所在计算机)的IP地址或主机名(如果与Web服务器所在是同一台主机,可以使用“localhost”);
●username、password是用来连接MySQL服务器的用户名及口令;
●执行成功返回MySQL连接标识(linkid),否则返回FALSE。
(2)选择工作数据库
在PHP与MySQL成功建立连接后,可以使用如下函数选择工作数据库
●dbname是欲选择的工作数据库名称;
●linkid是连接标识,此参数为可选参数,如果没有指定连接标识,则使用上一个打开的连接;
●执行成功返回TRUE,否则返回FALSE。
(3)执行SQL查询
通过下面的函数可以向指定的连接标识关联的服务器中的当前工作数据库发送一条查询(SQL语句)。
sql为查询字符串,并且不应以分号结束;
●如果没有指定linkid,则使用上一个打开的连接;
●此函数仅对SELECT、SHOW、EXPLAIN或DESCRIBE语句返回一个资源标识,如果查询执行不正确则返回FALSE。
对于其它类型的SQL语句,执行成功时返回TRUE,否则返回FALSE。
(4)发送一条MySQL查询(PHP4.0.6起不提供使用此函数)
●根据查询结果返回一个正的MySQL结果资源号,出错时返回FALSE。
(5)获取前一次MySQL操作所影响的记录行数
●此函数返回最后一次与连接标识关联的INSERT、UPDATE或DELETE查询所影响的记录行数。
如果连接标识没有指定,则默认使用最后一次由mysql_connect()函数打开的连接标识。
(6)获取结果集中行的数目
●此函数仅对SELECT语句有效。
要取得被INSERT、UPDATE或者DELETE查询所影响到的行的数目,用mysql_affected_row()。
(7)从结果集中获取一行作为关联数组
●返回根据从结果集获取的行生成的数组,如果没有更多行则返回FALSE。
(8)取得上一步INSERT操作产生的ID
●返回给定的linkid中上一步INSERT查询中产生的AUTO_INCREMENT的ID号。
如果没有指定linkid,则使用上一个打开的连接。
(9)关闭MySQL连接
●关闭指定的连接标识所关联到的到MySQL服务器的连接。
如果没有指定linkid,则关闭上一个打开的连接。
通常不需要使用此函数,因为已打开的非持久连接会在脚本执行完毕后自动关闭。