DEV Community

Cover image for Website Security Configuration Audit from Android in 15 Minutes: curl, openssl, dig — No Hacking, No Root
AbbatFariDi
AbbatFariDi

Posted on

Website Security Configuration Audit from Android in 15 Minutes: curl, openssl, dig — No Hacking, No Root

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"
Enter fullscreen mode Exit fullscreen mode

Output:

content-type: text/html; charset=UTF-8
strict-transport-security: max-age=31536000; includeSubDomains; preload
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

Formally valid but practically useless:

content-security-policy: default-src *
content-security-policy: script-src 'unsafe-inline'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

or (allow same domain only):

x-frame-options: SAMEORIGIN
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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=()
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Output:

New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Protocol  : TLSv1.3
Cipher    : TLS_AES_128_GCM_SHA256
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Output:

notBefore=Feb 16 00:00:00 2026 GMT
notAfter=Mar 19 23:59:59 2027 GMT
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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"
Enter fullscreen mode Exit fullscreen mode
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"
Enter fullscreen mode Exit fullscreen mode

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)