240 lines
5.0 KiB
Markdown
240 lines
5.0 KiB
Markdown
---
|
|
name: perfex-security
|
|
description: Segurança para módulos Perfex CRM — validação de input, CSRF, prevenção XSS e protecção contra directory traversal. Baseado apenas na documentação oficial.
|
|
layer: wiki
|
|
---
|
|
|
|
# /perfex-security - Segurança Módulos Perfex CRM
|
|
|
|
Práticas de segurança para módulos. **Zero assumptions, zero hallucinations** - apenas documentação oficial.
|
|
|
|
---
|
|
|
|
## Documentação Base
|
|
|
|
- [Module Security](https://help.perfexcrm.com/module-security/)
|
|
- [CodeIgniter Security](https://codeigniter.com/userguide3/libraries/security.html)
|
|
|
|
---
|
|
|
|
## 1. Prevenção de Acesso Directo
|
|
|
|
**OBRIGATÓRIO em todos os ficheiros PHP:**
|
|
|
|
```php
|
|
<?php
|
|
|
|
defined('BASEPATH') or exit('No direct script access allowed');
|
|
|
|
// Resto do código
|
|
```
|
|
|
|
Isto previne execução directa via URL.
|
|
|
|
---
|
|
|
|
## 2. Prevenção de Directory Listing
|
|
|
|
**Incluir `index.html` vazio em todas as pastas:**
|
|
|
|
```
|
|
modules/meu_modulo/
|
|
├── index.html ← OBRIGATÓRIO
|
|
├── controllers/
|
|
│ └── index.html ← OBRIGATÓRIO
|
|
├── models/
|
|
│ └── index.html ← OBRIGATÓRIO
|
|
├── views/
|
|
│ └── index.html ← OBRIGATÓRIO
|
|
└── libraries/
|
|
└── index.html ← OBRIGATÓRIO
|
|
```
|
|
|
|
**Conteúdo do index.html:**
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>403 Forbidden</title>
|
|
</head>
|
|
<body>
|
|
<p>Directory access is forbidden.</p>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Input Validation (CRÍTICO)
|
|
|
|
### Usar Input Class do CodeIgniter
|
|
|
|
```php
|
|
// CORRECTO - Input class escapa automaticamente
|
|
$name = $this->input->post('name');
|
|
$id = $this->input->get('id');
|
|
$data = $this->input->post(); // Array de todos os POST
|
|
|
|
// ERRADO - Nunca usar $_POST/$_GET directamente
|
|
$name = $_POST['name']; // VULNERÁVEL!
|
|
```
|
|
|
|
### Sanitização Adicional
|
|
|
|
```php
|
|
// Inteiros
|
|
$id = (int) $this->input->post('id');
|
|
|
|
// Escape para output HTML
|
|
$name = html_escape($this->input->post('name'));
|
|
|
|
// Strip tags
|
|
$clean = strip_tags($this->input->post('content'));
|
|
|
|
// XSS clean (built-in)
|
|
$safe = $this->security->xss_clean($this->input->post('data'));
|
|
```
|
|
|
|
---
|
|
|
|
## 4. CSRF Protection
|
|
|
|
O Perfex CRM tem CSRF activado por defeito.
|
|
|
|
### Em Formulários (OBRIGATÓRIO)
|
|
|
|
```php
|
|
<?php echo form_open(admin_url('meu_modulo/save')); ?>
|
|
<!-- form_open() gera token CSRF automaticamente -->
|
|
<input type="text" name="name">
|
|
<button type="submit">Guardar</button>
|
|
<?php echo form_close(); ?>
|
|
```
|
|
|
|
**NUNCA usar HTML `<form>` directo:**
|
|
|
|
```html
|
|
<!-- ERRADO - Sem CSRF token -->
|
|
<form action="..." method="post">
|
|
```
|
|
|
|
### Em AJAX (jQuery)
|
|
|
|
jQuery do Perfex inclui CSRF automaticamente. Para outras bibliotecas:
|
|
|
|
```javascript
|
|
// Obter token CSRF
|
|
var csrfName = '<?php echo $this->security->get_csrf_token_name(); ?>';
|
|
var csrfHash = '<?php echo $this->security->get_csrf_hash(); ?>';
|
|
|
|
// Incluir em requests
|
|
$.ajax({
|
|
url: admin_url + 'meu_modulo/ajax_save',
|
|
type: 'POST',
|
|
data: {
|
|
[csrfName]: csrfHash,
|
|
name: $('#name').val()
|
|
}
|
|
});
|
|
```
|
|
|
|
### Excluir URLs de CSRF (v2.9.0+)
|
|
|
|
Para webhooks que não podem incluir CSRF:
|
|
|
|
```php
|
|
// modules/meu_modulo/config/csrf_exclude_uris.php
|
|
|
|
<?php
|
|
|
|
defined('BASEPATH') or exit('No direct script access allowed');
|
|
|
|
return [
|
|
'meu_modulo/webhook',
|
|
'meu_modulo/api/.*', // Regex suportado
|
|
];
|
|
```
|
|
|
|
---
|
|
|
|
## 5. SQL Injection Prevention
|
|
|
|
### Usar Query Builder (SEMPRE)
|
|
|
|
```php
|
|
// CORRECTO - Query Builder escapa parâmetros
|
|
$this->db->where('id', $id);
|
|
$this->db->where('status', $status);
|
|
$result = $this->db->get(db_prefix() . 'meu_modulo')->result();
|
|
|
|
// CORRECTO - Binding de parâmetros
|
|
$sql = "SELECT * FROM " . db_prefix() . "meu_modulo WHERE id = ? AND status = ?";
|
|
$result = $this->db->query($sql, [$id, $status])->result();
|
|
```
|
|
|
|
### NUNCA Concatenar Input
|
|
|
|
```php
|
|
// ERRADO - SQL Injection vulnerável!
|
|
$id = $_GET['id'];
|
|
$sql = "SELECT * FROM tblmeu_modulo WHERE id = " . $id;
|
|
|
|
// ERRADO - Mesmo com input class
|
|
$id = $this->input->get('id');
|
|
$sql = "SELECT * FROM tblmeu_modulo WHERE id = " . $id; // VULNERÁVEL!
|
|
```
|
|
|
|
---
|
|
|
|
## 6. XSS Prevention
|
|
|
|
### Em Views (SEMPRE)
|
|
|
|
```php
|
|
<!-- CORRECTO - Escape HTML -->
|
|
<td><?php echo html_escape($item->name); ?></td>
|
|
<input value="<?php echo html_escape($item->value); ?>">
|
|
|
|
<!-- ERRADO - XSS vulnerável -->
|
|
<td><?php echo $item->name; ?></td>
|
|
```
|
|
|
|
### Função html_escape()
|
|
|
|
```php
|
|
// Texto simples
|
|
echo html_escape($string);
|
|
|
|
// Para atributos HTML
|
|
echo html_escape($string, true);
|
|
```
|
|
|
|
---
|
|
|
|
## 7. File Upload Security
|
|
|
|
```php
|
|
public function upload()
|
|
{
|
|
// Configurar upload
|
|
$config['upload_path'] = './uploads/meu_modulo/';
|
|
$config['allowed_types'] = 'pdf|doc|docx|xls|xlsx'; // NUNCA permitir php!
|
|
$config['max_size'] = 2048; // KB
|
|
$config['encrypt_name'] = true; // Nome aleatório
|
|
|
|
$this->load->library('upload', $config);
|
|
|
|
if (!$this->upload->do_upload('ficheiro')) {
|
|
// Erro
|
|
$error = $this->upload->display_errors();
|
|
set_alert('danger', $error);
|
|
} else {
|
|
// Sucesso
|
|
$data = $this->upload->data();
|
|
$filename = $data['file_name'];
|
|
}
|
|
}
|
|
```
|
|
|
|
### Tipos Permitidos |