Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exlude include #114

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,632 changes: 1,632 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ clap = { version = "4.0.29", features = ["derive"] }
const_format = "0.2.30"
serde = { version = "^1.0", features = ["derive"] }
serde_json = "^1.0"
cherrybomb-engine = "^0.1"
cherrybomb-engine = { path = "cherrybomb-engine" }
serde_yaml = "^0.9.0"
uuid = {version = "1.2.2", features = ["v4"] }
dirs = "4.0.0"
Expand Down
6 changes: 2 additions & 4 deletions cherrybomb-engine/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cherrybomb-engine/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cherrybomb-engine"
version = "0.1.0"
version = "0.1.1"
authors = ["BLST Security"]
description = """
Cherrybomb enging crate
Expand All @@ -13,7 +13,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cherrybomb-oas = "^0.1"
cherrybomb-oas = { path = "../cherrybomb-oas" }
anyhow = "1.0.66"
thiserror = "1.0.37"
serde_json = "^1.0"
Expand Down
187 changes: 112 additions & 75 deletions cherrybomb-engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ pub mod config;
mod info;
mod scan;

use crate::config::Verbosity;
use crate::info::eps::EpTable;
use crate::info::params::ParamTable;
use crate::scan::active::active_scanner;
use crate::scan::active::http_client::auth::Authorization;
use cherrybomb_oas::legacy::legacy_oas::*;
use config::Config;
use scan::passive::passive_scanner;
use scan::*;
use std::collections::{HashMap, HashSet};
use serde_json::{json, Value};
use std::collections::HashMap;
use strum::IntoEnumIterator;
use config::{Config, Verbosity};
use info::{eps::EpTable, params::ParamTable};
use scan::*;
use scan::checks::{PassiveChecks, ActiveChecks};
use scan::active::{active_scanner, http_client::auth::Authorization};
use scan::passive::passive_scanner;
use cherrybomb_oas::legacy::legacy_oas::*;

fn verbose_print(config: &Config, required: Option<Verbosity>, message: &str) {
let required = required.unwrap_or(Verbosity::Normal);
Expand Down Expand Up @@ -51,16 +50,88 @@ pub async fn run(config: &Config) -> anyhow::Result<Value> {
}
};

// Creating checks lists
let mut checks : HashMap<&str,HashSet<&str>> = HashMap::new();
match config.profile {
config::Profile::Info => run_profile_info(&config, &oas, &oas_json),
config::Profile::Normal => run_normal_profile(&config, &oas, &oas_json).await,
config::Profile::Info => {
checks.insert("info",HashSet::new());
checks.insert("active",HashSet::new());
checks.insert("passive",HashSet::new())
},
config::Profile::Normal => {
checks.insert("passive",PassiveChecks::iter().map(|x| x.name()).collect());
checks.insert("active",ActiveChecks::iter().map(|x| x.name()).collect())
},
config::Profile::Intrusive => todo!("Not implemented!"),
config::Profile::Passive => run_passive_profile(&config, &oas, &oas_json),
config::Profile::Full => run_full_profile(config, &oas, &oas_json).await,
config::Profile::Passive => {
checks.insert("passive",PassiveChecks::iter().map(|x| x.name()).collect());
checks.insert("active",HashSet::new())

},
config::Profile::Full => {
checks.insert("info",HashSet::new());
checks.insert("passive",PassiveChecks::iter().map(|x| x.name()).collect());
checks.insert("active",ActiveChecks::iter().map(|x| x.name()).collect())
},
};
dbg!(&config.active_exclude);
dbg!(&config.active_include);
dbg!(&config.passive_exclude);
dbg!(&config.passive_include);
for active_check in config.active_exclude.iter() {
if let Some(a) = checks.get_mut("active") {
a.remove(active_check.as_str());
}
}
for passive_check in config.passive_exclude.iter() {
if let Some(a) = checks.get_mut("passive") {
a.remove(passive_check.as_str());
}
}
for active_check in config.active_include.iter() {
println!("hey");
if let Some(a) = checks.get_mut("active") {
println!("hereree");
a.insert(active_check.as_str());
dbg!(&a);
}

}
for passive_check in config.passive_include.iter() {
if let Some(a) = checks.get_mut("passive") {
a.insert(passive_check.as_str());
}
}
let mut report = json!({});
dbg!(&checks);
for check_type in checks.keys() {
match check_type.to_owned() {
"info" => {
verbose_print(config, None, "Running info checks...");
report["info"] = run_profile_info(config, &oas_json)?;
},
"passive" => {
verbose_print(config, None, "Running passive checks...");
report["passive"] = run_passive_profile(config, &oas, &oas_json, &checks[check_type])?;
},
"active" => {
verbose_print(config, None, "Running active checks...");
report["active"] = run_active_profile(config, &oas, &oas_json, &checks[check_type]).await?;
},
_ => {
return Err(anyhow::anyhow!("Unknown check type: {}", check_type));
}
}
}
Ok(report)
}

fn run_profile_info(config: &Config, oas: &OAS3_1, oas_json: &Value) -> anyhow::Result<Value> {


fn run_profile_info(
config: &Config,
oas_json: &Value
) -> anyhow::Result<Value> {
// Creating parameter list
verbose_print(config, None, "Creating param list...");
let param_scan = ParamTable::new::<OAS3_1>(oas_json);
Expand All @@ -81,7 +152,6 @@ fn run_profile_info(config: &Config, oas: &OAS3_1, oas_json: &Value) -> anyhow::

verbose_print(config, None, "Creating report...");
let report = json!({

"params": param_result,
"endpoints": endpoint_result,
});
Expand All @@ -92,13 +162,21 @@ async fn run_active_profile(
config: &Config,
oas: &OAS3_1,
oas_json: &Value,
checks: &HashSet<&str>
) -> anyhow::Result<Value> {
// Creating active scan struct
verbose_print(
config,
Some(Verbosity::Debug),
"Creating active scan struct...",
);
let checks : Vec<ActiveChecks> = checks
.iter()
.filter_map(|check| {
ActiveChecks::from_string(check)
})
.collect();

let mut active_scan = match active_scanner::ActiveScan::new(oas.clone(), oas_json.clone()) {
Ok(scan) => scan,
Err(e) => {
Expand All @@ -110,7 +188,7 @@ async fn run_active_profile(
verbose_print(config, None, "Running active scan...");
let temp_auth = Authorization::None;
active_scan
.run(active_scanner::ActiveScanType::Full, &temp_auth)
.run(active_scanner::ActiveScanType::Partial(checks), &temp_auth)
.await;
let active_result: HashMap<&str, Vec<Alert>> = active_scan
.checks
Expand All @@ -121,82 +199,41 @@ async fn run_active_profile(
Ok(report)
}

fn run_passive_profile(config: &Config, oas: &OAS3_1, oas_json: &Value) -> anyhow::Result<Value> {
fn run_passive_profile(
config: &Config,
oas: &OAS3_1,
oas_json: &Value,
checks: &HashSet<&str>,
) -> anyhow::Result<Value> {
dbg!(&config.passive_exclude);
// Creating passive scan struct
verbose_print(
config,
Some(Verbosity::Debug),
"Creating passive scan struct...",
);
let checks : Vec<PassiveChecks> = checks
.iter()
.filter_map(|check| {
PassiveChecks::from_string(check)
})
.collect();

let mut passive_scan = passive_scanner::PassiveSwaggerScan {
swagger: oas.clone(),
swagger_value: oas_json.clone(),
passive_checks: vec![], //TODO create check list from config
passive_checks: vec![],
verbosity: 0,
};

// Running passive scan
verbose_print(config, None, "Running passive scan...");
passive_scan.run(passive_scanner::PassiveScanType::Full);
passive_scan.run(passive_scanner::PassiveScanType::Partial(checks));
let passive_result: HashMap<&str, Vec<Alert>> = passive_scan
.passive_checks
.iter()
.map(|check| (check.name(), check.inner()))
.collect();
Ok(json!({ "passive": passive_result }))
}

async fn run_normal_profile(
config: &Config,
oas: &OAS3_1,
oas_json: &Value,
) -> anyhow::Result<Value> {
let mut report = json!({});
let mut results = HashMap::from([
("passive", run_passive_profile(config, oas, oas_json)),
("active", run_active_profile(config, oas, oas_json).await),
]);
for (key, value) in results.iter_mut() {
match value {
Ok(result) => {
if let Some(val) = result.get(key) {
report[key] = val.clone();
}
}
Err(e) => {
verbose_print(
config,
None,
&format!("WARNING: Error running {key} scan: {e}"),
);
}
}
}
Ok(report)
}

async fn run_full_profile(config: &Config, oas: &OAS3_1, oas_json: &Value) -> anyhow::Result<Value> {
let mut report = json!({});
let mut results = HashMap::from([
("active", run_active_profile(config, oas, oas_json).await),
("passive", run_passive_profile(config, oas, oas_json)),
("params", run_profile_info(config, oas, oas_json)),
("endpoints", run_profile_info(config, oas, oas_json)),
]);
for (key, value) in results.iter_mut() {
match value {
Ok(result) => {
if let Some(val) = result.get(key) {
report[key] = val.clone();
}
}
Err(e) => {
verbose_print(
config,
None,
&format!("WARNING: Error running {} scan: {}", key, e),
);
}
}
}
Ok(report)
}
1 change: 0 additions & 1 deletion cherrybomb-engine/src/scan/active/active_scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ impl<T: OAS + Serialize + for<'de> Deserialize<'de>> ActiveScan<T> {
};
}


fn payloads_generator(oas: &T, oas_value: &Value) -> Vec<OASMap> {
let mut payloads = vec![];
for (path, path_item) in oas.get_paths() {
Expand Down
2 changes: 1 addition & 1 deletion cherrybomb-oas/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cherrybomb-oas/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cherrybomb-oas"
version = "0.1.0"
version = "0.1.1"
authors = ["BLST Security"]
description = """
Cherrybomb OpenAPI Specification (OAS) struct and functions
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ async fn main() -> anyhow::Result<ExitCode> {
if !opt.no_telemetry {
telemetry::send(config.profile.clone(), config.verbosity.clone()).await?;
}
dbg!(&config);
let json_val = cherrybomb_engine::run(&config).await?;
match print_tables(json_val, &opt) {
Ok(exit_code) => Ok(exit_code),
Expand Down
4 changes: 2 additions & 2 deletions src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ enum CheckStatus {
pub fn print_tables(json_struct: Value, options: &Options) -> anyhow::Result<ExitCode> {
let mut status_vec = vec![];
if let Some(json_struct) = json_struct["passive"].as_object() {
status_vec.push(print_full_alert_table(json_struct, &options.format)?);
status_vec.push(print_alert_table(json_struct, &options.format)?);
//create_table_with_full_verbosity(&json_struct)?;
}
if let Some(json_struct) = json_struct["active"].as_object() {
Expand All @@ -83,7 +83,7 @@ pub fn print_tables(json_struct: Value, options: &Options) -> anyhow::Result<Exi
}
}
options::OutputFormat::Json => {
println!("{}", json_struct);
println!("{json_struct}");
if let Some(output_file) = &options.output {
let mut file = File::create(output_file)?;
file.write_all(json_struct.to_string().as_bytes())?;
Expand Down