ゴランにおける認証セッションの理解と構築

22461 ワード

導入


Webアプリの認証セッションは、悪意のある脅威に対する防衛の中心です.したがって、セキュリティテスターのためのreconの最初のポイントの一つです.
この記事では、GO開発者は、認証セッションでの認証セッション、認証セッションの脆弱性、デザインの欠陥、セッションベースとトークンベースの認証方法の違い、および各アプリケーションを適用するときに啓発されます.
両方のメソッドの例を使用します.

認証セッション


Webアプリケーションの認証プロトコルがセッション中です.以下の手順に従います.
  • クライアントはWebアプリケーションのログインセッションに認証要求を送信する
  • Webアプリはそれを受け取り、Webサーバに送る
  • Webサーバは既存の資格情報と一致する
  • マッチが見つかった場合、Webサーバはクッキーを返し、その後に関連するREST APIが必要なページに呼び出されます.
  • Web開発者が認証メカニズムを構築するとき、これらのメソッドのどちらかに依存します.
  • HTMLフォームの使用
  • 多因子機構の使用
  • クライアントSSL証明書
  • HTTP認証
  • 認証サービス
  • ウェブトークン
  • これらの方法のそれぞれを見てみましょう.

    HTMLフォームの使用


    HTMLフォームは、ユーザー名とパスワードが収集され、アプリケーションに送信されるWebアプリケーションを認証する最も一般的なメソッドです.このメカニズムは、インターネットで利用できるアプリケーションの90 %以上を説明します.

    多因子機構の使用


    より多くのセキュリティが必要なプラットフォームでは、オンライン決済システムのように、マルチステージフォーム充填セッションが開始され、ユーザーは追加の資格情報を提供するよう命令されます.銀行アプリでは、物理トークンがしばしば必要です.これらのトークンは、通常、1回のパスコード(OTPS)のストリームを生成するか、またはユーザーからの入力を必要とする課題を提供する.
    親指の規則は、高感度データのためにOTPSを利用することです.

    クライアントSSL証明書


    いくつかのWebアプリケーションは、SSLの証明書や暗号化メカニズムを使用します.このプロセスには以下が含まれる:
  • クライアント認証証明書の購入および生成.
  • 妥当性検査プロセスの完了.
  • ユーザーのクライアント証明書のダウンロードまたはエクスポート.
  • クライアント認証証明書をインポートする.
  • クライアント認証をサポートするサーバーの設定.
  • 証明書をテストし、それが動作することを確認します.
  • HTTP認証


    HTTPベースの認証は、インターネットの採用で非常にまれです.それはイントラネットベースでより使用されます.認証の最も基本的な形式です.HTTP認証では、クライアントのログイン資格情報がリクエストヘッダで送信されます.
    Authorization: Basic YWxqY2U6cGE2NXdbcmQ=
    
    基本認証は、ユーザ名とパスワードに暗号化を使用しません.このように、アプリケーションは、低値データがある場合に限られており、簡単にアクセスする必要があります.
    それでも、使うのはお勧めです.
    -- https接続で
    -本当に強いパスワードで
    -速度制限を加えて、自傷攻撃を防ぐ

    認証サービス


    認証サービスは、アプリケーションと信頼性に関して重くなっています.一般的で広く使用されている認証認証サービスは、Auth 0です.Auth0 開発者の間で幅広い人気と使用を得ている実装、適応可能な認証と認可プラットホームは簡単です.

    ウェブトークン


    JWT、またはJSONのWebトークンは、クライアントとサーバーの2つの当事者間のセキュリティ情報を共有するために使用されるオープン標準認証プロトコルです.クライアント資格情報は、この場合、サーバーに格納されませんが、保管と再利用のためにクライアントに戻されます.

    認証セッションにおける脆弱性


    HTMLフォームで可能である脆弱性と攻撃は、ほとんどアップグレードを加えて、ほとんどの認証方法で動作します.
    攻撃で利用できるデザイン欠陥を見てみましょう.

    Webアプリケーションにおける設計欠陥


    弱パスワード


    弱いパスワードは、まだこの時代のものです.彼らは短いパスワード、予測可能な単語、簡単に社会工学、単語や母音を表す明らかなシンボルを持つ名前を介して得ることができるユーザーの名前の形を取る.

    開発


    ハッカーが行う最初のことは、Webアプリケーションにログインを試み、パスワードボックスを埋める際にソフトウェアによって指定された規則に注意を払うことです.

    パスワード変更機能


    ウェブ開発者は、しばしば彼らのアプリでパスワード変更機能を提供することができません.この機能は、2つの特別な理由のために、しかし、Webアプリケーションで非常に重要です
  • 悪意のあるアクティビティを検出すると、ユーザーはすぐにパスワードを変更する
  • パスワード変更セッションの定期テストと検証のために
  • パスワード変更機能を使用しないWebアプリケーションの欠陥は以下のようになります.
  • 冗長なエラーメッセージ
  • 既存のパスワードフィールドで無制限の推測を許可する
  • “新しいパスワード”と“新しいパスワードを確認する”フィールドに一致する既存のパスワードを確認した後
  • 認証セッションの他の設計欠陥は忘れられたパスワード機能で存在します、私に機能を覚えてください、そして、無効な資格情報機能
    Goで認証セッションを構築する方法を学びましょう.

    Basic HTTP Authentication in Golang


    先に説明したように、基本的なHTTP認証方法は安全ではありません.しかし、次のようにハッシュ化して実装できます.
    func basicAuth(next http.HandlerFunc) http.HandlerFunc {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        username, password, ok := r.BasicAuth()
            if ok {
            usernameHash := sha256.Sum256([]byte(username))
                passwordHash := sha256.Sum256([]byte(password))
                  expectedUsernameHash := sha256.Sum256([]byte("username"))
                  expectedPasswordHash := sha256.Sum256([]byte("password"))
            usernameMatch := (subtle.ConstantTimeCompare(usernameHash[:], expectedUsernameHash[:]) == 1)
                  passwordMatch := (subtle.ConstantTimeCompare(passwordHash[:], expectedPasswordHash[:]) == 1)
            if usernameMatch && passwordMatch {
                    next.ServeHTTP(w, r)
                    return
                }
            }
        w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
        })
    }
    
    ユーザー名とパスワードが保管のためにハッシュされていないことを強調することは重要です.それらは一定時間で比較できる2つの等しい長さバイトスライスを得るためにハッシュされます.
    HTTP基本認証のこのメソッドを使用する場合、インポートされるパッケージには次のものがあります.
    import (
        "crypto/sha256"
        "crypto/subtle"
        "fmt"
        "log"
        "net/http"
        "os"
        "time"
    )
    
    struct型のアプリケーションインスタンスを作成するには、ユーザ名とパスワードを入力します.
    type application struct {
        username string
        password string
    }
    
    主な機能は、全体の操作とサーバーインスタンスを含みます:
    func main() {
        webapp := new(application)
    
        webapp.auth.username = os.Getenv("AUTH_USERNAME")
        webapp.auth.password = os.Getenv("AUTH_PASSWORD")
    
        if webapp.auth.username == "" {
            log.Fatal("Illegal username provided")
        }
    
        if webapp.auth.password == "" {
            log.Fatal("Illegal password provided")
        }
    
        mux := http.NewServeMux()
        mux.HandleFunc("/unprotected", webapp.unprotectedHandler)
        mux.HandleFunc("/protected", webapp.basicAuth(app.protectedHandler))
    
        srv := &http.Server{
            Addr:         ":8080",
            Handler:      mux,
            IdleTimeout:  time.Minute,
            ReadTimeout:  10 * time.Second,
            WriteTimeout: 30 * time.Second,
        }
    
        log.Printf("starting server on %s", srv.Addr)
        err := srv.ListenAndServeTLS("./localhost.pem", "./localhost-key.pem")
        log.Fatal(err)
    }
    

    Golangにおけるセッションベース認証セッション


    セッションベースの認証システムは、サーバー側のテンプレートを実装するWebアプリケーションでしばしば使用されます.OAuthとOpenIDはさらにアプリケーションを安全に追加することができます.
    ゴングでは、人気Gorilla Muxパッケージは
    
     package that can be used to create authentication sessions.
    Hence, the first step in creating an authentication session is to install the
    
     ```gorilla/mux```
    
     and
    
     ```gorilla/sessions```
    
     packages.
    
    
    
    ```Shell
    go get github.com/gorilla/mux
    go get github.com/gorilla/sessions
    
    その後、プロジェクトのローカルディレクトリを作成します.
    次に、インポート
    
     package as well as other important packages.
    
    
    
    ```Go
    package main
    import (
        "log"
        "net/http"
        "os"
        "time"
        "github.com/gorilla/mux"
        "github.com/gorilla/sessions"
    )
    
    APIエンドポイントのためのセッションベースの認証を作成していることを見て、我々は
    
     method in the sessions package we imported.
    
    
    
    ```Go
    var store =sessions.NewCookieStore([]byte(os.Getenv("SESSION_SECRET")))
    
    ダッシュボードにログインしていると仮定すると、必要なAPIエンドポイントは以下の通りです.
    -
    
    
    -
    
     ```/dashboard```
    
    
    -
    
     ```/logout```
    
    
    
    There will be a list of users having their own dashboards, so the server must have a map it can search for yours in. Initializing an example user credentials:
    
    
    
    ```Go
    var users = map[string]string{
        "Mac":   "username",
        "admin": "password"
    }
    
    ログインハンドラ関数は、クライアントの要求、資格証明のマッチング、および/ダッシュボードエンドポイントの復帰を担当します.
    この関数は最初にポストフォームを解析します.その後、クライアントの資格情報を取得します.
    func LoginHandler(w http.ResponseWriter, r *http.Request) {
       err := r.ParseForm()
       if err != nil {
          http.Error(w, "Please pass the data as URL form encoded",
     http.StatusBadRequest)
         return
       }
       username := r.PostForm.Get("username")
       password := r.PostForm.Get("password")
    
    }
    
    この関数は、収集したデータとサーバーに格納されているデータとを一致させます.この関数は既存のマッチを認証し、一致しない場合にエラーを返します.
    //continued in the LoginHandler function
    if originalPassword, ok := users[username]; ok {
        session, _ := store.Get(r, "session.id")
        if password == originalPassword {
            session.Values["authenticated"] = true
            session.Save(r, w)
        } else {
            http.Error(w, "Invalid Credentials",
    http.StatusUnauthorized)
            return
        }
    } else {
        http.Error(w, "User is not found", http.StatusNotFound)
        return
    }
    w.Write([]byte("Logged In successfully"))
    
    サーバーの資格情報ストアのクライアントの可用性に応じて、ログインは成功します.
    一方、LOG OUTセッションはGETリクエストを受け取り、
    
     method to false.
    
    
    
    ```Go
    func LogoutHandler(w http.ResponseWriter, r *http.Request) {
        session, _ := store.Get(r, "session.id")
        session.Values["authenticated"] = false
        session.Save(r, w)
        w.Write([]byte(""))
    }
    
    The
    
     method saves the cookie state after modification. 
    Next, it is important to create the
    
     ```/dashboard```
    
     API endpoint. The
    
     ```/dashboard```
    
     function would return the time of login:
    
    
    
    ```Go
    func DashboardHandler(w http.ResponseWriter, r *http.Request) {
        session, _ := store.Get(r, "session.id")
        if (session.Values["authenticated"] != nil) && session.Values
        ["authenticated"] != false {
            w.Write([]byte(time.Now().String()))
        } else {
            http.Error(w, "Forbidden", http.StatusForbidden)
        }
    }
    
    エンドポイントを書き終えたら、次のステップは
    
     function. This function will connect and start up all endpoints, and the server at an open port:
    
    
    
    ```Go
    main() {
        server := mux.NewRouter().StrictSlash(True)
        server.HandleFunc("/login", LoginHandler)
        server.HandleFunc("/dashboard", DashboardHandler)
        server.HandleFunc("/logout", LogoutHandler)
        http.Handle("/", server)
        srv := &http.Server{
            Handler: server,
            Addr:    "127.0.0.1:8080",
            // Good practice: enforce timeouts for servers you create!
            WriteTimeout: 15 * time.Second,
            ReadTimeout:  15 * time.Second,
        }
        log.Fatal(srv.ListenAndServe())
    }
    
    これでセキュア認証セッションが完了します.コマンドの実行go run main.golocalhostのサーバを起動します.

    ゴランにおけるトークンベース認証セッション


    このトークンまたはセッションベースの認証システムの欠点の1つは、それがプログラムメモリに、またはredisのような特別なサーバソフトウェアに資格情報を格納するということです.
    しかしながら、JWTはこれに解決策を提出します.JWTは、データベースに格納するクライアントにログイン資格情報を再送信する方法です.以下、手順を説明する.
  • クライアントはログインAPIエンドポイントにログイン要求を送信します
  • サーバは詳細を認証し、成功すればJWTを生成する
  • サーバはクッキーを作成する代わりにこれを返します.これを格納するのはクライアントの責任になります
    トークン
  • クライアントがトークンを担当しているので、次のREST API呼び出しをするためにヘッダーセクションにこれを加える必要があります
  • サーバーはヘッダーからJWTをチェックします、そして、それが首尾よく解読されるならば、サーバーはクライアントを認証します
    RESTful APIについては、トークンベースの認証は、それがステートレスであることを前提に最善かつ推奨されるアプローチです.
    GOでJWTトークンベースのセッションを作成するにはjwt-goパッケージがインポートされます.これは、署名メソッドとクレームマップを受け入れるnewwithRequestメソッドを持っています.
    GWTでJWTを実装する上での素晴らしいガイドはAuth0 blog .
  • 結論


    この時点で、読者は認証セッションがどのようなカバーの下にあるか、認証において可能な脆弱性の種類、Webアプリケーションを認証する際の一般的なオプション、およびセッションとトークンベースの認証セッションの違いと方法に注意しなければなりません.