Skip to content

Commit

Permalink
Limit upper border for JS challenge to deny hardcoding the challenge
Browse files Browse the repository at this point in the history
Detailed information in my comment to #1102 issue
  • Loading branch information
vankoven committed Nov 23, 2018
1 parent c662213 commit cdd449d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 25 deletions.
8 changes: 4 additions & 4 deletions etc/tempesta_fw.conf
Original file line number Diff line number Diff line change
Expand Up @@ -876,9 +876,9 @@
#
# 'delay_min' - Minimal timeout to make a client wait.
# 'delay_range' - Allowed time period to receive and accept client's session.
# 'delay_limit' - Maximum difference between current jiffies value when a
# consequent request is received and a timestamp specified
# in the sticky cookie. Optional parameter.
# 'delay_limit' - Maximum time to deliver request from client to the Tempesta
# server. Optional parameter. Default is 1/10 of
# 'delay_range'.
# 'resp_code' - Status code for response with JS challenge. Optional
# parameter, default is "503".
# <SCRIPT_TEMPLATE> - path to JS challenge script.. Optional parameter, default
Expand All @@ -890,7 +890,7 @@
# line breaks are not allowed inside the directive.
#
# Example:
# js_challenge resp_code=503 delay_min=1000 delay_range=1000 delay_limit=3000
# js_challenge resp_code=503 delay_min=1000 delay_range=3000 delay_limit=300
# /etc/ddos_redirect.html
#

Expand Down
47 changes: 26 additions & 21 deletions tempesta_fw/http_sess.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ static struct kmem_cache *sess_cache;
* @body - body (html with JavaScript code);
* @delay_min - minimal timeout client must wait before repeat the request,
* in jiffies;
* @delay_limit - maximum timeout between JS challenge generation and client's
* request to pass the challenge, in jiffies;
* @delay_limit - maximum time required to deliver request form a client to the
* Tempesta, in jiffies;
* @delay_range - time interval starting after @delay_min for a client to make
* a repeated request, in msecs;
* @st_code - status code for response with JS challenge;
Expand Down Expand Up @@ -871,21 +871,20 @@ tfw_http_sess_remove(TfwHttpSess *sess)
static int
tfw_http_sess_check_jsch(StickyVal *sv, TfwHttpReq* req)
{
unsigned long cur_time, min_time, max_time;
unsigned long min_time, max_time;

if (!tfw_cfg_js_ch)
return 0;

cur_time = jiffies;
/*
* When a client calculates it's own random delay, it uses range value
* encoded as msecs, we have to use the same, to have exactly the same
* calculation results. See etc/js_challenge.js.tpl .
*/
min_time = sv->ts + tfw_cfg_js_ch->delay_min
+ msecs_to_jiffies(sv->ts % tfw_cfg_js_ch->delay_range);
max_time = sv->ts + tfw_cfg_js_ch->delay_limit;
if (time_in_range(cur_time, min_time, max_time))
max_time = min_time + tfw_cfg_js_ch->delay_limit;
if (time_in_range(req->jrxtstamp, min_time, max_time))
return 0;

if (tfw_http_sticky_redirect_apllied(req)) {
Expand Down Expand Up @@ -1295,25 +1294,31 @@ tfw_cfg_op_jsch_parse_resp_code(TfwCfgSpec *cs, const char *val)
static void
tfw_cfgop_jsch_set_delay_limit(TfwCfgSpec *cs)
{
const unsigned long min_limit = tfw_cfg_js_ch->delay_min
+ msecs_to_jiffies(tfw_cfg_js_ch->delay_range);
const unsigned long warn_limit = min_limit + msecs_to_jiffies(100);
const unsigned long def_limit = min_limit + msecs_to_jiffies(1000);
const unsigned long min_limit = msecs_to_jiffies(100);
const unsigned long max_hc_p = 10;
const unsigned long max_limit =
msecs_to_jiffies(tfw_cfg_js_ch->delay_range) * max_hc_p / 100;
unsigned long hc_prob;

if (!tfw_cfg_js_ch->delay_limit) {
tfw_cfg_js_ch->delay_limit = def_limit;
tfw_cfg_js_ch->delay_limit = max_limit;
}
else if (tfw_cfg_js_ch->delay_limit < min_limit) {
TFW_WARN_NL("%s: delay limit is too low, "
"enforce it to minimum possible value "
"'delay_range + delay_min' (%u)\n",
cs->name, jiffies_to_msecs(min_limit));
tfw_cfg_js_ch->delay_limit = min_limit;
if (tfw_cfg_js_ch->delay_limit < min_limit) {
TFW_WARN_NL("%s: 'delay_limit' is too low, many slow/distant "
"clients will be blocked. "
"Minimum recommended value is %u, "
"but %u is provided\n",
cs->name,
jiffies_to_msecs(min_limit),
jiffies_to_msecs(tfw_cfg_js_ch->delay_limit));
}
else if (tfw_cfg_js_ch->delay_limit < warn_limit) {
TFW_WARN_NL("%s: delay limit is less than recommended value "
"'delay_range + delay_min + 100' (%u)\n",
cs->name, jiffies_to_msecs(warn_limit));
hc_prob = tfw_cfg_js_ch->delay_limit * 100
/ msecs_to_jiffies(tfw_cfg_js_ch->delay_range);
if (hc_prob > max_hc_p) {
TFW_WARN_NL("%s: 'delay_limit' is too big, attacker may "
"hardcode bots and breach the JavaScript challenge "
"with %lu%% success probability\n",
cs->name, hc_prob);
}
}

Expand Down

0 comments on commit cdd449d

Please sign in to comment.