マイクロソフト セキュリティ アドバイザリ: SQL Server の脆弱性により、リモートでコードが実行される

文書翻訳 文書翻訳
文書番号: 961040 - 対象製品
すべて展開する | すべて折りたたむ

目次

はじめに

マイクロソフトは、リモートでコードが実行される可能性がある 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 EXPLICIT
ON ERROR RESUME NEXT

' 定数値
CONST EXIT_SUCCESS       = 0
CONST EXIT_FAILURE       = 1
CONST EXIT_NOINSTANCES   = -1
CONST DEFAULTNAMESPACE   = "root\default"
CONST STDREGPROV         = "stdregprov"
CONST HKEY_LOCAL_MACHINE = &H80000002
CONST REG_MULTI_SZ       = 7
CONST REG_SZ             = 1
CONST adCmdText          = 1


Call VBMain()

Function VBMain()
Err.Clear
ON ERROR RESUME NEXT
		
Dim sInstances(), strInstance, i, TotalCount
VBMain = EXIT_SUCCESS
If GetInstances(sInstances, TotalCount) = FALSE Then
WScript.Quit EXIT_FAILURE
End If

If IsEmptyNull(sInstances) Then 
WScript.Echo "INFO:No instances are present."
VBMain = EXIT_NOINSTANCES
Exit Function
End If

For i = 0 To TotalCount-1
strInstance = sInstances(i,0)
GetFullInstance strInstance, sInstances(i,1)
If ApplyFix(sInstances(i,0), strInstance) = FALSE Then
WScript.Echo "ERROR:Could not apply the workaround on " + sInstances(i,0) + "."+ vbCRLF
VBMain = EXIT_FAILURE
End If
Next
	
WScript.Echo "INFO:Completed processing all the running SQL instances."
End Function

Function GetInstances(ByRef sInstances, ByRef TotalCount)
Err.Clear
ON ERROR RESUME NEXT
		
Dim sInstances1, sInstances2, i
Dim instCount1, instCount2
GetInstances = FALSE

If NOT GetRegValue ("", HKEY_LOCAL_MACHINE, "Software\Microsoft\Microsoft SQL Server", "InstalledInstances", sInstances1, REG_MULTI_SZ, TRUE) Then
WScript.Echo "ERROR:Failed to read SQL instances installed on the machine."
Exit Function
End If

sInstances2 = NULL
If IsOs64Bit() = TRUE Then
If NOT GetRegValue ("", HKEY_LOCAL_MACHINE, "Software\Microsoft\Microsoft SQL Server", "InstalledInstances", sInstances2, REG_MULTI_SZ, FALSE) Then
WScript.Echo "ERROR:Failed to read SQL instances installed on the machine."
Exit Function
End If
End If

If IsEmptyNull(sInstances1) AND IsEmptyNull(sInstances2) Then 
WScript.Echo "INFO:No instances present."
WScript.Quit EXIT_SUCCESS
End If
        
instCount1 = 0
instCount2 = 0 
TotalCount = 0
If IsEmptyNull(sInstances1) = FALSE Then
instCount1 = UBound(sInstances1) + 1
TotalCount = instCount1
End If
        
If IsEmptyNull(sInstances2) = FALSE Then
instCount2 = UBound(sInstances2) + 1
TotalCount = TotalCount + instCount2
End If

ReDim PRESERVE sInstances(TotalCount,1)
if instCount1 > 0 Then
For i = 0 To UBound(sInstances1)
sInstances(i,0) = sInstances1(i)
sInstances(i,1) = True
Next
End If
If instCount2 >0 Then
For i = 0 To UBound(sInstances2)
sInstances(i+instCount1,0) = sInstances2(i)
sInstances(i+instCount1,1) = FALSE
Next
End If
GetInstances = TRUE
End Function


Function ApplyFix(ByVal strInstance, ByVal strServerName)
Err.Clear
ON ERROR RESUME NEXT

Dim objConn, objCmd, objCmd1, objRS, objRS1
Dim strCommand, strConn
Dim strBuildVersion, strProductLevel, bApplyFix

' 戻り値を初期化
ApplyFix = FALSE
    
strConn = "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) Then
Set objConn = Nothing
Exit Function
End If

' 修正プログラムを適用する前にバージョンを検証する
strCommand = "select SERVERPROPERTY('ProductVersion') as version, SERVERPROPERTY('productlevel') as productlevel"
objCmd.ActiveConnection = objConn
objCmd.CommandType = adCmdText
objCmd.CommandText = strCommand
    	
Set objRS = objCmd.Execute()
If ErrorOccurred("ERROR:Could not execute """ + strCommand + """ on " + strInstance) = TRUE Then
objConn.Close()
Set objConn = Nothing
ApplyFix = FALSE
Exit Function   
End If

strBuildVersion = objRS("version")
strProductLevel = UCase(objRS("productlevel"))

bApplyFix = FALSE
' SQL 2000 および SQL 2005 (RTM、SP1 および SP2) のバージョンのみに回避策を適用する
If (CInt(Mid(strBuildVersion,1,1)) = 8) Then
bApplyFix = TRUE
ElseIf CInt(Mid(strBuildVersion,1,1)) = 9 AND (StrComp(strProductLevel,"RTM") = 0 OR StrComp(strProductLevel,"SP1") = 0 OR StrComp(strProductLevel,"SP2") = 0) Then
bApplyFix = TRUE
End If 
	
If bApplyFix = TRUE Then
strCommand = "deny execute on sp_replwritetovarbin to public"
objCmd1.ActiveConnection = objConn
objCmd1.CommandType = adCmdText
objCmd1.CommandText = strCommand
Set objRS1 = objCmd1.Execute()
If ErrorOccurred("ERROR:Could not execute """ + strCommand + """ on " + strInstance) = FALSE Then
WScript.Echo "INFO:Successfully applied the workaround on " + strInstance + " (" + strBuildVersion + ")."+ vbCRLF
ApplyFix = TRUE
End If
Else
WScript.Echo "INFO:Skipping collecting information for " + strInstance + " (" + strBuildVersion + ") as this instance is not vulnerable."+ vbCRLF
ApplyFix = TRUE
End If

objConn.Close()
Set objConn = Nothing
Set objCmd = Nothing
Set objCmd1 = Nothing
Set objRS = Nothing
Set objRS1 = Nothing
End Function

Private Function GetRegValue (ByVal strMachineName, ByVal hMainKey, ByVal strPath, ByVal strValueName, ByRef strValue, ByVal iValueType, ByVal b32bit)
Err.Clear
ON ERROR RESUME NEXT
	
Dim objLocator, objServices, objRegistry, objCtx
Dim sMultiStrings, lRc
GetRegValue = TRUE

' WMI に接続し、STDREGPROV クラスに対してオブジェクトを取得する
Set objCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
If b32bit = TRUE Then
objCtx.Add "__ProviderArchitecture", 32
Else
objCtx.Add "__ProviderArchitecture", 64
End If
objCtx.Add "__RequiredArchitecture", TRUE
set 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) Then
GetRegValue = FALSE
Exit Function
End If 

lRc = 0
Select Case iValueType
' REG_MULTI_SZ のみを考慮する
Case REG_MULTI_SZ
strValue = ""
lRC = objRegistry.GetMultiStringValue(hMainKey, strPath, strValueName, sMultiStrings)
strValue = sMultiStrings
Case REG_SZ
strValue = ""
lRC = objRegistry.GetStringValue(hMainKey, strPath, strValueName, strValue)
Case Else
GetRegValue = FALSE
End Select

If lRc = 2 Or lRc = 3 Then
GetRegValue = TRUE
strValue = ""
ElseIf Err.Number OR lRc <> 0 Then
GetRegValue = FALSE
End If
    
Set objLocator = Nothing
Set objServices = Nothing
Set objRegistry = Nothing
End Function

Function IsEmptyNull(sCheck)
IsEmptyNull = FALSE
If IsObject(sCheck) Then Exit Function
If IsArray(sCheck) Then Exit Function
If VarType(sCheck) = vbEmpty Then IsEmptyNull = TRUE :Exit Function
If VarType(sCheck) = vbNull Then IsEmptyNull = TRUE :Exit Function
If sCheck = "" Then IsEmptyNull = TRUE
End Function

Private Function ErrorOccurred (ByVal strIn)
If Err.Number <> 0 Then
WScript.Echo strIn
WScript.Echo "ERROR:0x" & Err.Number & " - " & Err.Description
Err.Clear
ErrorOccurred = TRUE
Else
ErrorOccurred = FALSE
End If
End Function

Function IsOs64Bit()
Err.Clear
ON ERROR RESUME NEXT
    
Dim objProc
Set objProc = GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'")
If objProc.Architecture = 0 Then
IsOs64Bit = FALSE
Else
IsOs64Bit = TRUE
End If
End Function

Function GetFullInstance (ByRef strInstanceName, ByVal b32bit)
Err.Clear
ON ERROR RESUME NEXT 

Dim objServices, objClusters, objCluster
Dim strMacName, isEmpty
Dim strKey, strInstID
    
GetFullInstance = TRUE
    
If strComp(UCase(strInstanceName), "MICROSOFT##SSEE", 1) = 0 Then
strInstanceName = "np:\\.\pipe\mssql$microsoft##ssee\sql\query"
Exit Function
End if

strMacName = ""
Set objServices = GetObject("winmgmts:root\cimv2")

' クエリ クラスタ サービス
Set objClusters = objServices.ExecQuery ("select * from win32_service where Name='ClusSvc' AND Started = TRUE")
isEmpty = TRUE
If Err.Number = 0 Then
For each objCluster in objClusters
isEmpty = FALSE
Next
End If

Set objServices = Nothing
Set objClusters = Nothing

If isEmpty = TRUE Then
strInstanceName = BuildInstanceName (".", strInstanceName)
Exit Function
End 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, b32bit

If StrComp(strMacName, "") <> 0 Then
strInstanceName = BuildInstanceName (strMacName, strInstanceName)
Exit Function
End If

strKey = "SOFTWARE\Microsoft\" + strInstanceName + "\Cluster"
GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bit

If StrComp(strMacName, "") <> 0 Then
strInstanceName = BuildInstanceName (strMacName, strInstanceName)
Exit Function
End If

' 2005/2008 インスタンスのレジストリ値を照会する
'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL
' RegValue = InstanceName
strInstID = ""
strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL"
GetRegValue "", HKEY_LOCAL_MACHINE, strKey, strInstanceName, strInstID, REG_SZ, b32bit
    
If StrComp(strInstID, "") = 0 Then
' このキーが存在しない場合は、SQL 2000 ローカル インスタンスとして返す
strInstanceName = BuildInstanceName (".", strInstanceName)
Exit Function
End If

strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\" + strInstID + "\Cluster"
GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bit
    
If StrComp(strMacName, "") = 0 Then
strMacName = "."
End If

strInstanceName = BuildInstanceName (strMacName, strInstanceName)
End Function

Function BuildInstanceName (ByVal strMachineName, ByVal strInstanceName)
Dim strPrefix
    
strPrefix = ""
If StrComp(strMachineName, ".")= 0 Then
strPrefix = "lpc:"
End If
    
If strComp(UCase(strInstanceName), "MSSQLSERVER", 1) = 0 Then
BuildInstanceName = strPrefix + strMachineName
Else
BuildInstanceName = strPrefix + strMachineName + "\" + strInstanceName
End if
End 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) をクリックしてください。
920277 Windows 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 を検出する更新されたスクリプトを追加。

プロパティ

文書番号: 961040 - 最終更新日: 2009年1月7日 - リビジョン: 3.0
この資料は以下の製品について記述したものです。
  • Windows Internal Database
  • Microsoft SQL Server 2005 Service Pack 2?を以下の環境でお使いの場合
    • Microsoft SQL Server 2005 Standard Edition
    • Microsoft SQL Server 2005 Enterprise Edition
    • Microsoft SQL Server 2005 Express Edition
    • Microsoft SQL Server 2005 Express Edition with Advanced Services
    • Microsoft SQL Server 2005 Enterprise X64 Edition
    • Microsoft SQL Server 2005 Standard X64 Edition
    • Microsoft SQL Server 2005 Enterprise Edition for Itanium Based Systems
  • Microsoft SQL Server 2000 Desktop Engine (Windows)
  • Microsoft SQL Server 2000 Desktop Engine (Windows)
  • Microsoft SQL Server 2000 Service Pack 4
キーワード:?
kbpubtypekc kbfix kbbug kbsecvulnerability kbsecbulletin kbsecurity KB961040
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com