2月月赛web_q

说在前面

因为赛制改革,这个月的月赛又是我在的队出的,除了我出的题目之外,做了另外一道web题,感觉又涨见识了。
虽然不算完完全全靠自己做出来的,但也还算是拿到了flag了吧。窃喜.jpg

WriteUp

打开这个题目…
网站已经有了一个titlehelloarticle,内容为content,可以通过http://xxx/article?title=hello这样的url来查询;

另外,返回包的内容显示,这个web服务是用python写的…(⊙o⊙)这是我头一次做到python起的题目哎…不知道后台是怎么写的。

再没有其他信息了,第一反应是sql注入,所以尝试了单引号、双引号,以及还瞎尝试了各种其他的特殊字符,都没用,什么都不返回。

感觉题目应该有两种可能:

  1. title参数这里存在注入;
  2. 有一个让我添加新的article的地方。

title这里已经尝试了,感觉没啥注入的可能性,那就找找有没有添加新的article的地方,比如publish post这样的链接…简单手动试了一下发现没有,就用burp跑字典。当时跑字典的时候其实是跑出来/add这个目录的,可惜…我没注意,提示是方法不允许,我第一反应就是http的请求方法不允许add。。。到底是怎样的脑回路让我做到…这样想的,http的请求方法里根本没有add好嘛??

然后到这里我就卡死了…即没有注入,又没有添加的地方,那还怎么搞???

然后我就邪恶地ssh连接了服务器,看了这个题目的源码…这就是场外力量??

(所以接下来到底应该以什么样的角度来说writeup呢??)

看了源码之后觉得这个题目缺少提示,尤其是在访问/add的时候,是需要验证session.get("is_admin")是否存在的,这不提示的话,做题人怎么知道是验证的is_admin呢???

要想访问/add需要满足两个条件:请求方法是post,不能是其他;要有is_admin这个session值。第一个条件容易满足,然后就去查python要怎么改session值。

这个web服务是用了python flask,主要参考了这篇
https://www.jianshu.com/p/faad255f587a
按照这个帖子最后的那段代码,伪造session…就可以绕过第二个条件的检测啦。这里还要提到那个secret_key…这个key值是保存在secret_key.py文件中的,这个文件名应该是要猜出来的…(目前还不知道正确做法要怎么拿到这个文件,如果不是猜出来的话,之后会更新一下)通过http://xxx/article?title=../secret_key.py来读取到。


2019.02.25更新

  1. 拿到secret_key是通过直接读取secret_key.py文件来获取的;
  2. 这个题目预期就是要让大家拿到源码,拿到最关键的s3rver.py是通过读取/proc/self/cmdline,在里面会看到启动方式,python /var/www/web_xxxx/s3rver.py,然后再利用路径穿越,任意文件读取拿到源码…可不是通过看服务器后台哦…/坏笑.gif

emm…刚开始就应该想到任意文件读的…我是到做到后面时候才突然反应过来这么个点可以利用的…
所以整个做题过程就是:任意文件读拿到源码,在源码里看到secret_key.py flag.py,再去读secret_key.py拿到key值,伪造session,进入到/add页面,再利用SSTI,进行任意代码执行,拿到flag


说到这里,我要歪一下楼,这个题目不是用数据库来存储信息的,article内容是存储在文件夹下的,通过读取文件来将查询结果显示到文件中。我感觉如果我没有看源码的话,我可能想不到是要读文件,也不会猜到要通过title去读文件,拿到key的值。title这个参数在后台只检测了flag字符串,所以存在路径穿越问题,但是有这个问题还是不足以拿到flag。(做的时候利用路径穿越问题查看了.bash_history文件的内容,不过没啥用)

好了,接着往下说。
把伪造session的代码贴一下。跟上面那个参考链接里的一样。

from flask import Flask, session
app = Flask(__name__)
app.config['SECRET_KEY']='ccedfbd953b3f4692e053822a4e58cac'
@app.route('/flag')
def set_id():
    session['is_admin']=1
    return "ok"
#app.run(debug=True)

在这里插入图片描述

这就进来/add目录了,接下来题目的逻辑就是post一个titlecontent值,后台会创建对应的文件,并将content内容写入到文件中,而且在写入成功之后会再读取文件显示到网页上。

因为在article?title=这里是限制了不能输入flag的,所以肯定还是要从add这里下手,怎么能读出flag。我刚开始一直在想能不能光靠路径穿越做出题目…就是说这个题目到底有没有非预期解,后来想想,如果要从article?title=这里下手,不管怎么样,在后台都是通过open()函数读取flag文件内容来拿到flag的,那我就一定要输入flag这个字符串(刚开始试了一下open函数有没有通配符这种用法,发现没有…),那就只能从add这里想办法了。

emm…然后去吃了个饭,回来也不知道是咋搜的,搜到了这篇文章。
https://www.jianshu.com/p/6e4aebd18660

原来这是一个常见的攻击啊。没用过flask不知道,能查到也不错,嘿嘿。直接把payload换上去。

title=hi&content={{ [].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['os'].popen('grep -rn "flag" /var/www').read()}}   //拿到flag文件的路径

title=hi&content={{ [].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['os'].popen('cat /var/www/web_sertdf/flag.py').read()}}

在这里插入图片描述

完美~ 可以执行任意指令,拿到flag就轻轻松松啦~~

把主要的代码贴一下:
在这里插入图片描述

这里还有个问题…感觉flag.py应该设置一下写权限,要不然就可能出现搅屎的情况了。??在写title时候写为title=../flag.py,然后flag文件就被覆盖,别的队都看不到了。??

总结

这可能是第一次一个题目磨蹭了一天吧,虽然中间也间隔着做了一些其他事情,比如睡个午觉…遛个圈。还是感觉方法论很重要,要在做题过程中指导自己,可能有哪几种方法,可以排除哪些方法,为什么排除这样…

这个题目也是自己没见过,不熟悉的东西,然后能找到相关帖子,找到解题方法,哇,突然感觉自己进步好大…

不过话说回来,不进到后台的话…我可能只有和出题人py一下才能做出来了…hhhhh…我到底在这里说什么方法论??哈??

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值