我正在进行一些实验,通过从我指定的SQL关键字数组中进行检查,将字符串JERRY附加到sql语句中的每个sql关键字。我想从搜索变量中删除字符串JERRY,这样,如果我键入一个UNION(SELECT 1,fname,用户名,来自用户的密码);-在搜索输入字段中,打印的sql语句应如下所示;
SELECTJERRY * FROMJERRY购物WHEREJERRY标题LIKEJERRY'%a'UNION(SELECT 1,fname,用户名,密码FROM用户);-%'
目标是我不希望输入搜索变量中的SQL关键字具有字符串JERRY。
但是现在,这就是我得到的;
SELECTJERRY * FROMJERRY购物WHEREJERRY标题LIKEJERRY'%a'UNIONJERRY(SELECT 1,fname,username,FROM FROMJERRY用户的密码);-%'
我该如何实现?
$search = $_GET['search'];
if (empty($search)) {
echo "Please fill in the search bar";
exit();
}
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
$sql = "SELECT * FROM shopping WHERE title LIKE '%$search%'";
$splittedSql = explode(" ", $sql);
foreach ($splittedSql as $sl) {
if (in_array($sl, $keywords)) {
$newstatement = $sl . "JERRY" . ' ';
} else {
$newstatement = $sl . ' ';
}
echo $newstatement;
}
答案 0 :(得分:2)
由于$search
会受到explode
的影响,因此使用空白,我们可以通过用唯一字符替换空白来避免这种情况:
$search = str_replace(" ","uniquecharacters",$search);
,然后将这些唯一字符替换为空格
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
$search = str_replace(" ","uniquecharacters",$search);
$sql = "SELECT * FROM shopping WHERE title LIKE '%$search%'";
$splittedSql = explode(" ", $sql);
foreach ($splittedSql as $sl) {
if (in_array($sl, $keywords)) {
$newstatement = $sl . "JERRY" . ' ';
} else {
$newstatement = str_replace("uniquecharacters"," ",$sl);
$newstatement = $sl . ' ';
}
echo $newstatement;
}
答案 1 :(得分:2)
问题是您正在使用包含用户提供的$search
值的静态查询进行检查。要获得理想的结果,就需要限制关键字替换。
一种方法是首先检查用户为指定关键字提供的$search
值,如果存在,则更改您的静态查询。然后,您可以事后应用用户提供的$search
值,使用sprintf
可以轻松实现。
您可以使用捕获组preg_replace
和替换值()
,使用$1JERRY
一次全部应用关键字值,而不用展开查询。
您可以在模式上使用单词边界\b
来避免对sAND
,tON
,lORe
等单词的误报。
与stripos
和$search
regex修饰符相反,最后使用in_array()
检查/i
的值,将允许$keyword
匹配和替换不区分大小写。
$search = 'a\' UNION (SELECT 1, fname, username, password FROM users);--';
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
//sprintf requires textual percent signs to be escaped as %%
$query = 'SELECT * FROM shopping WHERE title LIKE \'%%%s%%\'';
foreach ($keywords as $w) {
if (false !== stripos($search, $w)) {
//found a keyword build the replacement capture groups.
$patterns = '/\b(' . implode('|', $keywords) . ')\b/i';
$query = preg_replace($patterns, '$1JERRY', $query);
break;
}
}
printf($query, $search);
迭代$keywords
的另一种方法是使用preg_match
来确定$search
的值是否包含关键字值。
$search = 'a\' UNION (SELECT 1, fname, username, password FROM users);--';
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
$patterns = '/\b(' . implode('|', $keywords) . ')\b/i';
$query = 'SELECT * FROM shopping WHERE title LIKE \'%%%s%%\'';
if (preg_match($patterns, $search)) {
$query = preg_replace($patterns, '$1JERRY', $query);
}
printf($query, $search);
两种方法的结果:
SELECTJERRY * FROMJERRY shopping WHEREJERRY title LIKEJERRY '%a' UNION (SELECT 1, fname, username, password FROM users);--%'