CVE-2019-8400 (Other, published 2019-02-17T06:29Z)
Description: value: ORY Hydra before v1.0.0-rc.3+oryOS.9 has Reflected XSS via the oauth2/fallbacks/error error_hint parameter.
Severity: MEDIUM (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/ory/hydra
Files changed:
go.mod
go.sum
oauth2/handler_fallback_endpoints.go
Commit message: oauth2: Use html templates in fallback endpoints (#1202)

Signed-off-by: aeneasr <aeneas@ory.sh>

Vulnerable code:
	golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4
package main_test

import (
	"fmt"
	"github.com/jmoiron/sqlx"
	"github.com/ory/fosite"
	"github.com/ory/hydra/client"
	"github.com/ory/hydra/consent"
	"github.com/ory/hydra/jwk"
	"github.com/ory/hydra/oauth2"
	"github.com/ory/x/resilience"
	"github.com/sirupsen/logrus"
	"github.com/stretchr/testify/require"
	"os"
	"testing"
	"time"
)

func connect(t *testing.T, driver, dsn string) (db *sqlx.DB) {
	require.NoError(t, resilience.Retry(
		logrus.New(),
		time.Second * 5,
		time.Minute * 5,
		func() (err error) {
			db, err = sqlx.Open(driver, dsn)
			if err != nil {
				return err
			}

			return db.Ping()
		},
	))
	return db
}

func TestCreateSchemasAtRoot(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping database tests in short mode.")
		return
	}

	drivers := map[string]string{
		"TEST_DATABASE_POSTGRESQL": "postgres",
		"TEST_DATABASE_MYSQL":      "mysql",
	}
	urls := map[string]string{
		"TEST_DATABASE_POSTGRESQL": os.Getenv("TEST_DATABASE_POSTGRESQL"),
		"TEST_DATABASE_MYSQL":      os.Getenv("TEST_DATABASE_MYSQL"),
	}

	for e, u := range urls {
		if len(u) == 0 {
			t.Fatalf("Environment variable %s is empty but it should point to a database. If you are running this test locally, make sure to run `make test` instead of `go test ./...`", e)
		}

		driver := drivers[e]
		t.Run(fmt.Sprintf("driver=%s", driver), func(t *testing.T) {
			t.Logf("Connecting to database %s: %s", driver, u)

			db := connect(t, driver, u)
			cm := &client.SQLManager{DB: db, Hasher: &fosite.BCrypt{}}
			_, err := cm.CreateSchemas()
			require.NoError(t, err)

			jm := &jwk.SQLManager{DB: db, Cipher: &jwk.AEAD{Key: []byte("11111111111111111111111111111111")}}
			_, err = jm.CreateSchemas()
			require.NoError(t, err)

			om := &oauth2.FositeSQLStore{Manager: cm, DB: db, L: logrus.New()}
			_, err = om.CreateSchemas()
			require.NoError(t, err)

			crm := consent.NewSQLManager(db, nil, om)
			_, err = crm.CreateSchemas()
			require.NoError(t, err)
		})
	}
}
	"fmt"
	w.Write([]byte(`
`))
	fmt.Fprintf(w, `
	<li>Error: %s</li>
	<li>Description: %s</li>
	<li>Hint: %s</li>
	<li>Debug: %s</li>
`, r.URL.Query().Get("error"), r.URL.Query().Get("error_description"), r.URL.Query().Get("error_hint"), r.URL.Query().Get("error_debug"))

	fmt.Fprintf(w, `

Fixed code:
	golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
	"html/template"
	t, err := template.New("consent").Parse(`
`)
	if err != nil {
		h.H.WriteError(w, r, err)
		return
	}

	if err := t.Execute(w, nil); err != nil {
		h.H.WriteError(w, r, err)
		return
	}
	t, err := template.New("consent").Parse(`
	<li>Error: {{ .Name }}</li>
	<li>Description: {{ .Description }}</li>
	<li>Hint: {{ .Hint }}</li>
	<li>Debug: {{ .Debug }}</li>
`)
	if err != nil {
		h.H.WriteError(w, r, err)
		return
	}

	if err := t.Execute(w, struct {
		Name        string
		Description string
		Hint        string
		Debug       string
	}{
		Name:        r.URL.Query().Get("error"),
		Description: r.URL.Query().Get("error_description"),
		Hint:        r.URL.Query().Get("error_hint"),
		Debug:       r.URL.Query().Get("error_debug"),
	}); err != nil {
		h.H.WriteError(w, r, err)
		return
	}
	t, err := template.New("consent").Parse(`
	if err != nil {
		h.H.WriteError(w, r, err)
		return
	}

	if err := t.Execute(w, nil); err != nil {
		h.H.WriteError(w, r, err)
		return
	}