PCI Compliance and Custom Error Pages

On August 14, 2012, in How-to, Technical, by Guest
We are pleased to present this article by guest author Jeff Rhodes. It originally appeared on his blog, which is a great resource for .NET, VB and many other web technologies. We appreciate Jeff giving us permission to republish his fix for PCI scans by Security Metrics.


Those of us who accept credit cards are familiar with PCI (Payment Card Industry) compliance. In addition to protecting credit card numbers and so forth, your web sites need to tested for vulnerability to attacks and hackers. As part of compliance, your web sites are automatically scanned for vulnerabilities. Our site has always passed, but the report would show various weird vulnerabilities that I put down to being on a shared hosting service (DiscountASP.Net). But this most recent scan failed repeatedly with messages like this:

News database accessible over web (news.mdb) Impact: Attackers may access (read or destroy) application information, and in worst cases may take administrative control of the application. Data Sent: GET /help/trainingstudio/TrainingStudioContentEditor/news.mdb

When I went to help/trainingstudio/TrainingStudioContentEditor, there was no file named news.mdb or anything similar. I contacted the scan vendor (Security Metrics) and Emily evaluated the situation and came up with this explanation:

I have looked into these issues and I believe that each one is flagging because we are receiving affirmative (200 OK) responses for non-existent pages. Our scanner is sending a GET request for a specific page or file that is associated with a vulnerable program (ie. Guppy). The response to that GET request is a custom error page that you have created – but that customer error page’s status code is a 200 OK. The scanner sees the 200 OK and it flags the issue.

Sure enough, we had set up our site through DiscountASP.Net’s IIS tools (shown below) to show a custom error page (error.htm) if there was a missing page. So if the user put in a bogus link like http://www.plattecayon.com/cool.htm, that page would display. But unfortunately that page returned the standard 200 status code. I found this nice tool that shows you the actual status code: http://gsitecrawler.com/tools/Server-Status.aspx. When the scan looked for various rogue files, the 200 response put up red flags.

So what to do?

My first thought was to edit the error.htm page to set the status code to 404 (missing page). I had no luck finding a way to do that though. The next best thing was to use an ASP.NET page as that had the power to change the status code programmatically. Here is the code for missingPage.aspx.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
	If IsPostBack = False Then
	    Response.StatusCode = 404
	    Me.UpdateRepeaters(linksRepeater, 41)
	End If
End Sub

The important part is Response.StatusCode = 404. The last step was to make this the custom error page for missing pages. This is done in IIS (Internet Information Services) for non-ASP.NET pages and in web.config for extensions handled by ASP.NET. Here is the DiscountASP.Net interface for the IIS setting.

For the web.config, we used this entry:

<customerrors mode="RemoteOnly" defaultredirect="errorpage.aspx">
 <error statuscode="404" redirect="missingPage.aspx"></error>
</customerrors>

After making the changes, the site passed on the first try.

I hope this is helpful if any of you run into a similar situation. Note that returning the correct status code is helpful for search engines as well.

About Jeff Rhodes
Jeff Rhodes is the Chief Technical Officer and owner of Platte Canyon Multimedia Software Corporation, a leader in developing commercial software that Improves the Lives of Training Developers. He graduated at the top of his class at the Air Force Academy, where he earned a Bachelor of Science in Electrical Engineering. Jeff received a Masters degree in Economics from the London School of Economics, which he attended under a British Marshall Scholarship. Jeff is the author of “Programming for e-Learning Developers: ToolBook, Flash, JavaScript, & Silverlight” and “VBTrain.Net: Creating Computer and Web Based Training with Visual Basic .NET.” He also co-wrote “The ToolBook Companion.” He has had numerous articles on training development published and is a frequent presenter at conferences both in the U.S. and Europe. Jeff lives in Colorado Springs with his wife Sue and sons Derek and Michael.

 

Creating an ADO.net Data Service

On April 14, 2009, in How-to, Technical, by Guest

For the purposes of this demonstration we are using:

IIS 7.0, MS SQL 2008, Visual Studio 2008, C#

ASSUME VARIABLES:
$DASP_SQL_SERVER = tcp:sql2k801.discountasp.net
$DASP_SQL_DB_NAME = SQL2008_99999_nw
$DASP_SQL_USER_NAME = SQL2008_99999_nw_user
$DASP_PASSWORD = somepassword

//Set Up Northwind Database
1) Download the Northwind database sample from Microsoft

2) Attach the Northwind database to your MS SQL 2008 Server on DASP
– Make sure you can connect from MS SQL Data base manager
– Copy the connection string supplied for later use.

3) Open VS2008, Create new web project

4) Create Data Connection
– In the “Server Explorer Tab”: Right-Click[Data Connections]->Add Connection
– Enter Server name:$DASP_SQL_SERVER
– Select “Use SQL Server Authentication”
– Enter Username/Password: $SQL_USER_NAME, $DASP_PASSWORD
– Choose Radio Button “Select or enter a database name”
– From drop down box select: $SQL_DB_NAME
– Click: “Test Connection” button. (Sensure connection succeeded).

//Set up a Entity
5) In “Solution Explorer” tab Righ-Click[Web Project]->Add New Item
– Select: ADO.NET Entity Data Model
– Name it NorthWindModel.edmx
– Next > Select “Generate From Database”
– For Which data connection find the DASP connection in the drop down box
– Select: “Yes, include the sensitive data in the connection string”
– Name: NorthWindEntities (NOTE that “I” is missing from WND in the db name)
– Next> Select the “Customers” table from the db.
– For “Model Name Space” enter “NorthWindNameSpace”. Finish >
– Click on the “NorthWindModel.edmx” page which shows the DB fields
– Jot down the “Entity container Name” in the properties box in the bottom left
– It should be: “NorthWindEntitites”
– This will create a connection string in web.config (replace password characters with “*”):
<add name=”NorthWindEntities” connectionString=”metadata=res://*/NorthWindModel.csdl|res://*/NorthWindModel.ssdl|res://*/NorthWindModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=tcp:sql2k801.discountasp.net;Initial Catalog=SQL2008_99999_nw;Persist Security Info=True;User ID=SQL2008_99999_nw_user;Password=******;MultipleActiveResultSets=True&quot;” providerName=”System.Data.EntityClient” />

//Set up the Service
6) In “Solution Explorer” tab Righ-Click[Web Project]->Add New Item
– Select: ADO.NET Data Service
– Name: NorthWindDataService.svc. ADD >

7) Open WebDataService.svc.cs
– Modify the WebDataService class to look like this:

public class NorthWindDataService : DataService<NorthWindEntities>
  {
    public static void InitializeService(IDataServiceConfiguration config)
      {
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.UseVerboseErrors = true;
      }
    }

8 ) Open Web.config and replace your service model tag with (but change the DOMAIN!):

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
    <baseAddressPrefixFilters>
      <add prefix="http://YourHostedDomainName.com"/>
    </baseAddressPrefixFilters>
  </serviceHostingEnvironment>
</system.serviceModel>

9) Right click Web project folder -> Publish to DASP using FTP
– Use FTP address and FTP username (See DASP Control Panel->Account Management->Account Info)
– Ensure you use the right FTP address!

10) Start the IIS 7 Manager.
– Connect to IIS 7 on DASP
– In IIS click “Authentication”
– Disable anonymous.
11) Point to: http://YourHostedDomainName.com/NorthWindDataService.svc
– You should get an xml page.
– Query customers with by pointing to: http://YourHostedDomainName.com/NorthWindDataService.svc/Customers()

For continuing discussion on this article please see this forum thread.

Special thanks to guest blogger, Rob Leclerc, Ph.D.

 
iBlog by PageLines