diff --git a/Cargo.lock b/Cargo.lock index d3defab5..463389ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -295,6 +295,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "assemblyline-markings" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de017615511c9997a078ef4558e8f3743361f9dedc748b2c9d3caf49c866c14e" +dependencies = [ + "itertools 0.11.0", + "serde", + "serde_json", + "serde_yaml", +] + [[package]] name = "async-broadcast" version = "0.7.2" @@ -3183,6 +3195,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -3599,6 +3620,7 @@ name = "malwaredb" version = "0.1.2-dev" dependencies = [ "anyhow", + "assemblyline-markings", "bytesize", "cart_container", "chrono", @@ -3632,6 +3654,7 @@ dependencies = [ name = "malwaredb-api" version = "0.1.2-dev" dependencies = [ + "assemblyline-markings", "chrono", "hex", "serde", @@ -5840,6 +5863,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.6" @@ -7017,6 +7053,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index b9d4856b..bf7d347a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ build = "build.rs" default = [] admin = ["dep:dialoguer", "dep:flate2", "malwaredb-server/admin", "dep:chrono", "dep:walkdir", "dep:zip", "toml/serde"] admin-gui = ["malwaredb-server/admin", "dep:slint", "dep:slint-build", "futures/executor"] +assemblyline = ["malwaredb-server/assemblyline"] sqlite = ["malwaredb-server/sqlite"] vt = ["malwaredb-server/vt", "dep:malwaredb-virustotal"] @@ -25,6 +26,7 @@ malwaredb-server = { workspace = true } malwaredb-types = { workspace = true, features = ["elf", "macho", "office95", "officexml", "pdf", "pe32", "pef", "rtf"] } anyhow = { workspace = true } +assemblyline-markings = { workspace = true } bytesize = { workspace = true, features = ["serde"] } cart_container = { workspace = true, features = ["md5", "sha1"] } chrono = { workspace = true, optional = true } @@ -105,6 +107,7 @@ aes-gcm = { version = "0.10.3", default-features = false } anyhow = { version = "1.0", default-features = false } app-memory-usage-fetcher = { version = "0.2.1", default-features = false } argon2 = { version = "0.5.3", default-features = false } +assemblyline-markings = { version = "0.1.10", default-features = false } axum = { version = "0.8.4", default-features = false } axum-server = { version = "0.7.2", default-features = false } base64 = { version = "0.22.1", default-features = false } diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index 56da12b4..90993932 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -11,7 +11,12 @@ keywords.workspace = true rust-version.workspace = true categories = ["api-bindings", "data-structures"] +[features] +default = [] +assemblyline = ["dep:assemblyline-markings"] + [dependencies] +assemblyline-markings = { workspace = true, optional = true } chrono = { workspace = true, features = ["serde"] } hex = { workspace = true, features = ["alloc"] } serde = { workspace = true, features = ["derive", "std"] } diff --git a/crates/api/src/assemblyline.rs b/crates/api/src/assemblyline.rs new file mode 100644 index 00000000..a89b904f --- /dev/null +++ b/crates/api/src/assemblyline.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 + +use assemblyline_markings::config::ClassificationMarking; +use serde::{Deserialize, Serialize}; + +/// API endpoint for uploading a sample, POST, Authenticated for use by Assemblyline +pub const UPLOAD_SAMPLE: &str = "/v1/assemblyline/samples/upload"; + +/// New file sample being sent to `MalwareDB` +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct NewSample { + /// The original file name, might not be known + pub file_name: String, + + /// ID of the source for this sample + pub source_id: u32, + + /// Base64 encoding of the binary file + pub file_contents_b64: String, + + /// SHA-256 of the sample being sent, for server-side validation + pub sha256: String, + + /// Security control for Assemblyline integration based on + pub assemblyline_tlp: ClassificationMarking, + + /// Assemblyline's analysis data + pub assemblyline_data: serde_json::Map, +} diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index ef8a7fea..0bc516be 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -6,6 +6,9 @@ #![deny(clippy::pedantic)] #![forbid(unsafe_code)] +/// Data types and API endpoints for Assemblyline integration +#[cfg(feature = "assemblyline")] +pub mod assemblyline; /// Wrapper for fixed-size hash digests from hex strings pub mod digest; diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml index e25ffec1..f2896278 100644 --- a/crates/server/Cargo.toml +++ b/crates/server/Cargo.toml @@ -15,6 +15,7 @@ build = "build.rs" [features] default = [] admin = [] +assemblyline = ["malwaredb-api/assemblyline"] sqlite = ["dep:rusqlite"] vt = ["dep:malwaredb-virustotal", "postgres/with-serde_json-1"] diff --git a/crates/server/src/db/malwaredb_pg.sql b/crates/server/src/db/malwaredb_pg.sql index d24002ed..14b44b59 100644 --- a/crates/server/src/db/malwaredb_pg.sql +++ b/crates/server/src/db/malwaredb_pg.sql @@ -30,6 +30,8 @@ CREATE TABLE file ( nonce bytea[], key int REFERENCES encryptionkey(id), parent bigint REFERENCES file(id), + assemblyline_data json, + assemblyline_tlp text, PRIMARY KEY (id) ); diff --git a/crates/server/src/db/malwaredb_sqlite.sql b/crates/server/src/db/malwaredb_sqlite.sql index 790991f9..91527041 100644 --- a/crates/server/src/db/malwaredb_sqlite.sql +++ b/crates/server/src/db/malwaredb_sqlite.sql @@ -47,7 +47,9 @@ CREATE TABLE file ( confirmedmalicious integer, -- boolean nonce text, -- hex bytes key int REFERENCES encryptionkey(id), - parent int REFERENCES file(id) + parent int REFERENCES file(id), + assemblyline_data text, -- JSON + assemblyline_tlp text ); diff --git a/src/cli/admin/users.rs b/src/cli/admin/users.rs index 01943411..b88ab32c 100644 --- a/src/cli/admin/users.rs +++ b/src/cli/admin/users.rs @@ -38,6 +38,11 @@ pub struct Create { /// Create a read-only account, usually for guest access or demonstration #[arg(short, long, default_value_t = false)] pub readonly: bool, + + #[cfg(feature = "assemblyline")] + /// Classification level allowed for this user + #[arg(short, long)] + pub classification: String, } impl Create {