Bug 40897 Bug Bounty: Double the number of max conflux circs

We strongly suspect that bug 40897 was caused by a custom Tor client that
tried to use more than the default number of conflux circuits, for either
performance or traffic analysis defense gains, or both.

This entity hit a safety check on the exit side, which caused a UAF. Our
"belt and suspenders" snapped off, and hit us in the face... again...

Since there are good reasons to try more than 2 conflux legs, and research has
found some traffic analysis benefits with as many as 5, we're going to raise
and parameterize this limit as a form of bug bounty for finding this UAF, so
that this entity can try out a little more confluxing.

This should also make it easier for researchers to try things like gathering
traces with larger amounts of confluxing than normal, to measure real-world
traffic analysis impacts of conflux.

Shine on, you yoloing anonymous diamond. Let us know if you find out anything
interesting!
This commit is contained in:
Mike Perry 2023-12-06 17:23:19 +00:00
parent 03778a0f34
commit cc52f7e5b7
4 changed files with 21 additions and 14 deletions

View File

@ -56,6 +56,11 @@
#define NUM_LEGS_SET_MAX (UINT8_MAX) #define NUM_LEGS_SET_MAX (UINT8_MAX)
#define NUM_LEGS_SET_DEFAULT (2) #define NUM_LEGS_SET_DEFAULT (2)
/* For "cfx_max_legs_set" */
#define MAX_LEGS_SET_MIN (3)
#define MAX_LEGS_SET_MAX (UINT8_MAX)
#define MAX_LEGS_SET_DEFAULT (8)
/* For "cfx_send_pct". */ /* For "cfx_send_pct". */
#define CFX_SEND_PCT_MIN (0) #define CFX_SEND_PCT_MIN (0)
#define CFX_SEND_PCT_MAX (255) #define CFX_SEND_PCT_MAX (255)
@ -81,6 +86,8 @@ static uint8_t max_prebuilt_set = MAX_PREBUILT_SET_DEFAULT;
STATIC uint32_t max_unlinked_leg_retry = MAX_UNLINKED_LEG_RETRY_DEFAULT; STATIC uint32_t max_unlinked_leg_retry = MAX_UNLINKED_LEG_RETRY_DEFAULT;
/* Number of legs per set. */ /* Number of legs per set. */
static uint8_t num_legs_set = NUM_LEGS_SET_DEFAULT; static uint8_t num_legs_set = NUM_LEGS_SET_DEFAULT;
/* Maximum number of legs per set allowed at exits */
static uint8_t max_legs_set = MAX_LEGS_SET_DEFAULT;
/* The low Exit relay threshold, as a ratio between 0 and 1, used as a limit to /* The low Exit relay threshold, as a ratio between 0 and 1, used as a limit to
* decide the amount of pre-built set we build depending on how many Exit relay * decide the amount of pre-built set we build depending on how many Exit relay
* supports conflux in our current consensus. */ * supports conflux in our current consensus. */
@ -223,6 +230,13 @@ conflux_params_get_num_legs_set(void)
return num_legs_set; return num_legs_set;
} }
/** Return the maximum number of legs per set. */
uint8_t
conflux_params_get_max_legs_set(void)
{
return max_legs_set;
}
/** Return the drain percent we must hit before switching */ /** Return the drain percent we must hit before switching */
uint8_t uint8_t
conflux_params_get_drain_pct(void) conflux_params_get_drain_pct(void)
@ -275,6 +289,11 @@ conflux_params_new_consensus(const networkstatus_t *ns)
NUM_LEGS_SET_DEFAULT, NUM_LEGS_SET_DEFAULT,
NUM_LEGS_SET_MIN, NUM_LEGS_SET_MAX); NUM_LEGS_SET_MIN, NUM_LEGS_SET_MAX);
max_legs_set =
networkstatus_get_param(ns, "cfx_max_legs_set",
MAX_LEGS_SET_DEFAULT,
MAX_LEGS_SET_MIN, MAX_LEGS_SET_MAX);
/* Params used by conflux.c */ /* Params used by conflux.c */
cfx_send_pct = networkstatus_get_param(ns, "cfx_send_pct", cfx_send_pct = networkstatus_get_param(ns, "cfx_send_pct",
CFX_SEND_PCT_DFLT, CFX_SEND_PCT_DFLT,

View File

@ -16,6 +16,7 @@ uint8_t conflux_params_get_max_linked_set(void);
uint8_t conflux_params_get_max_prebuilt(void); uint8_t conflux_params_get_max_prebuilt(void);
uint8_t conflux_params_get_max_unlinked_leg_retry(void); uint8_t conflux_params_get_max_unlinked_leg_retry(void);
uint8_t conflux_params_get_num_legs_set(void); uint8_t conflux_params_get_num_legs_set(void);
uint8_t conflux_params_get_max_legs_set(void);
uint8_t conflux_params_get_drain_pct(void); uint8_t conflux_params_get_drain_pct(void);
uint8_t conflux_params_get_send_pct(void); uint8_t conflux_params_get_send_pct(void);

View File

@ -743,7 +743,7 @@ try_finalize_set(unlinked_circuits_t *unlinked)
/* If there are too many legs, we can't link. */ /* If there are too many legs, we can't link. */
if (smartlist_len(unlinked->legs) + if (smartlist_len(unlinked->legs) +
smartlist_len(unlinked->cfx->legs) > CONFLUX_MAX_CIRCS) { smartlist_len(unlinked->cfx->legs) > conflux_params_get_max_legs_set()) {
log_fn(LOG_PROTOCOL_WARN, LD_CIRC, log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
"Conflux set has too many legs to link. " "Conflux set has too many legs to link. "
"Rejecting this circuit."); "Rejecting this circuit.");

View File

@ -22,19 +22,6 @@ typedef enum {
CONFLUX_ALG_CWNDRTT = 2, CONFLUX_ALG_CWNDRTT = 2,
} conflux_alg_t; } conflux_alg_t;
/**
* Maximum number of linked circuits.
*
* We want to experiment with 3 guards, so we need at least 3 here.
*
* However, we need 1 more than this, to support using a test circuit to probe
* for a faster path, for applications that *require* a specific latency target
* (like VoIP).
*
* We may also want to raise this for traffic analysis defense evaluation.
*/
#define CONFLUX_MAX_CIRCS 4
/** XXX: Cached consensus params+scheduling alg */ /** XXX: Cached consensus params+scheduling alg */
struct conflux_params_t { struct conflux_params_t {
conflux_alg_t alg; conflux_alg_t alg;