Files
Workstation-Setup/PHASE-6-DOWNLOAD-SECURITY.md
2026-09-09 11:11:06 -07:00

446 lines
14 KiB
Markdown

# PHASE 6: DOWNLOAD SECURITY & TRUST CHAIN
## Validation Layers, Signature Verification, and Malware Scanning
**Phase Start Date:** 2026-09-09
**Scope:** Implement 7-layer download validation to prevent compromised software
**Outcomes:** Trust chain implementation with SHA256, Authenticode, and signature validation
---
## 6.1 DOWNLOAD VALIDATION LAYERS
### Layer 1: HTTPS Requirement
**Policy:** All downloads MUST use HTTPS (encrypted, prevents MitM attacks)
- **Exception:** Limited HTTP allow-list for specific vendors with documented justification
- **Check:**
```powershell
if ($DownloadUri -notmatch '^https://') {
if ($DownloadUri -in $HttpAllowList) {
Write-Warning "HTTP URI in allow-list: $DownloadUri"
} else {
throw "HTTP not allowed. URI must use HTTPS: $DownloadUri"
}
}
```
### Layer 2: File Size Validation
**Policy:** Verify download size matches expected range (prevents truncation or injection)
- **Check:**
```powershell
$file = Get-Item -LiteralPath $DownloadPath
if ($file.Length -lt $ExpectedMinBytes -or $file.Length -gt $ExpectedMaxBytes) {
throw "File size $($file.Length) outside expected range: $ExpectedMinBytes - $ExpectedMaxBytes"
}
```
### Layer 3: Archive Integrity Check
**Policy:** Validate ZIP/7z integrity before extraction (prevents corrupted installs)
- **Check:**
```powershell
# For ZIP: Use 7-Zip to test archive
& "7z.exe" t -ba $ArchivePath
if ($LASTEXITCODE -ne 0) {
throw "Archive integrity check failed: $ArchivePath"
}
```
### Layer 4: Expected Files Exist
**Policy:** Verify required executable/entry-point exists after extraction
- **Check:**
```powershell
$expectedFile = Join-Path $ExtractPath $ExpectedExecutable
if (-not (Test-Path -LiteralPath $expectedFile)) {
throw "Expected file not found: $expectedFile"
}
```
### Layer 5: SHA256 Hash Verification
**Policy:** Verify cryptographic integrity against known-good hash
- **Source:** Vendor website, GitHub release page, or computed during initial test
- **Check:**
```powershell
$actualHash = (Get-FileHash -LiteralPath $DownloadPath -Algorithm SHA256).Hash
if ($actualHash -ne $ExpectedSHA256) {
throw "SHA256 mismatch! Expected: $ExpectedSHA256, Got: $actualHash"
}
```
- **Dynamic Hash Discovery:**
- **GitHub:** Extract SHA256 from release description or workflow artifacts
- **Direct vendor:** May require manual verification first download
### Layer 6: Authenticode Signature Verification
**Policy:** Verify digital signature on executables (ensures code is from publisher)
- **Check:**
```powershell
$signature = Get-AuthenticodeSignature -LiteralPath $ExecutablePath
if ($signature.Status -ne 'Valid') {
throw "Signature invalid or missing: $ExecutablePath"
}
if ($signature.SignerCertificate.Issuer -notmatch 'Expected Issuer Pattern') {
throw "Unexpected signer: $($signature.SignerCertificate.Issuer)"
}
```
- **Trusted Publishers Database:**
- Microsoft (PowerToys, Sysinternals, Tools)
- GitHub (open-source projects may not be signed)
- Individual Vendors (7-Zip, VLC, Notepad++, etc.)
### Layer 7: Malware Scanning (Optional but Recommended)
**Policy:** Scan downloaded file with Windows Defender before extraction
- **Limitation:** Signature-based detection only; not foolproof
- **Check:**
```powershell
# Use Windows Defender CLI or WinAPI
$scanResult = Start-MpScan -ScanPath $DownloadPath -ScanType QuickScan -AsJob
Wait-Job $scanResult
if ($scanResult.State -ne 'Completed') {
throw "Malware scan failed or detected threat"
}
```
---
## 6.2 DOWNLOAD TRUST CONFIGURATION
### download-trust.json Structure
```json
{
"TrustChainConfig": {
"EnforceHTTPS": true,
"RequireSignature": true,
"VerifySHA256": true,
"AllowArchiveWithoutSignature": true,
"RunMalwareScan": true
},
"HttpAllowList": [
{
"Uri": "http://automotive.vendor.com/download",
"Reason": "Vendor does not support HTTPS (documented limitation)",
"ApprovedBy": "Admin",
"ApprovedDate": "2026-01-01",
"RiskLevel": "Medium",
"Mitigation": "Verify SHA256 on all downloads"
},
{
"Uri": "http://multiprogram.vendor/downloads",
"Reason": "MVCI PRO J2534 vendor limitation (VPN-protected)",
"ApprovedBy": "Admin",
"ApprovedDate": "2026-09-01",
"RiskLevel": "Medium",
"Mitigation": "VPN connection required, SHA256 mandatory"
}
],
"TrustedPublishers": [
{
"Name": "Microsoft Corporation",
"Issuers": [
"CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation",
"CN=Microsoft Code Signing PCA, O=Microsoft Corporation"
],
"Applications": ["PowerToys", "Sysinternals", "Windows Terminal"]
},
{
"Name": "Igor Pavlov",
"Issuers": ["CN=Igor Pavlov, O=Igor Pavlov"],
"Applications": ["7-Zip"],
"SignatureRequired": false,
"Notes": "7-Zip portable doesn't require signature; verify SHA256"
},
{
"Name": "GitHub (Open Source)",
"Issuers": [],
"Applications": [
"GHidra",
"ImHex",
"SavvyCAN",
"WinMerge",
"CyberChef",
"ShareX"
],
"SignatureRequired": false,
"Notes": "Most GitHub projects don't sign. Verify SHA256 from release page."
},
{
"Name": "VideoLAN Organization",
"Issuers": ["CN=VideoLAN Organization"],
"Applications": ["VLC"],
"SignatureRequired": true
}
],
"ApplicationDownloads": {
"WinGet_Core": [
{
"Name": "Git",
"PackageId": "Git.Git",
"Source": "WinGet",
"SourceType": "WinGet",
"RequiresValidation": false,
"Notes": "WinGet handles validation"
},
{
"Name": "Visual Studio Code",
"PackageId": "Microsoft.VisualStudioCode",
"SourceType": "WinGet",
"RequiresValidation": false
}
],
"Portable_Applications": [
{
"Name": "HxD",
"SourceType": "Direct",
"Uri": "https://mh-nexus.de/en/downloads/freeware/HxD/HxD.zip",
"ExpectedMinBytes": 1000000,
"ExpectedMaxBytes": 5000000,
"SHA256": "TO_BE_FILLED_AFTER_FIRST_DOWNLOAD",
"Signature": "Not signed (portable freeware)",
"TrustedPublisher": "mh-nexus",
"ValidationLayers": [1, 2, 3, 4, 5],
"RiskLevel": "Low"
},
{
"Name": "Ghidra",
"SourceType": "GitHubZip",
"Repository": "NationalSecurityAgency/ghidra",
"AssetRegex": "ghidra_.*_public\\.zip",
"ExpectedMinBytes": 150000000,
"ExpectedMaxBytes": 300000000,
"SHA256": "Extract from GitHub release description",
"Signature": "NSA-signed (sometimes)",
"TrustedPublisher": "NSA",
"ValidationLayers": [1, 2, 3, 4, 5],
"RiskLevel": "Low"
},
{
"Name": "MVCI PRO J2534",
"SourceType": "Direct_HTTP",
"Uri": "http://multiprogram.vendor/mvci-pro-latest.zip",
"ExpectedMinBytes": 50000000,
"ExpectedMaxBytes": 200000000,
"SHA256": "Manual_Vendor_Verification_Required",
"Signature": "Not signed",
"HttpAllowListReason": "Vendor limitation, VPN-protected",
"ValidationLayers": [1, 2, 3, 4, 5],
"RiskLevel": "High",
"RequiresVPN": true,
"Mitigation": "VPN + firewall rules, SHA256 from vendor"
},
{
"Name": "Sysinternals Suite",
"SourceType": "Zip",
"Uri": "https://download.sysinternals.com/files/SysinternalsEBD.zip",
"ExpectedMinBytes": 10000000,
"ExpectedMaxBytes": 50000000,
"SHA256": "Verify from Sysinternals website",
"Signature": "Microsoft-signed",
"TrustedPublisher": "Microsoft",
"ValidationLayers": [1, 2, 3, 4, 5, 6],
"RiskLevel": "Low"
}
]
},
"ValidationFunctions": {
"Verify-DownloadHTTPS": {
"Purpose": "Ensure download URI uses HTTPS or is on allow-list",
"RequiredParams": ["Uri"],
"ThrowsException": true
},
"Test-FileSize": {
"Purpose": "Verify file size is within expected range",
"RequiredParams": ["FilePath", "MinBytes", "MaxBytes"],
"ThrowsException": true
},
"Test-ArchiveIntegrity": {
"Purpose": "Test ZIP/7z integrity before extraction",
"RequiredParams": ["ArchivePath"],
"ThrowsException": true
},
"Test-ExpectedFiles": {
"Purpose": "Verify expected files exist after extraction",
"RequiredParams": ["ExtractPath", "ExpectedFiles"],
"ThrowsException": true
},
"Verify-FileHash": {
"Purpose": "SHA256 verification against known-good hash",
"RequiredParams": ["FilePath", "ExpectedHash"],
"ThrowsException": true
},
"Verify-AuthenticodeSignature": {
"Purpose": "Verify digital signature on executables",
"RequiredParams": ["ExecutablePath", "AllowedIssuers"],
"ThrowsException": false,
"Notes": "Warn if signature invalid, but allow if on allow-list"
},
"Invoke-MalwareScan": {
"Purpose": "Scan with Windows Defender before installation",
"RequiredParams": ["FilePath"],
"ThrowsException": false,
"Notes": "Optional layer; warn if threat detected"
}
},
"DownloadValidationPolicy": {
"WinGet_Packages": {
"Layers": [1, 2],
"Notes": "WinGet handles HTTPS and basic validation"
},
"GitHub_Open_Source": {
"Layers": [1, 2, 3, 4, 5],
"Notes": "No signatures, but source is auditable"
},
"Vendor_Direct": {
"Layers": [1, 2, 3, 4, 5, 6],
"Notes": "Require signature if vendor provides it"
},
"Internal_Tools": {
"Layers": [1, 2, 3, 4, 5, 6, 7],
"Notes": "Full validation for internal use"
}
}
}
```
---
## 6.3 POWERSHELL VALIDATION FUNCTIONS
### Function: Verify-DownloadIntegrity
```powershell
function Verify-DownloadIntegrity {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$FilePath,
[Parameter(Mandatory)]
[hashtable]$ValidationConfig,
[string]$ExpectedSHA256,
[switch]$SkipMalwareScan
)
# Layer 1: Already verified (HTTPS was enforced during download)
Write-Verbose "Layer 1: HTTPS requirement - Already validated during download"
# Layer 2: File Size
Write-Verbose "Layer 2: Validating file size..."
$fileSize = (Get-Item -LiteralPath $FilePath).Length
if ($fileSize -lt $ValidationConfig.ExpectedMinBytes -or
$fileSize -gt $ValidationConfig.ExpectedMaxBytes) {
throw "File size validation failed"
}
# Layer 3: Archive Integrity
if ($FilePath -match '\.(zip|7z)$') {
Write-Verbose "Layer 3: Testing archive integrity..."
& "7z.exe" t -ba $FilePath | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Archive integrity check failed"
}
}
# Layer 5: SHA256
Write-Verbose "Layer 5: Verifying SHA256..."
$actualHash = (Get-FileHash -LiteralPath $FilePath -Algorithm SHA256).Hash
if ($actualHash -ne $ExpectedSHA256) {
throw "SHA256 mismatch"
}
# Layer 6: Authenticode (if .exe or .dll)
if ($FilePath -match '\.(exe|dll)$') {
Write-Verbose "Layer 6: Verifying Authenticode signature..."
$sig = Get-AuthenticodeSignature -LiteralPath $FilePath
if ($sig.Status -ne 'Valid') {
Write-Warning "Signature is not valid"
}
}
# Layer 7: Malware Scan
if (-not $SkipMalwareScan) {
Write-Verbose "Layer 7: Running malware scan..."
# Call Invoke-MalwareScan
}
Write-Output "✓ All validation layers passed"
}
```
---
## 6.4 SECURITY BEST PRACTICES
### Do's
✅ Always use HTTPS
✅ Verify SHA256 before extraction
✅ Check Authenticode signatures on .exe/.dll files
✅ Test archive integrity
✅ Keep vendor checksums up-to-date
✅ Document approval for HTTP exceptions
✅ Run malware scans on high-risk downloads
### Don'ts
❌ Never disable certificate verification
❌ Don't trust SHA256 from untrusted sources
❌ Don't extract without size/integrity checks
❌ Don't ignore signature validation warnings
❌ Don't allow unsigned drivers without approval
❌ Don't download from HTTP for security-critical tools
---
## 6.5 HASH MANAGEMENT
### Storing Known-Good Hashes
**Initial Setup (Manual):**
1. Download application
2. Verify on vendor's site (HTTPS + signature + scan)
3. Calculate SHA256: `Get-FileHash -Algorithm SHA256`
4. Record in `download-trust.json`
**Updates:**
1. Check GitHub releases for new SHA256
2. Or: Download + verify with old hash from release notes
3. Update `download-trust.json`
4. Test in non-production first
**Verification During Setup:**
```powershell
# Pseudo-code
foreach ($app in $AppsToDownload) {
$downloadedFile = Invoke-WebRequest -Uri $app.Uri -OutFile $tempPath
$config = Get-DownloadConfig -AppName $app.Name
Verify-DownloadIntegrity -FilePath $tempPath -ValidationConfig $config `
-ExpectedSHA256 $config.SHA256
Extract-Application -FilePath $tempPath -DestPath $app.DestinationPath
}
```
---
## 6.6 SUMMARY TABLE
| Layer | Check | Enforced | Optional | Purpose |
|-------|-------|----------|----------|---------|
| 1 | HTTPS | ✅ Yes | HTTP allow-list | Encryption, prevent MitM |
| 2 | File Size | ✅ Yes | - | Detect truncation/injection |
| 3 | Archive Test | ✅ Yes | - | Detect corruption |
| 4 | Expected Files | ✅ Yes | - | Verify extraction worked |
| 5 | SHA256 | ✅ Yes | - | Cryptographic integrity |
| 6 | Authenticode | ✅ Yes | - | Code author verification |
| 7 | Malware Scan | ⚠️ Recommended | Yes | Defense in depth |
---
## NEXT STEPS
Phase 7 will implement **Execution Modes & Recovery** using these validated downloads.