V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
drymonfidelia
V2EX  ›  信息安全

用了参数化查询,还是被 SQL 注入了,上线 3 天几十个用户反馈账号被盗余额被刷完,求助怎么解决?

  •  
  •   drymonfidelia · 14 天前 · 7844 次点击

    Python+MongoDB 写的一个简单(虽然业务都很简单但是有九百多个接口,选型用 Python+MongoDB 就是为了往上面堆各种奇怪格式的简单接口方便)网站,拉日志排查发现有人提交了类似这种 Payload {"password":{"$ne":"111"}},登录接口好解决,直接 str 转换一下字段,剩下九百多个接口过一遍工作量太大了还容易有漏,有人了解如果我加一个中间件遍历提交的 JSON 把 $ 开头的 key 全部过滤掉就安全了吗?

    每次用新技术必被坑,上次是被 Tauri 浪费了一整天

    82 条回复    2024-06-12 08:12:18 +08:00
    jeesk
        1
    jeesk  
       14 天前 via Android
    技术方案评估你找 chatgpt ,也许比你自己决定好
    illl
        2
    illl  
       14 天前 via iPhone
    $ne 应该是 MongoDB 这种非关系型数据库注入的手段,建议还是多搜索了解一下相关的手段和正确防护方式。光检测了$,貌似可以使用 Unicode 编码绕过。先知上有相关的文章,可以看看。
    HFX3389
        3
    HFX3389  
       14 天前   ❤️ 1
    先上 WAF ,什么南墙、雷池之类的,先让 WAF 过滤一遍再说
    HFX3389
        4
    HFX3389  
       14 天前
    @jeesk #1 我觉得编程方面 claude-3 比 GPT4 好用多了也聪明多了...
    sagaxu
        5
    sagaxu  
       14 天前
    用户输入不是 str?
    fzls
        6
    fzls  
       14 天前
    客户端传入的参数你在服务器不校验,直接写入数据库的嘛?
    cnevil
        7
    cnevil  
       14 天前
    只有个$ne 不是注入漏洞吧。。我觉得你应该是存在别的漏洞
    比如越权啥的
    lambdaq
        8
    lambdaq  
       14 天前
    不是哥们。。。。mongo 也能被注入???
    drymonfidelia
        9
    drymonfidelia  
    OP
       14 天前
    @fzls 接口太多了,校验起来工作量翻倍
    drymonfidelia
        10
    drymonfidelia  
    OP
       14 天前
    @lambdaq 按照 2 楼的查一下,mongodb 注入花样还很多
    NewYear
        11
    NewYear  
       14 天前
    可能是我的知识太贫瘠了。

    我一般认为丢到数据库里的数据就两种, 非字符串和字符串。

    字符串就用引号包起来,做个转义,,,,非字符串就判断一下类型对不对。

    这是不用“参数化查询”、“绑定数据”的方法,如果用上绑定数据,就不用转义数据了(数据库会做这一步)。

    所以我迷茫了,你的问题在哪呀。(不太熟悉这个数据库)
    zeusho871
        12
    zeusho871  
       14 天前
    django 好像有个 mongo 库 啥都给你封装好的
    drymonfidelia
        13
    drymonfidelia  
    OP
       14 天前
    @NewYear @sagaxu MongoDB 不需要定义类型,list dict 随便找个字段都能直接塞
    Masterlxj
        14
    Masterlxj  
       14 天前
    不用 ORM ?
    hdben
        15
    hdben  
       14 天前
    听起来像是,没有对数据做任何处理, 直接把前段给的内容作为查询语句的一部分?
    drymonfidelia
        16
    drymonfidelia  
    OP
       14 天前
    @hdben 是,因为本来 MongoDB 就支持参数化查询,觉得没问题
    @Masterlxj ORM 要写模型麻烦
    dayeye2006199
        17
    dayeye2006199  
       14 天前 via Android
    自己搞不定就 ODM
    sagaxu
        18
    sagaxu  
       14 天前 via Android
    @drymonfidelia 用户请求参数构造成 map 了,框架层面可以禁用这个特性么?比如写个拦截器,所有参数统一转成 str ,特殊情况再特殊处理
    dearmymy
        19
    dearmymy  
       14 天前
    @Masterlxj 用 django 得 orm 是不是就不需要考虑 sql 注入了?
    vituralfuture
        20
    vituralfuture  
       14 天前 via Android
    web 框架基本都有数据类型校验的功能吧,或者用 pydantic 也行,fastapi 自带这个功能。另外后端基本常识,不信任前端传来的任何数据
    laminux29
        21
    laminux29  
       14 天前   ❤️ 1
    楼主举的注入例子:Payload {"password":{"$ne":"111"}}

    这正是参数化查询模块要去处理的事情,如果这还没注入了,你确定你正确使用了参数化查询模块?

    建议用 AI 把你的代码检查一遍。
    msg7086
        22
    msg7086  
       14 天前   ❤️ 3
    用户输入的密码为什么能传进 mongo ?换我的话会先取出 password hash 然后再在本地对比。
    这系统谁开发的啊这么简单的坑也能中的吗。
    输入参数校验是基本要求吧,这不叫工作量翻倍,这是之前为了走捷径把大动脉砍了,现在在亡羊补牢。
    再还有,你们的测试代码呢,这种场景不写 behavior test 的吗。
    hlwjia
        23
    hlwjia  
       14 天前   ❤️ 11
    既然你觉得用 ORM 怕麻烦,那现在处理这些问题你觉得麻烦不?

    如果 ORM 光是麻烦,没别的好处,也不会有人一直用吧


    还有 #9 楼你写的,“接口太多,校验起来工作量翻倍”,不知道你现在的工作量翻倍了没有
    Kinnice
        24
    Kinnice  
       14 天前 via Android
    1. 先上 waf
    2. 没正确使用参数校验模块
    among
        25
    among  
       14 天前
    mongoengine 用了吗
    vincent7245
        26
    vincent7245  
       14 天前   ❤️ 5
    "接口太多了,校验起来工作量翻倍"

    那还能说什么呢,最基础的防护都不做,没被删库也算攻击者仁慈了
    erwsd32ew
        27
    erwsd32ew  
       14 天前
    普通程序员除了依赖框架没有什么好手段,因为他们连相关的概念都没有,谈什么防御。简单的过滤字符串可不代表能解决问题,某个知名库一个特殊字符改了三次才解决问题。
    EndlessMemory
        28
    EndlessMemory  
       14 天前
    你这个管理起来问题不小
    walkeronway
        29
    walkeronway  
       14 天前
    嫌麻烦?这会儿被教做人了吧?你以为为啥大家都在做安全防护,是闲着没事干还是喜欢? C 端产品要直面所有可能的恶意,敢偷懒?

    话说静态扫描能扫出来你这些安全漏洞吗?
    awolf
        30
    awolf  
       14 天前
    LZ 开善堂的,大家可以散了
    kneo
        31
    kneo  
       14 天前 via Android   ❤️ 6
    啥叫用新技术必被坑?我看你就是最大的坑……
    uiiytwyfsdtr
        32
    uiiytwyfsdtr  
       14 天前
    网络攻防 其实防不胜防

    只能靠你自己的 经验 和 安全意识
    yidinghe
        33
    yidinghe  
       14 天前 via Android
    你把调用方的参数直接透传给数据库,不死才怪。首先防住登录接口,然后其他接口要有状态,根据调用方权限添加对应的查询条件,而且禁止调用方通过参数覆写这些条件。最后每个接口设置参数白名单,不在白名单中的参数过滤掉。
    drymonfidelia
        34
    drymonfidelia  
    OP
       14 天前
    @msg7086 这系统只支持短信验证,password 字段存的其实是短信验证码,所以没加密
    这套系统需求太杂了都是手动测试
    hefish
        35
    hefish  
       14 天前   ❤️ 1
    大佬 A:哎呀。。。没搞了,来帮帮我啊。。
    大佬 B:你这个要这么这么这么。。。
    大佬 A:那太麻烦了,谁有更好的办法吗?
    大佬 C:那你先这么这么这么。。。不然会有问题
    大佬 A:我觉着没问题。。
    大佬 D:你不写个 ORM 吗?
    大佬 A:写 ORM 太麻烦了。。。谁能帮帮我啊。。。

    。。。。
    gwy15
        36
    gwy15  
       14 天前 via iPhone
    你不会是从 req json.loads 读一个 object 然后直接传给 mongodb 吧
    janus77
        37
    janus77  
       14 天前   ❤️ 1
    哈哈哈,出现安全问题了,然后说别人的方法麻烦。。。
    安全就是麻烦的啊,你以为飞机起飞前一遍遍教人使用救生衣是干什么的?
    GG5332
        38
    GG5332  
       14 天前
    没有必要冷嘲热讽,安全从来都是一种取舍,只要被黑带来得损失都没有比写 ORM 的麻烦大,那就大可不必写,而且还更好,黑客也很开心,你也很开心。何尝不是一种 win ,win 。现实就是很多业务就是跟羊毛党黑产党相互依存,不离不弃。
    lneoi
        39
    lneoi  
       14 天前
    懒的话就上 web 防火墙,或者其他服务器防护软件,多多少少能处理大部分情况
    gongquanlin
        40
    gongquanlin  
       14 天前
    想起来接的一个擦屁股的活,大哥前后端全栈开发,查询语句直接前端拼 where 后端查询
    到现在 bug 一堆还没上线,到了上线之后还不知道咋甩锅呢,哈哈哈
    yjxjn
        41
    yjxjn  
       14 天前
    @drymonfidelia #9 你现在看看,工作量不仅翻倍,损失也在翻倍。
    fangxiaoning
        42
    fangxiaoning  
       14 天前
    要么就是有地方没有参数化,要么就是有其他漏洞吧,参数化了注入不了的
    bunny189
        43
    bunny189  
       14 天前 via iPhone
    早用我们 laravel P 事没有,所有东西都给你集成好了,开箱即用爽得很
    drymonfidelia
        44
    drymonfidelia  
    OP
       14 天前 via iPhone
    @fangxiaoning 按二楼提供的关键词,参数化了还有一堆花样能注入
    009694
        45
    009694  
       14 天前 via iPhone
    password 字段应该接受的是一个字符串 你是怎么把 dict 传递进去的?
    drymonfidelia
        46
    drymonfidelia  
    OP
       14 天前 via iPhone
    @009694 直接读的 json ,没有数据模型
    leegradyllljjjj
        47
    leegradyllljjjj  
       13 天前
    啥时代了还在被 sql 注入,就像 2024 一个计算机系大大学生说我的智能手机键盘坏了
    LeeReamond
        48
    LeeReamond  
       13 天前
    @hlwjia 这和 ORM 有什么关系,ORM 也是调底层驱动的。正常来说应该是用参数化查询就不会被按对象解析,只能说可能它这个 mongodb 比较奇怪吧。。
    sagaxu
        49
    sagaxu  
       13 天前   ❤️ 2
    @LeeReamond mongodb 查询时传入的 value 可以是 bson(list/map),driver 是分不清这个 bson 是你自己构造的还是被注入的,想不被注入,代码里要保证所有传入的 value 都是 str 或者 number ,str 里无论怎么写都不会被注入
    des
        50
    des  
       13 天前 via iPhone
    @drymonfidelia 参数化还能被注入,那就说明你写的不对
    MrKrabs
        51
    MrKrabs  
       13 天前
    神人
    podel
        52
    podel  
       13 天前
    接入 ORM
    yunye
        53
    yunye  
       13 天前
    这项目质量也能有用户充钱?
    drymonfidelia
        54
    drymonfidelia  
    OP
       13 天前
    @yunye 因为这个项目只有我们在做。项目质量差就是因为急着上线,招了一堆临时工赶进度
    drymonfidelia
        55
    drymonfidelia  
    OP
       13 天前
    @drymonfidelia 九百多个接口从立项到上线只用了一个月多一点
    scriptB0y
        56
    scriptB0y  
       13 天前
    不明白怎么注入的,假设 `{"$ne":"111"}` 这个字符串传回来,这也是个 string 吧,拿它来和真正的密码对比,肯定是不想等的呀? (做 hash 之后对比就更不想等了)
    drymonfidelia
        57
    drymonfidelia  
    OP
       13 天前
    @scriptB0y 因为 password 字段实际存的是短信验证码,我们偷懒直接三个条件(手机号 短信验证码 有效期)查出来有记录就登录成功
    drymonfidelia
        58
    drymonfidelia  
    OP
       13 天前
    卧槽怎么好像又被黑了,数据库有大上传流量
    Belmode
        59
    Belmode  
       13 天前
    离谱......

    如果不想每个接口上都单独校验,可以在中间件或者框架的过滤器上把正常接口的入参全部审查一遍。
    drymonfidelia
        60
    drymonfidelia  
    OP
       13 天前
    @Belmode 就是这么做的,目前会遍历 dict 每个 key ,只允许 number 、string 、list 的 value ,list 的 value 会再次过滤,只允许 string 和 number 的成员,希望不会再出问题
    drymonfidelia
        61
    drymonfidelia  
    OP
       13 天前
    @drymonfidelia 还有 boolern 和 null(None),也允许 忘写了
    scriptB0y
        62
    scriptB0y  
       13 天前
    @drymonfidelia 但是如果攻击者使用这个 {"$ne":"111"} 传进来,你查数据的内容不应该是:

    {"password": {"$eq": {\"$ne\":\"111\"}"}}

    这样吗?查询也不成立呀。

    莫非。。。你直接让前端给你传过来查询的语句?
    drymonfidelia
        63
    drymonfidelia  
    OP
       13 天前
    @scriptB0y 前端传来的是 JSON ,框架 parse 出来的 password 是一个 dict
    Masterlxj
        64
    Masterlxj  
       13 天前
    @dearmymy 是的,使用 ORM 基本可以避免 sql 注入
    lrh3321
        65
    lrh3321  
       13 天前 via Android
    你这 password 的类型都不对了,再怎么赶工,你也要先把它强转成字符串吧。
    LuckyLauncher
        66
    LuckyLauncher  
       13 天前
    “校验起来工作量翻倍”
    那等人把你们用户的余额都刷完,你就没有任何工作量了
    lambdaq
        67
    lambdaq  
       13 天前
    @drymonfidelia 大概明白了。直接把 json 里的东西传到 mongo 里去操作。。好家伙。。
    Nazz
        68
    Nazz  
       13 天前
    是不是让前端传 JSON 过来自己查询了
    drymonfidelia
        69
    drymonfidelia  
    OP
       13 天前 via iPhone
    @Nazz json 的字段值直接带入查询了
    bthulu
        70
    bthulu  
       13 天前
    改什么改, 报警啊
    mmdsun
        71
    mmdsun  
       13 天前
    这种可能是 json 序列号漏洞,比如 fastjson 这种漏洞提权就很多
    sampeng
        72
    sampeng  
       13 天前
    @drymonfidelia 嫌麻烦,就别怨踩雷
    Richared
        73
    Richared  
       13 天前
    这直接给参数拼 sql 去处理?都当字符串处理不就行了么。
    corcre
        74
    corcre  
       13 天前
    你这参数化处理是我见过最新奇的...
    rainingwrong
        75
    rainingwrong  
       13 天前
    @drymonfidelia 想啥呢,上 ORM
    MapleEve
        76
    MapleEve  
       13 天前
    这个为什么不上 ORM 啊
    GoRoad
        77
    GoRoad  
       13 天前
    大开眼界
    yumenlong
        78
    yumenlong  
       13 天前   ❤️ 1
    https://v2ex.com/t/1048368# 看了 op 这篇主题,感觉是来编故事赚铜币的吧.
    Kalan
        79
    Kalan  
       13 天前
    还有这种神人
    drymonfidelia
        80
    drymonfidelia  
    OP
       12 天前
    @yumenlong 我铜币根本用不完 骗来干什么
    h175h32
        81
    h175h32  
       12 天前
    装一个 web 防火墙
    vishun
        82
    vishun  
       12 天前
    绝对压根没有用参数化查询
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3284 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 10:55 · PVG 18:55 · LAX 03:55 · JFK 06:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.