一次php代码审计(复习)
0x0 背景
源于ciscn2022华东北赛区的一道题ezphp
总体结构如下
upload.php
如下
1 |
|
flag.php
如下
1 | if ($_SERVER['REMOTE_ADDR'] == "127.0.0.1"){ |
config.php
如下
1 |
|
0x01 想法1 Soap反序列化
看一眼就会发现纯纯的phar反序列化打php内置Soap类反序列化
poc:
1 |
|
怼半天没通
0x02 想法2 getimagesize-URL请求
这里我们要仔细看一下源码
1 | function checkimg($img){ |
这里没有任何所谓的check 只是单纯的用getimagesize
解析一下我们的参数
我就试了一下upload.php?img=http://127.0.0.1/flag.php
然后就获得flag.txt
看一下php官网对于这个函数的解释
好吧 默认支持url参数 从4.0.5添加的 基础功不扎实 这都不知道
0x03 代码分析
看一下getimagesize
函数的定义
还是大家非常熟悉的php_stream_open_wrapper
但今天聊点其他的
如果发出http请求之后会交给
1 | php_stream_url_wrap_http_ex http_fopen_wrapper.c:741 |
在php_stream_url_wrap_http_ex
获取服务器返回的数据之后会解析header
如果Location
存在并且状态码((response_code >= 300 && response_code < 304)|| 307 == response_code || 308 == response_code)时就会至follow_location
为真
1 | if (!strncasecmp(http_header_line, "Location:", sizeof("Location:")-1)) { |
随后判断是不是http[s]
请求
1 | char new_path[HTTP_HEADER_BLOCK_SIZE]; |
如果返回Location
为合法url
1 | 307 |
则会跳转
否则会拼接到原有url后跳转
1 | 307 |
0x04 other
php_stream_url*中会使用php_url_free
函数对传入的数据进行严格的替换无法进行CRLF
1 | PHPAPI void php_url_free(php_url *theurl) |
一次php代码审计(复习)