[spip-dev] [Spip-en] A typo on spip.net and a security hole in SPIP 1.9.2e

Its a quite stupid question, but in the configuration page of the private area, can you check that the url website isn’t “http://www.baidu.comhttp://www.baidu.com” ?

2008/9/25 Thomas Sutton <thomas@bouncingorange.com>

Hi again,

2008/9/25 Thomas Sutton <thomas@bouncingorange.com>

Hi Gilles,

Its a quite stupid question, but in the configuration page of the private area, can you check that the url website isn’t « http://www.baidu.comhttp://www.baidu.com » ?

No, it’s not. That’s the first thing I checked :slight_smile:

Yes, it was stupid :slight_smile:

The string baidu doesn’t occur in any file (except the cached files mentioned below) nor does it occur anywhere in the mysqldump of the database. I’ve never encountered this before (but I also haven’t left templates using #SPIP_CRON or #URL_PAGE live before) and I can’t tell what they did, so I can’t test it against SVN head.

It must be stored in the satabase, and particularilly in the table spip_meta.
Can you check this by parsing a backup of you database (generated with tools like phpMyAdmin)

That would help to find the bug.

.Gilles

    There are no CGI programs and no web applications installed except
    SPIP and Thelia. The only network services run on this machine are:

Hello Thomas,

There is a security update on Thélia because of a security hole on admin/auth.php : Thelia
You need to update to version > 1.3.61 or eventually to patch auth.php with an up-to-date version.

Regurlarly check thelia.fr blog for security advices. There is a second issue concerning atos : Thelia

Arnault

2008/9/25 Thomas Sutton <thomas@bouncingorange.com>

To fix the problem, modify ecrire/inc/utils.php and change starting on line 722 (in 1.9.2e):
if (isset($_SERVER[‹ HTTP_X_FORWARDED_HOST ›])){
$server = explode(‹ , ›,$_SERVER[‹ HTTP_X_FORWARDED_HOST ›]);
$server = trim(reset($server));
}
else
$server = $_SERVER[‹ HTTP_HOST ›];
to
$server = $_SERVER[‹ HTTP_HOST ›];

Je vote pour que ce patch soit appliqué rapidement dans toutes les branches.
D’autant que le ticket qui justifie ce code (http://trac.rezo.net/trac/spip/ticket/401) a été marqué comme invalide.

.Gilles

Je vote pour que ce patch soit appliqué rapidement dans toutes les branches.
D'autant que le ticket qui justifie ce code
(http://trac.rezo.net/trac/spip/ticket/401) a été marqué comme invalide.

Yes it should be applied.

But I'm not sure that Thomas's (excellent) way of provoking the bug is
the only one. Thomas can you verify in your access.log if there are
any requests containing "baidu"? And, please, can you reopen the
ticket and add your explaination and patch?

-- Fil

218.6.8.235 - - [19/Sep/2008:02:00:28 +0000] "GET http://www.baidu.com/
HTTP/1.1" 200 2399 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)"

Then maybe we could fix this by replying with a 403 (and halting
computation of the page) to this kind of badly formed requests?

-- Fil

Hi Fil,

218.6.8.235 - - [19/Sep/2008:02:00:28 +0000] "GET http://www.baidu.com/
HTTP/1.1" 200 2399 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)"

Then maybe we could fix this by replying with a 403 (and halting
computation of the page) to this kind of badly formed requests?

This isn't a bad request: HTTP/1.1 requests look like this:

Request-Line = Method SP Request-URI SP HTTP-Version CRLF
Method = "OPTIONS" | "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT"
Request-URI = "*" | absoluteURI | abs_path | authority

So "GET http://www.baidu.com/ HTTP/1.1" is an entirely valid request. Requests to HTTP proxy servers, for example, must specify absolute URIs and RFC2616 requires that all HTTP/1.1 servers should interpret this the same way they would interpret:

  GET / HTTP/1.1
  Host: www.baidu.com

and that the request should be rejected (the RFC says 400) if the specified host is not valid for this server (e.g., a virtual host we server, or something we'll proxy). This seems to be a misconfiguration on my part.

In this case, the request was almost certainly made by a robot looking for servers with mod_proxy (or similar) configured to proxy requests from all clients. If the page my server returns is the same as http://www.baidu.com/, then the robot will add this server to a list of hosts that can be used to "bounce" attacks on other hosts thus hiding the originator from the victim: it'll look like my server is the attacker (or child pornography distributor, or pirate, etc.), rather than the person hiding behind me.

As noted above, any compliant server MUST interpret this in the same way as the Host header and this will set $_SERVER['HTTP_HOST'] to whatever the client specified, which will trigger this bug. So too will request any with a Host header. You can't assume that anything in $_SERVER is true.

I think that url_de_base() and any similar functions should be rewritten to use values from $GLOBALS['meta'] or mes_options.php or config/*.php. I don't think it's too much of a burden that administrators have to check/change 'adresse_site' or a setting in config/ when their installation is behind a reverse proxy. They should be doing it anyway...

Regards,

Thomas Sutton

Web Developer
bouncingorange

Hi Gilles,

On 25/09/2008, at 2:09 PM, Gilles VINCENT wrote:

Its a quite stupid question, but in the configuration page of the private area, can you check that the url website isn't "http://www.baidu.comhttp://www.baidu.com" ?

No, it's not. That's the first thing I checked :slight_smile:

The string baidu doesn't occur in any file (except the cached files mentioned below) nor does it occur anywhere in the mysqldump of the database. I've never encountered this before (but I also haven't left templates using #SPIP_CRON or #URL_PAGE live before) and I can't tell what they did, so I can't test it against SVN head.

More in a second.

Regards,

Thomas Sutton

Web Developer
bouncingorange
graphic + web design

Hi All,

I've found the source of my problem: SPIP uses a number of sources to determine the host to use in links it generates for itself in ecrire/inc/utils.php url_de_base(). In particular, it uses $_SERVER['HTTP_X_FORWARDED_HOST'] if it is set. This is insecure and allows the clients to insert any host they want into the generated page which will then be cached and served to other clients.

To see this in action, you can use curl or some other client that allows you to set headers for requests.

1) Clear SPIP cache (or repeat until the cache gets cleared as normal)
2) curl -H 'X-Forwarded-Host: blah' http://spip.site.net/
3) Notice that links now point to http://blah/

If this request regenerates any skeletons that call url_de_base (including #URL_PAGE and #SPIP_CRON), then the value passed in *by the client* will/may be used as the SPIP address and the result may be cached and used for future requests. This is a massive security hole (though the exposure -- requests that regenerate a page -- is smaller than it might have been).

I've tested this against SPIP 1.9.2e and SVN 12732 and it worked with both.

SVN r12732

$ curl -H ‹ X-Forwarded-Host: blah.com › http://localhost/spip-head/
  ...
  <!-- SPIP-CRON --><div style=« background-image: url(‹ http://blah.com/spip-head/spip.php?action=cron ›); »></div>
  ...

SPIP 1.9.2e

$ curl -H 'X-Forwarded-Host: blah.com' http://localhost/spip/
  ...
         | <a href="http://blah.com/spip-1.9.2e/spip.php?page=plan">Site Map</a>
  ...

To fix the problem, modify ecrire/inc/utils.php and change starting on line 722 (in 1.9.2e):
         if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])){
                 $server = explode(',',$_SERVER['HTTP_X_FORWARDED_HOST']);
                 $server = trim(reset($server));
         }
         else
                 $server = $_SERVER['HTTP_HOST'];
to
  $server = $_SERVER['HTTP_HOST'];

Regards,

Thomas Sutton

Web Developer
bouncingorange
graphic + web design

Hi Arnault,

On 25/09/2008, at 3:55 PM, Arnault Pachot wrote:

    There are no CGI programs and no web applications installed except
    SPIP and Thelia. The only network services run on this machine are:

Hello Thomas,

There is a security update on Thélia because of a security hole on admin/auth.php : Thelia
You need to update to version > 1.3.61 or eventually to patch auth.php with an up-to-date version.

Regurlarly check thelia.fr blog for security advices. There is a second issue concerning atos : Thelia

I've got 1.3.7 installed, but thanks for the warning. I'll ask Geraldine (our Francophone) to add feed for the Thelia blog to her daily routine. :slight_smile:

Patching SPIP to fix the security hole is pretty easy (just delete a few lines of code in a single file). If anything does rely on this using this header (can't it be done with $GLOBALS['meta']['adresse_site']), making it an option (even one set manually in mes_option.php) should let those who need it use SPIP and let everyone else be secure.

Cheers,

Thomas Sutton
bouncingorange

Voici un des hacks possibles, par GET. Je pense qu'il y a aussi des
choses du genre
http://lebonsite/spip.php?http://lattaque/

http://lebonsite/http://lattaque/

---------- Forwarded message ----------
From: Thomas Sutton <thomas@bouncingorange.com>
Date: Fri, Sep 26, 2008 at 4:47 AM
Subject: Re: [spip-dev] [Spip-en] A typo on spip.net and a security
hole in SPIP 1.9.2e
To: Fil <fil@rezo.net>
Cc: Gilles VINCENT <gilles.vincent@gmail.com>, spip-dev@rezo.net

Hi Fil,

On 25/09/2008, at 5:44 PM, Fil wrote:

Je vote pour que ce patch soit appliqué rapidement dans toutes les branches.
D'autant que le ticket qui justifie ce code
(http://trac.rezo.net/trac/spip/ticket/401) a été marqué comme invalide.

Yes it should be applied.

But I'm not sure that Thomas's (excellent) way of provoking the bug is
the only one. Thomas can you verify in your access.log if there are
any requests containing "baidu"? And, please, can you reopen the
ticket and add your explaination and patch?

I've checked the Apache logs on this server and, once I remove my own
requests trying to find the problem, there is a single request from an
IP from CHINANET in Fujian province:

218.6.8.235 - - [19/Sep/2008:02:00:28 +0000] "GET
http://www.baidu.com/ HTTP/1.1" 200 2399 "-" "Mozilla/4.0 (compatible;
MSIE 4.01; Windows NT)"

This is pretty normal: Google the request and you'll find plenty of
mentions of this.

Several of the cached files containing the string "baidu" were
generated on 19 September at 02:00, including the processed skeleton
inc-pied.html (cached as
skel/html_41532c9143f310ca5a5e6f0e2a669ffd.php) and a bunch of cached
page fragments.

If you or any other SPIP developers want a copy of the logs,
mysqldump, or a tar of the site (including the cached data) I can make
them available on request.

Cheers,

Thomas Sutton
bouncingorange

--
Fil