What You Can Find From the Outside Without Server Access
1. What Is a Configuration Audit
Analysis of publicly available HTTP responses and DNS records — no authentication, no active interference. Only external configuration is assessed: HTTP headers, TLS/SSL, DNS, open ports. No vulnerabilities are exploited. No load on the server.
2. Tools
-
curl— HTTP server response -
openssl s_client— TLS connection check -
dig— DNS record lookup -
/dev/tcp— open port detection without nmap
All of this runs on Android via Termux, without root.
3. Target and Method
Domain: any — with the owner's permission. For this audit: an AI-generated product on a Netlify subdomain — adorable-dodol-5ab32d.netlify.app
Time: ~15 minutes. With the automation script — 2–3 minutes from check to PDF report.
Method: publicly available data only, no authentication, no server load.
4. HTTP Security Headers — Findings
Command:
curl -s -D - adorable-dodol-5ab32d.netlify.app -o /dev/null | grep -i "security\|frame\|content-type\|referrer\|permissions"
Output:
content-type: text/html; charset=UTF-8
strict-transport-security: max-age=31536000; includeSubDomains; preload
What this means:
-
content-type: text/html— server parameter header, not security-relevant -
strict-transport-security: max-age=31536000— HSTS enabled, browser remembers to use HTTPS for 1 year -
includeSubDomains— HSTS applies to subdomains -
preload— domain is in the browser's preloaded HSTS list, HSTS is on by default
HSTS (Strict-Transport-Security) instructs the browser to always use HTTPS, even if the user types http://. Protects against MITM attacks. Minimum: max-age=31536000. Maximum: add includeSubDomains; preload.
CSP (Content-Security-Policy) — a whitelist of allowed sources for scripts, images, etc. Without it, a script from any domain can be injected — the browser will execute it. Absent on the target — vulnerability.
Fix:
content-security-policy: default-src 'self'; script-src 'self'
Formally valid but practically useless:
content-security-policy: default-src *
content-security-policy: script-src 'unsafe-inline'
X-Frame-Options — prevents the page from being embedded in an iframe on another site. Without it, clickjacking is possible: an attack where a malicious site hides the target inside an iframe to trick user interactions. Absent — vulnerability.
Fix:
x-frame-options: DENY
or (allow same domain only):
x-frame-options: SAMEORIGIN
X-Content-Type-Options — prevents the browser from guessing file types. Without it, the browser may interpret a file differently from its declared content-type, potentially executing a malicious file as a script. Absent — vulnerability.
Fix:
x-content-type-options: nosniff
Referrer-Policy — controls what URL data the browser sends when following a link. Without it, URLs containing tokens or endpoints (e.g. https://.../path?token=secret) leak to the next site. Absent — vulnerability.
Fix:
referrer-policy: strict-origin-when-cross-origin
This sends only the origin (https://example.com/) on cross-origin navigation — no path, no parameters. If the connection downgrades from HTTPS to HTTP, no referrer is sent at all.
Permissions-Policy — defines which browser APIs the site may use. Without it, an embedded iframe can request camera, microphone, or geolocation access from the user. Absent — vulnerability.
Fix:
permissions-policy: camera=(), microphone=(), geolocation=()
Empty parentheses = denied for everyone.
5. TLS — Findings
Protocol and Cipher
Command:
echo | openssl s_client -connect adorable-dodol-5ab32d.netlify.app:443 \
-servername adorable-dodol-5ab32d.netlify.app 2>/dev/null | grep -E "Protocol|Cipher"
Output:
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Protocol : TLSv1.3
Cipher : TLS_AES_128_GCM_SHA256
What this means:
-
TLSv1.3— current standard ✔ -
AES_128— symmetric encryption, 128-bit key -
GCM— Galois/Counter Mode: combined encryption + authentication (AEAD), protects against data tampering -
SHA-256— hash function for integrity verification and handshake -
TLS_AES— Forward Secrecy built in by default in TLS 1.3 ✔
TLS 1.2 is acceptable with strong ciphers. TLS 1.0/1.1 — deprecated, publicly known vulnerabilities, disabled in modern browsers.
Forward Secrecy generates a unique key for each TLS session, stored nowhere. Traffic intercepted in the past cannot be decrypted even if a private key is later compromised. In TLS 1.3, this is guaranteed by default via TLS_AES ciphers.
Weak Ciphers
echo | openssl s_client -connect adorable-dodol-5ab32d.netlify.app:443 -cipher RC4 2>/dev/null | grep Cipher
echo | openssl s_client -connect adorable-dodol-5ab32d.netlify.app:443 -cipher 3DES 2>/dev/null | grep Cipher
Empty output — server refuses RC4 and 3DES. ✔
Certificate Expiry
Command:
echo | openssl s_client -connect adorable-dodol-5ab32d.netlify.app:443 \
-servername adorable-dodol-5ab32d.netlify.app 2>/dev/null | openssl x509 -noout -dates
Output:
notBefore=Feb 16 00:00:00 2026 GMT
notAfter=Mar 19 23:59:59 2027 GMT
If notAfter is in the past — vulnerability.
Self-Signed Certificate
Command:
echo | openssl s_client -connect adorable-dodol-5ab32d.netlify.app:443 \
-servername adorable-dodol-5ab32d.netlify.app 2>/dev/null | grep -i "self signed\|verify error"
Empty output — certificate issued by a trusted CA (Let's Encrypt, DigiCert, etc.) ✔
If output shows verify error:num=18:self signed certificate — vulnerability.
6. DNS / Email Protection
Applicable to owned domains only. Subdomain audits cannot assess email configuration. General rules below.
SPF (Sender Policy Framework) — lists servers authorized to send mail from the domain.
dig +short TXT example.com
| Value | Meaning |
|---|---|
-all |
Reject all others (strict) |
~all |
Softfail |
?all |
Neutral |
+all |
Accept all — dangerous |
| No output | SPF not configured |
For a non-mail domain with no listed servers: -all alone is correct.
DKIM (DomainKeys Identified Mail) — cryptographic signature on outgoing mail, verified by the recipient via DNS.
dig +short TXT selector._domainkey.example.com
The selector is chosen by the domain owner during DKIM setup. Without knowing the exact selector, DKIM presence cannot be reliably confirmed from the outside.
DMARC (Domain-based Message Authentication, Reporting and Conformance) — policy for mail that fails SPF or DKIM.
dig +short TXT _dmarc.example.com
| Value | Meaning |
|---|---|
p=none |
Reporting only — weak |
p=quarantine |
Send to spam — acceptable |
p=reject |
Reject — full protection |
| No output | DMARC not configured |
Additional flags:
-
adkim=s/aspf=s— strict match, subdomains not accepted -
adkim=r/aspf=r— relaxed, subdomains allowed (bypass risk) -
sp=reject— protect subdomains without their own DMARC
7. Open Ports
Command:
timeout 5 bash -c "echo >/dev/tcp/adorable-dodol-5ab32d.netlify.app/PORT" 2>/dev/null \
&& echo "open" || echo "closed"
| Port | Service | Unexpected open = |
|---|---|---|
| 80 | HTTP | Normal if redirecting to 443 |
| 443 | HTTPS | Normal |
| 22 | SSH | Normal if key-only access |
| 21 | FTP | Vulnerability |
| 3306 | MySQL | Vulnerability |
| 5432 | PostgreSQL | Vulnerability |
| 8080 | Alt HTTP | Normal with access control |
| 8443 | Alt HTTPS | Normal with access control |
Check redirect from 80 to 443:
curl -sI http://adorable-dodol-5ab32d.netlify.app | grep -i "location\|301\|302"
HTTP/1.1 301 or 302 — normal. No output — vulnerability.
8. Summary
Vulnerabilities found in 10–15 minutes without server access:
| Risk | Finding |
|---|---|
| High | Open ports: 21, 3306, 5432 |
| Medium | No Content-Security-Policy |
| Low | No X-Frame-Options |
| Low | No X-Content-Type-Options |
| Low | No Referrer-Policy |
| Low | No Permissions-Policy |
Full audit report available at: https://github.com/AbbatFariDi/Security-audits/blob/main/README.md
*I offer external configuration audits starting at $10. DM or find me on Kwork / Upwork.
Top comments (0)