作者:低碳的S | 来源:互联网 | 2023-08-12 20:25
前言:
最近在刷ctf题,在理解了大佬们的wp后自己做完之后,从头到尾把思路过了一遍,做次记录为以后复习和打比赛做准备,同时也希望能帮到别人。
0x01
进入网址,发现是一个论坛,有注册,登录和发表的功能,初步猜测应该是可以利用账号进行获取flag,我们先顺着页面向下找一找,看有没有什么提示信息,没有什么发现,然后路径扫描试试,发现有一个post.wtf路径存在路径穿越漏洞,能够获取网站的源码,所以我们试着用这个进行网站源码的获取
进入页面
向下找找看有没有什么有没有有用的东西,一堆源码,太花时间,所以我们直接搜索flag关键词,看有没有
果然有,get_flag1,所以我们把这段源码整理一下,整理如下
$ if contains 'user' ${!URL_PARAMS[@]} && file_exists "users/${URL_PARAMS['user']}"
$ then
$ local username=$(head -n 1 users/${URL_PARAMS['user']});
$ echo "${username}'s posts:
";
$ echo "";
$ get_users_posts "${username}" | while read -r post; do
$ post_slug&#61;$(awk -F/ &#39;{print $2 "#" $3}&#39; <<<"${post}");
$ echo "- $(nth_line 2 "${post}" | htmlentities)
";
$ done
$ echo "
";
$ if is_logged_in && [[ "${COOKIES[&#39;USERNAME&#39;]}" &#61; &#39;admin&#39; ]] && [[ ${username} &#61; &#39;admin&#39; ]]
$ then
$ get_flag1
$ fi
$ fi
在这段代码中的关键代码是&#xff1a;
if is_logged_in && [[ "${COOKIES[&#39;USERNAME&#39;]}" &#61; &#39;admin&#39; ]] && [[ ${username} &#61; &#39;admin&#39; ]]
$ then
$ get_flag1
这段代码的意思是说&#xff0c;如果我们的登录用户是admin&#xff0c;那么我们就能获得flag1&#xff0c;所以&#xff0c;看来&#xff0c;如果我们想要获得flag1&#xff0c;就必须是admin用户登录&#xff0c;那么如何登录呢&#xff1f;代码中也给了提示&#xff0c;代码检查的是COOKIEs&#xff0c;经过抓包&#xff0c;发现登录用户都会有自己的一个Token&#xff0c;看来我们只需要修改登录用户名和登录的Token即可登录admin用户
那么&#xff0c;我们从哪里获得admin用户的Token呢&#xff1f;我们还是利用路径穿越漏洞&#xff0c;看看有没有保存用户的目录&#xff0c;发现真的有
红色框里的是Token&#xff0c;在这个上面还有一串字符&#xff0c;经过分析是sha1&#xff0c;但是对于我们登录admin用户没有用处&#xff0c;所以我们伪造usernam和Token登录admin&#xff0c;但是这里提醒一下&#xff0c;不仅仅需要修改Token就可以进去&#xff0c;同时还得修改
这里解释一下为什么需要修改这个
这里我们发现每一个用户应该都是有一个文件来存储&#xff0c;所以想要登陆某个用户&#xff0c;也得加上这个&#xff0c;除非你是账号密码登陆
发现flag1&#xff0c;但是这个flag不是完整的&#xff0c;看来我们还得继续寻找第2个flag
0x02
到这里我们想想还有什么我们没有注意到&#xff0c;就是wtf&#xff0c;我们知道wtf不是一般常规的网页文件&#xff0c;所以我们试着寻找解析wtf文件的代码
这段就是解析wtf文件的代码&#xff0c;经过整理如下&#xff1a;
max_page_include_depth&#61;64
page_include_depth&#61;0
function include_page {# include_page pathnamelocal pathname&#61;$1local cmd&#61;[[ ${pathname(-4)} &#61; &#39;.wtf&#39; ]];local can_execute&#61;$;page_include_depth&#61;$(($page_include_depth&#43;1))if [[ $page_include_depth -lt $max_page_include_depth ]]thenlocal line;while read -r line; do# check if we&#39;re in a script line or not ($ at the beginning implies script line)# also, our extension needs to be .wtf[[ $ &#61; ${line01} && ${can_execute} &#61; 0 ]];is_script&#61;$;# execute the line.if [[ $is_script &#61; 0 ]]thencmd&#43;&#61;$&#39;n&#39;${line#$};elseif [[ -n $cmd ]]theneval $cmd log Error during execution of ${cmd};cmd&#61;fiecho $linefidone ${pathname}elseecho pMax include depth exceeded!pfi
}
这段代码是能够解析并执行wtf文件
function reply {local post_id&#61;$1;local username&#61;$2;local text&#61;$3;local hashed&#61;$(hash_username "${username}");curr_id&#61;$(for d in posts/${post_id}/*; do basename $d; done | sort -n | tail -n 1);next_reply_id&#61;$(awk &#39;{print $1&#43;1}&#39; <<<"${curr_id}");next_file&#61;(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文件并执行&#xff0c;那这样的话我们上传执行命令上去&#xff0c;让服务器执行我们的命令&#xff0c;从而我们能够找到服务器中flag2的位置和内容
到这里为止&#xff0c;我们想起论坛还有一个发表的功能
echo "${username}" > "${next_file}";
这段代码就是把用户名写在了评论文件的内容中&#xff0c;如果用户名是一段可执行代码&#xff0c;并且写入文件的格式是wtf格式的&#xff0c;那么这个文件就可以执行我们的代码了&#xff0c;所以我们需要怎么做呢&#xff1f;
0x03
通过以上分析&#xff0c;我们大致知道我们要做什么了&#xff0c;那接下来就来完成相应过程&#xff0c;首先&#xff0c;我们要写入一个后门&#xff0c;然后我们通过访问后门来得代码返回的结果&#xff0c;那么我们需要先注册一个用户名&#xff0c;而且用户名是可执行代码&#xff0c;然后观察返回结果
一、
上传后门
注册了一个普通用户&#xff0c;然后发表发表评论出上传一个后门&#xff0c;上面加%09的原因是&#xff1a;%09是水平制表符防止后台把我们的后门当做目录去解析&#xff0c;到此&#xff0c;后门上传成功&#xff0c;接下来注册含执行代码的用户
二、
注册用户
${find,/,-iname,get_flag2}
将用户名写入后门中
然后访问后门地址&#xff0c;得到如下回显
说明flag2的位置在这个路径&#xff0c;这里解释一下为什么要注册一个这样的用户&#xff0c;前面我们在得到flag1的时候的格式是get_flag1&#xff0c;所以这里我们注册一个get_flag2的用户&#xff0c;来寻找falg2,
三、
注册用户
$/usr/bin/get_flag2
让后访问后门地址
得到如下结果&#xff1a;
到此得到flag2
0x04
总结&#xff1a;这道题应该是最近做过的最难的了&#xff0c;通过这道题学到了很多姿势。对wtf格式的文件增长了利用姿势&#xff0c;通过用户名来执行代码在之前是真没想过。总之这题不愧为国际赛题