Acest articol se aplică site-urilor de SharePoint 2010 publicate în Internet care au cerințe de securitate diferite în structură lor.
Una din problemele de securitate în contextul implementărilor complexe este legată de modul de acces la diferite site-uri. Se întâmplă adeseori ca în contextul relaxării securității pentru portalurile de SharePoint publicate în Internet, să ne confruntăm cu un abuz de acces anonim la nivelul anumitor site-uri sau subsite-uri, fapt care poate duce la repudierea în public a unor informații sensibile.
În diagrama de mai sus site-ul Home are configurat acces anonim, site-urile cu albastru nu au acces anonim iar cele cu roșu au securitate individuală și configurat accesul anonim.
Dacă un anonim accesează adresa: http://home/Site3/ i se vor solicita datele de conectare. În cazul în care apelează http://home/site3/Site32/ nu i se mai cer datele de autentificare pentru a vizualiza pagina. Site-urile 321 și 322 pot avea acces anonim prin moștenire de la site-ul părinte Site32.
Propunerea principală a acestui articol este aceea de inventariere periodică a securității infrastructurii SharePoint în sensul depistării anumitor site-uri web cu conținut sensibil accesibil anonimilor.
În mod clasic pentru a enumera structura unei ferme de SharePoint putem folosi comanda:
stsadm -o enumallwebs > C:\ScriptsOutput\AllSubWebs.xml
care ne permite să exportăm în format XML toată structura din toate bazele de date. Această comandă nu extrage însă și starea de acces în mod anonim la site-ul Web. În aceste condiții trebuie să utilizăm comenzile Powershell specifice SharePoint pentru a putea extrage starea anonimilor.
În articolul lui Brian Beach [1] observăm că există 3 stări ale accesului anonim la un subweb SharePoint:
- fără acces anonim: valoarea 0
- Acces anonim cu configurație implicită de acces la liste și biblioteci: valoarea 1.
- Acces anonim la întregul site web: valoarea 2.
- Dar pentru a enumera toate site-urile avem nevoie de ceva mai mult. Articolul [3] lui Craig Trulove mi-a salvat destul de multă muncă, pentru că mi-a oferit posibilitatea de a identifica rapid o structură asemănătoare celei extrase de comanda stsadm și care să conțină și starea de acces a anonimilor la site.
- În scriptul de mai jos la linia 89 extrag în structura XML a infrastructurii valoarea parametrului de acces anonim. Copiați codul și salvați-l într-un fișier PS1.
1: # Autor: Craig Trulove
2: # WebPage: http://www.craigtothepoint.com/Lists/Posts/Post.aspx?ID=11
3: # Modified: Valy Greavu, valygreavu.com
4:
5: #Region Function Definition: EnumAllWebs
6: function EnumAllWebs
7: {
8: param
9: (
10: [string]$DatabaseName,
11: [string]$DatabaseServer
12: )
13: #Region Function Definition: FindSiteTemplateReference
14: # Checks to see if the specified template is installed in the farm
15: # Returns null if template is not found, returns the template if it is
16: function FindSiteTemplateReference
17: {
18: param
19: (
20: [int]$lcid,
21: [string]$TemplateName
22: )
23: foreach ($template in $templates)
24: {
25: if (($template.LCID -eq $lcid) -and ($template.Name -eq $TemplateName))
26: {
27: return $template
28: }
29: }
30: return $null
31: }
32: #EndRegion Function Definition: FindSiteTemplateReference
33: #Region Function Definition: ProcessOneContentDatabase
34: # Runs for each database
35: function ProcessOneContentDatabase
36: {
37: param
38: (
39: [System.Xml.XmlTextWriter]$writer,
40: [Microsoft.SharePoint.Administration.SPContentDatabase]$db
41: )
42: #Region Function Definition: OutputSiteXml
43: # Generates the XML for each site
44: function OutputSiteXml
45: {
46: param
47: (
48: [System.Xml.XmlTextWriter]$writer,
49: [Microsoft.SharePoint.SPSite]$site
50: )
51: $writer.WriteStartElement("Site")
52: $writer.WriteAttributeString("Id", $site.ID)
53: $writer.WriteAttributeString("OwnerLogin", $site.Owner.LoginName)
54: # Check if it is a host header site collection
55: if ($site.HostHeaderIsSiteName)
56: {
57: $writer.WriteAttributeString("HostHeader", $site.HostName)
58: }
59: if ($site.AllWebs.Count -gt 0)
60: {
61: $writer.WriteStartElement("Webs")
62: $writer.WriteAttributeString("Count", $site.AllWebs.Count)
63: foreach ($web in $site.AllWebs)
64: {
65: try
66: {
67: $reference = FindSiteTemplateReference -lcid $web.Language -TemplateName "$($web.WebTemplate)#$($web.Configuration)"
68: # Check if web template is properly installed
69: if ($reference -eq $null)
70: {
71: $str = "Unknown"
72: }
73: elseif ($web.Configuration -eq -1)
74: {
75: $str = [string]::Empty
76: }
77: else
78: {
79: $str = "$($web.WebTemplate)#$($web.Configuration)"
80: }
81: $writer.WriteStartElement("Web")
82: $writer.WriteAttributeString("Id", $web.ID)
83: $writer.WriteAttributeString("Url", $web.Url)
84: # Extract AnonymousState
85: # AnonymousState determines if anonymous users have access to the site collection as follows:
86: # A "0" disables anonymous access. In other words, anonymous users have no access to a Web site.
87: # A "1" allows default anonymous access. This specifies that anonymous users can access lists and libraries if the lists and libraries allow anonymous access.
88: # A "2" specifies that anonymous users can access the entire Web site.
89: $writer.WriteAttributeString("Anonymmous", $web.AnonymousState)
90: # Handle cases where str var not set or set to empty string
91: if (($str -ne $null) -and ($str -ne [string]::Empty))
92: {
93: $writer.WriteAttributeString("TemplateName", $str);
94: }
95: if ($web.Configuration -ne -1)
96: {
97: $writer.WriteAttributeString("TemplateId", $web.WebTemplate);
98: }
99: $writer.WriteEndElement()
100: }
101: catch [Exception]
102: {
103: }
104: finally
105: {
106: $web.Dispose()
107: }
108: }
109: # End element for webs
110: $writer.WriteEndElement()
111: }
112: # End element for site
113: $writer.WriteEndElement()
114: }
115: #EndRegion Function Definition: OutputSiteXml
116: $writer.WriteStartElement("Database")
117: $writer.WriteAttributeString("SiteCount", $db.CurrentSiteCount)
118: $writer.WriteAttributeString("Name", $db.Name)
119: $writer.WriteAttributeString("DataSource", $db.ServiceInstance.NormalizedDataSource)
120: # Only process sites if any exist
121: if ($db.Sites.Count -gt 0)
122: {
123: $writer.WriteStartElement("Sites")
124: foreach ($site in $db.Sites)
125: {
126: try
127: {
128: OutputSiteXml -writer $writer -site $site
129: }
130: catch [Exception]
131: {
132: }
133: finally
134: {
135: $site.Dispose()
136: }
137: }
138: # End element for sites
139: $writer.WriteEndElement()
140: }
141: #End element for database
142: $writer.WriteEndElement()
143: }
144: #EndRegion Function Definition: ProcessOneContentDatabase
145:
146: # Create bool vars for passing to sub functions
147: $local = Get-SPFarm
148: $services = New-Object Microsoft.SharePoint.Administration.SPWebServiceCollection $local
149: $cs = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
150: $templates = Get-SPWebTemplate
151: $StringWriter = New-Object System.IO.StringWriter
152: $writer = New-Object System.XMl.XmlTextWriter $StringWriter
153: $writer.Formatting = "indented"
154: $writer.WriteStartElement("Databases")
155: # if database was specifed process only that database
156: if ($DatabaseName)
157: {
158: # if databaseserver was not specified use default
159: if ($DatabaseServer -eq $null) { $DatabaseServer = $cs.DefaultDatabaseInstance.DisplayName }
160: $db = Get-SPContentDatabase -DatabaseName $DatabaseName -DatabaseServer $DatabaseServer
161: # Process database
162: ProcessOneContentDatabase -writer $writer -db $db
163: }
164: # otherwise process all databases
165: else
166: {
167: foreach ($service in $services)
168: {
169: foreach ($application in $service.WebApplications)
170: {
171: foreach ($database2 in $application.ContentDatabases)
172: {
173: # Process database
174: ProcessOneContentDatabase -writer $writer -db $database2
175: }
176: }
177: }
178: }
179: # End element for databases
180: $writer.WriteEndElement()
181: # Return output as string
182: $StringWriter.ToString()
183: $StringWriter.Flush()
184: $writer.Flush()
185: }
186: #EndRegion Function Definition: EnumAllWebs
187: # Call function
188: enumallwebs
Execuția:
.\enumallsubwebs.ps1 > C:\ScriptsOutput\AllSubWebs.xml
crează fișierul AllSubWebs.xml pe care-l putem deschide și analiza cu Excel.
Coloanele care ne interesează sunt:
- /Database/Sites/Site/Webs/Web/@Url – adresa URL a subsite-ului web
- /Database/Sites/Site/Webs/Web/@Anonim – starea de acces anonim care conține valorile: On, Disabled, Enabled
- Scriptul lui Craig conține o mică eroare care împiedică enumerarea corectă a site-urilor corespondente bazei de date MySite, dar de obicei această aplicație web nu se configurează pentru acces anonim.
- Fișierul XML deschis în Excel îl putem filtra pentru a identifica site-urile cu acces anonim, a le evalua în sensul dacă ele corespund politicilor instituției de acces. În cazul în care dorim să dezactivăm accesul anonim pentru anumite site-uri putem să compunem în Excel comenzile de dezactivare care trebuie să fie de felul următor:
1: # Preluare într-o variabilă PowerShell a valorii curente a site-ului care are activat acces anonim
2: $Web = Get-SPWeb http://home/site3/Site32/
3: # Dezactivarea accesului anonim.
4: $Web.AnonymousState = 0
5:
Operațiunea se repetă pentru toate site-urile ale căror acces anonim trebuie să fie dezactivat.
Succes!
Referințe:
- [1] Brian Beach, SharePoint 2010 & PowerShell: Anonymous Web Applications, http://blog.brianbeach.com/2010/11/sharepoint-2010-powershell-anonymous.html
- [2] Andre Galitsky, Enumerate SharePoint sites and subsites using PowerShell, http://sharepointnomad.wordpress.com/2009/05/08/enumerate-sharepoint-sites-and-subsites-using-powershell/
- [3] Craig Trulove,
Reproducing STSADM Functionality in PowerShell – Enumallwebs, http://www.craigtothepoint.com/Lists/Posts/Post.aspx?ID=11
va rugam un ajutor in instalarea sharepoint 2010; problema este
ca la instalare , dupa introducerea key-ului, nu apare optiunea de
a alege intre standalone si server farm ci trece direct la alegerea directorului de instalare (?!)
ApreciazăApreciază