1extern crate lazy_static;
2
3use lazy_static::lazy_static;
4use colored::Colorize;
5use ldap3::SearchEntry;
6use x509_parser::prelude::*;
7use std::collections::HashMap;
8use log::{info, debug, trace, error};
9
10use crate::enums::sid::decode_guid;
11use crate::enums::acl::parse_ntsecuritydescriptor;
12use crate::json::templates::bh_41::{prepare_adcs_ca_json_template,prepare_adcs_template_json_template};
13use crate::modules::adcs::utils::*;
14use crate::modules::adcs::flags::*;
15
16#[derive(Debug)]
17pub struct CA {
18 pub domain: String,
19 pub name: String,
20 pub dnshostname: String,
21 pub object_id: String,
22 pub user_specified_san: String,
23 pub request_disposition: String,
24 pub security: Vec<serde_json::value::Value>,
25 pub web_enrollment: String,
26 pub subject_name: String,
27 pub serial_number: String,
28 pub validity_start: String,
29 pub validity_end: String,
30 pub enabled_templates: Vec<String>
31}
32
33impl CA {
34 pub fn new(domain: &String) -> CA {
35 CA {
36 domain: String::from(domain.to_uppercase()),
37 name: String::from("name"),
38 dnshostname: String::from("name"),
39 object_id: String::from("object_id"),
40 user_specified_san: String::from("Unknown"),
41 request_disposition: String::from("Unknown"),
42 security: Vec::new(),
43 web_enrollment: String::from("Unknown"),
44 subject_name: String::from("subject_name"),
45 serial_number: String::from("serial_number"),
46 validity_start: String::from("validity_start"),
47 validity_end: String::from("validity_end"),
48 enabled_templates: Vec::new(),
49 }
50 }
51}
52
53pub fn parse_adcs_ca(
55 result: SearchEntry,
56 domain: &String,
57 adcs_templates: &mut HashMap<String, Vec<String>>,
58 old_bloodhound: bool,
59) -> serde_json::value::Value {
60
61 let result_dn: String;
62 result_dn = result.dn.to_uppercase();
63
64 let result_attrs: HashMap<String, Vec<String>>;
65 result_attrs = result.attrs;
66
67 let result_bin: HashMap<String, Vec<Vec<u8>>>;
68 result_bin = result.bin_attrs;
69
70 let mut ca_json = prepare_adcs_ca_json_template();
71
72 let mut ca = CA::new(domain);
74
75 debug!("Parse (CA) Certificate Authority: {}", result_dn);
77 for (key, value) in &result_attrs {
87 match key.as_str() {
88 "name" => {
89 ca.name = value[0].to_owned().to_uppercase();
90 ca_json["Properties"]["name"] = format!("{}@{}",ca.name,ca.domain).into();
91 ca_json["Properties"]["CA Name"] = value[0].to_owned().to_uppercase().into();
92 ca_json["Properties"]["domain"] = domain.to_owned().to_uppercase().into();
93 }
94 "cACertificateDN" => {
95 ca.subject_name = value[0].to_owned();
96 ca_json["Properties"]["Certificate Subject"] = ca.subject_name.to_owned().into();
97 trace!("cACertificateDN: {}",&ca.subject_name);
98 }
99 "dNSHostName" => {
100 ca.dnshostname = value[0].to_owned();
101 ca_json["Properties"]["DNS Name"] = ca.dnshostname.to_owned().into();
102 }
103 "certificateTemplates" => {
104 if value.len() <= 0 {
105 error!("No certificate templates enabled for {}",ca.name);
106 } else {
107 ca.enabled_templates = value.to_vec();
108 info!("Found {} enabled certificate templates",value.len().to_string().bold());
109 trace!("Enabled certificate templates: {:?}",value);
110 }
111 }
112 _ => {}
113 }
114 }
115 for (key, value) in &result_bin {
117 match key.as_str() {
118 "objectGUID" => {
119 ca.object_id = decode_guid(&value[0]);
121 ca_json["ObjectIdentifier"] = ca.object_id.to_owned().into();
122 }
123 "nTSecurityDescriptor" => {
124 let entry_type = "ca".to_string();
126 let relations_ace = parse_ntsecuritydescriptor(
128 &mut ca_json,
129 &value[0],
130 entry_type,
131 &result_attrs,
132 &result_bin,
133 &domain,
134 );
135 ca.security = relations_ace.to_owned();
136 ca_json["Aces"] = relations_ace.into();
137 }
138 "cACertificate" => {
139 let res = X509Certificate::from_der(&value[0]);
142 match res {
143 Ok((_rem, cert)) => {
144 ca.serial_number = cert.tbs_certificate.raw_serial_as_string().replace(":","").to_uppercase();
146 ca_json["Properties"]["Certificate Serial Number"] = ca.serial_number.to_owned().to_uppercase().into();
147 trace!("Certificate Serial Number: {:?}",&ca.serial_number);
148
149 ca.validity_start = cert.validity().not_before.to_datetime().to_string();
150 ca_json["Properties"]["Certificate Validity Start"] = ca.validity_start.to_owned().into();
151 trace!("Certificate Validity Start: {:?}",&ca.validity_start);
152
153 ca.validity_end = cert.validity().not_after.to_datetime().to_string();
154 ca_json["Properties"]["Certificate Validity End"] = ca.validity_end.to_owned().into();
155 trace!("Certificate Validity End: {:?}",&ca.validity_end);
156
157 },
158 _ => error!("CA x509 certificate parsing failed: {:?}", res),
159 }
160 }
161 _ => {}
162 }
163 }
164
165 if old_bloodhound {
167 ca_json["Properties"]["type"] = "Enrollment Service".to_string().into();
168 }
169
170 adcs_templates.insert(
172 ca.object_id.to_owned(),
173 ca.enabled_templates.to_owned(),
174 );
175
176 return ca_json
178}
179
180
181#[derive(Debug)]
182pub struct Template {
183 pub name: String,
184 pub object_id: String,
185 pub enrollment_agent: bool,
186 pub certificate_name_flag: Vec<String>,
187 pub enrollment_flag: Vec<String>,
188 pub private_key_flag: Vec<String>,
189 pub application_policies: Vec<String>,
190 pub extended_key_usage: Vec<String>,
191 pub any_purpose: bool,
192 pub client_authentication: bool,
193 pub requires_manager_approval: bool,
194 pub enrollee_supplies_subject: bool,
195 pub no_security_extension: bool,
196 pub requires_key_archival: bool,
197 pub authorized_signatures_required: u64,
198 pub validity_period: String,
199 pub renewal_period: String,
200 pub domain: String,
201}
202
203impl Template {
204 pub fn new(domain: &String) -> Template {
205 Template {
206 name: String::from("name"),
207 object_id: String::from("object_id"),
208 enrollment_agent: false,
209 certificate_name_flag: Vec::new(),
210 enrollment_flag: Vec::new(),
211 private_key_flag: Vec::new(),
212 application_policies: Vec::new(),
213 extended_key_usage: Vec::new(),
214 any_purpose: false,
215 client_authentication: false,
216 enrollee_supplies_subject: false,
217 requires_manager_approval: false,
218 no_security_extension: false,
219 requires_key_archival: false,
220 authorized_signatures_required: 0,
221 validity_period: String::from("validity_period"),
222 renewal_period: String::from("renewal_period"),
223 domain: String::from(domain.to_uppercase()),
224 }
225 }
226}
227
228pub fn parse_adcs_template(
230 result: SearchEntry,
231 domain: &String,
232 old_bloodhound: bool,
233) -> serde_json::value::Value {
234
235 let result_dn: String;
236 result_dn = result.dn.to_uppercase();
237
238 let result_attrs: HashMap<String, Vec<String>>;
239 result_attrs = result.attrs;
240
241 let result_bin: HashMap<String, Vec<Vec<u8>>>;
242 result_bin = result.bin_attrs;
243
244 let mut template_json = prepare_adcs_template_json_template();
245
246 debug!("Parse Certificate Template: {}", result_dn);
248 let mut template = Template::new(domain);
258
259 for (key, value) in &result_attrs {
261 match key.as_str() {
262 "name" => {
263 template.name = value[0].to_owned();
264 template_json["Properties"]["name"] = format!("{}@{}",template.name.to_owned().to_uppercase(),template.domain.to_owned()).into();
265 template_json["Properties"]["Template Name"] = template.name.to_owned().into();
266 template_json["Properties"]["domain"] = domain.to_owned().to_uppercase().into();
267 }
268 "displayName" => {
269 template_json["Properties"]["Display Name"] = value[0].to_owned().into();
270 }
271 "msPKI-Certificate-Name-Flag" => {
272 if value.len() != 0 {
273 template.certificate_name_flag = get_pki_cert_name_flags(
274 &mut template,
275 &mut template_json,
276 value[0].parse::<i64>().unwrap_or(0) as u64
277 );
278 template_json["Properties"]["Certificate Name Flag"] = template.certificate_name_flag.to_owned().into();
279 } else {
280 let mut res: Vec<String> = Vec::new();
281 res.push("None".to_string());
282 template.certificate_name_flag = res;
283 template_json["Properties"]["Certificate Name Flag"] = template.certificate_name_flag.to_owned().into();
284 }
285 }
286 "msPKI-Enrollment-Flag" => {
287 if value.len() != 0 {
288 template.enrollment_flag = get_pki_enrollment_flags(
289 &mut template,
290 &mut template_json,
291 value[0].parse::<i64>().unwrap_or(0) as u64
292 );
293 template_json["Properties"]["Enrollment Flag"] = template.enrollment_flag.to_owned().into();
294 } else {
295 let mut res: Vec<String> = Vec::new();
296 res.push("None".to_string());
297 template.enrollment_flag = res;
298 template_json["Properties"]["Enrollment Flag"] = template.enrollment_flag.to_owned().into();
299 }
300 }
301 "msPKI-Private-Key-Flag" => {
302 if value.len() != 0 {
303 template.private_key_flag = get_pki_private_flags(
304 &mut template,
305 &mut template_json,
306 value[0].parse::<i64>().unwrap_or(0) as u64
307 );
308 template_json["Properties"]["Private Key Flag"] = template.private_key_flag.to_owned().into();
309 } else {
310 let mut res: Vec<String> = Vec::new();
311 res.push("None".to_string());
312 template.private_key_flag = res;
313 template_json["Properties"]["Private Key Flag"] = template.private_key_flag.to_owned().into();
314 }
315 }
316 "msPKI-RA-Signature" => {
317 if value.len() != 0 {
318 template.authorized_signatures_required = value[0].parse::<i64>().unwrap_or(0) as u64;
319 template_json["Properties"]["Authorized Signatures Required"] = template.authorized_signatures_required.to_owned().into();
320 } else {
321 template.authorized_signatures_required = 0;
322 template_json["Properties"]["Authorized Signatures Required"] = template.authorized_signatures_required.to_owned().into();
323 }
324 }
325 "msPKI-RA-Application-Policies" => {
326 if value.len() != 0 {
328 let application_policies = value;
329 let mut values = Vec::new();
330 for oid in application_policies {
331 if OID_TO_STR_MAP.contains_key(oid){
332 values.push(OID_TO_STR_MAP.get(oid).unwrap().to_string());
333 }
334 continue
335 }
336 template.application_policies = values;
337 }
338 }
339 "pKIExtendedKeyUsage" => {
340 if value.len() != 0 {
341 let eku = value;
342 let mut values = Vec::new();
343 for oid in eku {
344 if OID_TO_STR_MAP.contains_key(oid){
345 values.push(OID_TO_STR_MAP.get(oid).unwrap().to_string());
346 }
347 continue
348 }
349 template.extended_key_usage = values;
350 template_json["Properties"]["Extended Key Usage"] = template.extended_key_usage.to_owned().into();
351 }
352 }
353 _ => {}
354 }
355 }
356 for (key, value) in &result_bin {
358 match key.as_str() {
359 "objectGUID" => {
360 template_json["ObjectIdentifier"] = decode_guid(&value[0]).to_owned().into();
362 }
363 "pKIExpirationPeriod" => {
364 template.validity_period = span_to_string(filetime_to_span(value[0].to_owned()));
365 template_json["Properties"]["Validity Period"] = template.validity_period.to_owned().into();
366 }
367 "pKIOverlapPeriod" => {
368 template.renewal_period = span_to_string(filetime_to_span(value[0].to_owned()));
369 template_json["Properties"]["Renewal Period"] = template.renewal_period.to_owned().into();
370 }
371 "nTSecurityDescriptor" => {
372 let entry_type = "template".to_string();
374 let relations_ace = parse_ntsecuritydescriptor(
376 &mut template_json,
377 &value[0],
378 entry_type,
379 &result_attrs,
380 &result_bin,
381 &domain,
382 );
383 template_json["Aces"] = relations_ace.into();
384 }
385 _ => {}
386 }
387 }
388
389 if template.extended_key_usage.contains(&"Any Purpose".to_string()) || template.extended_key_usage.len() == 0 {
392 template.any_purpose = true;
393 template_json["Properties"]["Any purpose"] = template.any_purpose.to_owned().into();
394 }
395
396 let mut isineku = false;
398 for eku in &template.extended_key_usage {
399 if vec!["Client Authentication","Smart Card Logon","PKINIT Client Authentication"].contains(&eku.as_str()) {
400 isineku = true;
401 }
402 }
403 template.client_authentication = template.any_purpose || isineku;
404 template_json["Properties"]["Client Authentication"] = template.client_authentication.to_owned().into();
405
406 let mut isineku = false;
408 for eku in &template.extended_key_usage {
409 if vec!["Certificate Request Agent"].contains(&eku.as_str()) {
410 isineku = true;
411 }
412 }
413 template.enrollment_agent = template.any_purpose || isineku;
414 template_json["Properties"]["Enrollment Agent"] = template.enrollment_agent.to_owned().into();
415
416 if template.enrollee_supplies_subject && !template.requires_manager_approval && template.client_authentication {
418 template_json["Properties"]["highvalue"] = true.into();
419 } else if template.enrollment_agent && !template.requires_manager_approval {
420 template_json["Properties"]["highvalue"] = true.into();
421 } else {
422 template_json["Properties"]["highvalue"] = false.into();
423 }
424
425
426 if old_bloodhound {
428 template_json["Properties"]["type"] = "Certificate Template".to_string().into();
429 }
430
431 return template_json
433}
434
435lazy_static! {
439 static ref OID_TO_STR_MAP: HashMap<String, String> = {
440 let mut map = HashMap::new();
441 map.insert(
442 "1.3.6.1.4.1.311.76.6.1".to_string(),
443 "Windows Update".to_string(),
444 );
445 map.insert(
446 "1.3.6.1.4.1.311.10.3.11".to_string(),
447 "Key Recovery".to_string(),
448 );
449 map.insert(
450 "1.3.6.1.4.1.311.10.3.25".to_string(),
451 "Windows Third Party Application Component".to_string(),
452 );
453 map.insert(
454 "1.3.6.1.4.1.311.21.6".to_string(),
455 "Key Recovery Agent".to_string(),
456 );
457 map.insert(
458 "1.3.6.1.4.1.311.10.3.6".to_string(),
459 "Windows System Component Verification".to_string(),
460 );
461 map.insert(
462 "1.3.6.1.4.1.311.61.4.1".to_string(),
463 "Early Launch Antimalware Drive".to_string(),
464 );
465 map.insert(
466 "1.3.6.1.4.1.311.10.3.23".to_string(),
467 "Windows TCB Component".to_string(),
468 );
469 map.insert(
470 "1.3.6.1.4.1.311.61.1.1".to_string(),
471 "Kernel Mode Code Signing".to_string(),
472 );
473 map.insert(
474 "1.3.6.1.4.1.311.10.3.26".to_string(),
475 "Windows Software Extension Verification".to_string(),
476 );
477 map.insert(
478 "2.23.133.8.3".to_string(),
479 "Attestation Identity Key Certificate".to_string(),
480 );
481 map.insert(
482 "1.3.6.1.4.1.311.76.3.1".to_string(),
483 "Windows Store".to_string(),
484 );
485 map.insert(
486 "1.3.6.1.4.1.311.10.6.1".to_string(),
487 "Key Pack Licenses".to_string(),
488 );
489 map.insert(
490 "1.3.6.1.4.1.311.20.2.2".to_string(),
491 "Smart Card Logon".to_string(),
492 );
493 map.insert(
494 "1.3.6.1.5.2.3.5".to_string(),
495 "KDC Authentication".to_string(),
496 );
497 map.insert(
498 "1.3.6.1.5.5.7.3.7".to_string(),
499 "IP security use".to_string(),
500 );
501 map.insert(
502 "1.3.6.1.4.1.311.10.3.8".to_string(),
503 "Embedded Windows System Component Verification".to_string(),
504 );
505 map.insert(
506 "1.3.6.1.4.1.311.10.3.20".to_string(),
507 "Windows Kits Component".to_string(),
508 );
509 map.insert(
510 "1.3.6.1.5.5.7.3.6".to_string(),
511 "IP security tunnel termination".to_string(),
512 );
513 map.insert(
514 "1.3.6.1.4.1.311.10.3.5".to_string(),
515 "Windows Hardware Driver Verification".to_string(),
516 );
517 map.insert(
518 "1.3.6.1.5.5.8.2.2".to_string(),
519 "IP security IKE intermediate".to_string(),
520 );
521 map.insert(
522 "1.3.6.1.4.1.311.10.3.39".to_string(),
523 "Windows Hardware Driver Extended Verification".to_string(),
524 );
525 map.insert(
526 "1.3.6.1.4.1.311.10.6.2".to_string(),
527 "License Server Verification".to_string(),
528 );
529 map.insert(
530 "1.3.6.1.4.1.311.10.3.5.1".to_string(),
531 "Windows Hardware Driver Attested Verification".to_string(),
532 );
533 map.insert(
534 "1.3.6.1.4.1.311.76.5.1".to_string(),
535 "Dynamic Code Generato".to_string(),
536 );
537 map.insert(
538 "1.3.6.1.5.5.7.3.8".to_string(),
539 "Time Stamping".to_string(),
540 );
541 map.insert(
542 "1.3.6.1.4.1.311.10.3.4.1".to_string(),
543 "File Recovery".to_string(),
544 );
545 map.insert(
546 "1.3.6.1.4.1.311.2.6.1".to_string(),
547 "SpcRelaxedPEMarkerCheck".to_string(),
548 );
549 map.insert(
550 "2.23.133.8.1".to_string(),
551 "Endorsement Key Certificate".to_string(),
552 );
553 map.insert(
554 "1.3.6.1.4.1.311.2.6.2".to_string(),
555 "SpcEncryptedDigestRetryCount".to_string(),
556 );
557 map.insert(
558 "1.3.6.1.4.1.311.10.3.4".to_string(),
559 "Encrypting File System".to_string(),
560 );
561 map.insert(
562 "1.3.6.1.5.5.7.3.1".to_string(),
563 "Server Authentication".to_string(),
564 );
565 map.insert(
566 "1.3.6.1.4.1.311.61.5.1".to_string(),
567 "HAL Extension".to_string(),
568 );
569 map.insert(
570 "1.3.6.1.5.5.7.3.4".to_string(),
571 "Secure Email".to_string(),
572 );
573 map.insert(
574 "1.3.6.1.5.5.7.3.5".to_string(),
575 "IP security end system".to_string(),
576 );
577 map.insert(
578 "1.3.6.1.4.1.311.10.3.9".to_string(),
579 "Root List Signe".to_string(),
580 );
581 map.insert(
582 "1.3.6.1.4.1.311.10.3.30".to_string(),
583 "Disallowed List".to_string(),
584 );
585 map.insert(
586 "1.3.6.1.4.1.311.10.3.19".to_string(),
587 "Revoked List Signe".to_string(),
588 );
589 map.insert(
590 "1.3.6.1.4.1.311.10.3.21".to_string(),
591 "Windows RT Verification".to_string(),
592 );
593 map.insert(
594 "1.3.6.1.4.1.311.10.3.10".to_string(),
595 "Qualified Subordination".to_string(),
596 );
597 map.insert(
598 "1.3.6.1.4.1.311.10.3.12".to_string(),
599 "Document Signing".to_string(),
600 );
601 map.insert(
602 "1.3.6.1.4.1.311.10.3.24".to_string(),
603 "Protected Process Verification".to_string(),
604 );
605 map.insert(
606 "1.3.6.1.4.1.311.80.1".to_string(),
607 "Document Encryption".to_string(),
608 );
609 map.insert(
610 "1.3.6.1.4.1.311.10.3.22".to_string(),
611 "Protected Process Light Verification".to_string(),
612 );
613 map.insert(
614 "1.3.6.1.4.1.311.21.19".to_string(),
615 "Directory Service Email Replication".to_string(),
616 );
617 map.insert(
618 "1.3.6.1.4.1.311.21.5".to_string(),
619 "Private Key Archival".to_string(),
620 );
621 map.insert(
622 "1.3.6.1.4.1.311.10.5.1".to_string(),
623 "Digital Rights".to_string(),
624 );
625 map.insert(
626 "1.3.6.1.4.1.311.10.3.27".to_string(),
627 "Preview Build Signing".to_string(),
628 );
629 map.insert(
630 "1.3.6.1.4.1.311.20.2.1".to_string(),
631 "Certificate Request Agent".to_string(),
632 );
633 map.insert(
634 "2.23.133.8.2".to_string(),
635 "Platform Certificate".to_string(),
636 );
637 map.insert(
638 "1.3.6.1.4.1.311.20.1".to_string(),
639 "CTL Usage".to_string(),
640 );
641 map.insert(
642 "1.3.6.1.5.5.7.3.9".to_string(),
643 "OCSP Signing".to_string(),
644 );
645 map.insert(
646 "1.3.6.1.5.5.7.3.3".to_string(),
647 "Code Signing".to_string(),
648 );
649 map.insert(
650 "1.3.6.1.4.1.311.10.3.1".to_string(),
651 "Microsoft Trust List Signing".to_string(),
652 );
653 map.insert(
654 "1.3.6.1.4.1.311.10.3.2".to_string(),
655 "Microsoft Time Stamping".to_string(),
656 );
657 map.insert(
658 "1.3.6.1.4.1.311.76.8.1".to_string(),
659 "Microsoft Publishe".to_string(),
660 );
661 map.insert(
662 "1.3.6.1.5.5.7.3.2".to_string(),
663 "Client Authentication".to_string(),
664 );
665 map.insert(
666 "1.3.6.1.5.2.3.4".to_string(),
667 "PKIINIT Client Authentication".to_string(),
668 );
669 map.insert(
670 "1.3.6.1.4.1.311.10.3.13".to_string(),
671 "Lifetime Signing".to_string(),
672 );
673 map.insert(
674 "2.5.29.37.0".to_string(),
675 "Any Purpose".to_string(),
676 );
677 map.insert(
678 "1.3.6.1.4.1.311.64.1.1".to_string(),
679 "Server Trust".to_string(),
680 );
681 map.insert(
682 "1.3.6.1.4.1.311.10.3.7".to_string(),
683 "OEM Windows System Component Verification".to_string(),
684 );
685 map
686 };
687}