-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
src: add WDAC integration (Windows) #54364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Review requested:
|
Can you run the formatter? |
I also want to add - this is meant to facilitate discussion regarding the general implementation. I'm not very familiar with the various module loaders and ways which code can be read off disk and executed. I assume there are gaps in my implementation and I would appreciate any expertise in the area to close them. Thanks! |
@nodejs/platform-windows |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #54364 +/- ##
==========================================
- Coverage 90.23% 90.23% -0.01%
==========================================
Files 633 634 +1
Lines 186818 186921 +103
Branches 36668 36689 +21
==========================================
+ Hits 168578 168663 +85
- Misses 11036 11058 +22
+ Partials 7204 7200 -4
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've discussed on the security-wg and the next steps are:
- Creating documentation
- Improving the test coverage
Then we can go the a proper code review. Meanwhile, I'm tagging @nodejs/tsc for awareness.
This is a Windows specific feature that will enabled by a node key in Windows system dictionary. So, it shouldn't be considered a semver-major or a specific Node.js API.
Currently, Windows should be the only environment that makes those checks available via API. We are still evaluating the status of OSX and Linux support for that. However, it's fair to assume this PR will only implement such guarantees for Windows users.
I recommend watching our meeting as we've discussed the usage and how this is turned-on in Windows systems (https://www.youtube.com/watch?v=w4zzH-otKNI)
FYI, we are working on a similar feature for Linux. The goal is the same but the implementation and API are different. Linux already provides access control systems and this new feature (previously open+O_MAYEXEC, now execveat+AT_CHECK) is the missing piece to control script execution the same way other kind of execution can already be controlled. This article gives a good overview: https://lwn.net/Articles/982085/ I plan to send a new patch series in a few weeks. Please let me know what you think. |
7cfafd5
to
e8e5e7a
Compare
e8e5e7a
to
18b9645
Compare
Hey @RafaelGSS , I've added more documentation about code integrity mode. Please let me know if it looks adequate, or if you'd like me to explain more. I also added doc/api/wdac-manifest.xml. This is the manifest we spoke about in the last meeting I attended. It declares the WDAC Application settings that NodeJS will query for. It should be hosted in an accessible place so when system admins author their Windows Code Integrity policy they know what settings are available to them, and it also adds some type-checking for the policy writer. I'll plan on attending the next security WG meeting to discuss in more detail if needed. Thanks |
35500fc
to
4186da7
Compare
4186da7
to
fcf35ec
Compare
Add calls to Windows Defender Application Control to enforce integrity of .js, .json, .node files. add typings. fix version number add integrity checks to esm loader fix esm code integrity tests only load code integrity module on Windows address typings feedback fix readability and formatting fix naming conventions fix error in merge
fcf35ec
to
93555d0
Compare
Failed to start CI⚠ Commits were pushed since the last approving review: ⚠ - src: add WDAC integration (Windows) ⚠ - fix formatting ⚠ - properly load isWindows ⚠ - fix formatting ⚠ - remove code_integrity from builtins on non windows ⚠ - fix spacing before comment ⚠ - only load code integrity module on Windows ✘ Refusing to run CI on potentially unsafe PRhttps://github.com/nodejs/node/actions/runs/15254533604 |
PTAL @nodejs/tsc @nodejs/security |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a few suggestions and comments.
distributing the signature information for their Node.js application. | ||
Application developers are also expected to design their application | ||
in robust ways to avoid unintended code execution. This includes | ||
use of `eval` and loading modules outside of standard methods. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use of `eval` and loading modules outside of standard methods. | |
avoiding the use of `eval` and avoiding loading modules outside of standard methods. |
prepareMainThreadExecution(); | ||
addBuiltinLibsToObject(globalThis, '<eval>'); | ||
markBootstrapComplete(); | ||
|
||
const { isWindows } = require('internal/util'); | ||
if (isWindows) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to pull the part which get the codes above so that it is under the isWindows check? If so it might be good to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see below that this uses a pattern common to what is in other files. So seeing that I think its fine either way for me.
LoadLibraryExA("wldp.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); | ||
|
||
if (wldp_module == nullptr) { | ||
// Wldp is included on all Windows systems that are supported by Node's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Wldp is included on all Windows systems that are supported by Node's | |
// Wldp is included on all Windows systems that are supported by Node.js |
Add calls to Windows Defender Application Control to enforce integrity of .js, .json, .node files.
Motivation
In the past I've spoken to @RafaelGSS and the Node security work group about code integrity. We feel like it's an important defense in depth feature and the removal of the --experimental-policy feature gives us room to use OS-level code integrity features. This is a first pass at a CI implementation that cooperates with the OS.
These additions add an additional layer of defense against malicious code execution on a system that is enforcing code integrity. Code Integrity enforcement mitigates the risk of malicious code modifications after signing-time. For example, they can prevent an arbitrary file-write vulnerability from turning into an RCE. These additional checks are only made if the OS in code integrity enforcement mode and has explicitly set a configuration value in their code integrity policy to have Node enforce CI.
Windows Defender Application Control (WDAC)
Official documentation: https://learn.microsoft.com/en-us/windows/security/application-security/application-control/windows-defender-application-control/wdac-and-applocker-overview
WDAC is the Windows code integrity subsystem. It enforces code integrity using digital signatures. This is straightforward for DLLs and EXEs, since they're loaded using well known entry points in the OS. However, dynamic runtimes (interpreters like Node.js or Python) make it difficult to determine whether a file being read will be executed. In order to assist dynamic runtimes, WDAC provides an interface for runtimes to call with the code they intent to execute, and WDAC will determine if the runtime is allowed to execute the code based off signature information. WDAC (wldp.dll) exposes various methods for runtimes to ask the OS questions about the code integrity policy on the system. These changes leverage three interfaces
WldpCanExecuteFile
,WldpGetApplicationSettingBoolean
, andWldpQuerySecurityPolicy
.WldpCanExecuteFile
- given a file handle, determines if the file is allowed to be executed from WDAC policy.WldpGetApplicationSettingBoolean
- Queries WDAC policy for an application-defined setting with a boolean value. This can be thought of as a more secure setting store.WldpQuerySecurityPolicy
- WdlpGetApplicationSettingBoolean is not available on all versions of Windows, so this method provides fallback behavior to query WDAC policy settings.High-level implementation
At startup, Node will query WDAC policy to see if it should enter integrity enforcement mode. If the policy provider
Node.js
has set the policy settingEnforceCodeIntegrity
to TRUE, then Node will callWldpCanExecuteFile
when a .js, .json, or .node file is loaded usingrequire
. If this setting is not enabled, the call to WldpCanExecuteFile will not be made and execution will continue as normal.Additionally, if
EnforceCodeIntegrity
is set to TRUE, we disable features that allow arbitrary code from being executed by Node (e.g. the "-e" command line option and the REPL) when the system is enforcing code integrity.Signing files
Signatures are stored in catalog file,
.cat
. This catalog file can be thought of as a collection of filenames and their associated hashes. A Node application author can generate a catalog using the Powershell commandNew-FileCatalog
documentation.PS> New-FileCatalog -CatalogFilePath ./MyApplicationCatalog.cat -Path ./MyApplicationRelease/
The catalog then can be signed with a certificate trusted by WDAC policy using Powershell with
Set-AuthenticodeSignature
documentation orsigntool.exe
The signed catalog can then be installed on the system MyApplication is being deployed to.
Other Questions
What about Linux?
At the moment, there is no unified code integrity subsystem that provides similar cooperative interfaces for interpreters on Linux. There are proposals in-flight and we're tracking this work and hope to keep the implementation as similar as possible across OSs.
Notable Change
Adding OS code integrity integration to mitigate unintended code execution. This feature is not enabled by default and must be opted into (see code_integrity.md for more information). When this feature is enabled, Node.js restricts loading of JavaScript modules to only those with signatures trusted by OS code integrity policy.