modules/navigation: Fixed code injection vulnerability

This commit is contained in:
michu2k
2021-07-31 16:40:03 +02:00
parent 4905db80ce
commit 86011d4a26
9 changed files with 91 additions and 104 deletions

View File

@@ -19,9 +19,9 @@ class Admin extends AdminModule
public function navigation()
{
return [
$this->lang('manage', 'general') => 'manage',
$this->lang('add_link') => 'newLink',
$this->lang('add_nav') => 'newNav'
$this->lang('manage', 'general') => 'manage',
$this->lang('add_link') => 'newLink',
$this->lang('add_nav') => 'newNav'
];
}
@@ -64,13 +64,9 @@ class Admin extends AdminModule
public function getNewLink()
{
// lang
if (isset($_GET['lang'])) {
$lang = $_GET['lang'];
} else {
$lang = $this->settings('settings', 'lang_site');
}
$this->assign['langs'] = $this->_getLanguages($lang, 'selected');
$lang = isset($_GET['lang']) ? $_GET['lang'] : $this->settings('settings', 'lang_site');
$this->assign['langs'] = $this->_getLanguages($lang, 'selected');
$this->assign['link'] = ['name' => '', 'lang' => '', 'page' => '', 'url' => '', 'parent' => '', 'class' => ''];
// list of pages
@@ -95,13 +91,9 @@ class Admin extends AdminModule
if (!empty($row)) {
// lang
if (isset($_GET['lang'])) {
$lang = $_GET['lang'];
} else {
$lang = $row['lang'];
}
$this->assign['langs'] = $this->_getLanguages($lang, 'selected');
$lang = isset($_GET['lang']) ? $_GET['lang'] : $row['lang'];
$this->assign['langs'] = $this->_getLanguages($lang, 'selected');
$this->assign['link'] = filter_var_array($row, FILTER_SANITIZE_SPECIAL_CHARS);
// list of pages
@@ -126,47 +118,39 @@ class Admin extends AdminModule
public function postSaveLink($id = null)
{
unset($_POST['save']);
$formData = htmlspecialchars_array($_POST);
// check if it's an external link
if ($_POST['page']) {
$fields = ['name', 'page', 'lang', 'parent'];
} else {
$fields = ['name', 'url', 'lang', 'parent'];
}
$fields = $formData['page'] ? ['name', 'page', 'lang', 'parent'] : ['name', 'url', 'lang', 'parent'];
$location = $id ? url([ADMIN, 'navigation', 'editLink', $id]) : url([ADMIN, 'navigation', 'newLink']);
if (!$id) {
$location = url([ADMIN, 'navigation', 'newLink']);
} else {
$location = url([ADMIN, 'navigation', 'editLink', $id]);
}
if (checkEmptyFields($fields, $_POST)) {
if (checkEmptyFields($fields, $formData)) {
$this->notify('failure', $this->lang('empty_inputs', 'general'));
$this->assign['form'] = filter_var_array($_POST, FILTER_SANITIZE_SPECIAL_CHARS);
$this->assign['form'] = filter_var_array($formData, FILTER_SANITIZE_SPECIAL_CHARS);
redirect($location);
}
if ($_POST['page']) {
$_POST['url'] = null;
if ($formData['page']) {
$formData['url'] = null;
}
// get parent
$parent = explode('_', $_POST['parent']);
$_POST['nav'] = $parent[0];
$_POST['parent'] = (isset($parent[1]) ? $parent[1] : 0);
$parent = explode('_', $formData['parent']);
$formData['nav'] = $parent[0];
$formData['parent'] = (isset($parent[1]) ? $parent[1] : 0);
if (!is_numeric($_POST['page'])) {
$_POST['url'] = $_POST['page'];
$_POST['page'] = 0;
if (!is_numeric($formData['page'])) {
$formData['url'] = $formData['page'];
$formData['page'] = 0;
}
if (!$id) {
$_POST['"order"'] = $this->_getHighestOrder($_POST['nav'], $_POST['parent'], $_POST['lang']) + 1;
$query = $this->db('navs_items')->save($_POST);
$formData['"order"'] = $this->_getHighestOrder($formData['nav'], $formData['parent'], $formData['lang']) + 1;
$query = $this->db('navs_items')->save($formData);
} else {
$query = $this->db('navs_items')->where($id)->save($_POST);
$query = $this->db('navs_items')->where($id)->save($formData);
if ($query) {
$query = $this->db('navs_items')->where('parent', $id)->update(['nav' => $_POST['nav']]);
$query = $this->db('navs_items')->where('parent', $id)->update(['nav' => $formData['nav']]);
}
}
@@ -227,7 +211,9 @@ class Admin extends AdminModule
*/
public function postSaveNav($id = null)
{
if (empty($_POST['name'])) {
$formData = htmlspecialchars_array($_POST);
if (empty($formData['name'])) {
if (!$id) {
redirect(url([ADMIN, 'navigation', 'newNav']));
} else {
@@ -237,7 +223,7 @@ class Admin extends AdminModule
$this->notify('failure', $this->lang('empty_inputs', 'general'));
}
$name = createSlug($_POST['name']);
$name = createSlug($formData['name']);
// check if nav already exists
if (!$this->db('navs')->where('name', $name)->count()) {
@@ -283,6 +269,7 @@ class Admin extends AdminModule
private function _getPages($lang, $selected = null)
{
$rows = $this->db('pages')->where('lang', $lang)->toArray();
if (count($rows)) {
foreach ($rows as $row) {
if ($selected == $row['id']) {
@@ -293,6 +280,7 @@ class Admin extends AdminModule
$result[] = ['id' => $row['id'], 'title' => $row['title'], 'slug' => $row['slug'], 'attr' => $attr];
}
}
return $result;
}
@@ -305,6 +293,7 @@ class Admin extends AdminModule
private function _getParents($lang, $nav = null, $page = null, $except = null)
{
$rows = $this->db('navs')->toArray();
if (count($rows)) {
foreach ($rows as &$row) {
$row['name'] = $this->tpl->noParse('{$navigation.'.$row['name'].'}');
@@ -331,6 +320,7 @@ class Admin extends AdminModule
}
}
}
return $rows;
}
@@ -358,6 +348,7 @@ class Admin extends AdminModule
$item['fullURL'] = (parse_url($item['url'], PHP_URL_SCHEME) || strpos($item['url'], '#') === 0 ? '' : '/').trim($item['url'], '/');
}
}
return $this->buildTree($items);
}
}
@@ -438,10 +429,6 @@ class Admin extends AdminModule
->desc('"order"')
->oneArray();
if (!empty($item)) {
return $item['order'];
} else {
return 0;
}
return !empty($item) ? $item['order'] : 0;
}
}

View File

@@ -10,13 +10,12 @@
*/
return [
'name' => $core->lang['navigation']['module_name'],
'description' => $core->lang['navigation']['module_desc'],
'author' => 'Sruu.pl',
'version' => '1.1',
'compatibility' => '1.3.*',
'icon' => 'list-ul',
'name' => $core->lang['navigation']['module_name'],
'description' => $core->lang['navigation']['module_desc'],
'author' => 'Sruu.pl',
'version' => '1.2',
'compatibility' => '1.3.*',
'icon' => 'list-ul',
'install' => function () use ($core) {
$core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `navs` (
`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,

View File

@@ -29,6 +29,7 @@ class Site extends SiteModule
$homepage = $this->settings('settings', 'homepage');
$lang_prefix = $this->core->lang['name'];
if ($lang_prefix != $this->settings('settings', 'lang_site')) {
$lang_prefix = explode('_', $lang_prefix)[0];
} else {
@@ -98,6 +99,7 @@ class Site extends SiteModule
}
}
}
return false;
}
}

View File

@@ -6,38 +6,38 @@
</div>
<div class="panel-body">
<form name="link" action="{?=url(ADMIN.'/navigation/saveLink/'.@$navigation.link.id)?}" method="POST">
<div class="form-group">
<label>{$lang.general.lang}</label>
<select name="lang" class="form-control">
<div class="form-group">
<label>{$lang.general.lang}</label>
<select name="lang" class="form-control">
{loop: $navigation.langs}
<option value="{$value.name}" {$value.attr}>{$value.name}</option>
{/loop}
</select>
</div>
<div class="form-group">
<label>{$lang.general.name}</label>
<input type="text" name="name" class="form-control" value="{$navigation.link.name}" required />
</div>
<div class="form-group">
<label>{$lang.navigation.page}</label>
<select name="page" class="form-control" data-use-search="true">
</select>
</div>
<div class="form-group">
<label>{$lang.general.name}</label>
<input type="text" name="name" class="form-control" value="{$navigation.link.name}" required />
</div>
<div class="form-group">
<label>{$lang.navigation.page}</label>
<select name="page" class="form-control" data-use-search="true">
<option value="0">--- URL ---</option>
{loop: $navigation.pages}
<option value="{$value.id}" {$value.attr}>{$value.title} ({$value.slug})</option>
{/loop}
</select>
</div>
<div class="form-group" id="url">
<label>{$lang.navigation.url}</label>
<input type="text" name="url" class="form-control" value="{$navigation.link.url}" placeholder="http://" />
</div>
</select>
</div>
<div class="form-group" id="url">
<label>{$lang.navigation.url}</label>
<input type="text" name="url" class="form-control" value="{$navigation.link.url}" placeholder="http://" />
</div>
<div class="form-group" id="class">
<label>{$lang.navigation.class}</label>
<input type="text" name="class" class="form-control" value="{$navigation.link.class}" placeholder="{$lang.general.can_be_empty}" />
</div>
<div class="form-group">
<label>{$lang.navigation.parent}</label>
<select name="parent" class="form-control">
<label>{$lang.navigation.class}</label>
<input type="text" name="class" class="form-control" value="{$navigation.link.class}" placeholder="{$lang.general.can_be_empty}" />
</div>
<div class="form-group">
<label>{$lang.navigation.parent}</label>
<select name="parent" class="form-control">
{loop: $navigation.navs}
<option value="{$value.id}" {$value.attr}>{$value.name}</option>
{if: isset($value.items)}
@@ -46,10 +46,10 @@
{/loop}
{/if}
{/loop}
</select>
</div>
<input type="submit" name="save" class="btn btn-primary" value="{$lang.general.save}" />
</form>
</select>
</div>
<input type="submit" name="save" class="btn btn-primary" value="{$lang.general.save}" />
</form>
</div>
</div>
</div>

View File

@@ -6,12 +6,12 @@
</div>
<div class="panel-body">
<form name="menu" action="{?=url(ADMIN.'/navigation/saveNav/'.@$navigation.id)?}" method="POST">
<div class="form-group">
<label>{$lang.general.name}</label>
<input type="text" name="name" class="form-control" value="{$navigation.name}" required />
</div>
<input type="submit" name="save" class="btn btn-primary" value="{$lang.general.save}" />
</form>
<div class="form-group">
<label>{$lang.general.name}</label>
<input type="text" name="name" class="form-control" value="{$navigation.name}" required />
</div>
<input type="submit" name="save" class="btn btn-primary" value="{$lang.general.save}" />
</form>
</div>
</div>
</div>

View File

@@ -10,7 +10,7 @@
</ul>
</div>
<div class="panel-body">
{if: isset($navigation.navs)}
{if: isset($navigation.navs)}
{loop: $navigation.navs}
<div class="table-responsive">
<table class="table table-striped no-margin">
@@ -61,7 +61,7 @@
</table>
</div>
{/loop}
{/if}
{/if}
</div>
</div>
</div>

View File

@@ -92,7 +92,6 @@ class Admin extends AdminModule
public function postSave($id = null)
{
$errors = 0;
$formData = htmlspecialchars_array($_POST);
// location to redirect

View File

@@ -10,14 +10,13 @@
*/
return [
'name' => $core->lang['users']['module_name'],
'description' => $core->lang['users']['module_desc'],
'author' => 'Sruu.pl',
'version' => '1.1',
'compatibility' => '1.3.*',
'icon' => 'user',
'install' => function () use ($core) {
'name' => $core->lang['users']['module_name'],
'description' => $core->lang['users']['module_desc'],
'author' => 'Sruu.pl',
'version' => '1.2',
'compatibility' => '1.3.*',
'icon' => 'user',
'install' => function () use ($core) {
$core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `users` (
`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,
`username` text NOT NULL,
@@ -31,9 +30,9 @@ return [
)");
$core->db()->pdo()->exec("CREATE TABLE `login_attempts` (
`ip` TEXT NOT NULL,
`attempts` INTEGER NOT NULL,
`expires` INTEGER NOT NULL DEFAULT 0
`ip` TEXT NOT NULL,
`attempts` INTEGER NOT NULL,
`expires` INTEGER NOT NULL DEFAULT 0
)");
$core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `remember_me` (
@@ -42,7 +41,7 @@ return [
`user_id` integer NOT NULL REFERENCES users(id) ON DELETE CASCADE,
`expiry` integer NOT NULL
)");
$avatar = uniqid('avatar').'.png';
$core->db()->pdo()->exec('INSERT INTO `users` (`username`, `fullname`, `description`, `password`, `avatar`, `email`, `role`, `access`)
VALUES ("admin", "Selina Kyle", "My name is Selina Kyle but I speak for Catwoman… A mon who can offer you a path. Someone like you is only here by choice. You have been exploring the criminal fraternity but whatever your original intentions you have to become truly lost.", "$2y$10$pgRnDiukCbiYVqsamMM3ROWViSRqbyCCL33N8.ykBKZx0dlplXe9i", "'.$avatar.'", "admin@localhost", "admin", "all")');
@@ -53,7 +52,7 @@ return [
copy(MODULES.'/users/img/default.png', UPLOADS.'/users/'.$avatar);
},
'uninstall' => function () use ($core) {
'uninstall' => function () use ($core) {
$core->db()->pdo()->exec("DROP TABLE `users`");
$core->db()->pdo()->exec("DROP TABLE `login_attempts`");
$core->db()->pdo()->exec("DROP TABLE `remember_me`");

View File

@@ -25,6 +25,7 @@ class Site extends SiteModule
$result[$value['id']] = $users[$key];
$result[$value['id']]['avatar'] = url('uploads/users/' . $value['avatar']);
}
return $result;
});
}