This article describes how to choose appreciated tokens in security design.
This article is for security demonstrating purposes only, and the author is not a full-time security researcher. API Tokens are not designing for critical environment such as TLS-breaking eavesdropper or compromised ROOT passwords. Any examples provided here are without warranty.
Alternatives
If we lack confidence in the security design for a particular job or project, leveraging third-party SaaS services such as Auth0, Hashicorp Vault, or cloud KMS can provide an effective solution. By utilizing these services, we can alleviate concerns regarding security design and focus on other critical aspects of our work, such as developing business-related applications or systems.
Threat Modeling
It’s critical to follow threat modeling before designing tokens in the system, which consists of confidentiality, integrity, availability, accountability, and authentication. Here are some key processes. Have a look at
Security premises of token design
Internal Design
Have a look inside the application binary
- User case diagrams such as login, authentication, or forward-auth.
- Data flow diagrams (DFDs) inside the application. Analyse high-value asserts that hackers might be interested in.
- Vulnerabilities in third-party libraries embedded in the application.
- ACL, scops, rate limits, and expiration.
External Dependencies
Enumerates the potential risks precaution against external components being compromised.
Data flow diagrams (DFDs) that are external to the application, such as hard disks, S3, database, hashicorp vault, KMS services, and even storage chips.
Deployment diagrams including VPC, WAF, Linux, containers, Kubernetes, or physical machines. The underlying components should be hardened periodically.
Http router configurations for Nginx, traefik, or consul.
Types of tokens
Designs for tokens can be classified via authenticates flow.
User-to-server token
User-to-server token is used for users speaking to a machine such as a news iOS App fetches data from the server via tokens owned by the current user.
Type | Description | Input | Scopes | Expiration |
---|---|---|---|---|
Password | The password held by users. | User-input | For login only | On-demand |
Session | Randomly generated after user login. | Server-Generated | Full | Hours |
Access Token | Impersonates users for API calls. | Server-Generated | On-demand | On-demand |
Sessions can be implemented with a custom header name such as x-authn-token
or custom cookie names. For instance, SpringBoot will use SessionResolver
to generate and resolve sessions from HTTP requests sent from users.
Server-to-server
Server-to-server token is a static token used for servers speaking directly to another server such as a database password, LDAP password, or AKSK in S3 Storage.
It’s considered more important than the user-side tokens. SRE experts will secure the deployment behind a VPC & WAF and must encrypt, rotate, and monitor the tokens periodically.
In the recent Aliyun Cloud global service failure, it was allegedly a single point of AKSK authentication failure that caused the the S3 storage failed to connect.
OAuth Token
OAuth Token is primarily used in SaaS services such as a hotel reservation website that connects customers, a hotel reservation server, and a payment SaaS service together. Once customers agree on the OAuth authentication, the hotel can charge the bill without further confirmation.
Client-side storage security
Browser session
The best way is to use in-memory storage with ServerWorkers as a proxy to handle the transmission.
As an alternative, in-browser storage such as local storage, session storage, and cookies are okay as long as we minimize the attack surface (XSS/CSRF). Here are some tips
- Enable subresource Integrity (SRI) that can check integrity from CDNs or local servers
- Disable IFrame embedding with the X-Frame-Options header.
- Restrict contents via the header
Content-Security-Policy
to enumerate trusting resources. - Sanitize HTML before rendering the page.
In-App session
Besides in-memory storage, leveraging key storage to a hardware-based key manager such as Keychain is also considered secure.
As for the transmission, consider enabling HTTPS & SSL Pinning to prevent MITM.
Server-side storage security
There are a few approaches including KMS, file, or database to store secrets. The simplest way is to store secrets in a database.
Before all
- The hard disk and database should be encrypted transparently.
- The connections between applications (such as a SpringBoot application) and databases should be encrypted with TLS.
Plaintext storage
It’s not allowed to store secrects in plaintext format in the database duo to it’s vulnerable to data leak when
- The database is compromised or the hard disk is stolen.
- The employee is malicious
- Junior programmers might print
select * from token
in the log – I’ve seen the code a lot.
Password derivation
The key derivations function(PDF), aka slow hashed/hierarchical keys, are used for generating irreversible passwords, such as PBKDF2, scrypt and bcrypt.
Usecase
In a user’s registration process, the function is used for generating the hash text that will be stored in the database. The hashed key derived from human inputs can strengthen the randomness and length as user-provided passwords (such as 6 digits of PIN code) are vulnerable to dictionary attacks.
Additionally, as a password derivation, it can generate one or more secrets.
- 1->1: In PBEWITHHMACSHA512ANDAES_256 encryption, it works as an encryption key (DEK) for AES GCM encryption.
- 2->1: In Two Secret Key Derivation (2SKD) , it involves in combining a new password from two passwords.
- 1->2: The hand input password will be splitted into two parts, one for login, another for password synchronization. See details
Should I provide an additional encryption layer for PBKDF2?
There is a scenario if someone has the database terminal in hand, he can bypass the authentication via privilege escalation such as
- Replacing the existing PBKDF2 hash in the database with a pre-calculated hash. It’s similar to replacing the password of a root user by modifying the file
/etc/passwd
. - Grant a user access by modifying relationships between users and tokens, such as updating the references of the
user_token_id
to a pre-generated token that you known.
To mitigate potential risks, one approach involves adding an extra layer, such as 2SKD or nested encryption, to encrypt sensitive columns representing user_token_id
as well as encrypted tokens. However, implementing such protections may be unnecessary since securing an extra encryption key requires exclusive and critical infrastructure beyond current needs. Furthermore, a compromised database could still expose digital asserts directly.
Should I use client-side hash for a password?
Client-side hash just replaces the password
with hash(password, salt, iteration)
, for backend servers they are considered the same, hackers can still impersonate users with the hashed password.
You needn’t to create your own HTTPS protocol. Hashing is only designed for preventing brute-force attacks, which don’t resolve MITM nor replay attacks issues.
Nonetheless, It’s okay to create a hash at a client level if you fail to persuade your leaders.
Symmetric encryption
Algorithm: Such as AESGCM256 with 96 nouces(IV).
Storage: The encrypted text can be directly stored in the database. However, the symmetric key requires isolated storage separating from the database and codebase.
Asymmetric encryption
Asymmetric encryption is primarily utilized for secure exchange of information, as examplified by SSL, saved logins, and license key generation. Tokens storage are rarely used duo to the slow performance.
Algorithm: Such as RSA4046
Storage: Same as above.
How to log requests safely?
See my another blog.
Where to store reversible encryption key?
Technically it’s a problem of chained trust storage, even if using cloud KMS or Hardware KMS as underlying storage, you have to provide at least one reversible key (aka master key, pin code, phrases, alias or seal key) inside the application for cryptography operations. Once the key is breached, the data may be potentially exposed.
As an application developer, leveraging third-party storage rather than self-implementation is the best known method.
- Never hard-code secrets in the source code, it can be considered as a backdoor by customers.
- Segregate the roles of the reversible key holders and the application developers.
- Deploy applications on PaaS orchestrators, as exemplified kubernetes or nomad, which both can inject secrets into files or environment variables within isolated namespaces via chroot jail.
- Use JCA Provider in Java, which uses PKCS internally.
As we have talked above, we can’t omit all threats from skilled attackers but make it more difficult to be compromised.