mirror of
https://git.sr.ht/~iwakuralain/text0Nly
synced 2025-07-27 15:36:11 +00:00
api security
This commit is contained in:
parent
9afe6dc04e
commit
16e16c5490
25
main/api.php
25
main/api.php
@ -5,6 +5,16 @@ header('X-Frame-Options: DENY');
|
||||
header('X-XSS-Protection: 1; mode=block');
|
||||
header('Content-Security-Policy: default-src \'self\'');
|
||||
|
||||
session_start();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (!isset($_SESSION['csrf_token']) || !isset($_SERVER['HTTP_X_CSRF_TOKEN']) ||
|
||||
$_SESSION['csrf_token'] !== $_SERVER['HTTP_X_CSRF_TOKEN']) {
|
||||
http_response_code(403);
|
||||
die(json_encode(['error' => 'Invalid CSRF token']));
|
||||
}
|
||||
}
|
||||
|
||||
$config = require 'config.php';
|
||||
$db = new PDO(
|
||||
"mysql:host={$config['db']['host']};dbname={$config['db']['name']}",
|
||||
@ -18,7 +28,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
$limit = min(max(1, $limit), 100);
|
||||
|
||||
try {
|
||||
$stmt = $db->query("SELECT username, message, created_at, signature, is_encrypted FROM messages ORDER BY created_at DESC LIMIT $limit");
|
||||
$stmt = $db->prepare("SELECT username, message, created_at, signature, is_encrypted FROM messages ORDER BY created_at DESC LIMIT ?");
|
||||
$stmt->execute([$limit]);
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$filtered_messages = array_map(function($msg) {
|
||||
@ -45,6 +56,14 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
die(json_encode(['error' => 'Method not allowed']));
|
||||
}
|
||||
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
$stmt = $db->prepare("SELECT COUNT(*) FROM messages WHERE username = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 MINUTE)");
|
||||
$stmt->execute([$ip]);
|
||||
if ($stmt->fetchColumn() > 10) {
|
||||
http_response_code(429);
|
||||
die(json_encode(['error' => 'Too many requests']));
|
||||
}
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!$input) {
|
||||
http_response_code(400);
|
||||
@ -56,9 +75,9 @@ $message = $input['message'] ?? '';
|
||||
$signature = $input['signature'] ?? '';
|
||||
$is_encrypted = !empty($input['encrypted']) ? 1 : 0;
|
||||
|
||||
if (!$username || !$message) {
|
||||
if (!$username || !$message || strlen($username) > 50 || strlen($message) > 10000) {
|
||||
http_response_code(400);
|
||||
die(json_encode(['error' => 'Missing required fields']));
|
||||
die(json_encode(['error' => 'Invalid input']));
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -17,6 +17,8 @@ CREATE TABLE users (
|
||||
is_moderator TINYINT(1) NOT NULL DEFAULT 0,
|
||||
login_attempts INT NOT NULL DEFAULT 0,
|
||||
last_attempt TIMESTAMP NULL,
|
||||
is_blocked TINYINT(1) NOT NULL DEFAULT 0,
|
||||
block_reason TEXT,
|
||||
INDEX idx_username (username)
|
||||
);
|
||||
|
||||
@ -24,5 +26,6 @@ CREATE TABLE registrations (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
ip VARCHAR(45) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_ip_created (ip, created_at)
|
||||
INDEX idx_ip_created (ip, created_at),
|
||||
INDEX idx_created_at (created_at)
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user