Встроенная в ASP.NET Identity уязвимость
От: vl690001x Россия  
Дата: 14.01.18 03:08
Оценка:
Разбираюсь тут с asp.net core
Как известно, в ASP.NET можно использовать встроенную систему авторизации — Identity, можно обойтись и без нее, используя авторизацию на базе Cookies и самому реализовать всю логику Identity.
Но и в том и в том случае кроется подвох — имеется серьезная уязвимость, думаю она не особо критична для серьезных разработчиков, но в любом случае, надо понимать что происходит, чтобы найти способ ее устранить.

В общем, суть такая, что для авторизации при входе на сайт, достаточно просто иметь сохраненные куки. Это конечно, логично и все так делают.
Но в этих куках никак не учитывается пароль, и соотвественно, middleware аутентификации не проверяет соотвствеие пароля хешу в БД. Она просто дешифрует куки в которых содержится логин и все права пользователя на сайте.

А значит, если некий Вася залез на сайт с компа Коли, потом пришел домой, вспомнил что сохранил там пароль, и потому решил его сменить, то... Коля тем не менее сможет войти на сайт под учеткой Васи.

Возможно, эта проблема не только ASP.NET, но и более общая.
Кто как с ней борется?
Re: Встроенная в ASP.NET Identity уязвимость
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 14.01.18 05:34
Оценка: 34 (4) +1
Здравствуйте, vl690001x, Вы писали:

V>Возможно, эта проблема не только ASP.NET, но и более общая.

V>Кто как с ней борется?
Ну для начала, как вы сами сказали, проблема (если это вообще проблема) не связана с ASP.Net Identity.
И даже с Cookies она связана опосредованно.

Если смотреть на ситуацию в общем, то протоколы аутентификации можно условно разбить на 2 группы:
— credentials пользователя передаются с клиента на сервер при каждом обращении. Например, так работает аутентификация пользователя в HTTP (когда credentials передаются на уровне транспорта).
— credentials передаются 1 раз при установлении сессии, а затем при каждом обращении используется так называемый сессионный токен, в котором credentials, как правило, отстутствуют.

У второго подхода есть масса аргументов "за":
1. Сервер, который непосредственно выполняет запрос, может не иметь доступа к credentials пользователя чтобы их проверить. Это, на самом деле крайне распространенная ситуация, сюда попадают все варианты аутентификации третьей стороной (через OpenID/OAuth/WS-Federeation/...), аутентификации единым центральным сервером (когда используются протоколы NTLM/Kerberos/HTTP Digest/... — т.е. когда сам пароль доступен только на стороне аутентификациооного сервера и на клиенте, а все промежуточные сервера видят только результат криптопреобразования, который еще и меняется случайным образом).
Как сверят credentials в этом случае?
2. Алгоритм аутентификации может быть куда сложнее "просто пароля". Сюда попадают такие случаи как многофакторная аутентификация, аутентификация по одноразовому (или временному паролю), аутентификация на основе сертификатов, биометрия, ...
Что и как хранить в данном случае и как проверять?
3. Далеко не всегда есть возможность одновременно сменить credentials на всех клиентах, где они используются. Например, служба, которая работает от имени пользователя. Как правильно обновить credentials для неё (если, конечно, мы хотим избежать ситуации, что служба начала сыпать ошибки из-за невозможности достучаться до сервера)? Остановить -> поменять credentials на сервере -> поменять credentials в настройках службы -> запустить? А если таких служб много?
4. Если передавать credentials вместе (или внутри) с сессионным токеном, то, теоретически, при вскрытии токена мы получим доступ к самим credentials, а значит дискредитирована будет не только текущая сессия, но и вцелом учетная запись пользователя.

Т.е. в случае использования сессионного токена нам нужно предпринять некие шаги, дабы исключить перехват сессии и сессионного токена.
Что обычно делают:
1. Ограничивают время жизни сессионного токена. Правда тут встает проблема — а какое время выставлять. Поставишь малое — замучаешь пользователя требованиями поавторить Credentials, поставишь большое — больше шансов у злоумышленника.
2. Ведут учет сессий на сервере и предлагают мехнизмы для: закрытия текущей сессии (например, когда явно отлогиниваешься), закрытия всех сессий (когда есть опасность дискредитации).
3. Используют дополнительные (не очень надежные, но всё же) мехнизмы — например, удаление кук при закрытии браузера на "чужом" компьютере.
4. Всячески предупреждают пользователя — не аутентифицироваться на ресурсах с ненадежных компьютеров и уж тем более не сохранять там пароли.
Re[2]: Встроенная в ASP.NET Identity уязвимость
От: vl690001x Россия  
Дата: 14.01.18 05:45
Оценка: 1 (1)
Здравствуйте, Михаил Романов, Вы писали:

МР>Ну для начала, как вы сами сказали, проблема (если это вообще проблема) не связана с ASP.Net Identity.

МР>И даже с Cookies она связана опосредованно.

Это безусловно проблема, потому что встроенный шаблон MVC сайта с использованием Identity, без дополнительных предпринятых мер (каких, я еще не понял), имеет серьезную уязвимость.
Там есть система смены пароля. Но она фактически бесполезна. Разве это не проблема?
Какой смысл мне менять пароль на своем компе, если все равно с тех мест где я входил ранее и сохранял куки, можно будет зайти на сайт под моей учеткой?

МР>Что обычно делают:

МР>1. Ограничивают время жизни сессионного токена. Правда тут встает проблема — а какое время выставлять. Поставишь малое — замучаешь пользователя требованиями поавторить Credentials, поставишь большое — больше шансов у злоумышленника.
МР>2. Ведут учет сессий на сервере и предлагают мехнизмы для: закрытия текущей сессии (например, когда явно отлогиниваешься), закрытия всех сессий (когда есть опасность дискредитации).
МР>3. Используют дополнительные (не очень надежные, но всё же) мехнизмы — например, удаление кук при закрытии браузера на "чужом" компьютере.
МР>4. Всячески предупреждают пользователя — не аутентифицироваться на ресурсах с ненадежных компьютеров и уж тем более не сохранять там пароли.

С моей точки зрения, все проще. Надо хранить в куках хеш от хеша пароля, и при входе на сайт, сравнивать его с хешем в БД.
Пусть это потребует дополнительного обращения к БД на каждый запрос, не думаю что это будет бить по скорости сильно, можно же использовать кеширование.
Почему так не делают? И можно ли как-то настроить такое поведение? Или другое, но чтобы оно решало указанную проблему?
Re[3]: Встроенная в ASP.NET Identity уязвимость
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 14.01.18 07:49
Оценка: 6 (1) +1
Здравствуйте, vl690001x, Вы писали:

V>Это безусловно проблема, потому что встроенный шаблон MVC сайта с использованием Identity, без дополнительных предпринятых мер (каких, я еще не понял), имеет серьезную уязвимость.

Я не вижу уязвимости в таком поведении.

V>Там есть система смены пароля. Но она фактически бесполезна. Разве это не проблема?

Почему бесполезна?
Смена пароля не позволяет аутентифицироваться вновь. Там, где вы уже аутентифицированы, сессия будет продолжать действовать

V>Какой смысл мне менять пароль на своем компе, если все равно с тех мест где я входил ранее и сохранял куки, можно будет зайти на сайт под моей учеткой?

Ну так вы не входите или чистите куки.
На самом деле, если вы входил на незнакомом компьютере на какой-то ресурс, вы уже потенциально дали злоумышленнику шанс украсть всё, что ему было нужно:
— он мог перехватить весь трафик межу браузером и сервером
— он мог внедрить на страницу скрипты, которые собрали и передали вовне все нужные данные
— он мог перехватить сами credentials, особенно, если вы пользовались обычной аутентификацией на основе форм.
...

То, что могли остаться куки (зависит от того, как было реализовано, и на сколько "стандартный" браузер использовался), это, имхо, самая мала из возможных проблем работы на "чужом" компьютере.


V>С моей точки зрения, все проще. Надо хранить в куках хеш от хеша пароля, и при входе на сайт, сравнивать его с хешем в БД.

Ну храните, если считаете, что это надо делать.
Механизм для того, чтобы проверять самому и при необходимости менять данные в Cookies есть.

V>Пусть это потребует дополнительного обращения к БД на каждый запрос, не думаю что это будет бить по скорости сильно, можно же использовать кеширование.

Только не забывайте сбрасывать кэш, когда пользователь меняет пароль, а то получите ровно то же самое + пользователь не сможет аутентифицироваться сам.

V>Почему так не делают?

Может и делают, для каких-то частных сценариев это вполне может быть полезным решением. Наверное.
А почему такое не делают в общих механизмах, я вроде достаточно четко описал: как минимум потому, что "пароля" может вообще не быть.
Как по мне, так сайтов с собственным хранилищем credentials скоро совсекм не останется.

V>И можно ли как-то настроить такое поведение?

Прямо "настроить", наверное нет. А вот немного дописать — вполне.

Делается это примерно так:
services.ConfigureApplicationCookie(co => co.Events = new MyEvents());

Где MyEvents это наследник от CookieAuthenticationEvents, в котором переопределены нужные вам методы событий.
Если очень схематично, то примерно так:
private class MyEvents : CookieAuthenticationEvents
{
    public override Task SigningIn(CookieSigningInContext context)
    {
        // Здесь нужно сохранить реальный пароль
        context.Properties.Items["password"] = "123";

        return base.SigningIn(context);
    }
    public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        var t = context.Properties.Items["password"];

        // Здесь нужно достать и сравнить с реальным паролем
        if (t != "123")
            context.RejectPrincipal();

        return base.ValidatePrincipal(context);
    }
}

Но, имхо, вы напрасно тратите здесь силы.
Более того, наверняка найдутся случаи когда было бы лучше, чтобы у пользователя таки осталось бы висеть сессия, даже после смены пароля.
Re: Встроенная в ASP.NET Identity уязвимость
От: Ромашка Украина  
Дата: 14.01.18 07:51
Оценка:
Здравствуйте, vl690001x, Вы писали:
V>Но в этих куках никак не учитывается пароль, и соотвественно, middleware аутентификации не проверяет соотвствеие пароля хешу в БД. Она просто дешифрует куки в которых содержится логин и все права пользователя на сайте.

Там еще должен быть SecurityStamp, который генерится случайно после каждой операции с учетными данными, такими как смена пароля. И он тоже сверяется.


Всё, что нас не убивает, ещё горько об этом пожалеет.
Re[4]: Встроенная в ASP.NET Identity уязвимость
От: vl690001x Россия  
Дата: 14.01.18 07:53
Оценка:
Здравствуйте, Михаил Романов, Вы писали:

МР>Но, имхо, вы напрасно тратите здесь силы.

МР>Более того, наверняка найдутся случаи когда было бы лучше, чтобы у пользователя таки осталось бы висеть сессия, даже после смены пароля.

Спасибо за подробное объяснение.
Я просто пытаюсь разобраться, и потому возникают вопросы. Может быть это не самая большая проблема, но она помогает мне понять устройство Identity.
Re[2]: Встроенная в ASP.NET Identity уязвимость
От: vl690001x Россия  
Дата: 14.01.18 07:55
Оценка:
Здравствуйте, Ромашка, Вы писали:

Р>Там еще должен быть SecurityStamp, который генерится случайно после каждой операции с учетными данными, такими как смена пароля. И он тоже сверяется.


Дело в том, что я проверял. Не знаю что там сверяется или не сверяется, но описанный мной сценарий реализуем, убедиться в этом можно создав шаблонное приложения с Identity, и воспользовавшись двумя разными браузерами для проверки.
Re[3]: Встроенная в ASP.NET Identity уязвимость
От: Ромашка Украина  
Дата: 14.01.18 08:33
Оценка: 6 (1) +1
Здравствуйте, vl690001x, Вы писали:
V>Дело в том, что я проверял. Не знаю что там сверяется или не сверяется, но описанный мной сценарий реализуем, убедиться в этом можно создав шаблонное приложения с Identity, и воспользовавшись двумя разными браузерами для проверки.

Ну так по дефолту как раз должно было включиться. В Startup должно быть приблизительно следующее:

    app.UseCookieAuthentication(new CookieAuthenticationOptions {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider {
            // Enables the application to validate the security stamp when the user logs in.
            // This is a security feature which is used when you change a password or add an external login to your account.  
            OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
        }
    });


Есть?


Всё, что нас не убивает, ещё горько об этом пожалеет.
Re[4]: Встроенная в ASP.NET Identity уязвимость
От: vl690001x Россия  
Дата: 14.01.18 08:42
Оценка:
Здравствуйте, Ромашка, Вы писали:

Р>Есть?


Нет, в Identity используется просто
app.UseAuthentication();
Re[5]: Встроенная в ASP.NET Identity уязвимость
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 14.01.18 08:57
Оценка:
Здравствуйте, vl690001x, Вы писали:

V>Нет, в Identity используется просто

V>
V>app.UseAuthentication();
V>

Для Core, как я понимаю, должен использоваться тот же подход с определением своих событий, как я приводил выше.
Т.е. класс событий будет выглядеть так:
private class MyEvents : CookieAuthenticationEvents
{
    public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        return SecurityStampValidator.ValidatePrincipalAsync(context);
    }
}

Правда, я подозреваю, луучше всё-таки использовать Generic-версию SecurityStampValidator<>.
Посмотрите на него внимательнее.
Re: Встроенная в ASP.NET Identity уязвимость
От: Qulac Россия  
Дата: 14.01.18 09:22
Оценка:
Здравствуйте, vl690001x, Вы писали:

V>Разбираюсь тут с asp.net core

V>Как известно, в ASP.NET можно использовать встроенную систему авторизации — Identity, можно обойтись и без нее, используя авторизацию на базе Cookies и самому реализовать всю логику Identity.
V>Но и в том и в том случае кроется подвох — имеется серьезная уязвимость, думаю она не особо критична для серьезных разработчиков, но в любом случае, надо понимать что происходит, чтобы найти способ ее устранить.

V>В общем, суть такая, что для авторизации при входе на сайт, достаточно просто иметь сохраненные куки. Это конечно, логично и все так делают.

V>Но в этих куках никак не учитывается пароль, и соотвественно, middleware аутентификации не проверяет соотвствеие пароля хешу в БД. Она просто дешифрует куки в которых содержится логин и все права пользователя на сайте.

Ну это уже 100 раз про это говорили: "Предоставлять доступ только на основании входных данных — смертный грех программиста". И проблема не только в паролях, пользователя могли забанить или как иначе изменить его права в системе, но у него останутся прежние права, пока он не почистит куки. Отсюда выводы как нужно делать.
Программа – это мысли спрессованные в код
Re: Встроенная в ASP.NET Identity уязвимость
От: bnk СССР http://unmanagedvisio.com/
Дата: 14.01.18 11:15
Оценка:
Здравствуйте, vl690001x, Вы писали:

V>А значит, если некий Вася залез на сайт с компа Коли, потом пришел домой, вспомнил что сохранил там пароль, и потому решил его сменить, то... Коля тем не менее сможет войти на сайт под учеткой Васи.


V>Возможно, эта проблема не только ASP.NET, но и более общая.

V>Кто как с ней борется?

Это не уязвимость, так работает куча сервисов. By Design.

Решается небольшим временем жизни токена, и обязательным https.
В шаблоне asp.net по умолчанию это полчаса (security stamp), если мне не изменяет память. Наприер, в google (gmail, docs, etc), microsoft (sharepoint, office online) — это час.
То есть, в твоем сценарии, Коля сможет спокойно читать почту Васи в течение получаса-часа после того, как Вася сменит пароль, и никого это особо не парит.
Re[2]: Встроенная в ASP.NET Identity уязвимость
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.01.18 05:21
Оценка:
Здравствуйте, bnk, Вы писали:
bnk>Решается небольшим временем жизни токена, и обязательным https.
bnk>В шаблоне asp.net по умолчанию это полчаса (security stamp), если мне не изменяет память. Наприер, в google (gmail, docs, etc), microsoft (sharepoint, office online) — это час.
bnk>То есть, в твоем сценарии, Коля сможет спокойно читать почту Васи в течение получаса-часа после того, как Вася сменит пароль, и никого это особо не парит.
Обычно всё чуть сложнее. Есть сессионный токен, и есть continuation token.
Когда прокисает сессионный, то сервер пытается его обновить без участия пользователя, через ту же authority, откуда брал токен в первый раз.
Если всё в порядке, то для пользователя просто возникает небольшая задержка во взаимодействии; иногда — с наблюдаемыми эффектами в GUI (типа "укажите ещё раз аккаунт, под которым хотите продолжать работу"), но без запроса Credentials.
Если нет (что-то изменилось в аккаунте пользователя), то его заставят повторно залогиниться.
Это позволяет сохранить приемлемый компромисс между комфортом (на некоторых сайтах я не переввожу пароль месяцами), и безопасностью (смена пароля обычно триггерит требование перелогиниться в течение ближайшего же часа).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Встроенная в ASP.NET Identity уязвимость
От: bnk СССР http://unmanagedvisio.com/
Дата: 15.01.18 09:14
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, bnk, Вы писали:


bnk>>Решается небольшим временем жизни токена, и обязательным https.

bnk>>В шаблоне asp.net по умолчанию это полчаса (security stamp), если мне не изменяет память. Наприер, в google (gmail, docs, etc), microsoft (sharepoint, office online) — это час.
bnk>>То есть, в твоем сценарии, Коля сможет спокойно читать почту Васи в течение получаса-часа после того, как Вася сменит пароль, и никого это особо не парит.

S>Обычно всё чуть сложнее. Есть сессионный токен, и есть continuation token.

S>Когда прокисает сессионный, то сервер пытается его обновить без участия пользователя, через ту же authority, откуда брал токен в первый раз.
S>Если всё в порядке, то для пользователя просто возникает небольшая задержка во взаимодействии; иногда — с наблюдаемыми эффектами в GUI (типа "укажите ещё раз аккаунт, под которым хотите продолжать работу"), но без запроса Credentials.
S>Если нет (что-то изменилось в аккаунте пользователя), то его заставят повторно залогиниться.
S>Это позволяет сохранить приемлемый компромисс между комфортом (на некоторых сайтах я не переввожу пароль месяцами), и безопасностью (смена пароля обычно триггерит требование перелогиниться в течение ближайшего же часа).

В стандарте Oauth2 например это называется access token и refresh token соответственно.
Суть в том, что в течение периода валидности access token-а — (те самые полчаса-час) ничто не остановит Колю от чтения почты Васи.
Даже если Вася сменил пароль
Re[4]: Встроенная в ASP.NET Identity уязвимость
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.01.18 04:04
Оценка:
Здравствуйте, bnk, Вы писали:
bnk>В стандарте Oauth2 например это называется access token и refresh token соответственно.
bnk>Суть в том, что в течение периода валидности access token-а — (те самые полчаса-час) ничто не остановит Колю от чтения почты Васи.
bnk>Даже если Вася сменил пароль
Это зависит от параноидальности Пети, который администрирует Васину почту. Потому что нет проблем добавить в токены client IP, резко затруднив угон токена (и обеспечивая Васе весёлую жизнь, если он читает почту с ноутбука в поезде, и его IP меняется хаотически)
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Встроенная в ASP.NET Identity уязвимость
От: bnk СССР http://unmanagedvisio.com/
Дата: 17.01.18 08:19
Оценка: +2
Здравствуйте, Sinclair, Вы писали:

S>Это зависит от параноидальности Пети, который администрирует Васину почту. Потому что нет проблем добавить в токены client IP, резко затруднив угон токена (и обеспечивая Васе весёлую жизнь, если он читает почту с ноутбука в поезде, и его IP меняется хаотически)


По сценарию выше, Коля читает Васину почту из своего дома, со своего компа, которым до этого он дал попользоваться Васе (client IP тот же?)

IMHO, такой сценарий попадает в разряд 'сам себе злобный Буратино', а не уязвимости.
Re[2]: Встроенная в ASP.NET Identity уязвимость
От: yenik  
Дата: 17.01.18 10:27
Оценка:
МР>3. Используют дополнительные (не очень надежные, но всё же) мехнизмы — например, удаление кук при закрытии браузера на "чужом" компьютере.
МР>4. Всячески предупреждают пользователя — не аутентифицироваться на ресурсах с ненадежных компьютеров и уж тем более не сохранять там пароли.

Ещё всячески рекомендуют пользоваться кнопкой Logout. Но это не на всех действует...
Re[6]: Встроенная в ASP.NET Identity уязвимость
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.01.18 18:29
Оценка:
Здравствуйте, bnk, Вы писали:

bnk>Здравствуйте, Sinclair, Вы писали:


S>>Это зависит от параноидальности Пети, который администрирует Васину почту. Потому что нет проблем добавить в токены client IP, резко затруднив угон токена (и обеспечивая Васе весёлую жизнь, если он читает почту с ноутбука в поезде, и его IP меняется хаотически)


bnk>По сценарию выше, Коля читает Васину почту из своего дома, со своего компа, которым до этого он дал попользоваться Васе (client IP тот же?)

bnk>IMHO, такой сценарий попадает в разряд 'сам себе злобный Буратино', а не уязвимости.
Совершенно верно. Я про то, что в оригинале (без client IP affinity) Коля угоняет Васин токен (через, к примеру, бесплатный вай-фай с тем же названием, что и любимый Васин), и пользуется им со своего компа.
Это гораздо более широкий класс уязвимостей, чем "получить физический доступ к Васиному компу, причём так, чтобы Вася не заметил"
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Встроенная в ASP.NET Identity уязвимость
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.01.18 05:24
Оценка:
Здравствуйте, Михаил Романов, Вы писали:

МР>Если смотреть на ситуацию в общем, то протоколы аутентификации можно условно разбить на 2 группы:

МР>- credentials пользователя передаются с клиента на сервер при каждом обращении. Например, так работает аутентификация пользователя в HTTP (когда credentials передаются на уровне транспорта).
МР>- credentials передаются 1 раз при установлении сессии, а затем при каждом обращении используется так называемый сессионный токен, в котором credentials, как правило, отстутствуют.

Сессионный токен это тоже credentials, только временные. И HTTP никоим разом не отменяет их использование. Разница в аутентификции на уровне транспорта и в куках отличается только переменной хидера, в которой передаются credentials.

МР>1. Ограничивают время жизни сессионного токена. Правда тут встает проблема — а какое время выставлять. Поставишь малое — замучаешь пользователя требованиями поавторить Credentials


Для этого придумали refresh token.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.