Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from emo-crab/dev
Browse files Browse the repository at this point in the history
cvss v4  api yew
cn-kali-team authored Nov 21, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents cd1d728 + 116244c commit 9c7da31
Showing 122 changed files with 30,778 additions and 780 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -13,4 +13,7 @@ Cargo.lock
*.xml.gz
*.json.gz
*.xml.zip
/examples/nvdcve/data-feeds.html
/helper/examples/nvdcve/data-feeds.html
/.env
/nvd-server/nvd-er.mwb.bak
/nvd-server/dist/
24 changes: 4 additions & 20 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -7,7 +7,8 @@ include = ["LICENSE", "Cargo.toml", "src/**/*.rs"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[workspace]
members = ["cpe", "cve", "cvss","cwe","nvd-db"]
members = ["cpe", "cve", "cvss", "cwe", "helper", "nvd-server", "nvd-yew"]
default-members = ["nvd-server"]

#https://github.com/johnthagen/min-sized-rust
[profile.release]
@@ -30,22 +31,5 @@ opt-level = 3


[dependencies]
cpe = { path = "cpe" }
cve = { path = "cve" }
cvss = { path = "cvss" }
cwe = { path = "cwe" }
nvd-db = { path = "nvd-db" }

[dev-dependencies]
serde = { version = "1", features = ["derive"] }
quick-xml = { version = "0.29.0", features = ["serde", "encoding_rs", "serialize"] }
serde_yaml = "0.9"
serde_json = "1.0"
flate2 = "1.0"
zip = "0.6"

[[example]]
name = "cpe-example"

[[example]]
name = "cve-example"


6 changes: 6 additions & 0 deletions Trunk.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[build]
target = "nvd-yew/index.html"
dist = "nvd-api/dist"

[[proxy]]
backend = "http://127.0.0.1:8888/api/"
18 changes: 4 additions & 14 deletions cpe/src/component.rs
Original file line number Diff line number Diff line change
@@ -5,9 +5,10 @@ use std::{convert::TryFrom, fmt, str::FromStr};

use crate::error::{CPEError, Result};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub enum Language {
// 任意值
#[default]
Any,
//不适用
NA,
@@ -17,12 +18,6 @@ pub enum Language {
Language(LanguageTag),
}

impl Default for Language {
fn default() -> Self {
Language::Any
}
}

impl FromStr for Language {
type Err = CPEError;
fn from_str(s: &str) -> Result<Self> {
@@ -97,9 +92,10 @@ impl<'de> Deserialize<'de> for Language {
}
}
// 组件
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub enum Component {
// 任意值
#[default]
Any,
// 不适用
NA,
@@ -148,12 +144,6 @@ impl TryFrom<String> for Component {
}
}

impl Default for Component {
fn default() -> Self {
Component::Any
}
}

impl FromStr for Component {
type Err = CPEError;

9 changes: 3 additions & 6 deletions cpe/src/dictionary.rs
Original file line number Diff line number Diff line change
@@ -34,12 +34,8 @@ to use or not, but this information is not required to be used or understood.
pub struct CPEItem {
#[serde(rename(deserialize = "@name"), deserialize_with = "parse_name")]
pub name: String,
#[serde(
default,
rename(serialize = "deprecated", deserialize = "@deprecated"),
skip_serializing_if = "Option::is_none"
)]
pub deprecated: Option<bool>,
#[serde(default, rename(serialize = "deprecated", deserialize = "@deprecated"))]
pub deprecated: bool,
#[serde(
default,
rename(serialize = "deprecation_date", deserialize = "@deprecation_date"),
@@ -48,6 +44,7 @@ pub struct CPEItem {
pub deprecation_date: Option<DateTime<Utc>>,
#[serde(rename(serialize = "cpe23", deserialize = "cpe23-item"))]
pub cpe23_item: CPE23Item,
#[serde(default)]
pub title: Vec<Title>,
#[serde(skip_serializing_if = "Option::is_none")]
pub notes: Option<Vec<Notes>>,
4 changes: 2 additions & 2 deletions cpe/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! cpe error
use thiserror::Error;
use thiserror::Error as ThisError;

pub type Result<T> = std::result::Result<T, CPEError>;

#[derive(Error, Debug, Clone)]
#[derive(ThisError, Debug, Clone)]
pub enum CPEError {
#[error("invalid wfn `{value}`")]
InvalidWfn { value: String },
17 changes: 16 additions & 1 deletion cpe/src/lib.rs
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ use part::Part;
// https://scap.nist.gov/schema/cpe/2.3/cpe-naming_2.3.xsd
// cpe:2.3:part:vendor:product:version:update:edition:language:sw_edition:target_sw: target_hw:other
// CPE属性
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct CPEName {
// 分类:a,o,h
@@ -56,7 +56,22 @@ pub struct CPEName {
// 表示无法归类上上述其他属性的值
pub other: Component,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Hash)]
pub struct Product {
pub part: String,
pub vendor: String,
pub product: String,
}

impl From<&CPEName> for Product {
fn from(val: &CPEName) -> Self {
Product {
part: val.part.to_string(),
vendor: val.vendor.to_string(),
product: val.product.to_string(),
}
}
}
impl CPEName {
// 从uri转CPE属性
pub fn from_uri(uri: &str) -> Result<Self> {
15 changes: 10 additions & 5 deletions cpe/src/part.rs
Original file line number Diff line number Diff line change
@@ -3,9 +3,10 @@ use crate::error::{CPEError, Result};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{fmt, str::FromStr};

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum Part {
// any
#[default]
Any,
// 硬件设备 h
Hardware,
@@ -44,12 +45,16 @@ impl<'de> Deserialize<'de> for Part {
}
}

impl Default for Part {
fn default() -> Self {
Part::Any
impl From<Part> for char {
fn from(val: Part) -> Self {
match val {
Part::Any => '*',
Part::Hardware => 'h',
Part::OperatingSystem => 'o',
Part::Application => 'a',
}
}
}

impl FromStr for Part {
type Err = CPEError;

1 change: 1 addition & 0 deletions cve/Cargo.toml
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ edition = "2021"

[dependencies]
serde = { version = "1", features = ["derive"] }
chrono = { version = "0.4", default-features = false, features = ["serde"] }
cpe = { path = "../cpe" }
cvss = { path = "../cvss" }
thiserror = "1.0"
33 changes: 25 additions & 8 deletions cve/src/configurations.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! configurations
//!
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
/// A configuration is a container that holds a set of nodes which then contain CPE Name Match Criteria. Configurations consist of three different types.
///
#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq)]
#[serde(deny_unknown_fields)]
pub struct Configurations {
// 版本
@@ -13,7 +14,16 @@ pub struct Configurations {
pub nodes: Vec<Node>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
impl Configurations {
pub fn unique_vendor_product(&self) -> Vec<cpe::Product> {
self
.nodes
.iter()
.flat_map(|node| node.vendor_product())
.collect()
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq)]
#[serde(deny_unknown_fields)]
pub struct Node {
// 逻辑操作符
@@ -25,8 +35,8 @@ pub struct Node {
}
/// Applicability statements are made to withstand changes to the Official CPE Dictionary without requiring consistent maintenance. CPE Match criteria comes in two forms CPE Match Strings and CPE Match String Ranges. Each of these are abstract concepts that are then correlated to CPE Names in the Official CPE Dictionary. Match criteria are displayed in bold text within a configuration node.
///
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all(deserialize = "camelCase"), deny_unknown_fields)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Match {
// 是否存在漏洞
pub vulnerable: bool,
@@ -43,8 +53,8 @@ pub struct Match {
#[serde(rename = "cpe_name")]
pub cpe_name: Vec<CPEUri>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(rename_all(deserialize = "camelCase"), deny_unknown_fields)]
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Eq)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CPEUri {
/// A CPE Match string is a single CPE Names string that correlates to one or many CPE Names in the Official CPE Dictionary. When a match string has the bug icon next to it, all matching CPE Names are considered vulnerable. You can click the caret below a CPE Match String to see the CPE Names in the dictionary that match.
#[serde(
@@ -53,7 +63,7 @@ pub struct CPEUri {
)]
pub cpe23_uri: cpe::CPEName,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Eq)]
#[serde(rename_all = "UPPERCASE", deny_unknown_fields)]
pub enum Operator {
And,
@@ -67,7 +77,9 @@ impl Match {
|| self.version_end_including.is_some()
|| self.version_end_excluding.is_some()
}

pub fn product(&self) -> cpe::Product {
cpe::Product::from(&self.cpe_uri.cpe23_uri)
}
pub fn match_version_range(&self, ver: &str) -> bool {
if let Some(start_inc) = &self.version_start_including {
if !cpe::version_cmp(ver, start_inc, ">=") {
@@ -147,4 +159,9 @@ impl Node {
}
false
}
pub fn vendor_product(&self) -> HashSet<cpe::Product> {
let product = self.cpe_match.iter().map(|m| m.product());
let children = self.children.iter().flat_map(|node| node.vendor_product());
product.chain(children).collect()
}
}
4 changes: 2 additions & 2 deletions cve/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! cve error
use thiserror::Error;
use thiserror::Error as ThisError;

pub type Result<T> = std::result::Result<T, CVEError>;

#[derive(Error, Debug, Clone)]
#[derive(ThisError, Debug, Clone)]
pub enum CVEError {
#[error("error decoding value `{value}`, not well formed UTF-8")]
Utf8Error {
57 changes: 2 additions & 55 deletions cve/src/impact.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! impact
use cvss::error::{CVSSError, Result};
use cvss::v2::ImpactMetricV2;
use cvss::v3::ImpactMetricV3;
use serde::{Deserialize, Serialize};
use std::str::FromStr;

/// This is impact type information (e.g. a text description, CVSSv2, CVSSv3, etc.).
///
@@ -18,56 +18,3 @@ pub struct Impact {
pub base_metric_v3: Option<ImpactMetricV3>,
// TODO: Implement V4?
}

/// cvss v2
///
/// The CVSSv2 <https://www.first.org/cvss/v2/guide> scoring data, split up into Base Metrics Group (BM), Temporal Metrics Group (TM) and Environmental Metrics Group (EM).
///
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all(deserialize = "camelCase"), deny_unknown_fields)]
pub struct ImpactMetricV2 {
pub cvss_v2: cvss::v2::CVSS,
// 漏洞的可利用 评分
pub exploitability_score: f32,
// 评分
pub impact_score: f32,
// 评级
pub severity: String,
pub ac_insuf_info: Option<bool>,
pub obtain_all_privilege: bool,
pub obtain_user_privilege: bool,
pub obtain_other_privilege: bool,
// 用户交互
pub user_interaction_required: Option<bool>,
}
/// cvss v3
///
/// The CVSSv3 <https://www.first.org/cvss/specification-document> scoring data.
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all(deserialize = "camelCase"), deny_unknown_fields)]
pub struct ImpactMetricV3 {
pub cvss_v3: cvss::v3::CVSS,
// 漏洞的可利用 评分
pub exploitability_score: f32,
// cvss 评分
pub impact_score: f32,
}

impl FromStr for ImpactMetricV3 {
type Err = CVSSError;

fn from_str(s: &str) -> Result<Self> {
match cvss::v3::CVSS::from_str(s) {
Ok(c) => {
let exploitability_score = c.exploitability_score();
let impact_score = c.impact_score();
Ok(Self {
cvss_v3: c,
exploitability_score,
impact_score,
})
}
Err(err) => Err(err),
}
}
}
Loading

0 comments on commit 9c7da31

Please sign in to comment.