Использование PowerShell для отправки защищенного письма, содержащего пароль [закрыто]

Мне нужно написать сценарий PowerShell для отправки защищенного письма, содержащего пароль. Я исследовал хорошие способы реализации, но не могу найти подходящий метод.

Сценарий таков: Человек запрашивает пароль, сценарий автоматически генерирует пароль и отправляет его на электронную почту этого человека, этот человек использует Outlook для открытия почтового ящика.

Мое желание состоит в том, чтобы заставить человека, используя его учетные данные AD, открыть почту, но чтобы сделать это, учетная запись, запускающая этот сценарий, должна иметь сертификат этого человека. Таким образом, это кажется невозможным.

Моя вторая идея заключается в том, чтобы создать веб-страницу, на которой лица, запрашивающие пароль, могут расшифровать пароль, полученный ими по электронной почте. Веб-страница требует Single-Sign-On и других ухищрений для защиты аутентифицированных пользователей, которые хотят войти в систему.

Если у вас есть идеи получше, не могли бы вы помочь мне разобраться с этим?

-1
задан 26 May 2018 в 08:48
2 ответа
param(
    $sAMAccount,
    $filePath
)

$RootDSE = [ADSI]("LDAP://RootDSE") 
$SearchForestForPerson = New-Object DirectoryServices.DirectorySearcher 
$SearchForestForPerson.SearchRoot = "GC://" + $RootDSE.rootDomainNamingContext 
$SearchForestForPerson.SearchScope = "subtree" 
$SearchForestForPerson.PropertiesToLoad.Add("distinguishedname") | Out-Null 
$SearchForestForPerson.PropertiesToLoad.Add("mail") | Out-Null 
$SearchForestForPerson.PropertiesToLoad.Add("usercertificate") | Out-Null 
$SearchForestForPerson.Filter = ("(&(objectClass=person)(CN=$sAMAccount))") 
$Recipient = $SearchForestForPerson.FindOne()
$ChosenCertificate = $null 
$Now = Get-Date 
If ($Recipient.Properties.usercertificate -ne $null) { 
    ForEach ($UserCertificate in $Recipient.Properties.usercertificate) { 
        $ValidForSecureEmail = $false 
        $Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]$UserCertificate 
        $Extensions = $Certificate.Extensions 
        ForEach ($Extension in $Extensions) { 
            If ($Extension.EnhancedKeyUsages -ne $null) { 
                ForEach ($EnhancedKeyUsage in $Extension.EnhancedKeyUsages) { 
                    If ($EnhancedKeyUsage.FriendlyName -eq "Secure Email") { 
                        $ValidForSecureEmail = $true 
                        break 
                    } 
                } 
                If ($ValidForSecureEmail) { 
                    break 
                } 
            } 
        } 
        If ($ValidForSecureEmail) { 
            If ($Now -gt $Certificate.NotBefore.AddMinutes(-5) -and $Now -lt $Certificate.NotAfter.AddMinutes(5)) { 
                $ChosenCertificate = $Certificate 
            } 
        } 
        If ($ChosenCertificate -ne $null) { 
            break 
        } 
    } 
}
$keytab = Get-item -Path $filePath
Add-Type -assemblyName "System.Security" 
$MailClient = New-Object System.Net.Mail.SmtpClient "ip.contoso.se" 
$Message = New-Object System.Net.Mail.MailMessage
$Message.To.Add($Recipient.properties.mail.item(0)) 
$Message.From = "noreply@contoso.se" 
$Message.Subject = "Test Unencrypted subject of the message"

$Body = "This is the password for your service account: p4ssw09rd23!"

$MIMEMessage = New-Object system.Text.StringBuilder 
$MIMEMessage.AppendLine("MIME-Version: 1.0") | Out-Null 
$MIMEMessage.AppendLine("Content-Type: multipart/mixed; boundary=unique-boundary-1") | Out-Null 
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine("This is a multi-part message in MIME format.") | Out-Null
$MIMEMessage.AppendLine("--unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine("Content-Type: text/plain") | Out-Null
$MIMEMessage.AppendLine("Content-Transfer-Encoding: 7Bit") | Out-Null
$MIMEMessage.AppendLine()|Out-Null
$MIMEMessage.AppendLine($Body) | Out-Null
$MIMEMessage.AppendLine() | Out-Null

$MIMEMessage.AppendLine("--unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine("Content-Type: application/octet-stream; name="+ $keytab.Name) | Out-Null
$MIMEMessage.AppendLine("Content-Transfer-Encoding: base64") | Out-Null
$MIMEMessage.AppendLine("Content-Disposition: attachment; filename="+ $keytab.Name) | Out-Null
$MIMEMessage.AppendLine() | Out-Null

[Byte[]] $binaryData = [System.IO.File]::ReadAllBytes($keytab)
[string] $base64Value = [System.Convert]::ToBase64String($binaryData, 0, $binaryData.Length)
[int] $position = 0
while($position -lt $base64Value.Length)
{
    [int] $chunkSize = 100
    if (($base64Value.Length - ($position + $chunkSize)) -lt 0)
    {
        $chunkSize = $base64Value.Length - $position
    }
$MIMEMessage.AppendLine($base64Value.Substring($position, $chunkSize))|Out-Null
$MIMEMessage.AppendLine()|Out-Null
$position += $chunkSize;
}
$MIMEMessage.AppendLine("--unique-boundary-1--") | Out-Null

[Byte[]] $BodyBytes = [System.Text.Encoding]::ASCII.GetBytes($MIMEMessage.ToString())
$ContentInfo = New-Object System.Security.Cryptography.Pkcs.ContentInfo (,$BodyBytes) 
$CMSRecipient = New-Object System.Security.Cryptography.Pkcs.CmsRecipient $ChosenCertificate 
$EnvelopedCMS = New-Object System.Security.Cryptography.Pkcs.EnvelopedCms $ContentInfo 
$EnvelopedCMS.Encrypt($CMSRecipient) 
[Byte[]] $EncryptedBytes = $EnvelopedCMS.Encode() 
$MemoryStream = New-Object System.IO.MemoryStream @(,$EncryptedBytes) 
$AlternateView = New-Object System.Net.Mail.AlternateView($MemoryStream, "application/pkcs7-mime; smime-type=enveloped-data;name=smime.p7m") 
$Message.AlternateViews.Add($AlternateView)
$MailClient.Send($Message)
0
ответ дан 5 December 2019 в 19:40

Если не считать шифрования пароля в электронном письме, я не могу избавиться от ощущения, что вы пытаетесь чтобы получить уровень безопасности электронной почты, для которого она просто не предназначена. Вы доверяете введению пароля в электронное письмо, но не доверяете тому, кто будет получателем, и пытаетесь добавить уровень проверки к отдельному электронному письму в Outlook. Для меня это звучит довольно некорректно.

Если вы все равно собираетесь настроить веб-страницу, почему бы не сделать все это на веб-странице с авторизацией пользователя там? Используйте адрес электронной почты только для уровня проверки 2FA, если он вам нужен.

1
ответ дан 5 December 2019 в 19:40

Теги

Похожие вопросы