fix: resolve sql injection while building dynamic query for filters
This commit is contained in:
@@ -4,7 +4,8 @@ use rusqlite::*;
|
||||
pub fn run<'a>(filter: &'a Filter) -> Result<Vec<Box<dyn ToSql + 'a>>, FailedTo> {
|
||||
let mut params: Vec<Box<dyn ToSql>> = Vec::new();
|
||||
for condition in filter.conditions() {
|
||||
let (_, comparison, condition) = condition;
|
||||
let (name, comparison, condition) = condition;
|
||||
params.push(Box::new(name));
|
||||
match (comparison, condition) {
|
||||
// BOOL
|
||||
(Comparison::Equal, Condition::Bool(value)) => params.push(Box::new(value)),
|
||||
|
||||
@@ -1,83 +1,82 @@
|
||||
use crate::*;
|
||||
|
||||
// TODO: possible sql injection for attribute_id!!!
|
||||
|
||||
const BASE_SELECT: &str = r#"SELECT * FROM entity"#;
|
||||
const INNER_JOIN_FRAGMENT: &str = r#"
|
||||
INNER JOIN attribute as attribute_{index}
|
||||
ON entity.id = attribute_{index}.entity_id
|
||||
AND attribute_{index}.id = '{attribute_id}'
|
||||
AND attribute_{index}.id = ?{attribute_id_index}
|
||||
AND attribute_{index}.{field} {op} ?{index}
|
||||
"#;
|
||||
const WHERE: &str = r#" WHERE 1=1"#;
|
||||
|
||||
fn compose_fragment(name: &str, field: &str, op: &str, index: usize) -> String {
|
||||
fn compose_fragment(field: &str, op: &str, index: usize) -> String {
|
||||
let attribute_index = index * 2 - 1;
|
||||
let field_index = index * 2;
|
||||
INNER_JOIN_FRAGMENT
|
||||
.replace("{attribute_id}", name)
|
||||
.replace("{field}", field)
|
||||
.replace("{op}", op)
|
||||
.replace("{index}", &index.to_string())
|
||||
.replace("{attribute_id_index}", &attribute_index.to_string())
|
||||
.replace("{index}", &field_index.to_string())
|
||||
}
|
||||
|
||||
fn from_condition(
|
||||
i: usize,
|
||||
name: &str,
|
||||
comparison: &Comparison,
|
||||
condition: &Condition,
|
||||
) -> Result<String, FailedTo> {
|
||||
let fragment = match (comparison, condition) {
|
||||
// BOOL
|
||||
(Comparison::Equal, Condition::Bool(_)) => compose_fragment(name, "value_bool", "=", i),
|
||||
(Comparison::Equal, Condition::Bool(_)) => compose_fragment("value_bool", "=", i),
|
||||
(_, Condition::Bool(_)) => return Err(FailedTo::ComposeFilter),
|
||||
// SIGNED INT
|
||||
(Comparison::Equal, Condition::SignedInt(_)) => compose_fragment(name, "value_int", "=", i),
|
||||
(Comparison::Equal, Condition::SignedInt(_)) => compose_fragment("value_int", "=", i),
|
||||
(Comparison::Greater, Condition::SignedInt(_)) => {
|
||||
compose_fragment(name, "value_int", ">", i)
|
||||
compose_fragment("value_int", ">", i)
|
||||
}
|
||||
(Comparison::Lesser, Condition::SignedInt(_)) => {
|
||||
compose_fragment(name, "value_int", "<", i)
|
||||
compose_fragment("value_int", "<", i)
|
||||
}
|
||||
(Comparison::GreaterOrEqual, Condition::SignedInt(_)) => {
|
||||
compose_fragment(name, "value_int", ">=", i)
|
||||
compose_fragment("value_int", ">=", i)
|
||||
}
|
||||
(Comparison::LesserOrEqual, Condition::SignedInt(_)) => {
|
||||
compose_fragment(name, "value_int", "<=", i)
|
||||
compose_fragment("value_int", "<=", i)
|
||||
}
|
||||
(_, Condition::SignedInt(_)) => return Err(FailedTo::ComposeFilter),
|
||||
// UNSIGNED INT
|
||||
(Comparison::Equal, Condition::UnsignedInt(_)) => {
|
||||
compose_fragment(name, "value_uint", "=", i)
|
||||
compose_fragment("value_uint", "=", i)
|
||||
}
|
||||
(Comparison::Greater, Condition::UnsignedInt(_)) => {
|
||||
compose_fragment(name, "value_uint", ">", i)
|
||||
compose_fragment("value_uint", ">", i)
|
||||
}
|
||||
(Comparison::Lesser, Condition::UnsignedInt(_)) => {
|
||||
compose_fragment(name, "value_uint", "<", i)
|
||||
compose_fragment("value_uint", "<", i)
|
||||
}
|
||||
(Comparison::GreaterOrEqual, Condition::UnsignedInt(_)) => {
|
||||
compose_fragment(name, "value_uint", ">=", i)
|
||||
compose_fragment("value_uint", ">=", i)
|
||||
}
|
||||
(Comparison::LesserOrEqual, Condition::UnsignedInt(_)) => {
|
||||
compose_fragment(name, "value_uint", "<=", i)
|
||||
compose_fragment("value_uint", "<=", i)
|
||||
}
|
||||
(_, Condition::UnsignedInt(_)) => return Err(FailedTo::ComposeFilter),
|
||||
// REAL
|
||||
(Comparison::Equal, Condition::Real(_)) => compose_fragment(name, "value_real", "=", i),
|
||||
(Comparison::Greater, Condition::Real(_)) => compose_fragment(name, "value_real", ">", i),
|
||||
(Comparison::Lesser, Condition::Real(_)) => compose_fragment(name, "value_real", "<", i),
|
||||
(Comparison::Equal, Condition::Real(_)) => compose_fragment("value_real", "=", i),
|
||||
(Comparison::Greater, Condition::Real(_)) => compose_fragment("value_real", ">", i),
|
||||
(Comparison::Lesser, Condition::Real(_)) => compose_fragment("value_real", "<", i),
|
||||
(Comparison::GreaterOrEqual, Condition::Real(_)) => {
|
||||
compose_fragment(name, "value_real", ">=", i)
|
||||
compose_fragment("value_real", ">=", i)
|
||||
}
|
||||
(Comparison::LesserOrEqual, Condition::Real(_)) => {
|
||||
compose_fragment(name, "value_real", "<=", i)
|
||||
compose_fragment("value_real", "<=", i)
|
||||
}
|
||||
(_, Condition::Real(_)) => return Err(FailedTo::ComposeFilter),
|
||||
// TEXT
|
||||
(Comparison::IsExactly, Condition::Text(_)) => compose_fragment(name, "value_text", "=", i),
|
||||
(Comparison::IsExactly, Condition::Text(_)) => compose_fragment("value_text", "=", i),
|
||||
(
|
||||
Comparison::StartsWith | Comparison::EndsWith | Comparison::Contains,
|
||||
Condition::Text(_),
|
||||
) => compose_fragment(name, "value_text", "LIKE", i),
|
||||
) => compose_fragment("value_text", "LIKE", i),
|
||||
(_, Condition::Text(_)) => return Err(FailedTo::ComposeFilter),
|
||||
};
|
||||
Ok(fragment)
|
||||
@@ -88,9 +87,9 @@ pub fn run(filter: &Filter) -> Result<String, FailedTo> {
|
||||
let mut statement = String::from(BASE_SELECT);
|
||||
let mut idx = 0;
|
||||
// for each condition add an inner join fragment
|
||||
for (i, (name, comparison, condition)) in filter.conditions().enumerate() {
|
||||
for (i, (_, comparison, condition)) in filter.conditions().enumerate() {
|
||||
idx = i + 1;
|
||||
let fragment = from_condition(idx, name, comparison, condition)?;
|
||||
let fragment = from_condition(idx, comparison, condition)?;
|
||||
statement.push_str(&fragment);
|
||||
}
|
||||
// add a neutral where condition
|
||||
|
||||
Reference in New Issue
Block a user