Waiting In Vain |
|
|
My latest posts can be found here: Previous blog posts:
Additionally, some earlier writings: |
The answer was always "Of course! Kill it!" but the problem then was that I never knew where it had got stuck, and what it thought it was doing. The problem was compounded by several factors:
The first thing to do was to identify the program, but that was easy. I wrote a web script which, when called, would run "top" and "ps" and provide the outputs. I set them up to be run every hour from my home machine, and thus I could see for myself when a script went 100% CPU. Then I waited. Finally I captured the output, and found that it was one of my wiki edit scripts. OK, perhaps not surprising, especially since it was trying to edit a non-existent page. But clearly someone was trying to hack into a non-existent account, and somehow it was provoking the script into behaviour I hadn't anticipated.
But now we know which binary to instrument. I insert some debugging and logging, then left it to run. It took 24 hours, but it went rogue again, and I had some information. Problem was, it was hanging somewhere where there were apparently no loops.
:def get_post_data(): : : try: data_len = int(os.environ['CONTENT_LENGTH']) : except: data_len = 0 : : data = '' : while len(data) < data_len: : data += stdin.read(data_len-len(data)) : : return data So we ask the environment how much data there is to read, and then repeatedly ask to read data until we have how much there was promised to us. The problem is, as I found, sometimes we are told that there is a non-zero amount to be read, but when you try to read it, there is nothing there. More details are available on request, but that's the nub of it.
:def get_post_data(): : : try: data_len = int(os.environ['CONTENT_LENGTH']) : except: data_len = 0 : : data = '' : while len(data) < data_len: : new_data = '' : for n in [1,2,3]: : new_data = stdin.read(data_len-len(data)) : if new_data != '': break : if new_data == '': break : data = data + new_data : : if data_len > 0: : : write_log( 'Data: len=%d, read=%d\n' % (data_len,len(data)) ) : if len(data) > 0: : write_log( 'Data: "%s"\n' % `data` ) More details on the attack
|
: pwd : wp-submit : log |
So what's happening? The nefarious actor's script is trying to login, and so is invoking a URL that, to them, looks like a WordPress login page. In this case they are trying to access:
But that page doesn't exist, so the "edit" script is invoked.
It's passes what the nefarious actor thinks are the necessary parameters for logging on to a WordPress site, but they don't know the username or passord to use. And that's where the "dictionary attack" part comes into it. They just try lots of things.
|
|
|
Here's an actual attempt from the log file:
: ===================== : Data: len=62, read=62 : Data: "'pwd=WEBSITE.org.uk1&wp-submit=Log%2BIn&log=WEBSITE.org'" : Data: len=62, read=0 : =====================
As you can see, the passwords being tried are simply variants on the website name.
And this is common:
a password choose a simple variant of the site's name. |
You can see why. If you have dozens of passwords to remember, you need a scheme to help you, and what better than simply taking the site's name and warping it somehow.
But hackers know that, and they've collected hundreds of rules to take site names, people's names, words from the dictionary, and warp them to create possible passwords, and here is the evidence that they do this on a grand scale. This site wasn't attacked because it was valuable, or prominent.
It was attacked because it was on the web.
One is that we can't trust promises from the system It might tell you that there's data to read, and then not actually have any data for you. In fact, the real lesson here might be not to read from the system directly in this context, but instead to use the excellent libraries provided that bundle up the data and give it to you in a suitable format. That may be true, but there is more background to this code than I've explained here, and I'll let that slide.
But the main lesson is that you really, really need to have strong passwords everywhere.
[0] https://www.xencentrichosting.uk/
Non Repeating Decimals | : | Impossible To Translate ... |
You can follow me on Mathstodon.
|
Quotation from Tim Berners-Lee |