Client Area

OWASP Top 10 — What Actually Breaks Indian Web Apps

ByDomain India Team·DomainIndia Engineering
22 min readPublished 24 Apr 2026Updated 23 Jun 2026159 views

In this article

  • 1How we ranked these — ground-truth from our hosting servers
  • 2A06 — Vulnerable Components (the #1 incident shape)
  • 3A07 — Identification & Authentication Failures (#2)
  • 4A01 — Broken Access Control (#3 by frequency, but huge by impact)
  • 5A03 — Injection (#4)

OWASP Top 10 — What Actually Breaks Indian Web Apps

Verdict at the top: OWASP publishes a Top 10 list of vulnerability categories. In our experience hosting thousands of Indian websites, three of those ten cause 80% of incidents we respond to: out-of-date WordPress plugins/themes (Vulnerable Components), credential stuffing on weak admin passwords (Authentication Failures), and unrestricted file uploads that get used to deploy phishing kits (Broken Access Control + Security Misconfiguration). The other seven matter, but if you fix the three above before anything else, you've eliminated most of the practical attack surface against your site. This guide ranks the Top 10 by what we actually see hit customer accounts on Domain India hosting, with verbatim log signatures, concrete defences in PHP and Node.js, and the war stories that explain why each one matters.

TL;DR
The OWASP Top 10 is a list, but the items aren't equally common. The top three are stale WordPress, weak admin passwords, and unrestricted file upload. Phishing kits, casino-spam SEO injection, and outbound spam floods are the three incident shapes we see most. Lockdown order: update everything, rotate passwords + add MFA, block file uploads outside an allow-listed type set, then work down the rest of the list.

How we ranked these — ground-truth from our hosting servers

The ranking below isn't OWASP's official ordering. It's the order of incidents we actually triage on Domain India hosting:

RankOWASP categoryHow we see it manifest
1A06 Vulnerable ComponentsOutdated WordPress plugins/themes → drive-by RCE → site defaced or used as phishing host
2A07 Auth FailuresWeak/reused admin password → credential stuffing → admin takeover
3A01 Broken Access ControlUnrestricted file upload → attacker uploads PHP shell → deploys phishing kit
4A03 InjectionSQL injection on a homemade form → DB dump or admin escalation
5A05 Security MisconfigurationDefault admin/admin, exposed .git, verbose error pages
6A09 Logging FailuresCustomer notices something is wrong only when Google flags the site
7A02 Cryptographic FailuresMD5 password hashes, plain HTTP login, secrets in git
8A04 Insecure DesignOTP without rate limit, password-reset that emails the password
9A10 SSRFImage-fetch features that proxy arbitrary URLs
10A08 Integrity FailuresUnsigned auto-updates, missing SRI on CDN scripts

If you have a budget of one weekend, fix items 1, 2, and 3. The rest can be sequenced over the following weeks.

A06 — Vulnerable Components (the #1 incident shape)

What we see in practice. A customer installs WordPress, picks a free theme, installs 15 plugins, then forgets. Six months later, a known CVE in one of those plugins is exploited by an automated scanner. Within hours the attacker drops a PHP webshell into /wp-content/uploads/ or /wp-content/themes/<theme>/. From there: SEO spam injection, phishing kit deployment, or use of the host as an outbound-spam relay.

Real incident (anonymised from our 2025 advisories): a customer's account had a phishing kit deployed across four of their domains, all hosted under one cPanel user. The pages were near-perfect clones of a Belgian bank's login screen, redirecting victim credentials to an attacker-controlled drop. Discovery: simultaneous abuse reports from the bank's fraud team and Hetzner's abuse desk. Account suspended within hours; the IP picked up Spamhaus listings before we contained it. Root cause: stale WordPress plugin with a known unauthenticated upload vulnerability. The customer thought they didn't have WordPress installed — they had inherited a one-page WordPress install from a developer who left two years earlier and forgot it existed.

Defence — automate it, you won't remember to do it manually:

bash
# Node.js
npm audit
npm audit fix

# PHP / Composer
composer audit

# WordPress (via WP-CLI)
wp plugin update --all
wp theme update --all
wp core update

# Container scanning
trivy image your-app:latest

Run on every CI build. Block merge on high-severity findings. For WordPress sites without CI, set a weekly cron to email you a wp plugin status snapshot.

GitHub's Dependabot and self-hosted Renovate auto-create PRs for dependency updates — turn them on for every repo you maintain. If you've inherited a project whose package files don't lock versions, the first task is to lock them.

The Domain India angle. Our shared hosting offers Imunify360 on most cPanel servers (DIC, MAS) — it scans for known malware patterns, blocks PHP execution in upload directories, and can quarantine compromised files. It is not a substitute for keeping plugins updated, but it catches the long tail.

A07 — Identification & Authentication Failures (#2)

What we see in practice. Brute-force login attempts hammer cPanel /login, WordPress /wp-login.php, and webmail at all hours. Most are blocked by CSF/LFD's per-account limits (we've tuned these to 5 SSH attempts → permanent ban, 25 panel/mail attempts → 1-hour temp, 4 temp bans within 24h → permanent), but the attacks themselves are constant. The successful breaches are usually credential stuffing — username/password combos leaked from another breach, replayed against your login.

Verbatim LFD log line of a brute-force attempt being blocked:

*Account Hacked? Detected* User: someuser, Service: ssh, Attempts: 6, IP: 45.x.x.x

A flurry of these around the same minute is a brute-force attempt. The LFD daemon banned the IP automatically; if not, it's because the attacker rotated IPs faster than the threshold counts.

Defences in priority order:

  1. Strong unique passwords for every admin account. Generated, not chosen. Stored in a password manager (1Password, Bitwarden, KeePassXC). Never reused.
  1. Multi-factor authentication everywhere it's available. WordPress: WP 2FA plugin or Wordfence Login Security. cPanel: enable 2FA from cPanel → Two-Factor Authentication. Custom apps: TOTP via speakeasy (Node) or OTPHP (PHP):

```javascript

import speakeasy from 'speakeasy';

// On user enrolment

const secret = speakeasy.generateSecret({ name: 'My App' });

// Save secret.base32 to user record, show secret.otpauth_url as QR

// On login verification

const valid = speakeasy.totp.verify({

secret: user.mfaSecret,

encoding: 'base32',

token: req.body.code,

window: 1, // accept ±30s drift

});

```

  1. Rate limit the login endpoint — both successful and failed attempts:

```javascript

import rateLimit from 'express-rate-limit';

app.post('/login', rateLimit({

windowMs: 15 60 1000,

max: 10,

message: { error: 'Too many attempts, try again in 15 minutes' },

standardHeaders: true,

}), loginHandler);

```

  1. Rotate the session ID on login to prevent session fixation:

```php

session_regenerate_id(true); // PHP, after successful login

```

```javascript

req.session.regenerate(() => { / set req.session.userId / }); // Express

```

  1. Lock accounts after N failed attempts. Five is a reasonable default for end users; three for admin accounts. Auto-unlock after 30 minutes; permanent lock after a higher threshold to prevent casual brute-force.
  1. Don't reveal which inputs were wrong. "Invalid email or password" — never "no account with that email" or "password incorrect for this account". The latter helps account-enumeration attacks.

A01 — Broken Access Control (#3 by frequency, but huge by impact)

What we see in practice. Two patterns dominate:

Pattern 1: Insecure Direct Object References (IDOR). GET /api/orders/42 returns order 42 to any authenticated user, not just the owner. Same for /api/invoices/, /api/users/, document downloads — anywhere the URL contains an ID and the server doesn't verify ownership. Trivially exploited by changing the number.

Pattern 2: Unrestricted file upload. Custom contact form or media uploader accepts any file extension without checking. Attacker uploads evil.php to a public path, opens it in a browser, gets remote code execution. From there, phishing kits, SEO spam, outbound mail abuse — all the incidents in this list.

Defence (Node.js IDOR):

javascript
app.get('/api/orders/:id', authenticate, async (req, res) => {
  const order = await db.order.findUnique({ where: { id: req.params.id } });
  if (!order) return res.status(404).send('Not found');
  // Critical: verify ownership
  if (order.userId !== req.user.id) {
    return res.status(404).send('Not found');     // 404, not 403 — don't confirm existence
  }
  res.json(order);
});

Rule: every resource query must filter by userId = session.userId or include an explicit role check. Don't rely on URLs or admin-menu placement.

Defence (file upload, PHP):

php
$allowedMimes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
$allowedExts  = ['jpg', 'jpeg', 'png', 'webp', 'pdf'];

$file = $_FILES['upload'];
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$mime = mime_content_type($file['tmp_name']);

if (!in_array($ext, $allowedExts, true) || !in_array($mime, $allowedMimes, true)) {
    http_response_code(400);
    exit('Invalid file type');
}

// Generate a safe filename — never trust user-supplied name
$safeName = bin2hex(random_bytes(16)) . '.' . $ext;

// Store outside the document root, OR ensure PHP can't execute in the upload dir
move_uploaded_file($file['tmp_name'], '/home/user/private-uploads/' . $safeName);

For storage location, prefer outside the public document root entirely — serve files via a script that streams them with proper Content-Type. If they must live in a public path, drop a .htaccess to disable PHP execution:

# In the upload directory
<FilesMatch "\.(php|phtml|phar|inc|cgi)$">
    Require all denied
</FilesMatch>

This single .htaccess line prevents the most common phishing-kit deployment pattern we see.

A03 — Injection (#4)

SQL injection is the canonical example, still widely exploited because homemade contact forms and search pages keep getting written without parameterisation.

php
// UNSAFE — SQL injection
$user = $db->query("SELECT * FROM users WHERE id = $id");

// SAFE — parameterised
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$user = $stmt->fetch();
javascript
// UNSAFE
const user = await db.query(`SELECT * FROM users WHERE id = '${id}'`);

// SAFE — parameterised
const user = await db.query('SELECT * FROM users WHERE id = $1', [id]);

NoSQL injection is its own category. With MongoDB:

javascript
// UNSAFE — attacker sends {"$ne": null} as password and bypasses auth
db.user.findOne({ email: req.body.email, password: req.body.password });

// SAFE — type check first
if (typeof req.body.email !== 'string' || typeof req.body.password !== 'string') {
  return res.status(400).send();
}
db.user.findOne({ email: req.body.email, password: hashedPassword });

OS command injection — exec'ing user input directly:

javascript
// NEVER
exec(`convert ${req.body.input} out.png`);

// Use execFile with array args (no shell interpretation)
execFile('convert', [req.body.input, 'out.png'], { timeout: 10000 });

// Still validate input is a safe filename
if (!/^[\w\-./]+$/.test(req.body.input)) return res.status(400).send();

LDAP injection, XPath injection, NoSQL operator injection — same pattern. Whenever you build a query string that mixes code and data, separate them via parameterised APIs or strict input validation.

For depth on SQL injection specifically, see our SQL injection prevention article.

A05 — Security Misconfiguration (#5)

The most common findings on customer audits:

  • Default admin/admin or admin/password123 left in place after CMS install.
  • /.git/ directory exposed to the public web (downloadable with one tool: git-dumper). Anyone gets your full source code, commit history, and any secrets ever committed.
  • phpinfo.php left at the document root — leaks PHP version, paths, environment.
  • Verbose error pages in production — leak stack traces, DB credentials in connection-error messages.
  • wp-config.php permissions set to 644 (world-readable) on shared hosting — other accounts on the server can read it under bad isolation. (CloudLinux's CageFS prevents this, but we still see customers chmod things wrong.)

Hardening checklist:

bash
# Remove default accounts
mysql -u root -p -e "DROP USER 'admin'@'localhost'; FLUSH PRIVILEGES;"

# Hide server tokens (nginx)
server_tokens off;

# Hide PHP version
expose_php = Off    # in php.ini or .user.ini

# Disable directory listing (Apache)
Options -Indexes

# Block .git, .env, .htaccess from being served
<FilesMatch "^\.">
    Require all denied
</FilesMatch>

Security headers for every response:

php
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: strict-origin-when-cross-origin');
header("Content-Security-Policy: default-src 'self'");
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');

Express equivalent:

javascript
import helmet from 'helmet';
app.use(helmet());     // sensible defaults; tighten as needed

For Cloudflare-fronted sites, set most of these as Transform Rules → Modify Response Headers; saves you from re-implementing per-app.

A09 — Logging & Monitoring Failures (#6 — but it's the reason you discover everything else late)

What we see in practice. Most customer breaches are noticed by Google (search-console manual action for hacked content), by Hetzner (abuse complaint), or by the customer's web host (us, when traffic spikes weirdly or outbound mail floods). Almost never by the customer's own monitoring. The reason: there is no monitoring.

Minimum logging discipline:

  • Auth events: login success, login failure, MFA challenge, password change, MFA reset.
  • Admin actions: role change, user deletion, settings change, data export.
  • Payment events: order created, payment captured, refund initiated, payment failed.
  • Security-sensitive API calls: file upload, password reset link generation, SSO callback.
  • All 5xx errors with stack trace.
  • All 4xx auth errors (failed authorization is more interesting than failed authentication).

Ship to a central system. On a VPS, the standard stack is Loki + Grafana for logs + dashboards; Prometheus for metrics; Alertmanager for paging. Our Production observability deep-dive covers setup. On shared hosting, the budget option is shipping logs to Better Stack, Papertrail, or Logtail — they have free tiers.

Alerts that catch the actual incidents:

  • 10+ failed logins for a single user in 5 minutes.
  • 100+ 5xx errors per minute (sudden break or scraper hammering).
  • New file in /wp-content/uploads/ with .php or .phtml extension.
  • Outbound email volume more than 2× the rolling-7-day baseline.
  • New admin user created (any time).
  • Geographic anomaly: login from India, then from a different country within an hour.

The last one — geographic anomaly — catches credential-stuffing breaches faster than anything else.

A02 — Cryptographic Failures (#7)

The bug. Passwords stored as MD5 or SHA-1, secrets committed to git, plain HTTP login forms (or HTTPS with mixed content from HTTP submission endpoints), self-signed cert in production.

Defences:

  1. Password hashing. Argon2id is the modern default; bcrypt is acceptable.

```php

$hash = password_hash($plain, PASSWORD_ARGON2ID);

$ok = password_verify($plain, $hash);

```

```javascript

import argon2 from 'argon2';

const hash = await argon2.hash(plain, { type: argon2.argon2id });

const ok = await argon2.verify(hash, plain);

```

Never SHA-256 / MD5 / SHA-1. Never roll your own with salt+pepper+iterations — the libraries handle this correctly; you won't.

  1. HTTPS everywhere. Let's Encrypt is free, automatic via cPanel's AutoSSL, and one-click on a Domain India VPS via Caddy. Add HSTS with max-age=31536000 once you've confirmed all subdomains have certs (HSTS is a one-way commitment for a year).
  1. Encrypt sensitive columns. PII, financial data, anything flagged under DPDPA (any personal data of an Indian resident, in 2026) — encrypt at rest with AES-256-GCM. Keys live in environment variables or a secret manager (AWS Secrets Manager, HashiCorp Vault, Doppler), never in code.
  1. Secrets management. Never commit .env, never paste credentials in Slack, never email passwords. Rotate immediately if they leak (and assume they leaked the moment they were anywhere outside a vault). For Indian businesses processing payments, your Razorpay/Stripe webhook secrets and key IDs are the highest-priority items to lock down.

A04 — Insecure Design (#8)

These are the bugs no amount of careful coding fixes — they're in the spec.

  • Password reset that emails the current password. This means you stored it in plain text. Never do this.
  • OTP for login that's 4 digits with no rate limit. 10,000 possibilities, brute-forced in 5 minutes. Use 6 digits + per-attempt rate limit + per-OTP attempt count.
  • "Forgot email" that confirms which emails are registered. Helps account-enumeration. Always reply with the same generic "if an account exists, we sent an email."
  • Client-side-only validation. Anyone can disable JavaScript or call your API directly. Always validate on the server.
  • Trusting a referrer header for security. Referrers can be set or omitted at will by the client.
  • OTP sent over SMS for high-value actions. SIM-swap attacks are common in India; for actions like withdrawals, OTP-via-SMS isn't sufficient — pair with TOTP or push-app confirmation.

Defence: every new feature gets a "what if the attacker did X?" review before code. Threat-model your authentication flow, your money flow, your file-upload flow, and your privilege-elevation flow. Tools like Burp Suite Community Edition (free) help you replay requests with modified inputs.

A10 — Server-Side Request Forgery (SSRF) (#9)

The bug. Your app has a feature that fetches a URL on behalf of the user — image preview, OG-tag scraper, webhook tester. Attacker supplies an internal URL (http://169.254.169.254/latest/meta-data/ for AWS metadata, http://127.0.0.1:6379 for Redis, http://internal-db:5432).

Defence:

javascript
import { URL } from 'url';
import dns from 'dns/promises';
import net from 'net';

const BLOCKED_NETS = [
  '10.0.0.0/8',
  '172.16.0.0/12',
  '192.168.0.0/16',
  '169.254.0.0/16',     // link-local + AWS metadata
  '127.0.0.0/8',
  '0.0.0.0/8',
  '::1/128',
];

function isBlocked(ip) {
  // Use a CIDR library like 'ipaddr.js' to evaluate
  return BLOCKED_NETS.some(net => isInRange(ip, net));
}

async function safeFetch(userUrl) {
  const url = new URL(userUrl);
  if (!['http:', 'https:'].includes(url.protocol)) {
    throw new Error('Only HTTP/HTTPS allowed');
  }
  if (url.hostname === 'localhost' || url.hostname === '0.0.0.0') {
    throw new Error('Blocked hostname');
  }
  // Resolve hostname → IP, check against blocked list
  const ips = await dns.resolve(url.hostname);
  if (ips.some(ip => isBlocked(ip))) {
    throw new Error('Blocked IP');
  }
  return fetch(url, { redirect: 'manual' });    // don't follow redirects without re-checking
}

The redirect check matters: an attacker can supply https://evil.com/redirect that 302s to http://169.254.169.254/.... You must re-validate on each hop, or simply set redirect: 'manual' and refuse anything that isn't a 200.

India-specific SSRF target: government and bank APIs that listen on RFC1918 IPs. RBI, NPCI, UIDAI sandbox endpoints sometimes use non-routable IPs in dev environments — make sure your SSRF allow-list isn't accidentally letting prod calls hit dev infrastructure.

A08 — Software and Data Integrity Failures (#10)

The bug. Auto-updates without signature verification; CDN scripts without Subresource Integrity; CI pipelines that trust unauthenticated artefacts.

Defences:

  • Pin and lock dependencies. package-lock.json, composer.lock, pnpm-lock.yaml, bun.lockb. Don't commit a project without lockfiles.
  • Verify Docker image signatures (Sigstore / Cosign for OCI registries).
  • Sign your own releases — Sigstore for OSS, GPG for traditional distribution.
  • Subresource Integrity on CDN scripts — tells the browser to refuse the file if the hash doesn't match:

```html

<script src="https://cdn.example.com/lib.js"

integrity="sha384-abc123..."

crossorigin="anonymous"></script>

```

If lib.js ever changes (intentionally or via supply-chain attack), the browser blocks it. Generate hashes via cat lib.js | openssl dgst -sha384 -binary | openssl base64 -A.

What Indian web apps get hit by — patterns we see often

Generic OWASP examples don't capture the specific attack vectors targeting Indian sites. Patterns we triage repeatedly:

  • UPI-themed phishing pages cloning PhonePe, Paytm, GPay login screens — deployed on hijacked WordPress sites to steal UPI PINs.
  • Aadhaar verification scams — fake pages claiming to "update Aadhaar to avoid suspension" that capture personal details. Deployed on compromised .in sites because the TLD lends credibility.
  • GST-refund scam pages — fake CBIC/GST portal clones for tax-season fraud.
  • Indian-bank phishing kits — HDFC, ICICI, SBI, Axis login clones; we see specific kits rotated based on which bank is having a campaign or breach mention in news.
  • Casino-spam SEO injection — Hindi-language Bollywood/cricket-betting-themed spam pages injected into legitimate sites for SEO-jacking. Often deployed via an outdated WordPress plugin and persists for months until manual SEO audit.
  • Outbound spam relay abuse — once a phishing kit lands, the attacker often uses your account to send phishing to new victims. This is the abuse pattern that gets your IP listed on Spamhaus.

Defence is the same as everything above — but the operational cost of these in particular is high because Indian banks, Hetzner, and Spamhaus all maintain abuse-reporting pipelines, and a single compromised account can trigger reports from all three.

Tools we recommend

Free, run yourself:

  • OWASP ZAP — automated web app scanner. Run weekly against staging.
  • Burp Suite Community Edition — manual request inspection and replay. Indispensable for finding IDOR and access-control bugs.
  • nikto — web server scanner; finds default files, common misconfigurations.
  • `sqlmap` — SQL injection tester. Only run on apps you own.
  • `trivy` — container vulnerability scanner.
  • Plugin Check 2.0 (for WordPress plugins you build) — covered in our WordPress plugin guide.

Commercial:

  • Snyk, Semgrep, SonarQube — SAST in CI. Free tiers usually enough for a small team.
  • Detectify, Pentera, Astra — DAST and attack simulation. Worth it once your app is generating revenue.
  • Cloudflare Pro / Business — WAF + bot protection. Blocks the noisy 90% of attacks at the edge.

Imunify360 is included by default on most of our cPanel servers; it scans uploaded files, blocks PHP execution in upload directories, and quarantines known-malicious files. Not a replacement for the rest of this list, but a strong baseline.

What to do if your site has been hacked

Suspected compromise — phishing pages, casino spam in Google results, outbound mail floods, abuse reports — work in this order:

  1. Take the site offline. Cleanest is mv public_html public_html_offline so the attacker's payload can't propagate while you investigate. Customers panic about downtime; explain that an extra hour of downtime is much better than another week of phishing damage.
  1. Rotate every credential. cPanel password, FTP, email accounts, WordPress admin, database password, API keys committed to your code, payment gateway keys if exposed.
  1. Pull a backup from before the compromise. JetBackup retention varies by plan; check what date is available. Restore to a clean cPanel account if possible — full restore is safer than file-by-file cleanup.
  1. Audit `wp-content/uploads/`, `wp-content/plugins/`, `wp-content/themes/` for unexpected .php files. Compare file dates to your last legitimate update. Anything out of place is the malware.
  1. Update everything before going back online. WP core, every plugin, every theme. Remove anything you're not actively using. Same for the underlying PHP version if it's been EOL.
  1. Tell us. Open a ticket at [email protected]. We can review server-side logs (Apache access, exim mail, LFD) for the attacker's IPs and timing, scan with Imunify, and rebuild the cPanel account from clean if that's easier.
  1. Submit a Google Search Console reconsideration request if your site got a manual action.
  1. Write a one-page postmortem for yourself. Which plugin/credential/upload was the entry? How long was the attacker on the system? What did they exfiltrate? You'll do better next time if you actually look back.

Frequently asked questions

Q Do I need a security team if I'm a one-person business?

No. One engineer who runs npm audit / wp plugin update --all weekly, uses MFA on every admin account, and has a backup strategy is materially safer than 90% of the small Indian websites we host. Hire dedicated security people somewhere around 50 employees or when you start handling regulated data (health, financial, government).

Q What's "defense in depth"?

Multiple layers of protection. WAF blocks generic bot attacks at the edge; framework-level input validation catches what makes it through; output escaping prevents stored XSS from rendering; logging detects what slips past everything else. No single layer is enough.

Q Is Cloudflare WAF enough?

Cloudflare WAF blocks most automated attacks — bots scanning for known WordPress CVEs, OWASP-rule-matched payloads, geographic blocking. It does not block targeted attacks where an attacker who knows your stack writes a custom payload. Pair with the application-level defences in this guide.

Q How often should I update dependencies?

Critical security patches: within 24 hours of disclosure. Regular updates: weekly in dev, monthly batch into prod with smoke testing. For WordPress sites: enable auto-updates for minor versions and trusted plugins; manually review major versions.

Q ISO 27001 / SOC 2 — do I need them?

Selling to enterprises or government? Yes, increasingly. Serving small businesses or consumers only? Informal but disciplined security hygiene is enough. Don't pay for compliance certs you don't have a buyer asking for.

Q My WordPress site got hacked twice — same hosting, different cleanup teams. Why?

Almost always because the entry vector was never identified. Cleanup teams remove the malware they find but don't determine how it got there. Without that, the attacker's webshell or backdoor account remains, and the site is recompromised within weeks. Fixing requires forensics — server-side logs from your host, Wordfence/Sucuri scan reports, and a full audit of plugin versions at the time of compromise. Open a ticket; we'll provide what we can from the server-side.

Q Should I use a managed WordPress security service like Wordfence Premium / Sucuri / MalCare?

They're worth it for sites that have already been compromised once or that handle high-value transactions. For a brochureware site that's kept up-to-date, the basics in this guide plus Imunify (included on our hosting) are usually sufficient.

Q We use AWS / Azure / GCP — does any of this change?

Cloud providers add their own security primitives (IAM, KMS, GuardDuty, security hub) that are powerful but easy to misconfigure. Cloud-specific OWASP analogues exist (AWS Well-Architected security pillar, Azure Cloud Adoption Framework). Apply both: the application-level defences here, plus your cloud provider's IAM/network discipline.

Q I'm building a fintech / health / government app. What changes?

Compliance overhead — RBI guidelines for fintech (data localisation, audit trails), DPDPA + sector rules for health, MEITY-empanelled hosting and audit for government. Out of scope for this article but a real consideration. Talk to a compliance consultant before you build.

Bottom line

Most attacks on Indian websites aren't sophisticated. They exploit out-of-date software, weak passwords, and unrestricted file uploads — three categories that you can shut down in a weekend. Do those before anything else, set up basic logging so you'll know if something gets past, and put MFA on every admin account that supports it. The rest of the OWASP Top 10 matters too, but if you've nailed the top three, you've taken yourself out of the easy-target pool that most automated attacks aim at.

If your site has been compromised, or you'd like help identifying the entry vector after a previous incident, [email protected] — we can pull server-side logs and scan results for accounts hosted with us.

Need a hardened, monitored hosting environment for a high-value site? Domain India VPS Starter ₹553/month — root access, full log control, Imunify-compatible. Get a VPS plan

Was this article helpful?

Your feedback helps us improve our documentation

Still need help? Submit a support ticket