How to encode/decode url strings in an UWP App - c#

I'm building a UWP App which communicates with a Web-Api. At some Point I'm sending a string in the url to the Web-Api which can be manipulated by the user. Because of that the string can include characters which could do evil things to the Web-Api.
For example:
This is my UserController
[Route("api/user/{uid}")]
public User GetUser(string uid)
{
return userRepository.GetByUid(uid);
}
For the sake of this example we assume that the user can put in the uid manually in a textbox. Now if he puts in
../vipuser
He could have access to the VipUserController. Because the ../ goes one hirachy up.
I searched a little and found this SO article which recommends the use of System.Web.UrlEncodeUnicode and System.Web.UrlDecode.
But since UWP Apps doesn't include the System.Web namespace I was wondering if there is an alternative to this methods, which I can use into a UWP-App?

Uri.EscapeDataString() and Uri.UnescapeDataString() will do the trick.

Prefer System.Net.WebUtility.UrlDecode and System.Net.WebUtility.UrlEncode over the methods on Uri.
This is because WebUtility handles space ( ) and plus (+) consistently across both "multipart/form-data" and "application/x-www-form-urlencoded" encodings.

Related

API controller route attribute issue

I have an issue with an api controller attribute routing. The API receives a get request containing a scanned barcode to the route: "api/[controller]/{userId}/{barcodeId}". Where the barcode is like: 0015A765248.
But we now have some new barcodes coming in this format: BBRT058/639.
I've found out through debugging that the extra / in the new barcode is causing the issue as the API controller is now not being accessed.
As I think it is trying to reach controller: "api/[controller]/{userId}/{barcodeId}/{barcodeID}"
Which doesn't exist. Is it possible to modify the API controller route attribute to accept the barcodeId containing the additional /?
Actually modifying the new barcode style in any way code wise is not an option I am told.
I have considered creating a new controller to accept the new barcode: "api/[controller]/{userId}/{barcodeIdpart1}/{barcodeIDpart2}" for example.
But i'm not sure if creating a new controller that is a duplicate of the current one, with the only difference being the routing is a good idea. Also both barcode formats are likely still going to be used in the future.
I don't believe you need to make any changes to your code/controller as such and that it seems to be correct. However, I would recommend you update the client to correctly URL encode the barcode before making the outbound call to your controller. This will ensure that the controller correctly parses the barcode and then processes it further. Additionally, this will also ensure that any other special non ASCII characters are correctly handled in the future.
This solution is not really changing the barcode format but is encoding it just before making the outbound HTTP call to correctly transmit it over the wire. Alternate solutions by hacking the controller will usually result in a non standard brittle solution and is not recommended.
Client calls URL
Current: api/controllername/userId/BBRT058/639
Proposed: api/controllername/userId/BBRT058%2F639
For further reading:
https://en.wikipedia.org/wiki/Percent-encoding
https://www.tutorialspoint.com/html/html_url_encoding.htm
https://www.w3schools.com/tags/ref_urlencode.ASP
I would try to replace "/" with "!" or "!!" for example (you can select any sign or combination you like) - BBRT058!!639 before sending to the controller and replace back with "/" inside of the action.
barcodeId = barcodeId.Replace("!!", "/");
if you can't modify the barcode then try this
Route[("api/[controller]/{userId}/{barcodeId}/{barcodeIdpart2?})"]
public IActionResult GetBarcode(int userId, string barcodeId, string barcodeIdpart2 = null)
{
if (!string.IsNullOrEmpty(barcodeIdpart2)) barcodeId=barcodeId + "/" + barcodeIdpart2;
....
}
It will work for both styles

Is the novell.directory.ldap c# library allready preventing ldap injection or do I have to encode potential user input by myself?

im currently developing a user interface to manage users and stuff. As data store I have to use a ldap. I'm using the novell.directory.ldap library for ldap related things.
I'm now wondering if this library already does encoding of parameters it is receiving, e.g. when performing a search, or if I have to encode potential user input, like usernames which will be later used in searchqueries, by myself.
I've already tried to do encoding with the AntiXSSLibrary (I'm using the nuget package sicne the ldap encoding was not included in the .net Framework itself like the other parts of the library) and its Encoder.LdapFilterEncode() and Encoder.LdapDistinguishedNameEncode() methods.
This is my code when trying to encode:
public static LdapSearchResults PerformSearch(LdapConnection connection, string filter, string basedn)
{
string encodedFilter = Encoder.LdapFilterEncode(filter);
string encodedBasedn = Encoder.LdapDistinguishedNameEncode(basedn);
LdapSearchConstraints searchConstraints = new LdapSearchConstraints { BatchSize = 0 };
return connection.Search(encodedBasedn, LdapConnection.SCOPE_SUB, encodedFilter, null, false, searchConstraints);
}
If I pass the parameters directly (= not encoded) everything will work as expected.
If I pass the encoded filter I will receive a LdapLocalException with message "Filter Error" at the Search() method of the LdapConnection instance.
If I pass the unencoded filter and pass the encoded basedn I will receive a LdapException with message "Invalid DN syntax" when trying to access the search results.
If I pass the unencoded filter and pass the ecoded basedn, in this case encoded with the Encoder.LdapFilterEncode() method, everything will work fine.
So the central question is: Do I have to worry about ldap injection or is the library already taking care about this threat? Unfortunately I couldn't find an answer for this in the documentation and by searching the web.
If I have to encode (what I'm expecting I have to do at the moment) what is the easiest and safest way to encode inputs for ldap in C#/.Net when the AntiXSSLibrary is not working for me?

Can I use a format string in a URL to navigate to web page, replacing the specified portion of the URL?

I'm interested in creating some sort of simple C# application takes a user string and passes it into a target portion of the URL. For example, since user query is visible in the page URL DuckDuckGo
Example:
https://duckduckgo.com/?q=web+browsers&ia=web
In this case, the URL shows that I searched for "web browsers". I would like the user to be able to pass any string to the application (via some kind of prompt that appears with the application is launched), and then launch a web browser and navigate to the target URL with the user input inserted into URL where the query is specified. (i.e., https://duckduckgo.com/?q=operating+systems&ia=web), where the user entered the string "operating systems".
So I would like to know which type of C# application to use that can interact with OS (Windows 10) and how to write the code for the the format String and the user prompt. Any guidance would be appreciated.
Your question is very broad so the best that can be done is give a broad answer. You mention "application" and "interact with the OS", so I'm assuming a native application, not a web app. A quick way to pull this off would be to Google for "C# Web Browser Example"; there are plenty of applications out there with well-explained source code that will answer your question:
So I would like to know which type of C# application to use that can
interact with OS (Windows 10)
As for the string replacement, Armine already pointed that out in his previous post. A simple textbox on your form, passed to some parsing code with string replacement, will do the trick for building the URL. The resulting URL is then passed to the web browser control you've used in your C# application; the URL will be one of the properties of the control.
The idea is to take what user typed as a string, and then create another string which will contain the words of that string, separated by the plus character (+)
String what_user_typed=" javascript jquery";
String query=what_user_typed.Replace(" ","+"); // A space represents a new word
String url="https://www.google.com/search?query="+query
After creating the url you can then use a webbrowser to open that url
I have not executed this but think this is what the logic should be.
string input = "operating system";
string destinationURL = $"https://duckduckgo.com/?q={input}&ia=web";
string formattedURL = HttpContext.Current.Server.UrlEncode(destinationURL);
System.Diagnostics.Process.Start(formattedURL);

How to get current page URL in MVC 3

I am using the Facebook comments plugin on a blog I am building. It has some FBXML tags that are interpreted by the facebook javascript that is referenced on the page.
This all works fine, but I have to pass in the current, fully-qualified URL to the plugin.
<div style="width: 900px; margin: auto;">
<div id="fb-root"></div>
<fb:comments href="URL HERE" num_posts="10" width="900"></fb:comments>
</div>
What is the best way to get the URL of the current page? The request URL.
Solution
Here is the final code of my solution:
<fb:comments href="#Request.Url.AbsoluteUri" num_posts="15" width="900"></fb:comments>
You could use the Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString() or Request.Url.AbsoluteUri.
Add this extension method to your code:
public static Uri UrlOriginal(this HttpRequestBase request)
{
string hostHeader = request.Headers["host"];
return new Uri(string.Format("{0}://{1}{2}",
request.Url.Scheme,
hostHeader,
request.RawUrl));
}
And then you can execute it off the RequestContext.HttpContext.Request property.
There is a bug (can be side-stepped, see below) in Asp.Net that arises on machines that use ports other than port 80 for the local website (a big issue if internal web sites are published via load-balancing on virtual IP and ports are used internally for publishing rules) whereby Asp.Net will always add the port on the AbsoluteUri property - even if the original request does not use it.
This code ensures that the returned url is always equal to the Url the browser originally requested (including the port - as it would be included in the host header) before any load-balancing etc takes place.
At least, it does in our (rather convoluted!) environment :)
If there are any funky proxies in between that rewrite the host header, then this won't work either.
Update 30th July 2013
As mentioned by #KevinJones in comments below - the setting I mention in the next section has been documented here: http://msdn.microsoft.com/en-us/library/hh975440.aspx
Although I have to say I couldn't get it work when I tried it - but that could just be me making a typo or something.
Update 9th July 2012
I came across this a little while ago, and meant to update this answer, but never did. When an upvote just came in on this answer I thought I should do it now.
The 'bug' I mention in Asp.Net can be be controlled with an apparently undocumented appSettings value - called 'aspnet:UseHostHeaderForRequest' - i.e:
<appSettings>
<add key="aspnet:UseHostHeaderForRequest" value="true" />
</appSettings>
I came across this while looking at HttpRequest.Url in ILSpy - indicated by the ---> on the left of the following copy/paste from that ILSpy view:
public Uri Url
{
get
{
if (this._url == null && this._wr != null)
{
string text = this.QueryStringText;
if (!string.IsNullOrEmpty(text))
{
text = "?" + HttpEncoder.CollapsePercentUFromStringInternal(text,
this.QueryStringEncoding);
}
---> if (AppSettings.UseHostHeaderForRequestUrl)
{
string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
try
{
if (!string.IsNullOrEmpty(knownRequestHeader))
{
this._url = new Uri(string.Concat(new string[]
{
this._wr.GetProtocol(),
"://",
knownRequestHeader,
this.Path,
text
}));
}
}
catch (UriFormatException)
{ }
}
if (this._url == null) { /* build from server name and port */
...
I personally haven't used it - it's undocumented and so therefore not guaranteed to stick around - however it might do the same thing that I mention above. To increase relevancy in search results - and to acknowledge somebody else who seeems to have discovered this - the 'aspnet:UseHostHeaderForRequest' setting has also been mentioned by Nick Aceves on Twitter
public static string GetCurrentWebsiteRoot()
{
return HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}
Request.Url.PathAndQuery
should work perfectly, especially if you only want the relative Uri (but keeping querystrings)
I too was looking for this for Facebook reasons and none of the answers given so far worked as needed or are too complicated.
#Request.Url.GetLeftPart(UriPartial.Path)
Gets the full protocol, host and path "without" the querystring. Also includes the port if you are using something other than the default 80.
My favorite...
Url.Content(Request.Url.PathAndQuery)
or just...
Url.Action()
This worked for me for Core 3.0 for full URL:
$"{Request.Scheme}://{Request.Host.Value}{Request.Path.Value}"
One thing that isn't mentioned in other answers is case sensitivity, if it is going to be referenced in multiple places (which it isn't in the original question but is worth taking into consideration as this question appears in a lot of similar searches). Based on other answers I found the following worked for me initially:
Request.Url.AbsoluteUri.ToString()
But in order to be more reliable this then became:
Request.Url.AbsoluteUri.ToString().ToLower()
And then for my requirements (checking what domain name the site is being accessed from and showing the relevant content):
Request.Url.AbsoluteUri.ToString().ToLower().Contains("xxxx")
For me the issue was when I tried to access HTTPContext in the Controller's constructor while HTTPContext is not ready yet. When moved inside Index method it worked:
var uri = new Uri(Request.Url.AbsoluteUri);
url = uri.Scheme + "://" + uri.Host + "/";enter code here
The case (single page style) for browser history
HttpContext.Request.UrlReferrer

Override ~ behaviour in controls

Quick backstory: I'm making a "framed" version of my site that has a different master page than normal (one suitable for iframing). It's accessed by mysite.com/Framed/whatever, instead of mysite.com/whatever. This is rewritten in IIS to mysite.com/whatever?framed=true. That works fine.
The issue I'm having is that all the links are relative using a ~ like ~/Server.aspx which works fine in the normal site. I need to override that so instead of producing ../Server.aspx (as it "should") it produces ../Framed/Server.aspx or Server.aspx.
Currently this means that the page goes back to it's normal view (mystite.com/whatever2) as soon as you click on a link, I want it to continue to stay in mysite.com/Framed/...
Don't you really want "../Server.aspx?framed=true" ? That might be easier to pull off
~ resolves to the root of the application, so you could create a virtual directory beneath your main site for your framed version called "Framed", so "~/" resolves to "/Framed/". Then instead of using a query string switch to select your master page, you can check for the presence of "/Framed/" in the raw request URI.

Categories