记录CTF从入门到提高的学习过程
CTF练手平台
- 合天:http://www.hetianlab.com/
- 实验吧:http://www.shiyanbar.com/ctf/
- i春秋:https://www.ichunqiu.com/
- Bugku: http://ctf.bugku.com/
- 攻防世界: https://adworld.xctf.org.cn
- 蓝鲸安全 http://whalectf.xin/
- Jarvis OJ https://www.jarvisoj.com
SQL注入系列
Tricks
- 十六进制
- ‘ctf’ ->0xhex(ctf)
- #->%23 或者使用 –+
- =被过滤,like/regexp/!!=/!<>
- 盲注引号waf,ascii()变数字
- substring(str from pos for len) 绕过逗号waf
- rlike/regexp ‘正则’ 爆破数据
- or 被waf用||
- 空格被waf用/**/、反引号
- \N=NULL,可忽略空格
宽字节注入
编码介绍
- ASCII编码的范围是0-127
- 国际通用UTF-8编码
- 中文常用GBK编码
- URL编码(常见的如%20、%27、%23、%5C)
成因
当MySQL使用gbk编码时,会认为两个字符是一个汉字,产生宽字节注入,第一个字节要大于128
addslashes()
addslashes常用来加\来转义特殊字符,绕过有以下两种思路
- \前加一个\,形成\\‘,单引号就可以生效
- 弄没转义的\ -> 宽字节注入,原理如下
1
2\' -> \\' ->\%27
%df' -> %df\' -> $df%5C%27
例题
http://chinalover.sinaapp.com/SQL-GBK/index.php
SQL约束攻击
成因
- mysql在进行查询时会自动忽略空格
- 长度有限制,大于长度会自动截断
- 借助截断和自动忽略实现再注册
例题
报错注入
成因
- 利用sql函数的错误用法使其报错
常用报错函数
floor()
1 | and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a); |
updatexml()
1 | or updatexml(1,concat(0x7e,(version()),0x7e),0) |
extractvalue()
1 | and extractvalue(1,concat(0x7e,(select database()))) |
exp()
1 | and exp(~(select * from(select user())a)) |
NAME_CONST()
1 | select * from(select NAME_CONST(version(),1),NAME_CONST(version(),1))a; |
例题
http://ctf5.shiyanbar.com/web/baocuo/index.php
分割注入
1 | select * from users where username='admin' and password='password'; |
时间盲注
常用的时间盲注函数
- sleep(time)
1 | sleep(3); |
- if(param1,param2,param3)
1 | # 类似于三元表达式 |
- substr(str,pos=1,len)
1 | substr("admin",1,1); |
- substring(str,pos,[len])
1 | substring("admin",2,1); |
- substring(str from pos [for len])
1 | substring("admin" from 2 for 1); |
- mid(str,pos,len)
1 | mid("admin",2,1); |
- substring(str,delim,count)
1 | substring('aaabbb','a',2); |
- select case when condition then result [when] [else result] end from tables
1 | select case when username='admin' THEN 'aaa' ELSE (sleep(3)) end from user; |
- ascii(char)
1 | ascii('a'); |
- benchmark(count,expr)
1 | 重复计算count次expr()函数,实现延时效果 |
- 笛卡尔积延时
1 | select count(*) from information_schema.columns A, |
- GET_LOCK(str,timeout)
1 | 只适用于长连接 |
- rpad()/repeat + RLIKE
1 | 原理类似ddos |
布尔盲注
根据输入不同来对比输出的差异来进行判断
常用函数
- mid()
- substr()
- substring()
- left()
- right()
- ascii()
- ord()
order by 相关注入
位运算符
- &、|、 ~、^、<<、>>
借助报错
1 | order by updatexml(1,concat(0x7e,database()),0) |
借助时间/布尔盲注
此处需要结合位运算
1 | order by if(condition,true,false) |
括号包括可直接读数据
1 | (select flag from users order by 1,2,3) union (select *******) |
例题
http://chall.tasteless.eu/level1
desc相关注入
desc/describe:提供有关一个表/列的信息
1 | desc table_name column_name |
万能密码
1 | admin'# |
1 | '+' #字符串--->0 |
1 | aaa'=' |
文件上传系列
客户端校验
JS校验
检查方式:检查包的后缀是否为合法后缀,前端验证
突破方式:禁用js/抓包改包
服务端校验
MIME类型检测
- 检查方式:检查content-type字段是否合法
- 突破方式:抓包修改content-type字段为合法字段
黑名单
- 检查方式:检查文件后缀是否位于黑名单,黑名单不允许上传
- 绕过方式:
- 大小写:Php、PHP
- 特殊后缀:php3、php5、phtml、pht、phtml、phps
- .htaccess绕过(需要AllowOverride=ALL)
- .user.ini绕过(需要当前目录存在至少一个php文件)
- 00截断(需要php<5.3.4,magic_quotes_gpc=off)
- 超长文件名截断:windows为256byte,Linux为4096byte
白名单
- 检测方式:检测文件后缀是否为白名单,允许白名单文件上传
- 绕过方式:配合解析漏洞
文件头检测
- 检查方式:getimagesize()
- 绕过方式:GIF89a绕过检测
竞争上传
- 检测方式:先上传,检测文件不合法就删除
- 绕过方式:不断上传,赶紧访问,触发写入shell
phpinfo getshell
以post向任意php文件上传文件时会先产生一个临时文件,可以借助文件包含漏洞和自包含使其getshell
文件包含漏洞
常见函数
- include() 多次包含,有错继续
- require() 多次包含,有错停止
- include_once() 单次包含,有错继续
- require_once() 单次包含,有错停止
类别
远程文件包含
远程文件包含需要开启allow_url_fopen、allow_url_include两个参数
本地文件包含
可以借助本地文件包含,直接读取文件
伪协议
file、http、ftp、php、bzip2/zip/zlib、data、glob、phar 、ssh2、rar、ogg、expect
详细如下:

1 | php://filter/convert.base64-encode/resource=index.php |
1 | # 要求allow_url_include=On |
session文件包含
- 要求session.upload_progress.enabled=On
- session文件默认存储于/var/lib/php/session_{your_php_session_id}
思路
- 图片马+文件包含
- 白名单+伪协议
- 可以借助参数绕过后缀,比如a.php?abcd
- 包含apache日志文件:/var/log/apache2
- 系统环境变量:/proc/self/environ,要求php运行于CGI、可以尝试修改user-agent字段
- Session文件默认为tmp,可以通过phpinfo查看位置
- php自包含->递归爆栈
- php://filter/string.strip_tags/resource=/etc/passwd 造成php崩溃
命令执行
代码执行
- eval()
- assert()
- call_user_user_func() <– iscallable()
- call_user_func_array()
- create_function()
- preg_replace(“”/e)
- array_map()
- usort()
- uasort()
- ${php_code}
命令执行
- system()
- exec()
- passthru()
- shell_exec()
反引号- ob_start()、ob_end_flush()
绕过
- 分隔符:%0a、%0d、;、&、|、||、&&
- 空格: $IFS、${IFS}、$IFS$9、%09、<
- 关键词:拼接($a=l;$b=s;$a$b)、单引号、双引号
- 编码绕过:’echo xxxx|base64 -d’
- 利用特殊函数,如substr()绕过过滤
无回显
- 延时
- HTTP请求
- DNS外带
- 写shell
极限利用
- 15个字符的RCE
- 7个字符的RCE
- 5个字符的RCE
- 4个字符的RCE
- 无字母数字RCE(异或、取反、自增)
反序列化
序列化:数据持久化 serialize()
反序列化:数据内存化 unserialize()/phar
变量类型
- public
- protected
- private
魔法函数
- __construct()
- __toString()
- __destruct()
- __wakeup()
- __sleep()
- __call()
waf绕过
- O:+4
- php bug 72663绕wakeup()
- php bug 71101Session反序列化
SSRF
危害
- 对外网、内网、本地发起端口扫描,获取服务信息
- 攻击运行在内网或本地的应用程序(比如溢出)
- 对内网Web应用进行指纹识别,通过访问默认文件实现
- 攻击内外网的Web应用,主要是使用Get参数就可以实现的攻击
- 利用File协议读取本地文件
判断
- 回显
- 延时
- DNS请求
相关函数
- file_get_contents()
- fsockopen()
- curl_exec()+协议
IP限制绕过
- 加端口号
- 短网址
- 指向任意IP的域名 xip.io
- 进制绕过(八进制、十进制、十六进制、不同进制的组合)
- 302跳转
- 结合dict://、file://、gopher://
- http://www.baidu.com@192.168.0.1/
- 加参数 index.php?a=12345
gopher协议
- gopher攻击redis
- 未授权访问
- 定时任务反弹shell
- 写webshell
- 写密钥
- gopher攻击mysql
辅助工具:https://github.com/tarunkant/Gopherus
XXE
用途
文件读取、命令执行、内网端口扫描、攻击内网、Dos攻击
XML实体注入
- 实体引用
- DTD:文档类型定义
- 内部引用:<!DOCTYPE 根元素 [元素声明]>
- 外部引用: <!DOCTYPE 根元素 SYSTEM “文件或协议”>
1
2
3
4<!ENTITY %name "<!ENTITY "key" value>">
%name
用&来引用
- 外部引用: <!DOCTYPE 根元素 SYSTEM “文件或协议”>
协议利用
- file协议
- filter协议
- http协议外带
盲XXE
利用协议外带
代码审计
弱类型
- :==:数字与字符串比较,会把字符串转换为数字
- md5强碰撞:===
- strcmp()
- in_array()
- md5()、sha1()
- array_search()
- strpos()

变量覆盖
- extract()
- $$
- parse_str()
- import_request_variables()
参数解析
- parse_url()://会引起解析问题
空白符问题
- is_numeric():忽略%20、\t、\n、\r、\v、\f
- trim():忽略:\t、\n、\r、\0、\v
伪随机数
- mt_srand()
- mt_rand()
命令执行逃逸
- escapeshellarg()
- escapeshellcmd()
Tricks
- 运算优先级绕过
本文链接: https://blog.yd0ng.top/2020/02/02/CTF%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E6%8F%90%E9%AB%98/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!