
Сканер и анализатор веб-шеллов.
Анализатор веб-шеллов — это кроссплатформенный автономный бинарный файл, созданный исключительно для идентификации, декодирования и маркировки файлов, подозреваемых в том, что они являются веб-шеллами. Анализатор веб-шеллов является старшим братом проекта web shell scanner (http://github.com/tstillz/webshell-scan), который только сканирует файлы с помощью регулярных выражений, без декодирования или анализа атрибутов.
Регулярные выражения и встроенные процедуры декодирования, поставляемые со сканером, не гарантируют обнаружения каждого веб-шелла на диске и могут давать ложные срабатывания. Также рекомендуется протестировать анализатор и оценить его влияние перед запуском на производственных системах. Анализатор не имеет гарантии, используйте его на свой страх и риск.
PHP, ASP/X. JSP/X, CFM и другие типы в разработке.Каждый сканируемый файл может быть обработан через PRE и/или POST действия:
Идея функций PreDecodeActions заключалась в использовании регулярных выражений для идентификации совпадающей строки или шаблона, захвате необработанного совпавшего содержимого, выполнении определенных шагов декодирования/очистки и отправке конечного вывода обратно в механизм анализа для повторного сканирования/обработки. Очень простым примером этого является декодирование Base64. Чтобы проверить любую логику обнаружения для веб-шелла, закодированного в base64, мы должны сначала удалить все уровни base64. Для этого мы можем использовать следующее PreDecodeAction:
{
Name: "PHP_Base64Decode",
Regex: *regexp.MustCompile(`(?i)(?:=|\s+)(base64_decode\('('?\"?[A-Za-z0-9+\/=]+'?\"?))`),
DataCapture: *regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]+(?:'|"))`),
PreDecodeActions: []cm.Action{
{Function: cm.StringReplace, Arguments: []interface{}{"\"", "", -1}},
{Function: cm.StringReplace, Arguments: []interface{}{"'", "", -1}},
},
Functions: []cm.Base_Func{cm.DecodeBase64},
},
Глядя на блок выше, у нас есть имя функции, регулярное выражение для сопоставления, регулярное выражение для захвата данных (иногда можно настроить, что захватывать по сравнению с тем, что сопоставляется) и PreDecodeActions. В этом случае ДО применения функции cm.DecodeBase64 к совпадающему тексту система сначала удалит следующие элементы: " и '. PostDecodeActions работает наоборот, когда вывод проверяется ПОСЛЕ выполнения декодирования. Используя эту модель, мы можем создавать несколько пользовательских декодеров с бесконечными PRE/POST и функциями декодирования для удовлетворения большинства потребностей анализа веб-шеллов.
Обнаружение — это регулярное выражение, сопровождаемое именем и описанием. Идея этой модели заключалась в том, чтобы сделать обнаружения модульными и масштабируемыми, сохраняя контекст с фактическим обнаружением. Обнаружения имеют тот же формат, что и атрибуты, за исключением того, что атрибуты не могут генерировать обнаружение, они могут только добавлять контекст к существующему обнаружению. Давайте посмотрим на пример блока логики обнаружения ниже:
{
Name: "Generic_Embedded_Executable",
Description: "Looks for magic bytes associated with a PE file",
Regex: *regexp.MustCompile(`(?i)(?:(?:0x)?4d5a)`),
},
Основываясь на регулярном выражении, мы видим, что оно ищет встроенный Windows PE файл по магическим байтам заголовка 4D 5A. Если найдено, это приведет к обнаружению, и для файла будет сгенерирован JSON-отчет. В настоящее время обнаружения применяются на основе расширения файла или универсально для всех типов файлов. Например, процедуры декодирования для PHP определены в cm.GlobalMap.Function_Php, а теги для атрибутов определены в cm.GlobalMap.Tags_Php. Функции cm.GlobalMap.Function_Generics и теги в cm.GlobalMap.Tags_Generics применяются ко ВСЕМ расширениям веб-шеллов в качестве универсального средства.
Маркировка атрибутов — это новая концепция, которую я создал, которая добавляет «контекст» к существующему обнаружению веб-шелла. Одни атрибуты не могут в настоящее время генерировать обнаружение самостоятельно. В традиционном механизме сканирования сканер просто предупреждал бы, если обнаружен веб-шелл, но не предоставлял бы дополнительного контекста о возможностях (атрибутах) веб-шелла. Теги атрибутов работают так же, как логика обнаружения, однако они отображаются только после того, как обнаружение было идентифицировано, и не могут генерировать обнаружения самостоятельно. Посмотрим на пример логики ниже:
cm.GlobalMap.Tags_Php = []cm.TagDef{
{
Name: "PHP_Database_Operations",
Description: "Looks for common PHP functions used for interacting with a database.",
Regex: *regexp.MustCompile(`(?i)(?:'mssql_connect\|mysql_exec\()`),
Attribute: true,
},
}
Мы видим, что в структуре Tags_Php мы создали новый PHP-тег. Когда во время сканирования найдено совпадение, проверяется флаг Attribute, и если он установлен в True, обнаруженный веб-шелл получит тег PHP_Database_Operations, добавленный в его JSON-отчет вместе с частотой и блоком совпавшего текста, как показано в примере вывода ниже:
{
"filePath": "/testers/1.php",
"size": 66109,
"md5": "6793d8ebab93e5a0f91e5a331221f331",
"timestamps": {
"birth": "2019-02-03 02:02:22",
"created": "2020-07-29 02:50:15",
"modified": "2019-02-03 02:02:22",
"accessed": "2020-07-29 02:51:07"
},
"matches": {
"FilesMAn": 5,
"FilesMan": 29,
"cmd": 20,
"eval(": 4,
"exec(": 2,
"ipconfig": 1,
"netstat": 2,
"passthru(": 1,
"shell_exec(": 1
},
"decodes": {
"Generic_Base64Decode": 40,
"Generic_Multiline_Base64Decode": 165
},
"tags": {
"Generic_Embedding_Code_C": {
"bind(": 2,
"listen(": 2
},
"PHP_Banned_Function": {
"exec(": 3,
"get_current_user(": 1,
"getmyuid(": 1,
"link(": 7,
"listen(": 2,
"passthru(": 1,
"realpath(": 1,
"set_time_limit(": 1
},
"PHP_Database_Operations": {
"mysql_query(": 1
},
"PHP_Disk_Operations": {
"@chmod(": 1,
"@filegroup(": 4,
"@fileowner(": 4,
"@rename(": 2,
"fopen(": 7,
"fwrite(": 6
}
}
}
Эти теги не только помогают определить, что может делать веб-шелл, но и предоставляют таким командам, как консультанты по реагированию на инциденты (IR), выполняющим живые реагирования, точку опоры для того, куда потенциально смотреть дальше.
Никаких! Просто загрузите бинарный файл для вашей ОС, укажите каталог, который вы хотите сканировать (остальные аргументы необязательны), и вперед.
Запуск wsa без аргументов показывает следующие параметры:
/Users/beastmode$ ./wsa
Options:
-dir string
Directory to scan for web shells
-pretty
If set to true, the analyzer will output the results in a json indented form
-raw_contents
If a match is found, grab the raw contents and base64 + gzip compress the file into the JSON object.
-size int
Specify max file size to scan (default is 10 MB) (default 10)
-verbose
If set to true, the analyzer will print all files analyzer, not just matches
Единственный обязательный аргумент — dir. Вы можете переопределить другие настройки программы по умолчанию, если хотите.
Вывод анализатора будет записан на консоль (стандартный вывод). Пример ниже (для лучших результатов перенаправьте стандартный вывод в json-файл и просматривайте/обрабатывайте в автономном режиме):
Linux: ./wsa -dir /opt/www
Windows: wsa.exe -dir C:\Windows\Inetput\wwwroot
### With STDOUT and full web shell file encoded and compressed:
Linux: ./wsa -dir /opt/www -raw_contents=true > scan_results.json
После завершения анализатор выведет общие метрики сканирования в STDOUT, как показано в примере ниже:
{"scanned":311,"matches":122,"noMatches":189,"directory":"/webshell-master/php","scanDuration":1.4757737378333333,"systemInfo":{"hostname":"Beast","envVars":[""],"username":"beastmode","userID":"501","realName":"The Beast","userHomeDir":"/Users/beastmode"}}