测试环境CSRF错误DEBUG

测试环境CSRF错误DEBUG

昨天打包集成后,部署到测试环境出现了一些问题,错误是部分接口响应请求失败或者无访问权限,最后发现的错误原因并不重要,重要的是寻找问题方法的改进。

测试环境是一个Win环境,在发生问题之后是比较懵的,通过返回的错误码无法定位问题代码在哪里,只好在页面上点来点去,看看网络请求参数。而且一旦部署之后PHP源码就被加密了,不方便直接通过代码DEBUG,由于我认为自己没有修改重要文件不应该出现这样的问题,所以认为是测试环境的问题。于是我找到了Leader,却发现自己无法准确的描述问题,只好模糊的说一些接口无法请求等,这时我才发现自己都没有搞清楚。由于我猜测是前端的问题,Leader又去帮忙找了前端的同学,顺便给前端提了一些其他的BUG。

由于问题原因不确定,所以继续排查,我决定从后端出发把问题排查清楚。当目光聚焦之后,做事的目的性就更强了,我开始仔细阅读日志,发现问题并不是和想象的那样无从下手,因为错误日志里面就记录了调用的回溯日志,通过回溯记录很明显的就可以看到在哪个文件调用的函数。由于源码编译了,我将本地的真正源码上传替换了被编译的源码,这样测试环境就可以改代码DEBUG了,问题定位在了一个获取refer的函数上,这个函数返回了false造成了 400 错误码,然而这个问题在本地没有出现。

随后我对比测试和本地的网络请求有什么差异,也没有什么发现。那么一定是环境造成的问题,我深入到那个refer函数,发现是由于$_SERVER[‘HTTP_HOST’] 的值引起的问题,测试环境的URL使用 localhsot访问,但是 $_SERVER[‘HTTP_HOST’] 的值却是 127.0.0.1,而本地环境的$_SERVER[‘HTTP_HOST’]值与URL地址栏一致,框架在检测refer的时候认为host不一致可能是一种跨站攻击,因此响应错误码,CSRF也是类似的道理。

那么是什么原因造成了 HTTP_HOST这个值不同呢?对比了两个php版本号略有小版本差异,但是HTTP_HOST的信息应该是上游的Nginx给的,到底是谁的问题呢?打开wireshark,监听了所有php-cgi的端口,发现了测试环境中Nginx在使用localhost访问时,传给php-cgi的 HTTP_HOST值是 127.0.0.1,故此问题出现在Nginx。

追溯Nginx,这时候发生了问题,测试环境的Nginx可能做了修改,不允许查看版本号和编译信息。本次DEBUG暂停在此。

准确来说这只是一个开发环境引起的小问题,影响范围可能仅限于使用 localhost访问管理后台,但是花费了我一天的时间,还向leader汇报了此问题难解。错误处理方式还应当有所改进。

1、习惯性的不看日志和提示,在编程早期养成的坏习惯
2、问题现场的资料可以解决大多数问题,即问题具体表现和日志
3、尽快定位问题方向进行排查,无方向乱撞会导致问题无法解决和焦虑。例如这个问题发生的时候,一开始就有些拒绝排查,认为是打包环境引起的问题。但是又认为可能是后端的问题,也可能是前端的问题,反正不知道是谁的问题。加之debug不方便,导致一直没有进展。先明确问题方向,然后开始找原因,然后开始利用已知信息debug,日志很重要。

此外,也有一些其他的收货,例如学会了简单使用wireshark进行抓包,深入了解了YII的CSRF和COOKIE加密逻辑,以及为什么要有CSRF。

这里记录一下CSRF的收获。

1、CSRF解决了什么问题?

CSRF的存在是为了防止跨站攻击的,例如用户登录了银行网站,此时攻击者设计一个自己的网页,在网页上让用户点击某个图片等,实际上是一次post请求,请求银行网站将他的钱转移到骗子账户。当然,实际应用没这么简单,这是一个简单示例说明。那么我们需要一个手段来解决这个问题,这就是CSRF解决的问题。

2、CSRF是如何做到的?

那么CSRF的作用就是在请求时要求用户在表单中携带一个和COOKIE相同的值,如果值不同,那么认为这是一次非法请求,从而达到防止跨站攻击的目的。

3、CSRF的缺点

每次请求都需要携带一个CSRF的值,这在GET请求中放在URL中会很不好看,而且意义不大,因为有通常CSRF只用于针对POST请求的过滤,从元能力来说是针对用户资源的增、删、改操作进行防范(ps:查也通常不用防,反正都是用户自己看),具有这一类元能力的操作接口都需要开发者自己注意,放到对应的请求类型里面去,否则就有被跨站攻击的风险。

COOKIE加密比较简单,就是用服务端的一个key将COOKIE计算一个HASH值,连同COOKIE原文一起返回到客户端,当客户端请求的时候将客户端的COOKIE原文和key在一起计算HASH然后比对客户端传过来的HASH是否一致,不一致则说明COOKIE被伪造了。

发表评论

邮箱地址不会被公开。 必填项已用*标注