The company I am working at uses a REST API for database accesses. So basically, you just provide a SQL statement string and the REST API returns a Datatable. Now I am unsure as to how to prevent an SQL injection as I cannot generate the SQL command using parameters (as I normally would) since I have to provide a SQL statement string for the REST API.
The only way to make this safe is to whitelist a specific list of SQL queries that are pre-vetted. The REST API would compare the input to the whitelist. If the SQL query is one of the known queries in the whitelist, then it can run. Otherwise, the API returns an error status (I'd use 400 BAD REQUEST).
But I suppose the purpose of the API is to run any SQL statement the client inputs, verbatim. This is literally an SQL injection vulnerability by design. There is no way to make that not SQL injection.
Besides that, the API really goes against the conventions of a RESTful web service.
The URI of the request doesn't identify the resource.
I assume every request is a POST with the SQL query as a payload. You probably don't use http methods like PUT, PATCH, or DELETE.
The message in response, being only a datatable, isn't self-descriptive; it doesn't contain metadata the client can use to manipulate the resource.
SQL, being a generative grammar, allows an unlimited variety of queries. This doesn't fit the HATEOAS principle that the REST server should be able to describe the valid actions on request. The client must have implicit knowledge of your database schema.
You don't have a REST API. You have a web service with no specific interface.
The presence of a "query anything" API should be a huge red flag. It's probably a sign that the project isn't specified well in other ways.
Related
I am creating API and trying to figure out is planned approach any good.
That API is not public and it will be used by SPA and mobile app that I build.So I am thinking of GraphQL-like design but without posting json and with regular HTTP methods.
Something like this for GET methods:
Example 1 - get users with specific fields(_join indicates sql table join), ordering and limit:api.com?table=users&displayFields=id,name,email,address,tel,country_join&orderBy=asc&orderColumn=name&offset=0&limit=10
Example 2 - get users based on search parameters with all fields, ordering and limit:api.com?table=users&search=John&searchFields=name,email&orderBy=asc&orderColumn=name&offset=0&limit=10
I assume this is bad since REST is standard, otherwise I would see much more examples of this approach.
But why is this bad? For me it seems easier to develop and more flexible to use.
Is proper REST API for examples I provided easier to implement, safer, easier to use or cache?
The main difference I see between putting the variables in the url vs the request body are:
the length of the data as the url length is limited while the request body is not
special characters to be escaped in the url which can lead to long and unclear url
These are 2 pros in favor of data in request body, but I agree that data in url is much simpler to test and use as tou don't need an http client tool like curl or postman to validate your endpoints.
REST however has stricter conventions if you want to fully implement it:
use the right http requests (get, post, patch, delete and put) to implement crud operations on one single endpoint
return the right http code as a result
use standard data format for input and output (json or XML)
For better interoperability between systems it's advised to comply with REST and microservices design patterns.
For small applications we can follow some shortcuts and not comply fully. I have integrated several services so far and each time I can tell you no one of them implements standard REST :-)
I'm having real trouble getting Informatica PowerCenter or Developer to call a URI based REST API and I'm doing it for something simple (JIRA's API). Basically I want to call JIRA's worklog REST API which is a different URL for a list of issue ids and write it to our DB.
https://docs.atlassian.com/jira/REST/6.2/
/rest/api/2/issue/{issueIdOrKey}/worklog
Informatica PowerCenter supports only HTTP transformation which is only a simple GET. Unfortunately the latest version is still stuck in the 'old' query type URL building where they append inputs into search strings. E.g. if I have a "key" input field with value "ABC-1" and the URL is jira/rest/api/2/search it would actually build the URL on the fly into jira/rest/api/2/search?key=ABC-1. While some of JIRA's API works this way, some use the URI way e.g. jira/rest/api/2/ABC-1/worklog which requires embedding the value into the URI. There's no way I can get this to work :-
if I do jira/rest/api/$key/worklog it still converts the URI into jira/rest/api/$key/worklog/?key=ABC-1 so $key does not get replaced
even if i pre-build the URI outside the mapping it's not feasible as the URI needs to be dynamic to the list of JIRA keys and anyway because it appends ? at the end JIRA throws an error (because ? is a reserved key word for this API)
HTTP transformation does not support NTLMv2 authentication which our company's JIRA instance may upgrade to shortly
Last resort is to use a Java transformation in which Informatica has quite little value add. This also means I need to somehow pass in the JIRA user password for authentication which is a separate challenge (versus just storing as a HTTP connection)
Informatica Developer supports REST Web Consumer Transformation but has similar limitations with only building query type URL. Even worse I can't even dynamically build the URL since it's fixed to the HTTP connection object URL.
Am I straight outta luck?
I got the query and here I would like to answer about this. I can write here only points and it might be you won’t be able to understand that thing properly. So Here I am putting link of blog where the task "how to informatica read rest api is mentioned in detail step by step with video tutotial. Some examples are also there. Feel free to visit
https://zappysys.com/blog/read-json-informatica-import-rest-api-json-file/
Hope it will help.
The problem is that we have a complex query string for a search api and want to let the users have convenience of using body instead. So we want to allow both GET and POST(or PUT).
I understand that there will be a debate of search being a read only operation and it should be GET only as per REST standards. Also PUT is not cache friendly as i understand.
But i also know that its ok to deviate at times from the REST standards. But does it make sense to have two methods for client's convenience?
Using POST directly to query data is not a good thing, precisely for the reasons that you mentioned. If your search string is complex, perhaps you could simplify things by splitting the querying process in two steps - one involving a POST, and another one involving straight GETs.
The first step creates a query template using the POST. The query string is sent via message body, and becomes a new resource that users can query through GET. Query string allows for parameters, in a way similar to SQL queries. Taking a wild guess at how your query might look, here is an example:
(userName = $name) || (createdBefore > $asOf && deleted=false)
Your users would POST this in a message body, and get a new resource identifier back. This resource identifies a parameterized "view" into your data. Let's say the resource id for this view is aabb02kjh. Now your users can query it like this:
https://app.yourserver.net/aabb02kjh?name=airboss&asof=20140101
This adds some complexity to your API, but it lets users define and reuse query templates with very simple and standard query strings.
Interesting question. I mean by POST -> PUT,DELETE there are common workarounds for overriding HTTP methods:
sending a _method hidden input field with the post data
sending a _method query param in the URL
sending an X-HTTP-Method-Override header with the post
etc... So if they are valid (I am not sure about that), then you could use the same approach by GET as well.
According to REST constraints: cache and the uniform interface, and the HTTP method definitions, you have to use GET by retrieval requests. There are only a few URL query languages to make URLs readable, for example RQL, but you can always pick your favorite query language and serialize it for URL usage...
Another interesting approach to add link descriptions about the URL. (But that is very new for me either.)
We are creating a RESTful API (PHP on apache server) which will communicate with an Android application. Im new for this so excuse me if my question is dumb.
I want to ask for data from the api so I need to use GET method in the request taking into account the semantics. I have to send some additional data to specify what data am I requesting. In GET requests, I cannot send form data fields so how should I attach the data?
Using POST (but this is not semantic)
request header: POST http://example.com/api/v1/serials
request data: date_from=2013.01.01&date_to=2014.01.01&userid=112&is_in=0&starts_with=afx00
using GET and adding url params (I don't know if is this a good practice in a REST API)
request header: GET http://example.com/api/v1/serials?date_from=2013.01.01&date_to=2014.01.01&userid=112&is_in=0&starts_with=afx00
or making well formed URIs with no url params in GET (not sure about this as well.)
request header: GET http://example.com/api/v1/serials/date_from/2013.01.01/date_to/2014.01.01/userid/112/is_in/0/starts_with/afx00
Which one fits the best in the RESTful API architecture? Which should I use and why? Or maybe are there any other options for what I want?
Without question using URL parameters is best. It allows consumers to query for serials using their choice of filters. Your API should support returning results based on UserId alone, or a date range, or both. Or other combinations of inputs that make sense.
Embedding the key/value pairs of the filter in the resource path is an anti-pattern. It's difficult to understand what each path element means, and you would need to contort your routing engine to accommodate additional filter criteria. It also provides no flexibility in terms of choosing what filter criteria to use - you would in fact need to construct multiple resources paths for each combination of filters. And there is the management of ordering each pair (with URL params, ordering doesn't matter). Probably more reasons to avoid this, but those are the first that spring to mind.
Bot GET methods can be used. It is your choise. But I'll prefer using url params. It is easier.
What is the best way to avoid SOQL Injection when querying salesforce through the APIs?
The two main APIs I am interested in are the SOAP and REST APIs.
My current methods are to never use any input from the user (which is impractical if they are searching for a Company Name) or encoding certain characters within the string.
However I saw that there was parameterisation within the APEX, so i was wondering if there was a similar way of doing it through the APIs.
I think all you really need to do is to make sure that the input, in this case the company name, is escaped properly. I am not aware of a parameterized way of building a query object for either of the API's.
However, if you needed to you could expose a custom web service method from within Salesforce so that you can pass the value in. Then from within the Salesforce Apex Code language you can parameterize the value using a syntax similar to below:
public Account[] queryCompany(string companyName) {
return [SELECT Id FROM Account WHERE Name = :companyName];
}
Philosophical rant
What are you after really :)
If your application should work same way accessed from different sources (Salesforce UI, PHP connector, some mobile applications) then it probably makes most sense to think about Apex like some stored procedures that will be reused. This means you'd be passing safe parameters to them.
If you plan to hand-craft queries & not rely on Apex too hard - maybe what you need is something like database.com or other cloud-based DB solutions?
Actual answer
I'm not aware of an out of the box way to pass separately the query command and separately the params to it (like bind variables/prepared statements) through APIs. Both REST and SOAP API give you what's essentially Database.query() within Apex. Sure, there are some differences like retrieve() command or queryMore() but that's the baseline.
What you could do is to either expose some commonly used searches with methods similar to what John proposed (bonus points for extra performance - they're precompiled) or build something generic?
List<sObject> runQuery(String query, List<List<String>> params){...}
If the runQuery will contain bind variables like params[0] it should work. Looks crazy and I didn't test it though ;) I'd say that bind variables are the best method. Alternative would be to escape user's input but SQL and XSS injections can become amazingly creative. Check Examples of XSS that I can use to test my page input? for a start (yes, I'm aware you asked about SOQL only).
As for actual SOQL injection: http://wiki.developerforce.com/page/Secure_Coding_SQL_Injection. Since "worst that can happen" is that users will search for more than they were supposed to (no way to convert SELECT into INSERT) escaping should be safe-ish...