V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
tctc4869
V2EX  ›  JavaScript

防止 xss 和 sql 注入而进行非法字符过滤, js 前端有什么几乎一劳永逸的方式?

  •  
  •   tctc4869 · 2020-04-24 14:58:09 +08:00 · 13164 次点击
    这是一个创建于 1464 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网上有各种防止 xss 和 sql 注入的方案,前端的也有,后端的也有。各种方案太多太杂,看的我头疼。

    我的策略是,前端负责非法字符的过滤,转换,显示,让过滤后的安全数据入库,以及能安全的显示给用户看。而后端处理非法字符,就很简单。一旦检测到非法字符就直接返回 404,403,400 等错误码。

    那么问题来了,先不考虑富文本,就那种普通的文本框,假设每个用户用浏览器操作,在输入框里输入的内容中,都可能带有 sql 注入,xss 攻击所用的代码的一段文字或文章例,前端如何负责这些带有非法字符的过滤转换?让数据能安全的入库,然后在数据显示时,又能显示用户输入时的样子,又不出问题呢。

    第 1 条附言  ·  2020-04-24 15:44:20 +08:00
    有人误会我的描述,觉得后端是不用说明,我在说明一下,我的后端不是不处理,而是处理的简单粗暴,就看有没有非法字符,有就过去,没有就返回错误码,和无用信息。不搞过滤转码,那是前端要做的事情
    148 条回复    2020-04-26 11:04:57 +08:00
    1  2  
    u823tg
        101
    u823tg  
       2020-04-24 17:59:19 +08:00
    @Leon6868 #97
    看情况么
    const tag = document.createElement("script");
    tag.innerText = `console.log('v2')`;
    document.body.appendChild(tag);
    杠一下。 -_-
    moonlord
        102
    moonlord  
       2020-04-24 18:03:56 +08:00
    @u823tg 杠精说的就是你吧 =。=
    Leon6868
        103
    Leon6868  
       2020-04-24 18:04:00 +08:00
    @u823tg 我说的是 sql 注入。。innerText 确实可以避免的,#97 已经承认了。我的意思和#98 的差不多,你可以参考一下
    huang7230468
        104
    huang7230468  
       2020-04-24 18:05:28 +08:00
    还是从后端考虑吧,
    u823tg
        105
    u823tg  
       2020-04-24 18:11:36 +08:00
    @tctc4869 #98 二次注入你怎么办, 用户的输入本来就不可信。 严格来说存到数据库的数据得经过过滤,脏数据不可否认的有危险性。
    Deffi
        106
    Deffi  
       2020-04-24 18:14:02 +08:00
    前端过滤怎么行,人家直接走接口,又不一定走前端 js
    zhouwei520
        107
    zhouwei520  
       2020-04-24 18:14:18 +08:00
    一劳永逸是不是不做程序员?
    zhuisui
        108
    zhuisui  
       2020-04-24 18:16:45 +08:00
    `"topic_id": 665687, "content": "<img onerror=\"alert(111)\"/>", "content_rendered": "&lt;img onerror=\"alert(111)\"/&gt;",`
    这叫没转码?到底是谁瞎了
    "content_rendered" ,顾名思义,要渲染的内容,明明是转过的。
    zhw2590582
        109
    zhw2590582  
       2020-04-24 18:18:34 +08:00
    前端防用户手动输入都是做做样子,会 js 的人直接控制台里调接口了,前端还过滤个毛线,关键还是后端
    Deffi
        110
    Deffi  
       2020-04-24 18:19:20 +08:00
    前端过滤只是用户友好,后端过滤才是安全啊
    zhuisui
        111
    zhuisui  
       2020-04-24 18:21:55 +08:00
    各位,我相信题主的意思是:
    1. 前端是面向正常用户的,各种不合法输入都应该在检查后展示给用户原因。
    2. 而后端只需要粗暴的返回数据是否合法,因为如果数据是前端来的,那么必然已经经过前端的校验了。如果不是前端来的非法请求,那我也没必要告诉你为什么你的请求出问题了。
    otakustay
        112
    otakustay  
       2020-04-24 18:24:43 +08:00
    这事情的本质是:后端只管安全不管用户体验,前端完全负责用户体验,是否有可行性
    至少在注入这件事上,我想说没有可行性,用 SQL 参数带来的体验前端不能完全 cover 住
    当然在另外一些事上是可能有可行性的,要就事论事
    taaaang
        113
    taaaang  
       2020-04-24 18:28:51 +08:00
    验证和过滤从来都不只是前端的事情,哪来一劳永逸,多关注用户体验,其他交给后端。
    u823tg
        114
    u823tg  
       2020-04-24 18:30:22 +08:00
    @zhuisui #111 不行的, 有些数据我传进数据库是看似正常的, 程序二次从数据库取出来进行处理会造成注入。
    aguesuka
        115
    aguesuka  
       2020-04-24 19:08:37 +08:00
    @fancy111 有意思,不用后端,不用过滤,来吧

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>xss me</title>
    <script>
    window.onload = function () {
    const url = new URL(location.href)
    const input = url.searchParams.get('input');
    document.getElementById('output').innerText = input;
    document.querySelector('input').value = input;
    }
    </script>
    </head>
    <body>
    <form>
    <label>
    <input type="text" name="input"/>
    </label>
    <button type="submit">submit</button>
    </form>
    <pre id="output"></pre>
    </body>
    </html>
    sagaxu
        116
    sagaxu  
       2020-04-24 19:10:34 +08:00 via Android   ❤️ 1
    SQL 注入,prepared statement 一劳永逸,过滤是瞎鸡巴搞。

    XSS 注入,后端拼 html 的由后端转义,前后端分离的,前端负责搞定。
    cumt21g
        117
    cumt21g  
       2020-04-24 19:18:39 +08:00
    起作用的还是后端过滤吧
    skyRival
        118
    skyRival  
       2020-04-24 19:23:11 +08:00
    tctc4869
        119
    tctc4869  
    OP
       2020-04-24 19:36:20 +08:00
    @Deffi
    @zhw2590582
    @taaaang

    前端过滤,是因为前端是面向正常的客户端,而构造请求直接调后端接口不算正常的客户端,后端主要负责安全,用户体验交给前端。

    后端既然检测的非法数据,就代表请求的客户端是不正常的客户端,没有经过前端验证过滤的客户端,就没有必要从数据库拿数据了,更没有必要过滤数据。都已经是非正常用户了,没必要告诉客户端是不是请求出问题了。
    tctc4869
        120
    tctc4869  
    OP
       2020-04-24 19:38:15 +08:00
    @cumt21g 后端过滤是多此一举,浪费精力,后端负责通不通过就行,难道后端还要告诉非法请求的客户端,你的请求数据有问题么?正常的客户端就交给前端去负责。至于非法客户端。
    zhangysh1995
        121
    zhangysh1995  
       2020-04-24 19:40:42 +08:00
    考虑一下验证方法,把这篇论文实现,The essence of command injection attacks in web applications
    no1xsyzy
        123
    no1xsyzy  
       2020-04-24 19:42:51 +08:00
    严格白名单新建一套描述富文本的语言,然后写个该语言到 HTML 的编译器
    那建立一个和 html 很像的语言也没什么问题,但别偷懒,整个重新 parse 分析语义然后再重新渲染,不要 passthru
    BBcode 和 Markdown 在一定程度上就是逼自己和后续维护者别偷懒
    jinmaoi
        124
    jinmaoi  
       2020-04-24 19:43:27 +08:00
    @fancy111 我觉得他的意思根本就不是前端过滤输入,只是过滤输出而已.况且你举的那个 xss 并没有效果
    aguesuka
        125
    aguesuka  
       2020-04-24 19:47:10 +08:00
    @skyRival 是让你来注我不是我来注你
    Xezzon
        126
    Xezzon  
       2020-04-24 20:07:04 +08:00 via Android
    @aguesuka 你可真有意思,谁说了要这么写了?没事放 pre 在那干嘛?难道专门为了让别人来 xss 所以我就得不用 div 用 pre 呗?
    fxxwor99LVHTing
        127
    fxxwor99LVHTing  
       2020-04-24 21:13:11 +08:00
    前端做不了,
    buffzty
        128
    buffzty  
       2020-04-24 21:35:29 +08:00   ❤️ 1
    没人说用 react 吗? 用 react 不会出现 xss,显示时自动过滤
    render() {
    const txt = '</script><script>alert(11);</script>'
    return <div>{txt}</div>
    }
    // output
    &lt;/script&gt;&lt;script&gt;alert(11);&lt;/script&gt;
    mxT52CRuqR6o5
        129
    mxT52CRuqR6o5  
       2020-04-24 21:49:16 +08:00 via Android
    @buffzty xss 注入很多时候是有富文本的需求的
    mxT52CRuqR6o5
        130
    mxT52CRuqR6o5  
       2020-04-24 21:56:44 +08:00 via Android   ❤️ 1
    sql 注入靠前端防不了,攻击者完全可以自己手动构造请求不需要通过前端去发请求
    Xss 注入可以靠把富文本转成非 html 的抽象来解决(比如 quill)
    普通的文本框去设置 innerHTML 是水平不行
    buffzty
        131
    buffzty  
       2020-04-24 22:46:04 +08:00
    现在 orm 都是预处理.怎么可能注入呢
    binux
        132
    binux  
       2020-04-24 22:58:27 +08:00 via Android
    @fancy111 #6 说好的只用 innerText 的,如果 '</script><script>alert(11);</script>' 是用户输入的话,它是怎么进入 HTML 的? 你还不是拼接 HTML 了。
    rsjztz
        133
    rsjztz  
       2020-04-24 23:10:29 +08:00 via Android
    关于 xss,我看过前端拦截 xss 语句运行的操作,sqli 还是得后端过滤
    canwushuang
        134
    canwushuang  
       2020-04-24 23:20:10 +08:00 via Android
    你正则能过滤 get,还能大量过滤 post 和 put ?多次编码随你正则一样绕。超长字符击穿防线也是可以,emoji 也行。别防了。。。
    canwushuang
        135
    canwushuang  
       2020-04-24 23:29:32 +08:00 via Android
    @sagaxu % 直接 like
    neoblackcap
        136
    neoblackcap  
       2020-04-25 01:15:47 +08:00
    要过滤就直接先后端解析一遍,有问题就干掉,没问题就放行
    hblf
        137
    hblf  
       2020-04-25 01:16:41 +08:00 via iPhone   ❤️ 1
    都 0202 年了就别想着用过滤特殊字符解决 sqli 了吧,预编译比过滤安全一万倍
    xss 的过滤参考 owasp 自己出的 api
    各位开发大佬平时真的不看 owasp 的文档吗?
    Hyduan
        138
    Hyduan  
       2020-04-25 02:47:35 +08:00
    话说这个会有 xss 问题么。。各位大佬试试 https://codepen.io/Hyduan/pen/bGVqLQr
    Hyduan
        139
    Hyduan  
       2020-04-25 02:49:52 +08:00
    @Hyduan 暂且不考虑需要渲染 HTML 结构的情况,这种情况确实需要过滤
    tctc4869
        140
    tctc4869  
    OP
       2020-04-25 09:47:16 +08:00
    @buffzty 大多数情况下可以用 orm 或 prepared statement 实现 sql 防注入,但也有不得不必须用拼接 sql 语句的方式。这类方式多数是复杂的查询语句
    anUglyDog
        141
    anUglyDog  
       2020-04-25 13:02:59 +08:00
    DOLLOR
        142
    DOLLOR  
       2020-04-25 14:47:53 +08:00
    前后端分离用 react 、vue 框架根本就不用考虑这种事情,因为这些工具本来就是作为文本显示。奈何就是有人喜欢 jQuery,拼接 HTML 字符串,到处都是漏洞。
    liuser666
        143
    liuser666  
       2020-04-25 15:00:35 +08:00
    前端用一下算法对字符串加一层 hash 等等再 webpack 一下,然后后端同样,端口要求处理结果,最后后端对比,让他不得不从前端走。
    sagaxu
        144
    sagaxu  
       2020-04-26 09:27:32 +08:00 via Android
    @tctc4869 复杂查询可以拼模板拼参数,拼 SQL 能做的拼模板写法也差不多
    fancy111
        145
    fancy111  
       2020-04-26 09:34:37 +08:00
    @aguesuka 你先搞懂什么叫只用 innertext,你这个过滤是靠 searchParams 解析后转化的,还不用过滤,你连什么叫过滤都不懂。
    另外谁会这么用?你网站上显示的字符都是这样来的吗? 搞笑。
    xiaomimei
        146
    xiaomimei  
       2020-04-26 10:08:44 +08:00
    看楼上的有些人,就知道安全给开发反馈漏洞的时候有多难受了。
    stevenkang
        147
    stevenkang  
       2020-04-26 10:47:01 +08:00
    楼上争来争去,一群人按照前端渲染的角度来说,一群人按照后端渲染的角度来说,这样讨论问题毫无意义。

    # 前端渲染时
    1 、前端负责处理 XSS,用 innerText 可以解决。
    2 、后端负责处理 SQL 注入,用 prepared statement 可以解决。

    # 后端渲染时
    1 、前端不用处理 XSS 、SQL 注入。
    2 、后端负责处理 SQL 注入,用 prepared statement 可以解决。
    3 、后端还需额外处理用户提交的数据必须进行 HTML 转义后再渲染返回给前端。
    viikker
        148
    viikker  
       2020-04-26 11:04:57 +08:00
    没有
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   887 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:57 · PVG 04:57 · LAX 13:57 · JFK 16:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.