Skip to content

Commit

Permalink
fix(console): add csrf check (tkestack#2198)
Browse files Browse the repository at this point in the history
* fix(console): add csrf check

* fix(console): webpack support csrf-code

* feat(console): change DJB hash to md5

* fix(console): add csrf token cache
  • Loading branch information
jo-hnny committed Dec 8, 2022
1 parent 0e873ea commit 807d480
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 10 deletions.
23 changes: 20 additions & 3 deletions pkg/gateway/token/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,22 @@
package token

import (
"crypto/md5"
"encoding/base64"
"encoding/hex"
"fmt"
jsoniter "github.com/json-iterator/go"
"golang.org/x/oauth2"
"net/http"
"strings"
"time"

jsoniter "github.com/json-iterator/go"
"golang.org/x/oauth2"
"tkestack.io/tke/pkg/util/log"
)

const (
cookieName = "tke"
headerName = "X-CSRF-TOKEN"
)

var json = jsoniter.ConfigCompatibleWithStandardLibrary
Expand All @@ -47,6 +52,18 @@ func RetrieveToken(request *http.Request) (*Token, error) {
if err != nil {
return nil, err
}

// if is api request, check csrf
path := request.URL.Path
if strings.HasPrefix(path, "/api") {
csrfHeader := request.Header.Get(headerName)
cookieHash := md5.Sum([]byte(cookie.Value))

if csrfHeader != hex.EncodeToString(cookieHash[:]) {
return nil, fmt.Errorf("invalid CSRF token")
}
}

tokenJSON, err := base64.StdEncoding.DecodeString(cookie.Value)
if err != nil {
log.Error("Failed to base64 decode cookie value", log.Err(err))
Expand Down Expand Up @@ -87,7 +104,7 @@ func ResponseToken(t *oauth2.Token, writer http.ResponseWriter) error {
cookie := &http.Cookie{
Name: cookieName,
Value: tokenStr,
HttpOnly: true,
HttpOnly: false,
Secure: false,
Path: "/",
MaxAge: int(time.Until(t.Expiry).Seconds()),
Expand Down
15 changes: 15 additions & 0 deletions web/console/helpers/csrf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Cookies from 'js-cookie';
import SparkMD5 from 'spark-md5';

let CSRF_TOKEN = null;

export function createCSRFHeader() {
if (CSRF_TOKEN === null) {
const tkeCookie = Cookies.get('tke') ?? '';
CSRF_TOKEN = SparkMD5.hash(tkeCookie);
}

return {
'X-CSRF-TOKEN': CSRF_TOKEN
};
}
1 change: 1 addition & 0 deletions web/console/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ export { getCookie } from './cookieUtil';
export { reduceK8sQueryString, reduceK8sRestfulPath, reduceNs, parseQueryString, cutNsStartClusterId } from './urlUtil';
export * from './request';
export * from './format';
export * from './csrf';
5 changes: 4 additions & 1 deletion web/console/helpers/reduceNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { RequestParams, ResourceInfo } from '../src/modules/common/models';
import { changeForbiddentConfig } from '../index.tke';
import { parseQueryString } from './urlUtil';
import { getProjectName } from './appUtil';
import Cookies from 'js-cookie';
import { createCSRFHeader } from '@helper';

/** 是否展示没有权限的弹窗 */
export const Init_Forbiddent_Config = {
Expand Down Expand Up @@ -154,7 +156,8 @@ export const reduceNetworkRequest = async (
{},
{
'X-Remote-Extra-RequestID': uuid(),
'Content-Type': 'application/json'
'Content-Type': 'application/json',
...createCSRFHeader()
},
userDefinedHeader
),
Expand Down
18 changes: 15 additions & 3 deletions web/console/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion web/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"ifvisible.js": "^1.0.6",
"immer": "^7.0.8",
"js-base64": "^3.4.5",
"js-cookie": "^3.0.1",
"js-yaml": "^3.12.0",
"lodash": "^4.17.14",
"marked": "^0.7.0",
Expand All @@ -67,6 +68,8 @@
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-thunk": "=2.0.1",
"spark-md5": "^3.0.2",
"tea-chart": "^2.4.6",
"tea-component": "^2.7.3",
"ts-optchain": "^0.1.7",
"use-immer": "^0.4.1",
Expand Down Expand Up @@ -128,4 +131,4 @@
"webpack-cli": "^4.7.0",
"webpack-dev-server": "^3.11.2"
}
}
}
5 changes: 4 additions & 1 deletion web/console/src/webApi/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import { changeForbiddentConfig } from '@/index.tke';
import Axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
import Cookies from 'js-cookie';
import { createCSRFHeader } from '@helper';

const instance = Axios.create({
timeout: 10000
Expand All @@ -28,7 +30,8 @@ const instance = Axios.create({
instance.interceptors.request.use(
config => {
Object.assign(config.headers, {
'X-Remote-Extra-RequestID': uuidv4()
'X-Remote-Extra-RequestID': uuidv4(),
...createCSRFHeader()
});
return config;
},
Expand Down
28 changes: 28 additions & 0 deletions web/console/webpack/csrf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const SparkMD5 = require('spark-md5');

function parseCookie(cookieStr) {
cookieStr.split('; ').reduce((all, item) => {
const [key, value] = item.split('=');

return {
...all,
[key]: value
};
}, {});
}

function createCSRFHeader(cookieStr) {
const cookie = parseCookie(cookieStr);

const tkeCookie = cookie?.['tke'] ?? '';

const token = SparkMD5.hash(tkeCookie);

return {
'X-CSRF-TOKEN': token
};
}

module.exports = {
createCSRFHeader
};
3 changes: 2 additions & 1 deletion web/console/webpack/webpack.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();
const path = require('path');
const { Host, Cookie } = require('../server.config');
const { createCSRFHeader } = require('./csrf');

module.exports = ({ version }) =>
smp.wrap({
Expand All @@ -37,7 +38,7 @@ module.exports = ({ version }) =>
target: Host,
secure: false,
changeOrigin: true,
headers: { Cookie }
headers: { Cookie, ...createCSRFHeader(Cookie) }
},

'/websocket': {
Expand Down

0 comments on commit 807d480

Please sign in to comment.