How to get WebResource.axd querystring in correct case? - asp.net

I am getting the css files for minifying and compressing from QueryString["path"] everything works correctly for my own css files like main.css. But when I try to acess the webresource files I receive a 500 error. The parameter which comes after the webresource.axd is case sensitive and I receive it from QueryString["path"] lowercase.
This is what I get from QueryString["path"] :
http://localhost/test/webresource.axd?d=-phgrn6r6zgehvbi697-bxvkl_gidnplxpdeukz5kncgr9hvnfvttpgykwyw05cda-nymtz9od_bbww3ynzxha2&t=633789305460522066
The above link generate error : CryptographicException: Padding is invalid and cannot be removed.
This is what the correct link look like :
http://localhost/test/WebResource.axd?d=-pHGRn6r6ZGehvBI697-BxVKl_GIdNPlxPdEUKZ5KNcGR9hvnfVtTpgyKwYw05cDa-NymTz9OD_bBwW3ynZXhA2&t=633789305460522066
The only difference is in the case. CryptographicException seem to be common but even setting machineKey didn't fixed the problem. Any hint on how could I get the the webresource.axd in the original case?
EDIT
Code was requested :
public void ProcessRequest(HttpContext context) {
Control c = new Control();
string root = context.Request.Url.GetLeftPart(UriPartial.Authority);
string path = context.Request.QueryString["path"];
string content = string.Empty;
if (!string.IsNullOrEmpty(path)) {
if (context.Cache[path] == null) {
List<string> dependencies = new List<string>();
string[] styles = path.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
foreach (string style in styles) {
content += RetrieveStyle(root + c.ResolveUrl(style)) + Environment.NewLine;
dependencies.Add(context.Server.MapPath(style));
}
content = StripWhitespace(content);
context.Cache.Insert(path, content, new CacheDependency(dependencies.ToArray()), Cache.NoAbsoluteExpiration, new TimeSpan(DAYS_IN_CACHE, 0, 0, 0));
}
}
}
It crashes in RetreiveStyle when I call :
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())

The culprit looks like the code that is generating the “path” querystring csv or some hardware or filter between that source and your handler.
If the source of handler request is a browser what does the handler url look like through view source or firebug? Is it lowercase already?
Working forward from that, do you have any modules etc registered in you IIS pipeline?

I do not have an answer but we have experienced a similar problem and I have a few things to add, which could help identifying the issue.
So, here it goes:
We have an iHTTPHandler (lets call it Login.ashx) that accepts a GET request, which contains a token in base64 format.
The token is then decrypted using Rijndael algorithm.
This process is working most of the time, however, in the last month we had several requests that failed due to System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed. error. This error is raised in our case when a token (base64 string) is in lowercase and cannot be decrypted.
After going through logs and activity records I can see that a particular user would attempt to come to our side via Login.ashx and the request would fail due to the error in question. The whole querystring of the request (there is more than just token) including names and values is in lowercase. Then the same user would attempt a login a few minutes later and is able to get in because the querystring was not transformed to lower case.
So, I have a feeling that the issue could be browser related. I am not sure if proxy could affect this.
Additional info:
There is no browser information captured in the server variables.
ALL_HTTP and ALL_RAW variables have almost no data:
ALL_HTTP HTTP_CACHE_CONTROL: no-cache HTTP_HOST:our server name
ALL_RAW Cache-Control: no-cache Host: our server name
There is also no HTTP_REFFERER.
I have tried to replicate this issue with different browsers (Safari3, Chrome1, Opera9.2, IE6,7,8, Firefox3) with no luck.
We have a web farm with 10 servers configured identically (at least I hope they are)
I will add more info if I get any progress.

Related

Apache commons fileupload timeout only with Firefox

I use the Apache commons fileupload 1.4 library in my java project.
I have a html part with a classic form with a file input and some hidden fields.
I have a problem with uploading files of around >500ko only with Firefox >= 52
It works well with files of 10mo in Chrome or Internet Explorer.
But with Firefox, I have a timeout after waiting several minutes after submitting the form.
After some debugging, I see that the code responsible of the timeout is :
List<FileItem> items = (new ServletFileUpload(new DiskFileItemFactory())).parseRequest(request);
The part with cause wait is "parseRequest".
I try to debug the content of request with debugger in IntelliJ, but there is no way to copy entire content value of this request object in raw format.
It's working in these cases :
- Firefox : version <= 52 or file size < 500ko (around, it's not really precise)
- Internet Explorer
- Chrome
There is no file size limit, it seems that depends on the request size, because the parsing request part is taking too much time...
I get the HTTP request with a Firefox extension in two cases.
One generating uploading a file of 3mo which doesn't works (the request file is huge, 3x the size of the uploaded file) :
https://code.empreintesduweb.com/13561.html
One generated uploading a file of 200ko which works (the request file is small) :
https://code.empreintesduweb.com/13560.html
In fact, the main difference is that in Chrome or IE, I don't have the raw content of the uploaded file in the request headers :
The part with :
obj
stream
....
endstream
endobj
Only appear with Firefox...
You can try setting the maximum file size, maybe the file size exceeds the maximum threshold .According to the documentation :
Uploaded items should be retained in memory as long as they are reasonably small.
Larger items should be written to a temporary file on disk.
Very large upload requests should not be permitted.
The built-in defaults for the maximum size of an item to be retained in memory, the maximum permitted size of an upload
request, and the location of temporary files are acceptable.
Try the following :
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// Set factory constraints
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(yourMaxMemorySize);
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
List<FileItem> items = new ServletFileUpload(factory).parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
// Process regular form field (input type="text|radio|checkbox|etc", select, etc).
String fieldName = item.getFieldName();
String fieldValue = item.getString();
// ... (do your job here)
} else {
// Process form file field (input type="file").
String fieldName = item.getFieldName();
String fileName = FilenameUtils.getName(item.getName());
InputStream fileContent = item.getInputStream();
// ... (do your job here)
}
}
} catch (FileUploadException e) {
throw new ServletException("Cannot parse multipart request.", e);
}
// ...
}
Here, we are providing a temp location for the file since the file is large.
A few things that are worth to try here:
Explicit the encoding: https://stackoverflow.com/a/10488411/4279120
Decompose your call and add iteration and try catch, ex. : https://www.programcreek.com/java-api-examples/?api=org.apache.commons.fileupload.FileItemIterator
Take a look at the MultipartConfig, it seems to provide such attributes as maxFileSize and maxRequestSize (see: https://www.codejava.net/java-ee/servlet/java-file-upload-example-with-servlet-30-api#maxFileSize%28%29)
Manually define the header of your Request if you can. It seems that adding "X-File-Name" and "X-File-Size", can also help, but this is a little old: AJAX File Upload with XMLHttpRequest
We may also help you better if you provide some more informations, like the versions of apache / java / servlet, and a few more code (especially the definition of request)
Some ressources that could be helpful:
XMLHttpRequest
Sending_files_using_a_FormData_object
How to set a header for a HTTP GET request, and trigger file download?
try this to set session timeout using setMaxInactiveInterval method
request.getSession().setMaxInactiveInterval(1200);
parameter Specifies the time, in seconds, between client requests before
the servlet container will invalidate this session. An interval value
of zero or less indicates that thesession should never timeout.
Thanks for all your answer.
Finally, I successfully resolve this issue, but in fact... not really.
I notice that there was some specific things in my form.
I had two inputs, one standard file input, and another which receive the file content encoded in base64 by some weird js before any upload.
So I was having one time the raw content of the file, and also the file in base64. Why ?! I don’t know.
But I delete all this, I create a new simple and clean form with a standard input file.
I use the stream API from ServletFileUpload, and it works, and takes only few seconds for big files.
So I don’t understand everything (why the problem was only on some browser for example), but I find a solution ;)
Thank you !

HTTP get request won't submit with a URL encoded parameter

I'm currently writing an ASP.NET Core web API that has an action with a encrypted value as a parameter.
I'm trying to test this action and the URL won't even submit in the web browser, at first I thought it could be due to the URL being too long but I've found this answer and my URL is well below the 2000 character limit. I've changed the parameter to a trivial string ("hello") and it submits fine and runs the code. I've tried in both Edge and IE11 whilst debugging my application, in Edge nothing happens at all, in IE11 I get a message saying:
Windows cannot find 'http://localhost:5000/api/...' Check the spelling and try again
In either case the code in the application doesn't execute (I've put a breakpoint on the first line of the controllers constructor which isn't being hit).
I've included an example of one of the URLs that isn't working below, as well as the code I'm using to generate the encrypted string, it uses HttpUtility.UrlEncode to convert the encrypted byte[] array to a string.
Example URL (one that doesn't work):
http://localhost:5000/api/testcontroller/doaction/%95%d6%f8%97%84K%1f%d4%40P%f0%8d%de%27%19%ed%ffAR%9c%c6%d4%b1%83%1e%9fX%ce%9b%ca%0e%d4j%d3Rlz%89%19%96%5dL%b1%16%e9V%14u%c7W%ee%89p%3f%f7%e6d%60%13%e5%ca%00%e9%a2%27%cb%d3J%94%a6%e1%b9%9c%914%06y%7e%0bn%ce%00%e5%7d%98b%85c%fa6m%7d%f7%f1%7b8%26%22%5e%1et%5e%10%0c%05%dd%deFAR%bb%93L%b9-W%e1K%82%d8%cc8%ce%e0%0c%2b%bc%19
Action:
[HttpGet("[action]/{encrypted}")]
public string DoAction(string encrypted)
{
return "Executed";
}
Generate encrypted string:
private string GenerateEncryptedString()
{
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
byte[] data = HttpUtility.UrlDecodeToBytes("AHMW9GMXQZXYL04EYBIW");
byte[] encryptedData = rsaProvider.Encrypt(data, true);
string encryptedString = HttpUtility.UrlEncode(encryptedData);
return encryptedString;
}
Not sure if I'm going wrong in my methodology for converting the encrypted data to a string but I would appreciate any feedback on how to fix this issue.
I think you should try to pass this data in the query string and not in the location (path) part of the url (some characters may be forbidden in paths as a security layer), so add a ?data= before the encoded data.
http://localhost:5000/api/testcontroller/doaction/?data=%95%d6%f8%97%84K%1f%d4%40P%f0%8d%de%27%19%ed%ffAR%9c%c6%d4%b1%83%1e%9fX%ce%9b%ca%0e%d4j%d3Rlz%89%19%96%5dL%b1%16%e9V%14u%c7W%ee%89p%3f%f7%e6d%60%13%e5%ca%00%e9%a2%27%cb%d3J%94%a6%e1%b9%9c%914%06y%7e%0bn%ce%00%e5%7d%98b%85c%fa6m%7d%f7%f1%7b8%26%22%5e%1et%5e%10%0c%05%dd%deFAR%bb%93L%b9-W%e1K%82%d8%cc8%ce%e0%0c%2b%bc%19

UserManager.GenerateEmailConfirmationToken returning tokens unsuitable for URL transmission

I have a ASP.NET MVC 5 website, and I'm implementing an email confirmation process based on the template from Microsoft.
While I'm composing the email body text, first I construct the URL a user will use to "click to verify your address".
To generate the security token I call:
UserManager.GenerateEmailConfirmationTokenAsync(user.Id)
This produces a code such as:
pporPNj6KzdZ3BYG8vQsKJu3dPJMwGgh+ZEGhCNnf9X6F0AS0f6qCowOQwQNfpYkl14bgEsmyPTKya5H6N4n2na2n5PgO+wpoihXxQTA7G8pK/lUYskX3jy2iA/ZM8m4Vm0prTyUuhMgfDlV+wkbR336FBRIAbKJDwOWvHHbJBDQ21gW93hyzca0li66aI1H
Obviously, this wouldn't be valid in a URL, but even URL encoding won't solve IIS's hate of such a URL.
HTTP Error 404.11 - Not Found
The request filtering module is configured to deny a request that contains a double escape sequence.
In my UserManager implementation, I'm using the tutorial boilerplate code for a TokenProvider.
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<SiteUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
How can I make these generated tokens a bit more URL friendly? What did potentially change that would prevent the ASP.NET's tutorial code not work?
It turns out that this token will get mangled by the built in class "UrlHelper" in a MVC controller, or Url in a WebAPI controller IF the target route lists these variables as part of the path, rather than the GET vars of the URL.
Eg: this call, creates a relative URL for the site route called "ConfirmEmail" and fills in the blanks
Url.Route("ConfirmEmail", new { userId = user.Id, code = code });
Before my route was:
[Route("register-email/{code}/{userId}", Name = "ConfirmEmail")]
Changing this to:
[Route("register-email", Name = "ConfirmEmail")]
Generates valid URLS that IIS can chew through. When these are not specified, they get appended after a ? mark as normal GET vars. No idea why IIS is picky like that, but there's the solution.

Sharepoint If-Modified-Since

I wrote a handler to be used within SharePoint that will generate a JSON string from a given parameter in the query-string. This JSON string will then be used by a JS function to display the relevant data in HTML to the client, however, the call is somewhat costly and would like to cache the output once.
The handler currently caters for everything regarding OUTPUT cache and tested within an application bares fruits, however, I'm baffled by the fact that, specifically in SharePoint (2007) the "If-Modified-Since" header attribute never appears, basically it always comes back as null.
I found blog-on-blog that discuss this in length in regards to images, and include files but I can't find anything specific regarding this with pages (ASPX, AXD, ASHX) and the handler self.
My only assumption here is the fact that I'm using an AXD file, which is not directly supported by OUTPUT cache by default?
The code looks something like:
bool isModifiedSinceLast = (context.Request.Headers.Get("If-Modified-Since") != null)
: true
? false;
if (!isModifiedSinceLast)
{
context.Response.Headers.AppendHeader("If-Modified-Since", Guid.NewGuid());
}
else
{
// complete the call from cache
}
Thanks,
Eric

URL Encoding being lost before processing - ASP.net

I am building a web-store that uses URL encoding extensively.
I have a list of Departments & Categories in my database which I use to generate the links. These are, of course, URL encoded before they are sent.
Some Typical Links are...
/MySite/Store/Countertop+Equipment/Can+Openers.aspx
/MySite/Store/Dinnerware.aspx
/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx
In my HTTPHandler I call app.Request.Path to obtain the current path. The string returned by this call is no longer URL encoded which is making it impossible for me to parse correctly.
Once the URL encoding is lost
/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx becomes
/MySite/Store/Kitchen/Pastry/Decorating.aspx.
This is obviously breaking the method that converts the URL to a QueryString.
Anyone know how to fix this?
Here is the core of my HTTPHandler
public void Init(System.Web.HttpApplication app)
{
app.BeginRequest += new EventHandler(Application_BeginRequest);
}
private void Application_BeginRequest(object sender, EventArgs e)
{
System.Web.HttpApplication app = (System.Web.HttpApplication)sender;
string realUrl = GetRealUrl(app.Request.Path);
if (!String.IsNullOrEmpty(realUrl))
app.Context.RewritePath(realUrl, false);
}
I really appreciate your help!
You cannot use Request.Url (including Url..PathAndQuery, AbsolutePath etc) as its OriginalString is already decoded.
So there is no point to use Request.Url at all and you can try to play with following:
Request.AppRelativeCurrentExecutionFilePath
Request.CurrentExecutionFilePath
Or in a worst-case scenario you'll need to parse the Url:
[Test]
public void RewriteProoveOfConcept() {
var path = #"/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx";
var res = Regex.Replace(path, #"/(.+)/(.+)/(.+)/(.+)\.aspx", #"/$1/YourPage.aspx?category1=$2&category2=$3&category3=$4");
Assert.AreEqual(#"/MySite/YourPage.aspx?category1=Store&category2=Kitchen&category3=Pastry%2f+Decorating", res);
}
This shows how you can get the URL:
/MySite/YourPage.aspx?category1=Store&category2=Kitchen&category3=Pastry%2f+Decorating
from:
/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx
Additionally consider using Routing instead of UrlRewrite.
Cheers,
Dmitriy.
Try the AbsolutePath or PathAndQuery properties on the Request object. Both of them should maintain the url encoding.
You can UrlEncode the URL before parsing it. Or better yet, keep URL's non-encoded in database. You don't even need to encode them if you use HyperLink control.
It turns out that the issue is occurring in IIS before .Net even gets its hands on the request. It appears that this is a dead end.
An additional word of warning is that my IIS test server (XP) was rejecting requests containing encoded amperstands as a security risk and could not be persuaded to cooperate with anything short of a registry edit. Not sure if this goes for all versions, but even if a server variable can be retrieved this seems like another good reason to use a different tactic.
Here is the follow-up question with the accepted solution-
ASP.Net URL Encoding

Resources