imagecms/ImageCMS

View on GitHub
application/libraries/lib_csrf.php

Summary

Maintainability
B
5 hrs
Test Coverage
<?php

if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}

/**
 * Image CMS
 * CSRF Library Beta.
 */
class Lib_csrf
{

    public $ci = NULL;

    private $enc_key = '';

    private $tokens = [];     // User token.

    private $sess_id = NULL;     // Session id.

    private $hidden_name = 'cms_token';

    private $max_tokens = 10;

    public $log_errors = FALSE;

    public $log_ajax_requests = FALSE;

    public function __construct() {
        $this->ci = &get_instance();

        $this->_generate_token();

        if ($this->check_token() === FALSE) {
            if ($this->log_errors === TRUE) {
                $this->_write_message('Wrong code.');
            }

            $err_text = 'Подозрение на атаку Cross-Site Request Forgery.';
            show_error($err_text);
            die();
        }
    }

    private function addDisabledCsrfUrls() {

        // Diable CSRF library form web money service
        $ci = $this->ci;
        if ($ci->uri->segment(1) == 'shop' && $ci->uri->segment(2) == 'cart' && $ci->uri->segment(3) == 'view' && $ci->input->get('result') == 'true' && $ci->input->get('pm') > 0) {
            define('ICMS_DISBALE_CSRF', true);
        }
        // Support for robokassa
        if ($ci->uri->segment(1) == 'shop' && $ci->uri->segment(2) == 'cart' && $ci->uri->segment(3) == 'view' && $ci->input->get('getResult') == 'true') {
            define('ICMS_DISBALE_CSRF', true);
        }
        if ($ci->uri->segment(1) == 'exchange') {
            define('ICMS_DISBALE_CSRF', true);
        }
        // Support for privat
        if ($ci->uri->segment(1) == 'shop' && $ci->uri->segment(2) == 'order' && $ci->uri->segment(3) == 'view' && $ci->input->post()) {
            define('ICMS_DISBALE_CSRF', true);
        }
        if ($ci->uri->segment(1) == 'shop' && $ci->uri->segment(2) == 'cart' && $ci->uri->segment(3) == 'view' && $ci->input->get('succes') == 'true') {
            define('ICMS_DISBALE_CSRF', true);
        }
        if ($ci->uri->segment(1) == 'shop' && $ci->uri->segment(2) == 'cart' && $ci->uri->segment(3) == 'view' && $ci->input->get('fail') == 'true') {
            define('ICMS_DISBALE_CSRF', true);
        }
        if ($ci->input->server('HTTP_REFERER') AND strpos($ci->input->server('HTTP_REFERER') . '', 'facebook.com')) {
            define('ICMS_DISBALE_CSRF', true);
        }
        if ($ci->input->server('HTTP_REFERER') AND strpos($ci->input->server('HTTP_REFERER') . '', 'facebook.com')) {
            define('ICMS_DISBALE_CSRF', true);
        }
        // Support for privat

        if ($ci->uri->segment(1) == 'shop' && $ci->uri->segment(2) == 'order' && $ci->uri->segment(3) == 'view') {
            define('ICMS_DISBALE_CSRF', true);
        }
        //new payment system
        if (preg_match('/payment_method_/i', $ci->uri->segment(1)) || preg_match('/payment_method_/i', $ci->uri->segment(2))) {
            define('ICMS_DISBALE_CSRF', true);
        }
        if ($ci->uri->segment(1) == 'facebook_store' && $ci->uri->segment(2) == 'auth_from_fb_store') {
            define('ICMS_DISBALE_CSRF', true);
        }

        if ($ci->uri->segment(4) == 'xbanners') {
            define('ICMS_DISBALE_CSRF', true);
        }
    }

    private function check_token() {
        $this->addDisabledCsrfUrls();
        if (count($_POST) > 0) {
            if (defined('ICMS_DISBALE_CSRF') AND ICMS_DISBALE_CSRF === TRUE) {
                return TRUE;
            }
            // Don't check ajax requests
            if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
                if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
                    if ($this->log_ajax_requests === TRUE) {
                        $this->_write_message('Ajax Request');
                    }
                    return TRUE;
                }
            }

            $post_token = $this->ci->input->post($this->hidden_name);

            if (array_search($post_token, $this->tokens) == FALSE) {
                if ($this->tokens[0] != $post_token) {
                    return FALSE;
                }
            }
        }

        return TRUE;
    }

    /**
     * Create input hidden
     */
    public function create_hidden_html() {
        return '<input type="hidden" value="' . $this->get_token() . '" name="' . $this->hidden_name . '" />';
    }

    /**
     * @param string $text
     */
    private function _write_message($text) {
        $this->ci->load->helper('file');

        $post_data = '<br/>Post data:<br/>';
        foreach ($_POST as $k => $v) {
            $post_data .= $k . ': ' . $v . '<br/>';
        }

        $request_uri = 'Request uri: ' . $_SERVER['REQUEST_URI'] . '<br/><br/>';

        $new_text = '<p>' . date('d-m-Y H:i:s') . ' IP:' . $_SERVER['REMOTE_ADDR'] . ' Referer: ' . $_SERVER['HTTP_REFERER'] . '<br/>' . $request_uri . $text . $post_data . '<br/>________________</p>';

        @write_file('./application/logs/csrf.html', $new_text, 'a');
    }

    private function _generate_token() {
        $this->sess_id = $this->_get_sess_id();
        $n_token = md5($this->sess_id . $this->enc_key);

        $this->tokens = $this->ci->session->userdata('ci_tokens');

        if (is_array($this->tokens) AND count($this->tokens) > $this->max_tokens) {
            $this->tokens = array_slice($this->tokens, -3, 3);
        }

        if (is_array($this->tokens)) {
            if (array_search($n_token, $this->tokens) === FALSE) {
                $this->tokens[] = $n_token;
            }
        } else {
            $this->tokens = [];
            $this->tokens[] = $n_token;
        }

        $this->ci->session->set_userdata('ci_tokens', $this->tokens);
    }

    public function get_token() {
        if (count($this->tokens) == 0) {
            $this->_generate_token();
        }
        return array_pop($this->tokens);
    }

    private function _get_sess_id() {
        return $this->ci->session->userdata('session_id');
    }

}

/* End of file lib_csfr.php */