Use bound parameters for every query that takes user data.

The queue image query took $id without quotes or a check, which allowed
SQL injection.
This commit is contained in:
tim
2026-09-25 21:29:09 +02:00
parent cda0602c95
commit c85f54116c
7 changed files with 70 additions and 89 deletions
+2 -2
View File
@@ -41,8 +41,8 @@ function display_img($id) {
$hidden = $is_admin ? "" : " AND hidden IS NOT TRUE"; $hidden = $is_admin ? "" : " AND hidden IS NOT TRUE";
} }
$query = "SELECT img, mime FROM $table WHERE 1 AND ID = ".$db->real_escape_string($id).$hidden." LIMIT 0, 1"; $query = "SELECT img, mime FROM $table WHERE 1 AND ID = ?".$hidden." LIMIT 0, 1";
$result = $db->query($query)or die("Query failed : ".$db->error); $result = $db->execute_query($query, array((int)$id)) or die("Query failed : ".$db->error);
$row = $result->fetch_assoc(); $row = $result->fetch_assoc();
if ($row) { if ($row) {
+14 -19
View File
@@ -105,28 +105,25 @@ function get_count() {
$search = get_search_args(); $search = get_search_args();
$queue = get_queue(); $queue = get_queue();
$table = which_table(); $table = which_table();
$params = array();
// if search= is defined, search.... // if search= is defined, search....
if ($search) { if ($search) {
$count_query = "SELECT COUNT(*) FROM $table WHERE". $count_query = "SELECT COUNT(*) FROM $table WHERE".
" ( title LIKE '%".$search."%'". " (title LIKE ? OR author LIKE ? OR date LIKE ? OR story LIKE ?)";
" OR author LIKE '%".$search."%'". $params = array_fill(0, 4, "%$search%");
" OR date LIKE '%".$search."%'".
" OR story LIKE '%".$search."%'".
" )";
// Otherwise, fall back to default view // Otherwise, fall back to default view
} else { } else {
$count_query = "SELECT COUNT(*) FROM ".$table." WHERE 1"; $count_query = "SELECT COUNT(*) FROM ".$table." WHERE 1";
} }
if (!$is_admin) if (!$is_admin)
$count_query .= " AND hidden IS NOT TRUE"; $count_query .= " AND hidden IS NOT TRUE";
$count_query .= " ;";
//echo $count_query." <br />"; //echo $count_query." <br />";
$row_count = NULL; $row_count = NULL;
echo $db->info; echo $db->info;
if ($count_query) { if ($count_query) {
if ($result = $db->query($count_query)) { if ($result = $db->execute_query($count_query, $params)) {
$row_count = $result->fetch_row(); $row_count = $result->fetch_row();
$result->close(); $result->close();
} else { } else {
@@ -149,35 +146,34 @@ function get_query($id = NULL) {
$queue = get_queue(); $queue = get_queue();
$table = which_table(); $table = which_table();
$results = array(); $results = array();
$params = array();
$limit = " LIMIT ".(int)$start." , ".(int)$show;
// If id= is defined, show the corresponding application only // If id= is defined, show the corresponding application only
if (is_numeric($id)) { if (is_numeric($id)) {
if (!$is_admin) if (!$is_admin)
$query = "SELECT * FROM $table WHERE 1 AND hidden IS NOT TRUE AND id = ".$id." LIMIT 0, 1"; $query = "SELECT * FROM $table WHERE 1 AND hidden IS NOT TRUE AND id = ".(int)$id." LIMIT 0, 1";
else else
$query = "SELECT * FROM $table WHERE 1 AND id = ".$id." LIMIT 0, 1"; $query = "SELECT * FROM $table WHERE 1 AND id = ".(int)$id." LIMIT 0, 1";
// if search= is defined, search.... // if search= is defined, search....
} else if ($search) { } else if ($search) {
$query = "SELECT * FROM $table WHERE". $query = "SELECT * FROM $table WHERE".
" ( title LIKE '%".$search."%'". " (title LIKE ? OR author LIKE ? OR date LIKE ? OR story LIKE ?)";
" OR author LIKE '%".$search."%'". $params = array_fill(0, 4, "%$search%");
" OR date LIKE '%".$search."%'".
" OR story LIKE '%".$search."%'".
" )";
if (!$is_admin) if (!$is_admin)
$query .= " AND hidden IS NOT TRUE"; $query .= " AND hidden IS NOT TRUE";
$query .= " ORDER BY ".$sort." " .$order." LIMIT " .$start." , ".$show." ;"; $query .= " ORDER BY ".$sort." ".$order.$limit;
// Otherwise, fall back to default view // Otherwise, fall back to default view
} else { } else {
$query = "SELECT * FROM ".$table." WHERE 1"; $query = "SELECT * FROM ".$table." WHERE 1";
if (!$is_admin) if (!$is_admin)
$query .= " AND hidden IS NOT TRUE"; $query .= " AND hidden IS NOT TRUE";
$query .= " ORDER BY ".$sort." " .$order." LIMIT " .$start." , ".$show." ;"; $query .= " ORDER BY ".$sort." ".$order.$limit;
} }
//echo $query; //echo $query;
if ($result = $db->query($query)) { if ($result = $db->execute_query($query, $params)) {
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
$row['queue_url'] = $queue ? 1 : 0; $row['queue_url'] = $queue ? 1 : 0;
$results[] = $row; $results[] = $row;
@@ -256,8 +252,7 @@ function get_id() {
function get_search_args() { function get_search_args() {
global $db; global $db;
if (isset($_GET['search']) && is_string($_GET['search'])) { if (isset($_GET['search']) && is_string($_GET['search'])) {
$search = $db->real_escape_string($_GET['search']); return $_GET['search'];
return $search;
} }
} }
+3 -3
View File
@@ -33,7 +33,7 @@ function sort_options($link) {
} else { } else {
$href = '<a href="'.$link.'?sort='.$sort_key.'&amp;order='.$order_key; $href = '<a href="'.$link.'?sort='.$sort_key.'&amp;order='.$order_key;
if (isset($_GET['queue'])) $href .= '&amp;queue='.$_GET['queue']; if (isset($_GET['queue'])) $href .= '&amp;queue='.$_GET['queue'];
if (isset($_GET['search'])) $href .= '&amp;search='.$search; if (isset($_GET['search'])) $href .= '&amp;search='.urlencode((string)$search);
if (isset($_GET['start'])) $href .= '&amp;start='.$start; if (isset($_GET['start'])) $href .= '&amp;start='.$start;
if (isset($_GET['show'])) $href .= '&amp;show='.$show; if (isset($_GET['show'])) $href .= '&amp;show='.$show;
$href .= '">'.$display.'</a>'; $href .= '">'.$display.'</a>';
@@ -71,7 +71,7 @@ function get_pager() {
if ($start > 0) { if ($start > 0) {
$string .= "\n".'<a href="'.$link.'?start='.$next; $string .= "\n".'<a href="'.$link.'?start='.$next;
if (isset($_GET['queue'])) $string .= '&amp;queue='.$queue_url; if (isset($_GET['queue'])) $string .= '&amp;queue='.$queue_url;
if (isset($_GET['search'])) $string .= '&amp;search='.$search; if (isset($_GET['search'])) $string .= '&amp;search='.urlencode((string)$search);
if (isset($_GET['show'])) $string .= '&amp;show='.$show; if (isset($_GET['show'])) $string .= '&amp;show='.$show;
if (isset($_GET['sort'])) $string .= '&amp;sort='.$sort; if (isset($_GET['sort'])) $string .= '&amp;sort='.$sort;
if (isset($_GET['order'])) $string .= '&amp;order='.$order; if (isset($_GET['order'])) $string .= '&amp;order='.$order;
@@ -85,7 +85,7 @@ function get_pager() {
if ($prev < get_count()) { if ($prev < get_count()) {
$string .= "\n".'<a href="'.$link.'?start='.$prev; $string .= "\n".'<a href="'.$link.'?start='.$prev;
if (isset($_GET['queue'])) $string .= '&amp;queue='.$queue_url; if (isset($_GET['queue'])) $string .= '&amp;queue='.$queue_url;
if (isset($_GET['search'])) $string .= '&amp;search='.$search; if (isset($_GET['search'])) $string .= '&amp;search='.urlencode((string)$search);
if (isset($_GET['show'])) $string .= '&amp;show='.$show; if (isset($_GET['show'])) $string .= '&amp;show='.$show;
if (isset($_GET['sort'])) $string .= '&amp;sort='.$sort; if (isset($_GET['sort'])) $string .= '&amp;sort='.$sort;
if (isset($_GET['order'])) $string .= '&amp;order='.$order; if (isset($_GET['order'])) $string .= '&amp;order='.$order;
+5 -8
View File
@@ -12,14 +12,11 @@ if (!isset($_SESSION['editor'])) {
open_db('open'); open_db('open');
$table = "editors"; $table = "editors";
$username = $db->real_escape_string($_POST['username'] ?? ''); $username = (string)($_POST['username'] ?? '');
$password = $db->real_escape_string(password_hash($_POST['password'] ?? '', PASSWORD_DEFAULT)); $password = password_hash((string)($_POST['password'] ?? ''), PASSWORD_DEFAULT);
$email = $db->real_escape_string($_POST['email'] ?? ''); $email = (string)($_POST['email'] ?? '');
$query = "INSERT INTO $table SET". $query = "INSERT INTO $table SET `username` = ?, `password` = ?, `email` = ?";
"`username` = '".$username."', ". if ($result = $db->execute_query($query, array($username, $password, $email))) {
"`password` = '".$password."', ".
"`email` = '".$email."'; ";
if ($result = $db->query($query)) {
$added = TRUE; $added = TRUE;
$is_admin = TRUE; $is_admin = TRUE;
} }
+3 -5
View File
@@ -14,11 +14,9 @@ if (isset($_SESSION['editor'])) {
$table = "editors"; $table = "editors";
open_db('open'); open_db('open');
$username = $db->real_escape_string($_POST['username'] ?? ''); $username = (string)($_POST['username'] ?? '');
$query = "SELECT * FROM $table WHERE ". $query = "SELECT * FROM $table WHERE username LIKE ? LIMIT 1";
"username LIKE '".$username."' ". $getid = $db->execute_query($query, array($username)) or die("Query failed: ".$db->error);
"LIMIT 1;";
$getid = $db->query($query) or die("Query failed: ".$db->error);
$row = $getid->fetch_assoc(); $row = $getid->fetch_assoc();
$stored_password = ''; $stored_password = '';
+32 -32
View File
@@ -22,6 +22,7 @@ function save_data($id = NULL) {
$comments = NULL; $comments = NULL;
$editor = 'original author'; $editor = 'original author';
} }
$id = is_numeric($id) ? (int)$id : NULL;
$queue = get_queue(); $queue = get_queue();
// Are we posting a story from the queue? // Are we posting a story from the queue?
@@ -37,10 +38,9 @@ function save_data($id = NULL) {
if (!$date) if (!$date)
$date = gmdate("Y-m-d H:i:s"); $date = gmdate("Y-m-d H:i:s");
// Verify image // Verify image
if ($move && isset($uploaded) && $uploaded === $id) { if ($move && isset($id) && isset($uploaded) && $uploaded === (string)$id) {
// Special case - transfer image from queue table // Special case - transfer image from queue table
$query = "SELECT img, mime FROM queue WHERE id = $id;"; if ($getimg = $db->execute_query("SELECT img, mime FROM queue WHERE id = ?", array($id))) {
if ($getimg = $db->query($query)) {
$row = $getimg->fetch_assoc(); $row = $getimg->fetch_assoc();
$img = $row['img']; $img = $row['img'];
$mime = $row['mime']; $mime = $row['mime'];
@@ -56,42 +56,42 @@ function save_data($id = NULL) {
} }
} }
if (is_numeric($id) && !$move) // Column => value; the values are bound as query parameters
$query = "UPDATE $table SET"; $fields = array(
else 'title' => $title,
$query = "INSERT INTO $table SET"; 'author' => $author,
$query .= " `title` = '".$db->real_escape_string($title)."'" 'email' => $email,
.", `author` = '".$db->real_escape_string($author)."'" 'editor' => $editor,
.", `email` = '".$db->real_escape_string($email)."'" );
.", `editor` = '".$db->real_escape_string($editor)."'";
if ($is_admin && isset($comments)) { if ($is_admin && isset($comments)) {
$query .= ", `comments` = '".$db->real_escape_string($comments)."'"; $fields['comments'] = $comments;
}
if ($hidden) {
$query .= ", `hidden` = TRUE";
} else {
$query .= ", `hidden` = FALSE";
} }
$fields['hidden'] = $hidden ? 1 : 0;
if ($remove_img && $story) { if ($remove_img && $story) {
$query .= ", `story` = '".$db->real_escape_string($story)."'"; $fields['story'] = $story;
$query .= ", `mime` = NULL"; $fields['mime'] = NULL;
$query .= ", `img` = NULL"; $fields['img'] = NULL;
} else if (isset($img)) { } else if (isset($img)) {
$query .= ", `mime` = '".$db->real_escape_string($mime)."'"; $fields['mime'] = $mime;
$query .= ", `img` = '".$db->real_escape_string($img)."'"; $fields['img'] = $img;
$query .= ", `story` = ''"; $fields['story'] = '';
} else { } else {
$query .= ", `story` = '".$db->real_escape_string($story)."'"; $fields['story'] = $story;
} }
if (!is_numeric($id) || $move) if (!is_numeric($id) || $move)
$query .= ", `date` = '".$db->real_escape_string($date)."'"; $fields['date'] = $date;
if (is_numeric($id) && !$move)
$query .= " WHERE `id` = '".$id."' LIMIT 1;"; $set = implode(', ', array_map(function ($column) { return "`$column` = ?"; }, array_keys($fields)));
else $params = array_values($fields);
$query .= ";"; if (is_numeric($id) && !$move) {
$query = "UPDATE $table SET $set WHERE `id` = ? LIMIT 1";
$params[] = $id;
} else {
$query = "INSERT INTO $table SET $set";
}
//echo $query; //echo $query;
$result = $db->query($query) or die("Query failed: ".$db->error); $result = $db->execute_query($query, $params) or die("Query failed: ".$db->error);
if (is_numeric($id) && $move) { if (is_numeric($id) && $move) {
$queue_id = $id; $queue_id = $id;
@@ -134,9 +134,9 @@ function delete_story($id, $move = FALSE) {
$queue = get_queue(); $queue = get_queue();
$table = which_table($move, 'delete'); $table = which_table($move, 'delete');
$query = "DELETE FROM $table WHERE `id` = '".$id."' LIMIT 1;"; $query = "DELETE FROM $table WHERE `id` = ? LIMIT 1";
//echo $query; //echo $query;
$result = $db->query($query)or die("Query failed : ".$db->error); $result = $db->execute_query($query, array((int)$id)) or die("Query failed : ".$db->error);
$message = ''; $message = '';
if (!$move) if (!$move)
+9 -18
View File
@@ -32,15 +32,11 @@ function check_persistent_login() {
$table = "persistent_sessions"; $table = "persistent_sessions";
open_db('open'); open_db('open');
$cookie_data = $db->real_escape_string($_COOKIE['PersistentAuth']); $cookie_data = (string)$_COOKIE['PersistentAuth'];
list($username, $key) = explode("|", $cookie_data, 2) + array('', ''); list($username, $key) = explode("|", $cookie_data, 2) + array('', '');
$username = $db->real_escape_string($username);
$key = $db->real_escape_string($key);
$query = "SELECT * FROM $table WHERE ". $query = "SELECT * FROM $table WHERE username LIKE ? LIMIT 1";
"username LIKE '".$username."' ". $getid = $db->execute_query($query, array($username)) or die("Query failed: ".$db->error);
"LIMIT 1;";
$getid = $db->query($query) or die("Query failed: ".$db->error);
$row = $getid->fetch_assoc(); $row = $getid->fetch_assoc();
open_db('close'); open_db('close');
@@ -67,12 +63,11 @@ function create_persistent_login($username) {
$table = "persistent_sessions"; $table = "persistent_sessions";
open_db('open'); open_db('open');
$username = $db->real_escape_string($username);
$key = bin2hex(random_bytes(100)); $key = bin2hex(random_bytes(100));
// Add session key to database // Add session key to database
$query = "INSERT INTO $table " . "(username, session) VALUES ('" . $username."', '" . $key . "');"; $query = "INSERT INTO $table (username, session) VALUES (?, ?)";
$db->query($query) or die("Query failed: ".$db->error); $db->execute_query($query, array($username, $key)) or die("Query failed: ".$db->error);
open_db('close'); open_db('close');
// Create cookie with key // Create cookie with key
@@ -86,16 +81,12 @@ function delete_persistent_login() {
$table = "persistent_sessions"; $table = "persistent_sessions";
open_db('open'); open_db('open');
$cookie_data = $db->real_escape_string($_COOKIE['PersistentAuth'] ?? ''); $cookie_data = (string)($_COOKIE['PersistentAuth'] ?? '');
list($username, $key) = explode("|", $cookie_data, 2) + array('', ''); list($username, $key) = explode("|", $cookie_data, 2) + array('', '');
$username = $db->real_escape_string($username);
$key = $db->real_escape_string($key);
// Add session key to database // Remove this session key from the database
$query = "DELETE FROM $table " . $query = "DELETE FROM $table WHERE username LIKE ? AND session LIKE ?";
" WHERE username LIKE '" . $username . "'" . $db->execute_query($query, array($username, $key)) or die("Query failed: ".$db->error);
" AND session LIKE '" . $key . "';";
$db->query($query) or die("Query failed: ".$db->error);
// Reap old sessions // Reap old sessions
$query = "DELETE FROM $table " . $query = "DELETE FROM $table " .