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

# Conflicts:
#	etc/tempesta_fw.conf
  • Loading branch information
vankoven committed Nov 26, 2018
1 parent e8d1e9e commit a5975a9
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 27 deletions.
12 changes: 6 additions & 6 deletions etc/tempesta_fw.conf
Original file line number Diff line number Diff line change
Expand Up @@ -691,21 +691,21 @@
#
# 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
# is "/etc/tempesta/js_challenge.conf".
# <TIME> - time in usecs.
#
# NOTE: During start process "tempesta.sh' uses 'grep' to update
# NOTE: During start process 'tempesta.sh' uses 'grep' to update
# <SCRIPT_TEMPLATE> file with values described in 'js_challenge' directive, so
# line braks are not allowed inside the directive.
# 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 @@ -103,8 +103,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 @@ -627,21 +627,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 its 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_applied(req)) {
Expand Down Expand Up @@ -1014,25 +1013,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 a5975a9

Please sign in to comment.