Showing posts with label Security. Show all posts
Showing posts with label Security. Show all posts

Monday, June 11, 2018

How to use Google to find unsecured web.configs

I can't believe how easy it is to find web.config that are not secured. Put this into Google and you will be amazed at what you will get back.

inurl:ftp inurl:web.config filetype:config

or

inurl:http inurl:web.config filetype:config

Imagine if any of them have passwords in them.

inurl:ftp inurl:web.config password

or

inurl:http inurl:web.config password



Saturday, May 20, 2017

Securing your ASP.NET MVC website Checklist

First, let me start by saying this is not a comprehensive list, but it is a good start.

Add headers for all requests

Add this to your web.config
<system.webServer>
    <httpProtocol>
      <customHeaders>
        <clear />
<remove name="X-AspNet-Version" />
<remove name="X-AspNetMvc-Version" />
<remove name="X-Powered-By" />
<remove name="Server" />
        <add name="X-XSS-Protection" value="1; mode=block"/>
        <add name="X-Content-Type-Options" value="nosniff"/>
        <add name="Strict-Transport-Security" value="max-age=31536000"/>
<add name="X-Frame-Options" value="DENY" />
<add name="Referrer-Policy" value="no-referrer" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>

This does a good job of explaining what some of the header options are

Require Strong Passwords

Go to your AccountController and find the code that creates the PasswordValidator and change it to something like this. Length is the most important thing to consider from a cryptographic complexity. 

NOTE: 12 is the minimum required, but 16 is better to make it sufficiently time consuming to hack.

manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 12,
                RequireNonLetterOrDigit = true,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true
            };

Remove ASP.NET Technology Headers


In Global.asax add the following to the Application_Start() event.

MvcHandler.DisableMvcResponseHeader = true;

You will also need to add the following to the web.config

<system.web>
<httpRuntime targetFramework="4.5.2" enableVersionHeader="false" />
</system.web>


Remove Server Info from headers

Add the following to Global.asax.cs

protected void Application_PreSendRequestHeaders()
        {
            if (HttpContext.Current != null)
            {
                HttpContext.Current.Response.Headers.Remove("Server");
            }
        }


Also read through security issues that require reviewing your code and maybe some knowledge of how your application is written.

Restrict origin of anything loaded

To be extra safe look at adding creating a white list of what stylesheets, scripts, etc can be loaded. This will take some digging on your site, but is probably worth the effort.


There is a nuget package that does some of this. This looks to be a better choice as it is per controller, etc and explains how to use it.


X-Frame-Options

MVC5 will add in the X-Frame-Option by default. If you want to remove it and make it DENY you will need to add the following line to your Application_Start() method in the Global.asax.cs.

System.Web.Helpers.AntiForgeryConfig.SuppressXFrameOptionsHeader = true;



Thursday, May 18, 2017

OWASP Top 10 Security for ASP.NET tips you may not know about

Below are my notes on what I thought was important out of the OWASP Top 10 Web Application Security Risks for ASP.NET

SQL Injection

Havij for testing for SQL Injection on a web url

Encoding output

Use the appropriate encoding (escaping character or character sequences) for the context you are using the input.

Use AntiXssEncoder.HtmlEncode() to HTML encode input when using web forms. (Available in NuGet or .NET 4.5). For example, use this before rendering user input what to the screen. <%: %> Syntax will automatically encode it.

ASP.NET MVC Razor automatically encodes for HTML unless you tell it not to. For example, on Model/ViewModel add the [AllowHtml] attribute to the property you want to allow.

Use Microsoft.Security.Application.Encoder.JavaScriptEncode() to encode input for JavaScript. For example taking input and assigning to a JavaScript variable.


You can turn off request validation at the site level (web.config) or the page level. See here for more details.

Hiding Payload

Url encoding can be used by hackers to get around XSS detectors and make the payload unclear to the average user. Another approach is to use a url shortener like tinyurl.com.

Session Persistence

Don't use the url for any sensitive information since they are in web logs, browser history, etc. A session id is definitely sensitive information that can allow someone else to be you while that session is still active. Cookies are a much safer place to pass and persist session ids. The only downside is cookies need to be enabled, but most people have cookies enabled. Cookies is the default behaviour for ASP.NET. Be sure to never send cookie with secret in it over an insecure connection.

Session Timeouts

In the case of a sliding forms timeout it is nice in that it can be extended forever by hitting the url and thus give a large window were someone can use a hijacked session.This is great for valid users and hackers love it too. So, turn off sliding timeout if you can to increase security.

The alternate is to set a fixed session timeout, but the problem is users will lose their session at the end of the timeout no matter what they are doing. There is no perfect solution for all cases. Set according to your needs to strike a balance between security and convenience for users. Do change default values to meet specific needs.

Indirect Reference Map

Indirect references can be used to conceal internal keys, but they are NEVER a substitute for access controls. Each internal id is replaced with a temporary indirect reference (that is stored on the server in the session for example and never exposed to the browser / user). This temporary indirect reference is cryptographically random and has no pattern for guessing. Once the session ends this mapping should expire. The map should be user specific so that it can't be used by any other user. This greatly reduces the ability for an attack by limiting who can use it and limiting the length of time it is valid and making it not guessable based on a pattern. 

Thought on GUIDs. A GUID is not a map. It is unique and does not have a pattern. They should be viewed as obfuscation of the key. They are not user specific and proper Access Control is a MUST if GUIDs are used. They do have the advantage they they cannot be enumerated easily and close to being Globally Unique. A better choice would be to use System.Security.Cryptography.RNGCryptoGraphicProvider.GetBytes() then HttpServerUtility.UrlTokenEncode() and a map instead of a GUID.

Access Control

Just because the url is not visible in the browser's url bar don't assume that a hacker can't look at the source of the page for urls to hack. The best defense is to add code on the controller action that checks the direct and indirect referenced keys belong to the user that is sending them. For example, if the user was passing the id of the record to be displayed, the controller action that displays the record should check that that user has access to that record.

Cross Site Request Forgery

Put simply it is a way to trick the browser to making valid request from an evil site by exploiting the fact that cookies are sent for all requests from that domain. The evil site make a request that is identical in form to the request that the original site would have done, but with malicious payload. It could for example, take advantage of an authentication cookie that was not secured property. 

ASP.NET MVC has a mechanism that adds randomness via a CSRF token.  This token is known to the legitimate page where the form is as a hidden field and the to the browser via a cookie. When the request is sent to the server both the hidden value and the cookie are sent and the server compares them and they must match. The trick is the hacker won't know what the value to put in the form so the attack will fail. This is actually very effective protection.

To implement this, you need to do two things. Add the attriubute called ValidateAntiForgeryToken to the controller action. Also, add @AntiForgeryToken() to you view just inside the BeginForm() brackets. 

Once you implement this, you will see a __RequestVerificationToken in the Request body when the request is made. There is also a matching cookie called __RequestVerificationToken. When the CRSF attack is executed the authentication cookie and the __ReuestVerificationToken cookies are sent with the attack request, but ASP.NET MVC returns a 500 error because there is no (or invalid) form field called __RequestVerificationToken in the request. The hacker doesn't have direct access to the cookies, but they are sent automatically by the browser. Thus the hacker has no way of know the CSRF token value. Attack has been stopped.

NOTE: There is also an Authorize attribute that is often the first line of defense, not as useful for CSRF attack since often authenticated users are the ones tricked into making the attacks.

NOTE: Checking the Referrer site can be helpful, but doesn't protect from CSRF.

Trace.axd

It contains such as cookies such as authToken, CSRF token, etc potentially connection string, versions of software, etc. Luckily the url is disabled by default. This can be enabled in MVC and Web Forms. Use a config transformation to remove the trace node on the Release configuration in case it is ever enabled in the web.config file.

Encrypt Connection String in web.config

It is good to have multiple layers of security. In case a hacker is able to access your web.config you want to limit what he can see. The connection string is quite important and should be encrypted.

To do so, run a command prompt as Administrator and execute:
aspnet-regiis -site "name of site in IIS" -app "app name or /" -pe "connectionStrings"

This uses the encryption key on the server and is server specific. So, it must be executed on that server.

The remaining risk is that someone can go to the server and run a the command to decrypt the string, so limit who can access the server.

Enable Retail Mode

Retail Mode prevents leaking of exception data on YSOD even when configuration is wrong for ALL applications on server. To do so, add the following deployment tag to the machine.config. This forces the same behavior as enabling customErrors. It is a safety net for all applications. 

<system.web>
      <deployment retail="true"/>

Password Rules

Make it harder for hackers by requiring longer passwords, not allowing words in the dictionary or variations of them, and require special characters, mixed case, numbers.

Storage of Passwords

If a hacker can get the username and salt and the hashed value and the operation used by the system to do the hashing then they can brute force attach and recover over 65% of the passwords (on average). To do this they simply call the hashing operation with a password from their list of likely passwords using the salt that they gained access to. Now they compare the hashes. If they are the same then they know the password that was originally used by the user. They now have everything needed to login as that user.

Membership Provider Default Implementation use near useless because we have both the hash and salt. Also SHA1 is too fast of an algorithm which means it can be cracked faster.

Be careful if someone has used your password on the internet and that hash has been compromised then a simple google search for that hash can show what the original password was. If a long salt was used then rainbow tables become useless. Salts make it harder to crash a hash, but it is just a matter of time and with Modern GPUs computing 7.5 billion hashes per second (in 2012) it is literally just a matter of time.

Check out Kerckhoffs' principle if you are wondering if your security is good. Basically it says, if you are not willing to give the design of how your security works and are thus relying on this lack of knowledge as part of the security then your security is not good enough. You must assume the attacker will learn how the security works soon enough.

Cryptography-Hashing

Faster algorithms are not good ironically. We actually want the hashing algorithm to take as long as we can stand. This is balanced with the processing required to login or register for example and how long it will take to hack. SHA1 is probably not sufficient anymore. One way around this is to apply the algorithm say 1000 times, but again that probably isn't enough. BCrypt allows us to directly control how many times we apply the algorithm.

No algorithm is fool proof especially when lists of password and hashes and salts are cataloged. It is all about making it too difficult / time consuming / financially unjustified, etc to do it. Even the most complex algorithms can be circumvented by cataloging the input and outputs.

Cyptography- Encryption

Encryption is less desirable than hashing because if the key is obtained then all the encrypted values can be decrypted and the original values are available. With Hashing it is a one way process and the original value cannot be obtained using the algorithm (must hack as noted earlier). 

The trick with encryption is that you must manage the safety of the key. DPAPI uses the machine key on the server the code is running on to do the encryption and decryption (symmetric algorithm) so the application does not have to.

Password Hacking tools

hashcat - advanced password recovery - brute force for comparing hashes and common hashing algorithms
RainbowCrack - Use rainbow tables to get a pregenerated list of hashes meeting different rules for password.

Restricting Urls in MVC

Don't use web.config location tag permission restrictions because it is based on url, not page. In MVC more than one route can point to the same page, but only the urls used to access them is protected in the location tag in web.config. This means if you have two routes you have to have to location tags in the web.config. This could lead to very buggy and inconsistent access. It worked well in Web Forms because the page is the url.

For MVC you want to protect the Controller and actions of the controller. The way to do that is the Authorize attribute. Just using it requires authenticated users. If you want to restrict to a role you can comma separate list them as a parameter to the Authorize attribute.

Don't forget to protect resources like JavaScript, reports, ajax calls, reports, API's, pdfs, etc. Really anything that is not in the browsers url bar, but does show up in the network traffic.

Side note: Never send sensitive data in the url because they can be in web server logs, error logs, history, etc.

Just because a url can't be guessed doesn't make it secure. Urls get leaked through many different routes such that they don't have to be guessed.

Insufficient Transport Layer Protection

If TLS (Transport Layer Security) is not properly done it opens up the opportunity for a MiTM (Man in the Middle) attack. This can be done by physically tap an ethernet cable, intercept traffic at the ISP level, monitor unprotected traffic at a wifi hotspot, or create a rogue wireless access point. 

With MiTM the attacker can see all http (not https though this is debatable) traffic from the victim. This would include any cookies that are not secured with HTTPS. All cookies that have sensitive information (arguably all do) should only be allowed to be sent via HTTPS (and the cookie not sent if http is used). 

To do this in ASP.NET WebForms you need to set the cookie with Secure to Yes by changing the web.config by adding a <httpCookies requireSSL="true" />. It can also be overridden per request using Response.Cookies.Add(). When you do this if you hit a page that uses HTTP the cookie will not be sent. If this is the authentication cookie it will ask you to log in again (won't be able to) if you access a http link from and https page because the auth cookie is not sent for the http page.

You can also require HTTPS per controller action by adding a RequireHttps. This will make sure the url cannot be access to HTTP. It is best to direct them to the HTTPS version instead of relying on a redirect from http to https. 

As a best practice and to avoid a browser warning that the entire site should use http instead a mixed of http and https. This can show up when the site requires https, but a script tag references http:// as the source. A clean way around this is to use protocol relative url. To do this set source="//hostname/somelib.js". Basically just remove the http: or https: from the url. It will then assume the protocol of the page (i.e. https). Be sure the url you are access supports both http and https.

As a side note, when using a load balancer the request comes to the load balancer  as HTTPS, but by the time it gets to the web server itself it is no longer HTTPS (it is HTTP). In this case, the load balancer typically adds HTTP X-forwarded-proto header headers instead of built in secure cookie attribute. This will require custom implementation.

HSTS is HTTP strict transport security and tells the browser to never make a http request to the site. The header Strict-Transport-Security does this. It has its limitations and patchy in browsers, but is still a good line of defense. it does require the certificate to be trusted.

HSTS can be implemented in an ASP.NET MVC application by adding the following to your web.config

<system.webServer>
       <httpProtocol>
      <customHeaders>
        <add name="Strict-Transport-Security" value="max-age=31536000"/>
      </customHeaders>
    </httpProtocol>
  </system.webServer>

Do NOT show a login form over HTTP (use HTTPS), even if the post is to HTTPS. The reason is that a MiTM attack could inject code on the page to do something like get form values (username and password) and send them off to another location in parallel to the normal submission.

Do NOT load HTTPS login forms inside an iframe on a HTTP page because the parent page is vulnerable and could be manipulated to load a different login form into the iframe. A better choice would be to show the actual login in a full screen window so users can see url and the secure icon in the browser.

Do NOT put username and passwords in urls because they are often in web server logs in plain text, etc.

Unvalidated Redirects and Forwards = bad reputation

They are useful to attackers because the unvalidated redirects abuse the trust the victim has in the site they trust.

Imagine you have a site and you want to track when a user clicks on a link so you have a redirect action on your controller that takes a target url that the user is to be redirected to. Another is how ASP.NET takes the user to the login page when they try to access a page that they don't have access to. In this case, the target url is an internal url or atleast is expected to be. 

The problem comes when a hacker manages to change the target url (when it is not validated) in the redirect link. From the users perspective the site they are on is one they likely trust or looks legitimate, but when the hacker gets to change the target url they can take them where ever they want. The user is harmed in this scenario and the site with this link is also. 

Now imagine the user receives a spam email and the link is something like http://1.usa.gov/OYCBM7. It could be via email, social media, compromised legitimate sites, etc. This could come from a url shortner site to make it difficult to tell where it is coming from. It also has a .gov so people will likely trust it. The long version of the url could be something like http://trustedsite.com/redirect?url=http://evilsite.com/malware. It could also have the query string encoded to obfuscate it.This also gets by blacklist detectors.

If you don't validate redirects and forwards on your site you are a potential target hackers to use your site for their evil ways. To protect your site, you need to validate the querystring before you redirect to the target site. The best way to do this is have a white list of acceptable urls. The white list could be a regex, string literal, int, list, etc. This would be in the action on the controller, etc where the redirect is done. 

There are scenario where you can't use a white list. In this case, you can check the referrer (UrlReferrer) in the request to determine if the user came from our site or some other site. In particular, the UrlReferrer will be null when request came from a non-browser request such as email client, twitter client, pasting into url bar in browser, etc. We can also check if the request is from our site (Request.UrlReferrer.Host != Request.Url.Host).

This is not 100% risk free. For example, Referrer header value can be faked / changed to be whatever and circumvent checks. This is not what happens when a victim follows a link though.

Security Related Sites

nakedsecurity
hak5
Troy Hunt

Tuesday, November 15, 2016

DDoS Attack (Denial of Service Attack)

Did you know?

Click here to get a visualization or data on what are the major denial of service attacks that are happening right now or in the past.

Click here For the latest news on DDos Attacks

Monday, October 17, 2016

Links of Interests

The C4 software architecture model
Google Maps Geocoding API - Address parsing, etc
F-secure VPN - proxy to any location, great, but not so cost effective
Google DeepMind Forum Post
Google DeepMind article in Nature Magazine
Public Lecture with Google DeepMind's Demis Hassabis
Best practices for deploying passwords and other sensitive data to ASP.NET and Azure App Service
Cloud Design Patterns
Selenium Bootcamp
Have I been pwned? - check if an email address has been breached.
Havij - SQL Injection penetration tool
Showdan.io - search engine for connected devices
Best of Troy Hunt
DevOps sessions from Build

REST
Reading:

Online Training:

Friday, September 23, 2016

Take aways from Agile on the Beach 2016

I attended Agile on the Beach in Falmouth (England). It was really great to hear so many people with different experiences. The videos and slides can be found here. Below are some of the highlights of what I found particularly interesting.

Keynote by Dr. Linda Rising
  • Surprisingly, people are moved to action by stories NOT facts (or evidence). In fact when someone is shown evidence as to why they are wrong they only stand firmer in their belief (as a defense mechanism).
  • A placebo can be just as useful as the "real thing" because what we BELIEVE can make us fail or succeed. The placebo allows us to believe in something.
Book: Thinking Fast. Slow...The Progress Principle (I think this is the book :)

Continuous Delivery
  • Tools: NCrunch, CruiseControl.Net, R#, NANT
  • Policy: Develop to one trunk (no long standing branches). Because of this, GIT may not be the best choice.
  • Goal: Want SMALL commits frequently. For example, about once an hour and ideally 2 files.
  • Break refactoring out in a separate commit.
  • Policy: Can't commit when build is broken
  • Policy: Run all tests before commit (on local machine)
  • Policy: Don't go home until a broken build is fixed. This doesn't mean late hours necessarily. It could just mean backing out the offending commit, and addressing it the next day, then recommit.
  • Goal: a pipeline should be about 4 minutes for quick feedback.
  • Goal: it is ideal for it to be faster to redeploy a change using the pipeline than manually backing out a release.
  • Goal: 75% code coverage. Most will be between 50% and 80%
  • Use Feature Toggles when required, but avoid if can.
  • Warm up an app after deploy
  • Measure commit to live time.
Quality Control
  • Broken Windows Effect - one broken window (bug, issue, technical debt, not tested unit, etc) begets more broken windows.
  • As developers we spend 70% of our time reading code (ours or someone else's) and the rest of the time copy and pasting. Consider poorly written code to be a broken window and copy and pasting that implementation pattern the creation of more broken windows.
  • Anti-patterns: Fat controllers, large models, functionality grouped into services or managers (not sure I understand the last one...).
  • Enforce standards on each commit and fail the build. Could be formatting rules, naming conventions, etc. This will make code diffs be much easier because we only have to read meaningful changes, not changes to code formats.
  • Code that is easy to change (opposite of code smell) has: High Cohesion, Loosely coupled, little duplication, low cyclomatic complexity.
  • Tools: ESLint (for JavaScript checking), Resharper, Visual Studio, NDepend, NCover
Problem Solving
  • Shorten Feedback loop: Idea -> Test -> Measure -> Learn -> (loop back)
  • Gall's Law: Solving complex problems (or systems) from scratch in one go does NOT work, but starting with simple case that works and iterating works (summarized from quote from John Gall).
Testing with Continuous Delivery
  • Testing Pyramid (GUI testing, Acceptance testing, unit testing)
  • Interestingly, only 20%-25% of the audience in the Testing in CD talk at AOTB used TDD. Maybe it isn't so surprising because people that already know it and use it may not attend a talk on it when there are new topics to be heard.
  • Interestingly, only 10%-15% of same group used BDD. 
  • Hypothesis Driven Development - Can be written as statements in the following format: We believe <this capability>, Will result in <this outcome>, We will have confidence to proceed when <we see measurable signal>.
Pen Testing (Penetration Testing) 
  • Expect 20-30 minutes scan time depending on application size
  • Run on UI and API.
  • Use BDD to describe security tests (see BDD Security) to have human readable tests for security.
  • Tools can find 70-80% of vulnerabilities, but the rest needs to be manually done.
Pen Testing Tools
  • Static code review using tools like Veracode.
  • BDD_Security - Define security tests using BDD style scenarios.
  • Mittn - define a hardening target using human-readable language
  • Arachni-Scanner - free with source and runs on Windows, Mac, and Linux
  • Gauntlt - may be useful as well to coordinate security tools.
  • ZAP - free security tools / scanner.
  • SSLyze - checks for mis-configurations affecting SSL Servers.
  • Nessus - a paid PCI vulnerability scanner.
Business Agility
  • Process: Test Hypothesis -> Quick delivery and release -> measurement -> repeat
  • Big Bang never works or at least very scary.
  • Use The Strangler Pattern to avoid big bang.
  • Postel's Law - Architect for testability, develop for evolve-ability.
  • Last Response Moment - wait as long as you can (so you have more information), but no longer.
  • Beware of the silver bullet
  • Continuous Delivery - automate as much as you can. Note, you can still have approvals in your process, but the action once approved is still automatic.
  • Conway's Law - organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations
  • Keep systems poised for change.
  • Don't think yes, no to ideas, but instead think what are the risks and benefits. Then the other person get's to decide if it is worth it.
  • Do the simplest possible thing that might work because the complexity may never be needed.
Understanding the problem
Keeping up

Monday, April 11, 2011

How to consume a SharePoint Web Service with WCF Client

SharePoint Web Services are great because they can be called from any computer that can connect to SharePoint, not just the server that is running SharePoint. This is nice for installations of SharePoint like MOSS 2007 or 2010, but it is critical for SharePoint Online (BPOS) or SharePoint 360 where you will NOT have access to the server that SharePoint runs on. The problem is they are not nearly as easy to work with as just using the SharePoint object model, and they don’t expose everything through the web services. This is a real bummer! It is still a very useful alternative for situations where you cannot use the SharePoint Object Model.

There are a few tricks for working with SharePoint Web Services. There are lots of ways you can access the web services. I prefer to use WCF to access the services so that I get cool syntax from XElement.

Here is a list of web services that are available. Let’s use the Webs web service. Below are the step by step (close anyway) to using the web service in Visual Studio 2010.

  1. Create a console (for simplicity) or any other project type in Visual Studio 2010. NOTE: This can be on your laptop that is NOT running SharePoint.
  2. Go to the docs for the Webs Web Service. Here you will see that the url is: http://<Site>/_vti_bin/Webs.asmx you need to replace <Site> with your hostname or dns name, etc.
  3. Add a Service Reference to the above url (after you replaced <Site> with your site info). I am naming my MyWebs, but you can call it whatever you like, just make the appropriate changes to the code I show later.
  4. If you require all users to be authenticated (don’t accept anonymous users) then you will need to change the WCF bindings that were automatically created in your app.config such that it will pass security information to the web service. To do this, just search for the url of the web service. That will take you to a XML tag called endpoint. In that same XML tag you will see an attribute called WebsSoap. In this same app.config do a search for WebsSoap. This will take you to a binding tag. In that binding tag you will see a security tag. That security tag should have a mode=”None” attribute. Change mode=”None” to mode=”TransportCredentialOnly”. Then just below that you will see a transport tag, change the clientCredentialType=”None” to clientCredentialType=”Ntlm” and change the proxyCredentialType=”None” to proxyCredentialType=”Ntlm”
  5. All SharePoint services are work on Site Collections or Sites (webs) so really the docs should say http://<Site>/<subsite>/_vti_bin/Webs.asmx because if you are dealing with a subsite you need to use that url. You don’t need to add a service reference for each site, you can change it in the code. Be sure to change the endpoint address line in the example below.
  6. Since we are using WCF, we get XElement which gives us LINQ syntax and objects from XML. How cool is that! When determining what is available as attributes it is easiest to just look in the debugger (use the visualizer).
  7. Now that we the results as objects we can do whatever we want with them.

NOTE: You can also do this with the old Web Service client, but you don’t have XElement, LINQ support, but changing the URL is as easy as just changing the url and the Credentials property is all you need to change the credentials. You also don’t really have to worry about the WCF app.config stuff, but in the end I still like WCF.

 

private static void GetWebs()
{
    using (var ws = new MyWebs.WebsSoapClient())
    {
        // pass the proper credentials. Comment/Uncomment the proper lines depending on your situation
        ws.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials; // use current security context
        //ws.ClientCredentials.Windows.ClientCredential = new NetworkCredential("username", "password", "domain"); // use another Active Directory account
        //ws.ClientCredentials.Windows.ClientCredential = new NetworkCredential("username", "password"); // use account that is used for BPOS

        // change url to the site we want to work with
        ws.Endpoint.Address = new System.ServiceModel.EndpointAddress("
http://myhost/sites/SomeSiteHere/_vti_bin/Webs.asmx");

        // get all the webs at and below the specified site
        var results = ws.GetAllSubWebCollection();
               
        // use XElement and LINQ to get our results and create objects from the XML.
        var test = from r in results.Elements()
                    orderby r.Attribute("Url").Value
                    select new { Title = r.Attribute("Title").Value, Url = r.Attribute("Url").Value };

        // the results are just objects now, so do whatever you want with them.
        foreach (var item in test)
        {
            //Console.WriteLine(item.Url + " | " + item.Title);
            Console.WriteLine(item.Url);
        }

    }
}

Friday, January 21, 2011

FireFox supports Integrated Windows Authentication

Most people (including me until recently) don’t know that FireFox support Integrated Windows Authentication (NTLM). The behavior that most people are accustomed to is when you go to a web site on a corporate intranet that often requires Windows Authentication using Firefox you get a prompt for your username and password and for Internet Explorer you are logged in automatically. So, the assumption that many people (me included) make is that Firefox doesn’t support Integrated Windows Authentication. Fortunately, this is a wrong assumption.

Internet explorer determines what sites are ok to use Integrated Windows Authentication on by looking to see if the site is in the Intranet Zone which can be done by looking the url, etc. Well Firefox doesn’t use that criteria. Firefox instead uses a white list or in others you have to explicitly tell it which sites to trust and that will then use Integrated Windows Authentication. Since the list is empty by default every site that has Integrated Windows Authentication enabled still gets a prompt. The simple solution is to add the sites that are on your intranet that use Integrated Windows Authentication to this list.

The Easy Way

The good news is that someone created a nice and easy to use Add-on for Firefox. So you can open up Firefox and go to Tools menu | Add-ons | Get Add-ons tab and type in the search box: NTLMAuth. You will likely get one result and it is for an add-on called NTLMAuth For Firefox. Click the Add to Firfox… button, install, and restart Firefox.

Open up Firefox again and go to Tools menu | NTLM-Enabled Sites

You will get a screen that looks like this:

image

All you have to do is add the sites you want to have Integrated Windows Authentication enabled for. No more prompt will be shown for these sites. Please note that you do NOT want to use http:// or anything after the domain name except a colon then port number if it is not port 80.

For example, you could put www.apple.com or myapp.mycompany.com:1234.

For Geeks

The truth be told you don’t need the add-on at all. You can do this with just Firefox itself. The add-on just saves you from changing some configuration items in Firefox.

If you want to do it yourself, here is what you need to do.

  1. Open FireFox
  2. Type about:config in the address bar. (Tip: Don’t let Google try to search on this item if that feature is enabled by hitting escape after you type it). Hit enter of course to go to it.
  3. If you are using FireFox 3.x or later you will be warned. Agree if you want to continue. If you have already told it to not bother you in the past you won’t get this prompt.
  4. You can look through the list or simply type network.automatic in the Filter at the top of the the screen. Look for a line that is called network.automatic-ntlm-auth.trusted-uris. Double-click that like to bring up the tiny little editor. It’ll look like this.

    image 
  5. You can now type in your sites separated by commas. It worked for me without spaces, but I read that you can use spaces also.

    TIP: I recommend just typing them all into notepad or some text editor, then copy and paste the big line into this little textfield.
  6. Click OK and that is it.

Tuesday, May 4, 2010

Getting Current User when using WCF and Silverlight

First off, when you start to create a WCF Service in Visual Studio 2010 or 2008 for that matter, you can choose WCF Service, but if you are using Silverlight as the client, you do NOT want to select this. You want to select, Silverlight-enabled WCF Service. If you don’t or didn’t you can follow the instructions here to make sure a few things are in place and then you will be in the same position as if you had selected the Silverlight-enabled WCF Service.

All I want to do is get the username of the user that is using my Silverlight application. Note, this also opens the door to ASP.NET roles.

Alot of what I read said that if I mess with my app.config and turn on transport or message security then I can get the user if I go to System.ServiceModel.ServiceSecurityContext.Current. Well, maybe that was for a Self-Hosted WCF service or some other scenario, but I could not get it to work in my tests with Silverlight with IIS hosted WCF Service. I think my biggest difficulty with these docs were that all the configuration tags that I expected to see in the web.config (they had an app.config) were not there, but yet I had a working (without security) WCF Service.

I had to assume it uses some defaults. I figured out that I was right. If you read A Developer's Introduction to Windows Communication Foundation 4 you will understand much better. It is a fairly lengthy read, but well worth it. There is actually a section on Workflow Foundation 4, but the first part of the article is most excellent in describing the defaults and how they work. For instance search it for ProtocolMapping to see that the defaults include basicHttpBinding, netTcpBinding, netNamedPipeBinding, and netMsmqBinding. They are defined in the Machine.config. WCF 4 also support inheritance / merging of configuration items. Very cool.

I am using an IIS hosted WCF service. I want to use Windows Authentication for authentication. Nothing fancy. What I found works well and quite easily is ensure the following things are in specified and in synch with each other. They must all agree!

Web Server
  • IIS has anonymous access disabled (not enabled).
  • IIS has Integrated Windows authentication enabled.
  • If you are using Visual Studio 2010 and using the built-in dev server, the default settings are fine. I did NOT have to check the NTLM Authentication checkbox.
Web.config
  • This is needed to have ASP.NET be able to get security info as well.
<system.web>
<authentication mode="Windows"/>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
  • Make sure you have aspnet compatability enabled as follows:
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"  aspNetCompatibilityEnabled="true"/>
Your Service Class
  • Make sure to add the following above your class for your WCF Service. You can also use Required, instead of of Allowed
    [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]

And now the moment of glory. You can now get the user just like you would in ASP.NET.

System.Web.HttpContext.Current.User.Identity.Name

References: A Developer's Introduction to Windows Communication Foundation 4

Monday, October 26, 2009

Make Windows Firewall tell you when it is blocking something

Depending on how Windows Firewall is configured, it may or may not tell you that it blocked something. If you want to configure it to notify you when it blocks something, just do one of the following.

netsh firewall set notifications ENABLE ALL

or

Use regedit and set the value to zero

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsFirewall\DomainProfile\DisableNotifications = 0

You have to stop and start the Windows Firewall service for these settings to take effect. A reboot would also do the trick. :)

Thursday, August 27, 2009

How to get the current user from a Silverlight application

First, when I say current user, I am assuming that you are using NTLM / Windows Authentication / Active Directory. In a ASP.NET website, you would use something like User.Identity.Name. However, in Silverlight there is no such thing. So, the short answer appears to be that you can’t. At least not directly from Silverlight.

The trick is in what other tools do we have that we can use. One option ASP.NET and Javascript combination to get the value from ASP.NET, pass it to the Silverlight control as an initparam, and use it in the Silverlight app. This is is a HUGE security hole. I can’t believe people actual accept this as an option. All someone would have to do is create a .html page that has the Silverlight application object on it, and set the username to some admin user, and there is full access, no password needed. For the code, click here.

Needless to say, I don’t think the above technique is an option. The best option by far is to create a web service and get the value from it. While it is still possible to fake the response from the web server, would be a bit more difficult and would require faking a network route or something similar.

The best option if you can help it is to never need it from Silverlight. Always use this value from the web service that your Silverlight app uses already. That way there is nothing to fake, etc. It is all server-side then. If you have to have the username in the actual Silverlight application, then I recommend don’t use it for security purposes without doing server-side validation also. Think of Silverlight as a first line of defense, and the server-side (web service) being made more robust.

In case, you don’t know what the web service method would look like, below is an example.

public string GetCurrentUsername()
{
return User.Identity.Name;
}

Tuesday, July 28, 2009

Handling 401 (Access Denied) errors with ASP.NET

Handling 401 (Access Denied) errors are easy to handle in ASP.NET. The reason is that it is a simple configuration that can be made at the IIS level, not at the code level.

While it is true you can get to the Request.Status or Request.StatusCode in your Global.asax file. You can also do a Server.Transfer() or Response.Redirect() on your master page. There are lots of ways to handle this. The problem is that if you want to distinguish between 401.1, 401.2, 401.3… 401.7 it is best to use the solution presented here.

Here is a good list of the HTTP Codes. For reference, here is what it says about the 401 codes.

401 - Access denied. IIS defines several different 401 errors that indicate a more specific cause of the error. These specific error codes are displayed in the browser but are not displayed in the IIS log:
401.1 - Logon failed.
401.2 - Logon failed due to server configuration.
401.3 - Unauthorized due to ACL on resource.
401.4 - Authorization failed by filter.
401.5 - Authorization failed by ISAPI/CGI application.
401.7 – Access denied by URL authorization policy on the Web server.

I recommend replacing 401.1 and 401.2 standard files in IIS with your own. This will cause the standard 401.1. and 401.2 pages to not be displayed and instead your custom files be shown to the end user. 401.1 is what the user will get if they click the Cancel button on the authentication prompt. 401.2 is what they will get if they actually have bad username and password for three attempts.

The first thing we need to do is create a new web site or create a virtual directory inside a web site. This is the location were we will save our custom access denied files. In theory you could do this in the same location as your web application, but I like to use the same 401.1 and 401.2 files for all my applications. That way there is less configuration when I deploy a new application to a server.

  1. Make sure Anonymous is enabled under the Directory Security tab.
  2. Navigate in Windows Explorer to the directory and files.
  3. Right-click the directory, choose Properties.
  4. Go to the Security tab and make sure the IIS_WPG group has Read permissions.

To setup your web site (your ASP.NET application) just do the following:

  1. Open up Internet Information Services (IIS) Manager.
  2. Expand Web Sites in the tree view
  3. Right-click on your website or virtual directory and choose the Properties menu item.
  4. Go to the Custom Errors tab as shown below.

    image

  5. Click on 401.1 line and click the Edit… button.
  6. You will see a window titled Edit Custom Error Properties.
  7. Select File from Message type drop down list.
  8. Use the Browse… button to select the access denied page that resides in the anonymous web site we set up.
  9. The window should look something like this.
    image
  10. Do the same thing for the 401.2 item.

Now when a user would normally get the generic 401.1 or 401.2 pages, they will now get your custom pages.