Skip to content

Commit

Permalink
合并旧指纹
Browse files Browse the repository at this point in the history
  • Loading branch information
cn-kali-team committed Aug 8, 2024
1 parent d0eb58c commit d874086
Show file tree
Hide file tree
Showing 92 changed files with 2,148 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ argh = "0.1.12"
serde = { version = "1.0.196", features = ["derive"] }
serde_yaml = "0.9"
serde_json = "1"
pinyin = "0.10.0"
engine = { git = "https://github.com/emo-crab/observer_ward.git" }
#engine = { path = "../observer_ward/engine" }
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::path::PathBuf;
use argh::FromArgs;

#[derive(Debug, Clone, FromArgs)]
Expand All @@ -15,6 +16,9 @@ pub struct HelperConfig {
/// convert service fingerprint yaml
#[argh(switch)]
pub service: bool,
/// convert v3 yaml to v4 yaml
#[argh(option)]
pub v3_to_v4: Option<PathBuf>,
}

impl Default for HelperConfig {
Expand Down
29 changes: 29 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ pub mod cli;
mod error;
pub mod nmap;
mod service;
mod v3;

pub use v3::{WebFingerPrint, V3WebFingerPrint};
use crate::error::{new_io_error, Result};
pub use crate::service::match_line::MatchLine;
pub use crate::service::probe::{Probe, ZeroDuration};
use engine::request::PortRange;
use std::str::{FromStr, Lines};
use pinyin::ToPinyin;

// 转下划线风格
pub fn to_kebab_case(input: &str) -> String {
Expand Down Expand Up @@ -163,6 +166,32 @@ impl<'buffer> FingerPrintParse<'buffer> {
}
}

pub fn hans_to_pinyin(hans: &str) -> String {
let mut pinyin_str = String::new();
let mut is_han = false;
let mut is_letter = false;
for c in hans.chars() {
if let Some(py) = c.to_pinyin() {
if is_han || is_letter {
pinyin_str.push('-');
}
pinyin_str.push_str(py.plain());
is_han = true;
is_letter = false;
} else {
if is_han {
pinyin_str.push('-');
is_han = false;
}
is_letter = true;
pinyin_str.push(c);
}
}
pinyin_str = pinyin_str.replace(" ", "-");
pinyin_str = pinyin_str.replacen("--", "-", 10);
pinyin_str
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
34 changes: 30 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use engine::request::{HttpRaw, Requests};
use engine::template::Template;
use helper::cli::HelperConfig;
use helper::nmap::nmap;
use helper::to_kebab_case;
use helper::{to_kebab_case, V3WebFingerPrint};
use std::collections::BTreeMap;
use std::env;
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::str::FromStr;

const UNKNOWN_VENDOR: &str = "00_unknown";
Expand Down Expand Up @@ -138,7 +138,7 @@ fn sync_nuclei() {
.join(sub_tag)
.join(yaml_path.file_name().unwrap().to_string_lossy().to_string()),
)
.unwrap();
.unwrap();
break;
}
}
Expand All @@ -153,7 +153,7 @@ fn sync_nuclei() {
.join(product)
.join(yaml_path.file_name().unwrap().to_string_lossy().to_string()),
)
.unwrap();
.unwrap();
}
continue;
}
Expand Down Expand Up @@ -520,6 +520,29 @@ fn cse_to_template(one_cse: CSE, vpf: VPF) -> Template {
return t;
}

fn v3_to_v4(v3_path: PathBuf) {
let v3_yaml_list = find_yaml_file(&v3_path, false);
let current_fingerprint_dir = env::current_dir().unwrap().join("web-fingerprint");
let all_product: Vec<String> = find_yaml_file(&current_fingerprint_dir, true).into_iter()
.map(|p| p.file_name().unwrap().to_string_lossy().trim_end_matches(".yaml").to_string())
.collect();
for v3_path in v3_yaml_list {
let v3_file = File::open(&v3_path).unwrap();
let v3_finger: V3WebFingerPrint = serde_yaml::from_reader(v3_file).unwrap();
let template: Template = v3_finger.into();
if !all_product.contains(&template.info.name) {
if let Some((_x, y)) = template.info.name.split_once("-") {
if all_product.contains(&y.to_string()) {
continue;
}
}
let v4_path = current_fingerprint_dir.join("00_unknown").join(format!("{}.yaml", template.info.name));
let v4_file = File::create(&v4_path).unwrap();
serde_yaml::to_writer(v4_file, &template).unwrap();
}
}
}

fn main() {
let config = HelperConfig::default();
if config.convert {
Expand All @@ -538,6 +561,9 @@ fn main() {
if config.service {
nmap();
}
if let Some(v3_path) = config.v3_to_v4 {
v3_to_v4(v3_path);
}
}

#[cfg(test)]
Expand Down
133 changes: 133 additions & 0 deletions src/v3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use std::collections::{BTreeMap, HashSet};
use engine::info::{Info, Severity, VPF};
use engine::matchers::{Condition, Favicon, Matcher, MatcherType, Part, Word};
use engine::request::Requests;
use engine::template::Template;
use serde::{Deserialize, Serialize};
use crate::hans_to_pinyin;
// 旧版指纹,数据结构

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebFingerPrintRequest {
/// 请求路径
pub path: String,
/// 请求方法
pub request_method: String,
/// 请求头
pub request_headers: BTreeMap<String, String>,
/// 请求数据,base64编码后的
pub request_data: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebFingerPrintMatch {
/// 匹配状态码
pub status_code: u16,
/// 匹配favicon的hash列表
#[serde(default)]
pub favicon_hash: Vec<String>,
/// 匹配的请求头
pub headers: BTreeMap<String, String>,
/// 匹配的关键词列表
pub keyword: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct V3WebFingerPrint {
/// 组件名称
#[serde(default)]
pub name: String,
/// 权重
#[serde(default)]
pub priority: u32,
pub fingerprint: Vec<WebFingerPrint>,
}

/// 单个指纹结构
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebFingerPrint {
/// 指纹的自定义请求
#[serde(flatten)]
pub fingerprint: WebFingerPrintRequest,
/// 匹配部分
#[serde(flatten)]
pub match_rules: WebFingerPrintMatch,
}

impl Into<Template> for V3WebFingerPrint {
fn into(self) -> Template {
let mut info = Info {
name: self.name.to_lowercase().clone(),
severity: Severity::Info,
author: vec!["cn-kali-team".to_string()],
tags: vec![
"detect".to_string(),
"tech".to_string(),
],
..Info::default()
};
info.set_vpf(VPF {
vendor: "00_unknown".to_string(),
product: self.name.clone(),
framework: None,
verified: false,
});
let mut index = Requests::default_web_index();
index.http[0].operators.matchers = v3_finger_to_matcher(&self.fingerprint);
Template {
id: hans_to_pinyin(&self.name).to_lowercase(),
info,
flow: None,
requests: index,
self_contained: false,
stop_at_first_match: false,
variables: Default::default(),
}
}
}

fn v3_finger_to_matcher(finger: &Vec<WebFingerPrint>) -> Vec<Matcher> {
let mut ms = Vec::new();
let mut or_word = HashSet::new();
let mut header = HashSet::new();
let mut favicon = HashSet::new();
for wfp in finger.iter() {
header.extend(wfp.match_rules.headers.iter().map(|(k, v)| format!("{}: {}", k.to_lowercase(), v.trim_end_matches("*").to_lowercase())).collect::<Vec<String>>());
favicon.extend(wfp.match_rules.favicon_hash.clone());
if wfp.match_rules.keyword.len() > 1 {
// 多个必须AND关系
ms.push(Matcher {
matcher_type: MatcherType::Word(Word { words: wfp.match_rules.keyword.clone() }),
condition: Condition::And,
..Matcher::default()
})
} else {
if !wfp.match_rules.favicon_hash.is_empty() {
continue;
}
or_word.extend(wfp.match_rules.keyword.clone());
// 单个OR,或者空
}
}
if !header.is_empty() {
ms.push(Matcher {
part: Part::Header,
matcher_type: MatcherType::Word(Word { words: header.into_iter().map(|x| x).collect() }),
..Matcher::default()
})
}
if !favicon.is_empty() {
ms.push(Matcher {
matcher_type: MatcherType::Favicon(Favicon { hash: favicon.into_iter().map(|x| x).collect() }),
..Matcher::default()
})
}
if !or_word.is_empty() {
ms.push(Matcher {
matcher_type: MatcherType::Word(Word { words: or_word.into_iter().map(|x| x).collect() }),
condition: Condition::Or,
..Matcher::default()
})
}
return ms;
}
22 changes: 22 additions & 0 deletions web-fingerprint/00_unknown/apollo-adminservice.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
id: apollo-adminservice
info:
name: apollo-adminservice
author: cn-kali-team
tags: detect,tech
severity: info
metadata:
product: apollo-adminservice
vendor: 00_unknown
verified: false
http:
- method: GET
path:
- '{{BaseURL}}/'
matchers:
- type: word
words:
- 'content-length: 19'
part: header
- type: word
words:
- apollo-adminservice
20 changes: 20 additions & 0 deletions web-fingerprint/00_unknown/casbin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
id: casbin
info:
name: casbin
author: cn-kali-team
tags: detect,tech
severity: info
metadata:
product: Casbin
vendor: 00_unknown
verified: false
http:
- method: GET
path:
- '{{BaseURL}}/'
matchers:
- type: word
words:
- <title>casdoor
- casdoor/manifest.json
condition: and
22 changes: 22 additions & 0 deletions web-fingerprint/00_unknown/cisco-ios-xe.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
id: cisco-ios-xe
info:
name: cisco-ios-xe
author: cn-kali-team
tags: detect,tech
severity: info
metadata:
product: CISCO-IOS-XE
vendor: 00_unknown
verified: false
http:
- method: GET
path:
- '{{BaseURL}}/'
matchers:
- type: favicon
hash:
- d2962d133fd209cf567d05d1683f3fc1
- type: word
words:
- <script>window.onload=function(){ url ='/webui';window.location.href=url;}</script>
- <script>window.onload=function(){ url ='/webui/';window.location.href=url;}</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
id: dahua-zhi-hui-yuan-qu-zong-he-guan-li-ping-tai
info:
name: dahua-智慧园区综合管理平台
author: cn-kali-team
tags: detect,tech
severity: info
metadata:
product: dahua-智慧园区综合管理平台
vendor: 00_unknown
verified: false
http:
- method: GET
path:
- '{{BaseURL}}/'
matchers:
- type: word
words:
- <li id="DSS-help">
- <span>DSS助手</span>
condition: and
- type: word
words:
- Created by IntelliJ IDEA.
- /WPMS
condition: and
- type: word
words:
- Created by IntelliJ IDEA.
- Selene
condition: and
- type: word
words:
- '"include/styles/common/favicon.ico'
- portal/login_init.action
condition: and
- type: word
words:
- /WPMS/asset/common/css/base.css
Loading

0 comments on commit d874086

Please sign in to comment.