メイン コンテンツへスキップ
サポート
Microsoft アカウントでサインイン
サインインまたはアカウントを作成してください。
こんにちは、
別のアカウントを選択してください。
複数のアカウントがあります
サインインに使用するアカウントを選択してください。

はじめに

マイクロソフトは、リモートでコードが実行される可能性がある 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) をクリックしてください。

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 を検出する更新されたスクリプトを追加。

ヘルプを表示

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

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

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

この情報は役に立ちましたか?

言語の品質にどの程度満足していますか?
どのような要因がお客様の操作性に影響しましたか?
[送信] を押すと、Microsoft の製品とサービスの改善にフィードバックが使用されます。 IT 管理者はこのデータを収集できます。 プライバシーに関する声明。

フィードバックをいただき、ありがとうございます。

×