Exploit-DB #9295
Description: Firebird SQL - op_connect_request main listener shutdown
Type: dos
Platform: windows
Date: 2009-07-28
Author: Core Security

Exploit:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

      Core Security Technologies - CoreLabs Advisory
           http://www.coresecurity.com/corelabs/

Firebird SQL op_connect_request main listener shutdown vulnerability


1. *Advisory Information*

Title: Firebird SQL op_connect_request main listener shutdown vulnerability
Advisory ID: CORE-2009-0707
Advisory URL: http://www.coresecurity.com/content/firebird-sql-dos
Date published: 2009-07-28
Date of last update: 2009-07-28
Vendors contacted: Firebird SQL
Release mode: Coordinated release


2. *Vulnerability Information*

Class: Denial of service (DoS)
Remotely Exploitable: Yes
Locally Exploitable: No
Bugtraq ID: 35842
CVE Name: CVE-2009-2620


3. *Vulnerability Description*

Firebird SQL [1] is an open source relational database management system
offering many ANSI SQL standard features that runs on Linux, Windows,
and a variety of Unix platforms.

A remote denial of service vulnerability has been found in Firebird SQL,
which can be exploited by a remote attacker to force the server to close
the socket where it is listening for incoming connections and to enter
an infinite loop, by sending an unexpected 'op_connect_request' message
with invalid data to the server.


4. *Vulnerable packages*

   . Firebird SQL v1.5.5
   . Firebird SQL v2.0.1
   . Firebird SQL v2.0.5
   . Firebird SQL v2.1.1
   . Firebird SQL v2.1.2
   . Firebird SQL v2.1.3 RC1
   . Firebird SQL v2.5.0 Beta 1


5. *Non-vulnerable packages*

   . Firebird SQL v2.1.3 Release Candidate 2 (estimated release: July 2009)
   . Firebird SQL v2.5 Beta 2 (estimated release: July 2009)
   . Firebird SQL v1.5.6 (estimated release: August 2009)
   . Firebird SQL v2.0.6 (estimated release: October 2009)

Please build a fresh CVS checkout to have a fixed version sooner.


6. *Vendor Information, Solutions and Workarounds*

The issue is resolved in all branches of the Firebird SQL repository. It
is registered in the Firebird SQL bug tracker as:
http://tracker.firebirdsql.org/browse/CORE-2563


7. *Credits*

This vulnerability was discovered and researched by Francisco Falcon
from Core Security Technologies.


8. *Technical Description / Proof of Concept Code*


8.1. *Introduction*

Firebird SQL is an open source relational database management system
offering many ANSI SQL standard features that runs on Linux, Windows and
a variety of Unix platforms.

A remote denial of service can be triggered by an unauthenticated
attacker, by sending an unexpected 'op_connect_request' message with
invalid data of length greater than or equal to 12 bytes to the server.

Inside the server ('src/remote/server.cpp'), the function
'process_packet2()' processes a packet received from a client. This
function has a 'switch' statement that considers all the possible
opcodes defined in the protocol (see 'P_OP' enum 'in
src/remote/protocol.h').

/-----------

src/remote/server.cpp:

...
3404	P_OP op = receive->p_operation;
3405	switch (op)
3406	{
3407	case op_connect:
	...
3426	case op_compile:
	...
3430	case op_attach:
	...

- -----------/

 In the case of an 'op_connect_request' packet, the execution flow goes
to the following 'case' in the 'switch' statement:

/-----------

src/remote/server.cpp:

...
3584	case op_connect_request:
3585		aux_request(port, &receive->p_req, sendL);
3586		break;

- -----------/

 After calling 'aux_request()' function and executing the 'break'
statement, execution lands here:

/-----------

src/remote/server.cpp:

...
3652	if (port && port->port_state == state_broken) {
3653		if (!port->port_parent) {
3654			gds__log("SERVER/process_packet: broken port, server exiting");
3655			port->disconnect(sendL, receive);
3656			ThreadData::restoreSpecific();
3657			return false;
3658		}
3659		port->disconnect(sendL, receive);
3660		port = NULL;
3661	}

- -----------/

 By debugging the 'fbserver.exe' binary when it receives an
'op_connect_request' packet, we can see that the conditions of the first
'if' statement are satisfied, but the condition of the second 'if' is
not, so execution flow goes to the 'port->disconnect()' call:

/-----------

005ACE2C  |>  837E 0C 03           CMP DWORD PTR DS:[ESI+C],3
    ;port->port_state == state_broken ?
005ACE30  |.  75 1B                JNZ SHORT fbserver.005ACE4D
005ACE32  |.  837E 1C 00           CMP DWORD PTR DS:[ESI+1C],0
    ;port->port_parent == 0?
005ACE36  |.  75 0A                JNZ SHORT fbserver.005ACE42
    ;this conditional jump is taken
005ACE38  |.  68 D4D65F00          PUSH fbserver.005FD6D4
    ;  ASCII "SERVER/process_packet: broken port, server exiting"
005ACE3D  |.^ E9 44FDFFFF          JMP fbserver.005ACB86
005ACE42  |>  53                   PUSH EBX
    ; /Arg2
005ACE43  |.  57                   PUSH EDI
    ; |Arg1
005ACE44  |.  8BCE                 MOV ECX,ESI
    ; |
005ACE46  |.  E8 65D7FFFF          CALL <fbserver.rem_port::disconnect>
    ; \port->disconnect(sendL, receive)

- -----------/

 The type of 'port' is 'struct rem_port', as defined in
'src/remote/remote.h'. This struct type has a 'disconnect()' function
that is implemented in 'src/remote/server.cpp':

/-----------

src/remote/server.cpp:

1464	void rem_port::disconnect(PACKET* sendL, PACKET* receiveL)

- -----------/

 Inside this function, the following code is executed, in order to free
both the sent and received packets and to close the corresponding sockets:

/-----------

src/remote/server.cpp:

...
1492	REMOTE_free_packet(this, sendL);
1493	REMOTE_free_packet(this, receiveL);
1494	this->disconnect();

- -----------/

 That call to 'this->disconnect()' will ultimately lead to the
'disconnect()' function in 'src/remote/inet.cpp'. This function is
intended to break a remote connection, and receives a 'rem_port'
structure as parameter.

/-----------

src/r