Copying from one server to other with credentials - copy

I'm trying to copy a file from one server to another server so that it doesn't ask me to enter my login info and I don't have to store the password blatently in the code. The problem is, it's still coming up with a credential request GUI, even though I give the -Credential parameter. This is how I store the password in a file:
read-host -assecurestring | convertfrom-securestring | out-file C:\secString.txt
Then the code looks like this:
function GetSecureLogin() {
$username = "usa02xxxswg2\20xbackup"
$password = get-content C:\secString.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
}
function CopyFileToFolder ([string]$Source, [string]$destination){
Copy-Item "$Source" -Destination "$destination" -Credential $cred #this is where the login info box is coming up but shouldn't be
}
######################start here#####################
$cred = ""
GetSecureLogin
$tempSource = "filename.txt"
$ToLocation = "$ToLoc"
CopyFileToFolder $tempSource $ToLoc
Any ideas? I'm relatively new to PowerShell, so I could be doing something silly. I'm not sure how to tell if $cred is getting back to my Copy function ok or if it's out of scope.
I've looked at these examples but I'm having trouble deciding if I need to do something different because they are specifying the server info and I'm trying to avoid that since I just want to use UNC path like I was doing before. The copying was working fine without login because I was using my Active Directory login to save the task. Now we want to use a locally saved login (where the script is run) and then it needs a different local login when it's trying to access the other server.
copy-item with alt cred,
powershell without prompt for cred,
copy without cred,
copy with alt cred,
cred without password prompt

I'm trying to figure out if returning $cred from my GetSecureLogin function, and assigning it to $cred in the main part of the script will fix the problem where it's asking me for the login info when I do the copy. It looks like my co-worker moved all the directories, so I still have to test this once I figure out where he moved them to.

Looks like I figured it out. I did it like this link. It was a little tricky in that I didn't have to use the directory that came after my sharename, but once I got rid of the subdirectory, it worked.
copy with credentials and New-PSDrive

Related

Setting autologon to a local user after joining to a domain

I'm building an application to assist in re-configuring devices on our network. I've got the entire script working except for setting the device to auto logon. Nothing I am trying seems to work. Now, the use is a little different, as the device will be joined to the domain, but logged on with a local user account. I'm trying to use the Sysinternals Autologon utility, but it is not working.
Here is the relevant code for logging on:
function Set-Autologon {
param (
[Parameter()][string]$domain
)
$exePath = "$scriptPath\$autologon"
$user = 'aloha'
$logonPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
$defaultdomain = "DefaultDomainName"
$alohass = '<very long string>' | ConvertTo-SecureString -Key $key
$alohaptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($alohass)
$aloharesult = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($alohaptr)
LogInfo "Setting auto logon for $aloha user."
Start-Process -FilePath $exePath -ArgumentList "/accepteula", $user, $domain, $aloharesult -Wait -Verbose
}
The domain is being passed in as that is coming from a CSV file. The $key is set somewhere else in the script. I've tried with the /accepteula in both the front and the back.
What am I missing here?
Thanks
This should work with "/accepteula" as the last argument but, you can create a DWORD registry key in HKCU\Software\Sysinternals\AutoLogon for EulaAccept=1 before running the exe. You could also try starting the autologon.exe with the /accepteula flag and then immediately killing the process before running with the username/credentials arguments.

Prevent PowerShell script from being read

I have the below PowerShell script (myscript.ps1) in which I ask for username and password. Depending on the username and password it copies a file to a certain destination.
$credentials = Get-Credential
if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1")
{ Copy-Item "test1.pdf" "\test\test1.pdf"; }
else
{ Copy-Item "test2.pdf" "\test\test2.pdf"; }
Requirement: I want to make this file protected so no one can edit it and see the username and password.
PS2EXE
I found a solution found here which converts the PowerShell script to an .exe file. When I originally run the script using PowerShell a dialog box appears allowing me to enter the username and password:
After the .exe is generated and when I run it the credentials dialog box no longer appears. Instead, the console appears saying "Credential:"
I don't know why? I want the credentials form to still appear when running the exe. Any thoughts please?
Q: Why does the EXE prompt with "Credential"?
This isn't an answer to the real question, and is based on guessing/supposition about PS2EXE, but I hope it is useful to clear up some confusion.
Having looked briefly at the PS2EXE page linked above, it seems that this utility encodes the script in Base64 and bundles it with a lightweight (?) custom PowerShell host. When run, I suppose the EXE starts the host, decodes the script and runs it.
The problem is that the Get-Credential cmdlet is running within a PS host that probably can't interact with the desktop. That is, it can't put up the GUI prompt for credentials. It therefore needs to prompt for the Credential property on the command line, explaining why you see that behaviour.
Workaround with Read-Host?
Instead of trying to use Get-Credential to prompt for username and password, you could embrace what PS2EXE seems to be doing and just use Read-Host:
$UserName = Read-Host "Enter username"
$Password = Read-Host "Enter password" -AsSecureString
$Credentials = New-Object System.Management.Automation.PSCredential $UserName,$Password
if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1")
{ ... }
Using -AsSecureString will hide the password on the screen. The $Password variable will be of type System.Security.SecureString, which can be used to create a PSCredential object as shown.
You'd need to test this, but it seems that you're able to read from the shell but not from a GUI prompt.
And just to be clear: none of this is anywhere near best-practice security. If you need authentication/authorization for these activities, step back and look at the problem again.
Workaround with two scripts?
It seems that PS2EXE doesn't support -AsSecureString in the same way that normal PowerShell does, i.e. it doesn't hide the characters. A possible workaround for this would be to collect the username and password from the user in one script and then pass them to a PS2EXE-converted script for processing.
Launch-MyScript.ps1:
$Credentials = Get-Credential
& MyScript.exe $Credentials.Username $Credentials.Password
MyScript.exe (coverted with PS2EXE):
param($Username,$Password)
$Credentials = New-Object System.Management.Automation.PSCredential $Username,$Password
if ($Credentials.Username -eq "user1" -and
$Credentials.GetNetworkCredential().password -eq "pass1")
{
...
}
The user runs Launch-MyScript.ps1 and completes the password prompt. Then the EXE is run automatically with the username and password passed in as arguments. Note that, as shown above, the password is a Secure String. Test this; I'm not using PS2EXE so it's a theoretical solution at the moment.
If you can't pass $Password along the pipeline as a Secure String object, you can convert it to text with ConvertFrom-SecureString in the first script, then conver it back with ConvertTo-SecureString in the second one.
According to this article http://windowsitpro.com/powershell/protect-your-powershell-scripts you should first set ur execution policy to AllSigned by Set-ExecutionPolicy AllSigned, then create a certificate using makecert cmdlet.
Then u can sign single script using Set-AuthenticodeSignature cmdlet or use .pfx File to Sign a Script which appears even safer.
Hope it helps a bit.

Powershell - Copying File to Remote Host and Executing Install exe using WMI

EDITED: Here is my code now. The install file does copy to the remote host. However, the WMI portion does not install the .exe file, and no errors are returned. Perhaps this is a syntax error with WMI? Is there a way to just run the installer silently with PsExec? Thanks again for all the help sorry for the confusion:
#declare params
param (
[string]$finalCountdownPath = "",
[string]$slashes = "\\",
[string]$pathOnRemoteHost = "c:\temp\",
[string]$targetJavaComputer = "",
[string]$compname = "",
[string]$tempPathTarget = "\C$\temp\"
)
# user enters target host/computer
$targetJavaComputer = Read-Host "Enter the name of the computer on which you wish to install Java:"
[string]$compname = $slashes + $targetJavaComputer
[string]$finalCountdownPath = $compname + $tempPathTarget
#[string]$tempPathTarget2 =
#[string]$finalCountdownPath2 = $compname + $
# say copy install media to remote host
echo "Copying install file and running installer silently please wait..."
# create temp dir if does not exist, if exist copy install media
# if does not exist create dir, copy dummy file, copy install media
# either case will execute install of .exe via WMII
#[string]$finalCountdownPath = $compname + $tempPathTarget;
if ((Test-Path -Path $finalCountdownPath) )
{
copy c:\hdatools\java\jre-7u60-windows-i586.exe $finalCountdownPath
([WMICLASS]"\\$targetJavaComputer\ROOT\CIMV2:win32_process").Create("cmd.exe /c c:\temp\java\jre-7u60-windows-i586.exe /s /v`" /qn")
}
else {
New-Item -Path $finalCountdownPath -type directory -Force
copy c:\hdatools\dummy.txt $finalCountdownPath
copy "c:\hdatools\java\jre-7u60-windows-i586.exe" $finalCountdownPath
([WMICLASS]"\\$targetJavaComputer\ROOT\CIMV2:win32_process").Create("cmd.exe /c c:\temp\java\jre-7u60-windows-i586.exe /s /v`" /qn")
}
I was trying to get $Job = Invoke-Command -Session $Session -Scriptblock $Script to allow me to copy files on a different server, because I needed to off load it from the server it was running from. I was using the PowerShell Copy-Item to do it. But the running PowerShell script waits until the file is done copying to return.
I want it to take as little resources as possible on the server that the powershell is running to spawn off the process on another server to copy the file. I tried to user various other schemes out there, but they didn't work or the way I needed them to work. (Seemed kind of kludgey or too complex to me.) Maybe some of them could have worked? But I found a solution that I like that works best for me, which is pretty easy. (Except for some of the back end configuration that may be needed if it is is not already setup.)
Background:
I am running a SQLServer Job which invokes Powershell to run a script which backups databases, copies backup files, and deletes older backup files, with parameters passed into it. Our server is configured to allow PowerShell to run and under the pre-setup User account with SQL Server Admin and dbo privileges in an Active Directory account to allow it to see various places on our Network as well.
But we don't want it to take the resources away from the main server. The PowerShell script that was to be run would backup the database Log file and then use the another server to asynchronously copy the file itself and not make the SQL Server Job/PowerShell wait for it. We wanted it to happen right after the backup.
Here is my new way, using WMI, using Windows Integrate Security:
$ComputerName = "kithhelpdesk"
([Wmiclass]'Win32_Process').GetMethodParameters('Create')
Invoke-WmiMethod -ComputerName RemoteServerToRunOn -Path win32_process -Name create -ArgumentList 'powershell.exe -Command "Copy-Item -Path \\YourShareSource\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak -Destination \\YourShareDestination\YourDatabase_2018-08-07_11-45.log.bak"'
Here is my new way using passed in Credentials, and building arg list variable:
$Username = "YouDomain\YourDomainUser"
$Password = "P#ssw0rd27"
$ComputerName = "RemoteServerToRunOn"
$FromFile = "\\YourShareSource\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak"
$ToFile = "\\YourShareDestination\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak"
$ArgumentList = 'powershell.exe -Command "Copy-Item -Path ' + $FromFile + ' -Destination ' + $ToFile + '"'
$SecurePassWord = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $Username, $SecurePassWord
([Wmiclass]'Win32_Process').GetMethodParameters('Create')
Invoke-WmiMethod -ComputerName $ComputerName -Path win32_process -Name create -ArgumentList $ArgumentList -Credential $Cred
We think that this above one is the preferred one to use.
You can also run a specific powershell that will do what you want it to do (even passing in parameters to it):
Invoke-WmiMethod -ComputerName RemoteServerToRunOn -Path win32_process -Name create -ArgumentList 'powershell.exe -file "C:\PS\Test1.ps1"'
This example could be changed to pass in parameters to the Test1.ps1 PowerShell script to make it more flexible and reusable. And you may also want to pass in a Credential like we used in a previous example above.
Help configuring WMI:
I got the main gist of this working from: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-wmimethod?view=powershell-5.1
But it may have also needed WMI configuration using:
https://helpcenter.gsx.com/hc/en-us/articles/202447926-How-to-Configure-Windows-Remote-PowerShell-Access-for-Non-Privileged-User-Accounts?flash_digest=bec1f6a29327161f08e1f2db77e64856b433cb5a
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-5.1
Powershell New-PSSession Access Denied - Administrator Account
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-wmimethod?view=powershell-5.1 (I used to get how to call Invoke-WmiMethod).
https://learn.microsoft.com/en-us/powershell/scripting/core-powershell/console/powershell.exe-command-line-help?view=powershell-6 (I used to get syntax of command line)
I didn't use this one, but could have: How to execute a command in a remote computer?
I don't know for sure if all of the steps in the web articles above are needed, I suspect not. But I thought I was going to be using the Invoke-Command PowerShell statement to copy the files on a remote server, but left my changes from the articles above that I did intact mostly I believe.
You will need a dedicated User setup in Active Directory, and to configure the user accounts that SQL Server and SQL Server Agent are running under to give the main calling PowerShell the privileges needed to access the network and other things to, and can be used to run the PowerShell on the remote server as well. And you may need to configure SQLServer to allow SQL Server Jobs or Stored Procedures to be able to call PowerShell scripts like I did. But this is outside the scope of this post. You Google other places on the internet to show you how to do that.

How to run PowerShell script from a computer to untrusted domain?

I have some PowerShell scripts to update data in active directory. Now I want to run these scripts from another domain joined computer, but the user that is currently logged in does not have admin rights to AD to run the scripts. How can I pass the credentials first to connect to domain as administrator and then run the script?
I know about the command get-credentials but I don't want any manual intervention.
There is batch file which runs the script and I want to put the credentials once.
I also don't want to show the password to the logged in user. Is there any possibility we can save the password in encrypted format?
Hope there is trust between the two domains
$Server = 'XXXXXXXXXX'
$username = 'Domain\XXXXXXXXXX'
$password = 'XXXXXXXXXX'
$securepassword = ConvertTo-SecureString $Password -AsPlainText -force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList ($username,$securepassword)
Get-ADComputer -Identity $Server -Credential $cred
You can change the entire script in to exe file using PowerGUI and use credentials to save it from being opened.
or
use the script by Brenton J.W. Blawat for encryption located at http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Script-410ef9df
or
use the simple script mentioned in the below article
http://www.interworks.com/blogs/trhymer/2013/07/08/powershell-how-encrypt-and-store-credentials-securely-use-automation-script
Instead of using a batch file you could write a VBS wrapper and then use the script encoder to turn it into a VBE. The script encoder is technically not supported in Vista or 7 but it still works if you can find it somewhere. The other option would be to put all your code into a .Net EXE. Once it’s compiled it would hide the password from an ordinary user. Someone that knows what they are doing could still extract it so be aware of that. The same goes of an encoded VBE.

Creating file in a user context in powershell

I am trying to create a file using powershell in a specific user context. E.g I have a user user01 on my local machine and I want to create a file in its context.
I am doing something like
New-Item c:\file.txt -Credential User01
It works but prompts me for password which I dont want it to. Is there any way I can accomplish this without having it prompt for password ?
The credential parameter on new-item is not actually supported for filesystems, so I'm not sure what you mean by "it works." It does NOT create the file as the passed user. In fact, the filesystem provider will say:
"The provider does not support the use of credentials. Perform the operation again without specifying credentials."
Taking an educated guess, I'd say you're trying to create a file with a different owner. PowerShell cannot do this on its own, so you'll need the following non-trivial script:
http://cosmoskey.blogspot.com/2010/07/setting-owner-on-acl-in-powershell.html
It works by enabling the SeBackup privilege for your security token (but you must already be an administrator.) This allows you to set any arbitrary owner on a file. Normally you can only change owner to administrators or your own account.
Oh, and this script is for powershell 2.0 only.
Rather than use a PowerShell cmdlet or .NET scripting on this one, you might take a look at the Windows utility takeown.exe. However, even it requires you supply the user's password that you're assigning ownership to.
Ok, I do start process in the user context and then create a file. Works like a charm.
Password, FilePath and UserName are passed in as arguments from command line.
$pw = convertto-securestring "$Password" -asplaintext –force
$credential = new-object -typename system.management.automation.pscredential -argumentlist "-default-",$pw
$localArgs = "/c echo>$FilePath"
[System.Diagnostics.Process]::Start("cmd", $localArgs, "$UserName", $credential.Password, "$Computer")
Or just make a call to SUBINACL.EXE? No need for password then.