OculusCyber Logo

OculusCyber

Home

Browse Topics


OWASP Top 10 — prescriptive rules with Java examples

By oculus

November 9, 2025


A01 – Broken Access Control

Rules

  • Enforce authorization on the server for every request. Never rely on client claims.
  • Deny-by-default routes; expose only through explicit configuration.
  • Use method/URL‑level checks and object‑level checks (IDOR prevention).
  • Prefer RBAC (roles/permissions) or ABAC (attributes). Centralize policy.

Java (Spring Security) – method level

@PreAuthorize("hasAuthority('INVOICE_READ') and #tenantId == authentication.details.tenantId")
public Invoice getInvoice(UUID tenantId, UUID invoiceId) { ... }

Object‑level (service‑side) enforcement

Invoice inv = repo.findById(id).orElseThrow(NotFound::new);
authorizer.assertCanView(authn, inv.getTenantId());

CWE links: 285, 639, 863, 276

A02 – Cryptographic Failures

Rules

  • TLS 1.2+ everywhere; HSTS on internet origins.
  • Use AES‑GCM for data at rest, PBKDF2/bcrypt/Argon2 for passwords.
  • No ECB. Random IV/nonce per message; store alongside ciphertext.
  • Keys in KMS/HSM, not env vars. Rotate.
  • For JWT: RS256/ES256, set exp, aud, iss, and validate clock skew.

Java – AES‑GCM utility

Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = SecureRandom.getInstanceStrong().generateSeed(12); // 96-bit
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
c.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] ct = c.doFinal(plaintext);

Password hashing (Spring)

PasswordEncoder enc = new BCryptPasswordEncoder(12);
String hash = enc.encode(password);

CWE links: 327, 329, 330, 522, 916

A03 – Injection (SQL/NoSQL/OS/LDAP)

Rules

  • Do parameterized queries only. Never build SQL via string concat.
  • Validate and whitelist identifiers (columns, sort fields) if dynamic.
  • For OS commands: avoid shell; use API or ProcessBuilder with fixed args.

Java – JDBC parameterization

try (PreparedStatement ps = con.prepareStatement(
  "SELECT id, name FROM users WHERE email = ?")) {
  ps.setString(1, email);
  try (ResultSet rs = ps.executeQuery()) { /* ... */ }
}

Node (pg)

const {rows} = await db.query('SELECT * FROM x WHERE id = $1', [id]);

CWE links: 89, 78, 90, 943

A04 – Insecure Design

Rules

  • Add rate limits for login, password reset, sensitive APIs.
  • Enforce business invariants server‑side (e.g., cannot transfer negative amount).
  • Use state machines for multi‑step workflows.

CWE links: 840, 841, 284

A05 – Security Misconfiguration

Rules

  • Disable directory listing; set X-Content-Type-Options: nosniff.
  • Minimal CORS; explicit origins; OPTIONS preflight only; do not wildcard with credentials.
  • Remove default creds; pin versions; disable debug/actuator in prod.

Spring Security headers

http.headers(h -> h
  .xssProtection(x -> x.block(true))
  .contentTypeOptions(HeadersConfigurer.ContentTypeOptionsConfig::and)
  .httpStrictTransportSecurity(hsts -> hsts.includeSubDomains(true).preload(true))
);

CWE links: 16, 933, 276, 732

A06 – Vulnerable & Outdated Components

Rules

  • Lock to vetted versions (Maven/Gradle BOM). No +.
  • SCA in CI; fail on known exploited vulns (CISA KEV/EPSS high).
  • Ban unmaintained libs; replace with platform features.

Gradle example

dependencies { implementation platform('org.springframework.boot:spring-boot-dependencies:3.3.4') }

CWE links: 1104, 937

A07 – Identification & Authentication Failures

Rules

  • Centralize auth (OIDC/OAuth2). No homegrown passwords.
  • Sessions: secure, httpOnly cookies; rotate on privilege change; short JWT TTL.
  • Account enumeration: same responses/timing for login/reset.

Spring Security – session

http.sessionManagement(s -> s.sessionFixation().migrateSession());

CWE links: 287, 384, 798

A08 – Software & Data Integrity Failures (incl. insecure deserialization)

Rules

  • Verify signatures/hashes of artifacts; enforce protected branches; signed commits.
  • Do not use Java native deserialization (ObjectInputStream). Use JSON with strict schemas.
  • For Jackson: disable polymorphic typing; whitelist classes.

Java – disallow default typing

ObjectMapper m = new ObjectMapper();
m.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// No enableDefaultTyping

CWE links: 502, 494, 353

A09 – Security Logging & Monitoring Failures

Rules

  • Log security events (authN/Z, input validation failures, changes) with trace IDs.
  • Never log secrets, full tokens, or PII. Mask.
  • Ship logs to SIEM; create alerts for authz failures, rate limit trips, unexpected 5xx.

Logback mask example

<turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">...</turboFilter>

CWE links: 778, 532

A10 – Server‑Side Request Forgery (SSRF)

Rules

  • Block server egress by default; use allowlist for outbound HTTP.
  • Reject private/link‑local/loopback destinations after DNS resolve.
  • Prefer back‑end APIs/SDKs over arbitrary URLs from users.

Java – allowlist + IP verification

URI uri = URI.create(inputUrl);
String host = uri.getHost();
if (!ALLOWLIST.contains(host)) throw new IllegalArgumentException("disallowed host");
InetAddress addr = InetAddress.getByName(host);
if (addr.isAnyLocalAddress() || addr.isLoopbackAddress() || addr.isLinkLocalAddress())
  throw new SecurityException("private address");

CWE links: 918