寒假解刷题记录

记录一些在刷题过程中,发现的一些有趣的题目

显示了后端的SQL语句,我们可以使用\转义符转义username后面的引号,令username的第一个引号和password的第一个引号闭合,逃逸出password第一个引号后面的内容

如输入

数据库查询语句事实上变成了这样:

=》 strtolower("1")strtolower("3")strtolower("b")

param1=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3Bu%93%D8Igm%A0%D1U%5D%83%60%FB%07%FE%A2&param2=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB%07%FE%A2

param1[]=QNKCDZO&param2[]=240610708

预处理语句使用方式:

预定义语句也可以通过变量进行传递:

payload:

1.尝试 `‘ ’‘ ) )) ') ") ')) ")),找不到字符型注入点

2.输入不等于0的数字返回 1 ;输入过滤了的字符返回 Nonono;输入其他字符空白无显示;

3.尝试堆叠注入,1;show tables;#时返回如下:

Array ( [0] => 1) Array ( [0] => Flag )

推测其执行语句为select GET['query'] || flag from Flag

1.利用php字符串解析特性绕过WAF

发现 [7]=> string(5) "f1agg"

在该题就是要伪造session,欺骗服务器,假装自己就是admin

这里首先要随便注册一个账号,得到session

这里将name的值改为admin

登入后页面修改伪造的session得到flag

POST:welcome to the zjctf

ssi注入

看到后缀为shtml,可考虑尝试

直接执行服务器上的各种程序<#exec>

知识点:

payload 1:

-iL  从inputfilename文件中读取扫描的目标。

-oN 把扫描结果重定向到一个可读的文件logfilename中。

escapeshellarg — 把字符串转码为可以在 shell 命令里使用的参数

功能 :escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,shell 函数包含 exec(), system() 执行运算符(反引号)

escapeshellcmd — shell 元字符转义

反斜线(\)会在以下字符之前插入: &#;`|*?~<>^()[]{}$, \x0A 和 *\xFF*。 ’ 和 “ 仅在不配对儿的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。

详细分析一下这个过程:

传入的参数是

由于escapeshellarg先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。所以处理之后的效果如下:

经过escapeshellcmd针对第二步处理之后的参数中的\以及a=1'中的单引号进行处理转义之后的效果如下所示:

由于第三步处理之后的payload中的\\被解释成了\而不再是转义字符,所以单引号配对连接之后将payload分割为三个部分

所以这个payload可以简化为curl 127.0.0.1\ -v -d a=1',即向127.0.0.1\发起请求,POST 数据为a=1'。

因为过滤了php,可以用phtml绕过,里面的内容用短标签

先进过escapeshellarg 函数变为

再经过escapeshellcmd函数变为

可以发现单引号已经全部闭合

可以看成

无字母数字绕过

payload:

蚁剑链接 无权限读取readflag

将github中一下两个文件 上传有有权限的目录,在这里选择/tmp

preg_match正则最大回溯绕过+换行绕过

payload1:

payload2:

这里cat的路径要写 /bin/cat是因为通过查看源代码:putenv('PATH=/home/rceservice/jail');,可以发现jail应用于当前环境,cat不在当前配置的环境变量中,需要我们自行写完整路径

SSRF 最基础的漏洞场景

这样的链接就是有可能存在ssrf的,因为服务器有可能是向本机发起请求来获取相应的图片

倘若没有对image参数进行任何的检测,就可以构造其他的请求

做题四步走:

知识点: basename()函数的使用

With the default locale setting "C", basename() drops non-ASCII-chars at the beginning of a filename.

该函数会去掉文件名开头的非ASCII值(%80 --- %ff)

题目的关键代码其实只有上半部分

paylaod:

完全考在了知识盲区,跟着wp复现了一遍

知识点:

根据源码可以发现php会对传过去的参数用escapeshellarg函数过滤。先创建一个目录sandbox/md5(orange+ip),然后执行GIT $_GET['url'],然后会创建文件夹,并将执行GIT $_GET['url']后的结果放在该文件夹下面filename传过去的文件中。

如果GET后面跟路径的话,可以直接获取文件或目录内容

GET /etc/passwd

GET / 读取根目录

Perl语言的open函数

在Perl中可以用open或者sysopen函数来打开文件进行操作,这两个函数都需要通过一个文件句柄(即文件指针)来对文件进行读写定位等操作

1:读:open(文件句柄,"<文件名")/open(文件句柄,"文件名"),前提文件必须已经存在,否则会返回0,出错信息在$!中。2:写:open(文件句柄,">文件名"),文件如果不存在,那么创建之,如果存在,内容被清空,长度截为0,$!中有出错信息。

当GET使用file协议的时候就会调用到perl的open函数

perl脚本中GET命令执行漏洞:(前提是文档需要存在,若存在,才会触发最终的代码执行)

在perl下,如果open的第二个参数(path)可控,我们就能进行任意代码执行。综合看起来像是一个把文件名拼接入命令导致的命令执行。

payload:

其实如果对于这个open不理解的化=话还有更简单的做法,直接在自己的vps根目录下写一个木马文件

蚁剑连接即可

感觉挺复杂的一题

知识点:

​ 1.无数字字母shell

​ 2.利用.htaccess上传文件

​ 3.绕过open_basedir

题目源码

第一关

首先判断是否从GET方法获取 " _ " 参数的值

然后通过 strlen() 函数对GET方法对该值进行长度检测 , 如果字符串长度大于 18 就拦截信息

接下来通过 preg_match() 正则过滤该值中的敏感字符 , 这个正则表达式非常严谨 , 过滤了绝大部分的可写字符

最后通过 count_chars() 函数来限制该值中不同字符的个数

很明显需要我们通过eval调用get_the_flag函数,然后上传bypass文件,最后拿到shell拿到flag。

Payload : ${xxxx^xxxx}{x}();&x= ... , 转换后就变成了 $_GET[x]();&x= ...

放几个有用的脚本

payload1:

${%A0%B8%BA%AB^%ff%ff%ff%ff}{%A0}();&%A0=get_the_flag

第二关

首先对文件后缀进行正则检查 , 如果文件后缀是以 " ph " 开头 , 则不通过检测 .

然后对文件内容进行检查 , 如果文件内容中出现 " <? " 这个部分 , 则不通过检测 .

最后通过 exif_imagetype() 函数对文件类型进行检查 , 如果文件不是一张图片 , 则不通过检测 .

PHP版本是 PHP 7.2 , 所以 这种写法已无法使用 . 要想绕过 " <? " 的检测 , 必须对文件内容进行编码(比如base64)再上传 .

找到一种能够同时满足 图片文件 . PHP文件 , .htaccess文件 的文件格式 . 要满足PHP文件和配置文件的格式 ,就需要添加文件的 " 不解析行 " 了( 比如注释行 )

X-Bitmap(XBM)是一种古老但通用的图像文件格式 , 它与现在的许多Web浏览器都兼容 . X-Windows图形界面(UNIX和Linux常用的GUI)的C代码库xlib中有一个组件专门描述了它的规范 .

XBM 文件头是通过两行 #define 定义的 , 而这种定义方式刚好在 php文件 和 .htaccess文件 中代表注释

第三关:

bypass open_basedir

知识点:

由于performance_schema过于复杂,所以mysql在5.7版本中新增了sys 数据库,基础数据来自于performance_chema和information_schema两个库,本身数据库不存储数据。

sys数据库中的以下三个视图中存储了表名table_name:

盲猜列名为flag ,直接得到flag

2.无列名注入

在这里用到的是逐字符检索数据法

paylaod:

知识点:

1.反弹shell

当程序打开一个文件, 会获得程序的文件描述符, 而此时如果文件被删除, 只会删除文件的目录项, 不会清空文件的内容, 原来的进程依然可以通过描述符对文件进行读取, 也就是说, 文件还存在内存里。

考察点:phar反序列化

知识点:

1.文件包含

sprintf输出格式问题

sprintf("$url method&content_size:$method%d", $detect)我们可以知道 %d 前面还有一个可以控制的变量,也就是我们传入的q3。经过了解,我们知道在sprintf这里面 % 才是转义字符,我们可以传入POST%s%最后把%d给取消转义。达到绕过效果

payload:

通过分析代码发现有两个要求

X-Forwarded-For:127.0.0.1

$decr === $cipher

第一个要求很容易满足,我们看第二个,需要传入变量decrypt,使其强等于aesEn($data, ‘y1ng‘);的加密结果在该加密算法中存在的唯一变量是 $data ,而 $data = $_SESSION[‘secret‘];,我们看代码最后面,可以知道 $_SESSION[‘secret‘]; 是由伪随机数长度加密得到的。

但是假如我们另session 为空,那么自然而然就不存在 $_SESSION[‘secret‘]; ,这个时候aesEn加密得到的值就是固定的

传值即可

知识点

\uXXXX可以在JSON中转义字符,例如A,\u0041等效

2.伪协议读取

由于$content中不能存在 /HarekazeCTF\{.+\}/i类似内容,所有我们可以对content 进行base64 加密,这里用到了 php://filter 伪协议

payload:

不知道什么原因 页面回显极慢,没做,记录下原理

知识点:

知识点:

linux进程管理之打开的每个进程的链接

预期解的话基本上解法和 [V&N2020 公开赛]CHECKIN 一模一样,由于不知道什么原因,一直报Wrong Key!,题目没有进行下去,这里就不多加赘述

paylaod:/page?url=../../../../proc/self/fd/3,这里的/proc/self也是一个链接文件,当进程访问此链接时,就会访问这个进程本身的/proc/pid目录,从而得到 secret_key ,之后反弹shell即可,flag在根目录,可以直接 cat /flag

非预期解

?url=../../../../../../flag

知识点:

js测试的话可以用Error().stack直接查看报错信息,还能获取更多的信息

payload1:

payload2

join拼接字符串

题目没有什么难度,不过也给我提了一个醒。以前看到 Js 文件一般都是直接跳过,,以后要对Js 文件多加留意

payload:

因为回自动跳转到 /die/ ,用burp suite 抓包,总流程如下

拼接下即可得到flag

知识点:ThinkPHP6.0任意文件创建

知识点:

还有一种方法是结合limit offset进行盲注

select * from table limit 2 offset 1;

//含义是从第1条(不包括)数据开始取出2条数据,limit后面跟的是2条数据,offset后面是从第1条开始读取,即读取第2,3条

知识点:

解法一:

Welcome To Find Secret

Tell me your secret.I will encrypt it so others can't see

输个大一点的secret值时,发现报错 比如?secret=11111

这个页面是flask应用开启了调试模式后运行错误的表现

这段代码的意思是不存在变量secret时,返回Tell me your secret.I will encrypt it so others can't see

否则对secret的值进行RC4加密,密钥为HereIsTreasure,再经由过程render_template_string履行

想到SSTI模板注入

注意下,这里的ciscn起过滤作用,只不过在buuctf的flag中没有ciscn字样所以该过滤没有起应有的作用

这里我们需要对 RC4加密由一个大致的了解,RC4加密算法为对称加密算法,即明文经加密后得到密文,密文经加密后得到明文,就比如在这个页面 ?secret=1页面返回d , 而 ?secret=d页面返回1

我们可以对poc 进行 RC4加密,加密脚本网上很多

不过这里poc的生成还可以使用cyberchef工具,并不一定要写脚本

payload:

解法二:

这个页面是flask应用开启了调试模式后运行错误的表现,在较旧版本的flask中可以直接在这个页面中打开python控制台运行代码,而在较新的版本中的flask中要打开python控制台需要输入一个pin码,如下:

pin码会在服务器端运行flask应用时输出,其格式为“ xxx-xxx-xxx”,其中x为任意一个数字,表示pin有10亿种组合。作为攻击者,我们目前是不知道pin编码的,除非你有耐性进行爆破,实际上爆破也是可行的,因为在固定的机器上,pin码是固定的

至此,所有参数获取完毕,输入有效载荷计算密码:

[GYCTF2020]FlaskApp 同意可以用求PIN的方法求flag

知识点:

一. SoapClient

SOAP是webService三要素(SOAP、WSDL(WebServicesDescriptionLanguage)、UDDI(UniversalDescriptionDiscovery andIntegration))之一:WSDL 用来描述如何访问具体的接口, UDDI用来管理,分发,查询webService ,SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。其采用HTTP作为底层通讯协议,XML作为数据传送的格式。SoapClient类可以创建soap数据报文,与wsdl接口进行交互。

第一个参数的意思是:控制是否是wsdl模式,如果为NULL,就是非wsdl模式.如果是非wsdl模式,反序列化的时候就会对options中的url进行远程soap请求,第二个参数的意思是:一个数组,里面是soap请求的一些参数和属性。

简单的用法

可以利用 SoapClient 类的 __call (当调用对象中不存在的方法会自动调用此方法)方法来进行 SSRF

二. CRLF Injection漏洞

首先要对HTTPheaders 和 HTTPbody 要有一些基本的了解,如图,它们之前用空行区分

得到如下

三. call_user_func

call_user_func函数中的参数可以是一个数组,数组中第一个元素为类名,第二个元素为类方法。

先传入extract(),将$b覆盖成回调函数,这样题目中的 call_user_func($b,$a) 就可以变成 call_user_func(‘call_user_func’,array(‘SoapClient’,’welcome_to_the_lctf2018’)) ,即调用 SoapClient 类不存在的 welcome_to_the_lctf2018 方法,从而触发 __call 方法发起 soap 请求进行 SSRF 。

四. PHPsession 反序列化

我们先通过一个样例代码,看看3种不同的 session 序列化处理器处理 session 的情况。

而当session反序列化和序列化时候使用不同引擎的时候,即可触发漏洞

php引擎会以|作为作为key和value的分隔符,我们在传入内容的时候,比如传入

那么使用php_serialize引擎时可以得到序列化内容

然后用php引擎反序列化时,|被当做分隔符,于是

被当作key

被当做vaule进行反序列化

于是,我们只要传入

即可触发漏洞

知识点就讲到这里,接下去来分析一下题目

第一步:由于 PHP 中的原生 SoapClient 类存在 CRLF 漏洞,所以我们可以伪造任意 header ,构造 SoapClient 类,并用php_serialize引擎进行序列化,存入session

我们可以利用回调函数,通过给f传参,值为session_start,然后post提交 array('serialize_handler'=>'php_serialize')

执行脚本得到

第二步:通过变量覆盖,调用SoapClient类,从而触发__call 方法

传值f=extract&name=SoapClient POST:b=call_user_func. 这样 call_user_func($b,$a)就变成call_user_func(‘call_user_func’,array(‘SoapClient’,’welcome_to_the_lctf2018’)) ,即调用 SoapClient 类不存在的 welcome_to_the_lctf2018 方法,从而触发 __call 方法发起 soap 请求进行 SSRF 。

第三步:将PHPSESSID改为我们在SoapClient类里设置的123456即可得到flag

知识点:Ruby/erb模板注入

思路是JWT攻击

测试:在 点击work的时候抓包,将 cookie:auth=xxx,进行jwt解码

确认思路,但是想要伪造jwt需要密钥SECRET

重点看/work

当 params[:do] == "#{params[:name][0,7]} is working" ,secret会在 auth显示

所有我们要做的就是另params[:do] == "#{params[:name][0,7]} is working"

这里有一串代码 ERB::new("<script>alert('#{params[:name][0,7]} working successfully!')</script>").result 为ERb模板,还直接把可控参数 name 拼进去了,那么这里我们就可以传入一些构造过的参数,来达到我们的目的了。比如 name=<%=1%>,就会得 1。

erb得模板注入形式如下

但是题目只给了我们七个可控字符,除去这五个必要得字符,我们只能剩下2个字符可控

这里用到ruby全局变量

这里既然有匹配,那说明我们就可以用全局变量读出来了,也就是可以用上图的符号来读取匹配前的内容(即ENV["SECRET"])

因此我们可以构造,再进行url编码后传入。

?name=<%=$'%>&do=<%=$'%> is working&SECRET=

name=%3C%25=$'%25%3E&do=%3C%25=$'%25%3E%20is%20working&SECRET=

得到

知识点:

题目不难,不过第一次遇到这种题型记录一下。

一开始进去,发现这仿佛是一个静态的网页,没有传参没有交互。扫目录也没有任何信息泄露,入口都找不到咋做题…通过百度知道存在隐藏参数,这里用到一个隐藏参数查找的工具 Arjun

通过工具,知道有参数name

接下去就是常规模板注入了

学到了利用CTRL + F 知道可利用类位置的小方法

payload:

或者直接使用tplmap工具

知识点:

ell**

先看看源码,发现提示为如下内容

非预期 :利用逻辑漏洞,传参?pass=(响应包中的Hash值)

预期解:通过hashpump猜测 secret 长度 ,可以手工也可以脚本

查看响应头

这里可以用php7.0的bug

接下去蚁剑连接即可,不过需要利用插件绕过disable_function ,flag在env下

知识点:

Think PHP上传默认路径是/home/index/upload

Think PHP upload()多文件上传:

ThinkPHP 上传文件名爆破

这里的后缀命名方式运用了uniqid函数它是基于微秒的当前时间来更改文件名的,两个同时上传生成的文件名相差不会太远。先上传一个正常文件再上传一个木马文件,然后再上传一个正常文件,然后根据第一和第三个正常文件的文件名之间的差异,爆破出我们上传的木马文件名。

限制分析主要的限制有上传文件的后缀名限制为不能为.php与下面的这句关于只能上传图片的限制。

但是$upload->allowExts并不是Think\Upload类的正确用法,所以allowexts 后缀名限制是无效的,所有说我们只需绕过后缀不能为.php的限制

然后怎么绕过对文件名不能为.php的限制呢?这里要用到的知识点为 think\upload 类的多文件上传与 think\upload 类是怎么生成文件名的

think\upload 类的多文件上传tp多文件上传

upload() 函数不传参时为多文件上传,整个 $_FILES 数组的文件都会上传并保存。

think\upload类是怎么生成文件名的

从官方手册上可以查找到

$upload -> saveName = array ('uniqid' , ' ');

默认的命名规则设置是采用uniqid函数生成一个唯一的字符串序列。

uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID。故同时上传的两个文件的文件名一定不会差的很远,可爆破。所以这个时候我们上传第一个txt文件,再上传第三个txt文件,那么我们就可以知道我们上传第二个php木马文件在这个时间区域内的所在区间,就可以爆破出我们的木马文件

得到文件名之后, 访问连接即可得到flag ,本来还以为要命令执行的

看了大师傅的WP发现还有个非预期解 ,用 shell.<>php 来 绕过对php后缀的限制

知识点

获取源码

在主页的源码下方有一个开发人员留的信息,可知网站的源码已经被上传的github上面了。

而网站源码的名称就是网页页脚的wowouploadimage, github搜索这个名称,即可找到源码。

SQL注入 => 反序列化 => 读取Flag

在图片上传处,check函数并未对文件名(title)进行检测, 直接传递到最后的SQL语句当中。导致了SQL注入,并且属于Insert注入。

我们需要通过SQL注入修改保存的信息中的序列化的值来利用。

构造payload

反序列化payload生成:

payload:

这里的属性值ifview和config都是protected类型的,所以需要将payload修改为:

(以至于为什么要将修改为\0\0\0,是因为源码中在存取过程中对protected类型的属性进行了处理。)

正常上传图片的sql语句为:

由于title处是我们能够控制的,所以构造文件名如下:

因为上传的文件名中不能有双引号,所以将payload进行16进制编码。

和以前做的入门题 秋名山车神 神似,直接放脚本

知识点:

原型链的污染主要和两个函数有关

merge()clone()

常用源码如下,可以看出clone与merge并无本质区别:

本质上这两个函数会有风险,就是因为存在能够控制数组(对象)的“键名”的操作。但是要想实现原型链污染,光只要键名可控是不够的。以下面这个例子为参考:

尝试把第二个键名设为__proto__并赋值b为2。看看能不能把object的属性b改为2。

污染失败

可以看见最后

返回的是

,并没有污染成功。

主要原因就是因为

没有被认为是一个键名。而这就需要我上面提到的另一个条件,代码如下时:

污染成功

javascript的大小写绕过

"ı".toUpperCase() == 'I'"ſ".toUpperCase() == 'S'"K".toLowerCase() == 'k'

知识点就讲到这里,接下去分析下题目

先分析下几个主要的路由

payload:

到/info路径,下载得到flag文件

知识点:

思路是通过投稿恶意XSS,然后点击审核,管理员就会来到我们的页面,审核我们的投稿这样的话我们可以构造恶意代码,让管理员进去,从而窃取管理员的cookie,进入后台为所欲为

平台会自动帮我们生成xss代码,自己可以研究一下那一摞代码都是干嘛的,很有意思哟OK,我们回到投稿页面,来一个最简单的脚本实验一下

提示我们上传成功,查看下上传文件源代码

CSP全称Content Security Policy ,可以直接翻译为内容安全策略,说白了,就是为了页面内容安全而制定的一系列防护策略. 通过CSP所约束的的规责指定可信的内容来源(这里的内容可以指脚本、图片、iframe、fton、style等等可能的远程的资源)。通过CSP协定,让WEB处于一个安全的运行环境中。

通过csp我们可以制定一系列的策略,从而只允许我们页面向我们允许的域名发起跨域请求,而不符合我们策略的恶意攻击则被挡在门外

它开启了'unsafe-eval',所以我们可以用eval来执行我们的代码

所以,我们的payload为

得到

至于为什么要加,原因如下

我们替换的&#作为字符引用需要用外部元素进行解析,而恰好就为外部元素

接下去将题目,在我们将payload投稿之后,到审查页面,验证码需要md5爆破,老套路了

-1 union select 1,flagg,3 from flag#

知识点:

username和password是用json格式发送的,并且会返回一段信息。先测试有没有注入点:我们尝试在username 后使用 ",发现报错了

使用#闭合,发现返回200

经过简单的手动fuzz之后发现没有办法进行联合查询(因为没有回显)和有Boolean回显的盲注,我猜可能是服务器全给WAF掉了,一般这种情况下可以考虑以下堆叠注入,所以我修改username为123';,结果发现回显正常:

这样一来,可以推测拼接到服务器端的SQL语句就是:

因为;号表示一个SQL语句的结束,;号后面的一个'号被认为是下一个SQL语句的开始,所以没有产生报错,也就是说,这个题目是存在堆叠注入的(;号被解析了)

大佬写的脚本

得到

下载得到源码,本来以为注入出来就是flag

审计,代码很简单

总的流程为,通过UserController类 中 的 actionIndex 方法,把$_REQUEST这个数组赋值给了$listData,然后传入了loadView 方法

还有注意下 r 变量的值为 user/Index ,原因如下代码,会将r参数的值 按 / 进行分割,拼接,我们利用变量覆盖函数对应的控制器为userController ,所以传参 ?r=user/Index

payload:

知识点:FILEINFO + getimagesize

首先判断文件大小,并使用 FILEINFO 判断上传图片类型,上传图片只能是 png 类型后面再用 getimagesize 判断文件像素大小,并且再进行一次类型判断,如果不是 png 类型就给出 flag

在这两种判断上传图片类型的函数中,有一个很有趣的现象, FILEINFO 可以识别 png 图片( 十六进制下 )的第一行,而 getimagesize 不可以

所以我们上传的文件内容如下

上传即可得到flag

知识点:利用汉字构造 shell

审计代码,发现从传入文件内容的第6个字母开始黑名单匹配,fuzz被过滤字符

只有这个几个是能用的了

通过

得到文件目录,post传参 system=env

(env是环境变量,相当于phpinfo)

知识点:无字母数字shell构造

PHP在处理字符串时有个有趣的特性。

PHP默认会把没有加引号的字符串当成常量处理,找不到对应常量就会将其解释成字符串

虽然抛出警告,但是还是打印出了abc,并且这个警告我们可以用"@",去掉。

还有一点,PHP调用函数,可以使用字符串调用。

通过脚本,匹配出 print_r(scandir('.'));

但是题目还有一个条件,就是出现的不同字符数不能超过13,除了必要的(,),^ , ; ,%ff我们最多再有8个字符

整理得

文件在scandir的结果最后面,那么用end()方法就可以得到文件名了。读文件可以用show_source或者readfile

知识点:XXE+SVG

/proc/self/cwd 显示当前位置

知识点:

我们要伪造admin ,首先需要知道session的处理器

session处理器形式我们可以通过读取session文件来得知,那么我们首先就需要先知道文件名,我们知道session文件命名格式为(sess_[PHPSESSID的值]),phpsessid可以通过查看cookie知道,所有我们下载文件即可

POST: direction=download&attr=&filename=sess_+phpsessid

得到返回内容

username:5:"guest"; (username前面有一个不可见字符)

可知session处理器为php_binary

本地伪造文件

将得到的这个文件重命名为sess ,并进行sha256编码

而下来要做的就是将这个sess文件上传了,上传点本地构造

我们可以下载一下这个文件,文件内容确实为我们伪造的damin

POST: direction=download&attr=&filename=sess_432b8b09e30c4a75986b719d1312b63a69f1b833ab602c9ad5f0299d1d76a5a4

这里注意要把cookie也改成432b8b09e30c4a75986b719d1312b63a69f1b833ab602c9ad5f0299d1d76a5a4

分析代码我们知道

$dir_path = "/var/babyctf/".$attr;

获得flag

知识点:XXE攻击

当Web应用采用JSON进行数据传输时,可能存在XXE漏洞。

在该题,我们可以通过使用本地DTD文件来利用XXE漏洞实现任意结果输出

Blind XXE 需要使用到DTD约束自定义实体中的参数实体。参数实体是只能在DTD中定义和使用的实体,以 % 为标志定义,定义和使用方法如下

而且参数实体还能嵌套定义,但需要注意的是,内层的定义的参数实体 % 需要进行HTML转义,否则会出现解析错误

该题我们引用的是linux system 本地的DT文件,路径如下

payload

知识点:XXE攻击

有waf ,通过修改编码方式绕过,将utf-8改为utf-16be

放在user或者group标签下最多显示15位字符

然后我们看一下User页面,发现其实还存在一个Intro标签,修改payload如下

将得到的文件上传即可得到flag

当然该题如果不知道 <inctro>时还可以利用报错的方式得到flag

做法类似[GoogleCTF2019 Quals]Bnv

payload:

知识点:

记录下流程,不知道为什么用的buu内网VPS nc 反弹不上

1.随便上传文件,然后点下载,抓包。看到有filename,猜测可能存在目录穿越以及任意文件下载

2.尝试通过报错来获取网站的绝对路径,设置URL参数 filename=../

4.把三个class文件下载下来,tomcat的class文件一般存储在/WEB-INF/classes/下面

jd-gui反编译

做法如下

修改里面的[Content_Types].xml文件,在第二行添加如下代码

保存后,重新将后缀改为xlsx

开启监听

nc -lvp 9999

上传 xlsx 文件,按理说应该被监听到的(f),不知道为什么,失败了..

知识点:

代码分析就不写了,该题改编自 EIS 2019 的 ezpop

主要记录以下用到的几个知识点和新思路,和原题唯一不同之处就是对文件名做了限制,如下

知识点一:通过 /../ 绕过文件名随机前缀,通过 /. 进行绕过文件名检验

知识点二:死亡exit 绕过

$data = "\n" . $data;

我们可使用 php://filter协议来施展魔法:使用php://filter流的base64-decode方法,将$data解码,利用php base64_decode函数特性去除“死亡exit”。

,base64编码中只包含64个可打印字符,而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。一个正常的base64_decode实际上可以理解为如下两个步骤:

“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“a”一共8个字符。这样,"phpexita"被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>没有了。

payload:

还有一种解法是直接在$data就是文件内容里直接写要仔细的命令,通过

在该方法中直接将serialize 赋值为system ,进行命令执行

本地测试如下:

发现思路是正确的

payload:

看了大佬的wp发现还有一种做法是

知识点:

代码量较少,主要走了如下的限制

我们把写入文件的功能点放在.htaccess上来

我们大概可以有这么个思路:

error_log可以将php运行报错的记录写到指定文件中。

首先先考虑如何绕过\n换行追加数据导致.htaccess解析错误的限制

我们可以利用#注释符将整句话都注视掉,但是又由于有\n换行符的存在,我们不能直接使用#就将其注释掉,需要把\n进行“吃”掉。那么最常见的操作就是利用\斜杠将其转义了,这样\\n就是一个简单的\n字符串了。

初步构造.htaccess文件内容如下

不过令人失望的是 error_log的内容默认是htmlentities的,我们无法插入类似<?php phpinfo();?>的payload,因为< >等会被转义,我们需要绕过,这里利用UTF-7绕过

先尝试利用 UTF-7 编码我们需要插入的恶意代码,写入.htaccess的文件内容如下:

payload1:

第二步 再把以下内容写入.htaccess:,从而显示报错信息

payload2:

即可看到报错信息

还有一种解法是

用\来转义换行符来绕过最后加一行的限制。 所以同理也可以用\来绕过stristr处的所有限制。型如

payload

解法三:

这里我们看到题目的代码正则部分是

这里是判断是否为 1 ,如果为 1 则 die ,而根据正则回溯,当超过回溯次数,preg_match会返回false,自然就可以绕过了。

payload

没有preg_match的waf后就可以通过php://filter伪协议写入一句话

知识点:这一题的话就是找注入点要细心,抓包,F12看Network等等,js文件要注意

找到注入点后sqlmap 一把梭

知识点:XPATH注入

Xpath注入漏洞验证:

加一个 ' ;有下列报错,则可以确定Xpath注入的存在性

xpath盲注适用于攻击者不清楚XML文档的架构,没有错误信息返回,一次只能通过布尔化查询来获取部分信息,同样以0x05中的源码为例

Xpath盲注步骤:

从根节点开始判断:

判断根节点下的节点长度为8:

猜解根节点下的节点名称:

猜解出该节点名称为accounts

猜解accounts下的节点名称:

accounts下子节点名称为user

第一个user节点的子节点长度为8:'or string-length(name(/accounts/user[position()=1]/*[1]))=8 or ''='

读取user节点的下子节点

最终所有子节点值验证如下:

继续猜解:

均为 false,不再有子节点,则可以尝试读取这些节点的值

第一个user下的username值长度为6:

读取第一个user下usernaem的值

可依次读取所有的子节点的值,第二user节点的子节点值读取方式:

重复上边步骤即可

payload

知识点:反序列化链构造

既然直接给了一个unserialize,其他的什么都没有,所以首先考虑魔法函数__destruct

那么我们在全局搜索一下__destruct,找到的可利用类是TagAwareAdapter类

这个类里面有一个__destruct方法,调用了commit方法

之后commit方法又调用了invalidateTags这个方法

我们跟进invalidateTags这个方法看看

要注意的是,我们可以控制整个TagAwareAdapter类中的成员变量,所以我们可以控制所有的$this->xxx这样子的变量。

在这一段代码中

我们可以发现,我们可以调用任意一个实现了saveDeferred方法的类,所以我们可以找一个可利用类为:PhpArrayAdapter类

我们看一下这个类中的saveDeffer方法

进入到initialize这个方法,发现在本类中并没有定义,而是在一个trait这个关键词修饰的类中trait PhpArrayTrait

看一下trait这个关键词的用法

trait

这个关键词是php为了解决单继承的问题而特意建立的,在java这种面向对象的语言中,继承都是单继承的,一个类只能继承一个父类,这样确实体现了面向对象的思想,但是单继承在有的时候不是很方便

我们通过phpstorm的继承图生成可以清楚的看到PhpArrayAdapter这个类的继承关系

那么在本类中没有定义initialize这个方法的话,自然就会去父类中寻找,我们来看看父类的initialize方法:

我们可以在PhpArrayAdapter中定义好$this->file这个变量,那么在调用initialize方法的时候,只要这个file是一个存在的文件,就会调用include来包含进去,最后就可以读取到flag了

payload:

知识点:匿名创建函数

首先创建了一个$MY的匿名函数。会输出flag然后创建$hash会在eval函数中。与SUCTF拼接。形成一个新的函数名要想拿到flag就只有调用SUCTF_XXXX随机数的函数名。或者直接调用$MY

create_function()函数漏洞,create之后会自动生成一个函数名为%00lambda_%d

%d 这个值是一直递增的,这里的 %d 会一直递增到最大长度直到结束,这里我们可以通过大量的请求来迫使 Pre-fork 模式启动的Apache启动新的线程,这样这里的%d会刷新为1,就可以预测了。

paylaod

知识点 :

fuzz测试后发现过滤了union,select ,&,|,过滤了select然后存在堆叠注入的可以使用预处理注入,尝试写入shell,方法一hex编码

方法二 char()编码

还可以文件读取,不过读不到flag

知识点:

读取到这个文件了

继续读取m4aaannngggeee

关键之处在于

知识点:

在buu上复现的,方法对了,但是不知道为什么不出flag,导致死磕了很久,一直以为是自己方法错了

进入环境,点进去之后,发现跳转到baidu,很明显SSRF

fuzz后发现 file://等被过滤了,直接上 /proc/self/cmdline

只有满足存在session,且session['username'] == 'fuck'即可得到flag,想要伪造session,需要SECRET_KEY

对全部的源码进行分析了,直接查找所需的SECRET_KEY的值发现:

其对SECRET_KEY做了random随机处理,但random生成的随机数都是伪随机数,有一定的规律。发现了其中:

若获取了服务器的MAC地址值,那么就可以构造出为伪随机的种子值,想到Linux中一切皆文件,查找到MAC地址存放在/sys/class/net/eth0/address文件中,读取该文件:得到其十六进制所表示的MAC地址

然后脚本把它转换为10进制数,然后转换成SECRET_KEY

然后利用flask-session-cookie-manager进行伪造即可,然后将得到的伪session代替原session,访问/flag,即可得到flag ,迷惑的地方就是这里,我拿伪造的session进到/flag页面,一直给我回显Access denied

要哭了,看着wp搞了一天,结果最后还是没出flag,这里记录下过程

?phpinfo

满足success===true,就回显flag

在CGI(RFC 3875)的模式的时候, 会把请求中的Header, 加上HTTP_ 前缀, 注册为环境变量, 所以如果你在Header中发送一个Proxy:xxxxxx, 那么PHP就会把他注册为HTTP_PROXY环境变量, 于是getenv("HTTP_PROXY")就变成可被控制的了. 那么如果你的所有类似的请求, 都会被代理到攻击者想要的地址,之后攻击者就可以伪造,监听,篡改你的请求了

利用条件:

受影响范围

Guzzle>=4.0.0rc2,<6.2.1版本受此影响

刚开始一直在用buu内网vps进行复现,搞了好几个小时,一直连不上nc,后来在群里问了才知道,buu内网已经做隔离了,要直接访问外网资源,意思就是说直接拿自己的服务器搭呗

然后nc监听

问题就在这里,不管我怎么连,就是连不上

最后在burp改包

加一行

然后就会返回flag

知识点:session伪造

知道可以写note,然后可以下载,还知道要admin才可以getflag,session伪造,不过仅限于此猜测是,没什么思路,看了WP才知道,还有源码的存在,下载下来,源码比较简单,主要的代码如下

思路很明显了,伪造session.不过在伪造session之前需要知道session处理器,默认为php

做法:

然后修改session,到getflag页面即可得到flag,(不过这里我修改完session,点getflag后并没有flag,需要先到别的页面,再到getflag)

知识点:软链接读文件

随便输入访问到404页面,放到burp查看相应包

base64解密为 SECRET_KEY:keyqqqwwweee!@#$%^&*

脚本直接伪造admin

成功到上传界面,源码有注释

ln -s是Linux的一种软连接,类似与windows的快捷方式ln -s /etc/passwd forever404 这会出现一个forever404文本,里面包含密码/proc/self 记录了系统运行的信息状态等,cwd 指向当前进程运行目录的一个符号链接,即flask运行进程目录

或者先找到当前目录路径

将得到的压缩包上传,抓包查看response,即可得到flag

也可以命令注入:

知识点:

首先随便输了个php代码,根据报错发现是C语言编译器

编译后下载了一个文件.猜测flag应该是以文件形式存在服务器中,尝试使用#include ''预处理命令

知识点:WAF绕过

和国赛那题一样,就是范围变了下

总共三种方法,不过只有异或的方法适合这题

方法一:利用数学函数运算得到函数和命令

分析:

方法二:拼凑出getallheaders利用HeaderRCE

getallheaders — 获取全部 HTTP 请求头信息

分析

方法三:异或

在运行结果中找到_GET即可,构造payload

is_nan^64==>_G

tan^15==>ET

知识点:万能密码

SQL查询,过滤了:union、sleep、'、"、or、-、benchmark

order by测试字段数,发现当order by 2时返回正常order by 3返回没有这个字段,确定为两个字段,一个为uniqueid另一个应该就是flag

知识点:

也可以在命令行

知识点:

perl中ARGV是遍历数组变量@ARVG中的所有文件名的特殊文件句柄,@ARVG传给脚本的命令行参数列表

Perl 会将 perl 命令行参数列表放入到数组@ARGV中,而默认情况下,这些命令行参数是Perl的数据输入源,也就是Perl会以依次将他们当作文件进行读取

进入场景后有3个链接,点进去都是.pl文件,.pl文件都是用perl编写的网页文件

利用点在第三个链接,尝试后发现,Files链接可以上传文件并把文件内容打印出来。对此,大佬猜测后台代码如下

param()函数会返回一个列表的文件但是只有第一个文件会被放入到下面的接收变量中。如果我们传入一个ARGV的文件,那么Perl会将传入的参数作为文件名读出来。对正常的上传文件进行修改,可以达到读取任意文件的目的。

如果在原来的数据包中新增一个文件上传项,并且删除其filename参数, 后端会将第一个上传项的内容作为$file参数的值,因此我们可以控制$file变量的值

如果$file变量的值是ARGV文件句柄,而ARGV文件句柄会将@ARGV数组的每一项作为文件名并读取它们的内容,也就是说在URL后添加的路径会被放入到@ARGV数组中,配合之前引入的ARGV文件句柄,我们就可以读取任意文件

知识点:脚本编写

做这题之前先去学了下21点的玩法23333

访问/api可以得到一个 SecretState 这个是当前余额的一个哈希码

访问/api/deal可以进行赌博,但是只要我们的 state 不会变,我们的余额就不会变,当我们的应答包含 BlackJack 的时候,我们的余额会增加,然后我们就可以获取它的 SerectState 进行下一次赌博,这样就可以一直赢了

flag在state最后

知识点:

打开题目,是个 URL 转 PDF 的在线转换器,输入一个 URL,就会转成 PDF。但是不能直接用 file:// 协议去读本地文件,会报错。使用bp的Burp Collaborator模块看下请求

发现使用了 WeasyPrint

在 Hacker One – Ben Sadeghipour 的这个关于 SSRF 的 DEF CON 议题上,有一部分专门介绍了 Weasy Print。

Attachments are related files, embedded in the PDF itself. They can be specified through elements to add resources globally or through regular links with to attach a resource that can be saved by clicking on said link. The title attribute can be used as description of the attachment.

意思就是说我们可以使用锚和链接标签将文件作为附件嵌入到生成的PDF中,并且可以轻松地从PDF中提取附件

知识点:

代码分析

/接受action参数。如果没有就默认为indexfile=dirname+/template/+action+.png然后用pug引擎进行渲染。可以理解为执行这个文件

/file_upload上传文件时先判断是否是 127.0.0.1 也就是本地请求那么得找一个SSRF的点然后就是获取上传的文件,根据其传过去的 MIME 类型保存到指定目录filepath=/uploads/+mimetype+/而mimetype可控。那么我们可以跨目录,构造任意路径文件写入

/core接受一个q参数。然后对其进行黑名单检测然后对q输入的值进行请求,明显就是SSRF点了

不过我们还需要绕过黑名单,可以通过url编码进行绕过,也可以通过nodejs8特性进行绕过

payload:

知识点:VM2

用的是[HFCTF2020]JustEscape的payload

看了wp,官方解法是利用buffer的未清零特征

只要是调用过的变量,一定会存在内存中,所以需要使用Buffer()来读取内存,使用data=Buffer(500)分配一个800的单位为8位字节的buffer,编写Python3的EXP:

payload:

知识点:PhantomJS

通过查看请求头,在user-agent发现使用PhantomJS

Phantom JS是一个服务器端的 JavaScript API 的 WebKit。其支持各种Web标准: DOM 处理, CSS 选择器, JSON, Canvas, 和 SVG

搜索PhantomJS发现存在任意文件上传漏洞CVE-2019-17221,该漏洞通过file://URL的XMLHttpRequest触发

payload:

做法同URL TO PDF

知识点:

随便注册一波 账号npfs,密码123,到admin panel 发现要admin登入,抓包看下session,尝试篡改cookie来提权,但是加密方式未知,密钥未知。我们先注入点,fuzz发现在event_important参数存在模版注入,输入__class__,发现成功回显.

接着查找配置文件:__class__.__init__.__globals__[app].config ,得到key

fb+wwn!n1yo+9c(9s6!_3o#nqm&&_ej$tez)$_ik36n8d7o6mr#y

我们把两个session都解密看一下

这里user的值才是用来判断admin的,所有我们要伪造的是名为user的session,但是我们解密发现,字符串只有一个npfs,也就是我注册的用户名,我们无法直接伪造,这里用到了脚本

得到的user代替原来的即可伪造成功获得flag

知识点:

启动环境,是一个蜂蜜购买解密,有1366美金,购买flag需要1337美金,美金不足,猜测为session伪造,抓包,将session利用flask-session-master工具解密,

获得解密后的值:

确实包含金额,所有接下去要做的就是得到key

观察页面,发现大图片下方有一行小字

click to download our sweet images

之前省赛做到过类似的,web中对于这种可下载地方一般存在任意文件下载,下载抓包

修改其image的值为:

发送数据包,得到/etc/passwd文件内容,确定存在任意文件下载漏洞

当路径为../../proc/self/environ时,得到key

将得到的session进行替换,购买即可得到flag

知识点:

传入的 syc 和 lover 要求值不等但 md5 加密后相等

题目过滤了

之后会进行命令执行

md5()和sha1()可以对一个类进行hash,并且会触发这个类的 __toString 方法;且当eval()函数传入一个类对象时,也会触发这个类里的 __toString 方法。所以我们可以使用含有 __toString 方法的PHP内置类来绕过,用的两个比较多的内置类就是 Exception 和 Error ,他们之中有一个 __toString 方法,当类被当做字符串处理时,就会调用这个函数

这里以Error 类为例,我们来看看当触发他的 __toString 方法时会发生什么:

输出如下:

发现会以字符串的形式输出当前报错,包含当前的错误信息(payload)以及当前报错的行号(2),而传入 Error("payload",1) 中的错误代码“1”则没有输出出来。

在来看看下一个例子:

输出如下:

可见,$a 和 $b 这两个对象本身是不同的,但是 __toString 方法返回的结果是相同的。注意,这里之所以需要在同一行是因为 __toString 返回的数据包含当前行号。

Exception 类与 Error 的使用和结果完全一样,只不过 Exception 类适用于PHP 5和7,而 Error 只适用于 PHP 7

我们可以将题目代码中的 $syc 和 $lover 分别声明为类似上面的内置类的对象,让这两个对象本身不同(传入的错误代码不同即可),但是 __toString 方法输出的结果相同即可。

由于题目用preg_match过滤了小括号无法调用函数,所以我们尝试直接 include "/flag" 将flag包含进来即可;由于过滤了引号,我们直接用url取反绕过即可。

payload:

知识点:

没啥好说的,可以利用数组绕过

payload:POST传参

roam1[]=1&roam2[]=2

知识点:SQL注入(PHP_SESSION_UPLOAD_PROGRESS)

对于这里的addslashes转义,可以通过GBK编码绕过,接下去看login和register

比如说,我们可以通过如下脚本生成session文件sess_test1

THE END
0.关注|郑钦文因伤病退出宁波公开赛将全力备战年终总决赛关注|郑钦文因伤病退出宁波公开赛 将全力备战年终总决赛,澳网,郑钦文,奥运会,宁波市,国际女子职业网联,中国羽毛球公开赛jvzquC41yy}/3?80eqs0f‚4ctvodnn4LGMPO7L8273:S;TV0jvsm
1.艺术学院学子在第七届兰州国际钢琴公开赛决赛中喜获佳绩​日前,在兰州甘肃大剧院举办的2021第七届兰州国际钢琴公开赛决赛中,我校艺术学院艺术硕士19级研究生付翔飞,荣获非公开组斯克里亚宾作品演奏组第1名、青年A组第6名(前5名全部空缺),公开组青年组第14名的优异成绩。据悉,“兰州国际钢琴公开赛”由甘肃省青少年艺术教jvzquC41yy}/izuv0kew7hp1ktgq86434534B560jzn
2.第二届北京CBD高尔夫公开赛圆满完赛王洪杰逆袭夺冠北京时间9月29日,在最美的金秋季节,2019第二届北京CBD高尔夫公开赛于北京CBD国际高尔夫球会成功举办,这场以职业赛事赛制为规格运作的比赛,经过一番艰难激烈的比拼,悬念直到最后一刻才被揭晓。最终王洪杰成功逆袭,以两轮163杆(81-82)的成绩赢得本届公开赛总杆冠军;钱超以总杆167杆(81-86)获得亚军;邓晖以总杆167jvzquC41urusv|3ukpg/exr0ep5hquk1ejooc{jrqtz0496;/36.2:4fqe3jklj||tw:7=<6;;4tj}rn
3.斯诺克苏格兰公开赛产生八强周跃龙成中国“独苗”体育中新社北京12月15日电 北京时间15日晨,2023年斯诺克苏格兰公开赛产生八强,周跃龙成为中国“独苗”,约翰·希金斯则成为八强中唯一一位TOP16球员(世界排名前16位)。 本次苏格兰公开赛正赛第四日依然一日双赛,中国军团4人出战,其中周跃龙和张安达均是两次登场。 jvzquC41urusv|3eev|/exr142841:71375BT]Ne[nq28`PRPmJvG@t;|X€35:7370yivvq