Completed
Push — development ( a01039...53bd05 )
by Nils
07:42
created

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @file          kb.php
4
 * @author        Nils Laumaillé
5
 * @version       2.1.27
6
 * @copyright     (c) 2009-2017 Nils Laumaillé
7
 * @licensing     GNU GPL-3.0
8
 * @link          http://www.teampass.net
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 */
14
15
if (!isset($_SESSION['CPM']) || $_SESSION['CPM'] != 1 ||
16
    !isset($_SESSION['user_id']) || empty($_SESSION['user_id']) ||
17
    !isset($_SESSION['key']) || empty($_SESSION['key'])
18
) {
19
    die('Hacking attempt...');
20
}
21
22
// Load config
23 View Code Duplication
if (file_exists('../includes/config/tp.config.php')) {
24
    require_once '../includes/config/tp.config.php';
25
} elseif (file_exists('./includes/config/tp.config.php')) {
26
    require_once './includes/config/tp.config.php';
27
} else {
28
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
29
}
30
31 View Code Duplication
if (isset($SETTINGS['enable_kb']) === false || $SETTINGS['enable_kb'] !== "1") {
32
    die('Hacking attempt...');
33
}
34
35
/* do checks */
36
require_once $SETTINGS['cpassman_dir'].'/sources/checks.php';
37 View Code Duplication
if (!checkUser($_SESSION['user_id'], $_SESSION['key'], curPage())) {
38
    $_SESSION['error']['code'] = ERR_NOT_ALLOWED; //not allowed page
39
    include $SETTINGS['cpassman_dir'].'/error.php';
40
    exit();
41
}
42
43
//load language
44
require_once $SETTINGS['cpassman_dir'].'/sources/main.functions.php';
45
46
47
// Include files
48
require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
49
$superGlobal = new protect\SuperGlobal\SuperGlobal();
50
51
// Prepare GET variables
52
$get_id = $superGlobal->get("id", "GET");
53
54
//build list of categories
55
$tab_users = array();
56
$rows = DB::query(
57
    "SELECT id, login FROM ".prefix_table("users")." ORDER BY login ASC"
58
);
59
$counter = DB::count();
60
if ($counter > 0) {
61
    foreach ($rows as $reccord) {
62
        $tab_users[$reccord['login']] = array(
63
            'id'=>$reccord['id'],
64
            'login'=>$reccord['login']
65
        );
66
    }
67
}
68
69
echo '
70
<div class="title ui-widget-content ui-corner-all">
71
    '.$LANG['knowledge_base'].'&nbsp;&nbsp;&nbsp;
72
    <button title="'.$LANG['add_new_kb'].'" onclick="OpenDialog(\'kb_form\')" class="button" style="font-size:16px;">
73
        <i class="fa fa-plus"></i>
74
    </button>
75
</div>';
76
77
//Show the KB in a table view
78
echo '
79
<div style="margin:10px auto 25px auto;min-height:250px;" id="kb_page">
80
<table id="t_kb" cellspacing="0" cellpadding="5" width="100%">
81
    <thead><tr>
82
        <th style="width:50px;"></th>
83
        <th style="width:25%;">'.$LANG['category'].'</th>
84
        <th style="width:50%;">'.$LANG['label'].'</th>
85
        <th style="width:15%;">'.$LANG['author'].'</th>
86
    </tr></thead>
87
    <tbody>
88
        <tr><td></td></tr>
89
    </tbody>
90
</table>
91
</div>';
92
93
//Hidden things
94
echo '
95
<input type="hidden" id="kb_id" value="" />';
96
97
/* DIV FOR ADDING A KN */
98
echo '
99
<div id="kb_form" style="display:none;">
100
    <label for="kb_label" class="label">'.$LANG['label'].'</label>
101
    <input type="text" id="kb_label" class="input text ui-widget-content ui-corner-all" />
102
    <br />
103
104
    <div style="width:100%;">
105
        <div style="float:left;width:50%;">
106
            <label for="kb_category" class="label">'.$LANG['category'].'</label>
107
            <input name="kb_category" id="kb_category" class="kb_text ui-widget-content ui-corner-all" style="width: 300px;" value="" />
108
        </div>
109
        <div style="float:right;width:50%;">
110
            <label class="modify_kb_label">'.$LANG['anyone_can_modify_it'].' : </label>
111
            <span class="div_radio">
112
                <input type="radio" id="modify_kb_yes" name="modify_kb" value="1" checked="checked" /><label for="modify_kb_yes">'.$LANG['yes'].'</label>
113
                <input type="radio" id="modify_kb_no" name="modify_kb" value="0" /><label for="modify_kb_no">'.$LANG['no'].'</label>
114
            </span>
115
        </div>
116
    </div>
117
118
    <div style="float:left;width:100%;">
119
        <label for="kb_description" class="label">'.$LANG['description'].'</label>
120
        <textarea rows="5" name="kb_description" id="kb_description" class="input" cols="70"></textarea>
121
    </div>
122
123
    <div style="float:left;width:100%;margin-top:15px;">
124
        <label for="kb_associated_to" class="label">'.$LANG['associate_kb_to_items'].'</label>
125
        <select id="kb_associated_to" class="multiselect" multiple="multiple" name="kb_associated_to[]" style="width: 860px; height: 150px;">';
126
//get list of available items
127
$items_id_list = array();
128
if (empty($_SESSION['list_folders_limited'])) {
129
    $_SESSION['list_folders_limited'] = array();
130
}
131
$rows = DB::query(
132
    "SELECT i.id as id, i.restricted_to as restricted_to, i.perso as perso, i.label as label,
133
        i.description as description, i.pw as pw, i.login as login, i.anyone_can_modify as anyone_can_modify,
134
        l.date as date
135
    FROM ".prefix_table("items")." as i
136
    INNER JOIN ".prefix_table("log_items")." as l ON (i.id = l.id_item)
137
    WHERE i.inactif = %i
138
    AND (l.action = %s OR (l.action = %s AND l.raison LIKE %s))
139
    AND i.id_tree IN %ls
140
    ORDER BY i.label ASC, l.date DESC",
141
    '0',
142
    'at_creation',
143
    'at_modification',
144
    'at_pw :%',
145
    array_unique(
146
        array_merge(
147
            $_SESSION['all_non_personal_folders'],
148
            $_SESSION['list_folders_editable_by_role'],
149
            $_SESSION['list_restricted_folders_for_items'],
150
            $_SESSION['list_folders_limited']
151
        )
152
    )
153
);
154
foreach ($rows as $reccord) {
155
    if (!in_array($reccord['id'], $items_id_list) && !empty($reccord['label'])) {
156
        // exclude item if it is restricted to a group the user doesn't have
157
        $include_item = false;
158
        if (empty($reccord['restricted_to'])) {
159
            $include_item = true;
160
        } elseif (count(array_intersect(explode(";", $reccord['restricted_to']), $_SESSION['user_roles'])) !== 0) {
161
            $include_item = true;
162
        }
163
        if ($include_item === true) {
164
            echo '
165
            <option value="'.$reccord['id'].'">'.$reccord['label'].'</option>';
166
            array_push($items_id_list, $reccord['id']);
167
        }
168
    }
169
}
170
echo '
171
        </select>
172
    </div>
173
</div>';
174
175
//DELETE DIALOG
176
echo '
177
<div id="div_kb_delete" style="display:none;">
178
    <p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;">&nbsp;</span>'.$LANG['confirm_deletion'].'</p>
179
</div>';
180
181
//Hidden things
182
echo '
183
<input type="hidden" id="kb_id" value="" />';
184
185
//Call javascript stuff
186
require_once 'kb.load.php';
187
188
//If redirection is done to a speoific KB then open it
189
if ($get_id !== null && empty($get_id) === false) {
190
    echo '
0 ignored issues
show
Security Cross-Site Scripting introduced by
' <script langua... --> </script>' can contain request data and is used in output context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $get_id is assigned
    in kb.php on line 52

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
191
        <script language="javascript" type="text/javascript">
192
        <!--
193
        openKB('.$get_id.');
194
        -->
195
        </script>';
196
}
197