00:00:15.599
So let's welcome Rafał Rothenberger with his talk about device.
00:00:28.199
Let me start with something maybe a bit more controversial. As popular as Device is, it has some pitfalls, edge cases, and maybe even security issues. I'm Rafał Rothenberger, and I'm a bit of a security freak and a software developer based here in Montreal. Let's start with a quick poll: who has never heard of or used Device?
00:01:03.660
Alright, that's a good number. Now, who is using it in any project right now?
00:01:08.520
Okay, that's great! So, what exactly is Device? Device is a library for authentication and user management. It provides an easy way to handle password resets, sessions, registrations, and all those boring things that almost every application needs. Why use it? The biggest argument here is that it's popular, dwarfing other solutions in terms of both usage and features.
00:01:27.720
There is a saying that popularity can’t be wrong, which gives the idea that because a lot of people are using it, it should be secure. However, what's the goal of this presentation? First of all, I want to discuss the limitations of Device and how it often misuses libraries like BCrypt. I will also cover how to implement token-based authentication for APIs since Device is mainly for view-based applications.
00:01:44.640
Given the prevalence of mobile devices in everyday life, we need more and more APIs. This talk will also address how to manage refresh tokens and why to store them in cookies, discuss enumeration attacks and their significance, and explain timing-based attacks.
00:02:15.480
Before diving deeper, let's discuss salt and pepper in a bit of a historical context. Back in the 70s and 80s, we were terrible at storing passwords; simply hashing them and saving them in databases was common. One problem with this approach was that the same password would always generate the same hash, making it trivial for attackers to brute-force weak passwords.
00:02:22.260
The second issue arose when I encountered a password leak. I now had access to a table of known hashes and passwords, allowing me to capitalize on future leaks without additional effort. To address these vulnerabilities, we started incorporating salt—a random string or bytes added to the password. Now, even if two users have the same password, their hashes will differ, mitigating previous issues.
00:02:43.680
In modern hashing algorithms, salt is often handled as a parameter rather than just appended, allowing for more complex security measures. However, this wasn’t enough, as weak passwords were still susceptible to brute-force attacks. To further secure data, we introduced what is known as pepper—another random element, not stored in the database but kept as a secret elsewhere. This means that even if someone uses a simple password like ‘password123’, without the pepper, you cannot verify the hash.
00:03:20.460
Now let's return to our discussion of BCrypt. BCrypt has specific design decisions, limiting the length of passwords in most implementations to 72 bytes. This limitation poses significant problems: the same password string that is 72 characters long, when combined with the same salt, produces the same hash. In many cases, this leads to developers simply truncating the string without providing error notifications.
00:03:52.920
As a consequence, Device now has a default password length limit of 128 characters, but effectively only uses a maximum of 72 bytes. Even worse, when Device tried to implement pepper by adding it at the end of passwords, it became possible to leak this information. If I create an account using a password of 72 'A's, only the first character of the pepper will factor into the hash. This means I can iterate through the alphabet at the end of my password and successfully log in, thereby exposing the pepper.
00:04:41.159
Is there anyone here who has used pepper with Device? Alright, not too many. While it may not be great, I think it's still important to use it properly, as ignoring such measures could expose security vulnerabilities.
00:05:05.760
It's essential to note that BCrypt is not a standard hashing function; it is specifically a password hashing function. The key difference here is that traditional hashing functions can accept arbitrary length inputs, transforming them into a fixed-size output. In contrast, BCrypt takes fixed-sized input and yields fixed-sized output, often limited to 72 bytes.
00:05:24.780
If you have ever programmed in C, you understand that strings often terminate with a null byte. When BCrypt encounters this null byte, it disregards everything following it, repeating the input until it reaches its fixed size, leading to the same hashes for wildly different passwords.
00:06:01.920
For this reason, it’s crucial to be aware of the security implications of these design choices. If you need to use Azure, rather than going through these complications, consider a more suitable solution like Argon. Argon can handle longer inputs and is better designed for password hashing.
00:06:35.460
Now let's discuss tokens. For applications utilizing token-based authentication for APIs, I recommend keeping it simple. Use simple opaque tokens instead of JWTs unless you need extra cryptographic assurance. Implementing standard tokens will keep your solution secure while allowing for other features like admin panels.
00:07:09.240
Tokens can be securely stored in cookies, making implementation straightforward. With frameworks like Rails, you already have built-in support for cookies, which have been vetted over the years. Cookies can prevent leaks, as they can be set to be HTTP-only, ensuring that even if JavaScript runs in the application, it won't access sensitive tokens.
00:07:51.780
Security with cookies further strengthens logging mechanisms. Cookies are first-party, meaning you control them directly within your application. If you choose to use secure settings for cookies and only allow them to be sent over HTTPS, this will protect your tokens from various attacks. Additionally, placing token restrictions to only restricted APIs significantly reduces vulnerability.
00:08:35.160
Let’s shift gears to enumeration attacks. An enumeration attack occurs when a user can infer the existence of accounts by observing the behavior of registration forms or confirmation messages. For example, if a user receives a confirmation link for a password reset, it reveals that their email is indeed valid and already has an account associated.
00:09:14.160
To protect against this vulnerability, ensure your registration forms don’t reveal if an email is already in use. A safer practice can be to inform users that an email has been sent to them, stating that if they’ve forgotten their password, they can reset it without confirming if the email is linked to an account. This reduces the chance of malicious actors identifying existing users.
00:09:57.599
It's important to care about the privacy of your users. Even with applications that assist with sensitive matters such as addiction, it's important to protect user identities from potential leaks via enumeration attacks. Implementing different messages or APIs can help ensure privacy and make it harder for attackers to leverage known methods to discern account presence.
00:10:35.520
As we wrap up, let’s discuss time-based attacks. These occur when timing differences in your application become an exploitable factor. By sending numerous requests to check for password reset emails, an attacker can measure response times to determine the validity of an email address. This means an attacker could send thousands of requests to infer which emails have accounts, which is a significant security risk.
00:11:03.780
To minimize timing attacks, consider offloading certain actions to asynchronous tasks. For example, instead of verifying an account on a password reset request, you could send the request to a background job to check the validity without revealing any immediate feedback to the attacker.
00:11:37.500
This approach would diminish timing-based attacks, as determined attackers would struggle to dissect response times effectively. Similarly, rate-limiting logins is also an actionable step to deter attackers from script-based enumeration attempts. Keep in mind that user engagement and data security are not mutually exclusive, and maximizing the experience while protecting privacy is essential.
00:12:10.920
In summary, if you’re using Device, consider switching to Argon for better performance and improved security with tokens and passwords. Remember to implement cookie-based storage if you're utilizing refresh tokens, and thoroughly address enumeration and timing attacks with proper techniques to ensure user privacy and security. I hope you have a great conference.
00:12:46.440
Before I conclude, are there any questions?
00:13:18.360
That's a great idea because outsourcing password management removes many associated risks. However, even with services like Auth0, authentication still relies on managing tokens to access APIs. Clients may still opt for in-house solutions if costs are a concern, but less reliance on password storage is generally favorable.
00:14:04.920
Regarding broken packages, have you ever considered reaching out to the maintainers? It can be beneficial to flag issues on their repository for broader benefit.
00:14:59.640
Indeed, I attempted to email them about leaking the pepper, but after three months without a response, I felt justified in addressing the matter publicly. Engaging with maintainers can be complicated, especially considering the need for backward compatibility with packages in the software ecosystem.
00:15:42.720
It can be an uphill battle between breaking changes and maintaining security. However, addressing vulnerabilities proactively should be prioritized to ensure users remain protected.
00:16:05.760
Thank you very much. Is there anything else I can clarify?
00:16:30.720
That's all for now; thank you again!