Пример класса captcha на php (2)

<?php
/**
* CaptchaV2 File
* Generates CAPTCHA Numbers and Chars Image
* @author Albert Demeter <borex8@hotmail.com>
* @version 2.1
* GNU General Public License (Version 2.1, March 7th, 2006)
*
* based on Hadar Porat's Captcha Numbers class v.1.5 <hpman28@gmail.com>
*
* This program is free software; you can redistribute
* it and/or modify it under the terms of the GNU
* General Public License as published by the Free
* Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

/**
* CaptchaNumbersV2 Class
* @access public
* @author Albert Demeter <borex8@hotmail.com>
* @version 2.0
*/
class CaptchaNumbersV2 {
  var $length = 6;
  var $font = 'fonts/arial.ttf';
  var $size = 15;
  var $angle = 10;
  var $type = 'png';
  var $height = 40;
  var $width = 80;
  var $grid = 7;
  var $string = '';
  var $captchaType = 'mixed';
  
  // automatically calculated based on the percent in the constructor
  var $dotsCount = 0;
  
  // background colors RED, GREEN and BLUE values (provide it as a number between 0-255)
  var $bgColorRed = 240;
  var $bgColorGreen = 240;
  var $bgColorBlue = 240;
  
  // if true then grid is drawn
  var $drawGrid = false;
  
  // if true then every grid line will have a different color
  var $randomGridColor = true;

  // if true then every letter will have a different color
  var $randomLetterColor = true;

  // fonts
  // there is feature of this script that it picks random fonts for each character displayed
  // you should define a fonts folder
  // a folder named fonts within this scripts directory is tested and working.  
  var $fonts_folder = 'fonts/';
  // the range of font size of each letter displayed as pixels. if you choose them same,
  //    fonts will be at that exact size.
  var $font_size_min = 14;
  var $font_size_max = 16;
  // font angles are for placing the fonts at a random angle. high values of angles might result unexpected.
  var $font_angle_min = 0;
  var $font_angle_max = 15;

  /**
  * @return void
  * @param int $length string length
  * @param int $size font size
  * @param String $type image type
  * @param String $captchaType text contain digits, chars or mixed
  * @param int $dotsPercent random pixels generated in image
  * @desc generate the main image
  */  
  function CaptchaNumbersV2($length = '', $size = '', $type = '', $captchaType = '', $dotsPercent = 10) {
    if ($length!='') $this -> length = $length;
    if ($size!='') $this -> size = $size;
    if ($type!='') $this -> type = $type;
    if ($captchaType!='') $this -> captchaType = $captchaType;

    $this -> width = $this -> length * $this -> size + $this -> grid + $this -> grid;
    $this -> height = $this -> size + (2 * $this -> grid);

    // dots count equals #% of all points in the image
    $this -> dotsCount = round(($this -> width * $this -> height) * $dotsPercent / 100);

    $this -> generateString();
  }

  /**
  * @return void
  * @desc display captcha image
  */    
  function display() {
    $this -> sendHeader();
    $image = $this -> generate();

    switch ($this-> type) {
      case 'jpeg': imagejpeg($image); break;
      case 'png': imagepng($image); break;
      case 'gif': imagegif($image); break;
      default:   imagepng($image); break;
    }
  }

  // following function is gathered from php.net, author is "fankounter@libero.it"
  // it is used for gathering the fonts from the spesicfied folder. I have modifeid it slightly
  function ls($__dir="./",$__pattern="*.*")
  {
    settype($__dir, "string");
    settype($__pattern, "string");
    $__ls = array();
    $__regexp = preg_quote($__pattern,"/");
    $__regexp = preg_replace("/[\\x5C][\x2A]/",".*",$__regexp);
    $__regexp = preg_replace("/[\\x5C][\x3F]/",".", $__regexp);
    if(is_dir($__dir))
     if(($__dir_h=@opendir($__dir))!==FALSE)
     {
     while(($__file=readdir($__dir_h))!==FALSE)
      if(preg_match("/^".$__regexp."$/",$__file))
      array_push($__ls,$__file);
     closedir($__dir_h);
     sort($__ls,SORT_STRING);
     }
    return $__ls;
  }
  
  // function picks a random font for each letter each time
  function random_font() {
    $fonts = $this -> ls($this -> fonts_folder, "*.ttf");
    $rand = mt_rand(0, sizeof($fonts)-1);
    $this -> font = $this -> fonts_folder.$fonts[$rand];
  }

  // the font size would be determined randomly within the limits defined above.
  function random_font_size() {
    $this -> size = mt_rand($this -> font_size_min, $this -> font_size_max );
  }

  // the angle would be determined randomly within the limits defined above.
  function random_font_angle() {
    $this -> angle = mt_rand($this -> font_angle_min, $this -> font_angle_max );
  }

  /**
  * @return Image
  * @desc generate the image
  */    
  function generate() {
    $image = ImageCreate($this -> width, $this -> height) or die("Cannot Initialize new GD image stream");

    // colors
    $background_color = ImageColorAllocate($image, $this -> bgColorRed, $this -> bgColorGreen, $this -> bgColorBlue);
    if (!$this -> randomLetterColor)
    {
     $net_color_1 = ImageColorAllocate($image, 10, 200, 10);
     $net_color_2 = ImageColorAllocate($image, 200, 10, 10);
    }
    if (!$this -> randomLetterColor)
    {
     $stringcolor_1 = ImageColorAllocate($image, 150, 150, 150);
     $stringcolor_2 = ImageColorAllocate($image, 120, 120, 250);
    }

    if ($this -> drawGrid)
     for ($i = $this -> grid; $i < $this -> height; $i+=$this -> grid)
      {
      if ($this -> randomGridColor)
      {
       $net_color_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
       $net_color_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
      }
        if ($i%2) ImageLine($image, 0, $i, $this -> width, $i, $net_color_1);
          else ImageLine($image, 0, $i, $this -> width, $i, $net_color_2);
      }

    // make the text
    $str = $this -> getString();
    $x = $this -> grid;
    for($i = 0, $n = strlen($str); $i < $n; $i++)
    {
     if ($this -> randomLetterColor)
     {
      $stringcolor_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
      $stringcolor_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
     }
      $this -> random_font();
      $this -> random_font_size();
      $this -> random_font_angle();
       if ($i%2) ImageTTFText($image, $this -> size, $this -> angle, $x, $this -> size + $this -> grid - mt_rand(0, 5), $stringcolor_1, $this -> font, $str{$i} );
         else ImageTTFText($image, $this -> size, $this -> angle, $x, $this -> size + $this -> grid + mt_rand(0, 5), $stringcolor_2, $this -> font, $str{$i} );
      $x = $x + $this -> size;
    }
    
    // grid
    if ($this -> drawGrid)
     for ($i = $this -> grid; $i < $this -> width; $i+=$this -> grid)
      {
      if ($this -> randomGridColor)
      {
       $net_color_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
       $net_color_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
      }
        if ($i%2) ImageLine($image, $i, 0, $i, $this -> height, $net_color_1);
          else ImageLine($image, $i, 0, $i, $this -> height, $net_color_2);
      }
    for ($i = 0; $i < $this -> dotsCount; $i++)
    {
       $x = rand(0, $this -> width - 1);
      $y = rand(0, $this -> height - 1);
      $rgbIndex = imagecolorat($image, $x, $y);
      $rgb = imagecolorsforindex($image, $rgbIndex);
      //print $x . ' x ' . $y . ' : ' . $rgbIndex . '(' . $rgb['red'] . '-' . $rgb['green'] . '-' . $rgb['blue'] . ')<br>';

      // if background color create random pixel color
      if ($rgb['red'] == $this -> bgColorRed
           && $rgb['green'] == $this -> bgColorGreen
          && $rgb['blue'] == $this -> bgColorBlue)
      {
         $dotColor = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));
      }
      else
      {
         // not background color then generate a close shade color
        $rgb['red'] = $rgb['red'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['red']);
        if ($rgb['red'] < 0 || $rgb['red'] > 255) $rgb['red'] = mt_rand(0, 255);

        $rgb['green'] = $rgb['green'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['green']);
        if ($rgb['green'] < 0 || $rgb['green'] > 255) $rgb['green'] = mt_rand(0, 255);

        $rgb['blue'] = $rgb['blue'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['blue']);
        if ($rgb['blue'] < 0 || $rgb['blue'] > 255) $rgb['blue'] = mt_rand(0, 255);

         $dotColor = ImageColorAllocate($image, $rgb['red'], $rgb['green'], $rgb['blue']);
      }
      ImageSetPixel($image, $x, $y, $dotColor);
    }

    return $image;
  }

  /**
  * @return String
  * @desc generate the string
  */  
  function generateString() {
    $string = $this->create_random_value($this -> length, $this -> captchaType);
    $this -> string = $string;
    return true;
  }

  /**
  * @return void
  * @desc send image header
  */
  function sendHeader() {
    header('Content-type: image/' . $this -> type);
  }

  /**
  * @return String
  * @desc return the string
  */  
  function getString() {
    return $this -> string;
  }

 function create_random_value($length, $type = 'mixed') {
  if ( ($type != 'mixed') && ($type != 'chars') && ($type != 'digits')) return false;

  $rand_value = '';
  while (strlen($rand_value) < $length) {
   if ($type == 'digits') {
    $char = mt_rand(0,9);
   } else {
    $char = chr(mt_rand(0,255));
   }
   if ($type == 'mixed') {
    if (preg_match('/^[a-z0-9]$/i', $char)) $rand_value .= $char;
   } elseif ($type == 'chars') {
    if (preg_match('/^[a-z]$/i', $char)) $rand_value .= $char;
   } elseif ($type == 'digits') {
    if (preg_match('/^[0-9]$/', $char)) $rand_value .= $char;
   }
  }
  return $rand_value;
 }  
}
?>

Добавлено: 24 Июня 2018 09:11:32 Добавил: Андрей Ковальчук

Примеры использования HTTP/1.1 304 Not Modified

Для разгрузки канала клиента за счет кеширования браузером страниц можно использовать следующий код, позволяющий браузеру не загружать те страницы, которые у него уже есть в кэше. Аналогично можно сделать и для изображений. C помощью директив файла .htaccess сделана настройка чтобы все файлы с сервера отправлялись через index.php:

<?php
global $url;
$url    = $_SERVER['REQUEST_URI'];

if($url==""||$url=="/")
   $url="index.htm" ;
else $url=substr($url, 1);

if ( !file_exists( $url ) )     { header("HTTP/1.0 404 Not Found"); exit();}

// Получаем время последней модификации кэш-файла
$lastModified = max(filemtime($url),filemtime('index.php')); $slastModified = gmdate('D, d M Y H:i:s', $lastModified) . ' GMT';
// Выдаём заголовок HTTP Last-Modified
header('Last-Modified: ' . $slastModified ); 
// Получаем заголовки запроса клиента - только для Apache
$headers = getallheaders(); 
if (isset($headers['If-Modified-Since'])) {  // Разделяем If-Modified-Since (Netscape < v6 отдаёт их неправильно) 
   $modifiedSince = explode(';', $headers['If-Modified-Since']); 
   // Преобразуем запрос клиента If-Modified-Since в таймштамп
   $modifiedSince = strtotime($modifiedSince[0]); 
   // Сравниваем время последней модификации контента с кэшем клиента
   if ($lastModified <= $modifiedSince) { header('HTTP/1.1 304 Not Modified'); exit(); } // Разгружаем канал передачи данных!
   } 
echo "<DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n<HTML>\n";
echo "<HEAD>\n";
echo "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=windows-1251\">\n";
echo "<meta http-equiv=\"Last-Modified\" content=\"".$slastModified."\">\n";
?>

.htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} !index\.php$
RewriteCond %{REQUEST_URI} !\.jpg$
RewriteCond %{REQUEST_URI} !\.gif$
RewriteCond %{REQUEST_URI} !\.png$
RewriteCond %{REQUEST_URI} !\.js$
RewriteCond %{REQUEST_URI} !\.txt$
RewriteCond %{REQUEST_URI} !\.xml$
RewriteCond %{REQUEST_URI} !\.html$
RewriteCond %{REQUEST_URI} !\.htm$
RewriteCond %{REQUEST_URI} !\.mid$
RewriteCond %{REQUEST_URI} !\.avi$
RewriteCond %{REQUEST_URI} !\.css$
RewriteRule ^(.*)$ /index.php [L]

Добавлено: 29 Мая 2018 19:31:22 Добавил: Андрей Ковальчук

Пишем скрипт регистрации и авторизации пользователей для сайта на PHP

Сегодня напишу как сделать авторизацию на сайте с помощью моего простого скрипта.

Скрипт написан на PHP, для хранения информации о пользователях я использовал базу данных MySQL.

Для удобства создадим файл в котором будет осуществляться подключение к БД. Этот файл мы будем инклудить ко всем остальным скриптам где требуется связь с БД.

Содержимое файла «connectdb.php»:

<?
//данные о хосте, пользователе и базе данных
$host = 'localhost';
$user = 'root'; 
$pass = 'pass'; 
$dbname = 'test';
 
// подключаемся и выбираем бд, которую указали выше
if(!mysql_connect($host,$user,$pass))
  die('Не удалось подключиться к серверу MySql!');
elseif(!mysql_select_db($dbname))
  die('Не удалось выбрать БД!');
?>

Теперь напишем скрипт инсталяции, который будет создавать таблицу необходимую для хранения информации о пользователях.

Содержимое файла со скриптом инсталяции «install.php»:
<?
include('connectdb.php');// подключение к серверу MySql и выбор БД
 
// sql-скрипт для создания таблицы
$sql='CREATE TABLE users(
  id INT NOT NULL AUTO_INCREMENT,
  login VARCHAR(15),
  pass TEXT,
  email VARCHAR(150),
  PRIMARY KEY(id)
);';
 
//выполняем sql-запрос
if(!mysql_query($sql)){
  echo 'Ошибка при создании таблицы в БД!';
} else {
  echo 'Всё прошло отлично, таблица создана!';
}
?>

Пользователей нужно регистрировать — напишем для этого скрипт! Сразу скажу, что все вводимые данные не проверяются на правильность и скрипт уязвим для взломов, поэтому вам придётся самим доработать его как нужно.

Регистрация заключается в добавлении информации о пользователе (Логин, пароль…) в базу данных.

Создадим файл «register.php» и добавим в него следующее:
<?
include('connectdb.php');// подключение к серверу MySql и выбор БД
 
if (($_POST['login']!='') || 
    ($_POST['pass1']!='') || 
    ($_POST['pass2']!='') || 
    ($_POST['email']!='')) { // если все данные для регистрации введены, то продолжаем
    $pass1 = $_POST['pass1'];
    $pass2 = $_POST['pass2'];
 
    if (strcmp($pass1, $pass2) == 0) {// если пароли совпадают, то продолжаем
      $login = $_POST['login'];
      $email = $_POST['email'];
 
      //проверяем наличие в БД пользователя с логином $login
      $sql='SELECT * FROM users WHERE login='.$login; // скрипт для поиска по логину в таблице users
      if (!($res=mysql_query($sql)) || (mysql_num_rows($res) == 0)) { // если количество найденых записей ноль, то продолжаем
	  // sql-скрипт для добавления даных в таблицу
	  $sql = 'INSERT INTO users(login, pass, email) 
		  VALUES("'.$login.'", "'.$pass1.'", "'.$email.'")';
	  if(mysql_query($sql)) {// выполняем скрипт
	    echo 'Пользователь '.$_POST['login'].' успешно зарегистрирован! <a href="/index.php">Форма для входа.';
	  } else {
	    echo 'При регистрации произошла ошибка, <a href="/register.php">повторите попытку</a>.';
	  }
	} else echo 'Пользователь с таким логином уже зарегистрирован!';
    } else echo 'Введенные пароли не совпадают, <a href="/register.php">повторите попытку</a>.';
} else {
?>
  <form method='post' action='/register.php'>
  Введите Логин: <input type='text' size='30' name='login' /><br />
  Введите e-mail: <input type=text size=30 name='email' /><br />
  Пароль: <input type='password' name='pass1' size='30' /><br />
  Повторите пароль: <input type='password' name='pass2' size='30' /><br />
  <input type='submit' value='Регистрация' />
< ?  
}
?>
</form>

Далее нам нужно создать форму для авторизации и скрипт управления авторизацией.

Всё это будет находиться в файле «index.php»:
<?
/*!!!Чтобы не повредить работоспособности 
    скрипта выше этого комментария 
    не размещайте вообще ничего!!!*/
include('connectdb.php');// подключение к серверу MySql и выбор БД
$userinfo='';
$state='0';
if( (isset($_COOKIE['login'])) & (isset($_COOKIE['pass'])) ) {// если в куках лежит логин и зашифрованый пароля
  if (!isset($_GET['exit'])) {// если кнопка выход не была нажата
    $login=$_COOKIE['login'];
    $pass=$_COOKIE['pass'];
 
    // проверяем наличие пользователя в БД и достаём оттуда пароль
    $sql="SELECT id, pass FROM users WHERE login='$login'";
    $res=mysql_query($sql);
    if(mysql_num_rows($res)>0){// если пользователь есть в БД
      $userinfo = mysql_fetch_array($res);// в этой переменной лежит пароль из БД
      if(strcmp($pass,md5($userinfo['pass'])) == 0) { //проверяем схожесть пароля из БД с паролем из куков
 
	// достаём все данные из БД
	$sql="SELECT * FROM users WHERE login='$login'";
	$res=mysql_query($sql);
	$userinfo=mysql_fetch_array($res); // в этой переменной будет лежать вся информация о пользователе из БД
	$time=time();
	// устанавливаем куки для запоминания статуса пользователя
	setcookie("login",$login,$time+1800);
	setcookie("pass",$pass,$time+1800);
	$state = 1;// статус, если 1, тогда пользователь авторизован
      }
    }
  } else {
    //обнуляем куки, если была нажата кнопка выход
    setcookie("login");
    setcookie("pass");
  }
}
if($state != 1) {// если после проверки куков, оказалось, что пользователь не авторизован, то идем дальше
  if( (isset($_POST['login'])) & (isset($_POST['pass'])) ){ // если пользователь ввёл логин и пароль
  $login = $_POST['login'];	
 
  // проверяем наличие пользователя в БД и достаём оттуда пароль
  $sql = "SELECT id, pass FROM users WHERE login='$login'";
  $res = mysql_query($sql);
    if(mysql_num_rows($res)>0) {// если пользователь есть в БД
      $userinfo = mysql_fetch_array($res);// в этой переменной лежит пароль из БД и номер пользователя
      $pass = $_POST['pass'];
      if(strcmp($pass,$userinfo['pass'])==0){
 
	// достаём все данные из БД
	$sql="SELECT * FROM users WHERE login='$login'";
	$res=mysql_query($sql);
	$userinfo=mysql_fetch_array($res);// в этой переменной будет лежать вся информация о пользователе из БД
	$time=time();
	// устанавливаем куки для запоминания статуса пользователя, пароль шифруем
	setcookie("login", $login, $time+1800);
	setcookie("pass", md5($pass), $time+1800);
	$state = 1;// статус, если 1, тогда пользователь авторизован
      }
    }
  }
}
if($state != 1) {
?>
<form method="post" action="/index.php">
Логин: <input type="text" size="30" name="login"/><br />
Пароль: <input type="password" name="pass" size="30"/><br />
<input type="submit" value="Войти"/>
</form>
<br /><a href="/register.php">Регистрация</a>
< ?
} else {
  echo 'Вы вошли на сайт!<br /> Ваш Логин: '.$userinfo["login"].'<br />Выш E-mail: '.$userinfo["email"].'<br /> <a href="/index.php?exit=y">Выход</a>';
}
?>

Если нужно проверить авторизован пользователь или нет, то проверяем переменную $state, она должна быть ровна 1. В массиве $userinfo содержится вся информация из БД об авторизованном пользователе.

Теперь проверим как это всё работает. В файле «connectdb.php» укажите свои настройки БД.

После этого нужно создать таблицу, для этого следуем в браузере «http://вашсайт.com/install.php» и смотрим результат выполнения скрипта.

Добавлено: 24 Мая 2018 20:43:20 Добавил: Андрей Ковальчук

Как защитится от SQL иньекций, xss атак на PHP

Задача: создание функии для перехвата возможных xss атак и подключение к любому сайту на php.

Вариантом решения будет использование следующей функции.

function antihack () {  
  
$uri = $_SERVER['REQUEST_URI']; //определяем адрес запрашиваемой страницы  
  
$arr_u = explode("?", $uri ); //разделяем адрес на массив  
$url = $arr_u[0];  //того что до знака ?   
$p_url = $arr_u[1]; // и того что после  
  
  
$inj='/script|http|<|>|<|>|SELECT|UNION|UPDATE|AND|exe|exec|INSERT|tmp/i'; //это паттерн возможных типов атак в адресе (их можно дополнить своими)  
  
  
if (preg_match($inj, $p_url )) { // ищем патерн в нашем адресе, в том что за знаком ?  
  
    die("Hacking attempt!"); //если находим - посылаем куда подальше :=)  
}  
}  
  
  
antihack (); //Вызов функции

Желательно разместить этот скрипт в самом начале вашего кода. Дабы избежать попадания всяких гадостей на сайт и особенно в БД.

Добавлено: 24 Мая 2018 20:12:28 Добавил: Андрей Ковальчук

Пример класса captcha на php (2)

<?php
/**
* CaptchaV2 File
* Generates CAPTCHA Numbers and Chars Image
* @author Albert Demeter <borex8@hotmail.com>
* @version 2.1
* GNU General Public License (Version 2.1, March 7th, 2006)
*
* based on Hadar Porat's Captcha Numbers class v.1.5 <hpman28@gmail.com>
*
* This program is free software; you can redistribute
* it and/or modify it under the terms of the GNU
* General Public License as published by the Free
* Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

/**
* CaptchaNumbersV2 Class
* @access public
* @author Albert Demeter <borex8@hotmail.com>
* @version 2.0
*/

class CaptchaNumbersV2 {
  var $length = 6;
  var $font = 'fonts/arial.ttf';
  var $size = 15;
  var $angle = 10;
  var $type = 'png';
  var $height = 40;
  var $width = 80;
  var $grid = 7;
  var $string = '';
  var $captchaType = 'mixed';
  
  // automatically calculated based on the percent in the constructor
  var $dotsCount = 0;
  
  // background colors RED, GREEN and BLUE values (provide it as a number between 0-255)
  var $bgColorRed = 240;
  var $bgColorGreen = 240;
  var $bgColorBlue = 240;
  
  // if true then grid is drawn
  var $drawGrid = false;
  
  // if true then every grid line will have a different color
  var $randomGridColor = true;

  // if true then every letter will have a different color
  var $randomLetterColor = true;

  // fonts
  // there is feature of this script that it picks random fonts for each character displayed
  // you should define a fonts folder
  // a folder named fonts within this scripts directory is tested and working.  
  var $fonts_folder = 'fonts/';
  // the range of font size of each letter displayed as pixels. if you choose them same,
  //    fonts will be at that exact size.
  var $font_size_min = 14;
  var $font_size_max = 16;
  // font angles are for placing the fonts at a random angle. high values of angles might result unexpected.
  var $font_angle_min = 0;
  var $font_angle_max = 15;

  /**
  * @return void
  * @param int $length string length
  * @param int $size font size
  * @param String $type image type
  * @param String $captchaType text contain digits, chars or mixed
  * @param int $dotsPercent random pixels generated in image
  * @desc generate the main image
  */  
  function CaptchaNumbersV2($length = '', $size = '', $type = '', $captchaType = '', $dotsPercent = 10) {

    if ($length!='') $this -> length = $length;
    if ($size!='') $this -> size = $size;
    if ($type!='') $this -> type = $type;
    if ($captchaType!='') $this -> captchaType = $captchaType;

    $this -> width = $this -> length * $this -> size + $this -> grid + $this -> grid;
    $this -> height = $this -> size + (2 * $this -> grid);
    
    // dots count equals #% of all points in the image
    $this -> dotsCount = round(($this -> width * $this -> height) * $dotsPercent / 100);
    
    $this -> generateString();
  }

  /**
  * @return void
  * @desc display captcha image
  */    
  function display() {
    $this -> sendHeader();
    $image = $this -> generate();

    switch ($this-> type) {
      case 'jpeg': imagejpeg($image); break;
      case 'png': imagepng($image); break;
      case 'gif': imagegif($image); break;
      default:   imagepng($image); break;
    }
  }

// following function is gathered from php.net, author is "fankounter@libero.it"
  // it is used for gathering the fonts from the spesicfied folder. I have modifeid it slightly
  function ls($__dir="./",$__pattern="*.*")
  {
    settype($__dir, "string");
    settype($__pattern, "string");
    $__ls = array();
    $__regexp = preg_quote($__pattern,"/");
    $__regexp = preg_replace("/[\\x5C][\x2A]/",".*",$__regexp);
    $__regexp = preg_replace("/[\\x5C][\x3F]/",".", $__regexp);
    if(is_dir($__dir))
     if(($__dir_h=@opendir($__dir))!==FALSE)
     {
     while(($__file=readdir($__dir_h))!==FALSE)
      if(preg_match("/^".$__regexp."$/",$__file))
      array_push($__ls,$__file);
     closedir($__dir_h);
     sort($__ls,SORT_STRING);
     }
    return $__ls;
  }
  
  // function picks a random font for each letter each time
  function random_font() {
  
    $fonts = $this -> ls($this -> fonts_folder, "*.ttf");
    
    $rand = mt_rand(0, sizeof($fonts)-1);
    
    $this -> font = $this -> fonts_folder.$fonts[$rand];
  }
  
  // the font size would be determined randomly within the limits defined above.
  function random_font_size() {
  
    $this -> size = mt_rand($this -> font_size_min, $this -> font_size_max );
  }
  
  // the angle would be determined randomly within the limits defined above.
  function random_font_angle() {
  
    $this -> angle = mt_rand($this -> font_angle_min, $this -> font_angle_max );
  }
  
  /**
  * @return Image
  * @desc generate the image
  */    
  function generate() {
    $image = ImageCreate($this -> width, $this -> height) or die("Cannot Initialize new GD image stream");
    
    // colors
    $background_color = ImageColorAllocate($image, $this -> bgColorRed, $this -> bgColorGreen, $this -> bgColorBlue);
    if (!$this -> randomLetterColor)
    {
     $net_color_1 = ImageColorAllocate($image, 10, 200, 10);
     $net_color_2 = ImageColorAllocate($image, 200, 10, 10);
    }
    if (!$this -> randomLetterColor)
    {
     $stringcolor_1 = ImageColorAllocate($image, 150, 150, 150);
     $stringcolor_2 = ImageColorAllocate($image, 120, 120, 250);
    }

    if ($this -> drawGrid)
     for ($i = $this -> grid; $i < $this -> height; $i+=$this -> grid)
      {
      if ($this -> randomGridColor)
      {
       $net_color_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
       $net_color_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
      }
        if ($i%2) ImageLine($image, 0, $i, $this -> width, $i, $net_color_1);
          else ImageLine($image, 0, $i, $this -> width, $i, $net_color_2);
      }

    // make the text
    $str = $this -> getString();
    $x = $this -> grid;
    for($i = 0, $n = strlen($str); $i < $n; $i++)
    {
     if ($this -> randomLetterColor)
     {
      $stringcolor_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
      $stringcolor_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
     }
      $this -> random_font();
      $this -> random_font_size();
      $this -> random_font_angle();
       if ($i%2) ImageTTFText($image, $this -> size, $this -> angle, $x, $this -> size + $this -> grid - mt_rand(0, 5), $stringcolor_1, $this -> font, $str{$i} );
         else ImageTTFText($image, $this -> size, $this -> angle, $x, $this -> size + $this -> grid + mt_rand(0, 5), $stringcolor_2, $this -> font, $str{$i} );
      $x = $x + $this -> size;
    }
    
    // grid
    if ($this -> drawGrid)
     for ($i = $this -> grid; $i < $this -> width; $i+=$this -> grid)
      {
      if ($this -> randomGridColor)
      {
       $net_color_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
       $net_color_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
      }
        if ($i%2) ImageLine($image, $i, 0, $i, $this -> height, $net_color_1);
          else ImageLine($image, $i, 0, $i, $this -> height, $net_color_2);
      }

    for ($i = 0; $i < $this -> dotsCount; $i++)
    {
       $x = rand(0, $this -> width - 1);
      $y = rand(0, $this -> height - 1);
      $rgbIndex = imagecolorat($image, $x, $y);
      $rgb = imagecolorsforindex($image, $rgbIndex);
      //print $x . ' x ' . $y . ' : ' . $rgbIndex . '(' . $rgb['red'] . '-' . $rgb['green'] . '-' . $rgb['blue'] . ')<br>';

      // if background color create random pixel color
      if ($rgb['red'] == $this -> bgColorRed
           && $rgb['green'] == $this -> bgColorGreen
          && $rgb['blue'] == $this -> bgColorBlue)
      {
         $dotColor = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));
      }
      else
      {
         // not background color then generate a close shade color
        $rgb['red'] = $rgb['red'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['red']);
        if ($rgb['red'] < 0 || $rgb['red'] > 255) $rgb['red'] = mt_rand(0, 255);

        $rgb['green'] = $rgb['green'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['green']);
        if ($rgb['green'] < 0 || $rgb['green'] > 255) $rgb['green'] = mt_rand(0, 255);

        $rgb['blue'] = $rgb['blue'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['blue']);
        if ($rgb['blue'] < 0 || $rgb['blue'] > 255) $rgb['blue'] = mt_rand(0, 255);

         $dotColor = ImageColorAllocate($image, $rgb['red'], $rgb['green'], $rgb['blue']);
      }
      ImageSetPixel($image, $x, $y, $dotColor);
    }
    
    return $image;
  }


  /**
  * @return String
  * @desc generate the string
  */  
  function generateString() {
    $string = $this->create_random_value($this -> length, $this -> captchaType);
    $this -> string = $string;
    return true;
  }


  /**
  * @return void
  * @desc send image header
  */
  function sendHeader() {
    header('Content-type: image/' . $this -> type);
  }
  
  /**
  * @return String
  * @desc return the string
  */  
  function getString() {
    return $this -> string;
  }
  
  
 function create_random_value($length, $type = 'mixed') {
  if ( ($type != 'mixed') && ($type != 'chars') && ($type != 'digits')) return false;

  $rand_value = '';
  while (strlen($rand_value) < $length) {
   if ($type == 'digits') {
    $char = mt_rand(0,9);
   } else {
    $char = chr(mt_rand(0,255));
   }
   if ($type == 'mixed') {
    if (preg_match('/^[a-z0-9]$/i', $char)) $rand_value .= $char;
   } elseif ($type == 'chars') {
    if (preg_match('/^[a-z]$/i', $char)) $rand_value .= $char;
   } elseif ($type == 'digits') {
    if (preg_match('/^[0-9]$/', $char)) $rand_value .= $char;
   }
  }

  return $rand_value;
 }  
}
?>

Добавлено: 21 Мая 2018 07:39:31 Добавил: Андрей Ковальчук

Способы защиты от sql инъекций

Sql injection - Внедрения sql кода в запрос.
Данная уязвимость позволяет выполнить почти любой sql запрос и получить информацию о базах, таблицах и данных.
Что в итоге приведёт получения таблицы с пользователям и расшифровке ихних паролей.
Для защиты от sql мы должны фильтровать входные данные $_POST запроса, $_GET запроса, сессий($_SESSION) и кук($_COOKIE).
Примечания: в обычном виде опасность не несёт, но если используется в sql запросах то нужно получаемые данные отфильтровать.
Для защиты от sql инъекций используйте функцию mysql_real_escape_string
Пример:

mysql_query("SELECT * FROM table WHERE url='".mysql_real_escape_string($_GET['url'])."'");

Функция str_replace:
str_replace("'","\'", $_GET['url']);

Можно написать одну функцию:
function safe($var){
         
        if(is_array($var)){
             
            foreach($var as $k => $v){
                 
                if(is_array($k))
                    $res[safe($k)] = str_replace("'","\'",htmlspecialchars($v));
                elseif(is_array($v))   
                    $res[str_replace("'","\'",htmlspecialchars($k))] = safe($v);
                elseif(is_array($k) and is_array($v))  
                    $res[safe($v)] = safe($k);
                    else
                        $res[str_replace("'","\'",htmlspecialchars($k))] = str_replace("'","\'",htmlspecialchars($v));
            }
             
        }
        else $res = str_replace("'","\'",htmlspecialchars($var));
        return $res;
    }

Данная функция защит вас также от xss уязвимости, но чтобы она вас защитила вам нужно прописать с верху файла index.php саму функцию и этот код.
$_POST = safe($_POST);
$_GET = safe($_GET);
$_SESSION = safe($_SESSION);

Если вы пропишите данный код, то вам не нужно больше писать не где функцию для защиты от sql.

Добавлено: 20 Мая 2018 21:25:47 Добавил: Андрей Ковальчук

Пишем восстановление пароля на php

Пишем восстановление пароля на phpЕсли вы пишите свою CMS и незнаете как организовать восстановление пароля то эта статья для вас. Для начала давайте определимся с алгоритмом работы.

1. Создаем форму куда пользователь будет вписывать свой логин для востановления
2. Проверяем есть ли пользователь в базе
3. Если юзер есть в базе, то генерируем новый пароль.
4. Для безопасности я советую вам хранить пароли в зашифрованом виде. Поэтому перегоняем в md5 хеш.
5. Переписываем пороль в базу уже хэшированым
6. Шлём пороль на это мыло

Вот и всё. И так начнем. Создадим файл lostpass.php и в него впишем сдедующий код:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<head>
<title>Восстановление пароля - Админцентр</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="images/siteico0.ico" type="image/x-icon" />

<style type="text/css" media="all">
* { margin: 0; padding: 0; }
body {background: #fAfAfA; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12px;}
img {border:none;}
#conteiner {width: 400px; margin: 7em auto;}
#conteiner .loform {
    padding: 16px 16px 16px 16px;
    font-weight: normal;
    -moz-border-radius: 11px;
    -khtml-border-radius: 11px;
    -webkit-border-radius: 11px;
    border-radius: 5px;
    background: #fff;
    border: 1px solid #e5e5e5;
    -moz-box-shadow: rgba(200,200,200,1) 0 4px 18px;
    -webkit-box-shadow: rgba(200,200,200,1) 0 4px 18px;
    -khtml-box-shadow: rgba(200,200,200,1) 0 4px 18px;
    box-shadow: rgba(200,200,200,1) 0 4px 18px;
}
#conteiner .mess {
    margin-bottom: 10px;
    padding: 10px;
    font-weight: normal;
    -moz-border-radius: 5px;
    -khtml-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    border: 1px solid;
    -moz-box-shadow: rgba(200,200,200,1) 0 4px 18px;
    -webkit-box-shadow: rgba(200,200,200,1) 0 4px 18px;
    -khtml-box-shadow: rgba(200,200,200,1) 0 4px 18px;
    box-shadow: rgba(200,200,200,1) 0 4px 18px;
    color:#000;
    font-family:Verdana, Arial, Helvetica, sans-serif;
    font-size:11px;
}


#conteiner .loform p {color:#808080; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:14px; margin:5px;}
#conteiner .loform input {background:#fafafa; border:1px solid #cccccc; color:#666666; padding:4px; width:98%; font-size:25px; margin-bottom:20px;}
#conteiner .loform input.submit {margin-top:-16px; width:74px; height:64px; border: 1 px; text-align:right; vertical-align:top;}
#conteiner .loform a {color: #bcbcbc; text-decoration: none;}
#conteiner .loform a:hover {color:#d7722f;}

#conteiner .logo {text-align:center; padding-bottom:20px;}
</style>
</head>
<body>
<div id="conteiner">
    <div class="logo">
      <p><strong>Восстановление пароля</strong></p>
    </div>

<div class="loform">
            <form name="form1" method="post" action="lostpass.php">
            <p>Логин <input ype="text" name="username" size="40" /></p>
            <p>

                <input type="submit" value="востановить" size="40" name="go">

            </p>
        </form>
        
    </div>
</div>
</body>
</html>

<?php    

//подключаем базу в моём случае

$settings_dir = "../settings"; include "$settings_dir/database.php";


$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
$mail = mysql_real_escape_string($_POST['mail']);

// проверяем, если юзер в таблице с таким же логином
    $query = "SELECT `user_id`
                FROM `users`
                WHERE `username`='{$username}'
                LIMIT 1";
    $sql = mysql_query($query) or die(mysql_error());
    if (mysql_num_rows($sql)==1)
    {
//если есть
//генерируем пороль        
$simvols = array ("0","1","2","3","4","5","6","7","8","9",
                        "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
                        "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
      for ($key = 0; $key < 6; $key++)
        {
          shuffle ($simvols);
          $string = $string.$simvols[1];

        }

//перегоняем в md5 хэш
$pass = md5(md5($string));

//переписываем пороль в базе уже хэшированый

$query = "UPDATE `users`
                    SET
                        `password`='{$pass}'
                                                   WHERE `username`='{$username}' ";
        $sql = mysql_query($query) or die(mysql_error());

//получаем мыло из базы для нашего пользователя

$query = "SELECT `mail`
                FROM `users`
                                 WHERE
                `username`='{$username}'
                LIMIT 1";
    $sql = mysql_query($query) or die(mysql_error());

$row = mysql_fetch_assoc($sql);
$mail = $row['mail'];

//шлём пороль на это мыло

mail($mail, "Запрос на востонавление пороля", "Здравствуйте $login ваш новый пороль : $string");

    }



?>

Добавлено: 20 Мая 2018 07:07:49 Добавил: Андрей Ковальчук

Как защитить сайт от взлома. Самый простой способ :)

Как защитить сайт от взлома. Самый простой способ :) Часто случается так, что злоумышленник зная структуру файлов и папок вашего сайта, может обратиться непосредственно к подключаемому файлу и получить доступ на сервер. Что бы этого не допустить необходимо знать как защитить сайт от взлома проверенным способом:

1. В главных файлах, таких как index.php, установить константу:

define('MySite','1');

2. Во всех файлах, которые мы подключаем к главному файлу проверить, существует ли такая константа. Если такой константы нет, то вывести необходимое сообщение и остановить выполнение скрипта.
defined('MySite') or die('Вы попытались получить несанкционированный доступ к файлу. Пожалуйста вернитесь на главную страницу.');

Вот и все. Такая незамысловатая конструкция поможет сохранить ваш сайт в целостности и сохранности.

P.S. Разработчики DLE используют такую структуру для защиты своей CMS.

Добавлено: 20 Мая 2018 07:03:37 Добавил: Андрей Ковальчук

Как запретить пользователю сохранять картинки?

Политика браузеров такова, чтобы любому пользователю предоставить свободный доступ как исходнику html страницы так и к картинкам на страницы. Обычно всё это делается через контекстное меню. Значит надо искать способы, чтобы пользователи не могли вызывать это меню.

С выходом в свет появилась возможность управлять меню. Теперь в тэге <IMG> можно использовать событие oncontextmenu которое обрабатывается каждый раз, когда контекстное меню собирается появиться на страничке. Если перехватить это событие и возвращать false, то контекстное меню не будет появляться. Поэтому если использовать

<img src="images/picture.jpg" oncontextmenu="return false">

то пользователь никогда не увидит контекстного меню для данного элемента страницы.

Те, кто не использует Internet Explorer 5.0 могут проделать эту хитрость при помощи Cascading Style Sheets (CSS):
<img src="images/clear.gif" width=200 height=142
style="background:url(images/picture.jpg)">

Здесь использован тэг <IMG> для отображения прозрачной картинки GIF с теми же размерами чтои реальная картинка. А затем, при помощи стиля в качестве фона установлено нужное изображение. Данный приём работает в Internet Explorer 4.0.

Однако, это ухищрение не будет работать в Навигаторе, а нижеприведённое будет:
<div style="background:url(images/picture.jpg) no-repeat; width:200;
height:142">
<img src="images/clear.gif" width=200 height=142>
</div>

Этот код фактически проделывает тоже самое - поверх реальной картинки помещается прозрачное изображение, а сама картинка делается фоном тэга <DIV>.

И помните, что пользователь очень захочет получить картинку, то он всегда сможет посмотреть исходник странички и вычислить точный путь картинки. Так что шипко не обольщайтесь, данные ухищрения расчитаны на неопытных юзеров :)

Добавлено: 20 Мая 2018 06:36:52 Добавил: Андрей Ковальчук

Безопасная работа с файлами. Пример счетчика

PHP без работы с файлами неинтересен. Динамика на сайтах обеспечивается различными счетчиками, голосованиями, рейтингами, опросами, комментариями посетителей. Разумеется, для всего этого можно использовать базы данных, например, MySQL, но не везде они есть.

Рассмотрим пример простейшего счетчика:

 $cf1 = @file ("counter.txt");
 $co = trim($cf1[0])+1;
 $cf2 = @fopen ("counter.txt", "w");
 fput($cf2, $co);
 fclose ($cf2);

Все вроде замечательно, но только при условии, что на страницу, снабженную этим счетчиком, заходит не более одного посетителя в год. Чаще бывает наоборот. Одновременно несколько (десятков) человек просматривают данную страницу. Вероятность, что вышеприведенный код выполнится одновременно несколькими посетителями, велика.

Например, первый скрипт прочитал значение счетчика, увеличил на единицу и открыл файл для перезаписи. В этот момент второй скрипт прочитал значение счетчика из пустого файла (параметр "w" указывает на то, что открываемый файл становится пустым). Ошибочное чтение обнулило значение счетчика во втором скрипте. Первый скрипт записал в открытый файл правильное значение счетчика и закрыл файл. Второй скрипт увеличил значение счетчика на единицу: 0 + 1 = 1 и записал в файл это число. Таким образом, мы потеряли правильное значение счетчика.

Эту проблему можно решить, используя функцию flock(), но она не будет работать под IIS от Microsoft.

Воспользуемся другим способом: будем создавать файлы-флаги. Алгоритм простой: создаем файл-ловушку, работаем с нужным файлом, удаляем файл-ловушку.
 cre_t("_counter");
 . . . работаем со счетчиком 
 del_t("_counter");

Рассмотрим подробнее функции cre_t() и del_t().
 # Создаем замок на определенный файл
 function cre_t($fn){
   $trp_p = 5;
   $present = 1;
   while ($present == 1){
     $i = 0;
     $j = rand (2000, 5500);
     while ($i<$j){
       $i = $i + 1;
     }
     if (!file_exists($fn)){
       $mf = @fopen($fn, "w");
       @fclose($mf);
       @fflush($mf);
       @chmod($fn, 0666); # Меняем атрибуты
       $present = 0;
     }
     else{
       if ((time() - @filemtime($fname))>$trp_p){
         @unlink ($fname);
       }
     }
     @clearstatcache($fname);
   }
   return 1;
 }

 # Снимаем замок с файла
 function del_t($fn){
   return @unlink ($fn);
 }

Цикл в функции cre_t() работает до тех пор, пока существует файл-ловушка. Чтобы не происходило бесконечного зацикливания, добавлена проверка времени создания файла-ловушки. Если файл-ловушка существует более 5 секунд, то удаляем его самостоятельно. Установка атрибута 0666 на файл-ловушку позволяет различным скриптам удалять этот файл.

Описанный метод обеспечивает приемлемую защиту для безопасной работы с файлами. Но, разумеется, 100% безопасность возможна лишь с использованием базы данных и встроенной команды LOCK_TABLE.

Добавлено: 16 Мая 2018 16:59:42 Добавил: Андрей Ковальчук

Целесообразность защиты информации

В наш 21 век все большую роль в любой сфере жизни человека приобретает информация. И потому этому веку суждено стать «информационным». Нематериальная составляющая производственных процессов несет в себе информационную компоненту, которая в любом производстве с течением времени заметно возрастает. Вместе с этим следует акцентировать внимание на вопросе о защите информации. Но прежде, чем установить защиту, нужно определить степень важности и значимости этой информации.
Домашний пользователь не станет применять криптографические меры с целью уберечь скрытую информацию от посторонних лиц. Даже, если у него и есть такая информация, максимум, он может ограничиться маскировкой личных файлов или установкой пароля на систему, более «продвинутые» пользователи применяют пароли или шифры к конкретным каталогам с ценной информацией.

Малые предприятия также используют систему паролей. Доступ к ценной информации разрешен, естественно, только обладателям паролей. Часто в целях предотвращения утечки информации персонал фирмы лишается возможности ее копирования на гибкие и лазерные диски из-за отсутствия соответствующих дисководов в системном блоке. Однако, выходом из такого положения может стать флэшка, подключаемая к USB- порту. Следует упомянуть о коммерческой тайне, которую обязан блюсти каждый работник предприятия. Об ее эффективности лучше промолчать, так как эта мера в действительности шаткий барьер на пути к добыче ценной информации.

Крупным компаниям, особенно разработчикам продукции, в условиях непрекращающейся конкуренции в господствовании на различных рынках недостаточна система ограничения доступа. Такие компании нуждаются в комплексных мерах защиты информации. В этот комплекс входят криптографическая, физическая, электромагнитная и другие типы защиты, в том числе человеческий фактор. Выстраивая комплексную защиту, всегда нужно помнить о принципе «слабейшего звена», который утверждает, что устойчивость всей системы защиты равна устойчивости ее слабейшего звена. Принимая меры по защите той или иной информации, следует подумать, а имеет ли это смысл. Прежде всего - с экономической точки зрения. Например, известная компания Microsoft тратит много средств на защиту своего программного продукта. Тем не менее, качество выпускаемой продукции, разумно построенная система защиты информации позволяют оставаться ей лидером на рынке программных продуктов. Но абсолютно надёжной защиты не существует. Это должны помнить все, кто организует защиту информации. Любую защиту можно преодолеть. Но лишь «в принципе». Это может потребовать таких затрат сил, средств или времени, что добытая информация их не окупит. А значит, надежной признается та защита, преодоление которой потребует от противника затрат, значительно превышающих ценность информации. Таким образом, руководитель любого предприятия, будь то малого, среднего или крупного, должен руководствоваться следующим принципом – на защиту информации потратить средств не свыше необходимого.

Добавлено: 11 Мая 2018 13:50:32 Добавил: Андрей Ковальчук

Защитить сайт

Безопасность сайтов и систем, открытых для всеобщего доступа через сеть интернет, уже далеко не один год является головной болью специалистов, отвечающих за их безопасность. Уже в начальный период существования интернета практика показала, что к существующим в этой сфере угрозам нельзя относиться спустя рукава. Так, ещё в 1994 г. в результате взлома через интернет американского СитиБанка, который приписывают русскому хакеру Владимиру Левину, было украдено более 12 млн. долларов. А вскоре были успешно взломаны и сайты НАТО, ЦРУ и Минюста США. Не чувствуют себя в безопасности владельцы сайтов и в наше время. Например, в прошлом (2007) году были взломаны сайты Газпрома, компании Nokia, сайты Утро.ру и РБК, сайты партии "Яблоко" и лаборатории Касперского и т. д.
В значительной мере защищённость сайтов зависит, безусловно, от правильной настройки и конфигурирования сервера с установленной на нём операционной системой, а также дополнительного сетевого оборудования. Однако, т. к. подавляющее большинство веб-мастеров размещают свои сайты на виртуальном хостинге, то влияние на данные факторы оказывается за пределами их возможностей, к тому же данные вопросы достаточно сложны, чтобы рассматривать их в рамках этой обзорной статьи. Как правило, если ваш сайт расположен у известного и надёжного хостера, то сервера администрируются достаточно грамотно и их взлом требует значительных усилий и, безусловно, весьма высокой квалификации самих хакеров. В то же время, даже будучи расположеном на абсолютно защищённом сервере, сайт никак не застрахован от элементарных ошибок, которые часто допускают сами малоосведомлённые в вопросах безопасности владельцы сайтов, открывая своими руками ворота для взломщиков. Итак, что же нужно знать, чтобы уменьшить опасность для своего сайта быть взломанным?

Во-первых, наиболее устойчив к взлому сайт, состоящий из статичных html-страничек. Основная опасность для сайта исходит от установленных на нём серверных скриптов (таких, как скрипты, написанные на языках php, perl, asp и т. д.). К сожалению, в наше время многие люди, создающие себе даже простой сайт-визитку, часто не утруждают себя освоением элементарных умений редактирования html-страничек с помощью визуальных редакторов и предпочитают устанавливать сайт на CMS, чтобы иметь возможность вносить правки и администрировать сайт удалённо. Представляет ли опасность любой скрипт? Конечно, правильно написанный скрипт безопасен. Однако на практике, особенно в том случае, если скрипт является сложным, громоздким и создаётся не одним программистом, а несколькими людьми, весьма высока вероятность появления в этом скрипте тех или иных ошибок, которые могут быть использованы для взлома сайта. Кроме этого, использование громоздких скриптов делает ваш сайт более уязвимым к DDoS-атакам, о которых будет сказано ниже. Поэтому, если у вас есть возможность выбирать между html-страничками и сайтом на CMS, странички которого генерируются скриптом, выбирайте первый вариант.

Если от использования скриптов на сайте отказаться всё же нельзя, следует ответственно подойти к их выбору (или написанию) и установке. Сейчас существует большое число различных скриптов и движков для сайта - разных типов CMS, блогов, форумов, интернет-магазинов и т. д. и т. п. Среди них встречаются как коммерческие версии, за которые нужно платить, так и бесплатные, которые вы можете скачать и установить на своём сайте совершенно свободно. К сожалению, проблемы с безопасностью часто всплывают и у тех, и у других. Если вы решили использовать готовые скрипты, следует учесть несколько вещей. Во-первых, перед тем, как использовать выбранный скрипт, нужно обязательно поискать на специализированных форумах, сайтах, таких, как, например antichat.ru, securitylab.ru и т. п., информацию об устойчивости данного скрипта (например, форумного движка) ко взлому. Если вы вдруг обнаружите, что в нём существуют какие-либо уязвимости, если отыщете эксплойты (т. е. готовые программные коды, использующие некую обнаруженную уязвимость, а воспользоваться таким готовым рецептом взлома может любой нашедший его школьник), то это верный сигнал, что для поставленной задачи лучше выбирать какой-нибудь другой скрипт.

Нежелательно также устанавливать самые свежие версии скриптов, которые ещё не прошли проверку временем - вероятность наличия дыр в таких скриптах больше. Лучше использовать те версии, которые работают на большом количестве сайтов уже достаточно продолжительное время и не имели за это время обнаруженных уязвимостей (хотя и это не является стопроцентной гарантией). После же установки скрипта следует периодически заглядывать на сайт, осуществляющий его поддержку - в случае, если какие-то уязвимости в скрипте вдруг будут найдены, там должны быть выложены обновления или патчи, которые нужно скачать и установить, чтобы ликвидировать уязвимость. К сожалению, многие веб-мастера часто пренебрегают этим, и в результате хакеры, узнавшие об обнаруженных уязвимостях, получают возможность взлома их сайтов.

Если вы пишете скрипт самостоятельно, следует также соблюдать предосторожность. Ключевым моментом, на который всегда нужно обращать повышенное внимание, является обработка получаемых скриптом данных. Это касается как данных, получаемых из форм, т. е. методом POST, так и в адресной строке, т. е. методом GET. Следует иметь в виду, что пользователь может ввести там всё, что угодно (и хакер как раз и будет пробовать это делать). Недостаточная фильтрация этих данных является, пожалуй, самой распространённой ошибкой в плане создания дыр в безопасности. Допустим, есть скрипт, который добавляет на страницу комментарий к какой-нибудь статье, вводимый пользователем через форму (подобный тому, как есть на этом сайте). Если в скрипте не предусмотреть фильтрацию вводимых данных, то хакер может ввести через форму код на javascript, который попадёт в код страницы и будет выполняться при её загрузке (подобный метод носит название XSS). С помощью такого фокуса легко сделать страницу неработоспособной или украсть, например, cookies администратора сайта, содержащие пароль, и получить, т. о., доступ к администраторским функциям. Семь раз нужно проверить скрипт, если на основе вводимых пользователем данных формируется запрос к базе данных (часто встречающиеся ошибки в реализации запроса к базе позволяют осуществить взлом с помощью т. н. SQL-инъекции), в код скрипта включаются какие-то файлы (напр., с помощью директивы include), или пользователю предоставляется право загружать какие-то файлы на ваш сервер (при отсутствии достаточной проверки хакер может загрузить на ваш сайт shell и сделать с ним всё, что угодно).

Естественно, помимо заботы об отсутствии уязвимостей в скриптах, администратор сайта должен заботиться и о правильном подборе и сохранности своего пароля, иначе все остальные усилия о безопасности пойдут прахом.

Даже если ваш сайт не имеет абсолютно никаких уязвимостей, существует способ всё равно вывести его из строя. Это - т. н. DDoS-атака. Сущность подобной атаки в том, что с большого числа компьютеров на ваш сайт начинает поступать громадное количество запросов, обслужить которые сервер просто не в состоянии. Хотя с помощью DDoS-атаки нельзя взломать сайт, можно добиться того, что он перестанет работать, и от подобного рода атаки не застрахованы даже очень крупные и известные сайты. Хотя полностью защититься от DDoS-атак нельзя, можно улучшить устойчивость вашего сайта к ним. Прежде всего нужно ограничить использование скриптов, потребляющих слишком много ресурсов, особенно, если при этом ещё осуществляется и подключение к базе данных. При наличии на вашем сайте громоздкого скрипта хакер может прервать его нормальное функционирование даже посылая запросы с одного единственного компьютера (напр., при использовании старых версий форума phpbb его можно было "подвесить" путём частого обращения к функции поиска по форуму, в новых версиях введена 15-секундная задержка). Ну и, конечно, если на ваш сайт будет проведена DDoS-атака, вам придётся полагаться на ответственность вашего хостера. К сожалению, не все компании выражают готовность в таких случаях принимать все необходимые меры и давать отпор, некоторые могут просто отключить ваш сайт.

Добавлено: 11 Мая 2018 13:49:36 Добавил: Андрей Ковальчук

Блокировка ip адреса

Сейчас в интернете очень активно спамят посещаемые и не очень интернет-ресурсы различных направлений и тематик. Несмотря на множество всевозможных способов защиты, расположенных на большинстве сайтов, спамеров остановить не всегда получается. Иногда они вручную или в полуавтоматическом режиме заполняют формы в гостевых, форумах, комментариях…, причем настолько нагло рекламируют себя или свой сайт, что диву даешься от их беспринципности. И от таких посягательств на "чистоту" вашего контента, а как следствие и сайта в целом, зачастую спасает только блокировка ip адреса спамера. На мой взгляд, блокировка по ip – очень эффективный метод борьбы со спамом, но применять его можно только в крайних случаях, например, когда с одного и того же ip вас спамили больше двух-трех раз. Использовать этот метод нужно крайне осторожно, дабы случайно не закрыть доступ к вашему сайту для поисковых машин, которые составляют основную часть трафика любого сайта.

В этой статье рассмотрен простейший php-скрипт, который имеет два уровня защиты сайта: предупреждение спамера о том, что ему не поздоровится, если он еще раз наспамит и полная блокировка доступа к сайту по ip. Единственным минусом блокировки по ipявляется то, что спамер может пользоваться бесплатным и общедоступным прокси-сервером, и если забаннить сервер с этим ip, то к вашему сайту не смогут получить доступ и те, кто использует его исключительно в мирных целях. Поэтому прежде чем банить смотрите, кто есть кто через сервис whois.

А вот и сам php-код простейшего скрипта для блокировки пользователя по ip:

<?php
/* http://wm-help.net/ */
/* Сообщение при банне ip */
define("bann_message", "Для вашего IP: %ip% доступ к сайту закрыт.");
 
/* Предупреждение о возможности банна по ip */
define("wrong_message", "Вы предупреждены администратором данного сайта о возможной блокировке вашего IP: %ip% в случае дальнейшего нарушения правил.");
 
/* массив с ip и типом блокировки. в ключе массива IP, в значении тип блокировки */
$bann_array = array(
                    "195.66.203.247"=>"bann", // реальный плохой IP
                    "220.94.220.60"=>"bann",  // реальный плохой IP
                    //"127.0.0.1"=>"wrong"      // Test
                    );
 
/* Функция для почти 100% определения IP адреса посетителя. */
/* Перебирает все возможные переменные с IP. */
function _ip()
{
  if(isset($HTTP_SERVER_VARS)) {
    if(isset($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"])) {
    $realip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"];
    }elseif(isset($HTTP_SERVER_VARS["HTTP_CLIENT_IP"])) {
      $realip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"];
    }else{
      $realip = $HTTP_SERVER_VARS["REMOTE_ADDR"];
    }
  }else{
  if(getenv( 'HTTP_X_FORWARDED_FOR' ) ) {
    $realip = getenv( 'HTTP_X_FORWARDED_FOR' );
  }elseif ( getenv( 'HTTP_CLIENT_IP' ) ) {
    $realip = getenv( 'HTTP_CLIENT_IP' );
  }else {
    $realip = getenv( 'REMOTE_ADDR' );
  }
}
return $realip;
}
 
/* Определяет, что делать с владельцем того или иного ip адреса */
function bann_on_not_to_bann()
{
    global $bann_array; // получаем массив с ip адресами
    $user_ip = _ip();   // получаем ip
 
/* разбираем массив на ключ и значение */
foreach($bann_array as $ip=>$type)
{
    if ($ip == $user_ip) // проверяем
    {
        switch($type) // если ip совпал то смотрим что делать
        {
            case "wrong": // предупреждение
            {
                echo str_replace("%ip%", $user_ip, wrong_message); // выводим предупреждение
                break; // выход из switch
            }
            case "bann": // блокировка
            {
                die(str_replace("%ip%", $user_ip, bann_message)); // Сообщение о том, что доступ закрыт + завершение работы php
                // break не требуется т.к. дальше уже ничего не выполняется
            }
        }
    }
}
}
 
/* проверяем владельца ip и блокируемпредупреждаем если это спамер */
bann_on_not_to_bann();
?>

Для того, чтобы использовать данный скрипт блокировки ipадресов создайте php-файл ip_bann.php и поместите в него весь код скрипта, который вы видите выше. Затем в самом начале основного скрипта, обычно это index.php допишите строчку:
include 'ip_bann.php';

Так же этот php-скрипт можно использовать для блокировки ip непосредственно в скриптах отвечающих за добавление сообщений пользователей на ваш сайт, а не повсеместно, данный вариант иногда бывает даже лучше.

Добавлено: 11 Мая 2018 11:04:54 Добавил: Андрей Ковальчук

Защита сайта от скачивания на PHP

Очень неприятно, когда в интеренете появляются сайты, сделаные методом скачивания содержимого с твоего, долгими трудами созданного. Вот от таких непорядочных людей и помогает этот скрипт.

Запись запрещающей строки в .htaccess осуществляется автоматически.

Скрипт вставляется в каждую страницу сайта с помощью include.

Описание настроек скрипта:
// error_reporting(0) После установки и настройки скрипта комментарий снять.
$limit // Максимально допустимое количество обращений к сайту с одного IP-адреса в минуту.
$htaccess // Путь к файлу .htaccess
$htstring // Комментарий к строке в файле .htaccess
$dirfiles // Путь к папке с временными файлами
$logfiles // Имена временных файлов
$excludes // Массив исключений с именами хостов, которым "можно всё"

<?php
#########################################################################
# High Activity AntiRip                                                 #
# --------------------------------------------------------------------- #
# Скрипт служит для защиты сайта от тотального скачивания "под корень". #
# Запись запрещающей строки в .htaccess осуществляется автоматически.   #
# --------------------------------------------------------------------- #
# http://deb.telenet.ru/ | http://www.woweb.ru/load/74-1-0-4183         #
#########################################################################

//error_reporting(0);
$address = $_SERVER['REMOTE_ADDR'];
$ref = $_SERVER['HTTP_REFERER'];
$url = urldecode($_SERVER['REQUEST_URI']);
$limit = 20;
$timenow = time();
$browser = $_SERVER['HTTP_USER_AGENT'];
$htaccess = $_SERVER['DOCUMENT_ROOT']."/.htaccess";
$dirfiles = $_SERVER['DOCUMENT_ROOT']."/antirip/logfiles/";
$logfiles = "$dirfiles".$address;
$hostname = gethostbyaddr($address);
$datetime = date("Y-m-d H:i:s");
$ip1 = getenv("HTTP_X_FORWARDED_FOR");
$ip2 = getenv("REMOTE_ADDR");
$hostip1 = gethostbyaddr($ip1);
$hostip2 = gethostbyaddr($ip2);
if ($ip1 != $ip2) {
  $htstring = NULL;
  if (!empty($ip1)) {
    preg_match_all('/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/', $ip1, $ip1);
    $ip1 = array_unique($ip1[0]);
    foreach ($ip1 as $v) {
      $htstring.="Deny from ".$v."    \\\\ Заблокирован Внутренний IP    \\\\ $hostip1\r\n";
    }
  }
  if (!empty($ip2)) {
    $htstring.="Deny from ".$ip2."    \\\\ Заблокирован IP Proxy    \\\\ $hostip2\r\n";
  }
} else {
  $htstring = "Deny from ".$address."    \\\\ Заблокирован Внешний IP    \\\\ $hostname\r\n";
}
$excludes = array(
"yandex.ru",
"rambler.ru",
"googlebot.com",
"webaltabot.com",
"inktomisearch.com",
"search.live.com",
"deb.telenet.ru",
"213.248.56.160",
"81.19.77.184"
);

if ($opendir = opendir($dirfiles)) {
  while (false !== ($log = readdir($opendir))) {
    if ($log != "." and $log != "..") {
      $timelog = date(filemtime("$dirfiles"."$log"));
      if ($timelog < ($timenow - 60)) {
        unlink("$dirfiles"."$log");
      }
    }
  }
}

foreach ($excludes as $v) {
  if (preg_match('/'.$v.'/', $hostname)) {exit;}
}

if (!file_exists($logfiles)) {fopen($logfiles, "w+");}
$write = "$datetime - $hostname<br>Browser: $browser<br>Referer: $ref<br>URL: $url<br>\r\n";
if ($logfiles) {
  if (is_writable($logfiles)) {
    if (!$handle = fopen($logfiles, 'a')) {exit;}
    if (fwrite($handle, $write) === FALSE) {exit;}
    fclose($handle);
  }    
}

if ((count(file($logfiles)) > $limit) and ($timelog > ($timenow - 60))) {
  if ($htaccess) {
    foreach (file($htaccess) as $h) {
      if ($h === $htstring) {
        exit;
      }
    }
    if (is_writable($htaccess)) {
      if (!$handle = fopen($htaccess, 'a')) {exit;}
      if (fwrite($handle, $htstring) === FALSE) {exit;}
      fclose($handle);
    }    
  }
}
?>

Добавлено: 11 Мая 2018 11:03:30 Добавил: Андрей Ковальчук

Защита информации в интернете. Часть 3. Защищенные электронные транзакции (SET)

Протокол защищенных электронных транзакций (SET), разработанный Visa International и MasterCard, специально предназначен для защиты транзакций в электронной коммерции. Протокол SET использует цифровые сертификаты для идентификации каждой стороны в электронной транзакции, включая покупателя, продавца и банк. Защита информации, передаваемой по Сети, дополняется методами криптографии, в которых используются открытые ключи.

Продавцы должны иметь цифровой сертификат и специальное программное течение от SET для обработки транзакций. У заказчика также должен быть цифровой сертификат и программное обеспечение электронного кошелька. Электронный кошелек устроен наподобие реального бумажника. В нем может храниться формация о нескольких кредитных или дебетовых картах, а также цифровой сертификат, удостоверяющий владельца карт. Электронный кошелек упрощает процессс совершения электронных покупок; покупателям больше не требуется повторно вводить информацию о кредитной карте в очередном электронном магазине.

Давайте рассмотрим, как выполняется транзакция электронной торговли, в которой используется протокол SET. Когда покупатель делает заказ, программное обеспечение SET продавца посылает данные заказа и цифровой сертификат продавца электронному кошельку заказчика, активизируя таким образом и программное обеспечение электронного кошелька. Заказчик выбирает карту, которая будет участвовать в транзакции. Затем данные кредитной карты и заказа зашифровываются, используя открытый ключ банка продавца, и отсылаются продавцу вместе с цифровым сертификатом покупателя. Продавец затем переправляет эту информацию в свой банк, где этот платеж должен быть обработан. Расшифровывать сообщение может только банк. Банк продавца посылает сумму платежа и свой цифровой сертификат в банк покупателя, чтобы получить подтверждение о возможности обработки транзакции. Если указанная сумма может быть списана с карточного счета, банк покупателя посылает подтверждение банку продавца. Банк продавца затем посылает разрешение на совершение сделки продавцу. В заключение, продавец посылает свое подтверждение сделки заказчику.

В протоколе SET продавец фактически не имеет доступа к частной информации клиента. Номер кредитной карты клиента не хранится на сервере продавца, что уменьшает риск мошенничества.

Хотя протокол SET специально разработан для транзакций электронной торговли и обеспечивает высокий уровень защиты, пока он не является стандартным протоколом, используемым для совершения транзакций. Часть проблемы заключается в том, что протокол SET требует специального программного обеспечения на стороне сервера, так и на стороне клиента, что приводит к дополнительным издержкам. Кроме того, подобные транзакции отнимают больше времени, чем транзакции, использующие другие протоколы, например SSL.

SET Secure Electronic Transaction LLC — организация, сформированная Visa и MasterCard для поддержки и продвижения на рынок протокола SET.

Пример: Microsoft Authenticode

Как вы сможете узнать, что программное обеспечение, которое вы приобрели в электронном магазине, безопасно и в него не были внесены какие-либо изменения? (каким образом вы можете убедиться в том, что не загружаете вместе с программой компьютерный вирус, который может уничтожить данные на вашем компьютере? Вы уверены в тех, от кого получили программное обеспечение? Этот список вопросов можно продолжить. С развитием электронной торговли компании, торгующие программным обеспечением, предлагают свой товар в электронных магазинах, откуда покупатели могут их загрузить непосредственно на свои компьютеры. Необходимо защищать разгружаемое программное обеспечение, чтобы быть уверенным в том, что при передаче по каналам связи оно не было изменено. Технология Microsoft Authenticode — подписи программного кода — совместно с цифровыми сертификатами VeriSign (цифровыми идентификаторами), идентифицирует издателя программного обеспечения и позволяет обнаружить изменения в коде программы, если они были туда внесены в процессе передачи данных по каналам связи. Защита Authenticode встроена в браузер Microsoft Internet Explorer. Распространители программного обеспечения должны получить цифровые сертификаты, специально разработанные для распространения программного обеспечения. Сертификаты могут быть получены у организаций, отвечающих за распределение сертификатов, таких, как, например, VeriSign. Чтобы получить удостоверение, продавец программного обеспечения должен предоставить свой открытый ключ, информацию о себе и подписать соглашение о том, что они не будут распространять программное обеспечение, которое может нанести ущерб. Это дает покупателям возможность обратиться за помощью, если загруженное программное обеспечение от сертифицированных распространителей причинило им вред.

Технология Microsoft Authenticode использует цифровую подпись. Программное обеспечение, подписанное цифровой подписью и удостоверенное цифровым сертификатом поставщика служат доказательством того, что программное обеспечение не несет в себе опасности и не было изменено.

Когда клиент пытается загрузить файл, на экране появляется диалоговое окно, в котором отображается цифровой сертификат и имя поставщика цифрового сертификата. Кроме того, даются ссылки на поставщика цифрового сертификата и поставщика программного продукта, чтобы клиент мог получить информацию о каждом из них до того, как он загрузит файл. Если Microsoft Authenticode определит, что программное обеспечение было скомпрометировано, транзакция будет прервана.

Добавлено: 11 Мая 2018 11:01:12 Добавил: Андрей Ковальчук