Skip to content

Commit 51fb78b

Browse files
hardening: prepared statements, XSS fixes, CSRF protection, and CI
SQL injection hardening: - Migrate all query construction to prepared statements throughout - Centralize match filter building in syslog_build_match_filter() - Add lock result validation for partition create/remove operations - Move partition count query inside lock for atomicity XSS and CSRF: - Replace form_selectable_cell with form_selectable_ecell for output escaping - Add html_escape on user-visible output - Add CSRF token validation on purge action - Remove eval() in JS autocomplete, use jQuery .text() for DOM safety Poller safety: - Replace max_seq with uniqueID (rand 1-127) for concurrent poller safety - Add syslog_execute_ticket_command/syslog_execute_alert_command helpers - DRY refactor of bulk action confirm dialogs Tests and CI: - Add SyslogMatchFilter, SyslogPreprocess, SyslogPartition unit tests - Add integration test CI workflow with MySQL - Add domain stripping and partitioning integration tests Signed-off-by: Thomas Vincent <[email protected]>
1 parent cb0b5e0 commit 51fb78b

42 files changed

Lines changed: 6641 additions & 1066 deletions

Some content is hidden

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

.github/workflows/plugin-ci-workflow.yml

Lines changed: 62 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -32,65 +32,7 @@ on:
3232
- develop
3333

3434
jobs:
35-
quality-checks:
36-
name: PHP Quality (Lint, Stan, CS)
37-
runs-on: ubuntu-latest
38-
steps:
39-
- name: Checkout Cacti
40-
uses: actions/checkout@v4
41-
with:
42-
repository: Cacti/cacti
43-
path: cacti
44-
45-
- name: Checkout Syslog Plugin
46-
uses: actions/checkout@v4
47-
with:
48-
path: cacti/plugins/syslog
49-
50-
- name: Setup PHP 8.3
51-
uses: shivammathur/setup-php@v2
52-
with:
53-
php-version: '8.3'
54-
extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring
55-
tools: php-cs-fixer, phpstan
56-
57-
- name: Check PHP Syntax (Lint)
58-
run: |
59-
cd cacti/plugins/syslog
60-
if find . -name '*.php' -not -path './vendor/*' -exec php -l {} 2>&1 \; | grep -iv 'no syntax errors detected'; then
61-
print "Syntax errors found!"
62-
exit 1
63-
fi
64-
65-
- name: Run PHP CS Fixer (Dry Run)
66-
run: |
67-
cd cacti/plugins/syslog
68-
php-cs-fixer fix --dry-run --diff --ansi --config=../../../.php-cs-fixer.php . || true
69-
70-
- name: Create PHPStan config
71-
run: |
72-
cd cacti/plugins/syslog
73-
cat > phpstan.neon << 'EOF'
74-
parameters:
75-
level: 5
76-
paths:
77-
- .
78-
excludePaths:
79-
- vendor/
80-
- locales/
81-
ignoreErrors:
82-
- '#has invalid return type the\.#'
83-
bootstrapFiles:
84-
- ../../include/global.php
85-
EOF
86-
87-
- name: Run PHPStan Analysis
88-
run: |
89-
cd cacti/plugins/syslog
90-
phpstan analyse --no-progress --error-format=github || true
91-
9235
integration-test:
93-
needs: quality-checks
9436
runs-on: ${{ matrix.os }}
9537

9638
strategy:
@@ -110,7 +52,7 @@ jobs:
11052
ports:
11153
- 3306:3306
11254
options: >-
113-
--health-cmd="mysqladmin ping"
55+
--health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -pcactiroot"
11456
--health-interval=10s
11557
--health-timeout=5s
11658
--health-retries=3
@@ -205,7 +147,7 @@ jobs:
205147
sed -i "s/'cacti'/'cacti'/g" ${{ github.workspace }}/cacti/plugins/syslog/config.php
206148
sed -i "s/'cactiuser'/'cactiuser'/g" ${{ github.workspace }}/cacti/plugins/syslog/config.php
207149
sed -i 's/\/\/\$/\$/g' ${{ github.workspace }}/cacti/plugins/syslog/config.php
208-
sudo chmod 664 ${{ github.workspace }}/cacti/include/config.php
150+
sudo chmod 664 ${{ github.workspace }}/cacti/plugins/syslog/config.php
209151
210152
- name: Configure Apache
211153
run: |
@@ -236,6 +178,59 @@ jobs:
236178
run: |
237179
cd ${{ github.workspace }}/cacti
238180
sudo php cli/plugin_manage.php --plugin=syslog --install --enable
181+
182+
- name: Check PHP Syntax for Plugin
183+
run: |
184+
cd ${{ github.workspace }}/cacti/plugins/syslog
185+
if find . -name '*.php' -exec php -l {} 2>&1 \; | grep -iv 'no syntax errors detected'; then
186+
echo "Syntax errors found!"
187+
exit 1
188+
fi
189+
190+
- name: Create PHPStan config
191+
run: |
192+
cd ${{ github.workspace }}/cacti/plugins/syslog
193+
cat > phpstan.neon << 'EOF'
194+
parameters:
195+
level: 5
196+
paths:
197+
- .
198+
excludePaths:
199+
- vendor/
200+
- locales/
201+
ignoreErrors:
202+
- '#has invalid return type the\.#'
203+
bootstrapFiles:
204+
- ../../include/global.php
205+
EOF
206+
207+
- name: Install PHPStan
208+
run: |
209+
cd ${{ github.workspace }}/cacti/plugins/syslog
210+
composer require --dev phpstan/phpstan --with-all-dependencies || composer global require phpstan/phpstan
211+
212+
- name: Run PHPStan Analysis
213+
run: |
214+
cd ${{ github.workspace }}/cacti/plugins/syslog
215+
if [ -f vendor/bin/phpstan ]; then
216+
vendor/bin/phpstan analyse --no-progress --error-format=github
217+
else
218+
phpstan analyse --no-progress --error-format=github
219+
fi
220+
221+
- name: Install PHP-CS-Fixer
222+
run: |
223+
cd ${{ github.workspace }}/cacti/plugins/syslog
224+
composer require --dev friendsofphp/php-cs-fixer --with-all-dependencies || composer global require friendsofphp/php-cs-fixer
225+
226+
- name: Run PHP-CS-Fixer Check
227+
run: |
228+
cd ${{ github.workspace }}/cacti/plugins/syslog
229+
if [ -f vendor/bin/php-cs-fixer ]; then
230+
vendor/bin/php-cs-fixer fix --dry-run --diff --format=github
231+
else
232+
php-cs-fixer fix --dry-run --diff --format=github
233+
fi
239234
240235
- name: Run Plugin Regression Tests
241236
run: |
@@ -246,40 +241,39 @@ jobs:
246241
php "$test"
247242
done
248243
fi
249-
250-
244+
251245
- name: Run Cacti Poller
252246
run: |
253247
cd ${{ github.workspace }}/cacti
254248
sudo php poller.php --poller=1 --force --debug
255249
if ! grep -q "SYSTEM STATS" log/cacti.log; then
256-
print "Cacti poller did not finish successfully"
250+
echo "Cacti poller did not finish successfully"
257251
cat log/cacti.log
258252
exit 1
259253
fi
260-
254+
261255
- name: Populate Syslog Test Data
262256
run: |
263257
sudo chmod +x ${{ github.workspace }}/cacti/plugins/syslog/.github/workflows/populate_syslog_incoming.sh
264258
cd ${{ github.workspace }}/cacti/plugins/syslog/.github/workflows
265259
sudo ./populate_syslog_incoming.sh
266260
267-
268261
- name: force Syslog Plugin Poller
269262
run: |
270263
cd ${{ github.workspace }}/cacti
271264
sudo php plugins/syslog/syslog_process.php --debug
272265
if ! grep -q "SYSTEM SYSLOG STATS" log/cacti.log; then
273-
print "Syslog plugin poller did not finish successfully"
266+
echo "Syslog plugin poller did not finish successfully"
274267
cat log/cacti.log
275268
exit 1
276269
fi
277270
278-
279271
- name: View Cacti Logs
280272
if: always()
281273
run: |
282274
if [ -f ${{ github.workspace }}/cacti/log/cacti.log ]; then
283-
print "=== Cacti Log ==="
275+
echo "=== Cacti Log ==="
284276
sudo cat ${{ github.workspace }}/cacti/log/cacti.log
285277
fi
278+
279+

.github/workflows/populate_syslog_incoming.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
ITERATIONS=100
66

77

8-
SQL_ALERT_RULE_INSERT="INSERT INTO syslog_alert (id,hash,name,severity,method,level,num,type,enabled,repeat_alert,open_ticket,message,body,user,date,email,notify,command,notes)
8+
SQL_ALERT_RULE_INSERT="REPLACE INTO syslog_alert (id,hash,name,severity,method,level,num,type,enabled,repeat_alert,open_ticket,message,body,user,date,email,notify,command,notes)
99
VALUES (1,'8f440030d3425e37cb66e5df54902bb0','interface down alert',1,0,1,1,'messageb','on',0,'','interface down','admin',1767376990,NULL,0,NULL,NULL);"
1010

11-
SQL_REMOVAL_RULE_INSERT="INSERT INTO syslog_remove (id,hash,name,type,enabled,method,message,user,date,notes)
11+
SQL_REMOVAL_RULE_INSERT="REPLACE INTO syslog_remove (id,hash,name,type,enabled,method,message,user,date,notes)
1212
VALUES (1,'0faf589f7b6b7da1bcec40b92340487d','exploded','messageb','on','del',
1313
'the box exploded','admin',1767376604,NULL);"
1414

CHANGELOG.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
--- develop ---
44

55
* issue#250: Fix date filter persistence by validating before shift_span detection
6-
* issue#258: Execute CREATE TABLE SQL correctly during replication sync
7-
* issue#278: Extract duplicated alert command execution paths in syslog_process_alerts
8-
* issue#278: Extract alert command execution into shared helper in functions.php; command tokenization now uses preg_split (handles tabs and consecutive spaces); /bin/sh fallback for non-executable command templates removed (use absolute paths with execute bit set)
6+
* issue#260: Replace eval-based callback execution in autocomplete handling
97
* issue: Making changes to support Cacti 1.3
108
* issue: Don't use MyISAM for non-analytical tables
119
* issue: The install advisor for Syslog was broken in current Cacti releases

LICENSE

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,4 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277277
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278278
POSSIBILITY OF SUCH DAMAGES.
279279

280-
<<<<<<< Updated upstream
281-
=======
282280
END OF TERMS AND CONDITIONS
283-
>>>>>>> Stashed changes

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ To use a dedicated DB first create a database in mysql and assign a user you wil
8686
$use_cacti_db = true;
8787
```
8888

89-
to
89+
to
9090

91-
``console
91+
```console
9292
$use_cacti_db = false;
9393
```
9494

composer.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"require-dev": {
3+
"pestphp/pest": "^4.4"
4+
},
5+
"config": {
6+
"allow-plugins": {
7+
"pestphp/pest-plugin": true
8+
}
9+
}
10+
}

0 commit comments

Comments
 (0)