Apache–jMeter – Test Plan – ASP.Net – Forms Authentication–Troubleshooting

Background

In a previous post we spoke about the steps we undertook to design a test plan for authenticating users connecting to an ASP.Net web site.

In this post, we will shield light on the headwinds that batted us along the way.

 

Headwinds

Outline

  1. Workflow
  2. Thread Group
    • Thread Group Configuration
      • More threads than necessary
  3. HTML Page
    • Hidden fields
    • Entry fields
    • Action or Push button
  4. Component – Cookies Manager
  5. Component – View Results Tree
  6. Component – View Results Table
  7. Web Server
    • HTTP Logs
    • Failed Request Tracing

 

Workflow

This is a very crude drawing …

Workflow_20171026_0533PM

But, it hopefully shows workflow  ..

  1. First HTTP Request Default
  2. Second HTTP Request
    • Use Get Method to request session page
    • Returns to us the session date ( viewstate, eventValidation, viewStateGenerator )
  3. Parse returned Page
    • Using CSS /JQuery parse data and retrieve session data mentioned above
  4. Third HTTP Request
      • Use Post Method to submit user credentials
      • Make sure that session data we parsed earlier is packaged, as well

 

Thread Group

Thread Group Configuration

More threads than Necessary

Images
Thread Group – Configuration @ 7:11 PM

At 7:11 PM, we were hopeful and set up for fifty users, a ramp time of 10 seconds.

And, 2 repetitions.

ThreadGroup_20171024_0714PM

 

Thread Group – Configuration @ 1:03 AM

At 1 AM of the next day, we were humbled to 1 user and a single iteration.

ThreadGroup_20171025_1158AM

 

Explanation

Once we could not successfully authenticate and started adding ViewResultsTree and viewResultsInTable, we started seeing double and some of it was due to the fact that we had more workers than was necessary.

 

HTML Page

Hidden Fields

Images

Explanation

  1. Make a note of all hidden fields
  2. Determine how they are populated
    • Static versus Dynamic
    • Vetted against replay
  3. Encoded ( Yes or No )

 

Cookies Manager

For state management, you will need cookies, server and client side, so please save yourself the headache by enabling them.

Image

Image – Before

HTTPCookieManager_20171025_1152AM

Image – After

HTTPCookieManager_20171026_0459PM

Explanation

  1. Once things are good
    • Clear cookies each iteration
      • Please mark “Clear cookies each iteration” once you are comfortable with your design

 

View Results Tree

Get

View Results Tree – Request

Image

ViewResultsTree_Request_20171025_1204PM

 

Explanation

Take a good look at the Post data

  1. Post data
    • Do you have that the user field populate
    • What about the hidden fields
      • Are the hidden fields supplied by the system and are they varied as a counter measure against replay

 

View Results Tree – Response data

Image

ViewResultsTree_ResponseData_20171025_1204PM

 

Explanation

Our response data looks perfect.

Post

View Results Tree – Request

Image

ViewResultsTree_Request_20171025_0127PM

 

Explanation
  1. Get data
    • Because our request type is not a Get, but a Post, the Get data is left vacant
  2. Cookies Data
    • We are authenticated and we have our cookies

 

Web Server

Please check IIS Logs and enable Failed Request Tracing

  • HTTP Logs
  • Failed Request Tracing

Failed Request Tracing

IIS Failed Request Tracking module offers superlative debugging tooling.

Failed Request Tracing – 001

Failed Request Tracing – 001 – Image

 

Failed Request Tracing – 001 – Textual

Validation of viewstate MAC failed. 
If this application is hosted by a Web Farm or cluster, ensure that machineKey configuration specifies the same validationKey and validation algorithm. 
AutoGenerate cannot be used in a cluster.
See http://go.microsoft.com/fwlink/?LinkID=314055 for more information.

 

 

Failed Request Tracing – 002

Failed Request Tracing – 002 – Image

 

Failed Request Tracing – 002 – Textual

The state information is invalid for this page and might be corrupted.

 

Dedication

Dedicated to Michael Stover.

Main » jmeter-user » 2003-07 » RE: using the regular expression extractor to obtain a form value
Link

MichaelStoverWorkflow_20171026_0545PM


					

IIS Logs / Log Parser Studio – Aggregated Hits per Server

Background

Our monitoring team has developed and rolled out scripts for monitoring our web farm.

And, we are getting alerts through email.

Quite a lot of emails are coming across and wanted to see if they are coming from same host or a combination of hosts.

 

Emails

Looked at the emails and they happen to be coming from same host.

And, so will have to engage our Network team and see how the Load Balancer is configured.

Is there a prospect that more traffic is being directed at the failing node?

Network Load Balancer

As we prepared to go to the Network Load Balancer team took the opportunity to take gather and query the IIS Logs, as well.

 

TroubleShooting

Log Parser Studio

Query


SELECT 
            To_String(date, 'yyyy-MM-dd') as dated

          , sc-status as status

          , sum (
                    case s-ip
                        when '10.0.4.25' then 1
                        else 0
                   end
               ) as S1

          , sum (
                    case s-ip
                        when '10.0.4.26' then 1
                        else 0
                   end
               ) as S2


          , sum (
                    case s-ip
                        when '10.0.4.27' then 1
                        else 0
                   end
               ) as S3

         , sum (
                    case s-ip
                        when '10.0.4.28' then 1
                        else 0
                   end
               ) as S4

          , min(TO_TIMESTAMP(date, time)) as tsRecordedMin


          , max(TO_TIMESTAMP(date, time)) as tsRecordedMax


FROM '[LOGFILEPATH]' 


where   (


           (

             TO_TIMESTAMP(date, time) 
                     between timestamp('2017/08/02 10:30:00', 'yyyy/MM/dd hh:mm:ss')  
                          and timestamp('2017/08/02 17:20:00', 'yyyy/MM/dd hh:mm:ss')
           )

       )

/*

	and  c-ip not in ('10.0.4.141')
	
*/

group by
         date
       , sc-status


order by
           dated 
         , status



Output

Time Range – 1 ( August 2nd 10:30 AM – 5:20 PM )

Results

Explanation
  1. It is difficult to make case that traffic is exhaustively being waded into a specific host

Time Range – 2 ( August 8th 5:13 PM – 8:40 PM )

Results

Explanation
  1. In our second time slot, 4700 records bearing HTTP 200 is right around average

Summary

At this time it is likely that the sufferance we are seeing with this specific host is not due to outside pressure, but internal to the host itself.

 

Internet Information (IIS) / Log Parser – Queries – String Pattern Matching

Background

Looking for File I/O Exceptions in the Event Viewer.

 

Query

Sample

Sample 001

Code


SELECT TOP 100 
 
         TimeGenerated
       , ComputerName
       , EventCategoryName
       , EventTypeName
       , EventID
       , SourceName
       , Message as Mesg
       , Strings as Strings
       , EXTRACT_TOKEN(Strings,1,'|') AS AppName
       , EXTRACT_TOKEN(Strings,2,'|') AS AppVersion
       , EXTRACT_TOKEN(Strings,3,'|') AS S3
       , EXTRACT_TOKEN(Strings,4,'|') AS Module
       , INDEX_OF(Message, 'System.IO.IOException') as indexOf
       , case INDEX_OF(Message, 'System.IO.IOException') 
            when 0 then 'N'
            when NULL then 'N'
            else 'Y'
         end as IOE
       , CASE strcnt(Message, 'System.IO.IOException')
             when 0 then 'No'
             else 'Yes'   
         end as IOException
 
from  '[LOGFILEPATH]'
 
WHERE ( EventType = 1 OR EventType = 2 )

and    INDEX_OF(Message, 'System.IO.IOException') > 0

 
ORDER BY
         TimeGenerated DESC


Output

 

Explanation

  1. INDEX_OF
    • We use INDEX_OF to find the position of the sought string in the Message column
      • When the column contains System.IO.IOException the query returns the starting position of the found pattern
      • When not found, null is returned
  2. STRCNT
    • We invoke STRCNT to count number of matches
      • When String not found, 0 return
      • When matched, number of matches

 

References

  1. StackOverflow
    • Log Parser Case Statement
      Link

 

SQL Server – Reporting Services ( v2005 ) on Windows 2008 – Web Service Setting

Error

Reporting Services Configuration Manager – Configure Report Server – Web Services Identity – Red Exclamation Mark

WebServiceIdentity-Red (Cropped)

 

Reporting Services Configuration Manager – Configure Report Server – Web Services Identity – Set to new values

WebServiceIdentity-Setting-v2 ( Cropped )

Once Apply is clicked on…

ThereWasErrorSettingTheIdentity

 

Tell me more

Image

800708AC

Textual

 ReportServicesConfigUI.WMIProvider.WMIProviderException: An unknown error has occurred in the WMI Provider. Error Code 800708AC at ReportServicesConfigUI.WMIProvider.RSReportServerAdmin.SetWebServiceIdentity(String applicationPool) 

Remediation

Local Groups

Verified that the required local OS Groups are created and that Web Service Account has been added to the designated groups.

The OS Groups are

  1. SQLServer2005ReportingServicesWebServiceUser$<computer-name>$<instance-name>
  2. SQLServer2005ReportServerUser$<computer-name>$<instance-name>
  3. IIS_WPG

 

Group Intent Naming Convention Sample
 WebServiceUsers Members in the group have the required access to be assigned as the log on account for the associated instance of SQL Server Reporting Services in SQL Server 2005  SQLServer2005ReportingServicesWebServiceUser$<computer-name>$<instance-name>  SQLServer2005ReportingServicesWebServiceUser$HRDB$V2005MIRROR
 ReportServerUsers Members in the group have the required access and privileges to be assigned as the log on account for the associated instance of SQL Server Reporting Services in SQL Server 2005. SQLServer2005ReportServerUser$<computer-name>$V2005MIRROR  SQLServer2005ReportServerUser$HRDB$V2005MIRROR
 IIS_WPG  The IIS_WPG user is a the IIS Worker Process Group, and is needed in order for IIS to run / access applications within a folder.

The IIS_IUSRS is a the Internet Guest Account, this is used to allow anonymous access to the folder / files

 

 

WebServiceUsers

Original

WebServiceUsers-20160726-1055PM ( Original)

 

Revised

WebServiceUsers-20160726-1058PM ( Revised )

 

ReportServerUsers

ReportServerUsers-20160726-1053PM ( Original)

 

IIS_WPG

  1. Created a new group ( IIS_WPG)
  2. Added Web Service Account to group ( IIS_WPG)

IIS_WPG ( Created group & added Web Service)

Web Service Identity – Successfully Changed

WebServiceIdentity-SuccessfullyChanged ( Cropped)

 

Crediting

Crediting Dave Sells (MSFT ).

Answer provided

SQL Server > SQL Server Reporting Services, Power View
Set Web Service Identity to domain account
Here

…\Reporting Services\ReportServer\rsreportserver.config

WebServiceAccount is empty

Is WebServiceAccount Element is empty?

Here we have the WebServiceAccount Element marked as empty

WebServiceAccountIsEmpty

 

Please fill it with the account name, can be local account or domain name.

WebServiceAccountFilled

Causation

A mangled installation \ configuration can lead to the WebServiceAccount not being properly recorded in the rsreportserver.config.

 

Crediting

Crediting JoeUMN ( Profile ).

WebServiceAccountAsEmpty

Answer provided

SQL Server > SQL Server Reporting Services, Power View
Set Web Service Identity to domain account
Here

Virtual Directory Application Pool set incorrectly

There are two virtual directories ( Reports and ReportServer), either of them could be set incorrectly

To correct do the following:

  1. Launch Internet Information Services ( IIS ) Manager
    • Access the corresponding Web site and Virtual Directory ( by default “Default Web Site” \ “ReportServer” and “Default Web Site” \ “Reports” )
    • Right click on your selection
    • From the drop-down menu select “Manage Application” \ “Advanced Settings…”
    • The “Advanced Settings” window
      • In the “Application Pool” dropdown, review the Application Pool selected
        • In our case a former one was selected and so we changed to the new one

 

Access Website \ Virtual Directory – Application \ Manage Application \ Advanced Settings

LaunchApplicationAdvancedSettings

 

Website \ Virtual Directory – Application \ Manage Application \ Advanced Settings { Incorrect }

ApplicationAdvancedSettings-InCorrected

 

Website \ Virtual Directory – Application \ Manage Application \ Advanced Settings { Transitioning }

 

SelectApplicationPool

Website \ Virtual Directory – Application \ Manage Application \ Advanced Settings { Corrected }

ApplicationAdvancedSettings-Corrected

 

Crediting

Crediting JoeUMN ( Profile ).

ChangeApplicationPoolOnMsdn

Answer provided

SQL Server > SQL Server Reporting Services, Power View
Set Web Service Identity to domain account
Here

Summary

Our problem is that SQL Server v2005 targets MS Windows 2003, which has IIS_WPG.

MS Windows 2008 forsook IIS_WPG for IIS_IUSRS.

 

Transact SQL – Securing Personally Identifiable Information ( PII) Data at the Database Column Level

Background

We are letting more and more people directly query our database.

But, as we have some Personal Identifier Information ( PII) columns we have to be a bit careful.

Those columns are encrypted, but unfortunately we are using the same symmetric keys and those users need access to some of the encrypted columns, but are to be denied access to others.

 

Denying access to some columns

Granting and Revoking Object & Column permissions

Tasks

  1. Grant view definition on symmetric key
  2. Grant control on certificate
  3. Grant select on specific tables
  4. Revoke select on specific columns ( the targeted table list is a subset of tables listed earlier )

Code


/* 
	Encryption Objects
*/
grant View Definition on  SYMMETRIC KEY::[symkeyPII] to [roleUser]
go

grant control on certificate::[certPII] to [roleUser]
go

grant execute on dbo.Salt  to [roleUser]
go

/* 
	Tables
*/
grant select on [dbo].[employee] to [roleUser]
go

grant select on [dbo].[salary] to [roleUser]
go


/* 
	Table -  Columns
*/
revoke select on 
		 OBJECT::[dbo].[employee]
			(
				  [last4ssn]
				, [drvlicense]
			)
		 from [roleUser]
GO  

go

 

 

Review Granted & Denied Permission Sets

Here is a Stored Procedure that lists granted and denied permissions.

Code



use master
go

if object_id('dbo.sp_ListObjectLevelPermissions') is null
begin

	exec('create procedure dbo.sp_ListObjectLevelPermissions as select 1/0 ')

end
go

alter procedure dbo.sp_ListObjectLevelPermissions
(
	@username sysname
)
as

begin

	/*
		Get Object Level Permissions
	*/
	SELECT
			  [UserName]
			= USER_NAME(dppriper.grantee_principal_id)
 
		, [principalType]
			= dppri.type_desc
 
		, [classDesc]
			= dppriper.class_desc
 
		, objectName
			=
			case dppriper.class_desc    
				when 'DATABASE' then db_Name(dppriper.major_id) 
				when 'OBJECT_OR_COLUMN'
					   then Object_Schema_Name(dppriper.major_id) 
									  + '.'
									  + object_Name(dppriper.major_id) 
				when 'SCHEMA' then schema_Name(dppriper.major_id) 
				when 'SYMMETRIC_KEYS' then
				   ( 
						select [name] 
						from sys.symmetric_keys 
						where dppriper.major_id
							   = symmetric_key_id
					)
					when 'CERTIFICATE' then
					(
						select [name] 
						from sys.certificates 
						where dppriper.major_id = certificate_id
					)
			end


		, columnName
			=
			case dppriper.class_desc    
				when 'OBJECT_OR_COLUMN'
					   then tblSC.name
				else NULL
			end
 
		, [permissionName]
			= dppriper.permission_name
 
		, [permissionState]
			= dppriper.state_desc

		, [grantStatement]
			=
			case dppriper.class_desc    

				when 'DATABASE' 
					then
							  dppriper.state_desc + ' '
							+ dppriper.permission_name
							+ case 

								when dppriper.[state] in ('G', 'W')
									 then ' to '

								when dppriper.[state] in ('D', 'R')
										 then ' from '

							  end
							+ quotename(USER_NAME(dppriper.grantee_principal_id))
							+ ';'
								collate database_default


				when 'OBJECT_OR_COLUMN'
					   then dppriper.state_desc + ' '
								+ dppriper.permission_name
								+ ' on '
								+ quotename(Object_Schema_Name(dppriper.major_id)) 
								+ '.'
								+ quotename(object_Name(dppriper.major_id) )
								+ ' '
								+
									case
										when ( dppriper.minor_id is null ) then ''
										when ( dppriper.minor_id = 0 ) then ''
										else '('
												+ 
													case dppriper.class_desc    
															when 'OBJECT_OR_COLUMN'
																then quotename(tblSC.name)
														 else ''
													end
											 + ')'
									end

								+ case 

									when dppriper.[state] in ('G', 'W')
										 then ' to '

									when dppriper.[state] in ('D', 'R')
											 then ' from '

									else 'N/A'

								  end

								+ quotename(USER_NAME(dppriper.grantee_principal_id))
								+ ';'
								 collate database_default

				when 'SCHEMA' 
						then
								  dppriper.state_desc + ' '
								+ dppriper.permission_name
								+ ' on '
								+ ' SCHEMA :: '
								+ quotename(Schema_Name(dppriper.major_id)) 
								+ ' to '
								+ quotename(USER_NAME(dppriper.grantee_principal_id))
								+ ';'
								 collate database_default

				when 'SYMMETRIC_KEYS' 
					   then dppriper.state_desc + ' '
								+ dppriper.permission_name
								+ ' on '
								+ ' symmetric key::'
								+
								   ( 
										select quotename( [name] )
										from sys.symmetric_keys 
										where dppriper.major_id
											   = symmetric_key_id
									)
								+ ' to '
								+ quotename(USER_NAME(dppriper.grantee_principal_id))
								+ ';'
								 collate database_default

				when 'CERTIFICATE' 
					   then dppriper.state_desc + ' '
								+ dppriper.permission_name
								+ ' on '
								+ ' certificate::'
								+
								   ( 
										select quotename( [name] )
										from sys.[certificates] tblSC
										where dppriper.major_id
											   = certificate_id
									)
								+ ' to '
								+ quotename(USER_NAME(dppriper.grantee_principal_id))
								+ ';'
								 collate database_default



			end

			--, dppriper.major_id			
 
	FROM    sys.database_permissions dppriper
 
	INNER JOIN sys.database_principals dppri
 
		   ON dppriper.grantee_principal_id = dppri.principal_id

	LEFT OUTER JOIN sys.columns tblSC
 
		    ON dppriper.major_id = tblSC.object_id
		   AND dppriper.minor_id = tblSC.column_id

 
	where dppriper.grantee_principal_id 
		= case
				 when @username is null then dppriper.grantee_principal_id
			 
				 else user_id(@username)
 
			  end

	UNION ALL

	/*
		Get Role Permissions
	*/
	SELECT
			  [UserName]
			= USER_NAME(dppriper.member_principal_id)
 
		, [principalType]
			--= dppri.type_desc
 			= 'Database Role'

		, [classDesc]
			--= dppriper.class_desc
			= 'Database Role'
 
		, objectName
			= 'Database' collate database_default

		, columnName
			= null

		, [permissionName]
			= cast(dppriR.name as sysname) collate database_default

			 
		, [permissionState]
			= 'Grant' collate database_default

		, [grantStatement]
			= 'exec sp_addrolemember '
					+ '  @rolename = '
					+ quotename(dppriR.name)
					+ ' '
					+ ' ,'
					+ '  @membername = '
					+ quotename(USER_NAME(dppriper.member_principal_id))
					+ ' '
					+ ';'
				 collate database_default

 
    FROM	sys.database_role_members dppriper
 
	INNER JOIN sys.database_principals dppriM
 
		   ON dppriper.member_principal_id = dppriM.principal_id

	INNER JOIN sys.database_principals dppriR
 
		   ON dppriper.role_principal_id = dppriR.principal_id

	where dppriper.member_principal_id 
		= case
				 when @username is null then dppriper.member_principal_id
			 
				 else user_id(@username)
 
		  end


	order by
		  USERNAME
		, [principalType]
		, objectName
		, permissionName


end

go

grant execute on [dbo].[sp_ListObjectLevelPermissions] to [public]
go

EXEC sys.sp_MS_marksystemobject 'dbo.sp_ListObjectLevelPermissions'
go



Review Permissions

Code


use [HRDB]
go

declare @username sysname

set @username = 'roleUser'

exec dbo.sp_ListObjectLevelPermissions
 @username = @username

Output

permissionSet

Source Control

GitHub

Link

Input Error: Can not find script file “c:\inetpub\adminscripts\adsutil.vbs”

Background

Trying to inspect an IIS Configuration setting on a MS Windows 2008 box and ran into an error as the MS Script that drives the whole thing is missing

Lab

Code


set "_baseScriptFolder=c:\inetpub\adminscripts"

set "_identifier=1"

cscript c:\inetpub\adminscripts\adsutil.vbs get w3svc/1/root/reports/NTAuthenticationProviders

Output


Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.

Input Error: Can not find script file "c:\inetpub\adminscripts\adsutil.vbs".

 

Diagnostic

MS Windows 2008 ships with IIS v7.  The Admin Scripts were discontinued post IIS v6.

To gain access to c:\inetpub\adminscripts\adsutil.vbs, one has to augment IIS with “IIS 6 Scripting Tools“.

Remediation

GUI

Steps

  1. Open Server Manager
  2. Click on Web Server (IIS)
  3. Scroll to Role Services and click “Add Role Services”
  4. You will need to install
    • IIS 6 Management Compatibility
      • IIS 6 Metabase Compatibility
      • IIS 6 WMI Compatibility
      • IIS 6 Scripting Tools

 

AddRoleServices-Menu

Walkthrough

SelectRoleServices

Revised

SelectRoleServices - After

Script


start /w pkgmgr /iu:IIS-Metabase;IIS-WMICompatibility;IIS-LegacyScripts

References

AdminScripts folder is missing in IIS 7

  1. AdminScripts folder is missing in inetpub in IIS 7 RS
    Link
  2. Missing IIS admin scripts – Can not find script file
    Link

 

IIS Management

  1. Saad Ladki
    Home > Learn > Install > Chapter 1. Installing IIS 7 > Install Typical IIS Workloads
    Link
  2. IIS Team – You do not have permission to view this directory or page using the credentials that you supplied.
    Link