Ir para o conteúdo

Arquitetura de segurança

Esta página documenta a arquitetura de segurança do omegaUp, incluindo mecanismos de autenticação, modelo de autorização, limitação de taxa e sistema de sandbox para execução de código.

Visão geral da segurança

flowchart TB
    subgraph "Client Layer"
        Browser[Browser]
        API[API Client]
    end

    subgraph "Edge Security"
        TLS[TLS Termination]
        Rate[Rate Limiting]
        CSRF[CSRF Protection]
    end

    subgraph "Application Security"
        Auth[Authentication]
        Authz[Authorization]
        Valid[Input Validation]
    end

    subgraph "Execution Security"
        Sandbox[Minijail Sandbox]
        Limits[Resource Limits]
    end

    Browser --> TLS
    API --> TLS
    TLS --> Rate
    Rate --> CSRF
    CSRF --> Auth
    Auth --> Authz
    Authz --> Valid
    Valid --> Sandbox
    Sandbox --> Limits

Autenticação

Autenticação baseada em token

omegaUp usa autenticação baseada em token por meio do cookie ouat (omegaUp Auth Token).

Geração de Tokens

sequenceDiagram
    participant U as User
    participant A as Auth API
    participant D as Database

    U->>A: POST /api/user/login/
    A->>D: Verify credentials
    D-->>A: User valid
    A->>A: Generate token
    A->>D: Store token
    A-->>U: Set-Cookie: ouat={token}

Estrutura do token

{entropy}-{identity_id}-{hash}
- entropy: 15 bytes de dados aleatórios (codificação hexadecimal) - identity_id: ID de identidade do usuário - hash: SHA-256(sal + identidade_id + entropia)

Validação de token

// Token validated on each request
$identityExt = \OmegaUp\DAO\AuthTokens::getIdentityByToken($authToken);
if (is_null($identityExt)) {
    throw new UnauthorizedException('loginRequired');
}

Autenticação de token de API

Para acesso programático, os usuários podem criar tokens de API:

# Authorization header format
Authorization: token {api_token}

# With identity selection
Authorization: token Credential={api_token},Username={identity}

Limites de taxa

Os tokens de API têm limites de taxa configuráveis:

Tipo de limite Padrão Cabeçalhos
Solicitações/hora 1000 X-RateLimit-Limit
Restante - X-RateLimit-Remaining
Redefinir hora - X-RateLimit-Reset

Integração OAuth

Autenticação de terceiros por meio de:

  • Google: OAuth 2.0 com verificação de token de ID
  • Facebook: OAuth 2.0 com token de acesso
sequenceDiagram
    participant U as User
    participant O as omegaUp
    participant G as Google

    U->>G: Login with Google
    G-->>U: ID Token
    U->>O: POST with ID token
    O->>G: Verify token
    G-->>O: Valid
    O->>O: Create/link account
    O-->>U: Set session

Autorização

Controle de acesso baseado em função

flowchart TD
    subgraph Roles
        SA[System Admin]
        QR[Quality Reviewer]
        Mentor[Mentor]
        User[Regular User]
    end

    subgraph Resources
        System[System Settings]
        Problems[Problems]
        Contests[Contests]
        Groups[Groups]
    end

    SA --> System
    SA --> Problems
    SA --> Contests
    SA --> Groups

    QR --> Problems
    Mentor --> Contests

    User --> Contests
    User --> Groups

Níveis de permissão

Nível Descrição Exemplo
Administrador do sistema Acesso total à plataforma Configuração do site
Revisor de Qualidade Revise a qualidade do problema Nomeações de qualidade
Mentor Guia codificadores do mês Selecione os vencedores
Administrador do concurso Gerenciar concurso específico Adicionar problemas, usuários
Administrador de problemas Gerenciar problema específico Atualizar declarações
Administrador de grupo Gerenciar grupo Adicionar membros

Verificações de autorização

// Check system admin
if (!\OmegaUp\Authorization::isSystemAdmin($identity)) {
    throw new ForbiddenAccessException();
}

// Check contest admin
if (!\OmegaUp\Authorization::isContestAdmin($identity, $contest)) {
    throw new ForbiddenAccessException();
}

// Check group membership
if (!\OmegaUp\Authorization::isGroupAdmin($identity, $group)) {
    throw new ForbiddenAccessException();
}

Sistema ACL

Os recursos usam listas de controle de acesso:

-- ACL table
CREATE TABLE `ACLs` (
    `acl_id` int NOT NULL AUTO_INCREMENT,
    `owner_id` int NOT NULL,
    PRIMARY KEY (`acl_id`)
);

-- User permissions
CREATE TABLE `User_Roles` (
    `user_id` int NOT NULL,
    `role_id` int NOT NULL,
    `acl_id` int NOT NULL,
    PRIMARY KEY (`user_id`, `role_id`, `acl_id`)
);

-- Group permissions
CREATE TABLE `Group_Roles` (
    `group_id` int NOT NULL,
    `role_id` int NOT NULL,
    `acl_id` int NOT NULL,
    PRIMARY KEY (`group_id`, `role_id`, `acl_id`)
);

Validação de entrada

Validação de parâmetros

Todas as entradas da API são validadas:

// Required string
$alias = $r->ensureString('alias', 
    fn ($alias) => \OmegaUp\Validators::alias($alias)
);

// Optional int with bounds
$page = $r->ensureOptionalInt('page', 
    lowerBound: 1, 
    upperBound: 1000
);

// Enum validation
$status = $r->ensureEnum('status', 
    ['open', 'resolved', 'banned']
);

Prevenção de injeção SQL

Todas as consultas ao banco de dados usam instruções preparadas:

// Safe query with parameters
$result = \OmegaUp\MySQLConnection::getInstance()->GetAll(
    'SELECT * FROM Problems WHERE alias = ?',
    [$problemAlias]
);

Prevenção XSS

A saída tem escape por padrão nos modelos:

{# Auto-escaped #}
{{ problem.title }}

{# Raw HTML (explicit) #}
{{ problem.description | raw }}

Limitação de taxa

Limites de taxa de endpoint

Ponto final Limite Janela
/api/user/login/ 10 1 minuto
/api/run/create/ 1 por problema 60 segundos
/api/* (padrão) 100 1 minuto

Implementação

// Check rate limit
$key = "ratelimit:{$ip}:{$endpoint}";
$count = $redis->incr($key);

if ($count === 1) {
    $redis->expire($key, 60);
}

if ($count > $limit) {
    throw new RateLimitExceededException();
}

Ignorar para concursos

Durante os concursos, os limites da taxa de envio são relaxados:

  • Normal: 1 envio a cada 60 segundos por problema
  • Concurso: submissions_gap configurável

Proteção CSRF

Validação de token

Os formulários incluem tokens CSRF:

<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
// Validate on POST
if ($request->method === 'POST') {
    if ($request['csrf_token'] !== $session['csrf_token']) {
        throw new CSRFException();
    }
}

Cookies do mesmo site

Os cookies de sessão usam o atributo SameSite:

setcookie(
    OMEGAUP_AUTH_TOKEN_COOKIE_NAME,
    $token,
    [
        'path' => '/',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Lax'
    ]
);

Sandbox de execução de código

Caixa de areia Minijail

O código do usuário é executado em um ambiente altamente restrito:

flowchart TB
    subgraph "Minijail Restrictions"
        NS[Namespace Isolation]
        SC[Seccomp Filters]
        CG[Cgroup Limits]
        FS[Filesystem Isolation]
    end

    Code[User Code] --> NS
    NS --> SC
    SC --> CG
    CG --> FS
    FS --> Execute[Restricted Execution]

Isolamento de namespace

Espaço para nome Restrição
PID Não é possível ver outros processos
Rede Sem acesso à rede
Monte Raiz somente leitura, gravações limitadas
Usuário Usuário não root
IPC Sem memória compartilhada

Lista de permissões do Seccomp

Somente syscalls essenciais são permitidos:

// Allowed syscalls
read, write, open, close, fstat, mmap, mprotect,
munmap, brk, rt_sigaction, rt_sigprocmask, 
ioctl, access, exit_group, arch_prctl

// Blocked (examples)
socket, connect, fork, execve, ptrace, 
shmget, msgget, semget

Limites de recursos

Recurso Limite Aplicação
Tempo de CPU Específico do problema cgrupo
Hora da parede Limite de CPU 2x Temporizador
Memória Específico do problema cgrupo
Tamanho do arquivo 10 MB limite
Processos 1 cgrupo
Abrir arquivos 10 limite

Configuração TLS

Requisitos de certificado

  • TLS 1.2 mínimo
  • Somente conjuntos de cifras fortes
  • HSTS habilitado

Configuração Nginx

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;

add_header Strict-Transport-Security "max-age=31536000" always;

TLS de serviço interno

Os serviços usam TLS mútuo:

grader:
  volumes:
    - ./ssl/grader.crt:/etc/omegaup/ssl/grader.crt
    - ./ssl/grader.key:/etc/omegaup/ssl/grader.key
    - ./ssl/ca.crt:/etc/omegaup/ssl/ca.crt

Cabeçalhos de segurança

# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Registro de auditoria

Eventos de login

CREATE TABLE `Identity_Login_Log` (
    `identity_id` int NOT NULL,
    `ip` int UNSIGNED NOT NULL,
    `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
);

Ações Administrativas

As ações críticas são registradas:

  • Mudanças na função do usuário
  • Mudanças na visibilidade do problema
  • Modificações do concurso
  • Resoluções de nomeação de qualidade

Resposta a Incidentes

Modo de bloqueio

O bloqueio de emergência desativa operações confidenciais:

if (OMEGAUP_LOCKDOWN) {
    throw new ForbiddenAccessException('forbiddenInLockdown');
}

Invalidação de Sessão

Forçar logout de todas as sessões:

// Delete all auth tokens for user
\OmegaUp\DAO\AuthTokens::deleteAllByUser($userId);

Documentação Relacionada