Retrieving everything after ? in a query string - c#

I am actually an HW and FW engineer and very new to web programming.
In a recent product we embedded wi-fi connectivity and our products(clients) send get requests to a server using the format below and it is unfortunately fixed.
IP Number:Port Number/default.aspx?XX-XX-XX-XX-XX-XXY*Z*
XX-XX-XX-XX-XX-XX is the MAC address of the product
Y is an integer which may vary between 1 to 99999
Z is the opcode which may again vary from A to Z
We want to get everything after the ? sign to determine from which terminal this request is coming from and which action we shall take in the database.
Since we are using IIS webserver we think an asp page fits better to such a requirement.
What method would you request to retrieve all the string after the ? sign using C#.

You can parse the Urls using the Uri class
var queryPart = new Uri("your url here").Query;

Try Request.Url.Query if you want the raw query string as a string.
I usually use Request.Url.ToString() to get the full URL (including query string), no concatenation required.

Related

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?

How to maintain the right URL in C#/ASP.NET?

I am given a code and on one of its pages which shows a "search result" after showing different items, it allows user to click on one of records and it is expected to bring up a page so that specific selected record can be modified.
However, when it is trying to bring up the page I get (by IE) "This page cannot be displayed".
It is obvious the URL is wrong because first I see something http://www.Something.org/Search.aspx then it turns into http://localhost:61123/ProductPage.aspx
I did search in the code and found the following line which I think it is the cause. Now, question I have to ask:
What should I do to avoid using a static URL and make it dynamic so it always would be pointing to the right domain?
string url = string.Format("http://localhost:61123/ProductPage.aspx?BC={0}&From={1}", barCode, "Search");
Response.Redirect(url);
Thanks.
Use HttpContext.Current.Request.Url in your controller to see the URL. Url contains many things including Host which is what you're looking for.
By the way, if you're using the latest .Net 4.6+ you can create the string like so:
string url = $"{HttpContext.Current.Request.Url.Host}/ProductPage.aspx?BC={barCode}&From={"Search"}";
Or you can use string.Format
string host = HttpContext.Current.Request.Url.Host;
string url = string.Format("{0}/ProductPage.aspx?BC={1}&From={2}"), host, barCode, "Search";
You can store the Host segment in your AppSettings section of your Web.Config file (per config / environment like so)
Debug / Development Web.Config
Production / Release Web.Config (with config override to replace the localhost value with something.org host)
and then use it in your code like so.
// Creates a URI using the HostUrlSegment set in the current web.config
Uri hostUri = new Uri(ConfigurationManager.AppSettings.Get("HostUrlSegment"));
// does something like Path.Combine(..) to construct a proper Url with the hostName
// and the other url segments. The $ is a new C# construct to do string interpolation
// (makes for readable code)
Uri fullUri = new Uri(hostUri, $"ProductPage.aspx?BC={barCode}&From=Search");
// fullUrl.AbosoluteUri will contain the proper Url
Response.Redirect(fullUri.AbsoluteUri);
The Uri class has a lot of useful properties and methods to give you Relative Url, AbsoluteUrl, your Url Fragments, Host name etc etc.
This should do it.
string url = string.Format("ProductPage.aspx?BC={0}&From={1}", barCode, "Search");
Response.Redirect(url);
If you are using .Net 4.6+ you can also use this string interpolation version
string url = $"ProductPage.aspx?BC={barcode}&From=Search";
Response.Redirect(url);
You should just be able to omit the hostname to stay on the current domain.

Mobile Services: How to handle the case where your query string is too long?

With Azure Mobile Services Offline Support I'm issuing a PullAsync query like so:
// This list contains 53 emails
var deviceContactEmails = new List<string> { "derek#gmail.com", "sarah#gmail.com", ... };
var query = _userTable.Where(x => deviceContactEmails.Contains(x.Email));
await _userTable.PullAsync(query);
The Mobile Services SDK translates query into a URL encoded GET request with a filter like so (this was a list of 60 emails used for the Contains but I cut out a lot of the middle for brevity):
https://rememberwhen.azure-mobile.net/tables/User?$filter=((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net')%20or%20(email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))%20or%20(email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))%20or%20(email%20eq%20'carlin_jmecwrv_stulberg%40tfbnw.net'))&$skip=0&$top=50&__includeDeleted=true&__systemproperties=__createdAt%2C__version
The problem is that if deviceContactEmails is too long, the service will complain about the query string length. Trying to filter on this many items in the URL is a problem, so I need to filter by passing the items in the body of the request with JSON or some other way.
So I guess the question is: How do I correctly set this up using the Mobile Service SDK with offline support so I can avoid exceeding the limit on the query string length in the URL encoded request?
It looks like I need to create a custom API to send the list of emails as the body of the request. I'll update this answer and accept if I solve it.

Query String from the URL

I have an application URL that can be launched from browser with query string passed in.
My Development URL is
http://localhost:15094/MyPage.html?user=username&role=admin
Client URL will be path to MyPage.html in the hard Drive
file:///C:/Program%20Files/Client/MyPage.html?user=username&role=admin
When the url is localhost with http, i can extract the query string using
System.Windows.Browser.HtmlPage.Document.DocumentUri.Query
// this gives me ?user=username&role=admin
// from http://localhost:15094/MyPage.html?user=username&role=admin
But I want ?user=username&role=admin when client use the URL
file:///C:/Program%20Files/Client/MyPage.html?user=username&role=admin
System.Windows.Browser.HtmlPage.Document.DocumentUri.Query does not work with it I suppose.
Please note Development URL is with http and when the application is installed on a Client's machine, the url will be without http, this is how application should work. Please do not suggest to host it in IIS etc.
My Question is very simple:
How would you extract the query string from "file:///C:/Program%20Files/Client/MyPage.html?user=username&role=admin" ?
If System.Windows.Browser.HtmlPage.Document.DocumentUri.Query works fine for url's without http, why I am not getting query string right?
A simple way to do this without being clever is to use IndexOf eg:
var originalUrl = "file:///C:/Program%20Files/Client/MyPage.html?user=username&role=admin";
var extractedQueryString = string.Empty;
if(originalUrl.IndexOf("?") != -1)
{
extractedQueryString = originalUrl.Substring(originalUrl.IndexOf("?"));
}
Wrote this off the top of my head without compiling but think I got it right.
Also to get the filename part of the string if you're wondering would be:
var extractedFileName = originalUrl.Substring(0, originalUrl.IndexOf("?"));

Safe Process.Start implementation for untrusted URL strings

My goal is to safely open a web page in a users default browser. The URL for this web page is considered "untrusted" (think of it as a link in a document opened with this software, but the document could be from anywhere and the links in it could be malicious)
I want to avoid someone passing "C:\Windows\malicious_code.exe" off as a URL
My current thought is to do something like this:
Uri url = new Uri(urlString, UriKind.Absolute);
if( url.Scheme == Uri.UriSchemeHttp || url.Scheme == Uri.UriSchemeHttps )
{
Process.Start(url.AbsoluteUri);
}
Am I forgetting about anything else that my 'urlString' might contain that makes this dangerous (e.g. a new line character which would allow someone to sneak a second process to be started in after the URL or a possible execution of a relative executable starting with http)?
I'm pretty sure both of those cases are handled by this (as I don't believe Process.Start allows you to start two processes as you would in a BATCH file and this should only allow strings starting with http: or https: and are valid urls)
Is there a better way to do this in C#?
What you want to check is the scheme of the url (i.e. ftp://, http://, file://, etc.) Here is a list of schemes: http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes
To find the scheme of a URL, use:
Uri u = new Uri("C:\\Windows");
String scheme = (u.GetLeftPart(UriPartial.Scheme).ToString());
For me, the above example gives file://. Just check the scheme, using the code above, and reject the ones you want to filter. Also, surround the parsing with a try-catch block and if an exception is caught, reject the URL; it can't be parsed so you shouldn't trust it.
If you want to ultra-paranoid-safe, you could always parse the URL using a URL parser and reconstruct it, validating each part as you go along.

Categories