从 BugScan Chaos Memos 看摆龙门阵

题目延缓关闭,可以体验一波 http://114.55.62.235/

当了一回擂主,出了一道擂台赛题目,套路了一波。于是贱贱的出来分享一下摆龙门阵的过程了。如果有老司机愿意当擂主,希望这篇文章能帮到你。

选材

热门,关注度高,好玩的漏洞。

从选材上,我挑选了近期热门的漏洞 S2-032 命令执行漏洞,安全研究人员应该密切关注国内外最新漏洞。这里提一下为什么不选 S2-033,这个时间,S2-033 的 Exp 其实已经出来了,但是全民使用的利用工具还没有普及,是的,太新的东西不能用,不然你会觉得我是来骗 Exp 的。为什么不选 S2-033 其实还有个原因,后面会提到。

现实意义

尽可能的有现实意义。

BugScan Chaos Memos 整体背景是一个内网渗透, Flag 在一台内网 FTP 服务器上,需要通过 Web 当跳板,访问 FTP 服务拿到 Flag。这在现实中,是经常碰到的。

在 Web 漏洞展示上,这里没有用 .action 或者 .do,在大多数人的眼里,判断是不是 Struts2 就是看 URL 是不是 .action 或者 .do。这显然是一个误区,所以这次第一关的目的就是纠正这个错误的观念。asp, aspx, jsp, php 后缀各种乱上都可以成功访问。

没错,Web 服务指纹识别难就难在程序员可以这么整你。怎么才能提高扫描器的识别准确率,这确实是值得我们思考。

难度定位

难度需要适中,不宜简单至送分,也不能难的不讲道理。

一开始,我计划的是通过 Web 迷惑,一旦你识破了是 S2-032, 就可以直接读到 Flag。这样的话,这个题最多就只有 50 积分了。太简单。但是也不能像那些CTF比赛一样,难到没朋友,什么 PHP 出了一个 Bug,把这个利用起来,那种实在是太难了。

S2-032 代码执行,比较简单,Curl 读 FTP 也比较简单,但是组合起来,就比较有意思了。所以我推荐的就是组合拳。

安全性

题目本身需要保证安全性。要防止有人搅屎。权限限制必须要严格。

这次比较尴尬的地方是 xss, 我一开始想呈现的是一个完整功能的网站,为的就是模拟真实。后来发现用户输入这里是可以 XSS 的,写了一个 XssFilter 又不敢上。Exp 里面有特殊字符,怕过滤了之后影响命令执行。但是上线的时候各种不看 hint 各种 XSS,于是本宝宝生气了,把其它功能给阉了。不过后面发现,我是手抖了一下,把 id 弄成 String 类型了,改成 int 就没问题了。

同时,因为命令执行,如果用户到服务器上,把整个网站目录给删除了,会影响其它同学什么什么的。

构建

推荐使用 Docker 来构建,写成 Dockerfile 布署方便,安全性相对比较好。一旦有人搅屎,能快速恢复环境。如果你不会 Docker 的话,我推荐你看这本书:《Docker - 从入门到实践》

挖坑过程

好了,上面说了那么多,都是一些基本原则。需要擂主都注意的。这里我就说说我挖坑的过程。我们就按做题角度来说一说我都挖了哪些坑。

  1. 样式

    如果你看过 S2-033 的漏洞的演示站点,就会发现,这次的 UI 和那个站点是一模一样的。那个站点在 Struts2 安装包里面就有,叫 struts-rest-showcase。没错,第1个坑,就是这个 UI,会将见过这个站点的人思路导向最新的 S2-033,也许你会拿着 S2-033 的 PoC 测试一通,哈哈哈,坑的就是你。当然,这个 UI 也在一定程度上提醒了老司机,这个可能是 Struts2(第 1 处tips)。

  2. 后缀

    S2-032 的漏洞,如果是按常理出牌,是会将 URL 以 .action 或者是 .do 结尾。所以我要隐藏掉这个典型的后缀。

    struts.xml 里面配置:

    1
    <constant name="struts.action.extension" value="php,asp,aspx,jsp" />

    如此就将后缀成功修改。此处就是第2个坑

  3. 错误页面

    从 IIS 的配置信息里面,将错误页面抠出来,放到 /WebContent/errors/ 目录下,然后在 web.xml 里面配置:

    1
    2
    3
    4
    5
    6
    7
    8
    <error-page>
    <error-code>404</error-code>
    <location>/errors/404.htm</location>
    </error-page>
    <error-page>
    <error-code>500</error-code>
    <location>/errors/500.htm</location>
    </error-page>

    如此就把 404 与 500 错误页面成功伪造成 IIS 的啦,第 3 处坑

    其实在添加数据,删除数据后的跳转页面,整体风格用的 thinkphp 的默认风格,有没有被骗到?嘻嘻嘻。

  4. 页面信息

    在页脚部分,加入 Powered By 字样,见过的人一眼就能看出来不是,但是,对于一些扫描器来说,这些都是判断的依据。第4处坑

    当然页面里面,也隐藏了提示。

    Pwoered By 后面加了 that's true? ,最下方的 Seeing Isn't Beliving (译:眼见为虚) 统统都暗示页面很多信息都是伪造的,第2处提示

    第3处提示就比较难懂了。一开始进入页面后,有3条数据,前两个都是最近才爆出的通用型漏洞,第3条,指引关注近期热门漏洞。但是,这些放在那里其实没什么太大用处,因为可以被任何人删除。所以我刻意写到了注释里面。

  5. 头部伪造

    第5处坑,很多人判断是不是 tomcat 容器,都是看 HTTP 返回头部的 Server 字段,所以我就将他修改成 nginx 了。

    修改 tomcat 的 server.xml,在 Connector 里面加上 server="nginx":

    1
    2
    3
    <Connector server="nginx" port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />

    所以前端展示的信息里面,url 上是 asp,aspx,jsp,php,报错页面是 IIS 的,返回头部是 nginx 的。总体上,切合了主题:BugScan Chaos(混乱的) Memos。

    天使酱说我应该把所有的全部伪装成某一种语言的,我要真这么搞,再故意卖一个伪注入的破绽,我的天呐,我还想活着呢。

  6. 用户信息伪造

    进入服务器之后相信很多人,whoami 一下后发现用户是 nt_authority_system,没错这就是第6处坑啦。不注意看,会真当成 Windows 其实还可以再装的像一点的。

    使用这个用户,还有个用处就是降权, 我们来看一下 Dockerfile 里面部分内容:

    1
    2
    3
    4
    5
    6
    7
    8
    RUN set -x \
    && useradd -r nt_authority_system \
    && chmod a+x $CATALINA_HOME/bin/*.sh \
    && chmod a+w $CATALINA_HOME/logs/ \
    && chmod a+w -R $CATALINA_HOME/work/Catalina/ \
    && chmod a+w -R $CATALINA_HOME/temp/

    USER nt_authority_system

    -r 创建系统账户,也就是当个服务账号来用,只给这个用户几个目录可以写,网站目录是只能读不能写的。所以,你想传 webshell 上去?踩第7处坑了吧?使用 docker 的好处之一就是系统很精简,所以很多库都没有,后来我看到有些同学还在 /tmp 目录里面各种传远控,不过大部分都跑不起来吧。

  7. 迷惑的目录名

    我们先看一下相关的配置文件:

    1
    2
    3
    ENV WIN_DIR /C:\\Windows/System32/tomcat/bin/
    RUN mkdir -p "$WIN_DIR"
    WORKDIR $WIN_DIR

    目录名这里,我新建了一个目录,/C:\\Windows/System32/tomcat/bin/ 哈哈哈,注意前面的 /,不注意看的时候,就会看走眼。其实本来是想把整个网站也放在这个目录下面的,这样就更有迷惑性了。

    WORKDIR 将启动的目录放在这个目录下面,所以,你一进去,习惯性的 ls, dir 返回的东西是空的,空的,空的!没错,就是造成一个执行出错的假像,第8处坑

  8. 配置文件

    首先是第3处提示, echo "hahaha, flag is not in this mechine.">/f1ag_is_n0t_H3r3 在根目录下面放了这个文件,提示 flag 不在这台服务器上,于是很自然的就会想到需要内网渗透。那么,就需要去翻配置文件了。

    一般配置文件里面会留下一些连接的信息,比如数据库,比如备份服务器密码等。

    拿到一个 JSP 的站点,首先应该去看 web.xml,之后再看其它的文件,那么在 web.xml 里面看到了配置信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- 	
    <conn>
    <conndb>
    <type>mysql</type>
    <host>localhost</host>
    <port>3306</port>
    <user>root</user>
    <password>Kd72Cb4AD498458D</password>
    </conndb>
    Backup Server
    <ftp>
    <host>bugscan</host>
    <user>ftp</user>
    <password>Kd72Cb4AD498458D</password>
    </ftp>
    </conn>
    -->

    这里是第9处坑,我故意加了一个 mysql 的配置,不为别的,就是恶心你,因为netstat命令被干掉了(这里忘记了 ss 命令,好尴尬),你看不到是不是真的开了这个服务。但是,另一方面,提示已经说了不在这台机器上,于是 mysql 就可以直接排除了。问题是,你信吗?hahaha. 其实当时有想过把 hosts 地址改成 bugscan.net

  9. FTP 配置

    FTP 这里实际上是一个虚拟的 ftp, 西瓜大牛用 py 重写的一个 ftp。这里是第10处坑,ftp 外部是不能访问的,只能由这台服务器代你访问,当时是真的想把 hosts 文件改成 bugscan.net, 这样就能坑到更多人了。

    首先需要用配置文件里面的用户名密码拿到 readme.txt,之后就是拿 flag 了。没错,ftp 命令被干掉了。但是故意留下了 curl,So, 快去看 curl 怎么访问 ftp 吧。

擂主提交的东西

如果是 Web 的题目,只需要将相关的文件全部写成 Dockerfile 形式,再加上布署的文档,就 OK 啦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  bugscan_chaos_memos tree -L 2
.
├── java8
│   └── Dockerfile
├── python27
│   ├── Dockerfile
│   ├── get-pip.py
│   └── python.tar.xz
├── pyftp
│   ├── Dockerfile
│   └── ftpserver.py
├── s2-032
│   ├── Dockerfile
│   └── apache-tomcat-7.0.68.tar.gz
└── README.md

4 directories, 11 files

像上面的目录结构就是我本次提交的目录结构,其实 java8 和 python27 是可以通过 docker hub 来安装的,但是我这边网速不是慢嘛,自己 build image 的时候太慢了,于是我就先把这两个基础 image 弄出来了。

总结一下

s2-032 + curl 访问 ftp ,整体思路是撕开内网一个口子,然后,通过这个口子去进一步攻击内网。到这里,如果你还说你对内网渗透一脸懵逼的话,那真的是太尴尬了。

  • .php 不一定是 PHP 写的
  • Server:nginx 不一定是 nginx
  • 看到默认的错误页面,不一定是真的错误页面

Seeing isn’t beliving~