m-dwyer / CryptoBlocker

A script to deploy File Server Resource Manager and associated scripts to block infected users
GNU General Public License v2.0
53 stars 103 forks source link

Filescreen group is not created #12

Open pvries86 opened 8 years ago

pvries86 commented 8 years ago

The script fails when it has to create a filescreen group with the command: &filescrn.exe Filegroup Add "/Filegroup:$fileGroupName" "/Members:$($monitoredExtensions -Join "|")"

I think this issue started showing recently, maybe because the list of extensions has become to large?

celtic-bear commented 8 years ago

I have almost the same issue. Script runs fine, but when I run old version it creates File Screen and File Group. When I am running new one it removes old all rules and not creating anything new.

celtic-bear commented 8 years ago

I've resolved the issue by making some changes in the code:

`

Function PurgeNonAdminDirectoryPermissions([string] $directory) { $acl = Get-Acl $directory

if ($acl.AreAccessRulesProtected)
{
    $acl.Access | % { $acl.PurgeAccessRules($_.IdentityReference) }
}
else
{
    $acl.SetAccessRuleProtection($true, $true)
}

$ar = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM","FullControl","Allow")
$acl.AddAccessRule($ar)
$ar = $ar = New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators","FullControl","Allow")
$acl.AddAccessRule($ar)
Set-Acl -AclObject $acl -Path $directory

}

function ConvertFrom-Json20([Object] $obj) { Add-Type -AssemblyName System.Web.Extensions $serializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer return ,$serializer.DeserializeObject($obj) } ################################ Functions ################################

Add to all drives

$drivesContainingShares = Get-WmiObject Win32Share | Select Name,Path,Type | Where-Object { $.Type -eq 0 } | Select -ExpandProperty Path | % { "$((Get-Item -ErrorAction SilentlyContinue $_).Root)" } | Select -Unique if ($drivesContainingShares -eq $null -or $drivesContainingShares.Length -eq 0) { Write-Host "No drives containing shares were found. Exiting.." exit }

Write-Host "The following shares needing to be protected: $($drivesContainingShares -Join ",")"

$majorVer = [System.Environment]::OSVersion.Version.Major $minorVer = [System.Environment]::OSVersion.Version.Minor

Write-Host "Checking File Server Resource Manager.."

Import-Module ServerManager

if ($majorVer -ge 6) { $checkFSRM = Get-WindowsFeature -Name FS-Resource-Manager

if ($minorVer -ge 2 -and $checkFSRM.Installed -ne "True")
{
    # Server 2012
    Write-Host "FSRM not found.. Installing (2012).."
    Install-WindowsFeature -Name FS-Resource-Manager -IncludeManagementTools
}
elseif ($minorVer -ge 1 -and $checkFSRM.Installed -ne "True")
{
    # Server 2008 R2
    Write-Host "FSRM not found.. Installing (2008 R2).."
    Add-WindowsFeature FS-FileServer, FS-Resource-Manager
}
elseif ($checkFSRM.Installed -ne "True")
{
    # Server 2008
    Write-Host "FSRM not found.. Installing (2008).."
    &servermanagercmd -Install FS-FileServer FS-Resource-Manager
}

} else {

Assume Server 2003

Write-Host "Other version of Windows detected! Quitting.."
return

}

$fileGroupName = "CryptoBlockerGroup" $fileTemplateName = "CryptoBlockerTemplate" $fileScreenName = "CryptoBlockerScreen"

$webClient = New-Object System.Net.WebClient $jsonStr = $webClient.DownloadString("https://fsrm.experiant.ca/api/v1/get")

Write-Host $jsonStr -BackgroundColor DarkGreen

$monitoredExtensions = @(ConvertFrom-Json20($jsonStr) | % { $_.filters })

$scriptFilename = "C:\FSRMScripts\KillUserSession.ps1" $batchFilename = "C:\FSRMScripts\KillUserSession.bat" $eventConfFilename = "$env:Temp\cryptoblocker-eventnotify.txt" $cmdConfFilename = "$env:Temp\cryptoblocker-cmdnotify.txt"

$scriptConf = @' param([string] $DomainUser)

Function DenySharePermission ([string] $ShareName, [string] $DomainUser) { $domainUserSplit = $DomainUser.Split("\")

$trusteeClass = [wmiclass] "ROOT\CIMV2:Win32_Trustee"
$trustee = $trusteeClass.CreateInstance()
$trustee.Domain = $domainUserSplit[0]
$trustee.Name = $domainUserSplit[1]

$aceClass = [wmiclass] "ROOT\CIMV2:Win32_ACE"
$ace = $aceClass.CreateInstance()
$ace.AccessMask = 2032127
$ace.AceType = 1
$ace.Trustee = $trustee

$shss = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter "Name='$ShareName'"
$sd = Invoke-WmiMethod -InputObject $shss -Name GetSecurityDescriptor | Select -ExpandProperty Descriptor

$sclass = [wmiclass] "ROOT\CIMV2:Win32_SecurityDescriptor"
$newsd = $sclass.CreateInstance()
$newsd.ControlFlags = $sd.ControlFlags

foreach ($oace in $sd.DACL)
{
    $newsd.DACL +=  [System.Management.ManagementBaseObject] $oace
}

$newsd.DACL += [System.Management.ManagementBaseObject] $ace

$share = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter "Name='$ShareName'"
$setResult = $share.SetSecurityDescriptor($newsd)

return $setResult.ReturnValue

}

Let's try altering share permissions..

$Username = $DomainUser.Split("\")[1]

$affectedShares = Get-WmiObject -Class Win32Share | Select Name, Path, Type | Where { $.Type -eq 0 }

$affectedShares | % { Write-Host "Denying [$DomainUser] access to share [$($.Name)].." DenySharePermission -ShareName $.Name -DomainUser $DomainUser }

Write-Host $affectedShares '@

$batchConf = @" @echo off powershell.exe -ExecutionPolicy Bypass -File "$scriptFilename" -DomainUser %1 "@

$scriptDirectory = Split-Path -Parent $scriptFilename $batchDirectory = Split-Path -Parent $batchFilename

if (-not (Test-Path $scriptDirectory)) { Write-Host "Script directory [$scriptDirectory] not found. Creating.." New-Item -Path $scriptDirectory -ItemType Directory }

if (-not (Test-Path $batchDirectory)) { Write-Host "Batch directory [$batchDirectory] not found. Creating.." New-Item -Path $batchDirectory -ItemType Directory }

FSRM stipulates that the command directories/files can only be accessible by SYSTEM or Administrators

As a result, we lock down permissions for SYSTEM and local admin only

Write-Host "Purging Non-Admin NTFS permissions on script directory [$scriptDirectory].." PurgeNonAdminDirectoryPermissions($scriptDirectory) Write-Host "Purging Non-Admin NTFS permissions on batch directory [$batchDirectory].." PurgeNonAdminDirectoryPermissions($batchDirectory)

Write-Host "Writing defensive PowerShell script to location [$scriptFilename].." $scriptConf | Out-File -Encoding ASCII $scriptFilename Write-Host "Writing batch script launcher to location [$batchFilename].." $batchConf | Out-File -Encoding ASCII $batchFilename

$eventConf = @" Notification=E RunLimitInterval=0 EventType=Warning Message=User [Source Io Owner] attempted to save [Source File Path] to [File Screen Path] on the [Server] server. This file is in the [Violated File Group] file group, which is not permitted on the server. An attempt has been made at blocking this user. "@

$eventConf = New-FsrmAction -Type Email -RunLimitInterval 0 -EventType Warning

$cmdConf = New-FsrmAction -Type Command -RunLimitInterval 0 -Command $batchFilename -CommandParameters [Source Io Owner]

$cmdConf = @" Notification=C RunLimitInterval=0 Command=$batchFilename Arguments=[Source Io Owner] MonitorCommand=Enable Account=LocalSystem "@

Write-Host "Writing temporary FSRM Event Viewer configuration to location [$eventConfFilename].." $eventConf | Out-File $eventConfFilename Write-Host "Writing temporary FSRM Command configuration to location [$cmdConfFilename].." $cmdConf | Out-File $cmdConfFilename

Write-Host "Adding/replacing File Group [$fileGroupName] with monitored file [$($monitoredExtensions -Join ",")].."

Remove-FsrmFileGroup -Name $fileGroupName New-FsrmFileGroup -Name $fileGroupName -IncludePattern @($monitoredExtensions)

Write-Host "Adding/replacing File Screen Template [$fileTemplateName] with Event Notification [$eventConfFilename] and Command Notification [$cmdConfFilename].." Remove-FsrmFileScreenTemplate $fileTemplateName

New-FsrmFileScreenTemplate -Name $fileTemplateName -IncludeGroup $fileGroupName -Notification

&filescrn.exe Template Add "/Template:$fileTemplateName" "/Add-Filegroup:$fileGroupName" "/Add-Notification:E,$eventConfFilename" "/Add-Notification:C,$cmdConfFilename" /Type:Passive

Write-Host "Adding/replacing File Screens.." $drivesContainingShares | % { Write-Host "`tAdding/replacing File Screen for [$_] with Source Template [$fileTemplateName].."

&filescrn.exe Screen Delete "/Path:$_" /Quiet
Write-Host filescrn.exe Screen Add "/Path:$_" "/SourceTemplate:$fileTemplateName"
&filescrn.exe Screen Add "/Path:$_" "/SourceTemplate:$fileTemplateName"

}

Write-Host "Removing temporary FSRM Event Viewer configuration file [$eventConfFilename].." Write-Host "Removing temporary FSRM Event Viewer configuration file [$cmdConfFilename].." Remove-Item $eventConfFilename Remove-Item $cmdConfFilename `

pvries86 commented 8 years ago

I see you are using the Powershell FSRM cmdlets. Unfortunately these do not work with Windows Server 2008 (R2). Any other solutions available that are compatible with Win2008 and newer?

celtic-bear commented 8 years ago

I found the the error in main script. when it is trying to create filegoups with extensions it cannot correctly convert that API to extensions, I thought it will be easier to just change to Powershell FSRM command :) I will try to check one more time and if I resolve the issue will post it here

celtic-bear commented 8 years ago

Only workaround that I was be able to do is to import with Powershell, export it and change script for 2008server not to create FileGroupTemplate, but import it from a network location. It is not creating this big list after HOW TO DECRYPT FILES.txt file

timwiserairit commented 8 years ago

Could you possibly release a version of the script that has that functionality baked in, please?

nreisbeck commented 8 years ago

I'll be submitting a PR with a workaround for this temporarily. I've refactored some code to leverage the built in native PowerShell cmdlets in 2012+ and also fixed the outstanding issue with the 2008 filescrn.exe command.

In short the filescrn add group command seemingly ran into an overflow condition right around 4 KB worth of char give or take and that completely broke the command.

The 2012+ cmdlets do not seem to exhibit this behavior and will happily (at this point) take the entire file extension array.

Sit tight and hopefully @m-dwyer will accept the pull request.

@celtic-bear can you please remove all of that garbage from your comment. Comments are not for submitting code in, thanks 👍

codaamok commented 7 years ago

@nreisb how did you identify an overflow was your obstacle?

nreisbeck commented 7 years ago

@CodaAmok The filescreen add was failing around the 3900-4000 character mark, which was close enough to the 4096 byte mark. This was enough to reasonably suspect that the filescrn.exe Screen Add could only accept 4096 bytes and the error handling in most legacy methods is not robust enough to catch and trap this condition.

I am still planning on submitting a PR for my refactored code which may be of some use for people, but it's taken a back burner to other work projects for the time being.

codaamok commented 7 years ago

@nreisb I spent yesterday trying to figure out why the below was failing. This issue pointed me in the right direction, so I just spent the last 30 minutes looking closer at the passed string ($x).

Invoke-Command -Session $session -ScriptBlock { param($x) cmd /c "Filescrn.exe Filegroup Add /Filegroup:Ransomware /Members:$x" } -Args $x

Unfortunately the errors given lead me to believe all day yesterday that I wasn't passing the variable correctly or the syntax was wrong.

I controlled $x's character count. 4097 worked OK but 4098 would fail: "The parameter is incorrect". Just to be sure, I played around with the chars before that hard limit to rule out an encoding issue but it's looking very likely that you're right.

Well spotted, I'm gutted I didn't think of that yesterday but glad I came across this repo.

Could you explain how your line solves this problem?

&filescrn.exe Filegroup Add "/Filegroup:$fileGroupName" "/Members:$($monitoredExtensions -Join "|")"

Edit: I may have wasted more time than I first thought. Despite using the Experiant list all along, I failed to read the install page that already highlights 4KB issue. Here is a solution (lines 12-51). I was thinking of something similar but I'm glad I found this as it's much simpler than the approach I was first thinking of.

Edit: it seems I'm late to the party, you use the same function. Moving on...

nreisbeck commented 7 years ago

&filescrn.exe Filegroup Add "/Filegroup:$fileGroupName" "/Members:$($monitoredExtensions -Join "|")" was the original code that just took ALL of the entires and put them in A group. Which eventually became too large and caused the command to fail

LN25-40 handles the 'get first 4096, back off one and write to group, get next 4096, etc.'

codaamok commented 7 years ago

@nreisb New-FsrmFileGroup takes 1kb strings, currently working on some lines using the fsrm cmdlets, will mod my fork when it's usable. Thankfully, @Kittzus 's PR provides the ground work.

Kittzus commented 7 years ago

@CodaAmok Glad to be of use! :)

Minkus32 commented 7 years ago

@Kittzus your script works well, however one thing none of the version so is enable a filescreen on the share path vs the entire drive. One of the problems with entire drive is that you cannot enable Active filtering if the shares are on C:\ as windows 2012 r2 blocks it. If you configure the screen on a path under C:\ it works great. Would love to see one that enumerates the shares and adds a screen for each one.

codaamok commented 7 years ago

@Minkus32 not strictly true, you can apply active screening to the system drive just not at the root of C: - you can apply to subfolders for example C:\Users. I am yet to post mine but I have a function which does just this: enumerates and creates file screens on absolute folder locations rather than entire drive, but only for the C: drive.

Minkus32 commented 7 years ago

that would be perfect. I am looking for something I an push to file servers in a scheduled basis that would auto protect them without me needing to login and adjust things so if you want me to test out your script let me know.

Minkus32 commented 7 years ago

I would love to test out that script as I have quite a few clients with shares on the C drives of their VM’s…

From: CodaAmok [mailto:notifications@github.com] Sent: Friday, January 06, 2017 3:54 PM To: m-dwyer/CryptoBlocker CryptoBlocker@noreply.github.com Cc: Minkus32 mark.hodges@shaw.ca; Mention mention@noreply.github.com Subject: Re: [m-dwyer/CryptoBlocker] Filescreen group is not created (#12)

@Minkus32https://github.com/Minkus32 not strictly true, you can apply active screening to the system drive just not at the root of C: - you can apply to subfolders for example C:\Users. I am yet to post mine but I have a function which does just this: enumerates and creates file screens on absolute folder locations rather than entire drive, but only for the C: drive.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/m-dwyer/CryptoBlocker/issues/12#issuecomment-271032533, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AXz3wQHAJLS02aQS8nixcrMKChn7MZNjks5rPsYcgaJpZM4JW_HP.

cjpalmer commented 7 years ago

The updated code for this does not appear to be available in Master and I can't see any branches. I can only see the new code when I click through the above. Is this still an outstanding issue as I would like to try the new code and see if it works in my environment. I am currently getting the error message from filescrn.exe on my 2008R2 server where I am testing this before I test it on my 2012R2 servers.