From cc2d02cfe51d68dde4aaf92e1f236fb5980ca7c0 Mon Sep 17 00:00:00 2001 From: Roman Babenko Date: Mon, 16 Oct 2023 13:51:11 +0300 Subject: [PATCH] JKS and PKCS12 storages with default passwords --- credsweeper/deep_scanner/deep_scanner.py | 8 +++ credsweeper/deep_scanner/jks_scanner.py | 38 +++++++++++ credsweeper/deep_scanner/pkcs12_scanner.py | 44 +++++++++++++ credsweeper/utils/util.py | 33 ++++++++++ requirements.txt | 4 ++ setup.py | 2 + tests/__init__.py | 6 +- tests/data/depth_3.json | 72 +++++++++++++++++++++ tests/data/doc.json | 72 +++++++++++++++++++++ tests/samples/changeit_crt.jks | Bin 0 -> 1463 bytes tests/samples/changeit_crt.pkcs12 | Bin 0 -> 1782 bytes tests/samples/changeme_key.jks | Bin 0 -> 1379 bytes tests/samples/dummy.jks | Bin 11 -> 1378 bytes tests/test_main.py | 2 +- tests/utils/test_util.py | 44 +++++++++++++ 15 files changed, 321 insertions(+), 4 deletions(-) create mode 100644 credsweeper/deep_scanner/jks_scanner.py create mode 100644 credsweeper/deep_scanner/pkcs12_scanner.py create mode 100644 tests/samples/changeit_crt.jks create mode 100644 tests/samples/changeit_crt.pkcs12 create mode 100644 tests/samples/changeme_key.jks diff --git a/credsweeper/deep_scanner/deep_scanner.py b/credsweeper/deep_scanner/deep_scanner.py index e5db0bd76..1cb40883a 100644 --- a/credsweeper/deep_scanner/deep_scanner.py +++ b/credsweeper/deep_scanner/deep_scanner.py @@ -19,8 +19,10 @@ from .encoder_scanner import EncoderScanner from .gzip_scanner import GzipScanner from .html_scanner import HtmlScanner +from .jks_scanner import JksScanner from .lang_scanner import LangScanner from .pdf_scanner import PdfScanner +from .pkcs12_scanner import Pkcs12Scanner from .tar_scanner import TarScanner from .xml_scanner import XmlScanner from .zip_scanner import ZipScanner @@ -37,8 +39,10 @@ class DeepScanner( EncoderScanner, # GzipScanner, # HtmlScanner, # + JksScanner, # LangScanner, # PdfScanner, # + Pkcs12Scanner, # TarScanner, # XmlScanner, # ZipScanner @@ -79,6 +83,10 @@ def get_deep_scanners(data: bytes) -> List[Any]: deep_scanners.append(GzipScanner) elif Util.is_pdf(data): deep_scanners.append(PdfScanner) + elif Util.is_jks(data): + deep_scanners.append(JksScanner) + elif Util.is_asn1(data): + deep_scanners.append(Pkcs12Scanner) else: deep_scanners = [ByteScanner, EncoderScanner, HtmlScanner, XmlScanner, LangScanner] return deep_scanners diff --git a/credsweeper/deep_scanner/jks_scanner.py b/credsweeper/deep_scanner/jks_scanner.py new file mode 100644 index 000000000..9e3852893 --- /dev/null +++ b/credsweeper/deep_scanner/jks_scanner.py @@ -0,0 +1,38 @@ +import logging +from abc import ABC +from typing import List + +import jks + +from credsweeper.credentials import Candidate +from credsweeper.deep_scanner.abstract_scanner import AbstractScanner +from credsweeper.file_handler.data_content_provider import DataContentProvider + +logger = logging.getLogger(__name__) + + +class JksScanner(AbstractScanner, ABC): + """Implements jks scanning""" + + def data_scan( + self, # + data_provider: DataContentProvider, # + depth: int, # + recursive_limit_size: int) -> List[Candidate]: + """Tries to scan JKS to open with standard password""" + candidates = [] + for pw_probe in ["", "changeit", "changeme"]: + try: + keystore = jks.KeyStore.loads(data_provider.data, pw_probe, try_decrypt_keys=True) + if keystore.private_keys or keystore.secret_keys: + candidate = Candidate.get_dummy_candidate(self.config, data_provider.file_path, + data_provider.file_type, + f"{data_provider.info}:'{pw_probe}' - has keys") + else: + candidate = Candidate.get_dummy_candidate(self.config, data_provider.file_path, + data_provider.file_type, + f"{data_provider.info}:'{pw_probe}' - default password") + candidates.append(candidate) + except Exception as jks_exc: + logger.debug(f"{data_provider.file_path}:{pw_probe}:{jks_exc}") + return candidates diff --git a/credsweeper/deep_scanner/pkcs12_scanner.py b/credsweeper/deep_scanner/pkcs12_scanner.py new file mode 100644 index 000000000..b4f94088c --- /dev/null +++ b/credsweeper/deep_scanner/pkcs12_scanner.py @@ -0,0 +1,44 @@ +import logging +from abc import ABC +from typing import List + +import cryptography.hazmat.primitives.serialization.pkcs12 + +from credsweeper.credentials import Candidate +from credsweeper.deep_scanner.abstract_scanner import AbstractScanner +from credsweeper.file_handler.data_content_provider import DataContentProvider + +logger = logging.getLogger(__name__) + + +class Pkcs12Scanner(AbstractScanner, ABC): + """Implements jks scanning""" + + def data_scan( + self, # + data_provider: DataContentProvider, # + depth: int, # + recursive_limit_size: int) -> List[Candidate]: + """Tries to scan JKS to open with standard password""" + candidates = [] + for pw_probe in [b"", b"changeit", b"changeme"]: + try: + (private_key, certificate, additional_certificates) \ + = cryptography.hazmat.primitives.serialization.pkcs12.load_key_and_certificates(data_provider.data, + pw_probe) + if private_key: + candidate = Candidate.get_dummy_candidate( + self.config, # + data_provider.file_path, # + data_provider.file_type, # + f"{data_provider.info}:'{pw_probe.decode()}' - has keys PKCS12") + else: + candidate = Candidate.get_dummy_candidate( + self.config, # + data_provider.file_path, # + data_provider.file_type, # + f"{data_provider.info}:'{pw_probe.decode()}' - default password PKCS12") + candidates.append(candidate) + except Exception as pkcs_exc: + logger.debug(f"{data_provider.file_path}:{pw_probe.decode()}:{pkcs_exc}") + return candidates diff --git a/credsweeper/utils/util.py b/credsweeper/utils/util.py index e512911b0..20d3fc760 100644 --- a/credsweeper/utils/util.py +++ b/credsweeper/utils/util.py @@ -3,6 +3,7 @@ import logging import math import os +import struct import tarfile from dataclasses import dataclass from pathlib import Path @@ -392,6 +393,38 @@ def is_pdf(data: bytes) -> bool: return True return False + @staticmethod + def is_jks(data: bytes) -> bool: + """According https://en.wikipedia.org/wiki/List_of_file_signatures - jks""" + if isinstance(data, bytes) and 4 <= len(data): + if data.startswith(b"\xFE\xED\xFE\xED"): + return True + return False + + @staticmethod + def is_asn1(data: bytes) -> bool: + """Only sequence type 0x30 and size correctness is checked""" + data_length = len(data) + if isinstance(data, bytes) and 4 <= data_length: + # sequence + if 0x30 == data[0]: + # https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/basic-encoding-rules.html#Lengths + length = data[1] + byte_len = (0x7F & length) + if 0x80 == length and data.endswith(b"\x00\x00"): + return True + elif 0x80 < length and byte_len < data_length: # additional check + len_bytes = data[2:2 + byte_len] + try: + long_size = struct.unpack(">h", len_bytes) + except struct.error: + long_size = (-1,) # yapf: disable + length = long_size[0] + else: + byte_len = 0 + return data_length == length + 2 + byte_len + return False + @staticmethod def is_elf(data: Union[bytes, bytearray]) -> bool: """According to https://en.wikipedia.org/wiki/Executable_and_Linkable_Format use only 5 bytes""" diff --git a/requirements.txt b/requirements.txt index cda32a15e..193d70eb4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ # Common requirements beautifulsoup4==4.12.2 +cryptography==41.0.4 GitPython==3.1.37 google-auth-oauthlib==1.1.0 humanfriendly==10.0 @@ -16,6 +17,7 @@ whatthepatch==1.0.5 pdfminer.six==20221105 password-strength==0.0.3.post2 python-dateutil==2.8.2 +pyjks==20.0.0 # ML requirements numpy==1.24.4 @@ -45,6 +47,8 @@ types-PyYAML types-requests types-oauthlib types-python-dateutil +types-pyjks types-regex types-humanfriendly yapf + diff --git a/setup.py b/setup.py index 0353ce5e6..10a7bf307 100644 --- a/setup.py +++ b/setup.py @@ -5,6 +5,7 @@ install_requires = [ "beautifulsoup4>=4.11.0", # the lowest version with XMLParsedAsHTMLWarning + "cryptography", # "GitPython", # "google_auth_oauthlib", # "humanfriendly", # @@ -24,6 +25,7 @@ "scikit-learn", # "onnxruntime", # "python-dateutil", # + "pyjks", # ] setuptools.setup( diff --git a/tests/__init__.py b/tests/__init__.py index 7687efa34..e31377623 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,7 +1,7 @@ from pathlib import Path # total number of files in test samples -SAMPLES_FILES_COUNT: int = 114 +SAMPLES_FILES_COUNT: int = 117 # credentials count after scan SAMPLES_CRED_COUNT: int = 129 @@ -11,10 +11,10 @@ SAMPLES_POST_CRED_COUNT: int = 122 # with option --doc -SAMPLES_IN_DOC = 80 +SAMPLES_IN_DOC = 83 # archived credentials that are not found without --depth -SAMPLES_IN_DEEP_1 = SAMPLES_POST_CRED_COUNT + 16 +SAMPLES_IN_DEEP_1 = SAMPLES_POST_CRED_COUNT + 19 SAMPLES_IN_DEEP_2 = SAMPLES_IN_DEEP_1 + 16 SAMPLES_IN_DEEP_3 = SAMPLES_IN_DEEP_2 + 3 diff --git a/tests/data/depth_3.json b/tests/data/depth_3.json index fa3683c20..3f04f682b 100644 --- a/tests/data/depth_3.json +++ b/tests/data/depth_3.json @@ -557,6 +557,78 @@ } ] }, + { + "api_validation": "NOT_AVAILABLE", + "ml_validation": "NOT_AVAILABLE", + "ml_probability": null, + "rule": "Dummy candidate", + "severity": "info", + "line_data_list": [ + { + "line": "dummy line", + "line_num": 0, + "path": "tests/samples/changeit_crt.jks", + "info": "tests/samples/changeit_crt.jks:'changeit' - default password", + "value": null, + "value_start": -2, + "value_end": -2, + "variable": null, + "entropy_validation": { + "iterator": null, + "entropy": null, + "valid": null + } + } + ] + }, + { + "api_validation": "NOT_AVAILABLE", + "ml_validation": "NOT_AVAILABLE", + "ml_probability": null, + "rule": "Dummy candidate", + "severity": "info", + "line_data_list": [ + { + "line": "dummy line", + "line_num": 0, + "path": "tests/samples/changeit_crt.pkcs12", + "info": "tests/samples/changeit_crt.pkcs12:'changeit' - default password PKCS12", + "value": null, + "value_start": -2, + "value_end": -2, + "variable": null, + "entropy_validation": { + "iterator": null, + "entropy": null, + "valid": null + } + } + ] + }, + { + "api_validation": "NOT_AVAILABLE", + "ml_validation": "NOT_AVAILABLE", + "ml_probability": null, + "rule": "Dummy candidate", + "severity": "info", + "line_data_list": [ + { + "line": "dummy line", + "line_num": 0, + "path": "tests/samples/changeme_key.jks", + "info": "tests/samples/changeme_key.jks:'changeme' - has keys", + "value": null, + "value_start": -2, + "value_end": -2, + "variable": null, + "entropy_validation": { + "iterator": null, + "entropy": null, + "valid": null + } + } + ] + }, { "api_validation": "NOT_AVAILABLE", "ml_validation": "VALIDATED_KEY", diff --git a/tests/data/doc.json b/tests/data/doc.json index 579d4c1e4..e618a5d98 100644 --- a/tests/data/doc.json +++ b/tests/data/doc.json @@ -437,6 +437,78 @@ } ] }, + { + "api_validation": "NOT_AVAILABLE", + "ml_validation": "NOT_AVAILABLE", + "ml_probability": null, + "rule": "Dummy candidate", + "severity": "info", + "line_data_list": [ + { + "line": "dummy line", + "line_num": 0, + "path": "tests/samples/changeit_crt.jks", + "info": "tests/samples/changeit_crt.jks:'changeit' - default password", + "value": null, + "value_start": -2, + "value_end": -2, + "variable": null, + "entropy_validation": { + "iterator": null, + "entropy": null, + "valid": null + } + } + ] + }, + { + "api_validation": "NOT_AVAILABLE", + "ml_validation": "NOT_AVAILABLE", + "ml_probability": null, + "rule": "Dummy candidate", + "severity": "info", + "line_data_list": [ + { + "line": "dummy line", + "line_num": 0, + "path": "tests/samples/changeit_crt.pkcs12", + "info": "tests/samples/changeit_crt.pkcs12:'changeit' - default password PKCS12", + "value": null, + "value_start": -2, + "value_end": -2, + "variable": null, + "entropy_validation": { + "iterator": null, + "entropy": null, + "valid": null + } + } + ] + }, + { + "api_validation": "NOT_AVAILABLE", + "ml_validation": "NOT_AVAILABLE", + "ml_probability": null, + "rule": "Dummy candidate", + "severity": "info", + "line_data_list": [ + { + "line": "dummy line", + "line_num": 0, + "path": "tests/samples/changeme_key.jks", + "info": "tests/samples/changeme_key.jks:'changeme' - has keys", + "value": null, + "value_start": -2, + "value_end": -2, + "variable": null, + "entropy_validation": { + "iterator": null, + "entropy": null, + "valid": null + } + } + ] + }, { "api_validation": "NOT_AVAILABLE", "ml_validation": "NOT_AVAILABLE", diff --git a/tests/samples/changeit_crt.jks b/tests/samples/changeit_crt.jks new file mode 100644 index 0000000000000000000000000000000000000000..be4d66ed3004bffc1dfe1949bae3d04b59b7198a GIT binary patch literal 1463 zcmb`G`8U)H7{+Hc_BBSy9osdQ;yY*TBWu~qG6_*)nu_MmFpHWnX>up~=oVq3Y`5u# zlU)>X%2Hww*%{d-sc>&o=5l}P54bQuC{35`H;_pKtUtTNNc zw(|k^FK;p0incc*$(tZ=gR#jA9Ma)ib(Mr4dz3G>p!%0FJZ)AV*0#}YV}dzV-5^$8 z*Us~7P2ogGc$_;&;<9X`TFMP|B)-f(pHHZm@#NO$vTj4~4Y=Nk%XQPmFIrW2OH;0! z^tlJ5CD7|eO$AozvCt@O4aR4{_8YfiVwCV`Ma{b{L&=lXE3+uBy=3yWD%NA#OZivX zsC1~|eIZ`&gUZOqy)BB>9%=T;#bLgaWj7GFzY?N9n9NXubFK-KL(G_@m^EBxICFli zB+pd;r9e?AKRKe9p(d)|;%{}#K@d4y3(2g78Ov-r3r2xRo?5BNdkX!>9X@<*0$yV@ z(c%7@it@ri?N-H9(U3b6WXQXD^XmEgO5vf=*w^ze*iSektK-XcuHRp}(Qm zrS#xrv6lnNr7*YlfsHSjgDZ%qK2U~V4qCPIy{sw&<)#Zv;Z=6A9{W9MaOLmq%hNt8 zan85s)vxFa87Q!%0C*c5ZBc`0Yz2T2w|X`%=g;^vDMiJG?C!>A*I^n(*P)JuL-2Kt zwz^OJI1bK*?`D)V9+MZ-f{H9Xw3oYL_2ukjr?H&0fp}|dM%C%9jsSg1$lO+6h)OCy zHb0VT(>{UrC5xY)-M~6~L!e*~xY!AB0OWV_s;K}5i(#;xc1QpUyR5RyZ~(d^fab0t z4^xBfVb%oA$JWiwf@ukoNuB!wH0{LH?+~hfk~cJ_6aw;e8QWXhX@e zFh)oU`ET}Igz4bs3C|}DG{v9+?K`XmuV_(K|Cw@YzRWUG`^4|-KJq~;J<~x;ja{m1 zoP2I#!shJK&CGEmFI?lur*m2Tag?@Y+#0I)^-u+R{o&)ziXZW;yl*9M)ep$wi4WjaXEIxit^XPAbg_Rvnlz9iVc}THAJtBP}9hW^>2b45&pssc vmXOXZBAh3kw?s-uf;*o8AU{zATb0~+D?%@UD^AIAI(n;vkP literal 0 HcmV?d00001 diff --git a/tests/samples/changeit_crt.pkcs12 b/tests/samples/changeit_crt.pkcs12 new file mode 100644 index 0000000000000000000000000000000000000000..9790e0d4e0afc18a9a98382ee9a5985e4514e422 GIT binary patch literal 1782 zcmV7Duzgg_YDCD0ic2gjRb-Qi72`Yw2hW8Bt2LUi<1_>&LNQU+thDZTr0|Wso1P}~>7>JLV(-q)9iMj+gU|oQM1@Pz*5LH4K{h3E~e4^*o-!}n` z^+c30k^F?hnUWbiYOHBy?zOroEZQ`QK(hEF$~nZw1mGQ2)8DdWOMU*oCZYVb zjk7S9KRgQ3cE)706qvtVuu$$RB?LpSgZ%2^fB#BvWE^s+kSahm)d%lFk zVQ1%^b^dvcKcBBkk~#HTkw7Xr3Y&6%KP`4x?!Utjil^Dt{7InKDY_eEyTg47ML$j( z#>LH0Cm)!$p{Yc&+_`EJsxD4Tb~E)4d1nlYJ}CugRw6tX#KteqZ^rNreia1z4p;^h z1~~nNH(+lL&Ty@f0V5{}xeD4;07CCzBnOP=9JteIStxMzY4;Mzhem$32vq^@J0i;l z5A@aVyuZrXKFz-N`*TT&BA!3D2D3eY&JYM>JDXWSx=o>X#r7(Mv-QyrgB4#Qo(98b zAcWzpDa>UA!cU4)Wo-1#mwiaIscdI1641ML*402*sO6D^GfLs2mOrtD=5*^CW0y~S zn#z5ws@|~@7D4>jG71apCu3oisKbI8>bgw#BaT2il|pzYE`qyt7gZH$8_PqU6Wi5 z&%Tr9VTDkf&TK`}H+RNjZ;G79!s}lVaK8g|d+gn60>1(y$&VgdIa+(L$OT3UhDp+- zM+KOk>~DKWQ-C$O5h;XB>pjzPw`27{2hb;B0C=lM>(4R-yPemNnc{m%a2(=cqXW}17dNlnByQk^H z|055$gTk^4+4cpUtjS-2V_8FS{S#+3SqeS}vl6msssA^L>huaELSFe~|zc z&<3AXPuWtT1TPPf3Qr~5&ct*BArZtaN|6! zjiP@kIV&`K?}1}m3$|Y)21V9SQWS4O&qoS1I3s5{)%ZMALWlXto+xW{!{X(V4a@vq@ttV#T^WoI@Zk# z+I()K&RZ0Z;a7;pXgzqH(jNrfa523soJJ;{*1WBH#5!wa$T+Sgxh1xL>!S5y-ihp4 z+X!&{PfuRl3Q^BAh}nuLXoBOr!YeNCQ@)JAfln<|@x($_>v0OBO3}A?q~bx-{|(1B zCSsoEqO@!L&#JXO=d=OnC>Z;Xx}T?{VN{|wc-RXj^4g3wxxf?P(XU%P;xxsIZW%rc z!#X8+n9npd#ys>!v8E#E<0gNiJFl4dD4Gv+hPM2X#MKEQ1O4&stS?ZLun@)1Wo5Vw zr#9T4Z!+q=eBMrv@k{!>;<5rI^WA!~ljfo;k8)J5sm31y#`IUtq7ntMc$`2nF9DZ% zRWs%ArW*QsfR6d^w=9X$9}ojXR@R z5=y=Q?Vt=+hhubvnNc~{=)j(NvZNYg%urDYN(+h8UNC9O71OfpC00bZa%-pf_YOxwef*&m436HL0G0IsiKskir+Xbz{+OVz!6d7+1 Y$_azrhpr2p`e#<)A^5gy0s;aj5c79DRsaA1 literal 0 HcmV?d00001 diff --git a/tests/samples/changeme_key.jks b/tests/samples/changeme_key.jks new file mode 100644 index 0000000000000000000000000000000000000000..ce34433259eecf595b8550c973b4b6453d2e3e97 GIT binary patch literal 1379 zcmezO_TO6u1_mY|W&~rl;>6s7oKzsUTUnm#I#6ntK@-z913oq`Z8k<0MlB{mMn+Z! zmL{e}4aXk1jmk^ro%Zd%j9F&-3>Ya z7H{G{t2|4LO>X06+rQJY)tS#Z-3r@K_QFY5=-jS_?ZJs(U(O3Oe|TN_*#m|Dkq7pt zU47;LSkcBwxGK)m-sg_+$xHE`KF_bMe6#b&117FI@wY`OD@5!z)Ro(NTQnWY$atZ7 z>d-=QqyJ7DFKu$T)b}FV#!audYj(dgr<4NA(fxrAQS+;$GG@tN=w1@bX{#>LYqxsS z{MEl^N-n#!`%k9P&u;e%e#^wo z+Tu-_Grwx;)Xv`VcotjjVbip&h6`dRyEi;s@GWSk+`)~{cPu%zZ`UpD6HJyq9X~T? zHFdimtnT~za)ATa(d*OxP1uqvd%kW_-r4!Tj)v=Rv~OA-`YgwfS>EvD9{u3yw;N7e zTO{&Wx}Uu_$WQUgGl4d1oo6o=duQKwJ1)=RuT|~2YwF}D7rWW^h5luiVJQ8z_ayty zjQNR6of$b_HmleDo_#T5*5Uab4^M9Ae#ZBma7o0mBCg{OAZ`tQp%ZD#j*FzvZizHV;QF6$EQ*l0}w z0hj3;45t?FnaQxtc~$AYJEF{{7cVV5`l4&z!gbo!o0o6pGm_g7#`$r9wPJ5Lo3H@O z(s0o$?h9>_r1xKqTeoiN=0t^kDKTf3E;iC|S#s#oZ1zQb(V83DE52J~9ZQ!IUE`4{ z68MOvLbb6tUpiN~WzHp&il7JUcZ7eH4WLJM1y|U-9eO%>~c* z@`O!!b#%U|>^(api{0l%_F6BTbF({c%{I$F?W~qjFFpx8U;En}oT6DH^h^ybfeASY zn2_TPni!8SU}j=uVq#HZe)-CPmyJ`a&71Ljyx214{!#Q;R4Gej_6TV*_JDOQ--n9ML!*+2_Cv z&D_|_V9?mf)Y!Jfzx@jcFPsV5>p=>?{T+!`0Lwdxu;DHTyOJl9n5-> zT67~bE&W*U?Z6H9)SE7C32;nS-?;tG^+(0kQ!+0c7T!?M&}ysgz4j;*Gb01zVnqXa z16g3;$?~y?v52fan6G6bFy+}_Nn1N0=Zrt|cf~WRssft^! zWm}$oJIZJ~d9vo=3rACq%E&7PMkjjC-(zJlRc5B@uj}&`AHEg#tNHM*XV2eUNz&s! zCeQG8$0wJCTCc9$-C46$Wvf?tr%+t{%G;~sZGz?&l+MdC|86>cKj+e2TXI#WJk{Uu uWl~e=!>unQ+WLOJjGnrBb76q+yQRPW-dulupU|rC+gw#``MkTG-U0vx3^z>x literal 0 HcmV?d00001 diff --git a/tests/samples/dummy.jks b/tests/samples/dummy.jks index 16905b157539d3ef30654ef42cfb4dd00291d492..eb58f4761a136cebfafd421f22b4a514a8cabe5b 100644 GIT binary patch literal 1378 zcmezO_TO6u1_mY|W&~rl;>6s7oKzsUTUq+!KA_Z2gC?e}27GK>+H8z0j9N^BjEt-d zEKN)cr`|ug;_HlJO>3RFO&+ppozkY;S|#-KAFVy`{s7PS%QyT~nF^|#wiNdrJ$Uoa zA}@VGF2?m$Yq>ZQq8?nGQ2Fqr*6+gwnrmz0*KKuHTK$^KrTt0XQu{ovE{O%-?)NEN z+xq4~OlI8Aqe8(ye*d_h>vVi-`lN5V&Ms5W?p<2G!8?NedHX-BCASWSoH%;O>*TDM z0x4Ur>v`5S2M%SNI+guTUuE)!^yl~9=NFwQ@^x!nTy$)@8{0P#>zW5i5(0(}7yC~C zEjHS}ZkCH_&96mg3k}6hgT-Wiw3itNsO_1#H}cERH?ddW`E>*&-I-Nm@v8%Gj z2R)8mvhwpkBvnht*}f{s^Ar1j^M>iYU*^vbzKoimzkaEO=#K+K@2Omsk40ns{yltZ!N_S9`jLCz?22lQj(co8Q~2ggEuDYA zy>s>d%^RbbBi#Yg+boklEe&;7Hr%c7_=d*TC!d5=ulc6;@SeT< zc=IU}b#1;=jVfl>eX^^TZkg)-fl1*`x3sycrb@HP+AUdr$0Llj!oIGSbQfO5Y*)A} zem%GUJezZz&8%NP_XHo8dB5su%6@(CF7~kH@+zC9x8zG_U%j|)cR$iIm^OwwdHhEg{l_Rwe%JPjTZ*kiu@sRb`#Wyd-z3<(a8aKnAJ~oj>AiEmIsWfEZEw2v1poB^B^LyI|827|`u}+R@ zw_mT&YN^l4C%B)TkX8!KnHm$YqiUbB)EVK1dDG+~MEUB9jGZ~a37R!R&(y#Yn2wWx z={U}yiShUXW+p}^CYG4jdn*li**LY@JlekVGBR?rG8iNpavN~6F^96S2{Tnx81fo$ zgE$<*EJ=xZ*@k=uJRmN+Fl%aJQAq}j&n3)SnwME(XvhyV4k*tp%$A>)mYJMtC}bc2 z5?~hQ%*jtq%*n_vE-_FL=QT1mG%z$WurReSHjR?tH!?CXHZV4{gbL8Z5smYaeGbge z%#FPa292Fejg1VauUyIB7NsfmME>`qFPxoUw|P2!TI|!Fwr)$Zj9A5^=%a-WCeJ*( z9PhID+h;#m`ZKEXr$$!vK4y{0D-VcDI{O!^-dis;h4X!>JFk4ec_wqU;B(SHeciuY zUpF-*^*Yb7mfCk;KX@cB+I#Y^+2OZJ7khR#$sXi7{(ROc3Ay=JLZwX1j0}v66%FJK zWPyPv%f}+dBH~|`@m^f*>b|8Pj&vRjS6F=P^y)rj9{}Ty8R+!1Lw6XzT$-)@B4zh# zZjER|*GapbSQZrD(!Q*JquoaTf7YCYl None: content_provider: FilesProvider = TextProvider([SAMPLES_PATH]) cred_sweeper = CredSweeper(find_by_ext=True) cred_sweeper.run(content_provider=content_provider) - self.assertEqual(SAMPLES_POST_CRED_COUNT + 1, len(cred_sweeper.credential_manager.get_credentials())) + self.assertEqual(SAMPLES_POST_CRED_COUNT + 3, len(cred_sweeper.credential_manager.get_credentials())) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # diff --git a/tests/utils/test_util.py b/tests/utils/test_util.py index f31b94d2a..80e0c4f70 100644 --- a/tests/utils/test_util.py +++ b/tests/utils/test_util.py @@ -16,6 +16,50 @@ class TestUtils(unittest.TestCase): + def test_asn1_p(self): + based_data = """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 +C5z6Z1bgIfi2awICAicQ""" + data = base64.b64decode(based_data) + self.assertTrue(Util.is_asn1(data)) + + def test_asn1_n(self): + based_data = """MIIG8gIBAzCCBpwGCSqGSIb3DQEHAaCCBo0EggaJMIIGhTCCBoEGCSqGSIb3DQEHBqCCBnIwggZu +AgEAMIIGZwYJKoZIhvcNAQcBMGYGCSqGSIb3DQEFDTBZMDgGCSqGSIb3DQEFDDArBBSQgogxffCn +2ow1ucAT4NGvWzziNMWKbhk+C8M6JXiYzzQ1xjz0RrGmIujjJn+iO6+Y+CiaD3SGtvyRxNUJIQP9 +C5z6Z1bgIfi2awICAicQ""" + data = base64.b64decode(based_data) + self.assertFalse(Util.is_asn1(data)) + def test_get_extension_n(self): self.assertEqual("", Util.get_extension(None)) self.assertEqual("", Util.get_extension("/"))