网络安全-php安全知识点

目录

语法与注释

输出

变量

弱类型安全

超级全局常量

函数

常用

字符串相关

正则表达式

子字符串位置

数据库相关

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中有一些相等的值

  • ''0false==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 KaTeX parse error: Undefined control sequence: \[ at position 12: limit = -1 \̲[̲, int &count ]] )

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

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

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

预定义的字符是:

  1. & (和号)成为 &
  2. " (双引号)成为 "
  3. ’ (单引号)成为 ’
  4. < (小于)成为 <
  5. > (大于)成为 >

故可以使用单引号的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 KaTeX parse error: Expected 'EOF', got '&' at position 19: …ameter , 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官方手册


关于黑客&网络安全学习指南

学好 网络安全不论是就业还是做副业赚钱都不错,但要学会 网络安全 还是要有一个学习规划。最后给大家分享一份全套的 网络安全学习资料,给那些想学习网络安全的小伙伴们一点帮助!

内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础等教程,带你从零基础系统性的学好网络安全。

1.学习路线图
在这里插入图片描述

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。

2.网络安全视频教程600集和配套电子书
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

在这里插入图片描述

温馨提示:篇幅有限,已打包文件夹,获取方式在:CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

3.技术文档
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。
在这里插入图片描述

4.工具包、面试题和源码
“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。
在这里插入图片描述

还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取:CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…
在这里插入图片描述

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取:CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

网络安全技术库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值