Repository: Netflix/lemur

Issue:
No rate limiting for login 
Currently there is no rate limiting mechanism for the login endpoint. An attacker could potentially take advantage of this functionality to overwhelm the system and try to gain access to user accounts.

References
[OWASP's Page on Blocking Brute-Force Attacks](https://owasp.org/www-community/controls/Blocking_Brute_Force_Attacks)

---

The referenced issue was found via a pen test conducted in collaboration with [Infor](https://www.infor.com/) and [Cobalt.io](https://www.cobalt.io/)


Discussion:

Resolving patch:
diff --git a/lemur/auth/views.py b/lemur/auth/views.py
--- a/lemur/auth/views.py
+++ b/lemur/auth/views.py
@@ -15,6 +15,8 @@
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives import hashes, hmac
 from flask import Blueprint, current_app
+from flask_limiter import Limiter
+from flask_limiter.util import get_remote_address
 from flask_principal import Identity, identity_changed
 from flask_restful import reqparse, Resource, Api
 
@@ -31,6 +33,7 @@
 
 mod = Blueprint("auth", __name__)
 api = Api(mod)
+limiter = Limiter(app=current_app, key_func=get_remote_address)
 
 
 def exchange_for_access_token(
@@ -351,6 +354,7 @@ def __init__(self):
         self.reqparse = reqparse.RequestParser()
         super(Login, self).__init__()
 
+    @limiter.limit("10/5minute")
     def post(self):
         """
         .. http:post:: /auth/login
diff --git a/lemur/common/schema.py b/lemur/common/schema.py
--- a/lemur/common/schema.py
+++ b/lemur/common/schema.py
@@ -8,12 +8,12 @@
 
 """
 from functools import wraps
-from flask import request, current_app
-from sentry_sdk import capture_exception
-from sqlalchemy.orm.collections import InstrumentedList
 
+from flask import request, current_app
 from inflection import camelize, underscore
 from marshmallow import Schema, post_dump, pre_load
+from sentry_sdk import capture_exception
+from sqlalchemy.orm.collections import InstrumentedList
 
 
 class LemurSchema(Schema):
diff --git a/lemur/factory.py b/lemur/factory.py
--- a/lemur/factory.py
+++ b/lemur/factory.py
@@ -9,32 +9,29 @@
 .. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
 
 """
-import os
-import importlib
-import logmatic
 import errno
-import pkg_resources
+import importlib
+import os
 import socket
 import stat
-
 from logging import Formatter, StreamHandler
 from logging.handlers import RotatingFileHandler
 
+import logmatic
+import pkg_resources
+import sentry_sdk
+from click import get_current_context
 from flask import Flask, current_app
 from flask_replicated import FlaskReplicated
-from click import get_current_context
-
-import sentry_sdk
 from sentry_sdk.integrations.celery import CeleryIntegration
+from sentry_sdk.integrations.flask import FlaskIntegration
 from sentry_sdk.integrations.redis import RedisIntegration
 from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
-from sentry_sdk.integrations.flask import FlaskIntegration
 
 from lemur.certificates.hooks import activate_debug_dump
 from lemur.common.health import mod as health
 from lemur.extensions import db, migrate, principal, smtp_mail, metrics, cors
 
-
 DEFAULT_BLUEPRINTS = (health,)
 
 API_VERSION = 1


Test patch: