Компрометация и изменение сессионных данных
Встал вопрос о том, а могут ли сессионные данные скомпрометированы или же изменены на стороне клиента.
Допустим я сохраняю данные пользователя в сессии
HttpContext.Session.SetString(ROLE, "User")
И не хотелось бы при получении этих данных из сессии, получить роль не User, а допустим Admin
Ибо в моем случае данных из сессии используются для создания jwt.
Так вот, как я понимаю, юзеру не приходят сами данные, ему приходит лишь идентификатор сессии, и было бы логично предположить что данные не могут быть скомпрометированы или изменены, так как сами данные хранятся на сервере, а юзер имеет лишь идентификатор, и не взаимодействует с этими данными напрямую.
Но я не уверен в этом, возможно есть какие-то дыры, которых стоит опасаться, если такие есть, расскажите о таковых.
Буду премного благодарен любой информации.
Моя ситуация, почему я считаю что мне нужны сессии:
Мейн эндпоинт который валидирует данные, и в целом выполняет некоторую логику:
[HttpPost("login")]
public async Task<IActionResult> Login(UserModel userModel)
{
try
{
if (userModel.email is null || userModel.password is null)
return StatusCode(422, new { message = AccountErrorMessage.InvalidUserData });
var email = userModel.email.ToLowerInvariant();
var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.email == email);
if (user is null)
return StatusCode(404, new { message = AccountErrorMessage.UserNotFound });
bool IsCorrect = _passwordManager.CheckPassword(userModel.password, user.password!);
if (!IsCorrect)
return StatusCode(401, new { message = AccountErrorMessage.PasswordIncorrect });
var clientInfo = Parser.GetDefault().Parse(HttpContext.Request.Headers["User-Agent"].ToString());
if ((bool)!user.is_2fa_enabled)
return await FactLogin(clientInfo, user);
int code = _generateCode.GenerateSixDigitCode();
var emailDto = new EmailDto
{
username = user.username,
email = user.email,
subject = EmailMessage.Verify2FaHeader,
message = EmailMessage.Verify2FaBody + code
};
await _emailSender.SendMessage(emailDto);
HttpContext.Session.SetString(ID, user.id.ToString());
HttpContext.Session.SetString(EMAIL, email);
HttpContext.Session.SetString(USERNAME, user.username!);
HttpContext.Session.SetString(ROLE, user.role!);
HttpContext.Session.SetString(CODE, code.ToString());
return StatusCode(200, new { message = AccountSuccessMessage.EmailSended });
}
catch (UserException)
{
_logger.LogCritical("When trying to update the data, the user was deleted");
_tokenService.DeleteTokens();
_logger.LogDebug("Tokens was deleted");
return StatusCode(404);
}
catch (Exception)
{
return StatusCode(500);
}
}
Эндпоинт верификации:
[HttpPost("verify/2fa")]
public async Task<IActionResult> VerifyTwoFA([FromQuery] int code)
{
int correctCode = int.Parse(HttpContext.Session.GetString(CODE));
int userId = int.Parse(HttpContext.Session.GetString(ID));
string? email = HttpContext.Session.GetString(EMAIL);
string? username = HttpContext.Session.GetString(USERNAME);
string? role = HttpContext.Session.GetString(ROLE);
if (email is null || username is null || role is null)
return StatusCode(422, new { message = AccountErrorMessage.NullUserData });
if (!code.Equals(correctCode))
return StatusCode(422, new { message = AccountErrorMessage.CodeIncorrect });
var clientInfo = Parser.GetDefault().Parse(HttpContext.Request.Headers["User-Agent"].ToString());
var userModel = new UserModel
{
id = userId,
username = username,
email = email,
role = role
};
HttpContext.Session.Clear();
return await FactLogin(clientInfo, userModel);
}
Да конечно же можно второй раз запрашивать данные из бд, но мне не хочется лишний раз нагружать бд
Ответы (1 шт):
Состояние сеанса ("сессия") хранится либо в памяти сервера (по умолчанию), либо в СУБД, либо в каком-нибудь redis. Изменить его клиент не может никак.
Однако, ссылка на это состояние (идентификатор сессии) хранится в куках, и может быть использована злоумышленником с помощью XSRF-атак (cross-site request forgery, подделки межсайтовых запросов). Поэтому защищайте любые мутирующие действия анти-XSRF токенами, и ни в коем случае не ставьте политику CORS в режим "разрешать всё и всем".