北京三个程序员信息技术有限公司
PHP安全编码——书写安全的代码
7、跨站请求伪造攻击的防范
2024-02-13
提问
问题1:什么是跨站请求伪造攻击?
问题2:跨站请求伪造攻击与跨站脚本攻击有什么区别?
问题3:如何防范跨站请求伪造攻击?
课程单元
1、什么是跨站请求伪造攻击
2、一些跨站请求伪造攻击的例子
3、跨站请求伪造攻击的防范
1、什么是跨站请求伪造攻击
跨站请求伪造攻击,简写作CSRF,在用户在当前已登录的Web网站上,假冒用户身份,自动执行某些操作。
跨站请求伪造攻击,黑客不需要获得当前用户的cookie或者用户的身份,而是通过用户自己的浏览器,来自动执行假冒的操作。
2、一些跨站请求伪造攻击的例子
2.1、一个假冒用户添加好友的例子
例如,一个论坛,添加好友的代码为:
<form action=“addfriend.php” method=“get”>
添加谁为好友:<input type=“text” name=“username” />
</form>
那么,我们向用户发送一个站内信,内容为:
<img src=“addfriend.php?username=黑客用户” />
当用户查看该站内信时,就自动执行了添加用户的请求,将黑客用户加为好友了。
2.2、改进的用户添加好友的例子
我们将添加好友改为post方式:
<form action=“addfriend.php” method=“post”>
添加谁为好友:<input type=“text” name=“username” />
</form>
这样,用户就不能用简单的发送:“addfriend.php?username=黑客用户”的方式来实施攻击,因为这只是get方式,而添加代码已经改成post方式了。
但是,黑客依然可以用js的方式,来实施攻击,比如把下面的代码发送给用户:
<form id=“addform” action=“addfriend.php” method=“post”>
<input type=“hidden” name=“username” value=“黑客用户” />
</form>
<script>addform.submit();</script>
用户访问到这部分代码时,依然会自动以post的方式提交添加用户的请求。
2.3、一个假冒用户删除帖子的例子
例如,一个论坛,删除帖子的代码为:
<a href=“tipsdel.php?tipId=123”>删除该帖子</a>
同样,我们也可以伪造一个站内信,发送给用户,而自动删除用户的帖子:
<img src=“tipsdel.php?tipId=123” />
当用户查看该站内信时,就自动请求了tipsdel.php,从而自动将该帖子删除了。
特别是,如果该用户是论坛管理员,很可能通过这种方法,就能将论坛所有帖子都给删除掉。
跟刚才的方式一样,即使我们将删除帖子改为只接受post方式,目前也没法防范这种攻击。
以此类推,只要用户登录了网站,如果没有进行防范,黑客用户完全可以用类似的简单办法,来自动执行添加用户、删除帖子、发送邮件等各种本来只有用户自己确认后才能执行的操作。
3、如何防范跨站请求伪造攻击
3.1、防范难点
难点1:攻击是通过已经登录的用户,采用自己的浏览器来执行的,黑客并不需要获取用户的任何信息,黑客也不需要实际执行任何攻击操作,完全是用户不知情的情况下自动执行的,因此防范上难度比较大。
难点2:无法通过服务器过滤用户输入的方式来防范,比如前面的例子中,采取类似防范跨脚本攻击的方式,过滤站内信的html的方式来防范攻击是无效的。
例如,黑客可以给用户发送这样的站内信:
点击下面的链接:http://黑客网站/hack.html,如果链接不能点击,请复制该链接,打开一个新的窗口,粘贴链接。
这样的话,黑客可以把攻击代码挪到自己的网站上,用户打开黑客网站时,就自动请求了原始网站,而原始网站是没法对黑客网站的html代码进行过滤的。同时,因为原始网站用户还没关掉,用户是开的新窗口打开黑客网站的,所以原始的网站用户的登录信息依然存在,所以黑客依然可以实施同样的攻击。
3.2、防范方法1:判断请求来源
在服务器上,addfriend.php、tipsdel.php中,都增加来源网站的判断,即判断一下$_SERVER[“HTTP_REFERER”]是否是自己网站,如果不是,则停止执行后续的代码。这样可以在一定程度上避免黑客将用户诱导到新窗口中的自己网站,然后再执行攻击的情况。
但是,$_SERVER[“HTTP_REFERER”]是可以伪造的,同时,有些情况下,浏览器不会发送或者发送给php的$_SERVER[“HTTP_REFERER”]是不准确的,因此,php不能完全信任这种方法。
3.3、防范方法2:增加验证码
例如,get方式添加好友的代码,我们改为这样:
<form action=“addfriend.php” method=“get”>
添加谁为好友:<input type=“text” name=“username” />
<input type=“hidden” name=“token” value=“123” />
</form>
其中,token是服务器生成的,每次用户添加好友时,都生成不一样的值,同时把这个值存入session中。再执行addfriend.php时,首先判断$_POST[“token”]与$_SESSION[“token”]是否一致,如果不一致则不执行添加操作。
因为token是每次都重新生成的,黑客没法提前知道token是多少,因此也就没法通过发一个自动执行代码给用户的方式来实现攻击。
例如,黑客发送这样的代码给用户:
<img src=“addfriend.php?username=黑客用户&token=123” />
因为token是一次性的,每次都在变化,黑客没法提前发送一个正确的token给用户,因此也就无法实现攻击。
同样,对于post方式,服务器也可以使用类似的token的方式来进行防范工作。
这种做法是目前流行的针对跨站请求伪造攻击较为有效的防范方法。
关注我们,获取更多资讯