How to get previous URL in JSF using FacesContext? - jsf

I need to get the redirected URL or id in JSF using FacesContext. For current URL, I'm using.
String currentPage = FacesContext.getCurrentInstance().getViewRoot().getViewId();

Closest you can get is the referer header via ExternalContext#getRequestHeaderMap():
String referrer = externalContext.getRequestHeaderMap().get("referer");
// ...
You should only keep in mind that this is a client-controlled value and can thus be fully spoofed from client side on (i.e. the enduser can easily edit or even remove it).
Even then, there are cases where the client application won't send it along. For an overview, see among others this question: In what cases will HTTP_REFERER be empty.
Depending on the functional requirement, you'd better manually pass it along as request parameter, or store it in view or session scope.

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.

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.
}

Alter Query Strings Server Side

I have an Express application that gets search parameters and page numbers via query strings.
var name = req.query.name;
var state = req.query.state;
var category = req.query.category;
var pageNum = req.query.pagenum;
What I want is if the search query has a page number and yields no results, to do a search without the page number and pass that back to the client. This works fine, and the front-end is receiving the data correctly.
The only thing is that I want the URL to reflect the changed page number search, so rather than being website.com/search?page=4&state=AL I'd like it to have the page number stripped or changed to 1. I can do this via Javascript on the front-end, but I'd rather have the url changed on the server side (it makes more sense to me at least, rather than having to change every template to do that).
EDIT:
Looks like the only way of doing this is to redirect to the URL without the page query string parameter. It seems this will help me out in getting this done.
I don't quite know your environment, but generally URLs cannot be "changed" on server-side, because they are displayed in the browser on the client-side. The user sees the last whole page request's url. You can only force an URL update (actually a page reload with different URL) from server-side with a HTTP redirect header.
You could check if there are any results for the query with page number, and if not, simply send a redirect to the URL without the page number, so the user sees that extended result with its proper (page-less) URL.
Hope it helps something.

Security and GET-parameter or page-parameter in Seam/JSF

Page parameter (in Seam) or GET parameter (general) are often mentioned as a proper means to transfer information from one view to another. But obviously it is not a good idea to have sensitive data in the url, e.g //myserver/show.jsf?userId=12, since it is easy to manipulate these params and look at data someone is not permitted to look at.
So far I've been using what examples and literature show (couse until now was not important):
<s:link..>
<f:param value="#{user.id}" name="userId" />
</s:link>
in the JSF-file and in the according target page.xml
<param name="userId" value="#{userHome.userId}" />
I am interested in two things (still kind of new to Seam):
1) What different possible strategies of securing unpermitted access, to e.g. different user accounts, are you using, if you want to stick to page parameter? I'm sure some of you have been facing that challenge already. And what are the pros and cons of these strategies.
2) I want to make use of the Seam EntityHome objects here and there in the project since it is a comfortable handling of entities and kind of a DAO structure - but how to efficiently work with HomeObjects if not using page parameter?
Would appreciate to some thoughts and experiences from you guys. Thanks a lot.
josh
GET parameters are not inherently unsafe, all REST services rely on data being put in the URL. Parameters (GET or POST) are unsafe if your user detail page, in your example, does not check if you actually have access to user account "12". Also, don't think POST parameters are any harder to manipulate than GET parameters.
So, your code should check if you are entitled to view sensitive data. To handle unauthorized access, you can just throw an org.jboss.seam.security.AuthorizationException in the setUserId() method if the user is setting an ID he is not entitled to. Launching this exception makes Seam follow the exception handling mechanism described in pages.xml (by default it redirects to the /error.xhtml page with an error message).
#In Identity identity; // The standard Seam Identity component
#In Long sessionUserId; // You should outject this during user login
public void setUserId(Long userId) {
// Grant access is user is an admin or his id is the same as the one
// he is trying to set. Otherwise, exception.
if (!identity.hasRole('admin') && !sessionUserId.equals(userId)) {
throw new AuthorizationException("Not authorized");
}
this.userId = userId;
}

JSF: How to capture response that is send to client

I want to implement some kind of help-functionality within my jsf-application
Scenario:
When the users of my app are having problems, they send me screenshots. These are of poor quality and I cannot see the information I want.
My idea: I add a "help"-Button into my jsf-Page. When this button is pressed I store the render-response (resulting html) that is send to client on my hd.
Now I can open that generated html-file and can see the information I want (e.g. values of inputfield)
Now my Question.
How can I perform this task?
I have tried PhaseListener and using
PrintWriter w = new PrintWriter(System.out);
DebugUtil.simplePrintTree(FacesContext.getCurrentInstance().getViewRoot(),"",w);
but this is just the component tree and not the resulting html
In other words: I want to capture the output of FacesContext.getExternalContext().getResponse() that is send to client
any ideas?
Use a Filter around the FacesServlet. There define a HttpServletResponseWrapper and in turn make its getOutputStream() and getWriter() return wrappers of the original objects. In the wrappers, in addition to delegating to the original implementation, store the written data somewhere else.

Resources