HttpWebRequest automatically encodes URI - asp.net

So I've got a site in .NET 2.0 (VB.NET)
I need to send a request to a third party service with a WebRequest. Unfortunately, the request needs to send URL encoded data in the query string and it appears that the HTTP request object automatically decodes URLs.
I ran across this post
Creating an Uri in .NET automatically urldecodes all parameters from passed string
and this post Help with C# HttpWebRequest URI losing its encoding which point me to this documentation https://msdn.microsoft.com/en-us/library/system.uri(v=VS.100).aspx which basically tells me I'm screwed and I"m going to have to hack like crazy to get this to work.
There seems like there has to be an easier way to stop the WebRequest from automatically decoding the URLs. Does anyone have any ideas?

Related

IIS 8.5 400 Bad Request

I've some difficulties with an ASP.Net Core Web Api Application which is hosted on an IIS 8.5.
The IIS 8.5 returns a 400 status code for a specific post request.
The faulty request is executed by an web application which is hosted on the same domain with a different port. The API is configured to handle cors and the preflight of the faulty request is successfully completed.
I noticed a weird thing:
The Api is deployed with Swagger UI included. So I tried to reproduce the error with the Swagger UI. But in this case the request is successful.
The body and the url of both requests are absolutely the same and there are no noticeable differences in the headers except, of course, of the request origin.
It looks like the request is not processed by the Api at all (I should see sth. in our log files in this case), so I'm pretty sure the error occurs somewhere in the IIS itself.
I've already investigated the httperr.log file. It contains the flowing line at the time of the failed request:
2018-12-05 15:38:36 192.168.100.132 62121 192.168.100.173 1142
HTTP/1.1 POST /api/some/request/path 400 13 BadRequest myServicePool
I was hoping this file would contain more details about the cause of the error.
I was wondering if the "13" before "BadRequest" has any special meaning?
Does anyone have an idea, based on the information given, why this error occurs? I don't really think so. But I would be more than happy if anybody can give me a hint where to search for more details about the cause of the error.
Let me know if you need more details.
It's better if we can have sample code of how you are sending the request in your code.
However, with the given facts I assume the problem is in the content of the request body. Even the swagger request and the request you are sending look like exactly the same, it should be varying in some aspects.
Are you using a JSON converter? If you are using a JSON converter and if you are serializing a .NET model to a JSON string and attaching in the request please make sure that you are formatting it with Camel Case.
Because by default it might just be converting the .NET model as it is with the Pascal case.
EXAMPLE
I'll elaborate this using Newtonsoft JSON library.
.NET model serialized without specifying the format
var businessLeadJson = JsonConvert.SerializeObject(ObjectA);
Converted result - {"Company":"sample","ContactName":"contact 1"}
.NET model serialized by specifying the format
var businessLeadJson = JsonConvert.SerializeObject(businessLead, new
JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() });
Converted result - {"company":"sample","contactName":"contact 1"}
Please notice the case of the property names in JSON strings. The first letter is capital in the first result.
Therefore I recommend you to try serializing your objects that are attaching as the payload (request body) by specifying the formatting, becasue REST APIs expect the JSON strings in the correct format.
Please specify the Camel case formatting when you are serializing the object of your request body.
Good Luck..!
I've justed managed to reproduce this error by accident.
The problem is, that the application send an empty Authorization-Header if the user hasn't login yet.
It seems that causes an Bad Request on some configurations/IIS versions, or what ever the difference is between the systems,and on some it's no problem.

Overriding HTTP request headers via query string

We have a client of a ServiceStack service that cannot easily send the correct value for some request headers (such as Accept or Accept-Encoding).
Is there any mechanism in ServiceStack (or ASP.NET) that can allow the client to use query string parameters to override the value of request headers, in a generic way?
The format URL param recognized by ServiceStack is close, but it seems to not help in this specific case (the client needs to send Accept: image/png, which seems to be ignored by the format param).
Or another way to look at this, is there a way to name or annotate the properties of a GET request DTO so that ServiceStack will populate those properties with the values of request headers during deserialization? This could provide an alternative approach for solving this problem.

Any holes in securing a HTTP request with HMAC using ONLY the HTTP method and URL?

I want to redirect my users browser using HTTP code 303 to a GET URL that I secure using HMAC. Because the request will come from the users browser, I will not have fore-knowledge of the request headers. So I am generating the HMAC hash using the values of the HTTP method and URL only. For example, the URL I want the browser to do to might be:
GET /download
?name=report.pdf
&include=http://url1
&include=http://url2
This create report.pdf for me, containing the contents of all the urls specified using the include query param.
My HMAC code will change this URL to be
GET /download
?name=report.pdf
&include=http://url1
&include=http://url2
&hmac-algorithm=simple-hmac
&hmac-signature=idhihhoaiDOICNK
I can issue HTTP 303 to the user using this URL, and the user will get their report.pdf.
As I am not including the request headers in the signature, I am wondering two things:
1) Can a would-be attacker take advantage of the fact that I am not signing the request headers?
2) Is there a better way to achieve what I am trying to do?
When I realised that what I am talking about here is a signed URL, I checked the Amazon Docs and found "REST Authentication Example 3: Query String Authentication Example" in this document: http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html.
This example is about a signed URL for use through a browser. About signing the headers, the document says:
You know that when the browser makes the GET request, it won't provide a Content-Md5 or a Content-Type header, nor will it set any x-amz- headers, so those parts are all kept empty.
In other words, Amazon leave the headers out of the signature.
Amazon make no mention of potential security holes, so until I hear otherwise (or get hacked :) ), I will assume my approach above is fine.

Handling bad request in asp.net web api

I have a api url like below in my mvc4 app
http://localhost:15839/api/mydata/getdata/3365895543/PROBLEMDATA/myotherparam
Now client is consuming the above url to send httprequest. In response api is sending back a response. but in PROBLEMDATA of the url user is sending bad characters that are giving me Bad Request - Invalid URL. I can't force my client source to encode data. i need to handle it in my web api and give back my client a string "Unsucessful". I have seen this webapi cycle wondering at which point I should handle this. probably at http message handler but How?
I may need to follow this. but Register(HttpConfiguration config) also doesn't get hit
I believe you can capture this globally by overriding the application_error method. From there I suppose you could produce the "unsucessful" response or pass the request along to be handled at the controller level.
Take a look at this question as well.

Programmatically POST to ASP type WEBPAGE

I have been toiling over HttpURLConnection and setRequestProperty for 2 days so far and I cannot get this webpage to Post and return the page I desire. This is what I have so far...
...
String data = URLEncoder.encode("acctno", "UTF-8") + "=" + URLEncoder.encode("1991462", "UTF-8");
URL oracle = new URL("http://taxinquiry.princegeorgescountymd.gov");
HttpURLConnection yc = (HttpURLConnection) oracle.openConnection();
yc.setRequestMethod("POST");
yc.setRequestProperty("Content-Type", "text/html; charset=utf-8");
yc.setRequestProperty("Content-Length", "19004");
yc.setRequestProperty("Cache-Control", "private");
yc.setRequestProperty("Set-Cookie", "ASP.NET_SessionId=v5rdm145zv3jm545kdslgz55; path=/");
yc.setRequestProperty("X-AspNet-Version", "1.1.4322");
yc.setRequestProperty("X-Powered-By", "ASP.NET");
yc.setRequestProperty("Server", "Microsoft-IIS/6.0");
yc.setDoOutput(true);
yc.setDoInput(true);
OutputStreamWriter out = new OutputStreamWriter(yc.getOutputStream());
out.write(data);
out.flush();
//out.write(data);
out.close();
...
It returns the same page defined in URL. it doesn't send me the requested page which should have an ending /taxsummary.aspx
It looks as if the asp takes the post data and generates an HTML unique for each parameter given. How do I give it the correct parameters?
Your code looks fine. I believe it sends POST correctly. I think that the problem is not here. When you are using browser you first perform at least one HTTP GET to arrive to the form. When you are doing this the server creates HTTP session for you and returns its id in response header Set-Cookie. When you are submitting the form using browser it sends this header (Cookie) back, so the server can identify the session.
When you are working from java you are skipping the first phase (HTTP GET). So the first thing you are doing is POST while you do not have session yet. I do not know what is the logic of this ASP page but I think that it just rejects such requests.
So, first check this guess. You can use plugin to Firefox named LiveHttpHeaders. Install it and perform the operation manually. You will see all HTTP requests and responses. Save them. Check that the session ID is sent back from server to client. Now implement exactly the same in java.
BTW often the situation is event more complicated when server sends multiple redirect responses. Int this case you have to follow them. HttpConnection has method setFollowRedirects(). Call it with parameter true.
BTW2: Apache HttpClient is a perfect replacement to HttpConnection. it does everything and is very recommended when you are implementing such tasks.
That's all. Good luck. Sometimes it is not easy...

Resources