saml: extract_authn_context does not support SAML 2.0 authorisation statements
Summary
2FA bypassing does not work for SAML 2.0 providers that provide AuthnStatement
in the saml2
namespace.
According to https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/auth/saml/auth_hash.rb#L31, saml:AuthnStatement
is the only supported AuthnStatement; it does not support saml2:AuthnStatement>saml2:AuthnContext>saml2:AuthnContextClassRef
.
Steps to reproduce
Use any SAML 2.0 provider that provides AuthnStatement
in the saml2
namespace.
What is the current bug behavior?
G Suite will provide
<saml2:AuthnStatement AuthnInstant="2018-10-23T15:30:12Z">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified<saml2:AuthnContextClassRef/>
</saml2:AuthnContext>
</saml2:AuthnStatement>
But this will return an empty string currently.
What is the expected correct behavior?
extract_authn_context
should return urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified
.
Output of checks
This bug happens on gitlab-ee.
Results of GitLab environment info
Expand for output related to GitLab environment info
System information System: Ubuntu 18.04 Proxy: no Current User: git Using RVM: no Ruby Version: 2.4.4p296 Gem Version: 2.7.6 Bundler Version:1.16.2 Rake Version: 12.3.1 Redis Version: 3.2.12 Git Version: 2.18.1 Sidekiq Version:5.2.1 Go Version: unknown GitLab information Version: 11.4.0-ee Revision: cfe266cbac3 Directory: /opt/gitlab/embedded/service/gitlab-rails DB Adapter: postgresql DB Version: 9.6.8 URL: https://git.redacted.io HTTP Clone URL: https://git.redacted.io/some-group/some-project.git SSH Clone URL: git@git.redacted.io:some-group/some-project.git Elasticsearch: no Geo: no Using LDAP: no Using Omniauth: yes Omniauth Providers: GitLab Shell Version: 8.3.3 Repository storage paths: - default: /var/opt/gitlab/git-data/repositories Hooks: /opt/gitlab/embedded/service/gitlab-shell/hooks Git: /opt/gitlab/embedded/bin/git
Results of GitLab application Check
Expand for output related to the GitLab application check
Checking GitLab Shell ... GitLab Shell version >= 8.3.3 ? ... OK (8.3.3) Repo base directory exists? default... yes Repo storage directories are symlinks? default... no Repo paths owned by git:root, or git:git? default... yes Repo paths access is drwxrws---? default... yes hooks directories in repos are links: ... 4/1 ... ok 5/2 ... ok 4/5 ... ok 6/6 ... ok 5/8 ... ok 5/9 ... ok 5/10 ... ok 4/12 ... ok 4/14 ... ok 4/15 ... ok 4/16 ... ok 5/18 ... ok 4/19 ... ok 5/21 ... ok 32/22 ... ok 32/23 ... ok 32/24 ... ok 32/25 ... ok 5/26 ... ok 4/28 ... ok 5/29 ... ok 4/30 ... ok 5/31 ... ok 5/32 ... ok 32/33 ... ok 32/34 ... ok 4/35 ... ok 36/36 ... ok 36/38 ... ok 4/39 ... ok 36/40 ... ok 36/41 ... ok 36/43 ... ok 32/46 ... ok 4/47 ... ok 4/48 ... ok 5/50 ... ok 4/51 ... ok 4/52 ... ok 6/56 ... ok 6/57 ... ok 6/58 ... ok 5/59 ... ok 4/60 ... ok 4/61 ... ok 4/62 ... ok 36/64 ... ok 6/65 ... ok 4/66 ... ok 63/67 ... ok 32/68 ... ok 32/69 ... ok 63/72 ... ok 32/73 ... ok 6/74 ... ok 6/76 ... ok 37/77 ... repository is empty 6/78 ... ok 5/83 ... ok 4/84 ... ok 63/87 ... ok 63/88 ... ok 4/89 ... ok 63/90 ... ok 5/91 ... ok 4/92 ... ok 4/94 ... ok 4/95 ... ok 6/97 ... ok 63/98 ... ok 4/99 ... ok 4/100 ... ok 63/101 ... ok 63/102 ... ok 67/103 ... ok 63/104 ... ok 67/105 ... ok 63/106 ... ok 70/107 ... ok 63/109 ... ok 4/110 ... ok 72/111 ... ok 115/112 ... ok 4/113 ... ok 72/114 ... ok 115/115 ... ok 63/116 ... ok 32/117 ... ok 63/119 ... ok 32/120 ... ok 63/121 ... ok 72/123 ... ok 72/124 ... ok 32/125 ... ok 115/126 ... ok 4/127 ... ok 32/128 ... ok 72/129 ... ok 58/132 ... ok 32/134 ... ok 58/135 ... ok 63/137 ... ok 90/139 ... ok 63/140 ... ok 72/141 ... ok 70/142 ... ok 87/143 ... ok 63/144 ... ok 93/145 ... ok 93/146 ... ok 32/147 ... ok 96/148 ... ok 63/149 ... ok 97/150 ... ok 96/152 ... ok 96/153 ... ok 96/154 ... ok 96/155 ... ok 96/156 ... ok 96/157 ... ok 102/159 ... ok 102/160 ... ok 102/161 ... ok 102/162 ... ok 96/163 ... ok 96/164 ... ok 63/165 ... ok 125/166 ... ok 96/168 ... ok 32/169 ... ok 63/170 ... ok 63/171 ... ok 72/172 ... ok 63/173 ... ok 63/174 ... ok 63/175 ... ok 70/176 ... ok 93/177 ... ok 70/178 ... ok 63/179 ... ok 70/180 ... ok 93/181 ... ok 93/182 ... ok 115/183 ... ok 93/184 ... ok 93/185 ... ok 96/186 ... ok 96/187 ... ok 115/188 ... ok 102/189 ... ok 102/190 ... ok 102/191 ... ok 102/192 ... ok 102/194 ... ok 102/195 ... ok 102/196 ... ok 63/197 ... ok 96/198 ... ok 96/199 ... ok 93/200 ... ok 63/201 ... ok 96/202 ... ok 96/204 ... ok 96/205 ... ok 96/206 ... ok 63/207 ... ok 63/208 ... ok 87/209 ... ok 128/210 ... ok 63/211 ... ok 63/212 ... ok 87/213 ... ok 97/215 ... ok 63/216 ... ok 70/217 ... ok 63/218 ... ok 115/219 ... ok 97/220 ... ok 63/222 ... ok 96/223 ... ok 63/224 ... ok 115/225 ... ok 32/226 ... ok 96/227 ... ok 32/228 ... ok 87/229 ... ok 93/230 ... ok 63/231 ... repository is empty 96/232 ... ok 70/233 ... ok 63/234 ... ok 63/235 ... ok 63/236 ... ok 63/237 ... ok 63/238 ... ok 63/239 ... ok 63/240 ... repository is empty 63/241 ... repository is empty 63/242 ... ok 63/243 ... ok 96/247 ... ok 144/248 ... ok 115/249 ... ok 96/251 ... ok 63/252 ... ok 5/253 ... ok 96/254 ... ok 96/255 ... ok 96/256 ... ok 63/257 ... ok 32/259 ... ok 115/260 ... ok 90/270 ... ok 96/272 ... ok 63/273 ... ok 150/274 ... ok 150/275 ... ok 150/276 ... ok 150/277 ... ok 150/278 ... ok 63/279 ... ok Running /opt/gitlab/embedded/service/gitlab-shell/bin/check Check GitLab API access: OK Redis available via internal API: OK Access to /var/opt/gitlab/.ssh/authorized_keys: OK gitlab-shell self-check successful Checking GitLab Shell ... Finished Checking Sidekiq ... Running? ... yes Number of Sidekiq processes ... 1 Checking Sidekiq ... Finished Reply by email is disabled in config/gitlab.yml Checking LDAP ... LDAP is disabled in config/gitlab.yml Checking LDAP ... Finished Checking GitLab ... Git configured correctly? ... yes Database config exists? ... yes All migrations up? ... yes Database contains orphaned GroupMembers? ... no GitLab config exists? ... yes GitLab config up to date? ... yes Log directory writable? ... yes Tmp directory writable? ... yes Uploads directory exists? ... yes Uploads directory has correct permissions? ... yes Uploads directory tmp has correct permissions? ... yes Init script exists? ... skipped (omnibus-gitlab has no init script) Init script up-to-date? ... skipped (omnibus-gitlab has no init script) Projects have namespace: ... 4/1 ... yes 5/2 ... yes 4/5 ... yes 6/6 ... yes 5/8 ... yes 5/9 ... yes 5/10 ... yes 4/12 ... yes 4/14 ... yes 4/15 ... yes 4/16 ... yes 5/18 ... yes 4/19 ... yes 5/21 ... yes 32/22 ... yes 32/23 ... yes 32/24 ... yes 32/25 ... yes 5/26 ... yes 4/28 ... yes 5/29 ... yes 4/30 ... yes 5/31 ... yes 5/32 ... yes 32/33 ... yes 32/34 ... yes 4/35 ... yes 36/36 ... yes 36/38 ... yes 4/39 ... yes 36/40 ... yes 36/41 ... yes 36/43 ... yes 32/46 ... yes 4/47 ... yes 4/48 ... yes 5/50 ... yes 4/51 ... yes 4/52 ... yes 6/56 ... yes 6/57 ... yes 6/58 ... yes 5/59 ... yes 4/60 ... yes 4/61 ... yes 4/62 ... yes 36/64 ... yes 6/65 ... yes 4/66 ... yes 63/67 ... yes 32/68 ... yes 32/69 ... yes 63/72 ... yes 32/73 ... yes 6/74 ... yes 6/76 ... yes 37/77 ... yes 6/78 ... yes 5/83 ... yes 4/84 ... yes 63/87 ... yes 63/88 ... yes 4/89 ... yes 63/90 ... yes 5/91 ... yes 4/92 ... yes 4/94 ... yes 4/95 ... yes 6/97 ... yes 63/98 ... yes 4/99 ... yes 4/100 ... yes 63/101 ... yes 63/102 ... yes 67/103 ... yes 63/104 ... yes 67/105 ... yes 63/106 ... yes 70/107 ... yes 63/109 ... yes 4/110 ... yes 72/111 ... yes 115/112 ... yes 4/113 ... yes 72/114 ... yes 115/115 ... yes 63/116 ... yes 32/117 ... yes 63/119 ... yes 32/120 ... yes 63/121 ... yes 72/123 ... yes 72/124 ... yes 32/125 ... yes 115/126 ... yes 4/127 ... yes 32/128 ... yes 72/129 ... yes 58/132 ... yes 32/134 ... yes 58/135 ... yes 63/137 ... yes 90/139 ... yes 63/140 ... yes 72/141 ... yes 70/142 ... yes 87/143 ... yes 63/144 ... yes 93/145 ... yes 93/146 ... yes 32/147 ... yes 96/148 ... yes 63/149 ... yes 97/150 ... yes 96/152 ... yes 96/153 ... yes 96/154 ... yes 96/155 ... yes 96/156 ... yes 96/157 ... yes 102/159 ... yes 102/160 ... yes 102/161 ... yes 102/162 ... yes 96/163 ... yes 96/164 ... yes 63/165 ... yes 125/166 ... yes 96/168 ... yes 32/169 ... yes 63/170 ... yes 63/171 ... yes 72/172 ... yes 63/173 ... yes 63/174 ... yes 63/175 ... yes 70/176 ... yes 93/177 ... yes 70/178 ... yes 63/179 ... yes 70/180 ... yes 93/181 ... yes 93/182 ... yes 115/183 ... yes 93/184 ... yes 93/185 ... yes 96/186 ... yes 96/187 ... yes 115/188 ... yes 102/189 ... yes 102/190 ... yes 102/191 ... yes 102/192 ... yes 102/194 ... yes 102/195 ... yes 102/196 ... yes 63/197 ... yes 96/198 ... yes 96/199 ... yes 93/200 ... yes 63/201 ... yes 96/202 ... yes 96/204 ... yes 96/205 ... yes 96/206 ... yes 63/207 ... yes 63/208 ... yes 87/209 ... yes 128/210 ... yes 63/211 ... yes 63/212 ... yes 87/213 ... yes 97/215 ... yes 63/216 ... yes 70/217 ... yes 63/218 ... yes 115/219 ... yes 97/220 ... yes 63/222 ... yes 96/223 ... yes 63/224 ... yes 115/225 ... yes 32/226 ... yes 96/227 ... yes 32/228 ... yes 87/229 ... yes 93/230 ... yes 63/231 ... yes 96/232 ... yes 70/233 ... yes 63/234 ... yes 63/235 ... yes 63/236 ... yes 63/237 ... yes 63/238 ... yes 63/239 ... yes 63/240 ... yes 63/241 ... yes 63/242 ... yes 63/243 ... yes 96/247 ... yes 144/248 ... yes 115/249 ... yes 96/251 ... yes 63/252 ... yes 5/253 ... yes 96/254 ... yes 96/255 ... yes 96/256 ... yes 63/257 ... yes 32/259 ... yes 115/260 ... yes 90/270 ... yes 96/272 ... yes 63/273 ... yes 150/274 ... yes 150/275 ... yes 150/276 ... yes 150/277 ... yes 150/278 ... yes 63/279 ... yes Redis version >= 2.8.0? ... yes Ruby version >= 2.3.5 ? ... yes (2.4.4) Git version >= 2.9.5 ? ... yes (2.18.1) Git user has default SSH configuration? ... yes Active users: ... 61 Elasticsearch version 5.1 - 5.5? ... skipped (elasticsearch is disabled) Checking GitLab ... Finished
Possible fixes
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/auth/saml/auth_hash.rb#L31
Replacing the xpath query with either
//*[name() = 'saml:AuthnStatement' or name()='saml2:AuthnStatement']/*[name() = 'saml:AuthnContext' or name()='saml2:AuthnContext']/*[name() = 'saml:AuthnContextClassRef' or name()='saml2:AuthnContextClassRef']/text()
or
//*[local-name() = 'AuthnStatement']/*[local-name() = 'AuthnContext']/*[local-name() = 'AuthnContextClassRef']/text()
will work.