Windows Powershell SMTP server requires a secure connection - windows

I get the error:
Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at
At C:\documents\yes.ps1:22 char:1
+ Send-MailMessage #EmailSplat
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
ion
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
$MyEmail = "****#gmail.com"
$SMTP= "smtp.gmail.com"
$To = "****#gmail.com"
$Subject = "Attachments"
$Body = "Here's the attachment"
$Creds = (Get-Credential -Credential "$MyEmail")
$env:localappdata
Start-Sleep 2
$Attachments = get-childitem "$env:******" | select-object -ExpandProperty FullName
$EmailSplat = #{To = $to
From = $MyEmail
Attachments = $Attachments
Subject = $Subject
Body = $Body
SmtpServer = $SMTP
Credential = $Creds
UseSsl = $True
Port = 587
DeliveryNotificationOption = 'never'
}
Send-MailMessage #EmailSplat

You need to enable Allow less secure apps in your google account because Google may block sign in attempts from some apps (or devices) that don't use modern security standards.
Sign into google account, and after that, go to:
https://www.google.com/settings/security/lesssecureapps
And enable the Allow less secure apps option.

The step without which this won't work is : App Password
After Allow less secure apps, I was still facing the same issue because google recently updated its authentication mechanism. Here are the steps
Make Sure the account from which you're trying to send mail has Two Factor Authentication enabled and it has also Allow less secure apps enabled.
If you're successful with step 1, You will be able to see App Passwords options.
Just select the appropriate option where you want to use your google account.
For the OP, My images shows what you need.
After Enabling Two Factor Authentication this is what should be there
After creating app password

Related

How to fix security within WinSCP SFTP scripts in PowerShell with hard-coded passwords

So my organization has tasked me with cleaning up some of the security issues in regards to some automated scripts that have hard coded passwords within the scripts that are running as automated tasks. One such task contains SFTP scripts that export and import files to and from with the password, host name, credentials, port, and everything exposed within the script. As a result, I would like to first see about how to call such credentials within a separate file that can be hidden and two see about encryption and salting it later. But my main focus is getting them out of the script in case traffic is every intercepted. Here is what the PowerShell code looks like:
param (
$localPath = 'E:\FTP\SchooLinks\course_requests.csv',
$remotePath = '/schoolinks_exports/course_planning/course_requests.csv'
)
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "<domain_name>"
UserName = "<username>"
Password = "<password>"
SshHostKeyFingerprint = "<fingerprint>"
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Upload files
$transferOptions = New-Object WinSCP.TransferOptions
$transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
$transferResult =
$session.GetFiles($remotePath, $localPath, $False, $transferOptions)
# Throw on any error
$transferResult.Check()
# Print results
foreach ($transfer in $transferResult.Transfers)
{
Write-Host "Download of $($transfer.FileName) succeeded"
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}
Another one that we have looks like this:
param (
$localPath = 'E:\FTP\TalentEd\SkywardApplicantExportSQL.txt',
$remotePath = '/SkywardApplicantExportSQL.txt'
)
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "<domain>"
UserName = "<username>"
Password = "<password>"
SshHostKeyFingerprint = "<sha_fingerprint>"
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Upload files
$transferOptions = New-Object WinSCP.TransferOptions
$transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
$transferResult =
$session.GetFiles($remotePath, $localPath, $False, $transferOptions)
# Throw on any error
$transferResult.Check()
# Print results
foreach ($transfer in $transferResult.Transfers)
{
Write-Host "Download of $($transfer.FileName) succeeded"
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}
I am familiar with Python and json and calling stuff within a json file similar to the following:
import json
with open('secrets.json','r') as f:
config = json.load(f)
and calling it with (config['object']['nested_element']) within the Python script.
I would like to do something similar with PowerShell, however I have very limited knowledge to PowerShell.
Yeppers, of course, never store creds in clear text in files.
There are several ways to store credentials for use. Secure file (xml, etc..), the registry, or Windows Credential Manager and this is well documented on Microsoft sites, as well as in many articles all over the web and via Q&A's on StackOverflow.
Just search for 'securely store credentials PowerShell'
Sample results...
Working with Passwords, Secure Strings and Credentials in Windows
PowerShell
How to run a PowerShell script against multiple Active Directory
domains with different credentials
Accessing Windows Credentials Manager from PowerShell
Save Encrypted Passwords to Registry for PowerShell
...and/or the modules via the MS powershellgallery.com directly installable from your PowerShell environments.
Find-Module -Name '*cred*' |
Format-Table -AutoSize
<#
# Results
Version Name Repository Description
------- ---- ---------- -----------
2.0 CredentialManager PSGallery Provides access to credentials in the Windows Credential Manager
2.0.168 VcRedist PSGallery A module for lifecycle management of the Microsoft Visual C++ Redistributables. Downloads the supp...
1.3.0.0 xCredSSP PSGallery Module with DSC Resources for WSMan CredSSP.
1.1 VPNCredentialsHelper PSGallery A simple module to set the username and password for a VPN connection through PowerShell. Huge tha...
1.0.11 pscredentialmanager PSGallery This module allows management and automation of Windows cached credentials.
4.5 BetterCredentials PSGallery A (compatible) major upgrade for Get-Credential, including support for storing credentials in Wind...
1.0.4 WindowsCredential PSGallery Management module for Windows Credential Store.
...
#>
So many thanks to #postanote and #Martin Prikryl I was able to figure this out.
You can basically use a config.xml file with contents similar to this:
<Configuration>
<localPath>insert_local_file_path</localPath>
<remotePath>insert_remote_file_path</remotePath>
<Protocol>[WinSCP.Protocol]::Sftp</Protocol>
<HostName>insert_hostname</HostName>
<UserName>username</UserName>
<Password>mypassword</Password>
<SshHostKeyFingerPrint>fingerprint</SshHostKeyFingerPrint>
</Configuration>
From here you can use the following at the beginning of your template:
# Read XML configuration file
[xml]$config = Get-Content ".\config.xml"
param (
$localPath = $config.Configuration.localPath
$remotePath = $config.Configuration.remotePath
)
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = $config.Configuration.Protocol
HostName = $config.Configuration.HostName
UserName = $config.Configuration.UserName
Password = $config.Configuration.Password
SshHostKeyFingerprint = $config.Configuration.SshHostKeyFingerprint
}
I have more SFTP templates here people can use at
https://github.com/Richard-Barrett/ITDataServicesInfra/tree/master/SFTP

How do I get notification to my phone, when my PC starts?

I want to know how can I get notification to my phone when my PC goes online (Turns On).
TeamViewer can help you: https://www.teamviewer.com.
If you install this app on your pc and you sync your user on your iPhone, I guess that whenever your pc starts you will get a notification
If your pc have login in, you can create an powershell script for any time when some one login in your pc you receive an email. Or, this is hard, you can creat an powershell script for when an service start on your pc, send you an email too, you set the service on the start.
$filter="*[System[EventID=7036] and EventData[Data='SIOS DataKeeper']]"
$A = Get-WinEvent -LogName System -MaxEvents 1 -FilterXPath $filter
$Message = $A.Message
$EventID = $A.Id
$MachineName = $A.MachineName
$Source = $A.ProviderName
$EmailFrom = "sios#medfordband.com"
$EmailTo = "sios#medfordband.com"
$Subject ="Alert From $MachineName"
$Body = "EventID: $EventID`nSource: $Source`nMachineName: $MachineName `n$Message"
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("sios#medfordband.com", "MySMTPP#55w0rd");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
Like this, the event is the SIOS DataKeeper, when someone start the service you will receive an email. You can set the service for windows start, when the windows start you will receive an email.

Can you create an anonymous-access Windows share all from PowerShell?

Windows makes it difficult to create a network share with anonymous access (in other words, users who the share-hosting machine does not know about can access). The net share ShareName=C:\DesiredShareSource /GRANT:EVERYONE,FULL gives access to Everyone, but that does not include anonymous access (e.g. non-domain joined users, WITHOUT prompting credentials).
I know there's a way to do this from a GUI (https://serverfault.com/questions/272409/setting-up-an-anonymous-windows-server-2008-network-share), but is there a way changing security policies and creating anonymous network shares can be done strictly from PowerShell?
EDIT
This is what happens when I run the WMI script posted by Ansgar Wiechers. I get an exception but the share mounts successfully:
However, when I try and connect to the share from another box on the same network, I am still prompted for a username and password, as seen below:
Again, I want anonymous access (no username and password) to be set up all from command line.
Here is the exact code I am using in testingAnonShare.ps1, on a Win7 system:
$path = 'C:\Users\<REDACTED>\Desktop\Attempt'
$name = 'testinganon'
$description = 'share description'
function Get-Trustee($sid) {
$trustee = ([wmiclass]'Win32_Trustee').CreateInstance()
$trustee.SID = ([wmi]"Win32_SID.SID='$sid'").BinaryRepresentation
return $trustee
}
function New-FullAce($sid) {
$ace = ([wmiclass]'Win32_ACE').CreateInstance()
$ace.AccessMask = 2032127 # full control
$ace.AceFlags = 3 # container inherit + object inherit
$ace.AceType = 0 # access allowed
$ace.Trustee = Get-Trustee $sid
return $ace
}
$sd = ([wmiclass]'Win32_SecurityDescriptor').CreateInstance()
$sd.ControlFlags = 4
$sd.DACL = (New-FullAce 'S-1-1-0'),
(New-FullAce 'S-1-5-7')
$wmi = Get-WmiObject Win32_Share -List
$wmi.Create($path, $name, 0, $null, $description, '', $sd) | Out-Null
All examples create a share called test mapped to a path D:\test, granting full access to Anonymous and Everyone.
Windows Server 2012 R2 and newer
To create a share with everyone having Full access this is the command
New-SmbShare -Name 'test' -path 'D:\test' -FullAccess 'ANONYMOUS LOGON','Everyone'
To update an existing share to have the same permission is a little more complicated. First, assume the share name is test. Here is the code to change it to the same permissions as above.
Get-SmbShare -Name test |
Set-SmbShare -SecurityDescriptor 'O:BAG:DUD:(A;;FA;;;AN)(A;;FA;;;WD)'
To get the SecurityDescriptor string, create a share test like you want it and run the following command.
(get-smbshare -Name Test).SecurityDescriptor
Backward compatible (NET SHARE)
This can also be done with net share
net share test=D:\test /GRANT:"ANONYMOUS LOGON,FULL" /GRANT:"Everyone,FULL"
In addition to New-SmbShare (Windows Server 2012 or newer) and net share you can also use WMI for creating network shares.
$path = 'C:\DesiredShareSource'
$name = 'sharename'
$description = 'share description'
function Get-Trustee($sid) {
$trustee = ([wmiclass]'Win32_Trustee').CreateInstance()
$trustee.SID = ([wmi]"Win32_SID.SID='$sid'").BinaryRepresentation
return $trustee
}
function New-FullAce($sid) {
$ace = ([wmiclass]'Win32_ACE').CreateInstance()
$ace.AccessMask = 2032127 # full control
$ace.AceFlags = 3 # container inherit + object inherit
$ace.AceType = 0 # access allowed
$ace.Trustee = Get-Trustee $sid
return $ace
}
$sd = ([wmiclass]'Win32_SecurityDescriptor').CreateInstance()
$sd.ControlFlags = 4
$sd.DACL += (New-FullAce 'S-1-1-0').PSObject.BaseObject
$sd.DACL += (New-FullAce 'S-1-5-7').PSObject.BaseObject
$wmi = Get-WmiObject Win32_Share -List
$wmi.Create($path, $name, 0, $null, $description, '', $sd) | Out-Null
S-1-1-0 and S-1-5-7 are the well-known SIDs of the Everyone and Anonymous groups respectively.
Appending each ACE separately to the DACL property is required to make the code work with PowerShell v2. In more recent version you can assign the ACEs as an array, and you also don't need to unwrap the base object:
$sd.DACL = (New-FullAce 'S-1-1-0'), (New-FullAce 'S-1-5-7')
To actually enable anonymous access to shares you also need to make three changes to the local security policy (source):
Start secpol.msc.
Navigate to Security Settings → Local Policies → Security Options.
Change the following settings:
Accounts: Guest account status → Enabled
Network access: Let Everyone permissions apply to anonymous users → Enabled
Network access: Shares that can be accessed anonymously → sharename
Note that I did not have to change the setting Network access: Restrict anonymous access to Named Pipes and Shares to enable anonymous access from Windows 7 to an anonymous share on Server 2012 R2, but I did have to add NTFS permissions for the Everyone group.
$acl = Get-Acl -Path 'C:\DesiredShareSource'
$ace = New-Object Security.AccessControl.FileSystemAccessRule(
'Everyone', 'ReadAndExecute', 'ContainerInherit, ObjectInherit', 'None', 'Allow'
)
$acl.AddAccessRule($ace)
Get-Acl -Path 'C:\DesiredShareSource' -AclObject $acl
I'm not aware of a way to make the policy changes with a script. You may be able to cook up something by wrapping secedit in PowerShell, but whenever I had to deal with secedit it turned out to be … bothersome, so I wouldn't recommend it. In a domain environment you can deploy local security policy settings via group policies, though.

Is there an easy way to check if CredSSP is enabled on a systems?

I am aware of the Get-WSManCredSSP function; however, this cmdlet does not work well in a script. This returns a long string similar to the following:
The machine is configured to allow delegating fresh credentials to the following target(s): wsman/*,wsman/*,wsman/*,wsman/*
This computer is configured to receive credentials from a remote client computer.
I cannot easily include this in a script that I am writing, so I'm looking for an alternative way to check CredSSP.
Can't you consider using this as documented in the CmdLet help: Gets the WS-Management CredSSP setting on the client (<localhost|computername>\Client\Auth\CredSSP).
On a local machine it gives :
(Get-Item WSMan:\localhost\Client\Auth\CredSSP).value
You can use it like this :
(Get-Item WSMan:\localhost\Client\Auth\CredSSP).value -eq $false
You can first test if WinRm is available :
(Get-Service -Name winrm ).Status
I was also struggling with the limitations of the Get-WSManCredSSP output, and found this helper script by Victor Vogelpoel/Ravikanth Chaganti to be really helpful.
Some examples:
Check if current machine has been configured as CredSSP server and/or client:
(Get-WSManCredSSPConfiguration).IsServer
(Get-WSManCredSSPConfiguration).IsClient
Check if a specified client machine has been set up for delegation:
Get-WSManCredSSPConfiguration | % { $_.ClientDelegateComputer.Contains('clientcomputername') }
(not intended as a replacement for the work of Vogelpoel & Chaganti, but as a quick summary of a quick reading of CredSSP.cs, so you can get a quick grasp of what it's doing - that said, it was tested on several systems I had at hand and seems to work)
function Get-WSManCredSSPState
{
$res = [pscustomobject]#{DelegateTo = #(); ReceiveFromRemote = $false}
$wsmTypes = [ordered]#{}
(gcm Get-WSManCredSSP).ImplementingType.Assembly.ExportedTypes `
| %{$wsmTypes[$_.Name] = $_}
$wmc = new-object $wsmTypes.WSManClass.FullName
$wms = $wsmTypes.IWSManEx.GetMethod('CreateSession').Invoke($wmc, #($null,0,$null))
$cli = $wsmTypes.IWSManSession.GetMethod('Get').Invoke($wms, #("winrm/config/client/auth", 0))
$res.ReceiveFromRemote = [bool]([xml]$cli).Auth.CredSSP
$afcPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation\AllowFreshCredentials'
if (test-path $afcPath)
{
$afc = gi $afcPath
$res.DelegateTo = $afc.GetValueNames() | sls '^\d+$' | %{$afc.GetValue($_)}
}
return $res
}

How can I monitor the Exchange 2003 Event Service from my application?

We had our server guys set up something on Exchange so that for a particular email address, any attachments sent to it will be dumped to a location on the file server.
The Exchange Event Service controls this behaviour, but it seems that this particular service fails fairly often. I dont know why - I dont have access to the Exchange server and it is run by a team in a different country.
Is it possible to monitor this exchange service programatically so I can warn the users if it goes down? I know that the 'right' solution is to have this handled by the Exchange team, but because of the timezone differences (and their massive workload) I really need to handle it from my end.
Could you do something like this with WebDav?
You could use the following powerShell script:
# Getting status of Exchange Services and look for anything that's "stopped"
$ServiceStatus = get-service MSExch* | where-object {$_.Status -eq "stopped"}
# Convert Result to String
$ServiceStatusText = $ServiceStatus | fl | Out-String
# If $ServiceStatus <> $null then send notification
If ($ServiceStatus -ne $null)
{
###Exchange Server Values
$FromAddress = "Exchange-Alert#YOUR_DOMAIN.local"
$ToAddress = "your_address#YOUR_DOMAIN.com"
$MessageSubject = "CRITICAL: An exchange service is has stopped"
$MessageBody = "One or more Exchange services has stopped running or crashed. Please check the server ASAP for possible issues`n"
$MessageBody = $MessageBody + $ServiceStatusText
$SendingServer = "msexch02.pnlab.local"
###Create the mail message and add the statistics text file as an attachment
$SMTPMessage = New-Object System.Net.Mail.MailMessage $FromAddress, $ToAddress, $MessageSubject, $MessageBody
###Send the message
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SMTPClient.Send($SMTPMessage)
}
# Else don't do anything and exit
Else
{
$null
}

Resources