Опрос сети на предмет поиска уязвимых версий службы управления ключами SafeNet Sentinel License Manager (HASP License Manager)

Многим администраторам так или иначе приходилось в своей работе сталкиваться с аппаратными ключами защиты Alladin HASP/SafeNet Sentinel и приходилось устанавливать поставляемый в составе ПО поддержки этих ключей программный пакет HASP License Manager/Sentinel License Manager. Это приложение отвечает за контроль лицензий всевозможного ПО, используемого во множестве самых разных приложений, начиная с бизнес-систем типа и заканчивая разнообразными критичными для производственных процессов системами АСУ ТП.

Как правило, единожды установив это ПО, администратор не задумывается о необходимости его периодического обновления, так как не для всех очевидно то, что такое ПО может стать источником серьёзных проблем информационной безопасности, делая систему, на которой оно установлено, критически уязвимой и открывая новые векторы для возможных атак.

В Январе на сайте команды Kaspersky Lab Industrial Control Systems Cyber Emergency Response Team (ICS CERT) был опубликован интересный отчёт о проделанной работе по выявлению уязвимостей в программно-аппаратном комплексе SafeNet Sentinel компании Gemalto: Серебряная пуля для атакующего. Исследование безопасности лицензионных токенов.

Результатом работы, проделанной в 2016-2017 годах, стало обнаружение 14 серьёзных уязвимостей, информация по которым была передана вендору. Однако, как следует из пояснения Kaspersky Lab ICS CERT, должной огласки эта проблема так и не получила, так как вендор после исправления уязвимостей не сделал никаких публичных объявлений о необходимости скорейшего обновления. Поэтому мы решили не оставаться в стороне и включиться в процесс продвижения этой информации.

Для лучшего понимания серьёзности проблемы, мы наглядно продемонстрируем то, как легко эксплуатируется одна из уязвимостей на необновлённой версии ПО SafeNet Sentinel License Manager (LM). Но для начала стоит сказать пару слов о том, как устроен этот License Manager.

 

Общая информация о Sentinel License Manager

После установки пакета Sentinel LDK Run-time, в системный каталог Windows попадает приложение hasplms.exe, которое обеспечивает доступ локальных приложений к аппаратным лицензионными ключам (как правило, это USB-токены), подключенным к данному серверу, либо может выступать в качестве перенаправителя клиентских запросов на удалённые экземпляры License Manager.

Данное приложение работает, как служба Windows, в контексте привилегий служебного пользователя SYSTEM (локальная система):

 

Нетрудно догадаться о том, что эксплуатация возможных уязвимостей такой службы будет выполняться с высоко-привилегированным уровнем доступа к системе.

Служба hasplms открывает в системе TCP/UDP-прослушиватели, через которые и возможна, как локальная, так и удалённая, эксплуатация уязвимостей.

Занятно в этой ситуации то, что при установке пакета Sentinel LDK Run-time в системе (без какого-либо явного оповещения администратора) автоматически создаётся разрешающее правило Windows Firewall для приложения hasplms.exe. Этим правилом разрешён любой входящий трафик на любые порты, поэтому никаких проблем с доступностью из сети TCP–прослушивателя, открываемого службой на порту 1947, не возникает.

На указанном порту служба hasplms фактически имеет веб-сервер, с которым можно общаться по протоколу HTTP. В частности этот веб-сервер обеспечивает работу веб-сайта SafeNet Sentinel License Manager Admin Control Center (ACC), через который можно выполнять ряд административных действий по манипуляциям со службой управления ключами.

Сразу стоит отметить тот факт, что в конфигурации по умолчанию служба hasplms настроена таким образом, что удалённый доступ на порт 1947 запрещён, но зато на этот порт разрешены любые локальные подключения на localhost "не взирая на чины и звания". А это уже может стать реальной проблемой на многопользовательских системах, например на сервере с ролью Remote Desktop Services. Фактически на таких системах зачастую и оказывается ПО Sentinel, так как оно обеспечивает успешный запуск всевозможных бизнес приложений, использующих аппаратные ключи защиты. И получается, что на такой системе, любой непривилегированный пользователь может получить доступ веб-серверу License Manager.

 

Эксплуатация уязвимости

После небольшого захода в Интернет-поисковик, выяснилось, что в публичном доступе уже почти 2 года доступен эксплоит, позволяющий работать с одной из известных уязвимостей: Exploit Database - Gemalto Sentinel License Manager 18.0.1.55505 - Directory Traversal. На базе этой информации рассмотрим наглядный пример эксплуатации уязвимости с некорректной обработкой параметра alpremove в коде веб-страницы action.html веб-сервера License Manager.

Итак, предположим, что мы от имени простого непривилегированного пользователя вошли на сервер удалённых рабочих столов с ОС Windows Server 2012 R2 с запущенным в конфигурации по умолчанию License Manager. И предположим, на данной системе есть некоторый файл, к которому у нас нет доступа, но, который при этом, мы неистово желаем удалить, да и ещё не оставив после себя никаких следов.

Для примера я создал файл с именем "Important File.security" в корне системного диска C:\. Для чистоты эксперимента можно даже явным образом ограничить доступ к этому файлу так, чтобы он был доступен только Администраторам и локальной системе.

Имеющаяся в нашей необновлённой версии ПО Sentinel уязвимость позволяет удалить этот файл практически двумя последовательными GET-запросами. Выполнить эти запросы можно разными способами (тут всё зависит от сноровки атакующего). Мы будем использовать доступную по умолчанию всем пользователям системы оболочку Powershell:

Invoke-WebRequest -Uri "http://127.0.0.1:1947/_int_/action.html?alpremove=/../../../../../../../Important File.security"
Invoke-WebRequest -Uri "http://127.0.0.1:1947/_int_/action.html?alpremove=/../../../../../../../Important File.security"

Первый запрос переименует целевой файл, добавив к имени файла расширение "bak", то есть в нашем случае имя файла изменится на "Important File.security.bak"

Здесь хорошо видно, что веб-сервер LM успешно "проглотил" наш запрос и ещё в ответе рассказал нам о своей версии.

Вторым точно таким же GET-запросом ранее переименованный bak-файл будет удалён.

image

Напомню, что веб-сервер LM выполняется от имени SYSTEM, и поэтому у нас не возникает никаких проблем с доступом при удалении файла. При этом в системе от выполненного деструктивного действия фактически не остаётся никаких следов, которые бы могли в дальнейшем помочь администратору при выяснении причин случившегося.

Более сложный вид будет иметь задача изменения любого существующего в системе файла, реализуемая путём отсылки POST-запроса HTTP, пример которого рассмотрен здесь. Но я думаю, что продемонстрированной возможности несанкционированного действия более чем достаточно для того, чтобы принять решение о необходимости обновления License Manager до актуальной версии.

В рассмотренном примере мы действовали на уровне локального доступа, но если License Manager находится в конфигурации по умолчанию, то нам не составит труда получить локальный доступ к веб-консоли Sentinel License Manager Admin Control Center (ACC), открыв в веб-браузере адрес:

http://127.0.0.1:1947/

В АСС мы можем перейти в раздел Configuration и легким движением руки включить выключенный по умолчанию удаленный доступ Allow Remote Access to ACC:

Начиная с этого момента эксплуатировать уязвимости LM можно будет по сети, не имея локального доступа к данному серверу.

На тот случай, если нужно включить удалённый доступ, но браузер пользователю недоступен, в функционале License Manager Admin API, имеется параметр <accremote>, который через функцию Set может быть установлен в 1, что будет равнозначно включению опции Allow Remote Access to ACC через браузер.

Итак, наличие проблемы на старых версиях LM очевидно. Теперь нужно определиться с тем, на каких системах в нашей сети установлено данное ПО, чтобы оценить масштаб проблемы и запланировать объём необходимой работы по обновлению. Ведь не стоит забывать про то, что данное ПО может быть не только на серверных системах, но и, в ряде случаев, на клиентских системах.

 

Обнаружение уязвимых хостов

Для обнаружения уязвимых систем могут использоваться самые разные механизмы. Здесь всё зависит от нашей фантазии и текущих возможностей. Например можно воспользоваться возможностями продуктов Microsoft System Center, если такие имеются в инфраструктуре, – будто проверка BaseLine в SCCM или самописный Management Pack в SCOM. Любой метод будет иметь свои преимущества и недостатки. Здесь я приведу пример нехитрого PowerShell-скрипта, как наиболее доступного инструмента для любого Windows-администратора.

В начальных строках скрипта задаём переменные:

  • $StartScanIP - Начальный IP адрес диапазона сканирования сети;
  • $EndScanIP - Конечный IP диапазона;
  • $HTTPport - Номер порта на котором запущен HTTP-сервер на базе LM;
  • $ActualVersionMask – Интересующая нас маска имени веб-сервера, получаемого в HTTP-ответе;
  • $ActualVersionFull - Имя веб-сервера для актуальной на данный момент версии LM.

Для ускорения процесса сканирования скрипт работает множеством потоков, поэтому нагрузка на систему, где он будет запущен, может быть ощутимой. Обратите также внимание на величину, указанную в $WebRequest.Timeout. Если сканирование будет выполняться в сетях не очень хорошего качества (сильная загрузка сети, потери пакетов и т.п.), то возможно имеет смысл увеличить значение этого параметра. Но нужно понимать, что это приведёт к увеличению общего времени сканирования.

[System.Net.IPAddress]$StartScanIP = "10.1.0.1"
[System.Net.IPAddress]$EndScanIP =   "10.1.0.254"
[int]$HTTPport = "1947"
[string]$ActualVersionMask = "HASP LM/*"
[string]$ActualVersionFull = "HASP LM/20.05"
#
$Watch = [System.Diagnostics.Stopwatch]::StartNew()
$Watch.Start()
#
$ScanIPRange = @() 
if($EndScanIP -ne $null) 
{
  $StartIP = $StartScanIP -split '\.' 
  [Array]::Reverse($StartIP)   
  $StartIP = ([System.Net.IPAddress]($StartIP -join '.')).Address  
  #               
  $EndIP = $EndScanIP -split '\.' 
  [Array]::Reverse($EndIP)   
  $EndIP = ([System.Net.IPAddress]($EndIP -join '.')).Address  
  #               
  For ($x=$StartIP; $x -le $EndIP; $x++) {     
      $IP = [System.Net.IPAddress]$x -split '\.' 
      [Array]::Reverse($IP)    
      $ScanIPRange += $IP -join '.'  
  }
} 
  else 
{ 
 $ScanIPRange = $StartScanIP 
} 

Workflow Network-Scan{
  param($ippool,$port)    
  $WFResult = @()
  foreach -parallel -throttlelimit 50 ($ip in $ippool)
  {
    $ItemReturn = inlinescript
    {
       [uri]$Url = "http://" + $USING:ip + ":" + $USING:port
       $WebRequest = [System.Net.WebRequest]::Create($Url)
       $WebRequest.Timeout = 1000 #Default 600000
       $WebRequest.AuthenticationLevel = "None"
       $WebRequest.Method = "HEAD"
       try{
           $WebResponse = $WebRequest.GetResponse()
       }
       catch [System.Net.WebException]{
             $WebResponse = $_.Exception.Response
       }
       If ($WebResponse.Server) {
          try{
             $hName = [System.Net.Dns]::GetHostByAddress($USING:ip).HostName
          } 
          catch{
             $hName = " - "
          }
          $Item = New-Object System.Object
          $Item | Add-Member -MemberType NoteProperty -Name "SrvIP" -Value $USING:ip
          $Item | Add-Member -MemberType NoteProperty -Name "SrvName" $hName
          $Item | Add-Member -MemberType NoteProperty -Name "Version" $WebResponse.Server
          $Item | Add-Member -MemberType NoteProperty -Name "Status" $WebResponse.StatusCode
             return $Item
       }        
     } #inlinescript
     $WORKFLOW:WFResult += $ItemReturn
   }
  return $WORKFLOW:WFResult
}
$Result = Network-Scan $ScanIPRange $HTTPport
$Result | Sort-Object Version,SrvIP,Status | Format-Table -GroupBy Version -Autosize `
  @{Name="Host IP address";Expression = { $_.SrvIP }; Alignment="Center"},
  @{Name="Host name from DNS";Expression = { $_.SrvName }; Alignment="Center"},
  @{Name="HTTP-server version";Expression = { $_.Version };Alignment="Center"},
  @{Name="Remote HTTP status";Expression = { $_.Status };Alignment="Center"},
  @{Name="Update is required";Expression = { 
     if (
     ($_.Version -like $ActualVersionMask) -and 
     ($_.Version -notlike $ActualVersionFull)) {"Yes"} 
     else {"No"} 
  };Alignment="Center"}
  
Write-Host $Result.Count "hosts found on network range " $StartScanIP "-" $EndScanIP
$Watch.Stop()
Write-Host "Script time:" $Watch.Elapsed

В результате работы скрипта мы должны получить отсортированный по версиям LM список хостов:

   Version: HASP LM/16.00

Host IP address   Host name from DNS   HTTP-server version Remote HTTP status Update is required
---------------   ------------------   ------------------ ------------------ ------------------
 10.1.0.93       kom-rds83.holding.com   HASP LM/16.00        Forbidden             Yes        
 10.1.0.94       kom-rds84.holding.com   HASP LM/16.00           ОК                 Yes        
 10.1.0.95       kom-rds85.holding.com   HASP LM/16.00        Forbidden             Yes        


   Version: HASP LM/20.05

Host IP address   Host name from DNS    HTTP-server version Remote HTTP status Update is required
---------------  ------------------     ------------------- ------------------ ------------------
 10.1.0.20       kom-lic56.holding.com    HASP LM/20.05        Forbidden             No        


4 hosts found on network range  10.1.0.1 - 10.1.0.254
Script time: 00:00:09.1204247

В вывод попадают только те хосты, с которых получен ответ на HTTP-запрос, выполненный на проверяемый нами порт 1947. В данном примере мы обнаружили 4 сервера с доступной из сети службой LM. На всех четырёх хостах получен HTTP-ответ от LM, причём на одном из хостов включен удалённый доступ к ACC - статус ОK, то есть получен HTTP-код 200. На всех остальных хостах удалённый доступ выключен - статус Forbidden, то есть получен HTTP-код 403. Три хоста имеют старые уязвимые версии LM и требуют обновления.

 

Обновляемся и усиливаем защиту Sentinel License Manager

После получения списка уязвимых систем, нам нужно выполнить обновление ПО Sentinel LDK Run-time по рекомендации Kaspersky Lab ICS CERT до версии не ниже 7.6.

Последнюю актуальную версию ПО можно скачать с сайта Gemalto Sentinel Customer Community 

На данный момент времени там фигурирует пакет Sentinel HASP LDK Windows GUI Run-time Installer версии 7.65 (файл HASPUserSetup.exe), который включает в себя License Manager версии 20.05

Обратите внимание на то, что по завершению установки инсталлятор, с подозрительно улыбающимися гражданами, как бы предлагает нам подумать о том, что нужно бы открыть порт 1947

Однако комичность ситуации заключается в том, что, как и в старых версиях, инсталлятор сам создаёт нескромное разрешающее правило в Windows Firewall, не спрашивая об этом у администратора. Это как раз одна из странностей, на которую обращают внимание в своей статье специалисты Kaspersky Lab ICS CERT.

После завершения установки можно откорректировать созданное инсталлятором правило Windows Firewall, сузив до разумных пределов область разрешений (например, как минимум, разрешив подключения только с IP-подсетей, где есть клиенты использующие ключи с данного LM)

Либо если удалённый доступ к службе управления ключами не требуется, а служба используется только локально приложениями на сервере (когда лицензионные ключи установлены в самом сервере, либо когда ключи установлены в другом сервере и данный LM работает в режиме проксирования запросов на сторонний LM) данное правило Windows Firewall можно попросту отключить.

Обратите внимание на то, что после переустановки или установки новой версии (обновления) инсталлятор перепишет данное правило Windows Firewall, заново разрешив доступ к службе "везде и вся". Не забывайте про это при последующих обновлениях.

После обновления ПО до актуальной версии, весьма желательно задать пароль для ограничения доступа к ACC, чтобы даже в случае локального доступа к ACC у непривилегированных пользователей не было возможности беспрепятственно менять конфигурацию сервера LM (например включать удалённый доступ к нему).

Для этого в обновлённой версии АСС мы можем перейти в раздел Configuration, переключить Password Protection в режим защиты всех веб-страниц All ACC Pages, а также кнопкой Change Password задать пароль для ограничения доступа к веб-серверу:

Кстати здесь же внизу страницы мы увидим имя конфигурационного файла, в котором LM и хранит всю заданную конфигурацию.

После проведённых мероприятий по обновлению и усилению защиты всех установленных экземпляров Sentinel License Manager, можно повторно запустить скрипт сканирования сети.

Только один комментарий Комментировать

  1. sergikotikov /

    Спасибо, только не совсем понят кто уязвим в вашем примере

Добавить комментарий