ASP.NET Authentication Troubleshooting - c#

I have a fairly complex web app that was built (by a contractor) to use integrated authentication. As part of the authentication process, a GetNetworkID() function is used that looks like this:
private string GetNetworkID()
{
return HttpContext.Current.User.Identity.Name.Split(new char[] { '\\' })[1];
}
When I run this on my development box, the HttpContext.Current.User.Identity.Name value is
myNetwork\\myUserID, so the above funciton returns my User ID, as intended, and the authenticaiton process works just fine.
But when I run this on my web server, I get an Index was outside the bounds of the array error thrown by the return statement in the GetNetworkID() function.
I'm a bit lost on how to troubleshoot this and how to figure out if it's an IIS configuration issue (my web server is a Windows Server 2008 box running IIS 7), or something else.
If I hard-code my User ID as the return value for the GetNetworkID() function, it works on the web server, but I don't have any great ideas about how to debug on the web server to determine what the HttpContext.Current.User.Identity.Name return value is that's causing the array index error.
Any suggestions?

IIS runs as the IIS Service Account, so Current.User.Identity is likely going to be the name of the IIS Account.
For completeness sake, you should check for '\' either with a Find() or by calling split, and checking the length of the resultant array. If the length is 1, that means the id isn't in the form of domain\username.
In general, if you want to debug, you can write any value to the HTTP Response stream like so:
Response.Write(HttpContext.Current.User.Identity.Name)
Another method is to setup an ASP page variable, and set the page variable to the value you'd like to inspect. You can display the variable value either through ASP code, or through Javascript.

You might be missing an IIS setting.
Try in IIS:
Website (right click) | Properties | Directory Security (tab)
Click "Edit..."
Then select "Integrated Windows Authentication"

I think the user that logs into your web applciation on the other server, is not a valid login. And hence a result is not returned on User.Identity.Name.
Like you said, it works when you hardcoded the username.
This means, the user creditials of the PC you are using to login is not permitted on your site. This therefore must be different to the credentials you are hardcoding.
Best bet is to debug on web server (it isn't hard - all you want to return is the User.Identity.Name and you can get the username and deduce logic from there), and verify the contents in your web.config file.

As Alan pointed out (and I upvoted him for it) you probably want to add a check on what form the User.Identity.Name takes. An updated routine could for example look like this:
private string GetNetworkID()
{
var name = HttpContext.Current.User.Identity.Name;
return name.InStr("\\") > -1 ? name.Split("\\")[1] : name;
}
This will return the second part of the login name if a \ is present, and the full string if not.

Related

MVC5 block Action from all but localhost

I looked for a solution to this problem that seems simple to me without success on the internet.
In a sample project I've made for the test :
I have a Controller NotAuthorizedwith a public ActionResult Index() { return View(); }
The Index view only contain the text This page need to be only available in local.
So, my problem is that, I want that the only way to access NotAuthorized/Index is from IIS himself, anybody from LAN or WAN need to get a 403 error.
I think web.config can do the job but is it secured ? and how to implement it ?
It's for a big project, I need to block an API from internet because only the application need to use it.
In the final project, the application use it by local adress like "127.0.0.1/xxx".
Sorry for my english, not my language.
Edit : (following greatbear302 solution)
Tested on a published application with WebDeploy (what I need).
The site bindings are :
192.168.0.5:9999
testmvc on 192.168.0.5:80
On IIS, I click on my site, and in the Views directory, on my 'NotAuthorized' directory who contain the page I don't want users can access.
On the IP Address and Domain Restrictions, I've set All deny and 192.168.0.5 (IIS) authorized.
running tests :
192.168.0.5:9999/NotAuthorized: I see the page.
testmvc/NotAuthorized : I see the page.
I don't know what to do next.
In IIS
Click on your site
Click IP Address and Domain Restrictions (if this feature is missing, install from Add Remove Windows Components in Control Panel)
Click Allow Entry on right most pane
In Specific IP Address field, enter the IP address of the server hosting your API and click OK
Click Edit Feature Settings, in Access for Unspecified Clients, select Deny and click OK
Without any success with IIS, I go on a basic IP filtering on the application.
My IIS execute the application on 192.168.0.5 so here my code :
public ActionResult Index() {
ViewBag.UserIP = Request.UserHostAddress;
if (Request.UserHostAddress != "192.168.0.5")
throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Accès non autorisé");
return View();
}
It do the job. I'll see in the future if I can make a better solution for my problem.

Is there a variable to see if a website has been deployed

As the title says really - is there a built in c# (or MVC) variable, ie something in httpcontext or something like that, that can tell me if the site has been deployed to the live server (or if it is running locally) or do I need to put something into the web.config?
Also does
#if DEBUG
#endif
Only fire locally or can a deployed site also run in debug mode?
There is nothing built-in that you can use. You need to give your application that capability yourself.
If you know the IP address or domain name of the "live" web server, you can use Request.ServerVariables["LOCAL_ADDR"] or the Request.Url.Host property respectively to determine whether or not it has been deployed.
public bool IsDeployed()
{
return Request.ServerVariables["LOCAL_ADDR"] == "123.123.123.123";
// or for domain name
return Request.Url.Host == "mydomain.com";
}

open a webpage on specific computers even internet is active on computer

I have webpage for my company with user name password protected.
Now I want to open that webpage on specific computers those I allow, even internet is active on that computer.I am using asp.net 4.0 with c#.
Is there any one help me that i can allow only specific computers to open that webpage otherwise it will generate error.
Anyone Help Plz !
Create a whitelist of ip of allowed computer.
in global.asax match the ip with the ip in your list.
If ip is not in the list redirect to error page else continue.
For above method the ip need to be static. If this is not possible then follow this method.
Create a page in your website for loggingin...
give the url to only users/computer to which you want to activate.
when the authentication occurs and successfull write a cookie.
delete you newly created page.
again in your global.asax search for this cookie value .
if value is found then ok else redirect to error page.
You must set your cookie value like 180 days so that you dont need to reactivate your 2nd login page.
however if possible use 1st method only.
As you application require user name and password to open it.
As all the request goes first to gloabal file as follows
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
string localAddress = Context.Request.ServerVariables["LOCAL_ADDR"];
// Returns "::1" when running under the VS server, however it throws an
// exception under IIS Express, so I assume it also does so under IIS.
}
Create a list anywhere and keep the ip's list which is allowed.
If it is one of those then allow it.
Other wise deny the request.
Here is good link if you have a range define
How to check a input IP fall in a specific IP range

HttpContext.Current.Request.Url.Authority giving wrong Authority names

I have two production web servers that are load balanced and that sit in a DMZ. I have a form that needs to open another form based on certain criteria. One of the servers works fine and gives the full authority name ie, "host.n.n.com". The other prod server only returns "host" and as a result the page cannot be found. Here's the code i'm using:
urlString.Append(url.Scheme);
urlString.Append("://");
urlString.Append(url.Authority);
urlString.Append("/somedir/anotherdir/");
urlString.Append(formName + ".aspx");
server 1(working) comes back with http://host.n.n.com/somedir/anotherdir/formName.aspx
server 2(broke) comes back with http://host/somedir/anotherdir/formName.aspx
IIS appears to be onfigured the same across both servers.
Thanks in advance for any help
The Authority property comes from the request itself.
If the request from the user is made from 'host.n.n.com' or 'host' This is what the property will reflect. You can test this locally by using http://localhost/yoursite/page.aspx vs http://yourcomputername/yoursite/page.aspx. The same page will return 'localhost` and 'yourcomputername' respectively.
Why not make the URL a configuration setting?

Open website in the user's default browser without letting them launch anything else?

I would like to open a website in a user's default web browser, however since the url is user-defined I would also like to prevent them from doing anything other than opening a website.
I have seen people use Process.Start(url); to open a site in the default browser, but since the url is user-defined I want to be sure they don't enter something like a script location and execute it.
I also don't want to use Process.Start("iexplore", url); since I would rather open the link in the user's default browser.
Is there a way I can open a website in the user's default browser, without letting them launch any other process or command?
EDIT
For example, I don't want users to be able to enter C:\Windows\Notepad.exe into the Customer's Website field and open Notepad when they click the Website link
EDIT #2
I am not looking for a way to filter user's access online or have this substitute for property security. I am simply looking for a way to prevent users from launching any other application by entering in a bad url. If they enter "google" for a Customer's website, it should not throw an Open With file dialog, but instead launch the user's default web browser with the word "google" in the URL
You could look up the default browser from the registry. It's in several different places, but I think HKEY_CURRENT_USER\Software\Classes\http\shell\open\command would be a good place to look.
Extract the executable name from that, then Process.Start it with the user-entered URL as a parameter.
I found a way to do it, however I haven't tested to see if this will work on other operating systems
I get the Path for the DefaultWebBrowser from the registry and then use Process.Start(defaultBrowserPath, url);
public static void OpenWebsite(string url)
{
Process.Start(GetDefaultBrowserPath(), url);
}
private static string GetDefaultBrowserPath()
{
string key = #"http\shell\open\command";
RegistryKey registryKey =
Registry.ClassesRoot.OpenSubKey(key, false);
return ((string)registryKey.GetValue(null, null)).Split('"')[1];
}
Well, not really. What you could do is check whether it's a HTTP(s) URL, and whether the URL returns a text/html content-type - but not even that will help if the browser uses content sniffing (ignores content-type, tries to determine it from file content - IIRC IE6 does this, not sure what others).
Also, various browsers are susceptible to various security holes in malformed URLs (why does IE come to mind again?), so you may want to check for things like null hacks, EOL hacks, etc etc.
In the end, there is no perfect URL check - old/unpatched browsers will always be susceptible to some exploits, and that's not really something you can fix. You can, however, filter out most of them - whether it will be 80%, 99%, or 99.99%, depends on the amount of time you are willing to invest.
If I'm understanding you right, then there is no solution to the problem you describe. You're saying: how can I filter user-entered data (hopefully in the form of a Uri, but even a Uri is a very broad concept) to ensure that it's not malicious content. The answer is that without doing it manually, you can't.
http://here.dowloadmyvirus.com is a perfectly valid site Uri but you can never ever guarantee the content that will be served from there.
It needn't even be a Uri: if you hit Start/Run and type "iexplore c:\windows\notepad.exe" then (with IE9 RTM) I get my own local notepad.exe launched as a download. There's nothing to stop you pointing at a malicious script hosted online.
I'd suggest that you either need to limit access so that only a few trusted users can edit whatever data it is you're managing, or have an audit process in place to ensure that such content is validated before it's published.
I've worked out a way, which takes advantage of the fact that javascript runs in a sandbox.
Have a web-page (e.g. http://mydomain/LaunchPage.html) that is accessibly to your desktop application. Call it by putting your URL on the query string (so http://mydomain/LaunchPage.html?URL=http://www.google.com).
All the LaunchPage does is to use JavaScript to set the document.location.
<script>
/*
* Retrieve names values from the query string.
* Based on an idea from
* http://ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/Get_Query_String_Using_Javascript.shtml
*/
function queryString(key) {
args = window.location.search.substring(1).split("&");
for (i = 0; i < args.length; i++) {
keyValuePair = args[i].split("=");
if (keyValuePair[0].toUpperCase() == key.toUpperCase()) {
return keyValuePair[1];
}
}
return null;
}
document.Location = queryString("URL");
</script>
If the URL is set to a local file or something, then the JavaScript sandbox will prevent it being used.
You can now use the following code in perfect safety.
Process.Start("http://mydomain/LaunchPage.html?URL=C:\Windows\Notepad.exe")
EDIT Note that the HTML file could be installed alongside your application. If you have done this, the code to launch it would be something like:
Process.Start("c:\<InstallRoot>\LaunchPage.html?URL=C:\Windows\Notepad.exe")
I think you can check the url to confirm that it is a valid URL not a path of an executable file.
You can use regular expressions to validate the url, have a look here here.
Good luck!
It seems to me that you are worrying about something that is not in fact a problem. If the user could run a program rather than a URL from your app, then they could just as well run a program themselves. It's only a security concern if you accept input from some entity other than the logged on user.

Categories

Resources