8

I'm working on a web service that uses ffmpeg on the backend for processing user uploaded media files. I'm giving the users some options to customize how their videos are processed, which is essentially parameterize the ffmpeg command.

I'm planning to run ffmpeg in a Docker environment, possibly with a new container per execution. Regardless, this environment could be used to execute arbitrary code and might have have access to some of my secrets.

Beyond command-line injection, are there any other security concerns to consider here?

I am running ffmpeg inside a docker container with networking disabled and passing the input and output files via a shared directory.

The command below does the following:

  • Puts the input file into a shared directory with the container
  • Runs ffmpeg inside the container with whatever options are passed
  • Puts the output file into the host shared directory, where the host will then copy it to it's final storage location

Command:

docker run -v <TEMP_DIR_ON_HOST>:/temp/ --network none \
    jrottenberg/ffmpeg -stats \
    -i /temp/<INPUT_FILE> \
    <FFMPEG_OPTIONS> \
    /temp/<OUTPUT_FILE>

A few notes:

  • TEMP_DIR_ON_HOST is a single use directory for one conversion
  • FFMPEG_OPTIONS are scrubbed, but could potentially contain injection
  • I'm not locked into the jrottenberg/ffmpeg image, I might make a copy or at least lock down to a particular version.

I think that disabling networking and limiting outside file access greatly reduces the risk even if malicious commands are injected somehow.

Are there any major risks beyond wasted resources?

ThoriumBR
  • 51,983
  • 13
  • 131
  • 149
leros
  • 183
  • 1
  • 5

1 Answers1

9

Yes there are security risks, especially if you allow arbitrary formats. FFmpeg supports a huge variety of formats, both popular and obscure, for video, audio, and images. Any vulnerability in decoders for any of the numerous formats could be exploited to gain arbitrary code execution. This becomes even more likely given the fact that FFmpeg is written in C, which is not memory safe, and is optimized for speed instead of security. You must assume any untrusted input passed to FFmpeg can be used to gain full arbitrary code execution in the context of the running process and build your threat model around that.

There are a few things you can do to mitigate potential risks in addition to hardening Docker:

  • Seccomp sandboxing - Enable seccomp in Docker to limit the syscalls that can be made. A syscall, or system call, is the interface used by userspace to communicate with the kernel. Certain syscalls are complex and can be insecure, opening up bugs in the kernel to exploitation.

  • Formats/codecs - Disable unused decoders to reduce the attack surface area of the decoder. Many formats, or formats with obscure features, have low-quality decoders that are not regularly checked for bugs. While the Opus decoder is likely of acceptable quality, what about G.726?

  • Resource limits - Restrict resources that any given FFmpeg process can use. Resources can not only be used to DoS the system, but can be necessary to exploit other vulnerabilities to elevate privileges, for example certain kinds of integer overflows that require large memory allocations.

  • Mandatory Access Controls - Use a MAC like AppArmor or SELinux to restrict accesses and protect sensitive objects, even in the case of a Docker breakout. You can also use a MAC to limit network connections, since there is no reason FFmpeg should upload or download data.

  • Compiler hardening - Use hardening when building FFmpeg, or download a hardened version. Compiler hardening like PIE, SSP, and FORTIFY_SOURCE can make vulnerabilities harder to exploit. PIE is especially important, as it allows the operating system to make full use of ASLR.

Glorfindel
  • 2,263
  • 6
  • 19
  • 30
forest
  • 65,613
  • 20
  • 208
  • 262
  • 2
    This is good advice. If I can lock down the docker container to do nothing but 1) download the input files and 2) only make outbound connections to upload the resulting files, then the amount of damage possible is much lower. All they could do is eat up CPU and memory in the container. – leros Dec 28 '18 at 04:47
  • 3
    @leros It would be better to limit the network connection to a broker outside of docker, and only pass the raw file input to the container and retrieve the raw output. Networking should be done outside of it. – forest Dec 28 '18 at 04:57
  • I've taken some of your suggestions and updated my original post with an edit. The ffmpeg execution is now performed inside of another container rather than executing ffmpeg directly. Networking in that container is disabled and files are passed in/out via a single use directory. I believe this limits the surface area of an attack now. Yes, arbitrary code could be run inside of the container, but it's damage would be limited to wasting resources and writing files to the temp directory that are only copied or ignored. Can you reassess? Would you do additional hardening? – leros Dec 28 '18 at 18:33
  • @leros I would still do additional hardening. The most important thing is to enable the seccomp sandbox and limit the supported formats/codecs. Additional hardening like compiler hardening is optional and not as important, but still a good idea if you are able to do it. The most important thing is to provide _defense in depth_ by layering multiple times of defenses and not relying on just one or two. – forest Dec 29 '18 at 04:43