Powershell - Masking a line with secure string causing - powershell

To log into something, I have to enter a username on page1, password on page2, then click submit on page3. To make it easier I wrote a PS script. I double checked it by hard-coding the password, and it was successful.
But not wanting to hard-code the password I used the added $pass and how to read it. But now I get invalid password when I run the script.
I wanted to use Get-Credentials, but didn't know how to just pass in the username or password on their specific pages.
I would appreciate any advice to help me in the right direction towards my goal.
$pass = Read-Host 'd\P What is your password?' -AsSecureString
[Runtime.InteropServices.Marshal]::PtrToStringAuto(
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass))
$IE = New-Object -ComObject InternetExplorer.Application
$URL = 'https://website/'
$IE.Visible = $true
$IE.Navigate($URL)
While ($IE.Busy -eq $true) {Start-Sleep -Milliseconds 1000}
$ie.Document.getElementById('DATA').value = "P0523586"
$Submit = $ie.Document.getElementsByTagName('Input') | ? {$_.Type -eq "Submit"}
$Submit.click()
While ($IE.Busy -eq $true) {Start-Sleep -Milliseconds 1000}
$ie.Document.getElementById('DATA').value = "$pass"
$Submit = $ie.Document.getElementsByTagName('Input') | ? {$_.Type -eq "Submit"}
$Submit.click()
While ($IE.Busy -eq $true) {Start-Sleep -Milliseconds 1000}
$Submit = $ie.Document.getElementsByTagName('Input') | ? {$_.Type -eq "Submit"}
$Submit.click()

Get-Credential is a good way to go about this as you aren't storing anything that should be kept secure in the script.
It's easiest to assign the Object returned from Get-Credentials to a variable:
$credentials = Get-Credential
You can then use $credentials.UserName to retrieve the username:
PS> $credentials.UserName
myusername
And $credentials.Password to retrieve Secure Password Object
PS> $credentials.Password
System.Security.SecureString
This can be used by other PowerShell commands, but needs to be decoded (made un-secure) before it can be sent to a process that cannot accept secure password objects.
To retrieve the password in plain-text, you can use the GetNetworkCredential method like this:
PS> $credentials.GetNetworkCredential().Password
mypassword
In your script you would add $credentials = Get-Credential at the start of your script, and submit the username/password to the form like this:
$ie.Document.getElementById('DATA').value = $credentials.UserName
$ie.Document.getElementById('DATA').value = $credentials.GetNetworkCredential().Password

Related

PowerShell script to download from Web

I am trying to log on web page using PowerShell and generate some. Although Powershell ISE gives some errors, current script works okay(sometimes log on sometimes not) but last part seem doesn't work to generate the Report by clicking the "CSV" Button.
Any help please?
$username = "username"
$password = "password"
$ie = New-Object -ComObject InternetExplorer.Application
$ie.visible=$true
$ie.navigate("http://..../login")
while($ie.ReadyState -ne 4) {start-sleep -m 300}
$ie.document.IHTMLDocument3_getElementById('user_session_email').Value=$username
$ie.document.IHTMLDocument3_getElementById('user_session_password').Value=$password
$ie.Document.IHTMLDocument3_getElementById('commit').Click()
$ie.navigate("http://..../activity_reports")
while($ie.ReadyState -ne 4) {start-sleep -m 100}
$currentDate= (Get-Date).ToString('dd-MM-yyyy')
$ie.document.IHTMLDocument3_getElementById('from_date').innertext= $currentDate
$ie.document.IHTMLDocument3_getElementById('to_date').Value=$currentDate
$Link=$ie.Document.IHTMLDocument3_getElementByType('submit') | where-object {$_.class -eq 'btn
btn-default btn-sm'}
$Link.click()

IE Automation with Powershell send ENTER Key

I am doing an IE Automation with ServiceNow where there is an option to fill the search data but there is no search button available to use the CLICK method. So I am looking for the method to enter key like {ENTER} or {~} once I filled the search data. But I am in a middle stage of PowerShell scripting and not sure how to use that.
If someone could help me with the method that would be greatly appreciate.
$IE = New-Object -ComObject InternetExplorer.application
$IE.FullScreen = $false
$IE.Visible = $true
$IE.Navigate($ServiceNowURL)
While ($IE.Busy -eq $true)
{
Start-Sleep -Milliseconds 50
}
$Enter = Read-Host 'To continue press ENTER'
#Enter
$Search = $IE.Document.IHTMLDocument3_getElementsByTagName('input') | ? {$_.id -eq 'sysparm_search'}
$EnterValue = $Search.value() = $TicketNumber
First, you need to active IE window and bring it to front using AppActivate, then set focus to the search area using focus(). After that, you can send Enter key using SendKeys.
I use https://www.google.com to search as an example and you can refer to my code sample below. I test it and it works well:
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
$ie = New-Object -ComObject 'InternetExplorer.Application'
$ie.Visible=$true
$ie.Navigate("https://www.google.com") #change it to your own url
while($ie.ReadyState -ne 4 -or $ie.Busy) {Start-Sleep -m 100}
$search=$ie.Document.getElementsByName("q")[0] #change it to your own selector
$search.value="PowerShell" #change it to your own search value
Sleep 5
$ieProc = Get-Process | ? { $_.MainWindowHandle -eq $ie.HWND }
[Microsoft.VisualBasic.Interaction]::AppActivate($ieProc.Id)
$search.focus()
[System.Windows.Forms.SendKeys]::Sendwait("{ENTER}");

Auto login script

I am trying to fix a script that automatically opens a page in edge and logs in. i can get it to open the page but the script errors out without entering the login info or directing to the desired final destination. the internal server page uses j_username and j_password to id the location where the credentials are entered. Im fairly new to coding and would like help to understand what im doing wrong and what i could be doing better.
Here is the code:
$ie = New-Object -ComObject 'msedge.Application'
$ie.Visible= $true # Make it visible
start microsoft-edge:http://internal URL to company
$usernmae="user"
$password="password"
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 5;}
$usernamefield = $ie.document.getElementByID('j_username')
$usernamefield.value = $username
$passwordfield = $ie.document.getElementByID('j_password')
$passwordfield.value = $password
$Link = $ie.document.getElementByID('login-submit')
$Link.click()
{Start-Sleep -Seconds 10;}
start microsoft-edge:http://final destination internal URL to company
$ie.Quit()
Your problem was that the $ie object is not connected to the browser when you use start microsoft-edge:http://internal URL to company. Use the Navigate method:
$ie = New-Object -ComObject 'msedge.Application'
$ie.Visible= $true # Make it visible
$ie.Navigate("https://internal-login-page")
Do {sleep 1} While ($ie.Busy)
$usernamefield = $ie.document.getElementByID('j_username')
$usernamefield.value = "user"
$passwordfield = $ie.document.getElementByID('j_password')
$passwordfield.value = "password"
$Link = $ie.document.getElementByID('login-submit')
$Link.click()
Do {sleep 1} While ($ie.Busy)
$ie.Navigate("https://final-page")

How do you get table data from a website after you login using powershell?

My company wants me to grab data from their internal website, organize it, and send it to a database. The data is displayed on tables that you navigate to within the site. I'm wanting to pull the fields into a file or memory for further processing.
So far, I can log into the site in powershell by getting the submit login button's ID, and passing my username/password. I'm able to pass use the navigate method to change the page to the appropriate page within the site. However, running an Invoke-WebRequest on the new page, as well as using the Net.WebClient on the new page is returning the information found on the original site's login screen(I know, because nothing from the table makes it into the returned values, regardless of the commands I use). The commented code is what I've tried previously.
Here is the code-minus the values of my id/password/site link
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ie = New-Object -ComObject 'internetExplorer.Application'
$ie.Visible= $true # Make it visible
$username="myid"
$password="mypw"
$ie.Navigate("https://webpage.com/index.jsp")
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
$usernamefield = $ie.document.getElementByID('login')
$usernamefield.value = "$username"
$passwordfield = $ie.document.getElementByID('password')
$passwordfield.value = "$password"
$Link = $ie.document.getElementByID('SubmitLogin')
$Link.click()
$url = "https://webpage.com/home.pa#%5BT1%2CM181%5D"
$ie.Navigate($url)
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
$doc = $ie.document
$web = New-Object Net.WebClient
$web.DownloadString($url)
#$r = Invoke-WebRequest $url
#$r.Forms.fields | get-member
#$InnerText = $r.AllElements |
# Where-Object {$_.tagName -ne "TD" -and $_.innerText -ne $null} |
# Select -ExpandProperty innerText
#write-host $InnerText
#$r.AllElements|Where-Object {$_.InnerHtml -like "*=*"}
#$doc = $ie.Document
#$doc.getElementByID("ext-element-7") | % {
# if ($_.id -ne $null){
# write-host $_.id
# }
#}
$ie.Quit()
I obviously don't have your page and can't ensure that the body of the POST from signing in contains the fields login and password so that will require some trial & error from you. As a mini-example, if you open up your console dev tools network tab and filter by POST, you can observe how your login page signs you in. When I open reddit to sign in, it sends a POST to https://www.reddit.com/login with a body containing a username and password key/value (both plaintext). This action sets up my browser session to persist my login.
Here's a code example that uses the HtmlAgilityPack library to interact with the resulting page as if it were XML.
Enabling TLS1.2:
[System.Net.ServicePointManager]::SecurityProtocol =
[System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
Setting up your web session:
$iwrParams = #{
'Uri' = 'https://webpage.com/index.jsp'
'Method' = 'POST'
'Body' = #{
'login' = $username
'password' = $password
}
'SessionVariable' = 'session'
# avoids cases where IE has not been opened
'UseBasicParsing' = $true
}
# don't care about response - only here to initialize the session
$null = Invoke-WebRequest #iwrParams
Getting the protect page content:
$iwrParams = #{
'Uri' = 'https://webpage.com/home.pa#%5BT1%2CM181%5D'
'WebSession' = $session
'UseBasicParsing' = $true
}
$output = (Invoke-WebRequest #iwrParams).Content
Downloading/adding HtmlAgility:
if (-not (Test-Path -Path "$PSScriptRoot\HtmlAgilityPack.dll" -PathType Leaf))
{
Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/HtmlAgilityPack -OutFile "$PSScriptRoot\html.zip"
Expand-Archive -Path "$PSScriptRoot\html.zip" -DestinationPath "$PSScriptRoot\html" -Force
Copy-Item -Path "$PSScriptRoot\html\lib\netstandard2.0\HtmlAgilityPack.dll" -Destination "$PSScriptRoot\"
Remove-Item -Path "$PSScriptRoot\html", "$PSScriptRoot\html.zip" -Recurse -Force
}
Add-Type -Path "$PSScriptRoot\HtmlAgilityPack.dll"
$html = [HtmlAgilityPack.HtmlDocument]::new()
Loading/parsing your page content:
$html.LoadHtml($output)
# do stuff with output.
$html.DocumentNode.SelectNodes('//*/text()').Text.Where{$PSItem -like '*=*'}
Footnote
I made the assumption in the code you were executing from a script where $PSScriptRoot will be populated. If it's being run interactively, you can use the $pwd automatic variable instead (carry-over from *nix, print working directory). This code requires PSv5+.
After some serious effort-I managed to get the pages to work correctly. Turns out I wasn't waiting for everything to load-but once I had that, I eventually found the correct tag/name to make everything work.
Assuming the code in the original post is correct up to "ie.Navigate($url)"
$ie.Navigate($url)
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
$r = Invoke-WebRequest $url
$doc = $ie.document
$j = ($doc.getElementsByTagName("body") | Where {$_.className -eq 'thefullclassname found in the quotes of <body class="" of the area you wanted'}).innerText
write-host $j
This gave me the output of a very annoyingly done table that isn't a "table", and has the first row/col on it's own-so formatting the output to an easy to use version will be the new hassle. At least I got everything on the page that had the text I needed...so progress!

Powershell start IE in private and log in to page

I'm trying to automate a process of activating accounts by logging in to email, I have it working when I am not on the business network with the following code.
$username = "user"
$password = "pass"
$url = "url"
$ie = New-Object -com InternetExplorer.Application
$ie.visible=$true
$ie.navigate($url)
while ($ie.Busy -eq $true){Start-Sleep -seconds 1;}
$usernamefield = $ie.Document.getElementByID('UsernameTextBox')
$usernamefield.value = $username
$passwordfield = $ie.Document.getElementByID('PasswordTextBox')
$passwordfield.value = $password
$ie.document.getElementById("ctl00_ContentPlaceHolder1_SubmitButton").click()`
My issue is that once connected to the business network it then uses SSO to log in so I do not get the option to put in a username and password. To be able to put in a username and password I need to start IE in private mode. I have been able to start IE in private with the start-process command but I cannot find a way to select the window to type in the username and password.
Is there a way I can use powershell to log in to the website in a private browser?
You can get a handle to the private IE by starting it with start-process, as you referred to.
Start-Process -FilePath "C:\Program Files (x86)\Internet Explorer\iexplore.exe" -ArgumentList ' -private http://bogus.bogus'
Then you can connect to it by finding it -
$Shell = New-Object -Com Shell.Application
$apps = $shell.windows()
$ie = $apps | where { $_.locationname -eq 'http://bogus.bogus/' }
Happy scripting. :)