V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
wyzerg
V2EX  ›  Python

前端编辑器传来的数据, BeautifulSoup 防止 xss 攻击,为了解析 script 缺得到了 <script> 此题怎解, 555

  •  
  •   wyzerg · 2019-08-06 00:57:11 +08:00 · 2167 次点击
    这是一个创建于 1972 天前的主题,其中的信息可能已经有所发展或是发生改变。
    [这是前端的内容:]
    <h1>hello</h1>
    <span>123</span>
    <h1>hello</h1>
    <span>123</span>
    <h1>hello</h1><span>123</span>
    <script>alert(123)</script>
    <script>alert(123)</script>
    <script>alert(123)</script>




    [后端解析到的是:]
    <pre><span style="color:#6a8759;">&lt;h1&gt;hello&lt;/h1&gt;&lt;span&gt;123&lt;/span&gt; </span><span style="color:#6a8759;">&lt;h1&gt;hello&lt;/h1&gt;&lt;span&gt;123&lt;/span&gt; </span><span style="color:#6a8759;"> </span><span style="color:#6a8759;">&lt;h1&gt;hello&lt;/h1&gt;&lt;span&gt;123&lt;/span&gt; </span><span style="color:#6a8759;"> </span><span style="color:#6a8759;"> </span><span style="color:#6a8759;">&lt;script&gt;alert(123)&lt;/script&gt; </span><span style="color:#6a8759;">&lt;script&gt;alert(123)&lt;/script&gt; </span><span style="color:#6a8759;">&lt;script&gt;alert(123)&lt;/script&gt;</span></pre>


    [后端代码是:]
    if request.method=="POST":
    title=request.POST.get('title')

    content=request.POST.get("content")
    #拿到标签字符串
    soup = BeautifulSoup(content, "html.parser",fromEncoding="UTF-8")
    #先过滤:
    for tag in soup.find_all():
    if tag.name == "script" : #####问题出在这里,哪怕我换成”&lt;/script&gt;“,也匹配不到这里的 if
    print("script--------->",tag.name) #####所以压根走不到这里,我懵了,555 怎样变回 script 呀??
    tag.decompose() # 从 soup 里吧这个 script 的 tag 删除掉


    desc = soup.text[0:150] #对文本进行截断 #######这里就变回了 script,怎么让前面的就变回 script ??
    13 条回复    2019-08-07 18:45:19 +08:00
    ysc3839
        1
    ysc3839  
       2019-08-06 01:44:13 +08:00 via Android
    为什么要解析后删除掉?直接转换成 HTML entity (例如 &lt;),确保不会当成 html 代码就行了。
    starsriver
        2
    starsriver  
       2019-08-06 02:02:16 +08:00 via Android
    entity 转换一句话的事情。

    以及转换完加反斜杠才是正确做法吧。
    locoz
        3
    locoz  
       2019-08-06 08:23:27 +08:00 via Android
    这不就是个 html encode 吗,decode 回去就是正常的样子了啊
    Leigg
        4
    Leigg  
       2019-08-06 09:21:45 +08:00 via Android
    xss 的解决方案就是将斜杠括号引号全部转义。
    wyzerg
        5
    wyzerg  
    OP
       2019-08-06 14:10:36 +08:00
    @Leigg
    @ysc3839
    @locoz
    @starsriver
    谢谢非常感谢,我用
    @ysc3839 方法试了下,用这个解决了
    import html
    content=request.POST.get("content")
    content = html.unescape(content)
    soup = BeautifulSoup(content, "html.parser")

    ----------------
    html.unescape 这个方法就是把转义的 script 标签( &lt;script&gt; ),再反转义回来( <script> )
    这样 for 循环,for tag in soup.find_all():就能拿到正规的<script>标签了,然后避免 xss 就把他 decompose() 删除掉就可以了,非常感谢
    ysc3839
        6
    ysc3839  
       2019-08-06 14:47:27 +08:00 via Android
    @wyzerg 我还是认为你没必要删除。你要实现的是把这段代码直接作为 html 代码插入页面中吗?那我还可以用 img onerror 来执行脚本,办法多了去了。最终会变成猫鼠游戏。
    wyzerg
        7
    wyzerg  
    OP
       2019-08-06 15:44:54 +08:00
    @ysc3839 老哥,那比如博客园,csdn 那种,放代码进去就是你的办法吗,你的意思是,&lt;script&gt; 获取到了,不转 script 了,那我存数据库就是&lt;script&gt; ,那前端调用呢?我应该模板用 safe 吧,这么说我有点懵了😂
    no1xsyzy
        8
    no1xsyzy  
       2019-08-06 15:53:15 +08:00
    额你这是拿 contenteditable="true" 做编辑器?
    不要转换啊,<safeHTML>"&lt;" 直接传给前端不会含可执行的标签的。
    no1xsyzy
        9
    no1xsyzy  
       2019-08-06 16:00:27 +08:00
    那你这个样子做,如果我要给别人展示一段 HTML 代码怎么做?我如何包括一个 script 标签?
    如果你指望的是像各个免费邮箱的 “纯文本编辑” 或者说 “ HTML 代码编辑” 的话,邮箱们其实有比较完善的处理方案,还要把所有的 @on(.*) 给换成 @on_$1 等(混杂了 XPath 和 RegExp 有点诡异,就这么看吧),但你不知道哪天 W3C 弄出一个新的标准使得某个奇怪的地方突然变成可以执行代码的了,又是 XSS。
    如果要富文本,BBcode、Markdown、有限 HTML (仅 font h[1-6] br 等特定的) 哪个方案不行?非要自己做过滤?
    wyzerg
        10
    wyzerg  
    OP
       2019-08-06 16:10:45 +08:00
    @no1xsyzy 嗯嗯 我解释下哈
    前端我用的是 KindEditor 做编辑器,在正常输入: <span>123</span> <script>alert(123)</script>
    然后 post 请求发给后端
    后端 request.POST 拿到数据
    查看这条数据是变成了: </span>123<span style="color:#6a8759;"> &lt;script&gt;alert(123)&lt;/script&gt;
    如果为了展示给前端,用模板语法{{ article_obj.content|safe }}:显示:<span>123</span> 效果
    所以把 script 过滤掉了。。。
    no1xsyzy
        11
    no1xsyzy  
       2019-08-06 18:20:43 +08:00
    @wyzerg 我还是没明白你需要什么效果?
    如果我想要写一段关于网页和 JavaScript 技术的文字如下:
    ```
    <template>
    <div>
    {{foo}}
    </div>
    </template>

    <script>
    export default {
    data(){return {foo:"bar"}}
    }
    </script>
    ```
    我该如何写?
    是不是用户永远不被允许写下包含 "<script>" 的文字了?
    wyzerg
        12
    wyzerg  
    OP
       2019-08-07 17:14:02 +08:00
    @no1xsyzy 是的,我是这个方法过滤掉 script -,-
    no1xsyzy
        13
    no1xsyzy  
       2019-08-07 18:45:19 +08:00
    @wyzerg 也就是说你拒绝了非常多技术性内容?
    你甚至不希望写下格式化的文字,那么为什么不直接 textarea 解决呢?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2626 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 06:50 · PVG 14:50 · LAX 22:50 · JFK 01:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.