דלג לתוכן הראשי
היכנס דרך Microsoft
היכנס או צור חשבון.
שלום,
בחר חשבון אחר.
יש לך חשבונות מרובים
בחר את החשבון שברצונך להיכנס באמצעותו.

מבוא

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 ולאחר מכן הפעל את קובץ ה- script באמצעות CScript.exe. ה- script סובב בין המופעים הפועלים של SQL Server במחשב המקומי ומחיל את הפתרון העוקף על הגירסאות המושפעות. עליך להיות חבר בתפקיד מנהל מערכת בכל מופע של SQL Server כדי להחיל את הפתרון העוקף. אם אין לך חשבון Windows החבר בתפקיד מנהל מערכת בכל השרתים המושפעים שבהם פועלת התוכנית SQL Server, ייתכן שיהיה עליך להפעיל script זה ממספר חשבונות. ב- Windows Server 2008 וב- Windows Vista, אם אתה משתמש בחשבון מנהל של Windows החבר בתפקיד מנהל מערכת, עליך להפעיל script זה משורת פקודה "גבוהה".

'*************************************************************************************
'תיאור: script זה סובב סביב כל המופעים הפועלים של SQL Server
' ומונע הרשאת ביצוע ב- sp_replwritetovarbin לציבור בכל
' הגירסאות המושפעות.
' מסופק כפתרון עוקף ואינו מיועד לשימוש במקרה
' שעדכון אבטחה מסופק ומותקן.
'*************************************************************************************

OPTION EXPLICIT
ON ERROR RESUME NEXT

' ערכי Constant
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
הבא

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
הבא
End If
If instCount2 >0 Then
For i = 0 To UBound(sInstances2)
sInstances(i+instCount1,0) = sInstances2(i)
sInstances(i+instCount1,1) = FALSE
הבא
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
הבא
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/en-us/library/bb490887.aspxהערה מומלץ שלא תשתמש ב- script זה אם סופק עדכון אבטחה והתקנת אותו.

בעיות מוכרות שעלולות להתרחש בעת הפעלת SCRIPT זה

בעיה 1

בעת הפעלת script זה, תקבל הודעת שגיאה זו:

: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.(אין אפשרות למצוא את האובייקט 'sp_replwritetovarbin', מכיוון שאינו קיים או שאין לך הרשאה).
:ERROR Could not apply the workaround on <instancename>.(אין אפשרות להחיל את הפתרון העוקף על [שם המופע]).

סיבה 1

אתה מקבל הודעת שגיאה זו אם אין לך את ההרשאות הדרושות להחלת השינוי. הודעת שגיאה זו מציינת שלא הצלחת להיכנס בהצלחה למופע "<instancename>".


הודעת שגיאה זו מתרחשת בדרך כלל ב- SQL Server Express שבה הקבוצה "Built-In\Users" כוללת כניסה למסד הנתונים כברירת מחדל. עם זאת, קבוצה זו אינה חברה בתפקיד מנהל המערכת.

כמו כן, הודעת שגיאה זו עלולה להתרחש אם שחררת את הפרוצדורה sp_replwritetovarbin זו היתה ההמלצה מדוח של ספק חיצוני. Microsoft אינה ממליצה על שחרור הפרוצדורה המאוחסנת. במקום זאת, מומלץ להחיל פתרון זה.

פתרון 1

ודא שהחשבון שאליו אתה מתחבר הוא חבר בתפקיד מנהל המערכת במופע זה של מסד הנתונים. אם החשבון אינו חבר, הוסף את המשתמש שאתה מחבר לתפקיד מנהל המערכת, או השתמש בחשבון של משתמש אחר. עבור SQL Server 2005 וגירסאות קודמות, הקבוצה "Built-in\Administrators" היא חברה בתפקיד מנהל המערכת כברירת מחדל. כאשר אתה מפעיל script זה ב- Windows Vista או ב- Windows Server 2008, ודא שאתה מפעיל אותו משורת פקודה "גבוהה".

בעיה 2

אם אתה מפעיל script זה ב- SQL Server 2005, אתה מקבל את הודעת השגיאה הבאה:

Error: Could not connect to <instancename> (אין אפשרות להתחבר ל[שם המופע]).
:ERROR 0x-2147217843 - Login failed for user '<user>'. (כניסה נכשלה עבור המשתמש [שם משתמש])
:ERROR Could not apply the workaround on <instancename>.(אין אפשרות להחיל את הפתרון העוקף על [שם המופע]).

סיבה 2

אתה מקבל הודעת שגיאה זו אם לא הצלחת להתחבר למופע ">instancename<" על-אף שמופע זה קיים.


הודעת שגיאה זו מופיעה בדרך כלל כאשר אתה מתחבר למופעים של Windows Internal Database או שלMicrosoft SQL Server 2000 Desktop Edition (Windows). בדרך כלל, לאף חשבון משתמש אין כניסה למסדי נתונים אלה.

פתרון 2

ודא שלחשבון שבו אתה משתמש כדי להפעיל את ה- script יש כניסה למסד הנתונים החבר בתפקיד מנהל המערכת.

לא מומלץ להוסיף משתמשים בודדים למסדי נתונים של Windows Internal Database ושלMicrosoft SQL Server 2000 Desktop Edition (Windows). אם תעשה זאת, המשתמשים שתוסיף עלולים להפריע לפעילותם הסדירה של מסדי נתונים אלה. במקרה זה, ודא שאתה מתחבר מחשבון החבר בתפקיד מנהל המערכת. הקבוצה "Built-in\Administrators" ב- Windows היא חברה בתפקיד מנהל המערכת כברירת מחדל עבור SQL Server 2005 וגירסאות קודמות. כאשר אתה מפעיל script זה ב- 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)". הוא מותקן עם כמה מוצרים מאת Microsoft, ביניהם SharePoint Services.

פתרון 3

ה- script של הפתרון העוקף מיועד לפעול עם Windows Internal Database. אין צורך בפעולה מצדך.

מספר יישומים אינם מסירים את Windows Internal Database כאשר התקנתם מוסרת.
לקבלת מידע נוסף אודות אופן ההסרה של Windows Internal Database, לחץ על מספר המאמר שלהלן כדי להציגו מתוך מאגר הידע Microsoft Knowledge Base:

920277 Windows Internal Database אינו מופיע ברשימה של הכלי הוספה/הסרה של תוכניות ואינו מוסר כאשר אתה מסיר את Windows SharePoint Services 3.0 מהמחשב. (ייתכן שקישור זה מפנה לתוכן שחלק ממנו או כולו מופיע באנגלית)

בעיה 4

בעת הפעלת script זה, תקבל הודעת שגיאה זו:


Error: Could not connect to .\<instancename>‎ (אין אפשרות להתחבר ל[שם המופע]).
:ERROR 0x-2147467259 - [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied ‏(SQL Server אינו קיים או שהגישה נדחתה)

סיבה 4

הודעת שגיאה זו מופיעה כאשר התנאים הבאים מתקיימים:

  • גירסת 32 סיביות של SQL Server 2000 מותקנת במערכת הפעלה של 64 סיביות.

  • במחשב שלך מותקנת גירסת 64 סיביות של SQL Server 2005 או של SQL Server 2008.


הודעת שגיאה זו מופיעה כאשר קובץ Script משתמש בגירסת 64 הסיביות של הקובץ dbmslpcn.dll. לגירסה זו אין אפשרות לנהל תקשורת עם מופעי WoW של SQL Server 2000.

פתרון 4

השתמש בגירסת 32 סיביות של הקובץ cscript.exe שנמצא בתיקיה ‎%WINDOWS%\SysWOW64 כדי להפעיל את קובץ ה- Script. פעולה זו טוענת את גירסת 32 הסיביות של הוקבץ dbmslpcn.dll, שיכולה לזהות מופעי WoW.

מידע נוסף

לקבלת מידע נוסף כיצד לזהות את הגירסה והמהדורה של SQL Server, לחץ על מספר המאמר שלהלן כדי להציג את המאמר ב-Microsoft Knowledge Base:

321185כיצד לזהות את הגירסה והמהדורה של SQL Server

מידע נוסף

בטבלה הבאה רשומים שינויים טכניים משמעותיים שנעשו במאמר זה. מספר המהדורה ותאריך הסקירה במאמר זה עשויים להצביע על שינויי עריכה או שינויי מבנה קטנים במאמר זה שאינם כלולים בטבלה.

תאריך

מהדורות

31 בדצמבר 2008

כולל קובץ Script מעודכן המזהה מופעי אשכולות של מעבר לגיבוי בעת כשל של SQL Server.

30 בדצמבר 2008

כולל קובץ Script מעודכן המזהה גירסאות 32 סיביות של SQL Server שמפעילות גירסאות 64 סיביות של Windows.

זקוק לעזרה נוספת?

מעוניין באפשרויות נוספות?

גלה את יתרונות המנוי, עיין בקורסי הדרכה, למד כיצד לאבטח את המכשיר שלך ועוד.

קהילות עוזרות לך לשאול שאלות ולהשיב עליהן, לתת משוב ולשמוע ממומחים בעלי ידע עשיר.

האם מידע זה היה שימושי?

עד כמה אתם מרוצים מאיכות השפה?
מה השפיע על החוויה שלך?
בלחיצה על 'שלח', אתה מאפשר למשוב שלך לשפר מוצרים ושירותים של Microsoft. מנהל ה-IT שלך יוכל לאסוף נתונים אלה. הצהרת הפרטיות.

תודה על המשוב!

×