Bypassing Spring Security Filter - spring-security

My implementation of AbstractPreAuthenticatedProcessingFilter overrides getPreAuthenticatedPrincipal(). In a certain circumstance, I'd like to bypass this security filter.
To do so, I returned null as per the Javadoc [EDIT] and that worked.
Note that this will not affect cases where the principal returned by
getPreAuthenticatedPrincipal(javax.servlet.http.HttpServletRequest) is
null, when the chain will still proceed as normal.

Related

How can I get a #PostAuthorize failure to cause a rollback with #Transactional?

I have some complicated access restrictions in my application which basically require looking at a combination of the user's roles, as well as some deep properties of the domain objects, to make access decisions.
For some of my methods (specifically things like getItem(Integer id) and updateItem(Integer id, FormBean form)), I can't really know ahead of time if they're allowed to access that item, as I don't have it yet, so I had been using #PostAuthorize.
However, that latter example, updateItem(id, form) presents a challenge. I only want to allow them to update the form in certain specific cases. Right now, I do see the #PostAuthorize causing them to get an HTTP 403 response when they do something they shouldn't, but the database changes aren't rolled back.
Is it possible to get #PreAuthorize, #Transactional and #PostAuthorize to all play nicely together in this case? (I think maybe by adjusting the order of some advice on them... but I'm not totally clear on how that ordering should be done).
Or, has my system gotten complex enough that I should really bite the bullet on Domain ACLs? Unfortunately, the documentation on those feels rather thin...
Spring framework used Ordered to define the ordering of beans.
The easiest way to explicit define the order for #Transactional and #PostAuthorize are through the annotations:
#EnableTransactionManagement(order = 0)
#EnableGlobalMethodSecurity(prePostEnabled = true, order = 1)
Why not use #PreAuthorize("hasPermission(#id, 'read')") and #PreAuthorize("hasPermission(#id, 'update')") and implement your own version of PermissionEvaluator?
But if you really do wish to use #PostAuthorize then you could try fiddling with the ordering of security and transactional aspects, as is described here.
My guess would be:
// perform security check first, will throw exception if bad
#EnableGlobalMethodSecurity(prePostEnabled = true, order = 0)
// apply tm around security check and update, allowing for rollback
#EnableTransactionManagement(order = 1)

Custom ConcurrentSessionControlStrategy

I'm using spring-security 3.1.
I have to implement session concurrency strategy in a way that the maximum number of sessions is specified by user. Here is what I did :
Coded a class extending
org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy and overrode the method
protected int getMaximumSessionsForThisUser(Authentication authentication)
I configured it using namespace configuration :
<security:http>
...
<security:session-management session-authentication-strategy-ref="mySessionAuthenticationStrategy"/>
...
</security:http>
<bean id="mySessionAuthenticationStrategy" class="foo.bar.MySessionAuthenticationStrategy">
<constructor-arg ref="sessionRegistry"/>
</bean>
<bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
The problem is that "MySessionAuthenticationStrategy" is never called :(
I digged in spring api to see that the following line(70) in SessionManagementFilter is false (preventing any SessionAuthenticationStrategy to be invoked) :
if (!securityContextRepository.containsContext(request))
Why is that ?
I read the documentation where they suggest to set the session authentication strategy in the UsernamePasswordAuthenticationFilter, but it's not an option for me since I'm combining form login with SAML login plus a PreAuthentication mechanism validating authentication token (3 different authentication mechanisms).
Any of you can help ?
Short answer (which is a guess): The problem could be that your pre-auth filter (or other non-form login filter) creates a session without itself invoking the SessionAuthenticationStrategy first.
Long explanation: The line you mentioned is basically checking whether the request has just been authenticated in the current execution of the filter chain without the auth-filter creating a new session. The check inspects if there is a session, and if an auth object has already been saved to the session.
If it finds the session and the saved auth object, that means nothing has to be done: everything has already been arranged regarding authentication and session management either by some other filter, or by the same SessionManagementFilter during processing a previous request earlier in the same session.
The other case is when no session has been created or the (non-anonymous) auth object has not yet been saved in the existing session. Only in this case is it the SessionManagementFilter's responsibility to actully perform session management by invoking the SessionAuthenticationStrategy.
According to your description, this second case never occurs, which means that the session is already created, and the auth object is already saved at this point of execution. That should mean your custom auth filter must have created a session, which is not a problem in itself. The general rule however is that anyone creating a session must first consult the SessionAuthenticationStrategy itself. If your auth filter chooses to ignore it, nothing can be done by the SessionManagementFilter (it cannot undone the session creation, even if the SessionAuthenticationStrategy had raised a veto against the user's authenticatation).
Doublecheck if this is the case, and try avoid creating a session in your pre-auth filter. Note that session creation can also happen in a sneaky way by SaveToSessionResponseWrapper.saveContext() getting called e.g. upon a redirect.

Can I configure Spring Security to prompt for domain name, along with user name and password

I am authenticating using LDAP, and everything works fine for users within a specific domain. But I'm having difficulty understanding how I can authenticate users that are under a second domain. My current configuration shown below specifies the first domain in the user-search-base. I removed that parameter, in hopes that it would search all domains, but that didn't work. I also tried specifying the domain as part of the user name when prompted, such as domain\user, but this didn't work either.
<security:authentication-manager alias="authenticationManager">
<security:ldap-authentication-provider
user-search-filter="(samaccountname={0})"
user-search-base="dc=domain,dc=company,dc=com"
user-context-mapper-ref="userContextMapper" >
</security:ldap-authentication-provider>
</security:authentication-manager>
<security:ldap-server
url="ldap://some.url.com:3000"
manager-dn="CN=USER1,OU=FacMgr,OU=FAC,OU=Exchange,dc=domain,dc=company,dc=com"
manager-password="xxxx"/>
Will I need to create a custom search, and if so, can someone provide an example in this context?
It appears as though you're using Active Directory, in which case I wonder why you're not using the more basic ActiveDirectoryLdapAuthenticationProvider class.
At any rate, you should be able to accomplish what you need by extending either LdapAuthenticationProvider or ActiveDirectoryLdapAuthenticationProvider, and passing the appropriate domain to the superclass' method.
Create a constructor which accepts two different LdapAuthenticator objects, and add a second 'try' statement in the doAuthentication method's catch (UsernameNotFoundException notFound) statement (after the check against bad credentials). Use whatever approach you like to get the getAuthenticator method to try the second authenticator if the first one fails.
This approach should work, but if both domains have a username of jsmith, but the user in question resides on the second, you may encounter problems -- that is, this is not a particularly good solution, but it is a solution.
To build this all up properly, use a custom authentication filter (extend the UsernamePasswordAuthenticationFilter), and have the LdapAuthenticationProvider.getAuthenticator() method identify the domain from the value passed by the filter (in your custom login form).
You may need different manager accounts, but this is hopefully enough for you to go on.
The trick to making this work is to use ActiveDirectoryLdapAuthenticationProvider. To do this, just make the following changes:
In resources.groovy:
// Domain 1
ldapAuthProvider1(ActiveDirectoryLdapAuthenticationProvider,
"mydomain.com",
"ldap://mydomain.com/"
)
// Domain 2
ldapAuthProvider2(ActiveDirectoryLdapAuthenticationProvider,
"mydomain2.com",
"ldap://mydomain2.com/"
)
In Config.groovy:
grails.plugin.springsecurity.providerNames = ['ldapAuthProvider1', 'ldapAuthProvider2']
This is all the code you need. You can pretty much remove all other grails.plugin.springsecurity.ldap.* settings in Config.groovy as they don't apply to this AD setup.
Documentation:
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ldap-active-directory

db level ACL filtering

I am looking at Spring-security 3.0 for this, spring's ACL filtering happens as post(api call) operation. There are 2 issues with that :-
it will break paginated query
Even if i take pagination out on layer above the api fetching results( i am using spring-hibernate here) , the db query each time is wasteful as it fetches and populates all results even if most of them are destined to be filtered out at java level
I have seen solutions where each query is appended with the acl queries which does the filtering at the db level , but that looks ugly as it pollutes business logic with authorization concern, are there any ways/frameworks that does db-level acl filtering transparently ? I like spring-securities overall approach of enforcing security declaratively through config/annotations thus sparing the code from security related logic directly, but i think it loses out on this on performance concerns
For the issues that you mentioned , only the #1 one is the real issue to me .
For the #2 issue if I understand correctly , it is the query that return a result list without any pagination behaviour. Because of that , it is supposed to assume that size of the result is finite and will not grow to the point that it will become very slow to return the result . Otherwise you need to make this query to be pageable and go back to the #1 issue. Given the finite result list , I doubt that filtering at the application level using #PostFilter will become noticeably slower than filtering at the database level.
I have seen solutions where each query is appended with the acl
queries which does the filtering at the db level , but that looks ugly
as it pollutes business logic with authorization concern, are there
any ways/frameworks that does db-level acl filtering transparently ? I
like spring-securities overall approach of enforcing security
declaratively through config/annotations thus sparing the code from
security related logic directly,
So for the #1 issue , if you are using Hibernate , you can check out #Filter which allows you to declaratively define a where clause that will be appended to the select SQL when querying certain entity. The filter is by default turned off and required to be enabled per transaction .The where clause can also be parameterised .
That means you can simply use Spring AOP to define an annotation to annotate the query method that you want to enable the authorization .Then in the advice that backed by this annotation , turn on this filter and configure the parameters for the where clause based on the current user information if necessary. For the query method that is not annotated with this annotation , the filter is turned off and not aware of the authorization concern.
Basically it is the same as appending the authorization logic to the query , but with the help of AOP and the nature of the #Filter , the business logic is not aware of any authorization logic.
If Hibernate filter is not suitable for your requirements, you can then look into which data access technologies allow you to modify the query easily by adding the authorization logic to it. For example , using JPA Criteria API is also possible as it provides the object model to represent a query ,and hence adding the authorization logic to the query is just equivalent to tweaking the query object.
The idea is that you need to have a proper design of the data access layer such that you can use AOP to configure the underlying technology to apply the authorization concern easily and in a consistent way. And use AOP to separate the authorization logic from the business logic.

Method security in Spring Security

I have a question regarding using Spring Security to protect against SQL injection. First of all, I know that use prepared statement can protect from any SQL injection. But In my project I want to show that use Spring Security could help to protect or mitigate against this kind of attack. what i did so far, i made connection using JDBC & Spring and I applied Spring Security and every thing is fine. My question is in my project i used two ways to protect against SQL injection. The first one is Santizing user input and the second one is using Spring Security. I could pass malicious input through Sanitizaing and I want to show that the role of spring security. for example, I pass this input:
TV' UNION SELECT credit_no From credit;--
In this case how I can tell Spring security that it doesnot give any users the credit number. By the way, I used method security level. Just I want to give me an easy way to analyze the user input to see If it has access to data which he asked such as credit.
I hope that clear
Well, your question is not 100% clear, and it may vary on your architecture, but pre post annotations can work well to grab user input.
You can create your own permission evaluator and check permission for pre authorization in your methods.
#PostFilter("hasPermission(filterObject, 'customoperation')")
public CreditCard getCreditCard(String userInput) {
//
}
and your hasPermission method (that you've read about in the link above) goes something like:
public boolean hasPermission(Authentication authentication,
Object target, Object permission) {
if ("customoperation".equals(permission)) {
//your logic here, returning true or false, filtering the object
}
return false;
}
You can also extend the expression handler to use custom functions. Check this answer.

Resources