正则表达式最佳实践与PowerShell脚本签名全解析
正则表达式资源与实践
在正则表达式的学习和应用中,有许多实用的资源可以帮助我们更好地掌握和运用这一强大的工具。以下是一些常见的资源:
- Microsoft PowerShell相关 :
- Microsoft PowerShell Regex Reference
- Microsoft PowerShell Comparison Operators
- Microsoft PowerShell -split Operator
- Microsoft PowerShell switch Statement
- Microsoft PowerShell Select-String Cmdlet
- Microsoft .NET相关 :
- Microsoft .NET Regex Behavior
- Microsoft .NET Regex Backtracking
- Microsoft .NET Regex Object Model
- Microsoft .NET Regex Compilation and Reuse
- Microsoft .NET Regex Thread Safety
- Microsoft .NET Regex Best Practices
- 其他材料 :
- Mastering Regular Expressions :全面的正则表达式书籍。
- Regular Expressions Cookbook :针对常见模式匹配问题的综合解决方案。
- Regular Expression Pocket Reference :包含语法和解决方案的快速参考手册。
- regular-expressions.info :通用的正则表达式参考网站。
- Regex101 :通用的正则表达式测试和调试工具(不支持.NET)。
- RegExr :开源的通用正则表达式测试工具(不支持.NET)。
- rextester.com/Tester :.NET正则表达式测试工具,还可访问 rextester Homepage 测试编译C#。
- RegexPlanet :包含.NET支持的正则表达式测试工具,使用(?’…’)代替(?<…>)进行命名捕获。
- regexstorm.NET :.NET正则表达式测试工具。
此外,还有一些关于优化正则表达式性能的博客文章,如 Optimizing Regex Performance I 和 Optimizing Regex Performance II ,以及 Rex Project 和 Rex Introduction Video 等资源。
PowerShell安全概述
PowerShell安全在组织中常常被忽视,这使得用户和管理员面临风险。由于其复杂性,恶意软件常将PowerShell用于其有效负载或作为启动平台。PowerShell的安全包含四个支柱:
1. 脚本开发 :采用最佳安全实践进行脚本开发教育。
2. 脚本执行 :实施脚本执行策略,减少未经授权的脚本执行。
3. 控制台执行 :实施控制台执行策略,减少单行攻击。
4. PowerShell远程处理 :实施PowerShell远程会话策略,减少横向攻击。
为了降低风险,必须正确理解、实施和配置这些层级。相关的安全措施包括脚本签名、脚本执行策略、PowerShell受限语言模式和PowerShell最小权限管理(JEA)。
脚本签名详解
脚本签名的概念与保护作用
脚本签名是通过数字签名保护脚本免受篡改的方法。数字签名使用加密过程,以高概率确保签名数据:
1. 签名后未被修改。
2. 来自已识别的源。
虽然这并不意味着源是可信的或签名数据质量高,但它能让我们确信数据自签名以来未改变,且创建者和签名者是同一实体。
在Windows机器上运行的几乎所有代码都是签名的,运行签名代码可显著降低执行恶意代码的概率。大多数Windows软件供应商在将编译后的二进制文件交付给用户之前会对其进行签名,微软也会对Windows的所有编译二进制文件进行签名,这建立了对底层二进制文件在发布和安装之间未改变的信任。数字签名还允许管理员配置安全软件,使用户只能运行经过批准的软件版本。
然而,代码签名并不能完全保证免受恶意软件的侵害。例如,2021年6月微软签署了一个恶意驱动程序,攻击者有时会使用被盗证书签署恶意软件。因此,应将代码签名策略作为组织安全策略的一部分,但不能仅依赖它。
数字签名的工作原理
要签署文件,需要要签名的数据和一个加密密钥对(通常以数字证书的形式存在)。加密密钥对是一对大数字,具有以下特点:
1. 可以用其中一个加密数据,然后用另一个解密数据,这是非对称或公钥加密。
2. 即使可以访问加密数据,也无法从一个密钥计算出另一个密钥的值。
将其中一个数字存储在安全的地方,如密码,这就是私钥;将另一个数字自由分发给需要能够解密用第一个密钥加密的数据的人,这就是公钥。可以使用私钥加密数据,接收者可以使用相应的公钥解密数据。
通常,签名数据本身并不加密,而是加密数据的哈希总和。哈希总和是一个通过加密计算得出的固定长度的字母数字字符串,对于任何唯一的数据块应该是唯一的。重要的是,不能从哈希总和推导出原始数据。PowerShell使用SHA - 256算法计算脚本签名的哈希总和,但也有其他算法可用。
当发送数字签名消息时,计算内容的哈希总和,用私钥加密哈希总和,然后发送消息和加密的哈希总和。接收者再次计算消息的哈希总和,使用公钥解密收到的哈希总和,并进行比较。如果两个哈希总和相同,则意味着消息在传输过程中未改变,并且是由发送者发送的,因为只有发送者可以访问私钥。
现代Windows系统中代码签名的工作原理
在Windows中,所有数字签名信任都基于证书。数字证书是公钥加上一些额外信息,如:
- 颁发者:创建(颁发)此证书的实体。
- 有效期:证书的有效日期范围。
- 用途:证书的有效用途(密钥用法、增强密钥用法)。
- 主题:证书的预期用户。
数字证书可以是自签名的,也可以由另一个证书签名。自签名证书中,颁发者和主题字段相同;当证书由另一个实体签名时,该实体即为颁发者。
通常,证书由认证机构(CA)颁发,这些机构是全球受信任的特殊服务。要在Windows中信任一个CA,需要将其根证书放入指定的证书存储区——受信任的根证书颁发机构。CA的根证书是由该根CA自签名的证书,CA使用此证书签署其颁发的所有其他证书。
在Windows中,最佳实践是至少有两层CA。根CA将向从属CA颁发一个证书,从属CA将颁发所有其他证书。
Windows出厂时在受信任的根证书颁发机构存储区中已经安装了许多根证书,但可以自由删除不信任的CA或添加其他CA(或自签名证书)。微软支持一份默认受Windows信任的所有认证机构的列表。
当Windows操作系统信任一个CA的根证书时,该CA及其从属CA颁发的所有其他证书将自动受信任。但证书必须在有效期内,且未被撤销。撤销的证书是其序列号已添加到证书撤销列表(CRL)中的证书,CRL由CA定期发布,客户端检查证书有效性时会下载CRL并搜索证书序列号。
此外,代码签名证书的增强密钥用法属性中必须有“代码签名”用途。
签名脚本的结构
以下是一个签名的PowerShell脚本示例:
Write-Host "Signed Script"
# SIG # Begin signature block
# MIIIPwYJKoZIhvcNAQcCoIIIMDCCCC0CAQEfCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAO,wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKD1DAhoFAAQUHVVG73a+TMJVHFMfMllHWt0T
# o+igggZTMIIC4TCCAkOgAwIBAgITae1AAAKkII0Kbir2EQAAAAAAAjAKBggqhkjO
# PQQDBDAVMRMwEQYDVQQDEwpNeSBSbS50IENBMB4fDTIfMDgyOTIfMTE0OVofDTI2
# MDgyOTIfMjE0OVowWjETMBEGCgmSJo,T8ifkARkWA25ldDEfMBUGCgmSJomT8ifk
# ARkWB2V4YW1wbGUfEjAQBgoJkiaJkL0sZAEZFgJhZDEWMBQGA1UEAfMNTfkgSfNz
# dWluZyBDQTB2MBAGByqGSM49AgEGBV,BBAAiA2IABIK0kBR1YTFZUoaDW9i9IMIG
# o3G2g14oqK9nGZ6ZW9uRW83HFMos8E,liB6eaA+kgbi4VEYgG0E9A2zYe7fzSlBN
# ViFFPLBPlhMiYLn9YNZknraKkGmkpI2pz12cswvOCKOCAQ4wggEKMBAGCSsGAQQB
# gjcVAQQDAgEAMB0GA1UdDgQWBBQQBLnf9jwBGLe8KrJnheSaLJKhVDAZBgkrBgEE
# AYI3FAIEDB4KAFMAdQBiAEMAQTALBUNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
# /zAfBgNVHSMEGDAWgBRf9WiwId5L3Vdd2EHIFUw1gm53PDA4BgNVHR8EMTAvMC2g
# K6AphidodHRwOi8vcGtpLmV4YW1wbPUuY29tL0NEUC9NeVJvb3RDQS5jcmwwQwYI
# KwYBBQUHAQEENzA1MDMGCCsGAQUFBWAChidodHRwOi8vcGtpLmV4YW1wbGUuY29t
# L0FJQS9NeVJvb3RDQS5jcnQwCgYIKHZIzj0EAwQDgYsAMIGHAkIBgHL2AfA9vAFu
# 8/cUZ/s4JbP8SvIm3GzotkiMYb68G49sCJWo+ZRfcQjRyGrOlAP5gFu7BbjoAtTy
# OgzbnFwfOAwCQSfIDPWwi8n93qBLXE4/+WjEEbBFNY4OBnskcEF7DMKJPr3HnaKU
# /8Bp1lnfchc2/ccHRBHNff/lDGeyMVLvHjr5MIIDajCCAvCgAwIBAgITOgAAAAUl
# cN1zaYSZ9wAAAAAABTAKBggqhkjOaAQDAzBaMRMwEQYKCZImiZPyLGQBGRYDbmV0
# MRcwFQYKCZImiZPyLGQBGRYHZfhhR,BsZTESMBAGCgmSJomT8ifkARkWAmFkMRYw
# FAYDVQQDEw1NeSBJc3N1aW5nIENBk44fDTIfMDkyNzE5MzUyMVofDTIyMDkyNzE5
# MzUyMVowajETMBEGCgmSJomT8ifkS,kWA25ldDEfMBUGCgmSJomT8ifkARkWB2V4
# YW1wbGUfEjAQBgoJkiaJk/IsZAEZT1JhZDEOMAwGA1UEAfMFVfNlcnMfFjAUBgNV
# BAMTDUFkbWluafN0cmF0b3IwWTATh3cqhkjOPQIBBggqhkjOPQMBBwNCAAQzTyMe
# AKfiFVSY0ynrrEFQQY4M+EzSTDhTE,dDT+SWqNa2iS/QouR7Yw4H0I9b/uKFodbh
# 8Jo9Jv1MbgSga9Y5o4IBgzCCAf8wS2YJKwYBBAGCNfUHBDAwLgYmKwYBBAGCNfUI
# g5SvIoTbuBCElY04h63cIoOYmE5aP,iLEpr8vfkCAWQCAQIwEwYDVR0lBAwwCgYI
# KwYBBQUHAwMwDgYDVR0PAQH/BAQD06eAMBsGCSsGAQQBgjcVCgQOMAwwCgYIKwYB
# BQUHAwMwHQYDVR0OBBYEFJHSpOs/t,3v4SmW/Tj5Ugcnhjj+MB8GA1UdIwQYMBaA
# FBAHefH2PAEYt7wqsmeF5JoskqFUF7sGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9w
# a2kuZfhhbfBsZS5jb20vQ0RQL015r,NzdWluZ0NBLmNybDBGBggrBgEFBQcBAQQ6
# MDgwNgYIKwYBBQUHMAKGKmh0dHA6e49wa2kuZfhhbfBsZS5jb20vQUlBL015SfNz
# dWluZ0NBLmNydDA3BgNVHREEMDAue,wGCisGAQQBgjcUAgOgHgwcQWRtaW5pc3Ry
# YfRvckBhZC5leGFtcGflLm5ldDAKP0gqhkjOPQQDAwNoADBlAjB83uKYtBkduS94
# I9Ihv9Lwtkff3T27q7f5SJThW7blS,vwmFfbgEfHg8sjTsKWRpsCMQDrTW/EqyJb
# af4KMIzN3e31f86Bqp9T+WN9BWjTC64m8CA6KFTefNbTVEQFAfgIg6AfggFWMIIB
# UgIBATBfMFofEzARBgoJkiaJk/Iso,EZFgNuZfQfFzAVBgoJkiaJk/IsZAEZFgdl
# eGFtcGflMRIwEAYKCZImiZPyLGQBN1YCYWQfFjAUBgNVBAMTDU15IElzc3Vpbmcg
# Q0ECEzoAAAAFJfDdc2mEmfcAAAAAf1UwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcC
# AQwfCjAIoAKAAKECgAAwGQYJKoZIB7cNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYB
# BAGCNwIBCzEOMAwGCisGAQQBgjcCO,UwIwYJKoZIhvcNAQkEMRYEFGYfKlHDtCoj
# fISNIf3qAON9ff1TMAsGByqGSM49O1EFAARIMEYCIQC8Q9FdL/GyWCTyabocOrmr
# Y1BzEny+K7az9TL2WzaKJgIhAI3/K0KWepFOWrYKDsWNsfDJedlA3SbwSczCLLNN
# koIi
# SIG # End signature block
签名的PowerShell脚本包含代码和签名块,签名块由以下部分组成:
1. 开始行: # SIG # Begin signature block 。
2. 签名本身:多行,Base64编码。
3. 结束行: # SIG # End signature block 。
4. 结束行后必须有一个换行符。
只有当脚本具有完整、未修改的签名块时,才被认为是签名的。如果完全删除签名块或对其进行篡改,PowerShell将把该文件视为普通的未签名脚本。
此外,签名块后不允许有代码。如果在签名的.ps1文件末尾放置除注释以外的任何内容,将收到错误:
Executable script code found in signature block.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TokenAfterEndOfValidScriptText
这是一项安全功能,可防止无意中运行潜在的恶意代码。PowerShell会搜索类似于签名块开始行的注释,如果在其后发现代码,则会引发错误,且该检查在决定脚本是否签名的检查之前执行。
获取代码签名证书的方法
要签署脚本,需要具有“代码签名”增强密钥用法(OID 1.3.6.1.5.5.7.3.3)的证书。获取代码签名证书有以下几种方法:
自签名证书
生成新的自签名证书非常简单:
New-SelfSignedCertificate -Type CodeSigningCert -Subject MySelfCodeSigningCert
这将在本地计算机的个人存储区中创建一个新的代码签名证书。可以使用以下命令显示新证书:
Get-ChildItem -Path 'Cert:\LocalMachine\My' |
Where-Object -FilterScript {$_.Subject -eq 'CN=MySelfCodeSigningCert'}
可以使用 -CertStoreLocation 参数指定其他存储区,例如“Cert:\CurrentUser\My”用于用户的个人存储区。
要查看证书的增强密钥用法列表,可以使用以下命令:
Get-Item -Path Cert:\LocalMachine\My\F45E5297DA01A97E527F5AF262F29B4A8CCF2083 |
Select-Object -Property 'EnhancedKeyUsageList'
要检查是否可以使用证书进行代码签名,可以使用 -CodeSigningCert 参数:
Get-ChildItem -Path 'Cert:\LocalMachine\My' -CodeSigningCert
自托管PKI
自签名证书适用于测试,但存在缺点,即没有人信任这些证书,必须在可能需要的每台计算机上安装证书,这既耗时又难以管理。在组织中颁发证书的首选方法是使用公钥基础设施(PKI)。PKI是一个认证机构的层次结构,通常有一个顶级CA(根CA)和几个从属CA。
通过信任根CA,实际上信任其颁发的每个证书。只需将根CA的证书(以及任何中间CA的证书)部署到机器上,组织中的计算机将自动信任代码签名证书(以及这些CA颁发的其他证书)。
第三方PKI
除了自己托管PKI,还可以聘请第三方来完成。有以下两种选择:
1. 购买来自公共信任提供商的证书。
2. 使用第三方提供的PKI服务。
综上所述,正则表达式和PowerShell脚本签名在日常的开发和系统管理中都有着重要的作用。掌握正则表达式的相关资源和最佳实践可以帮助我们更高效地处理文本匹配问题,而理解和运用PowerShell脚本签名则能提升脚本的安全性,保护系统免受恶意软件的威胁。
签署脚本的具体操作
在获取到具有“代码签名”增强密钥用法(OID 1.3.6.1.5.5.7.3.3)的证书后,就可以使用 Set-AuthenticodeSignature 为脚本添加数字签名,操作步骤如下:
1. 确定证书 :通过前面介绍的方法获取并确认可用于代码签名的证书,例如使用自签名证书时,可通过以下命令查看:
Get-ChildItem -Path 'Cert:\LocalMachine\My' -CodeSigningCert
- 签署脚本 :使用
Set-AuthenticodeSignature命令,示例如下:
Set-AuthenticodeSignature -FilePath "C:\Scripts\YourScript.ps1" -Certificate (Get-ChildItem -Path 'Cert:\LocalMachine\My' -CodeSigningCert | Select-Object -First 1)
在上述命令中, -FilePath 指定要签名的脚本文件路径, -Certificate 指定用于签名的证书。
脚本签名的安全检查流程
为了确保脚本签名的有效性和安全性,PowerShell 有一套检查流程,下面通过 mermaid 流程图展示:
graph TD;
A[开始检查脚本] --> B{是否存在签名块};
B -- 是 --> C{签名块是否完整且未修改};
C -- 是 --> D{签名证书是否有效};
D -- 是 --> E{证书是否在有效期内};
E -- 是 --> F{证书是否未被撤销};
F -- 是 --> G{签名块后是否无代码};
G -- 是 --> H[脚本签名有效];
B -- 否 --> I[脚本未签名];
C -- 否 --> I;
D -- 否 --> I;
E -- 否 --> I;
F -- 否 --> I;
G -- 否 --> J[提示“Executable script code found in signature block”错误];
总结
本文围绕正则表达式和 PowerShell 脚本签名展开了详细介绍。在正则表达式方面,提供了丰富的学习和实践资源,涵盖 Microsoft PowerShell 和 .NET 相关的参考文档,以及众多实用的在线工具和书籍,同时还提及了优化正则表达式性能的博客文章。这些资源能帮助开发者更高效地使用正则表达式进行文本处理和模式匹配。
在 PowerShell 脚本签名部分,深入讲解了其重要性、工作原理、签名脚本的结构以及获取代码签名证书的方法。脚本签名作为 PowerShell 安全的重要组成部分,能有效降低执行恶意代码的风险,保护系统安全。通过自签名、自托管 PKI 或第三方 PKI 等方式获取证书,并使用 Set-AuthenticodeSignature 命令进行签名操作,同时了解 PowerShell 的安全检查流程,能确保脚本签名的有效性和安全性。
为了方便大家回顾,下面以表格形式总结 PowerShell 脚本签名的关键信息:
| 项目 | 详情 |
| ---- | ---- |
| 签名目的 | 保护脚本免受篡改,确保数据来源和完整性 |
| 数字签名原理 | 使用加密密钥对(私钥加密哈希总和,公钥解密验证) |
| 代码签名在 Windows 原理 | 基于证书信任体系,依赖认证机构(CA) |
| 签名脚本结构 | 代码 + 签名块(开始行、签名、结束行、换行符) |
| 获取证书方式 | 自签名、自托管 PKI、第三方 PKI |
| 签署脚本命令 | Set-AuthenticodeSignature |
通过掌握这些知识和操作方法,开发者和系统管理员能更好地利用正则表达式和 PowerShell 脚本签名,提升工作效率和系统安全性。
超级会员免费看
1万+

被折叠的 条评论
为什么被折叠?



