目录

语法与注释

输出

变量

弱类型安全

超级全局常量

函数

常用

字符串相关

正则表达式

子字符串位置

数据库相关

mysqli

pdo

伪协议相关

反序列化漏洞

serialize函数

unserialize函数

魔法函数

举例


写给和我一样没学过php的安全小白,只是为了让你看懂php代码,专门学后端的请出门左转。学安全需要学的东西太多,你不可能把js学的和做前端的同学一样好、把php学的和做后端的一样好,把数据库学的和做数据库优化的同学一样好,把Apache学的和做服务器端的同学一样好,我们只能关注他们涉及的领域中不安全的因素,找到漏洞,提出修改意见。

php是后端常用的语言,在靶机或CTF比赛中也需要进行php代码审计,所以就看看从学安全的角度需要关心哪些部分。

语法与注释

PHP以 <?php 开始,以 ?> 结束:

<?php
// PHP 代码
?>

<?php
// 这是 PHP 单行注释

/*
这是
PHP 多行
注释
*/
?>

输出

在 PHP 中有两个基本的输出方式: echo 和 print。

echo 和 print 区别:

  • echo - 可以输出一个或多个字符串。
  • print - 只允许输出一个字符串,返回值总为 1。

echo是经常用的,一般用于回显,比如sql注入时回显查询语句结果。

变量

PHP 变量规则:

  • 变量以 $ 符号开始,后面跟着变量的名称
  • 变量名必须以字母或者下划线字符开始
  • 变量名只能包含字母数字字符以及下划线(A-z、0-9 和 _ )
  • 变量名不能包含空格
  • 变量名是区分大小写的

php是弱类型语言,不用在变量前面加类型。从学安全的角度,能看懂哪个是变量就ok了,如果以后学的更深入了,需要使用php来写POC,进行持续性漏洞再回过头来学习命名规则等。

弱类型安全

php中有一些相等的值

  • ''==0==false==NULL
  • '123'==123
  • 'abc'==0
  • '123a'==123
  • '0x01'==1
  • '0e123456789'=='0e987654321'
  • [false] ==[0]==[NULL]==['']
  • true == 1

在PHP中,比较两个值是否相等可以使用“==”或“===”,前者会自动进行类型转换。

<?php
$input = "1abc";
if($input==1)
{echo "flag";
}
?>

结果如下:

其他的请读者自行尝试。

超级全局常量

常量值被定义后,在脚本的其他任何地方都不能被改变。

PHP 超级全局变量列表:

  • $GLOBALS

$GLOBALS 是一个包含了全部变量的全局组合数组,变量的名字就是数组的键,在一个PHP脚本的全部作用域中都可以访问。

$GLOBALS["___mysqli_ston"]

  • $_SERVER

$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。

元素/代码 描述
$_SERVER['PHP_SELF'] 当前执行脚本的文件名,与 document root 有关。例如,在地址为 http://example.com/test.php/foo.bar 的脚本中使用 $_SERVER['PHP_SELF'] 将得到 /test.php/foo.bar。__FILE__ 常量包含当前(例如包含)文件的完整路径和文件名。 从 PHP 4.3.0 版本开始,如果 PHP 以命令行模式运行,这个变量将包含脚本名。之前的版本该变量不可用。
$_SERVER['GATEWAY_INTERFACE'] 服务器使用的 CGI 规范的版本;例如,"CGI/1.1"。
$_SERVER['SERVER_ADDR'] 当前运行脚本所在的服务器的 IP 地址。
$_SERVER['SERVER_NAME'] 当前运行脚本所在的服务器的主机名。如果脚本运行于虚拟主机中,该名称是由那个虚拟主机所设置的值决定。
$_SERVER['SERVER_SOFTWARE'] 服务器标识字符串,在响应请求时的头信息中给出。 (如:Apache/2.2.24)
$_SERVER['SERVER_PROTOCOL'] 请求页面时通信协议的名称和版本。例如,"HTTP/1.0"。
$_SERVER['REQUEST_METHOD'] 访问页面使用的请求方法;例如,"GET", "HEAD","POST","PUT"。
$_SERVER['REQUEST_TIME'] 请求开始时的时间戳。从 PHP 5.1.0 起可用。 (如:1377687496)
$_SERVER['QUERY_STRING'] query string(查询字符串),如果有的话,通过它进行页面访问。
$_SERVER['HTTP_ACCEPT'] 当前请求头中 Accept: 项的内容,如果存在的话。
$_SERVER['HTTP_ACCEPT_CHARSET'] 当前请求头中 Accept-Charset: 项的内容,如果存在的话。例如:"iso-8859-1,*,utf-8"。
$_SERVER['HTTP_HOST'] 当前请求头中 Host: 项的内容,如果存在的话。
$_SERVER['HTTP_REFERER'] 引导用户代理到当前页的前一页的地址(如果存在)。由 user agent 设置决定。并不是所有的用户代理都会设置该项,有的还提供了修改 HTTP_REFERER 的功能。简言之,该值并不可信。)
$_SERVER['HTTPS'] 如果脚本是通过 HTTPS 协议被访问,则被设为一个非空的值。
$_SERVER['REMOTE_ADDR'] 浏览当前页面的用户的 IP 地址。
$_SERVER['REMOTE_HOST'] 浏览当前页面的用户的主机名。DNS 反向解析不依赖于用户的 REMOTE_ADDR。
$_SERVER['REMOTE_PORT'] 用户机器上连接到 Web 服务器所使用的端口号。
$_SERVER['SCRIPT_FILENAME'] 当前执行脚本的绝对路径。
$_SERVER['SERVER_ADMIN'] 该值指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。如果脚本运行在一个虚拟主机上,则该值是那个虚拟主机的值。
$_SERVER['SERVER_PORT'] Web 服务器使用的端口。默认值为 "80"。如果使用 SSL 安全连接,则这个值为用户设置的 HTTP 端口。
$_SERVER['SERVER_SIGNATURE'] 包含了服务器版本和虚拟主机名的字符串。
$_SERVER['PATH_TRANSLATED'] 当前脚本所在文件系统(非文档根目录)的基本路径。这是在服务器进行虚拟到真实路径的映像后的结果。
$_SERVER['SCRIPT_NAME'] 包含当前脚本的路径。这在页面需要指向自己时非常有用。__FILE__ 常量包含当前脚本(例如包含文件)的完整路径和文件名。
$_SERVER['SCRIPT_URI'] URI 用来指定要访问的页面。例如 "/index.html"。
  • $_REQUEST

用于收集HTML表单提交的数据。

  • $_GET

HTML form标签的属性method="get"时,$_GET可以收集URL中发送的数据。

  • $_POST

HTML form标签的属性method="post"时,$_POST可以收集表单中发送的数据。

  • $_FILES
  • $_ENV
  • $_COOKIE
  • $_SESSION

函数

常用

  • array()

创建数组

  • bool is_numeric ( mixed $var )

检测变量是否为数字或数字字符串,注意,可以是16进制,字符串转16进制可以绕过。is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值。

由于php是弱类型语言,会使用这个函数来判断一下。

  • rand(min,max)

生成随机整数

  • sleep(seconds)

延迟执行当前脚本若干秒

  • bool isset ( mixed $var [, mixed $... ] )

检测变量是否已设置并且非 NULL

  • die(message)

输出一条消息,并退出当前脚本。

  • md5()

以下值在md5加密后以0E开头:

  1. QNKCDZO
  2. 240610708
  3. s878926199a
  4. s155964671a
  5. s214587387a

可以用于md5相等,但两值不相等的情况

base64_encode()、base64_decode()、sha1()strcmp()

传入数组,返回NULL

字符串相关

正则表达式

  • int preg_match ( string $pattern , string $subject)

执行一个正则表达式匹配

匹配

这里需要注意一下 i ,表示大小写不敏感,即php、PHP、PhP都会被过滤掉,有的时候没有写i,黑名单里面有select关键字时,我们可以使用SELECT来绕过。

  • mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] ) : string

返回字符串的一部分,字符串可以包含中文,substr函数是不能包含中文的。

子串

子字符串位置

  • mb_strpos ( string $haystack , string $needle [, int $offset = 0 [, string $encoding = mb_internal_encoding() ]] ) : int

查找字符串在另一个字符串中首次出现的位置(汉字占一个位置),如果没有找到字符串则返回 false。类似的还有:

  • strpos()-查找字符串在另一字符串中第一次出现的位置(区分大小写,汉字占两个位置)
  • strrpos()-查找字符串在另一字符串中最后一次出现的位置(区分大小写)
  • stripos()-查找字符串在另一字符串中第一次出现的位置(不区分大小写)
  • strripos()-查找字符串在另一字符串中最后一次出现的位置(不区分大小写)

安全问题

由于返回的是false,一旦使用==进行判断,我们可以构造第二个字符串是第一个的开始,即可绕过

<?php
$str1 = "abcd";
$str2 = "ab";
if(strpos($str1,$str2)==false)
{echo "flag";
}
?>

绕过结果
  • str_replace(find,replace,string,count)

替换字符串中的一些字符(区分大小写),注意,可以通过双写或者大小写进行绕过。

  • mixed preg_filter ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

执行一个正则表达式搜索和替换。这个就不太好弄了,可能需要编码绕过。

  • htmlspecialchars(string,flags,character-set,double_encode)

把一些预定义的字符转换为 HTML 实体。

预定义的字符是:

  1. & (和号)成为 &amp;
  2. " (双引号)成为 &quot;
  3. ' (单引号)成为 '
  4. < (小于)成为 &lt;
  5. > (大于)成为 &gt;

故可以使用单引号的payload进行绕过。

  • strip_tags(string,allow)

剥去字符串中的 HTML、XML 以及 PHP 的标签。

  • addslashes(string)

返回在预定义的字符前添加反斜杠的字符串。

预定义字符是:

  1. 单引号(')
  2. 双引号(")
  3. 反斜杠(\)
  4. NULL

数据库相关

mysqli

  • mysqli_connect(host,username,password,dbname,port,socket)

打开一个到 MySQL 服务器的新的连接。

  • mysqli_error(connection)

返回最近调用函数的最后一个错误描述。

  • mysqli_close(connection)

关闭先前打开的数据库连接。

  • mysqli_query(connection,query,resultmode)

执行某个针对数据库的查询

  • mysqli_fetch_assoc(result)

从结果集中取得一行作为关联数组

  • mysqli_fetch_row(result)

从结果集中取得一行,并作为枚举数组返回

  • mysqli_num_rows(result)

返回结果集中行的数量

  • mysqli_real_escape_string(connection,escapestring)

转义在 SQL 语句中使用的字符串中的特殊字符,难道转义后我们就没有办法注入了?NO!!!

php官方函数参考手册中写到,会被进行转义的字符包括: NUL (ASCII 0),\n,\r,\,'," 和 Control-Z.

也就是或如果是数字型注入,例如,payload是 1 and 1=1# ,那么这个函数没有用,因为payload中不包含以上字符。

另外,在调用 mysqli_real_escape_string() 函数之前, 必须先通过调用mysqli_set_charset()函数或者在 MySQL 服务器端设置字符集。如果字符集设置不当,可以通过宽字节注入来进行绕过。

pdo

PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。

PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。

  • public PDOStatement PDO::prepare ( string $statement [, array $driver_options = array() ] )

为 PDOStatement::execute() 方法准备要执行的SQL语句,SQL语句可以包含零个或多个命名(:name)或问号(?)参数标记,参数在SQL执行时会被替换。这样就没法破坏sql语句的结构,不是拼接,也就是网络安全-SQL注入原理及防御SQL注入中提到的sql注入防御的第一种。

举例:

prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );

你以为sql语句是

SELECT first_name, last_name FROM users WHERE user_id = id LIMIT 1;

于是使用 1 or 1=1#作为payload,认为下面的sql语句会被执行

SELECT first_name, last_name FROM users WHERE user_id = 1 or 1=1#

但实际上执行的是

SELECT first_name, last_name FROM users WHERE user_id = 1 or 1=1# LIMIT 1;

或者说 直接判断 1 or 1=1# 是不是数字型参数,不是的话根本就不会去执行,也就安全了。

  • bool PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] )

绑定一个PHP变量到用作预处理的SQL语句中的对应命名占位符或问号占位符。

例如(绑定变量id与prepare里的id):

bindParam( ':id', $id, PDO::PARAM_INT )

  • bool PDOStatement::execute ([ array $input_parameters ] )

执行预处理过的语句。

  • mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] )

从一个 PDOStatement 对象相关的结果集中获取下一行。

  • int PDOStatement::rowCount ( void )

返回上一个由对应的 PDOStatement 对象执行DELETE、 INSERT、或 UPDATE 语句受影响的行数。

伪协议相关

函数

伪协议的学习 - Paddling - 博客园

伪协议方法

php伪协议 - 简书

反序列化漏洞

PHP提供serialize和unserialize函数,将任意类型的数据转换成string类型或者相反。当unserialize函数的参数被用户控制的时候就会形成反序列化漏洞。

serialize函数

serialize() 函数用于序列化对象或数组,并返回一个字符串序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结构不会改变。

string serialize ( mixed $value )

参数

$value: 要序列化的对象或数组。

返回

字符串

unserialize函数

unserialize() 函数用于将通过serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构。

mixed unserialize ( string $str )

参数

$str: 序列化后的字符串。

返回

返回的是转换之后的值,可为 integer、float、string、array 或 object。

如果传递的字符串不可解序列化,则返回 FALSE,并产生一个 E_NOTICE。

魔法函数

序列化对象就要谈到类,其中有三个魔法函数:__construct、__destruct、__toString。

<?php
class test{var $url;var $name;
function __construct( $par1, $par2 ) {$this->url = $par1;$this->name = $par2;echo "call __construct<br>";
}function __toString() {echo "call __toString<br>";return $this->url;}function __destruct() {echo "call __destruct<br>";echo "bye<br>";
}
}$t = new test('https://blog.csdn.net/lady_killer9','FrankYu');
echo $t . PHP_EOL;
?> 

魔法函数
  • __construct在创建对象时被调用
  • __toString在对象被当做字符串时被调用
  • __destruct在脚本结束时被调用

举例

有这样一段代码

<?php
class test{var $path = "";function __toString() {$file = fopen($this->path, "r") or exit("无法打开文件!");// 读取文件每一行,直到文件结尾while(!feof($file)){echo fgets($file). "<br>";}fclose($file);return $this->path;
}
}
$para = '';
echo unserialize($para);
?> 

其中,para是你可控的,代码的作用就是反序列化你传入的参数,然后打印出来。

分析:打印必调用__toString函数,__toString函数中会打开$path文件,所以,我们需要构造一个path为敏感文件路径的test类对象,并得到序列化后的字符串,将该字符串作为参数para。

<?php
class test{var $path = "";function __toString() {$file = fopen($this->path, "r") or exit("无法打开文件!");// 读取文件每一行,直到文件结尾while(!feof($file)){echo fgets($file). "<br>";}fclose($file);return $this->path;
}
}
$hack = new test();
$hack->path = "/box/script.php";
echo serialize($hack);
?> 

得到序列化字符串

成功读取了敏感文件/box/script.php

显示了服务器保存的代码

更多函数,请查看php官方手册

更多内容查看:网络安全-自学笔记

喜欢本文的请动动小手点个赞,收藏一下,有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

网络安全-php安全知识点相关推荐

  1. 网络安全基础课程知识点(1)

    网络安全基础课程知识点(1) 一.OIS七层模型图 1.应用层 通过人机交互来实现各种服务,用户接口,应用程序(文件传输,电子邮件,文件服务,虚拟终端). 所需设备:网关. 由抽象语言→ 编码 2.表 ...

  2. 网络安全学科复习知识点个人整理

    学习目标:临近期末,特此对课内网络安全相关知识点进行整理,也为日后回顾知识点方便阅览. 参考书目:<网络安全技术及应用(第3版)>立体化教材 注明: 1.知识点来源于教材,该重点为个人向整 ...

  3. 网络安全必学知识点之XSS漏洞

    xss漏洞小结 一.初识XSS 1.什么是XSS XSS全称跨站脚本(Cross Site Scripting),为避免与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆 ...

  4. 网络安全入门必学内容有哪些?网络安全最全知识点汇总来了

    随着时代的发展,经济.社会.生产.生活越来越依赖网络.而随着万物互联的物联网技术的兴起,线上线下已经打通,虚拟世界和现实世界的边界正在变得模糊.这使得来自网络空间的攻击能够穿透虚拟世界的边界,直接影响 ...

  5. 网络安全与管理知识点总结

    网络安全与管理 第一章 概述 第二章 信息收集 第三章 网络隐身 第四章 网络扫描 第五章 网络攻击 第六章 网络后门及痕迹清除 第七章 访问控制与防火墙 第八章 入侵防御 思维导图在下载资源,需要自 ...

  6. 北邮 网络安全 期末复习 知识点总结之APT攻击

    APT攻击与检测 APT简介 高级持续性威胁(Advanced Persistent Threat) 攻击者掌握先进的专业知识和丰富有效的资源,通过 多种攻击途径(如网络.物理设施和欺诈手段等),实现 ...

  7. 网络安全-靶机dvwa之sql注入Low到High详解(含代码分析)

    目录 SQL Injection-LOW Union注入 注入点判断 字段判断 获取数据库名 获取表名 获取列名 获取数据 Error注入 获取表名 获取列名 获取数据 源码解析 主要步骤 漏洞原因 ...

  8. 网络安全能不能自学?自学能不能学会?

    前言 网络安全作为现在比较火的行业,也让好多小伙伴准备去学习网络安全知识,那么这个时候就会有一个问题摆在我们的面前,那就是网络安全能不能自学?自学能不能学会呢? 这个问题肯定不是一个有固定的答案的问题 ...

  9. 学好网络安全看这篇文章让你少走弯路

    首先看一下学网络安全有什么好处: 1.可以学习计算机方面的知识 在正式学习网络安全之前是一定要学习计算机基础知识的.只要把网络安全认真的学透了,那么计算机基础知识是没有任何问题的,操作系统.网络架构. ...

最新文章

  1. 再有人问你MySQL是如何查询数据的,请把这篇文章甩给他!
  2. YunYang1994/tensorflow-yolov3 IndexError: list index out of range 解决办法
  3. 并发编程——进程——进程理论的创建
  4. 音视频技术开发周刊 | 161
  5. 通过虚方法实现方法重写-多态
  6. 递归-汉诺塔(代码、分析、汇编)
  7. VSCode 汉化、设置为 中文语言显示 、中文界面
  8. Flink-org.apache.flink.streaming.api.windowing.windows.Window
  9. 专科段《质量管理》课程复习资料(2)——单项选择题
  10. Everthing搜索神器,工作利器
  11. 数学作图工具_数学趣览X 曾让古希腊人犯怵的三大几何作图难题
  12. jq动态改变路径_在react中使用jQuery动态更改图片路径遇到的问题
  13. Android WiFi系统【转】
  14. 光端机2m是什么意思,光端机E1与2M有什么关系?
  15. 帆软:根据参数查看不同报表
  16. 300etf期权怎么玩?正规平台有哪些呢?
  17. 自然语言处理-中文分词相关算法(MM、RMM、BMM、HMM)
  18. 【转】Python实现量化选股
  19. 关于sentinel LDK加密war包实现应用加密的使用方法
  20. 华为云服务器的使用方法

热门文章

  1. esxi做文件服务器拒绝,VMware ESXi和ESX “lsassd”服务远程拒绝服务漏洞
  2. 【Sql】安装sql server 提示Polybase要求安装Oracle JRE 7更新51(64位)或更高版本
  3. java笔试题含答案总结
  4. Flink1.13.2运行在大数据星环TDH集群的jdk1.7上解决办法
  5. 【计算机网络】南航计算机网络第五章 运输层
  6. 粒子群算法(PSO)光伏发电 MPPT实现多峰值寻优,阴影遮蔽光伏发电算法 使用s函数编写粒子群算法
  7. adb的下载安装与环境配置
  8. PostgreSQL实战之增量备份
  9. PostgreSQL实战之PostGIS
  10. 在Spring Boot中配置Thymeleaf的模板路径