How to encrypt ViewState (server stored) that generates colon separated random numbers on client? - jsf

I have an application build on top of Mojarra 2.1.20 (package com.sun.faces, RI for JSF 2.2 specification).
I have a context param javax.faces.STATE_SAVING_METHOD with value as server specified in my application deployment descriptor file web.xml
JSF is injecting the following ViewState hidden element on my post login page
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="random_number1:random_number2" autocomplete="off" />
The hidden element has value in some random number format and separated by a colon.
Since STATE_SAVING_METHOD is server, the actual ViewState in my case is getting stored on the server. But the client is just getting the unique ViewState identifier or random numbers from the server. My understanding is that when user submits a form with this hidden element, the server extracts these random numbers, identifies the actual ViewState from these numbers and then processes the request and sends back the response to the client/user.
Based on the above understandings, I have following queries on the ViewState and its vulnerabilities-
Why two colon separated random numbers instead of one? What these two
colon separated random numbers represents? What autocomplete="off" means?
Does these server generated random number map to actual ViewState
stored on the server? Is this understanding correct?
Are these server generated random numbers already in encrypted
format? Is encryption required on these random numbers to potentially
avoid data leak and other vulnerabilities in the application?
How to encrypt these random numbers in my case when ViewState is
saved on server?
Could we somehow avoid injection of the element in sources without
getting displayed as hidden element?

Why two colon separated random numbers instead of one? What these two colon separated random numbers represents?
The view state is basically stored in a nested map like as Map<FirstId, Map<SecondId, ViewState>>. This map is in turn stored in the HttpSession. The first ID is the 'logical' view ID (basically representing XHTML page itself) and the second ID is the 'actual' view state ID.
What autocomplete="off" means?
It prevents web browsers from autofilling the value of the input element with previously submitted value from the browser cache. It should not be needed because the value is already prepopulated and the input element is a hidden type, but older Firefox versions were known to incorrectly overwrite this. Using autocomplete="off" is basically a work around against them.
Does these server generated random number map to actual ViewState stored on the server? Is this understanding correct?
Yes.
Are these server generated random numbers already in encrypted format? Is encryption required on these random numbers to potentially avoid data leak and other vulnerabilities in the application?
No.
How to encrypt these random numbers in my case when ViewState is saved on server?
Not needed.
Could we somehow avoid injection of the element in sources without getting displayed as hidden element?
Not needed. You would in first place still need the JSESSIONID cookie in order to be able to successfully perform view state injection. But when one already has the JSESSIONID cookie at hands then you've anyway much bigger problems than only ViewState tampering, such as potentially a gaping XSS hole. Moreover, in case of server side state saving the "injected" view state can only be user's own view state obtained from another page in the same HTTP session and absolutely not a random one from a completely different user/session.
Your security concern would only apply if the view state was stored in the ServletContext (the application scope) instead of in the HttpSession (the session scope). But this is clearly not the case.
See also:
Reusing ViewState value in other session (CSRF)
Why JSF saves the state of UI components on server?
com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews
CSRF, XSS and SQL Injection attack prevention in JSF

Related

What kinds of security vulnerabilites can be instroduced by binding specifically GET request data to page model properties?

I'm reading tutorials on ASP .NET Core and Razor Pages.
One of them, when dealing with the BindProperty attribute, has remarks I find hardly understandable:
Razor Pages, by default, bind properties only with non-GET verbs.
Binding to properties can reduce the amount of code you have to write.
Binding reduces code by using the same property to render form fields
(<input asp-for="Customer.Name" />) and accept the input.
For security reasons, you must opt in to binding GET request data to
page model properties. Verify user input before mapping it to
properties. Opting in to this behavior is useful when addressing
scenarios which rely on query string or route values.
To bind a property on GET requests, set the [BindProperty] attribute's
SupportsGet property to true: [BindProperty(SupportsGet = true)]
(emphasis mine) Source: Introduction to Razor Pages in ASP.NET Core § Writing a basic form
I do not understand. Why do extra security measures need to be taken when dealing specifically with GET requests?
As far as I can tell, GET requests are supposed to be safer, not less safe than POST requests, because GET only retrieves data, while POST sends data to the server. So, more often than not, POST requests need extra security measures GET reqs don't need.
And yet now I'm reading that it's fine to do X with POST but careful, don't do this with GET recklessly, you must opt-in and be warned, take precautions!
Why are these warnings necessary? What kind of security vulnerabilities can be introduced by binding GET request data to page model properties? And why are these vulnerabilites not applicable to POST requests?
Binding is two-way model, meaning it binds a given element for both rendering ("show this value here") and submitting back ("save this value there"). For example, you'd use binding to populate an input field with a value that a user could then update and POST back. Binding handles dealing with the value automatically.
If you simply want to display a value, you don't need to use binding at all. Simply make it a public property of your model and reference it directly ({Model.PropertyName}).
There are a bunch of reasons for avoiding [BindProperty(SupportsGet = true)] but I think HTTP's RFC 7231, Section 9.4 covers it well:
URIs are intended to be shared, not secured, even when they identify secure resources. URIs are often shown on displays, added to templates when a page is printed, and stored in a variety of unprotected bookmark lists. It is therefore unwise to include information within a URI that is sensitive, personally identifiable, or a risk to disclose.
Authors of services ought to avoid GET-based forms for the submission of sensitive data because that data will be placed in the request-target. Many existing servers, proxies, and user agents log or display the request-target in places where it might be visible to third parties. Such services ought to use POST-based form submission instead.
Since the Referer header field tells a target site about the context that resulted in a request, it has the potential to reveal information about the user's immediate browsing history and any personal information that might be found in the referring resource's URI.

How to manipulate a view state data in web application?

I am testing a web application which is an attendance submitting page. The functionality is that if two users happen to update same student attendance we shall display a warning of the change with the latest change.
For this Developers have implemented some logic like they will save the value that we enter in text box which are not yet saved in view state.They will be comparing values of view state, current data and database data and display the latest change.
As part of testing, I would like to know is there anyway so that I can modify/hack the data that developer store in view state.
You cannot do that using javascript, You can access the Hidden field "__ViewState" through JavaScript but it is all encrypted. You can only see the encrypted values.
Even if you change it through javascript, server side it will check if the data is tampered.
You can decrypt and see viewstate using below code. For this to work the ViewState must be set as not encrypted More Info
string str = System.Text.Encoding.ASCII.GetString(Convert.FromBase64Strin‌​g(txtViewState.Text)‌​);
But tampering viewstate is not quite possible since EnableViewStateMac property is true by default in ASP.NET
More Info

Populate form with cookies in Facelets page

Filling some inputs of a form in a JSP page using Servlets is quite straightforward: set attribute value of the input to the value of the cookie:
<input id="id" type="text" value="${cookie.name.value}">
and the Servlet just reads the parameters from request and assign them to the bean.
Now I am using JSF 2.2 + Facelets and in this case the value attribute is directly linked to the bean:
<h:inputText value="#{Bean.property}"/>
and there is no need to write a Servlet.
I guess I can just use an intermediate backing bean and assign the values to the real one when processing the form submission but it does not feel right.
What is the best way to do this?
UPDATE
I want to clarify my intentions:
The form is big, and part of it is just gathering user data (name, telephone, email address, etc).
I don't want to implement a sign up / sign in system because it is not going to be used frequently and it is only for a reduced (but not fixed) number of users. So it is better to make the user fill its data everytime than making the user sign up in our system, with all the added complications: the user has to remember login details that will be used maybe once a month or even less, we have to implement the login system, add security...
But, in order to make filling the form easier, I think is a good idea to store user data in cookies, and the next time the user needs to use the form, the part of it that just ask for user data (which it would not have changed, probably) is filled automatically.
So, the idea is:
The first time, the user fills the whole form: the data we actually need and the user information for contact purposes: name, telephone, email address, etc.
The next time, given that the user is on the same computer, the part of the form that gathers user information for contact purposes is already filled using the cookies. The user can edit contact details if needed before submitting the form, of course.
In summary, I can't use a resource bundle with defaults, because it's different for every user, and implementing a login system is quite overkill. That's why I want to use cookies to automatically fill part of the form, but I don't know what's the best way to do this using JSF.

solution for: select input, dropdown tampering prevention

for hidden field tampering protection: Id, RowVersion, I use a version of Adam Tuliper AntiModelInjection.
I'm currently investigating a way to prevent tampering of valid options found in select lists/drop downs. Consider a multitenant shared database solution where fk isn't safe enough and options are dynamic filtered in cascading dropdowns.
In the old days of ASP.NET webforms, there was viewstate that added tampering prevention for free. How is select list tampering prevention accomplished in ajax era? Is there a general solution by comparing hashes rather than re-fetching option values from database and comparing manually?
Is ViewState relevant in ASP.NET MVC?
If you can, the single solution here is to filter by the current user ids permission to that data, and then those permissions are validated once again on the save.
If this isn't possible (and there are multiple ways server side to accomplish this via things like a CustomerId fk in your records, to adding to a temporary security cache on the server side, etc) , then a client side value can provide an additional option.
If a client side option is provided like was done with Web Forms, then consider encrypting based on their
a.) User id plus another key
b.) SessionId (session must be established ahead of time though or session ids can change per request until session is established by a value stored in the session object.
c.) Some other distinct value
HTTPS is extremely important here so these values aren't sniffed. In addition ideally you want to make them unique per page. That could be the second key in A above. Why? We don't want an attacker to figure out a way to create new records elsewhere in your web app and be able to figure out what the hashes or encrypted values are for 1,2,3,4,5,6,etc and create essentially a rainbow table of values to fake.
Leblanc, in my experience, client side validation has been used mostly for user convenience. Not having to POST, to only then find out that something is wrong.
Final validation needs to occurs in the server side, away from the ability to manipulate HTML. Common users will not go on to temper with select lists and drop downs. This is done by people trying to break your page or get illegal access to data. I guess my point is final security needs to exist in the server, instead of the client side.
I think a global solution could be created given a few assumptions. Before i build anything I'll like to propose an open solution to see if anyone can find flaws or potential problems.
Given all dropdowns retrieve their data remotely. - in an ajax era and with cascading boxes this is now more common. (We are using kendo dropdowns.)
public SelectList GetLocations(int dependantarg);
The SelectList will be returned back as json - but not before having newtonsoft serialization converter automatically inject: (done at global level)
EncryptedAndSigned property to the json. This property will contain a Serialized version of the full SelectList containing all valid values that is also encrypted.
EncryptedName property to the json. This property will have the controller actionname - For this example the EncryptedName value would be "GetLocations"
When the http post is made EncryptedName : EncryptedAndSigned must be sent in the post also. For this JSON POST example it would be:
{
Location_Id: 4,
GetLocations: 'EncryptedAndSigned value'
}
On the server side:
[ValidateOptionInjection("GetLocations","Location_Id")
public ActionResult Update(Case case)
{
//access case.Location_Id safety knowing that this was a valid option available to the user.
}

Should I sanitize user input upon 'before_validate' or 'before_save'?

If I receive user input, does it make any difference if I validate first and then sanitize before saving it to the database?
Or is there any risk in validating unsanitized input?
(when I say 'sanitize' I mainly mean stripping out any HTML tags)
UPDATE & CLARIFICATION:
I wouldn't put HTML tags into the database. I would sanitize the input before saving it - but after validating against my model. The reason the validation and sanitization are separate is because they are separate libraries - the only question is whether I should call 'sanitize' upon 'before_validate' or upon 'before_save'.
The only risk I can think of is if you are performing extensive client-side validation. If you were validating and then spitting the values back onto the page in your error messages then you could have an issue.
For example, if you have a textbox that has to only contain numbers and a user enters a letter in that textbox. If your client side script generates an error message like " 'somevalue' is an invalid value for this textbox ", then you are injecting whatever the user has entered into the box back onto the page. Either way, it will only affect that user's session.
Why are you separating HTML stripping (or escaping) from other validation? Isn't it all the same thing?
And why would you put HTML tags into the database only to strip them later? Doesn't that mean that your database is temporarily incorrect?
I don't see why you're separating "validation" from "sanitize". They're two sides of the same coin. Do everything you can to make sure the data is perfect before committing it to the database.
"the only question is whether I should call 'sanitize' upon 'before_validate' or upon 'before_save'."
The distinction is too subtle for words. You must do both. Generally, you do not want to try and validate HTML.
Therefore, it's only sensible if you (1) "sanitize" to strip HTML tags and then (2) validate what's left.
I'm not sure how else you could do it.
ALWAYS validate and sanitize before submitting to the database. Without doing so, you could expose your database to SQL injection attacks.
What order you do so depends on what you want your user experience to be. If you validate first, then you could provide validation back to the user easier (You could use javascript and regular expressions to do this)
Required xkcd cartoon:

Resources