Monitoring Java Application Security
with JDK Tools and JFR Events
Hello! I am Ana
Agenda
JFR Security Events Overview
Observing JDK Security Properties
Monitoring TLS Protocol
Analysing X.509 certificates
Continuous Monitoring in the Cloud
Goal
JFR Security Events Overview
JDK Flight Recorder(JFR) Events
When running a Java application, JFR can collect events that occur in the JVM.
JFR Events express the state of the application and underlying JVM.
For profiling, store event data in a .jfr file.
Timestamp Duration ThreadID
Stack
Trace ID
Event Specific Payload
JFR Event Components
Event
ID
JFR Security Events
Name Goal Backported
To
Enabled By
Default*
jdk.SecurityPropertyModification Records calls to Security.setProperty(String
key, String value).
Oracle JDK 11.0.5
and 8u231
No
jdk.TLSHandshake Keeps track of TLS handshake activity. Oracle JDK 11.0.5
and 8u231
No
jdk.X509Certificate Records details of X.509 Certificates. Oracle JDK 11.0.5
and 8u231
No
jdk.X509Validation Records details of X.509 certificates
negotiated in successful X.509 validation.
Oracle JDK 11.0.5
and 8u231
No
jdk.InitialSecurityProperty For insights on initial JDK security
properties.
Oracle JDK 17.0.7
and 11.0.20
Yes
jdk.SecurityProviderService Records service provider method
invocations.
JDK 17.0.8, 11.0.22
and 8u391
No
* In default.jfc and profile.jfc shipped within a JDK
Observing JDK Security Properties
Dealing with Security Properties
Initial security properties set statically in the $JAVA_HOME/conf/security file.
Dynamically set security properties via java.security.Security methods.
Early security considerations reduce long-term risks.
Ways to Observe Initial Security Properties
Log the initial security properties.
java -Djava.security.debug=properties
Record jdk.InitialSecurityProperty JFR event.
Enable JFR recording java -XX:StartFlightRecording:settings=default,duration=60s
Or start a flight recording by connecting to the running application from JDK Mission Control.
Using –Xshowsettings:security option
Configuration since JDK 22 Description Ported to*
java -XshowSetttings:security will show all security settings JDK 21.0.4, JDK
17.0.12, Oracle JDK
11.0.24, Oracle JDK
8u421
java -XshowSetttings:security:property will show the values of security
properties.
java -XshowSetttings:security:providers will show the installed security
providers and their supported
algorithms.
java -XshowSetttings:security:tls will show the enabled TLS protocols
and cipher suites.
How to Trace Security Properties
Changes?
Broad View Over JDK Security Properties
Inspect the recording with jcmd or JDK Mission Control.
Start a JFR recording when launching the application.
java -XX:StartFlightRecording:settings=default,duration=60s
Have jdk.SecurityPropertyModification enabled in JFR configuration.
$JAVA_HOME/bin/jfr configure jdk.SecurityPropertyModification#enabled=true
Extra Tips to Observe Security Properties (1)
Configure more JFR events by adding a space between each setting.
Setup jdk.SecurityPropertyModification when launching the JVM.
Set more JFR events when launching the JVM, separated by comma.
$JAVA_HOME/bin/jfr configure event1#enabled=true event2#enabled=false
java -XX:StartFlightRecording:settings=default,+jdk.SecurityPropertyModification#enabled=true
java -XX:StartFlightRecording:settings=default,+event1#enabled=true,+event2#enabled=false
Extra Tips to Observe Security Properties (2)
Configure each JFR event from JDK Mission Control (JMC)
Inspect the evolution of captured events in JMC.
Event Browser > Java Development Kit > Security
Create a connection to a running JVM (this time -XX:StartFlightRecording is not mandatory).
In JMC menu, select File > Connection... > [Select one running JVM] > Start Flight Recording
Configure each JDK Security event.
Monitoring TLS Protocol
Why is TLS Important?
Message integrity: identify the unauthorized modification of data during transit.
Authenticity: ability to identify a user/system before communicating information.
certificate authorities/digital certificates
Confidentiality: protect sensitive data/information from unauthorized users.
encryption/decryption
certificate authorities/digital certificates
Capture TLS Protocol Information
Use a network protocol analyzer tool.
Attach the tool to the network interface where the JVM communicates.
Look for "Server Hello" record to determine TLS version used on a particular socket.
A Java developer friendly way: inspect debug logs.
java -Djavax.net.debug=ssl:handshake
Configure jdk.TLSHandshake JFR event to get essential TLS information.
Capture TLS Protocol Details with JDK Tools
Run jfr configure command in a terminal window.
jfr configure jdk.TLSHandshake#enabled=true
jdk.TLSHandshake#stackTrace=true
Switch jdk.TLSHandshake options to true in JFR configuration file.
Start a recording while jdk.TLSHandshake is enabled as well.
java -XX:StartFlightRecording:settings=default,duration=60s,
+jdk.TLSHandshake#enabled=true,+jdk.TLSHandshake#stackTrace=true
Local Demo Setup Overview
Running TicTacToe locally
Monitor with JDK tools
Spring Boot application
with JDK 23
Keystore
Truststore
Client Certificate #local.ext file
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = springboot
IP.1 = 127.0.0.1
Inspect TLS Handshakes with Jcmd and JFR
# start a recording
jcmd llvmid JFR.start duration=60s filename=/tmp/TLS.jfr
# use jfr print command
$JAVA_HOME/bin/jfr print --events "TLS*" /tmp/TLS.jfr
jdk.TLSHandshake {
startTime = 12:55:27.396 (2024-03-03)
peerHost = "google.com"
peerPort = 8443
protocolVersion = "TLSv1.3"
cipherSuite = "TLS_AES_128_GCM_SHA256"
certificateId = 587815551
eventThread = "tomcat-handler-15" (javaThreadId = 93, virtual)
stackTrace = [
sun.security.ssl.Finished.recordEvent(SSLSessionImpl) line: 1165
sun.security.ssl.Finished$T13FinishedConsumer.onConsumeFinished(ServerHandshakeContext, ByteBuffer)
line: 1138
...
]
}
Analysing X.509 Certificates
Importance of X.509 Certificates
Bind an identity to a public key using a digital signature.
Enable secure communication and transaction between two parties.
Establish trust based on a series of fields:
version
serial number
signature (algorithm ID and parameters)
issuer name
validity period
subject name
subject public key (and associated algorithm ID)
View Certificate Details
# use keytool to query certificates in JDK truststore
$JAVA_HOME/bin/keytool -cacerts -list –v
# use keytool to query certificates in a keystore
keytool -v -list -keystore /path/to/keystore
# print verbose X.509 certificate information
java -Djava.security.debug=certpath -Djavax.net.debug=all
Enable Details about X.509 Certificates in JFR
# enable jdk.X509Certificate, jdk.X509Validation events in your JFR configuration file
<event name="jdk.X509Certificate">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>
<event name="jdk.X509Validation">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>
# or run jfr configure command in a terminal window
$JAVA_HOME/bin/jfr configure jdk.X509Certificate#enabled=true jdk.X509Validation#enabled=true
# or enable JFR events on application launch
java -XX:StartFlightRecording:settings=default,jdk.X509Certificate#enabled=true,
+jdk.X509Validation#enabled=true
Capture Certificate Details with jcmd and JFR
Execute a diagnostic command via jcmd.
.
jcmd llvmid JFR.start duration=60s filename=/tmp/cert.jfr
Run your application with -XX:StartFlightRecording flag and have
jdk.X509Certificate and jdk.X509Validation options enabled.
Show recorded details about X.509 Certificates.
$JAVA_HOME/bin/jfr print --events jdk.X509Certificate /tmp/cert.jfr
The jfr scrub Command
• Filter data from the specified recording file.
jfr scrub [filters] [recording-file] [output-file]
• Supply which events to include.
jfr scrub --include-events jdk.FileRead,jdk.FileWrite
• Include a category and exclude events.
jfr scrub --include-categories GC* --exclude-events jdk.GCLocker
• Remove all events by category: jfr scrub --exclude-categories GC*
[JFR scrub recording data— JDK-8281175]
Continuous Monitoring in the Cloud
Streaming JFR Events
JDK Flight Recorder provides rich, structured data, and API support to event
streams.
Since JDK 16, you can transfer recorded events programmatically, as they occur,
over the network using javax.management.MBeanServerConnection.
Until JDK 16, developers could monitor a Java process on a remote host and
control what is recorded via JDK Mission Control.
Monitor a Remote Host with MBeanServerConnection
String host = "com.example";
int port = 7091;
String url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi";
JMXServiceURL u = new JMXServiceURL(url);
JMXConnector c = JMXConnectorFactory.connect(u);
MBeanServerConnection connection = c.getMBeanServerConnection();
try (RemoteRecordingStream stream = new RemoteRecordingStream(connection)) {
stream.enabled("jdk.X509Certificate").withStackTrace();
stream.onEvent("jdk.X509Certificate", System.out::println),
stream.start();
}
Stream JFR Events Actively, Within Process
CompositeMeterRegistry metricsRegistry = Metrics.globalRegistry;
try (var es = EventStream.openRepository()) {
es.onEvent("jdk.X509Validation", recordedEvent -> {
Gauge.builder("jdk.X509Validation", recordedEvent,
e -> e.getLong("validationCounter"))
.description("X509 Certificate Validation Gauge")
.register(metricsRegistry);
});
es.start();
} catch (IOException e) {
throw new RuntimeException("Couldn't process event", e);
}
Evolving the Demo Setup
Oracle Cloud
Run podman compose with TicTacToe in Oracle Cloud Instance
Monitor with JDK tools
Spring Boot application
with JDK 23 Keystore
Player
Monitoring tool
(Prometheus) Configuration
Volume
Volume
Java Management Service
Let’s play and observe!
Stay Tuned For More!
Inside.java
Dev.java youtube.com/java
Useful links
• Monitoring Java Application Security with JDK tools and JFR Events: https://dev.java/learn/security/monitor/
• Stack Walker ep 2 on JFR https://inside.java/2023/05/14/stackwalker-02/
• Introduction to JDK Mission Control: https://youtu.be/7-RKyp05m8M
• JMC9 – What’s new?: https://youtu.be/KzWwGSRxIi4
• Continuous monitoring with JDK Flight Recorder: https://www.infoq.com/presentations/monitoring-jdk-jfr/
• Code used during demo: https://github.com/ammbra/tictactoe
• OCI Instance installation: https://inside.java/2024/07/16/build-oci-instance-with-java-concepts/
• Compose files in OCI: https://docs.oracle.com/en/learn/podman-compose/index.html#confirm-podman-compose-is-working
• More articles on Java Management Service: https://inside.java/tag/cloud
• Gunnar Morling’s article on custom JFR events: https://www.morling.dev/blog/rest-api-monitoring-with-custom-jdk-flight-
recorder-events/

Monitoring Java Application Security with JDK Tools and JFR Events

  • 1.
    Monitoring Java ApplicationSecurity with JDK Tools and JFR Events
  • 2.
  • 3.
    Agenda JFR Security EventsOverview Observing JDK Security Properties Monitoring TLS Protocol Analysing X.509 certificates Continuous Monitoring in the Cloud
  • 4.
  • 5.
  • 6.
    JDK Flight Recorder(JFR)Events When running a Java application, JFR can collect events that occur in the JVM. JFR Events express the state of the application and underlying JVM. For profiling, store event data in a .jfr file. Timestamp Duration ThreadID Stack Trace ID Event Specific Payload JFR Event Components Event ID
  • 7.
    JFR Security Events NameGoal Backported To Enabled By Default* jdk.SecurityPropertyModification Records calls to Security.setProperty(String key, String value). Oracle JDK 11.0.5 and 8u231 No jdk.TLSHandshake Keeps track of TLS handshake activity. Oracle JDK 11.0.5 and 8u231 No jdk.X509Certificate Records details of X.509 Certificates. Oracle JDK 11.0.5 and 8u231 No jdk.X509Validation Records details of X.509 certificates negotiated in successful X.509 validation. Oracle JDK 11.0.5 and 8u231 No jdk.InitialSecurityProperty For insights on initial JDK security properties. Oracle JDK 17.0.7 and 11.0.20 Yes jdk.SecurityProviderService Records service provider method invocations. JDK 17.0.8, 11.0.22 and 8u391 No * In default.jfc and profile.jfc shipped within a JDK
  • 8.
  • 9.
    Dealing with SecurityProperties Initial security properties set statically in the $JAVA_HOME/conf/security file. Dynamically set security properties via java.security.Security methods. Early security considerations reduce long-term risks.
  • 10.
    Ways to ObserveInitial Security Properties Log the initial security properties. java -Djava.security.debug=properties Record jdk.InitialSecurityProperty JFR event. Enable JFR recording java -XX:StartFlightRecording:settings=default,duration=60s Or start a flight recording by connecting to the running application from JDK Mission Control.
  • 11.
    Using –Xshowsettings:security option Configurationsince JDK 22 Description Ported to* java -XshowSetttings:security will show all security settings JDK 21.0.4, JDK 17.0.12, Oracle JDK 11.0.24, Oracle JDK 8u421 java -XshowSetttings:security:property will show the values of security properties. java -XshowSetttings:security:providers will show the installed security providers and their supported algorithms. java -XshowSetttings:security:tls will show the enabled TLS protocols and cipher suites.
  • 12.
    How to TraceSecurity Properties Changes?
  • 13.
    Broad View OverJDK Security Properties Inspect the recording with jcmd or JDK Mission Control. Start a JFR recording when launching the application. java -XX:StartFlightRecording:settings=default,duration=60s Have jdk.SecurityPropertyModification enabled in JFR configuration. $JAVA_HOME/bin/jfr configure jdk.SecurityPropertyModification#enabled=true
  • 14.
    Extra Tips toObserve Security Properties (1) Configure more JFR events by adding a space between each setting. Setup jdk.SecurityPropertyModification when launching the JVM. Set more JFR events when launching the JVM, separated by comma. $JAVA_HOME/bin/jfr configure event1#enabled=true event2#enabled=false java -XX:StartFlightRecording:settings=default,+jdk.SecurityPropertyModification#enabled=true java -XX:StartFlightRecording:settings=default,+event1#enabled=true,+event2#enabled=false
  • 15.
    Extra Tips toObserve Security Properties (2) Configure each JFR event from JDK Mission Control (JMC) Inspect the evolution of captured events in JMC. Event Browser > Java Development Kit > Security Create a connection to a running JVM (this time -XX:StartFlightRecording is not mandatory). In JMC menu, select File > Connection... > [Select one running JVM] > Start Flight Recording Configure each JDK Security event.
  • 17.
  • 18.
    Why is TLSImportant? Message integrity: identify the unauthorized modification of data during transit. Authenticity: ability to identify a user/system before communicating information. certificate authorities/digital certificates Confidentiality: protect sensitive data/information from unauthorized users. encryption/decryption certificate authorities/digital certificates
  • 19.
    Capture TLS ProtocolInformation Use a network protocol analyzer tool. Attach the tool to the network interface where the JVM communicates. Look for "Server Hello" record to determine TLS version used on a particular socket. A Java developer friendly way: inspect debug logs. java -Djavax.net.debug=ssl:handshake Configure jdk.TLSHandshake JFR event to get essential TLS information.
  • 20.
    Capture TLS ProtocolDetails with JDK Tools Run jfr configure command in a terminal window. jfr configure jdk.TLSHandshake#enabled=true jdk.TLSHandshake#stackTrace=true Switch jdk.TLSHandshake options to true in JFR configuration file. Start a recording while jdk.TLSHandshake is enabled as well. java -XX:StartFlightRecording:settings=default,duration=60s, +jdk.TLSHandshake#enabled=true,+jdk.TLSHandshake#stackTrace=true
  • 21.
    Local Demo SetupOverview Running TicTacToe locally Monitor with JDK tools Spring Boot application with JDK 23 Keystore Truststore Client Certificate #local.ext file authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE subjectAltName = @alt_names [alt_names] DNS.1 = localhost DNS.2 = springboot IP.1 = 127.0.0.1
  • 22.
    Inspect TLS Handshakeswith Jcmd and JFR # start a recording jcmd llvmid JFR.start duration=60s filename=/tmp/TLS.jfr # use jfr print command $JAVA_HOME/bin/jfr print --events "TLS*" /tmp/TLS.jfr jdk.TLSHandshake { startTime = 12:55:27.396 (2024-03-03) peerHost = "google.com" peerPort = 8443 protocolVersion = "TLSv1.3" cipherSuite = "TLS_AES_128_GCM_SHA256" certificateId = 587815551 eventThread = "tomcat-handler-15" (javaThreadId = 93, virtual) stackTrace = [ sun.security.ssl.Finished.recordEvent(SSLSessionImpl) line: 1165 sun.security.ssl.Finished$T13FinishedConsumer.onConsumeFinished(ServerHandshakeContext, ByteBuffer) line: 1138 ... ] }
  • 23.
  • 24.
    Importance of X.509Certificates Bind an identity to a public key using a digital signature. Enable secure communication and transaction between two parties. Establish trust based on a series of fields: version serial number signature (algorithm ID and parameters) issuer name validity period subject name subject public key (and associated algorithm ID)
  • 25.
    View Certificate Details #use keytool to query certificates in JDK truststore $JAVA_HOME/bin/keytool -cacerts -list –v # use keytool to query certificates in a keystore keytool -v -list -keystore /path/to/keystore # print verbose X.509 certificate information java -Djava.security.debug=certpath -Djavax.net.debug=all
  • 26.
    Enable Details aboutX.509 Certificates in JFR # enable jdk.X509Certificate, jdk.X509Validation events in your JFR configuration file <event name="jdk.X509Certificate"> <setting name="enabled">true</setting> <setting name="stackTrace">true</setting> </event> <event name="jdk.X509Validation"> <setting name="enabled">true</setting> <setting name="stackTrace">true</setting> </event> # or run jfr configure command in a terminal window $JAVA_HOME/bin/jfr configure jdk.X509Certificate#enabled=true jdk.X509Validation#enabled=true # or enable JFR events on application launch java -XX:StartFlightRecording:settings=default,jdk.X509Certificate#enabled=true, +jdk.X509Validation#enabled=true
  • 27.
    Capture Certificate Detailswith jcmd and JFR Execute a diagnostic command via jcmd. . jcmd llvmid JFR.start duration=60s filename=/tmp/cert.jfr Run your application with -XX:StartFlightRecording flag and have jdk.X509Certificate and jdk.X509Validation options enabled. Show recorded details about X.509 Certificates. $JAVA_HOME/bin/jfr print --events jdk.X509Certificate /tmp/cert.jfr
  • 28.
    The jfr scrubCommand • Filter data from the specified recording file. jfr scrub [filters] [recording-file] [output-file] • Supply which events to include. jfr scrub --include-events jdk.FileRead,jdk.FileWrite • Include a category and exclude events. jfr scrub --include-categories GC* --exclude-events jdk.GCLocker • Remove all events by category: jfr scrub --exclude-categories GC* [JFR scrub recording data— JDK-8281175]
  • 29.
  • 30.
    Streaming JFR Events JDKFlight Recorder provides rich, structured data, and API support to event streams. Since JDK 16, you can transfer recorded events programmatically, as they occur, over the network using javax.management.MBeanServerConnection. Until JDK 16, developers could monitor a Java process on a remote host and control what is recorded via JDK Mission Control.
  • 31.
    Monitor a RemoteHost with MBeanServerConnection String host = "com.example"; int port = 7091; String url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi"; JMXServiceURL u = new JMXServiceURL(url); JMXConnector c = JMXConnectorFactory.connect(u); MBeanServerConnection connection = c.getMBeanServerConnection(); try (RemoteRecordingStream stream = new RemoteRecordingStream(connection)) { stream.enabled("jdk.X509Certificate").withStackTrace(); stream.onEvent("jdk.X509Certificate", System.out::println), stream.start(); }
  • 32.
    Stream JFR EventsActively, Within Process CompositeMeterRegistry metricsRegistry = Metrics.globalRegistry; try (var es = EventStream.openRepository()) { es.onEvent("jdk.X509Validation", recordedEvent -> { Gauge.builder("jdk.X509Validation", recordedEvent, e -> e.getLong("validationCounter")) .description("X509 Certificate Validation Gauge") .register(metricsRegistry); }); es.start(); } catch (IOException e) { throw new RuntimeException("Couldn't process event", e); }
  • 33.
    Evolving the DemoSetup Oracle Cloud Run podman compose with TicTacToe in Oracle Cloud Instance Monitor with JDK tools Spring Boot application with JDK 23 Keystore Player Monitoring tool (Prometheus) Configuration Volume Volume Java Management Service
  • 34.
  • 35.
    Stay Tuned ForMore! Inside.java Dev.java youtube.com/java
  • 36.
    Useful links • MonitoringJava Application Security with JDK tools and JFR Events: https://dev.java/learn/security/monitor/ • Stack Walker ep 2 on JFR https://inside.java/2023/05/14/stackwalker-02/ • Introduction to JDK Mission Control: https://youtu.be/7-RKyp05m8M • JMC9 – What’s new?: https://youtu.be/KzWwGSRxIi4 • Continuous monitoring with JDK Flight Recorder: https://www.infoq.com/presentations/monitoring-jdk-jfr/ • Code used during demo: https://github.com/ammbra/tictactoe • OCI Instance installation: https://inside.java/2024/07/16/build-oci-instance-with-java-concepts/ • Compose files in OCI: https://docs.oracle.com/en/learn/podman-compose/index.html#confirm-podman-compose-is-working • More articles on Java Management Service: https://inside.java/tag/cloud • Gunnar Morling’s article on custom JFR events: https://www.morling.dev/blog/rest-api-monitoring-with-custom-jdk-flight- recorder-events/