Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot authentificate with a specific special character in password #5

Open
mneitsabes opened this issue Nov 7, 2018 · 7 comments
Open

Comments

@mneitsabes
Copy link

Hi,

I'm using the version 2.5.4 of your library. When a user try to authentificate with a password containing the £ character, the authentification fails.

I used a Windows Server 2016 and the password is working within the domain.

Best regards,

@VitriolCZ
Copy link

I have same problem with czech symbols ěščřžýáíé

@dapphp
Copy link
Owner

dapphp commented Jan 9, 2019

Hi,

Sorry for the delay to the initial post. I started to look in to this and then dropped it.

Coming back to it today, I don't have an answer but we don't seem to be alone with the problem. Here are a couple similar reports:

https://serverfault.com/questions/644046/%C2%A3-sign-in-password-fails-windows-nps-radius-authentication-against-sonicwall-sra
https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/36021112-allow-for-multi-byte-unicode-characters-to-be-al

Using dapphp/radius client to auth against FreeRADIUS, I can auth fine with passwords such as Password1£, ěščřžýáíé1@#, 😎 🐈 🏃 🐎 ¯_(ツ)_/¯, пассворд1! etc etc. Similarly, radclient from FreeRADIUS works similarly.

Using Windows Server 2016, copying the £ from this post and changing the password to Password1£ from AD Users & Computers (with or without store reversible password), I am unable to auth with either radius client using PAP, CHAP, CHAP-MD5, or EAP-MSCHAPv2.

For example:

$ radtest nemo 'Password1!' xx.xx.xx.xx 20 xyzzy5461
Sending Access-Request of id 30 to xx.xx.xx.xx port 1812
	User-Name = "nemo"
	User-Password = "Password1!"
	NAS-IP-Address = 127.0.0.1
	NAS-Port = 20
	Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host xx.xx.xx.xx port 1812, id=30, length=90
	Class = 0xc5a10a930000013700010200408e122f00000000c56bc667a3f4cdae01d4a8532ea252dc000000000000000b
	MS-Link-Utilization-Threshold = 50
	MS-Link-Drop-Time-Limit = 120

Then changing password:

$ radtest nemo 'Password1£' xx.xx.xx.xx 20 xyzzy5461
Sending Access-Request of id 25 to xx.xx.xx.xx port 1812
	User-Name = "nemo"
	User-Password = "Password1£"
	NAS-IP-Address = 127.0.0.1
	NAS-Port = 20
	Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Reject packet from host xx.xx.xx.xx port 1812, id=25, length=20

Similarly, it will not work with ěščřžýáíé1@#.

In all cases, the NPS server logs a generic password mismatch error like:

Authentication Details:
	Connection Request Policy Name:	Use Windows authentication for all users
	Network Policy Name:		-
	Authentication Provider:		Windows
	Authentication Server:		WIN-A3MG0N4A3EC.testing.local
	Authentication Type:		MS-CHAPv1
	EAP Type:			-
	Account Session Identifier:		-
	Logging Results:			Accounting information was written to the local log file.
	Reason Code:			16
	Reason:				Authentication failed due to a user credentials mismatch. Either the user name provided does not map to an existing user account or the password was incorrect.

It would seem that PAP would be a good test case as it's the simplest algorithm for encoding a password. I've also tried with and without multi-byte aware code, though it seems we should be operating on bytes, and not characters. I have confirmed that PAP auth using the current code works fine against FreeRADIUS.

I can't turn up any useful information as to what the problem is or what, if any, solutions there are.

Anyone have any ideas?

I'm going to try some Radius clients made for Windows next, locally on the server.

@mportelag
Copy link

Hi,

We´re also using version 2.5.4 and detect the authentication error with special characters. We use Windows Server 2016 and the passwords work with our the domain.

The problem seems to be that the library interprets all characters with 1 byte (basic UTF-8) while special characters are encoded with more than 1 byte (see column UTF-8(hex.) in https://www.utf8-chartable.de/unicode-utf8-table.pl?names=-&unicodeinhtml=hex). The solution is to update the code implementing it with the functions that contemplate the possibility of more than 1 byte to code (implementations mb (multibyte string) -> https://www.php.net/manual/en/book.mbstring.php).

We have reviewed the code and have developed a possible implementation of the str2unicode($str) function (Pear_CHAP.php file):

PROBLEM:
for ($i = 0; $i < strlen($str); $i++) {
$a = ord($str{$i}) << 8;
$uni .= sprintf("%X", $a);
}
SOLUTION:
for ($i = 0; $i < mb_strlen($str); $i++) {
$a = mb_ord(mb_substr($str,$i,1)) << 8;
$uni .= sprintf("%X", $a);
}

Example: Spanish character ñ

  • Bad: Library interprets two characters (1 byte + 1 byte)
    • character 1:
      UTF-8 Hex: c3
      Unicode: C300
    • character 2:
      UTF-8 Hex: b1
      Unicode: B100
  • Good: Library must be interpret one character (2 bytes)
    • character:
      UTF-8 Hex: c3 b1
      Unicode: F100

We have tested the solution on our system using EAP-MSCHAPv2 authentication.
If you agree with this possible solution, could you update the library with these changes? Thank you.

Regards,

Miguel.

mportelag added a commit to mportelag/radius that referenced this issue Aug 2, 2019
Issue dapphp#5 : Cannot authentificate with a specific special character in password.
Add support for multibyte string (https://www.php.net/manual/en/book.mbstring.php) in str2unicode function (Pear_CHAP.php).
Function interprets all characters with 1 byte (basic UTF-8) while special characters are encoded with more than 1 byte (see column UTF-8(hex.) in https://www.utf8-chartable.de/unicode-utf8-table.pl?names=-&unicodeinhtml=hex).
@mportelag
Copy link

Hi,

We´re also using version 2.5.4 and detect the authentication error with special characters. We use Windows Server 2016 and the passwords work with our the domain.

The problem seems to be that the library interprets all characters with 1 byte (basic UTF-8) while special characters are encoded with more than 1 byte (see column UTF-8(hex.) in https://www.utf8-chartable.de/unicode-utf8-table.pl?names=-&unicodeinhtml=hex). The solution is to update the code implementing it with the functions that contemplate the possibility of more than 1 byte to code (implementations mb (multibyte string) -> https://www.php.net/manual/en/book.mbstring.php).

We have reviewed the code and have developed a possible implementation of the str2unicode($str) function (Pear_CHAP.php file):

PROBLEM:
for ($i = 0; $i < strlen($str); $i++) {
$a = ord($str{$i}) << 8;
$uni .= sprintf("%X", $a);
}
SOLUTION:
for ($i = 0; $i < mb_strlen($str); $i++) {
$a = mb_ord(mb_substr($str,$i,1)) << 8;
$uni .= sprintf("%X", $a);
}

Example: Spanish character ñ

* Bad: Library interprets two characters (1 byte + 1 byte)
  
  * character 1:
    UTF-8 Hex: c3
    Unicode: C300
  * character 2:
    UTF-8 Hex: b1
    Unicode: B100

* Good: Library must be interpret one character (2 bytes)
  
  * character:
    UTF-8 Hex: c3 b1
    Unicode: F100

We have tested the solution on our system using EAP-MSCHAPv2 authentication.
If you agree with this possible solution, could you update the library with these changes? Thank you.

Regards,

Miguel.

NOTE: This proposal only work with PHP >= 7.2. mb_ord function was added in this version (https://www.php.net/manual/en/function.mb-ord.php). For use with older php versions, function can can be manually coded (like https://github.com/symfony/polyfill-mbstring/blob/master/Mbstring.php).

@dapphp
Copy link
Owner

dapphp commented Aug 2, 2019

Hi Miguel (@mportelag),

Thank you for the work on this. When I test it, it does fix auth for password Password1£, but I still get incorrect password errors for пассворд1@@ and ěščřžýáíé1@#. Maybe it's something with my test Windows server or NPS setup.

Are you able to auth either of those passwords using your fix?

I can't auth using any of these passwords when testing with FreeRADIUS radtest either. I've yet to figure out what M$ is doing different. With your code, I've tried converting from UTF-8 to UCS-2/UCS-4/UTF-16 and various other encodings without any luck. It doesn't give me great hope that even the FreeRADIUS client can't auth with the passwords against Windows Server 2016.

@mportelag
Copy link

Hi @dapphp ,
We test our code with your passwords and gets incorrect password too. We don´t understand what is the problem. If we develop any solution to all cases, we'll notify you.
Regards,

@HenkPoley
Copy link
Contributor

HenkPoley commented May 7, 2020

Maybe this is relevant: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/6e803168-f140-4d23-b2d3-c3a8ab5917d2

However, the DC requires that the password value be specified in a UTF-16 encoded Unicode string containing the password surrounded by quotation marks, [..]
..
Following is an example of the first steps of password encoding. Suppose the implementer wants to set unicodePwd to the string "new".

 ASCII "new":     0x6E 0x65 0x77
 UTF-16 "new":    0x6E 0x00 0x65 0x00 0x77 0x00
 UTF-16 "new"
     with quotes: 0x22 0x00 0x6E 0x00 0x65 0x00 0x77 0x00 0x22 0x00

The 10-byte octet string is then BER-encoded and sent in an LDAP Modify request as described previously.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants