wtf.sh-150

2023-11-05 01:10
文章标签 150 sh wtf

本文主要是介绍wtf.sh-150,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

最近在刷ctf题,在理解了大佬们的wp后自己做完之后,从头到尾把思路过了一遍,做次记录为以后复习和打比赛做准备,同时也希望能帮到别人。

0x01

进入网址,发现是一个论坛,有注册,登录和发表的功能,初步猜测应该是可以利用账号进行获取flag,我们先顺着页面向下找一找,看有没有什么提示信息,没有什么发现,然后路径扫描试试,发现有一个post.wtf路径存在路径穿越漏洞,能够获取网站的源码,所以我们试着用这个进行网站源码的获取

进入页面

向下找找看有没有什么有没有有用的东西,一堆源码,太花时间,所以我们直接搜索flag关键词,看有没有

果然有,get_flag1,所以我们把这段源码整理一下,整理如下

<html>
<head><link rel="stylesheet" type="text/css" href="/css/std.css" >
</head>
$ if contains 'user' ${!URL_PARAMS[@]} && file_exists "users/${URL_PARAMS['user']}"
$ then
$   local username=$(head -n 1 users/${URL_PARAMS['user']});
$   echo "<h3>${username}'s posts:</h3>";
$   echo "<ol>";
$   get_users_posts "${username}" | while read -r post; do
$       post_slug=$(awk -F/ '{print $2 "#" $3}' <<< "${post}");
$       echo "<li><a href=\"/post.wtf?post=${post_slug}\">$(nth_line 2 "${post}" | htmlentities)</a></li>";
$   done 
$   echo "</ol>";
$   if is_logged_in && [[ "${COOKIES['USERNAME']}" = 'admin' ]] && [[ ${username} = 'admin' ]]
$   then
$       get_flag1
$   fi
$ fi
</html>

在这段代码中的关键代码是:

if is_logged_in && [[ "${COOKIES['USERNAME']}" = 'admin' ]] && [[ ${username} = 'admin' ]]
$   then
$       get_flag1

这段代码的意思是说,如果我们的登录用户是admin,那么我们就能获得flag1,所以,看来,如果我们想要获得flag1,就必须是admin用户登录,那么如何登录呢?代码中也给了提示,代码检查的是cookies,经过抓包,发现登录用户都会有自己的一个Token,看来我们只需要修改登录用户名和登录的Token即可登录admin用户

那么,我们从哪里获得admin用户的Token呢?我们还是利用路径穿越漏洞,看看有没有保存用户的目录,发现真的有

红色框里的是Token,在这个上面还有一串字符,经过分析是sha1,但是对于我们登录admin用户没有用处,所以我们伪造usernam和Token登录admin,但是这里提醒一下,不仅仅需要修改Token就可以进去,同时还得修改

这里解释一下为什么需要修改这个

这里我们发现每一个用户应该都是有一个文件来存储,所以想要登陆某个用户,也得加上这个,除非你是账号密码登陆

发现flag1,但是这个flag不是完整的,看来我们还得继续寻找第2个flag

0x02

到这里我们想想还有什么我们没有注意到,就是wtf,我们知道wtf不是一般常规的网页文件,所以我们试着寻找解析wtf文件的代码

这段就是解析wtf文件的代码,经过整理如下:

max_page_include_depth=64
page_include_depth=0
function include_page {# include_page pathnamelocal pathname=$1local cmd=[[ ${pathname(-4)} = '.wtf' ]];local can_execute=$;page_include_depth=$(($page_include_depth+1))if [[ $page_include_depth -lt $max_page_include_depth ]]thenlocal line;while read -r line; do# check if we're in a script line or not ($ at the beginning implies script line)# also, our extension needs to be .wtf[[ $ = ${line01} && ${can_execute} = 0 ]];is_script=$;# execute the line.if [[ $is_script = 0 ]]thencmd+=$'n'${line#$};elseif [[ -n $cmd ]]theneval $cmd  log Error during execution of ${cmd};cmd=fiecho $linefidone  ${pathname}elseecho pMax include depth exceeded!pfi
}

这段代码是能够解析并执行wtf文件

function reply {local post_id=$1;local username=$2;local text=$3;local hashed=$(hash_username "${username}");curr_id=$(for d in posts/${post_id}/*; do basename $d; done | sort -n | tail -n 1);next_reply_id=$(awk '{print $1+1}' <<< "${curr_id}");next_file=(posts/${post_id}/${next_reply_id});echo "${username}" > "${next_file}";echo "RE: $(nth_line 2 < "posts/${post_id}/1")" >> "${next_file}";echo "${text}" >> "${next_file}";# add post this is in reply to to posts cacheecho "${post_id}/${next_reply_id}" >> "users_lookup/${hashed}/posts";
}

这段代码是能够上传wtf文件并执行,那这样的话我们上传执行命令上去,让服务器执行我们的命令,从而我们能够找到服务器中flag2的位置和内容

到这里为止,我们想起论坛还有一个发表的功能

echo "${username}" > "${next_file}";

这段代码就是把用户名写在了评论文件的内容中,如果用户名是一段可执行代码,并且写入文件的格式是wtf格式的,那么这个文件就可以执行我们的代码了,所以我们需要怎么做呢?

0x03

通过以上分析,我们大致知道我们要做什么了,那接下来就来完成相应过程,首先,我们要写入一个后门,然后我们通过访问后门来得代码返回的结果,那么我们需要先注册一个用户名,而且用户名是可执行代码,然后观察返回结果

一、

上传后门

注册了一个普通用户,然后发表发表评论出上传一个后门,上面加%09的原因是:%09是水平制表符防止后台把我们的后门当做目录去解析,到此,后门上传成功,接下来注册含执行代码的用户

二、

注册用户

${find,/,-iname,get_flag2}

将用户名写入后门中

然后访问后门地址,得到如下回显

说明flag2的位置在这个路径,这里解释一下为什么要注册一个这样的用户,前面我们在得到flag1的时候的格式是get_flag1,所以这里我们注册一个get_flag2的用户,来寻找falg2,

三、

注册用户

$/usr/bin/get_flag2

让后访问后门地址

得到如下结果:

到此得到flag2

0x04

总结:这道题应该是最近做过的最难的了,通过这道题学到了很多姿势。对wtf格式的文件增长了利用姿势,通过用户名来执行代码在之前是真没想过。总之这题不愧为国际赛题

这篇关于wtf.sh-150的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Leetcode面试经典150题-128.最长连续序列-递归版本另解

之前写过一篇这个题的,但是可能代码比较复杂,这回来个简洁版的,这个是递归版本 可以看看之前的版本,两个版本面试用哪个都保过 解法都在代码里,不懂就留言或者私信 class Solution {/**对于之前的解法,我现在提供一共更优的解,但是这种可能会比较难懂一些(思想方面)代码其实是很简洁的,总体思想如下:不需要排序直接把所有数放入map,map的key是当前数字,value是当前数开始的

表单验证(WTF)

官方文档 在Flask项目开发中针对提交表单的校验,可以使用Flask-WTF扩展库进行快速的字段校验,也可以进行页面快速渲染,并提供跨站请求伪造的保护功能。 安装Flask-WTF pip install flask-wtf 实现注册功能 注册表单模型定义 在定义的表单类中定义需要验证的username、password和password2字段,并实现如下校验: 校验密码passw

Leetcode面试经典150题-2.两数相加

解法都在代码里,不懂就留言或者私信 理论上提交这个就是最优解 字节考过不下20次,这个高居字节面试榜第9名 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) {

Leetcode面试经典150题-83.删除链表中的重复元素

解法都在代码里,不懂就留言或者私信 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int va

力扣面试150 分隔链表 模拟

Problem: 86. 分隔链表 👨‍🏫 参考题解 Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val

力扣面试经典算法150题:接雨水

接雨水 今天的题目是力扣面试经典算法150题中的困难难度数组题目:分发糖果。 题目链接:https://leetcode.cn/problems/trapping-rain-water/description/?envType=study-plan-v2&envId=top-interview-150 题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱

Leetcode面试经典150题-106.从中序和后序序列构造二叉树

解法都在代码里,不懂就留言或者私信 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val;

力扣面试150 旋转链表 闭链成环

Problem: 61. 旋转链表 👨‍🏫 力扣官解 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }*

Hyperledger Fabric教程(6)-- byfn.sh分析-peer-base.yaml

vim base/peer-base.yaml peer节点的通用基础配置

1.百度150道题,今天开刷。1.用C语言实现一个revert函数,它的功能是将输入的字符串在原串上倒序后返回。

#include "stdio.h"#include <string.h>#include <cstdlib>char * revert(char *str){int len = strlen(str);int i = 0;char temp;while(i < len/2) //这里注意,不能取等号{temp = str[len-1-i];str[len-1-i] =str [i];st