You thought you figured out how to build your Node.js web applications with Docker? Chances are, you're probably missing out on a lot! Many articles on this topic have been written, yet sadly, without thoughtful consideration of security and production best practices for building Node.js Docker images.
In this session, we run through step-by-step production-grade guidelines for building optimized and secure Node.js Docker images by understanding the pitfalls and insecurities with every Dockerfile directive and then fixing it. We will also be hacking a live running Node.js Docker container and demonstrate several vectors of attacks. Join in and master the Node.js best practices for Docker-based applications.
14. @liran_tal
Attacking the heart of
developer tooling
// April 15, 2021
Codecov is a code quality tool
Disclosing a compromised artifact used in CI
15. @liran_tal
Attacking the heart of
developer tooling
// April 15, 2021
“Security response professionals are scrambling to measure the fallout from a
software supply chain compromise of Codecov Bash Uploader that went
undetected since January and exposed sensitive secrets like tokens, keys and
credentials from organizations around the world.”
// SecurityWeek.com
16. @liran_tal
Attacking the heart of
developer tooling
How did Codecov learn of Bash Uploader incident?
shasum,
4 months later,
by a community member
// April 15, 2021
17. @liran_tal
Attacking the heart of
developer tooling
// April 15, 2021
source: https://www.bleepingcomputer.com/news/security/codecov-hackers-gained-access-to-mondaycom-source-code
35. @liran_tal
const PDFImageLib = require("pdf-image").PDFImage;
const pdfData = new PDFImageLib(pdfFilePath);
What if pdfFilePath is user controlled?
36. @liran_tal
const PDFImageLib = require("pdf-image").PDFImage;
const pdfData = new PDFImageLib("asd.pdf"; touch /tmp/hacked"");
Like this ☝
40. @liran_tal
FROM node:lts-alpine@sha256:b2da3316ac
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY --chown=node:node . /usr/src/app
RUN npm ci --only=production
USER node
CMD "npm" "start"
✔ Drop privileges before executing
✔ Preserve proper permissions
54. @liran_tal
“Node.js was not designed to run as PID 1 which leads to
unexpected behaviour when running inside of Docker.
For example, a Node.js process running as PID 1 will not
respond to SIGINT (CTRL-C) and similar signals”
- Node.js Docker working group
recommendations, [source].
55. @liran_tal
FROM node:lts-alpine@sha256:b2da3316ac
RUN apk add dumb-init
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN npm ci --only=production
CMD ["dumb-init", "node", "server.js"]
▶
Lightweight init system: dumb-init
▶
57. @liran_tal
async function closeGracefully(signal) {
console.log(`*^!@4=> Terminating: ${signal}`)
await fastify.close()
// await db.close() if we have a db connection
process.exit()
}
process.on('SIGINT', closeGracefully)
process.on('SIGTERM', closeGracefully)
▶
59. @liran_tal
$ docker scan node:14.10.1
✗ High severity vulnerability found in imagemagick/libmagickcore-6.q16-3
Description: XML Injection
Info: https://snyk.io/vuln/SNYK-DEBIAN9-IMAGEMAGICK-1049975
Introduced through: imagemagick@8:6.9.7.4+dfsg-11+deb9u10
From: imagemagick@8:6.9.7.4+dfsg-11+deb9u10 and 24 more…
Image layer: Introduced by your base image (node:14.10.1)
Fixed in: 8:6.9.7.4+dfsg-11+deb9u11
▶
60. @liran_tal
$ docker scan node:14.10.1
✗ High severity vulnerability found in imagemagick/libmagickcore-6.q16-3
Description: XML Injection
Info: https://snyk.io/vuln/SNYK-DEBIAN9-IMAGEMAGICK-1049975
Introduced through: imagemagick@8:6.9.7.4+dfsg-11+deb9u10
From: imagemagick@8:6.9.7.4+dfsg-11+deb9u10 and 24 more…
Image layer: Introduced by your base image (node:14.10.1)
Fixed in: 8:6.9.7.4+dfsg-11+deb9u11
▶
61. @liran_tal
$ docker scan node:14.10.1
✗ High severity vulnerability found in imagemagick/libmagickcore-6.q16-3
Description: XML Injection
Info: https://snyk.io/vuln/SNYK-DEBIAN9-IMAGEMAGICK-1049975
Introduced through: imagemagick@8:6.9.7.4+dfsg-11+deb9u10
From: imagemagick@8:6.9.7.4+dfsg-11+deb9u10 and 24 more…
Image layer: Introduced by your base image (node:14.10.1)
Fixed in: 8:6.9.7.4+dfsg-11+deb9u11
▶
62. @liran_tal
$ docker scan node:14.10.1
✗ High severity vulnerability found in imagemagick/libmagickcore-6.q16-3
Description: XML Injection
Info: https://snyk.io/vuln/SNYK-DEBIAN9-IMAGEMAGICK-1049975
Introduced through: imagemagick@8:6.9.7.4+dfsg-11+deb9u10
From: imagemagick@8:6.9.7.4+dfsg-11+deb9u10 and 24 more…
Image layer: Introduced by your base image (node:14.10.1)
Fixed in: 8:6.9.7.4+dfsg-11+deb9u11
Tested 412 dependencies for known issues, found 624 issues.
▶
63. @liran_tal
What’s the worst that can happen?
🙃
$ docker scan node:14.10.1
Tested 412 dependencies for known issues, found 624 issues.
64. @liran_tal
$ docker scan node:14.10.1
✗ High severity vulnerability found in imagemagick/libmagickcore-6.q16-3
Description: XML Injection
Info: https://snyk.io/vuln/SNYK-DEBIAN9-IMAGEMAGICK-1049975
Introduced through: imagemagick@8:6.9.7.4+dfsg-11+deb9u10
From: imagemagick@8:6.9.7.4+dfsg-11+deb9u10 and 24 more…
Image layer: Introduced by your base image (node:14.10.1)
Fixed in: 8:6.9.7.4+dfsg-11+deb9u11
Tested 412 dependencies for known issues, found 624 issues.
▶
What now? 😕
67. @liran_tal
$ docker scan node:14.10.1
✗ High severity vulnerability found in imagemagick/libmagickcore-6.q16-3
Description: XML Injection
Info: https://snyk.io/vuln/SNYK-DEBIAN9-IMAGEMAGICK-1049975
Introduced through: imagemagick@8:6.9.7.4+dfsg-11+deb9u10
From: imagemagick@8:6.9.7.4+dfsg-11+deb9u10 and 24 more…
Image layer: Introduced by your base image (node:14.10.1)
Fixed in: 8:6.9.7.4+dfsg-11+deb9u11
Tested 412 dependencies for known issues, found 624 issues.
▶
What now? 😕
72. @liran_tal
Level up your Node.js container-fu
Follow best practices for building containers securely
source: https://snyk.io/blog/10-best-practices-to-containerize-nodejs-web-applications-with-docker/