[wp-hackers] Rethinking check_admin_referer()
Brian at TheCodeCave.com
Wed Apr 19 20:48:41 GMT 2006
Hey! I've perused your book! Good to "meet" you.
You've got the basic order correct. My approach was a classic Cross Site
Request Forgery (CSRF pronounced "Sea Surf") directed specifically at WP.
In the most basic example of a CSRF, there is no form or anything else on
the other side. You ask for one thing, a picture perhaps, and I give you
another, perhaps a command to delete the current post.
A simple CSRF attack works against WP because WP only uses a referer check
for protection. Because I am redirecting a request YOU made from an admin
page, the referer remains *wp-admin*. This vulnerability makes me have
mixed feelings about what to do when a valid nonce is not supplied. Falling
back to only the referer check avoids the AYS prompt, yeah, but it doesn't
offer an defense against a CSRF. But if the topic of the discussion is
convenience and not security, then only a referer check is needed.
You asked "Does step 3 use GET or POST?". A better question would be "Does
step 4 use GET or POST?". If it used a post, my method would not work.
What I did was relatively unsophisticated, I hadn't heard of a CSRF attack a
week ago. Other might be able to get around a POST too. My attempts last
Here, I'll tell you what... I just created a less dynamic version of the
destructive link. It will only attempt to delete post #999999. And if you
have that many posts, you probably could use a few less anyway.
Here's the link:
You can open it in your browser and see a picture of me. It is perfectly
safe in most environments.
Now leave a comment on your blog under a fake name and with that as your
home page. You'll probably need to log out to do this. Again, it is safe
and your users can click on it till their heart's content.
Next, go to your dashboard: http://www.yoursite.com/wp-admin/
You'll see the new comment listed there. Click on the name for that comment
because you're curious about what I (you) look like. You should get an
error message saying that there was a problem deleting the post because your
blog doesn't have a post #999999.
If you did have a post #999999 on your blog, your screen would have simply
BTW, I didn't have time to make it any more complex. Like I said, I'd not
tried this before; so simple changes could cause the deletion to fail. For
instance, if go to http://www.yoursite.com/wp-admin/index.php instead of
http://www.yoursite.com/wp-admin/, it will not work.
If I could get around that, this method should work for embedded images from
the Manage Comment View page. You can see it would work because this link
embedded as an image in the comment shows up as a broken link. That means
the payload was triggered.
This first try just wasn't sophisticated enough to handle anything but the
front page of the dashboard. I had tried several methods to get around
that. They should have worked, but I think my host actually has some
problems in this area. In the past, I've done other legit things using
similar techniques that should have just worked, but just didn't. I was
following examples directly as others used them. Unfortunately, I don't
have a second host to try this stuff on to confirm that it is the host and
not my methods.
Anyway, there you go. A relatively safe proof of concept that doesn't
reveal anything that isn't covered by the very definition of this kind of
attack as defined by wikipedia http://en.wikipedia.org/wiki/Csrf. Though I
might actually finally get a wikipedia account in order to correct the last
statement in their definition. I'm using CSRF specifically to get around a
More information about the wp-hackers