XSS-Bot的简单实现

xss-跨站脚本伪造,其利用的核心是诱导目标用户访问站点,渲染页面,执行恶意代码。在CTF题目中需要一个Bot来代替真实受害用户。

Webdriver

浏览器引擎可以通过脚本操作浏览器的行为,包括xssBot所用到的后台登陆,渲染页面等操作。可操作性也是很高的。

目前主流的浏览器都有对应的Webdriver,Python操作Webdriver的文章也已经有很多,不必赘述。

但是,Webdriver的操作需要基于浏览器进行,在一个Docker镜像中,只有Webdriver是不行的,Webdriver并不是一个可以独立运行的浏览器。所以在Docker题目中Webdriver的解决方案比较复杂。

Phantomjs

Phantomjs是一个支持跨平台的无界面浏览器,但是它已经停止更新并被官方弃用。好处是依然可用,且十分便利。

在Docker中可以直接使用,Github:https://github.com/ariya/phantomjs 下载地址:https://phantomjs.org/download.html

版本要求

对selenium的版本要求为selenium<=2.48.0,新版本会抛出异常如下
UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead

他表示在新版的Selenium中已经弃用PhantomJS。

Docker搭建

Dockerfile

FROM debian:buster-slim

ARG PHANTOM_JS_VERSION
ARG DUMB_INIT_VERSION

# 设置国内源
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list

# https://bitbucket.org/ariya/phantomjs/downloads/
ENV PHANTOM_JS_VERSION ${PHANTOM_JS_VERSION:-2.1.1-linux-x86_64}

# 安装运行时依赖,包括 Python 3 pip 和 setuptools
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
bzip2 \
libfontconfig \
python3 \
python3-pip \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& pip3 install --upgrade pip setuptools

# https://github.com/Yelp/dumb-init/releases
ENV DUMB_INIT_VERSION ${DUMB_INIT_VERSION:-1.2.2}

RUN set -x \
# 安装官方的 PhantomJS 发布版
&& mkdir /tmp/phantomjs \
&& curl -Ls https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-${PHANTOM_JS_VERSION}.tar.bz2 \
| tar -xj --strip-components=1 -C /tmp/phantomjs \
&& mv /tmp/phantomjs/bin/phantomjs /usr/local/bin \
# 安装 dumb-init(用于正确处理 PID 1)。
&& curl -Lso /tmp/dumb-init.deb https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_amd64.deb \
&& dpkg -i /tmp/dumb-init.deb

# PhantomJS 需要 OpenSSL 配置,即使是空的,否则会出现“libssl_conf.so: cannot open shared object file”的错误
ENV OPENSSL_CONF=/opt/openssl.cnf

RUN set -x \
# 以非 root 用户运行
&& useradd --system --uid 52379 -m --shell /usr/sbin/nologin phantomjs \
&& touch /opt/openssl.cnf \
# 基本测试
&& su phantomjs -s /bin/sh -c "dumb-init phantomjs --version"

USER phantomjs

EXPOSE 8910

ENTRYPOINT ["dumb-init"]
CMD ["phantomjs"]

# 注意:健康检查仅在以 --webdriver=8910 启动时才有意义
#HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
# CMD curl --connect-timeout 5 --silent --show-error --fail http://localhost:8910/wd/hub/status || exit 1

上面是一个搭建后可用的PhantomJS,使用docker构建镜像后,可以引入此镜像进行题目编写,或者在词镜像上增加其他内容。

此镜像配备Python3.7环境,pip3环境,同时取消了端口暴露,以便更让好的在GZCTF平台运行而不暴露额外端口。此镜像的DockerHub标签sj1t/phantomjs_noexpose:latest 此镜像基于Github项目改编,源地址:https://github.com/wernight/docker-phantomjs/blob/master/latest/Dockerfile

因为XSS Bot基于python会更好实现,所以干脆XSS题目基于Python Flask编写,所以没有PHP环境,可以修改Dockerfile构建PHP版本。注意此Dockerfile最终使用的用户非root用户。启动此浏览器服务使用命令phantomjs --webdriver=8910,会在docker容器中的8910端口提供浏览器服务。

Python实现XSS Bot

代码如下

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

def check_answer():
driver = webdriver.Remote(
command_executor='http://127.0.0.1:8910/wd/hub',
desired_capabilities=DesiredCapabilities.PHANTOMJS)

driver.get("http://127.0.0.1:5000/login")

driver.find_element_by_name('username').send_keys('admin')
driver.find_element_by_name('password').send_keys('password')

login_button = driver.find_element_by_css_selector('input[type="submit"]')
login_button.click()

# 防止弹窗阻塞js执行
driver.execute_script("window.confirm = function(msg) { return true; }")
driver.execute_script("window.alert = function(msg) { return true; }")
driver.execute_script("window.prompt = function(msg) { return true; }")

driver.quit()

以存储型XSS举例,需要进行验证时调用此函数即可,可以定时调用,也可以在每次用户提交留言内容时调用。

XSS Bot处理js弹窗

以存储型XSS距离,使用PhantomJS进行模拟管理员登录后,比如用户插入了<script>alert(1)</script>语句,PhantomJS渲染时会触发弹窗,js弹窗时会阻塞下面的js执行,如果不处理弹窗,下面的js就解析不到,下面的其他js代码比如xss平台也无法外带,简单的处理办法如下

# 防止弹窗阻塞js执行
driver.execute_script("window.confirm = function(msg) { return true; }")
driver.execute_script("window.alert = function(msg) { return true; }")
driver.execute_script("window.prompt = function(msg) { return true; }")

其他

此解决方案亦可以适用于简单的CSRF Bot的实现。

PhantomJS还可以结合Python实现爬虫,网页截图等,虽然已不再被官方支持,但是依然简洁好用。而Chrome或FireFox甚至Edge的Webdriver,也会是今后爬虫的主流解决方案。