Decrypting AES encrypted password to plain text in PowerShell Script - powershell

I have been following along on numerous how-to articles that explain how to decrypt an AES encrypted password. No matter how I try, the password ends up with $password displaying as System.Security.SecureString. I need the password to echo in plain text because I am calling a command line utility that does not use windows permissions (ADSI/LDAP). Here's my script:
$PasswordFile = "$PSScriptRoot\PowerShell\AESpassword.txt"
$KeyFile = "$PSScriptRoot\PowerShell\AES.key"
$key = Get-Content $KeyFile
$MyPassword = ConvertTo-SecureString (Get-Content $PasswordFile | ConvertTo-SecureString -Key $key) -AsPlainText -Force
$Marshal = [System.Runtime.InteropServices.Marshal]
$BSTR = $Marshal::SecureStringToBSTR($MyPassword)
$password = $Marshal::PtrToStringAuto($BSTR)

According to #MathiasRJessen the suggestion to use $MyPassword = Get-Content $PasswordFile | ConvertTo-SecureString -Key $key worked like a charm! Thank you so much! Make sure to post that comment as the answer so I can give you credit for it. :)

Related

Powershell securestring containing comma, or ? or : not working

I've a script to convert a string to a securestring, to use it in a powershell script.
The script works fine, but I'm not able to use password when there is a comma , or ? or : (I don't know which of the special char don't work ....) inside.
Here is the script :
# Creating SecureString object
$PasswordFile = "X:\pwd\password.txt" # where the securestring will be stored
$KeyFile = "X:\pwd\password.key" # where the AES.Key is located
$Key = Get-Content $KeyFile
$Password = "azerty,12?34:5" | ConvertTo-SecureString -AsPlainText -Force # put your password
$Password | ConvertFrom-SecureString -key $Key | Out-File $PasswordFile
Thanks
I already tried a lot of escape sequences,
'''password''',
backslash, ....

Using encrypted password to send mail is failing

I'm trying to use a stored encrypted password in a script that sends an email but I keed getting the error:
send-mailmessage : The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM
[DM6PR66666019.namprd456.prod.outlook.com]
I used the following code to create the text file:
$passwordtostore = 'NotTheRealPassword$9gv8z6VHnPfDd8zc'
$secureStringPWD = $passwordtostore | ConvertTo-SecureString -AsPlainText -Force
$secureStringText = $secureStringPWD | ConvertFrom-SecureString
Set-Content "c:\temp\scriptsencrypted_password1.txt" $secureStringText
I use the following to import the password:
$passwordFile = "c:\temp\scriptsencrypted_password1.txt"
$password = Get-Content $passwordFile | ConvertTo-SecureString
Here's the sendmail function I am using:
function SendMail($ToEmails,$FromEmail,$Subj,$Body,$UserName,$Password){
$cred = New-Object System.Management.Automation.PSCredential $UserName,$Password
$MailParams=#{"from"=$FromEmail; "to"=$ToEmails;"body"=$Body;"subject"=$Subj;"smtpserver"="smtp.office365.com"}
send-mailmessage #MailParams -Credential $cred -UseSsl $true -port 587
}
Here's the code which calls the function:
$alertEmail = "me.stillme#mydomain.com"
$username="psemail#mydomain.com"
$passwordFile = "c:\temp\scriptsencrypted_password1.txt"
$password = Get-Content $passwordFile | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential($username, $password)
Import-Module -Name "..\SendMail.psm1"
... Doing some stuff
SendMail $alertEmail $username "This is the subject" "this is the body" $credential.UserName $credential.Password
Personally, I fail to see why you would make a function in a module you need to import for the Send-MailMessage cmdlet..
This makes things a lot harder to use.
Also, it kind of looks like you are switching the emailaddresses To and From inside the function.
Anyway, things go wrong when you are creating the credentials, split it into username and (secure) password to send as parameters to the function and recombine them into a credentials object in there.
Why not skip that module function and simply do:
$password = Get-Content 'c:\temp\scriptsencrypted_password1.txt' -Raw | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object System.Management.Automation.PsCredential('YourLoginName', $password)
$MailParams=#{
From = 'me.stillme#mydomain.com'
To = 'psemail#mydomain.com'
Body = "this is the body"
Subject = "This is the subject"
SmtpServer = 'smtp.office365.com'
Port = 587
UseSsl = $true
Credential = $credential
}
Send-MailMessage #MailParams
This will make your script far more readable/maintainable
I found two issues with my code above:
An unescaped $ in the password.
Once I added " -NoNewline" to the set-content, it began to work.
So, to create the encrypted file:
$passwordtostore = "7K9CBgvc4rttvfctrsef6PVHqnP6fDdwhatevervtfdscttzSc"
$secureStringPWD = $passwordtostore | ConvertTo-SecureString -AsPlainText -Force
$secureStringText = $secureStringPWD | ConvertFrom-SecureString
Set-Content "D:\Powershell Scripts\encrypted.hash" $secureStringText -NoNewline
Then to retrieve the password and use it in a credential:
$password = Get-Content $passwordFile -Raw | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential($username, $password)
It wasn't the source of the issue, but I did implement #Theo's suggestion re: using send-mailmessage.

Password from SecureString makes the script hanging

$password = Get-Content 'c:\temp\tmp1\pw.dat' | ConvertTo-SecureString
& "C:\Program Files\PuTTY\pscp.exe" -P 2222 -pw $password 'c:\temp\tmp1\test.txt' 'root#localhost:/home/root/temp'
The above code just got hanging; However, the code below worked.
$password='mypw'
& "C:\Program Files\PuTTY\pscp.exe" -P 2222 -pw $password 'c:\temp\tmp1\test.txt' 'root#localhost:/home/root/temp'
Any suggestion? I do not think I typed the password wrong since I did it several times. Furthermore, I expect an error message if the password was typed wrong.
By the way, the objective of the script is to transfer the file to a linux box.
As stated in a comment the .dat file is created using
read-host -AsSecureString | ConvertFrom-SecureString | out-file
So there are 2 ways I know of doing this.
$EncryptedString = read-host -AsSecureString | ConvertFrom-SecureString
$SecureString = $EncryptedString | ConvertTo-SecureString
$Pointer = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
$PlainTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($Pointer)
$PlainTextPassword
The secret here is the [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString) which turns the string into a bytes and returns a pointer to where it is located
The next part [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($Pointer) goes to the pointer and turns the bytes into a string.
The other way would be turning the secure string into a PSCredential.
$EncryptedString = read-host -AsSecureString | ConvertFrom-SecureString
$SecureString = $EncryptedString | ConvertTo-SecureString
$PlainTextPassword = ([PsCredential]::new("DoesntMatter",$SecureString)).GetNetworkCredential().Password
$PlainTextPassword
This turns the Secure String into a PSCredential where you can get the NetworkCredential's password which is in plain text.

Use powershell to send email while saving your password securely in encrypted file

I have found similar threads but none that solve my issue. I am trying to send an email using SMTP server, with attachment (via gmail). That's the easy bit done. The main error response I get is
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required."
I think it has to do with getting the password from the password file into the Credentials
"Password123" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:\Folder\Password.txt"
$EmailFrom = "emailaddress#gmail.com"
$EmailTo = "otheremailaddress#gmail.com"
$Subject = "Log file from server"
$Subject = "Subject"
$Body = "Here is the log file from the server"
$File = "C:\Folder\LogFile.txt"
$attachment = New-Object System.Net.Mail.Attachment($File,'text/plain')
$mailmessage = New-Object system.net.mail.mailmessage
$mailmessage.from = ($EmailFrom)
$mailmessage.To.add($emailto)
$mailmessage.Subject = $Subject
$mailmessage.Body = $Body
$mailmessage.Attachments.Add($attachment)
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$username = "emailaddress#gmail.com"
$pass = Get-Content "C:\Folder\Password.txt" | ConvertTo-SecureString -AsPlainText -Force
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($username, $pass);
$SMTPClient.Send($mailmessage)
I want to remove the first line of this code as it's never a good idea to have a password in the script.
If I change the password variable to the following I have no issue
$pass = "Password123"
All the other forum posts I found have suggested things haven't solved my problem.
Also changing gmails settings to allow access from less secure apps doesn't solve my problem.
Any help would greatly be appreciated
Thanks in advance.
EDIT:
I have gmail accessible for less secure apps
I have 2 step verification off for gmail
I believe the issue is reading the password file. It's a case of not being able to accept password from the file when it is encrypted. I tried it with an un-encrypted password but that isn't much better for scripting
I've ran into issues with this in the past - I think one of the common gotcha's was already mentioned by Mathias - watch out for running under different credentials (running as a schedule job) since decoding depends on using the user's session information. The one thing I'm not quite sure about in your example is why you're doing a subsequent convert to plain text- otherwise though, the below should take your username and password, export it to a file, then import it in as a credential you can use later.
$user = "UsernameGoesHere"
$passwordtostore = 'PasswordGoesHere'
$secureStringPWD = $passwordtostore | ConvertTo-SecureString -AsPlainText -Force
$secureStringText = $secureStringPWD | ConvertFrom-SecureString
Set-Content "C:\temp\authenticationfile.cfg" $secureStringText
# Retrieve password
$pwdin = Get-Content "C:\temp\authenticationfile.cfg"
$password = $pwdin | ConvertTo-SecureString
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $user,$password
Hope that helps?

using secure password with multiple users without prompt

I am trying to have my password secured and stored in a file so that I don't need to enter each time when I run the script.
First step, I ran the following, entered the password which got stored into E:\cred.txt file. The txt file now contains an encrypted password.
(Get-Credential).Password | ConvertFrom-SecureString | Out-File "E:\cred.txt"
Secondly, I ran the below Script:
$File = "E:\cred.txt"
$User = "jason#domain.com"
#### I have two different user accounts, one for admin and other for operator,
#### however both user accounts use same password.
$adminuser = $User
$operator = $User -replace "#domain.com"
#### I would need to read $File to get only the password
$pass = New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList (Get-Content $File | ConvertTo-SecureString)
$adminuser
$operator
$pass
Output:
jason#domain.com
jason
UserName Password
-------- --------
From the output, it seems New-Object refers to both UserName and Password. And when I try to connect to systems, it fails with Authentication error. Since I already have two different usernames hard coded within the script, how should I get only the password stored in $pass? or is it possible to include all usernames ($User, $adminuser, $operator) into the cred.txt file?
Try this:
#saving credentials
Get-Credential | Export-CliXml -Path c:\credential.xml
#importing credentials to a variable
$Credential = Import-CliXml -Path c:\credential.xml
Or this:
#you could then write it to a file or, i say its a better approach to a registry key
$SecurePassword = ConvertTo-SecureString -String 'P#ssw0rd' -AsPlainText -Force | ConvertFrom-SecureString
#now you are taking it back as a secure string
$RegistrySecureString = $SecurePassword | ConvertTo-SecureString
#you can aslo see the password
$UserName = "NULL"
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $RegistrySecureString
$Password = $Credentials.GetNetworkCredential().Password
#P#ssw0rd