[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华

文章目录

  • 概述
  • [安洵杯 2019]easy_web
  • [WUSTCTF2020]朴实无华


概述

本文主要记录[安洵杯 2019]easy_web和[WUSTCTF2020]朴实无华的做题过程和相关思路

[安洵杯 2019]easy_web

打开题目,发现在url上有两个参数,分别是imgcmd,发现毫无思路,直接看源码进行审计
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第1张图片
对于img的值其构成为大小写字母数字,符合Base64编码的特征,尝试对其进行Base64解码
注:由于TXpVek5UTTFNbVUzTURabE5qYz0的长度为27不满足4的倍数,需要在其后面添加=,使长度为28,再进行解码
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第2张图片
解码后的结果同样满足Base64编码规则,再次进行解码
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第3张图片
得到的结果为一串16进制,将其转换为字符串为555.png
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第4张图片
尝试将555.png拼接到url进行访问,发现就是题目一开始所展示的那张图
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第5张图片
在题目首页中查看该图片的加载方式,发现是通过Base64方式进行加载的
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第6张图片
通过上面的分析,可以知道只要将需要读取的本地文件的文件名经过一次字符串转16进制,两次Base64编码,再传输到img参数中,即可在题目首页看到对应文件的Base64编码
那么首先尝试读取index.php
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第7张图片
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第8张图片

将上面的的Base64编码进行解码后可以得到index.php的源代码


error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "";
    echo "
"
; } echo $cmd; echo "
"
; if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) { echo("forbid ~"); echo "
"
; } else { if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) { echo `$cmd`; } else { echo ("md5 is funny ~"); } } ?> <html> <style> body{ background:url(./bj.png) no-repeat center center; background-size:cover; background-attachment:fixed; background-color:#CCCCCC; } </style> <body> </body> </html>

那么现在看来img参数的作用应该就是帮助我们获取index.php源代码的,接下来的关键是cmd参数,通过查看源代码,发现对cmd参数的值进行了过滤,比如cattac等,并且下面还有更为重要的一段判断代码

if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
    echo `$cmd`;
} else {
    echo ("md5 is funny ~");
}

这里由于使用了string进行了强制转换,发现数组经string强制转换后的值都为"Array",不能满足!==,所以无法使用数组进行绕过
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第9张图片
那么这里就要考虑使用md5强碰撞

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

注意,在使用hackbar发送post数据时会自动将数据进行一次url编码,所以我这里使用bp,由于没有过滤dir命令,那我就使用dir命令查看flag的位置
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第10张图片
使用cat的命令直接读取flag的内容
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第11张图片
注意,在查看其他师傅WP时发现有师傅有疑惑,说\为什么没有被检测到或者ca\t为什么可以绕过,我在本地测试了一下,有一些收获:
1.首先我们可以看到在preg_match函数的匹配模式$pattern中确实含有|\\|\\\\|,一眼看上去像是检测了\\\,其实不是,在php对于转义字符的说明中有一段话
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第12张图片
由于preg_match函数的匹配模式为字符串,那么首先它应该被当作是字符串进行处理
在 /x|\\|\\\\|z/ 中三个高亮的反斜杠都是起到转义的作用,使得后面的反斜杠能够作为匹配模式中的内容
2.经过字符串的处理之后,实际上的匹配模式/x|\|\\|z/ ,而匹配模式中又是允许转义字符存在的,那么其中的\将再次发挥转义作用,即 /x|\|\\|z/ 中高亮的转义字符再次进行转义,最后实际的匹配模式为/x||\|z/,即匹配x|\z
以下是一个小案例:
不匹配\

[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第13张图片

匹配|\

[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第14张图片

[WUSTCTF2020]朴实无华

打开题目,只有一句话,看页面源代码也没有收获,直接用dirsearch,发现有robots.txt404.html

在这里插入图片描述

访问robots.txt发现提示有fAke_f1agggg.php

在这里插入图片描述
访问fAke_f1agggg.php说不是flag,而且页面源代码中也没有线索
在这里插入图片描述
查看fAke_f1agggg.php请求头响应头,发现在响应头中提示有fl4g.php
[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第15张图片

访问fl4g.php,发现是一道代码审计题目,需要过三个关卡

 
header('Content-type:text/html;charset=utf-8'); 
error_reporting(0); 
highlight_file(__file__); 


//level 1 
if (isset($_GET['num'])){ 
    $num = $_GET['num']; 
    if(intval($num) < 2020 && intval($num + 1) > 2021){ 
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.
"
; }else{ die("金钱解决不了穷人的本质问题"); } }else{ die("去非洲吧"); } //level 2 if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5($md5)) echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.
"
; else die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲"); }else{ die("去非洲吧"); } //get flag if (isset($_GET['get_flag'])){ $get_flag = $_GET['get_flag']; if(!strstr($get_flag," ")){ $get_flag = str_ireplace("cat", "wctf2020", $get_flag); echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.
"
; system($get_flag); }else{ die("快到非洲了"); } }else{ die("去非洲吧"); } ?>

第一关,其中涉及到intval函数,可以使用科学计数法表示进行绕过

  • intval('2e4')==>当遇到第一个非数字时停止,结果为2
  • intval('2e4'+1)==>2e4首先转换成20000再加1,结果为20001

[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第16张图片

第二关,是==弱类型比较

  • 0e215962017被看作是科学计数法0的21…次方,即为0
  • 0e291242476940776845150308577824被看作是科学计数法0的29…次方,也为0,故相等

[安洵杯 2019]easy_web&[WUSTCTF2020]朴实无华_第17张图片
第三关,!strstr($get_flag," ")会检测是否含有空格,有的话就会退出,str_ireplace("cat", "wctf2020", $get_flag)会将$get_flag中的ctf替换为wctf2020,那么这里就不能直接用cat命令,可以先用ls看看当前目前都有哪些文件,发现一个文件名很长的文件
在这里插入图片描述

使用tac来绕过cat检测和使用$IFS$9来绕过空格检测

在这里插入图片描述

你可能感兴趣的:(php)