Today I wanted to talk about something I touched upon recently, the bloat in size of a previous script I had been working on. I really love to have a small script that does exactly what it needs to do, and nothing more. I call them TinyTools.
I don’t really have a philosophy about what they should be, other than the above. If I were pushed, I would say that they had to use maybe 20 lines of code, max. They retain readability, and can be ported around very easily.
These are the kinds of tools that I like to write, and the kind I like to use more than anything.
I’m not saying that there is anything wrong with the opposite. Many of the tools that I use day in and day our are giant monoliths of software, that have taken thousands of hours of development time to come to fruition.
It really comes down to the old ‘hacking vs development’ debate.
I am still not a developer.
One of the tools I regularly run against my own site is WPScan, which is just absolutely fantastic. WordPress is the software used by the worlds websites. It is so popular that there is a tool specifically for identifying vulnerabilities in sites running it.
WordPress gets a bad rap too. WordPress sites get hacked all the time, and not really by way of fault in the core WordPress team. It’s the extensibility that opens it up to so many attacks.
If you have a default WordPress install, then there will be very few avenues of attack open to a malicious actor. The more themes and plugins that are added though, the more avenues of attack are created.
If there is an easily detectable or script-able attack discovered for a very popular theme, then many WordPress sites will be attacked. WPScan has many options, and is very powerful in it’s own right, but one of the really interesting parts of the tool, for me, is it’s ability to enumerate usernames.
I really wanted to know how it was doing that, and probably the easiest way to figure out how it does that is by reading the code. It’s written in Ruby, and I have no idea what I am doing there, so that option is out for me.
Next up would be to route everything it does through a proxy, and check all the requests it makes, but that option sounds way more boring, and I honestly only thought about it afterwards.
I decided to use the tools that I do know how to use, or at least I *thought* i knew how to use, in order to make a new TinyTool that I can use whenever I want to know the usernames for a WordPress site, which is far more often than you would imagine.
There is another reason that I wanted to make this tool. WPScan is great, and so long as you know what you are doing with Ruby, like bundle install and making sure you have the right Gems and such, you can just clone the git repo, and everything should just work fine.
I do not know what I am doing with Ruby. It took me around an hour of googling, apt-getting, gem updating and everything just to get it working in my environment. That is too much, so a small tool will suit us far better.
So after making sure that I had a working version of WPScan, then we need a test site to run it on. That means installing WordPress on an old VM in my lab. I chose the one I used for tracking the Mirai botnet, as it was the first in the list.
Setting up WordPress, which has a “Famous 5 minute install” was not as much of a pain as WPScan generally is if you do not know what you are doing, but it was certainly not 5 minutes. I think the only thing I spent 5 minutes on was installing dummy content. This is all for adding it to a server you control though. Adding it to a webhost is waaaay easier.
As I mentioned, I added some dummy content that was not in any way related to the site, such as users that have never posted content etc.
I also added a few posts to the site so that it looked at least somewhat acceptable.
So eventually I have my two virtual machines, they can even talk to each other and everything. Next up is Wireshark, which can capture every packet sent over an interface. Interface in this context means either the wifi connection, or over the network adapter at the back of your PC.
I have a virtual network adapter in place for when virtual machines need to either talk to each other or to the internet. We are going to monitor traffic over this interface and then run the WPScan tool against our local WordPress install and see what requests it makes.
The syntax for the WPScan request is “wpscan -u WordPress_Site_Address –enumerate u”
I came across some errors whilst running the WPScan tool, but eventually managed to get to the part where it enumerated usernames.
If we open up the packet capture, we will be able to see every single piece of communication between the server and the client. By right clicking on the packets, we can also select “Follow > TCP Stream”. This will show us a to-and-fro between the server and client on one particular conversation. If a file is being transmitted, this is an excellent way of retrieving it.
There is one super interesting request that is made in this stream, and I have outlined it in the screenshot.
Apparently there is some kind of “author” tag that you can specify. Perhaps this is where WPScan is getting that information about usernames. I tried a quick test, by submitting the following request.
I got redirected to this page
Trying it again, with other numbers led me to find more pages by more authors, even when they had not published anything. I was really hoping that the “root” at the end was the username of the author, but it turns out that it is just the first name.
So now we know how it’s done, or at least how we can discover if there are any posts by that person. Diving in further, I right-clicked to examine the source code further, and searched for the username, which I found.
Looking around at the other usernames that I knew existed, I could see that this element is always present and follows the format (author author-)(username)( author-)(username number).
That means that if we can ask the WordPress site for say authors in the range of 1-10, then it will send us a page each time, where the username of the author is listed, if they exist. We can use some regular expression magic to search the text it returns to us, and look for that pattern above.
Regular expressions are, in my opinion, the least regular of all expressions. Once you know how they work, then they become one of the most powerful things you will ever use, most especially when it comes to working with Linux based environments.
So our pseudo-code is going to look something like this.
- Generate the numbers 1-10 (for sake of example)
- Ask the website for the authors, numbered 1-10
- Examine the response to see if that pattern exists
- Where it does, print out the bit in the middle (the username)
Suprisingly this can all be achieved with 15 lines, and looks like this.
url = sys.argv
for i in range(1,10):
req = requests.get(url + "/?author=%d" % i)
m = re.search('(author author-).*(author-)',req.text)
Let’s give it a whirl against our test WordPress install and see what happens!
It has figured out all the usernames, and seems to be working well. I tried it out against a few other WordPress sites owned by friends, and they all reported the success of the tool, some more begrudgingly than others.
This should massively underscore the need for complex passwords when it comes to your sites, or any other service for that matter. Usernames can be enumerated in hundreds of different ways for hundreds of different services, so by having a complex password, you really reduce the ease of attack against something you probably rely heavily upon.
If you don’t have a password manager, then I would highly recommend that you get one, stat! 1Pass is excellent, and it is really good at removing the security friction experienced by users when trying to access stuff online (long complex passwords are boring to remember).
Anyway, I hope you all have an excellent week!