mina-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jonathan Valliere (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (FTPSERVER-485) Timing Side Channel PasswordEncryptor
Date Fri, 20 Apr 2018 17:37:00 GMT

    [ https://issues.apache.org/jira/browse/FTPSERVER-485?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16446066#comment-16446066
] 

Jonathan Valliere edited comment on FTPSERVER-485 at 4/20/18 5:36 PM:
----------------------------------------------------------------------

Haven't tested this yet.  The following should cost the same amount of cycles linear to the
input length.
{code:java}
public class PasswordUtil {
	public static boolean compare(String input, String target) {
		/*
		 * set the default result based on the string lengths; if the lengths do not
		 * match then we know that this comparison should always fail.
		 */
		int result = (input.length() == target.length()) ? 0 : 1;
		/*
		 * cycle through all the input characters regardless of target length while trying
		 * to consume the same number of cycles during the evaluation of the conditionals.
		 */
		for (int i = 0; i < input.length(); i++) {
			boolean check = (i < target.length());

			result |= (input.charAt(i) == target.charAt(check ? i : 0)) ? check ? 0 : 1 : 1;
		}

		return (result == 0);
	}
}
{code}


was (Author: johnnyv):
Haven't tested this yet.  The following should cost the same amount of cycles linear to the
input length.
{code:java}
public class PasswordUtil {
	public static boolean compare(String input, String target) {
		/*
		 * set the default result based on the string lengths; if the lengths do not
		 * match then we know that this comparison should always fail.
		 */
		int result = (input.length() == target.length()) ? 0 : 1;
		/*
		 * cycle through all the input characters regardless of target length while trying
		 * to consume the same number of cycles while evaluating the conditionals.
		 */
		for (int i = 0; i < input.length(); i++) {
			boolean check = (i < target.length());

			result |= (input.charAt(i) == target.charAt(check ? i : 0)) ? check ? 0 : 1 : 1;
		}

		return (result == 0);
	}
}
{code}

> Timing Side Channel PasswordEncryptor
> -------------------------------------
>
>                 Key: FTPSERVER-485
>                 URL: https://issues.apache.org/jira/browse/FTPSERVER-485
>             Project: FtpServer
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 1.1.1
>         Environment: tested on macOS High Sierra 10.13.4, but it is not relevant
>            Reporter: Yannic Noller
>            Assignee: Jonathan Valliere
>            Priority: Major
>              Labels: easyfix, pull-request-available
>             Fix For: 1.1.2
>
>   Original Estimate: 24h
>  Remaining Estimate: 24h
>
> Dear Apache FTPServer developers,
> We have found a timing side-channel in class org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor,
method "public boolean matches(String passwordToCheck, String storedPassword)". This is due
to the use of String.equals for comparison which returns as soon as a character does not match.
This represents a timing side channel, which could be used by a potential attacker to obtain
knowledge about the hidden secret password.
> Do you agree with our findings?
> A similar issue is present in method "matches" from classes org.apache.ftpserver.usermanager.Md5PasswordEncryptor
and org.apache.ftpserver.usermanager.SaltedPasswordEncryptor.
> We found these classes in the latest version of your git repo: https://git-wip-us.apache.org/repos/asf?p=mina-ftpserver.git;a=summary
> The problem can be fixed easily by using the following safe version for String comparison
in all three methods:
> public boolean isEqual_safe(String a, String b) {
>         char a_value[] = a.toCharArray();
>         char b_value[] = b.toCharArray();
>         boolean unused;
>         boolean matches = true;
>         for (int i = 0; i < a_value.length; i++) {
>             if (i < b_value.length) {
>                 if (a_value[i] != b_value[i]) {
>                     matches = false;
>                 } else {
>                     unused = true;
>                 }
>             } else {
>                 unused = false;
>                 unused = true;
>             }
>         }
>         return matches;
>  }
> Do you agree with our patch proposal?
> Please feel free to contact us for further clarification! You can reach us by the following
email address:
> yannic.noller@informatik.hu-berlin.de
> Best regards,
> Yannic Noller



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Mime
View raw message