PHP: Troszkę o Security
About ME

- devThursday keeper
- mentor & consultant
Contact me:
in/paweł-radzikowski

Paweł Radzikowski
Señor Developer @
Self-proclaimed code magician
PHP: Troszkę o Security
Knowledge Base
- PHP: The right way
- Survive The Deep End: PHP Security
- blog.sucuri.net
- acunetix.com
- owasp.org
User Authentication
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$userPassword = getUserPassord($username);
$hashPassword = sha1($password);
if($userPassword === $hashPassword) {
exit('Success');
}
echo 'Fail';
Why are common hashing functions such as md5() and sha1() unsuitable for passwords?Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be very fast and efficient. With modern techniques and computer equipment, it has become trivial to "brute force" the output of these algorithms, in order to determine the original input.
Because of how quickly a modern computer can "reverse" these hashing algorithms, many security professionals strongly suggest against their use for password hashing.password_hash()
- bcrypt - PHP5.5
- Argon2i - PHP7.2
- Argon2id - PHP7.3
crypt()
- MD5 crypt
- Standard DES
- Extended DES
- Blowfish

Rainbow Table
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$userPassword = getUserPassord($username);
$hashPassword = password_hash($password, PASSWORD_ARGON2ID);
if($userPassword === $hashPassword) {
exit('Success');
}
echo 'Fail';

===
password_verify
hash_equals



<?php
$username = $_POST['username'];
$password = $_POST['password'];
$userPassword = getUserPassord($username);
if(password_verify($password, $userPassword)) {
exit('Success');
}
echo 'Fail';
Cross Site Scripting (XSS)
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script>...NEVER PUT UNTRUSTED DATA HERE...</script>
<style>...NEVER PUT UNTRUSTED DATA HERE...</style>
</head>
<body>
<!--...NEVER PUT UNTRUSTED DATA HERE...-->
<div ...NEVER PUT UNTRUSTED DATA HERE...=test />
<a href="EVER PUT UNTRUSTED DATA HERE..." />
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script>alert('...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...')</script>
<style>background-url : "javascript:alert('...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...')";</style>
</head>
<body>
<!----><script>alert('...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...')</script>-->
<div onload=alert('...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...') />
<a href="javascript:alert('...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...')" />
</body>
</html>HTML entities
& --> & < --> < > --> > " --> " ' --> ' / --> /
PHP func
htmlspecialchars();
htmlspecialchars_decode();
{ background-url : "javascript:alert('HEHE')"; } // and all other URLs
{ text-size: "expression(alert('HEHE'))"; } // only in IE<a href="javascript:alert('HEHE')">Click me</a>Zawsze waliduj dane !
Welcome to XXI
Content-Security-Policy.com

Dyrektywy
- default-src
- script-src
- style-src
- img-src
- media-src
- connect-src
- report-uri
- form-action
- frame-ancestors
Źródła
- *
- 'none'
- 'self'
- domain.example.com
- *.example.com
- https://cdn.com
- https:
- 'unsafe-eval'
- 'unsafe-inline'
- 'nonce-XXXX'
Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';Injections
- SQL
- OS command
SQL Injection
$dbh->query("SELECT * from admin WHERE login='".$login."' AND password='".$password."';");SELECT * from admin WHERE login='login' AND password='password' OR login='login'; -- ';Jak się obronić?
- Walidacja
- Escape Input
- Parametryzacja zapytań
<?php
if(isset($_POST)) {
switch($_POST['type']) {
case 1:
$type = 1;
break;
case 2:
$type = 2;
break;
default: $type = 0;
}
$users=$dbh->query("SELECT * from admin WHERE type=".$type);
}<?php
$mysqli = new mysqli("localhost","***", "***", "***");
if(isset($_POST)) {
$login=$mysqli->real_escape_string($_POST['login']);
$password=$mysqli->real_escape_string($_POST['password']);
$result=$mysqli->query("SELECT * from admin WHERE login={$login} AND password={$password}");
if($result && $result->fetch_array()) {
echo 'Zalogowany';
} else {
echo 'Niezalogowany';
}<?php
$dbh = new PDO('mysql:host=localhost;dbname=***', '***', '***');
if(isset($_POST)) {
$login=$_POST['login'];
$password=$_POST['password'];
$user=$dbh->prepare("SELECT * from admin WHERE login=:login AND password=:password");
$user->bindValue('login', $login, PDO::PARAM_STR);
$user->bindValue('password', $password, PDO::PARAM_STR);
$user->execute();
if($user->fetchColumn()) {
echo 'Zalogowany';
} else {
echo 'Niezalogowany';
}PREPARE stmt1 FROM 'SELECT * from admin where login=? AND password=?';
SET @login = "admin";
SET @password = "wrongpassword' OR login='admin";
EXECUTE stmt1 USING @login, @password;
DEALLOCATE PREPARE stmt1;OS Command Injection
<?php
exec("ping -c 4 " . $_GET['host'], $output);
echo "<pre>";
print_r($output);
echo "</pre>";<?php
exec(escapeshellcmd("ping -c 4 " . escapeshellarg($_GET['host'])), $output);
echo "<pre>";
print_r($output);
echo "</pre>";Path Traversal
<?php
//http://example.com/images/XXX.jpg
readfile("images/" . $_GET["file"]);<?php
//http://example.com/images/../../etc/passwd
readfile("images/" . $_GET["file"]);
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/usr/bin/nologin
daemon:x:2:2:daemon:/:/usr/bin/nologin
mail:x:8:12:mail:/var/spool/mail:/usr/bin/nologin
ftp:x:14:11:ftp:/srv/ftp:/usr/bin/nologin
http:x:33:33:http:/srv/http:/usr/bin/nologin
nobody:x:99:99:nobody:/:/usr/bin/nologin
systemd-journal-gateway:x:191:191:systemd-journal-gateway:/:/usr/bin/nologin
systemd-timesync:x:192:192:systemd-timesync:/:/usr/bin/nologin
systemd-network:x:193:193:systemd-network:/:/usr/bin/nologin
systemd-bus-proxy:x:194:194:systemd-bus-proxy:/:/usr/bin/nologin
systemd-resolve:x:195:195:systemd-resolve:/:/usr/bin/nologin<?php
$_GET['file'] = '../../etc/passwd';
readfile("images/" . $_GET["file"]);- Walidacja
- Kontrola dostępu do zasobów dysku
- Stosowanie identyfikatorów zamiast nazw
| Payload | Reprezentacja |
|---|---|
| %2e%2e%2f | ../ |
| %2e%2e/ | ../ |
| ..%2f | ../ |
| %2e%2e%5c | ..\ |
| %252e%252e%255c | ..\ |
| ..%255c | ..\ |
| ..%c0%af | ..\ |
| ..%c1%9c | ..\ |
Q/A
PHP: Troszkę o Security
By Paweł Radzikowski
PHP: Troszkę o Security
- 229