Electron-Based App Security Testing Fundamentals Part 2— Installing and Detecting Electron-Based Application

Ways to Detect Electron-Based Applications both Manually and Automatically

YoKo Kho
HakTrak Cybersecurity Squad
10 min readApr 24, 2024

--

بسم الله الرحمن الرحيم

This marks the second part of a series of articles exploring the fundamentals of security testing for Electron-based applications.

In this part, we will explore the essential processes of installing and detecting installed Electron-based applications, including the way to detect the presence of Electron applications on various operating systems — both manually and automatic.

In the previous part, we have explained the overview of electron, how electron works, and simple steps needed to create a simple electron-based application.

III. The Explanation

After understanding the process of creating a simple Electron-based application in the previous chapter, we will now provide an overview of the installation process and basic steps to detect installed Electron-based applications on an operating system.

3.1. Installing the Application

Similar to installing applications on any OS, what we need here is the binary of the existing application. In this context, our focus leans towards macOS. However, it’s worth noting that the installation process doesn’t significantly differ across other operating systems such as Windows or Linux.

When we click on the previously created .dmg file, a simple popup will appear with the application name exactly as specified in the “productName” parameter in the package.json file during the build process.

Figure 1 Simple Popup

Moreover, in the header bar, we will also find the version of the application, which also corresponds to the value we entered in the “version” parameter in the same file.

So, let’s say we have installed it, then essentially we will find this application within our application directory (such as /Applications on macOS or Program Files on Windows OS).

It’s important to note that unlike the Windows environment — which allows users to view the content of a package directly in Program Files, on macOS, we need to select “show package content” to see the contents of the installed application directory.

Figure 2 Show Package Contents

3.2. Manual Detection of Installed Electron-Based Applications

As we know, each operating system has its own characteristic directory structure used to store newly installed applications. For example:

  • In macOS, this directory is typically located at /Applications or /Users/Username/Applications.
  • In Windows, it can be found in Program Files, AppData, or WindowsApp.
  • Meanwhile, in Linux-based systems, this is usually located in the directories /opt or /usr/share.

There might be questions about how we identify the presence of an Electron application after locating its application directory. Simply put, applications built with the Electron framework have a unique characteristic, namely the existence of files in the .asar format.

Figure 3 Sample of .asar File on macOS
Figure 4 Sample of.asar File on Windows
Figure 5 Sample of.asar File on Linux-Based System (For Example: Ubuntu)

As a brief explanation, this file serves as an archive containing all JavaScript, HTML, CSS, images, and other resources used within the Electron-based application. Essentially, it encapsulates a collection of all necessary files to run the application (quoting from electronjs, this format also can mitigate issues around long path names on Windows, speed up require and conceal our source code from cursory inspection).

Are there any other formats that can help us identify Electron-based applications on our operating system? Yes, indeed. Some of these include:

  • The “Electron Framework.framework” directory within the “Frameworks” directory — for macOS.
Figure 6 “Electron Framework.framework” Directory
  • The “electron.icns” (icon resource) file, tipically located in the “Resources” directory — for macOS.
Figure 7 electron.icns File
  • The “LICENSE.electron.txt” file — on some Linux-based systems.
Figure 8 LICENSE.electron.txt File
  • The “package.json” file (though we may need to examine its contents first).
Figure 9 package.json File
  • Specific keyword searches that uniquely characterize configurations in Electron-built applications, such as ‘contextIsolation’ and ‘nodeIntegration’.
Figure 10 Search for Specific Keyword

3.3. The Automated Way

Considering that there are many variables to be searched for, and there may be numerous applications within a single host, then the initial step that can be taken in the basic identification process is maybe to perform some automated executions.

3.3.1. Automated Detection of Electron-Based Applications on macOS

As we all know, macOS has directories that use the .app naming convention (although we cannot strictly call it an extension). Essentially, these directories contain all the files and resources required to run an application.

Despite being directories, when clicked, the operating system will execute the program contained within them. As explained in section 3.1, the contents of these directories can also be further explored.

Given that resources for macOS applications are typically located within .app directories, we can use the mdfind command to perform intensive searches for the presence of a file.

As an information, mdfind itself is a search command in macOS that utilizes the Spotlight search index system to search for files and directories based on their metadata and content. For example, if we want to find all files with the .png extension, we can run the mdfind ‘.png’ command in the terminal, and the output will display all files with the .png extension on our system.

Here is a simple sample script that can be used to assist users in identifying Electron-based applications on macOS:

import os
import subprocess

def get_app_name(app_path):
return os.path.basename(app_path)

def get_electron_version(filename):
try:
output = subprocess.check_output(f"strings '{filename}' | grep 'Chrome/' | grep -i Electron | grep -v '%s' | sort -u | cut -f 3 -d '/'", shell=True)
return output.decode().strip()
except subprocess.CalledProcessError:
return None

def generate_github_link(version):
return f"https://github.com/electron/electron/releases/tag/v{version}"

def format_row(app_name, electron_version, filename):
return f"{app_name:30s} {electron_version:20s} {filename}"

def find_electron_apps():
try:
apps = subprocess.check_output("mdfind 'kind:app'", shell=True).decode().splitlines()
apps = sorted(set(apps))

print("_" * 100)
print(format_row("App Name", "Electron Version", "File Name"))
print("=" * 100)

for app in apps:
filename = os.path.join(app, "Contents/Frameworks/Electron Framework.framework/Electron Framework")
if os.path.isfile(filename):
app_name = get_app_name(app)
electron_version = get_electron_version(filename)
print(format_row(app_name, electron_version, filename))

print("\n")

print("=" * 60)
print("App Name" + " " * 24 + "GitHub Link")
print("=" * 60)

for app in apps:
filename = os.path.join(app, "Contents/Frameworks/Electron Framework.framework/Electron Framework")
if os.path.isfile(filename):
app_name = get_app_name(app)
electron_version = get_electron_version(filename)
github_link = generate_github_link(electron_version) if electron_version else "Not Found"
print(f"{app_name:30s} {github_link}")

except Exception as e:
print(f"Error: {e}")

if __name__ == "__main__":
find_electron_apps()

# As a note, this script is a simple port to Python (with additional information) from a bash script that made and improved by @CubicleApril. The original script can be seen at: https://gist.github.com/april/3da7c3720b0d9f3ee7dc9a95f623578d.
# Note: In the final output section, there is a small addition regarding a link containing updated information about using Electron.
# Repo: https://github.com/yokokho/Find-Electron-Apps-on-macOS

So, what’s basically this script do? In short, after obtaining the list of applications installed in macOS, this script will attempt to locate the presence of the “Electron Framework.framework”. And for the electron version used to build the application, it searches by examining the “Electron Framework” binary.

Figure 11 Result of Executed Script in macOS Environment

3.3.2. Automated Detection of Electron-Based Applications on Windows

Similar to our explanation in the macOS part, there are also specific directories in Windows where applications are typically installed — that contain the necessary files and resources for running applications. Examples of these directories include Program Files, AppData (including subdirectories such as “Programs”), and WindowApp. And in some cases, applications may also be found in the user’s directory, such as Downloads or Documents directories, which can occur because the application may be a portable app.

It’s essential to highlight that access to the WindowApp directory is restricted by default as a security measure implemented by Windows. To view the list of directories inside WindowApp, specific permissions need to be configured.

In light of this situation, here is a simple example PowerShell script designed to help users in identifying Electron-based applications installed on Windows:

function Is-ElectronApp {
param($directory)

Get-ChildItem -Path $directory -Filter "*.asar" -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
$appName = if ($_.FullName -like "*\Program Files*\*") {
$splitPath = (Split-Path -Path $_.Directory).Split('\')
$splitPath[2..($splitPath.Length - 3)] -join '\'
} elseif ($_.FullName -like "*\AppData\Local\Programs\*" -or $_.FullName -like "*\AppData\LocalLow\Programs\*" -or $_.FullName -like "*\AppData\Roaming\Programs\*") {
(Split-Path -Path $_.Directory).Split('\')[6]
} elseif ($_.FullName -like "*\AppData\Local\*" -or $_.FullName -like "*\AppData\LocalLow\*" -or $_.FullName -like "*\AppData\Roaming\*") {
(Split-Path -Path $_.Directory).Split('\')[5]
} elseif ($_.FullName -like "*\Users\$env:USERNAME\Desktop\*" -or $_.FullName -like "*\Users\$env:USERNAME\Downloads\*" -or $_.FullName -like "*\Users\$env:USERNAME\Documents\*") {
(Split-Path -Path $_.Directory).Split('\')[4]
} else {
Split-Path -Path $_.Directory
}
$appPath = $_.Directory
[PSCustomObject]@{
AppName = $appName
AppPath = $appPath
}
}
}

$drives = Get-PSDrive -PSProvider 'FileSystem'
$directoriesToSearch = @("\Program Files", "\Program Files (x86)", "\Users\$env:USERNAME\AppData\Local", "\Users\$env:USERNAME\AppData\LocalLow", "\Users\$env:USERNAME\AppData\Roaming", "\Users\$env:USERNAME\Desktop", "\Users\$env:USERNAME\Downloads", "\Users\$env:USERNAME\Documents")

$electronApps = foreach ($drive in $drives) {
foreach ($directory in $directoriesToSearch) {
$fullPath = Join-Path -Path $drive.Root -ChildPath $directory
if (Test-Path -Path $fullPath) {
Is-ElectronApp -directory $fullPath
}
}
}

if ($electronApps) {
$electronApps | Format-Table -AutoSize
} else {
Write-Output " "Electron-based applications not found."
}

# Repo: https://github.com/yokokho/Find-Electron-Apps-on-Windows

In summary, this script attempts to locate drive letters on Windows and then proceeds to search common paths where applications are typically found (such as Program Files, AppData, and several user directories like Desktop, Downloads, and Documents).

Unlike macOS which utilizes the mdfind function, in Windows, (with my limited knowledge) we need to define specific paths manually within the script. While there may be other potential paths, such as WindowApp, at least this serves as an initial step in identifying the presence of Electron-based applications within a Windows OS.

Figure 12 Result of Executed Script in Windows Environment

It’s important to note that we may encounter duplicate information in the output. Well, this is because we are using ‘.asar’ as the search keyword, and there is a possibility that within a directory, there are more than one ‘.asar’ files. Furthermore, the retrieval of the application name (AppName) is still based on the directory name, which sometimes results in inaccurate output when users use a different directory name from the application name.

3.3.3. Automated Detection of Electron-Based Applications on Linux

And here we are, in the final part of the automated detection topic. Linux-based systems also have designated directories for storing installed applications, such as /usr/share or /opt directories. Additionally, there’s a possibility that users may choose to install apps in their /home directories as well (for example, in the Documents directory).

Technically, we could utilize the `locate` command to swiftly locate .asar files or any other files related to Electron. However, there’s a little note, if we haven’t updated the `updatedb` database yet, the results may not be optimal. Since our goal is to execute the script at a low-level user privilege, we opt not to use `locate` command.

Considering this situation, so we attempted to create a simple Python script that roughly follows the same flow as the one we developed for Windows:

import os

def is_electron_app(directory):
for file in os.listdir(directory):
if file.endswith('.asar') or file == 'LICENSE.electron.txt':
return True
return False

def get_app_name(directory):
split_directory = directory.split('/')
if directory.startswith('/usr/share/'):
if len(split_directory) > 3:
return split_directory[3]
elif directory.startswith('/opt/'):
if len(split_directory) > 2:
return split_directory[2]
elif directory.startswith('/home/'):
if len(split_directory) > 4:
return split_directory[4]
else:
return os.path.basename(directory)


def find_electron_apps():
directories_to_search = ['/opt', '/usr/share', '/home']
electron_apps = []

for directory in directories_to_search:
for root, dirs, files in os.walk(directory):
if is_electron_app(root):
app_name = get_app_name(root)
electron_apps.append((app_name, root))
dirs[:] = []

if electron_apps:
print("_" * 100)
print(f"{'App Name':30s} {'Location'}")
print("=" * 100)
for app_name, location in electron_apps:
print(f"{app_name:30s} {location}")
else:
print("Electron-based applications not found.")

if __name__ == "__main__":
find_electron_apps()

# Repo: https://github.com/yokokho/Find-Electron-Apps-on-Linux

In summary, this script searches designated directories where applications are commonly installed, such as /usr/share or /opt, as well as the /home directories where users may choose to install apps. Basically, this script adopts a similar approach to the previous PowerShell script by navigating through common directories to locate Electron-related files. While it may not cover all potential paths, at least it can provide an initial step in identifying Electron-based applications within a Linux environment.

Figure 13 Result of Executed Script in Linux Environment

As a note, the determination of the application name (App Name) still relies on the directory name, occasionally resulting in inaccurate output if users utilize a directory name different from the application name.

Well, here we are, almost nearing the end of this part. We hope that readers now have a fundamental understanding of Electron-based applications, covering installation procedures to detection methods across different operating systems. In the next part, we’ll try to explore how to extract files stored in the .asar format and highlight the importance of this process.

REFERENCES

--

--