Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added CredentialsProvider callback for getting username and password #2097

Merged
merged 1 commit into from
Jun 4, 2022
Merged

Conversation

jan-bar
Copy link
Contributor

@jan-bar jan-bar commented May 29, 2022

Recently encountered a security problem, the running process was scanned to the redis plaintext username and password.

so I was inspired by CredentialsProvider and added the same method to the redis library.

I use the cheatengine scanner to run the memory password string.

I block the initConn method, and then use cheatengine to scan the memory of the program. After the initConn method is executed, the password in the memory will be delete immediately.

func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
	if cn.Inited {
		return nil
	}
	cn.Inited = true

	username, password := c.opt.Username, c.opt.Password
	if c.opt.CredentialsProvider != nil {
		username, password = c.opt.CredentialsProvider()
		defer fmt.Scanln() // blocking method while testing
	}

	if password == "" &&
		c.opt.DB == 0 &&
		!c.opt.readOnly &&
		c.opt.OnConnect == nil {
		return nil
	}

	connPool := pool.NewSingleConnPool(c.connPool, cn)
	conn := newConn(ctx, c.opt, connPool)

	_, err := conn.Pipelined(ctx, func(pipe Pipeliner) error {
		if password != "" {
			if username != "" {
				pipe.AuthACL(ctx, username, password)
			} else {
				pipe.Auth(ctx, password)
			}
		}

		if c.opt.DB > 0 {
			pipe.Select(ctx, c.opt.DB)
		}

		if c.opt.readOnly {
			pipe.ReadOnly(ctx)
		}

		return nil
	})
	if err != nil {
		return err
	}

	if c.opt.OnConnect != nil {
		return c.opt.OnConnect(ctx, conn)
	}
	return nil
}

Here is my test process.

test.gif

…t username and password will not be stored in the memory, and the username and password will only be generated once when the CredentialsProvider is called. After the method is executed, the username and password strings on the stack will be released.
@vmihailenco vmihailenco merged commit 56a3dbc into redis:master Jun 4, 2022
@vmihailenco
Copy link
Collaborator

Thanks

evilaffliction pushed a commit to reactive-go/redis that referenced this pull request Jun 15, 2022
…aintext username and password will not be stored in the memory, and the username and password will only be generated once when the CredentialsProvider is called. After the method is executed, the username and password strings on the stack will be released. (redis#2097)

Co-authored-by: janbar <janbar@163.com>
evilaffliction pushed a commit to reactive-go/redis that referenced this pull request Jun 15, 2022
…aintext username and password will not be stored in the memory, and the username and password will only be generated once when the CredentialsProvider is called. After the method is executed, the username and password strings on the stack will be released. (redis#2097)

Co-authored-by: janbar <janbar@163.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants