防止CSRF攻击与针对CSRF方法接口测试的调整

简介: 防止CSRF攻击与针对CSRF方法接口测试的调整

1 CSRF攻击介绍


CSRFCross-siterequest forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。


我们用一个POST请求做个比方,黑客可以构建自己的网页Form界面,Formaction指向要攻击的网站,Form中的元素的name与攻击的网站的值保持一致,从而达到CSRF攻击的目的。


比如被攻击的网站是http://www.a.com,页面提交网站是http://www.a.com/input.html,提交后处理的网站是http://www.a.com/display.jspinput.html的网页内容如下:

<form action="display.jsp" method="post" >
地址:<input type="text" name="address"  id="id_address" size="20" maxlength="100"  required />
电话:<input type="text" name="phone"  id="id_ phone" size="20" maxlength="100"  required />
</form>


现在我们在本地构造一个界面充当input.html

<form action="http://www.a.com/display.jsp" method="post"  >
地址:<input type="text" name="address"  id="id_address" size="20" required />
电话:<input type="text" name="phone"  id="id_ phone" size="20"required />
</form>


这样黑客就可以用自己的页面向http://www.a.com/display.jsp发起攻击了。我在我的著作《软件测试技术实战设计、工具及管理》一书中序言中曾经提及这么一件事情:


2000年我所在的公司与CCTV‘开心辞典’目组合作开发网上答题的项目,这是一个智力娱乐性节目,我编写了前端的答题代码,考虑到可能有人用计算机程序来答题,比如编写一个死循环,一直选择B(或A C D),这可以使答题的速度很快,命中率也非常高,为此我选用JavaScript过滤了使用死循环的答题者。可是到了开心辞典’正式使用这个软件的时候,发现仍然有人使用死循环来答题,可我的程序是正确的。后来在一次聊天模块中,通过登录账号我找到了这位‘达人’,他说我们前端的确没有漏洞,他是通过自己编写的程序绕过我们前端进入到系统后端的,而我们的后端并没有进行校验。当初如果有专业的测试人员,这个Bug是有可能避免的。”


其实这就是一个很典型的CSRF攻击。


2 Django是如何防范CSRF攻击的


首先我们确认setting.py中的这个开关是否代开。

MIDDLEWARE = [
     'django.middleware.security.SecurityMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
]…
见黑体部分。


见黑体部分。然后我们在所有模板有<form>…</form>的地方都加上一个{%csrf_token%}这个标记。现在我们以登录模块来分析Django是如何防范CSRF攻击的。在此之前,我们打开一个HTTP抓包工具,我这里用的是Fiddle 4,然后我们进入登录界面,查看网页源代码会发现:

<input type='hidden' name='csrfmiddlewaretoken' value='XltpK31i171tGLIH2leLWio0xM5TY8NC56oaU58CiIc5xLfqSiiehfJDSEnZesrX    ' />


也就是说{%csrf_token%}被一个名为csrfmiddlewaretokenhidden类型给取代了。其值为“XltpK31i171tGLIH2leLWio0xM5TY8NC56oaU58CiIc5xLfqSiiehfJDSEnZesrX”一个一百位的字符串,然后我们查看Fiddle 4,会看见页面产生了一个名为csrftokencookie,其值也为XltpK31i171tGLIH2leLWio0xM5TY8NC56oaU58CiIc5xLfqSiiehfJDSEnZesrX”,如图4-1所示。

image.png

4-1 产生的cookie


如果我们刷新这个登录页面,我们会发现这100个字符串会变化的,但是cookie的值与hidden中的值保持不变。后来我查询了一些资料,发现不仅仅是Django是用这种方式处理CSRF注入的,其他大部分都是使用这种方法处理CSRF注入的。即在用户登录这个网站的时候产生一个叫做csrf tokencsrf令牌)的随机字符串,即我前面提到的100位会发生变化的字符串,然后把这csrf token放入到cookie中(所以要是用CSRF防御机制,必须打开浏览器的cookie),并且放到页面的form表单中,产生一个类似于“<input type='hidden' name='csrfmiddlewaretoken' value='csrf token'”的表单,然后在提交表单的时候验证cookie中的值是不是与hidden的值保持一致,如果保持一致,则返回200代码,否则返回403拒绝访问代码。


3 接口测试代码的调整


为了适应CSRF的加入,我们必须对我们的测试代码进行调整,由于我们对代码进行了很好的封装,所以在这里只需要调整测试代码util.pyUtil类中的run_test()方法。我先把改造后的代码展示给大家。


#运行测试接口
        # mylist测试数据
        # values登录数据
        def    run_test(self,mylist,values,sign):
                #获取测试URL
                Login_url =    self.url+"/login_action/" #login_Url为登录的URL
                run_url =    mylist["Url"] #run_url为运行测试用例所需的URL
                                  #获取csrf_token
                data =    self.s.get(Login_url)
                csrf_token =    data.cookies["csrftoken"]
                #初始化登录变量
                #获取登录数据
                username =    values.split(',')[1].strip("\"")
                password =    values.split(',')[2].strip("\"")
                #判断当前测试是否需要登录
                if sign:
                        #使用当前用户登录系统
                        payload    ={"username":username,"password":password,"csrfmiddlewaretoken":csrf_token}
                        try:
                                data =    self.s.post(Login_url,data=payload)
                        except    Exception as e:
                                   print(e)
                #运行测试接口
                try:
                        #为POST请求,由于post请求参数肯定是存在的,所以这里不判断有无参数
                        if    mylist["Method"] == "post":
                                #有请求参数
                                payload =    eval(mylist["InptArg"])
                                payload["csrfmiddlewaretoken"]    = csrf_token
data = self.s.post(run_url,data=payload)
                        #为GET请求
                        elif    mylist["Method"] == "get":
                                   if mylist["InptArg"].strip()=="":
                                           #没有请求参数
                                        data    = self.s.get(run_url)
                                   else:
                                           #有请求参数
                                           payload = eval(mylist["InptArg"])
                                        data =    self.s.get(run_url,params=payload)
                except Exception    as e:
                        print(e)
                else:
                        return    data


首先我们通过代码:“data =self.s.get(Login_url)”访问登录页面,然后通过代码“csrf_token = data.cookies["csrftoken"]”获取产生的CSRF令牌cookie。我们在初始化登录操作与执行post操作的时候把令牌参数csrf_token加入到post参数中。在初始化登录操作中代码为:

#使用当前用户登录系统
payload  ={"username":username,"password":password,"csrfmiddlewaretoken":csrf_token}
try:
       data =  self.s.post(Login_url,data=payload)


执行post操作中代码为:

#为POST请求,由于post请求参数肯定是存在的,所以这里不判断有无参数
if mylist["Method"] == "post":
#有请求参数
payload = eval(mylist["InptArg"])
payload["csrfmiddlewaretoken"] = csrf_token
data = self.s.post(run_url,data=payload)


       查看了网站上许多资料,都是要求在接口测试前利用requests.get(url,cookies=cookies)设置一个cookie,我采用了这个方法是根本行不通的,因为访问页面的时候,这个cookie是已经产生的,所以我们首先需要获取这个cookie值,然后把它放到post方法的变量中(也不是向有些网站说的再把这个cookie设置进别的页面)。

目录
相关文章
|
11月前
|
数据采集 监控 机器人
浅谈网页端IM技术及相关测试方法实践(包括WebSocket性能测试)
最开始转转的客服系统体系如IM、工单以及机器人等都是使用第三方的产品。但第三方产品对于转转的业务,以及客服的效率等都产生了诸多限制,所以我们决定自研替换第三方系统。下面主要分享一下网页端IM技术及相关测试方法,我们先从了解IM系统和WebSocket开始。
260 4
|
2月前
|
测试技术 开发者 Python
Python单元测试入门:3个核心断言方法,帮你快速定位代码bug
本文介绍Python单元测试基础,详解`unittest`框架中的三大核心断言方法:`assertEqual`验证值相等,`assertTrue`和`assertFalse`判断条件真假。通过实例演示其用法,帮助开发者自动化检测代码逻辑,提升测试效率与可靠性。
258 1
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
如何让AI更“聪明”?VLM模型的优化策略与测试方法全解析​
本文系统解析视觉语言模型(VLM)的核心机制、推理优化、评测方法与挑战。涵盖多模态对齐、KV Cache优化、性能测试及主流基准,助你全面掌握VLM技术前沿。建议点赞收藏,深入学习。
500 8
|
10月前
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
5月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
896 23
|
7月前
|
SQL 安全 测试技术
2025接口测试全攻略:高并发、安全防护与六大工具实战指南
本文探讨高并发稳定性验证、安全防护实战及六大工具(Postman、RunnerGo、Apipost、JMeter、SoapUI、Fiddler)选型指南,助力构建未来接口测试体系。接口测试旨在验证数据传输、参数合法性、错误处理能力及性能安全性,其重要性体现在早期发现问题、保障系统稳定和支撑持续集成。常用方法包括功能、性能、安全性及兼容性测试,典型场景涵盖前后端分离开发、第三方服务集成与数据一致性检查。选择合适的工具需综合考虑需求与团队协作等因素。
948 24
|
5月前
|
测试技术
软考软件评测师——可靠性测试测试方法
软件可靠性是指软件在规定条件和时间内完成预定功能的能力,受运行环境、软件规模、内部结构、开发方法及可靠性投入等因素影响。失效概率指软件运行中出现失效的可能性,可靠度为不发生失效的概率,平均无失效时间(MTTF)体现软件可靠程度。案例分析显示,嵌入式软件需满足高可靠性要求,如机载软件的可靠度需达99.99%以上,通过定量指标评估其是否达标。
|
5月前
|
消息中间件 缓存 监控
性能测试怎么做?方法、流程与核心要点解析
本文系统阐述了性能测试的核心方法论、实施流程、问题定位优化及报告编写规范。涵盖五大测试类型(负载验证、极限压力、基准比对、持续稳定性、弹性扩展)与七项关键指标,详解各阶段任务如需求分析、场景设计和环境搭建,并提供常见瓶颈识别与优化实战案例。最后规范测试报告内容框架与数据可视化建议,为企业级实践提出建立基线库、自动化回归和全链路压测体系等建议,助力高效开展性能测试工作。
|
9月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
579 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!