Following an HTTP request
My SEC-260 work began with HTTP as an application-layer request-response protocol. The initial study note compared it with DNS, FTP, IMAP, POP3, RDP, SMB, SMTP, and SSH, then concentrated on the methods and messages used by web clients and servers.
The basic operation was:
GETretrieves a representation of a resourceHEADretrieves the response headers without the bodyPOSTsubmits data for processing or creates a subordinate resource according to the applicationPUTcreates or replaces the state at a target URI
The early paper used the word PUSH in one list, but HTTP defines PUT, not PUSH, as a standard method. It also treated an index file as the automatic result of every request for a host. In practice, the selected virtual host, route, application framework, and server configuration decide what the root path returns.
A Wireshark capture from a Kali Linux virtual machine followed a request to apache.org. DNS resolved the name to the address 151.101.2.132 in that lab session. I then filtered the capture by protocol and address to follow the sequence:
- DNS resolved the requested host.
- TCP completed its three-way handshake.
- The client sent an HTTP request.
- The server returned the response and content.
Separate exercises used GET to retrieve a resource and HEAD to request only its headers. I also reviewed 4xx client-error responses and changed the listening port of a web service to see how the URL, socket, and server configuration must agree.
The filters used in the report included:
dns
tcp && ip.addr == 151.101.2.132
http && ip.addr == 151.101.2.132
The TCP filter exposed the SYN, SYN-ACK, and ACK that established the connection. The HTTP filter then isolated the request and response on that stream. This connected a browser action to name resolution, transport setup, an application request, and returned content rather than treating “opening a page” as one event.
Because the traffic was plain HTTP, request paths, headers, and content were visible in the capture. That gave me a baseline for understanding what TLS changes and what metadata remains visible after encryption.
TLS and certificate inspection
The TLS exercises covered the handshake, negotiated cryptography, certificate validity, issuer, subject, and chain of trust. I inspected a public certificate issued by DigiCert, recorded an RSA public key, and noted that the certificate in the 2021 capture expired on 8 March 2023.
That date was a property of one certificate, not the lifetime of the site or key pair in general. Certificate inspection needs the exact leaf certificate, hostname, validity interval, subject alternative names, issuer, signature algorithm, key usage, and chain presented during that connection.
Another lab set the browser’s SSLKEYLOGFILE mechanism and generated TLS traffic in the controlled environment. The resulting key-log file contained session secrets that Wireshark could associate with the corresponding capture, allowing it to dissect the protected application data.
This method did not recover a server’s private key or break TLS. It instrumented the authorised client at the point where that client already possessed the negotiated secrets. The capture and key log had to describe the same sessions, and the secrets had to be protected because anyone holding both could read those recorded exchanges.
That exercise separated three ideas that are often compressed into “HTTPS”:
- the certificate helps authenticate the server
- the handshake establishes shared session keys
- symmetric encryption protects the application traffic after the handshake
Possessing a server certificate does not reveal its private key, and the certificate itself is not “decrypted” by the browser. The browser verifies the issuer’s signature, checks the identity and validity constraints, and uses the negotiated handshake to establish the secure session. Depending on the TLS version and cipher suite, key establishment may use ephemeral Diffie-Hellman or another supported mechanism; it is not fixed by the fact that the certificate contains an RSA public key.
Building a local certificate authority
I then built a small OpenSSL certificate authority for the lab. I created an empty certificate index, initialised the serial file to 1000, and made a dedicated private-key directory before generating the CA material.
The CA directory kept:
- a private-key area
- an index of issued certificates
- a serial counter
- the CA certificate
The historical CA key was generated as a 2048-bit RSA key encrypted with the OpenSSL -des3 option. I then created a self-signed CA certificate with a 365-day validity period. On the web server I generated a separate private key and certificate-signing request. The request was transferred to the CA with Secure Copy over SSH, signed, and returned as a server certificate.
This reproduced the basic roles in a public-key infrastructure:
- the server retains its private key
- the request identifies the public key and requested subject
- the CA validates and signs the request
- clients trust the resulting certificate through the CA
The CA index and serial gave the issuing process state: the serial distinguished certificates, while the index recorded what the CA had issued. A real CA also needs policy around subject names, key usage, validity, revocation, renewal, audit, and who is permitted to approve a request.
The lab used historical OpenSSL command forms, Triple DES protection for the CA key, and one simple signing authority. A current deployment would need current key protection, restricted offline or hardware-backed root keys, constrained certificate profiles, revocation handling, automation, and separation between root and issuing authorities.
Heartbleed as a protocol implementation failure
I researched Heartbleed, CVE-2014-0160, as part of the TLS work. The flaw was an out-of-bounds read in vulnerable OpenSSL implementations of the TLS heartbeat extension.
A heartbeat request included a declared payload length. The vulnerable implementation trusted that value without checking it against the actual payload and returned adjacent process memory. The exposure could contain credentials, session material, or other data resident in the server process.
The request contained a message type, claimed payload length, payload bytes, and padding. The affected implementation copied the claimed number of bytes into its response without first confirming that the request actually contained that many payload bytes. A short payload paired with an excessive length could therefore make the process return adjacent heap memory.
The original coursework overstated the affected scope as any server running SSL or TLS up to version 1.1. The vulnerability belonged to specific OpenSSL releases with the heartbeat implementation enabled, not to every implementation of those protocol versions.
The case showed the difference between a protocol goal and an unsafe implementation. TLS could be correctly negotiated while a bug in one extension still exposed memory outside the intended message. Patching the library stopped new reads, but incident response also needed to consider what may already have been exposed. Rotating private keys, replacing certificates, invalidating sessions, and changing credentials were part of recovery where exposure could not be ruled out.
The paper also looked at extended-validation certificates. EV involves additional verification of the legal organisation behind a certificate request. That vetting changes certificate policy and identity assurance; it does not make the encrypted connection cryptographically stronger than another certificate using the same key and protocol settings, and modern browser interfaces no longer give EV the prominent visual treatment it once received.
Hardening an IIS service
The IIS exercise moved from protocol inspection into server configuration. I wrote a short hardening plan and applied the controls in a lab instance.
Request Filtering was configured to:
- limit URL and query-string length to 40 characters in the demonstration
- reject file extensions that were not explicitly allowed
- allow PDF as the example permitted extension
- narrow the types of content accepted by the service
The value 40 was deliberately restrictive for the screenshot and would break many ordinary application routes and query strings. It demonstrated where the control lived, not a sensible universal threshold.
IP and Domain Restrictions allowed the lab range from 10.0.5.1 to 10.0.5.100 and denied other clients. The deny action was configured to abort the request by resetting the TCP connection. Dynamic restrictions blocked clients that exceeded a configured request rate, providing a basic response to automated enumeration or request flooding.
HTTPS was added through a self-signed certificate binding, and the unencrypted port-80 binding was removed for the exercise. That forced clients onto the encrypted listener, although a production site would normally use a trusted certificate and a deliberate HTTP-to-HTTPS redirect or HSTS deployment rather than only removing the HTTP binding.
The FTP configuration disabled anonymous authentication and allowed four failed login requests before blocking the source address for one minute. These controls reduced unauthenticated access and rate-limited repeated attempts. They did not replace strong credentials, encrypted transport, least privilege, and monitoring.
The values used in the coursework were demonstration settings, not universal production thresholds. Request limits and rate controls should be based on the application’s real traffic and tested for false positives.
Apache request controls and logging
The Apache exercises covered ModSecurity, mod_evasive, and access-log interpretation.
ModSecurity acted as a web application firewall layer. It could inspect requests against rules and block patterns associated with common attacks. The retained submission is screenshot-led and does not preserve a custom ruleset, so I do not attribute specific detection coverage to it.
mod_evasive tracked request frequency and temporarily rejected clients that crossed the configured threshold. The lab recorded a count of 20 requests and a 50-second blocking period. Its short note mixes the names of the interval and count directives, so these values are best read as the tested policy rather than a reusable configuration fragment.
Neither module repaired a vulnerable application. They added detection and response controls around it. A rule can be bypassed, conflict with legitimate traffic, or create operational noise if it is not tuned against the application.
I also parsed Apache access-log entries into their component fields:
- remote host
- request time
- method and requested resource
- HTTP version
- response status
- response size or duration
- user agent
Comparing a normal request with a missing page showed how a single line records the client, request, and server outcome. That log structure became useful later in the SYS-320 automation work, where repeated records were parsed and transformed into analyst output.
The server controls and logs belonged together. Request filtering, IP restrictions, ModSecurity, and mod_evasive could all reject traffic, but an administrator still needed logs that explained which rule acted, which client was affected, and whether normal use produced false positives. A block without useful evidence becomes difficult to tune and investigate.
Currentness
These labs reflect a 2021 web-server environment. Browser certificate interfaces, TLS versions, OpenSSL defaults, IIS features, Apache modules, and recommended cryptographic settings have changed. The page records the protocol and administration work I completed, not a current hardening checklist.
Across the series, I moved from reading one HTTP exchange to controlling the server and trust infrastructure around it: packet capture, certificate inspection, session-key logging, private CA operation, memory-safety research, IIS request policy, FTP authentication controls, Apache filtering, rate controls, and access logs. That progression later fed into web-application testing and network-forensics work, where protocol evidence and server configuration had to be interpreted together.
