Ticket #4137 (assigned defect)

Opened 2 years ago

Last modified 9 months ago

Pingback Denial of Service possibility

Reported by: foobarwp12 Assigned to: pishmishy (accepted)
Priority: high Milestone: 2.9
Component: Security Version: 2.1.3
Severity: normal Keywords: xmlrpc ddos possibility has-patch 2nd-opinion needs-testing
Cc: josephscott

Description

The pingback feature of Wordpress (2.1.3) allows DDOS attacks either against the server hosting wordpress or against a third one.

When a client sends a pingback, wordpress calls "wp_remote_fopen" to download the referring URL. On servers having "allow_url_fopen" activated, this function will try to download the /whole/ URL without any timeout or size limit. (except those set in php.ini, which will usually lead to a ~8MB download)

So if you post ~100 xmlrpc requests referring to a /huge/ file, every server meeting those prerequisites should effectively be down (for a while). You should at least be able to generate lots of traffic.

On the other hand, if you google for blogs and post the same URL to each of 'em, the target server should be DDOSed.

I suggest allowing pingbacks only if the connection was opened from the host mentioned in the source URL.

I'll attach a demo exploit (I didn't test it for the entered URL; it worked for a local installation.)

Attachments

exploit.py (0.7 kB) - added by foobarwp12 on 04/11/07 19:43:47.
Exploit
4137-functions.patch (0.9 kB) - added by pishmishy on 07/03/07 10:59:52.
Patch to fix wp_remote_fopen()s use when allow_url_fopen
4137-functions-curl.patch (2.2 kB) - added by pishmishy on 07/03/07 14:29:27.
potential fix for issue when curl is used?
4137-functions-new.patch (2.2 kB) - added by pishmishy on 08/13/07 14:21:07.
patch improved with suggestions

Change History

04/11/07 19:43:47 changed by foobarwp12

  • attachment exploit.py added.

Exploit

04/11/07 19:48:35 changed by foolswisdom

  • version set to 2.1.3.
  • milestone changed from 2.0.eventually to 2.2.

04/11/07 22:32:29 changed by rob1n

  • owner changed from anonymous to rob1n.
  • milestone changed from 2.2 to 2.3.

We'll put this in for 2.3.

06/14/07 02:43:49 changed by rob1n

  • owner deleted.

(in reply to: ↑ description ) 07/03/07 08:46:22 changed by pishmishy

  • owner set to pishmishy.
  • status changed from new to assigned.
  • summary changed from Pingback DDOS possibility to Pingback Denial of Service possibility.

Replying to foobarwp12:

I suggest allowing pingbacks only if the connection was opened from the host mentioned in the source URL.

This is a tricky one. I think this suggestion will break for URLs where the host name is an alias for another host as the URL's hostname might be completely different to the hostname of the system where the pingback request comes from.

Setting a limit the size of the download wouldn't completely remove the amplification effect (the limit would have to be less than the size of the xmlrpc request) but it is what the Pingback specification recommends.

I've changed the name of this ticket - there is the potential for a distributed denial of service here but the real issue is the amplification in bandwidth leading to a traditional denial of service attack.

07/03/07 10:59:52 changed by pishmishy

  • attachment 4137-functions.patch added.

Patch to fix wp_remote_fopen()s use when allow_url_fopen

07/03/07 11:02:37 changed by pishmishy

  • keywords changed from xmlrpc ddos possibility to xmlrpc ddos possibility has-patch 2nd-opinion.

The attachment fixes the problem when allow_url_fopen has been set but doesn't fix the problem when curl is used to fetch the source page. I believe that this case can be fixed using callbacks but my PHP isn't up to the task. I'm opening that part up to others.

07/03/07 14:29:27 changed by pishmishy

  • attachment 4137-functions-curl.patch added.

potential fix for issue when curl is used?

07/03/07 14:31:40 changed by pishmishy

  • keywords changed from xmlrpc ddos possibility has-patch 2nd-opinion to xmlrpc ddos possibility has-patch 2nd-opinion needs-testing.

This second attachment contains a potential fix for the issue when using curl to fetch the pages. It feels ugly to me but I hope that it should do the trick. I've only tested the function outside of WordPress and it does appear to be able to limit the number of bytes fetched with curl but how well it plays with WordPress I wouldn't like to guess.

07/04/07 15:26:53 changed by Otto42

You may want to set the CURLOPT_RANGE parameter as well. On servers that support it (HTTP 1.1, some FTP's), it will limit the server to only returning the amount of data you want. On those that don't support it, it won't have any effect.

I would also suggest setting CURLOPT_BUFFERSIZE (only for PHP5 and up) to some value like 4096 or something. I think the default action of curl in the way you're using it will simply retrieve the whole page and return it to your read function as a single string, or as some really large buffer or something.

Using a CURLOPT_TIMEOUT of some value, like 30-60 seconds, would also limit the impact from this sort of thing.

Essentially, there's no certain way to make curl stop retrieving data. But these would at least help.

08/13/07 14:21:07 changed by pishmishy

  • attachment 4137-functions-new.patch added.

patch improved with suggestions

08/13/07 14:22:07 changed by pishmishy

Sorry for the delay in an updated patch, been on holiday. I've amended the patch with Otto42's suggestions.

08/29/07 17:48:40 changed by ryan

  • milestone changed from 2.3 to 2.4 (next).

09/26/07 16:47:19 changed by josephscott

  • cc set to josephscott.

03/11/08 15:25:01 changed by lloydbudd

  • milestone changed from 2.5 to 2.6.