V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
black11black
V2EX  ›  问与答

允许用户上传自定义图片或视频的场景,如何防止被上传恶意代码?

  •  
  •   black11black · 2020-10-18 09:55:41 +08:00 via Android · 4324 次点击
    这是一个创建于 1489 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题,假如应用场景是想要做一个图床的话,允许用户自定义上传,如果系统做的特别糟糕是有可能被上传二进制并执行的。

    很好奇现在通用的安全防范做法是什么,如何确保用户上传的图片确实是图片?

    自己写二进制分析感觉不太靠谱,工作量太大且不准确。如果交给 ffmpeg 这种工具转码一次的话能规避吗? ffmpeg 等工具有没有出现过 0day 被利用的情况?

    另外统一转码的话开销也很大,图片的话有损压缩会导致失真,视频的话则是太慢。以前记得 B 站做过直传视频后码率合规就不转码的操作,他们怎么处理的,如果用户传的视频外挂了二进制文件会怎么办

    很好奇,谢谢大家
    44 条回复    2020-10-20 23:46:42 +08:00
    OldActorsSmile
        1
    OldActorsSmile  
       2020-10-18 10:00:12 +08:00 via Android
    我刚好最近也在做图床,我只在前端检验文件扩展名,我觉得,哪怕有代码,放在一个.jpg 后缀的文件传上来也不会被执行。

    我的图床是 http://imgbed.cn ,支持视频
    nvkou
        2
    nvkou  
       2020-10-18 10:05:14 +08:00 via Android   ❤️ 1
    前端靠不住。后端或则 lambda 分析下数据流的头,找特征码。格式是固定的。不对劲就拒绝
    cmdOptionKana
        3
    cmdOptionKana  
       2020-10-18 10:09:06 +08:00
    linux 有权限设置,用户上传的文件用 0666 或 0600 保存,就不会被执行。
    black11black
        4
    black11black  
    OP
       2020-10-18 10:27:11 +08:00 via Android
    @cmdOptionKana 服务器被提权只是一种极端情况,一般来说如果网站本身不受攻击,但被用来分发恶意二进制文件,应该也是网站方面不可接受的吧
    black11black
        5
    black11black  
    OP
       2020-10-18 10:28:28 +08:00 via Android
    @OldActorsSmile 如果你这么设计的话感觉被恶意利用的是很容易发生的,比如如果我把二进制拆分上传,把你的图床当做免费网盘来用
    zhangshine
        6
    zhangshine  
       2020-10-18 10:44:27 +08:00
    加个免责声明
    cmdOptionKana
        7
    cmdOptionKana  
       2020-10-18 10:47:50 +08:00
    @black11black 图床必然需要 “生成缩略图” 这一步,这里就可以发现是否真的图片。
    InternetExplorer
        8
    InternetExplorer  
       2020-10-18 11:04:39 +08:00 via Android
    不要把系统做的这么糟糕
    unixeno
        9
    unixeno  
       2020-10-18 11:09:15 +08:00 via Android
    检查 magic number 呗
    OldActorsSmile
        10
    OldActorsSmile  
       2020-10-18 11:12:26 +08:00
    @black11black

    我后续会增加一些限制,比如每日上传数量超过一定量就启用图形验证码。
    spohar
        11
    spohar  
       2020-10-18 11:13:46 +08:00
    文件重命名,限制文件夹权限不可执行。 强烈推荐白名单方式,只允许固定格式上传服务端校验.此外,对于图片的处理,可以使用压缩函数或者 resize 函数,在处理图片的同时破坏图片中可能包含的 HTML 代码。
    Ptu2sha
        12
    Ptu2sha  
       2020-10-18 11:19:45 +08:00
    我想知道你怎么把恶意代码放在 nginx 的服务器上通过 web 访问来执行?
    你想通了这个问题就不存在了
    hzwjz
        13
    hzwjz  
       2020-10-18 11:27:34 +08:00   ❤️ 1
    最近在看 Go in Practice,其中 Technique 46 列举了三种方法

    - 使用 request headers 中的 Content-Type, 但是这个是有上传文件的客户端设置的。
    - 与 MIME type 关联起来的文件扩展,这个可以提供简单的分析出文件的类型
    - 解析文件的并且根据文件内容来检测文件内容的类型。 这也是 @nvkou 所说的那种方法了。

    使用 `http` package 中的 `DetectContentType` 检测文件的头 512 bytes 。
    black11black
        14
    black11black  
    OP
       2020-10-18 11:34:40 +08:00 via Android
    @Ptu2sha 垃圾的业务代码当然可以做到,这个问题没意义。
    black11black
        15
    black11black  
    OP
       2020-10-18 11:35:32 +08:00 via Android
    @unixeno magic number 是啥,大佬讲讲
    black11black
        16
    black11black  
    OP
       2020-10-18 11:36:10 +08:00 via Android
    @OldActorsSmile 问句题外话,你的检验是怎么做的,业务端维护一个访问计数吗
    black11black
        17
    black11black  
    OP
       2020-10-18 11:39:50 +08:00 via Android
    @hzwjz
    @nvkou 听起来是个防君子不防小人的做法,比如我在正常的图片后面帖一段二进制代码,你校验特征应该是一样的。我不知道现在还有没有那种打开图片的同时也能打开附加二进制的神奇漏洞了
    masy
        18
    masy  
       2020-10-18 12:20:53 +08:00
    @OldActorsSmile 我的论坛都被恶意用户上传了一句话木马改后缀名.jpg 作为头像。按理开源的论坛安全性也是差不多的,我技术有限也不能突破非正常图片的上传限制,也不知道那个恶意用户是怎么成功上传的。一句话木马基本上把站给端了。
    mumbler
        19
    mumbler  
       2020-10-18 12:39:06 +08:00 via Android
    ffmpeg 转码成功就肯定是安全的,你可以拿个二进制伪装视频传 B 站试试啊,看 B 站是如何处理的
    Track13
        20
    Track13  
       2020-10-18 12:40:22 +08:00 via Android
    @black11black 很久以前的免流就是这么干的
    nvkou
        21
    nvkou  
       2020-10-18 13:08:33 +08:00
    @black11black
    如果文件头不符合标准,在一些鲁棒性比较差的库中就直接报错说文件打不开了.这一点可以反向利用.反正你生成缩略图要把文件当做图片使用
    另外就是浏览器判断文件实际上是靠 MIME 声明. 你声明这是个 jpg,实际内容是 js.对于浏览器来说就是图裂了
    buffzty
        22
    buffzty  
       2020-10-18 13:41:04 +08:00
    很多用户上传二进制文件到图床并不是要攻击图床网站.而是把图床网站当作木马母站. 一般的 linux 木马都是一些脚本.脚本中会向木马母站请求下载二进制木马. 如果黑客用自己网站容易被查,所以会用第三方网站.我见过很多都是放在图床上.
    要我说 2 个措施 1. 后台任务读文件前一定字节判断是否为匹配格式. 2.保存文件上传时间,上传者源 ip,源端口,jc 叔叔能根据这 2 个找到当时哪个主机在使用这个 ip 和端口
    muzuiget
        23
    muzuiget  
       2020-10-18 16:41:53 +08:00
    只要你理解“URL 中的路径和硬盘中的路径没有对应关系”这个概念,这个问题不攻自破。

    所以我猜楼主的写 PHP 的?
    anerinck
        24
    anerinck  
       2020-10-18 16:48:12 +08:00   ❤️ 1
    @muzuiget lz 的意思是防止图床网站变成病毒分发网站吧,想自己做一个过滤
    Felldeadbird
        25
    Felldeadbird  
       2020-10-18 19:20:32 +08:00
    首先,严格判断文件后缀和初步获取文件的信息。

    图片 上传过来都做一个 压缩。确保是图片。

    视频做转码。也可以先上传,不回调上传地址。待解码完成后再更新地址。
    walkersz
        26
    walkersz  
       2020-10-18 19:46:02 +08:00
    用户上传的图片或视频不要保存原文件。
    图片读一遍,自己另存一份分比率、品质相同的。主要是为了防止有人在图片中夹带私货。比如这个文件( https://vkceyugu.cdn.bspapp.com/VKCEYUGU-imgbed/aec34c98-6265-4fec-8267-8df015e54399.jpg ),我在里面夹带了一首歌
    视频也转码一下。
    geebos
        27
    geebos  
       2020-10-18 19:55:47 +08:00
    对于图片可以验证分辨率,一般来说图片的大小是由分辨率来决定的,碰到大小异常的基本可以确定有问题
    walkersz
        28
    walkersz  
       2020-10-18 20:03:50 +08:00
    @OldActorsSmile 看我 26 楼的回复。用你的图床做的示范。你看下哈
    OldActorsSmile
        29
    OldActorsSmile  
       2020-10-18 23:28:06 +08:00
    @walkersz

    确实扩展名改成 mp3 可以播放,这个我觉得无所谓,用户想这么传就这么传吧,我不觉得属于恶意代码
    OldActorsSmile
        30
    OldActorsSmile  
       2020-10-18 23:30:15 +08:00
    @black11black

    每传一张图数据库也会同步记录。比如检测今天已经传了 1000 张,那么今天后续的上传都要图形验证码
    akira
        31
    akira  
       2020-10-18 23:34:41 +08:00
    一个比较鸡贼的方法。 传到其他支持图片 /视频处理的平台,例如 7 牛,或者阿里云的,处理后再下载回来。
    imdong
        32
    imdong  
       2020-10-19 00:22:21 +08:00 via iPhone
    远古时期,确实有一句话木马作为图片上传,然后执行的漏洞。
    black11black
        33
    black11black  
    OP
       2020-10-19 01:59:54 +08:00 via Android
    @akira 这个不解决问题,技术讨论纯粹是想知道这些商业公司都是怎么保证安全性的
    black11black
        34
    black11black  
    OP
       2020-10-19 02:04:38 +08:00 via Android
    @imdong 我们上学的时候也没少做渗透演示,虽然主流方式几乎是靠注入,但我丝毫不怀疑不经严格设计的业务代码会给整个机器带来极大的风险,2020 年的 linux 发行版,你也没法保证比如用限权用户部署就绝对安全了。楼上一大堆人装大头菜我也是佛了,还有问楼主是不是写 php 的这种引战的,通通 block
    crab
        35
    crab  
       2020-10-19 02:18:22 +08:00
    服务器安全用执行权限限制,被滥用没办法的,因为可以一张正常图尾部加二进制直接就过检测了,腾讯阿里都很多上传接口被滥用做图和视频床。
    buffzty
        36
    buffzty  
       2020-10-19 06:08:42 +08:00
    楼主先把这个防护做一下 随便找一台服务器 wrk 一下 每秒上 g 的流量. 阿里云 cdn 那种不限速的 一台主机一个小时就能刷好几千流量费
    ladypxy
        37
    ladypxy  
       2020-10-19 06:10:43 +08:00 via iPhone
    上传文件目录不给执行权限,其他目录不给写入权限,就是传了木马又能如何
    black11black
        38
    black11black  
    OP
       2020-10-19 07:09:29 +08:00
    @ladypxy 生产环境可以这么搞,个人站点之类的不容易,因为个人站点很难专机专用
    ladypxy
        39
    ladypxy  
       2020-10-19 08:47:46 +08:00
    @black11black 这个和是不是个人站点没关系啊?
    tesorouo
        40
    tesorouo  
       2020-10-19 09:39:08 +08:00
    不是应该挂 OSS 或者 S3,然后直接 call api 上传 /下载嘛?然后设置过滤检验不就齐了
    zarte
        41
    zarte  
       2020-10-19 09:58:55 +08:00
    就算图片里面是恶意代码通过 ng 直接访问文件目前有这个漏洞可以提权?
    lshero
        42
    lshero  
       2020-10-19 09:59:43 +08:00
    不给脚本执行权限就行了啊
    imdong
        43
    imdong  
       2020-10-19 10:24:32 +08:00 via iPhone
    看来楼主是想做到滴水不漏的安全防护,但我建议做到一定程度即可,因为“边际效益”会越来越低。

    历史上好像确实出现过操作系统的图片程序出现过一个 0day,特定构造的图片,其特殊的信息头可能导致任意代码执行,而这种情况不排除未来也会出现,这是你无法处理的,而且也不是你的责任,应该是用户端的安全防护,执行程序需要做的。

    楼主尽可能做到保护好自己的服务器不被攻击即可,至于图片被下载到本地后是否会影响用户,这个不是你能考虑的问题了,至于直接把其他文件的文件扩展名改成图片格式的客户端是否会执行,参见前两天那个关于后缀的讨论。

    说想防止被黑客利用分发二进制的,我再提供一个你绝对无法避免的问题,我把二进制文件的每一个字节转化为图片上的一个点,这个图片就是标准的图片,我客户端(下载器)读取图片后还原为程序再去执行,怎么办,无法避免,而且这种情况历史上就是出现过,Chrone 的某个扩展程序就爆出过这样的后门。

    所以做到以下几点,就合格了,服务器不被任意代码执行,不会有注入之类的问题,防止被恶意流量攻击(似乎没有太好的办法),上传的文件基本符合文件特征就好了,因为相比于上传的恶意文件是否会被客户端执行,我更关注的是是否会被当做在线流媒体分发平台,比如把音频,视频当做图片上传,然后网页在线播放(改后缀,指定头,都不影响播放)
    akira
        44
    akira  
       2020-10-20 23:46:42 +08:00
    如果是担心上传的图片被执行,那只要做好文件权限就可以了,上传上来的东西不要给执行权限已经可以搞定 90%以上的问题了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2837 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 13:46 · PVG 21:46 · LAX 05:46 · JFK 08:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.