Google Chrome Detection (Windows)
| Source | Link |
|---|---|
| www.google.com/chrome/ |
#
# (C) Tenable Network Security, Inc.
#
include("compat.inc");
if (description)
{
script_id(34196);
script_version("1.27");
script_set_attribute(attribute:"plugin_modification_date", value:"2025/07/10");
script_xref(name:"IAVT", value:"0001-T-0511");
script_name(english:"Google Chrome Detection (Windows)");
script_set_attribute(attribute:"synopsis", value:
"The remote Windows host contains a web browser.");
script_set_attribute(attribute:"description", value:
"Google Chrome, a web browser from Google, is installed on the remote
Windows host.");
script_set_attribute(attribute:"see_also", value:"https://www.google.com/chrome/");
script_set_attribute(attribute:"solution", value:
"n/a");
script_set_attribute(attribute:"agent", value:"windows");
script_set_attribute(attribute:"risk_factor", value:"None");
script_set_attribute(attribute:"plugin_publication_date", value:"2008/09/12");
script_set_attribute(attribute:"plugin_type", value:"local");
script_set_attribute(attribute:"asset_inventory", value:"True");
script_set_attribute(attribute:"asset_inventory_category", value:"software_enumeration");
script_set_attribute(attribute:"cpe", value:"cpe:/a:google:chrome");
script_set_attribute(attribute:"thorough_tests", value:"true");
script_end_attributes();
script_category(ACT_GATHER_INFO);
script_family(english:"Windows");
script_copyright(english:"This script is Copyright (C) 2008-2025 and is owned by Tenable, Inc. or an Affiliate thereof.");
script_dependencies("smb_hotfixes.nasl");
script_require_keys("SMB/Registry/Enumerated");
script_require_ports(139, 445);
exit(0);
}
include("smb_func.inc");
include("install_func.inc");
include("collection_metadata.inc");
var app = "Google Chrome";
var fa_app_name = "chrome";
# Walk up the path and check if each directory
# in the path is a reparse point.
function reparse_points_exist_in_path(check_path)
{
local_var check_ret;
while (check_path != "\" && strlen(check_path) > 0)
{
check_ret = FindFirstFile(pattern:check_path);
# Look for reparse point directories
# in file attributes.
if (!isnull(check_ret[2]) &&
# FILE_ATTRIBUTE_DIRECTORY
((check_ret[2] >> 4) & 0x1) &&
# FILE_ATTRIBUTE_REPARSE_POINT
((check_ret[2] >> 10) & 0x1)
)
return TRUE;
check_path = ereg_replace(
pattern:"^(.*)\\([^\\]*)?$",
replace:"\1",
string:check_path
);
}
return FALSE;
}
get_kb_item_or_exit("SMB/Registry/Enumerated");
# Connect to the appropriate share.
var name = kb_smb_name();
var port = kb_smb_transport();
#if (!get_port_state(port)) audit(AUDIT_PORT_CLOSED, port);
var login = kb_smb_login();
var pass = kb_smb_password();
var domain = kb_smb_domain();
#soc = open_sock_tcp(port);
#if (!soc) audit(AUDIT_SOCK_FAIL, port);
#session_init(socket:soc, hostname:name);
if(!smb_session_init()) audit(AUDIT_FN_FAIL, 'smb_session_init');
var rc = NetUseAdd(login:login, password:pass, domain:domain, share:"IPC$");
if (rc != 1) {
NetUseDel();
audit(AUDIT_SHARE_FAIL, "IPC$");
}
# Connect to remote registry.
var hklm = RegConnectRegistry(hkey:HKEY_LOCAL_MACHINE);
if (isnull(hklm))
{
NetUseDel();
audit(AUDIT_REG_FAIL);
}
# Determine possible paths where it might be installed.
var paths = make_array();
var path_keys = make_array();
var keys = make_list(
"SOFTWARE\Classes\Applications\chrome.exe\shell\open\command",
"SOFTWARE\Classes\ChromeHTML\shell\open\command",
"SOFTWARE\Clients\StartMenuInternet\chrome.exe\shell\open\command",
"SOFTWARE\Clients\StartMenuInternet\Google Chrome\shell\open\command"
);
var path = NULL;
var key_h, item, exe, lcpath;
foreach var key (keys)
{
key_h = RegOpenKey(handle:hklm, key:key, mode:MAXIMUM_ALLOWED);
if (!isnull(key_h))
{
item = RegQueryValue(handle:key_h, item:NULL);
if (!isnull(item))
{
# nb: the exe itself appears in quotes.
exe = ereg_replace(pattern:'^"([^"]+)".*', replace:"\1", string:item[1]);
path = ereg_replace(pattern:'^(.+)\\\\[^\\\\]+\\.exe.*$', replace:"\1", string:exe, icase:TRUE);
lcpath = tolower(path);
if (!paths[lcpath])
{
paths[lcpath] = path;
path_keys[path] = key;
}
}
RegCloseKey(handle:key_h);
}
}
# If the "Perform thorough tests" setting is enabled, include local user directories too.
var pdir = "";
var winroot;
if (thorough_tests)
{
# Find out where user directories are stored.
key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList";
key_h = RegOpenKey(handle:hklm, key:key, mode:MAXIMUM_ALLOWED);
if (!isnull(key_h))
{
item = RegQueryValue(handle:key_h, item:"ProfilesDirectory");
if (!isnull(item)) pdir = item[1];
RegCloseKey(handle:key_h);
}
if (pdir && stridx(tolower(pdir), "%systemdrive%") == 0)
{
key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion";
key_h = RegOpenKey(handle:hklm, key:key, mode:MAXIMUM_ALLOWED);
if (!isnull(key_h))
{
item = RegQueryValue(handle:key_h, item:"SystemRoot");
if (!isnull(item))
{
winroot = ereg_replace(pattern:"^([A-Za-z]):.*", replace:"\1:", string:item[1]);
pdir = winroot + substr(pdir, strlen("%systemdrive%"));
}
RegCloseKey(handle:key_h);
}
}
}
RegCloseKey(handle:hklm);
NetUseDel(close:FALSE);
if (pdir)
{
# Get OS ver
var windows_version = get_kb_item("SMB/WindowsVersion");
var share = ereg_replace(pattern:"^([A-Za-z]):.*", replace:"\1$", string:pdir);
var dirpat = ereg_replace(pattern:"^[A-Za-z]:(.*)", replace:"\1\*", string:pdir);
rc = NetUseAdd(login:login, password:pass, domain:domain, share:share);
if (rc == 1)
{
var retx = FindFirstFile(pattern:dirpat);
var user;
while (!isnull(retx[1]))
{
path = NULL;
user = retx[1];
if (user != "." && user != "..")
{
# 2k / 2k3 / XP
if (windows_version < 6 )
path = pdir + "\" + user + "\Local Settings\Application Data\Google\Chrome\Application";
# Vista / Win 7 / 2k8
else
path = pdir + "\" + user + "\AppData\Local\Google\Chrome\Application";
if (!isnull(path))
{
lcpath = tolower(path);
if (!paths[lcpath]) paths[lcpath] = path;
}
}
retx = FindNextFile(handle:retx);
}
}
}
# Determine version numbers of any actual Chrome installs.
var vers = make_array();
##
# Check both 'Program Files (x86)' and 'Program Files'
# Use uppercase path keys to ensure uniqueness
##
var altpath, up_altpath, altpaths, path_ds, up_path;
foreach path (paths)
{
up_path = toupper(path);
path_ds[up_path].display_path = path;
path_ds[up_path].registry_key = path_keys[path];
if ("Program Files (x86)" >< path)
{
altpath = path - " (x86)";
up_altpath = toupper(altpath);
altpaths[up_altpath].display_path = altpath;
altpaths[up_altpath].registry_key = path_keys[altpath];
}
else if ("Program Files" >< path)
{
altpath = ereg_replace(string:path, pattern:"Program Files", replace:"Program Files (x86)");
up_altpath = toupper(altpath);
altpaths[up_altpath].display_path = altpath;
altpaths[up_altpath].registry_key = path_keys[altpath];
}
}
foreach altpath (keys(altpaths))
{
path_ds[altpath].display_path = altpaths[altpath].display_path;
path_ds[altpath].registry_key = altpaths[altpath].registry_key;
}
spad_log(message:'path datastructure: ' + obj_rep(path_ds));
var reg_key, strip_path, version;
var max_version, max_dll, size, modified, max_size, max_modified, tmp;
##
# Check paths
##
foreach var path_key (keys(path_ds))
{
path = path_ds[path_key].display_path;
reg_key = path_ds[path_key].registry_key;
share = ereg_replace(pattern:"^([A-Za-z]):.*", replace:"\1$", string:path);
dirpat = ereg_replace(pattern:"^[A-Za-z]:(.*)", replace:"\1\*", string:path);
NetUseDel(close:FALSE);
rc = NetUseAdd(login:login, password:pass, domain:domain, share:share);
if (rc == 1)
{
# Look for, and skip, Windows Reparse Points
# that would cause one install to be reported
# twice.
strip_path = dirpat - "\*";
if (reparse_points_exist_in_path(check_path:strip_path))
continue;
max_version = "";
retx = FindFirstFile(pattern:dirpat);
var dir, fh, dll, ver, i, max;
while (!isnull(retx[1]))
{
dir = retx[1];
if (dir =~ "^[0-9]+[0-9.]+$")
{
dll = substr(dirpat, 0, strlen(dirpat)-2-1) + "\" + dir + "\chrome.dll";
fh = CreateFile(
file:dll,
desired_access:GENERIC_READ,
file_attributes:FILE_ATTRIBUTE_NORMAL,
share_mode:FILE_SHARE_READ,
create_disposition:OPEN_EXISTING
);
if (!isnull(fh))
{
ver = GetFileVersion(handle:fh);
if (!isnull(ver))
{
size = direct_GetFileSize(handle:fh);
tmp = GetFileVersionEx(handle:fh);
if (!isnull(tmp) && !isnull(tmp['dwTimeDateStamp']))
{
modified = tmp['dwTimeDateStamp'];
}
version = ver[0] + "." + ver[1] + "." + ver[2] + "." + ver[3];
# nb: upgrades don't remove old versions so we look for the highest.
if (!max_version)
{
max_version = version;
max_dll = dll;
max_size = size;
max_modified = modified;
}
else
{
max = split(max_version, sep:'.', keep:FALSE);
for (i=0; i<4; i++)
max[i] = int(max[i]);
if (
ver[0] > max[0] ||
(ver[0] == max[0] && ver[1] > max[1]) ||
(ver[0] == max[0] && ver[1] == max[1] && ver[2] > max[2]) ||
(ver[0] == max[0] && ver[1] == max[1] && ver[2] == max[2] && ver[3] > max[3])
)
{
max_version = version;
max_dll = dll;
max_size = size;
max_modified = modified;
}
}
}
CloseFile(handle:fh);
}
}
retx = FindNextFile(handle:retx);
}
if (max_version)
{
var file_info = { dll: max_dll, size: max_size, modified: max_modified };
if (!empty_or_null(vers[max_version]))
{
append_element(value: path, var: vers[max_version].paths);
append_element(value: reg_key, var: vers[max_version].keys);
append_element(value: file_info, var: vers[max_version].version_file_info);
}
else
{
vers[max_version] = {
paths: [path],
version_file_info: [file_info],
keys: [reg_key]
};
}
}
}
}
NetUseDel();
# If any installs were found, mark it as installed in the KB and issue a report.
if (max_index(keys(vers)))
{
set_kb_item(name:"SMB/Google_Chrome/Installed", value:TRUE);
var info = "";
foreach version (sort(keys(vers)))
{
var len = max_index(vers[version].paths);
for(var idx = 0; idx < len; idx++)
{
path = vers[version].paths[idx];
file_info = vers[version].version_file_info[idx];
reg_key = vers[version].keys[idx];
set_kb_item(name:"SMB/Google_Chrome/"+version+"/"+path, value:path);
var collect = new collection_metadata::collection_metadata();
collect.track_windows_pe_version(
path: file_info.dll,
size: file_info.size,
last_modified: file_info.modified
);
register_install(
app_name:app,
vendor : 'Google',
product : 'Chrome',
path:path,
version:version,
cpe:"cpe:/a:google:chrome",
fa_app_name: fa_app_name,
enhanced_inventory: collect.inventory_data());
delete(collect);
}
}
if (!thorough_tests)
{
# nb: report already has an extra blank line at the end.
info +=
'Note that Nessus only looked in the registry for evidence of Google\n' +
'Chrome. If there are multiple users on this host, you may wish to\n' +
"enable the 'Perform thorough tests' setting and re-scan. This will" + '\n' +
"cause Nessus to scan each local user's directory for installs." + '\n';
}
report_installs(app_name:app, port:port, extra:info);
}
else
{
audit(AUDIT_NOT_INST, app);
}
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
10 Jul 2025 00:00Current
5.4Medium risk
Vulners AI Score5.4