Logging, Access Control & Basic Hardening

Web Servers Fundamentals

Chapter 8 · Logging, Access Control & Basic Hardening

Chapter 5 flagged directory listing as a real, common misconfiguration. This chapter widens that lens: what each server records about every request by default, how to restrict access at the web-server layer itself before a request ever reaches the application, and a handful of other low-cost hardening steps worth knowing about.

Access Logs & Error Logs

Every request handled is normally recorded in an access log — client IP, timestamp, the request line itself, the response status code, and typically the response size — while server-side problems (a misconfiguration, a backend failing to respond) go to a separate error log. Apache uses access.log/error.log, with the exact fields recorded controlled by a configurable LogFormat. Nginx uses its own access_log/error_log directives, similarly format-configurable. IIS records requests in the W3C Extended Log File Format by default, configured through IIS Manager. All three capture broadly the same core information, just formatted and configured differently.

Basic Access Control

Restricting who can reach a given path can happen at the web-server layer itself, before a request ever reaches the application behind it. Apache's Require directive (via mod_authz_host) can restrict access by IP, and .htpasswd-backed Basic Authentication can require a username/password. Nginx uses its own allow/deny directives for IP restriction and auth_basic for password protection. IIS offers the equivalent through its IP Address and Domain Restrictions feature, plus Basic or Windows Authentication configured per site. In every case, a request that fails this check never reaches the application at all — the rejection happens at the web server itself.

Basic Hardening: Hiding Version Information

# Apache (httpd.conf / apache2.conf) ServerTokens Prod ServerSignature Off # Nginx (nginx.conf) server_tokens off;

By default, all three servers reveal their own name and version number in response headers or error pages — Apache's ServerTokens/ServerSignature and Nginx's server_tokens off suppress this; IIS requires an add-on (commonly via URL Rewrite rules) to strip its own version string similarly. The goal is reducing the information an attacker can gather during initial reconnaissance — knowing the exact server version can point directly at known, unpatched vulnerabilities for that specific version.

Revisiting Directory Listing

Chapter 5's own directory-listing warning belongs on this same checklist: confirming it's genuinely disabled (not just left at whatever the default happens to be) is one more low-cost step in the same category as version hiding and access control — each one closes off a small piece of information or access an attacker could otherwise use.

ApacheNginxIIS
Access/error logsaccess.log/error.log, configurable LogFormataccess_log/error_log directivesW3C Extended Log File Format
IP-based access controlRequire (mod_authz_host)allow/denyIP Address and Domain Restrictions
Password auth.htpasswd + Basic Authauth_basicBasic/Windows Authentication
Hide version infoServerTokens/ServerSignatureserver_tokens offRequires an add-on (e.g. URL Rewrite)
Where these logs go next
Raw access and error logs are exactly the kind of data an observability stack (Observability's own material) is built to collect, aggregate, and alert on — this chapter covers what each server records natively; what happens to that data afterward is a separate, later concern. Similarly, hiding version information and tightening access control are the same category of step covered from the attacker's own perspective in Penetration Testing Methodology's reconnaissance material.
Hiding version information is not, by itself, security
Suppressing a server's version string is a real, worthwhile, low-cost step — but it's security through obscurity: it slows down casual or fully automated scanning, not a determined attacker willing to fingerprint the server through other means. It is never a substitute for actually keeping the server patched and correctly configured — the same caution OWASP Top 10's own material applies broadly to any control whose entire value is "the attacker doesn't immediately know something," rather than a control that actually blocks an attack outright.

Hands-On Exercises

Exercise 1

Write the Nginx configuration that restricts access to a /admin/ path to only the IP address 203.0.113.10, denying everyone else.

📄 View solution
Exercise 2

A team disables ServerTokens/server_tokens on their production servers and considers the server "properly secured" as a result, deprioritizing an overdue security patch. Using this chapter's own warning box, explain what's wrong with this reasoning.

📄 View solution
Exercise 3

Explain, in your own words, why restricting access to a sensitive path at the web-server layer (via IP restriction or Basic Auth) is meaningfully different from relying on the application itself to check permissions before showing that content.

📄 View solution

Chapter 8 Quick Reference

  • All three servers log requests by default — Apache/Nginx via configurable plain-text formats, IIS via W3C Extended Log File Format
  • Access control at the web-server layer rejects disallowed requests before they ever reach the application
  • Hiding version info (ServerTokens/server_tokens off) reduces reconnaissance value but is security through obscurity, not a real fix
  • Directory listing (Chapter 5) belongs on this same hardening checklist — confirm it's genuinely disabled, not just defaulted