MXS-2457 Allow strings to be treated as fields

Before this change, if the firewall was configured to block the use
of certain columns, it could be be bypassed simply by

        > set @@sql_mode='ANSI_QUOTES';
        > select "ssn" from person;

The reason is that as the query classifier is not aware of whether
'ANSI_QUOTES' is on or not, it will not know that what above appears
to be the string "ssn", actually is the field name `ssn`. Consequently,
the select will not be blocked and the result returned in cleartext.

It's now possible to instruct the query classifier to report all strings
as fields, which will prevent the above. However, it will also mean that
there may be false positives.
This commit is contained in:
Johan Wikman 2019-05-03 08:58:56 +03:00
parent fe5160a714
commit 4aa8eac799
3 changed files with 48 additions and 4 deletions

View File

@ -36,9 +36,10 @@ typedef enum qc_init_kind
enum qc_option_t
{
QC_OPTION_STRING_ARG_AS_FIELD = (1 << 0), /*< Report a string argument to a function as a field. */
QC_OPTION_STRING_AS_FIELD = (1 << 1), /*< Report strings as fields. */
};
const uint32_t QC_OPTION_MASK = QC_OPTION_STRING_ARG_AS_FIELD;
const uint32_t QC_OPTION_MASK = QC_OPTION_STRING_ARG_AS_FIELD | QC_OPTION_STRING_AS_FIELD;
/**
* qc_sql_mode_t specifies what should be assumed of the statements

View File

@ -2268,7 +2268,6 @@ static void unalias_names(st_select_lex* select,
}
static void add_field_info(parsing_info_t* info,
st_select_lex* select,
const char* database,
const char* table,
const char* column,
@ -2276,8 +2275,6 @@ static void add_field_info(parsing_info_t* info,
{
mxb_assert(column);
unalias_names(select, database, table, &database, &table);
QC_FIELD_INFO item = {(char*)database, (char*)table, (char*)column};
size_t i;
@ -2353,6 +2350,20 @@ static void add_field_info(parsing_info_t* info,
}
}
static void add_field_info(parsing_info_t* info,
st_select_lex* select,
const char* database,
const char* table,
const char* column,
List<Item>* excludep)
{
mxb_assert(column);
unalias_names(select, database, table, &database, &table);
add_field_info(info, database, table, column, excludep);
}
static void add_function_field_usage(const char* database,
const char* table,
const char* column,
@ -3063,6 +3074,19 @@ static void update_field_infos(parsing_info_t* pi,
}
break;
case Item::STRING_ITEM:
if (this_thread.options & QC_OPTION_STRING_AS_FIELD)
{
String* s = item->val_str();
int len = s->length();
char tmp[len + 1];
memcpy(tmp, s->ptr(), len);
tmp[len] = 0;
add_field_info(pi, nullptr, nullptr, tmp, excludep);
}
break;
default:
break;
}

View File

@ -832,6 +832,14 @@ public:
update_field_infos_from_expr(pAliases, context, pExpr, pExclude);
break;
case TK_STRING: // select "a" ..., for @@sql_mode containing 'ANSI_QUOTES'
if (this_thread.options & QC_OPTION_STRING_AS_FIELD)
{
const char* zColumn = pExpr->u.zToken;
update_field_infos_from_column(pAliases, context, zColumn, pExclude);
}
break;
case TK_VARIABLE:
{
if (zToken[0] == '@')
@ -1184,6 +1192,17 @@ public:
}
}
void update_field_infos_from_column(QcAliases* pAliases,
uint32_t context,
const char* zColumn,
const ExprList* pExclude)
{
if (must_check_sequence_related_functions() || must_collect_fields())
{
update_field_info(pAliases, context, nullptr, nullptr, zColumn, pExclude);
}
}
void update_field_infos_from_exprlist(QcAliases* pAliases,
uint32_t context,
const ExprList* pEList,