Developers February 22, 2020

Do you obfuscate your resource IDs?

Karl Hughes @karlhughes

I'm starting a new project and I don't want my first few customers to know that they're the first people using it or that it's so small. I'm thinking about obfuscating resource IDs in the URLs.

Do y'all do this too? Or is it more trouble than its worth?

  1. 5

    Yes, I do, and you should, too. (Wow.)

    But not for the reason you mentioned.

    Unobfuscated IDs do not only reveal the size of your database, or the traction/load your system potentially has. They also allow attackers to tamper with the system more easily e.g. by simply incrementing or decrementing a value.

    This all goes hand in hand with other security concerns, like not revealing the webserver in the response headers (or generally any information about your stack), not sending detailed error details to the client, etc.

    You may not have to apply every single security measure out there. But obfuscated IDs is a cheap one. One simple way, available in many languages, is Hashids: https://hashids.org/

    1. 1

      Hashids is great. Lately, though, I’ve stopped using auto–incrementing IDs in general in favor of ksuids: https://github.com/segmentio/ksuid

  2. 5

    I don't think showing small resource IDs in URLs has any impact whatsoever in the success of your product or business. If you're solving a problem for your customers, they won't care about it, so neither should you!

    I thought about hiding post IDs in Typehut but ended up deciding not to do it for that very reason.

    1. 2

      This is not good advice. Almost every project I've started that has gotten even a little bit popular has been subjected to ID incrementing attacks. Even if it was just bug bounty hunters looking to make some easy cash.

  3. 3

    Yes. I always use UUIDs.

  4. 2

    I generally don't care. I think if they are early adopters, they will be more lenient. I come from before UUIDs rose to popularity. If I'm making a web page's information public, like a table on a web page, or a REST API, low numbers, and incremental increases doesn't matter to me.

    A simple solution might be this. I assume all, but at least MySQL lets you set the current value, and it's increment amount. For MySQL there's 2 system variables to set all tables "auto_increment_increment" and "auto_increment_offset". Alternatively, if you wanted to just modify the value for one table "ALTER TABLE users AUTO_INCREMENT=1001;" We were using these variables to solve issues with replication.

    </question>
    <comments commentary>

    IMHO, this whole UUID thing in the comments, is a holy war. There are reasons and instances where UUID is the better choice, and reasons not to use it. Do whatever reasonably gets your product out the door faster. Don't rewrite your tables, and recode your app until you have a reason to.

    </comments commentary>

    Best of luck!

  5. 2

    You NEED to use UUIDs for everything.

    You should just make this your default practice.

  6. 1

    Use UUID. If this is some kind of SaaS, feel free to use normal IDs, but scope them for a given customer (the counter is unique to the customer).

  7. 1

    Yes! Aside from most of the security concerns addressed in this thread, there is another benefit to them. When doing maintenance tasks (e.g extending someone's trial), it can save you from accidently pasting another resource type's ID (e.g. instead of organization ID, you paste the user's ID) and end up extending another customer's trial instead. With UUIDs, it's highly unlikely you will get collisions so you would simply get "Record Not Found".

  8. 1

    I use MongoDB for my DB so I use their ObjectIDs for resource IDs. They have a timestamp embedded into them (making them sortable) and are essentially globally unique.

    But, if you aren't using MongoDB, I'd use a UUID.

    Depending on what the resources are, you might also want to go for a slugified version of the resource's name for the URL (you'll still want an ID internally). For example, an event named INCH 2020 from an organization called MICHN would be: https://event1.io/e/michn/inch-2020

    That makes for a much more friendly and memorable URL than something like: https://event1.io/e/4eb6fd8e-8fb4-4664-816a-6e53544d07fc

  9. 1

    Yes, absolutely. We didn't start until we were about 6 months into coding, but it something we are really adamant about doing in every area of our app now (including going back and fixing the old code which didn't hash the IDs).

    As we get bigger and more popular, I am so glad we did it. You will be surprised at how much people try to 'game' the app by changing URLs etc.

    PS: We weren't too worried about the size perception for customers - we simply changed the autoincrement starting pointer to 104978 and other random huge numbers for our main data tables.

  10. 1

    Yes, yes and yes.

    You always should obfuscate these kind of indicators if you do a public application. Period.

    In case of exposure:

    • Your customrs might think it is a hobby app.
    • Your competitors could have an x-ray on your metrics (signups per day, in your case call for papers per day)

    and similar things.

    Setting the incremential ID on the database is not enough. Somebody could simply measure the same ID between two dates and also get lots of information on whatever you do.

    Example in this case:
    People do scrape booking.com and get an idea on how prices fluctuate and how many rooms are available.

    Be careful :)

  11. 1

    For most databases, you can just set the starting value of an automatically generated column. That way, the first customer gets ID 732 if you want them to.

    1. 4

      The problem would still be the difference between one post and another between a given time. This is not something you want other people to know :)

  12. 1

    This comment was deleted 5 months ago.

  13. 10

    This comment was deleted a month ago.

    1. 1

      I don't buy the security aspect of it, if someone shouldn't be able to view a page then the web server should enforce that. UUIDs are not necessarily generated using a cryptographicly secure RNG (it depends on the language), so by exposing them in urls without any auth checks you're still subject to bad actors guessing them. It just makes it a bit harder to guess.

      That said, there are other reasons to use them like being able to generate them from application code and not revealing the size of the dataset.

      1. 1

        This comment was deleted a month ago.

    2. 1

      You mean primary key rather than primary_key, right?

      Good advice. I use the uuid-ossp extension too. Another advantage of UUIDs over something like SERIAL or BIGSERIAL for primary keys and foreign key references is that when you dump and restore (e.g. into a test database) you don't have to worry about preserving sequences. The relationships will remain intact.

      1. 2

        This comment was deleted a month ago.

  14. 1

    This comment was deleted 4 months ago.

Recommended Posts