Valid JSON in Firebase API keys - json

I have been testing webhooks from http://context.io/ with Firebase. Which will fire off a POST whenever a valid email is sent.
The issue is that a couple of the keys have a '.' in the name. Which has Firebase sending me a 400 error:
"error" : "Invalid data; couldn't parse JSON object, array, or value. Perhaps you're using invalid characters in your key names."
Can I use security rules to manipulate the newData to replace the '.' or do i need to a use a proxy server in-between.
If so, what is the recommended approach for a thin nodejs proxy server, only made to do this.

Security rules only enforce security and cannot be used as translators or filters. Thus, you'll have to manipulate the keys before sending them to Firebase.
It doesn't look like you are forced to use the email as the key, since you can structure the URL to which context.io sends your requests. Could you save the effort of a proxy by using the context.io unique ids or some other unique id instead of email address?

If you REALLY want to work with the email as the key, you can still do it using a base64 encoded value of the email address.
This has many benefits including sorting integrity as well as faster lookups if you're constantly searching by email and accessing data within that.
Ref:
Python: https://docs.python.org/3/library/base64.html
Javascript: http://www.w3schools.com/jsref/met_win_atob.asp

Related

XSS vulnerability for JSON API

I have a REST API that accepts and returns JSON data.
A sample request response is a follows
Request
{
"repos": [
"some-repo",
"test-repo<script>alert(1)</script>"
]
}
Response
{
"error": "Error Message",
"repos": [
"test-repo<script>alert(1)</script>"
]
}
Is my API vulnerable for XSS?. From what I understand, since the Content-Type is set to application/json, the API as such is safe from XSS. The client needs to ensure that the output is encoded to prevent any XSS attacks.
To add an additional layer of security, I can add some input encoding/validation in the API layer.
Please let me know if my assessment is right and any other gotchas that I need to be aware of
I think it's right that any XSS issue here is a vulnerability of the client. If the client inserts HTML into a document, then it is its responsibility to apply any neccessary encoding.
The client knows what encoding is required not the server. Different encoding, or no encoding may be needed in different places for the same data. For example:
If a client did something like:
$(div).html("<b>" + repos + "</b>");
then it would be vulnerable to XSS, so repos would need to be HTML encoded here.
But if it did something like:
$(div).append($("<b>").text(repos));
then HTML encoding would have resulted in HTML entity codes being wrongly displayed to the user.
Or if the client wanted to do some processing of the data, it may want the plaintext data first to do the processing, and then encode it later to output it.
Input validation can help too, but the rules for what is valid input may not align with what is safe to use without encoding. Things like ampersands, quotes and brackets can appear in valid text data too. But if your data can't contain these characters, you can reject the input as invalid.
Your API will not be vulnerable to XSS unless it also provides a UI that consumes it. It will be the clients of your API which could be vulnerable - they will need to make sure they correctly encode any data from your API before they use it in any UI.
I think your api is vulnerable, though the script may not be execute. Talking to XSS prevention, we always suggest decode/validation dangerous characters when the api deals the input. There is a common requirement "clean the data before it store in the DB".
As for your situation, the api just response a json, but we don't know where the data in json will be used to. usually the frontend accept the data without any decode/validation, if that, there will be a xss.
you talk about that the client use decode the data they get from your api. Yes I agree, but frontend always "trust" the backend so that they won't decode the data. but the api server should not trust any input from frontend due to this can be controlled/changed by (malicious)users.

Azure FCM NotificationHubClient Configuration for Data Payload?

Using
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString(notificationHubConnection, notificationHubName, enableTestSend);
NotificationOutcome outcome = await hub.SendDirectNotificationAsync(fcmNotification, deviceUri);
I am able to send and receive notifications using FCM via the Azure hub to a Xamarin Android app, finally. However the payload is not present in the received RemoteMessage even though the sent fcmNotification json payload looks good and passes validation. I am basically looking at the RemoteMessage.Data property, but not finding the expected payload array. Looking at RemoteMessage structure, I haven't found any part of the payload array either.
I know that the Azure hub manipulates the notification by adding the necessary headers like content type, e.g. "application/json". Are there any other settings that are needed to be passed to enable the "data" only payload?
Additional settings are not necessary, but the format of the entire notification contents has to have this type of structure:
"{ \"data\":{ \"A\": \"aaa\",\"B\": \"bbb\",\"C\": \"ccc\",\"D\": \"ddd\",\"E\": \"eee\",\"F\": \"fff\"}}"
The number of data elements is up to you. The data element name can be anything as well as the associated content except for the need for backslash usage for special characters. Both the element name and content can be inserted using variables creating a traditional composite string.
What is especially important is the inserted spaces as shown. Also note that traditional Json formatting is not acceptable because of the need for those spaces.

Does using multipart/form-data Content Type for a RESTful POST api a good practice?

I have a situation where I have to write a api to create a resource and amongst datafields that I need to accept is a string that is basically contents of a html file. As I see it I have a choice between structuring the entire thing as a json object where this field is a string field with urlencoded html string , and having the Content Type as multipart/form-data where each of the fields and the html string (UTF-8 encoded) is a part in the message.
Not using json is something I am not comfortable with as I feel violating the REST standards in not structuring the content of the entity I am about to create thus there is a loss of information for the consumers as they can't tell immediately looking at my api definition about what data to feed to it. But practically multipart/form-data handles stuff like html file content better and more efficient as I will not have to urlencode it and can control the char-encoding also.
What will be a better approach in current context and upholding RESTful principles ? Also are there other trade-offs i should be aware of ? what about parsing a json with a huge string field (~ 200 Kb)embedded?
EDIT :- I was reading some similar questions on SO and one approach that stood out was the 2-step approach of making a first call with metadata to create the entity and then upload the file as an UPDATE process to the created entity wherein we use multipart/form-data. In that context, I guess , what I am asking is how sound is an approach where I send both metadata and the file in a single api call as multipart data , where each metadata field is actually a part in the multipart message as is the file.
The canonical way to upload files to REST API is using the multipart/form-data. As W3 recommendation guide says:
The content type "multipart/form-data" should be used for submitting
forms that contain files, non-ASCII data, and binary data.
Multipart/form-data has advantages over base64 to represent binary data. Is sticked to REST/Http philosophy, and simplify the develop of API clients.
Returning values from Forms: multipart/form-data
W3 Recommendation guide
The good practice is to use multipart/form-data whenever files are uploaded to the server along with database fields. Do not send a base64 JSON string as the request to your Rest API as it might corrupt the file or degrade the performance of your application.
As far as documenting multipart/form-data Rest API for your consumers is concerned you have to force your API consumers to use the same form fields which you have predefined in your web service.
Returning Values from Forms: multipart/form-data
I started using FormData objects everywhere on the client-side, in lieu of regular form input fields, for dynamic REST posts. FormData is presented in a positive light in various tutorials, so I went with it.
However, down the line, this caused me problems when decoding the form data into my Go structs. FormData objects are sent as "multipart/form-data" (regardless of files being sent) and I believe my decoder in Go didn't convert the raw data back to string form. Eventually my SQL queries were throwing panics, as hex data was being sent in where strings should have been.
So with some adjustment, I could use FormData however I've decided to revert to the simple universal recommendation: Use "multipart/form-data" only for special cases like when sending files. Otherwise, just use regular "application/x-www-form-urlencoded".

Add custom header on non-ajax post

AFAIK it's not possible to set a header field when a form is submited, it can only be done in ajax requests
This questions also points that it's not possible:
How to set a Header field on POST a form?
Custom HTTP Request headers in HTML
But reading Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet it's mentioned that:
Encrypted Token Pattern
Overview
The Encrypted Token Pattern leverages an encryption, rather than
comparison, method of Token-validation. After successful
authentication, the server generates a unique Token comprised of the
user's ID, a timestamp value and a nonce, using a unique key available
only on the server. This Token is returned to the client and embedded
in a hidden field. Subsequent AJAX requests include this Token in the
request-header, in a similar manner to the Double-Submit pattern.
Non-AJAX form-based requests will implicitly persist the Token in its hidden field, although I recommend persisting this data in a
custom HTTP header in such cases. On receipt of this request, the
server reads and decrypts the Token value with the same key used to
create the Token.
This sentence confuses me:
I recommend persisting this data in a custom HTTP header in such cases
Could anyone shed some light on it?
Yes, the sentence implies that the POST operation is invoked by a custom JavaScript handler in order to inject the AUTH header. I've corrected the OWASP description to reflect this oversight.

Is there any action I could do with POST, but not with GET?

I know differences and advantages of each command, my question is could I replace POST requests with GET everywhere? And which these commands calls by default while sending request from html form?
could I replace POST requests with GET everywhere
No (and it would be a terrible idea to try).
Things that a form can do with POST that you can't do with GET include:
Sending lots of data
Sending files
There are other things that would simply be stupid to do with GET.
From http://www.w3.org/TR/html5/forms.html#attr-fs-method :
The method and formmethod content attributes are enumerated attributes
with the following keywords and states:
The keyword get, mapping to the state GET, indicating the HTTP GET
method. The keyword post, mapping to the state POST, indicating the
HTTP POST method. The invalid value default for these attributes is
the GET state. (There is no missing value default.)
When using GET to transfer data from the client to the server, the data is added to the URL, there is not BODY of the request. There is usually a limit on how long a URL can be, in the old days this was 1024 characters but that really depends on the server software and server middleware and even the browser.
This means if you want to transfer loads or data or upload a file to the server, you can not do it with GET.