-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
187 lines (149 loc) · 6.87 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
var colors = require('colors/safe');
var randomstring = require("randomstring"),
encryptDecrypt = require("./lib/encrypt-decrypt"),
separator = "###",
defaultTimeDiff = 250000;
function isJsonString(str) {
try {
var js = JSON.parse(str);
if (Object.keys(js).length < 2) {
console.warn(colors.red("CSRFImmunity Module (csrfImmunity.js) : Options parameter is not enough. Application might be risky to CSRF attacks"));
}
} catch (e) {
console.log(e);
console.log(colors.red("CSRFImmunity Module (csrfImmunity.js) : Not a valid JSON string, " + str));
// throw new Error(e);
return false;
}
return true;
}
module.exports = {
setKeyForEncryption: function(key) {
if (key !== "" && key !== null) {
encryptDecrypt.setKeyForEncryption(key);
return this;
} else {
console.log(colors.red("Key not found. Please provide the encryption key"));
return null;
}
},
generateTimeBasedToken: function(options, callback) {
//options needed to generate the csrf token Ex : {"formname":"loginform", formaction="http://www.weekendsecurity.org/submit"}
options = options || '{"null": "null"}';
//Check for valid JSON string
if(isJsonString(options)){
//Time calculated to check the CSRF token validity
var milliseconds = new Date().getTime();
//A random String to pass in the CSRF token and cookie value
var randomString = randomstring.generate(15);
//Converting the options JSON to hexadecimal value
var optionsBuffer = new Buffer(options);
var encodedOptions = optionsBuffer.toString('hex');
//Collecting all the token parameters for token generations
var tokenHidden = encodedOptions + separator + randomString + separator + milliseconds;
// Encrypting the CSRF token
var token = encryptDecrypt.encrypt(tokenHidden);
callback(token);
}else{
throw new Error('Options is not a JSON String');
}
},
generateToken: function(options, callback) {
options = options || '{"null": "null"}';
//Check for valid JSON string
if(isJsonString(options)){
//Time calculated to check the CSRF token validity
var milliseconds = new Date().getTime();
//A random String to pass in the CSRF token and cookie value
var randomString = randomstring.generate(15);
//Converting the options JSON to hexadecimal value
var optionsBuffer = new Buffer(options);
var encodedOptions = optionsBuffer.toString('hex');
//Collecting all the token parameters for token generations
var tokenHidden = encodedOptions + separator + randomString;
// Encrypting the CSRF token
var token = encryptDecrypt.encrypt(tokenHidden);
callback(token);
}else{
throw new Error('Options is not a JSON String');
}
},
verifyTimeBasedToken: function(csrfToken, options) {
//The options which is used to generate the CSRF token
options = options || '{"null":"null"}';
//Check for valid JSON string
if(isJsonString(options)){
//Need the CSRF token to be passed here for verification
csrfToken = csrfToken || "";
//Return false if the csrfToken and cookieValue are sent null
if (csrfToken === "") {
return false;
}
//Decrypting the csrf token
try {
var decTokenHidden = encryptDecrypt.decrypt(csrfToken);
//Split the tokens using the separators and store it in an array
var decTokenHiddenArray = decTokenHidden.split(separator);
//Converting the options in the hidden token to ascii and then into Javascript object
var optionsBuffer = new Buffer(decTokenHiddenArray[0], 'hex');
var optionsjsFromToken = JSON.parse(optionsBuffer.toString('ascii'));
var optionsjsFromParam = JSON.parse(options);
//Fetching the time limit of token validity from options parameter.
var timeDef = optionsjsFromParam.milliseconds || defaultTimeDiff;
var currentMilliseconds = new Date().getTime();
//Verifying if the CSRF token with time, and options parameter
if (currentMilliseconds < Number(decTokenHiddenArray[2]) + timeDef) {
for (var key in optionsjsFromToken) {
if (optionsjsFromToken[key] !== optionsjsFromParam[key]) {
return false;
}
}
return true;
} else {
return false;
}
} catch (e) {
console.log(colors.red(e));
console.log(colors.red("CSRFImmunity (index.js) : CSRF decryption failed.", e));
throw new Error(e);
}
}else{
throw new Error('Options is not a JSON String');
}
},
verifyToken: function(csrfToken, options) {
//The options which is used to generate the CSRF token
options = options || '{"null":"null"}';
if(isJsonString(options)){
//Need the CSRF token to be passed here for verification
csrfToken = csrfToken || "";
//Return false if the csrfToken and cookieValue are sent null
if (csrfToken === "") {
return false;
}
//Decrypting the csrf token
try {
var decTokenHidden = encryptDecrypt.decrypt(csrfToken);
//Split the tokens using the separators and store it in an array
var decTokenHiddenArray = decTokenHidden.split(separator);
//Converting the options in the hidden token to ascii and then into Javascript object
var optionsBuffer = new Buffer(decTokenHiddenArray[0], 'hex');
var optionsjsFromToken = JSON.parse(optionsBuffer.toString('ascii'));
var optionsjsFromParam = JSON.parse(options);
//Verifying if the CSRF token with time, and options parameter
for (var key in optionsjsFromToken) {
if (optionsjsFromToken[key] !== optionsjsFromParam[key]) {
return false;
}
}
return true;
} catch (e) {
console.log(e);
console.log(colors.red("CSRFImmunity (csrfImmunity.js) : CSRF decryption failed."));
throw new Error(e);
}
}else{
throw new Error('Options is not a JSON String');
}
}
};