PDA

View Full Version : What is this spam? WordPress SQL in the comments.


turtle
2008-06-13, 08:24
http://1veryhappyfamily.com/an/wpspam.png

I don't allow commenting on this particular WP install. It's really only there to run a podcast. So I got these two messages waiting to be moderated. The name line is what strikes me as really odd. Was this a hack attempt? I don't know enough about coding to know what was being attempted, but it obviously want to say they loved the podcast!

Any insight would be great. :)

Banana
2008-06-13, 08:29
He was trying a SQL injection attack. I know nothing about WP, but there are some stuff out there that's stupidly designed where you can pass a SQL statement and it will be parsed as another SQL statement on top of whatever it is normally used for.

Brad
2008-06-13, 08:31
That's a SQL injection attempt. Someone is hoping that you (or your software) are not properly escaping strings or that you aren't using prepared statements when querying the database.

http://imgs.xkcd.com/comics/exploits_of_a_mom.png

turtle
2008-06-13, 15:16
Thanks guys. (Love the comic Brad)

So what would this person be attempting to do? Just crash my DB? If they had gained access, what would this really give them?

Brad
2008-06-14, 12:45
Without knowing more about WordPress' database schema it's hard to tell. It looks like he's trying to insert a custom user in the first "Name:" field, possibly an admin account, and then trying to get information about admin access in the second "Name:" field.

Banana
2008-06-14, 13:27
I didn't exactly understand it myself, but am I mistaken in thinking that it was crappily written SQL, especially the second one?

1) He tried to do a UNION, which usually requires that we have same numbers of column, which he has no idea, no?

2) "SELECT 1 FROM wp_users" is a odd construction, and IINM, would return "1" or nothing at all if there weren't any fields with name "1" (and why the heck would it be named "1")?

3) It looks as if he was trying to get the password for admin, but had to do some reverse, padding and other juggling all at once. ( I do know for a fact that if you have a Microsoft Word document that's locked with a password, you can just save it as XML, get something like password="XXX", then you reverse the XXX then using the hex editor, delete the reversed string to effectively unlock it- something to do with endianness, I guess.)

chucker
2008-06-14, 13:43
1) He tried to do a UNION, which usually requires that we have same numbers of column, which he has no idea, no?

Correct.

2) "SELECT 1 FROM wp_users" is a odd construction, and IINM, would return "1" or nothing at all if there weren't any fields with name "1" (and why the heck would it be named "1")?

SELECT 1 FROM wp_users will return 1 the number of times wp_users has rows that match the following WHERE clause.

Banana
2008-06-14, 13:44
Is that for a different SQL dialect? I only do that with either TOP for T-SQL or LIMIT for MySQL.

chucker
2008-06-14, 13:50
Is that for a different SQL dialect? I only do that with either TOP for T-SQL or LIMIT for MySQL.

That's for T-SQL. I don't have a MySQL handy* to check if it applies there, too, but I would assume as much.

And TOP and LIMIT are actually not the same. Those give you a specific amount of rows; "SELECT 1" gives you a specific content within the rows; the amount of rows depends on the table's existing data.

*) Okay, okay: I'm just too lazy.

Banana
2008-06-14, 13:57
Hmm. Interesting- I don't think I ever saw that kind of statement before. A quick check in MySQL's manual, it's not used in same sense you just described;

SELECT 1 FROM foo; =
foo
1 'Literal value; returns same value for every row

Nonetheless, glad I learned something new. :)

Brad
2008-06-14, 14:14
Another way the "SELECT 1" construct is handy is in conjunction with an EXISTS and a subquery.

Such as:

SELECT name
FROM users
WHERE EXISTS (SELECT 1 FROM posts WHERE users.user_id = posts.user_id AND posts.rating = 5);

If there are many rows in posts with a rating of 5 and the user_id, the final result will still only have one row for that user_id. This isn't a great example because the query is so simple and there are several other ways to get this result, but this trick comes in handy when you have much larger sets of data and tables to work with.

It looks as if he was trying to get the password for admin, but had to do some reverse, padding and other juggling all at once.
Do keep in mind that it's very likely this user is simply a bot or a script kiddie targeting a specific, known vulnerability in WordPress and that this is a trick that actually works on vulnerable systems.

Banana
2008-06-14, 14:29
Brad, thanks for that li'l example. When I have a chance, I'll try and play with that. May end up useful in future.

Banana
2008-06-14, 14:44
Okay, I'm now quite curious.

Apparently, Wordpress is powered by MySQL, but as I posted above, SELECT 1 construction doesn't work; it will return all rows, displaying same value '1' for each row. I wonder if this could actually be a stored procedure or something like that?

EDIT: I think I'm just slow. It looks like SELECT 1 is supposed to replace SELECT * to provide better performance when we need to know how many rows or something else that doesn't really depend on actual data in table, which was why Brad used an subquery example, right?

And Turtle, just so you know...
BlogSecurity currently maintains a list of WordPress vulnerabilities.[8]
In January 2007, many high-profile Search engine optimization (SEO) blogs, as well as many low-profile commercial blogs featuring Adsense, were targeted and attacked with a WordPress exploit.[9]
A separate vulnerability on one of the project site's web servers allowed an attacker to introduce exploitable code in the form of a back door to some downloads of WordPress 2.1.1. The 2.1.2 release addressed this issue; an advisory released at the time advised all users to upgrade immediately.[10]
In May 2007, a study revealed that 98% of WordPress blogs being run are exploitable.[11]
In a June 2007 interview, Stefen Esser, the founder of the PHP Security Response Team, spoke critically of WordPress's security track record, citing problems with the application's architecture that make it unnecessarily difficult to write code that is secure from SQL injection vulnerabilities, as well as other problems.[12]

chucker
2008-06-14, 15:27
as I posted above, SELECT 1 construction doesn't work; it will return all rows, displaying same value '1' for each row.

That's exactly what it's supposed to do.

DIT: I think I'm just slow. It looks like SELECT 1 is supposed to replace SELECT * to provide better performance when we need to know how many rows or something else that doesn't really depend on actual data in table, which was why Brad used an subquery example, right?

Bingo.

turtle
2008-06-14, 16:05
I have no idea which version on WP is being used on this site. I can't even figure out where it's listed so I can know and update if needed. The organization uses a "do everything" hosting company and I get limited access to stuff like this. We have to pay big if they have to make any changes. The good part is I have FTP access to the WP directory on the server. :) I guess I could update it, but if I break the theme then I'm stuck and I'm not ready to pay them for this.

Brad
2008-06-14, 16:39
Apparently, Wordpress is powered by MySQL, but as I posted above, SELECT 1 construction doesn't work; it will return all rows, displaying same value '1' for each row. I wonder if this could actually be a stored procedure or something like that?

[...]

EDIT: I think I'm just slow. It looks like SELECT 1 is supposed to replace SELECT * to provide better performance
As chucker said, that's basically the idea. :) This is why it's useful in situations like the exists + subselect because you don't need to keep the values in the subselect; you only want to know that they exist.

This idea is also useful for inserts + selects. Say you're working at a car dealership and you have a table "car_type" that contains columns make, model, and year and you have to manually update the database every year with the new models. Let's assume that you have the following data:

make | model | year
-------+--------------------+------
Honda | Civic Sedan | 2008
Honda | Civic Coupe | 2008
Honda | Civic Hybrid Sedan | 2008
Honda | Accord Sedan | 2008
Honda | Accord Coupe | 2008
Honda | Fit | 2008
Honda | Fit Sport | 2008


You get news that Honda's 2009 lineup is exactly the same as the 2008 lineup and you need to update the database accordingly. What do you do?

You can either do a whole slew of inserts...


INSERT INTO car_type VALUES ('Honda', 'Civic Sedan', 2009);
INSERT INTO car_type VALUES ('Honda', 'Civic Coupe', 2009);
INSERT INTO car_type VALUES ('Honda', 'Civic Hybrid Sedan', 2009);
INSERT INTO car_type VALUES ('Honda', 'Accord Sedan', 2009);
INSERT INTO car_type VALUES ('Honda', 'Accord Coupe', 2009);
INSERT INTO car_type VALUES ('Honda', 'Fit', 2009);
INSERT INTO car_type VALUES ('Honda', 'Fit Sport', 2009);


OR you can do a single insert + select like this...

INSERT INTO car_type SELECT make, model, 2009 FROM car_type WHERE make = 'Honda' AND year = 2008;

In this case, the '2009' in the SELECT behaves exactly like the '1' in the SELECT of the previous example. The only difference here is that we're also getting other values in the SELECT and passing them to the INSERT.

In either case, we get...
make | model | year
-------+--------------------+------
Honda | Civic Sedan | 2008
Honda | Civic Coupe | 2008
Honda | Civic Hybrid Sedan | 2008
Honda | Accord Sedan | 2008
Honda | Accord Coupe | 2008
Honda | Fit | 2008
Honda | Fit Sport | 2008
Honda | Civic Sedan | 2009
Honda | Civic Coupe | 2009
Honda | Civic Hybrid Sedan | 2009
Honda | Accord Sedan | 2009
Honda | Accord Coupe | 2009
Honda | Fit | 2009
Honda | Fit Sport | 2009


Pretty neat, huh? :)

Banana
2008-06-14, 16:49
Very!

I remember seeing that tip when I had that MySQL class but I don't recall anything about SELECT 1 (or may have forgotten that one). Either way, it's great to remember that one again. Thanks again, Brad! :)

turtle
2008-06-19, 19:53
Here's the latest, this time on my Video version of the blog:
Author : \')/* (IP: 64.38.5.174 , srv1.greatideas.com)
E-mail :
URI : http://ekibastos
Whois : http://ws.arin.net/cgi-bin/whois.pl?queryinput=64.38.5.174
Comment:
<strong>ekibastos...</strong>

ekibastos...


From WP:
http://1veryhappyfamily.com/an/spam1.png

Interesting that I'm just now getting hit with this when the blogs have been going for over a year now. :\