package feed import ( "encoding/json" "fmt" ) const ( None = iota // no priv req/user interaction Low // low complexity/priv req Medium // medium complexity/priv req High // high complexity/priv req Complete // complete integrity impact Partial // partial integrity impact Critical // critical severity CvssVersion31 // CVSS version 3.1 CvssVersion20 // CVSS version 2.0 Single // Single authentication ) // TODO: parse cpe // CVSS integrity/availability impact level type ImpactLevel int // Unmarshal CVSS integrity/availability impact level from JSON. func (me *ImpactLevel) UnmarshalJSON(b []byte) error { // decode string, check for error var s string if err := json.Unmarshal(b, &s); err != nil { return err } // check value switch s { case "NONE": *me = None case "LOW": *me = Low case "PARTIAL": *me = Partial case "HIGH": *me = High case "COMPLETE": *me = Complete default: // return error return fmt.Errorf("unknown impact level: %s", s) } // return success return nil } // CVSS score type Score float32 // Unmarshal CVSS score from JSON. func (me *Score) UnmarshalJSON(b []byte) error { // decode float, check for error var v float32 if err := json.Unmarshal(b, &v); err != nil { return err } // check score if v < 0.0 || v > 10.0 { return fmt.Errorf("score out of bounds: %f", v) } // save result, return success *me = Score(v) return nil } // CVSS severity type Severity int // Unmarshal CVSS severity from JSON. func (me *Severity) UnmarshalJSON(b []byte) error { // decode string, check for error var s string if err := json.Unmarshal(b, &s); err != nil { return err } // check value switch s { case "LOW": *me = Low case "MEDIUM": *me = Medium case "HIGH": *me = High case "CRITICAL": *me = Critical default: // return error return fmt.Errorf("unknown severity: %s", s) } // return success return nil } type V2AccessVector byte const ( V2AVAdjacentNetwork V2AccessVector = iota V2AVLocal V2AVNetwork ) // Unmarshal CVSS V2 access vector from JSON. func (me *V2AccessVector) UnmarshalJSON(b []byte) error { // decode string, check for error var s string if err := json.Unmarshal(b, &s); err != nil { return err } // check value switch s { case "ADJACENT_NETWORK": *me = V2AVAdjacentNetwork case "LOCAL": *me = V2AVLocal case "NETWORK": *me = V2AVNetwork default: // return error return fmt.Errorf("unknown CVSS v2 access vector: %s", s) } // return success return nil } // CVSS V2 attack complexity type AccessComplexity int // Unmarshal CVSS V2 access complexity from JSON. func (me *AccessComplexity) UnmarshalJSON(b []byte) error { // decode string, check for error var s string if err := json.Unmarshal(b, &s); err != nil { return err } // check value switch s { case "LOW": *me = Low case "MEDIUM": *me = Medium case "HIGH": *me = High default: // return error return fmt.Errorf("unknown access complexity: %s", s) } // return success return nil } // CVSS V2 authentication type Authentication int // Unmarshal CVSS V2 authentication from JSON. func (me *Authentication) UnmarshalJSON(b []byte) error { // decode string, check for error var s string if err := json.Unmarshal(b, &s); err != nil { return err } // check value switch s { case "NONE": *me = None case "SINGLE": *me = Single default: // return error return fmt.Errorf("unknown authentication: %s", s) } // return success return nil } // CVE metadata type CveMetadata struct { // CVE ID Id string `json:"ID"` // CVE assigner email address Assigner string `json:"ASSIGNER"` } // CVE description string. type Description struct { // Language code Lang string `json:"lang"` // String value Value string `json:"value"` } // CVE problem type type CveProblemType struct { // problem type descriptions Descriptions []Description `json:"description"` } // Slice of CVE problem types. type CveProblemTypes struct { // problem types ProblemTypes []CveProblemType `json:"problemtype_data"` } // CVE reference type CveReference struct { // reference URL Url string `json:"url"` // reference name Name string `json:"name"` // reference source RefSource string `json:"refsource"` // tags Tags []string `json:"tags"` } // Slice of CVE references type CveReferences struct { References []CveReference `json:"reference_data"` } // CVE item descriptions type CveDescription struct { // slice of descriptions Descriptions []Description `json:"description_data"` } // CVE data type Cve struct { // feed data type DataType DataType `json:"CVE_data_type"` // feed data format DataFormat DataFormat `json:"CVE_data_format"` // feed data format version DataVersion DataVersion `json:"CVE_data_version"` // CVE metadata Metadata CveMetadata `json:"CVE_data_meta"` // CVE problem types ProblemTypes CveProblemTypes `json:"problemtype"` // CVE references References CveReferences `json:"references"` // CVE description Description CveDescription `json:"description"` } // CPE match type CpeMatch struct { // Vulnerable? Vulnerable bool `json:"vulnerable"` VersionEndExcluding string `json:"versionEndExcluding"` // CPE URI (FIXME: decode this) Cpe23Uri string `json:"cpe23Uri"` // CPE names (not sure if this is correct) Names []string `json:"cpe_name"` } // CVE item configuration node type ConfigurationNode struct { // node operator Operator NodeOp `json:"operator"` // node children Children []ConfigurationNode `json:"children"` CpeMatches []CpeMatch `json:"cpe_match"` } // CVE item configurations type ItemConfigurations struct { // data version DataVersion DataVersion `json:"CVE_data_version"` // slice of configuration nodes Nodes []ConfigurationNode `json:"nodes"` } // CVSS version. type CvssV3Version int // Unmarshal CVSS version from JSON. func (me *CvssV3Version) UnmarshalJSON(b []byte) error { // decode string, check for error var s string if err := json.Unmarshal(b, &s); err != nil { return err } // check value switch s { case "3.1": *me = CvssVersion31 default: // return error return fmt.Errorf("unknown CVSS V3 version: %s", s) } // return success return nil } // CVSS V2 version. type CvssV2Version int // Unmarshal CVSS version from JSON. func (me *CvssV2Version) UnmarshalJSON(b []byte) error { // decode string, check for error var s string if err := json.Unmarshal(b, &s); err != nil { return err } // check value switch s { case "2.0": *me = CvssVersion20 default: // return error return fmt.Errorf("unknown CVSS V2 version: %s", s) } // return success return nil } // CVSS V3 type CvssV3 struct { // CVSS V3 version Version CvssV3Version `json:"version"` // CVSS V3 vector string (FIXME: add custom type) VectorString string `json:"vectorString"` // attack vector AttackVector V3AttackVector `json:"attackVector"` // attack complexity AttackComplexity V3AttackComplexity `json:"attackComplexity"` // privileges required PrivilegesRequired V3PrivilegesRequired `json:"privilegesRequired"` // user interaction UserInteraction V3UserInteraction `json:"userInteraction"` // scope Scope V3Scope `json:"scope"` // integrity impact IntegrityImpact ImpactLevel `json:"integrityImpact"` // availability impact AvailabilityImpact ImpactLevel `json:"availabilityImpact"` // base score BaseScore Score `json:"baseScore"` // base severity BaseSeverity Severity `json:"baseSeverity"` } // CVSS V3 base metrics type BaseMetricV3 struct { CvssV3 CvssV3 `json:"cvssV3"` ExploitabilityScore Score `json:"exploitabilityScore"` ImpactScore Score `json:"impactScore"` } // CVSS V2 type CvssV2 struct { // CVSS V2 version Version CvssV2Version `json:"version"` // CVSS V3 vector string (FIXME: add custom type) VectorString string `json:"vectorString"` // attack vector AccessVector V2AccessVector `json:"accessVector"` // attack complexity AccessComplexity AccessComplexity `json:"accessComplexity"` // authentication Authentication Authentication `json:"authentication"` ConfidentialityImpact ImpactLevel `json:"confidentialityImpact"` IntegrityImpact ImpactLevel `json:"integrityImpact"` AvailabilityImpact ImpactLevel `json:"availabilityImpact"` // base score BaseScore Score `json:"baseScore"` } // CVSS V2 base metrics type BaseMetricV2 struct { CvssV2 CvssV2 `json:"cvssV2"` severity Severity `json:"severity"` ExploitabilityScore Score `json:"impactScore"` ImpactScore Score `json:"impactScore"` InsufficientInfo bool `json:"acInsufInfo"` ObtainAllPrivilege bool `json:"obtainAllPrivilege"` ObtainUserPrivilege bool `json:"obtainUserPrivilege"` ObtainOtherPrivilege bool `json:"obtainOtherPrivilege"` UserInteractionRequired bool `json:"userInteractionRequired"` } // Item impact type Impact struct { // CVSS V3 base metrics BaseMetricV3 BaseMetricV3 `json:"baseMetricV3"` // CVSS V2 base metrics BaseMetricV2 BaseMetricV2 `json:"baseMetricV2"` } // CVE feed item type Item struct { // item CVE data Cve Cve `json:"cve"` // item configuration Configurations ItemConfigurations `json:"configurations"` // item impact Impact Impact `json:"impact"` // item published date PublishedDate Time `json:"publishedDate"` // last modification date LastModifiedDate Time `json:"lastModifiedDate"` } // NVD feed type Feed struct { // feed data type DataType DataType `json:"CVE_data_type"` // feed data format DataFormat DataFormat `json:"CVE_data_format"` // feed data format version DataVersion DataVersion `json:"CVE_data_version"` // number of CVEs in feed NumCVEs uint64 `json:"CVE_data_numberOfCVEs,string"` // data timestamp Timestamp Time `json:"CVE_data_timestamp"` // CVE items Items []Item `json:"CVE_Items"` }