Podszywanie się pod użytkownika Django przez admina

Mam aplikację Django. Po zalogowaniu się jako użytkownik admin, chcę być w stanie przekazać tajny parametr w adresie URL i mieć całą witrynę zachowywać się tak, jakbym był innym użytkownikiem.

Załóżmy, że mam URL /my-profile/, który pokazuje aktualnie zalogowany profil użytkownika. Chcę być w stanie zrobić coś takiego jak /my-profile/?__user_id=123 i mieć podstawowy widok wierzyć, że faktycznie jestem użytkownikiem O ID 123 (w ten sposób renderować że profil użytkownika).

Po co mi to?

Po prostu dlatego, że o wiele łatwiej jest odtworzyć pewne błędy, które pojawiają się tylko na koncie jednego użytkownika.

Moje pytania:
  1. Jaki byłby najprostszy sposób na wdrożenie czegoś takiego?

  2. Czy powinienem mieć na uwadze jakieś obawy związane z bezpieczeństwem? Zauważ, że (oczywiście) chcę mieć tę funkcję tylko dla administratorów, a nasi administratorzy mają pełny dostęp do kodu źródłowego, bazy danych itp. w każdym razie, więc to nie jest naprawdę "backdoor"; to tylko sprawia, że to łatwiejsze dostęp do konta użytkownika.

Author: ibz, 2010-02-11

6 answers

Nie mam jeszcze wystarczającej reputacji, aby edytować lub odpowiedzieć (chyba), ale odkryłem, że chociaż rozwiązanie działało w prostych przypadkach, bardziej solidnym rozwiązaniem dla mnie było użycie zmiennej sesyjnej. W ten sposób nawet żądania AJAX są poprawnie obsługiwane bez modyfikowania adresu URL żądania, aby zawierał parametr podszywania się pod GET.

class ImpersonateMiddleware(object):
    def process_request(self, request):
        if request.user.is_superuser and "__impersonate" in request.GET:
            request.session['impersonate_id'] = int(request.GET["__impersonate"])
        elif "__unimpersonate" in request.GET:
            del request.session['impersonate_id']
        if request.user.is_superuser and 'impersonate_id' in request.session:
            request.user = User.objects.get(id=request.session['impersonate_id'])

Użycie:

log in: http://localhost/?__impersonate=[USERID]
log out (back to admin): http://localhost/?__unimpersonate=True
 32
Author: Charles Offenbacher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 19:02:19

Rozwiązałem to za pomocą prostego oprogramowania pośredniczącego. Obsługuje również przekierowania (tzn. parametr GET jest zachowywany podczas przekierowania). Tutaj jest:

class ImpersonateMiddleware(object):
    def process_request(self, request):
        if request.user.is_superuser and "__impersonate" in request.GET:
            request.user = models.User.objects.get(id=int(request.GET["__impersonate"]))

    def process_response(self, request, response):
        if request.user.is_superuser and "__impersonate" in request.GET:
            if isinstance(response, http.HttpResponseRedirect):
                location = response["Location"]
                if "?" in location:
                    location += "&"
                else:
                    location += "?"
                location += "__impersonate=%s" % request.GET["__impersonate"]
                response["Location"] = location
        return response
 9
Author: ibz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-11 10:42:12

Wygląda na to, że sporo innych osób miało ten problem i napisało do tego aplikacje wielokrotnego użytku, a przynajmniej niektóre są wymienione na stronie django packages do przełączania użytkowników . Najbardziej aktywni w momencie pisania wydają się być:

  • django-hijack umieszcza przycisk "hijack" na liście użytkowników w adminie, wraz z odrobiną u góry strony na czas przejęcia konta.
  • impostor oznacza, że możesz zalogować się używając nazwy użytkownika " me as other" i własne hasło
  • django-impersonate ustawia adresy URL, aby zacząć podszywać się pod użytkownika, stop, search itp
 9
Author: Hamish Downer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-27 11:10:46

Nie widzę, jak to jest dziura bezpieczeństwa bardziej niż używanie su-someuser jako root na maszynie unix. root lub django-admin z dostępem root/admin do bazy danych może udawać wszystko, jeśli chce. ryzyko polega tylko na pęknięciu konta django-admin, w którym to momencie cracker może ukryć utwory, stając się innym użytkownikiem, a następnie udając akcje jako użytkownik.

Tak, można to nazwać backdoorem, ale jak mówi ibz, administratorzy i tak mają dostęp do bazy danych. możliwość dokonaj zmian w bazie danych w tym świetle jest również backdoor.

 2
Author: eMBee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 16:17:37

@Charles Offenbacher odpowiedź jest świetna dla podszywania się pod użytkowników, którzy nie są uwierzytelniani za pomocą tokenów. Jednak nie będzie działać z aplikacjami po stronie klientów, które używają uwierzytelniania tokenów. Aby podszywać się pod użytkowników do pracy z aplikacjami używającymi tokenów, należy bezpośrednio ustawić nagłówek HTTP_AUTHORIZATION w Podszywanym oprogramowaniu pośrednim. Moja odpowiedź w zasadzie plagiatuje odpowiedź Karola i dodaje wiersze do ręcznego ustawiania wspomnianego nagłówka.

class ImpersonateMiddleware(object):
    def process_request(self, request):
        if request.user.is_superuser and "__impersonate" in request.GET:
            request.session['impersonate_id'] = int(request.GET["__impersonate"])
        elif "__unimpersonate" in request.GET:
            del request.session['impersonate_id']
        if request.user.is_superuser and 'impersonate_id' in request.session:
            request.user = User.objects.get(id=request.session['impersonate_id'])
            # retrieve user's token
            token = Token.objects.get(user=request.user)
            # manually set authorization header to user's token as it will be set to that of the admin's (assuming the admin has one, of course)
            request.META['HTTP_AUTHORIZATION'] = 'Token {0}'.format(token.key)
 0
Author: davetw12,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-20 15:58:03

Skonfiguruj tak, aby mieć dwie różne nazwy hostów na tym samym serwerze. Jeśli robisz to lokalnie, możesz połączyć się z 127.0.0.1 lub localhost, na przykład. Twoja przeglądarka zobaczy to jako trzy różne witryny i możesz być zalogowany z różnymi użytkownikami. To samo działa na twojej stronie.

Więc oprócz www.mysite.com możesz ustawić test.mysite.com, i zaloguj się tam z użytkownikiem. Często konfiguruję strony (z Plone) więc mam zarówno www.mysite.com oraz admin.mysite.com, i tylko pozwalają dostęp do stron administratora stamtąd, co oznacza, że mogę zalogować się do normalnej strony z nazwą użytkownika, który ma problemy.

 -1
Author: Lennart Regebro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-11 07:45:00