PHP 文件读写操作
文件的打开与关闭(读文件中的内容, 向文件中写内容)
文件的读写可以针对图片文件;
1.读取文件中的内容
file_get_contents(); php5以上 返回值为字符传
file() 数组中的每个单元都是文件中相应的一行, 包括换行符在内 返回值为数组
readfile(); 直接输出到缓冲区,不需要用echo(直接将文件读出并输出到浏览器) 返回值为从文件中读入的字节数
不足:全部读取, 不能读取部分, 也不能指定的区域
mode 说明
\’r\’ 开头读(read)
\’r+\’ 开头读写
\’w\’ 清零写(write)
\’w+\’ 清零读写
\’a\’ 追加写(append)
\’a+\’ 追加读写
\’x\’ 谨慎写
\’x+\’ 谨慎读写
fread() string fread ( int $handle , int $length ) 读取文件, 参数$length单位为字节(最大值:8192)
fgetc() string fgetc ( resource $handle ) 返回一个包含有一个字符的字符串
fgets() string fgets ( resource $handle ) 返回一个包含有一行字符的字符串
fgetss() string fgetss ( resource $handle [, int $length [, string $allowable_tags ]] )
从文件指针中读取一行并过滤掉HTML标记
文件锁
2.写入文件
file_put_contents(\”URL\”, \”内容字符串\”); //php5以上,函数返回值为int
如果文件不存在, 则创建, 并写入内容
如果文件存在, 则删除文件中的内容, 重新写
默认为重新写, 可以通过第三个参数使用常量:FILE_APPEND来完成追加写;
格式: file_put_contents(\”URL\”, \”内容字符串\”, FILE_APPEND);
不足: 不能加锁
fopen()
fwrite() 别名 fputs
不同的操作系统具有不同的的结束符号,基于UNIX的系统使用\”\\n\”作为行结束字符,基于windows的系统使用\”\\r\\n\”作为行结束字符
基于Macintosh的系统使用\”\\r\”作为行结束字符。当要写入一个文本文件并想插入一个新行时,需要使用相应的操作系统的行结束符号。
注意:windows操行系统下,\”\\r\\n\”只是在代码中换行,如果要在浏览器显示结果中换行应采用\”<br/>\”
feof() 测试文件指针是否到了文件结束的位置
bool feof ( resource $handle )
stream_get_contents 和file_get_content的区别?
stream_get_contents — 读取资源流到一个字符串, 即其读取的内容是一个已经打开的资源句柄,
如fopen函数打开的文件句柄, 而 file_get_content可以直接读取文件内容读取到一个字符串, 保存在内存中。
本地文件:
./test.txt
c:/appserv/www/index.html
/usr/local/apahce/index.html
远程:
http://www.baidu.com
http://www.163.com
ftp://user@passwd:www.baidu.com/index.php
3.文件内部移动指针
ftell($file) 返回文件指针读/写的位置
fseek($file, 10); 在文件指针中定位
whence 的值定义为:
SEEK_SET – 设定位置等于 offset 字节。 默认值
SEEK_CUR – 设定位置为当前位置加上 offset 。 (要移动到当前文件之前的位置, 需要给 offset 传递一个负值。)
SEEK_END – 设定位置为文件尾加上 offset 。(要移动到文件尾之前的位置, 需要给 offset 传递一个负值。)
rewind(); 将 handle 的文件位置指针设为文件流的开头。
4.文件的锁定一些机制处理
要取得共享锁定(读取的程序), 将 operation 设为 LOCK_SH。 share 共享
要取得独占锁定(写入的程序), 将 operation 设为 LOCK_EX。 exclusive 独享
要释放锁定(无论共享或独占), 将 operation 设为 LOCK_UN。 unshackle 释放锁定
如果不希望 flock() 在锁定时堵塞, 则给 operation 加上 LOCK_NB(Windows 上还不支持)。
flock($fp, LOCK_EX | LOCK_NB)
fflush()将缓冲内容输出到文件
本函数强制将所有缓冲的输出写入 handle 文件句柄所指向的资源。 成功时返回 TRUE , 或者在失败时返回 FALSE 。
文件指针必须是有效的, 必须指向由 fopen() 或 fsockopen() 成功打开的文件(并还未由 fclose() 关闭)。
文件的读写可以针对图片文件;
5 文件截取
接受文件指针 handle 作为参数, 并将文件大小截取为 size, 从开始截取到指定的字符数(大小)。
PHP源码系列之扩展的原理与开发
- 一、前言
- 二、PHP扩展与Zend扩展
- 三、扩展的组成结构
- 四、扩展的加载过程
- 五、扩展的开发教程
1、本文使用源码版本为PHP-7.1.192、本文安装的PHP版本为7.1.193、使用电脑为Mac,操作系统信息如下
4、本文提到的扩展开发是PHP扩展,而不是Zend扩展
5、文章原文来自于博客(https://github.com/WGrape/Blog),关注获取最新文章
在/php-src/Zend/zend_modules.h头文件中定义了_zend_module_entry结构体,这个结构体就是PHP扩展的结构体,称为module,除了一些基本信息外,主要提供了以下个钩子函数
- MINT :模块初始化时被调用
- MSHUTDOWN :模块结束化时被调用
- RINT :每一次请求时被调用
- RSHUTDOWN :每一次请求结束后被调用
在/php-src/Zend/zend_extensions.h头文件中定义了_zend_extension结构体,这个结构体就是Zend扩展的结构体,称为extension。相比PHP扩展,主要提供了更底层的钩子函数,如下所示
Json扩展定义结构体为zend_module_entry,可知它是PHP扩展
Opcache扩展定义结构体为zend_extension,可知它是Zend扩展
Xdebug扩展必须在Zend生命周期内Hook才能实现对代码的调试,所以Xdebug是Zend扩展
扩展是区分php扩展和zend扩展的,在PHP源码中也严格区分module和extension这两个定义
- module表示php extension,即PHP的扩展,通过extension=*加载
- extension表示zend extension,即Zend的扩展,通过zend_extension=*加载
在源码中的php-src/ext目录就是扩展目录,如json、mysqli、pdo等常用的扩展,其中每个扩展都主要由以下文件组成
- tests :单元测试目录
- config.m4 :扩展的编译配置文件(Unix系统)
- config.w32 :扩展的编译配置文件(Windows系统)
- php_{$module}.h :扩展的头文件
- {$module}.c :扩展源文件
- {$module}.php :扩展的测试文件
在编译扩展成功后,会在扩展目录下生成一个run-test.php脚本文件,这个脚本会自动执行tests目录下的所有单元测试。
此外在扩展目录下还会自动生成一个{$module}.php扩展的测试文件,可以方便的测试扩展是否可以正常加载和使用
扩展下载后只有源码,需要进行编译生成.so扩展文件后才可以被PHP使用,config.m4和config.w32这两个文件就是在后续执行phpize阶段会使用到的编译配置文件。
m4是一种宏处理文件,主要由PHP_ARG_WITH和PHP_ARG_ENABLE两部分构成,一般使用第二部分即可,用于开启指定的扩展。这样在编译阶段,就会判断$PHP_PHP_HELLO变量不是no,从而执行此扩展的编译。
其中dnl宏会删除本行多余的字符,可以简单的理解为注释,如下所示,如果需要编译php_hello这个扩展,把PHP_ARG_ENABLE部分最前面的dnl宏都去掉即可
一般名为php_{$module}.h的是扩展头文件,一般用于定义需要的常量和函数等
一般名称为{$module}.c的是扩展源文件,主要由以下部分组成
- zend_module_entry :定义扩展的结构体
- PHP_FUNCTION :定义扩展的函数
- Hook_FUNCTION :如 PHP_MINIT_FUNCTION 等
在php-src/main/main.c文件中,php_module_startup()函数会执行扩展的加载与初始化。
在此函数中,extension_lists是一个保存着解析ini配置后获得的所有扩展(包括PHP扩展和Zend扩展)的链表,通过使用&extension_lists.engine和&extension_lists.functions获取PHP扩展列表和Zend扩展链表,然后通过php_load_zend_extension_cb()或php_load_php_extension_cb()分别完成不同类型扩展的加载
如在PHP扩展与Zend扩展一节中看到的,这两种扩展分别提供了不同的钩子函数,这些函数在PHP生命周期内的调用顺序如下图所示
获取PHP源码后,切换至7.1.19版本,按如下命令操作
切换到ext扩展目录下,在此目录下,有一个ext_skel脚本,可以用来自动生成扩展的基础文件。比如创建一个print_hello的扩展,按如下命令操作
执行成功后,会得到如下提示
回到在ext目录下,发现已经成功生成print_hello目录,主要包含如下文件
- tests :单元测试目录
- config.m4 :扩展的编译配置文件(Unix系统)
- config.w32 :扩展的编译配置文件(Windows系统)
- php_print_hello.h :扩展的头文件
- print_hello.c :扩展源文件
- print_hello.php :扩展的测试文件
打开config.m4配置文件,如下所示
找到PHP_ARG_ENABLE这段代码,删掉前面的dnl宏,如下所示
找到PHP_FUNCTION(表示定义的扩展函数),在如下confirm_print_hello_compiled函数中添加一句输出hello world的代码
通过执行以下命令执行对扩展的编译处理
执行make命令成功后如下所示
执行sudo make install命令成功后如下所示
测试脚本会先动态加载print_hello扩展,并输出扩展中所有提供的函数,最后执行在print_hello.c源文件中定义的confirm_print_hello_compiled 函数,如果正常执行则说明扩展加载且执行成功
脚本执行成功后如下所示
到目前为止,简单的print_hello扩展就已经开发完成,当然还可以在print_hello.c源文件中定义更多的扩展函数,做更多有趣的事情!不过篇幅有限就不再讲解,关于扩展的高阶使用请关注博客(https://github.com/WGrape/Blog),获取最新文章!
今晚拿下PHP反序列化的一系列操作
在CTF中反序列化类型的题目还是比较常见的,之前有学习过简单的反序列化,以及简单pop链的构造。这次学习内容为php内置的原生类的反序列化以及一点进阶知识。
在题目给的的代码中找不到可利用的类时,这个时候考虑使用php中的一些原生类有些类不一定能够进行反序列化,php中使用了zend_class_unserialize_deny来禁止一些类的反序列化。
原生类常见的用法是用来进行XSS、SSRF、反序列化、或者XXE,今天就来好好总结一下。在CTF中常使用到的原生类有这几类1、Error2、Exception3、SoapClient4、DirectoryIterator5、SimpleXMLElement下面针对这几个类来进行总结。
soap是webServer的三要素之一(SOAP、WSDL、UDDI),WSDL用来描述如何访问具体的接口,UUDI用来管理、分发、查询webServer,SOAP是连接web服务和客户端的接口,SOAP 是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息。所以它的使用条件为:1.需要有soap扩展,需要手动开启该扩展。2.需要调用一个不存在的方法触发其__call()函数。3.仅限于http/https协议
类摘要:PHP手册
注意这个__call()方法public __call(string $name, array $args): mixed该方法被触发的时候,它可以发送HTTP或HTTPS请求。使用这个类时,php中的scapClient类可以创建soap数据报文,与wsdl接口进行交互。用法如下:
测试
kali开启监听nc -lvp 4444,执行该文件。【注意开启soap模块】
kali中就会返回监听到的内容
这道题目就是利用的PHP原生类进行反序列化来实现SSRF,因为在这里是没有给出可利用的类,所以就需要使用原生类。在解答此题的过程中,还需要利用到CRLF。CRLF是回车 + 换行(\\r\\n)的简称,进行url编码后是%0a%0d%0a%0d这道题的思路就是先利用ssrf访问flag.php然后post一个数据 toke=ctfshow和请求头X-Forwarded-For 就能把flag写到flag.txt中了。用到SoapClient类了。这个类中有个__call魔术方法,触发时会调用SoapClient类的构造方法。
使用get传入vip的参数即可。然后访问flag.txt就可以得到flag了。此处无报错,即是成功。
Error类是php的一个内置类,用于自动自定义一个Error,在php7的环境下可能会造成一个xss漏洞,因为它内置有一个 __toString() 的方法,常用于PHP 反序列化中。
另一种,Exception 内置类,与上述类似,只是换了一个类,将Error换成了Exception
其它与上述相同。
使用条件:open参数可控。
在同目录下创建一个test.php。然后执行上面的代码,就会发现test.php已经被删除了。
前提:需要有sqlite3扩展,且不是默认开启,需要手动开启
示例:
SimpleXMLElement暂无示例。
学习不止,脚步不停!欲想学安全,必先了解一番,我这里整理了300PDF文档,包括网络安全学习视频、全套工具包、渗透测试、技术文档、应急响应等,需要的关注我,私信回复“资料”获取!!
PHP反序列化的一些原生类的基础知识暂时学习到这里,后面关于PHP反序列化的还有phar反序列化,session反序列化。慢慢来吧。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。