Least Privilege: Separate database users per application
Use different database users for different web applications instead of the same owner/admin account. Each separate web application requiring database access should have a designated database user account. This provides good granularity in access control and reduces privileges as much as possible. For example, a login page needs only select access to username and password fields, while a sign-up page needs insert privilege - different DB users can enforce this restriction.
Least Privilege: Use SQL views to enhance granularity
Use SQL views to limit read access to specific fields of a table or joins of tables. For example, if the system must store unhashed passwords, revoke all access to the password table (except owner/admin) and create a view that outputs the hash of the password field instead of the field itself. Any successful SQL injection will be restricted to stealing the hashed passwords since no application DB user has access to the table itself.
Input validation as secondary defense for SQL injection
Input validation can be a secondary defense used to detect unauthorized input before it is passed to the SQL query, even when primary defenses like prepared statements are used. However, validated data is not necessarily safe to insert into SQL queries via string building. Refer to the Input Validation Cheat Sheet for more details.
Dynamic SQL in stored procedures requires auditing
When dynamic SQL must be generated inside stored procedures, auditors should look for uses of sp_execute, execute, or exec within SQL Server stored procedures. The stored procedure must use input validation or proper escaping to prevent injection of malicious SQL code. This practice should be avoided when possible.
Input validation for SAML implementations
Just because SAML is a security protocol does not mean that input validation goes away. Ensure that all SAML providers and consumers perform proper input validation.
AuthnRequest required data elements
An AuthnRequest must contain an ID and SP identifier. The ID is a string uniquely identifying the request, and SP identifies the Service Provider that initiated the request. The request ID attribute must be returned in the response as InResponseTo="<requestId>" to guarantee authenticity of the response from the trusted IdP.
SAML Response required data elements
A SAML Response must contain: ID (string uniquely identifying the response), SP (identifies the recipient of the response), IdP (identifies the identity provider authorizing the response), and {AA} K -1/IdP (the assertion digitally signed with the private key of the IdP).
XML schema validation before SAML processing
Always perform schema validation on the XML document prior to using it for any security-related purposes. Always use local, trusted copies of schemas for validation. Never allow automatic download of schemas from third party locations. If possible, inspect schemas and perform schema hardening to disable possible wildcard type or relaxed processing statements.
Absolute XPath expressions for SAML XML signature validation
Never use getElementsByTagName to select security related elements in an XML document without prior validation. Always use absolute XPath expressions to select elements, unless a hardened schema is used for validation. This avoids signature-wrapping attacks.
RelayState parameter validation in IdP-initiated SSO
If the contract of the RelayState parameter is a URL, make sure the URL is validated and explicitly on an allowlist. This counters open redirect attacks in IdP-initiated SSO flows.
SP Destination attribute validation
Validate the Destination attribute on <samlp:Response> exactly matches the SP's expected Assertion Consumer Service (ACS) URL as specified in SAML Core 2.0 §3.2.2.1. Reject responses that are missing Destination or where it does not match. This prevents cross-SP assertion replay attacks.
SP Audience validation
Validate that <saml:Audience> in the SAML Response matches the SP's EntityID.
SP NotBefore and NotOnOrAfter validation
Service Providers must validate NotBefore and NotOnOrAfter timestamp attributes in SAML assertions.
SP SubjectConfirmationData validation
Service Providers must validate the Recipient attribute, InResponseTo, and <saml:SubjectConfirmationData> which contains Recipient, NotOnOrAfter, and InResponseTo attributes.
SP XML signature Reference URI validation
Service Providers must verify that the <ds:Reference URI> in the XML signature covers the <saml:Assertion> element being trusted. This mitigates XML Signature Wrapping attacks.
AuthAssert required data elements
An authentication assertion within a SAML Response must contain: ID (string uniquely identifying the assertion), C (client identifier), IdP (identity provider identifier), and SP (service provider identifier).
Defense: Use CSS obfuscation tools (JSS minify)
JSS (CSS in JS) provides a `minify` option that generates obfuscated class names such as `.c001`, `.c002` instead of descriptive names, reducing the chance of attackers guessing application features.
Risk: CSS selectors reveal application features to unauthenticated attackers
Motivated attackers examine CSS files from View-Source to learn about application features and roles even without being logged in. Descriptive CSS selector names like `.profileSettings`, `.editUser`, `.addUser`, `.deleteUser` can be mapped to actual features, providing attackers with intelligence for gaining access to sensitive roles.
Risk: Global CSS files with role-based selectors enable feature discovery
Creating a single global CSS file containing styling for all roles (Student, Teacher, Super User, Administrator) with role-specific selectors like `.addUsers`, `.deleteUsers`, `.addNewAdmin`, `.exportUserData` allows attackers to map selectors to features without authentication. This reveals the application's feature set and access control structure.
Defense: Isolate CSS files by access control level
Create separate CSS files for each role or access control level. For example, create `StudentStyling.CSS` for Student role and `AdministratorStyling.CSS` for Administrator role. Ensure these CSS files are only accessible to authenticated users with the proper access control level. If an authenticated user attempts to access a CSS file for a higher privilege level through forced browsing, log and alert on the potential intrusion attempt.
Defense: Obfuscate CSS class names and selectors
Remove identifying information from CSS files by using non-descriptive, obfuscated class names and selectors. Instead of `.addUserButton`, use selectors like `#page_u header button:first-of-type`. Write CSS rules that apply across multiple pages to reduce the need for specific selectors. Use build-time and runtime tools to automatically obfuscate class names.
Defense: Use CSS obfuscation tools (CSS Modules)
CSS Modules provides `modules` and `localIdentName` options to generate obfuscated class names, functioning similarly to JSS but allowing import of any CSS file without major structural changes to the application.
Defense: Use .Net Blazor CSS Isolation
.Net Blazor CSS Isolation scopes CSS to the component it is used in and results in obfuscated selectors like `button.add[b-3xxtam6d07]`, preventing feature discovery through CSS inspection.
Defense: Use CSS utility frameworks to reduce specific selectors
CSS libraries such as Bootstrap and Tailwind reduce the need for specific, descriptive CSS selectors by providing a strong base theme to work from, making it harder for attackers to map selectors to features.
Risk: Malicious CSS in user-authored HTML enables clickjacking
Web applications that allow users to author content via HTML input are vulnerable to malicious use of CSS. Attackers can upload HTML with crafted CSS styles that exploit allowed styling to perform clickjacking attacks, causing page clicks to navigate to malicious websites. Example: LinkedIn had a vulnerability where malicious CSS was used to hijack page clicks.
Sanitization definition and security context
Sanitization is the process of cleaning or filtering input by removing, replacing, or modifying potentially dangerous characters or content to make dirty input clean according to a security policy. Examples include stripping <script> tags from HTML input and removing special characters from filenames. Sanitization should be used as a secondary defense; parameterized queries or output escaping are preferred where possible.
Encoding definition and purpose
Encoding transforms data into a different format using a publicly available scheme so that it can be safely consumed by a different system. Encoding is for data usability and compatibility, not for security. Encoding is always reversible. Examples include Base64, URL Encoding, and HTML Entity Encoding. Using the wrong encoding can lead to vulnerabilities, but encoding itself is not a security control.
Escaping definition and security purpose
Escaping is a sub-type of encoding where specific characters are prefixed with a signal character (like a backslash) to prevent them from being misinterpreted by a parser as control characters. Escaping ensures the interpreter treats the data as text rather than code or commands. Examples include \' in SQL, \n in strings, and < in HTML. Escaping is essential for preventing injection attacks including XSS and SQL injection.
Serialization definition and insecure deserialization risk
Serialization converts an object or data structure into a format that can be stored or transmitted, such as a byte stream, and later reconstructed. The security context is that insecure deserialization occurs when untrusted data is used to reconstruct an object, potentially leading to Remote Code Execution (RCE).
Python Lambda input validation example with email regex
Example Python Lambda handler with email validation: parse the event body as JSON, extract the email field, validate it against the regex pattern [^@]+@[^@]+\.[^@]+ (basic email format), return HTTP 400 with "Invalid email" if validation fails, otherwise process safely and return HTTP 200.
Event data validation for serverless: treat payloads as untrusted, validate input, sanitize, protect against injection
Treat all event payloads as untrusted input. Apply strong input validation and sanitization covering length, type, and format. Protect against common injection attacks including SQL injection, XSS, JSON injection, and deserialization attacks. Strip unnecessary fields and metadata before processing.
Command injection via unescaped exec() function
Using the exec() function with unescaped user input creates a command injection vulnerability. Example vulnerability: exec(sprintf('rm %s', $filename)); where $filename comes from user input. An attacker could provide 'test.txt && rm -rf .' to execute arbitrary commands.
Command injection mitigation using native PHP functions
To prevent command injection, use native PHP filesystem functions like unlink() or Symfony Filesystem Component remove() method instead of exec(). These functions do not execute shell commands and are safer for file operations.
Open redirection vulnerability from unvalidated redirect parameter
Open redirection occurs when an application redirects users to a URL from an unvalidated query parameter. Example vulnerability: $this->redirect($url) where $url comes from user input. Attackers can craft malicious URLs to redirect unsuspecting users to malicious sites.
File upload validation with File constraint maxSize and mimeTypes
Validate file uploads server-side using Symfony's File constraint. Configuration options: 'maxSize' (maximum file size, e.g., '1024k' for 1 MB), 'mimeTypes' (array of allowed MIME types, e.g., ['application/pdf', 'application/x-pdf']).
File upload validation with PHP Attributes example
Use PHP Attributes to validate uploaded files. Example: #[File(maxSize: '1024k', mimeTypes: ['application/pdf', 'application/x-pdf'])] on the UploadedFile property. This validates file size and MIME type at the DTO level.
File upload validation with Symfony Form example
Use Symfony Form to validate file uploads with the File constraint. Add 'file' field with FileType::class and include File constraint with 'maxSize' and 'mimeTypes' options in the constraints array.
Secure file upload storage location
Store uploaded files outside the public directory to prevent direct access. If using the public directory, configure the web server to deny access to the upload directory.
Directory traversal protection using realpath validation
Protect against directory traversal by validating the absolute path of requested files. Use PHP realpath() function to resolve the actual path and verify it starts with the storage directory. Example: $realBase = realpath($storagePath); $realPath = realpath($filePath); if ($realPath === false || !str_starts_with($realPath, $realBase)) { // Directory Traversal! }
Use unique filenames for uploaded files
Ensure each uploaded file has a unique name to prevent overwriting existing files. Combine a unique identifier with the original filename to generate a unique name.
Directory traversal protection using basename
Strip directory information from filename input using PHP basename() function to prevent directory traversal attacks. Example: $filePath = $storagePath . '/' . basename($filename);
Cart data validation before payment gateway order creation
All cart details including product IDs, prices, and discounts must be validated on the backend before sending to the payment gateway. Totals must be recalculated server-side using trusted data before order creation to prevent price tampering or product substitution via client-side manipulation.
Block List ModSecurity Virtual Patch Example
Example block list ModSecurity virtual patch for SQL injection. For the PoC payload `http://localhost/wordpress/wp-content/plugins/levelfourstorefront/scripts/administration/exportsubscribers.php?reqID=1' or 1='1`, which inserts a single quote character and adds additional SQL query logic, the virtual patch can disallow the single quote character:
```
SecRule REQUEST_URI "@contains /wp-content/plugins/levelfourstorefront/scripts/administration/exportsubscribers.php" "chain,id:1,phase:2,t:none,t:Utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase,block,msg:'Input Validation Error for \'reqID\' parameter.',logdata:'%{args.reqid}'"
SecRule ARGS:/reqID/ "@pm '"
```
Positive Security Model Virtual Patching
Positive security model (allowlist) is a comprehensive security mechanism that provides an independent input validation envelope to an application. The model specifies the characteristics of valid input (character set, length, etc.) and denies anything that does not conform. By defining rules for every parameter in every page, the application is protected by an additional security envelope independent from its code. This approach is recommended as it provides better protection than negative security.
Allow List ModSecurity Virtual Patch Example for SQL Injection
Example virtual patch for WordPress Shopping Cart Plugin SQL injection vulnerability in reqID parameter:
```
##
## Verify we only receive 1 parameter called "reqID"
##
SecRule REQUEST_URI "@contains /wp-content/plugins/levelfourstorefront/scripts/administration/exportsubscribers.php" "chain,id:1,phase:2,t:none,t:Utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase,block,msg:'Input Validation Error for \'reqID\' parameter - Duplicate Parameters Names Seen.',logdata:'%{matched_var}'"
SecRule &ARGS:/reqID/ "!@eq 1"
##
## Verify reqID's payload only contains integers
##
SecRule REQUEST_URI "@contains /wp-content/plugins/levelfourstorefront/scripts/administration/exportsubscribers.php" "chain,id:2,phase:2,t:none,t:Utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase,block,msg:'Input Validation Error for \'reqID\' parameter.',logdata:'%{args.reqid}'"
SecRule ARGS:/reqID/ "!@rx ^[0-9]+$"
```
This virtual patch inspects the reqID parameter value on the specified page and prevents any characters other than integers as input. Assign rule IDs properly and track them in the bug tracking system.
Negative Security Model Virtual Patching
Negative security model (denylist) is based on a set of rules that detect specific known attacks rather than allowing only valid traffic. Negative security rules can usually be implemented more quickly than positive security rules, however the possible evasions are more likely.
Positive vs Negative Security Model Considerations
Positive security rules provide better protection but are often a manual process and thus not scalable and difficult to maintain for large or dynamic sites. Negative security rules can be implemented more quickly but have higher likelihood of evasions. While manual positive security rules for an entire site may not be feasible, a positive security model can be selectively employed when a vulnerability alert identifies a specific location with a problem.
Exploit-Specific Virtual Patches Pitfall
Avoid creating exploit-specific virtual patches that block only the exact payload used in an attack. For example, if an XSS vulnerability identified in testing used payload `<script>alert('XSS Test')</script>`, creating a patch that simply blocks that exact payload may provide immediate protection but its long term value is significantly decreased. Attackers can easily modify payloads to bypass exploit-specific patches.
WebSocket input validation message structure JSON schema
Treat all WebSocket messages as untrusted input. Validate message structure and content using JSON schemas and allow-lists. Set reasonable size limits (typically 64KB or less) and implement rate limiting to prevent message flooding.
WebSocket binary data validation magic numbers file type
For binary data, verify file types using magic numbers rather than trusting content-type headers. Scan uploads for malware when appropriate, and use safe deserialization for protocols like protobuf or MessagePack.
WebSocket message replay attack prevention nonce timestamp
To prevent message replay attacks, include timestamps or nonces in messages and reject duplicates to ensure old messages cannot be maliciously resent. Example: ws.on('message', (data) => { const message = JSON.parse(data); if (!isValidNonce(message.nonce)) { ws.close(1008, 'Replay detected'); return; } });
WebSocket JSON parsing use JSON.parse not eval
Always use JSON.parse() instead of eval() for JSON processing. eval() enables code execution from untrusted input. Safe: const message = JSON.parse(data); Dangerous: const message = eval('(' + data + ')');
Enforce consistent SOAP encoding style
The same encoding style must be enforced between the SOAP client and the server.
SOAP payload validation against XSD
Web services must validate SOAP payloads against their associated XML schema definition (XSD).
XSD maximum length and character set definition
The XSD defined for a SOAP web service should, at a minimum, define the maximum length and character set of every parameter allowed to pass into and out of the web service.
XSD strong validation patterns for fixed format parameters
The XSD defined for a SOAP web service should define strong (ideally allow-list) validation patterns for all fixed format parameters such as zip codes, phone numbers, list values, etc.
XML content validation requirements
Content validation for XML input should include: validation against malformed XML entities, validation against XML Bomb attacks, validating inputs using a strong allowlist, and validating against external entity attacks (XXE).
Inline virus scanning for SOAP attachments
Ensure Virus Scanning technology is installed and preferably inline so files and attachments could be checked before being saved on disk.
XML DoS protection against entity expansion
Protection against XML entity expansion is required to protect against XML Denial of Service attacks.
XML DoS protection against overlong element names
Validating against overlong element names is required to protect against XML Denial of Service attacks. If working with SOAP-based Web Services, the element names are the SOAP Actions.