Article
The CIS (Center for Internet Security) Benchmarks are internationally recognized security configuration guidelines that provide prescriptive guidance for hardening systems, software, and cloud environments. For Java applications, achieving CIS compliance means systematically implementing security controls across the application stack—from the JVM and application server to the container and underlying operating system. This comprehensive approach ensures Java applications meet industry-best security practices.
What are CIS Benchmarks for Java?
CIS Benchmarks provide detailed, consensus-based security configuration guidelines for:
- Operating Systems: Linux, Windows, etc.
- Middleware: Tomcat, JBoss, WebLogic, WebSphere
- Containers: Docker, Kubernetes
- Cloud Platforms: AWS, Azure, GCP
- Java Runtime: JVM security settings
For Java applications, compliance involves implementing controls across multiple layers of the technology stack to create a defense-in-depth security posture.
Why CIS Compliance is Critical for Java Applications
- Industry Standard: CIS Benchmarks are developed through community consensus and widely adopted
- Regulatory Compliance: Many regulations (HIPAA, PCI-DSS, SOX) reference or require CIS controls
- Risk Reduction: Systematically addresses common misconfigurations that lead to breaches
- Audit Readiness: Provides documented evidence of security diligence
- Supply Chain Security: Ensures consistent security posture across environments
JVM CIS Compliance Hardening
1. Secure JVM Launch Configuration
Implement CIS-recommended JVM security settings:
#!/bin/bash # cis-jvm-launch.sh java \ # CIS 1.1: Use security manager -Djava.security.manager \ -Djava.security.policy==/app/conf/cis-security.policy \ # CIS 1.2: Configure cryptographic policies -Djava.security.properties==/app/conf/cis-java.security \ # CIS 1.3: Disable weak TLS protocols -Djdk.tls.disabledAlgorithms=SSLv2, SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 2048, RSA keySize < 2048 \ # CIS 1.4: Disable weak certificate algorithms -Djdk.certpath.disabledAlgorithms=MD2, MD5, SHA1, RSA keySize < 2048, DSA keySize < 2048, EC keySize < 224 \ # CIS 1.5: Configure secure random number generation -Djava.security.egd=file:/dev/./urandom \ # CIS 1.6: Restrict RMI access -Djava.rmi.server.hostname=localhost \ -Dcom.sun.management.jmxremote.authenticate=true \ -Dcom.sun.management.jmxremote.ssl=true \ # CIS 1.7: Disable JNI from untrusted code -Djava.security.manager \ # Memory and execution security -Xmx1024m -Xms512m \ -XX:MaxMetaspaceSize=256m \ -XX:+UseG1GC \ -XX:+ExitOnOutOfMemoryError \ -XX:+CrashOnOutOfMemoryError \ # Logging security (CIS 1.8) -Dlog4j2.formatMsgNoLookups=true \ -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \ -jar application.jar
2. CIS-Compliant Java Security Policy
// cis-security.policy
grant {
// CIS 2.1: Minimal permissions for application code
permission java.util.PropertyPermission "user.timezone", "read";
permission java.util.PropertyPermission "file.encoding", "read";
permission java.util.PropertyPermission "java.io.tmpdir", "read";
permission java.util.PropertyPermission "user.home", "read";
// CIS 2.2: Network permissions (restrictive)
permission java.net.SocketPermission "database.example.com:5432", "connect";
permission java.net.SocketPermission "redis.example.com:6379", "connect";
permission java.net.SocketPermission "logs.example.com:514", "connect";
// CIS 2.3: File system permissions (least privilege)
permission java.io.FilePermission "/app/logs/-", "read,write";
permission java.io.FilePermission "/app/tmp/-", "read,write,delete";
permission java.io.FilePermission "/app/conf/-", "read";
// CIS 2.4: Restrict reflection
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
// CIS 2.5: Runtime permissions
permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "setContextClassLoader";
permission java.lang.RuntimePermission "modifyThread";
// Explicitly deny dangerous permissions
permission java.lang.RuntimePermission "exitVM", "", deny;
permission java.lang.RuntimePermission "setFactory", "", deny;
permission java.io.FilePermission "<<ALL FILES>>", "execute", deny;
permission java.net.SocketPermission "*:1-1023", "listen,accept", deny;
};
// Grant permissions to trusted libraries only
grant codeBase "file:${java.home}/lib/-" {
permission java.security.AllPermission;
};
grant codeBase "file:/app/lib/trusted/*" {
permission java.security.AllPermission;
};
3. CIS Java Security Properties
# cis-java.security # CIS 3.1: Cryptographic strength configuration jdk.tls.disabledAlgorithms=SSLv2, SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5, DSA, DH keySize < 2048, RSA keySize < 2048, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1, RSA keySize < 2048, DSA keySize < 2048, EC keySize < 224 # CIS 3.2: Configure secure random securerandom.source=file:/dev/./urandom securerandom.strongAlgorithms=NativePRNGBlocking:SUN # CIS 3.3: RMI security java.rmi.server.randomIDs=true sun.rmi.transport.tcp.readTimeout=30000 sun.rmi.transport.tcp.handshakeTimeout=30000 # CIS 3.4: JAXP security jdk.xml.enableExtensionFunctions=false jdk.xml.xpath.totalEntitySizeLimit=50000
Apache Tomcat CIS Compliance
1. CIS-Compliant server.xml
<!-- CIS Tomcat Benchmark Implementation -->
<Server port="8005" shutdown="SHUTDOWN" address="127.0.0.1">
<!-- CIS 4.1: Use security listener -->
<Listener className="org.apache.catalina.security.SecurityListener"
checkedOsUsers="root"
checkedOsGroups="tomcat"/>
<Service name="Catalina">
<!-- CIS 4.2: HTTPS connector with strong crypto -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true"
maxThreads="150"
minSpareThreads="25"
maxConnections="10000"
connectionTimeout="30000"
maxHttpHeaderSize="8192"
<!-- CIS 4.3: Security headers -->
server=" "
xpoweredBy="false"
<!-- CIS 4.4: Disable risky features -->
enableLookups="false"
allowTrace="false"
maxPostSize="10485760"
maxSavePostSize="4096"
<!-- CIS 4.5: TLS configuration -->
sslEnabledProtocols="TLSv1.2,TLSv1.3"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
keyAlias="tomcat"
keystoreFile="/app/conf/keystore.jks"
keystorePass="${keystore.password}">
</Connector>
<Engine name="Catalina" defaultHost="localhost">
<!-- CIS 4.6: Host configuration -->
<Host name="localhost" appBase="webapps"
unpackWARs="true"
autoDeploy="false"
deployOnStartup="false">
<!-- CIS 4.7: Access logging -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b %D"
rotatable="true"/>
<!-- CIS 4.8: Remote address filter -->
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.0\.0\.1,::1,10\.\d+\.\d+\.\d+"/>
<!-- CIS 4.9: Error reporting -->
<Valve className="org.apache.catalina.valves.ErrorReportValve"
showReport="false"
showServerInfo="false"/>
</Host>
</Engine>
</Service>
</Server>
2. CIS-Compliant web.xml
<!-- CIS Web Application Security --> <web-app> <!-- CIS 5.1: Session configuration --> <session-config> <session-timeout>30</session-timeout> <cookie-config> <http-only>true</http-only> <secure>true</secure> <same-site>strict</same-site> </cookie-config> </session-config> <!-- CIS 5.2: Security constraints --> <security-constraint> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> <!-- CIS 5.3: Error pages --> <error-page> <error-code>404</error-code> <location>/error/404.html</location> </error-page> <error-page> <error-code>500</error-code> <location>/error/500.html</location> </error-page> <!-- CIS 5.4: MIME type security --> <mime-mapping> <extension>json</extension> <mime-type>application/json</mime-type> </mime-mapping> </web-app>
Spring Boot CIS Compliance
1. CIS-Compliant Application Properties
# application-cis.properties
# CIS 6.1: Server security
server.port=8443
server.servlet.session.timeout=1800
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true
server.servlet.session.cookie.same-site=strict
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=${KEYSTORE_PASSWORD}
server.ssl.key-store-type=JKS
server.ssl.key-alias=tomcat
server.ssl.protocol=TLS
server.ssl.enabled-protocols=TLSv1.2,TLSv1.3
# CIS 6.2: Actuator security
management.endpoints.web.exposure.include=health,info
management.endpoints.web.base-path=/internal/actuator
management.endpoint.health.show-details=when_authorized
management.endpoint.health.roles=ADMIN
management.server.port=9091
management.server.address=127.0.0.1
# CIS 6.3: Security headers
server.servlet.session.tracking-modes=cookie
server.servlet.application-display-name=Application
2. CIS-Compliant Security Configuration
@Configuration
@EnableWebSecurity
public class CisSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
// CIS 7.1: CSRF protection
.csrf(csrf -> csrf
.ignoringRequestMatchers("/api/public/**")
)
// CIS 7.2: Security headers
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("default-src 'self'; script-src 'self' 'unsafe-inline'"))
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.maxAgeInSeconds(31536000))
.frameOptions(frame -> frame
.deny())
.xssProtection(xss -> xss
.headerValue(XXssConfig.HeaderValue.ENABLED_MODE_BLOCK))
.contentTypeOptions(ContentTypeOptionsConfig::disable)
)
// CIS 7.3: Session management
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.sessionFixation(sf -> sf.migrateSession())
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
)
// CIS 7.4: Authorization
.authorizeHttpRequests(authz -> authz
.requestMatchers("/actuator/**").hasRole("ADMIN")
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/user/**").hasRole("USER")
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.build();
}
}
Container CIS Compliance
1. CIS-Compliant Dockerfile
# CIS Docker Benchmark Compliance FROM eclipse-temurin:17-jre-alpine # CIS 8.1: Use minimal base image LABEL maintainer="[email protected]" \ cis.benchmark.version="1.0" \ security.scan="true" # CIS 8.2: Create non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup # CIS 8.3: Install security updates RUN apk update && apk upgrade && rm -rf /var/cache/apk/* # CIS 8.4: Copy application with secure permissions COPY --chown=appuser:appgroup target/application.jar /app/application.jar COPY --chown=appuser:appgroup cis-security.policy /app/conf/cis-security.policy COPY --chown=appuser:appgroup cis-java.security /app/conf/cis-java.security # CIS 8.5: Set secure file permissions RUN chmod -R 750 /app && \ chmod 400 /app/conf/*.policy && \ chmod 400 /app/conf/*.security && \ find /app -type f -name "*.jar" -exec chmod 440 {} \; # CIS 8.6: Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD curl -f https://localhost:8443/actuator/health || exit 1 # CIS 8.7: Use non-root user USER appuser # CIS 8.8: Secure entrypoint ENTRYPOINT ["java", "-Djava.security.manager", "-Djava.security.policy==/app/conf/cis-security.policy", "-jar", "/app/application.jar"]
2. CIS-Compliant Kubernetes Deployment
# cis-compliant-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-app
labels:
app: java-app
cis-benchmark: "v1.0"
spec:
replicas: 3
selector:
matchLabels:
app: java-app
template:
metadata:
labels:
app: java-app
spec:
# CIS 9.1: Security context
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: java-app
image: company/java-app:cis-v1.0
# CIS 9.2: Container security context
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
# CIS 9.3: Resource limits
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "500m"
# CIS 9.4: Environment security
env:
- name: KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: keystore-password
# CIS 9.5: Readiness and liveness probes
livenessProbe:
httpGet:
path: /actuator/health
port: 8443
scheme: HTTPS
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health
port: 8443
scheme: HTTPS
initialDelaySeconds: 30
periodSeconds: 5
# CIS 9.6: Volume mounts (read-only)
volumeMounts:
- name: tmp
mountPath: /tmp
readOnly: false
- name: logs
mountPath: /app/logs
readOnly: false
volumes:
- name: tmp
emptyDir: {}
- name: logs
emptyDir: {}
Automated CIS Compliance Validation
1. Compliance Validation Script
@Component
public class CisComplianceValidator {
private static final Logger logger = LoggerFactory.getLogger(CisComplianceValidator.class);
@EventListener
public void validateCisCompliance(ApplicationReadyEvent event) {
logger.info("Starting CIS compliance validation...");
validateJvmSecurity();
validateCryptographicSettings();
validateSessionSecurity();
validateNetworkSecurity();
logger.info("CIS compliance validation completed");
}
private void validateJvmSecurity() {
// CIS 10.1: Verify security manager
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
throw new CisComplianceException("CIS 10.1: Security manager is not enabled");
}
// CIS 10.2: Verify TLS settings
String disabledAlgorithms = Security.getProperty("jdk.tls.disabledAlgorithms");
if (!disabledAlgorithms.contains("TLSv1") || !disabledAlgorithms.contains("TLSv1.1")) {
throw new CisComplianceException("CIS 10.2: Weak TLS protocols are enabled");
}
}
private void validateCryptographicSettings() {
// CIS 10.3: Verify key sizes
String certPathAlgorithms = Security.getProperty("jdk.certpath.disabledAlgorithms");
if (!certPathAlgorithms.contains("RSA keySize < 2048")) {
throw new CisComplianceException("CIS 10.3: Weak RSA keys are allowed");
}
}
private void validateSessionSecurity() {
// CIS 10.4: Verify session timeout
int sessionTimeout = environment.getProperty("server.servlet.session.timeout", Integer.class, 1800);
if (sessionTimeout > 3600) {
throw new CisComplianceException("CIS 10.4: Session timeout exceeds maximum (3600 seconds)");
}
}
}
2. CIS Compliance Reporting
@Service
public class CisComplianceService {
public CisComplianceReport generateComplianceReport() {
List<CisControl> controls = Arrays.asList(
checkControl("CIS 1.1", "JVM Security Manager", checkSecurityManager()),
checkControl("CIS 1.2", "Cryptographic Policies", checkCryptoPolicies()),
checkControl("CIS 1.3", "TLS Configuration", checkTlsConfiguration()),
checkControl("CIS 4.1", "Tomcat Security Listener", checkTomcatSecurity()),
checkControl("CIS 6.1", "Spring Boot Security", checkSpringBootSecurity()),
checkControl("CIS 8.1", "Container Security", checkContainerSecurity())
);
return CisComplianceReport.builder()
.timestamp(Instant.now())
.application(environment.getProperty("spring.application.name"))
.version(environment.getProperty("app.version"))
.controls(controls)
.complianceScore(calculateComplianceScore(controls))
.build();
}
private CisControl checkControl(String id, String description, boolean compliant) {
return CisControl.builder()
.id(id)
.description(description)
.compliant(compliant)
.timestamp(Instant.now())
.build();
}
}
Continuous Compliance Monitoring
1. CIS Compliance Dashboard
@RestController
@RequestMapping("/api/cis")
public class CisComplianceController {
@Autowired
private CisComplianceService complianceService;
@GetMapping("/report")
public CisComplianceReport getComplianceReport() {
return complianceService.generateComplianceReport();
}
@GetMapping("/controls")
public List<CisControl> getControlStatus() {
return complianceService.getControlStatus();
}
@GetMapping("/exceptions")
public List<CisException> getComplianceExceptions() {
return complianceService.getApprovedExceptions();
}
}
Best Practices for CIS Compliance
- Start with Assessment: Conduct baseline assessment before implementing controls
- Prioritize Critical Controls: Focus on Level 1 controls that don't impact functionality
- Document Exceptions: Maintain formal documentation for any non-compliant controls
- Automate Validation: Implement automated compliance checking in CI/CD pipelines
- Regular Audits: Conduct quarterly compliance audits and reviews
- Version Control: Track CIS Benchmark versions and update configurations accordingly
- Training: Educate development and operations teams on CIS requirements
CIS Compliance Checklist for Java Applications
- [ ] JVM security manager enabled
- [ ] Weak TLS protocols disabled (TLS 1.0, 1.1)
- [ ] Cryptographic algorithms properly configured
- [ ] Application runs as non-root user
- [ ] File system permissions properly set
- [ ] Session timeout configured appropriately
- [ ] Security headers implemented
- [ ] Error messages sanitized
- [ ] Access logs enabled and secured
- [ ] Resource limits configured
Conclusion
Achieving CIS Benchmark compliance for Java applications is a comprehensive process that requires systematic implementation of security controls across the entire technology stack. By following the prescriptive guidance provided by CIS Benchmarks, organizations can significantly enhance their security posture, meet regulatory requirements, and build resilient Java applications.
The journey to CIS compliance involves not just technical implementation but also establishing processes for continuous monitoring, validation, and improvement. For Java teams operating in enterprise environments, CIS compliance provides a standardized framework for security excellence that is recognized and respected across the industry. In an era of increasing cyber threats, CIS Benchmark compliance represents a critical step toward building truly secure Java applications.
Advanced Java Supply Chain Security, Kubernetes Hardening & Runtime Threat Detection
Sigstore Rekor in Java – https://macronepal.com/blog/sigstore-rekor-in-java/
Explains integrating Sigstore Rekor into Java systems to create a transparent, tamper-proof log of software signatures and metadata for verifying supply chain integrity.
Securing Java Applications with Chainguard Wolfi – https://macronepal.com/blog/securing-java-applications-with-chainguard-wolfi-a-comprehensive-guide/
Explains using Chainguard Wolfi minimal container images to reduce vulnerabilities and secure Java applications with hardened, lightweight runtime environments.
Cosign Image Signing in Java Complete Guide – https://macronepal.com/blog/cosign-image-signing-in-java-complete-guide/
Explains how to digitally sign container images using Cosign in Java-based workflows to ensure authenticity and prevent unauthorized modifications.
Secure Supply Chain Enforcement Kyverno Image Verification for Java Containers – https://macronepal.com/blog/secure-supply-chain-enforcement-kyverno-image-verification-for-java-containers/
Explains enforcing Kubernetes policies with Kyverno to verify container image signatures and ensure only trusted Java container images are deployed.
Pod Security Admission in Java Securing Kubernetes Deployments for JVM Applications – https://macronepal.com/blog/pod-security-admission-in-java-securing-kubernetes-deployments-for-jvm-applications/
Explains Kubernetes Pod Security Admission policies that enforce security rules like restricted privileges and safe configurations for Java workloads.
Securing Java Applications at Runtime Kubernetes Security Context – https://macronepal.com/blog/securing-java-applications-at-runtime-a-guide-to-kubernetes-security-context/
Explains how Kubernetes security contexts control runtime permissions, user IDs, and access rights for Java containers to improve isolation.
Process Anomaly Detection in Java Behavioral Monitoring – https://macronepal.com/blog/process-anomaly-detection-in-java-comprehensive-behavioral-monitoring-2/
Explains detecting abnormal runtime behavior in Java applications to identify potential security threats using process monitoring techniques.
Achieving Security Excellence CIS Benchmark Compliance for Java Applications – https://macronepal.com/blog/achieving-security-excellence-implementing-cis-benchmark-compliance-for-java-applications/
Explains applying CIS security benchmarks to Java environments to standardize hardening and improve overall system security posture.
Process Anomaly Detection in Java Behavioral Monitoring – https://macronepal.com/blog/process-anomaly-detection-in-java-comprehensive-behavioral-monitoring/
Explains behavioral monitoring of Java processes to detect anomalies and improve runtime security through continuous observation and analysis.