2013年5月30日星期四

IIS Web服务器安全设置

IIS Web服务器安全设置

2009-10-21 10:04:09  www.hackbase.com  来源:互联网
  IIS Web服务器安全加固步骤:步骤 注意:安装和配置 Windows Server 2003。1. 将\System32\cmd.exe转移到其他目录或更名;2. 系统帐号尽量少,更改默认帐户名( ...
  IIS Web服务器安全加固步骤:
  
  
  步骤
  注意:
  
  安装和配置 Windows
  Server
  2003。
  1. 将\System32\cmd.exe转移到其他目录或更名;
  
  2. 系统帐号尽量少,更改默认帐户名(如Administrator)和描述,密码尽量复杂;
  
  3. 拒绝通过网络访问该计算机(匿名登录;内置管理员帐户;Support_388945a0;Guest;所有非操作系统服务帐户)
  
  4. 建议对一般用户只给予读取权限,而只给管理员和System以完全控制权限,但这样做有可能使某些正常的脚本程序不能执行,或者某些需要写的操作不能完成,这时需要对这些文件所在的文件夹权限进行更改,建议在做更改前先在测试机器上作测试,然后慎重更改。
  
  5. NTFS文件权限设定(注意文件的权限优先级别比文件夹的权限高):
  
  文件类型
  建议的 NTFS 权限
  
  CGI 文件(.exe、.dll、.cmd、.pl)
  脚本文件 (.asp)
  包含文件(.inc、.shtm、.shtml)
  静态内容(.txt、.gif、.jpg、.htm、.html)
  Everyone(执行)
  Administrators(完全控制)
  System(完全控制)
  
  
  6. 禁止C$、D$一类的缺省共享
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
  
  \lanmanserver\parameters
  AutoShareServer、REG_DWORD、0x0
  
  7. 禁止ADMIN$缺省共享
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
  
  \lanmanserver
  
  \parameters
  AutoShareWks、REG_DWORD、0x0
  
  8. 限制IPC$缺省共享
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
  
  \Lsarestrictanonymous REG_DWORD 0x0 缺省
  0x1 匿名用户无法列举本机用户列表
  0x2 匿名用户无法连接本机IPC$共享
  说明:不建议使用2,否则可能会造成你的一些服务无法启动,如SQL Server
  
  9. 仅给用户真正需要的权限,权限的最小化原则是安全的重要保障
  
  10. 在本地安全策略->审核策略中打开相应的审核,推荐的审核是:
  账户管理 成功 失败
  登录事件 成功 失败
  对象访问 失败
  策略更改 成功 失败
  特权使用 失败
  系统事件 成功 失败
  目录服务访问 失败
  账户登录事件 成功 失败
  审核项目少的缺点是万一你想看发现没有记录那就一点都没辙;审核项目太多不仅会占用系统资源而且会导致你根本没空去看,这样就失去了审核的意义。 与之相关的是:
  在账户策略->密码策略中设定:
  密码复杂性要求 启用
  密码长度最小值 6位
  强制密码历史 5次
  最长存留期 30天
  在账户策略->账户锁定策略中设定:
  账户锁定 3次错误登录
  锁定时间 20分钟
  复位锁定计数 20分钟
  
  11. 在Terminal Service Configration(远程服务配置)-权限-高级中配置安全审核,一般来说只要记录登录、注销事件就可以了。
  
  12. 解除NetBios与TCP/IP协议的绑定
  控制面版——网络——绑定——NetBios接口——禁用 2000:控制面版——网络和拨号连接——本地网络——属性——TCP/IP——属性——高级——WINS——禁用TCP/IP上的NETBIOS
  
  13. 在网络连接的协议里启用TCP/IP筛选,仅开放必要的端口(如80)
  
  14. 通过更改注册表Local_Machine\System\CurrentControlSet
  
  \Control\LSA-RestrictAnonymous = 1来禁止139空连接
  
  15. 修改数据包的生存时间(TTL)值
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
  
  \Tcpip\Parameters
  DefaultTTL REG_DWORD 0-0xff(0-255 十进制,默认值128)
  
  16. 防止SYN洪水攻击
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
  
  \Tcpip\Parameters
  SynAttackProtect REG_DWORD 0x2(默认值为0x0)
  
  17. 禁止响应ICMP路由通告报文
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
  
  \Tcpip\Parameters
  \Interfaces\interface
  PerformRouterDiscovery REG_DWORD 0x0(默认值为0x2)
  
  18. 防止ICMP重定向报文的攻击
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
  
  \Tcpip\Parameters
  EnableICMPRedirects REG_DWORD 0x0(默认值为0x1)
  
  19. 不支持IGMP协议
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
  
  \Tcpip\Parameters
  IGMPLevel REG_DWORD 0x0(默认值为0x2)
  
  20. 设置arp缓存老化时间设置
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services:
  
  \Tcpip
  
  \Parameters
  ArpCacheLife REG_DWORD 0-0xFFFFFFFF(秒数,默认值为120秒)
  ArpCacheMinReferencedLife REG_DWORD 0-0xFFFFFFFF(秒数,默认值为600)
  
  21. 禁止死网关监测技术
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services:\Tcpip
  
  \Parameters
  EnableDeadGWDetect REG_DWORD 0x0(默认值为ox1)
  
  22. 不支持路由功能
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services:
  
  \Tcpip\Parameters
  IPEnableRouter REG_DWORD 0x0(默认值为0x0)
  
  安装和配置 IIS 服务:
  
  
  1. 仅安装必要的 IIS 组件。(禁用不需要的如FTP 和 SMTP 服务)
  
  2. 仅启用必要的服务和 Web Service 扩展,推荐配置:
  
  UI 中的组件名称
  设置
  设置逻辑
  
  后台智能传输服务 (BITS) 服务器扩展
  启用
  BITS 是 Windows Updates 和“自动更新”所使用的后台文件传输机制。如果使用 Windows Updates 或“自动更新”在 IIS 服务器中自动应用 Service Pack 和热修补程序,则必须有该组件。
  
  公用文件
  启用
  IIS 需要这些文件,一定要在 IIS 服务器中启用它们。
  
  文件传输协议 (FTP) 服务
  禁用
  允许 IIS 服务器提供 FTP 服务。专用 IIS 服务器不需要该服务。
  
  FrontPage 2002 Server Extensions
  禁用
  为管理和发布 Web 站点提供 FrontPage 支持。如果没有使用 FrontPage 扩展的 Web 站点,请在专用 IIS 服务器中禁用该组件。
  
  Internet 信息服务管理器
  启用
  IIS 的管理界面。
  
  Internet 打印
  禁用
  提供基于 Web 的打印机管理,允许通过 HTTP 共享打印机。专用 IIS 服务器不需要该组件。
  
  NNTP 服务
  禁用
  在 Internet 中分发、查询、检索和投递 Usenet 新闻文章。专用 IIS 服务器不需要该组件。
  
  SMTP 服务
  禁用
  支持传输电子邮件。专用 IIS 服务器不需要该组件。
  
  万维网服务
  启用
  为客户端提供 Web 服务、静态和动态内容。专用 IIS 服务器需要该组件。
  
  
  万维网服务子组件
  
  UI 中的组件名称
  安装选项
  设置逻辑
  
  Active Server Page
  启用
  提供 ASP 支持。如果 IIS 服务器中的 Web 站点和应用程序都不使用 ASP,请禁用该组件;或使用 Web 服务扩展禁用它。
  
  Internet
  
  数据连接器
  禁用
  通过扩展名为 .idc 的文件提供动态内容支持。如果 IIS 服务器中的 Web 站点和应用程序都不包括 .idc 扩展文件,请禁用该组件;或使用 Web 服务扩展禁用它。
  
  远程管理 (HTML)
  禁用
  提供管理 IIS 的 HTML 界面。改用 IIS 管理器可使管理更容易,并减少了 IIS 服务器的攻击面。专用 IIS 服务器不需要该功能。
  
  远程桌面 Web 连接
  禁用
  包括了管理终端服务客户端连接的 Microsoft ActiveX? 控件和范例页面。改用 IIS 管理器可使管理更容易,并减少了 IIS 服务器的攻击面。专用 IIS 服务器不需要该组件。
  
  服务器端包括
  禁用
  提供 .shtm、.shtml 和 .stm 文件的支持。如果在 IIS 服务器中运行的 Web 站点和应用程序都不使用上述扩展的包括文件,请禁用该组件。
  
  WebDAV
  禁用
  WebDAV 扩展了 HTTP/1.1 协议,允许客户端发布、锁定和管理 Web 中的资源。专用 IIS 服务器禁用该组件;或使用 Web 服务扩展禁用该组件。
  
  万维网服务
  启用
  为客户端提供 Web 服务、静态和动态内容。专用 IIS 服务器需要该组件
  
  
  
  3. 将IIS目录&数据与系统磁盘分开,保存在专用磁盘空间内。
  
  4. 在IIS管理器中删除必须之外的任何没有用到的映射(保留asp等必要映射即可)
  
  5. 在IIS中将HTTP404 Object Not Found出错页面通过URL重定向到一个定制HTM文件
  
  6. Web站点权限设定(建议)
  
  Web 站点权限:
  授予的权限:
  
  读
  允许
  
  写
  不允许
  
  脚本源访问
  不允许
  
  目录浏览
  建议关闭
  
  日志访问
  建议关闭
  
  索引资源
  建议关闭
  
  执行
  推荐选择 “仅限于脚本”
  
  
   7. 建议使用W3C扩充日志文件格式,每天记录客户IP地址,用户名,服务器端口,方法,URI字根,HTTP状态,用户代理,而且每天均要审查日志。(最好 不要使用缺省的目录,建议更换一个记日志的路径,同时设置日志的访问权限,只允许管理员和system为Full Control)。
  
  8. 程序安全:
  1) 涉及用户名与口令的程序最好封装在服务器端,尽量少的在ASP文件里出现,涉及到与数据库连接地用户名与口令应给予最小的权限;
  2) 需要经过验证的ASP页面,可跟踪上一个页面的文件名,只有从上一页面转进来的会话才能读取这个页面。
  3) 防止ASP主页.inc文件泄露问题;
  4) 防止UE等编辑器生成some.asp.bak文件泄露问题。
  
  安全更新。
  应用所需的所有 Service Pack 和 定期手动更新补丁。
  
  安装和配置防病毒保护。
  推荐NAV 8.1以上版本病毒防火墙(配置为至少每周自动升级一次)。
  
  安装和配置防火墙保护。
  推荐最新版BlackICE Server Protection防火墙(配置简单,比较实用)
  
  监视解决方案。
  根据要求安装和配置 MOM代理或类似的监视解决方案。
  
  加强数据备份。
  Web数据定时做备份,保证在出现问题后可以恢复到最近的状态。
  
  考虑实施 IPSec 筛选器。
  用 IPSec 过滤器阻断端口
  
  Internet 协议安全性 (IPSec) 过滤器可为增强服务器所需要的安全级别提供有效的方法。本指南推荐在指南中定义的高安全性环境中使用该选项,以便进一步减少服务器的受攻击面。
  
  有关使用 IPSec 过滤器的详细信息,请参阅模块其他成员服务器强化过程。
  
  下表列出在本指南定义的高级安全性环境下可在 IIS 服务器上创建的所有 IPSec 过滤器。
  
  服务
  协议
  源端口
  目标端口
  源地址
  目标地址
  操作
  镜像
  
  Terminal Services
  TCP
  所有
  3389
  所有
  ME
  允许
  是
  
  HTTP Server
  TCP
  所有
  80
  所有
  ME
  允许
  是
  
  HTTPS Server
  TCP
  所有
  443
  所有
  ME
  允许
  是
  
  
  在实施上表所列举的规则时,应当对它们都进行镜像处理。这样可以确保任何进入服务器的网络通信也可以返回到源服务器。
  
  
  
  SQL服务器安全加固
  
  步骤
  说明
  
  MDAC 升级
  安装最新的MDAC(http://www.microsoft.com/data/download.htm
  
  密码策略
   由于SQL Server不能更改sa用户名称,也不能删除这个超级用户,所以,我们必须对这个帐号进行最强的保护,当然,包括使用一个非常强壮的密码,最好不要在数 据库应用中使用sa帐号。新建立一个拥有与sa一样权限的超级用户来管理数据库。同时养成定期修改密码的好习惯。数据库管理员应该定期查看是否有不符合密 码要求的帐号。比如使用下面的SQL语句:
  Use master
  Select name,Password from syslogins where password is null
  
  数据库日志的记录
  核数据库登录事件的“失败和成功”,在实例属性中选择“安全性”,将其中的审核级别选定为全部,这样在数据库系统和操作系统日志里面,就详细记录了所有帐号的登录事件。
  
  管理扩展存储过程
  xp_cmdshell是进入操作系统的最佳捷径,是数据库留给操作系统的一个大后门。请把它去掉。使用这个SQL语句:
  use master
  sp_dropextendedproc 'xp_cmdshell'
  如果你需要这个存储过程,请用这个语句也可以恢复过来。
  sp_addextendedproc 'xp_cmdshell', 'xpsql70.dll'
  
  OLE自动存储过程(会造成管理器中的某些特征不能使用),这些过程包括如下(不需要可以全部去掉:
  Sp_OACreate Sp_OADestroy Sp_OAGetErrorInfo Sp_OAGetProperty
  Sp_OAMethod Sp_OASetProperty Sp_OAStop
  
  去掉不需要的注册表访问的存储过程,注册表存储过程甚至能够读出操作系统管理员的密码来,如下:
  Xp_regaddmultistring Xp_regdeletekey Xp_regdeletevalue Xp_regenumvalues Xp_regread Xp_regremovemultistring Xp_regwrite
  
  防TCP/IP端口探测
  在实例属性中选择TCP/IP协议的属性。选择隐藏 SQL Server 实例。
  请在上一步配置的基础上,更改原默认的1433端口。
  在IPSec过滤拒绝掉1434端口的UDP通讯,可以尽可能地隐藏你的SQL Server。
  
  对网络连接进行IP限制
  使用操作系统自己的IPSec可以实现IP数据包的安全性。请对IP连接进行限制,保证只有自己的IP能够访问,拒绝其他IP进行的端口连接。
  
  
  附:Win2003系统建议禁用服务列表
  
  名 称
  服务名
  建议设置
  
  自动更新
  wuauserv
  禁用
  
  Background Intelligent Transfer Service
  BITS
  禁用
  
  Computer Browser
  Browser
  禁用
  
  DHCP Client
  Dhcp
  禁用
  
  NTLM Security Support Provider
  NtLmSsp
  禁用
  
  Network Location Awareness
  NLA
  禁用
  
  Performance Logs and Alerts
  SysmonLog
  禁用
  
  Remote Administration Service
  SrvcSurg
  禁用
  
  Remote Registry Service
  RemoteRegistry
  禁用
  
  Server
  lanmanserver
  禁用
  
  TCP/IP NetBIOS Helper Service
  LmHosts
  禁用
  
  DHCP Client
  Dhcp
  禁用
  
  NTLM Security Support Provider
  NtLmSsp
  禁用
  
  Terminal Services
  TermService
  禁用
  
  Windows Installer
  MSIServer
  禁用
  
  Windows Management Instrumentation Driver Extensions
  Wmi
  禁用
  
  WMI Performance Adapter
  WMIApSrv
  禁用
  
  Error Reporting
  ErrRep
  禁用

2013年5月28日星期二

浅谈csrf漏洞的测试方法

浅谈csrf漏洞的测试方法

来源:本站转载 作者:佚名 时间:2012-12-08 14:03:19
 CSRF(cross-site request forgery)跨站请求伪造攻击
CSRF.指的是能够破坏其他正常用户的会话,或者是把其他用户的会话据为己有.
攻击过程:
受害者发起伪造请求,攻击者发送恶意代码,受害者在不知不觉中发送执行恶意代码的请求,服务器响应受害者的正当请求确认执行,至此CSRF攻击结束。
CSRF攻击的本质:强迫受害者的浏览器向一个易受攻击的Web应用程序发送请求.
CSRF攻击特征:
1.用户请求修改信息——Web服务响应一张空白表单
2.用户修改信息并提交—-Web服务响应请求,保存
CSRF攻击直接跨越了第一步,直接修改数据….
攻击原理:
1.Get请求:隐式的通过http标签发出一个Get请求;
2.Post请求:通过Iframe能够设置界面大小为0的特性,加载页面自动执行,达到隐藏的目的;
登录式CSRF攻击:监听用户实际操作(这个不是很清楚,感觉就像钓鱼网站);
Web2.0攻击:Web2.0虽然在一定程度上限制了CSRF攻击但是,通过脚本渗透漏洞,邮件或者上传文件攻击,也能达到攻击的目的
测试方法:
对于这类攻击,防范的办法是:session标记必须随机生成;禁止用户自主选择session标记;确认已有的session标记无法被二次使用;对会话进行时效限制,或者通过REFERER的域来识别是否一个标记登陆了多个用户等.其实就是杜绝标记被伪造和复用.
csrf 漏洞主要出现在http cookie被用于传送会话令牌的地方。一旦应用程序已经在用户的浏览器中设定一个cookie,他们的浏览器会自动在随后的每 个请求中将这个 cookie返回给应用程序。无论请求是源自应用程序提供的一个链接、从其他地方受到的一个url或者其他来源,他都会这样做。如果应用 程序并未采取防范 措施,防止令牌滥用,那么程序就易于受到csrf攻击。
对 于csrf的测试。首先,我们可以尝试查找出程序中的增删改功能的操作,可用于代表不知情的用户执行某种敏感操作,找到一项应用程序功能后,使用攻击者能 够提前决定的请求参数,也就是说,其中并不包含任何会话令牌或者其他无法预测的数据。然后创建一个html页面,他不需要进行任何用户交互即可提出想要的 请求。对于get请求,可以使用一个<img>标签,并通过src参数设置易受攻击的url;对于post请求,可以建立一个表单,其中包含 实施攻击所需要的全部相关参数的隐藏字段,并将其目标设为易受攻击的url。可以使用javascript在页面加载时自动提交该表 单 (document.formname.submit())。


登录应用程序后,使用相同的浏览器加载专门设计的html页面,确认应用程序是否执行想要的操作。
防范思路:
1.form中添加秘密信息、用户代号验证等
2.双提交cookie:cookie在form post之前被JS读取,限制跨域规则将被应用。
这里就涉及到同源策略:
同源策略:要求动态内容只能阅读与之同源的Http应答和cookie,而不能阅读来自不同源的内容,但是它对写操作没有任何限制。
同源:指的是同协议,同域名和同端口
可以通过被请求的页面中对JS的变量document.domain进行响应的设置,
可以使浏览器有限度地违反同源策略
—————————————————————————————————————————
举例:
如果http://www.foo.com/bar/baz.html页面中含有下列内容:
< script >
document.domain = “foo.com”;
< / script >
那么任何http://xyz.foo.com/anywhere.html页面内的脚本都可以向http://www.foo.com /bar /baz.html发送HTTP请求,并可以读取其内容。在此种情况下,如果攻击者能够向http: //xyz.foo.com /anywhere.html中注入HTML或JavaScript的话,那么他同时也能在http: //www.foo.com/bar/baz.html中注入JavaScript代码。
为此,攻击者需要首先在http://xyz.foo.com/anywhere.html(其document.domain设为foo.com)中 注 入HTML和JavaScript,并向http://www.foo.com/bar/baz.html(其document.domain也设 为 foo.com)中载入一个iframe,然后就可以通过JavaScript来访问该iframe的内容了。 例 如,http://xyz.foo.com/anywhere.html中的下列代码将在www.foo.com域中执行一个JavaScript 的 alert()函数:
< iframe src=”http://www.foo.com/bar/baz.html”
onload=”frames[0].document.body.innerHTML+=’onerror=alert(1)’”>< / iframe >
这样,document.domain将允许攻击者跨域活动(域际旅行)。注意,你不能在document.domain变量中放入任何域名,相反,只 能 在document.domain变量中放置“源”页面即所在页面的域名的上级域名,如www.foo.com的上级域名是foo.com 。
————————————————————————————————————————–
这里涉及到了域的概念(http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.4.1),
set-cookie机制:

 Set-Cookie: <name>=<value>[;<name>=<value>]...
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; httponly]
里面也有对域的访问设置,其中的path and domain可以设置.
其中的httponly是关于防止cookie通过js伪协议获取,强迫cookie过期
额,可以讲讲JS的cookie的提取方法
打开你登录过的任意网站,输入:javascript:alert(document.cookie)
你就可以获取到你想要的用户cookie信息了,再配合XSS攻击,能够做到非常多的事情
如何防范cookie被偷呢?
从IE6开始,微软就在他的浏览器上加入了HttpOnly Cookie的支持
cookie的安全
就我所知有两种方法,一个就是从javax.servlet.http.Cookie派生,产生一个类对httponly进行设置
另外一种就是基于cookie的session机制,建议把所有的cookie读写,改成session读写
session的安全机制,主要是通过添加两个拦截器:日志、白名单…
其中taobao的轻量级安全框架Webx3就是这样做的…..
cookie机制里面有一个特性就是共享特性,在我理解就是在设置的域范围内可以共享这个cookie (不知道对不对)
同源策略虽然让Web的安全有了一定的提高但是在Web应用是极为不利的,
所以之后W3就提出了P3P概念跨域访问cookie
P3P解决了Web应用上的难题,但是浏览器读取P3P头打开了第三方cookie的读取开关,带来了安全的隐患。这就要防止站外提交
防止站外提交:判断Http头的Referer
但是Flash没有Referer头,这就要引申到Flash Security了,Flash的安全也是非常重要的可以说另外一个JS的安全隐患(从安全的威胁性来讲)
 Flash Security:浏览器所贯彻的域安全策略被flash所打破,客户端所做的种种过滤也同样 被 flash所打破(只要你还使用flash)。但是flash也已经感觉到了这个问题,并且时时在改进,在设计上也引入了一些比较好的安全机制,恰当 的使 用这些安全机制可以避免你的应用程序遭到攻击。
应用程序安全设计的时候应该秉承最小化原则,在flash的大部分应用中,由于功能需求就经常需要跨域获取数据
域安全是浏览器安全的基本策略,flash作为浏览器的扩展允许跨域获取数据就从根本上打破了浏览器的安全性
flash 在跨域时唯一的限制策略就是crossdomain.xml文件,该文件限制了flash是否可以跨域获取数据以及允许从什么地方跨域获取数据。
Discuz 论坛存在一个flash CSRF的Bug,由于Discuz!对flash跨域策略文件及上传图片文件处理不严导致可以绕过formhash及Referer的限制,导致csrf攻击.
这里稍微提一下Discuz的一类论坛的formhash技术,
formhash:类似于验证码,防止网站外部提交数据。
我们回到上面的CSRF攻击,额好像讲的差不多了,这里可以提一下JS的劫持技术
JS劫持技术:针对Json动态数据接口的攻击方式,也是一种变现的CSRF攻击
劫持技术还有DNS劫持技术Dll劫持技术等等,额,原理也挺简单,不过这些跟CSRF不搭边,就不去讲了。
———————————————————————————————————–
防御原理:
上面讲了很多关于攻击啊,现在讲讲Webx3的CSRF防御原理
Webx3使用form service处理和验证表单,其中一点很重要的是要禁用GET请求,因为未使用form service来处理的表单将无法自动禁用GET请求。
注意,禁用GET提交表单,只能增加CSRF攻击的困难,但不能杜绝这种攻击。
下面讲一下它的CSRFToken校验的具体过程
1. 通过一个pull tool实现在模板和session中生成CSRF Token,随机生成的csrfToken 会在session存在一个副本,以 便于校验,值得注意的是同一请求中csrfToken只会生成一遍,所以多次调 用$csrfToken.hiddenField将产生完全一样的结果;
2.通过pipeline value实现对比request和session中的csrfToken,注意仅在request中存在token时,才会对这个token进行验证,这样你是不是觉得很Bug,其实不然!如果不是这样,那么那些普通的、非表单提交的请求也会被拒绝。

3. 想到了吧,对,就是要校验request是否存在token,对于不存在csrfToken的提交表单中,会使用validator来验证,在 配置文件 中定义一个form service的validator验证request中是否存在csrfToken。当然每一个group中都要这么设置是非常麻 烦的,你可以定义一个公用的parent group 以后继承的每一个group都会自动生成validator验证。
对于不使用form service的还可以进行手工测试
if(!CsrfToken.check(request)){
return;
}
CSRFToken只能使用一次,这样就防止了表单的刷新过后的重复提交
(在表单提交以后,网站进行一次外部重定向,即使用户点了浏览器上的“刷新”按钮,也不会产生重复提交表单)
然而,如果你利用cookie的session机制,把csrfToken保存到cookie中,只要让表单和cookie同时被提供给网站即可实现攻击
所以csrfToken必须保存在服务器端,Webx3的session机制可以扩展,你可以创建一个基于服务端存储的session store。
Webx3 CSRF token验证机制,默认最多支持8个表单同时开启,这个在多表单提交的时候很关键,
可以在pipeline里面进行设置,如果设置过小可能会冲掉前面的,会使表单提交失败。
这 里要顺便讲讲Http Header的安全,其实在前面的几个学习笔记中已经有提到了在RC中添加<basic />会自动生成一个 respone-header-security-filter的过滤器就能够防止CRLF Injection和Http Header过大引起的拒绝 服务攻击



CSRFTester:一款CSRF漏洞的安全测试工具

CSRFTester:一款CSRF漏洞的安全测试工具

发布: 2011-5-11 09:43 | 作者: 网络转载 | 来源: 领测软件测试网采编 | 查看: 131次 | 进入软件测试论坛讨论
然后进行代理设置,如下图-4所示:
图-4
  此处我们设置CSRFTester代理地址为127.0.0.1 ,端口为8008。代理设置完成,就可以使用CSRFTester工具了。
  步骤2: 使用合法账户访问网站
  首先打开CSRFTester工具,点击Start Recording,如下图-5所示,CSRFTester会将我们之后使用浏览器访问的所有页面,表单之类进行抓取记录。
图-5
  然后打开火狐浏览器,访问我们要测试的网站,CSRFTester工具会将所有访问的链接抓取,如下图-6所示,我们访问wordpress的新增账户页面。
图-6
  我们新增一个账户test,如下图-7所示,为网站目前的存在的账户。
图-7
  步骤3:通过CSRF修改并伪造请求
  CSRTTest将所有的页面表单都抓取下来了,等到抓取到了我们要做测试的页面时,就可以点击Stop Recording ,停止抓取URL,并开始修改相应的表单进行测试,如下图-8所示:
图-8
  Stop Recording之后,我们点击要测试的URL,然后修改相应的表单信息,如下图-9所示:
图-9
  如上图-9所示为我们抓取的增加用户的页面,红色区域为增加用户的表单信息,现在我们修改表单信息并提交,如果能够增加用户成功,则说明网站存在CSRF漏洞。

如何防范CSRF漏洞——测试篇

如何防范CSRF漏洞——测试篇

字体:        | 上一篇 下一篇 | 打印  | 我要投稿  | 推荐标签: Web测试 安全测试
CSRF(Cross Site Request Forgey)是排在OWASP Top10第5位的漏洞,它迫使已被认证的用户在Web系统上执行其所不欲的操作。这种攻击依赖于以下:
  1) Web浏览器对会话相关信息的处理方式(如cookie或Http认证信息)
  2) 攻击者对正确的Web系统的URL的了解;
  3) 应用会话管理仅依赖于浏览器所了解的信息;
  4) 一些HTML的tag会导致对http(s)资源的直接访问其中,前3点是确认系统是否存在该漏洞的主要前提,第4点则是用来帮助攻击者利用该漏洞的。
  第1点:浏览器自动发送用于识别用户会话的信息,假设site是一个Web应用站点,victim是一个已经在该系统上经过认证的用户。在server的响应中,site发送一个带有代表victim身份的cookie给victim,原则上,一旦浏览器接收到了服务器发送的cookie,就会在后面对站点的访问中都带上这个cookie;
  第2点:如果应用在URL中没有使用会话相关的信息,那就意味着应用的URL,它们的参数,相应的值可以被识别。
  第3点:是指诸如cookie、或者是基于http的认证信息,存放在浏览器中后,就会包含在后面的每次请求中。
  下面,我们用Get方法在做个例子,如果用户已经通过了认证,那么在他做下一次请求时,请求数据中会自动加上cookie
GET请求一般会有多种原因产生,
  * 用户真正在访问Web系统;
  * 用户在访问地址栏中切实敲入了URL;
  * 用户点击了一个连接指向了这个URL;
   这些调用对于系统来说是无法区别的,特别的,第三种方式相对来说是极为危险的,有很多种方法可以用来仿造连接的真实属性,连接可以被嵌入到一封邮件中, 或者在某个恶意网站上,看上去这个连接好像是在访问另一个网站,而事实上却是被引到了Web系统的访问上。如果用户点击了连接,由于它已经被系统认证通过 了,浏览器就会对系统提交一个待用认证信息的GET请求。这就在系统上完成了一个操作(尽管这个操作不是用户本身所期望做的)。
 攻击者还可以通过Web的一些标记,注入img来达到这个目的。举个例子,假设攻击者发给用户一封邮件,引诱用户访问了一个URL,而这个URL的页面含有下面的HTML:
<html><body>
...
<img src=”https://www.company.example/action” width=”0” height=”0”>
...
</body></html>
那么用户在点击这个URL时,浏览器将会做什么呢,它将会尝试显示一个宽度为0的图片,而事实上这是访问了www.company.example/action,显然如果浏览器并没有阻断下载img的图片,那么该动作就会执行了。
  该问题的存在是基于以下一些事实:
  * 有一些HTML的tags可能会执行一些脚本(如img)
  * 浏览器本身并不能识别img这个tag里的值是否是真实合法的图片
  * 不管图片是否是在网站本地或是其他网站,图片都会被下载
  举个例子:
  假设用户要登录到某个防火墙web管理系统,登录时,用户必须对系统进行身份验证,所以用户的会话信息会保存在cookie中。假设我们的防火 墙管理系统允许认证过的用户根据防火墙规则的排号来删除规则(甚至允许用户输入“*”来删除所有的规则),那么下一步显示的就是删除页面,假定表单下面就 会提交一个GET请求,是以如下的格式:
  https://[target]/fwmgt/delete?rule=1
  或https://[target]/fwmgt/delete?rule=*
  我们举的例子很简单,仅仅是为了说明CSRF的存在。
那么,如果用户输入了“*”,然后按取了Delete键,那么就提交了如下的GET请求,
  https://www.company.example/fwmgt/delete?rule=*
  同时就删除了所有的防火墙规则。
显然,如果用户直接在地址栏中输入https://[target]/fwmgt/delete?rule=*,或者通过某个链接转接到这个url,或者如上面所说,把链接隐藏在img这个tag后面,诸如此种方法,如果用户在点击这个连接的时候,已经登录进了防火墙管理系统,显然这个访问就能成功奏效,从而达到了删除所有规则的目的。
  让我们想象一下,如果这样的攻击用于一些敏感系统,竞拍系统,或者是银行转账等等,所造成的后果将会多大。
  应对方法:
  对于用户来说,由于CSRF漏洞极为普遍,所以在我们的日常使用中要注意以下几点:
  * 保证系统使用完就注销登录的习惯;
  * 不要使用浏览器的保存用户名/密码的功能,不要使用网站的“记住我”功能
  * 不要使用同一个浏览器浏览普通网页和你的关键性Web系统
  对于开发人员来说,如上所述,由于将会话相关的信息放入了URL才造成了上述的问题,那么如果我们在URL层面增加会话特定的信息,那么对攻击 者来说就增加了了解URL结构的难度。另外,我们还可以尽可能的使用POST,而不是GET;尽可能多的增加一些诸如“你确定要这样做吗?”的页面等……
  说到这,想必大家都已明白CSRF是什么了,下面我们来看下针对这个漏洞,作为测试人员该如何去测试。
  一般的测试用例应该如下构建:
  1. 假设u是需要被测试的URL,例如u =http://www.example.com/action;
  2. 构建一个包含了访问上述URL信息的html页面;
  3. 确保合法用户已经登录了系统;
  4. 诱使该用户在自己不知情的情况下访问上述URL;
  5. 确认是否执行了该操作。


如何防止CSRF注入式攻击

如何防止CSRF注入式攻击

0x01 什么是CSRF攻击
    CSRF是Cross Site Request Forgery的缩写(也缩写为XSRF),直译过来就是跨站请
求伪造的意思,也就是在用户会话下对某个CGI做一些GET/POST的事情——这些事情用
户未必知道和愿意做,你可以把它想做HTTP会话劫持。
    网站是通过cookie来识别用户的,当用户成功进行身份验证之后浏览器就会得到一个标
识其身份的cookie,只要不关闭浏览器或者退出登录,以后访问这个网站会带上这个
cookie。如果这期间浏览器被人控制着请求了这个网站的url,可能就会执行一些用户不想
做的功能(比如修改个人资料)。因为这个不是用户真正想发出的请求,这就是所谓的请
求伪造;呵呵,因为这些请求也是可以从第三方网站提交的,所以前缀跨站二字。
    举个简单的例子,某个bbs可以贴图,在贴图的URL中写入退出登陆的链接,当用户阅读
这个帖子之后就会logout了,因为用户以自己的身份访问了退出登陆链接,在用户看来是帖
子里面有一张有问题的“图片”,而不是想要退出,但程序就会认为是用户要求退出登陆
而销毁其会话。这就是传说中的CSRF攻击了。
    不要小看CSRF哦,记得以前L-Blog就存在一个CSRF漏洞(当时还不知道这个概
念:p),它添加管理员是这样的一个链接:http://localhost/L-Blog/admincp.asp?
action=member&type=editmem&memID=2&memType=SupAdmin
,我们只要构造好ID想
办法让管理员访问到这个URL就可以了;还有Google那个CSRF漏洞[1],将导致邮件泄
漏;另外,不要以为只有XSS才能爆发蠕虫,只要条件合适,CSRF同样是有可能的。

0x02 威胁来自哪里
    贴图只是GET的方式,很多时候我们需要伪造POST的请求。一个办法是利用跨站,
当然目标站点可能不存在跨站,这个时候我们可以从第三方网站发动攻击。
    比如我要攻击一个存在问题的blog,那就先去目标blog留言,留下一个网址,诱其主
人点击过来(这个就要看你的忽悠本事咯:p),然后构造个HTML表单提交些数据过去。
    多窗口浏览器就帮了一点忙。
    多窗口浏览器(firefox、遨游、MyIE……)便捷的同时也带来了一些问题,因为多窗
口浏览器新开的窗口是具有当前所有会话的。即我用IE登陆了我的Blog,然后我想看新闻
了,又运行一个IE进程,这个时候两个IE窗口的会话是彼此独立的,从看新闻的IE发送请
求到Blog不会有我登录的cookie;但是多窗口浏览器永远都只有一个进程,各窗口的会话
是通用的,即看新闻的窗口发请求到Blog是会带上我在blog登录的cookie。
    想一想,当我们用鼠标在Blog/BBS/WebMail点击别人留下的链接的时候,说不定一场
精心准备的CSRF攻击正等着我们。

0x03 发起CSRF攻击
    从第三方站点利用POST发动CSRF攻击就是利用Javascript自动提交表单到目标CGI。
每次都去写表单不是很方便,辅助进行的工具有XSS POST Forwarder[2]和CSRF Redirector[3],这里我也写了相应的ASP版本[4]。使用的时候只要把提交的url和参数传
给它,它就会自动POST到目标。
    比如我要提交一些数据到
www.0x54.org/a.asphttp://www.0x54.org/lake2/xss_post_forwarder.asp?
lake2=http://www.0x54.org/a.asp&a=123&b=321&c=%26%23%25

(这里要自己考虑URL编码哦)
    不过实际攻击的时候你得动动脑子:如何才能把用户诱骗到我们的网页来。

0x04 一个实例
    因为CSRF不如XSS那么引人注目,所以现在找一个存在CSRF的Web应用程序还是很
容易的。这次我们的目标是百度,just for test。
    随便你用什么办法,让一个已登陆百度的用户访问一下这个URL:
    http://www.0x54.org/lake2/xss_post_forwarder.asp?
lake2=http://passport.baidu.com/ucommitbas&u_jump_url=&sex=1
&email=CSRF@baidu.com&sdv=&zodiac=0&birth_year=0&birth_month=0&birth_day=0
&blood=0&bs0=%C7%EB%D1%A1%D4%F1
&bs1=%C7%EB%D1%A1%D4%F1&bs2=%CE%DE&txt_bs=&birth_site=%3B%3B
&b%3Drs0=%C7%EB%D1%A1%D4%F1
&rs1=%C7%EB%D1%A1%D4%F1&rs2=%CE%DE&txt_rs=&reside_site=%3B%3B

    呵呵,然后看看那人个人资料是不是被修改了。这里有点郁闷,当那人访问URL后浏览
器会返回到资料修改成功的页面,我们就被发现了。那么,有没有办法不让浏览器刷新
呢?
    有。
    一个办法是用iframe,构造这样的HTML代码:
    <iframe width=0 height=0 src="http://www.0x54.org/lake2/xss_post_forwarder.asp?
lake2=http://passport.baidu.com/ucommitbas&u_jump_url=&sex=1
&email=CSRF@baidu.com&sdv=&zodiac=0&birth_year=0&birth_month=0
&birth_day=0&blood=0&bs0=%C7%EB%D1%A1%D4%F1
&bs1=%C7%EB%D1%A1%D4%F1&bs2=%CE%DE&txt_bs=
&birth_site=%3B%3B&b%3Drs0=%C7%EB%D1%A1%D4%F1
&rs1=%C7%EB%D1%A1%D4%F1&rs2=%CE%DE&txt_rs=&reside_site=%3B%3B"></iframe
>
    还有一个办法就是用flash了。

0x05 CSRF With Flash
    flash是可以提交数据到任意URL的,打开盗版的 Adobe flash CS 3 Professional,新
建一个 flash文件(ActionScript 3.0) ,在默认的图层上点右键选动作,然后把以下代码
添加进去:

       import flash.net.URLRequest;
       import flash.system.Security;
       var url = new URLRequest("http://www.0x54.org/lake2");
       var lake = new URLVariables();
       lake = "a=lake2";
       url.method = "POST";
       url.data = lake;
       sendToURL(url);
       stop();
    导出为swf文件,访问之,抓包看看效果咯:
http://www.0x54.org/lake2/flash/test1.html
    每次都去写as和编译swf很麻烦的,根据CSRF Redirector的思路我写了一个类似的
flash程序[5],再拿百度来试试效果,访问带如下HTML的网页:
    <EMBED src="http://www.0x54.org/lake2/flash/flash_hacking.swf?
f=1&t=http://passport.baidu.com/ucommitbas
&d=u_jump_url%3D%26sex%3D1%26email%3DCSRF@
baidu.com%26sdv%3D%26zodiac%3D0%26birth_year%3D0%26birth_month
%3D0%26birth_day%3D0%26blood%3D0%26bs0%3D%25C7%25EB%25D1
%25A1%25D4%25F1%26bs1%3D%25C7%25EB%25D1%25A1%25D4%25F1
%26bs2%3D%25CE%25DE%26txt_bs%3D%26birth_site%3D%253B%253B
%26b%253Drs0%3D%25C7%25EB%25D1%25A1%25D4%25F1%26rs1%3D
%25C7%25EB%25D1%25A1%25D4%25F1%26rs2%3D%25CE%25DE
%26txt_rs%3D%26reside_site%3D%253B%253B"></EMBED
>
(还是要注意URL二次编码)
    这里不要只局限于发请求,其实flash是可以得到返回内容的,要是返回内容有敏感信
息的话,就可以读出来发送到我们控制的Web去。当然,这个得看目标站点是否让flash
跨域取内容了。

0x06 检测CSRF
    检测CSRF漏洞都是体力活了,先抓取一个正常请求的数据包,然后去掉referer字段
再重新提交,如果还是有效那基本上就存在问题了。当然参数可能含有不能预测的参数(比如userid什么的),这个时候就看这个不可预测的参数能不能通过其他手段比如flash
拿到,如果能,呵呵,则还是存在问题。还有就是试着改post为get,因为有些程序是不
区分get/post的。
    应用程序的功能和返回形式都各不相同,所以想自动化测试CSRF漏洞还是有点困难
的,OWASP上面有一个叫做CSRFTester的工具不妨拿来一试[6]

0x07 防御CSRF
    在Web应用程序侧防御CSRF漏洞,一般都是利用referer、token或者验证码,Nexus
的文章[7]已经写的很全面了;superhei也有提出bypass的思路[8],请参考他们的文章。

    还有一个思路是在客户端防御,貌似可以做成一个类似HTTP Watch的软件,挂在浏览
器上拦截或者过滤跨域的cookie
欢迎转载,转载请注明:转载自陈善波 [ http://justwannaloveyou.cnblogs.com/]

浅谈CSRF攻击方式

浅谈CSRF攻击方式

来源:hyddd
一.CSRF是什么?
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
二.CSRF可以做什么?
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。
三.CSRF漏洞现状
CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出 CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站),YouTube和百度HI……而现在,互联网 上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”。
四.CSRF的原理
下图简单阐述了CSRF攻击的思想:
浅谈CSRF攻击方式从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了……)
3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
上面大概地讲了一下CSRF攻击的思想,下面我将用几个例子详细说说具体的CSRF攻击,这里我以一个银行转账的操作作为例子(仅仅是例子,真实的银行网站没这么傻:>)
示例1:
银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
危险网站B,它里面有一段HTML的代码如下:
1
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块…
为什么会这样呢?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中 的<img>以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏 览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com /Transfer.php?toBankId=11&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账 操作),所以就立刻进行转账操作……
示例2:
为了杜绝上面的问题,银行决定改用POST请求完成转账操作。
银行网站A的WEB表单如下:
1
2
3
4
5
<form action="Transfer.php" method="POST">
    <p>ToBankId: <input type="text" name="toBankId" /></p>
    <p>Money: <input type="text" name="money" /></p>
    <p><input type="submit" value="Transfer" /></p>
  </form>
后台处理页面Transfer.php如下:
1
2
3
4
5
6
7
<?php
    session_start();
    if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money']))
    {
        buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']);
    }
  ?>
危险网站B,仍然只是包含那句HTML代码:
1
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
和示例1中的操作一样,你首先登录了银行网站A,然后访问危险网站B,结果…..和示例1一样,你再次没了1000块~T_T,这次事故的原因是: 银行后台使用了$_REQUEST去获取请求的数据,而$_REQUEST既可以获取GET请求的数据,也可以获取POST请求的数据,这就造成了在后台 处理程序无法区分这到底是GET请求的数据还是POST请求的数据。在PHP中,可以使用$_GET和$_POST分别获取GET请求和POST请求的数 据。在JAVA中,用于获取请求数据request一样存在不能区分GET请求数据和POST数据的问题。
示例3:
经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用$_POST,只获取POST请求的数据,后台处理页面Transfer.php代码如下:
1
2
3
4
5
6
7
<?php
    session_start();
    if (isset($_POST['toBankId'] && isset($_POST['money']))
    {
        buy_stocks($_POST['toBankId'], $_POST['money']);
    }
?>
然而,危险网站B与时俱进,它改了一下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
  <head>
    <script type="text/javascript">
      function steal()
      {
               iframe = document.frames["steal"];
               iframe.document.Submit("transfer");
      }
    </script>
  </head>
 
  <body onload="steal()">
    <iframe name="steal" display="none">
      <form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">
        <input type="hidden" name="toBankId" value="11">
        <input type="hidden" name="money" value="1000">
      </form>
    </iframe>
  </body>
</html>
如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块……因为这里危险网站B暗地里发送了POST请求到银行!
总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一个<img>就 可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很 严重。
理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!
五.CSRF的防御
我总结了一下看到的资料,CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。
1.服务端进行CSRF防御
服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。
(1).Cookie Hashing(所有表单都包含同一个伪随机值):
这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了:>
1
2
3
4
5
<?php
    //构造加密的Cookie信息
    $value = “DefenseSCRF”;
    setcookie(”cookie”, $value, time()+3600);
?>
在表单里增加Hash值,以认证这确实是用户发送的请求。
1
2
3
4
5
6
7
8
9
<?php
    $hash = md5($_COOKIE['cookie']);
  ?>
  <form method=”POST” action=”transfer.php”>
    <input type=”text” name=”toBankId”>
    <input type=”text” name=”money”>
    <input type=”hidden” name=”hash” value=”<?=$hash;?>”>
    <input type=”submit” name=”submit” value=”Submit”>
  </form>
然后在服务器端进行Hash值验证
1
2
3
4
5
6
7
8
9
10
11
12
<?php
        if(isset($_POST['check'])) {
             $hash = md5($_COOKIE['cookie']);
             if($_POST['check'] == $hash) {
                  doJob();
             } else {
        //...
             }
        } else {
      //...
        }
      ?>
这个方法个人觉得已经可以杜绝99%的CSRF攻击了,那还有1%呢….由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,这就另外的1%。一般的攻击者看到有需要算Hash值,基本都会放弃了,某些除外,所以如果需要100%的杜绝,这个不是最好的方法。
(2).验证码
这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄….这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。
(3).One-Time Tokens(不同的表单包含一个不同的伪随机值)
在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提 交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单 都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。
以下我的实现:
1).先是令牌生成函数(gen_token()):
1
2
3
4
5
6
7
<?php
     function gen_token() {
    //这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。
    //这个可以参考我写的Findbugs笔记中的《Random object created and used only once》
          $token = md5(uniqid(rand(), true));
          return $token;
     }
2).然后是Session令牌生成函数(gen_stoken()):
1
2
3
4
5
6
7
8
9
10
11
12
<?php
       function gen_stoken() {
      $pToken = "";
      if($_SESSION[STOKEN_NAME]  == $pToken){
        //没有值,赋新值
        $_SESSION[STOKEN_NAME] = gen_token();
      }   
      else{
        //继续使用旧的值
      }
       }
     ?>
3).WEB表单生成隐藏输入域的函数:
1
2
3
4
5
6
7
<?php
       function gen_input() {
            gen_stoken();
            echo “<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\”
                 value=\”" . $_SESSION[STOKEN_NAME] . “\”> “;
       }
     ?>
4).WEB表单结构:
1
2
3
4
5
6
7
8
9
10
<?php
          session_start();
          include(”functions.php”);
     ?>
     <form method=”POST” action=”transfer.php”>
          <input type=”text” name=”toBankId”>
          <input type=”text” name=”money”>
          <? gen_input(); ?>
          <input type=”submit” name=”submit” value=”Submit”>
     </FORM>
5).服务端核对令牌:
这个很简单,这里就不再啰嗦了。
上面这个其实不完全符合“并行会话的兼容”的规则,大家可以在此基础上修改。

其实还有很多想写,无奈精力有限,暂且打住,日后补充,如果错漏,请指出:>
PS:今天下午写这篇文档的时候FF崩溃了一次,写了一半文章的全没了,郁闷好久T_T…….
转载请说明出处,谢谢[hyddd(http://www.cnblogs.com/hyddd/)]

CSRF 攻击的应对之道

CSRF 攻击的应对之道

(2012-08-21 10:15:01)
标签:

杂谈

分类: WEB开发
简介: CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,该攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作,有很大的危害性。

CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作。比如说,受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。
在讨论如何抵御 CSRF 之前,先要明确 CSRF 攻击的对象,也就是要保护的对象。从以上的例子可知,CSRF 攻击是黑客借助受害者的 cookie 骗取服务器的信任,但是黑客并不能拿到 cookie,也看不到 cookie 的内容。另外,对于服务器返回的结果,由于浏览器同源策略的限制,黑客也无法进行解析。因此,黑客无法从返回的结果中得到任何东西,他所能做的就是给服务 器发送请求,以执行请求中所描述的命令,在服务器端直接改变数据的值,而非窃取服务器中的数据。所以,我们要保护的对象是那些可以直接产生数据改变的服 务,而对于读取数据的服务,则不需要进行 CSRF 的保护。比如银行系统中转账的请求会直接改变账户的金额,会遭到 CSRF 攻击,需要保护。而查询余额是对金额的读取操作,不会改变数据,CSRF 攻击无法解析服务器返回的结果,无需保护。
 
在业界目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。下面就分别对这三种策略进行详细介绍。
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。
然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。
即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 <input type=”hidden” name=”csrftoken” value=”tokenvalue”/>,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。
该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
然而这种方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。