Most of us tend to overlook how we handle certain data, such as social security numbers, date of birth, or phone numbers, assuming they’re automatically treated as confidential. Seemingly ordinary elements like customer ID numbers in our database can unexpectedly lead to sensitive data leaks and can lead to unexpected complications.
For example, consider a scenario where the browser’s address bar displays “/customer/56/edit”. A customer ID that increments with each new entry might inadvertently reveal the actual size of our database to competitors. This implies that we have a minimum of 56 clients in our database. Such unintended information disclosure could potentially have adverse effects on our business.
We should grasp that any numbers displayed in the address bar or accessible via the request inspector in a browser’s developer tool can potentially lead to information leakage.
Here are some examples. What can they tell us?
{
"user": "John Mallon",
"payment": {
"amount": 150.00,
"cardNumber": "**** **** **** 1234",
},
"billId": "17"
}
The first impression is that everything is done safely, However, I encourage you to examine the billId more closely. It’s the same incremental ID that could potentially reveal whether there have been 17 payments specifically for John Mallon or 17 payments in the entire service.
So, what measures can we take to address this situation?
There are several approaches we can take in this situation. For instance, you could develop a custom algorithm to mask the actual database ID or opt to use UUIDs for this purpose.
A Universally Unique Identifier (UUID) is a 128-bit identifier used in computer systems to label information. UUIDs are designed to be practically unique when generated using standard methods. Unlike many other numbering systems, their uniqueness doesn’t rely on a central authority or coordination between parties. Although there’s a very slim chance of duplication, the probability is considered negligible due to the sheer uniqueness of UUIDs.
We can utilize the alphanumeric string representation of UUID characters to achieve the unique identification of data entries. UUIDs typically follow a specific pattern of 8–4–4–4–12 characters, where each segment is a combination of alphanumeric characters and hyphens.
123e4567-e89b-12d3-a456-426655440000
Let’s slightly rework our answers from the server API.
{
"user": "John Mallon",
"payment": {
"amount": 150.00,
"cardNumber": "**** **** **** 1234",
},
"billId": "123e4567-e89b-12d3-a456-426655440000"
}
/customer/a1f57b85-3f2c-49d9-b649-8b17cf8e2a9e/edit
As you can observe, the UUID effectively conceals the incremental value, ensuring that the actual number of data entries in the Bills or Customers table remains hidden.
HashIds
If your system cannot switch to UUID or you want to continue using IDs as an incremented number, consider using hashes.
Examples:
// JAVASCRIPT
// see: https://www.npmjs.com/package/hashids
import Hashids from 'hashids'
const hashids = new Hashids()
// Encode
const hashedId = hashids.encode(1, 2, 3) // o2fXhV
// Decode
const numbers = hashids.decode(hashedId) // [1, 2, 3]
// RUST
// see: https://github.com/charsyam/hashids_rust
use hashids::HashIds;
let ids_hash = HashIds::new_with_salt("this is my salt".to_string()).unwrap();
// Encode
let hashedId = ids_hash.encode(vec![12345]); // NkK9
// Decode
let numbers = ids.decode("NkK9".to_string()).next().unwrap(); // [12345]
// C#
// see: https://github.com/ullmark/hashids.net
using HashidsNet;
var hashids = new Hashids("this is my salt");
// Encode
var hash = hashids.Encode(12345);
// Decode
numbers = hashids.Decode("NkK9");
# Python
# see: https://pypi.org/project/hashids/
from hashids import Hashids
hashids = Hashids()
# Encode
hashid = hashids.encode(123) # 'Mj3'
# Decode
ints = hashids.decode('Mj3') # (123,)
This way, your backend continues working with simple numeric IDs, while the frontend receives a non-cryptographic, obfuscated version of the number.
{
"user": "John Mallon",
"payment": {
"amount": 150.00,
"cardNumber": "**** **** **** 1234",
},
"billId": "Mj3"
}
Top comments (0)