From ea75741ec22ecef34bc7073f1163e17a8a2bf9fc Mon Sep 17 00:00:00 2001 From: Jens L Date: Sat, 28 Oct 2023 21:24:06 +0200 Subject: [PATCH] security: fix oobe-flow reuse when akadmin is deleted (#7361) Signed-off-by: Jens Langhammer # Conflicts: # website/docs/releases/2023/v2023.10.md --- .../migrations/0026_alter_flow_options.py | 25 ++++++++++++++ .../migrations/0027_auto_20231028_1424.py | 34 +++++++++++++++++++ blueprints/default/flow-oobe.yaml | 19 +++++++++++ blueprints/system/bootstrap.yaml | 6 ---- website/docs/releases/2023/v2023.8.md | 4 +++ website/docs/security/GHSA-rjvp-29xq-f62w.md | 27 +++++++++++++++ website/sidebars.js | 1 + 7 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 authentik/flows/migrations/0026_alter_flow_options.py create mode 100644 authentik/flows/migrations/0027_auto_20231028_1424.py create mode 100644 website/docs/security/GHSA-rjvp-29xq-f62w.md diff --git a/authentik/flows/migrations/0026_alter_flow_options.py b/authentik/flows/migrations/0026_alter_flow_options.py new file mode 100644 index 000000000..c53d3774e --- /dev/null +++ b/authentik/flows/migrations/0026_alter_flow_options.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.6 on 2023-10-10 17:18 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("authentik_flows", "0025_alter_flowstagebinding_evaluate_on_plan_and_more"), + ] + + operations = [ + migrations.AlterModelOptions( + name="flow", + options={ + "permissions": [ + ("export_flow", "Can export a Flow"), + ("inspect_flow", "Can inspect a Flow's execution"), + ("view_flow_cache", "View Flow's cache metrics"), + ("clear_flow_cache", "Clear Flow's cache metrics"), + ], + "verbose_name": "Flow", + "verbose_name_plural": "Flows", + }, + ), + ] diff --git a/authentik/flows/migrations/0027_auto_20231028_1424.py b/authentik/flows/migrations/0027_auto_20231028_1424.py new file mode 100644 index 000000000..856961a98 --- /dev/null +++ b/authentik/flows/migrations/0027_auto_20231028_1424.py @@ -0,0 +1,34 @@ +# Generated by Django 4.2.6 on 2023-10-28 14:24 + +from django.apps.registry import Apps +from django.db import migrations +from django.db.backends.base.schema import BaseDatabaseSchemaEditor + + +def set_oobe_flow_authentication(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): + from guardian.shortcuts import get_anonymous_user + + Flow = apps.get_model("authentik_flows", "Flow") + User = apps.get_model("authentik_core", "User") + + db_alias = schema_editor.connection.alias + + users = User.objects.using(db_alias).exclude(username="akadmin") + try: + users = users.exclude(pk=get_anonymous_user().pk) + # pylint: disable=broad-except + except Exception: # nosec + pass + + if users.exists(): + Flow.objects.filter(slug="initial-setup").update(authentication="require_superuser") + + +class Migration(migrations.Migration): + dependencies = [ + ("authentik_flows", "0026_alter_flow_options"), + ] + + operations = [ + migrations.RunPython(set_oobe_flow_authentication), + ] diff --git a/blueprints/default/flow-oobe.yaml b/blueprints/default/flow-oobe.yaml index d72f8d652..e37603ebb 100644 --- a/blueprints/default/flow-oobe.yaml +++ b/blueprints/default/flow-oobe.yaml @@ -85,6 +85,19 @@ entries: identifiers: name: default-oobe-password-usable model: authentik_policies_expression.expressionpolicy +- attrs: + expression: | + # This policy ensures that the setup flow can only be + # used one time + from authentik.flows.models import Flow, FlowAuthenticationRequirement + Flow.objects.filter(slug="initial-setup").update( + authentication=FlowAuthenticationRequirement.REQUIRE_SUPERUSER, + ) + return True + id: policy-default-oobe-flow-set-authentication + identifiers: + name: default-oobe-flow-set-authentication + model: authentik_policies_expression.expressionpolicy - attrs: fields: - !KeyOf prompt-field-header @@ -129,6 +142,7 @@ entries: evaluate_on_plan: true invalid_response_action: retry re_evaluate_policies: false + id: binding-login identifiers: order: 100 stage: !KeyOf stage-default-authentication-login @@ -144,3 +158,8 @@ entries: policy: !KeyOf policy-default-oobe-prefill-user target: !KeyOf binding-password-write model: authentik_policies.policybinding +- identifiers: + order: 0 + policy: !KeyOf policy-default-oobe-flow-set-authentication + target: !KeyOf binding-login + model: authentik_policies.policybinding diff --git a/blueprints/system/bootstrap.yaml b/blueprints/system/bootstrap.yaml index 5bda8b3ff..07bbd2391 100644 --- a/blueprints/system/bootstrap.yaml +++ b/blueprints/system/bootstrap.yaml @@ -42,9 +42,3 @@ entries: user: !KeyOf admin-user attrs: key: !Context token - - model: authentik_blueprints.blueprintinstance - identifiers: - metadata: - labels: - blueprints.goauthentik.io/system-bootstrap: "true" - state: absent diff --git a/website/docs/releases/2023/v2023.8.md b/website/docs/releases/2023/v2023.8.md index 7c805ae83..cacd8772a 100644 --- a/website/docs/releases/2023/v2023.8.md +++ b/website/docs/releases/2023/v2023.8.md @@ -155,6 +155,10 @@ image: - web: don't import entire SourceViewPage in flow and user interface (#6761) - web: replace ampersand (#6737) +## Fixed in 2023.8.4 + +- \*: fix [GHSA-rjvp-29xq-f62w](../security/GHSA-rjvp-29xq-f62w), Reported by [@devSparkle](https://github.com/devSparkle) + ## API Changes #### What's New diff --git a/website/docs/security/GHSA-rjvp-29xq-f62w.md b/website/docs/security/GHSA-rjvp-29xq-f62w.md new file mode 100644 index 000000000..b4b44d07c --- /dev/null +++ b/website/docs/security/GHSA-rjvp-29xq-f62w.md @@ -0,0 +1,27 @@ +# GHSA-rjvp-29xq-f62w + +_Reported by [@devSparkle](https://github.com/devSparkle)_ + +## Potential Installation takeover when default admin user is deleted + +### Summary + +In the affected versions, when the default admin user has been deleted, it is potentially possible for an attacker to set the password of the default admin user without any authentication. + +### Patches + +authentik 2023.8.4 and 2023.10.2 fix this issue, for other versions the workaround can be used. + +### Impact + +authentik uses a blueprint to create the default admin user, which can also optionally set the default admin users' password from an environment variable. When the user is deleted, the `initial-setup` flow used to configure authentik after the first installation becomes available again. + +### Workarounds + +Ensure the default admin user (Username `akadmin`) exists and has a password set. It is recommended to use a very strong password for this user, and store it in a secure location like a password manager. It is also possible to deactivate the user to prevent any logins as akadmin. + +### For more information + +If you have any questions or comments about this advisory: + +- Email us at [security@goauthentik.io](mailto:security@goauthentik.io) diff --git a/website/sidebars.js b/website/sidebars.js index 6b8a56bdf..aae3a118d 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -362,6 +362,7 @@ const docsSidebar = { }, items: [ "security/policy", + "security/GHSA-rjvp-29xq-f62w", "security/CVE-2023-39522", "security/CVE-2023-36456", "security/2023-06-cure53",