XSS过滤

Posted 许二

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XSS过滤相关的知识,希望对你有一定的参考价值。

XSS过滤封装用法

封装到app01/form.py文件中进行验证

技术分享
from django.forms import Form,widgets,fields

class ArticleForm(Form):
    title = fields.CharField(max_length=64)
    content = fields.CharField(
        widget=widgets.Textarea(attrs={id:i1}))

    #此处为xss验证
    def clean_content(self):
        old = self.cleaned_data[content]
        from utils.xss import xss
        return xss(old)
app01/form.py
技术分享
CONTENT=‘‘
def create_article(request,site):
    from app01.form import ArticleForm
    if request.method == GET:
        obj = ArticleForm()
        return render(request,creat_article.html,{site:site})
    else:
        obj = ArticleForm(request.POST)
        if obj.is_valid():
            content = obj.cleaned_data[content]
            global CONTENT      #这里记得要设置全局变量
            CONTENT = content
            return HttpResponse(上传成功)

# 查看文章内容,只是简单的
def see(request):
    return render(request,see.html,{CONTENT:CONTENT})
app01/views
技术分享
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$Title$</title>
</head>
<body>
<h3>发布文章</h3>
<form action="/background/{{ site }}/create_article.html" method="POST">
    {% csrf_token %}
    文章标题<input type="text">
    <textarea name="content" id="i1" cols="30" rows="10"></textarea>
    <input type="submit" value="提交"  style="margin-left: 35%">
</form>

<script src="/static/kindeditor-4.1.10/kindeditor-all.js"></script>
<script>
    // KindEditor 上传的瞬间,帮你生成iframe+form进行伪Ajax操作
    KindEditor.create(#i1,{
        width:1000px,
        height:500px,
        resizeType:2,   // 默认是否可以拖动改变高度和宽带,0,1,2,其中默认是2,可以拖动改变宽度和高度。
        uploadJson:/upload_img.html, // 上传文件位置,注意不能写目录/static/files...类似这种,识别不了。要写url
        // 注意:上传文件时,是以POST请求提交的,但是要写上{% csrf_token %},上面表单中写的上传文件时没法用到,要配置
        extraFileUploadParams:{csrfmiddlewaretoken:"{{ csrf_token }}"}

    })
</script>
</body>
</html>
creat_article.html
技术分享
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$Title$</title>
</head>
<body>
{{ CONTENT|safe }}
</body>
</html>
see.html
技术分享
from bs4 import BeautifulSoup
def xss(old):
    soup = BeautifulSoup(old,html.parser)
    tags = soup.find_all()
    vaild_tag = {p:[class,id],img:[src],div:[class]}
    for tag in tags:
        if tag.name not in vaild_tag:
            tag.decompose()
        if tag.attrs:
            for k in list(tag.attrs.keys()):
                if k not in vaild_tag[tag.name]:
                    del tag.attrs[k]
    comment_str=soup.decode()
    return comment_str
utils/xss.py

 下面是xss.py内容的注释 

技术分享
# 通过beautifulsoup4 模块可以避免写正则表达式来完成过滤上传文件中的恶意攻击
from bs4 import BeautifulSoup
content = """
<p id=‘i1‘ a=‘123‘ b=‘999‘>
    <script>alert(123)</script>
</p>

<p id=‘i2‘>
    <div>
        <p>asdfasdf</p>
    </div>
    <img id=‘i3‘ src="/static/imgs\1.jpg"  />
</p>
"""
soup = BeautifulSoup(content,html.parser)     # parser为beautifulsoup4 模块的内置解析块,将html解析成对象
tag = soup.find(name=img)     # 获取的是img标签,name= 标签名
# print(tag)  #<img  id="i3" src="/static/imgs.jpg"/>  ,为字符串??
tag = soup.find(name=p)   #获取的是 p 标签及 p 标签内的子内容
# print(tag)  #<p a="123" b="999" id="i1"><script>alert(123)</script></p>
v = soup.find(name=p,attrs={id:i2,name:‘‘})     # 也可以通过id 和 name 获取,条件是且的关系
# print(v)    #<p id=‘i2‘><div><p>asdfasdf</p></div><img id=‘i3‘ src="/static/imgs\1.jpg"  /></p>
# 以上find 获取的都是选中的内容和其内部包含的子内容,且获取的是字符串类型
#find_all 获取的是列表类型,列表里是对象
v = soup.find_all(name=p)
# print(v)   #递归找到所有的标签,步骤:找第一个父类,父类和子类中符合的取出来,然后再把子类符合的标签取出来。子类符合的标签可能被取出来很多次
#[<p a="123" b="999" id="i1"><script>alert(123)</script></p>, <p id="i2"><div><p>asdfasdf</p></div><img  id="i3" src="/static/imgs.jpg"/></p>, <p>asdfasdf</p>]

#以下为过滤部分
vaild_tag = [p,img,div]   #白名单,设置白名单不设黑名单的原因是xss攻击的方式多种多样,而且不断更新
tags = soup.find_all()
for tag in tags:
    if tag.name not in vaild_tag:
        # tag.clear()     # tag.clear()只是把tag标签的内容删掉,标签本身不被删掉
        tag.decompose()     #删除的是标签内的内容和标签本身
print(soup)  #soup是对象,要拿到过滤后的结果,需要decode下
comment_str=soup.decode()   #comment_str 这是拿到最终被过滤后的结果

#白名单也可以设置为字典格式,标签部分属性设置为白名单
vaild_tag = {p:[class,id],img:[src],div:[class]}
for tag in tags:
    if tag.name not in vaild_tag:
        tag.decompose()
    if tag.attrs:
        for k in list(tag.attrs.keys()):
            if k not in vaild_tag[tag.name]:
                del tag.attrs[k]
comment_str=soup.decode()    #将soup对象转换成字符串,encode()将soup对象转换成字节
xss.py注释

 

以上是关于XSS过滤的主要内容,如果未能解决你的问题,请参考以下文章

xss过滤函数

XSS:如何从 C# 中的字符串中删除 JS 片段?

【快学springboot】15、SpringBoot过滤XSS脚本攻击

XSS 攻击的预防

XSS过滤JAVA过滤器filter 防止常见SQL注入

SpringMVC过滤字符防御xss攻击