go-passbolt-cli icon indicating copy to clipboard operation
go-passbolt-cli copied to clipboard

Passbolt export to keepass using mfaMode: noninteractive-totp fails when mfaTotpToken contains padding

Open Stenstromen opened this issue 10 months ago • 8 comments

Describe the bug: When executing a KeePass export using the --mfaMode noninteractive-totp, specifying the --mfaTotpToken as is (with possible '===' padding thrown in at the end), throws the error:

Error: Logging in: Getting CSRF Token: MFA Callback: Error Generating MFA Code: Decoding token string: illegal base32 data at input byte 52

To Reproduce: Run a export with mfaMode noninteractive-totp and specify the mfaTotpToken, like the following example:

passbolt export keepass -f 'keepassFile.kdbx' -p 'password' --mfaMode 'noninteractive-totp' --mfaTotpToken 'O479J4873KP50M18C65S4DSK942RH89XI8G25S8SSD52F8BE2R746=='

Output when using --debug:

Using config file: /Users/$USER/Library/Application Support/go-passbolt-cli/go-passbolt-cli.toml
[go-passbolt] Request URL: https://example.com/auth/verify.json?api-version=v2
[go-passbolt] Raw Request: {"gpg_auth":{"keyid":"...","server_verify_token":"..."}}
[go-passbolt] Raw Response: {"header":{"id":"...","status":"error","servertime":1739383356,"action":"...","message":"The authentication failed.","url":"\/auth\/verify.json?api-version=v2","code":200},"body":null}
[go-passbolt] Request URL: https://example.com/auth/login.json?api-version=v2
[go-passbolt] Raw Request: {"gpg_auth":{"keyid":"..."}}
[go-passbolt] Raw Response: {"header":{"id":"...","status":"error","servertime":1739383356,"action":"...","message":"The authentication failed.","url":"\/auth\/login.json?api-version=v2","code":200},"body":null}
[go-passbolt] Got Encrypted Auth Token: ...
[go-passbolt] Decrypted Auth Token: gpgauthv1.3.0|36|...|gpgauthv1.3.0
[go-passbolt] Request URL: https://example.com/auth/login.json?api-version=v2
[go-passbolt] Raw Request: {"gpg_auth":{"keyid":"...","user_token_result":"gpgauthv1.3.0|36|...|gpgauthv1.3.0"}}
[go-passbolt] Raw Response: {"header":{"id":"...","status":"success","servertime":1739383356,"action":"...","message":"You are successfully logged in.","url":"\/auth\/login.json?api-version=v2","code":200},"body":{"id":"...","role_id":"...","username":"...","active":true,"deleted":false,"disabled":null,"created":"2022-10-11T18:58:49+00:00","modified":"2024-10-28T15:16:54+00:00","groups_users":[],"profile":{"id":"...","user_id":"...","first_name":"...","last_name":"...","created":"2022-10-11T18:58:49+00:00","modified":"2024-10-28T15:16:54+00:00","avatar":{"id":"...","profile_id":"...","created":"2024-10-28T15:16:54+00:00","modified":"2024-10-28T15:16:54+00:00","url":{"medium":"https:\/\/example.com\/avatars\/view\/b3f75a0b-0a99-4515-9e43-13689e85ad55\/medium.jpg","small":"https:\/\/example.com\/avatars\/view\/b3f75a0b-0a99-4515-9e43-13689e85ad55\/small.jpg"}}},"gpgkey":{"id":"...","user_id":"...","armored_key":"...","bits":3072,"uid":"...","key_id":"...","fingerprint":"...","type":"RSA","expires":null,"key_created":"2022-10-11T18:58:59+00:00","deleted":false,"created":"2022-10-11T18:59:07+00:00","modified":"2022-10-11T18:59:07+00:00"},"role":{"id":"...","name":"admin","description":"Organization administrator","created":"2012-07-04T13:39:25+00:00","modified":"2012-07-04T13:39:25+00:00"},"last_logged_in":null}}
[go-passbolt] Got Cookies: [passbolt_session=...; Path=/; HttpOnly; SameSite=Lax]
[go-passbolt] Request URL: https://example.com/users/me.json?api-version=v2
[go-passbolt] Raw Response: {"header":{"id":"...","status":"error","servertime":1739383357,"action":"...","message":"MFA authentication is required.","url":"\/mfa\/verify\/error.json","code":403},"body":{"mfa_providers":["totp"],"providers":{"totp":"https:\/\/example.com\/mfa\/verify\/totp.json"}}}
Error: Logging in: Getting CSRF Token: MFA Callback: Error Generating MFA Code: Decoding token string: illegal base32 data at input byte 52

Passbolt Server Version:

  • Edition: Community
  • Version 4.11.0-1

go-passbolt-cli Version:

  • OS: macOS
  • Version 0.3.1

Stenstromen avatar Feb 12 '25 18:02 Stenstromen

Hi @Stenstromen, so the reason for the failure is because your mfaTotpToken is not a valid base32 string and only valid base32 can be used to generate totps. Can you try converting it from base64 to base32 and see if it works?

Nelwhix avatar Feb 13 '25 18:02 Nelwhix

Hi @Nelwhix ,

The string I use in my example is intentionally not valid, because it didn't feel right to use my actual live one.

My main point with this issue is that while the Passbolt WebUI TOTP Generator accepts a base32 string with padding added to the end as a valid one. Say 52F10769M85H704GWXJIVY39FPK8S3EZ02ZX5KVC598S91149WM2A==== (again, not an actual valid TOTP secret).

But the exact same string, with the padding added, is not considered valid by go-passbolt-cli. But when the padding at the end is removed, 52F10769M85H704GWXJIVY39FPK8S3EZ02ZX5KVC598S91149WM2A, it is considered valid by go-passbolt-cli --mfaTotpToken. (???)

TLDR

Does not Work (valid base32 string with padding)

passbolt export keepass -f 'keepassFile.kdbx' -p 'password' --mfaMode 'noninteractive-totp' --mfaTotpToken '52F10769M85H704GWXJIVY39FPK8S3EZ02ZX5KVC598S91149WM2A===='

Works (base32 padding removed)

passbolt export keepass -f 'keepassFile.kdbx' -p 'password' --mfaMode 'noninteractive-totp' --mfaTotpToken '52F10769M85H704GWXJIVY39FPK8S3EZ02ZX5KVC598S91149WM2A'

Stenstromen avatar Feb 21 '25 00:02 Stenstromen

Okay I get you now, I have been able to reproduce it locally. Working on a fix

Nelwhix avatar Feb 23 '25 01:02 Nelwhix

@speatzle made a PR, please tell me what you think.

Nelwhix avatar Feb 23 '25 12:02 Nelwhix

Looks good, ill try to Test and Merge Tomorrow

speatzle avatar Feb 23 '25 15:02 speatzle

Test with the latest release v0.3.2

Nelwhix avatar Mar 04 '25 16:03 Nelwhix

@Nelwhix

I just attempted an export (go-passbolt-cli v0.3.2) with the padding still there, and it works!

Stenstromen avatar Mar 04 '25 18:03 Stenstromen

Let's go💪🏾💪🏾

Nelwhix avatar Mar 04 '25 21:03 Nelwhix