Phase 1: Preparation
The compliance detection and installation solution is made up of a
VPModuleScanner.js detection script and a VPModule.msi file. You must create an
SMS package that contains both files. To help you create the SMS package and
program objects for this detection script and http module, this section
includes the contents of a Package Definition File (PDF).
The
following text should be copied and pasted in a Notepad file and saved with an
.SMS extension. For example, use
Aspnet.sms.
[PDF]
Version=2.0
[Package Definition]
Publisher=Microsoft
Name=ASP .NET Scan and Install Package
Version=1.0
Language=ALL
Programs=Scan,Install,UnInstall
[Scan]
Name=ASP .NET Scan
CommandLine=wscript //B vpmodulescanner.JS -o %TEMP%\aspnet.log
UserInputRequired=False
EstimatedRunTime=5
AdminRightsRequired=True
CanRunWhen=AnyUserStatus
SupportedClients=Win NT (I386)
Win NT (I386) MinVersion1=5.00.0000.0
Win NT (I386) MaxVersion1=5.00.9999.9999
Win NT (I386) MinVersion2=5.10.0000.0
Win NT (I386) MaxVersion2=5.10.9999.9999
Win NT (I386) MinVersion3=5.20.0000.0
Win NT (I386) MaxVersion3=5.20.9999.9999
[Install]
Name=ASP .NET Install
CommandLine=wscript //B vpmodulescanner.JS -o %TEMP%\aspnet.log -install
UserInputRequired=False
EstimatedRunTime=5
AdminRightsRequired=True
CanRunWhen=AnyUserStatus
SupportedClients=Win NT (I386)
Win NT (I386) MinVersion1=5.00.0000.0
Win NT (I386) MaxVersion1=5.00.9999.9999
Win NT (I386) MinVersion2=5.10.0000.0
Win NT (I386) MaxVersion2=5.10.9999.9999
Win NT (I386) MinVersion3=5.20.0000.0
Win NT (I386) MaxVersion3=5.20.9999.9999
[UnInstall]
Name=ASP .NET UnInstall
CommandLine=msiexec /q /x "VPModule.msi"
UserInputRequired=False
EstimatedRunTime=5
AdminRightsRequired=True
CanRunWhen=AnyUserStatus
SupportedClients=Win NT (I386)
Win NT (I386) MinVersion1=5.00.0000.0
Win NT (I386) MaxVersion1=5.00.9999.9999
Win NT (I386) MinVersion2=5.10.0000.0
Win NT (I386) MaxVersion2=5.10.9999.9999
Win NT (I386) MinVersion3=5.20.0000.0
Win NT (I386) MaxVersion3=5.20.9999.9999
To create the package and program objects, follow these steps:
- In the SMS Administrator Console, click
Packages.
- Right-click Packages, click
New, click Package from
Definition.
A Create Package from Definition
Wizard starts. Use this wizard to create the package and program
objects. You will be prompted to supply the package definition file that you
created earlier. You can also select the source files (VPModuleScanner.js and
VPModule.msi) to complete the package creation. - When you finish the steps in the wizard, a new Microsoft
ASP.NET Scan and Install Package is created.
Phase 2: Compliance scan
We recommend that you first assess how many systems the
VPModule.msi file applies to and what systems require the file.
To
execute the compliance scan, first use the ASP.NET Scan program to create an
advertisement. This program is located in the Microsoft ASP.NET Scan and
Install package.
Deploy this advertisement to a pilot group first,
before you execute a broader deployment.
After you execute the
compliance scan on a client system, you will receive one of the following
return codes:
0 | VPModule Installed |
20000 | VPModule required |
20001 | .NET Framework configuration file not
found |
20002 | .NET Framework version not supported by the
VPModule. (This return code should be returned only from systems with interim
builds of the .NET Framework.) |
20003 | VPModule requirement status could not be
confirmed |
Important Systems that require the VPModule.msi file will return exit code
20000. Exit code 20000 is a failure code. The standard software distribution
reports will put these systems into the failed category. Correct representation
of the compliance status is available through the sample reports.
Use
the sample reports that are located in the
ASP.NET Scan - Advertisement
Status category to monitor the progress of the detection script
deployment and execution.
Report generation is described later in this
article.
Phase 3: Module installation
As soon as the extent of non-compliant systems is known, SMS
administrators can deploy the VPModule.msi file.
Create an SMS
advertisement that is based on the ASP.NET Install program. This advertisement
will deploy an MSI package that installs the mitigation module. The MSI package
will be executed in an unattended manner, and a system restart should not be
required.
Important Systems that require the VPModule.msi file will return exit code
20000. Exit code 20000 is a failure code. The standard software distribution
reports will put these systems into the failed category. Correct representation
of the compliance status is available through the sample reports.
Use
the sample reports that are located in the
ASP.NET Scan - Advertisement
Status category to monitor the progress of the detection script
deployment and execution.
Uninstall option
The MSI package also includes an uninstall option. Target the
uninstall option only at systems that have the mitigation module installed.
To identify systems that have successfully installed mitigation
module, a collection should be based on a query that includes the following
condition:
select * from SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on
SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where
SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName = "Microsoft ASP.NET ValidatePath
Module"
Sample reports
A set of sample reports that supports compliance assessment is
included in this section. To implement the reports, copy and paste the
following text in Notepad, and then save the file with a .mof extension. For
example, use Aspnet.mof.
Note Make sure that the site code in the first line of the file is
amended to reflect the site code of the primary site where these reports will
be installed. For example, if you install these reports at SMS Primary Site
A01, the first line should be:
#pragma namespace("\\\\.\\root\\sms\\site_A01")
When the file has been generated, you must compile it. At the SMS
primary site server where the reports are to be installed and the SMS provider
is located, run the compilation at a command prompt by typing the following:
mofcomp.exe aspnet.mof
The following are sample reports:
#pragma namespace("\\\\.\\root\\sms\\site_PPP")
//////////////////////////////////////////////////////////////////////////////////////
// Please don't modify the following report. This report is already shipped with SMS
//////////////////////////////////////////////////////////////////////////////////////
instance of SMS_Report as $N108
{
Category = "Software Distribution - Advertisement Status";
Comment = "This report shows the status messages reported for a particular computer and advertisement.";
DrillThroughColumns = {5};
GraphXCol = 1;
GraphYCol = 2;
MachineDetail = FALSE;
MachineSource = FALSE;
Name = "Advertisement status messages for a particular client and advertisement";
NumPrompts = 2;
RefreshInterval = 0;
ReportParams = {
instance of SMS_ReportParameter
{
AllowEmpty = FALSE;
DefaultValue = "";
PromptText = "Advertisement ID";
SampleValueSQL = "begin\r\n if (@__filterwildcard = '')\r\n select AdvertisementID, AdvertisementName, Comment from v_Advertisement order by AdvertisementName\r\n else\r\n select AdvertisementID, AdvertisementName, Comment from v_Advertisement\r\n WHERE AdvertisementID like @__filterwildcard\r\n order by AdvertisementName\r\nend";
VariableName = "AdvertID";
},
instance of SMS_ReportParameter
{
AllowEmpty = FALSE;
DefaultValue = "";
PromptText = "Computer Name";
SampleValueSQL = "begin\r\n if (@__filterwildcard = '')\r\n SELECT DISTINCT SYS.Netbios_Name0 from v_R_System SYS WHERE SYS.Client0=1 ORDER By SYS.Netbios_Name0\r\n else\r\n SELECT DISTINCT SYS.Netbios_Name0 from v_R_System SYS WHERE SYS.Client0=1\r\n and SYS.Netbios_Name0 like @__filterwildcard\r\n ORDER By SYS.Netbios_Name0\r\nend";
VariableName = "Name";
}};
SQLQuery = "/* status message detail, params=machine name, AdvertisementID */\r\n\r\nselect DATEADD(ss,@__timezoneoffset,stat.Time) as Time, info.MessageStateName, info.MessageName, stat.MessageID, stat.RecordID\r\nfrom v_StatusMessage stat\r\njoin v_StatMsgAttributes att on stat.RecordID=att.RecordID and stat.Time=att.AttributeTime\r\nleft join v_AdvertisementStatusInformation info on stat.MessageID=info.MessageID\r\nwhere stat.Component in ('SMS System Offer Data Provider (ODP)', 'Available Programs Manager (APM)', 'Software Distribution','Device Client')\r\n and stat.MachineName=@Name and att.AttributeID=401\r\n and att.AttributeValue=@AdvertID\r\norder by stat.Time";
StatusMessageDetailSource = TRUE;
};
//////////////////////////////////////////////////////////////////////////////////////
// New report for ASP .NET scan Advertisement
//////////////////////////////////////////////////////////////////////////////////////
instance of SMS_Report as $N410
{
Category = "ASP .NET Scan - Advertisement Status";
Comment = "This report will show a list of all resources that are in a specific state for ASP .NET scan advertisement. For example, you can see which resources have successfully run ASP .NET scan program and whether they are compliant or not.\r\n(Client type: 0 = Legacy Client; 1 = Advanced Client)";
DrillThroughColumns = {9, 1};
DrillThroughReportPath = $N108;
GraphXCol = 1;
GraphYCol = 2;
MachineDetail = FALSE;
MachineSource = FALSE;
Name = "All system resources for ASP .NET scan advertisement in a specific state";
NumPrompts = 2;
RefreshInterval = 0;
ReportParams = {
instance of SMS_ReportParameter
{
AllowEmpty = FALSE;
DefaultValue = "";
PromptText = "Software Distribution Status";
SampleValueSQL = "begin\r\n if (@__filterwildcard = '')\r\n select distinct MessageStateName from v_AdvertisementStatusInformation where MessageState <= 13 order by MessageStateName\r\n else\r\n select distinct MessageStateName from v_AdvertisementStatusInformation where MessageState <= 13\r\n and MessageStateName like @__filterwildcard\r\n order by MessageStateName\r\nend";
VariableName = "StateName";
},
instance of SMS_ReportParameter
{
AllowEmpty = FALSE;
DefaultValue = "";
PromptText = "Advertisement ID";
SampleValueSQL = "begin\r\n if (@__filterwildcard = '')\r\n select AdvertisementID, AdvertisementName, Comment from v_Advertisement order by AdvertisementName\r\n else\r\n select AdvertisementID, AdvertisementName, Comment from v_Advertisement\r\n WHERE AdvertisementID like @__filterwildcard\r\n order by AdvertisementName\r\nend";
VariableName = "AdvertID";
}};
SQLQuery = "declare @State int\r\n\r\nselect @State=MessageState \r\nfrom v_AdvertisementStatusInformation\r\nwhere MessageStateName=@StateName and MessageState < 100\r\n\r\nif @State in (0,1,2,3) /* no status, accepted, rejected, expired */\r\n select sys.Netbios_Name0, sys.User_Domain0, sys.User_Name0, site.SMS_Installed_Sites0, Client_Type0, \r\n LastAcceptanceMessageID, LastAcceptanceMessageIDName, \r\n DATEADD(ss,@__timezoneoffset,LastAcceptanceStatusTime) as LastAcceptanceStatusTime,\r\n AdvertisementID\r\n from v_ClientAdvertisementStatus stat\r\n join v_R_System sys on stat.ResourceID=sys.ResourceID\r\n left join v_RA_System_SMSInstalledSites site on stat.ResourceID=site.ResourceID\r\n where stat.LastAcceptanceState=@State and stat.AdvertisementID=@AdvertID\r\nelse if @StateName = 'Vulnerable' /* Vulnerable */\r\nselect sys.Netbios_Name0, sys.User_Domain0, sys.User_Name0,site.SMS_Installed_Sites0, Client_Type0, \r\n LastStatusMessageID, LastStatusMessageIDName, \r\n DATEADD(ss,@__timezoneoffset,LastStatusTime) as LastStatusTime, \r\n AdvertisementID, LastExecutionResult, LastExecutionContext\r\n from v_ClientAdvertisementStatus stat\r\n join v_R_System sys on stat.ResourceID=sys.ResourceID\r\n left join v_RA_System_SMSInstalledSites site on stat.ResourceID=site.ResourceID\r\n where stat.LastState=11 and stat.AdvertisementID=@AdvertID\r\n and ISNULL(stat.LastExecutionResult, 0)='20000'\r\n else if @State = 11 /* failed */\r\n select sys.Netbios_Name0, sys.User_Domain0, sys.User_Name0,site.SMS_Installed_Sites0, Client_Type0, \r\n LastStatusMessageID, LastStatusMessageIDName, \r\n DATEADD(ss,@__timezoneoffset,LastStatusTime) as LastStatusTime, \r\n AdvertisementID, LastExecutionResult, LastExecutionContext\r\n from v_ClientAdvertisementStatus stat\r\n join v_R_System sys on stat.ResourceID=sys.ResourceID\r\n left join v_RA_System_SMSInstalledSites site on stat.ResourceID=site.ResourceID\r\n where stat.LastState=@State and stat.AdvertisementID=@AdvertID\r\nand ISNULL(stat.LastExecutionResult, 0)!='20000'\r\nelse if @State in (9,12,13) /* running, reboot pending, suceeded */\r\n select sys.Netbios_Name0, sys.User_Domain0, sys.User_Name0, site.SMS_Installed_Sites0, Client_Type0, \r\n LastStatusMessageID, LastStatusMessageIDName,\r\n DATEADD(ss,@__timezoneoffset,LastStatusTime) as LastStatusTime, \r\n AdvertisementID, LastExecutionContext\r\n from v_ClientAdvertisementStatus stat\r\n join v_R_System sys on stat.ResourceID=sys.ResourceID\r\n left join v_RA_System_SMSInstalledSites site on stat.ResourceID=site.ResourceID\r\n where stat.LastState=@State and stat.AdvertisementID=@AdvertID\r\nelse\r\n select sys.Netbios_Name0, sys.User_Domain0, sys.User_Name0, site.SMS_Installed_Sites0, Client_Type0, \r\n CASE LastStatusMessageID WHEN 65535 THEN 10002 ELSE LastStatusMessageID END as LastStatusMessageID, \r\n LastStatusMessageIDName,\r\n DATEADD(ss,@__timezoneoffset,LastStatusTime) as LastStatusTime, \r\n AdvertisementID\r\n from v_ClientAdvertisementStatus stat\r\n join v_R_System sys on stat.ResourceID=sys.ResourceID\r\n left join v_RA_System_SMSInstalledSites site on stat.ResourceID=site.ResourceID\r\n where stat.LastState=@State and stat.AdvertisementID=@AdvertID";
StatusMessageDetailSource = FALSE;
XColLabel = "";
YColLabel = "";
};
//////////////////////////////////////////////////////////////////////////////////////
// New report for ASP .NET scan Advertisement
//////////////////////////////////////////////////////////////////////////////////////
instance of SMS_Report as $N411
{
Category = "ASP .NET Scan - Advertisement Status";
Comment = "This report shows the status summary of all resources that have been targeted by an ASP .NET Scan advertisement. The summary is broken into two parts. Acceptance status will summarize how many resources have received, rejected, or not yet received the advertisement. Delivery status will summarize the resources that have run or attempted to run the scan program and are vulnerable.";
DrillThroughColumns = {1, 4};
DrillThroughReportPath = $N410;
GraphXCol = 1;
GraphYCol = 2;
MachineDetail = FALSE;
MachineSource = FALSE;
Name = "ASP .NET scan Status of a specific advertisement";
NumPrompts = 1;
RefreshInterval = 0;
ReportParams = {
instance of SMS_ReportParameter
{
AllowEmpty = FALSE;
DefaultValue = "";
PromptText = "Advertisement ID";
SampleValueSQL = "begin \n if (@__filterwildcard = '') \n select AdvertisementID, AdvertisementName, Comment from v_Advertisement order by AdvertisementName \n else \n select AdvertisementID, AdvertisementName, Comment from v_Advertisement \n WHERE AdvertisementID like @__filterwildcard \n order by AdvertisementName \nend";
VariableName = "AdvertID";
}};
SecurityKey = "";
SQLQuery = "declare @Total int \ndeclare @Accepted int \n \nselect @Total=count(*), @Accepted=sum(case LastState when 0 then 0 else 1 end) \nfrom v_ClientAdvertisementStatus \nwhere AdvertisementID=@AdvertID \n \nselect LastAcceptanceStateName as C013, count(*) as C015, \n ROUND(100.0*count(*)/@Total,1) as C016, \nAdvertisementID \nfrom v_ClientAdvertisementStatus \nwhere AdvertisementID=@AdvertID \ngroup by LastAcceptanceStateName, AdvertisementID \n \nselect LastStateName as C017, count(*) as C015, \n ROUND(100.0*count(*)/@Accepted,1) as C016, \nAdvertisementID \nfrom v_ClientAdvertisementStatus \nwhere AdvertisementID=@AdvertID and (LastState not in (0, 11) OR \n(LastState = 11 and ISNULL(LastExecutionResult, 0) != '20000')) \ngroup by LastStateName, AdvertisementID UNION \n select 'Vulnerable' as C017, count(*) as C015, \n ROUND(100.0*count(*)/@Accepted,1) as C016, AdvertisementID \nfrom v_ClientAdvertisementStatus \nwhere AdvertisementID=@AdvertID and \n(LastState = 11 and ISNULL(LastExecutionResult, 0) = '20000') \ngroup by AdvertisementID";
StatusMessageDetailSource = FALSE;
};