Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
gitlab-ce
Commits
29022350
Commit
29022350
authored
Jun 16, 2017
by
blackst0ne
Committed by
Douwe Maan
Jul 26, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add CSRF token verification to API
parent
f2da36f1
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
80 additions
and
4 deletions
+80
-4
changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml
...s/unreleased/33601-add-csrf-token-verification-to-api.yml
+4
-0
lib/api/helpers.rb
lib/api/helpers.rb
+34
-4
spec/lib/api/helpers/csrf_tokens_spec.rb
spec/lib/api/helpers/csrf_tokens_spec.rb
+42
-0
No files found.
changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml
0 → 100644
View file @
29022350
---
title
:
Add CSRF token verification to API
merge_request
:
12154
author
:
@
blackst0ne
lib/api/helpers.rb
View file @
29022350
...
...
@@ -328,6 +328,33 @@ module API
private
def
xor_byte_strings
(
s1
,
s2
)
s2_bytes
=
s2
.
bytes
s1
.
each_byte
.
with_index
{
|
c1
,
i
|
s2_bytes
[
i
]
^=
c1
}
s2_bytes
.
pack
(
'C*'
)
end
# Check if CSRF tokens are equal.
# The header token is masked.
# So, before the comparison it must be unmasked.
def
csrf_tokens_valid?
(
request
)
session_token
=
request
.
session
[
'_csrf_token'
]
header_token
=
request
.
headers
[
'X-Csrf-Token'
]
session_token
=
Base64
.
strict_decode64
(
session_token
)
header_token
=
Base64
.
strict_decode64
(
header_token
)
# Decoded CSRF token passed from the frontend has to be 64 symbols long.
return
false
if
header_token
.
size
!=
64
header_token
=
xor_byte_strings
(
header_token
[
0
...
32
],
header_token
[
32
..-
1
])
ActiveSupport
::
SecurityUtils
.
secure_compare
(
session_token
,
header_token
)
rescue
false
end
def
private_token
params
[
APIGuard
::
PRIVATE_TOKEN_PARAM
]
||
env
[
APIGuard
::
PRIVATE_TOKEN_HEADER
]
end
...
...
@@ -336,12 +363,15 @@ module API
env
[
'warden'
]
end
def
verified_request?
request
=
Grape
::
Request
.
new
(
env
)
request
.
head?
||
request
.
get?
||
csrf_tokens_valid?
(
request
)
end
# Check the Rails session for valid authentication details
#
# Until CSRF protection is added to the API, disallow this method for
# state-changing endpoints
def
find_user_from_warden
warden
.
try
(
:authenticate
)
if
%w[GET HEAD]
.
include?
(
env
[
'REQUEST_METHOD'
])
warden
.
try
(
:authenticate
)
if
verified_request?
end
def
initial_current_user
...
...
spec/lib/api/helpers/csrf_tokens_spec.rb
0 → 100644
View file @
29022350
require
'spec_helper'
describe
API
::
Helpers
do
subject
do
Class
.
new
.
include
(
described_class
).
new
end
let
(
:header_token
)
{
'WblCcheb1qQLHFVhlMtwOhxJr5613vUT05vCvToRvfJ68UPT7+eV5xpaY9CjubnF3VGbTfIhQYkZWmWTfvZAWQ=='
}
let
(
:session_token
)
{
'I0gBofh8Q0MRRjaxN3LJ/8EYNNNH/7SaysGnLkTn/as='
}
before
do
class
Request
attr_reader
:headers
attr_reader
:session
def
initialize
(
header_token
=
nil
,
session_token
=
nil
)
@headers
=
{
'X-Csrf-Token'
=>
header_token
}
@session
=
{
'_csrf_token'
=>
session_token
}
end
end
end
it
'should return false if header token is invalid'
do
request
=
Request
.
new
(
nil
,
session_token
)
expect
(
subject
.
send
(
:csrf_tokens_valid?
,
request
)).
to
be
false
end
it
'should return false if session_token token is invalid'
do
request
=
Request
.
new
(
header_token
,
nil
)
expect
(
subject
.
send
(
:csrf_tokens_valid?
,
request
)).
to
be
false
end
it
'should return false if header_token is not 64 symbols long'
do
request
=
Request
.
new
(
header_token
[
0
..
16
],
session_token
)
expect
(
subject
.
send
(
:csrf_tokens_valid?
,
request
)).
to
be
false
end
it
'should return true if both header_token and session_token are correct'
do
request
=
Request
.
new
(
header_token
,
session_token
)
expect
(
subject
.
send
(
:csrf_tokens_valid?
,
request
)).
to
be
true
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment