Powershell Byte Array input string invalid format - powershell

I've written a powershell script which changes the password of a local administrator that works well - It sets the password through a config file which contains the encrypted password and the aes key with which it was generated.
Its done the way described here: http://www.adminarsenal.com/admin-arsenal-blog/secure-password-with-powershell-encrypting-credentials-part-2
Now we have a management suite which streamlines administration of windoze and linux, and somehow it doesnt pass the aes key right into the script.
If I try to execute it through the management suite, I get the following error:
Cannot convert value "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33" to type "System.Byte". Error: "Input string was not in a correct Format."
I think the problem is the difference between PS and the management suite to handle variables (Or the black magic Powershell does under the hood which the management suite doesnt). In the script im reading in the aes-key from config file to a variable, which contains the values that are in the error message, which represent the aes key.
Now my question is: How do i get powershell to recognize the aes key as a byte array?
I cannot simply do a get-content C:\aes_keyfile, which maybe does the right typecast or whatever, because the streamline process has its own methods, so what I get in the script is the following:
$blah = $blahobject.get_variable("aeskey")
$blah
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33
I cant do:
[byte[]]$new_blah = $blah - Error: Cannot convert value "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33" to type "System.Byte[]". Error: "Input string was not in a correct format.""
What is the correct format? How can I find out what it is current and what it expects?

Ok, i found it out, thanks to your hint with the type:
I had to split it at the comma, so the right way is:
[byte[]]$new_blah = $blah.split(",")
Now the decryption of the password works.
Thanks a lot :>

Related

flask_bcrypt does not allow encoded (Byte) password with '\x00' in the middle

I have some code that accepts a password in string format, and hash it with SHA3-512 before passing it to flask_bcrypt for hashing. However, by some coincidence, I found a test case that produces a hash that contains '\x00' in the middle of the hash result, as seen below:
password_str = 'tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!.'
password_bytes = password_str.encode('utf-8')
hashed = hashlib.sha3_512(password_bytes).digest()
The result of the hash is:
b'u~"\x98\xac\xc8E2eV\xbb\x8e#}\x92R\xdc\xa2\xab\xab\xcb\x8d.~\x9f\x82a\xbf\xec]k\xdb\xc55\x1d\xa4\x00\xe8\x03\x94\xb0\x91\x14\xf0\x9ec\x9a\x9ay\xfeP\xe3\x07J\x00\xb5\xbd\xba\xcb(\xf5\xdb\xab\x1a'
As we can see, there is an '\x00' found in the middle of the hash, but not at the end. flask_bcrypt detects this a ValueError exception:
if b"\x00" in password:
raise ValueError("password may not contain NUL bytes")
I understand that '\x00' is a reserved character and possible attack vector due to hash-length extension attacks. However, I do not think that I have done anything outside the ordinary. Is there a best practice that sanitizes the hash prior to passing it to bcrypt or flask_bcrypt that I am missing, or is there another type of byte-encoding that should be used with passwords?
It would be weird to reject a normal password just because it's derived hash conflicts with the auth library used.. Any help or advice is greatly appreciated. Thank you!
BCrypt was designed to hash user passwords, this is not the same as e.g. SHA which is meant to hash binary input like a file. A user entered password actually never contains a \0 character, after all it is the user who desides about his own password, not a hacker trying to exploit a security vulnerability.
In other words, you should pass in the password as string directly, and avoid the UTF-8 encoding which converts it to a binary value.

Password escapes in SQL Azure connection string

I had the bright idea of generating a secure password using KeePass password manager and give it to my DBA.
Now I constructed my Azure SQL connection string as follows
Server=tcp:something.database.windows.net,1433;Initial Catalog=SomeDbName;Persist Security Info=False;User ID=someuser;Password=[read later];MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
The password contains at least the following characters, along with upper/lowercase/digits
/"|&#]<#
Error is: ArgumentException: Format of the initialization string does not conform to specification starting at index 151.
At index 151 I can see the semicolon after the username (which I named someuser in the redacted example but only contains lowercase and a digit). VS Code points column 151 right before the ;Password= sequence
Questions:
Does my SQL Azure password contain illegal characters?
Which ones need to be escaped?
How do I escape them?
[Edit]: a note about the double quotes, which must be always escaped in C# Strings. I buried the connection string under Azure App configuration tab. It means that the double quote is unlikely to be re-escaped. I believe EF Core currently reads double-quote correctly
Actually escaping is specified here: connection-strings
Simple test shows that for your password, it is enough to add single quotes:
var csBuilder = new System.Data.SqlClient.SqlConnectionStringBuilder();
csBuilder.Password = "/\"|&#]<#";
var cs = csBuilder.ConnectionString;
Console.WriteLine(cs);
Password='/"|&#]<#'

Powershell: How to grab base64 value from attribute of SearchResultEntry object?

My goal is to fetch the published CRL of a CA from an LDAP connection.
I have a function to search the LDAP (not Active Directory!), which returns a System.DirectoryServices.Protocols.SearchResultEntryCollection as expected.
$results = LDAPsearch "$_LDAP_server`:$_LDAP_searchPort" "cn=$CA,$_LDAP_searchBase" '(&(certificateRevocationList=*))'
ForEach ($element in $results){
$element.Attributes['cn'].GetValues('string')
$element.Attributes['certificateRevocationList;binary'].GetValues('string')
}
The above properly reads the cn attribute value of each element returned, however the certificateRevocationList is returned in a strange format which does not correspond at all to the Base64 string I expect (e.g. the one that can be read if you export your data to an LDIF file or if you use the Linux ldapsearch command)...
How can I get the actual Base64 value ?
Unfortunately, you can only pass 'byte[]' or 'string' as parameter to the GetValues method (a 'Base64String' option here would be useful to me, but well...).
Current output below (where cn value is correctly written but not certificateRevocationList):
Retrieve the raw CRL as byte[], then convert to base64 yourself:
$crlBin = $element.Attributes['certificateRevocationList;binary'].GetValues('byte[]')
$crlB64 = [Convert]::ToBase64String($crlBin)
Just adding the option I ended up using, much easier since my end-goal was actually to save the CRL as a file (and be able to parse it):
$crlBin = $element.Attributes['certificateRevocationList;binary'].GetValues('byte[]')[0]
[IO.File]::WriteAllBytes("$_localDir\CRL_$CA.crl",$crlBin)
This writes the actual CRL file in DER format (can then easily be switched to PEM using certutil or openssl if needed). My initial idea was to construct a PEM-formatted CRL file from the Base64 value extracted, but I was looking way too far...
I'm leaving Mathias's response as the answer since he actually best answered my question ; I didn't specify that I wanted a CRL file in the end.

Are you able to use PtrToStringAuto to decrypt a secure string in Powershell 7 on macOS?

I have had no success in getting the following code snippet to output "Hello World!" in PS7
$string = $("Hello World!" | ConvertTo-SecureString -AsPlainText -Force)
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($string))
The above code is an example of decrypting a secure string without specifying a length.
This same code works in PS6 and PS5 to fully decrypt the Secure String, but does not work in PS7. The only way around this I have found is to use PtrToStringBSTR. Then it works as expected across all versions of PS for this use case.
I raised an issue at the Powershell repo on Github, but haven't had any responses. I'm honestly just looking for some confirmation that the behavior is the same for others.
https://github.com/PowerShell/PowerShell/issues/11953
I would think something like this would be a breaking change for a lot of code being ported to PS7.
Here is what I have found so far:
Documentation
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.ptrtostringauto?view=netframework-4.8
According to the documentation, when specifying an integer, PtrToStringAuto:
Allocates a managed String and copies the specified number of characters from a string stored in unmanaged memory into it.
Specifying an int of 11 Returns "Hello", this is because every other char returned is Null. In this case, you must specify an int of 23 to return the complete string "Hello World!" using this method. I have stored the output in a variable to demonstrate this.
$String = $("Hello World!" | ConvertTo-SecureString -AsPlainText -Force)
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($string), 23)
$String[0] Returns H
$String[1] Returns NULL
$String[2] Returns E
$String[3] Returns NULL
etc....
If no integer is specified, PtrToStringAuto:
Allocates a managed String and copies all characters up to the first null character from a string stored in unmanaged memory into it.
I believe this suggests that either the Secure String is being stored with NULL values, whereas in PS6 it was not, or that the behavior of the PtrToStringAuto function has changed, and now adheres to the behavior the documentation describes above.
This is only an issue on macOS; however, using PtrToStringBSTR in place of PtrToStringAuto to decrypt the Secure String works as expected across windows and macOS.
This seems related: https://stackoverflow.com/a/11022662/4257163
I also do not see anywhere that a change was made.
Note that [securestring] is not recommended for new code anymore.
While on Windows secure strings offer limited protection - by storing the string encrypted in memory - via the DPAPI - and by shortening the window during which the plain-text representation is held in memory, no encryption at all is used on Unix-like platforms.[1]
The only way around this I have found is to use PtrToStringBSTR.
That is not only a way around the problem, PtrToStringBSTR is the method that should have been used to begin with, given that the input string is a BSTR.[2]
Do note that converting a secure string to and from a regular [string] instance defeats the very purpose of using [securestring] to begin with: you'll end up with a plain-text representation of your sensitive data in your process' memory whose lifetime you cannot control.
If you really want to do this, a simpler, cross-platform-compatible approach is:
[System.Net.NetworkCredential]::new('dummy', $string).Password
[1] This is especially problematic when you save a secure string in a file, via ConvertFrom-SecureString or Export-CliXml - see this answer.
[2] The Auto in PtrToStringAuto() means that the unmanaged input string is assumed to use a platform-appropriate character encoding, whereas BSTR is
a "Unicode" (UTF-16) string on all platforms. On Windows, an unmanaged string is assumed to have UTF-16 encoding (which is why the code works), whereas on Unix-like platforms it is UTF-8 since .NET Core 3.0 (PowerShell [Core] 7.0 is based on .NET Core 3.1), which explains your symptoms: the NUL chars. in the BSTR instance's UTF-16 code units are interpreted as characters in their own right when (mis)interpreted as UTF-8. Note that .NET Core 2.x (which is what PowerShell [Core] 6.x is based on) (inappropriately) defaulted to UTF-16, which this PR fixed, amounting to a breaking change.

How to print variable inside function

I'm using RRDs::Simple function and it needs bunch of parameters.
I have placed these parameters in a special variable (parsing, sorting and calculating data from a file) with all quotes, commas and other stuff.
Of course
RRDs::create ($variable);
doesn't work.
I've glanced through all perl special variables and have found nothing.
How to substitute name of variable for the data that contained in that variable?
At least could you tell me with what kind of tools(maybe another special variables) it can be done?
Assuming I'm understanding what you're asking:
You've build the 'create' data in $variable, and are now trying to use RRDs::create to actually do it?
First step is:
print $variable,"\n"; - to see what is actually there. You should be able to use this from the command line, with rrdtool create. (Which needs a filename, timestep, and some valid DS and RRA parameters)
usually, I'll use an array to pass into RRDs::create:
RRDs::create ( "test.rrd", "-s 300",
"DS:name:GAUGE:600:U:U", )
etc.
If $variable contains this information already, then that should be ok. The way to tell what went wrong is:
if ( RRDs::error ) { print RRDs::error,"\n"; }
It's possible that creating the file is the problem, or that your RRD definitions are invalid for some reason. rrdtool create on command line will tell you, as will RRDs::error;