1. web
1.1 Easy_unserialize
考点:猜猜猜 + phar反序列化
参考资料:
1、简析GXY_CTF “BabySqli v3.0”之Phar反序列化 https://www.gem-love.com/ctf/490.html
感觉是以前的原题,但源码泄露位置始终找不到,太菜了!!
2、writeup:https://www.52hertz.tech/2020/05/26/whuctf2020_writeup/#Easy-unserialize
思路:
step1:主页面访问?acti0n=php://filter/convert.Base64-encode/resource=upload.php
acti0n真不知道哪里来的,对base有过滤,大写绕过。
step2:view.php页面的file_exists可结合phar实现反序列化;
生成的phar文件改后缀名,绕过限制(本题phar在白名单内,那就不用改);
读flag.php用show_source或者highlight_file都可以。
step3:delete=phar://new4.jpg
upload.php
<?php
error_reporting(0);
$dir = 'upload/'.md5($_SERVER['REMOTE_ADDR']).'/';
if(!is_dir($dir)) {
if(!mkdir($dir, 0777, true)) {
echo error_get_last()['message'];
die('Failed to make the directory');
}
}
chdir($dir);
if(isset($_POST['submit'])) {
$name = $_FILES['file']['name'];
$tmp_name = $_FILES['file']['tmp_name'];
$ans = exif_imagetype($tmp_name);
if($_FILES['file']['size'] >= 204800) {
die('filesize too big.');
}
if(!$name) {
die('filename can not be empty!');
}
if(preg_match('/(htaccess)|(user)|(..)|(%)|(#)/i', $name) !== 0) {
die('Hacker!');
}
if(($ans != IMAGETYPE_GIF) && ($ans != IMAGETYPE_JPEG) && ($ans != IMAGETYPE_PNG)) {
#用exif_imagetype来检测文件类型
$type = $_FILES['file']['type'];
if($type == 'image/gif' or $type == 'image/jpg' or $type == 'image/png' or $type == 'image/jpeg') {
echo "<p align=\"center\">Don't cheat me with Content-Type!</p>";
}
echo("<p align=\"center\">You can't upload this kind of file!</p>");
exit;
}
$content = file_get_contents($tmp_name);
if(preg_match('/(scandir)|(end)|(implode)|(eval)|(system)|(passthru)|(exec)|(chroot)|(chgrp)|(chown)|(shell_exec)|(proc_open)|(proc_get_status)|(ini_alter)|(ini_set)|(ini_restore)|(dl)|(pfsockopen)|(symlink)|(popen)|(putenv)|(syslog)|(readlink)|(stream_socket_server)|(error_log)/i', $content) !== 0) {
echo('<script>alert("You could not upload this image because of some dangerous code in your file!")</script>');
# 后台解析,出现弹框
exit;
}
$extension = substr($name, strrpos($name, ".") + 1);
#查找字符串在另一字符串中最后一次出现的位置(区分大小写)
if(preg_match('/(png)|(jpg)|(jpeg)|(phar)|(gif)|(txt)|(md)|(exe)/i', $extension) === 0) {
die("<p align=\"center\">You can't upload this kind of file!</p>");
}
$upload_file = $name;
move_uploaded_file($tmp_name, $upload_file);
if(file_exists($name)) {
echo "<p align=\"center\">Your file $name has been uploaded.<br></p>";
} else {
echo '<script>alert("此地无银三百两")</script>';
}
echo "<p align=\"center\"><a href=\"view.php\" >此地无银三百两</a></p>";
#header("refresh:3;url=index.php");
}
?>
view.php
<?php
#include_once "flag.php";
error_reporting(0);
class View
{
public $dir;
private $cmd;
function __construct()
{
$this->dir = 'upload/'.md5($_SERVER['REMOTE_ADDR']).'/';
$this->cmd = 'echo "<div style="text-align: center;position: absolute;left: 0;bottom: 0;width: 100%;height: 30px;">Powered by: xxx</div>";';
if(!is_dir($this->dir)) {
mkdir($this->dir, 0777, true);
}
}
function get_file_list() {
$file = scandir('.');
return $file;
}
function show_file_list() {
$file = $this->get_file_list();
for ($i = 2; $i < sizeof($file); $i++) {
#sizeof 返回数组中元素的数目。
echo "<p align=\"center\" style=\"font-weight: bold;\">[\".strval($i - 1).\"] $file[$i] </p>";
}
}
function show_img($file_name) {
$name = $file_name;
$width = getimagesize($name)[0];
$height = getimagesize($name)[1];
$times = $width / 200;
$width /= $times;
$height /= $times;
$template = "<img style=\"clear: both;display: block;margin: auto;\" src=\"$this->dir$name\" alt=\"$file_name\" width = \"$width\" height = \"$height\">";
echo $template;
}
function delete_img($file_name) {
$name = $file_name;
if (file_exists($name)) {
# 反序列化点
@unlink($name);
if(!file_exists($name)) {
echo "<p align=\"center\" style=\"font-weight: bold;\">此地无银三百两</p>";
header("refresh:3;url=view.php");
} else {
echo "Can not delete!";
exit;
}
} else {
echo "<p align=\"center\" style=\"font-weight: bold;\">此地无银三百两</p>";
}
}
function __destruct() {
eval($this->cmd);
}
}
$ins = new View();
chdir($ins->dir);
echo "<h3>此地无银三百两" . $ins->dir . "</h3>";
$ins->show_file_list();
if (isset($_POST['show'])) {
$file_name = $_POST['show'];
$ins->show_img($file_name);
}
if (isset($_POST['delete'])) {
$file_name = $_POST['delete'];
$ins->delete_img($file_name);
}
unset($ins);
?>
1.2 HappyGame
考点:原型链泄露 + 代码审计
参考资料:
1、Node.js 这个反序列化的漏洞到底有多大? https://zhuanlan.zhihu.com/p/25257419?columnSlug=FrontendMagazine
2、2019SCUCTF部分题解 https://www.neddos.tech/?p=172
3、express中request.params取参数问题 https://www.jianshu.com/p/0eb9edf209f8
4、 Node.js 常见漏洞学习与总结 https://xz.aliyun.com/t/7184
5、NodeJS远程代码执行 https://www.jb51.net/article/91411.htm
6、writeup: https://blog.szfszf.top/article/43/
注意事项:
1、
获取首字符不为数字的token, 因为javascript数字开头的变量会导致报错,所以多次尝试让它生成一个以字母开头的就行了,然后将sessionID用新生成的替换,不要漏掉最后的分号。
2、
3、本地搭建完成
在ubuntu下使用Postman,Body处改JSON格式,Headers改Cookie,发送方式为post。
1.3 BookShop
考点:css注入 + csrf
参考资料:
1、writeup: https://blog.szfszf.top/article/43/