# 第二节:XSS攻击
# XSS攻击
XSS(Cross Site Script)攻击又叫做跨站脚本攻击。他的原理是用户在使用具有`XSS`漏洞的网站的时候,向这个网站提交一些恶意的代码,当用户在访问这个网站的某个页面的时候,这个恶意的代码就会被执行,从而来破坏网页的结构,获取用户的隐私信息等。
## XSS攻击场景:
比如`A网站`有一个发布帖子的入口,如果用户在提交数据的时候,提交了一段`js`代码比如:`<script>alert("hello world");</script>`,然后`A网站`在渲染这个帖子的时候,直接把这个代码渲染了,那么这个代码就会执行,会在浏览器的窗口中弹出一个模态对话框来显示`hello world`!如果攻击者能成功的运行以上这么一段`js`代码,那他能做的事情就有很多很多了!
## XSS攻击防御:
1. 如果不需要显示一些富文本,那么在渲染用户提交的数据的时候,直接进行转义就可以了。在`Django`的模板中默认就是转义的。也可以把数据在存储到数据库之前,就转义再存储进去,这样以后在渲染的时候,即使不转义也不会有安全问题,示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django.template.defaultfilters <span class="hljs-keyword">import</span> escape
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Comment
<span class="hljs-keyword">from</span> django.http <span class="hljs-keyword">import</span> HttpResponse
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">comment</span><span class="hljs-params">(request)</span>:</span>
content = request.POST.get(<span class="hljs-string">"content"</span>)
escaped_content = escape(content)
Comment.objects.create(content=escaped_content)
<span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'success'</span>)
```
```
2. 如果对于用户提交上来的数据包含了一些富文本(比如:给字体换色,字体加粗等),那么这时候我们在渲染的时候也要以富文本的形式进行渲染,也即需要使用`safe`过滤器将其标记为安全的,这样才能显示出富文本样式。但是这样又会存在一个问题,如果用户提交上来的数据存在攻击的代码呢,那将其标记为安全的肯定是有问题的。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-title"># views.py</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span><span class="hljs-params">(request)</span>:</span>
message = <span class="hljs-string">"<span style='color:red;'>红色字体</span><script>alert('hello world');</script>"</span>;
<span class="hljs-keyword">return</span> render_template(request,<span class="hljs-string">'index.html'</span>,context={<span class="hljs-string">"message"</span>:message})
```
```
```
<pre class="calibre12">```
# index.html
```
```
那么这时候该怎么办呢?这时候我们可以指定某些标签我们是需要的(比如:span标签),而某些标签我们是不需要的(比如:script)那么我们在服务器处理数据的时候,就可以将这些需要的标签保留下来,把那些不需要的标签进行转义,或者干脆移除掉,这样就可以解决我们的问题了。这个方法是可行的,包括很多线上网站也是这样做的,在`Python`中,有一个库可以专门用来处理这个事情,那就是`sanitizer`。接下来讲下这个库的使用。
## `bleach`库:
`bleach`库是用来清理包含`html`格式字符串的库。他可以指定哪些标签需要保留,哪些标签是需要过滤掉的。也可以指定标签上哪些属性是可以保留,哪些属性是不需要的。想要使用这个库,可以通过以下命令进行安装:
```
<pre class="calibre12">```
pip install bleach
```
```
这个库最重要的一个方法是`bleach.clean`方法,`bleach.clean`示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">import</span> bleach
<span class="hljs-keyword">from</span> bleach.sanitizer <span class="hljs-keyword">import</span> ALLOWED_TAGS,ALLOWED_ATTRIBUTES
<span class="hljs-class">@require_http_methods(['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">message</span><span class="hljs-params">(request)</span>:</span>
<span class="hljs-title"># 从客户端中获取提交的数据</span>
content = request.POST.get(<span class="hljs-string">'content'</span>)
<span class="hljs-title"># 在默认的允许标签中添加img标签</span>
tags = ALLOWED_TAGS + [<span class="hljs-string">'img'</span>]
<span class="hljs-title"># 在默认的允许属性中添加src属性</span>
attributes = {**ALLOWED_ATTRIBUTES,<span class="hljs-string">'img'</span>:[<span class="hljs-string">'src'</span>]}
<span class="hljs-title"># 对提交的数据进行过滤</span>
cleaned_content=bleach.clean(content,tags=tags,attributes=attributes)
<span class="hljs-title"># 保存到数据库中</span>
Message.objects.create(content=cleaned_content)
<span class="hljs-keyword">return</span> redirect(reverse(<span class="hljs-string">'index'</span>))
```
```
相关介绍如下:
1. `tags`:表示允许哪些标签。
2. `attributes`:表示标签中允许哪些属性。
3. `ALLOWED_TAGS`:这个变量是`bleach`默认定义的一些标签。如果不符合要求,可以对其进行增加或者删除。
4. `ALLOWED_ATTRIBUTES`:这个变量是`bleach`默认定义的一些属性。如果不符合要求,可以对其进行增加或者删除。
### bleach更多资料:
1. github地址: <https://github.com/mozilla/bleach>
2. 文档地址: <https://bleach.readthedocs.io/>
- Introduction
- 第一章:学前准备
- 第一节:虚拟环境
- 第二节:准备工作
- 第三节:Django介绍
- 第四节:URL组成部分
- 第二章:URL与视图
- 第一节:第一个Django项目
- 第二节:视图与URL分发器
- 第三章:模板
- 第一节:模板介绍
- 第二节:模板变量
- 第三节:常用标签
- 第四节:常用过滤器
- 第五节:自定义过滤器
- 第七节:模版结构优化
- 第八节:加载静态文件
- 第四章:数据库
- 第一节:MySQL相关软件
- 第二节:数据库操作
- 第三节:ORM模型
- 第四节:模型常用字段
- 第五节:外键和表关系
- 第六节:增删改查操作
- 第七节:查询操作
- 第八节:QuerySet API
- 第九节:ORM模型迁移
- 第十节:ORM作业
- 第十一节:ORM作业参考答案
- 第十二节:Pycharm连接数据库
- 第五章:视图高级
- 第一节:限制请求method
- 第二节:页面重定向
- 第三节:HttpRequest对象
- 第四节:HttpResponse对象
- 第五节:生成CSV文件
- 第六节:类视图
- 第七节:错误处理
- 第六章:表单
- 第一节:表单概述
- 第二节:用表单验证数据
- 第三节:ModelForm
- 第四节:文件上传
- 第七章:cookie和session
- 第八章:上下文处理器和中间件
- 第一节:上下文处理器
- 第二节:中间件
- 第九章:安全
- 第一节:CSRF攻击
- 第二节:XSS攻击
- 第三节:点击劫持攻击
- 第四节:SQL注入
- 第十章:信号
- 第一节:什么是信号
- 第十一章:验证和授权
- 第一节:概述
- 第二节:用户对象
- 第三节:权限和分组
- 第十二章:Admin系统
- 第十三章:Django的缓存
- 第十四章:memcached
- 第十五章:Redis