مقدمة
أصدرت Microsoft نصائح إرشادية للأمان حول الثغرة الأمنية الموجودة في Microsoft SQL Server مما قد يسمح بتنفيذ التعليمات البرمجية عن بُعد. وتحتوي النصائح الإرشادية للأمان على معلومات إضافية ذات صلة بالأمان. لعرض "النصائح الإرشادية للأمان"، قم بزيارة موقع Microsoft التالي على الويب:
http://www.microsoft.com/technet/security/advisory/961040.mspxتتضمن هذه المقالة VB script الذي يمكنك استخدامه لتطبيق الحل البديل على كافة مثيلات SQL Server قيد التشغيل على جهاز كمبيوتر محلي.
مثال على VB SCRIPT الذي يمكنك استخدامه لتطبيق الحل البديل
يمكنك استخدام VB script لرفض إذن "التنفيذ" إلى الدور "عام" على الإجراء المخزن الموسع sp_replwritetovarbin على كافة إصدارات SQL Server المتأثرة قيد التشغيل على جهاز كمبيوتر محلي.
تقدم Microsoft الأمثلة البرمجية بغرض التوضيح فقط، دون أي ضمان صريح أو ضمني. ويتضمن ذلك، على سبيل المثال لا الحصر، الضمانات الضمنية الخاصة بالتسويق أو الملاءمة لغرض معين. تفترض هذه المقالة أنك معتاد على لغة البرمجة التي يتم شرحها والأدوات المستخدمة لإنشاء الإجراءات وتصحيحها. يمكن لمهندسي الدعم لدى Microsoft شرح وظيفة إجراء محدد. على الرغم من ذلك، لن يقوموا بتعديل هذه الأمثلة لتقديم وظيفة إضافية أو إنشاء إجراءات لاستيفاء متطلباتك الخاصة. قم بنسخ هذه التعليمة البرمجية إلى ملف نصي، احفظ الملف باستخدام ملحق اسم ملف .vbs، ثم قم بتشغيل ملف البرنامج النصي باستخدام CScript.exe. يتكرر البرنامج النصي خلال مثيلات SQL Server قيد التشغيل على جهاز الكمبيوتر المحلي ويقوم بتطبيق الحل البديل على الإصدارات المتأثرة. يجب أن تكون عضوًا في دور sysadmin على كل مثيل من SQL Server لتطبيق الحل البديل. إذا لم يكن لديك حساب Windows والذي يكون عضوًا في دور sysadmin على كافة الملقمات المتأثرة التي تعمل على تشغيل SQL Server، قد تضطر إلى تشغيل هذا البرنامج النصي من حسابات متعددة. على نظامي التشغيل Windows Server 2008 وWindows Vista، إذا كنت تستخدم حساب مسؤول Windows والذي يكون عضوًا في دور sysadmin، يجب تشغيل هذا البرنامج النصي من موجه أوامر "غير مقيد".'*************************************************************************************
'Description: This script iterates through all the running instances of SQL Server ' and denies execute permission on sp_replwritetovarbin to public on all ' the affected versions. ' THIS IS PROVIDED AS A WORKAROUND AND SHOULD NOT BE USED IN THE EVENT THAT ' A SECURITY UPDATE IS PROVIDED AND INSTALLED. '************************************************************************************* OPTION EXPLICIT ON ERROR RESUME NEXT ' Constant values 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 ' Initialize return value ApplyFix = FALSE strConn = "Provider=sqloledb;Initial Catalog=master;Integrated Security=SSPI;Data Source=" + strServerName + ";" ' Error checking is intentionally left to keep the code short Set objConn = CreateObject("ADODB.Connection") Set objCmd = CreateObject("ADODB.Command") Set objCmd1 = CreateObject("ADODB.Command") ' Open a Connection to the master Database objConn.Open strConn If ErrorOccurred("Error: Could not connect to " + strInstance) Then Set objConn = Nothing Exit Function End If ' Validate the version before applying the fix 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 ' Apply the workaround only for SQL 2000 and SQL 2005 (RTM, SP1 and SP2) versions 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 'Connect to WMI and get an object to STDREGPROV class. 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 ' We only care about 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") ' Query Cluster service 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 ' If we reach here that means the machine is a clustered node. ' So lets query registry to determine whether the SQL instance is clustered or not. ' For SQL 2000 query the following value ' HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<InstanceName>\Cluster ' ClusterName 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 ' Lets try querying the registry value for 2005/2008 instances '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 ' If this key doesnt exist, then return back as a SQL 2000 local instance 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، قم بزيارة موقع Microsoft التالي على الويب:
http://technet.microsoft.com/ar-sa/library/bb490887(en-us).aspxملاحظة نوصي بعدم استخدام هذا البرنامج النصي في حالة توفر تحديث أمني وتثبيته.
مشكلات معروفة قد تحدث عند تشغيل هذا البرنامج النصي
المشكلة الأولى
عند تشغيل البرنامج النصي، تظهر رسالة الخطأ التالية:
خطأ: تعذر تنفيذ "deny execute on sp_replwritetovarbin to public" على <اسم المثيل>
خطأ: 0x-2147217900 - لا يمكن العثور على الكائن 'sp_replwritetovarbin'، لأنه غير موجود أو أنك ليس لديك الإذن. خطأ: تعذر تطبيق الحل البديل على <اسم المثيل>.السبب الأول
تظهر لك رسالة الخطأ هذه إذا لم تكن لديك الأذونات المطلوبة لتطبيق هذا التغيير. تشير رسالة الخطأ هذه إلى أنك تمكنت من تسجيل الدخول بنجاح إلى المثيل "<اسم المثيل>."
تظهر رسالة الخطأ هذه عادةً في SQL Server Express حيث يتوفر لمجموعة "Built-In\Users" تسجيل الدخول إلى قاعدة البيانات افتراضيًا. على الرغم من ذلك، لا تعد هذه المجموعة من أعضاء دور sysadmin. قد تظهر رسالة الخطأ هذه أيضًا في حالة إسقاط الإجراء sp_replwritetovarbin. كانت هذه هي توصية من تقرير تابع لجهة أخرى. لا نوصي بإسقاط الإجراء الذي تم تخزينه. بدلاً من ذلك، نوصي بتطبيق هذا الحل.الحل الأول
تأكد من أن الحساب الذي ترتبط به عضو في دور sysadmin على ذلك المثيل لقاعدة البيانات. إذا لم يكن الحساب عضوًا، قم بإضافة حساب المستخدم، الذي ترتبط به، إلى دور sysadmin، أو استخدم حساب مستخدم آخر. بالنسبة لإصدار SQL Server 2005 والإصدارات الأسبق، تكون مجموعة "Built-in\Administrators" عضوًا في دور sysadmin افتراضيًًا. عند تشغيل هذا البرنامج النصي على نظام التشغيل Windows Vista أو نظام التشغيل Windows Server 2008، تأكد من تشغيله من موجه أوامر "غير مقيد".
المشكلة الثانية
في حالة تشغيل هذا البرنامج النصي في SQL Server 2005، تظهر رسالة الخطأ التالية:
خطأ: تعذر الارتباط بـ <اسم المثيل>
خطأ: 0x-2147217843 - فشل تسجيل الدخول للمستخدم '<المستخدم>'. خطأ: تعذر تطبيق الحل البديل على <اسم المثيل>.السبب الثاني
تظهر رسالة الخطأ هذه إذا لم تتمكن من الارتباط بالمثيل "<اسم المثيل>" حتى في حالة وجود هذا المثيل.
عادةً ما تظهر رسالة الخطأ هذه عند الارتباط بمثيلات Microsoft SQL Server 2000 Desktop Edition (Windows) أو Windows Internal Database. عادةً، لا يتوفر لحسابات المستخدمين تسجيلات دخول لقواعد البيانات هذه.الحل الثاني
تأكد من أن الحساب الذي تستخدمه لتشغيل البرنامج النصي يتوفر لديه تسجيل دخول على قاعدة البيانات التي تكون عضوًا في دور sysadmin.
لا نوصي بإضافة مستخدمين فرديين إلى قواعد بيانات Microsoft SQL Server 2000 Desktop Edition (Windows) وWindows Internal Database. في حالة القيام بذلك، قد يتداخل المستخدمون الذين تقوم بإضافتهم مع العملية العادية لقواعد البيانات هذه. في هذه الحالة، تأكد من الارتباط من حساب عضو في دور sysadmin. عادةً ما تكون مجموعة "Built-in\Administrators" في Windows عضوًا في دور sysadmin افتراضيًا في SQL Server 2005 وفي الإصدارات الأسبق. عند تشغيل هذا البرنامج النصي على نظام التشغيل Windows Vista أو نظام التشغيل Windows Server 2008، تأكد من تشغيله من موجه أوامر "غير مقيد".المشكلة الثالثة
قد تلاحظ وجود مثيل من قاعدة بيانات يسمى MICROSOFT##SSEE. على الرغم من ذلك، فإنك لا تقوم بتثبيت قاعدة البيانات هذه.
السبب الثالث
قاعدة البيانات هذه هي Windows Internal Database، تُعرف أيضًا باسم "SQL Server Embedded Edition"، أو أحيانًا تُعرف باسم "Windows Internal Database" أو "Microsoft SQL Server 2000 Desktop Edition (Windows)". يتم تثبيتها مع بعض المنتجات من Microsoft، بما في ذلك SharePoint Services.
الحل الثالث
يتم تصميم البرنامج النصي للحل البديل للعمل مع Windows Internal Database. لا يتطلب اتخاذ أي إجراء من جانبك.
بعض التطبيقات لا تعمل على إزالة Windows Internal Database عند إزالة تثبيتها. لمزيد من المعلومات حول كيفية إزالة Windows Internal Database، انقر فوق رقم المقالة التالي لعرضها في "قاعدة معارف Microsoft" (قد تحتوي هذه المقالة على ارتباطات إلى محتوى باللغة الإنجليزية (محتوى لم تتم ترجمته بعد)):920277 عدم سرد Windows Internal Database في أداة "إضافة أو إزالة البرامج" وعدم إزالتها عند إزالة Windows SharePoint Services 3.0 من جهاز الكمبيوتر
المشكلة الرابعة
عند تشغيل البرنامج النصي، تظهر رسالة الخطأ التالية:
خطأ: تعذر الارتباط بـ .\<اسم المثيل> خطأ: 0x-2147467259 - [DBNETLIB][ConnectionOpen (Connect()).]SQL Server غير موجود أو تم رفض الوصول
السبب الرابع
تظهر لك رسالة الخطأ هذه في حالة تحقق الشرطين التاليين:
-
تثبيت إصدار ٣٢ بت من SQL Server 2000 على نظام تشغيل يستند إلى x64 بت.
-
تثبيت إصدار ٦٤ بت من SQL Server 2005 أو SQL Server 2008 على جهاز الكمبيوتر.
تظهر رسالة الخطأ هذه عند استخدام البرنامج النصي لإصدار ٦٤ بت من ملف dbmslpcn.dll. لا يمكن لهذا الإصدار الاتصال بمثيلات WoW من SQL Server 2000.
الحل الرابع
استخدم إصدار ٣٢ بت من الملف cscript.exe من المجلد %WINDOWS%\SysWOW64 لبدء تشغيل البرنامج النصي. يؤدي ذلك إلى تحميل إصدار ٣٢ بت من الملف dbmslpcn.dll الذي يمكنه الكشف عن مثيلات WoW.
مراجع
لمزيد من المعلومات حول كيفية تحديد إصدار SQL Server ونسخته، انقر فوق رقم المقالة التالي لعرضها في "قاعدة معارف Microsoft" (قد تحتوي هذه المقالة على ارتباطات إلى محتوى باللغة الإنجليزية (محتوى لم تتم ترجمته بعد)):
321185كيفية تحديد إصدار SQL Server ونسخته
معلومات أخرى
يسرد الجدول التالي مراجعات تقنية هامة لهذه المقالة. قد يشير رقم المراجعة وتاريخ آخر مراجعة في هذه المقالة إلى مراجعات بنائية أو مراجعات تحريرية ثانوية غير متضمنة في الجدول لهذه المقالة.
التاريخ |
المراجعات |
---|---|
٣١ ديسمبر ٢٠٠٨ |
تتضمن برنامجًا نصيًا محدثًا يكشف عن مثيلات تجاوز الفشل للمجموعات لـ SQL Server. |
٣٠ ديسمبر ٢٠٠٨ |
تتضمن برنامجًا نصيًا محدثًا يكشف عن إصدارات ٣٢ بت من SQL Server تعمل على إصدارات ٦٤ من أنظمة تشغيل Windows. |