Spring 6 StrictHttpFirewall semicolon - spring

After migration to the new Spring Boot 3 (which uses Spring 6), I am facing an issue with semicolons in URL. By default, this should not be allowed, which after debugging was proven to be correct. StrictHttpFirewall object throws the
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"
as it should. But this exception ends up in some ObservationMarkingRequestRejectedHandler where it is somehow handled, but not re-thrown.
Before migration, semicolons (and other special characters) were returning status code 400, but now when the exception is lost somewhere in the process, the status code is 200, which is wrong.
Anybody else facing this issue?

Related

Forbid() returns 404

I have returned Forbid() from a web request, and the browser claims its receiving a 404 instead of a 403.
I have added a handler to the cookie authentication like so...
o.Events.OnRedirectToAccessDenied += ctx =>
{
ctx.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return Task.FromResult(0);
};
But this doesn't appear to be called.
Thus, why is a method that should return a 403 returning a 404?
I had the same issue. These were my steps to fix it:
Temporarily remove all the exception handling like app.UseExceptionHandler("/Home/Error") from Startup. In my case the 404 happened because the exception handling was broken.
Then I got the "real" error: My problem was that I had no authentication configured, and therefore no authentication schemes.
After I added the correct authentication options to Startup (in my case I used a custom authentication handler) I got the correct response code:
services.AddAuthentication(LicenseKeyAuthenticationOptions.Scheme)
.AddScheme<LicenseKeyAuthenticationOptions, LicenseKeyAuthenticationHandler>(LicenseKeyAuthenticationOptions.Scheme, null);
The Forbid() command seems to have an internal ASP.NET MVC controller redirect handling. In case you only want to provide a classic API and want 403 to be returned you should switch the command to
return StatusCode(StatusCodes.Status403Forbidden);
Don't forget to import the using
using static Microsoft.AspNetCore.Http.StatusCodes;
Source: https://stackoverflow.com/a/47708867/828184
So far I'm not aware if this behaviour of Forbid() could be changed.

Grails Spring Security only responds with ajax/JSON on login fail

I'm using spring security in a grails app and when a login fails it always redirects to "login/authfail?ajax=true" and a json is rendered.
I even tried to redefine the 'ajaxAuthFailUrl' to be the same as 'defaultFailureUrl', but even though it redirects to '/login/authfail?login_error=1' I still getting the same json.
I dig the spring plugin to see why it 'thinks' it's an ajax request. Then on 'SpringSecurityService.java' I put some debug messages on 'isAjax' method. The result was, first of all, it calls 'isAjax' 2 times in a row. And the request is considered an ajax for different reasons:
there is a header 'ajaxHeader'
there is an ajax parameter on the request
and finally when it checks the SavedRequest's headers, it also finds it to be an ajax call.
I confess I'm lost, I don't have a clue about how to try to fix it...
I'm using:
Grails 2.3.8
spring-security-core:2.0-RC4
runtime ':spring-security-acl:2.0-RC1'
and I have a custom authentication handler that is set on BootStrap:
authenticationProcessingFilter.authenticationSuccessHandler = new MyUrlAuthenticationSuccessHandler()

Exception filters and handlers not called on 405

In my WebApi app, I've got an exception filter
config.Filters.Add(New AppExceptionFilterAttribute)
The filter simply reformats the exception into a format that I prefer. This has been working fine when there's an application error. But today I got an error I hadn't seen before, a 405, and for some reason the filter is simply not called.
I tried adding a global exception handler:
config.Services.Replace(GetType(ExceptionHandling.IExceptionHandler), New AppExceptionHandler())
But this isn't called either! It seems that when I get a 405, WebApi insists on handling this itself, and not calling my filter or my handler, and so I can't reformat the exception the way I want, and this is really annoying.
How can I hook that 405 error?
Exception handling in Web Api is targeted for unhandled exceptions and so responses like 404 Not Found and 405 Method Not Allowed are not considered.

Exceptions in ASP.NET Web API custom exception handler never reach top level when CORS is enabled

I have created a custom Web API global exception handler like this:
public class MyGlobalExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
// here I handle them all, no matter sync or not
}
public override Task HandleAsync(ExceptionHandlerContext context,
CancellationToken cancellationToken)
{
// not needed, but I left it to debug and find out why it never reaches Handle() method
return base.HandleAsync(context, cancellationToken);
}
public override bool ShouldHandle(ExceptionHandlerContext context)
{
// not needed, but I left it to debug and find out why it never reaches Handle() method
return context.CatchBlock.IsTopLevel;
}
}
I'm registering it in my Global.asax Application_Start:
GlobalConfiguration.Configuration.Services.Replace(typeof(IExceptionHandler),
new MyGlobalExceptionHandler());
Everything worked fine, no matter where I threw exceptions - inside controller methods or in my custom attributes above controller methods, and no matter if I call it from AJAX requests or directly from browser.
But then one day I needed CORS support for my AJAX requests. I enabled CORS globally as described in the article Enabling Cross-Origin Requests in ASP.NET Web API
var cors = new EnableCorsAttribute("*", "*", "*"); // * is just for debugging purpose
config.EnableCors(cors);
At first everything seemed OK, CORS worked as expected, the server responded to OPTIONS request.
But the problems started when I wanted to check my authentication. Suddenly the exception was swallowed and I got an empty JSON {} response instead of my custom JSON formatted exception which I create in the Handle() method of my MyGlobalExceptionHandler.
While debugging, I was surprised to find that now for AJAX requests ShouldHandle() method is called only with IsTopLevel = false, thus the exception never bubbles up and never reaches my Handle() method. As soon as I disable CORS, everything works fine again (except cross-domain requests, of course).
Why IsTopLevel is never true when I enable CORS? How should I fix this?
One more side effect is as follows. If CORS is disabled, then if I throw any exception inside Handle() method, it reaches the Application_Error handler in Global.asax. But if I enable CORS and throw exceptions in my handler methods, these exceptions never reach Application_Error.
UPDATED WITH MORE DETAILS:
It seems, I found exactly when this is happening.
If I throw an exception in a controller method when CORS is enabled, then CORS doesn't kick in at all and does not send the Access-Control-Allow-Origin header. When the browser doesn't receive the header, it immediately disrupts the request and this disruption seems to affect also the exception handler - it never reaches ShouldHandle() method with IsTopLevel = true.
Chrome and Mozilla act like this even when I run AJAX request from a local html file to my websiet on IIS Express localhost.
But the situation is different on IE 11. When I open the html file there, it first asks me permissions to enable scripts. After I agree, then IE 11 ignores the fact that there are no CORS headers present and it doesn't disrupt the request, thus my exception handler receives IsTopLevel = true and is able to return a customised error response.
I guess, this should be fixed in the Web API core - even if I throw exceptions, CORS should still be able to kick in and send its headers, so the browser accepts the response. I have created a minimal test case application and I'll send it to the ASP.NET Team on CodePlex.
Link to the test project. (the project zip file will be marked, just click Download and ignore all the other files in that folder)
I have found the source of confusion.
It seems, WebAPI by default is using this exception handler:
https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Http/ExceptionHandling/DefaultExceptionHandler.cs
and it has major differences from the suggested exception handling in this article:
http://www.asp.net/web-api/overview/web-api-routing-and-actions/web-api-global-error-handling
see chapter "Appendix: Base Class Details", where the code of default exception base class is given.
In the example it checks for IsOutermostCatchBlock (which now seems to be moved to exceptionContext.CatchBlock.IsTopLevel) to see if it's time to handle the exception. When CORS is enabled, such approach won't work for the reasons I described above. ASP.NET team said, this behavior is by design and they won't change anything.
I hope someone experienced will write an up-to-date article with instructions for doing exception handling the right way with and without CORS.
Currently I see two ways to work around this in my code:
don't inherit my custom exception handler from System.Web.Http.ExceptionHandling.ExceptionHandler but implement IExceptionHandler directly
if inheriting from System.Web.Http.ExceptionHandling.ExceptionHandler, override
ShouldHandle method and return true always because CatchBlock.IsTopLevel might never have true value.
I tried both apporaches and they seem to work fine.

NETWORK_ERROR: XMLHttpRequest Exception 101

I am getting this Error
NETWORK_ERROR: XMLHttpRequest Exception 101
when trying to get XML content from one site.
Here is my code:
var xmlhttp;
if(window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
if (xmlhttp==null) {
alert ("Your browser does not support XMLHTTP!");
return;
}
xmlhttp.onReadyStateChange=function() {
if(xmlhttp.readyState==4) {
var value =xmlhttp.responseXML;
alert(value);
}
}
xmlhttp.open("GET",url,false);
xmlhttp.send();
//alert(xmlhttp.responseXML);
}
xmlhttp.open("GET",url,false);
xmlhttp.send(null);
Does any one have a solution?
If the url you provide is located externally to your server, and the server has not allowed you to send requests, you have permission problems. You cannot access data from another server with a XMLHttpRequest, without the server explicitly allowing you to do so.
Update: Realizing this is now visible as an answer on Google, I tried to find some documentation on this error. That was surprisingly hard.
This article though, has some background info and steps to resolve. Specifically, it mentions this error here:
As long as the server is configured to allow requests from your web application's origin, XMLHttpRequest will work. Otherwise, an INVALID_ACCESS_ERR exception is thrown
An interpretation of INVALID_ACCESS_ERR seems to be what we're looking at here.
To solve this, the server that receives the request, must be configured to allow the origin. This is described in more details at Mozilla.
The restriction that you cannot access data from another server with a XMLHttpRequest can apply even if the url just implies a remote server.
So:
url = "http://www.myserver.com/webpage.html"
may fail,
but:
url = "/webpage.html"
succeed - even if the request is being made from www.myserver.com
Request aborted because it was cached or previously requested? It seems the XMLHttpRequest Exception 101 error can be thrown for several reasons. I've found that it occurs when I send an XMLHttpRequest with the same URL more than one time. (Changing the URL by appending a cache defeating nonsense string to the end of the URL allows the request to be repeated. -- I wasn't intending to repeat the request, but events in the program caused it to happen and resulted in this exception).
Not returning the correct responseText or responseXML in the event of a repeated request is a bug (probably webKit).
When this exception occurred, I did get an onload event with readyState==4 and the request object state=0 and responseText=="" and responseXML==null. This was a cross domain request, which the server permits.
This was on an Android 2.3.5 system which uses webKit/533.1
Anyone have documentation on what the exception is supposed to mean?
Something like this happened with me when I returned incorrect XML (I put an attribute in the root node). In case this helps anyone.
xmlhttp.open("GET",url, true);
set the async part to true
I found a very nice article with 2 diferent solutions.
The first one implementing jQuery and JSONP, explaining how simple it is.
The second approach, it's redirecting trough a PHP call. Very simple and very nice.
http://mayten.com.ar/blog/42-ajax-cross-domain
Another modern method of solving this problem is Cross Origin Ressource Sharing.
HTML5 offers this feature. You can "wrap" your XMLhttp request in this CORS_request and
if the target browser supports this feature, you can use it and wont have no problems.
EDIT:
Additionaly i have to add that there are many reasons which can cause this Issue.
Not only a Cross Domain Restriction but also simply wrong Settings in your WEB.CONFIG of your Webservice.
Example IIS(.NET):
To enable HTTP access from external sources ( in my case a compiled Phonegap app with CORS request ) you have to add this to your WEB.CONFIG
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
Another scenario:
I got two webservices running... One on Port 80 and one on Port 90. This also gave me an XML HTTP Request Error. I even dont know why :). Nevertheless i think this can help many not well experienced readers.

Resources