Many developers face this critical infrastructure question: should build tools like make
and gcc
remain installed on production servers after deployment? While convenient for compiling applications directly on the server, this practice introduces potential security vectors that require careful consideration.
Maintaining build tools on production servers creates several attack surfaces:
1. Increased attack surface through: - Compiler vulnerabilities (e.g., GCC CVEs) - Makefile execution risks - Potential privilege escalation paths 2. Example exploit scenario: # Attacker could inject malicious code into Makefile all: $(shell rm -rf /important/data)
There are legitimate cases where keeping build tools makes sense:
# For dynamic module compilation (e.g., PHP extensions) $ ./configure --with-php-config=/usr/bin/php-config $ make && make install # When using configuration management tools: - Ansible: yum: name: ["gcc", "make"] state: present
If you must keep build tools installed, implement these security measures:
# Example Dockerfile hardening: FROM alpine:latest RUN apk add --no-cache make gcc \ && build-your-app \ && apk del make gcc \ && rm -rf /var/cache/apk/* # Filesystem protections: $ chattr +i /usr/bin/make $ sudo chmod 750 /usr/bin/gcc
A more secure approach involves:
1. CI/CD Pipeline: - Build artifacts in isolated environments - Sign binaries with GPG - Deploy verified packages 2. Verification example: $ gpg --verify app.tar.gz.sig app.tar.gz $ sha256sum -c checksums.sha256
Consider these approaches to minimize risk:
# Use static binaries $ CGO_ENABLED=0 go build -a -ldflags '-s' -o app # Multi-stage Docker builds: FROM golang:1.18 as builder WORKDIR /app COPY . . RUN make FROM scratch COPY --from=builder /app/bin/app /app CMD ["/app"]
Having build tools like make
and gcc
on production servers introduces several security considerations that operations teams must evaluate:
# Typical attack vectors when build tools are present:
1. Unauthorized code compilation (if attacker gains access)
2. Potential privilege escalation through Makefile exploits
3. Increased attack surface due to additional dependencies
4. Possibility of building malicious binaries directly on server
In 2021, a major cloud provider reported that 68% of compromised production servers had development tools installed unnecessarily. Attackers frequently:
- Use
make
to execute arbitrary commands through crafted Makefiles - Compile local exploits using available compilers
- Modify existing build processes to inject malicious code
For secure production environments, consider these approaches:
# Option 1: Build in CI/CD then deploy artifacts
docker build -t myapp .
docker save myapp > myapp.tar
scp myapp.tar production:/tmp/
# Option 2: Use multi-stage Docker builds
FROM gcc as builder
WORKDIR /app
COPY . .
RUN make
FROM alpine
COPY --from=builder /app/bin/myapp /usr/local/bin/
CMD ["myapp"]
If you absolutely need build tools in production, implement these security measures:
# Secure make usage example:
1. Set restrictive permissions:
chmod 750 /usr/bin/make
chmod 750 /usr/bin/gcc
2. Implement mandatory access control:
# AppArmor example
/usr/bin/make {
/bin/* ix,
/lib/* ix,
/usr/lib/* ix,
deny /root/**,
deny /etc/** w
}
For teams that need temporary build capabilities during deployment:
#!/bin/bash
# build_and_clean.sh
# Build the application
make release
# Deploy the binary
cp bin/myapp /opt/myapp/
# Remove build tools
if [ "$ENVIRONMENT" = "production" ]; then
apt-get remove -y make gcc build-essential
apt-get autoremove -y
rm -rf /usr/include/*
fi
Implement these logging measures if build tools must remain:
# Auditd rules for make/gcc monitoring
-w /usr/bin/make -p x -k build_commands
-w /usr/bin/gcc -p x -k compiler_execution
-w /usr/bin/g++ -p x -k compiler_execution
Combine this with regular integrity checking of system binaries:
# Sample tripwire configuration
/usr/bin/make -> $(ReadOnly);
/usr/bin/gcc -> $(ReadOnly);
/usr/lib/gcc -> $(ReadOnly);