Encode URL parameter values for sensitive content? - security

For those of you who often build web applications will know that at some point you will need some URL parameters sent.
The values of these parameters might even be sensitive and can be abused.
For instance, User 1 wants to vew User 2 so a URL might be
http://www.example.com/User/2
This works fine and it is easy to read the URL parameter in the code.
However this leads to a problem: If User 1 does not have access to User 2 then User 1 would easily be able to type this URL into his browser. Normally when you want to avoid access you use some form of access control (like ACL), however my question is in cases where the data is sensitive, is it better to make the URL string into an encoded string aswell?
A great example is LinkedIn. Here is a URL with what I think is an encoded parameter:
https://www.linkedin.com/hp/?dnr=wxTvRoX8KGA5n3H4yxFpQfGTcdpfl3PW5Ab5
Is there any rule for when you want to encode or not? And should you always use encoded strings?

In general, you don't want to put sensitive material into an URL. URLs have the tendency of being bookmarked, emailed, logged, etc... All things that make an URL not very private. Encoding the sensitive information is slightly better than not encoding it as the encoded information won't be accidentally viewed by someone. They'll have to intentionally decode before they can view it.
There are reasons beyond security for encoding URL parameters. A common example is to store a small binary data structure in the URL parameter such as page referrer information or a binary key into a table. My assumption is that the LinkedIn dnr parameter is encoded but not sensitive.

Related

What should I use as an endpoint to serve downloadable documents using REST API?

Right now I have an endpoint that servers a file to the user (json, csv, excel or pdf).
My question here is, which type of route should I use to serve it, path variables or query parameters (considering best practices and for developer comprehension):
baseURl/api/v1/resource/xlsx
or
baseURl/api/v1/resource?format=xlsx
Thank you in advance.
So long as you are consistent with the production rules of the http URI scheme, any spelling conventions you choose are fine.
Choosing spellings that match the capabilities of URI templates will make it easier to construct/deconstruct resource identifiers in a "common URI space", which is often convenient both for clients and servers.
Using path segments vs query is purely trade offs. Using application/x-www-form-urlencoded key value pairs in the query part mean that you can implement your URI template as an HTML form. Using path segments means that you can use dot segments to describe other identifiers in the common URI space.
If you don't care about either of those, it just comes down to which spellings you like best in an access log, or in your documents, or in a browser history, or when you paste them into an email message, or ....
It is best practice to use headers for HTTP to show what format the client can understand. You should use a get route and include the Accept header for the format.
Header key: Accept
Header Value: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept
HTML Input="file" Accept Attribute File Type (CSV)

Saving property with HTML - encode on entry, or on display?

I have a system which allows users to enter HTML-reserved characters into a text area, then post that to my application. That information is then saved to a database for later retrieval and display. Alarms are (should be) going off in your head. I need to make sure that I avoid XSS attacks, because I will display this data somewhere else in the application. Here are my options as I see it:
Encode before save to DB
I can HTML-encode the data on the way in to the database, so no HTML characters ever are entered in the database.
Pros:
Developers don't have to remember to HTML encode the data when its displayed on the web page.
Cons:
The data now doesn't make sense for desktop-based applications (or anything other than HTML). Stuff shows up like < > & etc.
Don't HTML encode before saving to DB
I can HTML encode the data whenever I need to display it on a web page.
Pros:
Feels right because it keeps the integrity of the data that was entered by the user.
Allows non-HTML based applications to just display this data without having to worry about HTML encoding.
Cons:
We might display this data in a lot of places, and we'll have to make sure that every developer knows that when you display this field, you'll need to HTML encode it.
People forget things. There WILL be at least once instance when we forget to HTML encode the data.
Scrub the data before saving to DB (don't HTML encode)
I can use a well-tested third party library to remove potentially dangerous HTML and get a safe HTML fragment to save the database, not HTML encoded.
Pros:
Preserves most of the original input so that display in a non-HTML format makes sense.
Less catastrophic if the developer forgets to HTML encode this information for display on a web page.
Cons:
Still messes with the data as the user originally entered it. If they really want to type a <script> or <object> tag, it won't make it, and we'll get support calls and emails because of that.
My question is: What is the best option, or if there is another way of going about this, what is it?
The right thing to do is not mangle/change user input.
So, do not encode before saving.
Yes, this puts the onus on the developers to remember and know that they need to encode anything coming out of the DB, but this is good practice regardless.

Eliminate < > as accepted characters in a wordpress password?

Is it possible to eliminate these characters from a wordpress password? I have heard that it can open up scripts this way, that hackers can use to get in. Thank you.
Simple answer:
Your friend has misinformed you. Restricting these characters in a wordpress password is not something you need to worry about. But as they say "There is no smoke without fire".
More background information:
In your own web-application code, you should always be especially careful whenever you take any data from a user (Whether from a form, a cookie,or a URL) or another external computer system or application. The reason for this is that you want to avoid the values being interpreted as code and not just used as data.
The issue that has led your friend to worry about the <> characters is called Cross-Site Scripting and is a kind of attack that malicious users can perform to "inject" html or javascript content into your pages. If you accept information from the user that contains these html mark-up characters and re-display it on the same, or another page, then you can cause their html or javascript content to become part of your page. Any javascript content will run with access to the same data as the user that views the page.
Whenever outside data is read, it sould always be
validated : i.e. checked that it looks like the kind of thing you are expecting, and rejected if it doe not.
and encoded: i.e. When this data is displayed to back to the user or sent to another part of the system, it is converted to be safe. The type of conversion always depends on how and where the data is being used.
Please note that the angle-bracket characters are not the only thing to worry about. Please also note that it is well proven that disallowing certain characters (also called "blacklisting") is never the best way to secure code. It is always safer to state what is allowed (also called "whitelisting").

Do you HtmlEncode during input or output?

When do you call Microsoft.Security.Application.AntiXss.HtmlEncode? Do you do it when the user submits the information or do you do when you're displaying the information?
How about for basic stuff like First Name, Last Name, City, State, Zip?
You do it when you are displaying the information. Preserve the original as it was entered, convert it for display on a web page. Let's say you were displaying it in some other way, like exporting it into Excel. In that case, you'd want to export the preserved original.
Encode every single string.
You should only encode or escape your data at the last possible moment, whether that's directly before you put it in the database, or display it on the screen. If you encode too soon, you run the risk of accidentally double encoding (you'll often see &amp; on newbies' websites - myself included).
If you do want to encode sooner than that, then take measures to avoid the double encoding. Joel wrote an article about good uses for hungarian notation, where he advocated use of prefixes to determine what is stored in the variable. eg: "us" for unsafe string, "ss" for safe string.
usFirstName = getUserInput('firstName')
ssFirstName = cleanString(usFirstName);
Also note that it doesn't matter what the type of information is (city, zip code, etc) - leaving any of these unchecked is asking for trouble.
It depends on your situation. Where I work, for years the company did no HTML encoding, so when we started doing it, it would have been almost impossible to find every location within the system that user input could be displayed on the page.
Instead we chose to sanitize input on its way into the system since there were fewer input points than output points. We sanitize immediately before inputting data into the DB, although we don't use Microsoft's AntiXss library, we use a set of homebrew methods that whitelist ranges of HTML tags and characters depending on the type of input.
If you're designing the system from scratch, or you have a system that is small (or managed well) enough to encode output, follow Corey's suggestion. It's definitely the better way to do it.
Encoding is not a property of the data, it is a property of the transport mechanism. Therefore you should unencode data when you receive it, and encode it appropriately before transmission. The transport mechanism determines what sort of encoding is necessary.
This principle holds true whether your transport mechanism is HTML, HTTP, smoke signals, etc. The trick is knowing how to do the types of encoding manually, and when various frameworks do the steps for you automagically. For instance, ASP.NET will encode data assigned to a System.Web.UI.WebControls.Button's Text, but not text assigned to a System.Web.UI.WebControls.Literal's Text. jQuery will encode content you set with .innerText(), but not content you set with .innerHtml().

Will HTML Encoding prevent all kinds of XSS attacks?

I am not concerned about other kinds of attacks. Just want to know whether HTML Encode can prevent all kinds of XSS attacks.
Is there some way to do an XSS attack even if HTML Encode is used?
No.
Putting aside the subject of allowing some tags (not really the point of the question), HtmlEncode simply does NOT cover all XSS attacks.
For instance, consider server-generated client-side javascript - the server dynamically outputs htmlencoded values directly into the client-side javascript, htmlencode will not stop injected script from executing.
Next, consider the following pseudocode:
<input value=<%= HtmlEncode(somevar) %> id=textbox>
Now, in case its not immediately obvious, if somevar (sent by the user, of course) is set for example to
a onclick=alert(document.cookie)
the resulting output is
<input value=a onclick=alert(document.cookie) id=textbox>
which would clearly work. Obviously, this can be (almost) any other script... and HtmlEncode would not help much.
There are a few additional vectors to be considered... including the third flavor of XSS, called DOM-based XSS (wherein the malicious script is generated dynamically on the client, e.g. based on # values).
Also don't forget about UTF-7 type attacks - where the attack looks like
+ADw-script+AD4-alert(document.cookie)+ADw-/script+AD4-
Nothing much to encode there...
The solution, of course (in addition to proper and restrictive white-list input validation), is to perform context-sensitive encoding: HtmlEncoding is great IF you're output context IS HTML, or maybe you need JavaScriptEncoding, or VBScriptEncoding, or AttributeValueEncoding, or... etc.
If you're using MS ASP.NET, you can use their Anti-XSS Library, which provides all of the necessary context-encoding methods.
Note that all encoding should not be restricted to user input, but also stored values from the database, text files, etc.
Oh, and don't forget to explicitly set the charset, both in the HTTP header AND the META tag, otherwise you'll still have UTF-7 vulnerabilities...
Some more information, and a pretty definitive list (constantly updated), check out RSnake's Cheat Sheet: http://ha.ckers.org/xss.html
If you systematically encode all user input before displaying then yes, you are safe you are still not 100 % safe.
(See #Avid's post for more details)
In addition problems arise when you need to let some tags go unencoded so that you allow users to post images or bold text or any feature that requires user's input be processed as (or converted to) un-encoded markup.
You will have to set up a decision making system to decide which tags are allowed and which are not, and it is always possible that someone will figure out a way to let a non allowed tag to pass through.
It helps if you follow Joel's advice of Making Wrong Code Look Wrong or if your language helps you by warning/not compiling when you are outputting unprocessed user data (static-typing).
If you encode everything it will. (depending on your platform and the implementation of htmlencode) But any usefull web application is so complex that it's easy to forget to check every part of it. Or maybe a 3rd party component isn't safe. Or maybe some code path that you though did encoding didn't do it so you forgot it somewhere else.
So you might want to check things on the input side too. And you might want to check stuff you read from the database.
As mentioned by everyone else, you're safe as long as you encode all user input before displaying it. This includes all request parameters and data retrieved from the database that can be changed by user input.
As mentioned by Pat you'll sometimes want to display some tags, just not all tags. One common way to do this is to use a markup language like Textile, Markdown, or BBCode. However, even markup languages can be vulnerable to XSS, just be aware.
# Markup example
[foo](javascript:alert\('bar'\);)
If you do decide to let "safe" tags through I would recommend finding some existing library to parse & sanitize your code before output. There are a lot of XSS vectors out there that you would have to detect before your sanitizer is fairly safe.
I second metavida's advice to find a third-party library to handle output filtering. Neutralizing HTML characters is a good approach to stopping XSS attacks. However, the code you use to transform metacharacters can be vulnerable to evasion attacks; for instance, if it doesn't properly handle Unicode and internationalization.
A classic simple mistake homebrew output filters make is to catch only < and >, but miss things like ", which can break user-controlled output out into the attribute space of an HTML tag, where Javascript can be attached to the DOM.
No, just encoding common HTML tokens DOES NOT completely protect your site from XSS attacks. See, for example, this XSS vulnerability found in google.com:
http://www.securiteam.com/securitynews/6Z00L0AEUE.html
The important thing about this type of vulnerability is that the attacker is able to encode his XSS payload using UTF-7, and if you haven't specified a different character encoding on your page, a user's browser could interpret the UTF-7 payload and execute the attack script.
One other thing you need to check is where your input comes from. You can use the referrer string (most of the time) to check that it's from your own page, but putting in a hidden random number or something in your form and then checking it (with a session set variable maybe) also helps knowing that the input is coming from your own site and not some phishing site.
I'd like to suggest HTML Purifier (http://htmlpurifier.org/) It doesn't just filter the html, it basically tokenizes and re-compiles it. It is truly industrial-strength.
It has the additional benefit of allowing you to ensure valid html/xhtml output.
Also n'thing textile, its a great tool and I use it all the time, but I'd run it though html purifier too.
I don't think you understood what I meant re tokens. HTML Purifier doesn't just 'filter', it actually reconstructs the html. http://htmlpurifier.org/comparison.html
I don't believe so. Html Encode converts all functional characters (characters which could be interpreted by the browser as code) in to entity references which cannot be parsed by the browser and thus, cannot be executed.
<script/>
There is no way that the above can be executed by the browser.
**Unless their is a bug in the browser ofcourse.*
myString.replace(/<[^>]*>?/gm, '');
I use it, then successfully.
Strip HTML from Text JavaScript

Resources