1

I have a 3rd party API that I need to connect to and they allow queries that can be formed by changing url parameters.

E.g. /data?startDate=2019-01-01 or /data?name='John Doe'

It is easy to form these queries by concatenating strings, but input cannot be trusted (our API is exposed to end users and accept parameters that have to be sent to the 3rd party API). That means that anyone can try to inject something in our URL and then it will be sent to the 3rd party.

If our API was talking to an SQL server, we could have used prepared queries to prevent injection, but how to do that with a URL?

It's possible to check that e.g. date is just date, but what if a custom string like name is allowed?

Example:

A query to a 3d party API: /data?$filter=(userId eq 1) and (startswith(someField, {userInput})) eq true

User input to my API: userInput="someText) or (userId eq 2"

  • I do not see any reason to use the HTTP GET method to transmit (sensitive) data. From a REST perspective, this is incorrect. The third party should have documentation in place which describes exactly what they are expecting for each parameter. In case of a date an example could be to only accept YYYY-MM-DD and not the other way around. If this is not in place, there is no way to validate your data. – Jeroen Oct 15 '19 at 10:49
  • It's OData that allows practically any kind of queries – Ilya Chernomordik Oct 15 '19 at 11:00
1

In general the answer is: you can't.

The best way to protect against injection attack is to separate data and commands. When talking with an SQL database, this means using prepared queries. When updating the DOM, this means using javascript methods that tell the browser "this is data to display and should not be interpreted as HTML".

Unfortunately this is one particular "backend" for which that simply is not possible, since you only have one communication channel. You definitely can and should use proper URL encoding so that an attacker can't use your system to feed extra parameters to the third party but, for instance, there is no great way to stop an SQLi payload from moving through your system.

Certainly you could do what some do and implement a WAF. I.e. if you see SELECT, 1=1, or other common SQLi payloads then you can refuse to pass along the request. In general though blacklisting is not an effective security measure (there are plenty of questions on this site about bypassing WAFs) and it also tends to get in the way for regular users through false positives. As a result I don't really recommend it. Indeed, you don't even necessarily know what technology they use on the backend. You might assume an SQL variant and try to detect SQLi payloads, when they are really operating a NoSQL database with a completely different syntax and vulnerabilities. Therefore you may end up protecting against the completely wrong "kinds" of things.

All that to say: you really have no choice except to trust that the third party is practicing proper security themselves. Which is really the only answer anyway, since as a general rule of thumb you have no control over the security of someone else.

  • You say that a 3d party has to have a protection e.g. against SQL injection further in their stack, but what I was more interested in is how to protect against changing the url query itself, I have edited the question to provide an example. If we don't trust user input, then I don't see how we can ensure there won't be e.g. or userId = 2 in the query. I guess it's not that easy to do this since there is no "parametrized" query in the URL – Ilya Chernomordik Oct 15 '19 at 20:16
  • @IlyaChernomordik Yes, that's exactly my point. There is no "parameterized" query in a URL, so there is no way to explicitly separate "data" from "commands". The only way you could try to stop such a query from happening would be by trying to detect such malicious queries and reject them, but (as mentioned in my answer), doing that is nearly impossible in practice. Moreover, you might make wrong assumptions. For instance you're showing an SQLi payload, but they may be using a NoSQL database which has completely different vulnerabilities. – Conor Mancone Oct 15 '19 at 20:35
  • Which is just one more way of showing that at the end of the day, only they can protect themselves. It might be different if their API provided a way to separate out data and commands, i.e. if they accepted JSON and asked for something like: "queries": [ { "field": "name", "search": "Ilya" } ]. However even that wouldn't guarantee that in the back end they don't just concatenate themselves and build an unsafe query. – Conor Mancone Oct 15 '19 at 20:37
  • Thanks for the answer! There is already too late for them to validate the query, since the URL that we would send is perfectly fine and correctly formed, so injection would happen on our side since the URL we create would be wrong and have the injected data already... – Ilya Chernomordik Oct 16 '19 at 11:19

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.