IIS gives 400 Bad Request for some links - asp.net

I'm using ASP.NET Identity for generating activation urls in format
https://example.com/activate/token
Where token is generated by Asp Identity and looks like this
Cl%2bsBAAAA2qxQHU9GHUuBNXILrSEDWgAAAAACAAAAAAAQZgAAAAEAACAAAADds1gNf52iBX54Z6V%2bY5ZJEZmCmhgPetK2mEuu5pEiLwAAAAAOgAAAAAIAACAAAADjqFZ3Qrk6o22AHQDtoo%2bUNO4NZZ9RubxnuFBPTwyX/3AAAAATHRJIHkbDX2PmNxDYV0e2P5uAohDpMlpaP1C/KjV1mz5z06X7YaehipzlgLa4IxcAT8AQK%2bW4Qxq4Y3No0kaVNQRpSIzdB6cv%2bjn47IY5hburRgSPbZ6L7xvmWoreBZCCBn4SHMxbcdfAKEnkDELpQAAAAIwoV4hLdqQyV5g6WAQM/kiO3/FKyauZKsWBI/tA/M7uq7CDiQRdZxqdO0SUO9xW851luaKDP6bi/daxEhAemzk%3d
Problem is sometimes ~1 in 10 times I get generic 400 error
Bad Request - Invalid URL
HTTP Error 400. The request URL is invalid.
Example bad link
http://example.org/activate/AQAAANCMnd8BFdERjHoAwE/Cl%2bsBAAAA2qxQHU9GHUuBNXILrSEDWgAAAAACAAAAAAAQZgAAAAEAACAAAACrbeGsadAFQETqBTsIuxf%2bJZqK0JOQvGC6M250gHsTEQAAAAAOgAAAAAIAACAAAACo6YtEGtjrvRO74X2G2VAQ1pAlBWksjnLo0zGxwrVrSXAAAAA%2bFfiwK3sL%2bbzK9wbM0r7Hoy4tueNmh4CNLD%2b2HeP7IldrAq40XbeLW0zlZo3CC2qWBfaGb5Z4HjziVYVT2Fvpg6dtm9UAmI4h5BPjzIBcJo8ZpiE4Z%2bQedRpAijhMHfsV2IDNptzCREWe3Wefi9aoQAAAAPzg9TNEhsqf76Qir%2bIyMxuuPsQkVykZVYFJ9/aI3EAAWK2de2VTUsXQBgdS4OGSI4AaAUEN%2b0Akdohw3Jd8zFo%3d
I think the problem is somewhere in IIS request is not hitting my application anywhere and, that's very strange, same error is showing on other websites like microsoft.com.
Eg.this makes 400 error
https://microsoft.com/en-us/AQAAANCMnd8BFdERjHoAwE/Cl%2bsBAAAA2qxQHU9GHUuBNXILrSEDWgAAAAACAAAAAAAQZgAAAAEAACAAAACrbeGsadAFQETqBTsIuxf%2bJZqK0JOQvGC6M250gHsTEQAAAAAOgAAAAAIAACAAAACo6YtEGtjrvRO74X2G2VAQ1pAlBWksjnLo0zGxwrVrSXAAAAA%2bFfiwK3sL%2bbzK9wbM0r7Hoy4tueNmh4CNLD%2b2HeP7IldrAq40XbeLW0zlZo3CC2qWBfaGb5Z4HjziVYVT2Fvpg6dtm9UAmI4h5Bhsqf76Qir%2bIyMxuuPsQkVykZVYFJ9/aI3EAAWK2de2VTUsXQBgdS4OGSI4AaAUEN%2b0Akdohw3Jd8zFo%3d
but this 404 error
https://www.microsoft.com/en-us/AQAAANCMnd8BFdERjHoAwE/Cl%2bsBAAAA2qxQHU9GHUuBNXILrSEDWgAAAAACAAAAAAAQZgAAAAEAACAAAAAbr0DBVHVcY2tO3Rvvk15d5%2bIuV3usPJmD2FTF15vpbwAAAAAOgAAAAAIAACAAAAAXddKnTogsgCGRRhIzbXbk14fsjcLJ5L0q5C/dRfsYlHAAAAAlAw9iARuxhShyGfzE6ZF193fX7zvxLnOfjgh74G5oLc5RPIVdQ7O8sJdj5H0BnysPxrCMk965izZRqjBKGZFNl6smYdmaGy5aPqxI1kTez%2bhHQH1GMW3GUmF%2bRoYdRqcmJLErgcb4sgMa7UGA16X1QAAAAJTk6s6OzBuA2B8whkUdwQnrCS2xgf7QR%2blA%2bm7UqUdXuhQfiFkL/oCINhyrJt%2bWJsjxvGhOcsW15DtzyqKvlWY%3d
It looks like length sometimes have meaning but not really?
Similar question but caused by known characters - %09 in a URL causes IIS (HTTP.SYS?) to return HTTP 400 immediately
PS. Url in format http://example.com/activate?token=token work fine

I think it is caused by the max length for Url segment (UrlSegmentMaxLength).
Source: https://support.microsoft.com/it-it/help/820129/http-sys-registry-settings-for-windows

Related

Server randomly returning empty response with status code 200

I have the same site running on two different machines (behind the same firewall), same exact code. I have created a test plan with Jmeter that just hits the home page. If I run with first url everything works as expected and get Size in bytes 17265. If I then other size I get a size of 0. Both are returning 200 status.
Is there a setting on the server side that could be causing this? I dont think it is a Jmeter setting since all I am doing for the 2nd request it changing the URL
ADDING INFORMATION
My HTTP Request Default I just add the URL and change nothing else
For the HTTP Request I didn't actuall modify ANY setting
This it the response body from one server:
And this is the Other that is ALSO returning a 200 Status:
Edit:
I had seen that article but I had already had those features installed and working unless the is an additional setting somewhere in IIS that says even if these features are installed don't use them. Assuming that the errors in the logs would be under IIS there are no errors.
Your server might be requiring headers such as Accept-Encoding which JMeter is not sending by default.
To add it in see here
As well here is a JMX file testing your domain. Disable the HTTP Header Manager and you will get a 200 status but no data.
As you mention in your question this is not a JMeter issue.
It seems the server code or configuration might not be correct as per following links (mentioned by https://stackoverflow.com/users/7294900/user7294900):
Why are blank pages being served with "200 OK" for asp.net errors in IIS 8.5 (Win 2012 R2)?
And also this one:
Why does IIS return empty responses?
Suppressing HTTP 500 response codes
Check server logs for error logs.

How to know if it's actually a 404 page?

What I learned from Foregenix:
The HTTP 404 Not Found Error means that the webpage you were trying to reach could not be found on the server. It is a Client-side Error which means that either the page has been removed or moved and the URL was not changed accordingly, or that you typed in the URL incorrectly
But then I also do web app pentests with Python and I am wondering that if I only check for the String 404 on the page, it may not really be a 404 error.
It can so happen that the page exists but the heading is 404 just to fool us.
So how exactly do I find out?
You can check the HTTP status code, and see if it is 404 or not. The status code is on the first line of the response:
HTTP/1.1 404 Not Found
If you are using HTTPlib you can just read the status property of the HTTPResponse object.
However, it is the server that decides what HTTP status code to send. Just because 404 is defined to mean "page not found" does not mean the server can not lie to you. It is quite common to do things like this:
Send 404 instead of 403, to hide the resource that requires authentication.
Send 404 instead of 500, to hide the fact something is not working.
Send 404 when your IP is blocked for some reason.
Without access to the server, it is impossible to know what is really going on behind the curtains.
You are right: someone could write "404 Page Not Found" in a HTML page and make you think that the page doesn't exist.
In order to properly recognize HTTP status codes such as the 404, you should capture the HTTP response with Python and parse it. HTTP 1 and HTTP 2 standards dictate that an HTTP response, which is written in the HTTP generic message format, must contain the status code.
Example of an HTTP response (from Tutorials Point):
HTTP/1.1 404 Not Found
Date: Sun, 18 Oct 2012 10:36:20 GMT
Server: Apache/2.2.14 (Win32)
Content-Length: 230
Connection: Closed
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>404 Not Found</title>
</head>
<body>
<h1>Not Found</h1>
<p>The requested URL /t.html was not found on this server.</p>
</body>
</html>
You should definitely not trust the HTML part, which can show a 404 error (or even a 418 I'm a teapot) when the page can in fact be found.
In addition to Anders' answer, I found a way to detect some cases where 404 is misused with a Timing attack. It is hardly reliable, though.
Send 404 instead of 403, to hide the resource that requires authentication.
Often servers need more time to determine that "you dont have authorization to get this resource", because they need more roundtrips to external resources like databases, then they need to determine "this is not there", quite often even cacheable and quickly to determine.
A typical example in an MVC application with a RDBS as backend is the difference between a simpleSELECT COUNT(id) FROM articles WHERE id=123 LIMIT 1
and the much more complex SELECT access FROM accesses JOIN articles ON articles.id = accesses.foreign_id WHERE articles.id = 123 AND accesses.type='articles' AND accesses.user_id = (SELECT id FROM users WHERE token='t0k3n' LIMIT 1). And that implies that the application can make such single line queries in the first place: more often it is a lot of "fetch a user, extract some data, now fetch a Thing, now ask Thing if user may access it through an authorization-api".
Unless the developers or the framework of the site took care to cover this case, quite often you'll see a notable difference in time to serve both cases of 404.
Send 404 instead of 500, to hide the fact something is not working.
Typically, crashing or unexpected errors occur only after some code has ran. 404-detection often comes early: after all, it is cheap to determine that something is not there (see above). Whereas the error would occur later on. Meaning that such a 500-hidden-as-404-error would, quite often take a lot longer to reach you then a normal 404.
Send 404 when your IP is blocked for some reason.
Here, the timing is often the other way around, depending on the implementation. Such IP-blocking would often be kept outside of the web-app (CMS etc) because it is much simpler and performant to handle higher up in the stack: the webserver, a proxy etc.
However, when the application itself takes care of this, generating an actual 404 is often reasonably cheap, whereas looking an IP in a database, applying masks and so on, takes some time. Similar to hiding a 403 as 404.

Why am i getting a 505 error code from the server?

I looked up the 505 response code and saw that it was "The Web server (running the Web site) does not support, or refuses to support, the HTTP protocol version specified by the client"
The web site I am trying to access on the web server is https://query.yahooapis.com/v1/public/yql?q=select * from yahoo.finance.quote where symbol %3D"msft"&diagnostics=true&env=store
I was able to get on the site and see that it provided xml data. However when I tried to make a HttpsURlConnection with that site, I got a 505 response code, code for doing so is
URL url = new URL(params[0]);
URLConnection connection = url.openConnection();
HttpsURLConnection httpConnect = (HttpsURLConnection) connection;
int responseCode = httpConnect.getResponseCode();
where i inspected the value of params[0] at runtime and saw that it had the right url in it. Does anyone know how i can fix this issue? The web server should support https because that link works. I don't understand why a 505 error is occuring then.
java.net.URL will allow you to create an invalid URL with spaces, which results in this error. Spaces in query parameters should be encoded as +, so make your URL:
https://query.yahooapis.com/v1/public/yql?q=select+*+from+yahoo+finance.quote+where+symbol+%3D"msft"&diagnostics=true&env=store
This request is still incorrect, and will result in a 400 ("expecting table got 'finance'"). From these questions:
Getting data from Yahoo Finance
Issue with AngularJS and financial quote
I believe you want:
https://query.yahooapis.com/v1/public/yql?q=select+*+from+yahoo.finance.quote+where+symbol+%3D"msft"&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys
I think i got the problem. I looked online and saw that someone else had the problem and that it was the spaces inside the url. I am not sure how to resolve this though

Response Redirect URL returns HTTP Error 400 - Bad Request

I'm a noob when it comes to ASP.NET. I know few basic commands such as Response.Redirect("URL") to redirect my application web page to a different location.
However i receive HTTP Error 400 - Bad Request, whenever i try to use the code shown below
Response.Redirect(Server.UrlEncode(this.Downloadlink));
where this.Downloadlink is a user defined property which returns something like this
http://mdn.vatsag.net/fp;files/DOWNLOAD/VTSetup.exe
If i post this link in the browser, the .exe file pops up (means the link is good)
However this error comes when i use the ASP.NET code.
Any form of response on this issue/reason is deeply appreciated.
See here: http://www.kirit.com/Response.Redirect%20and%20encoded%20URIs
In short: if you quickly want to fix the issue, remove the part of your code that is UrlEncoding the URL!

The request URL is invalid in IIS 7

here is my URL
http://abc.domain.com/controller/action/A74444C3A7FA858C7995CA9954CBCF1E26604634767C5575396D908E8415CF8CCC04C05F49FED0AA9D9743B69ABF232BDE9787A5222D081DA638896C0D2379A673E1747A2FFE1158F14AF098B2899D2ABEB4EA738D89369627E479796B6B2B9EA9B247CC59EF10E3A88B6A56A87F0818E2AD2A942FFA31F1C941BB7AF6FDC55FE6733353F28DFAC1827688604CBFBAB4856E6C75F810D13923F9D913F51F5B02980163E6CD63BC04610AD2C12E07360D7BC2C69F1B0CD03E
There are no invalid characters in the URL itself as everything is encrypted. Still I am getting
Bad Request - Invalid URL
HTTP Error 400. The request URL is invalid.
I know the URL is awfully long and I was able to resolve that issue in my Cassini by adding this
httpRuntime maxUrlLength="512"
in the web.config
However in IIS7 even after playing around with the requestfiltering maxurl and maxquerystring values I have not been able to resolve this.
This is an asp.net mvc 3 application.
This one is for posterity and for tracking my own problem. It's been said in another answer however, not as explicitly.
I've had the same problem on my end. The answer is of course to transfer the long URL segment to a Query string. Easier to handle.
The problem however is that HTTP.sys is not even letting the request through because a segment of the URL is exceeding 260 or so characters. However, we still had to support it.
You can change that setting in the registry. Once you reboot, the url will work.
Registry:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters]
"UrlSegmentMaxLength"=dword:00000400
This will effectively set the segment length to 1024.
Source
Your problem is you're not using a query string, but a path. A path has a maximum length of 255.
The final path segment is likely to be too long.
See: http://social.msdn.microsoft.com/Forums/nl/netfxnetcom/thread/723e6bfd-cab7-417b-b487-67f1dcfa524f

Resources