首页 > 编程技术 > php

PHP中的代码安全和SQL Injection防范

发布时间:2016-11-25 16:10




在现在各种黑客横行的时候,如何实现自己php代码安全,保证程序和服务器的安全是一个很重要的问题,我随便看了下关于php安全的资料,并不是很多,至少比asp少多了,呵呵,于是就想写点东西,来防止这些可能出现的情况。这里没有太深的技术含量,我只是比较简单的谈了谈。(以下操作如无具体说明,都是基于PHP+MySQL+Apache的情况)

先来说说安全问题,我们首先看一下两篇文章:
http://www.xfocus.net/articles/200107/227.html   
http://www.xfocus.net/articles/200107/228.html

上面文章是安全焦点上的关于PHP安全的文章,基本上比较全面的介绍了关于PHP的一些安全问题。

在PHP编码的时候,如果考虑到一些比较基本的安全问题,首先一点:
1. 初始化你的变量

为什么这么说呢?我们看下面的代码:
if ($admin)
{
    echo ''登陆成功!'';
    include(''admin.php'');
}
else
{
    echo ''你不是管理员,无法进行管理!'';
}

好,我们看上面的代码好像是能正常运行,没有问题,那么加入我提交一个非法的参数过去呢,那么效果会如何呢?比如我们的这个页是 http://www.traget.com/login.php,那么我们提交:http://www.target.com/login.php?admin=1,呵呵,你想一些,我们是不是直接就是管理员了,直接进行管理。
当然,可能我们不会犯这么简单错的错误,那么一些很隐秘的错误也可能导致这个问题,比如最近暴出来的phpwind 1.3.6论坛有个漏洞,导致能够直接拿到管理员权限,就是因为有个$skin变量没有初始化,导致了后面一系列问题。

那么我们如何避免上面的问题呢?首先,从php.ini入手,把php.ini里面的register_global = off,就是不是所有的注册变量为全局,那么就能避免了。但是,我们不是服务器管理员,只能从代码上改进了,那么我们如何改进上面的代码呢?我们改写如下:
$admin = 0;      // 初始化变量
if ($_POST[''admin_user''] && $_POST[''admin_pass''])
{
    // 判断提交的管理员用户名和密码是不是对的相应的处理代码
    // ...
    $admin = 1;
}
else
{
    $admin = 0;
}

if ($admin)
{
    echo ''登陆成功!'';
    include(''admin.php'');
}
else
{
    echo ''你不是管理员,无法进行管理!'';
}

那么这时候你再提交 http://www.target.com/login.php?admin=1 就不好使了,因为我们在一开始就把变量初始化为 $admin = 0 了,那么你就无法通过这个漏洞获取管理员权限。


2. 防止SQL Injection (sql注射)

SQL 注射应该是目前程序危害最大的了,包括最早从asp到php,基本上都是国内这两年流行的技术,基本原理就是通过对提交变量的不过滤形成注入点然后使恶意用户能够提交一些sql查询语句,导致重要数据被窃取、数据丢失或者损坏,或者被入侵到后台管理。
基本原理我就不说了,我们看看下面两篇文章就很明白了:
http://www.4ngel.net/article/36.htm
http://www.4ngel.net/article/30.htm

那么我们既然了解了基本的注射入侵的方式,那么我们如何去防范呢?这个就应该我们从代码去入手了。

我们知道Web上提交数据有两种方式,一种是get、一种是post,那么很多常见的sql注射就是从get方式入手的,而且注射的语句里面一定是包含一些sql语句的,因为没有sql语句,那么如何进行,sql语句有四大句:
select 、update、delete、insert,那么我们如果在我们提交的数据中进行过滤是不是能够避免这些问题呢


最近在看.net的新功能Linq,第一感觉,功能非常实用.
数组,字符串都可以用我们熟悉的 SQL 方式来查询,太方便啦!

就想看看PHP在这方面有没有这样的类库.

不查不知道,一查吓一跳,还真的有类似的类库,命名为PHPLinq.

PHPLinq的首页:
http://www.codeplex.com/PHPLinq

Examples

Examples can be found in the test package in the latest release.

A basic example

Let''s say we have an array of strings and want to select only the strings whose length is < 5. The PHPLinq way of achieving this would be the following:

// Create data source
$names = array("John", "Peter", "Joe", "Patrick", "Donald", "Eric");

$result = from(''$name'')->in($names)
->where(''$name => strlen($name) < 5'')
->select(''$name'');


Feels familiar to SQL? Yes indeed! No more writing a loop over this array, checking the string''s length, and adding it to a temporary variable.

You may have noticed something strange... What''s that $name => strlen($name) < 5 doing? This piece of code is compiled to an anonymous function or Lambda expression under the covers. This function accepts a parameter $name, and returns a boolean value based on the expression strlen($name) < 5.

An advanced example

There are lots of other examples available in the PHPLinq download, but here''s an advanced one... Let''s say we have an array of Employee objects. This array should be sorted by Employee name, then Employee age. We want only Employees whose name has a length of 4 characters. Next thing: we do not want an Employee instance in our result. Instead, the returning array should contain objects containing an e-mail address and a domain name.

First of all, let''s define our data source:

class Employee {
public $Name;
public $Email;
public $Age;

public function __construct($name, $email, $age) {
$this->Name = $name;
$this->Email = $email;
$this->Age = $age;




双引号会让程序被检查是不是有变量

用到变量的时候用双引号才可以被编译,才可以替代成变量的值

 

还有n等要也是要双引号的,用单引号就直接输出n了

而单引号将直接把程序给显示出来

单引号的特点,省时间,编译器不会把其当作变量去翻译哦

建议没变数的用单引号



<?php
/*
* 作用:主用于文件上传后的目录自动生成
* 时间:2006-3-12
* 作者:欣然随风
*/

class class_dir
{
     /**
      * 换算实际路径
      */
function dir_path($path)
{
   $adir = explode(''/'',$path);

   for($i=0;$i<count($adir);$i++)
   {
    $key = false;
    if($adir[$i] == "..") $key = $i;

    if($key !== false)
    {
     for($j=0;$j<count($adir);$j++)
     {
      if($j==$key-1 || $j==$key) continue;
      $newadir[] = $adir[$j];
     }
     $adir = $newadir;
     $newadir = false;
     $i=$i-2;
    }
   }
   Return $path = implode("/",$adir);
}

     /**
      * 按指定路径生成目录
      */
     function dir_mkdirs($path)
     {
   $path = $this->dir_path($path);
   $adir = explode(''/'',$path);
         $dirlist = '''';
         $rootdir = array_shift($adir);
         if(!file_exists($rootdir))
             mkdir($rootdir);

         foreach($adir as $val)
         {
              $dirlist .= "/".$val;
              $dirpath = $rootdir.$dirlist;
              if(!file_exists($dirpath))
        &nbs

可以通过XML-RPC让不同平台的软件互相交互,我们假设用PHP做前台(客户端),Python作为服务后台,之间通过XML-RPC调用Python提供的服务。例子如下:

1、PHP客户端

 <?php
//xmlrpc_client.php
//XML-RPC客户端演示程序
require(''xmlrpc.inc'');
$xmlrpc_internalencoding=''UTF-8'';
//创建client对象, 三个参数依次为 path, hostname, port
#$s=new xmlrpc_client(''/testxml/xmlrpc_server.php'', ''localhost'', 80);
$s=new xmlrpc_client(''/'', ''localhost'', 8888);

//create xmlrpcval object, which allows the encoding of our variable
//创建xmlrpcval对象,将我们的PHP变量编码为XML-RPC需要的XML形式
#$inputString=new xmlrpcval(''world胜利'', ''string'');
$inputString = php_xmlrpc_encode(''胜利world'');

//create an array of parameters
//尽管我们只有一个参数,但仍然要转换成数组的形式,因为xmlrpcmsg的第二个参数是一个参数表
$parameters=array($inputString);

//create the message object
//创建XML-RPC报文,参数分别为 远程方法名 和 参数表
$msg=new xmlrpcmsg(''echoString'', $parameters);
//$s->request_charset_encoding = ''utf-8'';
//send the message, get the response
//发送报文,返回值$rsp为一个xmlrpcresp对象,它包含以下三个方法:
//faultCode() 出错代码,如果成功将返回0
//faultString() 出错信息
//value() 返回值,以xmlrpcval对象形式存在,PHP使用前需要进行解码
$s->debug = true;
$rsp=$s->send($msg);

//check for errors
if($rsp->faultcode()==0) {
    //decode the response to a PHP type
    //xmlrpc_decode()函数用于将xmlrpcval对象解码
    $response=php_xmlrpc_decode($rsp->value());

    //print results
    print ''<pre>'';
    var_dump($response);
    print ''</pre>'';
} else {
    //print errors
    print ''Error: ''.$rsp->faultcode().'', ''.$rsp->faultstring().''<br>'';
}

//show messages
//然后我们来查看一下报文内容
$msg->createpayload();
print ''REQUEST:<xmp>''.$msg->payload.''</xmp>'';
print ''RESPONSE:<xmp>''.$rsp->serialize().''</xmp>'';

?>

2、Python服务端

# -*- coding:GB2312 -*-
import SimpleXMLRPCServer

#定义自己的CMS类
class MyCMS:
    def getVersion(self

<
标签:[!--infotagslink--]