Archive for June, 2009

Common Remediation Owner Enumeration (My Faux Standard In Development)

So we’ve run into a small snag with our automation: Automatically assigning remediation owners. It’s easy for our UNIX pilot. The same group fixes all the OS vulnerabilities. When we start adding Windows into the mix, it gets a little harder.

When a vulnerability is discovered for, let’s say Adobe Reader, we have different assignment teams that remediate it depending on the device. We have a separate group of engineers for Windows Servers, Windows Workstations, and for our Citrix remote access applications. (Luckily, we’re not running Adobe Reader on our UNIX platforms)

Tomorrow, I will start working on the logic to automatically determine remediation ownership and assign it correctly. It will be a complicated process mapping Application Owners to Applications, and Applications to Platforms to Devices. There will be multiple application owners per application CPE (Common Platform Enumeration), but one application owner per Application CPE per Device CPE.

Do any of you already have a solution for this?

Getting the data from the DB into the PHP Classes

This is just an example. I have no idea how you store your data. This is the method that works for my database framework. You can see where it queries the DB and then calls the classes I posted earler. This code loops through all the vulnerability scan records in the database for the current day. You would need to print the arrays somewhere to make it useful.

//I keep all my DB Login details in a separate file
include_once 'includes/db.php';
 
$myCvss = new cvss_details();
 
//Get Info From DB:
$result = mysql_query("SELECT vulns.server, vulns.cve_number, assets.business_risk, assets.data_risk, assets.location_risk, nvd_cve.cvss_score, nvd_cve.cvss_access_vector, nvd_cve.cvss_access_complexity, nvd_cve.cvss_authentication, nvd_cve.cvss_confidentiality_impact, nvd_cve.cvss_integrity_impact, nvd_cve.cvss_availability_impact FROM `vulns` LEFT JOIN (assets,nvd_cve) ON (assets.server=vulns.server AND nvd_cve.cve=vulns.cve_number) WHERE vulns.report_date = CURDATE()");
 
while ($row = mysql_fetch_array($result))
{
	$myCvss = new cvss_details();
 
	//debug defines
	$myCvss->set_cve_number($row['cve_number']);
	$myCvss->set_nist_cvss($row['cvss_score']);
	$myCvss->set_server($row['server']);
 
	//Define Base Score Details
	//Exploitability Metrics
	$myCvss->set_access_vector($row['cvss_access_vector']);
	$myCvss->set_access_complexity($row['cvss_access_complexity']);
	$myCvss->set_authentication($row['cvss_authentication']);
	//Impact Metrics
	$myCvss->set_conf_impact($row['cvss_confidentiality_impact']);
	$myCvss->set_integ_impact($row['cvss_integrity_impact']);
	$myCvss->set_avail_impact($row['cvss_availability_impact']);
 
	//Environmental Score Metrics
	//General Modifiers
	$myCvss->set_collateral_damage_potential("");
	$myCvss->set_target_distribution("");
	//Impact Subscore Modifiers
	$myCvss->set_conf_req($row['data_risk']);
	$myCvss->set_integ_req($row['location_risk']);
	$myCvss->set_avail_req($row['business_risk']);
 
	//Temporal Score Metrics
	$myCvss->set_exploitability("");
	$myCvss->set_remediation_level("");
	$myCvss->set_report_confidence("");
 
	$server_name[] = $row['server'];
	$cve_number[] = $row['cve_number'];
	$cvss_base_score[] = $row['cvss_score'];
 
	$calc = new calculate_cvss();
	$cvss_overall_score[] = round($calc->calculate($myCvss),1);	
}

PHP Class for Calculating SCAP CVSS V2 Device Specific Score

Did I mention that I wasn’t a programmer? If you can make improvements to this code, I’d love to hear from you. This is my hackjob of code for doing what I need to do. Anyway, here’s my calculator. The DB call code will be in another post.

class calculate_cvss {
	function calculate($cvssDetail)
	{
		$adjustedImpact = $this->adjusted_impact($cvssDetail->conf_impact,$cvssDetail->conf_req,$cvssDetail->integ_impact,$cvssDetail->integ_req,$cvssDetail->avail_impact,$cvssDetail->avail_req);
		$adjustedImpactFunction = $this->adjusted_impact_function($adjustedImpact);
		$exploitabilitySubScore = $this->exploitability_subscore($cvssDetail->access_complexity,$cvssDetail->authentication,$cvssDetail->access_vector);
		$adjustedBaseScore = $this->adjusted_base_score($adjustedImpact,$exploitabilitySubScore,$adjustedImpactFunction);
		$adjustedTemporalScore = $this->adjusted_temporal_score($adjustedBaseScore,$cvssDetail->exploitability,$cvssDetail->remediation_level,$cvssDetail->report_confidence);
		$adjustedTemporalScore = round($adjustedTemporalScore,1);
		$environmentalScore = $this->environmental_score($adjustedTemporalScore,$cvssDetail->collateral_damage_potential,$cvssDetail->target_distribution);
		$impact = $this->impact($cvssDetail->conf_impact,$cvssDetail->integ_impact,$cvssDetail->avail_impact);
		$impact = round($impact,1);
		$impactFunction = $this->impact_function($impact);
		$baseScore = $this->base_score($impact,$exploitabilitySubScore,$impactFunction);
		$baseScore = round($baseScore,1);
		$temporalScore = $this->temporal_score($baseScore,$cvssDetail->exploitability,$cvssDetail->remediation_level,$cvssDetail->report_confidence);
		$overallScore = $this->overall_score($environmentalScore,$temporalScore,$baseScore);
 
		//Debug Printing
		print "CVE Number: $cvssDetail->cve_number<br />";
		print "Server:	$cvssDetail->server<br />";
		print "Impact SubScore: $impact<br />";
		print "Exploitability SubScore: $exploitabilitySubScore<br />";
		print "CVSS Temporal Score: $temporalScore<br />";
		print "CVSS Environmental Score: $environmentalScore<br />";
		print "--Adjusted Temporal Score: $adjustedTemporalScore<br />";
		print "--Collateral Damage Potential: $cvssDetail->collateral_damage_potential<br />";
		print "--Target Distribution: $cvssDetail->target_distribution<br />";
		print "NIST CVSS Score: $cvssDetail->nist_cvss<br />";
		print "CVSS Base Score: $baseScore<br />";
		print "Overall CVSS Score: $overallScore<br />";
 
		return "$overallScore";				
	}
	function adjusted_impact($confImpact,$confReq,$integImpact,$integReq,$availImpact,$availReq)
	{
		$adjustedImpact = min(10,10.41*(1-(1-$confImpact*$confReq)*(1-$integImpact*$integReq)*(1-$availImpact*$availReq)));
		return $adjustedImpact;
	}
	function adjusted_impact_function($adjustedImpact)
	{
		if ($adjustedImpact = 0)
		{
			$adjustedImpactFunction = 0;
		}
		else
		{
			$adjustedImpactFunction = 1.176;
		}
		return $adjustedImpactFunction;
	}
	function exploitability_subscore($accessComplexity,$authentication,$accessVector)
	{
		$exploitabilitySubScore = 20*$accessComplexity*$authentication*$accessVector;
		return $exploitabilitySubScore;
	}
	function adjusted_base_score($adjustedImpact,$exploitabilitySubScore,$adjustedImpactFunction)
	{
		$adjustedBaseScore = (0.6*$adjustedImpact+0.4*$exploitabilitySubScore-1.5)*$adjustedImpactFunction;
		return $adjustedBaseScore;
	}
	function adjusted_temporal_score($adjustedBaseScore,$exploitability,$remediationLevel,$reportConfidence)
	{
		$adjustedTemporalScore = $adjustedBaseScore*$exploitability*$remediationLevel*$reportConfidence;
		return $adjustedTemporalScore;
	}
	function environmental_score($adjustedTemporalScore,$collateralDamagePotential,$targetDistribution)
	{
		$environmentalScore = ($adjustedTemporalScore+(10-$adjustedTemporalScore)*$collateralDamagePotential)*$targetDistribution;
		return $environmentalScore;
	}
	function overall_score($environmentalScore,$temporalScore,$baseScore)
	{
		if(!defined($environmentalScore))
		{
			if(!defined($temporalScore))
			{
				$overallScore = $baseScore;	
			}
			else
			{
				$overallScore = $temporalScore;
			}
		}
		else
		{
			$overallScore = $environmentalScore;
		}
		return $overallScore;
	}
	function impact($confImpact,$integImpact,$availImpact)
	{
		$impact = 10.41*(1-(1-$confImpact)*(1-$integImpact)*(1-$availImpact));
		return $impact;
	}
	function impact_function($impact)
	{
		if ($impact = 0)
		{
			$impactFunction = 0;
		}
		else
		{
			$impactFunction = 1.176;
		}
		return $impactFunction;
	}
	function base_score($impact,$exploitabilitySubScore,$impactFunction)
	{
		$baseScore = (.6*$impact+.4*$exploitabilitySubScore-1.5)*$impactFunction;
		return $baseScore;
	}
	function temporal_score($baseScore,$exploitability,$remediationLevel,$reportConfidence)
	{
		$temporalScore = $baseScore*$exploitability*$remediationLevel*$reportConfidence;
		return $temporalScore;
	}
}

PHP Class for Getting all the SCAP Details

Here is a PHP class I wrote for storing the SCAP details. The next post will be the class I wrote to calculate the Device Specific CVSS Score. I will also post the DB queries I use to get the data from my database into this PHP class.

class cvss_details {
	function set_nist_cvss($cvss)
	{
		//This is the calculated CVSS Base Score, provided by NIST.
		//For Comparison Debugging
		$this->nist_cvss = $cvss;
	}
	function set_cve_number($cve)
	{
		$this->cve_number = $cve;
	}
	function set_server($server)
	{
		$this->server = $server;
	}
	function set_collateral_damage_potential($cdp)
	{
		switch ($cdp)
		{
			case "NONE":
				$this->collateral_damage_potential = 0;
				break;
			case "LOW":
				$this->collateral_damage_potential = 0.1;
				break;
			case "LOW-MEDIUM":
				$this->collateral_damage_potential = 0.3;
				break;
			case "MEDIUM-HIGH":
				$this->collateral_damage_potential = 0.4;
				break;
			case "HIGH":
				$this->collateral_damage_potential = 0.5;
				break;
			default:
				$this->collateral_damage_potential = 0;
		}
	}
	function set_target_distribution($targetDistribution)
	{
		switch ($targetDistribution)
		{
			case "NONE":
				$this->target_distribution = 0;
				break;
			case "LOW":
				$this->target_distribution = 0.25;
				break;
			case "MEDIUM":
				$this->target_distribution = 0.75;
				break;
			case "HIGH":
				$this->target_distribution = 1;
				break;
			default:
				$this->target_distribution = 1;
		}
	}
	function set_conf_req($conf_req)
	{
		switch ($conf_req)
		{
			case 1:
				$this->conf_req = 1.51;
				break;
			case 2:
				$this->conf_req = 1;
				break;
			case 3:
				$this->conf_req = 0.5;
				break;
			default:
				$this->conf_req = 1;
		}
	}
	function set_integ_req($integ_req)
	{
		switch ($integ_req)
		{
			case 1:
				$this->integ_req = 1.51;
				break;
			case 2:
				$this->integ_req = 1;
				break;
			case 3:
				$this->integ_req = 0.5;
				break;
			default:
				$this->integ_req = 1;
		}
	}
	function set_avail_req($avail_req)
	{
		switch ($avail_req)
		{
			case 1:
				$this->avail_req = 1.51;
				break;
			case 2:
				$this->avail_req = 1;
				break;
			case 3:
				$this->avail_req = 0.5;
				break;
			default:
				$this->avail_req = 1;
		}
	}
	function set_access_complexity($accessComplexity)
	{
		switch ($accessComplexity)
		{
			case "HIGH":
				$this->access_complexity = 0.35;
				break;
			case "MEDIUM":
				$this->access_complexity = 0.61;
				break;
			case "LOW":
				$this->access_complexity = 0.71;
				break;
		}
	}
	function set_authentication($authentication)
	{
		switch ($authentication)
		{
			case "NONE":
				$this->authentication = 0.704;
				break;
			case "SINGLE_INSTANCE":
				$this->authentication = 0.56;
				break;
			case "MULTIPLE_INSTANCES":
				$this->authentication = 0.45;
				break;
		}
	}
	function set_access_vector($accessVector)
	{
		switch ($accessVector)
		{
			case "LOCAL":
				$this->access_vector = 0.395;
				break;
			case "ADJACENT_NETWORK":
				$this->access_vector = 0.646;
				break;
			case "NETWORK":
				$this->access_vector = 1;
				break;
		}
	}
	function set_conf_impact($confImpact)
	{
		switch ($confImpact)
		{
			case "NONE":
				$this->conf_impact = 0;
				break;
			case "PARTIAL":
				$this->conf_impact = 0.275;
				break;
			case "COMPLETE":
				$this->conf_impact = 0.660;
				break;
		}
	}
	function set_integ_impact($integImpact)
	{
		switch ($integImpact)
		{
			case "NONE":
				$this->integ_impact = 0;
				break;
			case "PARTIAL":
				$this->integ_impact = 0.275;
				break;
			case "COMPLETE":
				$this->integ_impact = 0.660;
				break;
		}
	}
	function set_avail_impact($availImpact)
	{
		switch ($availImpact)
		{
			case "NONE":
				$this->avail_impact = 0;
				break;
			case "PARTIAL":
				$this->avail_impact = 0.275;
				break;
			case "COMPLETE":
				$this->avail_impact = 0.660;
				break;
		}
	}
	function set_exploitability($exploitability)
	{
		switch ($exploitability)
		{
			case "UNPROVEN":
				$this->exploitability = 0.85;
				break;
			case "PROOF_OF_CONCEPT":
				$this->exploitability = 0.90;
				break;
			case "FUNCTIONAL":
				$this->exploitability = 0.95;
				break;
			case "HIGH":
				$this->exploitability = 1;
				break;
			default:
				$this->exploitability = 1;
		}
	}
	function set_remediation_level($remediationLevel)
	{
		switch ($remediationLevel)
		{
			case "OFFICIAL_FIX":
				$this->remediation_level = 0.87;
				break;
			case "TEMPORARY_FIX":
				$this->remediation_level = 0.90;
				break;
			case "WORKAROUND":
				$this->remediation_level = 0.95;
				break;
			case "UNAVAILABLE":
				$this->remediation_level = 1;
				break;
			default:
				$this->remediation_level = 1;
		}
	}
	function set_report_confidence($reportConfidence)
	{
		switch($reportConfidence)
		{
			case "UNCONFIRMED":
				$this->report_confidence = 0.90;
				break;
			case "UNCORROBORATED":
				$this->report_confidence = 0.95;
				break;
			case "CONFIRMED":
				$this->report_confidence = 1;
				break;
			default:
				$this->report_confidence = 1;
		}
	}
}

How I store my Data

I’ll be doing several posts tonight. First, I will explain how the data is stored in the database. For our vulnerability information, we use the XML feed from NIST. One of my team members wrote a parser for it that puts it into a database:

mysql> describe nvd_cve;
+-----------------------------+-------------+------+-----+---------+-------+
| Field                       | Type        | Null | Key | Default | Extra |
+-----------------------------+-------------+------+-----+---------+-------+
| cve                         | varchar(15) | NO   | PRI | NULL    |       |
| cvss_score                  | float       | YES  |     | NULL    |       |
| cvss_access_vector          | varchar(25) | YES  |     | NULL    |       |
| cvss_access_complexity      | varchar(15) | YES  |     | NULL    |       |
| cvss_authentication         | varchar(25) | YES  |     | NULL    |       |
| cvss_confidentiality_impact | varchar(15) | YES  |     | NULL    |       |
| cvss_integrity_impact       | varchar(15) | YES  |     | NULL    |       |
| cvss_availability_impact    | varchar(15) | YES  |     | NULL    |       |
| cvss_source                 | text        | YES  |     | NULL    |       |
| cvss_generated_on_datetime  | tinytext    | YES  |     | NULL    |       |
| cve_summary                 | text        | YES  |     | NULL    |       |
| cve_published               | tinytext    | YES  |     | NULL    |       |
| cve_last_modified           | tinytext    | YES  |     | NULL    |       |
| cpe                         | mediumtext  | YES  |     | NULL    |       |
+-----------------------------+-------------+------+-----+---------+-------+

All the information in the above table is from the NVD XML file at NIST. We are still in the process of working out a better way to use CPE, but that’s another blog post.

Next, our SCAP scanner checks every system every night, and writes the results to the database. It creates an entry for every vulnerability every night, and provides a “color”: Either Red if it’s vulnerable, or Green if it’s remediated.

mysql> describe vulns;
+--------------------+-------------+------+-----+---------+----------------+
| Field              | Type        | Null | Key | Default | Extra          |
+--------------------+-------------+------+-----+---------+----------------+
| id                 | int(11)     | NO   | PRI | NULL    | auto_increment |
| server             | varchar(40) | YES  |     | NULL    |                |
| color              | varchar(7)  | YES  |     | NULL    |                |
| report_date        | date        | YES  | MUL | NULL    |                |
| cve_number         | varchar(17) | YES  | MUL | NULL    |                |
| cve_date           | date        | YES  |     | NULL    |                |
| cve_description    | text        | YES  |     | NULL    |                |
| cve_remediation    | text        | YES  |     | NULL    |                |
| CVSS_Environmental | double      | YES  |     | NULL    |                |
+--------------------+-------------+------+-----+---------+----------------+

You’ll notice the CVSS_Environmental field in the table above. This is where the calculated Device-Specific CVSS Score is put. It uses information from the nvd_cve table, as well as the assets table.

And finally, we have a table for our assets. This is populated from our asset management system that our infrastructure group maintains.

mysql> describe assets;
+---------------+--------------+------+-----+---------+-------+
| Field         | Type         | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| server        | varchar(40)  | NO   | PRI |         |       |
| risk          | int(1)       | YES  |     | NULL    |       |
| environment   | tinytext     | YES  |     | NULL    |       |
| network       | tinytext     | YES  |     | NULL    |       |
| owner         | tinytext     | YES  |     | NULL    |       |
| os            | varchar(100) | YES  |     | NULL    |       |
| status        | varchar(25)  | YES  |     | NULL    |       |
| business_risk | int(1)       | YES  |     | NULL    |       |
| data_risk     | int(1)       | YES  |     | NULL    |       |
| location_risk | int(1)       | YES  |     | NULL    |       |
+---------------+--------------+------+-----+---------+-------+

The business_risk, data_risk, and location_risk fields I have talked about in a previous post. They are an integer from 1 to 3 and map to Availability Requirement, Confidentiality Requirement, and Integrity Requirement, respectively.

My next post will contain the PHP code I wrote to calculate the Device-Specific CVSS Score. The “CVSS_Environmental” field in the vulns table is calculated using a perl script one of my team members wrote. We aren’t actively using the PHP code in production, but I maintain it incase I need to do some quick reporting or charting.

CVSS Code Coming, SCAP Pilot Updates

I’ve finished my PHP code that calculates the device-specific CVSS V2 scores based on risk information provided by our server administrators. I’ve been presenting my charts daily for the past 2 weeks. Right now, there is about 400 UNIX systems in our pilot. I am getting better reception than I hoped for. With an additive CVSS V2 score of about 34,000, I figured people would freak out. Instead, they aren’t focusing on the number, but rather the downward trend the line chart has from day to day. When the SA’s patch a server overnight, the results are immediately shown and their positive progress is immediately seen by management. Instant gratification is great when you can make a group look good.

The buy-off from our infrastructure team is getting pretty easy. They see the value in real-time reporting of vulnerability status. Previously, we would get a 3rd party vulnerability assessment every several months or so. It was hard for them to have artifacts to present that showed their progress. Now we do it for them.

We will soon add some Windows systems to the pilot and test the waters with that side of the SA house.

And for the code, I’m not sure whether I should post it here in the blog, or as separate files. I’ll think about it tomorrow.