Session cookies as bearer tokens vs sender-constrained tokens
The fundamental problem with session cookies is they are 'Bearer Tokens' accepted without checking who sent them; servers only validate that the values are valid. To solve cookie theft, session cookies should be made 'Sender Constrained Tokens' that verify ownership.
Cookie theft impact equivalent to credential theft
Stealing a valid session cookie has the same impact as stealing authentication credentials until the cookie expires. Even with robust authentication processes like 2FA or Passkeys, a stolen session cookie enables full session hijacking for the duration of the session lifetime.
Device Bound Session Credentials API for cookie theft mitigation
The Device Bound Session Credentials API combines public key encryption with owner verification of session cookies. It verifies ownership using a private key generated and kept secret internally by the browser. Even if a session cookie is stolen, an attacker cannot impersonate the user without also stealing the browser's private key. This specification is still in drafting stages but is considered a future solution to cookie theft attacks.
Session validation options for suspected cookie theft
If a session hijacking is suspected, options include: (1) re-authenticate the user by temporarily invalidating the session and issuing a new session cookie, which is the most reliable method; (2) use CAPTCHA or similar challenge as an alternative that is useful against bots; (3) as a compromise, display CAPTCHA for normal browsing but require re-authentication before accessing confidential information or performing actions with side effects.
False positives and negatives in cookie theft detection
Cookie theft detection based on environment changes has limitations: False Positives occur when legitimate user travel or network changes trigger alerts; False Negatives occur when attackers operate from the same country or network as the user. Simple value comparison is insufficient; the detection must consider whether the meaning of changed values has changed significantly.
Middleware pattern for cookie theft detection
Cookie theft detection is typically implemented as middleware that checks session information (like IP address and User-Agent) against stored session values before allowing requests to proceed. The middleware can use helper functions like checkGeoIPRange() and checkUserAgent() to determine if changes indicate hijacking. For performance optimization, detection can be tuned by priority, checking only endpoints that view or modify important information intensively.
Cookie theft detection as primary mitigation strategy
Since cookie theft is generally carried out directly against users through malware or phishing attacks, the only effective countermeasure a service can implement is to detect as quickly as possible when a stolen cookie is used. Detection of theft in use is more practical than preventing the initial theft.
Sec-Fetch-* and sec-ch-ua headers for session monitoring
Recent browsers send sec-ch-ua and related headers (sec-ch-prefers-color-scheme, sec-ch-ua-arch, sec-ch-ua-bitness, sec-ch-ua-form-factors, sec-ch-ua-full-version, sec-ch-ua-full-version-list, sec-ch-ua-mobile, sec-ch-ua-model, sec-ch-ua-platform, sec-ch-ua-platform-version, sec-ch-ua-wow64) that provide browsing context information. These headers can be used as reference for detecting cookie theft but should not be relied upon, as not every browser sends them and they are not always sent even when supported.
Session cookie core information to save for theft detection
When a session is established on the server, save the following core information in association with the session: IP Address, User-Agent, Accept-Language, and Date. This information should be compared on each request to detect if the user environment has changed significantly.
Cookie theft detection vectors
Multiple vectors can be used to detect that a user environment has changed when a stolen cookie is used: access from different region (IP Address), access from different device (User-Agent), access from different language setting (Accept-Language), and access at different time of day (Date).
Additional headers to monitor for cookie theft detection
In addition to core session information (IP, User-Agent, Accept-Language, Date), also monitor these headers which can change depending on Device and OS: Accept and Accept-Encoding.
DEFAULT_AUTHENTICATION_CLASSES setting
DEFAULT_AUTHENTICATION_CLASSES is a list of authentication classes used by default to identify which user is authenticated by accessing request.user or request.auth properties. The classes are 'rest_framework.authentication.SessionAuthentication' for session authentication and 'rest_framework.authentication.BasicAuthentication' for basic authentication.
SQL Injection prevention - use parametrized queries
To prevent SQL injection, use parametrized queries. Be careful when using dangerous methods like raw(), extra(), and custom SQL via cursor.execute(). Do not add user input to these dangerous methods.
Insufficient Logging and Monitoring - what to log
Log all failed authentication attempts, denied access, and input validation errors with sufficient user context to identify suspicious or malicious accounts. Create logs in a format suited for log management solutions with enough detail to identify the malicious actor. Create logs that include stack trace, error message, and user ID who caused the error.
Security Misconfiguration - validate client data
Validate, filter, and sanitize all client-provided data and other data coming from integrated systems to prevent security misconfiguration.
Mass Assignment - use Meta.fields allowlist
To prevent mass assignment vulnerabilities, use Meta.fields with an allowlist approach when using ModelForms. Do not use Meta.exclude (denylist approach) or ModelForms.Meta.fields = '__all__'.
Broken Function Level Authorization - change DEFAULT_PERMISSION_CLASSES
To stop broken function level authorization, change the default value of DEFAULT_PERMISSION_CLASSES from 'rest_framework.permissions.AllowAny'. Use the correct permission classes for your project. Do not use AllowAny except for public API endpoints and do not overwrite the permission_classes variable on class-based views or the @permission_classes decorator on function-based views unless confident about the change and its impact.
Dependencies update process
Establish a process for updating dependencies with three mechanisms: general updates every month or quarter, weekly consideration of important security vulnerabilities that may trigger updates, and exceptional emergency updates when needed. When considering libraries, evaluate their security health including update frequency, known vulnerabilities, and active community support.
Broken User Authentication - use DEFAULT_AUTHENTICATION_CLASSES
To prevent broken user authentication, use the setting DEFAULT_AUTHENTICATION_CLASSES with the correct classes for your project and have authentication on every non-public API endpoint. Do not overwrite the authentication_classes variable on class-based views or the @authentication_classes decorator on function-based views unless confident about the change and its impact.
Broken Object Level Authorization - check_object_permissions
When using object-level permissions, call the method .check_object_permissions(request, obj) to verify that the object can be accessed by the user. Do not override the get_object() method without checking if the request should have access to that object.
Security Misconfiguration - core settings
Do not use default passwords. Set the Django settings DEBUG and DEBUG_PROPAGATE_EXCEPTIONS to False. Ensure the API can only be accessed by the specified HTTP verbs and disable all other HTTP verbs. Set SECRET_KEY to a random value and never hardcode secrets.
Improper Assets Management - API inventory
Create an inventory of all API hosts documenting the API version, environment (production, staging, test, development), and who should have network access. Document all aspects including authentication, errors, redirects, rate limiting, CORS policy, and endpoints with their parameters, requests, and responses.
DEFAULT_PAGINATION_CLASS disabled by default
DEFAULT_PAGINATION_CLASS specifies the default class to use for queryset pagination. In Django, pagination is disabled by default, which could cause Denial of Service (DoS) problems or attacks if there is a lot of data.
Excessive Data Exposure - use Meta.fields
To prevent excessive data exposure, only display the minimum amount of required information. Review the serializer and information being displayed. If the serializer inherits from ModelSerializer, do not use the exclude Meta property.
DEFAULT_THROTTLE_CLASSES is empty by default
DEFAULT_THROTTLE_CLASSES is a list of throttle classes that determines the default set of throttles checked at the start of a view. By default, there is no throttling in place since the default class is empty.
Lack of Resources and Rate Limiting - configure DEFAULT_THROTTLE_CLASSES
Configure the setting DEFAULT_THROTTLE_CLASSES to prevent lack of resources and rate limiting issues. Do not overwrite the throttle_classes variable on class-based views or the @throttle_classes decorator on function-based views unless confident about the change and its impact. If possible, implement rate limiting with a WAF or similar, with DRF as the last layer of rate limiting.
Secret Management - never hardcode secrets
Secrets should never be hardcoded. The best practice is to use a Secret Manager to store and manage secrets securely.
Remote Code Execution - YAML and pickle handling
To prevent RCE, use Loader=yaml.SafeLoader for YAML files and do not load user-controlled YAML files using the load() method. Do not add user input to dangerous methods (eval(), exec(), execfile()) and do not load user-controlled pickle files, including pandas.read_pickle().
Insufficient Logging and Monitoring - infrastructure monitoring
Configure a monitoring system to continuously monitor infrastructure, network, and API functioning. Use a Security Information and Event Management (SIEM) system to aggregate and manage logs from all components of the API stack and hosts. Configure custom dashboards and alerts to enable detection and timely response to suspicious activities.
Insufficient Logging and Monitoring - log handling
Handle logs as sensitive data with integrity guaranteed at rest and in transit. Do not log sensitive data such as passwords, API tokens, or personally identifiable information (PII).
DEFAULT_PERMISSION_CLASSES default is AllowAny
DEFAULT_PERMISSION_CLASSES defines the default set of permissions that Django checks before a view can be accessed. The default value is 'rest_framework.permissions.AllowAny', which means unless the default permission class is changed, everybody can access every view by default.
Django check_password function for password verification
Use the check_password utility function from django.contrib.auth.hashers to verify a plain-text password against a hashed password from the database. Returns True if passwords match, False otherwise.
Django brute-force attack prevention packages
Use packages like django_ratelimit or django-axes to prevent brute-force attacks on authentication endpoints.
Django SECRET_KEY rotation strategy
Regularly rotate the SECRET_KEY, keeping in mind that rotation can invalidate sessions and password reset tokens. Rotate the key immediately if it ever becomes exposed.
Django SECRET_KEY generation and storage requirements
The SECRET_KEY parameter in settings.py is used for cryptographic signing and must be kept confidential. Generate a key at least 50 characters containing a mix of letters, digits, and symbols using a strong random generator such as get_random_secret_key(). Never hard-code the SECRET_KEY in settings.py or other locations. Store it in environment variables or secrets managers, for example: SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY').
Django make_password function for password hashing
Use the make_password utility function from django.contrib.auth.hashers to hash plain-text passwords before storage. Example: hashed_pwd = make_password('plaintext_password').
Django AUTH_PASSWORD_VALIDATORS configuration
Configure AUTH_PASSWORD_VALIDATORS in settings.py to enforce password policies. Available built-in validators: UserAttributeSimilarityValidator (checks password similarity to user attributes like username, email, first_name, last_name; max_similarity default 0.7), MinimumLengthValidator (min_length default 8), CommonPasswordValidator (checks against common passwords list), and NumericPasswordValidator (rejects all-numeric passwords).
@login_required decorator for view access control
Use the @login_required decorator from django.contrib.auth.decorators to ensure only authenticated users can access a view. Users are redirected to the default login page if not authenticated, or to a custom login URL if specified with @login_required(login_url='/custom-path/').
Django authentication modules to install
Use django.contrib.auth app for user authentication operations such as login, logout, and password change. Include the following modules in INSTALLED_APPS in settings.py: 'django.contrib.auth', 'django.contrib.contenttypes', and 'django.contrib.sessions'.
Django DEBUG mode must be disabled in production
Never run DEBUG = True in production environments. Always ensure the application is never in DEBUG mode when deployed to production.
Windows Native Authentication Plugins for MySQL
MySQL offers Windows Native Authentication Plugins that provide similar functionality to SQL Server's Integrated Authentication, allowing connections using existing Windows accounts.
Database permission granularity levels
Most applications need only SELECT, UPDATE, and DELETE permissions. Avoid using database links or linked servers. Where they are required, use an account that has been granted access to only the minimum databases, tables, and system privileges required. Security-critical applications should apply permissions at more granular levels, including table-level permissions, column-level permissions, row-level permissions, and blocking access to the underlying tables while requiring all access through restricted views.
Principle of least privilege for database accounts
Database user accounts should only have the minimal permissions required for the application to function. Do not use the built-in root, sa, or SYS accounts. Do not grant the account administrative rights over the database instance. The account should only access the specific databases it needs. Development, UAT, and Production environments should all use separate databases and accounts.
Database credentials storage requirements
Database credentials should never be stored in the application source code, especially if unencrypted. Instead, they should be stored in a configuration file that: is outside of the web root; has appropriate permissions so that it can only be read by the required user(s); and is not checked into source code repositories. Where possible, credentials should also be encrypted or otherwise protected using built-in functionality, such as the web.config encryption available in ASP.NET.
Database account connection restrictions
Database accounts should only be able to connect from allowed hosts, which would often be localhost or the address of the application server. The account should not be the owner of the database as this can lead to privilege escalation vulnerabilities.
Windows Integrated Authentication for Microsoft SQL Server
For Microsoft SQL Server, consider using Windows or Integrated-Authentication, which uses existing Windows accounts rather than SQL Server accounts. This removes the requirement to store credentials in the application, as it will connect using the credentials of the Windows user it is running under.
Database account credential requirements
Database accounts should be protected with strong and unique passwords, used by a single application or service, and configured with the minimum permissions required (principle of least privilege). Regular reviews of accounts and permissions should be conducted. User accounts should be removed when an application is decommissioned. Passwords should be changed when staff leave or there is reason to believe they may have been compromised.
Database TLS requirements
The database should be configured to only allow encrypted connections. A trusted digital certificate must be installed on the server. The client application should connect using TLSv1.2 or higher with modern ciphers such as AES-GCM or ChaCha20. The client application must verify that the digital certificate is correct.
Email is a weak authentication factor
Email should not be treated as a strong authentication factor. Treat email as a weak factor. Require multi-factor authentication for sensitive operations. Do not rely on email alone for account security.
MAVLink 2.0 end-to-end encryption
Utilize end-to-end encryption for MAVLink 2.0 communications between drones and ground control stations, either through TLS or DTLS. Tools like ArduPilot and PX4 support MAVLink 2.0 security enhancements.
Firmware signing with rollback protection
Ensure that firmware and configuration updates are signed with cryptographic signatures. Implement rollback protection to prevent attackers from loading older, vulnerable firmware versions. Encrypt firmware packages, especially if they contain sensitive intellectual property.
MAVLink 2.0 message signing requirement
Implement message signing in MAVLink 2.0 protocol to prevent spoofing and replay attacks. Secure heartbeat messages to avoid command injection vulnerabilities. Heartbeat messages are single bytes sent at a certain frequency to all other nodes to inform of device existence.
CAN Bus physical access requirement
Most attacks on Controller Area Network (CAN) Bus used between internal drone system components require physical access to exploit. CAN works on a differential signal and hardware hacking may be possible by tapping into them. Use tools like DroneCAN for secure CAN communications.
Sensitive data handling in drone RAM
Store highly sensitive information such as encryption keys, credentials, and intellectual property in RAM and clear after use. Provide this data before mission start using secure channels.
Secure Boot implementation for drones
Every piece of firmware must be signed with a cryptographic key, with only signed software allowed to run. A first-stage bootloader must be immutable in ROM or eFuse-locked code and verify the signature on the second bootloader. Each component verifies the next component in the chain (second stage bootloader -> kernel -> application).
ZigBee AES-128 encryption
Enable AES-128 encryption to secure ZigBee transmissions used for telemetry and sensor communication in backup systems.
802.11w MFP for Wi-Fi deauthentication attack prevention
Use 802.11w Management Frame Protection (MFP) to prevent Wi-Fi deauthentication attacks. This is a default protocol in up-to-date Wi-Fi systems and prevents crafted packets that emulate a server from causing deauthentication.
Measured Boot for drone fleet verification
Measured Boot records what software was loaded at each stage, allowing remote systems like fleet managers or ground stations to verify that the drone is running only trusted code. It also allows authorization of local actions, such as releasing decryption keys only when the device boots properly.
Storage encryption for drone data at rest
Ensure data is secure at rest on drones, even if someone gains physical access while the drone is powered off. Recommended tools include LUKS for block-level encryption, gocryptfs for filesystem in userspace, and age for file encryption.
ZigBee network key rotation
Deploy network keys with frequent rotation for ZigBee communications to prevent key compromise. Monitor for ZigBee packet sniffing attacks using SDR-based tools like HackRF or YARD Stick One.