Skip to content

Commit 6df73cc

Browse files
committed
* security fix: replace string filtering by parameterization in almost all queries
1 parent a56ff90 commit 6df73cc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1969
-905
lines changed

Diff for: lib/core/core.php

+15-8
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,22 @@ function core_load_function($fid)
184184
break;
185185

186186
default:
187+
$query_params = NULL;
187188
if(is_numeric($fid))
189+
{
188190
$where = 'id = '.intval($fid);
191+
}
189192
else
190-
$where = 'codename = '.protect($fid);
193+
{
194+
$where = 'codename = :codename';
195+
$query_params = array(':codename' => $fid);
196+
}
191197

192-
$DB->query('SELECT *
193-
FROM nv_functions
194-
WHERE '.$where.'
195-
AND enabled = 1');
198+
$DB->query(
199+
'SELECT * FROM nv_functions WHERE '.$where.' AND enabled = 1',
200+
'object',
201+
$query_params
202+
);
196203

197204
$func = $DB->first();
198205

@@ -1179,9 +1186,9 @@ function navigate_compose_email($data, $style=array())
11791186
$title_color = '#595959';
11801187
$text_color = '#595959';
11811188

1182-
$background_color_db = $DB->query_single('value', 'nv_permissions', 'name = ' . protect("nvweb.comments.background_color") . ' AND website = ' . protect($website->id), 'id DESC');
1183-
$text_color_db = $DB->query_single('value', 'nv_permissions', 'name = ' . protect("nvweb.comments.text_color") . ' AND website = ' . protect($website->id), 'id DESC');
1184-
$title_color_db = $DB->query_single('value', 'nv_permissions', 'name = ' . protect("nvweb.comments.titles_color") . ' AND website = ' . protect($website->id), 'id DESC');
1189+
$background_color_db = $DB->query_single('value', 'nv_permissions', 'name = "nvweb.comments.background_color" AND website = ' . intval($website->id), 'id DESC');
1190+
$text_color_db = $DB->query_single('value', 'nv_permissions', 'name = "nvweb.comments.text_color" AND website = ' . intval($website->id), 'id DESC');
1191+
$title_color_db = $DB->query_single('value', 'nv_permissions', 'name = "nvweb.comments.titles_color" AND website = ' . intval($website->id), 'id DESC');
11851192

11861193
if (!empty($background_color_db))
11871194
$background_color = str_replace('"', '', $background_color_db);

Diff for: lib/core/database.class.php

+44-9
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,11 @@ public function reconnect()
9292
* in the current active language.
9393
*
9494
* @param string $sql The complete SQL query
95-
* @param string $fetch_mode How to retrieve the data: "object" or "array"
95+
* @param string $fetch_mode How to retrieve the data: "object" or "array"
96+
* @param array $parameters SQL query parameters associative array
9697
* @return boolean True if the query was executed without errors
9798
*/
98-
public function query($sql, $fetch_mode='object')
99+
public function query($sql, $fetch_mode='object', $parameters=array())
99100
{
100101
$this->lastError = '';
101102
$this->lastResult = '';
@@ -114,7 +115,15 @@ public function query($sql, $fetch_mode='object')
114115

115116
try
116117
{
117-
$statement = $this->db->query($sql);
118+
if(empty($parameters))
119+
{
120+
$statement = $this->db->query($sql);
121+
}
122+
else
123+
{
124+
$statement = $this->db->prepare($sql);
125+
$statement->execute($parameters);
126+
}
118127
$this->queries_count++;
119128

120129
// avoid firing a fatal error exception when the result is NULL
@@ -146,17 +155,28 @@ public function query($sql, $fetch_mode='object')
146155
* @param string $table Table name to get the data from
147156
* @param string $where SQL conditions in the WHERE clause
148157
* @param string $order SQL order conditions in the ORDER BY clause
158+
* @param array $parameters SQL query parameters associative array
149159
* @return string|integer Value of the first column of the first row of the resultset
150160
*/
151-
public function query_single($column, $table, $where = '1=1', $order = '')
161+
public function query_single($column, $table, $where = '1=1', $order = '', $parameters=array())
152162
{
153163
$rs = null;
154164
if(!empty($order))
155165
$order = ' ORDER BY '.$order;
156166

167+
$sql = 'SELECT ' . $column . ' FROM ' . $table . ' WHERE ' . $where . $order . ' LIMIT 1';
168+
157169
try
158170
{
159-
$stm = $this->db->query('SELECT ' . $column . ' FROM ' . $table . ' WHERE ' . $where . $order . ' LIMIT 1');
171+
if(empty($parameters))
172+
{
173+
$stm = $this->db->query($sql);
174+
}
175+
else
176+
{
177+
$stm = $this->db->prepare($sql);
178+
$stm->execute($parameters);
179+
}
160180
$this->queries_count++;
161181
$stm->setFetchMode(PDO::FETCH_NUM);
162182
$rs = $stm->fetchAll();
@@ -168,8 +188,14 @@ public function query_single($column, $table, $where = '1=1', $order = '')
168188
return NULL;
169189
}
170190

171-
if(empty($rs)) return NULL;
172-
else return $rs[0][0];
191+
if(empty($rs))
192+
{
193+
return NULL;
194+
}
195+
else
196+
{
197+
return $rs[0][0];
198+
}
173199
}
174200

175201

@@ -184,7 +210,7 @@ public function query_single($column, $table, $where = '1=1', $order = '')
184210
* @param integer $max How many rows will be returned of the resultset (after applying offset)
185211
* @return boolean True if the query could be executed without errors
186212
*/
187-
public function queryLimit($cols, $table, $where="1=1", $order="", $offset=0, $max=100)
213+
public function queryLimit($cols, $table, $where="1=1", $order="", $offset=0, $max=100, $parameters=array())
188214
{
189215
$this->lastError = '';
190216
$this->lastResult = '';
@@ -199,7 +225,16 @@ public function queryLimit($cols, $table, $where="1=1", $order="", $offset=0, $m
199225
LIMIT '.$max.'
200226
OFFSET '.$offset;
201227

202-
$statement = $this->db->query($sql);
228+
if(empty($parameters))
229+
{
230+
$statement = $this->db->query($sql);
231+
}
232+
else
233+
{
234+
$statement = $this->db->prepare($sql);
235+
$statement->execute($parameters);
236+
}
237+
203238
$this->queries_count++;
204239
$statement->setFetchMode($fetch);
205240
$this->lastResult = $statement->fetchAll();

Diff for: lib/core/language.class.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ public function load($code='en')
1818
{
1919
global $DB;
2020

21-
$DB->query('SELECT * FROM nv_languages WHERE code = '.protect($code));
21+
$DB->query(
22+
'SELECT * FROM nv_languages WHERE code = :code',
23+
'object',
24+
array(':code' => $code)
25+
);
2226
$data = $DB->first();
2327

2428
if(empty($data->id))

Diff for: lib/core/user.class.php

+16-7
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@ public function authenticate($user, $pass)
5151
$user = mb_strtolower($user);
5252

5353
$A1 = md5($user.':'.APP_REALM.':'.$pass);
54-
55-
if($DB->query('SELECT *
56-
FROM nv_users
57-
WHERE LOWER(username) = '.protect($user)))
54+
$found = $DB->query(
55+
'SELECT * FROM nv_users WHERE LOWER(username) = :username',
56+
'object',
57+
array(':username' => $user)
58+
);
59+
60+
if(!empty($found))
5861
{
5962
$data = $DB->result();
6063

@@ -336,9 +339,15 @@ public function setting($name, $value=NULL)
336339
'SELECT *
337340
FROM nv_settings
338341
WHERE type = "user" AND
339-
user = '.protect($this->id).' AND
340-
website = '.protect($website->id).' AND
341-
name = '.protect($name)
342+
user = :user AND
343+
website = :website AND
344+
name = :name',
345+
'object',
346+
array(
347+
':user' => $this->id,
348+
':website' => $website->id,
349+
':name' => $name
350+
)
342351
);
343352

344353
$setting = $DB->first();

Diff for: lib/layout/layout.class.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,13 @@ public function navigate_session()
563563
if(empty($fid))
564564
$fid = 'dashboard';
565565

566-
$user_profile_name = $DB->query_single('name', 'nv_profiles', 'id='.protect($user->profile));
566+
$user_profile_name = $DB->query_single(
567+
'name',
568+
'nv_profiles',
569+
'id = :user_profile',
570+
'NULL',
571+
array(':user_profile' => $user->profile)
572+
);
567573

568574
$this->add_content(
569575
'<div class="navigate-help">'.
@@ -753,6 +759,7 @@ public function navigate_additional_scripts()
753759
92: "'.t(92, 'Close').'",
754760
141: "'.t(141, 'Folder').'",
755761
152: "'.t(152, 'Continue').'",
762+
159: "'.t(159, 'Name').'",
756763
170: "'.t(170, 'Edit').'",
757764
171: "'.t(171, 'Order').'",
758765
185: "'.t(185, 'Searching elements').'",

Diff for: lib/layout/navibars.class.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function add_actions($actions)
3333
{
3434
// we are displaying a list
3535
$actions[$search_form_pos][] = '<img onclick="$(this).next().triggerHandler(\'submit\');" height="16" align="absmiddle" width="16" src="img/icons/silk/zoom.png"></a>';
36-
$actions[$search_form_pos][] = '<form method="GET" action="#" onsubmit=" navitable_quicksearch($(\'#navigate-quicksearch\').val()); return false;">';
36+
$actions[$search_form_pos][] = '<form method="GET" action="#" onsubmit=" if(typeof(navitable_quicksearch)==\'function\') { navitable_quicksearch($(\'#navigate-quicksearch\').val()); return false; } else return true;">';
3737
}
3838
else // other screen than a list
3939
{

Diff for: lib/layout/naviforms.class.php

+1
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ public function autocomplete($name, $value="", $source, $callback='""', $width="
263263
$("a[data-action=create_custom_value][data-uid='.$uid.']").on("click", function()
264264
{
265265
var text = prompt(navigate_t(159, "Name"));
266+
if(!text) return;
266267
text = text.trim();
267268
if(text != "")
268269
{

Diff for: lib/packages/about/about.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function about_layout()
5454
$navibars->add_tab_content_row(
5555
array(
5656
'<label>'.t(218, 'Third party libraries').'</label>',
57-
'<a href="http://www.tinymce.com" target="_blank">TinyMCE 4.8.0c</a><br />'
57+
'<a href="http://www.tinymce.com" target="_blank">TinyMCE 4.8.3</a><br />'
5858
)
5959
);
6060

Diff for: lib/packages/blocks/block.class.php

+14-6
Original file line numberDiff line numberDiff line change
@@ -610,8 +610,12 @@ public static function types($orderby='id', $asc='asc')
610610
$theme_blocks[$b]['count'] = $DB->query_single(
611611
'COUNT(*) AS total',
612612
'nv_blocks',
613-
' website = '.$website->id.' AND
614-
type = '.protect($theme_blocks[$b]['id'])
613+
' website = :wid AND type = :type',
614+
NULL,
615+
array(
616+
':wid' => $website->id,
617+
':type' => $theme_blocks[$b]['id']
618+
)
615619
);
616620
}
617621
}
@@ -671,11 +675,15 @@ public static function types_update($array)
671675
sort($array);
672676

673677
$array = serialize($array);
674-
678+
675679
$ok = $DB->execute('
676680
UPDATE nv_websites
677-
SET block_types = '.protect($array).'
678-
WHERE id = '.$website->id
681+
SET block_types = :block_types
682+
WHERE id = :wid',
683+
array(
684+
':wid' => $website->id,
685+
':block_types' => $array
686+
)
679687
);
680688

681689
if(!$ok)
@@ -939,7 +947,7 @@ public function backup($type='json')
939947
$DB->query('
940948
SELECT *
941949
FROM nv_blocks
942-
WHERE website = '.protect($website->id),
950+
WHERE website = '.intval($website->id),
943951
'object'
944952
);
945953

Diff for: lib/packages/blocks/block_group.class.php

+13-5
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,17 @@ public function load_by_code($code)
2727
global $DB;
2828
global $website;
2929

30-
if($DB->query('SELECT * FROM nv_block_groups
31-
WHERE code = '.protect($code).'
32-
AND website = '.$website->id))
30+
$found = $DB->query(
31+
'SELECT * FROM nv_block_groups
32+
WHERE code = :code
33+
AND website = '.$website->id,
34+
'object',
35+
array(
36+
':code' => $code
37+
)
38+
);
39+
40+
if($found)
3341
{
3442
$data = $DB->result();
3543
$this->load_from_resultset($data);
@@ -198,7 +206,7 @@ public static function paginated_list($offset, $limit, $order_by_field, $order_b
198206
$DB->queryLimit(
199207
'*',
200208
'nv_block_groups',
201-
'website = '.protect($website->id),
209+
'website = '.intval($website->id),
202210
$order_by_field.' '.$order_by_ascdesc,
203211
$offset,
204212
$limit
@@ -235,7 +243,7 @@ public function backup($type='json')
235243
$DB->query('
236244
SELECT *
237245
FROM nv_block_groups
238-
WHERE website = '.protect($website->id),
246+
WHERE website = '.intval($website->id),
239247
'object'
240248
);
241249
$out = $DB->result();

Diff for: lib/packages/blocks/blocks.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,17 @@ function run()
274274

275275
case 'path':
276276
case 5: // search an existing path
277-
$DB->query('SELECT path as id, path as label, path as value
277+
$DB->query(
278+
'SELECT path as id, path as label, path as value
278279
FROM nv_paths
279-
WHERE path LIKE '.protect('%'.$_REQUEST['term'].'%').'
280+
WHERE path LIKE :path
280281
AND website = '.$website->id.'
281282
ORDER BY path ASC
282283
LIMIT 10',
283-
'array');
284+
'array',
285+
array(
286+
':path' => '%' . $_REQUEST['term'] . '%'
287+
));
284288

285289
echo json_encode($DB->result());
286290

Diff for: lib/packages/brands/brand.class.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public function backup($type='json')
134134
global $DB;
135135
global $website;
136136

137-
$DB->query('SELECT * FROM nv_brands WHERE website = '.protect($website->id), 'object');
137+
$DB->query('SELECT * FROM nv_brands WHERE website = '.intval($website->id), 'object');
138138
$out = $DB->result();
139139

140140
if($type='json')

0 commit comments

Comments
 (0)