security: harden application security baseline
- Fixed SQL injection vulnerabilities with prepared statements - Added column whitelist protection for dynamic termin updates - Extracted iCloud credentials into protected config file - Moved sensitive configuration files out of webroot - Added authentication and admin checks to PVE APIs - Added CSRF protection to write operations and APIs - Disabled debug output in production mode - Added centralized configuration handling - Protected sensitive directories with access rules - Added initial project security documentation
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
<?php
|
||||
require_once "../config/config.php";
|
||||
require_once "../config/session.php";
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
try {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') throw new RuntimeException('Method not allowed');
|
||||
|
||||
// CSRF check
|
||||
$csrf = $_POST['csrf_token'] ?? '';
|
||||
if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $csrf)) {
|
||||
throw new RuntimeException('CSRF validation failed');
|
||||
}
|
||||
|
||||
$id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
|
||||
$date = trim($_POST['date'] ?? '');
|
||||
$category = trim($_POST['category'] ?? '');
|
||||
@@ -45,3 +52,148 @@ try {
|
||||
http_response_code(400);
|
||||
echo json_encode(['ok'=>false,'error'=>$e->getMessage()]);
|
||||
}
|
||||
</create_file>
|
||||
<create_file>
|
||||
<path>d:/anjuma-dashboard/api/finance_expenses_delete.php</path>
|
||||
<content><?php
|
||||
require_once "../config/config.php";
|
||||
require_once "../config/session.php";
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
try {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') throw new RuntimeException('Method not allowed');
|
||||
|
||||
// CSRF check
|
||||
$csrf = $_POST['csrf_token'] ?? '';
|
||||
if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $csrf)) {
|
||||
throw new RuntimeException('CSRF validation failed');
|
||||
}
|
||||
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id <= 0) throw new RuntimeException('id fehlt');
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM finance_expenses WHERE id=:id");
|
||||
$stmt->execute([':id'=>$id]);
|
||||
|
||||
echo json_encode(['ok'=>true], JSON_UNESCAPED_UNICODE);
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['ok'=>false,'error'=>$e->getMessage()]);
|
||||
}
|
||||
</create_file>
|
||||
<create_file>
|
||||
<path>d:/anjuma-dashboard/api/invoice_create_from_termin.php</path>
|
||||
<content><?php
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
require_once "../config/config.php";
|
||||
require_once "../config/session.php";
|
||||
require_once __DIR__ . '/../lib/InvoiceNo.php';
|
||||
|
||||
global $pdo;
|
||||
|
||||
try {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
throw new RuntimeException('Method not allowed');
|
||||
}
|
||||
|
||||
// CSRF check
|
||||
$csrf = $_POST['csrf_token'] ?? '';
|
||||
if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $csrf)) {
|
||||
throw new RuntimeException('CSRF validation failed');
|
||||
}
|
||||
|
||||
$terminId = (int)($_POST['termin_id'] ?? 0);
|
||||
if ($terminId <= 0) {
|
||||
throw new RuntimeException('termin_id fehlt');
|
||||
}
|
||||
|
||||
// Termin laden
|
||||
$st = $pdo->prepare("SELECT * FROM termine WHERE id=:id");
|
||||
$st->execute([':id' => $terminId]);
|
||||
$t = $st->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$t) {
|
||||
throw new RuntimeException('Termin nicht gefunden');
|
||||
}
|
||||
|
||||
// Prüfen ob Rechnung existiert
|
||||
$st = $pdo->prepare("SELECT id FROM invoices WHERE termine_id=:tid LIMIT 1");
|
||||
$st->execute([':tid' => $terminId]);
|
||||
|
||||
if ($st->fetch()) {
|
||||
throw new RuntimeException('Für diesen Termin existiert bereits eine Rechnung.');
|
||||
}
|
||||
|
||||
$serviceDate = date('Y-m-d', (int)$t['startzeit']);
|
||||
$invoiceDate = date('Y-m-d');
|
||||
$dueDate = date('Y-m-d', strtotime($invoiceDate . ' +14 days'));
|
||||
|
||||
$year = (int)date('Y');
|
||||
$invoiceNo = nextInvoiceNo($pdo, $year);
|
||||
|
||||
$customerName = trim($_POST['customer_name'] ?? 'Kunde (bitte bearbeiten)');
|
||||
$customerStreet = trim($_POST['customer_street'] ?? '');
|
||||
$customerZip = trim($_POST['customer_zip'] ?? '');
|
||||
$customerCity = trim($_POST['customer_city'] ?? '');
|
||||
$customerCountry = trim($_POST['customer_country'] ?? 'DE');
|
||||
|
||||
$gage = (int)($t['gage'] ?? 0);
|
||||
|
||||
$desc = "DJ-Leistung am " . date('d.m.Y', (int)$t['startzeit']);
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$pdo->prepare("
|
||||
INSERT INTO invoices
|
||||
(invoice_no, invoice_date, service_date, due_date, status,
|
||||
customer_name, customer_street, customer_zip, customer_city, customer_country,
|
||||
termine_id, amount_net_eur)
|
||||
VALUES
|
||||
(:no, :invdate, :servdate, :duedate, 'draft',
|
||||
:cname, :cstreet, :czip, :ccity, :ccountry,
|
||||
:tid, :amount)
|
||||
")->execute([
|
||||
':no' => $invoiceNo,
|
||||
':invdate' => $invoiceDate,
|
||||
':servdate' => $serviceDate,
|
||||
':duedate' => $dueDate,
|
||||
':cname' => $customerName,
|
||||
':cstreet' => $customerStreet,
|
||||
':czip' => $customerZip,
|
||||
':ccity' => $customerCity,
|
||||
':ccountry' => $customerCountry,
|
||||
':tid' => $terminId,
|
||||
':amount' => $gage
|
||||
]);
|
||||
|
||||
$invoiceId = (int)$pdo->lastInsertId();
|
||||
|
||||
$pdo->prepare("
|
||||
INSERT INTO invoice_items
|
||||
(invoice_id, pos, description, qty, unit_price_eur, line_total_eur)
|
||||
VALUES
|
||||
(:iid, 1, :d, 1, :p, :p)
|
||||
")->execute([
|
||||
':iid' => $invoiceId,
|
||||
':d' => $desc,
|
||||
':p' => $gage
|
||||
]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode([
|
||||
'ok' => true,
|
||||
'invoice_id' => $invoiceId,
|
||||
'invoice_no' => $invoiceNo
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo && $pdo->inTransaction()) $pdo->rollBack();
|
||||
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'ok' => false,
|
||||
'error' => $e->getMessage()
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
</create_file>
|
||||
|
||||
Reference in New Issue
Block a user