はじめに

マイクロソフトは、リモートでコードが実行される可能性がある Microsoft SQL Server の脆弱性に関するマイクロソフト セキュリティ アドバイザリをリリースしました。セキュリティ アドバイザリには、この問題に関連する追加のセキュリティ関連の情報が含まれています。セキュリティ アドバイザリを参照するには、次のマイクロソフト Web サイトにアクセスしてください。

http://www.microsoft.com/japan/technet/security/advisory/961040.mspxこの資料では、ローカル コンピュータ上の SQL Server で実行中のすべてのインスタンスに回避策を適用する VB スクリプトを掲載しています。

回避策を適用する VB スクリプトの例

この VB スクリプトを使用して、ローカル コンピュータで実行中の SQL Server で影響を受けるすべてのバージョンで、sp_replwritetovarbin 拡張ストアド プロシージャのパブリック ロールの実行権限を禁止できます。 マイクロソフトは、この情報をプログラミング言語の使用方法の一例として提供するだけであり、市場性および特定目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。この資料は、例示されているプログラミング言語やプロシージャの作成およびデバッグに使用するツールについて理解されているユーザーを対象としています。Microsoft Support 担当者は、特定のプロシージャの機能についての問い合わせにはお答えできますが、ユーザー固有の目的に合わせた機能の追加、プロシージャの作成などの内容変更は行っておりません。 以下のコードをテキスト ファイルにコピーし、拡張子 .vbs で保存し、CScript.exe を使用してスクリプトを実行します。スクリプトはローカル コンピュータ上の SQL Server で実行中のインスタンスで繰り返し処理され、影響を受けるバージョンに回避策を適用します。SQL Server に回避策を適用するには、各インスタンスで sysadmin ロールのメンバである必要があります。SQL Server を実行中の影響を受けるすべてのサーバーで sysadmin ロールのメンバである Windows アカウントを持っていない場合、複数アカウントでこのスクリプトを実行する必要がある可能性があります。Windows Server 2008 か Windows Vista で、sysadmin ロールのメンバである Windows administrator アカウントを使用している場合、このスクリプトは管理者特権のコマンド プロンプトで実行する必要があります。

'*************************************************************************************説明 : このスクリプトは SQL Server の実行中のすべてのインスタンスで繰り返し処理され、 '            影響を受けるすべてのバージョンでパブリックへの sp_replwritetovarbin の実行権限'            を禁止します。'            このスクリプトは回避策として提供されており、セキュリティ更新プログラムが提供され、インストール '            されている場合は使用しないでください。'*************************************************************************************OPTION EXPLICITON ERROR RESUME NEXT' 定数値CONST EXIT_SUCCESS       = 0CONST EXIT_FAILURE       = 1CONST EXIT_NOINSTANCES   = -1CONST DEFAULTNAMESPACE   = "root\default"CONST STDREGPROV         = "stdregprov"CONST HKEY_LOCAL_MACHINE = &H80000002CONST REG_MULTI_SZ       = 7CONST REG_SZ             = 1CONST adCmdText          = 1Call VBMain()Function VBMain()Err.ClearON ERROR RESUME NEXTDim sInstances(), strInstance, i, TotalCountVBMain = EXIT_SUCCESSIf GetInstances(sInstances, TotalCount) = FALSE ThenWScript.Quit EXIT_FAILUREEnd IfIf IsEmptyNull(sInstances) Then WScript.Echo "INFO:No instances are present."VBMain = EXIT_NOINSTANCESExit FunctionEnd IfFor i = 0 To TotalCount-1strInstance = sInstances(i,0)GetFullInstance strInstance, sInstances(i,1)If ApplyFix(sInstances(i,0), strInstance) = FALSE ThenWScript.Echo "ERROR:Could not apply the workaround on " + sInstances(i,0) + "."+ vbCRLFVBMain = EXIT_FAILUREEnd IfNextWScript.Echo "INFO:Completed processing all the running SQL instances."End FunctionFunction GetInstances(ByRef sInstances, ByRef TotalCount)Err.ClearON ERROR RESUME NEXTDim sInstances1, sInstances2, iDim instCount1, instCount2GetInstances = FALSEIf NOT GetRegValue ("", HKEY_LOCAL_MACHINE, "Software\Microsoft\Microsoft SQL Server", "InstalledInstances", sInstances1, REG_MULTI_SZ, TRUE) ThenWScript.Echo "ERROR:Failed to read SQL instances installed on the machine."Exit FunctionEnd IfsInstances2 = NULLIf IsOs64Bit() = TRUE ThenIf NOT GetRegValue ("", HKEY_LOCAL_MACHINE, "Software\Microsoft\Microsoft SQL Server", "InstalledInstances", sInstances2, REG_MULTI_SZ, FALSE) ThenWScript.Echo "ERROR:Failed to read SQL instances installed on the machine."Exit FunctionEnd IfEnd IfIf IsEmptyNull(sInstances1) AND IsEmptyNull(sInstances2) Then WScript.Echo "INFO:No instances present."WScript.Quit EXIT_SUCCESSEnd IfinstCount1 = 0instCount2 = 0 TotalCount = 0If IsEmptyNull(sInstances1) = FALSE TheninstCount1 = UBound(sInstances1) + 1TotalCount = instCount1End IfIf IsEmptyNull(sInstances2) = FALSE TheninstCount2 = UBound(sInstances2) + 1TotalCount = TotalCount + instCount2End IfReDim PRESERVE sInstances(TotalCount,1)if instCount1 > 0 ThenFor i = 0 To UBound(sInstances1)sInstances(i,0) = sInstances1(i)sInstances(i,1) = TrueNextEnd IfIf instCount2 >0 ThenFor i = 0 To UBound(sInstances2)sInstances(i+instCount1,0) = sInstances2(i)sInstances(i+instCount1,1) = FALSENextEnd IfGetInstances = TRUEEnd FunctionFunction ApplyFix(ByVal strInstance, ByVal strServerName)Err.ClearON ERROR RESUME NEXTDim objConn, objCmd, objCmd1, objRS, objRS1Dim strCommand, strConnDim strBuildVersion, strProductLevel, bApplyFix' 戻り値を初期化ApplyFix = FALSEstrConn = "Provider=sqloledb;Initial Catalog=master;Integrated Security=SSPI;Data Source=" + strServerName + ";"' コードを短く維持するため、エラー チェックが意図的に残されているSet objConn = CreateObject("ADODB.Connection")Set objCmd = CreateObject("ADODB.Command")Set objCmd1 = CreateObject("ADODB.Command")' マスタ データベースへの接続を開くobjConn.Open strConn If ErrorOccurred("Error:Could not connect to " + strInstance) ThenSet objConn = NothingExit FunctionEnd If' 修正プログラムを適用する前にバージョンを検証するstrCommand = "select SERVERPROPERTY('ProductVersion') as version, SERVERPROPERTY('productlevel') as productlevel"objCmd.ActiveConnection = objConnobjCmd.CommandType = adCmdTextobjCmd.CommandText = strCommandSet objRS = objCmd.Execute()If ErrorOccurred("ERROR:Could not execute """ + strCommand + """ on " + strInstance) = TRUE ThenobjConn.Close()Set objConn = NothingApplyFix = FALSEExit Function   End IfstrBuildVersion = objRS("version")strProductLevel = UCase(objRS("productlevel"))bApplyFix = FALSE' SQL 2000 および SQL 2005 (RTM、SP1 および SP2) のバージョンのみに回避策を適用するIf (CInt(Mid(strBuildVersion,1,1)) = 8) ThenbApplyFix = TRUEElseIf CInt(Mid(strBuildVersion,1,1)) = 9 AND (StrComp(strProductLevel,"RTM") = 0 OR StrComp(strProductLevel,"SP1") = 0 OR StrComp(strProductLevel,"SP2") = 0) ThenbApplyFix = TRUEEnd If If bApplyFix = TRUE ThenstrCommand = "deny execute on sp_replwritetovarbin to public"objCmd1.ActiveConnection = objConnobjCmd1.CommandType = adCmdTextobjCmd1.CommandText = strCommandSet objRS1 = objCmd1.Execute()If ErrorOccurred("ERROR:Could not execute """ + strCommand + """ on " + strInstance) = FALSE ThenWScript.Echo "INFO:Successfully applied the workaround on " + strInstance + " (" + strBuildVersion + ")."+ vbCRLFApplyFix = TRUEEnd IfElseWScript.Echo "INFO:Skipping collecting information for " + strInstance + " (" + strBuildVersion + ") as this instance is not vulnerable."+ vbCRLFApplyFix = TRUEEnd IfobjConn.Close()Set objConn = NothingSet objCmd = NothingSet objCmd1 = NothingSet objRS = NothingSet objRS1 = NothingEnd FunctionPrivate Function GetRegValue (ByVal strMachineName, ByVal hMainKey, ByVal strPath, ByVal strValueName, ByRef strValue, ByVal iValueType, ByVal b32bit)Err.ClearON ERROR RESUME NEXTDim objLocator, objServices, objRegistry, objCtxDim sMultiStrings, lRcGetRegValue = TRUE' WMI に接続し、STDREGPROV クラスに対してオブジェクトを取得するSet objCtx = CreateObject("WbemScripting.SWbemNamedValueSet")If b32bit = TRUE ThenobjCtx.Add "__ProviderArchitecture", 32ElseobjCtx.Add "__ProviderArchitecture", 64End IfobjCtx.Add "__RequiredArchitecture", TRUEset objLocator = createobject("wbemscripting.swbemlocator")set objServices = objLocator.connectserver(strMachineName,DEFAULTNAMESPACE, "", "",,,,objCtx)set objRegistry = objServices.get(STDREGPROV)If ErrorOccurred ("ERROR:Could not connect to WMI namespace " + DEFAULTNAMESPACE) ThenGetRegValue = FALSEExit FunctionEnd If lRc = 0Select Case iValueType' REG_MULTI_SZ のみを考慮するCase REG_MULTI_SZstrValue = ""lRC = objRegistry.GetMultiStringValue(hMainKey, strPath, strValueName, sMultiStrings)strValue = sMultiStringsCase REG_SZstrValue = ""lRC = objRegistry.GetStringValue(hMainKey, strPath, strValueName, strValue)Case ElseGetRegValue = FALSEEnd SelectIf lRc = 2 Or lRc = 3 ThenGetRegValue = TRUEstrValue = ""ElseIf Err.Number OR lRc <> 0 ThenGetRegValue = FALSEEnd IfSet objLocator = NothingSet objServices = NothingSet objRegistry = NothingEnd FunctionFunction IsEmptyNull(sCheck)IsEmptyNull = FALSEIf IsObject(sCheck) Then Exit FunctionIf IsArray(sCheck) Then Exit FunctionIf VarType(sCheck) = vbEmpty Then IsEmptyNull = TRUE :Exit FunctionIf VarType(sCheck) = vbNull Then IsEmptyNull = TRUE :Exit FunctionIf sCheck = "" Then IsEmptyNull = TRUEEnd FunctionPrivate Function ErrorOccurred (ByVal strIn)If Err.Number <> 0 ThenWScript.Echo strInWScript.Echo "ERROR:0x" & Err.Number & " - " & Err.DescriptionErr.ClearErrorOccurred = TRUEElseErrorOccurred = FALSEEnd IfEnd FunctionFunction IsOs64Bit()Err.ClearON ERROR RESUME NEXTDim objProcSet objProc = GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'")If objProc.Architecture = 0 ThenIsOs64Bit = FALSEElseIsOs64Bit = TRUEEnd IfEnd FunctionFunction GetFullInstance (ByRef strInstanceName, ByVal b32bit)Err.ClearON ERROR RESUME NEXT Dim objServices, objClusters, objClusterDim strMacName, isEmptyDim strKey, strInstIDGetFullInstance = TRUEIf strComp(UCase(strInstanceName), "MICROSOFT##SSEE", 1) = 0 ThenstrInstanceName = "np:\\.\pipe\mssql$microsoft##ssee\sql\query"Exit FunctionEnd ifstrMacName = ""Set objServices = GetObject("winmgmts:root\cimv2")' クエリ クラスタ サービスSet objClusters = objServices.ExecQuery ("select * from win32_service where Name='ClusSvc' AND Started = TRUE")isEmpty = TRUEIf Err.Number = 0 ThenFor each objCluster in objClustersisEmpty = FALSENextEnd IfSet objServices = NothingSet objClusters = NothingIf isEmpty = TRUE ThenstrInstanceName = BuildInstanceName (".", strInstanceName)Exit FunctionEnd If' 処理がここまで到達した場合は、マシンがクラスタ化ノードであることを意味します。' そのため、レジストリを照会し、SQL インスタンスがクラスタ化されているかどうかを判別します。' SQL 2000 の場合は、次の値を照会します' HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<InstanceName>\Cluster' クラスタ名strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\" + strInstanceName + "\Cluster"GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bitIf StrComp(strMacName, "") <> 0 ThenstrInstanceName = BuildInstanceName (strMacName, strInstanceName)Exit FunctionEnd IfstrKey = "SOFTWARE\Microsoft\" + strInstanceName + "\Cluster"GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bitIf StrComp(strMacName, "") <> 0 ThenstrInstanceName = BuildInstanceName (strMacName, strInstanceName)Exit FunctionEnd If' 2005/2008 インスタンスのレジストリ値を照会する'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' RegValue = InstanceNamestrInstID = ""strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL"GetRegValue "", HKEY_LOCAL_MACHINE, strKey, strInstanceName, strInstID, REG_SZ, b32bitIf StrComp(strInstID, "") = 0 Then' このキーが存在しない場合は、SQL 2000 ローカル インスタンスとして返すstrInstanceName = BuildInstanceName (".", strInstanceName)Exit FunctionEnd IfstrKey = "SOFTWARE\Microsoft\Microsoft SQL Server\" + strInstID + "\Cluster"GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bitIf StrComp(strMacName, "") = 0 ThenstrMacName = "."End IfstrInstanceName = BuildInstanceName (strMacName, strInstanceName)End FunctionFunction BuildInstanceName (ByVal strMachineName, ByVal strInstanceName)Dim strPrefixstrPrefix = ""If StrComp(strMachineName, ".")= 0 ThenstrPrefix = "lpc:"End IfIf strComp(UCase(strInstanceName), "MSSQLSERVER", 1) = 0 ThenBuildInstanceName = strPrefix + strMachineNameElseBuildInstanceName = strPrefix + strMachineName + "\" + strInstanceNameEnd ifEnd Function

CScript.exe の詳細については、次のマイクロソフト Web サイトを参照してください。

http://technet.microsoft.com/en-us/library/bb490887.aspx注 : セキュリティ更新プログラムが提供されていて、それをインストールした場合は、このスクリプトを使用しないことを推奨します。

このスクリプトを実行した場合に発生する可能性のある既知の問題

問題 1

スクリプトを実行すると、次のエラー メッセージが表示される。

ERROR: Could not execute "deny execute on sp_replwritetovarbin to public" on <instancename> ERROR: 0x-2147217900 - Cannot find the object 'sp_replwritetovarbin', because it does not exist or you do not have permission.ERROR: Could not apply the workaround on <instancename>.

原因 1

変更を適用するのに必要なアクセス許可がない場合、このエラー メッセージが表示されます。このエラー メッセージは、インスタンス "<instancename>" にログインできなかったことを示しています。このエラー メッセージは通常、"Built-In\Users" グループが既定でデータベースにログインする SQL Server Express で表示されます。しかし、このグループは sysadmin ロールのメンバではありません。また、sp_replwritetovarbin プロシージャをドロップした場合にも、このエラー メッセージが表示される場合があります。これはサードパーティ レポートからの勧告でした。マイクロソフトでは、ストアド プロシージャをドロップすることは推奨しません。代わりに、次の解決方法を適用することを推奨します。

解決方法 1

接続に使用するアカウントを、データベースの当該インスタンスの sysadmin ロールのメンバにします。アカウントがメンバでない場合は、接続に使用するユーザーを sysadmin ロールに追加するか、別のユーザー アカウントを使用します。SQL Server 2005 以前では、"Built-in\Administrators" グループは既定で sysadmin ロールのメンバです。Windows Vista または Windows Server 2008 でこのスクリプトを実行する場合は、管理者特権のコマンド プロンプトから実行します。

問題 2

SQL Server 2005 でこのスクリプトを実行すると、次のエラー メッセージが表示される。

Error: Could not connect to <instancename>エラー: 0x-2147217843 - ユーザー '<user>' はログインできませんでした。ERROR: Could not apply the workaround on <instancename>.

原因 2

インスタンス "<instancename>" が存在する場合であっても、このインスタンスに接続できなかった場合、このエラー メッセージが表示されます。通常、Windows Internal Database または Microsoft SQL Server 2000 Desktop Edition (Windows) インスタンスに接続する場合に、このエラー メッセージが表示されます。通常、これらのデータベースにログインするユーザー アカウントはありません。

解決方法 2

スクリプトの実行に使用するアカウントが、sysadmin ロールのメンバであるデータベースにログインできるようにします。マイクロソフトでは、Windows Internal Database および Microsoft SQL Server 2000 Desktop Edition (Windows) データベースに個別のユーザーを追加することを推奨しません。このように追加すると、追加したユーザーは、これらのデータベースの通常の処理に影響する場合があります。この場合は、sysadmin ロールのメンバであるアカウントから接続します。通常、SQL Server 2005 および以前のバージョンでは、Windows の "Built-in\Administrators" グループは既定で sysadmin ロールのメンバです。Windows Vista または Windows Server 2008 でこのスクリプトを実行する場合は、管理者特権のコマンド プロンプトから実行します。

問題 3

インストールしていないにもかかわらず、MICROSOFT##SSEE という名前のデータベースのインスタンスが見つかる場合がある。

原因 3

このデータベースは Windows Internal Database で、"SQL Server Embedded Edition"や、場合によっては "Windows Internal Database" または "Microsoft SQL Server 2000 Desktop Edition (Windows)" とも呼ばれます。これは、SharePoint Services などのマイクロソフトの一部の製品と共にインストールされます。

解決方法 3

回避策のスクリプトは、Windows Internal Database と共に動作するように設計されています。ユーザー側では操作は必要ありません。一部のアプリケーションでは、アンインストール時に Windows Internal Database が削除されません。 Windows Internal Database を削除する方法の関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。

920277Windows Internal Database が [プログラムの追加と削除] に表示されず、コンピュータから Windows SharePoint Services 3.0 を削除しても削除されない

問題 4

スクリプトを実行すると、次のエラー メッセージが表示される。

Error: Could not connect to .\<instancename>エラー: 0x-2147467259 - [DBNETLIB][ConnectionOpen (Connect()).]SQL Server が存在しないか、アクセスが拒否されました。

原因 4

このエラー メッセージは、以下の条件に該当する場合に表示されます。

  • x64 ビット オペレーティング システムに 32 ビット版の SQL Server 2000 をインストールしている。

  • コンピュータに 64 ビット版の SQL Server 2005 または SQL Server 2008 をインストールしている。

スクリプトで 64 ビット版の dbmslpcn.dll ファイルを使用する場合、このエラー メッセージが表示されます。このバージョンは、SQL Server 2000 の WoW インスタンスと通信できません。

解決方法 4

%WINDOWS%\SysWOW64 フォルダから 32 ビット版の cscript.exe ファイルを使用して、スクリプトを起動します。これにより、WoW インスタンスを検出できる 32 ビット版の dbmslpcn.dll ファイルが読み込まれます。

関連情報

SQL Server のバージョンとエディションを識別する方法の関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。

321185 SQL Server のバージョンとエディションを識別する方法

詳細

次の表は、この資料に加えられた重要な技術上の改定の一覧です。この資料のリビジョン番号と最新のレビュー日には、この表に含まれていない、軽微な編集上の改定または構造上の改定が反映されていることがあります。

日付

改訂内容

2008 年 12 月 31 日

SQL Server フェールオーバー クラスタリング インスタンスを検出する更新されたスクリプトを追加。

2008 年 12 月 30 日

64 ビット版の Windows で動作する 32 ビット版の SQL Server を検出する更新されたスクリプトを追加。

ヘルプを表示

その他のオプションが必要ですか?

サブスクリプションの特典の参照、トレーニング コースの閲覧、デバイスのセキュリティ保護方法などについて説明します。

コミュニティは、質問をしたり質問の答えを得たり、フィードバックを提供したり、豊富な知識を持つ専門家の意見を聞いたりするのに役立ちます。