skip to content

In Wireshark, why does a captured HTTPS session show only TLS Application Data records, and what must you supply to read the HTTP inside?

level: juniorimportance: must knowfreq 30%

answer

  1. keys never cross the wire
  2. two kinds of key material
  3. client-written log versus server key
  4. static RSA only for the key file

basics

~20 s

TLS encrypts every record after the handshake, so Wireshark sees only ciphertext. It decrypts only with key material: a key log of session secrets written by the client through SSLKEYLOGFILE, or the server's RSA private key for static-RSA sessions.

solid answer

~40 s

After the handshake every TLS record is encrypted with symmetric keys that both ends derive and never send, so the TLS dissector can only label the payload *Encrypted Application Data* (`tls.app_data`) and nothing above it is dissected. Wireshark decrypts only when you give it key material. The usual route is a key log: start the client with `SSLKEYLOGFILE` set, capture, then point the TLS protocol preference *(Pre)-Master-Secret log filename* (`tls.keylog_file`) at that file. The other route, the TLS *RSA keys list*, works only for TLS 1.2-or-older sessions that used static-RSA key exchange, because only then is a secret sent encrypted to the server's key; it never helps with (EC)DHE suites or TLS 1.3. Once it works, a *Decrypted TLS* tab appears in the bytes pane and HTTP is dissected normally.

go deeper

for a junior

Recall that TLS hides everything after the handshake, and that Wireshark needs either a client-written key log or, for static-RSA sessions only, the server's private key.

for a middle

Explain why the record keys are never on the wire, name the (Pre)-Master-Secret log filename preference, and say why the RSA keys list fails on (EC)DHE and TLS 1.3 sessions.

for a senior

Show judgement about key material as evidence: which route to choose for a given capture, how to keep a key log under the same access control as the capture, and when decryption is not needed at all.

for a principal

Frame the trade-off between reading payload during an investigation and holding long-lived keys that unlock far more than that investigation, and who should be allowed to create key logs.

## What an HTTPS capture really contains When you capture an HTTPS session on a host or a link you are responsible for, Wireshark sees every packet, but not every byte is readable. A TLS connection has two phases: - **The handshake.** The client sends a `ClientHello`, the server answers with a `ServerHello`, and the two agree on a protocol version and a **cipher suite**. In TLS 1.2 the server's certificate also crosses in the clear; in TLS 1.3 almost everything after the `ServerHello`, the certificate included, is already encrypted. - **The protected records.** The records that carry the application's data have content type 23, *application data*. Wireshark shows it as **Encrypted Application Data** (field `tls.app_data`). The HTTP request line, headers and body are all inside it, so the HTTP dissector never runs. So the TLS layer is visible and the application layer is not. That is the normal, correct state of an undecrypted capture, not a dissector fault. ## Why the keys are not in the capture The record keys are **symmetric keys derived independently at both ends** from secrets agreed during the handshake. With the ephemeral (EC)DHE key exchange that modern servers use, each side keeps a private value that never leaves the process, so nothing on the wire lets a third party recompute the keys later. That property, forward secrecy, is a cryptographic topic of its own; for an analyst it means one thing: **capturing more packets or capturing with more privilege never yields the keys.** Something that knew the secrets at the time has to hand them over. ## The two kinds of key material Wireshark accepts | Key material | Who produces it | What it decrypts | Where Wireshark takes it | |---|---|---|---| | **Key log** | The client's TLS library, when `SSLKEYLOGFILE` is set or the program registers a key-log callback | The sessions that client logged, any TLS version and key exchange | TLS preference *(Pre)-Master-Secret log filename* (`tls.keylog_file`) | | **RSA private key** | The server operator | Only sessions that used **static-RSA** key exchange (TLS 1.2 and older) | TLS preference *RSA keys list* | A **key log** is a text file with one line per secret, each keyed by the 32-byte random value from that session's `ClientHello`. Browsers that honour `SSLKEYLOGFILE`, curl when its TLS library supports it, and your own programs through OpenSSL's key-log callback can all write one. It is the route that works on today's traffic. The **RSA private key** route depends on the client having encrypted the premaster secret to the server's public key and sent it in the capture. Only static-RSA cipher suites do that; with (EC)DHE the RSA key merely signs the handshake, and TLS 1.3 removed static-RSA key exchange entirely. ## Choosing the route for a given capture Which kind of key material you can get depends on which end you control: - **You control the client** (a test browser, a curl command, your own service's outbound calls): set up a key log before the client starts. This works for every modern session. - **You control only the server, and it still negotiates static RSA**: the RSA keys list can work, but read the cipher suite in the `ServerHello` first, because most servers now choose ECDHE. - **You control neither end**: the stored capture stays opaque. Getting payload visibility then means changing where traffic is decrypted, a design decision that belongs to a different subject. ## What you see once decryption works 1. A **Decrypted TLS** tab appears beside the frame bytes in the packet bytes pane, showing the plaintext record. 2. The protocol negotiated inside the tunnel is dissected: HTTP/1.1 requests appear as `http`, HTTP/2 frames as `http2`. 3. In TLS 1.3, the encrypted handshake messages (the certificate, the `Finished` messages) become readable too, because the key log also holds the handshake traffic secrets. If the bytes pane shows no *Decrypted TLS* tab, Wireshark did not find matching key material for that session; working out why is a separate diagnosis. ## Mistakes that cost interviews - Expecting an elevated capture, a bigger snapshot length or a different interface to reveal plaintext. None of them changes what TLS put on the wire. - Believing the server **certificate** in the capture is key material. It holds a public key only. - Assuming the server's private key decrypts any session to that server. It decrypts static-RSA sessions only. - Thinking the URL path is visible. Of the URL, at most the host name travels in the clear, in the `ClientHello` server name extension; the path and headers are encrypted. Key material is as sensitive as the traffic it unlocks: use a test client you control, keep the key log with the capture under the same access rules, and delete both when the investigation ends.

  • Without any key material, what can you still read from a TLS 1.2 HTTPS session in Wireshark?
    The cleartext handshake: the `ClientHello` with its offered cipher suites and the server name (`tls.handshake.extensions_server_name`), the `ServerHello` with the chosen version and cipher suite (`tls.handshake.ciphersuite`), and in TLS 1.2 the server certificate. Record sizes and timing are visible too. The URL path, headers and bodies stay inside *Encrypted Application Data*; in TLS 1.3 even the certificate is encrypted.
  • Why is a key log usually preferred to the server's private key even when both would work?
    A key log holds per-session secrets: it decrypts the sessions it was written for and nothing else. The server's RSA private key decrypts every static-RSA session ever made to that server and lets its holder impersonate the server. Wireshark's *File > Export TLS Session Keys* turns what a private key unlocked into a key log, so only that is shared.

saying these in an interview costs you the question

  • Capturing with root or admin rights lets Wireshark see inside HTTPS.
  • The server certificate in the capture is enough to decrypt the session.
  • The server's private key decrypts every TLS session to that server.
  • The URL path of an HTTPS request is readable in the capture.
  • A stored HTTPS capture can never be decrypted after the fact.