15.1. Introduction to Web Security
Table of Contents
Why Web Security Matters
When you build backend systems, you are handling other people’s data and money. A single security mistake can expose passwords, leak private messages, or allow attackers to control your servers.
Security is not something you “add at the end.” It is part of every decision you make, from how you design your database to how you handle a single HTTP request.
Some real world examples of what can go wrong:
- An online store accidentally exposes all customer email addresses through an insecure API.
- A bug in a password reset feature lets anyone take over any account.
- A missing server side validation step allows attackers to delete other users’ data.
All of these are common, and all of them were caused by simple coding or design mistakes.
Important statement: As a backend developer, you are responsible for protecting user data, not only for making features work.
In this chapter, you will get a high level map of common security concepts and typical risks, so that later chapters about specific attacks and defenses will make sense.
Core Security Concepts
Before you learn “how to defend,” you need a mental model of what you are defending and what “secure” means.
Confidentiality, Integrity, Availability (CIA)
Security is often summarized with three letters, CIA:
| Concept | Meaning | Example in a backend context |
|---|---|---|
| Confidentiality | Only authorized people or systems can see the data | Others cannot see my private messages |
| Integrity | Data cannot be changed in an unauthorized way | No one can change my order amount without my consent |
| Availability | The service is up and can be used when needed | The API is not easily taken down by an attacker |
Core rule: A secure system protects confidentiality, integrity, and availability of data and services.
A system can fail in any of these ways:
- Confidentiality failure: A database dump with users’ passwords is exposed.
- Integrity failure: An attacker changes bank account balances or modifies logs.
- Availability failure: A denial of service attack makes your API unreachable.
When you design and code, ask yourself: “Could this feature break confidentiality, integrity, or availability if misused?”
The Security Mindset
Backend beginners often think: “How do I make this work?” A security minded developer also asks: “How could someone make this behave in a way I did not intend?”
Some practical ways to think like this:
- Assume all input is hostile, even if it comes from your own frontend.
- Assume users will try unexpected values, very large values, or special characters.
- Assume secrets can leak if you do not protect them.
- Assume error messages are read by attackers, not just by developers.
Example:
- You build an endpoint
/users/{id}that returns user details. - Functional thinking: “It returns user data if the user is logged in.”
- Security thinking: “Can user A get user B’s data by guessing their id? What if they pass negative numbers, huge numbers, or strings? Does the backend check permissions, or does it trust the client?”
Assets, Threats, and Attackers
You cannot protect “everything” equally. You need to know what is valuable, who might attack it, and how.
What Are You Protecting? (Assets)
In backend systems, typical assets include:
- User data: emails, names, addresses, phone numbers.
- Credentials: passwords, API keys, tokens.
- Financial data: payment information, subscription data.
- Business data: internal admin tools, reports, analytics.
- Infrastructure: servers, databases, queues, logs.
Different assets have different sensitivity levels. Exposing an email list is bad. Exposing password hashes is worse. Exposing raw passwords or payment details is usually critical.
Who Might Attack You?
Attackers are not always “super hackers.” Many successful attacks are very simple.
Types of attackers:
- Curious users who try URLs they should not access.
- Script kiddies who run automated tools against public websites.
- Competitors who want to see your internal dashboards.
- Malicious insiders with legitimate access misusing their privileges.
- Organized criminals focusing on financial or personal data.
You often do not know which kind of attacker you face, so you cannot rely on “obscurity” like “nobody will guess this URL.”
How Might They Attack? (Threats)
Common threat examples for a backend:
- Guessing or brute forcing passwords.
- Exploiting missing authorization checks to access other users’ data.
- Injecting SQL commands where you expect user input.
- Uploading executable files instead of safe images.
- Abusing your public APIs to overwhelm your servers.
Later chapters will cover these threats in detail. For now, remember this pattern:
- You have an asset.
- There is a way to reach it (an endpoint, a database, a file system).
- An attacker misuses that path.
Every public interface in your backend can be a potential attack path.
Defense in Depth
No single protection is perfect. If you rely on just one check, one bug might be enough to compromise your system. The idea of defense in depth is to have multiple, independent protections.
Example for storing passwords:
- Use HTTPS so passwords are encrypted in transit.
- Use strong password hashing on the server.
- Apply rate limiting on login attempts.
- Monitor login failures for suspicious activity.
If one layer fails or is bypassed, other layers still provide some protection.
Another example, accessing a protected admin panel:
- Authentication: Users must log in.
- Authorization: Only admins can access.
- Network restriction: Admin panel only accessible from specific IP ranges, or via VPN.
- Input validation: Admin forms still validate and sanitize all input.
- Logging and alerting: Admin actions are logged and monitored.
Key principle: Do not rely on a single security mechanism. Combine several layers, each reducing risk.
The Backend Trust Boundary
A trust boundary is a line between what you control and trust, and what you do not control.
For a typical web backend:
- Inside the boundary: Your application code, your database, internal services.
- Outside the boundary: Browsers, mobile apps, third party clients, the public internet.
All data crossing into your backend from outside the boundary is untrusted.
This includes:
- Request bodies (JSON, form data).
- Query parameters and path parameters.
- HTTP headers, including custom headers.
- Cookies and session IDs.
- File uploads.
Do not treat data as safe just because it comes from “your frontend.” Attackers can ignore the frontend and send requests directly.
Example:
Your frontend has a disabled HTML input field role="user". You trust that all users are “user” and never “admin.” An attacker uses a tool like curl or Postman and sends "role": "admin" in the request body. If your backend code does not enforce role rules, you just gave them admin rights.
The trust boundary exists at the HTTP interface of your backend. Everything that crosses that line must be validated, sanitized, and authorized on the server.
Common Types of Vulnerabilities
You will later study specific attacks like SQL injection, XSS, and CSRF in their own chapters. Here we give a high level introduction so that you can recognize the categories.
Injection Attacks
An injection occurs when untrusted input is treated as part of a command or query sent to another system.
Some main types:
- SQL Injection: Untrusted input becomes part of an SQL query.
- Command Injection: Input is passed to a system shell command.
- Template Injection: Input is processed by a template engine as code.
Example of unsafe Python code:
# Very unsafe example
user_id = request.query_params["user_id"]
sql = f"SELECT * FROM users WHERE id = {user_id};"
cursor.execute(sql)
If user_id is 1; DROP TABLE users;, the combined SQL might delete the table.
The safe approach uses parameterized queries, which will be covered in SQL and ORM chapters.
Authentication and Authorization Flaws
These problems occur when:
- Users can log in with weak or predictable passwords.
- Passwords are stored in plain text.
- Session tokens are easy to guess or not invalidated.
- The backend checks “who are you?” (authentication) but not “what can you do?” (authorization).
Typical examples:
- Any logged in user can access
/adminbecause the code only checksif user:but notif user.is_admin:. - A user can access
/users/123and read or modify user 123’s data even though they are user 456.
You will see these issues deeply in the Authentication and Authorization sections.
Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF)
These are attacks related to the browser and the way it interacts with your backend:
- XSS: Attacker injects malicious JavaScript that runs in a victim’s browser.
- CSRF: Attacker tricks a logged in user’s browser into making unintended requests to your backend.
As a backend developer, you prevent XSS by encoding output properly and validating input. You prevent CSRF by using proper tokens and same site cookies, which will be discussed later.
Insecure Direct Object References (IDOR)
In an IDOR vulnerability, the backend exposes a reference to an internal object, such as a numeric ID, and fails to check whether the current user is allowed to access it.
Example pattern:
- Endpoint:
GET /invoices/{invoice_id}. - Backend code:
SELECT * FROM invoices WHERE id = :invoice_id. - There is no check that the invoice belongs to the current user.
An attacker logs in, sees that their invoice is id=10, then tries id=11, id=12, and so on. If your backend does not verify ownership, they can read other people’s invoices.
Security Misconfigurations
Not all vulnerabilities are in your code. Many are in the environment:
- Leaving default passwords on tools or databases.
- Exposing debugging endpoints or admin panels publicly.
- Serving your application over HTTP without TLS.
- Misconfigured CORS that allows any site to make authenticated requests to your backend.
- Leaving directory listings or internal logs accessible over HTTP.
As a backend developer, you will be involved in configuration for web servers, containers, and cloud services. Misconfigurations often give attackers a very easy path.
Secure Development Principles
Security is easier if it is part of your usual way of writing code, not a special step you remember sometimes.
Principle of Least Privilege
Give users, services, and processes the minimum rights they need to do their job, and no more.
Examples:
- A web app database user only has rights to that app’s database, not all databases on the server.
- A background worker that only sends emails does not need access to modify user passwords.
- An API token for a reporting tool is read only, not read and write.
If an attacker gains access to a limited account, the damage is limited.
Important rule: Always grant the smallest set of permissions that still allows a task to work.
Never Trust, Always Verify
Do not trust:
- Client side validation.
- Hidden form fields.
- “Secure” JavaScript variables.
- Cookie values.
- URL parameters.
Server side you must:
- Validate types, ranges, and allowed values.
- Check authorization for each sensitive operation.
- Sanitize or escape data before using it in queries, templates, or file operations.
Example:
A registration form validates email format in JavaScript. That is helpful for users, but the backend should still enforce valid email format. Attackers can bypass frontend validation easily.
Fail Securely
When something goes wrong, your system should fail in a safe way.
Examples:
- If a permission check cannot be completed because of an error, deny access, do not grant access by default.
- If you cannot verify an authentication token, treat it as invalid and ask for login again.
- If input validation fails, reject the request and return a clear but generic error.
A bad pattern is “if something goes wrong in security related code, just ignore the error and continue.” That often leads to open doors.
Do Not Roll Your Own Crypto or Security Schemes
Security is hard to get right. Small mistakes can completely break a protection.
Avoid:
- Designing your own password hashing algorithm.
- Implementing your own token format instead of using well known standards.
- Designing your own encryption schemes.
Instead, rely on:
- Well reviewed libraries.
- Established standards like HTTPS, JWTs, and OAuth 2.0.
- Framework features that already handle common security tasks, like CSRF tokens.
You still need to understand how to use them correctly, but you do not need to invent them.
Basics of Protecting Data in Transit and at Rest
Two basic ideas appear everywhere in web security: encryption “in transit” and encryption “at rest.”
Data in Transit
“Data in transit” is data moving between clients and servers, usually over HTTP.
To protect it:
- Use HTTPS, not HTTP.
- Use TLS certificates from a trusted authority.
- Redirect all HTTP requests to HTTPS in production.
With HTTP, any network observer can see and modify requests:
- Plain text passwords.
- Session cookies.
- Personal data in query parameters or bodies.
With HTTPS, data is encrypted between browser and server, which protects confidentiality and integrity.
You will learn details of HTTPS and TLS in a separate chapter. For now, remember that any production backend that handles user data must use HTTPS.
Data at Rest
“Data at rest” is data stored on disk:
- Database files.
- Backups.
- Log files.
- Uploaded files.
You need different strategies:
- Passwords are stored as hashes, never as plain text.
- Sensitive values like API keys live in environment variables or secret managers, not in source code.
- Database encryption features may be used for particularly sensitive fields.
- Access to backups and logs must be restricted.
Encryption is not a magic bullet. If an attacker can access your running application, they may still get decrypted data. However, encryption at rest protects you in case of lost disks, backup leaks, or offline attacks.
Logging, Monitoring, and Security
Security is not only about prevention. It is also about detection and response.
You should log:
- Authentication events: logins, failed logins, password resets.
- Authorization failures: attempts to access forbidden resources.
- Input validation failures: repeated suspicious payloads.
- Important admin actions: changes in roles, configuration, financial data.
But be careful:
- Do not log passwords or full credit card numbers.
- Avoid logging complete authentication tokens.
- Be aware that logs themselves are sensitive data.
Monitoring tools and alerts help you see patterns:
- Many failed logins from the same IP might indicate a brute force attack.
- Spikes in traffic to rare endpoints might indicate scanning.
- Sudden increase in 500 Internal Server Errors might show an active exploit.
Later chapters on Logging and Monitoring will cover tools. For now, know that security without visibility is incomplete.
Security as an Ongoing Process
Security is never “done.” New vulnerabilities are discovered. New libraries have bugs. Requirements change.
Some continuous tasks for backend developers:
- Keep dependencies updated and watch for security advisories.
- Periodically review access rights and remove unused accounts or tokens.
- Improve input validation and error handling as you discover edge cases.
- Regularly back up and test restoring data.
- Perform security reviews for new features and new endpoints.
A useful habit is to ask for any new feature:
- What data does this expose?
- Who should be able to use it?
- How could it be abused?
- Where should it be logged?
This mindset will help you apply all later security topics effectively throughout your backend projects.
Views: 6
KAHIBARO