При открытии терминального сервера "наружу" неизбежно придет время, когда вы обнаружите в логах системы большое количество попыток подбора логина и пароля, которые, при большом потоке данных, могут банально заDDOSить сервер до полной невозможности работы пользователей. Да, есть и VPN, и проверка подлинности на уровне сети, и смена номера порта на роутере и т.д,, но все равно проходят и атаки идут. Так усложним им работу :)
Потребуется:
- Windows 2008+
- Скрипт
- База данных (Access файл или MS SQL)
- Настроенный брэндмауэр Windows (даже если сервер у вас за внешним файрволом)
Идея работы: ловим событие аудита отказа логина, помечаем адрес злоумышленника в базе, считаем сколько раз событие произошло и, при достижении определенного порога, делаем новую блокирующую запись в правилах файрволла.
В 2008+ сервере появилась возможность выполнить задачу при наступлении определенного события, так воспользуеся этим.
Создадим новую задачу по событию аудита отказа входа в систему, которая будет запускать VBS скрипт.
После создания задачи нужно открыть ее свойства и поставить галку "Выполнять с наивысшими правами".
Теперь нужно определиться, как передать параметры из события, в частности, интересует IP-адрес, с которого идет подбор паролей, и подбираемый логин. В Windows, как всегда, напрямую сделать нельзя, поэтому пойдем через черный ход.
В планировщике заданий находим созданную нами задачу, нажимаем на ней правой кнопкой и выбираем пункт "Экспортировать". Сохраняется файл в формате XML.
Сохранили? Теперь откроем файл в Блокноте и допишем следующие блоки, выделенные желтым цветом. Внимание, верстка немного едет, если что - см. рис 7.
- <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
- <RegistrationInfo>
- <Date>2013-12-02T22:50:07.3872408>
- <Author>X>
- >
- <Triggers>
- <EventTrigger>
- <Enabled>true>
- <Subscription><QueryList><Query Id="0" Path="Security"><Select Path="Security">*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4625]]</Select></Query></QueryList>>
- <ValueQueries>
- <Value name="TargetUserName">Event/EventData/Data[@Name='TargetUserName']>
- <Value name="IpAddress">Event/EventData/Data[@Name='IpAddress']>
- >
- >
- >
- <Principals>
- <Principal id="Author">
- <UserId>X>
- <LogonType>Password>
- <RunLevel>LeastPrivilege>
- >
- >
- <Settings>
- <MultipleInstancesPolicy>IgnoreNew>
- <DisallowStartIfOnBatteries>true>
- <StopIfGoingOnBatteries>true>
- <AllowHardTerminate>true>
- <StartWhenAvailable>false>
- <RunOnlyIfNetworkAvailable>false>
- <IdleSettings>
- <StopOnIdleEnd>true>
- <RestartOnIdle>false>
- >
- <AllowStartOnDemand>true>
- <Enabled>true>
- <Hidden>false>
- <RunOnlyIfIdle>false>
- <WakeToRun>false>
- <ExecutionTimeLimit>P3D>
- <Priority>7>
- >
- <Actions Context="Author">
- <Exec>
- <Command>C:\Windows\System32\cscript.exe>
- <Arguments>C:\Users\dmitry\BLOCK\RDP.vbs '$(TargetUserName)' '$(IpAddress)'>
- >
- >
- >
Сохраняем файл, удаляем старую задачу и там же импортируем новую из скорректированного способа. Таким вот затейливым способом можно распарсить данные в XML файле события и передать их в качестве параметров в нужный нам скрипт.
Собственно скрипт.
- Dim ipAddress, idLogin
- Const adOpenStatic = 3
- Const adLockOptimistic = 3
- Const toBlock = 4
- Set objConnection = CreateObject("ADODB.Connection")
- Set objRecordSet = CreateObject("ADODB.Recordset")
- Set objRecordSet2 = CreateObject("ADODB.Recordset")
- if wscript.arguments.count > 0 then
- idLogin = wscript.arguments.item(0)
- ipAddress = wscript.arguments.item(1)
- else
- idLogin = "---"
- ipAddress = "---"
- end if
- ' настраивам подключение к хранилищу
- ' в качестве хранилища может использоваться база данных как MS SQL, так и обычная база MS Access
- objConnection.Open _
- "Provider=SQLOLEDB;Data Source=cloud-sql;" & _
- "Trusted_Connection=Yes;Initial Catalog=RDP_BlockIP;" & _
- "User ID=RDP_BlockIP;Password=RDP_BlockIP;"
- ' отметим в базе что была попытка подключения с ipAddress с логином idLogin
- objRecordSet.Open "insert into dbo.IP values (GETDATE(), " & ipAddress & ", " & idLogin & ", null)", _
- objConnection, adOpenStatic, adLockOptimistic
- Dim wsh
- Set wsh = WScript.CreateObject("WScript.Shell")
- ' посчитаем, сколько раз за 24 часа было попыток подключения с указанного адреса
- ' считается только для адресов, которые не входят в адреса-исключения и не были уже обработаны ранее
- objRecordSet.Open "SELECT COUNT(LoginDate) as Attempts FROM [RDP_BlockIP].[dbo].IP WHERE [LoginDate] > GETDATE()-1 and (not [IP] in (select * from [RDP_BlockIP].[dbo].exclude_ip)) and (Done is null) and [IP] = " & ipAddress , _
- objConnection, adOpenStatic, adLockOptimistic
- objRecordSet.MoveFirst
- Dim fso, tf
- ' Сделаем событиный файл, который подхватит jabber-робот и пришлет адресату
- ' Можно убрать или заменить на отправку почты, или что-то еще
- Set fso = CreateObject("Scripting.FileSystemObject")
- Set tf = fso.CreateTextFile("\\betta\jabber\audit_rdp.txt", True)
- tf.WriteLine("dmitry@192.168.0.3")
- tf.WriteLine("********** RDP ALERT src: " & ipAddress & ", usr: " & idLogin & "**********")
- tf.WriteBlankLines(3)
- tf.Close
- ' По этоу строку можно удалять, если не требуется
- Do Until objRecordSet.EOF
- ' Если попыток подбора больше определенного значения...
- if (objRecordSet("Attempts") >= toBlock) and (Len(ipAddress)>4) Then
- ' ...то добавим в файрволл windows ipAddress с политикой блокировки доступа к порту 3389
- wsh.Run("netsh advfirewall firewall add rule name=RDP_AUTOBLOCK_" & Replace(ipAddress,"'","") & " dir=in action=block profile=any remoteip=" & Replace(ipAddress,"'","") & " localport=3389 protocol=tcp")
- ' Тут можно сделать СМС-оповещение, etc
- Set wsh = Nothing
- ' Пометим что для указанного адреса все события обработаны
- objRecordSet2.Open "update [RDP_BlockIP].[dbo].IP set [done]=1 where [IP] =" & ipAddress , _
- objConnection, adOpenStatic, adLockOptimistic
- end if
- objRecordSet.MoveNext
- Loop
Скрипт работает с базой (в примере с MS SQL), поэтому база должна быть, как и пользователь, с которым производится подключение.
Структура таблиц банальна (см. рис.). Первая таблица накапливает данные по IP-адресам, вторая предназначеня для адресов-исключений.
Итог работы.
Потираем руки и смотрим, как появляются новый записи при попытках брутфорса:
Обновление
Список часто подбираемых логинов, зафиксированных этим скриптом за 2 месяца
@dmin | alohasvr | denis | pos005 | test1 | Деректор |
1 | amberpos | gateway | pos05 | test3 | Директор |
123 | amministratore | guest | pos1 | user | дом |
1234 | an | home | pos2 | user1 | иванов |
12345 | angel | john | pos3 | User2 | Лена |
1234567 | aspnet | jose | pos4 | user3 | менеджер |
333 | augusto | Justin | pos5 | user4 | Нотариус |
666 | backup | kassa | raquel | user5 | пользователь |
777 | Boss | kasse_1 | rdspos | user6 | пользователь1 |
a | bruno | kasse1 | reception | usertask | склад |
actuser | Buh | Marko | root | zxc123 | смирнов |
adm | buh1 | max | sales | Админ | смирнова |
admin | buhgalter | Melissa | scan | Администратор | тест |
admin1 | caisse | micros | server | Алекс | |
admin2 | carlos | office | servr | Александр | |
administrator | comp3 | operator | sklad | Александра | |
administrator1 | cthsq29 | owner | support | алена | |
akapos | DataCenter | padicheva | support_388945a | бухгалтер | |
aloha01 | david | pochta | sys | главбух | |
alohaedc | debbie | pos | test | гость |