Web Security & Performance Optimization

Chapter 6
Server-Side Application Security

Bachelors Program in Full Stack Development
Web Security & Performance Optimization   •   Bachelor

Server-Side Application Security

Introduction

Server-side application security concerns the protection of code, data, services, and infrastructure that operate beyond the user’s browser. A server receives requests, interprets input, accesses databases and files, invokes services, applies business rules, and returns responses. Each step creates an opportunity for an attacker to influence execution or obtain information without authorization.

The central security problem is not simply that malicious strings may enter an application. It is that untrusted data can cross a boundary and be interpreted as instructions, file paths, network destinations, commands, serialized objects, or business decisions. Secure server-side development therefore depends on maintaining a clear distinction between data and instructions, enforcing authorization at the point of use, limiting the authority of components, and failing safely.

This chapter examines injection, insecure deserialization, file and path attacks, server-side request forgery, operating-system command execution, business-logic abuse, and unsafe error handling. It emphasizes validation, parameterization, isolation, least privilege, secure defaults, and layered controls. The examples use language-independent pseudocode or familiar web-development patterns; exact APIs vary by programming language and framework.

Learning Objectives

By the end of this chapter, a student should be able to:

  1. Explain how server-side trust boundaries create security risks.
  2. Distinguish validation, encoding, parameterization, and authorization.
  3. Prevent SQL, NoSQL, template, LDAP, and command injection.
  4. Assess the risks of deserializing attacker-controlled data.
  5. Secure file uploads, downloads, path handling, and archive extraction.
  6. Identify and mitigate SSRF and unsafe outbound requests.
  7. Apply controls against command execution and excessive process authority.
  8. Analyze business-logic abuse using invariants and threat scenarios.
  9. Design useful but non-revealing error handling and logging.
  10. Select appropriate testing, monitoring, and governance practices.

1. The Server-Side Trust Model

A server must treat requests, headers, cookies, uploaded files, webhook payloads, URL parameters, and data received from other services as untrusted. Authentication can establish an identity, but it does not make every value supplied by that identity safe. An authenticated user may be malicious, compromised, or simply able to manipulate fields that the interface normally hides.

A useful model is a sequence of trust boundaries:

Client → Web server → Application code → Data store or operating system → External service

At each boundary, the receiving component should:

  • define the expected type, length, format, and range of data;
  • authenticate and authorize the action;
  • interpret data using a safe interface rather than string concatenation;
  • limit resources and privileges;
  • record security-relevant events without exposing secrets.

Security controls should be placed close to the operation they protect. For example, a user-interface restriction that disables an administrator button is not authorization. The server must check the permission when the administrative operation is requested.

Validation, encoding, parameterization, and authorization

These controls solve different problems.

ControlMain purposeExample
ValidationDetermine whether input has an acceptable form or meaningRequire quantity to be an integer between 1 and 100
ParameterizationKeep data separate from an interpreter’s instructionsPrepared SQL statement
Output encodingPrevent data from being interpreted in a specific output contextHTML-escape a value inserted into a page
AuthorizationDetermine whether the actor may perform an action on a resourceCheck that a user owns an order
IsolationLimit the effect of compromise or misuseRun image processing in a restricted container

Validation should be performed on the server, even when client-side validation is also used. Prefer allowlists and structured types. A field defined as an integer should be parsed as an integer rather than checked only with a regular expression. Validation is not a replacement for parameterization: a value may satisfy a permitted format and still be dangerous when incorrectly embedded in an interpreter.

2. Injection Vulnerabilities

Injection occurs when an application combines untrusted data with a language interpreted by another component. The attacker’s data changes the meaning of the resulting program, query, expression, or document.

SQL injection

An unsafe query constructs SQL through concatenation:

query = "SELECT * FROM accounts WHERE email = '" + email + "'"

If email is interpreted as SQL syntax, the attacker may bypass conditions, read unauthorized records, alter data, or in some environments execute administrative operations.

The primary defense is a parameterized query:

statement = database.prepare(
    "SELECT id, password_hash FROM accounts WHERE email = ?"
)
statement.bind(1, email)
row = statement.execute()

The database receives the SQL structure separately from the value. An object-relational mapper can provide similar protection when used correctly, but raw query features and dynamically assembled fragments still require care. Parameterization generally applies to values, not arbitrary table names, column names, or sort directions. If an identifier must be selected dynamically, map a small validated application value to a fixed server-side identifier:

allowedSorts = {"name": "display_name", "date": "created_at"}
sortColumn = allowedSorts.get(requestedSort, "created_at")

Additional SQL controls include database accounts with only required permissions, separate read and write credentials where practical, transaction boundaries, and monitoring of abnormal query behavior. Escaping alone is fragile because it depends on the correct database, encoding, and context.

Other interpreter injection

The same principle applies beyond SQL.

  • NoSQL injection: Do not accept arbitrary query objects from clients. Convert input into expected scalar fields and construct query objects server-side.
  • LDAP injection: Use an LDAP library’s escaping and filter-construction APIs; do not concatenate user input into LDAP filters.
  • Template injection: Treat user content as data, not as a template. Use sandboxed template engines cautiously because template isolation may be incomplete.
  • Expression injection: Do not evaluate user input with general-purpose expression evaluators. Use a restricted grammar or explicit operations.
  • XML injection and entity attacks: Use safe parsers, disable external entities when not required, limit input size, and validate the document structure.

A secure design identifies every interpreter in the request path: database engines, shells, template engines, regular-expression engines, XML parsers, search query languages, and message brokers.

Regular-expression denial of service

Regular expressions can become an injection-like resource problem when attacker-controlled input causes excessive backtracking. Prefer linear-time patterns, bound input length, use regular-expression timeouts where available, and avoid applying complex expressions to unlimited data. A validation rule that consumes excessive CPU can be as damaging as a malformed database query.

3. Insecure Deserialization

Serialization converts an object or data structure into a transferable representation. Deserialization reconstructs it. Insecure deserialization occurs when attacker-controlled serialized data is reconstructed in a way that invokes dangerous methods, creates unexpected object types, bypasses security assumptions, or consumes excessive resources.

Risk depends on the format and implementation. Some object serialization systems preserve class identity and invoke constructors, property setters, callbacks, or magic methods. If a gadget chain is available in the application’s dependencies, deserialization can result in file access or code execution before ordinary application validation occurs.

Safer practices are:

  1. Prefer simple data formats such as JSON with explicitly defined schemas.
  2. Deserialize into primitive data-transfer objects rather than arbitrary classes.
  3. Use an allowlist of permitted types if object serialization is unavoidable.
  4. Authenticate serialized messages with a modern integrity mechanism; encryption alone does not guarantee authenticity.
  5. Reject unexpected fields, excessive nesting, oversized collections, and invalid types.
  6. Keep libraries and runtimes patched and remove unused gadget-producing dependencies.
  7. Never assume that base64 encoding makes data trustworthy; base64 provides representation, not confidentiality or integrity.

Signed or authenticated data must also be checked for freshness where replay is relevant. A valid old message may still be dangerous if it authorizes a previously valid action. Use timestamps, nonces, sequence numbers, or server-side state as appropriate.

4. File and Path Attacks

Files create several distinct attack surfaces: names and paths, content parsing, storage location, permissions, and resource consumption.

Path traversal

Path traversal occurs when an attacker causes a file operation to escape its intended directory, often using sequences such as ../, alternative separators, encoded forms, or platform-specific path syntax. A naïve check for the substring .. is insufficient because normalization and decoding rules vary.

A safer pattern is to avoid accepting paths at all. Give the client an opaque file identifier, retrieve the corresponding server-side record, and resolve a trusted storage path. If a relative path is genuinely required:

  1. Decode and normalize according to the platform’s rules.
  2. Resolve the candidate path against a fixed base directory.
  3. Confirm that the resolved path remains within the intended directory.
  4. Reject symbolic links or use a file API that safely confines resolution.
  5. Apply authorization to the file record, not merely to the path.

Conceptually, if B is the trusted base directory and C is the candidate path, the resolved path R = resolve(B, C) is acceptable only if R is inside B according to the operating system’s canonical path semantics. String-prefix tests are unsafe: /srv/app-data-evil may appear to begin with /srv/app-data while being outside the intended directory.

Upload security

File-extension checks alone are weak because extensions can be changed and content may be polyglot or malformed. A robust upload process should:

  • enforce size, count, and rate limits;
  • allow only required media types;
  • inspect file signatures where appropriate;
  • parse and re-encode images or documents using safe libraries when feasible;
  • generate a server-side filename;
  • store files outside the web root or behind an authenticated download handler;
  • prevent execution by storage configuration and operating-system permissions;
  • scan content where the threat model requires it;
  • remove metadata when privacy is important;
  • associate the file with an owner and authorization policy.

A file parser is itself an attack surface. Run high-risk parsers with minimal privileges, resource limits, and process isolation.

Archive extraction

Archive extraction can enable path traversal, symbolic-link attacks, and decompression bombs. Before extraction, inspect every entry, normalize its path, reject absolute paths and traversal, control symbolic links, and enforce limits on the number and expanded size of files. The archive’s compressed size is not a sufficient resource limit.

5. Server-Side Request Forgery

Server-side request forgery, or SSRF, occurs when an attacker influences a server into making a network request to an unintended destination. The vulnerable server may reach internal administration interfaces, cloud metadata services, loopback services, or other protected network segments that the attacker cannot access directly.

A common unsafe pattern is:

response = httpClient.get(request.query["url"])

The application may appear to be a harmless URL preview service, but the destination is attacker-controlled.

SSRF defenses

The strongest design is to avoid arbitrary outbound destinations. Use a server-side identifier mapped to a fixed destination or an allowlist of approved schemes, hosts, ports, and paths. Other controls include:

  • allow only HTTP or HTTPS when required;
  • reject credentials, unusual schemes, and unsupported ports;
  • resolve DNS and validate the resulting addresses;
  • block loopback, link-local, private, multicast, and other prohibited ranges according to the deployment environment;
  • re-check connections after redirects and DNS changes;
  • disable or tightly control redirects;
  • set connection, response-size, and total-time limits;
  • use egress firewalls and network segmentation;
  • place cloud metadata services behind authenticated, hardened access mechanisms;
  • avoid returning complete upstream responses to the user.

DNS validation is subtle. A hostname may resolve to a permitted address during validation and to a private address when the connection is made, or it may have multiple answers. Network-level egress controls are therefore an important second layer. SSRF prevention is not achieved by checking only whether a URL string begins with an approved prefix.

6. Operating-System Command Execution

Command injection occurs when untrusted input reaches a shell or command interpreter. For example:

command = "convert " + userFilename + " output.png"
executeShell(command)

Shell metacharacters, argument substitution, redirection, and platform-specific syntax may alter execution.

The preferred defense is to avoid the shell. Use a library API or execute a fixed binary with an argument array:

process.start(
    executable = "/usr/bin/convert",
    arguments = [inputPath, "/srv/output/output.png"],
    environment = minimalEnvironment,
    timeout = 10 seconds
)

The executable should be fixed, arguments should be typed or allowlisted, and the working directory should be controlled. If shell execution is unavoidable, use a carefully designed API that separates arguments from the command and apply platform-specific escaping; do not regard escaping as a complete substitute for avoiding the shell.

Process isolation is essential for high-risk operations. Use a dedicated low-privilege account, read-only mounts where possible, restricted filesystem access, network egress controls, CPU and memory limits, timeouts, and a disposable container or sandbox. Isolation reduces impact but does not repair vulnerable code; a sandbox escape or excessive permission can still be consequential.

7. Business-Logic Abuse

Business-logic vulnerabilities do not necessarily involve a parser or memory error. They exploit a valid sequence of operations to obtain an outcome that violates the system’s intended rules.

Examples include:

  • applying a discount repeatedly when it should be single-use;
  • changing the price between checkout and payment;
  • redeeming the same voucher concurrently;
  • cancelling an order after receiving a refund;
  • transferring more money than the account balance;
  • modifying another user’s object by changing an identifier;
  • bypassing a step in an approval workflow;
  • submitting a negative quantity or an unexpectedly large quantity;
  • abusing password-reset or invitation workflows at scale.

Modeling business rules

Start with assets, actors, state transitions, and invariants. An invariant is a property that must remain true after every permitted operation. Examples are:

  • an order total is calculated from server-side product and quantity data;
  • a refund cannot exceed the captured payment;
  • a voucher redemption count cannot exceed its permitted maximum;
  • a user can modify only resources within the user’s authorization scope;
  • a state transition must follow the approved workflow.

Security checks should be performed transactionally. A read-then-update sequence can suffer a race condition if two requests observe the same balance or redemption count. Use database transactions, row locks, atomic conditional updates, idempotency keys, or unique constraints as appropriate. For example, a redemption operation can atomically update a record only when used_count < limit, rather than checking the condition in one transaction and updating it later.

Rate limits, quotas, fraud detection, step-up authentication, and human review are complementary controls. They are not substitutes for correct authorization and state management.

8. Unsafe Error Handling and Logging

Errors are necessary for diagnosis, but responses can disclose stack traces, source paths, SQL statements, tokens, internal hostnames, dependency versions, or personal data. Detailed errors also help attackers refine probes.

A secure error architecture separates audiences:

  • Client response: a stable error code, suitable status code, and concise message.
  • Server log: diagnostic context, correlation identifier, endpoint, actor, timestamp, and sanitized technical details.
  • Operations channel: alerting and aggregated evidence for high-risk events.

Do not place passwords, session tokens, authorization headers, payment data, or unnecessary personal information in logs. Apply access control, retention limits, integrity protection, and secure transmission to logs. Log injection must also be considered: attacker-controlled values should be structured and encoded so that newlines or control characters cannot forge records.

Error handling should fail closed. A failed authorization lookup should not become permission granted. A payment timeout should not be interpreted as successful payment. A parser failure should not trigger a permissive fallback. Generic client responses should not hide the need for internal alerting and investigation.

Appropriate HTTP status codes communicate broad outcomes without revealing implementation details. For example, unauthorized access may use 401 when authentication is required and 403 when the server understands the identity but refuses the action. Applications may deliberately use a uniform response for resource lookup failures to reduce identifier enumeration, provided this is consistent with the product’s usability and monitoring needs.

9. A Secure Server-Side Development Process

Security is most effective when built into the development lifecycle.

Threat modeling

For each feature, identify assets, entry points, trust boundaries, privileged operations, data flows, and abuse cases. STRIDE can help classify spoofing, tampering, repudiation, information disclosure, denial of service, and elevation of privilege. Abuse-case analysis is particularly useful for business workflows.

Defensive implementation

Use framework security mechanisms, dependency pinning and updates, secure configuration, centralized authorization, typed request schemas, prepared statements, safe file APIs, and standard cryptographic libraries. Avoid custom cryptography and custom security protocols unless reviewed by specialists.

Verification

Testing should include:

  • unit tests for validators and authorization policies;
  • integration tests for database and file boundaries;
  • negative tests with malformed and oversized input;
  • concurrency tests for redemption, payment, and inventory operations;
  • static analysis and dependency scanning;
  • dynamic application testing;
  • fuzzing of parsers and structured inputs;
  • manual penetration testing for high-risk workflows;
  • review of infrastructure egress and privilege settings.

Security tests should assert both rejection and safe side effects. It is not enough that a malicious request returns an error if it has already created a file, changed a balance, or triggered an outbound request.

Illustrative Case: Insecure Document Preview Service

Background

A fictional company, Northstar Legal, provides a document portal. Users upload documents and request a preview. The original implementation stores the client-supplied filename, constructs a shell command to convert documents, and accepts a URL parameter for importing documents from partner systems.

Problem

A security review identifies four risks. The filename can influence a shell command. The upload directory is served directly by the web server. The import function accepts arbitrary URLs, creating SSRF. Finally, detailed conversion errors are returned to users and include local paths.

Analysis

The service combines untrusted data with three interpreters or privileged operations: a shell, a file system, and an HTTP client. The web server’s ability to serve uploaded content increases the impact of a malicious file. The import feature allows the application network position to be abused. Error responses expose information useful for further attacks.

Approach and solution

Northstar replaces filenames with random server-generated identifiers and stores files outside the web root. Uploads are limited by size and type, parsed in an isolated worker, and re-encoded into a safe preview format. Conversion uses a fixed executable and argument-array API under a low-privilege account with a timeout and no unnecessary network access.

The import feature is redesigned around registered partner identifiers rather than arbitrary URLs. A server-side mapping defines approved hosts and paths. Egress filtering blocks private and metadata address ranges, and redirects are disabled. Authorization is checked before both import and download. Client errors now contain a correlation ID and generic message; detailed diagnostics are kept in protected structured logs.

Outcome

The redesign removes arbitrary shell interpretation, reduces file execution risk, limits outbound destinations, and prevents routine disclosure of internal paths. It also improves operational visibility because conversion failures and blocked outbound requests are measurable events.

Learning points

The case demonstrates that no single input check would have solved the problem. Secure behavior required data-instruction separation, controlled storage, least privilege, network restrictions, authorization, resource limits, and audience-appropriate errors.

Challenges, Limitations, and Governance

No defense is absolute. Allowlists may become outdated, URL validation is complicated by DNS and redirects, sandboxing depends on correct configuration, and parsers can contain unknown vulnerabilities. Security controls should therefore be layered and periodically reviewed.

Organizations should define ownership for security patches, secrets, logging, incident response, and access reviews. Privacy principles require collecting and retaining only data needed for the service. Security monitoring must be proportionate and governed; logs should not become an uncontrolled repository of personal information.

Regulatory obligations vary by sector and jurisdiction, but common expectations include protection of personal data, reasonable access control, incident response, secure development, and evidence of risk management. Technical controls should be mapped to organizational requirements rather than adopted as isolated checklists.

Artificial intelligence can assist with code review, anomaly detection, test generation, and log analysis, but generated code may introduce injection, authorization, or data-leakage defects. AI systems that process confidential source code or production logs also create disclosure risks. Human review, controlled data handling, reproducible testing, and explicit security requirements remain necessary.

Best-Practice Checklist

  • Treat every request value and external response as untrusted.
  • Use typed schemas, length limits, range checks, and allowlists.
  • Use parameterized queries and safe interpreter APIs.
  • Avoid arbitrary deserialization and general-purpose evaluation.
  • Resolve files safely and store uploads outside executable web locations.
  • Restrict archive extraction and parser resources.
  • Avoid arbitrary outbound requests; enforce application and network allowlists.
  • Avoid shells; if processes are required, use fixed executables and argument arrays.
  • Apply least privilege and isolate risky workers.
  • Enforce authorization on every sensitive operation and resource.
  • Make state-changing operations atomic and idempotent where appropriate.
  • Return generic client errors and protect detailed logs.
  • Test negative cases, races, resource exhaustion, and side effects.
  • Monitor, patch, review, and rehearse incident response.

Chapter Summary

Server-side security is fundamentally about controlling how untrusted data crosses boundaries into interpreters, filesystems, networks, processes, and business workflows. Parameterized queries separate SQL instructions from values; safe parser and serialization choices prevent unexpected object behavior; canonical path handling and controlled storage reduce file attacks; fixed destinations, DNS-aware validation, and egress controls mitigate SSRF; and argument-based process APIs reduce command injection.

Business-logic security requires explicit authorization, state-transition analysis, invariants, atomic operations, and controls against replay and concurrency. Error handling should provide useful diagnostics to authorized operators without disclosing implementation details to clients. Across all categories, validation, least privilege, isolation, resource limits, monitoring, and layered testing work together. Secure coding is therefore not a collection of isolated filters but a disciplined method for designing trustworthy boundaries and limiting failure impact.

Key Terms

Trust boundary: A point where data or authority passes between components with different security assumptions.

Input validation: Checking whether data conforms to an expected type, structure, range, or business rule.

Parameterization: Supplying data separately from an interpreter’s instructions.

SQL injection: Manipulation of a database query through untrusted input.

Command injection: Manipulation of an operating-system command or shell through untrusted input.

Insecure deserialization: Unsafe reconstruction of attacker-controlled serialized data.

Path traversal: Escaping an intended directory through crafted path input.

Canonicalization: Converting a path or representation into a normalized form for reliable comparison.

SSRF: Causing a server to make an unintended request to a network destination.

Egress control: Restricting outbound network connections from a system.

Least privilege: Granting only the permissions required for a task.

Isolation: Separating a component so that compromise has limited consequences.

Business-logic vulnerability: Abuse of valid functions or workflows to violate intended rules.

Invariant: A property that must remain true after permitted operations.

Idempotency: A property whereby repeating an operation produces the same intended result as performing it once.

Fail closed: Denying access or operation when a security decision cannot be safely completed.

Correlation identifier: A value used to connect a client-facing error with protected server-side diagnostics.

Allowlist: An explicit collection of permitted values or behaviors.

Review Questions

5 Short Answer Questions

  1. Why is client-side validation insufficient for protecting a server-side application?
  2. What distinction exists between validation and parameterization?
  3. Why does base64 encoding not make serialized data trustworthy?
  4. Name two risks associated with archive extraction.
  5. What information should generally be excluded from application logs?

5 Long Answer Questions

  1. Explain SQL injection and compare parameterized queries with escaping as defensive techniques.
  2. Describe a secure design for file uploads, including storage, naming, parsing, authorization, and resource limits.
  3. Explain how SSRF works and why URL-string prefix checks are insufficient.
  4. Discuss how least privilege and isolation reduce the impact of command execution vulnerabilities.
  5. Explain how error responses, structured logging, and fail-closed behavior should work together.

3 Analytical / Application Questions

  1. An online store checks whether a voucher has remaining uses, then increments the usage count in a separate database operation. Analyze the race condition and propose a transactional design.
  2. A document service accepts a user URL, follows redirects, resolves DNS, and returns the fetched content. Identify at least four SSRF risks and design layered mitigations.
  3. A web application allows users to download /files/ plus a client-supplied filename. Develop a secure replacement design and justify how it handles authorization, path traversal, symbolic links, and error disclosure.

Multiple Choice Questions with Answers

Question 1

Which control most directly prevents SQL syntax from being interpreted as part of a user-supplied value?

A. Client-side length validation

B. Parameterized queries

C. Detailed error messages

D. Base64 encoding

Correct Answer: B. Parameterized queries

Question 2

Why is arbitrary object deserialization dangerous?

A. It always reduces network bandwidth

B. It can invoke unexpected classes or methods during reconstruction

C. It prevents all input validation

D. It guarantees that data is encrypted

Correct Answer: B. It can invoke unexpected classes or methods during reconstruction

Question 3

Which design is safest for downloading a user’s stored file?

A. Concatenate the supplied filename with a public directory path

B. Reject only filenames containing the literal string ..

C. Use an opaque file identifier, authorize ownership, and resolve a trusted storage path

D. Allow any path after URL decoding once

Correct Answer: C. Use an opaque file identifier, authorize ownership, and resolve a trusted storage path

Question 4

What is the primary security concern in SSRF?

A. The browser executes too much JavaScript

B. The server is induced to access unintended network destinations

C. The database automatically loses indexes

D. The user cannot upload a file

Correct Answer: B. The server is induced to access unintended network destinations

Question 5

Which approach best reduces command-injection risk when an external utility is required?

A. Concatenate all arguments into a shell string

B. Use a fixed executable with a separate argument array

C. Return the command in the error response

D. Encode the command with base64 before execution

Correct Answer: B. Use a fixed executable with a separate argument array

Question 6

Which statement about authorization is correct?

A. Hiding an administrative button is sufficient authorization

B. Authorization should be enforced by the server at the sensitive operation

C. Authentication automatically grants access to all user-supplied resources

D. Authorization is needed only for anonymous users

Correct Answer: B. Authorization should be enforced by the server at the sensitive operation

Question 7

Which is an example of a business-logic vulnerability?

A. A missing semicolon in a source file

B. A user redeeming a single-use voucher multiple times through concurrent requests

C. A slow but valid database index

D. A browser caching a stylesheet

Correct Answer: B. A user redeeming a single-use voucher multiple times through concurrent requests

Question 8

What does fail-closed behavior mean?

A. Granting access when an authorization service is unavailable

B. Returning a stack trace for every error

C. Denying the operation when a security decision cannot be safely completed

D. Deleting all audit logs after a failure

Correct Answer: C. Denying the operation when a security decision cannot be safely completed

Question 9

Which item should generally not be written to ordinary application logs?

A. A correlation identifier

B. An endpoint name

C. A session token

D. A timestamp

Correct Answer: C. A session token

Question 10

Why are network egress controls useful against SSRF?

A. They prevent all malformed HTML

B. They provide a second layer that can block prohibited destinations even if application validation fails

C. They replace the need for authorization

D. They make DNS unnecessary

Correct Answer: B. They provide a second layer that can block prohibited destinations even if application validation fails

Web Security & Performance Optimization
Chapter 6 of 15