Adding additonal Security to Website - java

I am running a Java Spring MVC based Web-Application. It is also based on the Hybris Platform.
Now, the basic functionality in terms of Authentication and Authorization is already implemented. Meaning we do have filters for sessions, a working user-system, etc.
However, we currently have no security measurements against things such as XSS and other kinds of possible attacks that are out there.
XSS is probably the biggest concern as it is the most common possible way of attacking.
Now, i wonder ... what steps would be smart to take?
I have taken a look around and i have seen that stuff like XSS-Filter exist.
Implementing such would be pretty easy, just copy past the source and add it as a in tomcats web.xml.
But i wonder if that is a satisfying amount of security from such filter?
There are also way more bloated solutions, for example i could use the spring-security.
However, reading the documentations, i feel like this is very bloated and a large part of it implements what is already implemented ( the two A's, for example). I feel like it would take a lot of work to configure it down to the amount of work that i need it to do. Am i wrong?
And:
How would you say is it recommended to deal with security issues, for example XSS? Do you use a certain predefined framework that suits the needs or is your security "hand-made" by following things like the cheat sheet?

Set Anti-XSS Headers (hint: use Spring Security or make your own Interceptor)
Content-Security-Policy: default-src 'self' --only allow content from your own site
X-XSS-Protection: 1; mode=block --prevent some reflective attacks in some browsers
X-Content-Type-Options: nosniff --can't trick browser into detecting and running js in other content types
Prevent malicious inbound HTML/JS/CSS
Use Hibernate Validator (you don't need to use Hibernate ORM to use this) with the #SafeHtml annotation on all user-supplied String fields.
You could validate all request headers, post params and query params in one Interceptor for simplistic XSS validation.
Escape all user-supplied data on output
Use OWASP's Java Encoder Project <e:forHtml value="${attr}" /> to escape output or JSTL's <c:out value="${attr}"/> and in web.xml set
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
They are equally safe if escaping HTML node text, but OWASP is safer for HTML attribute or <script> escaping.
If you have too many files to edit, consider http://pukkaone.github.io/2011/01/03/jsp-cross-site-scripting-elresolver.html
Make your session cookie unreadable by JavaScript. In web.xml:
<session-config>
<cookie-config>
<!-- browser will disallow JavaScript access to session cookie -->
<http-only>true</http-only>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
If you are hosting user-uploaded files, you need to use a different domain (not subdomain) for download links, so that evil content cannot clobber your session cookie (yes, this can happen even if it's httpOnly)

I'd like to add this answer, as i think it is a simple but important thing to notice:
In my case i realised that i do not need to allow any kind of critical special characters for user input. I analysed the situation and realised that it makes no sense and that there is no need to do so in any of my webpages.
So, instead of having to implement proper styled XSS-safe code on about 60k existing lines of code, i could simply install a filter that would purge out all special characters, that i do not want to allow.
You could see this a little critical in terms of user-friendliness, but it should be OK.
So: If you realise that you do not need to allow any special characters, that are going to be critical in one of the possible contexts (such as JS,HTML,attributes, ... ), then you could safe a lot of work, given that you are in the same situation that i am/was in.
Obviously implementing the steps mentioned by Neil is still proper style if you are doing your work from scratch.
If people had known these steps before all the JS and JSP stuff was written they surely would have implemented them, potentially needing them or not shouldnt matter.

Here is a list of things concerning hybris security that I've done on my projects :
First read documentations
Below links are full of resources and details about security in hybris.
Non fuctional requirement
Data protection
Deployment check list
SAP Commerce Security
XML parser
We often need to import data from xml.
All Sax parser should use below features :
XMLConstants.FEATURE_SECURE_PROCESSING = true
http://xml.org/sax/features/external-general-entities = false
http://xml.org/sax/features/external-parameter-entities = false
http://apache.org/xml/features/disallow-doctype-decl = true
It allows to
instructs the implementation to process XML securely. This may set limits on XML constructs to avoid conditions such as denial of
service attacks.
do not include external general entities.
do not include external parameter entities or the external DTD subset
throw a fatal error if the incoming document contains a DOCTYPE declaration
JSON
All input must be validated using the OWASP lib json-sanitizer. See https://www.owasp.org/index.php/OWASP_JSON_Sanitizer
Example :
String wellFormedJson = JsonSanitizer.sanitize(jsonData);
try
{
return new ObjectMapper().readValue(wellFormedJson, JsonNode.class).toString();
}
catch (final IOException ex)
{
LOG.error("Incorrect json data : " + wellFormedJson, ex);
}
LOG
String coming from outside the application must not be directly logged to prevent log injection.
Controller case
In web context all controllers must extends BaseController. This class contains the method logParam which should be used to log something unknown.
This method uses YSanitizer.sanitize(input).
public class YSanitizer
{
public static String sanitize(final String input) {
String output = StringUtils.defaultString(input).trim();
output = output.replaceAll("(\\r\\n|\\r|\\n)+", " ");
output = StringEscapeUtils.escapeHtml(output);
return output;
}
}
Other case
Calling StringEscapeUtils.escapeJava(valToLog) should be enough.
Protect sensitive data from heap inspection
Because heap can be inspected, sensitive data should not be stored in String objects.
Indeed Strings are immutable and can stay in the heap for a while.
To prevent this issue all sensitive strings must be stored in a char[].
This array should be filled with "0" as soon as possible (when the value is not needed).
Not that this method is not 100% safe but reduced the time window to find the password in the heap.
Cross-Site Scripting (XSS)
Make sure de.hybris.platform.servicelayer.web.XSSFilter is in the filters list of incoming requests
Deployment checks (from Go-Live Checklist)
Verify that the default passwords for all users have been changed
Change admin user password for production
Disable automatic login or pre-populated passwords for
Product cockpit
CMS cockpit
CS cockpit
hMC
Password encoding should be MD5 or better SHA256
Change default password encoder
Change SALT for MD5 and SHA256 password encoder
Verify the database password and the requirement to store them in plain text in local.properties.
Verify that user account and checkout pages are only accessiable via a secure SSL connection
Check that a Web application firewall is in place
Perform a code review to ensure that no sensitive data, like credit card information or passwords, are logged to the log file
Verify that the hybris application server is not running as root
Secure the JMX connected

Related

How does state get encoded or encrypted in Spring OAuth2?

How specifically is the state parameter related to the _csrf token in Spring OAuth2? Is state an encrypted version of _csrf as we would expect it to be?
Also, what specific Java syntax should be used to encode and encrypt a new _csrf value before encapsulating it into a new state parameter in Spring OAuth2?
THE CONTEXT
A client app redirects the user's web browser from the client app to the authorization server's authserver/login page. Then, in the authorization server app, a custom implementation of OncePerRequestFilter is used to redirect a request to /oauth/authorize?(list of params) into additional authentication steps, which ultimately redirect back into a new request to /oauth/authorize?(list of params). The problem is that the _csrf token changes during the additional authentication steps, and the documentation indicates that _csrf is used as the state parameter. This implies that the state value probably needs to be updated by the authorization server to reflect the new _csrf value.
HOW state IS GENERATED
The problem is that the encoded and encrypted value for state has already been set by the client app before the client app uses an OAuth2ClientAuthenticationProcessingFilter to transfer information for the authentication server to use while authenticating the user via the authentication steps mentioned above.
Some research indicates that the state key is generated by the client using a DefaultStateKeyGenerator, which in turn uses a RandomValueStringGenrator to generate a 6 character state value.
For example, in the original request made to /oauth/authorize?(list of params), the raw _csrf value is encoded into fupS1L, as shown in the following url:
/oauth/authorize?client_id=acme&redirect_uri=http://localhost:8080/login&response_type=code&state=fupS1L
If the _csrf value changes to a69fd23a-a393-4b27-a685-a323fd31db9a during the redirect flow, the value of fupS1L in the state parameter will no longer be valid, and the resulting token will not be authorized to permit access to protected resources.
What specific syntax do I use in order to convert the new _csrf value into an encrypted value similar to fupS1L that can be passed into a functional state parameter?
Also, is there any relationship between the state variable and the _csrf token? The RandomValueStringGenerator used by DefaultStateKeyGenerator seems to simply create a random 6 character String. I would like an authoritative answer by someone who has worked deeply with the code or even written it. I am doing a deep review of the code, so a casual passer by who reads the RandomValueStringGenerator source code and says state is not related to the csrf token would not be adding any value. The author of the API, however, would help us all out a lot by telling us how this works.
NOTE TO SPRING
It should not require this much digging to find documentation of such a simple thing.
I know it's quite old since its been asked. Still sharing what I know now, as I have worked through a similar requirement to pass a deeplink in the 'state' parameter. I wanted to redirect to this deeplink when flow comes back from the auth-server after a successful oauth sign-in session.
Primarily I followed this SOF answer -> https://stackoverflow.com/a/52462787/5107365. This suggests to extend the DefaultStateKeyGenerator to use the deeplink parameter from the request to AAS to encrypt+encode to set into the 'state' parameter. And, then the custom implementation of OAuth2ClientAuthenticationProcessingFilter.AuthenticationSuccessHandler is used to override determineTargetUrl method to decode+decrypt the state parameter when the flow comes back after successful auth. Hopefully it will help somebody who is in need of a similar requirement.

Open an authenticated image served by django from java using Apache http client

I Am serving an authenticated image using django. The image is behind a view which require login, and in the end I have to check more things than just the authentication.
Because of a reason to complicated to explain here, I cannot use the real url to the image, but I Am serving it with a custom url leading to the authenticated view.
From java the image must be reachable, to save or display. For this part I use Apache httpclient.
In Apacahe I tried a lot of things (every example and combination of examples...) but can't seem to get it working.
For other parts of the webapp I use django-rest-framwork, which I succesfully connected to from java (and c and curl).
I use the login_reuired decorator in django, which makes the attempt to get to the url redirect to a login page first.
Trying the link and the login in a webviewer, I see the 200 code (OK) in the server console.
Trying the link with the httpclient, I get a 302 Found in the console.... (looking up 302, it means a redirect..)
this is what I do in django:
in urls.py:
url(r'^photolink/(?P<filename>.*)$', 'myapp.views.photolink',name='photolink'),
in views.py:
import mimetypes
import os
#login_required
def photolink(request, filename):
# from the filename I get the image object, for this question not interesting
# there is a good reason for this complicated way to reach a photo, but not the point here
filename_photo = some_image_object.url
base_filename=os.path.basename(filename_photo)
# than this is the real path and filename to the photo:
path_filename=os.path.join(settings.MEDIA_ROOT,'photos',mac,base_filename)
mime = mimetypes.guess_type(filename_photot)[0]
logger.debug("mimetype response = %s" % mime)
image_data = open(path_filename, 'rb').read()
return HttpResponse(image_data, mimetype=mime)
by the way, if i get this working i need another decorator to pass some other tests....
but i first need to get this thing working....
for now it's not a secured url.... plain http.
in java i tried a lot of things... using apache's httpclient 4.2.1
proxy, cookies, authentication negociation, with follow redirects... and so on...
Am I overlooking some basic thing here?...
it seems the login of the website client is not suitable for automated login...
so the problem can be in my code in django....or in the java code....
In the end the problem was, using HTTP authorization.
Which is not by default used in the login_required decorator.
adding a custom decorator that checks for HTTP authorization did the trick:
see this example: http://djangosnippets.org/snippets/243/

Options for passing data across HTTP redirects

I am working on a Web application and need to pass data across HTTP redirects. For example:
http://foo.com/form.html
POSTs to
http://foo.com/form/submit.html
If there is an issue with the data, the Response is redirected back to
http://foo.com/form.html?error=Some+error+message
and the query param "error"'s value is displayed on the page.
Is there any other reliable way to pass data across redirects (ie HTTP headers, etc.).
Passing the data as query params works but isn't ideal because:
its cleartext (and in the query string, so SSL cant be relied on to encyrpt) so I wouldn't want to pass sensitive data
URIs are limited in length by the browser (albiet the length is generally fairly long).
IMPORTANT: This platform is state-less and distributed across many app servers, so I can't track the data in a server-side session object.
From the client-server interaction point of view, this is a server internal dispatch issue.
Browsers are not meant to re-post the entity of the initial request automatically according to the HTTP specification: "The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD."
If it's not already the case, make form.html dynamic so that it's an HTML static file. Send the POST request to itself and pre-fill the value in case of error. Alternatively, you could make submit.html use the same template as form.html if there is a problem.
its cleartext (and in the query string, so SSL cant be relied on to
encyrpt) so I wouldn't want to pass sensitive data
I'm not sure what the issue is here. You're submitting everything over plain HTTP anyway. Cookie, query parameters and request entity will all be visible. Using HTTPS would actually protect all this, although query parameters can still be an issue with browser history and server logs (that's not part of the connection, which is what TLS protects).
I think using cookies would be a reasonable solution depending on the amount of data. As you can't track it on the server side (by using a sessions for example, which would be much simpler)
You can store error message in database on server and reference to it by id:
http://foo.com/form.html?error_id=42
If error texts are fixed you even don't need to use a database.
Also, you can use Web Storage. Instead of redirection with "Location" header you can display output page with this JavaScript:
var error_message = "Something is wrong";
if( typeof(Storage) !== "undefined" ) {
localStorage.error_message = error_message;
else {
// fallback for IE < 8
alert(error_message);
}
location.href = "new url";
And after redirection you can read localStorage.error_message using JavaScript and display the message.

Simple example of JQuery Address to manage application state

I'm using the jQuery Address library to re-write my URL depending on what the user is doing in the page. The intention is to allow users to bookmark pages and come back later. The page never refreshes as all server interaction is done via ajax.
jQuery Address is writing URLs like this:
http://localhost:9000/#/u/scott_tiger
I need a to set up a route in Play to be able to route that request through to the appropriate controller. So I set this up:
GET /#/u/{username} Controller.showUser
This doesn't work though, the route definition gets ignored. I've tried loads of things such as trying to escape the "#" and replacing it with a variable that I've populated with Character.toString(35). None of this works.
Does anyone know how I can either define the route properly or get jQuery Address not to write the "#".
EDIT: The "#" doesn't get sent to the server does it. Doh! OK, question is revised.
No. The # and the part of the URL after that is not sent to the server. So your play app on the server will never see such URLs.
HTML5 solution
You need to handle these URLs on the client side using JavaScript. In modern browsers with good HTML5 support, you can modify the address without reloading the page. See Manipulating the browser history on how to do it for these browsers. And see When can I use... for browser support.
#-URLs
On Internet Explorer and older versions of other browsers you need to use # URLs and use JavaScript to load the state (e.g. get the user page /u/scott_tiger in your example). See How to run a JavaScript function when the user is visiting an hash link (#something) using JQuery? for how to do this in JavaScript. Also if a user bookmarks a page with a #-URL you need to reload the state.
See also: What's the shebang/hashbang (#!) in Facebook and new Twitter URLs for?
JavaScript libraries
You may use JavaScript libraries to handle this for you history.js is an example. Also bigger frameworks like Backbone.js handle this.
Does anyone know how I can get jQuery Address not to write the "#".
If you don't write the #-part of the URL, the state can not be linked. So you can not get back to e.g. Scott Tigers profile page if you bookmark the page, because the URL is only http://localhost:9000/ and you will arrive on the front page, while the user though he would arrive on the profile page.
Armed with my new understanding of URLs (thanks #Jonas) I realised that I'd missed half of the story.
I'm using JQuery Address to change the URL depending on what you click in the application. This works great and on lots of browsers. What I was missing was using JQuery Address to watch for external address changes (bookmarks, history, back/forward) and respond accordingly. i.e. set the page up correctly by firing the appropriate Ajax calls and rendering that data appropriately.
Changing the address
$.address.title("new title describing application state");
$.address.parameter("q", "val1");
$.address.parameter("g", "val2");
$.address.update();
Restoring the state
$.address.externalChange(function(event) {
var val1 = event.parameters["q"];
var val2 = event.parameters["g"];
// do something with those values
});

Difference between encodeURL and encodeRedirectURL

The javadoc for javax.servlet.http.HttpServletResponse is a little vague on the difference between what rules encodeURL and encodeRedirectURL follow, are there any examples of what those exact rules are? When will the output of encodeURL differ from encodeRedirectURL?
For a concrete example, I am already generating a redirect url that I will use with response.sendRedirect(url). I get that url already encoded, but I want to add a parameter to it which has a value that is another url:
param2=http://google.com
Which of the two functions do I use to encode this?
Salam Alekom Abduallah,
I looked and looked for an answer I knew I would find it in either stackoverflow or coderanch and there I found the answer from Charles Lyons the author of the book in my hand right now it was a cheerful coincidence.
posted 8/9/2008 11:41 AM
Exactly - the difference being that encodeURL always writes the
session ID into the URL (if required e.g. because cookies are
disabled), while encodeRedirectURL contains additional logic to
determine if it is desirable to write the session ID in. It is a
really bad idea to give foreign websites the session ID for example,
since then they could impersonate your user's session. Hence
encodeRedirectURL will only put the jsessionid on the URL if that URL
lies within the current Web application, and not perform any rewriting
otherwise.
Charles Lyons (SCJP 1.4, April 2003; SCJP 5, Dec 2006; SCWCD 1.4b, April 2004)
Author of OCEJWCD Study Companion for Oracle Exam 1Z0-899 (ISBN 0955160340)
also I found this answer too which was posted earlier,
posted 4/19/2006 8:02 AM Quote Report post to moderator Hi,
The encodeURL is used to encode the url for session tracking in
forward and include mechanism. The encodeRedirectURL encodes the
specified URL for use in the sendRedirect method.
The main difference between two is, the implementation of
encodeRedirectURL method includes the logic to determine whether the
session ID needs to be encoded in the URL in the case when you are
redirecting the URL to different context where the session information
is not required or invalid. The encodeURL method do not appent the
seesion id if the cookies are enabled. In addition to this
encodeRedirectURL do not append the session information if the URL is
redirected to the different context (web application). Because the
rules for making this determination can differ from those used to
decide whether to encode a normal link, this method is separete from
the encodeURL method.
Hope this help you.
Thanks
Narendra Dhande
encodeURL() is used for all URLs in a servlet's output.
It helps session ids to be encoded with the URL.
encodeRedirectURL() is used with res.sendRedirect only. It is also used for encoding session ids with URL but only while redirecting.

Categories