PowerShell 技能连载 - 对象的魔法(第 4 部分)
将一个对象转换为一个哈希表如何?通过这种方式,当将对象输出到一个网格视图窗口时,可以每行显示一个对象属性:
1 | # get any object |
将一个对象转换为一个哈希表如何?通过这种方式,当将对象输出到一个网格视图窗口时,可以每行显示一个对象属性:
1 | # get any object |
假设您希望隐藏对象所有没有值(为空)的属性。以下是一个简单的实现:
1 | # get any object |
这段代码将只输出包含值的属性。您甚至可以对属性排序:
1 | # get any object |
通过隐藏的 “PSObject
“ 属性,您可以获取对象成员的详细信息。例如,如果您希望知道哪个属性可以被改变,请试试这段代码:
1 | # get any object |
结果是进程对象的可以被赋值的属性列表:
MaxWorkingSet
MinWorkingSet
PriorityBoostEnabled
PriorityClass
ProcessorAffinity
StartInfo
SynchronizingObject
EnableRaisingEvents
Site
类似地,您可以轻松地找出所有当前没有值(为空)的属性:
1 | # get any object |
在 PowerShell 中,大多数据是以 PSObject
来表示的,它是一个由 PowerShell 添加的特殊的对象“包装器”。要获取这个特殊的包装器,可以通过对象名为 “PSObject
“ 的隐藏属性。让我们来看看:
1 | # get any object |
如您所见,该 “PSObject
“ 基本上是一个对象的描述。并且它包含了许多有用的信息。以下是一部分:
1 | # get any object |
这是我们的加密解密系列的第二部分。在第一部分中您学到了如何在一台计算机中安全地加密文本。现在我们来关注解密部分。
要正确地解密文本,必须指定加密时使用的相同编码。基于您的加密参数,您必须指定相同的密码。并且基于 -Scope
设置,解密将只能针对您和/或仅在您加密文本的同一机器上工作。
以下是 Unprotect-Text
函数。我们也从上一个技能中复制了 Protect-Text
函数,这样您可以方便地使用这两种功能:
1 | function Protect-Text |
以下是如何使用它的示例:
1 | $text = "This is my secret" |
Protect-Text
创建了一个 Base64 编码的字符串,它可以用 Unprotect-Text
函数来解密。如果您不希望额外的密码,那么只能使用基于 -Scope
的缺省的保护。
要节省空间,您可以使用字节数组来代替 Base64 编码的字符串:
1 | $b = Protect-Text -SecretText $text -scope CurrentUser -ReturnByteArray |
让我们来看看一种在计算机上加密文本的安全方法。以下的 Protect-Text
函数接受任意文本,并自动加密,不需要密码。它不使用密码,而是使用您的用户帐户和机器,或者只使用您的机器作为密钥。
如果使用 -Scope LocalMachine
,任何使用该机器的人都可以解密该文本,但如果该文本泄露给其他人,它无法在其它机器上解密。如果您使用 -Scope CurrentUser
,只有加密者可以解密,并且只能在加密的机器上解密。这个加密方案很适合保存您的私人密码。
此外,为了提高安全性,可以在顶部添加(可选)密码。当指定了密码时,将应用上述相同的限制,但此外还需要知道密码才能解密文本。
请注意您也可以控制文本解码。请确保加密和解密使用相同的编码。
以下是加密函数:
1 | function Protect-Text |
结果类似这样:
1 | PS> Protect-Text -SecretText 'I am encrypted' -scope LocalMachine |
如果您想了解如何将 Base64 编码的文本转换回原始文本,请看我们的下一个技能!
在内部,ActiveDirectory 将所有密码存储为所谓的 NTLM 哈希。有许多安全分析工具可以读取和转储这些哈希。
幸运的是,没有可行的方法来解密这些散列并检索原始密码,您可以使用(已知)密码并将其转换为 NTLM 哈希。这是字典攻击的基本过程:他们获取到很长的“已知密码”列表,将它们转换为 NTLM 散列,当它们与实际的 AD 帐户散列匹配时,就算破解出了密码。
这样,您的安全部门就可以将密码黑名单中的不安全密码(如“P@ssw0rd”)转换为NTLM散列,并将它们与Active Directory的密码散列进行比较,以识别需要更改密码的帐户。
这是将纯文本变为 NTLM HASH 的 PowerShell 代码:
1 | function ConvertTo-NTLMPasswordHash |
以下是一个有趣的 PowerShell 脚本,您可以用它来创建一个简易的多频道聊天室。您所需的只是一个所有人都有读写权限的网络共享目录。
该聊天室是基于文件的,并且使用 PowerShell 的功能来监视文件的改变。所以基本上,每个聊天频道是一个文本文件,并且无论何时,如果某人想“说”一些内容,那么就会向文件中添加一行。任何连接到该聊天频道的人实际上都在监视这个文件的改变。
显然,这个“聊天室”只适用于试验,并且有许多限制。例如,当某人在写文件时,其他人无法同时写入。但是,它很好地说明了 PowerShell 如何监视文件并在添加新文本时采取行动。您也可以将这个技术用在日志文件上:PowerShell 可以在日志文件有新内容的时候通知您,并且甚至自动过滤新增加的文本并根据触发关键字发出警告或采取行动。
在开始之前,请确保调整 ServerShare
并将它设置为一个可读写的网络共享目录。
下一步,您可以这样进入聊天室:
1 | Enter-Chat -ChatChannelName lunchbreak -Name Tobias -ShowOldPosts |
-ShowOldPosts
显示已有的聊天信息。如果没有添加这个参数,那么只能看见新的信息。无论何时运行 Enter-Chat
,它都会检查在 -ChatChannelName
中指定名称的文件,如果该文件不存在,就会创建它。
Get-ChatChannel
列出共享目录中的所有聊天文件,以及聊天室最后使用的时间。该信息完全取自文件属性 (LastWriteTime
)。
1 | # make sure you adjust this path |
在之前的技能中,我们讨论过了类似 haveIbeenpwned.com 的服务。它们从之前的黑客攻击中收集泄露的密码,这样您就可以检查您的密码是否已被泄露,并可能被包括在未来的字典攻击中。
以下是两个有用的函数:Test-Password
请求一个 SecureString。当您收到提示时,输入将会被屏蔽。接下来 Convert-SecureStringToText
将会将整个密码转为纯文本。然后 Test-Password
将把输入的整个密码进行哈希运算,并只发送前 5 个字节到 WEB 服务。您的原始密码永远不会泄露。
Web 服务将返回所有以该 5 个字节开头的泄露的密码哈希,这样您就可以检查返回的哈希中是否包含您的哈希。
如果您的密码在之前的攻击中出现,那么您将受到它在攻击中出现的次数。任何返回大于 0 的数字的密码都必须视为不安全的,并且不该使用。
请记住:当某个密码返回一个大于 0 的数字时,这并不意味着您的密码被破解了。它的意思是,在世界上所有地方中,您的密码在攻击中出现,所以要么您或者其他人使用它并且被黑客攻击:该密码现在不安全并且已成为攻击字典的一部分,黑客会尝试账户。如果您继续使用这个密码,黑客有可能在不就得将来利用简单(快速)的字典攻击来破解它。
在之前的提示中,我们已经讨论了haveIbeenpwned.com等服务。他们从以前的黑客攻击中收集泄露的密码,这样你就可以检查你的密码是否已被泄露,并可能被包括在未来的字典攻击中。
下面有两个有用的函数:Test-Password请求SecureString,因此当您收到提示时,您的输入将被屏蔽。然后将输入的密码转换为纯文本。然后,Test-Password散列您输入的密码,只将前5个字节发送给web服务。您的原始密码永远不会泄露。
web服务将返回所有以您的5个字节开头的密码散列,因此您可以检查返回的散列是否与您的散列匹配。
如果您的密码在以前的攻击中被发现,您将收到它参与攻击的次数。任何返回大于0的数字的密码都被认为是不安全的,不应该使用。
请记住:当密码返回一个大于0的数字时,这并不意味着您自己的密码被破解了。它的意思是,在世界上任何地方,你的密码在攻击中出现,所以要么你或其他人使用它并被黑客攻击。无论是你还是别人:这个密码现在是不安全的,因为它成为黑客攻击字典的一部分,黑客会尝试帐户。如果你继续使用这个密码,黑客很有可能在不久的将来利用简单(快速)的字典攻击来破解它。
1 | function Convert-SecureStringToText{ |
将加密的 SecureString 转换回纯文本非常有用。例如,通过这种方式,您可以使用 PowerShell 的“遮罩输入”特性。只需请求一个 SecureString, PowerShell 就会屏蔽用户输入的显示。接下来,将 SecureString 转换成纯文本,这样就可以在内部使用它来做任何您想做的事情:
1 | function Convert-SecureStringToText |
如果你想知道为什么一开始就可以将 SecureString 转换成纯文本,那么请注意:SecureString 只保护第三方的字符串内容,即“中间人”攻击。它绝不是保护真正输入密码的人。
这也体现了为什么使用凭据有风险。当一个脚本请求凭据时,脚本总是可以获取整个密码:
1 | $cred = Get-Credential -UserName $env:USERNAME -Message 'Enter your password' |
实际上,通过凭据对象,要获取输入的密码更容易,因为它有一个内置的方法实现这个功能:
1 | $cred = Get-Credential -UserName $env:USERNAME -Message 'Enter your password' |
当一个脚本请求凭据时,请确保信任该脚本(的作者)。