3

Story

We are developing an API that which allow consumer to create or modify (i.e. upsert) objects stored in database via an endpoint with HTTP PUT.

The primary key of the object stored in this way is a GUID instead of an auto-increment number to prevent potential conflicts in future and it was decided that the GUID should be provided by API consumer in both scenario during object creation and modification.

We are being informed that the advantage of this approach allows us to focus the intention of storing objects without differentiate between create or modify.

Question

In this case, we expect the API consumer to pass a GUID as object identifier and what can go wrong security-wise if we allow someone else to decide the primary key of the object stored?

I understand I may treat the provided GUID as candidate key and generating another unique identifier internally but it seems redundant and wonder if it's a plausible approach.

  • 1
    Presuming that you allow more than one "customer" to use this API, the question is: is the GUID required to be unique across your entire system, or just per customer? I.e. if I try to use GUID 12345 but some other customer already created a record with that GUID, what happens? Do I overwrite their record, or do we both just get a record with GUID 12345 and have no way to tell that someone else is using the same? I'm guessing the former, in which case this is a bad idea, but I want to confirm before attempting an answer. – Conor Mancone Oct 25 at 13:21
  • @ConorMancone thanks for raising an interesting point and customer A shouldn't be able to modify customer B record. In the scenario you've given customer B will need to generate a different GUID due to fail creation. – Zephyr Oct 26 at 5:00
2

It depends.

Objects are Secret

If the data being uploaded with those GUID is considered secret, then you do not want users to share the same GUID. For that reason, you want to include another identifier in your primary key to make sure that each customer has its own set of GUIDs. In other words, as Conor mentioned in his comment, every user would be able to create an object with GUID 12345 and the customer has no clue that another customer also has a object with GUID 12345.

You can easily do that by adding the customer identifier to the GUID to identify the object(s) on a per customer basis.

Note that in this case you would also include a way to identify the user since the data is secret. Either a long UUID like string that was given to the user when they logged in or directly the credentials of the user (that one only works if only the costumer's server access your server since such credentials.)

Objects are Public

When objects are anyway public, there is no real security issue. However, it puts a burden on the client which is to generate a new GUID when an upload fails because of a clash.

Now, a GUID should be unique so the possibility of a clash is minimal. It probably would happen because a hacker is trying to find objects which said hacker should not otherwise know exists.

Since the data is public, though, having a hacker find it is not big deal. It's available to them one way or another...

Identifier

The idea of an identifier that gets incremented has been used a lot and it is still being used a lot.

If the data the identifier references is public, then it is not important to have a number incremented one by one like this.

However, something that should remain somewhat secret should not use such numbers. This is because a hacker can easily check for all the objects by using a URL such as:

http://example.com/user/1
http://example.com/user/2
http://example.com/user/3
   ...
http://example.com/user/n

Now we can see that the hacker can find all the users. If the user's account is public, he can check their name, with that name, they can attempt a login with some random password. So you do have a vector of attack which is simplified.

Create vs Modify

Yes. This mechanism is used by many systems, especially in the NoSQL world. For example, Cassandra let you use INSERT or UPDATE to create and/or modify content.

Cassandra has one column which is called the PRIMARY KEY (as in SQL, only it can not be more than one column). That PRIMARY KEY is used to index the data. This is the same as your GUID only can be absolutely anything, including binary data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.