当前位置: 代码网 > it编程>前端脚本>Powershell > Powershell 脚本数字签名实现方法

Powershell 脚本数字签名实现方法

2024年05月15日 Powershell 我要评论
脚本很容易被冒名顶替或者更改,因为它们是由纯文本构成的。数字签名为脚本提供了更高的安全性,因为它能确定脚本和脚本的编辑者的唯一性,并且不能被更改。作为脚本的发布者,你能确定你的脚本没有被恶意篡改。即使

脚本很容易被冒名顶替或者更改,因为它们是由纯文本构成的。数字签名为脚本提供了更高的安全性,因为它能确定脚本和脚本的编辑者的唯一性,并且不能被更改。作为脚本的发布者,你能确定你的脚本没有被恶意篡改。即使专家也无能为力,因为这种机制是基于复杂逻辑的。幸运的是,在实际应用中,你不需要深究这些细节,只需要掌握powershell脚本签名的机制和过程。

准备一个合适的证书

因为不能使用传统的纸质签名给powershell脚本进行签名,你需要另一个工具“证书”。证书就像一把私有并且安全的钥匙。证书是你的个人电子身份特征。这把私密的钥匙确保只有证书的拥有者使用证书进行脚本签名。

可以通过mmc添加管理单元查看证书,但是在powershell中有专门查看证书的支持。可以通过虚拟驱动器cert:查看本机支持的证书。

创建自签名证书

创建一个自签名证书,需要用到microsoft的工具,makecert.exe 。这个工具不能单独下载,但是它包含在微软的.net framework中,如果你的电脑上已经安装了visual studio 那就方便多了。

开始->所有程序-microsoft visual studio 2010->visual studio tools->visual studio 命令提示(2010)

makecert.exe -pe -r -n "cn=mosserpowershelltestcert" -eku 1.3.6.1.5.5.7.3.3 -ss "my"
succeeded

这里要稍微注意 -eku 参数:1.3.6.1.5.5.7.3.3,不能是其它,否则证书的预期目的属性就不是代码签名了。
上面创建的证书会自动保存在currentusermy 路径下面。可以在powershell中查看:

ps e:> ls cert:currentusermy | where {$_.subject -eq "cn=mosserpowershelltestcert"}

  目录: microsoft.powershell.securitycertificate::currentusermy

thumbprint                subject
----------                -------
ba61af0b8a856422ad9ef86104c8cedb2583a21a cn=mosserpowershelltestcert

验证代码签名证书

查看支持代码签名的证书
查看证书的签发者,代表,序列号,指纹。

## 查看预期目的为代码签名的证书:
$certs = @(dir cert:currentusermy -codesigningcert)
"找到 {0} 个代码签名证书" -f $certs.count
# 找到 1 个代码签名证书
 
## 选择 刚才创建的证书
$certificate=ls cert:currentusermy | where {$_.subject -eq "cn=mosserpowershelltestcert"}
 
## 证书的代表
$certificate.subject
# cn=mosserpowershelltestcert
 
## 证书的签发者
$certificate.issuer
# cn=mosserpowershelltestcert
 
## 证书的序列号,指纹
$certificate | select serialnumber,thumbprint | fl *
# serialnumber : c23f35ea85d9a5ab466c07a7c0469a78
# thumbprint  : 586a4332f0528867da6a0900fcf0938edd277e22

声明一个证书受信任

你会发现,在你指定证书的类型,颁发者的名称等信息后,证书的原始数据(rawdata)会自动生成。这样你不能假冒别人生成一个证书,别人也不能假冒你的名字生成一个证书。如果通过powershell查看之前生成的证书是否受信任,答案为否。

ps e:> $certificate.verify()
false

为什么我们刚才生成的证书不受信任呢?我们可以通过一个简单的步骤找到答案。在.net 中有一个方法:displaycertificate()可以通过对话框显示证书,位于system.security.dll中。这个dll默认没有引用,需要添加引用,之后显示证书对话框。

ps e:> [system.reflection.assembly]::loadwithpartialname("system.security")

gac  version    location
---  -------    --------
true  v2.0.50727   c:windowsassemblygac_msilsystem.security2.0.0.0__b03f5f7f11d50a3asys...

[system.security.cryptography.x509certificates.x509certificate2ui]::displaycertificate($certificate)

powershell 查看证书 不受信任

对话框提示:此ca根证书不受信任,要启用信任,请将该证书安装到”受信任的根证书颁发机构“存储区。

所以接下来可以将该证书复制到受信任的存储区。可以通过certmgr.msc 手动操作,也可以通过powershell自动化操作。

ps e:> $rootstore= new-object system.security.cryptography.x509certificates.x509store("root","curre
ntuser")
$rootstore.open("readwrite")
$rootstore.add($certificate)
$rootstore.close()

在执行add操作时,会有一个确认的对话框,确定即可。

接下来我们查看一下验证信息。

ps e:> $certificate.verify()
true

给powershell 脚本签名

给powershell脚本进行数字签名只需要两步:找的一个受信任的代码签名证书,剩下的工作请交给:set-authenticodesignature吧。

ps e:> 'write-host "我的第一个签名脚本"' > firstsignscript.ps1
ps e:> $certificate=ls cert:currentusermy | where {$_.subject -eq "cn=mosserpowershelltestcert"}
ps e:> set-authenticodesignature .firstsignscript.ps1 $certificate

  目录: e:

signercertificate            status path
-----------------            ------ ----
586a4332f0528867da6a0900fcf0938edd277e22 valid firstsignscript.ps1

ps e:> get-content .firstsignscript.ps1
write-host "我的第一个签名脚本"

# sig # begin signature block
# miieiqyjkozihvcnaqccoiieejccba4caqexczajbgurdgmcgguamgkgcisgaqqb
# gjccaqsgwzbzmdqgcisgaqqbgjccar4wjgidaqaabbafzdtgwusitrck0sypfvnr
# ageaageaageaageaageamcewcqyfkw4dahofaaqunxrdr+ye6sfotfvzjfn8k15w
# otigggi0miicmdccaz2gawibagiqwj816oxzpatgbaenweaaedajbgurdgmchqua
# mcmxitafbgnvbamtge1vc3nlclbvd2vyu2hlbgxuzxn0q2vyddaefw0xmja2mtyx
# mzaymjzafw0zoteymzeymzu5ntlamcmxitafbgnvbamtge1vc3nlclbvd2vyu2hl
# bgxuzxn0q2vyddcbnzanbgkqhkig9w0baqefaaobjqawgykcgyear/2ez6is3zi4
# q2rsxfprmdynztxpwarz6sk663r6x2dfqwv+kuev4vbehj20bvd9ylvcs4qgccr6
# n0d+elfby6arpst51dnkngv74tzibu1m5ekg2+didlrktx3lwec66bl+qyfiozch
# zhqcazzgdx8m8en10/b2cdg9tm9ppqscaweaaantmgswewydvr0lbawwcgyikwyb
# bquhawmwvaydvr0bbe0ws4aqjhzaasg4klndyvipjnjeiqelmcmxitafbgnvbamt
# ge1vc3nlclbvd2vyu2hlbgxuzxn0q2vydiiqwj816oxzpatgbaenweaaedajbgur
# dgmchquaa4gbafa3lvwcba8mwndkdioczqubc9/+1vieqrgah7l6u6ohzuv2ibw1
# eplxz1/dyfemnzmy9z+/yjfji774uy1etzojnz0aykgppm0bk2iegzzpdilbkpv1
# ywrv5btrt053mnhryazqp0v9sp6pob4h10tknvh0dw882zrpeb4hkk+fmyibvzcc
# avmcaqewnzajmsewhwydvqqdexhnb3nzzxjqb3dlclnozwxsvgvzdenlcnqcemi/
# neqf2awrrmwhp8bgmngwcqyfkw4dahofakb4mbggcisgaqqbgjccaqwxcjaioaka
# akecgaawgqyjkozihvcnaqkdmqwgcisgaqqbgjccaqqwhaykkwybbagcnwibczeo
# mawgcisgaqqbgjccaruwiwyjkozihvcnaqkemryefmgyez64ufors3z9jguklvxh
# p2hlma0gcsqgsib3dqebaquabigamhfjhmvlauxkgio2p9iefbvp4am6n533k89j
# 7pqxkogmu/sg9d8pilifhljzw7bu66+uzfvosxluxvqapradeosc2bldpf5cu6o7
# 61bfsjc2h5dqcgbk/90okmejp4kjqrck7hlebvv23ddvsyl4cpplbuctvmo92zd1
# b/moxro=
# sig # end signature block

递归给所有脚本文件签名

给当前文件下的所有脚本签名

ps e:> set-authenticodesignature (ls *.ps1) $certificate

  目录: e:

signercertificate            status path
-----------------            ------ ----
586a4332f0528867da6a0900fcf0938edd277e22 valid firstsignscript.ps1
586a4332f0528867da6a0900fcf0938edd277e22 valid myscript.ps1
586a4332f0528867da6a0900fcf0938edd277e22 valid pipeline.ps1
586a4332f0528867da6a0900fcf0938edd277e22 valid pslib.ps1

如果你喜欢你甚至可以递归使用

set-authenticodesignature (dir -recurse -include *.ps1) $certificate

使用对话框选择证书

如果机器上安装了代码签名的证书有许多,你可以通过friendname 或者证书的名称,证书的指纹,过滤一个证书供脚本签名。

 dir cert:currentusermy |
 where {$_.subject -eq "cn=mosserpowershelltestcert"}

另一种方法是通过.net中的内置的对话框进行选择。将查询到的证书传递给selectfromcollection()方法,在在作此操作之前必须将证书放在一个特殊的集合中。

# 对话框文本:
$title = "可用的证书"
$text = "请选择用于代码签名的证书:"
# find certificates:
$certificates = dir cert: -recurse -codesigningcert
# 加载 system.security 类库
# 将证书存放在特殊的集合(x509certificate2collection)中:
[reflection.assembly]::loadwithpartialname("system.security")
$collection = new-object system.security.cryptography.x509certificates.x509certificate2collection
$certificates | foreach-object { $collection.add($_) }
# 显示选项:
$certificate =[system.security.cryptography.x509certificates.x509certificate2ui]::`
selectfromcollection($collection, $title, $text, 0)
# 使用选择的证书进行数字签名
set-authenticodesignature -certificate $certificate[0] -filepath .firstsignscript.ps1

powershel l对话框选择 证书

powershell脚本签名验证

在脚本中签名到底能带来什么好处,那就是可以进行验证。可以手动验证,也可以自动验证。签名验证会告诉你脚本是否信任,或者是否包含了恶意篡改。

用户自行验证:手动验证,可以检查一个脚本是否包含签名代码,签名者是谁?该签名者是否受信任。
自动验证:如果你将powershell的脚本执行策略设置为allsigned. powershell会在你尝试运行脚本时自动验证,代码和脚本签名是否一致。并且会询问签名者是否受信任。

手动验证

get-authenticodesignature命令可以验证签名。例如创建一个脚本,不进行签名,通过该命令进行验证。属性statusmessage会告诉你签名验证的结果。

 "'未签名'" >notsign.ps1
$checkresult=get-authenticodesignature .notsign.ps1
$checkresult.status
notsigned
$checkresult.statusmessage
文件 e:notsign.ps1 未经数字签名。系统将不执行该脚本。有关详细信息,请参阅 "get-help about_signing"
。
$checkresult.status.gettype().fullname
system.management.automation.signaturestatus

如果运行该未签名的脚本,也会收到错误提示信息,也就是statusmessage中包含的信息。脚本的验证结果状态包括:

成员名称 描述
hashmismatch 文件的哈希码和存储的签名不匹配
incompatible 无法验证签名,因为与当前操作系统不兼容
notsigned 文件没有签名
notsupportedfileformat 指定的文件格式不支持的系统签名。这通常意味着系统不知道如何签名或验证文件的类型。
nottrusted 证书的发布者在系统中不受信任.
unknownerror 文件签名无效
valid 该文件有一个有效的签名。这意味着只有签名的语法上是合法的。这并不意味着信任。

自动验证

你不须要去验证脚本的签名,当你运行一个脚本时,powershell会自动验证。即使验证过的脚本,如果有部分内容更新,自动验证也会给出警告。
在用户将脚本执行策略设置为allsigned和remotesigned时,自动验证就会激活,如果将执行策略设置为allsigned,所有的脚本都会验证。如果你选择remotesigned,从网络上下载的脚本执行会提示需要签名。

# 设置 executionpolicy 为 allsigned. 所有
# 脚本必须有正确的签名:
set-executionpolicy allsigned
# 创建一个没有签名的脚本.
# 该脚本不会执行:
无法加载文件 e:unsigned.ps1。文件 e:unsigned.ps1 未经数字签名。系统将不执行该脚本。有关详细信息,
请参阅 "get-help about_signing"。。
所在位置 行:1 字符: 15
+ .unsigned.ps1 < <<<
  + categoryinfo     : notspecified: (:) [], pssecurityexception
  + fullyqualifiederrorid : runtimeexception

即使签名可以通过验证,也需要用户的批准,才能执行。
.firstsignscript.ps1

是否要运行来自此不可信发布者的软件?
文件 e:firstsignscript.ps1 由 cn=mosserpowershelltestcert
发布,该文件对于您的系统是不可信的。请只运行来自可信发布者的脚本。
[v] 从不运行(v) [d] 不运行(d) [r] 运行一次(r) [a] 始终运行(a) [?] 帮助 (默认值为“d”): a
我的第一个签名脚本

#第二次执行,不会询问
我的第一个签名脚本

windows powershell显示执行的脚本未进行数字签名。

设置一下可以运行未签名的脚本或者为你的脚本签名。

set-executionpolicy bypass

到这里文章就结束了,需要的朋友可以参考一下。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com