| Bug #42574 | ValidateUser does not use the application id, allowing cross application login | ||
|---|---|---|---|
| Submitted: | 3 Feb 22:50 | Modified: | 5 Mar 12:26 |
| Reporter: | Craig Nagy | ||
| Status: | Closed | ||
| Category: | Connector/Net | Severity: | S3 (Non-critical) |
| Version: | 5.2.5 | OS: | Any |
| Assigned to: | Target Version: | ||
| Tags: | membershipprovider, validateuser, applicationname | ||
| Triage: | D3 (Medium) | ||
[3 Feb 23:28]
Craig Nagy
Sorry, fix is incorrect. There is no applicationId in the my_aspnet_Membership table. Perhaps fix should be in GetUserId. Users should be retrieved with application id in mind.
[4 Feb 9:27]
Tonci Grgin
Hi Craig and thanks for your report.
AFAIS in latest sources, same error is present, both for unreleased versions and 5.2:
// first get the user id. If that is -1, then the user doesn't exist
// so we just return false since we can't bump any counters
int userId = GetUserId(connection, username);
if (-1 == userId) return false;
string sql = @"SELECT Password, PasswordKey, PasswordFormat, IsApproved,
Islockedout FROM my_aspnet_Membership WHERE userId=@userId";
MySqlCommand cmd = new MySqlCommand(sql, connection);
cmd.Parameters.AddWithValue("@userId", userId);
cmd.Parameters.AddWithValue("@appId", applicationId); <<<
Verified as described by looking into sources although not using AppID is not an error
per-se but the way things can be set up, according to MSDN:
http://msdn.microsoft.com/en-us/library/0580x1f5.aspx
ApplicationName property
The application name that is stored with each profile. The profile provider uses the
application name to store profile information separately for each application. This
enables multiple ASP.NET applications to use the same data source without a conflict if
the same user name is created in different applications. Alternatively, multiple ASP.NET
applications can share a profile data source by specifying the same application name.
So it is my opinion you should lover the severity of reported problem to at least S3 if
not S4.
[4 Feb 15:06]
Craig Nagy
Severity lowered to S3 per Tonci's comment since it's likely that the situation
encountered is rare. However, it seems like a potentially serious security hole since two
applications sharing the provider may expect users to be maintained separately.
Applying the fix to GetUserById as follows resolves the issue.
private int GetUserId(MySqlConnection connection, string username)
{
MySqlCommand cmd = new MySqlCommand(
"SELECT id FROM my_aspnet_Users WHERE name LIKE @name AND applicationId=@appId",
connection);
cmd.Parameters.AddWithValue("@name", username);
cmd.Parameters.AddWithValue("@appId", applicationId);
object id = cmd.ExecuteScalar();
if (id == null) return -1;
return (int)id;
}
[4 Feb 15:48]
Craig Nagy
applicationId is also missing from the query in IsUserInRole.
[4 Feb 18:43]
Tonci Grgin
Craig, thank you. I do see this as rare complication but all necessary code seems to be in place so I notified c/NET team leader to take a look at this.
[4 Mar 8:01]
Tonci Grgin
Same problem reported in Bug#43339.
[4 Mar 17:20]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/68268
[4 Mar 17:21]
Reggie Burnett
fixed in 5.2.6
[5 Mar 12:26]
Tony Bedford
An entry was added to the 5.2.6 changelog: MySQLMembershipProvider.ValidateUser only used the userId to validate. However, it should also use the applicationId to perform the validation correctly. The generated query was, for example: SELECT Password, PasswordKey, PasswordFormat, IsApproved, Islockedout FROM my_aspnet_Membership WHERE userId=13 Note that applicationId is not used.

Description: MySQLMembershipProvider.ValidateUser only uses the userId to validate. It must also use the applicationId. It looks like this was intended, but left out of the actual sql query string. Example Generated Query: SELECT Password, PasswordKey, PasswordFormat, IsApproved, Islockedout FROM my_aspnet_Membership WHERE userId=13 How to repeat: 1. Create two applications using the same provider, with different applicationNames 2. Create a user in one application with a set user name (e.g. XXXXX) 3. Login to the _other_ application using the same user name 4. Login will succeed when it shouldn't. Suggested fix: Add the applicationId criteria to the sql query. Note, the correct parameter is already being added. Line ~1073: string sql = @"SELECT Password, PasswordKey, PasswordFormat, IsApproved, Islockedout FROM my_aspnet_Membership WHERE userId=@userId AND applicationId=@appId"; MySqlCommand cmd = new MySqlCommand(sql, connection); cmd.Parameters.AddWithValue("@userId", userId); cmd.Parameters.AddWithValue("@appId", applicationId);